diff --git a/.gitignore b/.gitignore index b35d90d94317f5179eb756468c5a087dc7d43e0a..d69c81f4490f7b7b7837bf86951ff257875b9514 100644 --- a/.gitignore +++ b/.gitignore @@ -57,3 +57,4 @@ /.Net6版本/VOL.WebApi/obj /.Net6版本/VOL.WebApi/bin /.Net6版本/VOL.WebApi/Properties/PublishProfiles +/Pure_Vite_Net7/Vue3Vite/report_form_rollup-plugin-visualizer.html diff --git "a/Pure_Vite_Net7/DB/mysql/mysql\346\211\271\351\207\217\346\227\245\345\277\227\345\206\231\345\205\245\345\244\261\350\264\245.txt" "b/Pure_Vite_Net7/DB/mysql/mysql\346\211\271\351\207\217\346\227\245\345\277\227\345\206\231\345\205\245\345\244\261\350\264\245.txt" new file mode 100644 index 0000000000000000000000000000000000000000..5b62f27f1481bf2d2b3924c858fbbc162fb9f1e2 --- /dev/null +++ "b/Pure_Vite_Net7/DB/mysql/mysql\346\211\271\351\207\217\346\227\245\345\277\227\345\206\231\345\205\245\345\244\261\350\264\245.txt" @@ -0,0 +1,7 @@ +1mysql־дʧʾ:The used command is not allowed with this MySQL version + 취ݿִ:set global local_infile = 'ON'; + + +2־дʱ:To use MySq1Bu1kLoader. Loca1=true, set AllowLoadLocalInfile =true in the connection string. + 취ں̨Ŀappsettings.jsonҵmysqlݿӣAllowLoadLocalInfile =true + diff --git "a/Pure_Vite_Net7/DB/mysql/mysql\350\241\250\347\273\223\346\236\204\344\270\216\350\241\250\346\225\260\346\215\256.sql" "b/Pure_Vite_Net7/DB/mysql/mysql\350\241\250\347\273\223\346\236\204\344\270\216\350\241\250\346\225\260\346\215\256.sql" new file mode 100644 index 0000000000000000000000000000000000000000..6bfaf8145d7838e7abb56525a9553d91eacfd8f2 --- /dev/null +++ "b/Pure_Vite_Net7/DB/mysql/mysql\350\241\250\347\273\223\346\236\204\344\270\216\350\241\250\346\225\260\346\215\256.sql" @@ -0,0 +1,1619 @@ +/* + Navicat Premium Data Transfer + + Source Server : 120.53.251.208 + Source Server Type : MySQL + Source Server Version : 50729 + Source Host : 120.53.251.208:3306 + Source Schema : 1105 + + Target Server Type : MySQL + Target Server Version : 50729 + File Encoding : 65001 + + Date: 06/11/2022 00:36:34 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for FormCollectionObject +-- ---------------------------- +DROP TABLE IF EXISTS `FormCollectionObject`; +CREATE TABLE `FormCollectionObject` ( + `FormCollectionId` char(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `FormId` char(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `Title` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL, + `FormData` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL, + `CreateDate` datetime(0) NULL DEFAULT NULL, + `CreateID` int(11) NULL DEFAULT NULL, + `Creator` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `Modifier` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `ModifyDate` datetime(0) NULL DEFAULT NULL, + `ModifyID` int(11) NULL DEFAULT NULL, + PRIMARY KEY (`FormCollectionId`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of FormCollectionObject +-- ---------------------------- +INSERT INTO `FormCollectionObject` VALUES ('00ac79fa-529b-45c1-ae98-1838d86f5e95', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"2022-04-21\",\"field1641207457900\":null,\"field1641207424694\":\"\"}', '2022-04-28 10:20:13', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('03c45672-2149-4399-9ecb-75644718f038', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":null}', '2022-02-17 13:16:44', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('0513b2ca-6ccd-489d-9e83-ea3de7b01754', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":\"d\"}', '2022-02-28 08:14:37', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('066ed25e-9f90-498f-bdec-05cb7881913e', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":null}', '2022-01-26 11:50:22', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('06febfc3-28d0-497f-828d-a29d5acfa366', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"2022-03-08\",\"field1641207457900\":\"324\",\"field1641207424694\":\"\"}', '2022-03-16 16:51:55', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('0a71d04e-6840-48ba-a3de-817896e1e111', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":null}', '2022-01-14 01:44:33', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('0b0d324e-916b-4246-9f7a-96f5f9435320', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":\"22\"}', '2022-03-10 08:58:21', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('0b3ac6d2-35ac-42b0-84c5-bd4a22157dc2', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意,十分满意\",\"field1641205647957\":\"非常满意\",\"field1650260639951\":\"1\",\"field1650260638189\":\"1\",\"field1650260647796\":\"1\",\"field1641206608182\":\"1\"}', '2022-05-14 23:18:19', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('0b5e3fb4-9c8b-407d-931e-bae4b8b34ce9', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1650260639951\":\"11\",\"field1650260638189\":null,\"field1650260647796\":null,\"field1641206608182\":null}', '2022-06-30 16:41:37', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('1041a590-3d36-43c8-8b1d-fe6a7a7ca18f', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1650260639951\":\"1\",\"field1650260638189\":\"1\",\"field1650260647796\":\"1\",\"field1641206608182\":\"1\"}', '2022-04-18 18:07:15', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('10e5c36a-c3b0-4d9f-83bc-c25bd97e2b82', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":\"0\"}', '2022-02-12 14:12:00', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('15290644-4a33-4c16-8326-fd75974592a6', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1650260639951\":\"7\",\"field1650260638189\":\"7777777777777777\",\"field1650260647796\":\"7777777777777777\",\"field1641206608182\":\"777\"}', '2022-06-06 16:31:29', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('1550cb90-47c6-43cd-8690-97999d72d92f', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1650260639951\":null,\"field1650260638189\":null,\"field1650260647796\":null,\"field1641206608182\":null}', '2022-06-13 10:35:58', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('16d5ead2-e9ef-40fb-b275-832898b8cdfa', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":\"fgdfghf gfh fg\"}', '2022-03-09 17:07:15', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('182125f4-f074-4b48-8ab1-e17aba5b82e9', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":\"FAS\"}', '2022-02-08 17:18:44', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('1da99df3-fc0c-48e6-98db-e95daeeddd05', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1650260639951\":\"4、输入框:\",\"field1650260638189\":\"5、输入框:\",\"field1650260647796\":\"6、输入框:\",\"field1641206608182\":\"7、其他意见:\"}', '2022-06-11 23:15:22', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('1f50d9ec-6be5-4410-b54b-e918ee0eb386', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"相当满意\",\"field1641206608182\":null}', '2022-03-24 21:27:29', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('201e9a14-7ee7-4f68-919f-aac4059dfc2c', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":null}', '2022-04-12 14:49:03', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('21323223-980d-4177-a144-210fd26f10bf', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":\"fq\"}', '2022-03-25 19:45:47', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('248d00a3-73fd-4c44-84b2-142543c61155', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":\"111\"}', '2022-02-17 14:01:27', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('25b4cd02-8602-4516-8394-b4025e9cc420', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1650260639951\":\"1\",\"field1650260638189\":\"2\",\"field1650260647796\":\"3\",\"field1641206608182\":\"4\"}', '2022-04-27 10:09:39', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('29819b15-d57b-435a-a4aa-68458e60bc4d', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1650260639951\":\"1\",\"field1650260638189\":\"2\",\"field1650260647796\":\"3\",\"field1641206608182\":\"\\n\"}', '2022-05-27 10:51:36', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('2cf3ecde-45f3-44e5-af2a-329a8e91e6da', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":\"人\"}', '2022-03-27 22:52:18', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('2e10dfbc-5e80-466d-9e68-00f4c03b03cb', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"2022-01-07\",\"field1641207457900\":null,\"field1641207424694\":\"\"}', '2022-01-19 11:10:53', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('2e426da4-9bc2-4086-b910-55335252e286', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"十分满意\",\"field1650260639951\":null,\"field1650260638189\":null,\"field1650260647796\":null,\"field1641206608182\":null}', '2022-07-07 17:15:39', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('2e71a231-ec58-4fe4-8101-f0d3405ac79d', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"0\",\"field1640871902689\":\"2022-03-12\",\"field1641207457900\":null,\"field1641207424694\":\"\"}', '2022-03-12 07:21:12', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('2e860327-82a9-4e51-a451-f32295db062a', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1650260639951\":\"5\",\"field1650260638189\":\"5\",\"field1650260647796\":\"5\",\"field1641206608182\":\"5\"}', '2022-05-11 09:59:04', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('2ea29d88-281d-449a-a200-645ca8c613d5', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"2017-05-04\",\"field1641207457900\":null,\"field1641207424694\":\"\"}', '2022-05-23 17:21:34', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('2f9fbaff-4c97-42e4-94b2-5fc2704b3a18', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"相当满意\",\"field1641206608182\":null}', '2022-03-03 10:14:39', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('32c11483-0898-447b-baff-a5911e988925', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":null}', '2022-02-05 11:32:07', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('33d6d570-c665-40b6-9035-c5f6a7fce01f', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":\"11111111\"}', '2022-03-04 16:54:25', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('35cbe5b1-2498-4f13-b605-ee6f191d30a9', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"2022-06-08\",\"field1641207457900\":\"v v \",\"field1641207424694\":\"\"}', '2022-06-03 22:02:09', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('370e55db-746a-40cd-90f2-ff73b64eab00', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"相当满意,比较满意\",\"field1641205647957\":\"非常满意\",\"field1650260639951\":null,\"field1650260638189\":null,\"field1650260647796\":null,\"field1641206608182\":null}', '2022-08-02 11:37:54', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('372a0316-bf48-4411-bef0-bdfc2deefeb8', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"非常满意\",\"field1650260639951\":null,\"field1650260638189\":null,\"field1650260647796\":null,\"field1641206608182\":null}', '2022-06-22 16:39:37', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('3990f4bd-68ac-483c-bc85-38335e83b88a', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"2022-01-30\",\"field1641207457900\":\"的风景埃里克就\",\"field1641207424694\":\"\"}', '2022-01-22 21:16:06', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('3bb62484-b056-43a2-9b33-5764fc625ab9', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"相当满意\",\"field1650260639951\":null,\"field1650260638189\":null,\"field1650260647796\":null,\"field1641206608182\":null}', '2022-06-16 10:45:34', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('3e7a21bf-dd68-4b6a-bfa9-b0aaa3e8d49f', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":\"1231\"}', '2022-03-02 13:58:08', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('3f22aafc-214f-4374-a97c-2cdcce81e08a', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":null}', '2022-03-31 16:19:16', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('4254e8ed-0e9f-4423-9f72-1007df7fceb1', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"相当满意\",\"field1641206608182\":\"test\"}', '2022-01-19 23:07:20', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('448ef9bf-bb84-4e56-af5b-17032207fa23', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1650260639951\":null,\"field1650260638189\":null,\"field1650260647796\":null,\"field1641206608182\":null}', '2022-08-01 10:56:59', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('4dcd83b4-5e1e-4299-9bc6-302313f98d5f', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":null}', '2022-04-02 21:09:23', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('4f443026-4c8f-4c27-b6b7-20eeefab42a1', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":\"sss\"}', '2022-02-25 17:30:06', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('51fcee24-aee5-4b55-9c30-f42082e8c61e', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意,十分满意,相当满意,比较满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":null}', '2022-01-13 08:56:25', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('52990452-b50e-497c-aa0f-5093214d690b', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":\"22233\"}', '2022-03-10 08:58:37', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('530ce4a0-d399-49e3-b417-9dfdf2ac4da7', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"十分满意,相当满意,比较满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":null}', '2022-03-31 15:29:02', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('53e1f20a-6c35-48b5-9fca-d5c72f87ca76', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"0\",\"field1640871902689\":\"2022-02-01\",\"field1641207457900\":null,\"field1641207424694\":\"\"}', '2022-02-08 23:58:30', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('55419def-5b55-4878-9575-430a9761ac93', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":null}', '2022-01-15 18:38:30', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('58253f8c-66d5-4eeb-a952-c84841351fe4', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"相当满意\",\"field1641205647957\":\"比较满意\",\"field1650260639951\":null,\"field1650260638189\":null,\"field1650260647796\":null,\"field1641206608182\":null}', '2022-05-23 17:21:10', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('584c592f-0fb5-4246-a57e-9f39e80f97da', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1650260639951\":null,\"field1650260638189\":null,\"field1650260647796\":null,\"field1641206608182\":null}', '2022-05-06 12:03:23', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('5d26599c-2dbb-4261-9569-01472b8f525d', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":null}', '2022-03-08 14:21:34', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('5dba775b-c261-46ec-bf4c-e3747e2939f8', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":null}', '2022-02-17 18:17:30', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('5e8d3723-e5b4-41a3-b088-12266b98c523', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"非常满意,十分满意,相当满意,比较满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":\"111222333\"}', '2022-02-14 13:39:41', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('5fa2dc0b-a498-4434-9286-690f0df8a914', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":null}', '2022-01-12 10:53:22', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('5fdcfca6-99b5-4477-b9d8-103e9787dc2f', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":null}', '2022-08-13 10:04:15', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('61ca3776-d945-4b44-9242-a73a70b925c4', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":\"qqqq\"}', '2022-02-20 21:11:02', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('63398fae-9ce4-4818-9103-68c095fc9b6b', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":null}', '2022-04-06 21:57:17', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('63c4f091-b740-4995-a4e4-f46183cfcb49', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"2022-06-16\",\"field1641207457900\":\"哈哈哈哈\",\"field1641207424694\":\"\"}', '2022-06-22 17:26:14', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('650dc3f2-075b-490b-9382-bd813af0dcd9', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"相当满意\",\"field1650260639951\":\"111\",\"field1650260638189\":\"111\",\"field1650260647796\":\"111\",\"field1641206608182\":\"111\"}', '2022-06-23 13:50:13', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('67941f5e-7f34-455b-9afd-280ec7f02240', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意,十分满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":\"请问\"}', '2022-01-22 17:22:18', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('6c8a34fc-f86a-4517-a792-2a941ceb2015', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"十分满意\",\"field1650260639951\":\"sdad\",\"field1650260638189\":null,\"field1650260647796\":null,\"field1641206608182\":null}', '2022-04-28 17:07:37', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('6d36b685-e343-4e0f-b17d-ba39d83e3f72', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意,非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":\"111\"}', '2022-01-18 16:07:10', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('6e279655-a553-494b-80e9-ac1b14361cab', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"2022-07-07\",\"field1641207457900\":\"1334\",\"field1641207424694\":\"\"}', '2022-07-07 16:52:47', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('71ccce55-7dd4-4de7-962b-a0625ffaabf7', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"2022-02-03\",\"field1641207457900\":null,\"field1641207424694\":\"\"}', '2022-02-17 21:57:14', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('73eb6ca6-1159-4c95-a0cd-03789e158dd6', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1650260639951\":null,\"field1650260638189\":null,\"field1650260647796\":null,\"field1641206608182\":null}', '2022-07-05 10:33:25', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('766e2ed2-8de0-4043-bc77-93533e4bb666', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":\"5\"}', '2022-08-11 09:38:56', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('7835bd2f-46f4-4476-92fc-562343f5222c', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"2022-08-03\",\"field1641207457900\":\"test\",\"field1641207424694\":\"\"}', '2022-08-07 17:14:22', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('793a839a-4fb4-45a4-a274-c265529a08d7', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":\"888\"}', '2022-04-06 21:57:39', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('7c2c5dde-1318-4382-848c-215a862bbc14', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"2022-01-01\",\"field1641207457900\":null,\"field1641207424694\":\"\"}', '2022-01-25 09:24:22', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('7cc358fe-d17c-49b0-a32d-4bde5b8d81ba', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意,相当满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":null}', '2022-08-03 15:58:01', 1, '超级管理员', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('7f7591b8-367e-4128-9e43-ef68e67edb5d', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":null}', '2022-04-14 09:20:31', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('7fd4ea6c-d4ec-4cbe-a0dd-1ea77992ba88', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":null}', '2022-02-22 17:22:06', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('814dbafb-dd62-438e-81c9-56e71cf49fa7', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"十分满意\",\"field1650260639951\":null,\"field1650260638189\":null,\"field1650260647796\":null,\"field1641206608182\":null}', '2022-06-11 21:45:22', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('8245c9b8-a4c9-4db8-96e4-3cc471acbb79', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"2022-06-10\",\"field1641207457900\":\"C#越学越不会了\",\"field1641207424694\":\"\"}', '2022-06-05 16:40:26', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('84754fa9-d2d0-4ed3-b3f0-90157a0a78c6', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":null}', '2022-03-02 14:23:40', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('848437d7-50be-40e7-88b4-de67ec402faa', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"2022-04-22\",\"field1641207457900\":null,\"field1641207424694\":\"\"}', '2022-04-13 13:25:29', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('8510b8ea-e415-48b7-adbd-c88c39fe8136', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":\"XIONG GONG\"}', '2022-08-16 09:20:07', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('87166fa0-cfba-406c-b09e-2d94308a4905', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1650260639951\":null,\"field1650260638189\":null,\"field1650260647796\":null,\"field1641206608182\":null}', '2022-06-02 21:48:04', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('87a68d22-74e1-498f-88cb-3462904eb0c7', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1650260639951\":null,\"field1650260638189\":null,\"field1650260647796\":null,\"field1641206608182\":null}', '2022-05-08 01:46:27', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('8f754069-a619-4eb5-9261-aab4163b9e34', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":null}', '2022-08-16 11:22:32', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('90513c4c-b639-4d0d-8c9d-fb69b77620f8', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"2022-01-05\",\"field1641207457900\":null,\"field1641207424694\":\"\"}', '2022-01-03 19:06:50', 1, '超级管理员', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('90f1525a-062c-4180-9a92-00bc802901c9', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"比较满意,十分满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":null}', '2022-01-21 15:24:27', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('9245c5de-c3d8-45a4-a8a0-a03975f15efc', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":null}', '2022-02-28 20:04:37', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('956d43cc-c96a-4945-a029-079b0f99508f', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"1999-06-01\",\"field1641207457900\":null,\"field1641207424694\":\"\"}', '2022-04-20 11:40:36', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('96348cf2-095e-4a37-8ab4-d0072b780c55', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":\"1\"}', '2022-04-12 15:11:51', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('9c1226c7-5694-4d52-8d2f-23ae5ade8b92', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1650260639951\":\"12\",\"field1650260638189\":\"34\",\"field1650260647796\":\"455\",\"field1641206608182\":\"66\"}', '2022-04-28 15:39:06', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('a37c1956-ddc0-457b-8f0a-93cdc44c257d', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意,相当满意\",\"field1641205647957\":\"相当满意\",\"field1641206608182\":\"没有意见\"}', '2022-01-03 19:05:46', 1, '超级管理员', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('a507f976-af08-4e7a-9885-9a04a97592df', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1650260639951\":null,\"field1650260638189\":null,\"field1650260647796\":null,\"field1641206608182\":null}', '2022-04-18 14:32:03', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('a5c0e586-c7ad-43f4-8629-aa9e1c672c42', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"2022-01-19\",\"field1641207457900\":null,\"field1641207424694\":\"\"}', '2022-01-21 13:49:39', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('a60cfa8b-cdb0-47f9-9cee-570c3150e055', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意,十分满意,相当满意,比较满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":null}', '2022-01-16 08:53:12', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('a7ac9b0d-f866-4db0-b499-59e3d36d8131', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意,相当满意\",\"field1641205647957\":\"十分满意\",\"field1650260639951\":\"1\",\"field1650260638189\":\"1\",\"field1650260647796\":\"1\",\"field1641206608182\":\"1\"}', '2022-07-19 16:00:56', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('a8adcb8f-3238-41f3-b3bd-28197a5bc230', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":null}', '2022-01-18 14:13:54', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('a92575b4-9889-42ed-9677-5a648a429970', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1650260639951\":\"1\",\"field1650260638189\":\"1\",\"field1650260647796\":\"1\",\"field1641206608182\":\"1\"}', '2022-04-26 10:09:18', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('ad25a88c-54c6-4164-8f8a-9d54d6489b42', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"2022-02-01\",\"field1641207457900\":null,\"field1641207424694\":\"\"}', '2022-02-15 13:35:39', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('ae89f005-a7a2-43cc-9786-99301569f78e', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1650260639951\":\"sdf\",\"field1650260638189\":\"dsf\",\"field1650260647796\":\"sdf\",\"field1641206608182\":\"dsf\"}', '2022-06-15 15:28:11', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('ae8f2272-1311-4a2d-a58c-ea2b6fa36578', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":\"0000\"}', '2022-03-16 15:53:31', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('afe8243d-a936-443f-864c-7b5278f26167', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"0\",\"field1640871902689\":\"2018-01-03\",\"field1641207457900\":\"这个低代码会有很多坑 实际用的时候 发现很痛苦\\n小项目会很方便\",\"field1641207424694\":\"\"}', '2022-01-14 15:53:14', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('b2097447-69bb-454f-809e-d47ad90301d9', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":null}', '2022-04-09 21:39:04', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('b5fab3ae-ec1d-4a51-a9b5-041104b957d8', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":null}', '2022-03-09 13:47:41', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('bf26c23b-88ed-404b-98f1-e081c4d92f54', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"非常满意,十分满意,相当满意,比较满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":null}', '2022-08-07 17:14:14', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('c0dbcff2-b8f6-4c3b-93ec-59ee17dbab6f', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"2017-03-24\",\"field1641207457900\":\"支持博主,希望网站越做越完善\",\"field1641207424694\":\"\"}', '2022-05-22 07:46:53', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('c1c56c53-785c-4641-a581-228326dcf491', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":null}', '2022-04-01 10:25:59', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('c217f308-55ed-431f-8de3-8a41c197c336', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"相当满意\",\"field1641205647957\":\"相当满意\",\"field1650260639951\":null,\"field1650260638189\":null,\"field1650260647796\":null,\"field1641206608182\":null}', '2022-04-18 14:32:43', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('c768c884-d674-44be-a003-aae62eeff90c', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意,相当满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":\"3333\"}', '2022-03-18 12:01:53', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('cafcb37f-b6e8-46a1-b786-78a38a76c40b', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1650260639951\":null,\"field1650260638189\":null,\"field1650260647796\":null,\"field1641206608182\":null}', '2022-07-19 23:39:56', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('cb7e2576-3b88-48bf-9202-3f77a9f915b5', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"相当满意\",\"field1650260639951\":null,\"field1650260638189\":null,\"field1650260647796\":null,\"field1641206608182\":null}', '2022-07-25 22:24:50', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('cccc519c-c448-4292-85d1-6a0ac2828fd9', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"2022-01-04\",\"field1641207457900\":\"123456\",\"field1641207424694\":\"\"}', '2022-01-03 19:09:53', 1, '超级管理员', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('cce9c0a6-8850-43a1-aca9-b7e6321dceef', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"0\",\"field1640871902689\":\"2022-01-16\",\"field1641207457900\":\"科技大道就看见\",\"field1641207424694\":\"\"}', '2022-01-16 16:21:36', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('cde313b5-1fa1-4c43-9765-df1d66f19249', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"十分满意\",\"field1650260639951\":\"111\",\"field1650260638189\":\"222\",\"field1650260647796\":\"333\",\"field1641206608182\":\"44\"}', '2022-05-07 15:33:29', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('ce238aa2-5355-463c-8341-15e08fce098b', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":\"78999\"}', '2022-04-12 18:53:36', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('cfa58a5a-2b94-42a2-8825-acd558983a2b', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"2022-04-27\",\"field1641207457900\":null,\"field1641207424694\":\"\"}', '2022-05-10 01:27:35', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('d01d07e6-b8dc-49de-b6a9-9b54333af37a', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":\"444\"}', '2022-03-23 14:43:19', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('d01d544c-d260-4ee9-9929-b18daba2b880', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1650260639951\":\"456\",\"field1650260638189\":\"456\",\"field1650260647796\":\"456\",\"field1641206608182\":\"456\"}', '2022-06-29 13:21:54', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('d3a90649-7dbe-4f27-ad73-2a201bd2b7fa', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":null}', '2022-04-13 13:22:36', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('d7833a92-c0d9-4a90-b70f-375b980258c4', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"0\",\"field1640871902689\":\"2022-01-01\",\"field1641207457900\":null,\"field1641207424694\":\"\"}', '2022-01-16 17:00:28', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('d8c84159-280d-4280-a374-63f4fecc9b8c', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":null}', '2022-03-12 07:21:22', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('d9d8dca9-8899-4636-886b-929d91de6cf9', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1650260639951\":\"e\",\"field1650260638189\":\"we\",\"field1650260647796\":\"ew\",\"field1641206608182\":\"we\"}', '2022-05-31 15:45:49', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('da47770c-9067-459b-805c-e7081480c9d4', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"非常满意\",\"field1650260639951\":null,\"field1650260638189\":null,\"field1650260647796\":null,\"field1641206608182\":null}', '2022-06-09 12:22:22', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('dc0319f2-3b02-465e-9c94-d32c19cc83ba', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1650260639951\":null,\"field1650260638189\":null,\"field1650260647796\":null,\"field1641206608182\":null}', '2022-07-01 09:24:58', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('dc4af657-1e89-4807-baf9-92693aff0762', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"比较满意,相当满意,十分满意\",\"field1641205647957\":\"相当满意\",\"field1650260639951\":null,\"field1650260638189\":null,\"field1650260647796\":null,\"field1641206608182\":null}', '2022-06-02 09:42:43', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('dc827875-7c48-4092-8299-615e60897dd6', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":null}', '2022-08-07 17:13:45', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('dd6b3150-808e-4ca9-b936-66b12e88173b', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"0\",\"field1640871902689\":\"2022-03-31\",\"field1641207457900\":null,\"field1641207424694\":\"\"}', '2022-04-26 10:08:55', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('dedb01d1-b168-4ef7-a9f8-e2fc809821d7', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"非常满意,十分满意,比较满意,相当满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":null}', '2022-02-22 09:11:27', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('dfd6a79c-5ee7-4362-a7b5-a7ee556dcb4f', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":\"36\"}', '2022-01-14 15:10:33', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('e003b80d-a262-49f5-86f5-7a9be8cfebb8', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":\";ppp\"}', '2022-01-18 22:46:35', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('e3eaeafe-19cc-4335-b05a-ba1723532a94', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"2022-06-15\",\"field1641207457900\":\"3333\",\"field1641207424694\":\"\"}', '2022-06-22 17:25:54', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('e4a9051a-acd6-4c9f-b484-6ade9641b97a', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":\"我的测试\"}', '2022-03-23 09:55:50', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('e6e08ec4-5b55-4b3f-8f1f-b399817ddab6', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":\"2323\"}', '2022-03-07 13:02:29', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('e75f8825-5934-4562-9846-a938e105a6aa', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"十分满意,相当满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":null}', '2022-04-18 11:56:55', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('e894b567-e6e0-4fb9-9eac-6b90557b4c06', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"2022-03-10\",\"field1641207457900\":\"dddd\",\"field1641207424694\":\"\"}', '2022-03-18 20:23:02', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('e8f5cdee-4b67-4191-bb48-0c9968fa49d4', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"2022-04-13\",\"field1641207457900\":\"432\",\"field1641207424694\":\"\"}', '2022-04-13 09:04:19', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('e913389c-e11a-4675-b8eb-a25c75086e37', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"非常满意,十分满意,相当满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":\"1111\"}', '2022-01-03 19:09:45', 1, '超级管理员', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('e988f446-00df-4d43-9682-eba419c9f18b', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"比较满意\",\"field1641205647957\":\"比较满意\",\"field1641206608182\":\"滚滚滚\"}', '2022-01-16 16:17:55', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('ed4863d4-6bf7-4f4c-bd6b-b984881d6dd1', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":\"123\"}', '2022-03-16 14:36:51', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('edfac119-20ec-494f-b92e-b9f340ef7093', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":null}', '2022-01-13 14:49:38', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('ef16549c-59b7-425d-b32e-424882eeb92f', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"非常满意,十分满意,相当满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":\"123\"}', '2022-04-01 15:27:07', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('f011feed-4cff-4f9d-a878-a38a8afd539c', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"0\",\"field1640871902689\":\"2022-08-19\",\"field1641207457900\":null,\"field1641207424694\":\"\"}', '2022-08-03 15:56:21', 1, '超级管理员', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('f549faa0-c6e0-431e-a029-a0ba7767386b', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":\"1\"}', '2022-02-16 11:45:15', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('f6cbc763-5cd0-4774-be84-06e7a9872278', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意,相当满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":null}', '2022-01-12 11:32:06', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('f6f2586f-2249-4bca-928f-0b513deab6e2', '0431a578-bfc9-407f-b95e-321c350f10cb', NULL, '{\"FormId\":\"0431a578-bfc9-407f-b95e-321c350f10cb\",\"field1640871905593\":\"1\",\"field1640871902689\":\"2022-08-09\",\"field1641207457900\":null,\"field1641207424694\":\"\"}', '2022-08-15 13:21:19', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('f8d30ab4-8d7f-42ac-899c-dac1c5f61619', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意,十分满意,相当满意,比较满意\",\"field1641205647957\":\"十分满意\",\"field1641206608182\":\"34343\"}', '2022-04-14 21:07:46', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('fa69e0b6-4bbd-4ac0-a691-cbbb2905f589', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1641206608182\":\"111\"}', '2022-03-04 16:53:11', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('fbb50231-efa5-46c2-a3bb-9ce2279de293', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"非常满意\",\"field1641205647957\":\"非常满意\",\"field1650260639951\":\"e\",\"field1650260638189\":\"qew\",\"field1650260647796\":\"eqw\",\"field1641206608182\":\"qwe\"}', '2022-07-14 14:52:12', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('fced572f-b387-46a4-9afc-c70c4931f3cf', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"0\",\"field1641206170991\":\"相当满意\",\"field1641205647957\":\"十分满意\",\"field1650260639951\":\"1\",\"field1650260638189\":\"1\",\"field1650260647796\":\"1\",\"field1641206608182\":\"1\"}', '2022-08-01 12:47:47', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('fd8d649a-ce7f-4801-89dc-0a7e3556468c', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1650260639951\":\"AAA\",\"field1650260638189\":\"AAA\",\"field1650260647796\":\"AAA\",\"field1641206608182\":null}', '2022-06-12 17:24:32', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('fe3cc538-3bf7-4c9c-a6cf-9c96386d17e5', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意,相当满意\",\"field1641205647957\":\"相当满意\",\"field1650260639951\":null,\"field1650260638189\":null,\"field1650260647796\":null,\"field1641206608182\":null}', '2022-05-02 14:30:57', 3362, '演示帐号', NULL, NULL, NULL); +INSERT INTO `FormCollectionObject` VALUES ('ff2b479b-66ca-4ad4-9272-6671d465d9d3', '8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', NULL, '{\"FormId\":\"8e6d9e7c-16c2-48b8-9d67-f1a1a19453da\",\"field1641205615398\":\"1\",\"field1641206170991\":\"十分满意\",\"field1641205647957\":\"十分满意\",\"field1650260639951\":null,\"field1650260638189\":null,\"field1650260647796\":null,\"field1641206608182\":null}', '2022-04-23 22:57:26', 3362, '演示帐号', NULL, NULL, NULL); + +-- ---------------------------- +-- Table structure for FormDesignOptions +-- ---------------------------- +DROP TABLE IF EXISTS `FormDesignOptions`; +CREATE TABLE `FormDesignOptions` ( + `FormId` char(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `Title` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `DaraggeOptions` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL, + `FormOptions` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL, + `FormConfig` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL, + `FormFields` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL, + `TableConfig` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL, + `CreateDate` datetime(0) NULL DEFAULT NULL, + `CreateID` int(11) NULL DEFAULT NULL, + `Creator` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `Modifier` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `ModifyDate` datetime(0) NULL DEFAULT NULL, + `ModifyID` int(11) NULL DEFAULT NULL, + PRIMARY KEY (`FormId`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of FormDesignOptions +-- ---------------------------- +INSERT INTO `FormDesignOptions` VALUES ('0431a578-bfc9-407f-b95e-321c350f10cb', '2021开发语言使用调查', '[{\"id\":5,\"name\":\"多种语言开发\",\"type\":\"radio\",\"icon\":\"el-icon-aim\",\"value\":0,\"data\":[{\"key\":\"0\",\"value\":\"否\"},{\"key\":\"2\",\"value\":\"xx11\"},{\"key\":\"1\",\"value\":\"是\"}],\"key\":\"enable\",\"field\":\"field1640871905593\",\"width\":100,\"readonly\":false,\"required\":true,\"values\":[\"否\"]},{\"id\":3,\"name\":\"从什么时候开始做开发?\",\"type\":\"date\",\"icon\":\"el-icon-date\",\"value\":null,\"field\":\"field1640871902689\",\"width\":100,\"readonly\":false,\"required\":true},{\"id\":2,\"name\":\"说点什么\",\"type\":\"textarea\",\"value\":\"\",\"icon\":\"el-icon-document-copy\",\"field\":\"field1641207457900\",\"width\":100,\"readonly\":false,\"required\":false},{\"id\":9,\"name\":\"图片上传\",\"type\":\"img\",\"url\":\"\",\"maxSize\":3,\"fileInfo\":[],\"multiple\":false,\"autoUpload\":false,\"maxFile\":5,\"icon\":\"el-icon-picture-outline\",\"field\":\"field1641207424694\",\"width\":100,\"readonly\":false,\"required\":false}]', '{\"fields\":{\"field1640871905593\":[],\"field1640871902689\":null,\"field1641207457900\":null,\"field1641207424694\":null},\"formOptions\":[[{\"field\":\"field1640871905593\",\"title\":\"多种语言开发\",\"type\":\"radio\",\"required\":true,\"readonly\":false,\"colSize\":12,\"data\":[{\"key\":\"0\",\"value\":\"否\"},{\"key\":\"2\",\"value\":\"xx11\"},{\"key\":\"1\",\"value\":\"是\"}],\"dataKey\":\"enable\"}],[{\"field\":\"field1640871902689\",\"title\":\"从什么时候开始做开发?\",\"type\":\"date\",\"required\":true,\"readonly\":false,\"colSize\":12}],[{\"field\":\"field1641207457900\",\"title\":\"说点什么\",\"type\":\"textarea\",\"required\":false,\"readonly\":false,\"colSize\":12}],[{\"field\":\"field1641207424694\",\"title\":\"图片上传\",\"type\":\"img\",\"required\":false,\"readonly\":false,\"colSize\":12,\"maxSize\":3,\"fileInfo\":[],\"multiple\":false,\"autoUpload\":false,\"maxFile\":5,\"url\":\"\"}]],\"tables\":[],\"tabs\":[]}', '[{\"field\":\"field1640871905593\",\"title\":\"多种语言开发\",\"type\":\"radio\",\"required\":true,\"readonly\":false,\"colSize\":12,\"data\":[{\"key\":\"0\",\"value\":\"否\"},{\"key\":\"2\",\"value\":\"xx11\"},{\"key\":\"1\",\"value\":\"是\"}],\"dataKey\":\"enable\"},{\"field\":\"field1640871902689\",\"title\":\"从什么时候开始做开发?\",\"type\":\"date\",\"required\":true,\"readonly\":false,\"colSize\":12},{\"field\":\"field1641207457900\",\"title\":\"说点什么\",\"type\":\"textarea\",\"required\":false,\"readonly\":false,\"colSize\":12},{\"field\":\"field1641207424694\",\"title\":\"图片上传\",\"type\":\"img\",\"required\":false,\"readonly\":false,\"colSize\":12,\"maxSize\":3,\"fileInfo\":[],\"multiple\":false,\"autoUpload\":false,\"maxFile\":5,\"url\":\"\"}]', NULL, '[]', '2021-12-29 23:39:22', 1, '超级管理员', '超级管理员', '2022-08-03 15:58:37', 1); +INSERT INTO `FormDesignOptions` VALUES ('8e6d9e7c-16c2-48b8-9d67-f1a1a19453da', '2021双减政策调查', '[{\"id\":5,\"name\":\"您的孩子放学后是否有学校布置的书面作业?\",\"type\":\"radio\",\"icon\":\"el-icon-aim\",\"value\":0,\"data\":[{\"key\":\"0\",\"value\":\"否\"},{\"key\":\"2\",\"value\":\"xx11\"},{\"key\":\"1\",\"value\":\"是\"}],\"key\":\"enable\",\"field\":\"field1641205615398\",\"width\":100,\"readonly\":false,\"required\":true,\"values\":[\"否\"]},{\"id\":6,\"name\":\"您认为放学后作业对孩子的负担怎样?\",\"values\":[\"非常满意\"],\"type\":\"checkbox\",\"key\":\"满意度\",\"data\":[{\"key\":\"非常满意\",\"value\":\"非常满意\"},{\"key\":\"十分满意\",\"value\":\"十分满意\"},{\"key\":\"相当满意\",\"value\":\"相当满意\"}],\"icon\":\"el-icon-circle-check\",\"field\":\"field1641206170991\",\"width\":100,\"readonly\":false,\"required\":true},{\"id\":5,\"name\":\"作为家长,对当前双减政策是否满意?\",\"type\":\"radio\",\"icon\":\"el-icon-aim\",\"value\":0,\"data\":[{\"key\":\"非常满意\",\"value\":\"非常满意\"},{\"key\":\"十分满意\",\"value\":\"十分满意\"},{\"key\":\"相当满意\",\"value\":\"相当满意\"}],\"key\":\"满意度\",\"field\":\"field1641205647957\",\"width\":100,\"readonly\":false,\"required\":true,\"values\":[\"非常满意\"]},{\"id\":2,\"name\":\"其他意见\",\"type\":\"textarea\",\"value\":\"\",\"icon\":\"el-icon-document-copy\",\"field\":\"field1641206608182\",\"width\":100,\"readonly\":false,\"required\":false}]', '{\"fields\":{\"field1641205615398\":[],\"field1641206170991\":[],\"field1641205647957\":[],\"field1641206608182\":null},\"formOptions\":[[{\"field\":\"field1641205615398\",\"title\":\"您的孩子放学后是否有学校布置的书面作业?\",\"type\":\"radio\",\"required\":true,\"readonly\":false,\"colSize\":12,\"data\":[{\"key\":\"0\",\"value\":\"否\"},{\"key\":\"2\",\"value\":\"xx11\"},{\"key\":\"1\",\"value\":\"是\"}],\"dataKey\":\"enable\"}],[{\"field\":\"field1641206170991\",\"title\":\"您认为放学后作业对孩子的负担怎样?\",\"type\":\"checkbox\",\"required\":true,\"readonly\":false,\"colSize\":12,\"data\":[{\"key\":\"非常满意\",\"value\":\"非常满意\"},{\"key\":\"十分满意\",\"value\":\"十分满意\"},{\"key\":\"相当满意\",\"value\":\"相当满意\"}],\"dataKey\":\"满意度\"}],[{\"field\":\"field1641205647957\",\"title\":\"作为家长,对当前双减政策是否满意?\",\"type\":\"radio\",\"required\":true,\"readonly\":false,\"colSize\":12,\"data\":[{\"key\":\"非常满意\",\"value\":\"非常满意\"},{\"key\":\"十分满意\",\"value\":\"十分满意\"},{\"key\":\"相当满意\",\"value\":\"相当满意\"}],\"dataKey\":\"满意度\"}],[{\"field\":\"field1641206608182\",\"title\":\"其他意见\",\"type\":\"textarea\",\"required\":false,\"readonly\":false,\"colSize\":12}]],\"tables\":[],\"tabs\":[]}', '[{\"field\":\"field1641205615398\",\"title\":\"您的孩子放学后是否有学校布置的书面作业?\",\"type\":\"radio\",\"required\":true,\"readonly\":false,\"colSize\":12,\"data\":[{\"key\":\"0\",\"value\":\"否\"},{\"key\":\"2\",\"value\":\"xx11\"},{\"key\":\"1\",\"value\":\"是\"}],\"dataKey\":\"enable\"},{\"field\":\"field1641206170991\",\"title\":\"您认为放学后作业对孩子的负担怎样?\",\"type\":\"checkbox\",\"required\":true,\"readonly\":false,\"colSize\":12,\"data\":[{\"key\":\"非常满意\",\"value\":\"非常满意\"},{\"key\":\"十分满意\",\"value\":\"十分满意\"},{\"key\":\"相当满意\",\"value\":\"相当满意\"}],\"dataKey\":\"满意度\"},{\"field\":\"field1641205647957\",\"title\":\"作为家长,对当前双减政策是否满意?\",\"type\":\"radio\",\"required\":true,\"readonly\":false,\"colSize\":12,\"data\":[{\"key\":\"非常满意\",\"value\":\"非常满意\"},{\"key\":\"十分满意\",\"value\":\"十分满意\"},{\"key\":\"相当满意\",\"value\":\"相当满意\"}],\"dataKey\":\"满意度\"},{\"field\":\"field1641206608182\",\"title\":\"其他意见\",\"type\":\"textarea\",\"required\":false,\"readonly\":false,\"colSize\":12}]', NULL, '[]', '2021-12-30 21:45:16', 1, '超级管理员', '超级管理员', '2022-08-03 15:57:54', 1); + +-- ---------------------------- +-- Table structure for Sys_City +-- ---------------------------- +DROP TABLE IF EXISTS `Sys_City`; +CREATE TABLE `Sys_City` ( + `CityId` int(11) NOT NULL, + `CityCode` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `CityName` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `ProvinceCode` varchar(20) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = COMPACT; + +-- ---------------------------- +-- Records of Sys_City +-- ---------------------------- +INSERT INTO `Sys_City` VALUES (1, '110100', '市辖区', '110000'); +INSERT INTO `Sys_City` VALUES (2, '110200', '县', '110000'); +INSERT INTO `Sys_City` VALUES (3, '120100', '市辖区', '120000'); +INSERT INTO `Sys_City` VALUES (4, '120200', '县', '120000'); +INSERT INTO `Sys_City` VALUES (5, '130100', '石家庄市', '130000'); +INSERT INTO `Sys_City` VALUES (6, '130200', '唐山市', '130000'); +INSERT INTO `Sys_City` VALUES (7, '130300', '秦皇岛市', '130000'); +INSERT INTO `Sys_City` VALUES (8, '130400', '邯郸市', '130000'); +INSERT INTO `Sys_City` VALUES (9, '130500', '邢台市', '130000'); +INSERT INTO `Sys_City` VALUES (10, '130600', '保定市', '130000'); +INSERT INTO `Sys_City` VALUES (11, '130700', '张家口市', '130000'); +INSERT INTO `Sys_City` VALUES (12, '130800', '承德市', '130000'); +INSERT INTO `Sys_City` VALUES (13, '130900', '沧州市', '130000'); +INSERT INTO `Sys_City` VALUES (14, '131000', '廊坊市', '130000'); +INSERT INTO `Sys_City` VALUES (15, '131100', '衡水市', '130000'); +INSERT INTO `Sys_City` VALUES (16, '140100', '太原市', '140000'); +INSERT INTO `Sys_City` VALUES (17, '140200', '大同市', '140000'); +INSERT INTO `Sys_City` VALUES (18, '140300', '阳泉市', '140000'); +INSERT INTO `Sys_City` VALUES (19, '140400', '长治市', '140000'); +INSERT INTO `Sys_City` VALUES (20, '140500', '晋城市', '140000'); +INSERT INTO `Sys_City` VALUES (21, '140600', '朔州市', '140000'); +INSERT INTO `Sys_City` VALUES (22, '140700', '晋中市', '140000'); +INSERT INTO `Sys_City` VALUES (23, '140800', '运城市', '140000'); +INSERT INTO `Sys_City` VALUES (24, '140900', '忻州市', '140000'); +INSERT INTO `Sys_City` VALUES (25, '141000', '临汾市', '140000'); +INSERT INTO `Sys_City` VALUES (26, '141100', '吕梁市', '140000'); +INSERT INTO `Sys_City` VALUES (27, '150100', '呼和浩特市', '150000'); +INSERT INTO `Sys_City` VALUES (28, '150200', '包头市', '150000'); +INSERT INTO `Sys_City` VALUES (29, '150300', '乌海市', '150000'); +INSERT INTO `Sys_City` VALUES (30, '150400', '赤峰市', '150000'); +INSERT INTO `Sys_City` VALUES (31, '150500', '通辽市', '150000'); +INSERT INTO `Sys_City` VALUES (32, '150600', '鄂尔多斯市', '150000'); +INSERT INTO `Sys_City` VALUES (33, '150700', '呼伦贝尔市', '150000'); +INSERT INTO `Sys_City` VALUES (34, '150800', '巴彦淖尔市', '150000'); +INSERT INTO `Sys_City` VALUES (35, '150900', '乌兰察布市', '150000'); +INSERT INTO `Sys_City` VALUES (36, '152200', '兴安盟', '150000'); +INSERT INTO `Sys_City` VALUES (37, '152500', '锡林郭勒盟', '150000'); +INSERT INTO `Sys_City` VALUES (38, '152900', '阿拉善盟', '150000'); +INSERT INTO `Sys_City` VALUES (39, '210100', '沈阳市', '210000'); +INSERT INTO `Sys_City` VALUES (40, '210200', '大连市', '210000'); +INSERT INTO `Sys_City` VALUES (41, '210300', '鞍山市', '210000'); +INSERT INTO `Sys_City` VALUES (42, '210400', '抚顺市', '210000'); +INSERT INTO `Sys_City` VALUES (43, '210500', '本溪市', '210000'); +INSERT INTO `Sys_City` VALUES (44, '210600', '丹东市', '210000'); +INSERT INTO `Sys_City` VALUES (45, '210700', '锦州市', '210000'); +INSERT INTO `Sys_City` VALUES (46, '210800', '营口市', '210000'); +INSERT INTO `Sys_City` VALUES (47, '210900', '阜新市', '210000'); +INSERT INTO `Sys_City` VALUES (48, '211000', '辽阳市', '210000'); +INSERT INTO `Sys_City` VALUES (49, '211100', '盘锦市', '210000'); +INSERT INTO `Sys_City` VALUES (50, '211200', '铁岭市', '210000'); +INSERT INTO `Sys_City` VALUES (51, '211300', '朝阳市', '210000'); +INSERT INTO `Sys_City` VALUES (52, '211400', '葫芦岛市', '210000'); +INSERT INTO `Sys_City` VALUES (53, '220100', '长春市', '220000'); +INSERT INTO `Sys_City` VALUES (54, '220200', '吉林市', '220000'); +INSERT INTO `Sys_City` VALUES (55, '220300', '四平市', '220000'); +INSERT INTO `Sys_City` VALUES (56, '220400', '辽源市', '220000'); +INSERT INTO `Sys_City` VALUES (57, '220500', '通化市', '220000'); +INSERT INTO `Sys_City` VALUES (58, '220600', '白山市', '220000'); +INSERT INTO `Sys_City` VALUES (59, '220700', '松原市', '220000'); +INSERT INTO `Sys_City` VALUES (60, '220800', '白城市', '220000'); +INSERT INTO `Sys_City` VALUES (61, '222400', '延边朝鲜族自治州', '220000'); +INSERT INTO `Sys_City` VALUES (62, '230100', '哈尔滨市', '230000'); +INSERT INTO `Sys_City` VALUES (63, '230200', '齐齐哈尔市', '230000'); +INSERT INTO `Sys_City` VALUES (64, '230300', '鸡西市', '230000'); +INSERT INTO `Sys_City` VALUES (65, '230400', '鹤岗市', '230000'); +INSERT INTO `Sys_City` VALUES (66, '230500', '双鸭山市', '230000'); +INSERT INTO `Sys_City` VALUES (67, '230600', '大庆市', '230000'); +INSERT INTO `Sys_City` VALUES (68, '230700', '伊春市', '230000'); +INSERT INTO `Sys_City` VALUES (69, '230800', '佳木斯市', '230000'); +INSERT INTO `Sys_City` VALUES (70, '230900', '七台河市', '230000'); +INSERT INTO `Sys_City` VALUES (71, '231000', '牡丹江市', '230000'); +INSERT INTO `Sys_City` VALUES (72, '231100', '黑河市', '230000'); +INSERT INTO `Sys_City` VALUES (73, '231200', '绥化市', '230000'); +INSERT INTO `Sys_City` VALUES (74, '232700', '大兴安岭地区', '230000'); +INSERT INTO `Sys_City` VALUES (75, '310100', '市辖区', '310000'); +INSERT INTO `Sys_City` VALUES (76, '310200', '县', '310000'); +INSERT INTO `Sys_City` VALUES (77, '320100', '南京市', '320000'); +INSERT INTO `Sys_City` VALUES (78, '320200', '无锡市', '320000'); +INSERT INTO `Sys_City` VALUES (79, '320300', '徐州市', '320000'); +INSERT INTO `Sys_City` VALUES (80, '320400', '常州市', '320000'); +INSERT INTO `Sys_City` VALUES (81, '320500', '苏州市', '320000'); +INSERT INTO `Sys_City` VALUES (82, '320600', '南通市', '320000'); +INSERT INTO `Sys_City` VALUES (83, '320700', '连云港市', '320000'); +INSERT INTO `Sys_City` VALUES (84, '320800', '淮安市', '320000'); +INSERT INTO `Sys_City` VALUES (85, '320900', '盐城市', '320000'); +INSERT INTO `Sys_City` VALUES (86, '321000', '扬州市', '320000'); +INSERT INTO `Sys_City` VALUES (87, '321100', '镇江市', '320000'); +INSERT INTO `Sys_City` VALUES (88, '321200', '泰州市', '320000'); +INSERT INTO `Sys_City` VALUES (89, '321300', '宿迁市', '320000'); +INSERT INTO `Sys_City` VALUES (90, '330100', '杭州市', '330000'); +INSERT INTO `Sys_City` VALUES (91, '330200', '宁波市', '330000'); +INSERT INTO `Sys_City` VALUES (92, '330300', '温州市', '330000'); +INSERT INTO `Sys_City` VALUES (93, '330400', '嘉兴市', '330000'); +INSERT INTO `Sys_City` VALUES (94, '330500', '湖州市', '330000'); +INSERT INTO `Sys_City` VALUES (95, '330600', '绍兴市', '330000'); +INSERT INTO `Sys_City` VALUES (96, '330700', '金华市', '330000'); +INSERT INTO `Sys_City` VALUES (97, '330800', '衢州市', '330000'); +INSERT INTO `Sys_City` VALUES (98, '330900', '舟山市', '330000'); +INSERT INTO `Sys_City` VALUES (99, '331000', '台州市', '330000'); +INSERT INTO `Sys_City` VALUES (100, '331100', '丽水市', '330000'); +INSERT INTO `Sys_City` VALUES (101, '340100', '合肥市', '340000'); +INSERT INTO `Sys_City` VALUES (102, '340200', '芜湖市', '340000'); +INSERT INTO `Sys_City` VALUES (103, '340300', '蚌埠市', '340000'); +INSERT INTO `Sys_City` VALUES (104, '340400', '淮南市', '340000'); +INSERT INTO `Sys_City` VALUES (105, '340500', '马鞍山市', '340000'); +INSERT INTO `Sys_City` VALUES (106, '340600', '淮北市', '340000'); +INSERT INTO `Sys_City` VALUES (107, '340700', '铜陵市', '340000'); +INSERT INTO `Sys_City` VALUES (108, '340800', '安庆市', '340000'); +INSERT INTO `Sys_City` VALUES (109, '341000', '黄山市', '340000'); +INSERT INTO `Sys_City` VALUES (110, '341100', '滁州市', '340000'); +INSERT INTO `Sys_City` VALUES (111, '341200', '阜阳市', '340000'); +INSERT INTO `Sys_City` VALUES (112, '341300', '宿州市', '340000'); +INSERT INTO `Sys_City` VALUES (113, '341400', '巢湖市', '340000'); +INSERT INTO `Sys_City` VALUES (114, '341500', '六安市', '340000'); +INSERT INTO `Sys_City` VALUES (115, '341600', '亳州市', '340000'); +INSERT INTO `Sys_City` VALUES (116, '341700', '池州市', '340000'); +INSERT INTO `Sys_City` VALUES (117, '341800', '宣城市', '340000'); +INSERT INTO `Sys_City` VALUES (118, '350100', '福州市', '350000'); +INSERT INTO `Sys_City` VALUES (119, '350200', '厦门市', '350000'); +INSERT INTO `Sys_City` VALUES (120, '350300', '莆田市', '350000'); +INSERT INTO `Sys_City` VALUES (121, '350400', '三明市', '350000'); +INSERT INTO `Sys_City` VALUES (122, '350500', '泉州市', '350000'); +INSERT INTO `Sys_City` VALUES (123, '350600', '漳州市', '350000'); +INSERT INTO `Sys_City` VALUES (124, '350700', '南平市', '350000'); +INSERT INTO `Sys_City` VALUES (125, '350800', '龙岩市', '350000'); +INSERT INTO `Sys_City` VALUES (126, '350900', '宁德市', '350000'); +INSERT INTO `Sys_City` VALUES (127, '360100', '南昌市', '360000'); +INSERT INTO `Sys_City` VALUES (128, '360200', '景德镇市', '360000'); +INSERT INTO `Sys_City` VALUES (129, '360300', '萍乡市', '360000'); +INSERT INTO `Sys_City` VALUES (130, '360400', '九江市', '360000'); +INSERT INTO `Sys_City` VALUES (131, '360500', '新余市', '360000'); +INSERT INTO `Sys_City` VALUES (132, '360600', '鹰潭市', '360000'); +INSERT INTO `Sys_City` VALUES (133, '360700', '赣州市', '360000'); +INSERT INTO `Sys_City` VALUES (134, '360800', '吉安市', '360000'); +INSERT INTO `Sys_City` VALUES (135, '360900', '宜春市', '360000'); +INSERT INTO `Sys_City` VALUES (136, '361000', '抚州市', '360000'); +INSERT INTO `Sys_City` VALUES (137, '361100', '上饶市', '360000'); +INSERT INTO `Sys_City` VALUES (138, '370100', '济南市', '370000'); +INSERT INTO `Sys_City` VALUES (139, '370200', '青岛市', '370000'); +INSERT INTO `Sys_City` VALUES (140, '370300', '淄博市', '370000'); +INSERT INTO `Sys_City` VALUES (141, '370400', '枣庄市', '370000'); +INSERT INTO `Sys_City` VALUES (142, '370500', '东营市', '370000'); +INSERT INTO `Sys_City` VALUES (143, '370600', '烟台市', '370000'); +INSERT INTO `Sys_City` VALUES (144, '370700', '潍坊市', '370000'); +INSERT INTO `Sys_City` VALUES (145, '370800', '济宁市', '370000'); +INSERT INTO `Sys_City` VALUES (146, '370900', '泰安市', '370000'); +INSERT INTO `Sys_City` VALUES (147, '371000', '威海市', '370000'); +INSERT INTO `Sys_City` VALUES (148, '371100', '日照市', '370000'); +INSERT INTO `Sys_City` VALUES (149, '371200', '莱芜市', '370000'); +INSERT INTO `Sys_City` VALUES (150, '371300', '临沂市', '370000'); +INSERT INTO `Sys_City` VALUES (151, '371400', '德州市', '370000'); +INSERT INTO `Sys_City` VALUES (152, '371500', '聊城市', '370000'); +INSERT INTO `Sys_City` VALUES (153, '371600', '滨州市', '370000'); +INSERT INTO `Sys_City` VALUES (154, '371700', '荷泽市', '370000'); +INSERT INTO `Sys_City` VALUES (155, '410100', '郑州市', '410000'); +INSERT INTO `Sys_City` VALUES (156, '410200', '开封市', '410000'); +INSERT INTO `Sys_City` VALUES (157, '410300', '洛阳市', '410000'); +INSERT INTO `Sys_City` VALUES (158, '410400', '平顶山市', '410000'); +INSERT INTO `Sys_City` VALUES (159, '410500', '安阳市', '410000'); +INSERT INTO `Sys_City` VALUES (160, '410600', '鹤壁市', '410000'); +INSERT INTO `Sys_City` VALUES (161, '410700', '新乡市', '410000'); +INSERT INTO `Sys_City` VALUES (162, '410800', '焦作市', '410000'); +INSERT INTO `Sys_City` VALUES (163, '410900', '濮阳市', '410000'); +INSERT INTO `Sys_City` VALUES (164, '411000', '许昌市', '410000'); +INSERT INTO `Sys_City` VALUES (165, '411100', '漯河市', '410000'); +INSERT INTO `Sys_City` VALUES (166, '411200', '三门峡市', '410000'); +INSERT INTO `Sys_City` VALUES (167, '411300', '南阳市', '410000'); +INSERT INTO `Sys_City` VALUES (168, '411400', '商丘市', '410000'); +INSERT INTO `Sys_City` VALUES (169, '411500', '信阳市', '410000'); +INSERT INTO `Sys_City` VALUES (170, '411600', '周口市', '410000'); +INSERT INTO `Sys_City` VALUES (171, '411700', '驻马店市', '410000'); +INSERT INTO `Sys_City` VALUES (172, '420100', '武汉市', '420000'); +INSERT INTO `Sys_City` VALUES (173, '420200', '黄石市', '420000'); +INSERT INTO `Sys_City` VALUES (174, '420300', '十堰市', '420000'); +INSERT INTO `Sys_City` VALUES (175, '420500', '宜昌市', '420000'); +INSERT INTO `Sys_City` VALUES (176, '420600', '襄樊市', '420000'); +INSERT INTO `Sys_City` VALUES (177, '420700', '鄂州市', '420000'); +INSERT INTO `Sys_City` VALUES (178, '420800', '荆门市', '420000'); +INSERT INTO `Sys_City` VALUES (179, '420900', '孝感市', '420000'); +INSERT INTO `Sys_City` VALUES (180, '421000', '荆州市', '420000'); +INSERT INTO `Sys_City` VALUES (181, '421100', '黄冈市', '420000'); +INSERT INTO `Sys_City` VALUES (182, '421200', '咸宁市', '420000'); +INSERT INTO `Sys_City` VALUES (183, '421300', '随州市', '420000'); +INSERT INTO `Sys_City` VALUES (184, '422800', '恩施土家族苗族自治州', '420000'); +INSERT INTO `Sys_City` VALUES (185, '429000', '省直辖行政单位', '420000'); +INSERT INTO `Sys_City` VALUES (186, '430100', '长沙市', '430000'); +INSERT INTO `Sys_City` VALUES (187, '430200', '株洲市', '430000'); +INSERT INTO `Sys_City` VALUES (188, '430300', '湘潭市', '430000'); +INSERT INTO `Sys_City` VALUES (189, '430400', '衡阳市', '430000'); +INSERT INTO `Sys_City` VALUES (190, '430500', '邵阳市', '430000'); +INSERT INTO `Sys_City` VALUES (191, '430600', '岳阳市', '430000'); +INSERT INTO `Sys_City` VALUES (192, '430700', '常德市', '430000'); +INSERT INTO `Sys_City` VALUES (193, '430800', '张家界市', '430000'); +INSERT INTO `Sys_City` VALUES (194, '430900', '益阳市', '430000'); +INSERT INTO `Sys_City` VALUES (195, '431000', '郴州市', '430000'); +INSERT INTO `Sys_City` VALUES (196, '431100', '永州市', '430000'); +INSERT INTO `Sys_City` VALUES (197, '431200', '怀化市', '430000'); +INSERT INTO `Sys_City` VALUES (198, '431300', '娄底市', '430000'); +INSERT INTO `Sys_City` VALUES (199, '433100', '湘西土家族苗族自治州', '430000'); +INSERT INTO `Sys_City` VALUES (200, '440100', '广州市', '440000'); +INSERT INTO `Sys_City` VALUES (201, '440200', '韶关市', '440000'); +INSERT INTO `Sys_City` VALUES (202, '440300', '深圳市', '440000'); +INSERT INTO `Sys_City` VALUES (203, '440400', '珠海市', '440000'); +INSERT INTO `Sys_City` VALUES (204, '440500', '汕头市', '440000'); +INSERT INTO `Sys_City` VALUES (205, '440600', '佛山市', '440000'); +INSERT INTO `Sys_City` VALUES (206, '440700', '江门市', '440000'); +INSERT INTO `Sys_City` VALUES (207, '440800', '湛江市', '440000'); +INSERT INTO `Sys_City` VALUES (208, '440900', '茂名市', '440000'); +INSERT INTO `Sys_City` VALUES (209, '441200', '肇庆市', '440000'); +INSERT INTO `Sys_City` VALUES (210, '441300', '惠州市', '440000'); +INSERT INTO `Sys_City` VALUES (211, '441400', '梅州市', '440000'); +INSERT INTO `Sys_City` VALUES (212, '441500', '汕尾市', '440000'); +INSERT INTO `Sys_City` VALUES (213, '441600', '河源市', '440000'); +INSERT INTO `Sys_City` VALUES (214, '441700', '阳江市', '440000'); +INSERT INTO `Sys_City` VALUES (215, '441800', '清远市', '440000'); +INSERT INTO `Sys_City` VALUES (216, '441900', '东莞市', '440000'); +INSERT INTO `Sys_City` VALUES (217, '442000', '中山市', '440000'); +INSERT INTO `Sys_City` VALUES (218, '445100', '潮州市', '440000'); +INSERT INTO `Sys_City` VALUES (219, '445200', '揭阳市', '440000'); +INSERT INTO `Sys_City` VALUES (220, '445300', '云浮市', '440000'); +INSERT INTO `Sys_City` VALUES (221, '450100', '南宁市', '450000'); +INSERT INTO `Sys_City` VALUES (222, '450200', '柳州市', '450000'); +INSERT INTO `Sys_City` VALUES (223, '450300', '桂林市', '450000'); +INSERT INTO `Sys_City` VALUES (224, '450400', '梧州市', '450000'); +INSERT INTO `Sys_City` VALUES (225, '450500', '北海市', '450000'); +INSERT INTO `Sys_City` VALUES (226, '450600', '防城港市', '450000'); +INSERT INTO `Sys_City` VALUES (227, '450700', '钦州市', '450000'); +INSERT INTO `Sys_City` VALUES (228, '450800', '贵港市', '450000'); +INSERT INTO `Sys_City` VALUES (229, '450900', '玉林市', '450000'); +INSERT INTO `Sys_City` VALUES (230, '451000', '百色市', '450000'); +INSERT INTO `Sys_City` VALUES (231, '451100', '贺州市', '450000'); +INSERT INTO `Sys_City` VALUES (232, '451200', '河池市', '450000'); +INSERT INTO `Sys_City` VALUES (233, '451300', '来宾市', '450000'); +INSERT INTO `Sys_City` VALUES (234, '451400', '崇左市', '450000'); +INSERT INTO `Sys_City` VALUES (235, '460100', '海口市', '460000'); +INSERT INTO `Sys_City` VALUES (236, '460200', '三亚市', '460000'); +INSERT INTO `Sys_City` VALUES (237, '469000', '省直辖县级行政单位', '460000'); +INSERT INTO `Sys_City` VALUES (238, '500100', '市辖区', '500000'); +INSERT INTO `Sys_City` VALUES (239, '500200', '县', '500000'); +INSERT INTO `Sys_City` VALUES (240, '500300', '市', '500000'); +INSERT INTO `Sys_City` VALUES (241, '510100', '成都市', '510000'); +INSERT INTO `Sys_City` VALUES (242, '510300', '自贡市', '510000'); +INSERT INTO `Sys_City` VALUES (243, '510400', '攀枝花市', '510000'); +INSERT INTO `Sys_City` VALUES (244, '510500', '泸州市', '510000'); +INSERT INTO `Sys_City` VALUES (245, '510600', '德阳市', '510000'); +INSERT INTO `Sys_City` VALUES (246, '510700', '绵阳市', '510000'); +INSERT INTO `Sys_City` VALUES (247, '510800', '广元市', '510000'); +INSERT INTO `Sys_City` VALUES (248, '510900', '遂宁市', '510000'); +INSERT INTO `Sys_City` VALUES (249, '511000', '内江市', '510000'); +INSERT INTO `Sys_City` VALUES (250, '511100', '乐山市', '510000'); +INSERT INTO `Sys_City` VALUES (251, '511300', '南充市', '510000'); +INSERT INTO `Sys_City` VALUES (252, '511400', '眉山市', '510000'); +INSERT INTO `Sys_City` VALUES (253, '511500', '宜宾市', '510000'); +INSERT INTO `Sys_City` VALUES (254, '511600', '广安市', '510000'); +INSERT INTO `Sys_City` VALUES (255, '511700', '达州市', '510000'); +INSERT INTO `Sys_City` VALUES (256, '511800', '雅安市', '510000'); +INSERT INTO `Sys_City` VALUES (257, '511900', '巴中市', '510000'); +INSERT INTO `Sys_City` VALUES (258, '512000', '资阳市', '510000'); +INSERT INTO `Sys_City` VALUES (259, '513200', '阿坝藏族羌族自治州', '510000'); +INSERT INTO `Sys_City` VALUES (260, '513300', '甘孜藏族自治州', '510000'); +INSERT INTO `Sys_City` VALUES (261, '513400', '凉山彝族自治州', '510000'); +INSERT INTO `Sys_City` VALUES (262, '520100', '贵阳市', '520000'); +INSERT INTO `Sys_City` VALUES (263, '520200', '六盘水市', '520000'); +INSERT INTO `Sys_City` VALUES (264, '520300', '遵义市', '520000'); +INSERT INTO `Sys_City` VALUES (265, '520400', '安顺市', '520000'); +INSERT INTO `Sys_City` VALUES (266, '522200', '铜仁地区', '520000'); +INSERT INTO `Sys_City` VALUES (267, '522300', '黔西南布依族苗族自治州', '520000'); +INSERT INTO `Sys_City` VALUES (268, '522400', '毕节地区', '520000'); +INSERT INTO `Sys_City` VALUES (269, '522600', '黔东南苗族侗族自治州', '520000'); +INSERT INTO `Sys_City` VALUES (270, '522700', '黔南布依族苗族自治州', '520000'); +INSERT INTO `Sys_City` VALUES (271, '530100', '昆明市', '530000'); +INSERT INTO `Sys_City` VALUES (272, '530300', '曲靖市', '530000'); +INSERT INTO `Sys_City` VALUES (273, '530400', '玉溪市', '530000'); +INSERT INTO `Sys_City` VALUES (274, '530500', '保山市', '530000'); +INSERT INTO `Sys_City` VALUES (275, '530600', '昭通市', '530000'); +INSERT INTO `Sys_City` VALUES (276, '530700', '丽江市', '530000'); +INSERT INTO `Sys_City` VALUES (277, '530800', '思茅市', '530000'); +INSERT INTO `Sys_City` VALUES (278, '530900', '临沧市', '530000'); +INSERT INTO `Sys_City` VALUES (279, '532300', '楚雄彝族自治州', '530000'); +INSERT INTO `Sys_City` VALUES (280, '532500', '红河哈尼族彝族自治州', '530000'); +INSERT INTO `Sys_City` VALUES (281, '532600', '文山壮族苗族自治州', '530000'); +INSERT INTO `Sys_City` VALUES (282, '532800', '西双版纳傣族自治州', '530000'); +INSERT INTO `Sys_City` VALUES (283, '532900', '大理白族自治州', '530000'); +INSERT INTO `Sys_City` VALUES (284, '533100', '德宏傣族景颇族自治州', '530000'); +INSERT INTO `Sys_City` VALUES (285, '533300', '怒江傈僳族自治州', '530000'); +INSERT INTO `Sys_City` VALUES (286, '533400', '迪庆藏族自治州', '530000'); +INSERT INTO `Sys_City` VALUES (287, '540100', '拉萨市', '540000'); +INSERT INTO `Sys_City` VALUES (288, '542100', '昌都地区', '540000'); +INSERT INTO `Sys_City` VALUES (289, '542200', '山南地区', '540000'); +INSERT INTO `Sys_City` VALUES (290, '542300', '日喀则地区', '540000'); +INSERT INTO `Sys_City` VALUES (291, '542400', '那曲地区', '540000'); +INSERT INTO `Sys_City` VALUES (292, '542500', '阿里地区', '540000'); +INSERT INTO `Sys_City` VALUES (293, '542600', '林芝地区', '540000'); +INSERT INTO `Sys_City` VALUES (294, '610100', '西安市', '610000'); +INSERT INTO `Sys_City` VALUES (295, '610200', '铜川市', '610000'); +INSERT INTO `Sys_City` VALUES (296, '610300', '宝鸡市', '610000'); +INSERT INTO `Sys_City` VALUES (297, '610400', '咸阳市', '610000'); +INSERT INTO `Sys_City` VALUES (298, '610500', '渭南市', '610000'); +INSERT INTO `Sys_City` VALUES (299, '610600', '延安市', '610000'); +INSERT INTO `Sys_City` VALUES (300, '610700', '汉中市', '610000'); +INSERT INTO `Sys_City` VALUES (301, '610800', '榆林市', '610000'); +INSERT INTO `Sys_City` VALUES (302, '610900', '安康市', '610000'); +INSERT INTO `Sys_City` VALUES (303, '611000', '商洛市', '610000'); +INSERT INTO `Sys_City` VALUES (304, '620100', '兰州市', '620000'); +INSERT INTO `Sys_City` VALUES (305, '620200', '嘉峪关市', '620000'); +INSERT INTO `Sys_City` VALUES (306, '620300', '金昌市', '620000'); +INSERT INTO `Sys_City` VALUES (307, '620400', '白银市', '620000'); +INSERT INTO `Sys_City` VALUES (308, '620500', '天水市', '620000'); +INSERT INTO `Sys_City` VALUES (309, '620600', '武威市', '620000'); +INSERT INTO `Sys_City` VALUES (310, '620700', '张掖市', '620000'); +INSERT INTO `Sys_City` VALUES (311, '620800', '平凉市', '620000'); +INSERT INTO `Sys_City` VALUES (312, '620900', '酒泉市', '620000'); +INSERT INTO `Sys_City` VALUES (313, '621000', '庆阳市', '620000'); +INSERT INTO `Sys_City` VALUES (314, '621100', '定西市', '620000'); +INSERT INTO `Sys_City` VALUES (315, '621200', '陇南市', '620000'); +INSERT INTO `Sys_City` VALUES (316, '622900', '临夏回族自治州', '620000'); +INSERT INTO `Sys_City` VALUES (317, '623000', '甘南藏族自治州', '620000'); +INSERT INTO `Sys_City` VALUES (318, '630100', '西宁市', '630000'); +INSERT INTO `Sys_City` VALUES (319, '632100', '海东地区', '630000'); +INSERT INTO `Sys_City` VALUES (320, '632200', '海北藏族自治州', '630000'); +INSERT INTO `Sys_City` VALUES (321, '632300', '黄南藏族自治州', '630000'); +INSERT INTO `Sys_City` VALUES (322, '632500', '海南藏族自治州', '630000'); +INSERT INTO `Sys_City` VALUES (323, '632600', '果洛藏族自治州', '630000'); +INSERT INTO `Sys_City` VALUES (324, '632700', '玉树藏族自治州', '630000'); +INSERT INTO `Sys_City` VALUES (325, '632800', '海西蒙古族藏族自治州', '630000'); +INSERT INTO `Sys_City` VALUES (326, '640100', '银川市', '640000'); +INSERT INTO `Sys_City` VALUES (327, '640200', '石嘴山市', '640000'); +INSERT INTO `Sys_City` VALUES (328, '640300', '吴忠市', '640000'); +INSERT INTO `Sys_City` VALUES (329, '640400', '固原市', '640000'); +INSERT INTO `Sys_City` VALUES (330, '640500', '中卫市', '640000'); +INSERT INTO `Sys_City` VALUES (331, '650100', '乌鲁木齐市', '650000'); +INSERT INTO `Sys_City` VALUES (332, '650200', '克拉玛依市', '650000'); +INSERT INTO `Sys_City` VALUES (333, '652100', '吐鲁番地区', '650000'); +INSERT INTO `Sys_City` VALUES (334, '652200', '哈密地区', '650000'); +INSERT INTO `Sys_City` VALUES (335, '652300', '昌吉回族自治州', '650000'); +INSERT INTO `Sys_City` VALUES (336, '652700', '博尔塔拉蒙古自治州', '650000'); +INSERT INTO `Sys_City` VALUES (337, '652800', '巴音郭楞蒙古自治州', '650000'); +INSERT INTO `Sys_City` VALUES (338, '652900', '阿克苏地区', '650000'); +INSERT INTO `Sys_City` VALUES (339, '653000', '克孜勒苏柯尔克孜自治州', '650000'); +INSERT INTO `Sys_City` VALUES (340, '653100', '喀什地区', '650000'); +INSERT INTO `Sys_City` VALUES (341, '653200', '和田地区', '650000'); +INSERT INTO `Sys_City` VALUES (342, '654000', '伊犁哈萨克自治州', '650000'); +INSERT INTO `Sys_City` VALUES (343, '654200', '塔城地区', '650000'); +INSERT INTO `Sys_City` VALUES (344, '654300', '阿勒泰地区', '650000'); +INSERT INTO `Sys_City` VALUES (345, '659000', '省直辖行政单位', '650000'); + +-- ---------------------------- +-- Table structure for Sys_Dictionary +-- ---------------------------- +DROP TABLE IF EXISTS `Sys_Dictionary`; +CREATE TABLE `Sys_Dictionary` ( + `Dic_ID` int(11) NOT NULL AUTO_INCREMENT, + `Config` varchar(4000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `CreateDate` datetime(0) NULL DEFAULT NULL, + `CreateID` int(11) NULL DEFAULT NULL, + `Creator` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `DBServer` varchar(4000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `DbSql` varchar(4000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `DicName` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `DicNo` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `Enable` tinyint(4) NOT NULL, + `Modifier` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `ModifyDate` datetime(0) NULL DEFAULT NULL, + `ModifyID` int(11) NULL DEFAULT NULL, + `OrderNo` int(11) NULL DEFAULT NULL, + `ParentId` int(11) NOT NULL, + `Remark` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`Dic_ID`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 76 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = COMPACT; + +-- ---------------------------- +-- Records of Sys_Dictionary +-- ---------------------------- +INSERT INTO `Sys_Dictionary` VALUES (3, '{valueField: \'Enable\',\ntextField: \'Enable\',\n containField: null,\n handler: null }', '2019-07-05 17:36:23', NULL, 'admin', '1', NULL, '是否值', 'enable', 1, '超级管理员', '2022-08-03 15:59:01', 1, NULL, 0, NULL); +INSERT INTO `Sys_Dictionary` VALUES (30, '{valueField: \'Success\',\n textField: \'Success\', \n containField: null,\n handler: null }\n', '2018-06-11 18:26:05', 0, '测试超级管理员', NULL, NULL, '响应状态', 'restatus', 1, '测试超级管理员', '2018-06-12 10:21:48', 1, NULL, 0, NULL); +INSERT INTO `Sys_Dictionary` VALUES (31, '{valueField: \'LogType\',\n textField: \'LogType\', \n containField: null,\n handler: null }\n', '2018-06-12 14:46:07', NULL, '测试超级管理员', NULL, NULL, '日志类型', 'log', 1, '超级管理员', '2022-02-21 12:43:18', 1, NULL, 1, NULL); +INSERT INTO `Sys_Dictionary` VALUES (32, '{valueField: \'Role_Id\',\n textField: \'RoleName\', \n containField: [\'Role_Id\',\'RoleName\'],\n handler: null }\n', '2018-06-14 16:48:35', NULL, '测试超级管理员', NULL, 'SELECT Role_Id as \'key\',RoleName as \'value\' FROM Sys_Role WHERE Enable=1\n', '角色列表', 'roles', 1, '测试超级管理员', '2018-07-13 15:03:53', 1, 123, 0, 'sql语句需要key,value列,界面才能绑定数据源'); +INSERT INTO `Sys_Dictionary` VALUES (35, '{\n valueField: \'AuditStatus\',\n textField: \'AuditStatus\',\n containField:null \n}', '2018-07-10 10:51:37', NULL, '测试超级管理员', NULL, NULL, '审核状态', 'audit', 1, '演示帐号', '2020-09-10 11:42:31', 3362, NULL, 0, NULL); +INSERT INTO `Sys_Dictionary` VALUES (36, '{\n valueField: \'Variety\',\n textField: \'Variety\',\n containField:null \n}', '2018-07-10 14:06:12', 1, '测试超级管理员', NULL, NULL, '分类', 'pz', 1, '超级管理员', '2022-03-26 02:18:40', 1, NULL, 0, NULL); +INSERT INTO `Sys_Dictionary` VALUES (37, '{\n valueField: \'AgeRange\',\n textField: \'AgeRange\',\n containField:null \n}', '2018-07-10 14:07:46', NULL, '测试超级管理员', NULL, NULL, '值范围', 'age', 1, '超级管理员', '2022-03-26 02:18:48', 1, NULL, 0, NULL); +INSERT INTO `Sys_Dictionary` VALUES (38, '{\n valueField: \'City\',\n textField: \'City\',\n containField:null \n}', '2018-07-10 14:18:25', NULL, '测试超级管理员', NULL, 'SELECT CASE WHEN CityName=\'市辖区\' THEN ProvinceName ELSE CityName end as \'key\',CASE WHEN CityName=\'市辖区\' THEN ProvinceName ELSE CityName end as \'value\' FROM Sys_City AS a \nINNER JOIN Sys_Province AS b \nON a.ProvinceCode=b.ProvinceCode\nWHERE a.CityName<> \'县\'', '城市', 'city', 1, '测试超级管理员', '2018-07-16 17:03:50', 1, NULL, 0, NULL); +INSERT INTO `Sys_Dictionary` VALUES (44, '{\n valueField: \'NewsType\',\n textField: \'NewsType\',\n containField:null \n}', '2018-07-10 16:15:59', 1, '测试超级管理员', NULL, NULL, '新闻类型', 'news', 1, '超级管理员', '2022-06-27 13:46:28', 1, NULL, 0, NULL); +INSERT INTO `Sys_Dictionary` VALUES (45, '{\n valueField: \'Expire\',\n textField: \'Expire\',\n containField:null \n}', '2018-07-10 16:38:40', 1, '测试超级管理员', NULL, NULL, '是否过期', 'expire', 1, NULL, NULL, NULL, NULL, 0, NULL); +INSERT INTO `Sys_Dictionary` VALUES (46, '{\n valueField: \'ProvinceName\',\n textField: \'ProvinceName\',\n containField:null \n}', '2018-07-16 13:27:34', NULL, '测试超级管理员', NULL, 'SELECT CASE WHEN CityName=\'市辖区\' THEN ProvinceName ELSE CityName end as \'key\',CASE WHEN CityName=\'市辖区\' THEN ProvinceName ELSE CityName end as \'value\' FROM Sys_City AS a \nINNER JOIN Sys_Province AS b \nON a.ProvinceCode=b.ProvinceCode\nWHERE a.CityName<> \'县\'', '省列表', 'pro', 1, '测试超级管理员', '2018-07-23 15:23:21', 1, NULL, 0, 'sql语句需要key,value列,界面才能绑定数据源'); +INSERT INTO `Sys_Dictionary` VALUES (48, '{\n valueField: \'ClassifyId\',\n textField: \'ClassifyTitle\',\n containField:null \n}', '2018-07-18 10:16:22', NULL, '测试超级管理员', NULL, NULL, '是否买入', 'nav', 1, '超级管理员', '2019-09-18 18:09:42', 1, NULL, 0, NULL); +INSERT INTO `Sys_Dictionary` VALUES (49, '{\n valueField: \'Gender\',\n textField: \'Gender\',\n containField:null \n}', '2018-07-23 10:04:45', NULL, '测试超级管理员', NULL, NULL, '性别', 'gender', 1, '测试超级管理员', '2018-07-23 11:10:28', 1, NULL, 0, NULL); +INSERT INTO `Sys_Dictionary` VALUES (50, '{\n valueField: \'Enable\',\n textField: \'Enable\',\n containField:null \n}', '2018-07-23 15:36:43', 1, '测试超级管理员', NULL, NULL, '启用状态', 'status', 1, NULL, NULL, NULL, NULL, 0, NULL); +INSERT INTO `Sys_Dictionary` VALUES (52, '{\n valueField: \'Choiceness\',\n textField: \'Choiceness\',\n containField:null \n}', '2018-07-24 15:45:47', 1, '测试超级管理员', NULL, NULL, '是否买入', 'cq', 1, '超级管理员', '2022-03-26 23:07:16', 1, NULL, 0, NULL); +INSERT INTO `Sys_Dictionary` VALUES (59, '{\n valueField: \'IsRegregisterPhone\',\n textField: \'IsRegregisterPhone\',\n containField:null \n}', '2018-08-29 15:54:21', 1, '测试超级管理员', NULL, NULL, 'test', 'isphone', 1, '超级管理员', '2020-12-19 18:02:55', 1, NULL, 0, NULL); +INSERT INTO `Sys_Dictionary` VALUES (62, '{\n valueField: \'IsTop\',\n textField: \'IsTop\',\n containField:null \n}', '2019-08-20 09:57:54', 1, '超级管理员', NULL, NULL, 'test1', 'top', 1, '超级管理员', '2022-01-03 19:13:37', 1, NULL, 1, 'dddd'); +INSERT INTO `Sys_Dictionary` VALUES (64, NULL, '2019-09-18 19:25:47', 1, '超级管理员', NULL, NULL, '订单类型', 'ordertype', 1, NULL, NULL, NULL, NULL, 0, NULL); +INSERT INTO `Sys_Dictionary` VALUES (65, NULL, '2019-09-19 10:07:23', 1, '超级管理员', NULL, NULL, '商品名称', 'pn', 1, '超级管理员', '2022-07-12 10:55:23', 1, NULL, 0, NULL); +INSERT INTO `Sys_Dictionary` VALUES (66, NULL, '2020-05-08 09:42:50', 1, '超级管理员', NULL, NULL, 'dr', 'dr', 1, NULL, NULL, NULL, NULL, 0, NULL); +INSERT INTO `Sys_Dictionary` VALUES (67, NULL, '2020-05-30 19:48:29', 1, '超级管理员', NULL, NULL, '获取所有角色Table显示用', 't_roles', 1, '超级管理员', '2020-05-30 19:48:36', 1, NULL, 0, NULL); +INSERT INTO `Sys_Dictionary` VALUES (69, NULL, '2020-09-18 23:13:42', 1, '超级管理员', NULL, NULL, '11', 'test111', 1, '超级管理员', '2022-06-16 11:00:09', 1, 1, 0, NULL); +INSERT INTO `Sys_Dictionary` VALUES (70, NULL, '2020-11-02 19:18:08', 1, '超级管理员', NULL, 'SELECT Role_Id AS id,parentId,Role_Id AS `key`,RoleName AS `value` FROM Sys_Role', '级联角色', 'tree_roles', 1, '超级管理员', '2021-02-28 14:35:35', 1, NULL, 0, NULL); +INSERT INTO `Sys_Dictionary` VALUES (75, NULL, '2022-01-03 19:31:24', 1, '超级管理员', NULL, NULL, '满意度', '满意度', 1, '超级管理员', '2022-03-26 23:07:19', 1, NULL, 0, NULL); + +-- ---------------------------- +-- Table structure for Sys_DictionaryList +-- ---------------------------- +DROP TABLE IF EXISTS `Sys_DictionaryList`; +CREATE TABLE `Sys_DictionaryList` ( + `DicList_ID` int(11) NOT NULL AUTO_INCREMENT, + `CreateDate` datetime(0) NULL DEFAULT NULL, + `CreateID` int(11) NULL DEFAULT NULL, + `Creator` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `DicName` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `DicValue` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `Dic_ID` int(11) NULL DEFAULT NULL, + `Enable` tinyint(4) NULL DEFAULT NULL, + `Modifier` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `ModifyDate` datetime(0) NULL DEFAULT NULL, + `ModifyID` int(11) NULL DEFAULT NULL, + `OrderNo` int(11) NULL DEFAULT NULL, + `Remark` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`DicList_ID`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 183 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = COMPACT; + +-- ---------------------------- +-- Records of Sys_DictionaryList +-- ---------------------------- +INSERT INTO `Sys_DictionaryList` VALUES (3, NULL, 1, 'admin', '否', '0', 3, NULL, '超级管理员', '2022-08-03 15:59:01', 1, 2, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (4, NULL, 1, 'xxx', '是', '1', 3, NULL, '超级管理员', '2022-08-03 15:59:01', 1, 1, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (22, '2018-06-11 18:26:05', 1, '测试超级管理员', '其他', '0', 30, NULL, '超级管理员', '2019-08-21 16:49:43', 1, 10, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (23, '2018-06-11 18:26:05', 1, '测试超级管理员', '成功', '1', 30, NULL, '超级管理员', '2019-08-21 16:49:43', 1, 100, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (24, '2018-06-12 09:41:58', 1, '测试超级管理员', '异常', '2', 30, NULL, '超级管理员', '2019-08-21 16:49:43', 1, 50, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (25, '2018-06-12 14:46:08', 1, '测试超级管理员', '系统', 'System', 31, NULL, '超级管理员', '2022-02-21 12:43:18', 1, 100, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (26, '2018-06-12 14:47:32', 1, '测试超级管理员', '登陆', 'Login', 31, NULL, '超级管理员', '2022-02-21 12:43:18', 1, 90, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (27, '2018-06-15 15:29:58', 1, '测试超级管理员', '新建', 'Add', 31, NULL, '超级管理员', '2022-02-21 12:43:18', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (28, '2018-06-15 15:29:58', 1, '测试超级管理员', '删除', 'Del', 31, 1, '超级管理员', '2022-02-21 12:43:18', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (29, '2018-06-15 15:30:34', 1, '测试超级管理员', '编辑', 'Edit', 31, 1, '超级管理员', '2022-02-21 12:43:18', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (37, '2018-07-10 10:51:38', 1, '测试超级管理员', '审核中', '0', 35, NULL, '演示帐号', '2020-09-10 11:42:31', 3362, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (38, '2018-07-10 10:51:38', 1, '测试超级管理员', '审核通过', '1', 35, NULL, '演示帐号', '2020-09-10 11:42:31', 3362, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (39, '2018-07-10 10:51:38', 1, '测试超级管理员', '审核未通过', '2', 35, NULL, '演示帐号', '2020-09-10 11:42:31', 3362, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (40, '2018-07-10 14:06:13', 1, '测试超级管理员', '数码相框', '数码相框', 36, 0, '超级管理员', '2022-03-26 02:18:40', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (41, '2018-07-10 14:06:13', 1, '测试超级管理员', '影棚器材', '影棚器材', 36, 0, '超级管理员', '2022-03-26 02:18:40', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (42, '2018-07-10 14:06:13', 1, '测试超级管理员', '户外器材', '户外器材', 36, 0, '超级管理员', '2022-03-26 02:18:40', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (44, '2018-07-10 14:06:13', 1, '测试超级管理员', '运动相机', '运动相机', 36, 0, '超级管理员', '2022-03-26 02:18:40', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (45, '2018-07-10 14:06:13', 1, '测试超级管理员', '微单相机', '微单相机', 36, 0, '超级管理员', '2022-03-26 02:18:40', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (46, '2018-07-10 14:06:13', 1, '测试超级管理员', '单反相机', '单反相机', 36, 0, '超级管理员', '2022-03-26 02:18:40', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (47, '2018-07-10 14:07:46', 1, '测试超级管理员', '50-60', '50-60', 37, 0, '超级管理员', '2022-03-26 02:18:48', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (48, '2018-07-10 14:07:46', 1, '测试超级管理员', '40-50', '40-50', 37, 0, '超级管理员', '2022-03-26 02:18:48', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (49, '2018-07-10 14:07:46', 1, '测试超级管理员', '30-40', '30-40', 37, 0, '超级管理员', '2022-03-26 02:18:48', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (50, '2018-07-10 14:07:46', 1, '测试超级管理员', '20-30', '20-30', 37, 0, '超级管理员', '2022-03-26 02:18:48', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (51, '2018-07-10 14:07:46', 1, '测试超级管理员', '10-20', '10-20', 37, 0, '超级管理员', '2022-03-26 02:18:48', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (64, '2018-07-10 16:15:59', 1, '测试超级管理员', '更新日志', '1', 44, 0, '超级管理员', '2022-04-20 01:31:15', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (65, '2018-07-10 16:15:59', 1, '测试超级管理员', '其他信息', '2', 44, 0, '超级管理员', '2022-04-20 01:31:15', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (66, '2018-07-10 16:38:40', 1, '测试超级管理员', '否', '0', 45, NULL, '超级管理员', '2019-09-03 13:20:46', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (67, '2018-07-10 16:38:40', 1, '测试超级管理员', '是', '1', 45, NULL, '超级管理员', '2019-09-03 13:20:46', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (71, '2018-07-11 17:11:19', 1, '测试超级管理员', 'PC请求异常', 'Exception', 31, NULL, '超级管理员', '2022-02-21 12:43:18', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (77, '2018-07-18 10:16:22', 1, '测试超级管理员', '现金', '1', 48, NULL, '超级管理员', '2019-09-18 18:09:42', 1, 120, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (78, '2018-07-18 10:16:23', 1, '测试超级管理员', '赊账', '2', 48, NULL, '超级管理员', '2019-09-18 18:09:42', 1, 70, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (79, '2018-07-18 10:16:23', 1, '测试超级管理员', '抵扣', '3', 48, NULL, '超级管理员', '2019-09-18 18:09:42', 1, 100, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (90, '2018-07-23 10:04:45', 1, '测试超级管理员', '男', '0', 49, NULL, '测试超级管理员', '2018-07-23 11:10:28', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (91, '2018-07-23 10:04:45', 1, '测试超级管理员', '女', '1', 49, NULL, '测试超级管理员', '2018-07-23 11:10:28', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (96, '2018-07-23 15:36:43', 1, '测试超级管理员', '未启用', '0', 50, 1, '超级管理员', '2019-08-16 18:17:47', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (97, '2018-07-23 15:36:43', 1, '测试超级管理员', '已启用', '1', 50, 1, '超级管理员', '2019-08-16 18:17:47', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (98, '2018-07-23 15:36:43', 1, '测试超级管理员', '已删除', '2', 50, 1, '超级管理员', '2019-08-16 18:17:47', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (101, '2018-07-24 15:45:47', 1, '测试超级管理员', '否', '0', 52, 0, '超级管理员', '2022-03-26 23:07:16', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (102, '2018-07-24 15:45:47', 1, '测试超级管理员', '是', '1', 52, 0, '超级管理员', '2022-03-26 23:07:16', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (128, '2018-08-29 15:54:21', 1, '测试超级管理员', '是', '1', 59, 0, '超级管理员', '2020-12-19 18:02:55', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (129, '2018-08-29 15:54:21', 1, '测试超级管理员', '否', '0', 59, 1, '超级管理员', '2020-12-19 18:02:55', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (130, '2018-09-04 16:13:47', 1, '测试超级管理员', '数码相机', '数码相机', 36, 1, '超级管理员', '2022-03-26 02:18:40', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (142, '2019-08-20 09:57:54', 1, '超级管理员', '是', '1', 62, 1, '超级管理员', '2022-01-03 19:13:37', 1, NULL, '1'); +INSERT INTO `Sys_DictionaryList` VALUES (143, '2019-08-20 09:57:54', 1, '超级管理员', '否', '0', 62, 1, '超级管理员', '2022-01-03 19:13:37', 1, NULL, '测试'); +INSERT INTO `Sys_DictionaryList` VALUES (144, '2019-08-21 16:40:50', 1, '超级管理员', '刷新Token', 'ReplaceToeken', 31, NULL, '超级管理员', '2022-02-21 12:43:18', 1, 110, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (145, '2019-08-21 16:49:43', 1, '超级管理员', 'Info', '3', 30, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (149, '2019-09-18 19:25:47', 1, '超级管理员', '发货', '1', 64, 1, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (150, '2019-09-18 19:25:47', 1, '超级管理员', '退货', '2', 64, 1, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (151, '2019-09-18 19:25:47', 1, '超级管理员', '返单', '3', 64, 1, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (152, '2019-09-19 10:07:23', 1, '超级管理员', '二手', '二手', 65, 1, '超级管理员', '2021-03-24 13:43:23', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (153, '2019-09-19 10:07:23', 1, '超级管理员', '潮流', '潮流', 65, 1, '超级管理员', '2021-03-24 13:43:23', 1, 4, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (154, '2019-09-19 10:07:23', 1, '超级管理员', '家电', '家电', 65, NULL, '超级管理员', '2021-03-24 13:43:23', 1, 6, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (155, '2019-09-19 10:07:23', 1, '超级管理员', '食品', '食品', 65, NULL, '超级管理员', '2021-03-24 13:43:23', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (156, '2019-10-11 10:41:32', 1, '超级管理员', '登陆已过期', 'ApiAuthorize', 31, NULL, '超级管理员', '2022-02-21 12:43:18', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (157, '2020-05-08 09:42:50', 1, '超级管理员', '否', '0', 66, 0, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (158, '2020-05-08 09:42:50', 1, '超级管理员', '是', '1', 66, 0, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (161, '2020-09-11 23:10:50', 1, '超级管理员', '审核', 'Audit', 31, 0, '超级管理员', '2022-02-21 12:43:18', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (162, '2020-09-11 23:10:50', 1, '超级管理员', '打印', 'Print', 31, 0, '超级管理员', '2022-02-21 12:43:18', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (164, '2020-09-11 23:12:54', 1, '超级管理员', '开启权限', 'Open', 31, 0, '超级管理员', '2022-02-21 12:43:18', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (165, '2020-09-11 23:12:54', 1, '超级管理员', '其他', 'Other', 31, 0, '超级管理员', '2022-02-21 12:43:18', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (168, '2020-11-05 10:28:22', 1, '超级管理员', 'Info', '3', 31, 0, '超级管理员', '2022-02-21 12:43:18', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (171, '2021-08-16 14:00:45', 1, '超级管理员', '3', '3', 69, 0, '超级管理员', '2021-10-15 16:27:27', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (175, '2022-01-03 19:31:25', 1, '超级管理员', '非常满意', '非常满意', 75, 0, '超级管理员', '2022-03-26 23:07:19', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (176, '2022-01-03 19:31:25', 1, '超级管理员', '十分满意', '十分满意', 75, 0, '超级管理员', '2022-03-26 23:07:19', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (177, '2022-01-03 19:31:25', 1, '超级管理员', '相当满意', '相当满意', 75, 0, '超级管理员', '2022-03-26 23:07:19', 1, NULL, NULL); +INSERT INTO `Sys_DictionaryList` VALUES (178, '2022-01-03 19:31:25', 1, '超级管理员', '比较满意', '比较满意', 75, 0, '超级管理员', '2022-03-26 23:07:19', 1, NULL, NULL); + +-- ---------------------------- +-- Table structure for Sys_Log +-- ---------------------------- +DROP TABLE IF EXISTS `Sys_Log`; +CREATE TABLE `Sys_Log` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `BeginDate` datetime(0) NULL DEFAULT NULL, + `BrowserType` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `ElapsedTime` int(11) NULL DEFAULT NULL, + `EndDate` datetime(0) NULL DEFAULT NULL, + `ExceptionInfo` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL, + `LogType` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `RequestParameter` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL, + `ResponseParameter` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL, + `Role_Id` int(11) NULL DEFAULT NULL, + `ServiceIP` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `Success` int(11) NULL DEFAULT NULL, + `Url` varchar(4000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `UserIP` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `UserName` varchar(4000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `User_Id` int(11) NULL DEFAULT NULL, + PRIMARY KEY (`Id`) USING BTREE, + INDEX `IDX_BeginDate`(`BeginDate`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = COMPACT; + +-- ---------------------------- +-- Records of Sys_Log +-- ---------------------------- + +-- ---------------------------- +-- Table structure for Sys_Menu +-- ---------------------------- +DROP TABLE IF EXISTS `Sys_Menu`; +CREATE TABLE `Sys_Menu` ( + `Menu_Id` int(11) NOT NULL AUTO_INCREMENT, + `MenuName` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `Auth` varchar(4000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `Icon` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `Description` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `Enable` tinyint(4) NULL DEFAULT NULL, + `OrderNo` int(11) NULL DEFAULT NULL, + `TableName` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `ParentId` int(11) NOT NULL, + `Url` varchar(4000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `CreateDate` datetime(0) NULL DEFAULT NULL, + `Creator` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `ModifyDate` datetime(0) NULL DEFAULT NULL, + `Modifier` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `MenuType` int(11) NULL DEFAULT NULL, + PRIMARY KEY (`Menu_Id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 129 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = COMPACT; + +-- ---------------------------- +-- Records of Sys_Menu +-- ---------------------------- +INSERT INTO `Sys_Menu` VALUES (2, '用户信息', '[{\"text\":\"查询\",\"value\":\"Search\"}]', 'el-icon-user-solid', NULL, 1, 1600, '.', 0, NULL, '2017-08-28 12:21:13', '2017-08-28 11:12:45', '2021-08-02 02:59:11', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (3, '角色管理', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"},{\"text\":\"导出\",\"value\":\"Export\"}]', '', NULL, 1, 900, 'Sys_Role', 2, '/Sys_Role', '2017-09-12 16:20:02', '2017-08-28 14:19:13', '2021-05-02 15:55:09', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (5, '日志管理', '[{\"text\":\"查询\",\"value\":\"Search\"}]', 'el-icon-info', NULL, 1, 1300, 'xxx', 0, '/', '2017-09-22 17:59:37', '2017-09-22 17:59:37', '2021-08-02 03:00:14', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (6, '系统日志', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"导出\",\"value\":\"Export\"}]', '', NULL, 1, 0, 'Sys_Log', 5, '/Sys_Log/Manager', '2017-09-22 18:00:25', '2017-09-22 18:0:25', '2019-08-14 16:20:35', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (9, '用户管理', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"},{\"text\":\"导入\",\"value\":\"Import\"},{\"text\":\"导出\",\"value\":\"Export\"},{\"text\":\"上传\",\"value\":\"Upload\"},{\"text\":\"审核\",\"value\":\"Audit\"}]', '', NULL, 1, 11110, 'Sys_User', 2, '/Sys_User', NULL, NULL, '2021-05-02 15:56:46', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (10, '表单与上传下载', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 0, '/', 28, '/formUpload', NULL, NULL, '2019-12-07 11:16:47', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (11, 'api加载table数据', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 600, 'table2', 12, '/table2', NULL, NULL, '2019-11-14 00:11:17', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (16, '首页轮播图片', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"},{\"text\":\"导入\",\"value\":\"Import\"},{\"text\":\"导出\",\"value\":\"Export\"},{\"text\":\"上传\",\"value\":\"Upload\"},{\"text\":\"审核\",\"value\":\"Audit\"}]', '', NULL, 0, 2000, 'App_HomeHeadImages', 15, '/App_HomeHeadImages/Manager', NULL, NULL, '2019-08-12 16:26:44', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (24, '后台加载table数据', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 0, 750, '/', 56, '/table', NULL, NULL, '2021-07-25 12:26:52', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (25, '其他组件', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"},{\"text\":\"导入\",\"value\":\"Import\"},{\"text\":\"导出\",\"value\":\"Export\"},{\"text\":\"上传\",\"value\":\"Upload\"},{\"text\":\"审核\",\"value\":\"Audit\"}]', '', NULL, 1, 1100, '/', 29, '/form6', NULL, NULL, '2019-09-22 23:27:37', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (26, '文件上传', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 1050, 'volUploadExample', 28, '/volUploadExample', NULL, NULL, '2019-12-17 18:29:50', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (27, 'table编辑(一)', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 1050, 'vtable', 12, '/table1', NULL, NULL, '2021-03-20 15:20:43', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (30, '图表', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 100000, 'App_PriceTendency', 34, '/chart', NULL, NULL, '2019-11-14 00:07:26', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (31, '图表+表单', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 950, 'App_Comment', 34, '/formChart', NULL, NULL, '2019-11-14 00:07:51', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (33, '完整table+forms', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 2, 800, 'tableForms', 12, '/tableForms', NULL, NULL, '2021-08-03 09:51:26', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (35, '可编辑的table', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 0, 730, 'editTable', 56, '/editTable', NULL, NULL, '2021-07-25 12:26:55', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (36, '表单一对多table', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"},{\"text\":\"导入\",\"value\":\"Import\"},{\"text\":\"导出\",\"value\":\"Export\"}]', '', NULL, 1, 950, 'App_TransactionAvgPrice1', 32, '/multi1', NULL, NULL, '2019-11-14 00:03:19', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (37, '表单+图表', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"},{\"text\":\"导入\",\"value\":\"Import\"},{\"text\":\"导出\",\"value\":\"Export\"},{\"text\":\"上传\",\"value\":\"Upload\"},{\"text\":\"审核\",\"value\":\"Audit\"}]', '', NULL, 1, 800, 'App_Transaction', 32, '/multi3', NULL, NULL, '2019-11-14 00:04:17', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (42, '主从表单明细一对多', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"},{\"text\":\"导出\",\"value\":\"Export\"}]', '', NULL, 2, 0, 'SellOrder1', 32, '/multi4', NULL, NULL, '2021-08-03 09:51:10', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (45, '不用节点放此处', '', '', NULL, 0, 0, '/', 0, NULL, NULL, NULL, '2022-08-19 16:30:43', '超级管理员', 0); +INSERT INTO `Sys_Menu` VALUES (49, '基础只读表单', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"导入\",\"value\":\"Import\"},{\"text\":\"导出\",\"value\":\"Export\"},{\"text\":\"上传\",\"value\":\"Upload\"}]', '', NULL, 1, 1000, 'App_Appointment', 48, '/App_Appointment', '2019-07-12 13:28:17', '超级管理员', '2022-03-26 01:33:01', '超级管理员', 0); +INSERT INTO `Sys_Menu` VALUES (50, '自动绑定下拉框', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"}]', '', NULL, 1, 900, 'App_TransactionAvgPrice', 48, '/App_TransactionAvgPrice', '2019-07-12 13:53:32', '超级管理员', '2020-12-27 13:34:36', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (51, '主从一对多弹出框(4)', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"},{\"text\":\"导出\",\"value\":\"Export\"},{\"text\":\"审核\",\"value\":\"Audit\"}]', '', NULL, 1, 800, 'App_ReportPrice', 74, '/App_ReportPrice', '2019-07-12 13:55:21', '超级管理员', '2021-03-14 23:53:29', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (52, '导入导出表单', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"},{\"text\":\"导入\",\"value\":\"Import\"},{\"text\":\"导出\",\"value\":\"Export\"}]', '', NULL, 1, 600, 'App_Transaction', 48, '/App_Transaction', '2019-07-12 13:56:15', '超级管理员', '2019-10-31 13:23:37', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (57, '单列表单', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 1000, '.', 56, '/form1', '2019-07-12 14:01:12', '超级管理员', '2019-09-20 13:59:00', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (58, '两列表单', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 900, '两列表单', 56, '/form2', '2019-07-12 14:01:43', '超级管理员', '2019-09-20 13:59:03', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (59, '多列表单自动数据源', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 800, '多列表单', 56, '/form3', '2019-07-12 14:02:17', '超级管理员', '2019-12-17 11:08:06', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (60, 'Table+表单', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 700, 'Table+表单', 56, '/form4', '2019-07-12 14:03:14', '超级管理员', '2019-09-20 13:59:09', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (61, '系统设置', '[{\"text\":\"查询\",\"value\":\"Search\"}]', 'el-icon-setting', NULL, 1, 1350, '系统', 0, '/', '2019-07-12 14:04:04', '超级管理员', '2021-08-02 02:59:47', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (62, '菜单设置', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"编辑\",\"value\":\"Update\"}]', '', NULL, 1, 10, 'Sys_Menu', 61, '/sysmenu', '2019-07-12 14:04:35', '超级管理员', '2019-10-31 13:23:09', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (63, '下拉框绑定设置', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"},{\"text\":\"导出\",\"value\":\"Export\"}]', '', NULL, 1, 10, 'Sys_Dictionary', 61, '/Sys_Dictionary', '2019-07-12 14:05:58', '超级管理员', '2019-08-16 17:41:15', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (64, '代码生成', '[{\"text\":\"查询\",\"value\":\"Search\"}]', 'el-icon-position', NULL, 1, 1500, '代码在线生成器', 0, '/coding', '2019-07-12 14:07:55', '超级管理员', '2021-08-02 02:59:37', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (65, '代码生成器', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"}]', '', NULL, 1, 10, '/', 64, '/coder', '2019-07-12 14:08:58', '超级管理员', '2021-05-18 09:50:56', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (67, '静态页面发布', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"},{\"text\":\"导出\",\"value\":\"Export\"},{\"text\":\"上传\",\"value\":\"Upload\"}]', '', NULL, 1, 10, 'App_News', 66, '/App_News', '2019-07-12 14:14:16', '超级管理员', '2019-12-22 00:40:46', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (68, '多弹出框上传', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"},{\"text\":\"导出\",\"value\":\"Export\"},{\"text\":\"审核\",\"value\":\"Audit\"}]', '', NULL, 1, 700, 'App_Expert', 48, '/App_Expert', '2019-07-12 14:24:15', '超级管理员', '2021-08-03 09:49:40', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (69, '前端自定义扩展', '', '', NULL, 0, 500, '前端自定义扩展', 48, '/coding', '2019-07-12 14:26:25', '超级管理员', '2019-09-25 17:22:22', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (70, '编辑器表格换行', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"},{\"text\":\"导入\",\"value\":\"Import\"},{\"text\":\"导出\",\"value\":\"Export\"},{\"text\":\"上传\",\"value\":\"Upload\"}]', '', NULL, 1, 400, 'App_NewsEditor', 48, '/App_NewsEditor', '2019-07-12 14:28:45', '超级管理员', '2021-08-03 09:50:03', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (71, '权限管理', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"编辑\",\"value\":\"Update\"}]', 'ivu-icon ivu-icon-ios-boat', NULL, 1, 1000, 'Sys_Role2', 2, '/permission', '2019-08-10 10:25:36', '超级管理员', '2020-12-21 23:27:09', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (73, '移动端H5开发', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, NULL, '/', 72, '/app/guide', '2019-08-14 13:16:55', '超级管理员', '2021-05-05 15:21:18', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (75, '主从一对一(1)', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"},{\"text\":\"导入\",\"value\":\"Import\"},{\"text\":\"导出\",\"value\":\"Export\"},{\"text\":\"上传\",\"value\":\"Upload\"},{\"text\":\"审核\",\"value\":\"Audit\"}]', '', NULL, 1, 1000, 'SellOrder', 74, '/SellOrder', '2019-08-22 18:12:43', '超级管理员', '2021-03-14 23:52:28', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (77, '表单只读', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 600, '表单只读', 56, '/form7', '2019-08-26 11:58:55', '超级管理员', '2019-09-20 13:59:13', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (78, '混合表单一对多', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"},{\"text\":\"导入\",\"value\":\"Import\"},{\"text\":\"导出\",\"value\":\"Export\"},{\"text\":\"上传\",\"value\":\"Upload\"},{\"text\":\"审核\",\"value\":\"Audit\"}]', '', NULL, 1, 900, '32', 32, '/multi2', '2019-10-12 09:18:41', '超级管理员', '2019-11-14 00:03:51', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (79, 'wangEditor编辑器', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 100, 'WangEditor编辑器', 66, '/kindEditor', '2019-12-22 00:36:10', '超级管理员', '2021-09-05 21:50:33', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (80, '静态页面列表', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 0, 'htmlList', 66, '/htmlList', '2019-12-22 00:36:54', '超级管理员', '2019-12-21 22:50:41', NULL, NULL); +INSERT INTO `Sys_Menu` VALUES (81, '后台参数校验', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 0, '/', 41, '/validator', '2020-02-02 20:01:59', '超级管理员', '2020-02-02 20:01:16', NULL, NULL); +INSERT INTO `Sys_Menu` VALUES (82, '数字排版', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 0, 'flex', 34, '/flex', '2020-04-07 23:55:33', '超级管理员', '2019-11-15 14:32:56', NULL, NULL); +INSERT INTO `Sys_Menu` VALUES (83, '从表图片上传', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"},{\"text\":\"导出\",\"value\":\"Export\"}]', '', NULL, 1, 0, 'vSellorderImg', 74, '/vSellorderImg', '2020-04-07 23:56:22', '超级管理员', '2020-04-07 23:56:28', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (85, 'tree与代码生成页面', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"}]', '', NULL, 1, 100, 'treetable1', 84, '/treetable1', '2020-04-26 20:20:28', '超级管理员', '2019-11-15 14:32:32', NULL, NULL); +INSERT INTO `Sys_Menu` VALUES (86, 'tree自定义table数据', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 10, 'treetable2', 84, '/treetable2', '2020-04-26 20:20:57', '超级管理员', '2020-04-26 20:21:34', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (89, '流程管理', '[{\"text\":\"查询\",\"value\":\"Search\"}]', 'el-icon-s-operation', NULL, 1, 1765, '.', 0, '', '2020-11-29 16:49:27', '超级管理员', '2022-07-25 03:04:30', '超级管理员', 0); +INSERT INTO `Sys_Menu` VALUES (90, '审批流程', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"},{\"text\":\"导出\",\"value\":\"Export\"}]', '', NULL, 1, 2000, 'Sys_WorkFlow', 89, '/Sys_WorkFlow', '2020-11-29 16:49:42', '超级管理员', '2022-08-15 04:33:07', '超级管理员', 0); +INSERT INTO `Sys_Menu` VALUES (91, '多列合并显示', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"},{\"text\":\"导入\",\"value\":\"Import\"},{\"text\":\"导出\",\"value\":\"Export\"}]', '', NULL, 1, 0, '/App_Expert', 48, '/App_Expert2', '2021-03-06 17:47:23', '超级管理员', '2021-02-28 22:18:37', NULL, NULL); +INSERT INTO `Sys_Menu` VALUES (92, '主从一对一(2)', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"},{\"text\":\"导入\",\"value\":\"Import\"},{\"text\":\"导出\",\"value\":\"Export\"}]', '', NULL, 1, 890, 'SellOrder2', 74, '/SellOrder2', '2021-03-14 23:52:46', '超级管理员', '2021-03-14 23:52:54', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (93, '主从一对一(3)', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"编辑\",\"value\":\"Update\"},{\"text\":\"导入\",\"value\":\"Import\"},{\"text\":\"导出\",\"value\":\"Export\"}]', '', NULL, 1, 880, 'SellOrder3', 74, '/SellOrder3', '2021-03-14 23:53:50', '超级管理员', '2021-03-14 23:52:54', NULL, NULL); +INSERT INTO `Sys_Menu` VALUES (94, '在线表格编辑', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"}]', '', NULL, 1, 0, 'App_Transaction2', 48, '/App_Transaction2', '2021-03-20 15:19:14', '超级管理员', '2021-02-28 22:18:37', NULL, NULL); +INSERT INTO `Sys_Menu` VALUES (95, 'table编辑(二)', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"}]', '', NULL, 1, 1040, 'table3', 12, '/table3', '2021-03-20 15:21:05', '超级管理员', '2021-03-20 15:21:07', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (96, 'treetable', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 0, 'treetable3', 84, 'treetable3', '2021-05-02 15:54:23', '超级管理员', '2019-11-15 14:32:32', NULL, NULL); +INSERT INTO `Sys_Menu` VALUES (97, '角色管理(tree)', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"}]', '', NULL, 1, 0, 'Sys_Role1', 2, '/Sys_Role1', '2021-05-02 15:56:15', '超级管理员', '2021-05-02 18:29:18', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (98, '低代码设计器', '[{\"text\":\"查询\",\"value\":\"Search\"}]', 'el-icon-news', NULL, 1, 3000, '.', 0, '', '2021-08-30 02:48:10', '超级管理员', '2022-03-27 02:14:48', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (99, '低代码设计器', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 1000, '.', 98, '/formDraggable', '2021-08-30 02:48:34', '超级管理员', '2022-03-27 02:15:01', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (100, '明细表', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 2, 0, 'SellOrderList', 74, '', '2021-09-27 00:47:23', '超级管理员', '2021-03-14 23:52:28', NULL, NULL); +INSERT INTO `Sys_Menu` VALUES (101, '表单配置', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"导出\",\"value\":\"Export\"}]', '', NULL, 1, 900, 'FormDesignOptions', 98, '/FormDesignOptions', '2022-01-03 19:32:02', '超级管理员', '2022-03-27 03:02:12', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (102, '数据收集', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"导出\",\"value\":\"Export\"}]', '', NULL, 1, 0, 'formCollectionResultTree', 98, '/formCollectionResultTree', '2022-01-03 19:33:09', '超级管理员', '2022-01-10 10:28:14', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (103, '多页签', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 0, '.', 105, '/tabsTable', '2022-01-08 17:14:01', '超级管理员', '2022-01-08 18:06:44', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (104, '多表头', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"}]', '', NULL, 1, 0, '.', 105, '/App_Appointment2', '2022-01-08 17:14:44', '超级管理员', '2022-01-08 18:06:49', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (106, '数据收集(表数据)', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"导出\",\"value\":\"Export\"}]', '', NULL, 2, 0, 'FormCollectionObject', 98, '/FormCollectionObject', '2022-01-10 10:28:31', '超级管理员', '2022-01-10 10:28:34', '超级管理员', NULL); +INSERT INTO `Sys_Menu` VALUES (108, '只读页面', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 10, 'App_Appointment', 107, 'pages/order/App_Appointment/App_Appointment', '2022-03-26 00:59:36', '超级管理员', '2022-03-27 09:00:19', '超级管理员', 1); +INSERT INTO `Sys_Menu` VALUES (109, '水平显示', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 0, '.', 107, '/pages/order/App_Appointment1/App_Appointment1', '2022-03-26 01:00:38', '超级管理员', '2022-03-26 01:10:16', '超级管理员', 1); +INSERT INTO `Sys_Menu` VALUES (111, '数据源绑定', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"}]', '', NULL, 1, 10, 'App_TransactionAvgPrice', 110, 'pages/appmanager/App_TransactionAvgPrice/App_TransactionAvgPrice', '2022-03-26 02:04:58', '超级管理员', '2022-03-27 09:00:13', '超级管理员', 1); +INSERT INTO `Sys_Menu` VALUES (113, '事件绑定', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"}]', '', NULL, 1, 10, 'App_Transaction', 112, '/pages/appmanager/App_Transaction/App_Transaction', '2022-03-26 03:09:17', '超级管理员', '2022-03-27 09:00:09', '超级管理员', 1); +INSERT INTO `Sys_Menu` VALUES (114, '格式化', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"}]', '', NULL, 1, 0, '.', 112, '/pages/appmanager/App_Transaction1/App_Transaction1', '2022-03-26 03:09:45', '超级管理员', '2022-03-26 22:39:35', '超级管理员', 1); +INSERT INTO `Sys_Menu` VALUES (116, '主表1对1', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"新建\",\"value\":\"Add\"},{\"text\":\"删除\",\"value\":\"Delete\"},{\"text\":\"编辑\",\"value\":\"Update\"}]', '', NULL, 1, 0, 'SellOrder', 115, '/pages/order/SellOrder/SellOrder', '2022-03-26 03:11:13', '超级管理员', '2022-03-26 23:29:38', '超级管理员', 1); +INSERT INTO `Sys_Menu` VALUES (118, '表单配置', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 10, '.', 117, '/pages/form/form2', '2022-03-26 03:12:39', '超级管理员', '2022-03-27 08:59:33', '超级管理员', 1); +INSERT INTO `Sys_Menu` VALUES (119, '表单只读', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 0, '.', 117, 'pages/form/form1', '2022-03-26 03:12:52', '超级管理员', '2022-03-27 08:59:28', '超级管理员', 1); +INSERT INTO `Sys_Menu` VALUES (121, '列表显示table', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 0, '.', 120, 'pages/table/table2/table2', '2022-03-26 03:13:47', '超级管理员', '2022-03-27 02:43:58', '超级管理员', 1); +INSERT INTO `Sys_Menu` VALUES (122, '表格显示table', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 0, 'App_Expert', 120, '/pages/table/table1/table1', '2022-03-26 03:13:59', '超级管理员', '2022-03-27 02:44:00', '超级管理员', 1); +INSERT INTO `Sys_Menu` VALUES (124, '生成页面扩展组件', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 0, '.', 123, 'pages/pagedemo/pagedemo', '2022-03-26 03:16:51', '超级管理员', '2022-03-27 09:04:15', '超级管理员', 1); +INSERT INTO `Sys_Menu` VALUES (125, '手动绑定数据', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 0, '.', 120, 'pages/table/table3/table3', '2022-03-27 03:02:06', '超级管理员', '2022-03-27 02:15:29', NULL, 1); +INSERT INTO `Sys_Menu` VALUES (126, '消息推送', '[{\"text\":\"查询\",\"value\":\"Search\"}]', 'el-icon-chat-line-round', NULL, 1, 2900, '.', 0, '/signalR', '2022-05-04 12:00:00', '超级管理员', '2022-05-05 15:31:04', '超级管理员', 0); +INSERT INTO `Sys_Menu` VALUES (127, '我的任务', '[{\"text\":\"查询\",\"value\":\"Search\"},{\"text\":\"导出\",\"value\":\"Export\"}]', '', NULL, 1, 1500, 'Sys_WorkFlowTable', 89, '/Sys_WorkFlowTable', '2022-08-15 04:33:28', '超级管理员', '2022-08-15 04:33:39', '超级管理员', 0); +INSERT INTO `Sys_Menu` VALUES (128, '发起流程', '[{\"text\":\"查询\",\"value\":\"Search\"}]', '', NULL, 1, 0, '发起流程', 89, '/flowdemo', '2022-08-15 04:33:54', '超级管理员', '2022-08-15 04:34:33', '超级管理员', 0); + +-- ---------------------------- +-- Table structure for Sys_Province +-- ---------------------------- +DROP TABLE IF EXISTS `Sys_Province`; +CREATE TABLE `Sys_Province` ( + `ProvinceId` int(11) NOT NULL, + `ProvinceCode` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `ProvinceName` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `RegionCode` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`ProvinceId`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = COMPACT; + +-- ---------------------------- +-- Records of Sys_Province +-- ---------------------------- +INSERT INTO `Sys_Province` VALUES (1, '110000', '北京市', '华北'); +INSERT INTO `Sys_Province` VALUES (2, '120000', '天津市', '华北'); +INSERT INTO `Sys_Province` VALUES (3, '130000', '河北省', '华北'); +INSERT INTO `Sys_Province` VALUES (4, '140000', '山西省', '华北'); +INSERT INTO `Sys_Province` VALUES (5, '150000', '内蒙古自治区', '华北'); +INSERT INTO `Sys_Province` VALUES (6, '210000', '辽宁省', '东北'); +INSERT INTO `Sys_Province` VALUES (7, '220000', '吉林省', '东北'); +INSERT INTO `Sys_Province` VALUES (8, '230000', '黑龙江省', '东北'); +INSERT INTO `Sys_Province` VALUES (9, '310000', '上海市', '华东'); +INSERT INTO `Sys_Province` VALUES (10, '320000', '江苏省', '华东'); +INSERT INTO `Sys_Province` VALUES (11, '330000', '浙江省', '华东'); +INSERT INTO `Sys_Province` VALUES (12, '340000', '安徽省', '华东'); +INSERT INTO `Sys_Province` VALUES (13, '350000', '福建省', '华东'); +INSERT INTO `Sys_Province` VALUES (14, '360000', '江西省', '华东'); +INSERT INTO `Sys_Province` VALUES (15, '370000', '山东省', '华东'); +INSERT INTO `Sys_Province` VALUES (16, '410000', '河南省', '华中'); +INSERT INTO `Sys_Province` VALUES (17, '420000', '湖北省', '华中'); +INSERT INTO `Sys_Province` VALUES (18, '430000', '湖南省', '华中'); +INSERT INTO `Sys_Province` VALUES (19, '440000', '广东省', '华南'); +INSERT INTO `Sys_Province` VALUES (20, '450000', '广西壮族自治区', '华南'); +INSERT INTO `Sys_Province` VALUES (21, '460000', '海南省', '华南'); +INSERT INTO `Sys_Province` VALUES (22, '500000', '重庆市', '西南'); +INSERT INTO `Sys_Province` VALUES (23, '510000', '四川省', '西南'); +INSERT INTO `Sys_Province` VALUES (24, '520000', '贵州省', '西南'); +INSERT INTO `Sys_Province` VALUES (25, '530000', '云南省', '西南'); +INSERT INTO `Sys_Province` VALUES (26, '540000', '西藏自治区', '西南'); +INSERT INTO `Sys_Province` VALUES (27, '610000', '陕西省', '西北'); +INSERT INTO `Sys_Province` VALUES (28, '620000', '甘肃省', '西北'); +INSERT INTO `Sys_Province` VALUES (29, '630000', '青海省', '西北'); +INSERT INTO `Sys_Province` VALUES (30, '640000', '宁夏回族自治区', '西北'); +INSERT INTO `Sys_Province` VALUES (31, '650000', '新疆维吾尔自治区', '西北'); +INSERT INTO `Sys_Province` VALUES (32, '710000', '台湾省', '港澳台'); +INSERT INTO `Sys_Province` VALUES (33, '810000', '香港特别行政区', '港澳台'); +INSERT INTO `Sys_Province` VALUES (34, '820000', '澳门特别行政区', '港澳台'); +INSERT INTO `Sys_Province` VALUES (35, 'thd', '桃花岛', '东北'); +INSERT INTO `Sys_Province` VALUES (43, '测试1', '测试1', '港澳台'); + +-- ---------------------------- +-- Table structure for Sys_QuartzLog +-- ---------------------------- +DROP TABLE IF EXISTS `Sys_QuartzLog`; +CREATE TABLE `Sys_QuartzLog` ( + `LogId` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `Id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `TaskName` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `ElapsedTime` int(11) NULL DEFAULT NULL, + `StratDate` datetime(0) NULL DEFAULT NULL, + `EndDate` datetime(0) NULL DEFAULT NULL, + `Result` int(11) NULL DEFAULT NULL, + `ResponseContent` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL, + `ErrorMsg` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL, + `CreateID` int(11) NULL DEFAULT NULL, + `Creator` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `CreateDate` datetime(0) NULL DEFAULT NULL, + `ModifyID` int(11) NULL DEFAULT NULL, + `Modifier` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `ModifyDate` datetime(0) NULL DEFAULT NULL, + PRIMARY KEY (`LogId`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of Sys_QuartzLog +-- ---------------------------- + +-- ---------------------------- +-- Table structure for Sys_QuartzOptions +-- ---------------------------- +DROP TABLE IF EXISTS `Sys_QuartzOptions`; +CREATE TABLE `Sys_QuartzOptions` ( + `Id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TaskName` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `GroupName` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `CronExpression` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `Method` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `ApiUrl` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `AuthKey` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `AuthValue` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `LastRunTime` datetime(0) NULL DEFAULT NULL, + `Status` int(11) NULL DEFAULT NULL, + `Describe` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `PostData` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TimeOut` int(11) NULL DEFAULT NULL, + `CreateID` int(11) NULL DEFAULT NULL, + `Creator` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `CreateDate` datetime(0) NULL DEFAULT NULL, + `ModifyID` int(11) NULL DEFAULT NULL, + `Modifier` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `ModifyDate` datetime(0) NULL DEFAULT NULL, + PRIMARY KEY (`Id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of Sys_QuartzOptions +-- ---------------------------- + +-- ---------------------------- +-- Table structure for Sys_Role +-- ---------------------------- +DROP TABLE IF EXISTS `Sys_Role`; +CREATE TABLE `Sys_Role` ( + `Role_Id` int(11) NOT NULL AUTO_INCREMENT, + `CreateDate` datetime(0) NULL DEFAULT NULL, + `Creator` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `DeleteBy` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `DeptName` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `Dept_Id` int(11) NULL DEFAULT NULL, + `Enable` tinyint(4) NULL DEFAULT NULL, + `Modifier` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `ModifyDate` datetime(0) NULL DEFAULT NULL, + `OrderNo` int(11) NULL DEFAULT NULL, + `ParentId` int(11) NOT NULL, + `RoleName` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`Role_Id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = COMPACT; + +-- ---------------------------- +-- Records of Sys_Role +-- ---------------------------- +INSERT INTO `Sys_Role` VALUES (1, '2018-08-23 11:46:06', 'admin', NULL, '无', 0, 1, '测试超级管理员', '2018-09-06 17:08:35', 1000, 0, '超级管理员'); +INSERT INTO `Sys_Role` VALUES (2, '2018-08-23 11:46:52', 'admin', NULL, '1', 0, 1, '超级管理员', '2019-12-08 20:15:46', NULL, 1, '测试管理员'); +INSERT INTO `Sys_Role` VALUES (3, '2018-08-23 11:47:10', 'admin', NULL, '无', 0, 1, '超级管理员', '2020-11-16 14:16:57', NULL, 5, '小编'); +INSERT INTO `Sys_Role` VALUES (4, '2018-08-23 11:47:41', 'admin', NULL, '无 ', 0, 1, '超级管理员', '2020-11-16 14:17:00', NULL, 0, '信息员'); +INSERT INTO `Sys_Role` VALUES (5, '2019-05-30 10:59:13', 'admin', NULL, '还没想好', NULL, 1, '超级管理员', '2019-12-08 20:16:43', NULL, 0, '主管'); +INSERT INTO `Sys_Role` VALUES (8, '2021-05-02 18:33:49', '超级管理员', NULL, NULL, NULL, 1, '', NULL, NULL, 4, '二级角色'); +INSERT INTO `Sys_Role` VALUES (10, '2021-07-09 22:28:18', '超级管理员', NULL, NULL, NULL, 1, '', NULL, NULL, 8, '三级角色'); +INSERT INTO `Sys_Role` VALUES (11, '2021-07-09 22:29:07', '超级管理员', NULL, NULL, NULL, 1, '超级管理员', '2021-08-06 11:22:06', NULL, 8, '四级角色'); +INSERT INTO `Sys_Role` VALUES (12, '2022-03-23 09:47:00', '超级管理员', NULL, NULL, NULL, 1, '', NULL, NULL, 2, '测试角色'); + +-- ---------------------------- +-- Table structure for Sys_RoleAuth +-- ---------------------------- +DROP TABLE IF EXISTS `Sys_RoleAuth`; +CREATE TABLE `Sys_RoleAuth` ( + `Auth_Id` int(11) NOT NULL AUTO_INCREMENT, + `AuthValue` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `CreateDate` datetime(0) NULL DEFAULT NULL, + `Creator` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `Menu_Id` int(11) NOT NULL, + `Modifier` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `ModifyDate` datetime(0) NULL DEFAULT NULL, + `Role_Id` int(11) NULL DEFAULT NULL, + `User_Id` int(11) NULL DEFAULT NULL, + PRIMARY KEY (`Auth_Id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 271 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = COMPACT; + +-- ---------------------------- +-- Records of Sys_RoleAuth +-- ---------------------------- +INSERT INTO `Sys_RoleAuth` VALUES (151, 'Search', '2020-05-05 12:05:34', '超级管理员', 30, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (152, 'Search,Add,Delete,Update,Export', '2020-05-05 12:05:34', '超级管理员', 3, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (153, 'Search,Add,Delete,Update,Export,Audit', '2020-05-05 12:05:34', '超级管理员', 51, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (154, 'Search', '2020-05-05 12:05:34', '超级管理员', 59, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (155, 'Search,Add,Delete,Update,Import,Export,Upload,Audit', '2020-05-05 12:05:34', '超级管理员', 37, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (156, 'Search', '2020-05-05 12:05:34', '超级管理员', 33, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (157, '', '2020-05-05 12:05:34', '超级管理员', 24, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (158, '', '2020-05-05 12:05:34', '超级管理员', 35, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (159, 'Search', '2020-05-05 12:05:34', '超级管理员', 60, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (160, 'Search,Add,Delete,Update,Export,Audit', '2020-05-05 12:05:34', '超级管理员', 68, '超级管理员', '2021-03-06 17:47:32', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (161, 'Search', '2020-05-05 12:05:34', '超级管理员', 77, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (162, 'Search,Add,Delete,Update,Import,Export', '2020-05-05 12:05:34', '超级管理员', 52, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (163, 'Search', '2020-05-05 12:05:34', '超级管理员', 11, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (164, 'Search,Add,Delete,Update', '2020-05-05 12:05:34', '超级管理员', 85, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (165, 'Search', '2020-05-05 12:05:34', '超级管理员', 79, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (166, 'Search', '2020-05-05 12:05:34', '超级管理员', 86, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (167, 'Search,Add,Delete,Update,Export,Upload', '2020-05-05 12:05:34', '超级管理员', 67, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (168, 'Search,Add,Delete,Update', '2020-05-05 12:05:34', '超级管理员', 65, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (169, 'Search,Add,Update', '2020-05-05 12:05:34', '超级管理员', 62, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (170, 'Search,Add,Delete,Update,Export', '2020-05-05 12:05:34', '超级管理员', 63, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (171, 'Search,Add,Delete,Update,Export', '2020-05-05 12:05:34', '超级管理员', 83, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (172, 'Search', '2020-05-05 12:05:34', '超级管理员', 80, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (173, 'Search', '2020-05-05 12:05:34', '超级管理员', 81, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (174, 'Search', '2020-05-05 12:05:34', '超级管理员', 82, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (175, 'Search,Add,Delete,Update,Export', '2020-05-05 12:05:34', '超级管理员', 42, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (176, 'Search', '2020-05-05 12:05:34', '超级管理员', 10, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (177, 'Search,Add,Delete,Update,Import,Export,Upload,Audit', '2020-05-05 12:05:34', '超级管理员', 78, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (178, 'Search,Delete,Export', '2020-05-05 12:05:34', '超级管理员', 6, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (179, 'Search,Add,Delete,Update', '2020-05-05 12:05:34', '超级管理员', 50, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (180, 'Search,Add,Delete,Update,Import,Export', '2020-05-05 12:05:34', '超级管理员', 36, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (181, 'Search,Add,Delete,Update,Import,Export,Upload,Audit', '2020-05-05 12:05:34', '超级管理员', 9, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (182, 'Search', '2020-05-05 12:05:34', '超级管理员', 48, '超级管理员', '2021-01-16 12:14:19', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (183, 'Search', '2020-05-05 12:05:34', '超级管理员', 74, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (184, 'Search', '2020-05-05 12:05:34', '超级管理员', 56, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (185, 'Search', '2020-05-05 12:05:34', '超级管理员', 32, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (186, 'Search', '2020-05-05 12:05:34', '超级管理员', 34, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (187, 'Search', '2020-05-05 12:05:34', '超级管理员', 12, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (188, 'Search', '2020-05-05 12:05:34', '超级管理员', 84, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (189, 'Search', '2020-05-05 12:05:34', '超级管理员', 41, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (190, 'Search,Add,Delete,Update,Import,Export,Upload,Audit', '2020-05-05 12:05:34', '超级管理员', 28, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (191, 'Search', '2020-05-05 12:05:34', '超级管理员', 66, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (192, 'Search', '2020-05-05 12:05:34', '超级管理员', 29, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (193, 'Search', '2020-05-05 12:05:34', '超级管理员', 72, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (194, 'Search', '2020-05-05 12:05:34', '超级管理员', 2, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (195, 'Search', '2020-05-05 12:05:34', '超级管理员', 64, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (196, 'Search', '2020-05-05 12:05:34', '超级管理员', 61, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (197, 'Search', '2020-05-05 12:05:34', '超级管理员', 5, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (198, 'Search,Add,Delete,Update,Import,Export,Upload,Audit', '2020-05-05 12:05:34', '超级管理员', 25, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (199, 'Search', '2020-05-05 12:05:34', '超级管理员', 26, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (200, 'Search', '2020-05-05 12:05:34', '超级管理员', 27, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (201, 'Search,Add,Delete,Update,Import,Export,Upload,Audit', '2020-05-05 12:05:34', '超级管理员', 75, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (202, 'Search', '2020-05-05 12:05:34', '超级管理员', 57, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (203, 'Search,Import,Export,Upload', '2020-05-05 12:05:34', '超级管理员', 49, '超级管理员', '2022-03-26 03:22:47', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (204, 'Search,Update', '2020-05-05 12:05:34', '超级管理员', 71, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (205, 'Search', '2020-05-05 12:05:34', '超级管理员', 31, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (206, 'Search', '2020-05-05 12:05:34', '超级管理员', 58, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (207, 'Search', '2020-05-05 12:05:34', '超级管理员', 73, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (208, 'Search', '2020-05-25 13:15:51', '超级管理员', 48, '超级管理员', '2020-05-25 13:15:51', 4, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (209, 'Search,Add,Update,Import,Export,Upload', '2020-05-25 13:15:51', '超级管理员', 49, '超级管理员', '2020-05-25 13:15:51', 4, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (210, 'Search,Add,Delete,Update', '2020-05-25 13:15:51', '超级管理员', 50, '超级管理员', '2020-05-25 13:15:51', 4, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (211, 'Search,Add,Update,Export,Audit', '2020-05-25 13:15:51', '超级管理员', 68, '超级管理员', '2020-05-25 13:15:51', 4, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (212, 'Search,Add,Delete,Update,Import,Export', '2020-05-25 13:15:51', '超级管理员', 52, '超级管理员', '2020-05-25 13:15:51', 4, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (213, 'Search,Import,Export,Upload', '2020-09-11 01:03:11', '演示帐号', 49, '演示帐号', '2020-09-11 01:03:11', 6, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (214, 'Search', '2020-11-29 16:52:52', '超级管理员', 89, '超级管理员', '2020-11-29 16:52:52', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (215, 'Search,Add,Delete,Update,Export', '2020-11-29 16:52:52', '超级管理员', 90, '超级管理员', '2022-07-25 03:10:47', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (216, 'Search,Add,Delete,Update,Import,Export,Upload', '2021-01-16 12:01:58', '超级管理员', 70, '超级管理员', '2021-01-16 12:01:58', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (217, 'Search,Add,Delete,Update,Import,Export', '2021-03-06 17:47:32', '超级管理员', 91, '超级管理员', '2021-03-06 17:47:32', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (218, 'Search,Add,Delete,Update,Import,Export', '2021-03-14 23:56:27', '超级管理员', 92, '超级管理员', '2021-03-14 23:56:27', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (219, 'Search,Add,Update,Import,Export', '2021-03-14 23:56:27', '超级管理员', 93, '超级管理员', '2021-03-14 23:56:27', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (220, 'Search,Add,Delete,Update', '2021-03-20 15:25:20', '超级管理员', 95, '超级管理员', '2021-03-20 15:25:20', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (221, 'Search,Add,Delete,Update', '2021-03-20 15:25:20', '超级管理员', 94, '超级管理员', '2021-03-20 15:25:20', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (222, 'Search', '2021-05-02 15:57:11', '超级管理员', 96, '超级管理员', '2021-05-02 15:57:11', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (223, 'Search', '2021-05-02 15:57:11', '超级管理员', 97, '超级管理员', '2021-05-02 15:57:11', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (224, 'Export', '2021-05-05 15:25:06', '超级管理员', 68, '超级管理员', '2021-05-05 15:25:06', 6, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (225, 'Search', '2021-08-30 02:51:00', '超级管理员', 98, '超级管理员', '2022-03-27 02:41:51', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (226, 'Search', '2021-08-30 02:51:00', '超级管理员', 99, '超级管理员', '2022-03-27 02:41:51', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (227, 'Search', '2021-09-27 00:47:34', '超级管理员', 100, '超级管理员', '2021-09-27 00:47:34', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (228, 'Search', '2022-01-08 17:16:55', '超级管理员', 103, '超级管理员', '2022-01-08 17:16:55', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (229, 'Search,Add,Delete,Update', '2022-01-08 17:16:55', '超级管理员', 104, '超级管理员', '2022-01-08 17:16:55', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (230, 'Search', '2022-01-08 18:07:11', '超级管理员', 105, '超级管理员', '2022-01-08 18:07:11', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (231, 'Search,Add,Delete,Export', '2022-01-08 18:07:11', '超级管理员', 101, '超级管理员', '2022-03-27 02:41:51', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (232, 'Search,Export', '2022-01-08 18:07:11', '超级管理员', 102, '超级管理员', '2022-03-27 02:41:51', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (233, 'Search,Export', '2022-01-10 10:30:29', '超级管理员', 106, '超级管理员', '2022-03-27 02:41:51', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (234, 'Search', '2022-03-26 03:22:47', '超级管理员', 108, '超级管理员', '2022-03-26 03:22:47', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (235, 'Search,Add,Delete,Update', '2022-03-26 03:22:47', '超级管理员', 111, '超级管理员', '2022-03-26 03:22:47', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (236, 'Search,Add,Delete,Update', '2022-03-26 03:22:47', '超级管理员', 114, '超级管理员', '2022-03-26 03:22:47', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (237, 'Search,Add,Delete,Update', '2022-03-26 03:22:47', '超级管理员', 113, '超级管理员', '2022-03-26 03:22:47', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (238, 'Search,Add,Delete,Update', '2022-03-26 03:22:47', '超级管理员', 116, '超级管理员', '2022-03-26 03:22:47', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (239, 'Search', '2022-03-26 03:22:47', '超级管理员', 119, '超级管理员', '2022-03-26 03:22:47', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (240, 'Search', '2022-03-26 03:22:47', '超级管理员', 118, '超级管理员', '2022-03-26 03:22:47', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (241, 'Search', '2022-03-26 03:22:47', '超级管理员', 109, '超级管理员', '2022-03-26 03:22:47', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (242, 'Search', '2022-03-26 03:22:47', '超级管理员', 122, '超级管理员', '2022-03-26 03:22:47', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (243, 'Search', '2022-03-26 03:22:47', '超级管理员', 124, '超级管理员', '2022-03-26 03:22:47', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (244, 'Search', '2022-03-26 03:22:47', '超级管理员', 120, '超级管理员', '2022-03-26 03:22:47', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (245, 'Search', '2022-03-26 03:22:47', '超级管理员', 117, '超级管理员', '2022-03-26 03:22:47', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (246, 'Search', '2022-03-26 03:22:47', '超级管理员', 123, '超级管理员', '2022-03-26 03:22:47', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (247, 'Search', '2022-03-26 03:22:47', '超级管理员', 115, '超级管理员', '2022-03-26 03:22:47', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (248, 'Search', '2022-03-26 03:22:47', '超级管理员', 112, '超级管理员', '2022-03-26 03:22:47', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (249, 'Search', '2022-03-26 03:22:47', '超级管理员', 110, '超级管理员', '2022-03-26 03:22:47', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (250, 'Search', '2022-03-26 03:22:47', '超级管理员', 121, '超级管理员', '2022-03-26 03:22:47', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (251, 'Search', '2022-03-26 03:22:47', '超级管理员', 107, '超级管理员', '2022-03-26 03:22:47', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (252, 'Search', '2022-03-27 02:39:28', '超级管理员', 107, '超级管理员', '2022-03-27 02:39:28', 12, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (253, 'Search', '2022-03-27 02:39:28', '超级管理员', 110, '超级管理员', '2022-03-27 02:39:28', 12, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (254, 'Search', '2022-03-27 02:39:28', '超级管理员', 112, '超级管理员', '2022-03-27 02:39:28', 12, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (255, 'Search', '2022-03-27 02:39:28', '超级管理员', 115, '超级管理员', '2022-03-27 02:39:28', 12, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (256, 'Search', '2022-03-27 02:39:28', '超级管理员', 123, '超级管理员', '2022-03-27 02:39:28', 12, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (257, 'Search', '2022-03-27 02:39:28', '超级管理员', 117, '超级管理员', '2022-03-27 02:39:28', 12, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (258, 'Search', '2022-03-27 02:39:28', '超级管理员', 124, '超级管理员', '2022-03-27 02:39:28', 12, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (259, 'Search', '2022-03-27 02:39:28', '超级管理员', 118, '超级管理员', '2022-03-27 02:39:28', 12, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (260, 'Search', '2022-03-27 02:39:28', '超级管理员', 119, '超级管理员', '2022-03-27 02:39:28', 12, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (261, 'Search,Add,Delete,Update', '2022-03-27 02:39:28', '超级管理员', 116, '超级管理员', '2022-03-27 02:39:28', 12, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (262, 'Search,Add,Delete,Update', '2022-03-27 02:39:28', '超级管理员', 113, '超级管理员', '2022-03-27 02:39:28', 12, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (263, 'Search,Add,Delete,Update', '2022-03-27 02:39:28', '超级管理员', 114, '超级管理员', '2022-03-27 02:39:28', 12, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (264, 'Search,Add,Delete,Update', '2022-03-27 02:39:28', '超级管理员', 111, '超级管理员', '2022-03-27 02:39:28', 12, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (265, 'Search', '2022-03-27 02:39:28', '超级管理员', 108, '超级管理员', '2022-03-27 02:39:28', 12, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (266, 'Search', '2022-03-27 02:39:28', '超级管理员', 109, '超级管理员', '2022-03-27 02:39:28', 12, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (267, 'Search', '2022-03-27 03:02:19', '超级管理员', 125, '超级管理员', '2022-03-27 03:02:19', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (268, 'Search', '2022-05-04 14:45:36', '超级管理员', 126, '超级管理员', '2022-05-04 14:45:36', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (269, 'Search,Export', '2022-08-15 05:02:56', '超级管理员', 127, '超级管理员', '2022-08-15 05:02:56', 2, NULL); +INSERT INTO `Sys_RoleAuth` VALUES (270, 'Search', '2022-08-15 05:02:56', '超级管理员', 128, '超级管理员', '2022-08-15 05:02:56', 2, NULL); + +-- ---------------------------- +-- Table structure for Sys_RoleAuthData +-- ---------------------------- +DROP TABLE IF EXISTS `Sys_RoleAuthData`; +CREATE TABLE `Sys_RoleAuthData` ( + `Auth_Id` int(11) NOT NULL, + `DataType_Id` int(11) NULL DEFAULT NULL, + `Role_Id` int(11) NULL DEFAULT NULL, + `User_Id` int(11) NULL DEFAULT NULL, + `Node_Id` varchar(50) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL, + `LevelID` int(11) NULL DEFAULT NULL, + `AuthValue` varchar(4000) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL, + `Creator` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `CreateDate` timestamp(0) NULL DEFAULT NULL, + `Modifier` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `ModifyDate` timestamp(0) NULL DEFAULT NULL, + PRIMARY KEY (`Auth_Id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = COMPACT; + +-- ---------------------------- +-- Records of Sys_RoleAuthData +-- ---------------------------- + +-- ---------------------------- +-- Table structure for Sys_TableColumn +-- ---------------------------- +DROP TABLE IF EXISTS `Sys_TableColumn`; +CREATE TABLE `Sys_TableColumn` ( + `ColumnId` int(11) NOT NULL AUTO_INCREMENT, + `ApiInPut` int(11) NULL DEFAULT NULL, + `ApiIsNull` int(11) NULL DEFAULT NULL, + `ApiOutPut` int(11) NULL DEFAULT NULL, + `ColSize` int(11) NULL DEFAULT NULL, + `ColumnCNName` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `ColumnName` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `ColumnType` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL, + `ColumnWidth` int(11) NULL DEFAULT NULL, + `Columnformat` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL, + `CreateDate` datetime(0) NULL DEFAULT NULL, + `CreateID` int(11) NULL DEFAULT NULL, + `Creator` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `DropNo` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `EditColNo` int(11) NULL DEFAULT NULL, + `EditRowNo` int(11) NULL DEFAULT NULL, + `EditType` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `Enable` int(11) NULL DEFAULT NULL, + `IsColumnData` int(11) NULL DEFAULT NULL, + `IsDisplay` int(11) NULL DEFAULT NULL, + `IsImage` int(11) NULL DEFAULT NULL, + `IsKey` int(11) NULL DEFAULT NULL, + `IsNull` int(11) NULL DEFAULT NULL, + `IsReadDataset` int(11) NULL DEFAULT NULL, + `Maxlength` int(11) NULL DEFAULT NULL, + `Modifier` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL, + `ModifyDate` datetime(0) NULL DEFAULT NULL, + `ModifyID` int(11) NULL DEFAULT NULL, + `OrderNo` int(11) NULL DEFAULT NULL, + `Script` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL, + `SearchColNo` int(11) NULL DEFAULT NULL, + `SearchRowNo` int(11) NULL DEFAULT NULL, + `SearchType` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `Sortable` int(11) NULL DEFAULT NULL, + `TableName` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `Table_Id` int(11) NULL DEFAULT NULL, + PRIMARY KEY (`ColumnId`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 865 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = COMPACT; + +-- ---------------------------- +-- Records of Sys_TableColumn +-- ---------------------------- +INSERT INTO `Sys_TableColumn` VALUES (20, NULL, NULL, NULL, NULL, '角色ID', 'Role_Id', 'int', 70, '', '2018-06-04 10:14:21', NULL, NULL, '', NULL, NULL, '', NULL, 1, 1, NULL, 1, 0, 1, NULL, '超级管理员', '2022-04-06 22:34:14', 1, 1420, '', NULL, NULL, '', 0, 'Sys_Role', 2); +INSERT INTO `Sys_TableColumn` VALUES (21, NULL, NULL, NULL, NULL, '父级ID', 'ParentId', 'int', 70, '', '2018-06-04 10:14:21', NULL, NULL, 'tree_roles', NULL, 1, 'cascader', NULL, 1, 1, NULL, 0, 0, 0, NULL, '超级管理员', '2022-04-06 22:34:14', 1, 1410, '', NULL, NULL, '', 0, 'Sys_Role', 2); +INSERT INTO `Sys_TableColumn` VALUES (22, NULL, NULL, NULL, NULL, '角色名称', 'RoleName', 'string', 90, '', '2018-06-04 10:14:21', NULL, NULL, '', NULL, 1, '', NULL, 1, 1, NULL, 0, 1, 0, 50, '超级管理员', '2022-04-06 22:34:14', 1, 1400, '', NULL, 1, 'text', 0, 'Sys_Role', 2); +INSERT INTO `Sys_TableColumn` VALUES (23, NULL, NULL, NULL, NULL, '部门ID', 'Dept_Id', 'int', 90, '', '2018-06-04 10:14:21', NULL, NULL, '', NULL, NULL, '', NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2022-04-06 22:34:14', 1, 1390, '', NULL, NULL, '', 0, 'Sys_Role', 2); +INSERT INTO `Sys_TableColumn` VALUES (24, NULL, NULL, NULL, NULL, '部门名称', 'DeptName', 'string', 90, '', '2018-06-04 10:14:21', NULL, NULL, '', NULL, 2, '', NULL, 1, 1, NULL, 0, 1, 0, 50, '超级管理员', '2022-04-06 22:34:14', 1, 1380, '', NULL, 1, 'text', 0, 'Sys_Role', 2); +INSERT INTO `Sys_TableColumn` VALUES (25, NULL, NULL, NULL, NULL, '排序', 'OrderNo', 'int', 90, '', '2018-06-04 10:14:21', NULL, NULL, '', NULL, NULL, '', NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2022-04-06 22:34:14', 1, 1370, '', NULL, NULL, '', 0, 'Sys_Role', 2); +INSERT INTO `Sys_TableColumn` VALUES (26, NULL, NULL, NULL, NULL, '创建人', 'Creator', 'string', 130, '', '2018-06-04 10:14:21', NULL, NULL, '', NULL, 4, '', NULL, 1, 1, NULL, 0, 1, 1, 50, '超级管理员', '2022-04-06 22:34:14', 1, 1360, '', NULL, NULL, '', 0, 'Sys_Role', 2); +INSERT INTO `Sys_TableColumn` VALUES (27, NULL, NULL, NULL, NULL, '创建时间', 'CreateDate', 'DateTime', 90, '', '2018-06-04 10:14:21', NULL, NULL, '', NULL, 4, 'datetime', NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2022-04-06 22:34:14', 1, 1350, '', NULL, 2, 'datetime', 0, 'Sys_Role', 2); +INSERT INTO `Sys_TableColumn` VALUES (28, NULL, NULL, NULL, NULL, '修改人', 'Modifier', 'string', 130, '', '2018-06-04 10:14:21', NULL, NULL, '', NULL, 5, '', NULL, 1, 1, NULL, 0, 1, 1, 50, '超级管理员', '2022-04-06 22:34:14', 1, 1340, '', NULL, NULL, '', 0, 'Sys_Role', 2); +INSERT INTO `Sys_TableColumn` VALUES (29, NULL, NULL, NULL, NULL, '修改时间', 'ModifyDate', 'DateTime', 90, '', '2018-06-04 10:14:21', NULL, NULL, '', NULL, 5, '', NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2022-04-06 22:34:14', 1, 1330, '', NULL, 2, 'datetime', 0, 'Sys_Role', 2); +INSERT INTO `Sys_TableColumn` VALUES (30, NULL, NULL, NULL, NULL, '', 'DeleteBy', 'string', 90, '', '2018-06-04 10:14:21', NULL, NULL, '', NULL, NULL, '', NULL, 0, 0, NULL, 0, 1, 0, 50, '超级管理员', '2022-04-06 22:34:14', 1, 1320, '', NULL, NULL, '', 0, 'Sys_Role', 2); +INSERT INTO `Sys_TableColumn` VALUES (31, NULL, NULL, NULL, NULL, '是否启用', 'Enable', 'sbyte', 90, '', '2018-06-04 10:14:21', NULL, NULL, 'enable', NULL, 2, 'switch', NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-04-06 22:34:14', 1, 1375, '', NULL, 1, 'select', 0, 'Sys_Role', 2); +INSERT INTO `Sys_TableColumn` VALUES (32, NULL, NULL, NULL, NULL, '字典ID', 'Dic_ID', 'int', 90, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 1, 0, 1, NULL, '超级管理员', '2019-08-23 10:17:27', 1, 1300, NULL, NULL, NULL, NULL, NULL, 'Sys_Dictionary', 3); +INSERT INTO `Sys_TableColumn` VALUES (33, NULL, NULL, NULL, NULL, '字典名称', 'DicName', 'string', 140, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, 1, NULL, NULL, 1, 1, NULL, 0, 0, 0, 100, '超级管理员', '2019-08-23 10:17:27', 1, 1290, NULL, NULL, 1, 'textarea', NULL, 'Sys_Dictionary', 3); +INSERT INTO `Sys_TableColumn` VALUES (34, NULL, NULL, NULL, NULL, '父级ID', 'ParentId', 'int', 90, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, 1, NULL, NULL, 1, 1, NULL, 0, 0, 0, NULL, '超级管理员', '2019-08-23 10:17:27', 1, 1280, NULL, NULL, 1, NULL, NULL, 'Sys_Dictionary', 3); +INSERT INTO `Sys_TableColumn` VALUES (35, NULL, NULL, NULL, NULL, '配置项', 'Config', 'string', 300, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, 4000, '超级管理员', '2019-08-23 10:17:27', 1, 1270, NULL, NULL, NULL, NULL, NULL, 'Sys_Dictionary', 3); +INSERT INTO `Sys_TableColumn` VALUES (36, NULL, NULL, NULL, 8, 'sql语句', 'DbSql', 'string', 200, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, 6, 'textarea', NULL, 1, 1, NULL, 0, 1, 0, 4000, '超级管理员', '2019-08-23 10:17:27', 1, 1260, NULL, NULL, NULL, NULL, NULL, 'Sys_Dictionary', 3); +INSERT INTO `Sys_TableColumn` VALUES (37, NULL, NULL, NULL, NULL, 'DBServer', 'DBServer', 'string', 90, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, 4000, '超级管理员', '2019-08-23 10:17:27', 1, 1250, NULL, NULL, NULL, NULL, NULL, 'Sys_Dictionary', 3); +INSERT INTO `Sys_TableColumn` VALUES (38, NULL, NULL, NULL, NULL, '排序号', 'OrderNo', 'int', 90, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, 2, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2019-08-23 10:17:27', 1, 1240, NULL, NULL, NULL, NULL, NULL, 'Sys_Dictionary', 3); +INSERT INTO `Sys_TableColumn` VALUES (39, NULL, NULL, NULL, NULL, '字典编号', 'DicNo', 'string', 90, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, 1, NULL, NULL, 1, 1, NULL, 0, 0, 0, 100, '超级管理员', '2019-08-23 10:17:27', 1, 1295, NULL, NULL, 1, NULL, NULL, 'Sys_Dictionary', 3); +INSERT INTO `Sys_TableColumn` VALUES (40, NULL, NULL, NULL, NULL, '备注', 'Remark', 'string', 90, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, 6, 'textarea', NULL, 1, 1, NULL, 0, 1, 0, 2000, '超级管理员', '2019-08-23 10:17:27', 1, 1220, NULL, NULL, NULL, '无', NULL, 'Sys_Dictionary', 3); +INSERT INTO `Sys_TableColumn` VALUES (41, NULL, NULL, NULL, NULL, '是否启用', 'Enable', 'sbyte', 90, NULL, '2018-06-06 14:05:43', NULL, NULL, 'enable', NULL, 2, 'select', NULL, 1, 1, NULL, 0, 0, 0, NULL, '超级管理员', '2019-08-23 10:17:27', 1, 1210, NULL, NULL, 2, 'drop', NULL, 'Sys_Dictionary', 3); +INSERT INTO `Sys_TableColumn` VALUES (42, NULL, NULL, NULL, NULL, NULL, 'CreateID', 'int', 90, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-08-23 10:17:27', 1, 1200, NULL, NULL, NULL, NULL, NULL, 'Sys_Dictionary', 3); +INSERT INTO `Sys_TableColumn` VALUES (43, NULL, NULL, NULL, NULL, '创建人', 'Creator', 'string', 130, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 1, 30, '超级管理员', '2019-08-23 10:17:27', 1, 1190, NULL, NULL, NULL, NULL, NULL, 'Sys_Dictionary', 3); +INSERT INTO `Sys_TableColumn` VALUES (44, NULL, NULL, NULL, NULL, '创建时间', 'CreateDate', 'DateTime', 150, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, 2, 'datetime', NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2019-08-23 10:17:27', 1, 1180, NULL, NULL, 2, 'datetime', NULL, 'Sys_Dictionary', 3); +INSERT INTO `Sys_TableColumn` VALUES (45, NULL, NULL, NULL, NULL, NULL, 'ModifyID', 'int', 90, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-08-23 10:17:27', 1, 1170, NULL, NULL, NULL, NULL, NULL, 'Sys_Dictionary', 3); +INSERT INTO `Sys_TableColumn` VALUES (46, NULL, NULL, NULL, NULL, '修改人', 'Modifier', 'string', 130, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 1, 30, '超级管理员', '2019-08-23 10:17:27', 1, 1160, NULL, NULL, NULL, NULL, NULL, 'Sys_Dictionary', 3); +INSERT INTO `Sys_TableColumn` VALUES (47, NULL, NULL, NULL, NULL, '修改时间', 'ModifyDate', 'DateTime', 150, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, NULL, 'datetime', NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2019-08-23 10:17:27', 1, 1150, NULL, NULL, 2, 'datetime', NULL, 'Sys_Dictionary', 3); +INSERT INTO `Sys_TableColumn` VALUES (48, NULL, NULL, NULL, NULL, '', 'DicList_ID', 'int', 90, '', '2018-06-06 14:12:18', NULL, NULL, '', NULL, NULL, '', NULL, 1, 0, NULL, 1, 0, 1, NULL, '超级管理员', '2021-05-05 19:40:42', 1, 1140, '', NULL, NULL, '', 0, 'Sys_DictionaryList', 4); +INSERT INTO `Sys_TableColumn` VALUES (49, NULL, NULL, NULL, NULL, '数据源ID', 'Dic_ID', 'int', 90, '', '2018-06-06 14:12:18', NULL, NULL, '', NULL, 0, '', NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2021-05-05 19:40:42', 1, 1130, '', NULL, NULL, '', 0, 'Sys_DictionaryList', 4); +INSERT INTO `Sys_TableColumn` VALUES (50, NULL, NULL, NULL, NULL, '数据源Value', 'DicValue', 'string', 90, '', '2018-06-06 14:12:18', NULL, NULL, '', NULL, 1, 'text', NULL, 1, 1, NULL, 0, 1, 0, 100, '超级管理员', '2021-05-05 19:40:42', 1, 1120, '', NULL, NULL, '', 0, 'Sys_DictionaryList', 4); +INSERT INTO `Sys_TableColumn` VALUES (51, NULL, NULL, NULL, NULL, '数据源Text', 'DicName', 'string', 90, '', '2018-06-06 14:12:18', NULL, NULL, '', NULL, 1, 'text', NULL, 1, 1, NULL, 0, 1, 0, 100, '超级管理员', '2021-05-05 19:40:42', 1, 1110, '', NULL, NULL, '', 0, 'Sys_DictionaryList', 4); +INSERT INTO `Sys_TableColumn` VALUES (52, NULL, NULL, NULL, NULL, '排序号', 'OrderNo', 'int', 90, '', '2018-06-06 14:12:18', NULL, NULL, '', NULL, 1, 'text', NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2021-05-05 19:40:42', 1, 1100, '', NULL, NULL, '', 0, 'Sys_DictionaryList', 4); +INSERT INTO `Sys_TableColumn` VALUES (53, NULL, NULL, NULL, NULL, '备注', 'Remark', 'string', 90, '', '2018-06-06 14:12:18', NULL, NULL, '', NULL, 1, 'text', NULL, 1, 1, NULL, 0, 1, 0, 2000, '超级管理员', '2021-05-05 19:40:42', 1, 1090, '', NULL, NULL, '', 0, 'Sys_DictionaryList', 4); +INSERT INTO `Sys_TableColumn` VALUES (54, NULL, NULL, NULL, NULL, '是否可用', 'Enable', 'sbyte', 90, '', '2018-06-06 14:12:18', NULL, NULL, 'enable', NULL, 1, 'switch', NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2021-05-05 19:40:42', 1, 1080, '', NULL, NULL, '', 0, 'Sys_DictionaryList', 4); +INSERT INTO `Sys_TableColumn` VALUES (55, NULL, NULL, NULL, NULL, '', 'CreateID', 'int', 90, '', '2018-06-06 14:12:18', NULL, NULL, '', NULL, NULL, '无', NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2021-05-05 19:40:42', 1, 1070, '', NULL, NULL, '', 0, 'Sys_DictionaryList', 4); +INSERT INTO `Sys_TableColumn` VALUES (56, NULL, NULL, NULL, NULL, '创建人', 'Creator', 'string', 130, '', '2018-06-06 14:12:18', NULL, NULL, '', NULL, NULL, '', NULL, 1, 1, NULL, 0, 1, 1, 30, '超级管理员', '2021-05-05 19:40:42', 1, 1060, '', NULL, NULL, '', 0, 'Sys_DictionaryList', 4); +INSERT INTO `Sys_TableColumn` VALUES (57, NULL, NULL, NULL, NULL, '创建时间', 'CreateDate', 'DateTime', 90, '', '2018-06-06 14:12:18', NULL, NULL, '', NULL, NULL, '', NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2021-05-05 19:40:42', 1, 1050, '', NULL, NULL, '', 0, 'Sys_DictionaryList', 4); +INSERT INTO `Sys_TableColumn` VALUES (58, NULL, NULL, NULL, NULL, '', 'ModifyID', 'int', 90, '', '2018-06-06 14:12:18', NULL, NULL, '', NULL, NULL, '', NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2021-05-05 19:40:42', 1, 1040, '', NULL, NULL, '', 0, 'Sys_DictionaryList', 4); +INSERT INTO `Sys_TableColumn` VALUES (59, NULL, NULL, NULL, NULL, '修改人', 'Modifier', 'string', 130, '', '2018-06-06 14:12:18', NULL, NULL, '', NULL, NULL, '', NULL, 1, 1, NULL, 0, 1, 0, 30, '超级管理员', '2021-05-05 19:40:42', 1, 1030, '', NULL, NULL, '', 0, 'Sys_DictionaryList', 4); +INSERT INTO `Sys_TableColumn` VALUES (60, NULL, NULL, NULL, NULL, '修改时间', 'ModifyDate', 'DateTime', 90, '', '2018-06-06 14:12:18', NULL, NULL, '', NULL, NULL, '', NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2021-05-05 19:40:42', 1, 1020, '', NULL, NULL, '', 0, 'Sys_DictionaryList', 4); +INSERT INTO `Sys_TableColumn` VALUES (61, NULL, NULL, NULL, NULL, NULL, 'Id', 'int', 90, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 1, 0, 1, NULL, '超级管理员', '2020-03-02 19:22:18', 1, 10000, NULL, NULL, NULL, NULL, NULL, 'Sys_Log', 5); +INSERT INTO `Sys_TableColumn` VALUES (62, NULL, NULL, NULL, 12, '日志类型', 'LogType', 'string', 120, NULL, '2018-06-11 18:22:16', NULL, NULL, 'log', NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 50, '超级管理员', '2020-03-02 19:22:18', 1, 8888, NULL, NULL, 3, 'checkbox', NULL, 'Sys_Log', 5); +INSERT INTO `Sys_TableColumn` VALUES (63, NULL, NULL, NULL, NULL, '请求参数', 'RequestParameter', 'string', 300, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 0, '超级管理员', '2020-03-02 19:22:18', 1, 7990, NULL, NULL, NULL, NULL, NULL, 'Sys_Log', 5); +INSERT INTO `Sys_TableColumn` VALUES (64, NULL, NULL, NULL, NULL, '响应参数', 'ResponseParameter', 'string', 250, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 0, '超级管理员', '2020-03-02 19:22:18', 1, 7980, NULL, NULL, NULL, NULL, NULL, 'Sys_Log', 5); +INSERT INTO `Sys_TableColumn` VALUES (65, NULL, NULL, NULL, NULL, '异常信息', 'ExceptionInfo', 'string', 280, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 0, '超级管理员', '2020-03-02 19:22:18', 1, 7970, NULL, NULL, NULL, NULL, NULL, 'Sys_Log', 5); +INSERT INTO `Sys_TableColumn` VALUES (66, NULL, NULL, NULL, NULL, '响应状态', 'Success', 'int', 90, NULL, '2018-06-11 18:22:16', NULL, NULL, 'restatus', NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2020-03-02 19:22:18', 1, 8700, NULL, NULL, 2, 'dropList', NULL, 'Sys_Log', 5); +INSERT INTO `Sys_TableColumn` VALUES (67, NULL, NULL, NULL, NULL, '开始时间', 'BeginDate', 'DateTime', 150, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2020-03-02 19:22:18', 1, 9999, NULL, NULL, 2, 'datetime', NULL, 'Sys_Log', 5); +INSERT INTO `Sys_TableColumn` VALUES (68, NULL, NULL, NULL, NULL, '结束时间', 'EndDate', 'DateTime', 150, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2020-03-02 19:22:18', 1, 880, NULL, NULL, NULL, NULL, NULL, 'Sys_Log', 5); +INSERT INTO `Sys_TableColumn` VALUES (69, NULL, NULL, NULL, NULL, '时长(毫秒)', 'ElapsedTime', 'int', 90, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2020-03-02 19:22:18', 1, 8600, NULL, NULL, NULL, NULL, NULL, 'Sys_Log', 5); +INSERT INTO `Sys_TableColumn` VALUES (70, NULL, NULL, NULL, NULL, '用户IP', 'UserIP', 'string', 90, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 100, '超级管理员', '2020-03-02 19:22:18', 1, 7920, NULL, NULL, 1, 'text', NULL, 'Sys_Log', 5); +INSERT INTO `Sys_TableColumn` VALUES (71, NULL, NULL, NULL, NULL, '服务器IP', 'ServiceIP', 'string', 90, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 100, '超级管理员', '2020-03-02 19:22:18', 1, 7910, NULL, NULL, 1, 'text', NULL, 'Sys_Log', 5); +INSERT INTO `Sys_TableColumn` VALUES (72, NULL, NULL, NULL, NULL, '浏览器类型', 'BrowserType', 'string', 90, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 200, '超级管理员', '2020-03-02 19:22:18', 1, 7900, NULL, NULL, NULL, NULL, NULL, 'Sys_Log', 5); +INSERT INTO `Sys_TableColumn` VALUES (73, NULL, NULL, NULL, NULL, '请求地址', 'Url', 'string', 300, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 4000, '超级管理员', '2020-03-02 19:22:18', 1, 9000, NULL, NULL, 1, 'text', NULL, 'Sys_Log', 5); +INSERT INTO `Sys_TableColumn` VALUES (74, NULL, NULL, NULL, NULL, '用户ID', 'User_Id', 'int', 90, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2020-03-02 19:22:18', 1, 7880, NULL, NULL, NULL, '无', NULL, 'Sys_Log', 5); +INSERT INTO `Sys_TableColumn` VALUES (75, NULL, NULL, NULL, NULL, '用户名称', 'UserName', 'string', 90, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 4000, '超级管理员', '2020-03-02 19:22:18', 1, 7870, NULL, NULL, NULL, NULL, NULL, 'Sys_Log', 5); +INSERT INTO `Sys_TableColumn` VALUES (76, NULL, NULL, NULL, NULL, '角色ID', 'Role_Id', 'int', 90, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2020-03-02 19:22:18', 1, 7860, NULL, NULL, 2, 'text', NULL, 'Sys_Log', 5); +INSERT INTO `Sys_TableColumn` VALUES (77, NULL, NULL, NULL, NULL, '', 'User_Id', 'int', 90, '', '2018-06-14 16:44:15', NULL, NULL, '', NULL, NULL, '', NULL, 1, 0, NULL, 1, 0, 1, NULL, '超级管理员', '2021-04-12 23:04:26', 1, 7850, '', NULL, NULL, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (78, NULL, NULL, NULL, NULL, '', 'Dept_Id', 'int', 90, '', '2018-06-14 16:44:15', NULL, NULL, '', NULL, NULL, '', NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2021-04-12 23:04:26', 1, 7840, '', NULL, NULL, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (79, 0, NULL, 1, NULL, '部门', 'DeptName', 'string', 150, '', '2018-06-14 16:44:15', NULL, NULL, '', NULL, 0, 'text', NULL, 1, 0, NULL, 0, 1, 0, 150, '超级管理员', '2021-04-12 23:04:26', 1, 7830, '', NULL, 2, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (80, 0, 0, 1, NULL, '角色', 'Role_Id', 'int', 150, '', '2018-06-14 16:44:15', NULL, NULL, 'roles', NULL, 2, 'drop', NULL, 1, 1, NULL, 0, 0, 0, NULL, '超级管理员', '2021-04-12 23:04:26', 1, 7820, '', NULL, 2, 'drop', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (81, NULL, NULL, NULL, NULL, '', 'RoleName', 'string', 90, '', '2018-06-14 16:44:15', NULL, NULL, '', NULL, 0, '', NULL, 1, 0, NULL, 0, 0, 0, 150, '超级管理员', '2021-04-12 23:04:26', 1, 7810, '', NULL, NULL, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (82, 1, 0, 1, NULL, '用户名', 'UserName', 'string', 120, '', '2018-06-14 16:44:15', NULL, NULL, '', NULL, 1, '', NULL, 1, 1, NULL, 0, 0, 1, 100, '超级管理员', '2021-04-12 23:04:26', 1, 7945, '', NULL, 1, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (83, 1, 0, NULL, NULL, '密码', 'UserPwd', 'string', 90, '', '2018-06-14 16:44:15', NULL, NULL, '', NULL, NULL, '', NULL, 0, 0, NULL, 0, 1, 0, 200, '超级管理员', '2021-04-12 23:04:26', 1, 7790, '', NULL, NULL, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (84, NULL, NULL, NULL, NULL, '用户真实姓名', 'UserTrueName', 'string', 150, '', '2018-06-14 16:44:15', NULL, NULL, '', NULL, 1, 'text', NULL, 1, 1, NULL, 0, 0, 0, 20, '超级管理员', '2021-04-12 23:04:26', 1, 7792, '', NULL, 1, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (85, NULL, NULL, NULL, NULL, '地址', 'Address', 'string', 190, '', '2018-06-14 16:44:15', NULL, NULL, '', NULL, 3, 'text', NULL, 1, 1, NULL, 0, 1, 0, 200, '超级管理员', '2021-04-12 23:04:26', 1, 7270, '', NULL, 4, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (86, NULL, NULL, NULL, NULL, '电话', 'Mobile', 'string', 140, '', '2018-06-14 16:44:15', NULL, NULL, '', NULL, 3, 'text', NULL, 1, 1, NULL, 0, 1, 0, 100, '超级管理员', '2021-04-12 23:04:26', 1, 7260, '', NULL, NULL, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (87, NULL, NULL, NULL, NULL, 'Email', 'Email', 'string', 140, '', '2018-06-14 16:44:15', NULL, NULL, '', NULL, 5, 'text', NULL, 1, 1, NULL, 0, 1, 0, 100, '超级管理员', '2021-04-12 23:04:26', 1, 7250, '', NULL, 4, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (88, NULL, NULL, NULL, NULL, '', 'Tel', 'string', 90, '', '2018-06-14 16:44:15', NULL, NULL, '', NULL, NULL, '', NULL, 1, 0, NULL, 0, 1, 0, 20, '超级管理员', '2021-04-12 23:04:26', 1, 7740, '', NULL, NULL, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (89, NULL, NULL, NULL, 12, '备注', 'Remark', 'string', 180, '', '2018-06-14 16:44:15', NULL, NULL, '', NULL, 7, 'textarea', NULL, 1, 1, NULL, 0, 1, 0, 200, '超级管理员', '2021-04-12 23:04:26', 1, 7230, '', NULL, NULL, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (90, NULL, NULL, NULL, NULL, '排序号', 'OrderNo', 'int', 90, '', '2018-06-14 16:44:15', NULL, NULL, '', NULL, 0, 'text', NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2021-04-12 23:04:26', 1, 7220, '', NULL, NULL, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (91, NULL, NULL, NULL, NULL, '是否可用', 'Enable', 'sbyte', 90, '', '2018-06-14 16:44:15', NULL, NULL, 'enable', NULL, 5, 'drop', NULL, 1, 1, NULL, 0, 0, 0, NULL, '超级管理员', '2021-04-12 23:04:26', 1, 7670, '', NULL, 4, 'drop', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (92, NULL, NULL, NULL, NULL, '', 'CreateID', 'int', 90, '', '2018-06-14 16:44:15', NULL, NULL, '', NULL, NULL, '', NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2021-04-12 23:04:26', 1, 7700, '', NULL, NULL, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (93, NULL, NULL, NULL, NULL, '创建人', 'Creator', 'string', 130, '', '2018-06-14 16:44:15', NULL, NULL, '', NULL, 6, '', NULL, 1, 1, NULL, 0, 1, 1, 200, '超级管理员', '2021-04-12 23:04:26', 1, 7690, '', NULL, NULL, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (94, NULL, NULL, NULL, NULL, '注册时间', 'CreateDate', 'DateTime', 150, '', '2018-06-14 16:44:15', NULL, NULL, '', NULL, 6, '', NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2021-04-12 23:04:26', 1, 7780, '', NULL, 5, 'datetime', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (95, NULL, NULL, NULL, NULL, '', 'ModifyID', 'int', 90, '', '2018-06-14 16:44:15', NULL, NULL, '', NULL, NULL, '', NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2021-04-12 23:04:26', 1, 7670, '', NULL, NULL, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (96, NULL, NULL, NULL, NULL, '修改人', 'Modifier', 'string', 130, '', '2018-06-14 16:44:15', NULL, NULL, '', NULL, NULL, '', NULL, 1, 1, NULL, 0, 1, 1, 200, '超级管理员', '2021-04-12 23:04:26', 1, 7660, '', NULL, NULL, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (97, NULL, NULL, NULL, NULL, '修改时间', 'ModifyDate', 'DateTime', 90, '', '2018-06-14 16:44:15', NULL, NULL, '', NULL, NULL, 'datetime', NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2021-04-12 23:04:26', 1, 7650, '', NULL, NULL, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (98, NULL, NULL, NULL, NULL, '审核状态', 'AuditStatus', 'int', 90, '', '2018-06-14 16:44:15', NULL, NULL, 'audit', NULL, NULL, '', NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2021-04-12 23:04:26', 1, 7640, '', NULL, NULL, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (99, NULL, NULL, NULL, NULL, '审核人', 'Auditor', 'string', 90, '', '2018-06-14 16:44:15', NULL, NULL, '', NULL, NULL, '', NULL, 1, 1, NULL, 0, 1, 0, 200, '超级管理员', '2021-04-12 23:04:26', 1, 7630, '', NULL, NULL, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (100, NULL, NULL, NULL, NULL, '审核时间', 'AuditDate', 'DateTime', 150, '', '2018-06-14 16:44:15', NULL, NULL, '', NULL, NULL, '', NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2021-04-12 23:04:26', 1, 7620, '', NULL, NULL, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (101, NULL, NULL, NULL, NULL, '最后登陆时间', 'LastLoginDate', 'DateTime', 150, '', '2018-06-14 16:44:15', NULL, NULL, '', NULL, NULL, '', NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2021-04-12 23:04:26', 1, 7610, '', NULL, 5, 'datetime', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (102, NULL, NULL, NULL, NULL, '最后密码修改时间', 'LastModifyPwdDate', 'DateTime', 150, '', '2018-06-14 16:44:15', NULL, NULL, '', NULL, NULL, '', NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2021-04-12 23:04:26', 1, 7600, '', NULL, NULL, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (114, NULL, NULL, NULL, NULL, '头像', 'HeadImageUrl', 'string', 150, '', NULL, NULL, NULL, '', NULL, 9, 'img', NULL, 1, 1, 1, NULL, 1, 0, 200, '超级管理员', '2021-04-12 23:04:26', 1, 7842, '', NULL, NULL, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (429, 1, 0, NULL, NULL, '手机号', 'PhoneNo', 'string', 150, '', NULL, NULL, NULL, '', NULL, NULL, '', NULL, 1, 1, NULL, NULL, 1, 0, 11, '超级管理员', '2021-04-12 23:04:26', 1, 7760, '', NULL, 3, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (431, NULL, NULL, NULL, NULL, 'Token', 'Token', 'string', 180, '', NULL, NULL, NULL, '', NULL, 4, '', NULL, 1, 1, NULL, NULL, 1, 0, 500, '超级管理员', '2021-04-12 23:04:26', 1, 7810, '', NULL, 2, '', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (506, NULL, NULL, NULL, NULL, '性别', 'Gender', 'int', 100, '', NULL, NULL, NULL, 'gender', NULL, 4, 'drop', NULL, 1, 1, NULL, NULL, 1, 0, NULL, '超级管理员', '2021-04-12 23:04:26', 1, 7843, '', NULL, 1, 'drop', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (654, NULL, NULL, NULL, NULL, '登陆设备类型', 'AppType', 'int', 150, '', NULL, NULL, NULL, 'ut', NULL, 0, '', NULL, 1, 1, NULL, NULL, 1, 0, NULL, '超级管理员', '2021-04-12 23:04:26', 1, 7809, '', NULL, 3, 'dropList', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (659, NULL, NULL, NULL, NULL, '是否手机用户', 'IsRegregisterPhone', 'int', 120, '', NULL, NULL, NULL, 'isphone', NULL, 2, 'drop', NULL, 1, 0, NULL, NULL, 0, 0, NULL, '超级管理员', '2021-04-12 23:04:26', 1, 7771, '', NULL, 3, 'drop', 0, 'Sys_User', 6); +INSERT INTO `Sys_TableColumn` VALUES (764, NULL, NULL, NULL, NULL, '', 'FormId', 'string', 110, NULL, '2022-01-03 19:26:44', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 1, 0, 1, 36, '超级管理员', '2022-01-03 19:28:41', 1, 1150, NULL, NULL, NULL, NULL, 0, 'FormDesignOptions', 84); +INSERT INTO `Sys_TableColumn` VALUES (765, NULL, NULL, NULL, NULL, '表单名称', 'Title', 'string', 220, NULL, '2022-01-03 19:26:44', 1, '超级管理员', NULL, NULL, 1, NULL, NULL, 1, 1, NULL, 0, 0, 0, 500, '超级管理员', '2022-01-03 19:28:41', 1, 1100, NULL, NULL, 1, 'like', 0, 'FormDesignOptions', 84); +INSERT INTO `Sys_TableColumn` VALUES (766, NULL, NULL, NULL, NULL, '设计器配置', 'DaraggeOptions', 'string', 110, NULL, '2022-01-03 19:26:44', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 0, '超级管理员', '2022-01-03 19:28:41', 1, 1050, NULL, NULL, NULL, NULL, 0, 'FormDesignOptions', 84); +INSERT INTO `Sys_TableColumn` VALUES (767, NULL, NULL, NULL, NULL, '表单参数', 'FormOptions', 'string', 110, NULL, '2022-01-03 19:26:44', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 0, '超级管理员', '2022-01-03 19:28:41', 1, 1000, NULL, NULL, NULL, NULL, 0, 'FormDesignOptions', 84); +INSERT INTO `Sys_TableColumn` VALUES (768, NULL, NULL, NULL, NULL, '表单配置', 'FormConfig', 'string', 110, NULL, '2022-01-03 19:26:44', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 0, '超级管理员', '2022-01-03 19:28:41', 1, 950, NULL, NULL, NULL, NULL, 0, 'FormDesignOptions', 84); +INSERT INTO `Sys_TableColumn` VALUES (769, NULL, NULL, NULL, NULL, '表单字段', 'FormFields', 'string', 110, NULL, '2022-01-03 19:26:44', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 0, '超级管理员', '2022-01-03 19:28:41', 1, 900, NULL, NULL, NULL, NULL, 0, 'FormDesignOptions', 84); +INSERT INTO `Sys_TableColumn` VALUES (770, NULL, NULL, NULL, NULL, '表格配置', 'TableConfig', 'string', 110, NULL, '2022-01-03 19:26:44', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 0, '超级管理员', '2022-01-03 19:28:41', 1, 850, NULL, NULL, NULL, NULL, 0, 'FormDesignOptions', 84); +INSERT INTO `Sys_TableColumn` VALUES (771, NULL, NULL, NULL, NULL, '创建时间', 'CreateDate', 'DateTime', 110, NULL, '2022-01-03 19:26:44', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-01-03 19:28:41', 1, 800, NULL, NULL, 1, 'datetime', 0, 'FormDesignOptions', 84); +INSERT INTO `Sys_TableColumn` VALUES (772, NULL, NULL, NULL, NULL, '', 'CreateID', 'int', 80, NULL, '2022-01-03 19:26:44', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2022-01-03 19:28:41', 1, 750, NULL, NULL, NULL, NULL, 0, 'FormDesignOptions', 84); +INSERT INTO `Sys_TableColumn` VALUES (773, NULL, NULL, NULL, NULL, '创建人', 'Creator', 'string', 130, NULL, '2022-01-03 19:26:44', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 30, '超级管理员', '2022-01-03 19:28:41', 1, 700, NULL, NULL, NULL, NULL, 0, 'FormDesignOptions', 84); +INSERT INTO `Sys_TableColumn` VALUES (774, NULL, NULL, NULL, NULL, '', 'Modifier', 'string', 130, NULL, '2022-01-03 19:26:44', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 30, '超级管理员', '2022-01-03 19:28:41', 1, 650, NULL, NULL, NULL, NULL, 0, 'FormDesignOptions', 84); +INSERT INTO `Sys_TableColumn` VALUES (775, NULL, NULL, NULL, NULL, '', 'ModifyDate', 'DateTime', 110, NULL, '2022-01-03 19:26:44', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-01-03 19:28:41', 1, 600, NULL, NULL, NULL, NULL, 0, 'FormDesignOptions', 84); +INSERT INTO `Sys_TableColumn` VALUES (776, NULL, NULL, NULL, NULL, '', 'ModifyID', 'int', 80, NULL, '2022-01-03 19:26:44', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2022-01-03 19:28:41', 1, 550, NULL, NULL, NULL, NULL, 0, 'FormDesignOptions', 84); +INSERT INTO `Sys_TableColumn` VALUES (777, NULL, NULL, NULL, NULL, '', 'FormCollectionId', 'string', 110, NULL, '2022-01-03 19:29:20', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 1, 0, 1, 36, '超级管理员', '2022-01-03 19:30:13', 1, 1000, NULL, NULL, NULL, NULL, 0, 'FormCollectionObject', 85); +INSERT INTO `Sys_TableColumn` VALUES (778, NULL, NULL, NULL, NULL, '', 'FormId', 'string', 110, NULL, '2022-01-03 19:29:20', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 36, '超级管理员', '2022-01-03 19:30:13', 1, 950, NULL, NULL, NULL, NULL, 0, 'FormCollectionObject', 85); +INSERT INTO `Sys_TableColumn` VALUES (779, NULL, NULL, NULL, NULL, '标题', 'Title', 'string', 110, NULL, '2022-01-03 19:29:20', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 0, '超级管理员', '2022-01-03 19:30:13', 1, 900, NULL, NULL, 1, 'like', 0, 'FormCollectionObject', 85); +INSERT INTO `Sys_TableColumn` VALUES (780, NULL, NULL, NULL, NULL, '表单数据', 'FormData', 'string', 110, NULL, '2022-01-03 19:29:20', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 0, '超级管理员', '2022-01-03 19:30:13', 1, 850, NULL, NULL, NULL, NULL, 0, 'FormCollectionObject', 85); +INSERT INTO `Sys_TableColumn` VALUES (781, NULL, NULL, NULL, NULL, '提交时间', 'CreateDate', 'DateTime', 110, NULL, '2022-01-03 19:29:20', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-01-03 19:30:13', 1, 800, NULL, NULL, 1, 'datetime', 0, 'FormCollectionObject', 85); +INSERT INTO `Sys_TableColumn` VALUES (782, NULL, NULL, NULL, NULL, '', 'CreateID', 'int', 80, NULL, '2022-01-03 19:29:20', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2022-01-03 19:30:13', 1, 750, NULL, NULL, NULL, NULL, 0, 'FormCollectionObject', 85); +INSERT INTO `Sys_TableColumn` VALUES (783, NULL, NULL, NULL, NULL, '提交人', 'Creator', 'string', 130, NULL, '2022-01-03 19:29:20', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 30, '超级管理员', '2022-01-03 19:30:13', 1, 700, NULL, NULL, 1, NULL, 0, 'FormCollectionObject', 85); +INSERT INTO `Sys_TableColumn` VALUES (784, NULL, NULL, NULL, NULL, '', 'Modifier', 'string', 130, NULL, '2022-01-03 19:29:20', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 30, '超级管理员', '2022-01-03 19:30:13', 1, 650, NULL, NULL, NULL, NULL, 0, 'FormCollectionObject', 85); +INSERT INTO `Sys_TableColumn` VALUES (785, NULL, NULL, NULL, NULL, '', 'ModifyDate', 'DateTime', 110, NULL, '2022-01-03 19:29:20', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-01-03 19:30:13', 1, 600, NULL, NULL, NULL, NULL, 0, 'FormCollectionObject', 85); +INSERT INTO `Sys_TableColumn` VALUES (786, NULL, NULL, NULL, NULL, '', 'ModifyID', 'int', 80, NULL, '2022-01-03 19:29:20', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2022-01-03 19:30:13', 1, 550, NULL, NULL, NULL, NULL, 0, 'FormCollectionObject', 85); +INSERT INTO `Sys_TableColumn` VALUES (801, NULL, NULL, NULL, NULL, '', 'WorkFlow_Id', 'string', 120, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 1, 0, 1, 36, '超级管理员', '2022-08-17 23:37:59', 1, 0, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlow', 88); +INSERT INTO `Sys_TableColumn` VALUES (802, NULL, NULL, NULL, NULL, '流程名称', 'WorkName', 'string', 120, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, 1, 1, NULL, 0, 0, 0, 200, '超级管理员', '2022-08-17 23:37:59', 1, 0, NULL, NULL, 1, 'like', 0, 'Sys_WorkFlow', 88); +INSERT INTO `Sys_TableColumn` VALUES (803, NULL, NULL, NULL, NULL, '表名', 'WorkTable', 'string', 120, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, 1, 1, NULL, 0, 0, 0, 200, '超级管理员', '2022-08-17 23:37:59', 1, 0, NULL, NULL, 1, '', 0, 'Sys_WorkFlow', 88); +INSERT INTO `Sys_TableColumn` VALUES (804, NULL, NULL, NULL, NULL, '功能菜单', 'WorkTableName', 'string', 120, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, 1, 1, NULL, 0, 1, 0, 200, '超级管理员', '2022-08-17 23:37:59', 1, 0, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlow', 88); +INSERT INTO `Sys_TableColumn` VALUES (805, NULL, NULL, NULL, NULL, '节点信息', 'NodeConfig', 'string', 120, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, 1, 1, NULL, 0, 1, 0, 0, '超级管理员', '2022-08-17 23:37:59', 1, 0, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlow', 88); +INSERT INTO `Sys_TableColumn` VALUES (806, NULL, NULL, NULL, NULL, '连接配置', 'LineConfig', 'string', 120, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, 1, 1, NULL, 0, 1, 0, 0, '超级管理员', '2022-08-17 23:37:59', 1, 0, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlow', 88); +INSERT INTO `Sys_TableColumn` VALUES (807, NULL, NULL, NULL, NULL, '备注', 'Remark', 'string', 120, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, 1, 1, NULL, 0, 1, 0, 500, '超级管理员', '2022-08-17 23:37:59', 1, 0, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlow', 88); +INSERT INTO `Sys_TableColumn` VALUES (808, NULL, NULL, NULL, NULL, '创建时间', 'CreateDate', 'DateTime', 120, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:37:59', 1, 0, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlow', 88); +INSERT INTO `Sys_TableColumn` VALUES (809, NULL, NULL, NULL, NULL, '', 'CreateID', 'int', 120, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:37:59', 1, 0, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlow', 88); +INSERT INTO `Sys_TableColumn` VALUES (810, NULL, NULL, NULL, NULL, '', 'Creator', 'string', 120, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, 30, '超级管理员', '2022-08-17 23:37:59', 1, 0, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlow', 88); +INSERT INTO `Sys_TableColumn` VALUES (811, NULL, NULL, NULL, NULL, '是否启用', 'Enable', 'sbyte', 120, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:37:59', 1, 0, NULL, NULL, 1, 'datetime', 0, 'Sys_WorkFlow', 88); +INSERT INTO `Sys_TableColumn` VALUES (812, NULL, NULL, NULL, NULL, '', 'Modifier', 'string', 120, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 30, '超级管理员', '2022-08-17 23:37:59', 1, 0, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlow', 88); +INSERT INTO `Sys_TableColumn` VALUES (813, NULL, NULL, NULL, NULL, '', 'ModifyDate', 'DateTime', 120, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:37:59', 1, 0, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlow', 88); +INSERT INTO `Sys_TableColumn` VALUES (814, NULL, NULL, NULL, NULL, '', 'ModifyID', 'int', 120, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:37:59', 1, 0, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlow', 88); +INSERT INTO `Sys_TableColumn` VALUES (815, NULL, NULL, NULL, NULL, '', 'WorkStepFlow_Id', 'string', 110, NULL, '2022-08-17 23:20:22', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 1, 0, 1, 36, '超级管理员', '2022-08-17 23:38:35', 1, 1250, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowStep', 89); +INSERT INTO `Sys_TableColumn` VALUES (816, NULL, NULL, NULL, NULL, '流程主表id', 'WorkFlow_Id', 'string', 110, NULL, '2022-08-17 23:20:22', 1, '超级管理员', NULL, NULL, 0, NULL, NULL, 1, 1, NULL, 0, 1, 0, 36, '超级管理员', '2022-08-17 23:38:35', 1, 1200, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowStep', 89); +INSERT INTO `Sys_TableColumn` VALUES (817, NULL, NULL, NULL, NULL, '流程节点Id', 'StepId', 'string', 120, NULL, '2022-08-17 23:20:22', 1, '超级管理员', NULL, NULL, 0, NULL, NULL, 1, 1, NULL, 0, 1, 0, 100, '超级管理员', '2022-08-17 23:38:35', 1, 1150, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowStep', 89); +INSERT INTO `Sys_TableColumn` VALUES (818, NULL, NULL, NULL, NULL, '节点名称', 'StepName', 'string', 180, NULL, '2022-08-17 23:20:22', 1, '超级管理员', NULL, NULL, 0, NULL, NULL, 1, 1, NULL, 0, 1, 0, 200, '超级管理员', '2022-08-17 23:38:35', 1, 1100, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowStep', 89); +INSERT INTO `Sys_TableColumn` VALUES (819, NULL, NULL, NULL, NULL, '节点类型(1=按用户审批,2=按角色审批,3=按部门审批)', 'StepType', 'int', 110, NULL, '2022-08-17 23:20:22', 1, '超级管理员', NULL, NULL, 0, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:38:35', 1, 1050, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowStep', 89); +INSERT INTO `Sys_TableColumn` VALUES (820, NULL, NULL, NULL, NULL, '审批用户id或角色id、部门id', 'StepValue', 'int', 110, NULL, '2022-08-17 23:20:22', 1, '超级管理员', NULL, NULL, 0, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:38:35', 1, 1000, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowStep', 89); +INSERT INTO `Sys_TableColumn` VALUES (821, NULL, NULL, NULL, NULL, '审批顺序', 'OrderId', 'int', 110, NULL, '2022-08-17 23:20:22', 1, '超级管理员', NULL, NULL, 0, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:38:35', 1, 950, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowStep', 89); +INSERT INTO `Sys_TableColumn` VALUES (822, NULL, NULL, NULL, NULL, '备注', 'Remark', 'string', 220, NULL, '2022-08-17 23:20:22', 1, '超级管理员', NULL, NULL, 0, NULL, NULL, 1, 1, NULL, 0, 1, 0, 500, '超级管理员', '2022-08-17 23:38:35', 1, 900, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowStep', 89); +INSERT INTO `Sys_TableColumn` VALUES (823, NULL, NULL, NULL, NULL, '创建时间', 'CreateDate', 'DateTime', 110, NULL, '2022-08-17 23:20:22', 1, '超级管理员', NULL, NULL, 0, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:38:35', 1, 850, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowStep', 89); +INSERT INTO `Sys_TableColumn` VALUES (824, NULL, NULL, NULL, NULL, '', 'CreateID', 'int', 80, NULL, '2022-08-17 23:20:22', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:38:35', 1, 800, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowStep', 89); +INSERT INTO `Sys_TableColumn` VALUES (825, NULL, NULL, NULL, NULL, '', 'Creator', 'string', 130, NULL, '2022-08-17 23:20:22', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 30, '超级管理员', '2022-08-17 23:38:35', 1, 750, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowStep', 89); +INSERT INTO `Sys_TableColumn` VALUES (826, NULL, NULL, NULL, NULL, '', 'Enable', 'sbyte', 110, NULL, '2022-08-17 23:20:22', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:38:35', 1, 700, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowStep', 89); +INSERT INTO `Sys_TableColumn` VALUES (827, NULL, NULL, NULL, NULL, '', 'Modifier', 'string', 130, NULL, '2022-08-17 23:20:22', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 30, '超级管理员', '2022-08-17 23:38:35', 1, 650, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowStep', 89); +INSERT INTO `Sys_TableColumn` VALUES (828, NULL, NULL, NULL, NULL, '', 'ModifyDate', 'DateTime', 110, NULL, '2022-08-17 23:20:22', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:38:35', 1, 600, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowStep', 89); +INSERT INTO `Sys_TableColumn` VALUES (829, NULL, NULL, NULL, NULL, '', 'ModifyID', 'int', 80, NULL, '2022-08-17 23:20:22', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:38:35', 1, 550, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowStep', 89); +INSERT INTO `Sys_TableColumn` VALUES (830, NULL, NULL, NULL, NULL, '', 'WorkFlowTable_Id', 'string', 110, NULL, '2022-08-17 23:21:04', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 1, 0, 1, 36, '超级管理员', '2022-08-17 23:40:13', 1, 1250, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTable', 90); +INSERT INTO `Sys_TableColumn` VALUES (831, NULL, NULL, NULL, NULL, '流程id', 'WorkFlow_Id', 'string', 110, NULL, '2022-08-17 23:21:04', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, 36, '超级管理员', '2022-08-17 23:40:13', 1, 1200, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTable', 90); +INSERT INTO `Sys_TableColumn` VALUES (832, NULL, NULL, NULL, NULL, '流程名称', 'WorkName', 'string', 180, NULL, '2022-08-17 23:21:04', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 200, '超级管理员', '2022-08-17 23:40:13', 1, 1150, NULL, NULL, 1, NULL, 0, 'Sys_WorkFlowTable', 90); +INSERT INTO `Sys_TableColumn` VALUES (833, NULL, NULL, NULL, NULL, '表主键id', 'WorkTableKey', 'string', 180, NULL, '2022-08-17 23:21:04', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, 200, '超级管理员', '2022-08-17 23:40:13', 1, 1100, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTable', 90); +INSERT INTO `Sys_TableColumn` VALUES (834, NULL, NULL, NULL, NULL, '表名', 'WorkTable', 'string', 120, NULL, '2022-08-17 23:21:04', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 200, '超级管理员', '2022-08-17 23:40:13', 1, 1050, NULL, NULL, 1, NULL, 0, 'Sys_WorkFlowTable', 90); +INSERT INTO `Sys_TableColumn` VALUES (835, NULL, NULL, NULL, NULL, '业务名称', 'WorkTableName', 'string', 120, NULL, '2022-08-17 23:21:04', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 200, '超级管理员', '2022-08-17 23:40:13', 1, 1000, NULL, NULL, 1, NULL, 0, 'Sys_WorkFlowTable', 90); +INSERT INTO `Sys_TableColumn` VALUES (836, NULL, NULL, NULL, NULL, '当前审批节点', 'CurrentOrderId', 'int', 110, NULL, '2022-08-17 23:21:04', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:40:13', 1, 950, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTable', 90); +INSERT INTO `Sys_TableColumn` VALUES (837, NULL, NULL, NULL, NULL, '审批状态', 'AuditStatus', 'int', 110, NULL, '2022-08-17 23:21:04', 1, '超级管理员', 'audit', NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:40:13', 1, 900, NULL, NULL, 1, 'select', 0, 'Sys_WorkFlowTable', 90); +INSERT INTO `Sys_TableColumn` VALUES (838, NULL, NULL, NULL, NULL, '创建时间', 'CreateDate', 'DateTime', 110, NULL, '2022-08-17 23:21:04', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:40:13', 1, 850, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTable', 90); +INSERT INTO `Sys_TableColumn` VALUES (839, NULL, NULL, NULL, NULL, '', 'CreateID', 'int', 80, NULL, '2022-08-17 23:21:04', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:40:13', 1, 800, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTable', 90); +INSERT INTO `Sys_TableColumn` VALUES (840, NULL, NULL, NULL, NULL, '创建时间', 'Creator', 'string', 130, NULL, '2022-08-17 23:21:04', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 30, '超级管理员', '2022-08-17 23:40:13', 1, 750, NULL, NULL, 1, 'datetime', 0, 'Sys_WorkFlowTable', 90); +INSERT INTO `Sys_TableColumn` VALUES (841, NULL, NULL, NULL, NULL, '', 'Enable', 'sbyte', 110, NULL, '2022-08-17 23:21:04', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:40:13', 1, 700, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTable', 90); +INSERT INTO `Sys_TableColumn` VALUES (842, NULL, NULL, NULL, NULL, '', 'Modifier', 'string', 130, NULL, '2022-08-17 23:21:04', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 30, '超级管理员', '2022-08-17 23:40:13', 1, 650, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTable', 90); +INSERT INTO `Sys_TableColumn` VALUES (843, NULL, NULL, NULL, NULL, '', 'ModifyDate', 'DateTime', 110, NULL, '2022-08-17 23:21:04', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:40:13', 1, 600, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTable', 90); +INSERT INTO `Sys_TableColumn` VALUES (844, NULL, NULL, NULL, NULL, '', 'ModifyID', 'int', 80, NULL, '2022-08-17 23:21:04', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:40:13', 1, 550, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTable', 90); +INSERT INTO `Sys_TableColumn` VALUES (845, NULL, NULL, NULL, NULL, '', 'Sys_WorkFlowTableStep_Id', 'string', 110, NULL, '2022-08-17 23:22:13', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 1, 0, 1, 36, '超级管理员', '2022-08-17 23:22:24', 1, 1500, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTableStep', 91); +INSERT INTO `Sys_TableColumn` VALUES (846, NULL, NULL, NULL, NULL, '', 'Modifier', 'string', 130, NULL, '2022-08-17 23:22:13', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 30, '超级管理员', '2022-08-17 23:22:24', 1, 650, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTableStep', 91); +INSERT INTO `Sys_TableColumn` VALUES (847, NULL, NULL, NULL, NULL, '', 'Enable', 'sbyte', 110, NULL, '2022-08-17 23:22:13', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:22:24', 1, 700, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTableStep', 91); +INSERT INTO `Sys_TableColumn` VALUES (848, NULL, NULL, NULL, NULL, '', 'Creator', 'string', 130, NULL, '2022-08-17 23:22:13', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 30, '超级管理员', '2022-08-17 23:22:24', 1, 750, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTableStep', 91); +INSERT INTO `Sys_TableColumn` VALUES (849, NULL, NULL, NULL, NULL, '', 'CreateID', 'int', 80, NULL, '2022-08-17 23:22:13', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:22:24', 1, 800, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTableStep', 91); +INSERT INTO `Sys_TableColumn` VALUES (850, NULL, NULL, NULL, NULL, '', 'CreateDate', 'DateTime', 110, NULL, '2022-08-17 23:22:13', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:22:24', 1, 850, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTableStep', 91); +INSERT INTO `Sys_TableColumn` VALUES (851, NULL, NULL, NULL, NULL, '', 'Remark', 'string', 220, NULL, '2022-08-17 23:22:13', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 500, '超级管理员', '2022-08-17 23:22:24', 1, 900, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTableStep', 91); +INSERT INTO `Sys_TableColumn` VALUES (852, NULL, NULL, NULL, NULL, '审核时间', 'AuditDate', 'DateTime', 110, NULL, '2022-08-17 23:22:13', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:22:24', 1, 950, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTableStep', 91); +INSERT INTO `Sys_TableColumn` VALUES (853, NULL, NULL, NULL, NULL, '审核状态', 'AuditStatus', 'int', 110, NULL, '2022-08-17 23:22:13', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:22:24', 1, 1000, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTableStep', 91); +INSERT INTO `Sys_TableColumn` VALUES (854, NULL, NULL, NULL, NULL, '审核人', 'Auditor', 'string', 110, NULL, '2022-08-17 23:22:13', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 50, '超级管理员', '2022-08-17 23:22:24', 1, 1050, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTableStep', 91); +INSERT INTO `Sys_TableColumn` VALUES (855, NULL, NULL, NULL, NULL, '审核人id', 'AuditId', 'int', 110, NULL, '2022-08-17 23:22:13', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:22:24', 1, 1100, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTableStep', 91); +INSERT INTO `Sys_TableColumn` VALUES (856, NULL, NULL, NULL, NULL, '审批顺序', 'OrderId', 'int', 110, NULL, '2022-08-17 23:22:13', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:22:24', 1, 1150, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTableStep', 91); +INSERT INTO `Sys_TableColumn` VALUES (857, NULL, NULL, NULL, NULL, '节点类型(1=按用户审批,2=按角色审批,3=按部门审批 )', 'StepValue', 'int', 110, NULL, '2022-08-17 23:22:13', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:22:24', 1, 1200, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTableStep', 91); +INSERT INTO `Sys_TableColumn` VALUES (858, NULL, NULL, NULL, NULL, '审批类型', 'StepType', 'int', 110, NULL, '2022-08-17 23:22:13', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:22:24', 1, 1250, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTableStep', 91); +INSERT INTO `Sys_TableColumn` VALUES (859, NULL, NULL, NULL, NULL, '节名称', 'StepName', 'string', 180, NULL, '2022-08-17 23:22:13', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 200, '超级管理员', '2022-08-17 23:22:24', 1, 1300, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTableStep', 91); +INSERT INTO `Sys_TableColumn` VALUES (860, NULL, NULL, NULL, NULL, '节点id', 'StepId', 'string', 120, NULL, '2022-08-17 23:22:13', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 100, '超级管理员', '2022-08-17 23:22:24', 1, 1350, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTableStep', 91); +INSERT INTO `Sys_TableColumn` VALUES (861, NULL, NULL, NULL, NULL, '流程id', 'WorkFlow_Id', 'string', 110, NULL, '2022-08-17 23:22:13', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 36, '超级管理员', '2022-08-17 23:22:24', 1, 1400, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTableStep', 91); +INSERT INTO `Sys_TableColumn` VALUES (862, NULL, NULL, NULL, NULL, '主表id', 'WorkFlowTable_Id', 'string', 110, NULL, '2022-08-17 23:22:13', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 0, 0, 36, '超级管理员', '2022-08-17 23:22:24', 1, 1450, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTableStep', 91); +INSERT INTO `Sys_TableColumn` VALUES (863, NULL, NULL, NULL, NULL, '', 'ModifyDate', 'DateTime', 110, NULL, '2022-08-17 23:22:13', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:22:24', 1, 600, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTableStep', 91); +INSERT INTO `Sys_TableColumn` VALUES (864, NULL, NULL, NULL, NULL, '', 'ModifyID', 'int', 80, NULL, '2022-08-17 23:22:13', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2022-08-17 23:22:24', 1, 550, NULL, NULL, NULL, NULL, 0, 'Sys_WorkFlowTableStep', 91); + +-- ---------------------------- +-- Table structure for Sys_TableInfo +-- ---------------------------- +DROP TABLE IF EXISTS `Sys_TableInfo`; +CREATE TABLE `Sys_TableInfo` ( + `Table_Id` int(11) NOT NULL AUTO_INCREMENT, + `CnName` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `ColumnCNName` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `DBServer` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `DataTableType` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `DetailCnName` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `DetailName` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `EditorType` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `Enable` int(11) NULL DEFAULT NULL, + `ExpressField` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `FolderName` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `Namespace` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `OrderNo` int(11) NULL DEFAULT NULL, + `ParentId` int(11) NULL DEFAULT NULL, + `RichText` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `SortName` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `TableName` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `TableTrueName` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `UploadField` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `UploadMaxCount` int(11) NULL DEFAULT NULL, + PRIMARY KEY (`Table_Id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 92 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = COMPACT; + +-- ---------------------------- +-- Records of Sys_TableInfo +-- ---------------------------- +INSERT INTO `Sys_TableInfo` VALUES (2, '角色管理', '角色管理', NULL, NULL, NULL, NULL, NULL, 1, 'RoleName', 'System', 'VOL.System', NULL, 8, NULL, NULL, 'Sys_Role', 'Sys_Role', NULL, NULL); +INSERT INTO `Sys_TableInfo` VALUES (3, '字典数据', '字典数据', NULL, NULL, '字典明细', 'Sys_DictionaryList', NULL, 1, 'DicName', 'System', 'VOL.System', NULL, 11, NULL, NULL, 'Sys_Dictionary', NULL, NULL, NULL); +INSERT INTO `Sys_TableInfo` VALUES (4, '字典明细', '字典明细', NULL, NULL, NULL, NULL, NULL, 1, NULL, 'System', 'VOL.System', NULL, 11, NULL, NULL, 'Sys_DictionaryList', 'Sys_DictionaryList', NULL, NULL); +INSERT INTO `Sys_TableInfo` VALUES (5, '系统日志', '系统日志', NULL, NULL, NULL, NULL, NULL, 1, NULL, 'System', 'VOL.System', NULL, 10, NULL, NULL, 'Sys_Log', 'Sys_Log', NULL, NULL); +INSERT INTO `Sys_TableInfo` VALUES (6, NULL, '用户管理', NULL, NULL, NULL, NULL, NULL, 1, 'UserName', 'System', 'VOL.System', NULL, 8, NULL, '', 'Sys_User', 'Sys_User', 'HeadImageUrl', 1); +INSERT INTO `Sys_TableInfo` VALUES (8, '用户基础信息', '用户基础信息', NULL, NULL, NULL, NULL, NULL, 1, NULL, 'System', 'VOL.System', 200, 0, NULL, NULL, '无', NULL, NULL, NULL); +INSERT INTO `Sys_TableInfo` VALUES (10, '日志管理', '日志管理', NULL, NULL, NULL, NULL, NULL, 1, NULL, 'System', 'VOL.System', NULL, 0, NULL, '170', '日志管理', '日志管理', NULL, NULL); +INSERT INTO `Sys_TableInfo` VALUES (11, '配置管理', '配置管理', NULL, NULL, NULL, NULL, NULL, 1, NULL, 'System', 'VOL.System', NULL, 0, NULL, '250', '配置管理', NULL, NULL, NULL); +INSERT INTO `Sys_TableInfo` VALUES (83, '表单设计', '表单设计', NULL, NULL, NULL, NULL, NULL, 1, NULL, 'System', 'VOL.System', NULL, 0, NULL, NULL, '表单设计', NULL, NULL, NULL); +INSERT INTO `Sys_TableInfo` VALUES (84, '表单设计', '表单设计', NULL, NULL, NULL, '', NULL, 1, 'Title', 'form', 'VOL.System', NULL, 83, NULL, 'CreateDate', 'FormDesignOptions', 'FormDesignOptions', NULL, NULL); +INSERT INTO `Sys_TableInfo` VALUES (85, '数据采集', '数据采集', NULL, NULL, NULL, NULL, NULL, 1, NULL, 'form', 'VOL.System', NULL, 83, NULL, 'CreateDate', 'FormCollectionObject', 'FormCollectionObject', NULL, NULL); +INSERT INTO `Sys_TableInfo` VALUES (87, '审批流程', '审批流程', NULL, NULL, NULL, NULL, NULL, 1, NULL, '审批流程', 'VOL.System', NULL, 0, NULL, NULL, '审批流程', NULL, NULL, NULL); +INSERT INTO `Sys_TableInfo` VALUES (88, '审批流程配置', '审批流程配置', NULL, NULL, '审批步骤', 'Sys_WorkFlowStep', NULL, 1, 'WorkName', 'flow', 'VOL.System', NULL, 87, NULL, 'CreateDate', 'Sys_WorkFlow', 'Sys_WorkFlow', NULL, NULL); +INSERT INTO `Sys_TableInfo` VALUES (89, '审批节点配置', '审批节点配置', NULL, NULL, '', NULL, NULL, 1, NULL, 'flow', 'VOL.System', NULL, 87, NULL, 'CreateDate', 'Sys_WorkFlowStep', 'Sys_WorkFlowStep', NULL, NULL); +INSERT INTO `Sys_TableInfo` VALUES (90, '审批流程', '审批流程', NULL, NULL, '审批节点', 'Sys_WorkFlowTableStep', NULL, 1, NULL, 'flow', 'VOL.System', NULL, 87, NULL, 'CreateDate', 'Sys_WorkFlowTable', 'Sys_WorkFlowTable', NULL, NULL); +INSERT INTO `Sys_TableInfo` VALUES (91, '审批节点', '审批节点', NULL, NULL, NULL, NULL, NULL, 1, NULL, 'flow', 'VOL.System', NULL, 87, NULL, 'CreateDate', 'Sys_WorkFlowTableStep', 'Sys_WorkFlowTableStep', NULL, NULL); + +-- ---------------------------- +-- Table structure for Sys_User +-- ---------------------------- +DROP TABLE IF EXISTS `Sys_User`; +CREATE TABLE `Sys_User` ( + `User_Id` int(11) NOT NULL AUTO_INCREMENT, + `Address` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `AppType` int(11) NULL DEFAULT NULL, + `AuditDate` datetime(0) NULL DEFAULT NULL, + `AuditStatus` int(11) NULL DEFAULT NULL, + `Auditor` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `CreateDate` datetime(0) NULL DEFAULT NULL, + `CreateID` int(11) NULL DEFAULT NULL, + `Creator` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `DeptName` varchar(150) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `Dept_Id` int(11) NULL DEFAULT NULL, + `Email` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `Enable` tinyint(4) NOT NULL, + `Gender` int(1) NULL DEFAULT NULL, + `HeadImageUrl` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `IsRegregisterPhone` int(11) NOT NULL, + `LastLoginDate` datetime(0) NULL DEFAULT NULL, + `LastModifyPwdDate` datetime(0) NULL DEFAULT NULL, + `Mobile` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `Modifier` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `ModifyDate` datetime(0) NULL DEFAULT NULL, + `ModifyID` int(11) NULL DEFAULT NULL, + `OrderNo` int(11) NULL DEFAULT NULL, + `Role_Id` int(11) NOT NULL, + `RoleName` varchar(150) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `PhoneNo` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `Remark` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `Tel` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `UserName` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `UserPwd` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `UserTrueName` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `Token` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`User_Id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 3380 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = COMPACT; + +-- ---------------------------- +-- Records of Sys_User +-- ---------------------------- +INSERT INTO `Sys_User` VALUES (1, '北京市西城区', 0, '2019-08-18 00:54:06', 1, '超级管理员', '2012-06-10 11:10:03', NULL, NULL, NULL, 0, '283591387@qq.com', 1, 1, 'Upload/Tables/Sys_User/202006191408112343/1111s.jpg', 0, '2017-08-28 09:58:55', '2019-12-14 15:13:49', NULL, '超级管理员', '2020-06-19 14:08:12', 1, 0, 1, '超级管理员', '13888888888', '~还没想好...', NULL, 'admin', 'j79rYYvCz4vdhcboB1Ausg==', '超级管理员', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIxIiwiaWF0IjoiMTY2NzY2NjA4OSIsIm5iZiI6IjE2Njc2NjYwODkiLCJleHAiOiIxNjY3NjczMjg5IiwiaXNzIjoidm9sLmNvcmUub3duZXIiLCJhdWQiOiJ2b2wuY29yZSJ9.YNJMmbtmwkVSOEOHGVZquZqvOnhDQkqJkRlM2Sx-o2g'); +INSERT INTO `Sys_User` VALUES (3362, '北京市还没注册', NULL, '2019-08-18 00:54:06', 1, '超级管理员', '2019-08-13 14:24:27', NULL, NULL, NULL, NULL, NULL, 1, 0, 'Upload/Tables/Sys_User/202004241341311851/04.jpg', 0, NULL, '2019-09-22 23:12:33', '01012345678', '超级管理员', '2021-01-27 12:53:41', 1, NULL, 2, '测试管理员', NULL, NULL, NULL, 'admin666', 'j79rYYvCz4vdhcboB1Ausg==', '演示帐号', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIzMzYyIiwiaWF0IjoiMTY2MDg5NTY1MiIsIm5iZiI6IjE2NjA4OTU2NTIiLCJleHAiOiIxNjYzNDg3NjUyIiwiaXNzIjoidm9sLmNvcmUub3duZXIiLCJhdWQiOiJ2b2wuY29yZSJ9.h2-MxpKITk_YN7wkQMNQgZok_ioP5o-bY_PR0MPbT9U'); +INSERT INTO `Sys_User` VALUES (3378, NULL, NULL, NULL, NULL, NULL, '2021-09-27 15:50:22', 1, '超级管理员', NULL, NULL, NULL, 0, 0, 'Upload/Tables/Sys_User/202109271550212214/12313.jpg', 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, '小编', NULL, NULL, NULL, 'Admin888', 'al7ulHECMmQ_i6lA3dPKlg==', 'Admin888', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIzMzc4IiwiaWF0IjoiMTY0NTQxODQ0NyIsIm5iZiI6IjE2NDU0MTg0NDciLCJleHAiOiIxNjQ1NDI1NjQ3IiwiaXNzIjoidm9sLmNvcmUub3duZXIiLCJhdWQiOiJ2b2wuY29yZSJ9.mbKyMF6dQMZEmOjnRy8MZwXjz3jsm2DsejSrkFWD3B4'); + +-- ---------------------------- +-- Table structure for Sys_WorkFlow +-- ---------------------------- +DROP TABLE IF EXISTS `Sys_WorkFlow`; +CREATE TABLE `Sys_WorkFlow` ( + `WorkFlow_Id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `WorkName` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '流程名称', + `WorkTable` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '表名', + `WorkTableName` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '功能菜单', + `NodeConfig` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '节点信息', + `LineConfig` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '连接配置', + `Remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `CreateDate` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `CreateID` int(11) NULL DEFAULT NULL, + `Creator` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `Enable` tinyint(4) NULL DEFAULT NULL COMMENT '是否启用', + `Modifier` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `ModifyDate` datetime(0) NULL DEFAULT NULL, + `ModifyID` int(11) NULL DEFAULT NULL, + PRIMARY KEY (`WorkFlow_Id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of Sys_WorkFlow +-- ---------------------------- +INSERT INTO `Sys_WorkFlow` VALUES ('c016fa5e-6f44-4d59-a929-7391e82caf18', '订单流程测试', 'SellOrder', '销售订单', '[{\"id\":\"1659276275052\",\"name\":\"流程-节点A\",\"type\":\"task\",\"left\":\"230px\",\"top\":\"15px\",\"ico\":\"el-icon-user-solid\",\"nodeType\":\"1\",\"userId\":1,\"roleId\":null},{\"id\":\"1659276282115\",\"name\":\"流程-节点B\",\"type\":\"task\",\"left\":\"228px\",\"top\":\"127px\",\"ico\":\"el-icon-goods\",\"nodeType\":\"1\",\"userId\":3362,\"roleId\":null},{\"id\":\"l0om4eidz\",\"name\":\"流程-节点C\",\"type\":\"timer\",\"left\":\"226px\",\"top\":\"243.25px\",\"ico\":\"el-icon-plus\",\"state\":\"success\",\"nodeType\":\"1\",\"userId\":3378,\"roleId\":null}]', '[{\"from\":\"1659276275052\",\"to\":\"1659276282115\"},{\"from\":\"1659276282115\",\"to\":\"l0om4eidz\"}]', '订单流程测试', '2022-08-15 05:00:03', 1, '超级管理员', 0, NULL, NULL, NULL); +INSERT INTO `Sys_WorkFlow` VALUES ('d3445da2-043f-4c8b-943a-0c8a8f92d4b5', '流程测试', 'App_Expert', '启用图片支持', '[{\"id\":\"1659276275052\",\"name\":\"流程C-节点A\",\"type\":\"task\",\"left\":\"46px\",\"top\":\"28px\",\"ico\":\"el-icon-user-solid\",\"nodeType\":\"1\",\"userId\":1,\"roleId\":null},{\"id\":\"1659276282115\",\"name\":\"流程C-节点B\",\"type\":\"task\",\"left\":\"61px\",\"top\":\"195px\",\"ico\":\"el-icon-goods\",\"nodeType\":\"1\",\"userId\":1,\"roleId\":null},{\"id\":\"txpo1vyv8u\",\"name\":\"添加节点\",\"type\":\"timer\",\"left\":\"266px\",\"top\":\"99px\",\"ico\":\"el-icon-plus\",\"state\":\"success\",\"stepValue\":null,\"nodeType\":1,\"userId\":3362,\"roleId\":null,\"deptId\":null},{\"id\":\"yshtxdrq9u\",\"name\":\"添加节点1\",\"type\":\"timer\",\"left\":\"498px\",\"top\":\"200px\",\"ico\":\"el-icon-plus\",\"state\":\"success\",\"stepValue\":null,\"nodeType\":1,\"userId\":3378,\"roleId\":null,\"deptId\":null},{\"id\":\"64q19orr1h\",\"name\":\"添加节点2\",\"type\":\"timer\",\"left\":\"515px\",\"top\":\"39px\",\"ico\":\"el-icon-plus\",\"state\":\"success\",\"stepValue\":null,\"nodeType\":1,\"userId\":1,\"roleId\":null,\"deptId\":null}]', '[{\"from\":\"1659276275052\",\"to\":\"1659276282115\"},{\"from\":\"1659276282115\",\"to\":\"txpo1vyv8u\"},{\"from\":\"txpo1vyv8u\",\"to\":\"yshtxdrq9u\"},{\"from\":\"yshtxdrq9u\",\"to\":\"64q19orr1h\"}]', '流程测试', '2022-08-15 05:02:05', 1, '超级管理员', 0, '超级管理员', '2022-08-17 00:30:38', 1); + +-- ---------------------------- +-- Table structure for Sys_WorkFlowStep +-- ---------------------------- +DROP TABLE IF EXISTS `Sys_WorkFlowStep`; +CREATE TABLE `Sys_WorkFlowStep` ( + `WorkStepFlow_Id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `WorkFlow_Id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '流程主表id', + `StepId` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '流程节点Id', + `StepName` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '节点名称', + `StepType` int(11) NULL DEFAULT NULL COMMENT '节点类型(1=按用户审批,2=按角色审批,3=按部门审批)', + `StepValue` int(11) NULL DEFAULT NULL COMMENT '审批用户id或角色id、部门id', + `OrderId` int(11) NULL DEFAULT NULL COMMENT '审批顺序', + `Remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `CreateDate` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `CreateID` int(11) NULL DEFAULT NULL, + `Creator` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `Enable` tinyint(4) NULL DEFAULT NULL, + `Modifier` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `ModifyDate` datetime(0) NULL DEFAULT NULL, + `ModifyID` int(11) NULL DEFAULT NULL, + PRIMARY KEY (`WorkStepFlow_Id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of Sys_WorkFlowStep +-- ---------------------------- +INSERT INTO `Sys_WorkFlowStep` VALUES ('08da7e37-f54f-4d01-841c-fd9981caf52c', 'c016fa5e-6f44-4d59-a929-7391e82caf18', '1659276275052', '流程-节点A', 1, 1, 1, NULL, '2022-08-15 05:00:03', 1, '超级管理员', NULL, NULL, NULL, NULL); +INSERT INTO `Sys_WorkFlowStep` VALUES ('08da7e37-f54f-4d43-8759-ea887bb9ad66', 'c016fa5e-6f44-4d59-a929-7391e82caf18', '1659276282115', '流程-节点B', 1, 3362, 2, NULL, '2022-08-15 05:00:03', 1, '超级管理员', NULL, NULL, NULL, NULL); +INSERT INTO `Sys_WorkFlowStep` VALUES ('08da7e37-f54f-4d6a-8e9b-5a067e559d4c', 'c016fa5e-6f44-4d59-a929-7391e82caf18', 'l0om4eidz', '流程-节点C', 1, 3378, 3, NULL, '2022-08-15 05:00:03', 1, '超级管理员', NULL, NULL, NULL, NULL); +INSERT INTO `Sys_WorkFlowStep` VALUES ('08da7e38-3e0b-48c7-8c31-702b73e9d97e', 'd3445da2-043f-4c8b-943a-0c8a8f92d4b5', '1659276275052', '流程C-节点A', 1, 1, 1, NULL, '2022-08-15 05:02:05', 1, '超级管理员', NULL, '超级管理员', '2022-08-17 00:30:38', 1); +INSERT INTO `Sys_WorkFlowStep` VALUES ('08da7e38-3e0b-48ef-8010-b941874857b5', 'd3445da2-043f-4c8b-943a-0c8a8f92d4b5', '1659276282115', '流程C-节点B', 1, 1, 2, NULL, '2022-08-15 05:02:05', 1, '超级管理员', NULL, '超级管理员', '2022-08-17 00:30:38', 1); +INSERT INTO `Sys_WorkFlowStep` VALUES ('257cb391-4b84-41eb-b8db-d38c6dde4e9c', 'd3445da2-043f-4c8b-943a-0c8a8f92d4b5', 'txpo1vyv8u', '添加节点', 1, 3362, 3, NULL, '2022-08-17 00:30:38', 1, '超级管理员', NULL, NULL, NULL, NULL); +INSERT INTO `Sys_WorkFlowStep` VALUES ('a6b7408c-9dc4-422d-8d98-c9a5660f579a', 'd3445da2-043f-4c8b-943a-0c8a8f92d4b5', 'yshtxdrq9u', '添加节点1', 1, 3378, 4, NULL, '2022-08-17 00:30:38', 1, '超级管理员', NULL, NULL, NULL, NULL); +INSERT INTO `Sys_WorkFlowStep` VALUES ('ee385e1c-d78a-4eb8-9539-661822dcbfb8', 'd3445da2-043f-4c8b-943a-0c8a8f92d4b5', '64q19orr1h', '添加节点2', 1, 1, 5, NULL, '2022-08-17 00:30:38', 1, '超级管理员', NULL, NULL, NULL, NULL); + +-- ---------------------------- +-- Table structure for Sys_WorkFlowTable +-- ---------------------------- +DROP TABLE IF EXISTS `Sys_WorkFlowTable`; +CREATE TABLE `Sys_WorkFlowTable` ( + `WorkFlowTable_Id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `WorkFlow_Id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '流程id', + `WorkName` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '流程名称', + `WorkTableKey` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '表主键id', + `WorkTable` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '表名', + `WorkTableName` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '业务名称', + `CurrentOrderId` int(11) NULL DEFAULT NULL COMMENT '当前审批节点', + `AuditStatus` int(11) NULL DEFAULT NULL COMMENT '审批状态', + `CreateDate` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `CreateID` int(11) NULL DEFAULT NULL, + `Creator` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建时间', + `Enable` tinyint(4) NULL DEFAULT NULL, + `Modifier` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `ModifyDate` datetime(0) NULL DEFAULT NULL, + `ModifyID` int(11) NULL DEFAULT NULL, + PRIMARY KEY (`WorkFlowTable_Id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of Sys_WorkFlowTable +-- ---------------------------- +INSERT INTO `Sys_WorkFlowTable` VALUES ('460b5903-4ff2-4f84-a88f-bbbf473942ec', 'c016fa5e-6f44-4d59-a929-7391e82caf18', '订单流程测试', 'ec217c01-42a2-435f-bdb6-70613b947bf9', 'SellOrder', '销售订单', 2, 1, '2022-08-15 05:01:04', 1, '超级管理员', 1, NULL, NULL, NULL); +INSERT INTO `Sys_WorkFlowTable` VALUES ('8abd4a91-fad8-466f-9fe4-6524188ef4c9', 'd3445da2-043f-4c8b-943a-0c8a8f92d4b5', '流程油荒', '287', 'App_Expert', '启用图片支持', 1, 0, '2022-08-15 05:02:14', 1, '超级管理员', 1, NULL, NULL, NULL); +INSERT INTO `Sys_WorkFlowTable` VALUES ('a251f602-f8d1-4399-8429-48d3349ad210', 'c016fa5e-6f44-4d59-a929-7391e82caf18', '订单流程测试', '978ad775-77c0-49ca-be31-ba36bb6f8af8', 'SellOrder', '销售订单', 1, 0, '2022-08-17 23:27:48', 1, '超级管理员', 1, NULL, NULL, NULL); +INSERT INTO `Sys_WorkFlowTable` VALUES ('b4d10013-8297-421f-aad4-3147fdac2450', 'c016fa5e-6f44-4d59-a929-7391e82caf18', '订单流程测试', '47e41e06-cb4a-4763-9aeb-df66cd6615e1', 'SellOrder', '销售订单', 2, 0, '2022-08-16 02:03:17', 1, '超级管理员', 1, NULL, NULL, NULL); + +-- ---------------------------- +-- Table structure for Sys_WorkFlowTableStep +-- ---------------------------- +DROP TABLE IF EXISTS `Sys_WorkFlowTableStep`; +CREATE TABLE `Sys_WorkFlowTableStep` ( + `Sys_WorkFlowTableStep_Id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `WorkFlowTable_Id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主表id', + `WorkFlow_Id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '流程id', + `StepId` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '节点id', + `StepName` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '节名称', + `StepType` int(11) NULL DEFAULT NULL COMMENT '审批类型', + `StepValue` int(11) NULL DEFAULT NULL COMMENT '节点类型(1=按用户审批,2=按角色审批,3=按部门审批 )', + `OrderId` int(11) NULL DEFAULT NULL COMMENT '审批顺序', + `AuditId` int(11) NULL DEFAULT NULL COMMENT '审核人id', + `Auditor` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '审核人', + `AuditStatus` int(11) NULL DEFAULT NULL COMMENT '审核状态', + `AuditDate` datetime(0) NULL DEFAULT NULL COMMENT '审核时间', + `Remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `CreateDate` datetime(0) NULL DEFAULT NULL, + `CreateID` int(11) NULL DEFAULT NULL, + `Creator` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `Enable` tinyint(4) NULL DEFAULT NULL, + `Modifier` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `ModifyDate` datetime(0) NULL DEFAULT NULL, + `ModifyID` int(11) NULL DEFAULT NULL, + PRIMARY KEY (`Sys_WorkFlowTableStep_Id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of Sys_WorkFlowTableStep +-- ---------------------------- +INSERT INTO `Sys_WorkFlowTableStep` VALUES ('02e50a7c-e04b-41cd-a8cf-6224b77a9c1b', '8abd4a91-fad8-466f-9fe4-6524188ef4c9', 'd3445da2-043f-4c8b-943a-0c8a8f92d4b5', '1659276282115', '流程C-节点B', 1, 1, 2, 1, NULL, NULL, NULL, NULL, '2022-08-15 05:02:14', NULL, NULL, 1, NULL, NULL, NULL); +INSERT INTO `Sys_WorkFlowTableStep` VALUES ('136b08e5-1fb5-4a07-8d7f-6f78d09c2685', '460b5903-4ff2-4f84-a88f-bbbf473942ec', 'c016fa5e-6f44-4d59-a929-7391e82caf18', 'l0om4eidz', '流程-节点C', 1, 3378, 3, 3378, NULL, NULL, NULL, NULL, '2022-08-15 05:01:04', NULL, NULL, 1, NULL, NULL, NULL); +INSERT INTO `Sys_WorkFlowTableStep` VALUES ('1ac547df-27cf-4eb4-9ad6-37881ef671cc', 'a251f602-f8d1-4399-8429-48d3349ad210', 'c016fa5e-6f44-4d59-a929-7391e82caf18', '1659276282115', '流程-节点B', 1, 3362, 2, 3362, NULL, NULL, NULL, NULL, '2022-08-17 23:27:48', NULL, NULL, 1, NULL, NULL, NULL); +INSERT INTO `Sys_WorkFlowTableStep` VALUES ('1c75af0d-96ea-4777-8f1b-98a8ba168d89', '8abd4a91-fad8-466f-9fe4-6524188ef4c9', 'd3445da2-043f-4c8b-943a-0c8a8f92d4b5', '1659276275052', '流程C-节点A', 1, 1, 1, 1, NULL, NULL, NULL, NULL, '2022-08-15 05:02:14', NULL, NULL, 1, NULL, NULL, NULL); +INSERT INTO `Sys_WorkFlowTableStep` VALUES ('21c8252a-15a3-4435-a6ca-0dbee4474bba', 'b4d10013-8297-421f-aad4-3147fdac2450', 'c016fa5e-6f44-4d59-a929-7391e82caf18', '1659276275052', '流程-节点A', 1, 1, 1, 1, '超级管理员', 1, '2022-08-16 02:03:38', '审批通过测试', '2022-08-16 02:03:17', NULL, NULL, 1, NULL, NULL, NULL); +INSERT INTO `Sys_WorkFlowTableStep` VALUES ('521f23e3-6d5d-4a9d-8e67-a289440f7ecd', 'a251f602-f8d1-4399-8429-48d3349ad210', 'c016fa5e-6f44-4d59-a929-7391e82caf18', '1659276275052', '流程-节点A', 1, 1, 1, 1, NULL, NULL, NULL, NULL, '2022-08-17 23:27:48', NULL, NULL, 1, NULL, NULL, NULL); +INSERT INTO `Sys_WorkFlowTableStep` VALUES ('81856e1e-9796-4ceb-8b8a-36b201604e25', '460b5903-4ff2-4f84-a88f-bbbf473942ec', 'c016fa5e-6f44-4d59-a929-7391e82caf18', '1659276275052', '流程-节点A', 1, 1, 1, 1, '超级管理员', 1, '2022-08-15 05:13:51', '1', '2022-08-15 05:01:04', NULL, NULL, 1, NULL, NULL, NULL); +INSERT INTO `Sys_WorkFlowTableStep` VALUES ('83485f9f-119b-4344-a26a-22a1f4a3760e', 'b4d10013-8297-421f-aad4-3147fdac2450', 'c016fa5e-6f44-4d59-a929-7391e82caf18', 'l0om4eidz', '流程-节点C', 1, 3378, 3, 3378, NULL, NULL, NULL, NULL, '2022-08-16 02:03:17', NULL, NULL, 1, NULL, NULL, NULL); +INSERT INTO `Sys_WorkFlowTableStep` VALUES ('d9a0f59c-7b3e-4099-84a5-2b3c74414b46', 'a251f602-f8d1-4399-8429-48d3349ad210', 'c016fa5e-6f44-4d59-a929-7391e82caf18', 'l0om4eidz', '流程-节点C', 1, 3378, 3, 3378, NULL, NULL, NULL, NULL, '2022-08-17 23:27:48', NULL, NULL, 1, NULL, NULL, NULL); +INSERT INTO `Sys_WorkFlowTableStep` VALUES ('e623c47c-e0f5-4052-a2be-baf857784499', '460b5903-4ff2-4f84-a88f-bbbf473942ec', 'c016fa5e-6f44-4d59-a929-7391e82caf18', '1659276282115', '流程-节点B', 1, 3362, 2, 3362, NULL, NULL, NULL, NULL, '2022-08-15 05:01:04', NULL, NULL, 1, NULL, NULL, NULL); +INSERT INTO `Sys_WorkFlowTableStep` VALUES ('f92d5a23-f572-446e-a3e4-e6063ee6dcdf', 'b4d10013-8297-421f-aad4-3147fdac2450', 'c016fa5e-6f44-4d59-a929-7391e82caf18', '1659276282115', '流程-节点B', 1, 3362, 2, 3362, NULL, NULL, NULL, NULL, '2022-08-16 02:03:17', NULL, NULL, 1, NULL, NULL, NULL); + +SET FOREIGN_KEY_CHECKS = 1; +set global local_infile = 'ON'; diff --git "a/Pure_Vite_Net7/DB/pgsql/pgsql(\345\220\253\345\237\272\347\241\200\346\225\260\346\215\256).sql" "b/Pure_Vite_Net7/DB/pgsql/pgsql(\345\220\253\345\237\272\347\241\200\346\225\260\346\215\256).sql" new file mode 100644 index 0000000000000000000000000000000000000000..acf7cde1037fd1038bd8a981ca9e3f82037a08b8 --- /dev/null +++ "b/Pure_Vite_Net7/DB/pgsql/pgsql(\345\220\253\345\237\272\347\241\200\346\225\260\346\215\256).sql" @@ -0,0 +1,1925 @@ +/* + Navicat Premium Data Transfer + + Source Server : pgsql + Source Server Type : PostgreSQL + Source Server Version : 100013 + Source Host : 132.232.2.109:5432 + Source Catalog : netcoredev + Source Schema : public + + Target Server Type : PostgreSQL + Target Server Version : 100013 + File Encoding : 65001 + + Date: 07/08/2020 20:09:37 +*/ + + +-- ---------------------------- +-- Sequence structure for app_expert_id_seq1 +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."app_expert_id_seq1"; +CREATE SEQUENCE "public"."app_expert_id_seq1" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 100 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for app_news111seq_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."app_news111seq_id_seq"; +CREATE SEQUENCE "public"."app_news111seq_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 10 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for app_news_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."app_news_id_seq"; +CREATE SEQUENCE "public"."app_news_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for app_reportprice_id1_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."app_reportprice_id1_seq"; +CREATE SEQUENCE "public"."app_reportprice_id1_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 100 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for app_reportprice_id2_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."app_reportprice_id2_seq"; +CREATE SEQUENCE "public"."app_reportprice_id2_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 100 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for app_reportprice_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."app_reportprice_id_seq"; +CREATE SEQUENCE "public"."app_reportprice_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for app_transaction_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."app_transaction_id_seq"; +CREATE SEQUENCE "public"."app_transaction_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for app_transactionavgprice_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."app_transactionavgprice_id_seq"; +CREATE SEQUENCE "public"."app_transactionavgprice_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for appnews_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."appnews_id_seq"; +CREATE SEQUENCE "public"."appnews_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for apptest_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."apptest_id_seq"; +CREATE SEQUENCE "public"."apptest_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for city_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."city_id_seq"; +CREATE SEQUENCE "public"."city_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for dic_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."dic_id_seq"; +CREATE SEQUENCE "public"."dic_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for sellorder_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."sellorder_id_seq"; +CREATE SEQUENCE "public"."sellorder_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for sellorderlist_id1_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."sellorderlist_id1_seq"; +CREATE SEQUENCE "public"."sellorderlist_id1_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for sellorderlist_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."sellorderlist_id_seq"; +CREATE SEQUENCE "public"."sellorderlist_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for sys_dictionary_id_seq1 +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."sys_dictionary_id_seq1"; +CREATE SEQUENCE "public"."sys_dictionary_id_seq1" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 100 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for sys_dictionarylist_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."sys_dictionarylist_id_seq"; +CREATE SEQUENCE "public"."sys_dictionarylist_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 500 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for sys_log_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."sys_log_id_seq"; +CREATE SEQUENCE "public"."sys_log_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for sys_menu_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."sys_menu_id_seq"; +CREATE SEQUENCE "public"."sys_menu_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 100 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for sys_province1_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."sys_province1_id_seq"; +CREATE SEQUENCE "public"."sys_province1_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 500 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for sys_province_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."sys_province_id_seq"; +CREATE SEQUENCE "public"."sys_province_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 100 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for sys_role_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."sys_role_id_seq"; +CREATE SEQUENCE "public"."sys_role_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 100 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for sys_role_id_seq1 +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."sys_role_id_seq1"; +CREATE SEQUENCE "public"."sys_role_id_seq1" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for sys_roleauth_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."sys_roleauth_id_seq"; +CREATE SEQUENCE "public"."sys_roleauth_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 100 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for sys_roleauthdata_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."sys_roleauthdata_id_seq"; +CREATE SEQUENCE "public"."sys_roleauthdata_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 100 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for sys_tablecolumn_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."sys_tablecolumn_id_seq"; +CREATE SEQUENCE "public"."sys_tablecolumn_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 800 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for sys_tableinfo_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."sys_tableinfo_id_seq"; +CREATE SEQUENCE "public"."sys_tableinfo_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 100 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for sys_user_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."sys_user_id_seq"; +CREATE SEQUENCE "public"."sys_user_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Table structure for App_Appointment +-- ---------------------------- +DROP TABLE IF EXISTS "public"."App_Appointment"; +CREATE TABLE "public"."App_Appointment" ( + "Id" uuid NOT NULL, + "CreateDate" timestamp(6), + "CreateID" int4, + "Creator" varchar(30) COLLATE "pg_catalog"."default", + "Describe" varchar(250) COLLATE "pg_catalog"."default" NOT NULL, + "Modifier" varchar(30) COLLATE "pg_catalog"."default", + "ModifyDate" timestamp(6), + "ModifyID" int4, + "Name" varchar(50) COLLATE "pg_catalog"."default" NOT NULL, + "PhoneNo" varchar(15) COLLATE "pg_catalog"."default" NOT NULL +) +; + +-- ---------------------------- +-- Records of App_Appointment +-- ---------------------------- +INSERT INTO "public"."App_Appointment" VALUES ('08d73c0e-edef-0a68-ab81-c3dc5e0fe407', '2019-09-18 16:05:11', 1, '超级管理员', '来自火星。。。', '超级管理员', '2020-04-24 13:47:46', 1, '元霸', '138888887698'); +INSERT INTO "public"."App_Appointment" VALUES ('08d73c0e-edf8-595b-9a8f-2ff134751833', '2019-09-18 16:05:11', 1, '超级管理员', '元歌有8个技能..', '超级管理员', '2020-04-24 13:44:04', 1, '元歌', '1300111235'); +INSERT INTO "public"."App_Appointment" VALUES ('08d73c11-6a43-97e8-ca70-e8b0d906807e', '2019-09-18 16:22:59', 1, '超级管理员', '来自火星。。。', '超级管理员', '2020-04-27 14:20:58', 1, '元华', '138888887698'); +INSERT INTO "public"."App_Appointment" VALUES ('1f140d53-1277-4294-9f87-cc2e6c0f3076', NULL, NULL, '0', '111', NULL, NULL, NULL, '222', '333'); +INSERT INTO "public"."App_Appointment" VALUES ('31dff565-cc48-4d52-8b3f-87122e79ebe3', NULL, NULL, '1', '111', NULL, NULL, NULL, '222', '333'); +INSERT INTO "public"."App_Appointment" VALUES ('58b8043f-8f57-4eec-ae92-8812708959f0', NULL, NULL, '2', '111', NULL, NULL, NULL, '222', '333'); +INSERT INTO "public"."App_Appointment" VALUES ('e59b2996-c518-4ce2-9b09-7482e8d8543d', NULL, NULL, '3', '111', NULL, NULL, NULL, '222', '333'); +INSERT INTO "public"."App_Appointment" VALUES ('3aa40cfa-2c12-4032-92e9-ab7c6e2372e2', NULL, NULL, '4', '111', NULL, NULL, NULL, '222', '333'); +INSERT INTO "public"."App_Appointment" VALUES ('952b2764-3ae4-471d-aae6-cef871af6de9', NULL, NULL, '5', '111', NULL, NULL, NULL, '222', '333'); +INSERT INTO "public"."App_Appointment" VALUES ('ae8e4087-bcd7-4f89-9843-744f0fd33b11', NULL, NULL, '6', '111', NULL, NULL, NULL, '222', '333'); +INSERT INTO "public"."App_Appointment" VALUES ('99544037-4f73-41be-b926-054bd6ce0b77', NULL, NULL, '7', '111', NULL, NULL, NULL, '222', '333'); +INSERT INTO "public"."App_Appointment" VALUES ('ebfe0081-a2c9-4585-b09e-bb14a595d06f', NULL, NULL, '8', '111', NULL, NULL, NULL, '222', '333'); +INSERT INTO "public"."App_Appointment" VALUES ('7f4aa284-300d-4f68-b78a-699141dfec4e', NULL, NULL, '9', '111', NULL, NULL, NULL, '222', '333'); + +-- ---------------------------- +-- Table structure for App_Expert +-- ---------------------------- +DROP TABLE IF EXISTS "public"."App_Expert"; +CREATE TABLE "public"."App_Expert" ( + "ExpertId" int4 NOT NULL DEFAULT nextval('app_expert_id_seq1'::regclass), + "AuditDate" timestamp(6), + "AuditId" int4, + "AuditStatus" int4 NOT NULL, + "Auditor" varchar(20) COLLATE "pg_catalog"."default", + "Certificate" varchar(2500) COLLATE "pg_catalog"."default", + "City" varchar(50) COLLATE "pg_catalog"."default", + "Company" varchar(50) COLLATE "pg_catalog"."default", + "CreateDate" timestamp(6), + "CreateID" int4, + "Creator" varchar(30) COLLATE "pg_catalog"."default", + "Education" varchar(50) COLLATE "pg_catalog"."default", + "ExpertName" varchar(20) COLLATE "pg_catalog"."default", + "HeadImageUrl" varchar(500) COLLATE "pg_catalog"."default", + "IDNumber" varchar(18) COLLATE "pg_catalog"."default", + "Modifier" varchar(30) COLLATE "pg_catalog"."default", + "ModifyDate" timestamp(6), + "ModifyID" int4, + "PhoneNo" varchar(11) COLLATE "pg_catalog"."default", + "Professional" varchar(50) COLLATE "pg_catalog"."default", + "ReallyName" varchar(20) COLLATE "pg_catalog"."default", + "Resume" varchar(500) COLLATE "pg_catalog"."default", + "SpecialField" varchar(800) COLLATE "pg_catalog"."default", + "UserName" varchar(30) COLLATE "pg_catalog"."default", + "UserTrueName" varchar(50) COLLATE "pg_catalog"."default", + "User_Id" int4, + "Enable" bytea +) +; + +-- ---------------------------- +-- Records of App_Expert +-- ---------------------------- + +-- ---------------------------- +-- Table structure for App_News +-- ---------------------------- +DROP TABLE IF EXISTS "public"."App_News"; +CREATE TABLE "public"."App_News" ( + "Id" int4 NOT NULL DEFAULT nextval('app_news_id_seq'::regclass), + "Author" varchar(50) COLLATE "pg_catalog"."default", + "BigImageUrls" varchar(500) COLLATE "pg_catalog"."default", + "Content" text COLLATE "pg_catalog"."default", + "CreateDate" timestamp(6), + "CreateID" int4, + "Creator" varchar(30) COLLATE "pg_catalog"."default", + "DailyRecommend" int2 NOT NULL, + "DetailUrl" varchar(200) COLLATE "pg_catalog"."default", + "Enable" int2, + "ImageUrl" varchar(500) COLLATE "pg_catalog"."default", + "Modifier" varchar(30) COLLATE "pg_catalog"."default", + "ModifyDate" timestamp(6), + "ModifyID" int4, + "NewsType" int4 NOT NULL, + "OrderNo" int4, + "ReleaseDate" timestamp(6), + "Title" varchar(50) COLLATE "pg_catalog"."default" NOT NULL, + "ViewCount" int4 +) +; + +-- ---------------------------- +-- Records of App_News +-- ---------------------------- +INSERT INTO "public"."App_News" VALUES (1, '2', '2', '2', '2020-06-14 19:59:26', 2, '2', 2, '2', 1, NULL, NULL, NULL, 1, 1, 2, '2020-06-14 19:59:34', 'tt1234', 2); + +-- ---------------------------- +-- Table structure for App_Reportprice +-- ---------------------------- +DROP TABLE IF EXISTS "public"."App_Reportprice"; +CREATE TABLE "public"."App_Reportprice" ( + "Id" int4 NOT NULL DEFAULT nextval('app_reportprice_id_seq'::regclass), + "Age" varchar(50) COLLATE "pg_catalog"."default" NOT NULL, + "AuditDate" timestamp(6), + "AuditId" int4, + "AuditStatus" int4, + "Auditor" varchar(20) COLLATE "pg_catalog"."default", + "City" varchar(15) COLLATE "pg_catalog"."default" NOT NULL, + "CreateDate" timestamp(6), + "CreateID" int4, + "Creator" varchar(30) COLLATE "pg_catalog"."default", + "Enable" int2, + "Modifier" varchar(30) COLLATE "pg_catalog"."default", + "ModifyDate" timestamp(6), + "ModifyID" int4, + "Price" numeric(10) NOT NULL, + "Variety" varchar(20) COLLATE "pg_catalog"."default" NOT NULL +) +; + +-- ---------------------------- +-- Records of App_Reportprice +-- ---------------------------- +INSERT INTO "public"."App_Reportprice" VALUES (67, '12-16月龄', '2019-10-21 16:41:22', 1, 1, '超级管理员', '忻州市', '2018-09-10 10:12:50', 3344, '啊啊啊', 0, '超级管理员', '2019-07-16 15:07:16', 1, 29, '西门塔尔'); +INSERT INTO "public"."App_Reportprice" VALUES (74, '7-12月龄', '2019-10-21 16:41:22', 1, 1, '超级管理员', '唐山市', '2019-07-11 18:25:35', 1, '超级管理员', 0, '超级管理员', '2019-08-09 09:28:41', 1, 65, '利木赞牛'); +INSERT INTO "public"."App_Reportprice" VALUES (75, '7-12月龄', '2019-10-21 16:41:22', 1, 1, '超级管理员', '北京市', '2019-07-11 18:28:53', 1, '超级管理员', 1, '超级管理员', '2019-08-09 09:29:03', 1, 43, '夏洛莱牛'); +INSERT INTO "public"."App_Reportprice" VALUES (83, '12-16月龄', '2019-10-21 16:41:22', 1, 1, '超级管理员', '天津市', '2019-07-26 13:20:43', 1, '超级管理员', 1, '超级管理员', '2020-02-01 12:42:37', 1, 12, '利木赞牛'); +INSERT INTO "public"."App_Reportprice" VALUES (85, '0-2月龄', '2019-10-21 16:42:04', 1, 2, '超级管理员', '天津市', '2019-10-21 16:41:48', 1, '超级管理员', 1, '超级管理员', '2020-04-03 22:56:46', 1, 23, '神户肉牛'); + +-- ---------------------------- +-- Table structure for App_Transaction +-- ---------------------------- +DROP TABLE IF EXISTS "public"."App_Transaction"; +CREATE TABLE "public"."App_Transaction" ( + "Id" int4 NOT NULL DEFAULT nextval('app_transaction_id_seq'::regclass), + "CowType" varchar(100) COLLATE "pg_catalog"."default", + "CreateDate" timestamp(6), + "CreateID" int4, + "Creator" varchar(30) COLLATE "pg_catalog"."default", + "Describe" varchar(500) COLLATE "pg_catalog"."default" NOT NULL, + "Enable" int2, + "Modifier" varchar(30) COLLATE "pg_catalog"."default", + "ModifyDate" timestamp(6), + "ModifyID" int4, + "Name" varchar(50) COLLATE "pg_catalog"."default" NOT NULL, + "PhoneNo" varchar(15) COLLATE "pg_catalog"."default" NOT NULL, + "Quantity" int4 NOT NULL, + "TransactionType" int4 NOT NULL +) +; + +-- ---------------------------- +-- Records of App_Transaction +-- ---------------------------- +INSERT INTO "public"."App_Transaction" VALUES (4, '1', '2019-09-18 18:10:01', 1, '超级管理员', '寒江孤影,江湖故人....', NULL, '超级管理员', '2020-04-24 13:39:41', 1, '寒江孤影', '13419098211', 25, 0); +INSERT INTO "public"."App_Transaction" VALUES (5, '1', '2019-09-18 18:10:01', 1, '超级管理员', '闻着臭,吃着更臭。。。。。', NULL, '超级管理员', '2020-04-24 13:38:37', 1, '不爱`吃臭`豆腐', '13419098211', 25, 1); +INSERT INTO "public"."App_Transaction" VALUES (6, '3', '2019-09-18 18:22:25', 1, '超级管理员', '浪子回头...。。。', NULL, '超级管理员', '2020-04-24 13:37:24', 1, '同是天涯流落人', '13419444421', 199, 1); +INSERT INTO "public"."App_Transaction" VALUES (27, '1', '2020-08-06 19:09:57.956672', 1, 'admin', '127', NULL, NULL, NULL, NULL, '18', '117', 17, 1); + +-- ---------------------------- +-- Table structure for App_TransactionAvgPrice +-- ---------------------------- +DROP TABLE IF EXISTS "public"."App_TransactionAvgPrice"; +CREATE TABLE "public"."App_TransactionAvgPrice" ( + "Id" int4 NOT NULL DEFAULT nextval('app_transactionavgprice_id_seq'::regclass), + "AgeRange" varchar(50) COLLATE "pg_catalog"."default" NOT NULL, + "AvgPrice" numeric(10,2) NOT NULL, + "City" varchar(15) COLLATE "pg_catalog"."default" NOT NULL, + "CreateDate" timestamp(6), + "CreateID" int4, + "Creator" varchar(30) COLLATE "pg_catalog"."default", + "Date" date NOT NULL, + "Enable" int4, + "IsTop" int4 NOT NULL, + "Modifier" varchar(30) COLLATE "pg_catalog"."default", + "ModifyDate" timestamp(6), + "ModifyID" int4, + "Variety" varchar(20) COLLATE "pg_catalog"."default" NOT NULL +) +; + +-- ---------------------------- +-- Records of App_TransactionAvgPrice +-- ---------------------------- +INSERT INTO "public"."App_TransactionAvgPrice" VALUES (13, '7-12月龄', 222.00, '北京市', '2020-08-06 18:45:09', 1, 'admin', '2020-08-12', NULL, 1, '', NULL, NULL, '6,5,4'); +INSERT INTO "public"."App_TransactionAvgPrice" VALUES (16, '16月龄以上', 33.00, '北京市', '2020-08-06 18:56:46', 1, 'admin', '2020-08-14', NULL, 1, '', NULL, NULL, '8'); +INSERT INTO "public"."App_TransactionAvgPrice" VALUES (15, '7-12月龄', 22.00, '北京市', '2020-08-06 18:56:09', 1, 'admin', '2020-08-17', NULL, 0, 'admin', '2020-08-06 18:56:54', 1, '2'); + +-- ---------------------------- +-- Table structure for SellOrder +-- ---------------------------- +DROP TABLE IF EXISTS "public"."SellOrder"; +CREATE TABLE "public"."SellOrder" ( + "Order_Id" uuid NOT NULL, + "OrderType" int4 NOT NULL, + "TranNo" varchar(100) COLLATE "pg_catalog"."default" NOT NULL, + "SellNo" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "Qty" int4 NOT NULL, + "AuditDate" timestamp(6), + "AuditStatus" int4 NOT NULL, + "AuditId" int4, + "Auditor" varchar(100) COLLATE "pg_catalog"."default", + "Remark" varchar(1000) COLLATE "pg_catalog"."default", + "CreateID" int4, + "Creator" varchar(255) COLLATE "pg_catalog"."default", + "CreateDate" timestamp(6), + "ModifyID" int4, + "Modifier" varchar(255) COLLATE "pg_catalog"."default", + "ModifyDate" timestamp(6) +) +; + +-- ---------------------------- +-- Records of SellOrder +-- ---------------------------- +INSERT INTO "public"."SellOrder" VALUES ('2779bbb4-6010-4bb9-a884-d30851429d80', 3, '2324', '222', 22, NULL, 0, NULL, NULL, NULL, 1, 'admin', '2020-08-06 19:33:40.123416', NULL, NULL, NULL); + +-- ---------------------------- +-- Table structure for SellOrderList +-- ---------------------------- +DROP TABLE IF EXISTS "public"."SellOrderList"; +CREATE TABLE "public"."SellOrderList" ( + "OrderList_Id" uuid NOT NULL, + "Order_Id" uuid NOT NULL, + "ProductName" varchar(200) COLLATE "pg_catalog"."default" NOT NULL, + "MO" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "Qty" int4 NOT NULL, + "Weight" numeric(11,2), + "Remark" varchar(1000) COLLATE "pg_catalog"."default", + "CreateID" int4, + "Creator" varchar(255) COLLATE "pg_catalog"."default", + "CreateDate" timestamp(6), + "ModifyID" int4, + "Modifier" varchar(255) COLLATE "pg_catalog"."default", + "ModifyDate" timestamp(6) +) +; + +-- ---------------------------- +-- Records of SellOrderList +-- ---------------------------- +INSERT INTO "public"."SellOrderList" VALUES ('5ce623dd-5e60-40ad-ad38-c47e600fd6c5', '2779bbb4-6010-4bb9-a884-d30851429d80', '食品', '2', 33, 11.00, '23', 1, 'admin', '2020-08-06 19:33:40.179994', NULL, NULL, NULL); + +-- ---------------------------- +-- Table structure for Sys_City +-- ---------------------------- +DROP TABLE IF EXISTS "public"."Sys_City"; +CREATE TABLE "public"."Sys_City" ( + "CityId" int4 NOT NULL DEFAULT nextval('city_id_seq'::regclass), + "CityCode" varchar(20) COLLATE "pg_catalog"."default", + "CityName" varchar(30) COLLATE "pg_catalog"."default", + "ProvinceCode" varchar(20) COLLATE "pg_catalog"."default" +) +; + +-- ---------------------------- +-- Records of Sys_City +-- ---------------------------- +INSERT INTO "public"."Sys_City" VALUES (1, '110100', '市辖区', '110000'); +INSERT INTO "public"."Sys_City" VALUES (2, '110200', '县', '110000'); +INSERT INTO "public"."Sys_City" VALUES (3, '120100', '市辖区', '120000'); +INSERT INTO "public"."Sys_City" VALUES (4, '120200', '县', '120000'); +INSERT INTO "public"."Sys_City" VALUES (5, '130100', '石家庄市', '130000'); + +-- ---------------------------- +-- Table structure for Sys_Dictionary +-- ---------------------------- +DROP TABLE IF EXISTS "public"."Sys_Dictionary"; +CREATE TABLE "public"."Sys_Dictionary" ( + "Dic_ID" int4 NOT NULL DEFAULT nextval('sys_dictionary_id_seq1'::regclass), + "Config" varchar(4000) COLLATE "pg_catalog"."default", + "CreateDate" timestamp(6), + "CreateID" int4, + "Creator" varchar(30) COLLATE "pg_catalog"."default", + "DBServer" varchar(4000) COLLATE "pg_catalog"."default", + "DbSql" varchar(4000) COLLATE "pg_catalog"."default", + "DicName" varchar(100) COLLATE "pg_catalog"."default" NOT NULL, + "DicNo" varchar(100) COLLATE "pg_catalog"."default" NOT NULL, + "Enable" int2 NOT NULL, + "Modifier" varchar(30) COLLATE "pg_catalog"."default", + "ModifyDate" timestamp(6), + "ModifyID" int4, + "OrderNo" int4, + "ParentId" int4 NOT NULL, + "Remark" varchar(2000) COLLATE "pg_catalog"."default" +) +; + +-- ---------------------------- +-- Records of Sys_Dictionary +-- ---------------------------- +INSERT INTO "public"."Sys_Dictionary" VALUES (3, '{valueField: ''Enable'', +textField: ''Enable'', + containField: null, + handler: null }', NULL, NULL, 'admi', '1', NULL, '是否值', 'enable', 1, '超级管理员', NULL, 1, NULL, 0, NULL); +INSERT INTO "public"."Sys_Dictionary" VALUES (30, '{valueField: ''Success'', + textField: ''Success'', + containField: null, + handler: null } +', NULL, 0, '测试超级管理员', NULL, NULL, '响应状态', 'restatus', 1, '测试超级管理员', NULL, 1, NULL, 0, NULL); +INSERT INTO "public"."Sys_Dictionary" VALUES (31, '{valueField: ''LogType'', + textField: ''LogType'', + containField: null, + handler: null } +', NULL, NULL, '测试超级管理员', NULL, NULL, '日志类型', 'log', 1, '测试超级管理员', NULL, 1, NULL, 0, NULL); +INSERT INTO "public"."Sys_Dictionary" VALUES (34, '{valueField: ''PINType'', + textField: ''PINTypeV'', + containField:null +}', NULL, NULL, '测试超级管理员', NULL, NULL, '验证码获取记录', 'pi', 1, '测试超级管理员', NULL, 1, NULL, 0, NULL); +INSERT INTO "public"."Sys_Dictionary" VALUES (35, '{ + valueField: ''AuditStatus'', + textField: ''AuditStatus'', + containField:null +}', NULL, NULL, '测试超级管理员', NULL, NULL, '审核状态', 'audit', 1, '测试超级管理员', NULL, 1, NULL, 0, NULL); +INSERT INTO "public"."Sys_Dictionary" VALUES (36, '{ + valueField: ''Variety'', + textField: ''Variety'', + containField:null +}', NULL, 1, '测试超级管理员', NULL, NULL, '品种', 'pz', 1, '超级管理员', NULL, 1, NULL, 0, NULL); +INSERT INTO "public"."Sys_Dictionary" VALUES (37, '{ + valueField: ''AgeRange'', + textField: ''AgeRange'', + containField:null +}', NULL, NULL, '测试超级管理员', NULL, NULL, '月龄', 'age', 1, '测试超级管理员', NULL, 1, NULL, 0, NULL); +INSERT INTO "public"."Sys_Dictionary" VALUES (39, '{ + valueField: ''ReplyStatus'', + textField: ''ReplyStatus'', + containField:null +}', NULL, NULL, '测试超级管理员', NULL, NULL, '回复状态', 'reply', 1, '测试超级管理员', NULL, 1, NULL, 0, NULL); +INSERT INTO "public"."Sys_Dictionary" VALUES (41, '{ + valueField: ''Sex'', + textField: ''Sex'', + containField:null +}', NULL, 1, '测试超级管理员', NULL, NULL, '公母牛', 'sex', 1, '超级管理员', NULL, 1, NULL, 1, NULL); +INSERT INTO "public"."Sys_Dictionary" VALUES (42, '{ + valueField: ''Temperature'', + textField: ''Temperature'', + containField:null +}', NULL, 1, '测试超级管理员', NULL, NULL, '温度', 'wd', 1, NULL, NULL, NULL, NULL, 0, NULL); +INSERT INTO "public"."Sys_Dictionary" VALUES (44, '{ + valueField: ''NewsType'', + textField: ''NewsType'', + containField:null +}', NULL, 1, '测试超级管理员', NULL, NULL, '新闻类型', 'news', 1, NULL, NULL, NULL, NULL, 0, NULL); +INSERT INTO "public"."Sys_Dictionary" VALUES (45, '{ + valueField: ''Expire'', + textField: ''Expire'', + containField:null +}', NULL, 1, '测试超级管理员', NULL, NULL, '是否过期', 'expire', 1, NULL, NULL, NULL, NULL, 0, NULL); +INSERT INTO "public"."Sys_Dictionary" VALUES (48, '{ + valueField: ''ClassifyId'', + textField: ''ClassifyTitle'', + containField:null +}', NULL, NULL, '测试超级管理员', NULL, NULL, '是否买入', 'nav', 1, '超级管理员', NULL, 1, NULL, 0, NULL); +INSERT INTO "public"."Sys_Dictionary" VALUES (49, '{ + valueField: ''Gender'', + textField: ''Gender'', + containField:null +}', NULL, NULL, '测试超级管理员', NULL, NULL, '性别', 'gender', 1, '测试超级管理员', NULL, 1, NULL, 0, NULL); +INSERT INTO "public"."Sys_Dictionary" VALUES (50, '{ + valueField: ''Enable'', + textField: ''Enable'', + containField:null +}', NULL, 1, '测试超级管理员', NULL, NULL, '启用状态', 'status', 1, NULL, NULL, NULL, NULL, 0, NULL); +INSERT INTO "public"."Sys_Dictionary" VALUES (52, '{ + valueField: ''Choiceness'', + textField: ''Choiceness'', + containField:null +}', NULL, 1, '测试超级管理员', NULL, NULL, '是否买入', 'cq', 1, '超级管理员', NULL, 1, NULL, 0, NULL); +INSERT INTO "public"."Sys_Dictionary" VALUES (53, '{ + valueField: ''SourceType'', + textField: ''SourceType'', + containField:null +}', NULL, 1, '测试超级管理员', NULL, NULL, '图片来源', 'ps', 1, NULL, NULL, NULL, NULL, 0, NULL); +INSERT INTO "public"."Sys_Dictionary" VALUES (59, '{ + valueField: ''IsRegregisterPhone'', + textField: ''IsRegregisterPhone'', + containField:null +}', NULL, 1, '测试超级管理员', NULL, NULL, '是否手机用户', 'isphone', 1, '超级管理员', NULL, 1, NULL, 0, NULL); +INSERT INTO "public"."Sys_Dictionary" VALUES (60, '{ + valueField: ''DailyRecommend'', + textField: ''DailyRecommend'', + containField:null +}', NULL, 1, '超级管理员', NULL, NULL, '是否今日推荐', 'dr', 1, '超级管理员', NULL, 1, NULL, 1, NULL); +INSERT INTO "public"."Sys_Dictionary" VALUES (62, '{ + valueField: ''IsTop'', + textField: ''IsTop'', + containField:null +}', NULL, 1, '超级管理员', NULL, NULL, '推荐价格', 'top', 1, '超级管理员', NULL, 1, NULL, 1, 'dddd'); +INSERT INTO "public"."Sys_Dictionary" VALUES (64, NULL, NULL, 1, '超级管理员', NULL, NULL, '订单类型', 'ordertype', 1, '超级管理员', NULL, 1, NULL, 0, 'xxxxx'); +INSERT INTO "public"."Sys_Dictionary" VALUES (66, NULL, NULL, 3362, 'zs', NULL, NULL, 'table中的角色列表', 't_roles', 1, NULL, NULL, NULL, NULL, 0, NULL); +INSERT INTO "public"."Sys_Dictionary" VALUES (1, NULL, '2020-06-14 20:58:26.970561', 1, 'admin', NULL, NULL, 'test0615', 'test0615', 0, NULL, NULL, NULL, NULL, 0, '11'); +INSERT INTO "public"."Sys_Dictionary" VALUES (46, '{ + valueField: ''ProvinceName'', + textField: ''ProvinceName'', + containField:null +}', NULL, NULL, '测试超级管理员', NULL, ' +SELECT CASE WHEN "CityName"=''市辖区'' THEN "ProvinceName" ELSE "CityName" end as key,CASE WHEN "CityName"=''市辖区'' THEN "ProvinceName" ELSE "CityName" end as value FROM Sys_City AS a +INNER JOIN Sys_Province AS b +ON a."ProvinceCode"=b."ProvinceCode" +WHERE a."CityName"<> ''县''', '省列表', 'pro', 1, 'admin', '2020-06-14 21:13:12.159191', 1, NULL, 0, 'sql语句需要key,value列,界面才能绑定数据源'); +INSERT INTO "public"."Sys_Dictionary" VALUES (38, '{ + valueField: ''City'', + textField: ''City'', + containField:null +}', NULL, NULL, '测试超级管理员', NULL, ' +SELECT CASE WHEN "CityName"=''市辖区'' THEN "ProvinceName" ELSE "CityName" end as key,CASE WHEN "CityName"=''市辖区'' THEN "ProvinceName" ELSE "CityName" end as value FROM "public"."Sys_City" AS a +INNER JOIN "public"."Sys_Province" AS b +ON a."ProvinceCode"=b."ProvinceCode" +WHERE a."CityName"<> ''县''', '城市', 'city', 1, 'admin', '2020-08-06 17:53:59.104961', 1, NULL, 0, NULL); +INSERT INTO "public"."Sys_Dictionary" VALUES (32, '{valueField: ''Role_Id'', + textField: ''RoleName'', + containField: ''Role_Id'',''RoleName'', + handler: null } +', NULL, NULL, '测试超级管理员', NULL, 'SELECT "Role_Id" as key,"RoleName" as value from "public"."Sys_Role"', '角色列表', 'roles', 1, 'admin', '2020-08-06 18:37:19.548483', 1, 123, 0, 'sql语句需要key,value列,界面才能绑定数据源'); +INSERT INTO "public"."Sys_Dictionary" VALUES (65, NULL, NULL, 1, '超级管理员', NULL, NULL, '商品名称', 'pn', 1, 'admin', '2020-08-06 19:12:10.22013', 1, 2, 0, '测试'); + +-- ---------------------------- +-- Table structure for Sys_DictionaryList +-- ---------------------------- +DROP TABLE IF EXISTS "public"."Sys_DictionaryList"; +CREATE TABLE "public"."Sys_DictionaryList" ( + "DicList_ID" int4 NOT NULL DEFAULT nextval('sys_dictionarylist_id_seq'::regclass), + "CreateDate" timestamp(6), + "CreateID" int4, + "Creator" varchar(30) COLLATE "pg_catalog"."default", + "DicName" varchar(100) COLLATE "pg_catalog"."default", + "DicValue" varchar(100) COLLATE "pg_catalog"."default", + "Dic_ID" int4, + "Enable" int2, + "Modifier" varchar(30) COLLATE "pg_catalog"."default", + "ModifyDate" timestamp(6), + "ModifyID" int4, + "OrderNo" int4, + "Remark" varchar(2000) COLLATE "pg_catalog"."default" +) +; + +-- ---------------------------- +-- Records of Sys_DictionaryList +-- ---------------------------- +INSERT INTO "public"."Sys_DictionaryList" VALUES (3, NULL, 1, 'admi', '否', '0', 3, NULL, '超级管理员', NULL, 1, 2, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (4, NULL, 1, 'xxx', '是', '1', 3, NULL, '超级管理员', NULL, 1, 1, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (22, NULL, 1, '测试超级管理员', '其他', '0', 30, NULL, '超级管理员', NULL, 1, 10, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (23, NULL, 1, '测试超级管理员', '成功', '1', 30, NULL, '超级管理员', NULL, 1, 100, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (24, NULL, 1, '测试超级管理员', '异常', '2', 30, NULL, '超级管理员', NULL, 1, 50, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (25, NULL, 1, '测试超级管理员', '系统', 'System', 31, NULL, '超级管理员', NULL, 1, 100, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (26, NULL, 1, '测试超级管理员', '登陆', 'Logi', 31, NULL, '超级管理员', NULL, 1, 90, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (27, NULL, 1, '测试超级管理员', '新建', 'Add', 31, NULL, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (28, NULL, 1, '测试超级管理员', '删除', 'Del', 31, 1, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (29, NULL, 1, '测试超级管理员', '编辑', 'Edit', 31, 1, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (33, NULL, 1, '测试超级管理员', '注册', '1', 34, NULL, '测试超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (34, NULL, 1, '测试超级管理员', '忘记密码', '2', 34, NULL, '测试超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (35, NULL, 1, '测试超级管理员', '验证码登录', '3', 34, NULL, '测试超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (36, NULL, 1, '测试超级管理员', '修改密码', '4', 34, NULL, '测试超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (37, NULL, 1, '测试超级管理员', '审核中', '0', 35, NULL, '测试超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (38, NULL, 1, '测试超级管理员', '审核通过', '1', 35, NULL, '测试超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (39, NULL, 1, '测试超级管理员', '审核未通过', '2', 35, NULL, '测试超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (40, NULL, 1, '测试超级管理员', '西门塔尔', '8', 36, NULL, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (41, NULL, 1, '测试超级管理员', '利木赞牛', '7', 36, NULL, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (42, NULL, 1, '测试超级管理员', '夏洛莱牛', '6', 36, NULL, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (43, NULL, 1, '测试超级管理员', '鲁西黄牛', '5', 36, NULL, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (44, NULL, 1, '测试超级管理员', '神户肉牛', '4', 36, NULL, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (45, NULL, 1, '测试超级管理员', '南阳牛', '3', 36, NULL, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (46, NULL, 1, '测试超级管理员', '秦川牛', '2', 36, NULL, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (47, NULL, 1, '测试超级管理员', '0-2月龄', '0-2月龄', 37, NULL, '测试超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (48, NULL, 1, '测试超级管理员', '2-6月龄', '2-6月龄', 37, NULL, '测试超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (49, NULL, 1, '测试超级管理员', '7-12月龄', '7-12月龄', 37, NULL, '测试超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (50, NULL, 1, '测试超级管理员', '12-16月龄', '12-16月龄', 37, NULL, '测试超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (51, NULL, 1, '测试超级管理员', '16月龄以上', '16月龄以上', 37, NULL, '测试超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (52, NULL, 1, '测试超级管理员', '未回复', '0', 39, NULL, '测试超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (53, NULL, 1, '测试超级管理员', '已回复', '1', 39, NULL, '测试超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (56, NULL, 1, '测试超级管理员', '公牛', '公牛', 41, NULL, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (57, NULL, 1, '测试超级管理员', '母牛', '母牛', 41, NULL, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (58, NULL, 1, '测试超级管理员', '39.5°C以上(升高);', '39.5°C以上(升高);', 42, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (59, NULL, 1, '测试超级管理员', '38°C~39.5°C以上(正常);', '38°C~39.5°C以上(正常);', 42, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (60, NULL, 1, '测试超级管理员', '38°C以下(降低);', '38°C以下(降低);', 42, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (64, NULL, 1, '测试超级管理员', '行业新闻', '1', 44, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (65, NULL, 1, '测试超级管理员', '行情资讯', '2', 44, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (66, NULL, 1, '测试超级管理员', '否', '0', 45, NULL, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (67, NULL, 1, '测试超级管理员', '是', '1', 45, NULL, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (68, NULL, 1, '测试超级管理员', 'App登陆', 'ApiLogi', 31, NULL, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (69, NULL, 1, '测试超级管理员', 'App发送验证码', 'ApiSendPI', 31, NULL, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (70, NULL, 1, '测试超级管理员', 'App请求异常', 'ApiExceptio', 31, NULL, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (71, NULL, 1, '测试超级管理员', 'PC请求异常', 'Exceptio', 31, NULL, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (77, NULL, 1, '测试超级管理员', '现金', '1', 48, NULL, '超级管理员', NULL, 1, 120, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (78, NULL, 1, '测试超级管理员', '赊账', '2', 48, NULL, '超级管理员', NULL, 1, 70, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (79, NULL, 1, '测试超级管理员', '抵扣', '3', 48, NULL, '超级管理员', NULL, 1, 100, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (86, NULL, 1, '测试超级管理员', 'App首页', 'AppHome', 31, NULL, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (89, NULL, 1, '测试超级管理员', '加入会议', 'JoinMeeting', 31, NULL, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (90, NULL, 1, '测试超级管理员', '男', '0', 49, NULL, '测试超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (91, NULL, 1, '测试超级管理员', '女', '1', 49, NULL, '测试超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (92, NULL, 1, '测试超级管理员', '修改密码', 'ApiModifyPwd', 31, 0, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (93, NULL, 1, '测试超级管理员', '加入我们', 'JoinUs', 31, 0, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (96, NULL, 1, '测试超级管理员', '未启用', '0', 50, 1, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (97, NULL, 1, '测试超级管理员', '已启用', '1', 50, 1, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (98, NULL, 1, '测试超级管理员', '已删除', '2', 50, 1, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (101, NULL, 1, '测试超级管理员', '否', '0', 52, 0, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (102, NULL, 1, '测试超级管理员', '是', '1', 52, 0, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (104, NULL, 1, '测试超级管理员', 'iPhone测试', 'IPhoneTest', 31, 0, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (109, NULL, 1, '测试超级管理员', 'PC后台上传', '0', 53, 0, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (110, NULL, 1, '测试超级管理员', '专家提问', '1', 53, 0, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (111, NULL, 1, '测试超级管理员', '公开提问', '2', 53, 0, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (112, NULL, 1, '测试超级管理员', '首面轮播', '3', 53, 0, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (128, NULL, 1, '测试超级管理员', '是', '1', 59, 0, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (129, NULL, 1, '测试超级管理员', '否', '0', 59, 1, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (130, NULL, 1, '测试超级管理员', '安格斯', '1', 36, 1, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (137, NULL, 1, '超级管理员', '是', '1', 60, 1, '超级管理员', NULL, 1, 2, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (138, NULL, 1, '超级管理员', '否', '0', 60, 1, '超级管理员', NULL, 1, 1, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (142, NULL, 1, '超级管理员', '是', '1', 62, 1, '超级管理员', NULL, 1, NULL, '1'); +INSERT INTO "public"."Sys_DictionaryList" VALUES (143, NULL, 1, '超级管理员', '否', '0', 62, 1, '超级管理员', NULL, 1, NULL, '测试'); +INSERT INTO "public"."Sys_DictionaryList" VALUES (144, NULL, 1, '超级管理员', '刷新Toke', 'ReplaceToeke', 31, NULL, '超级管理员', NULL, 1, 110, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (145, NULL, 1, '超级管理员', 'Info', '3', 30, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (147, NULL, 1, '超级管理员', 'xx', '2', 62, 1, '超级管理员', NULL, 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (149, NULL, 1, '超级管理员', '发货', '1', 64, 1, '超级管理员', NULL, 1, NULL, 'fd'); +INSERT INTO "public"."Sys_DictionaryList" VALUES (150, NULL, 1, '超级管理员', '退货', '2', 64, 0, '超级管理员', NULL, 1, NULL, 'fs'); +INSERT INTO "public"."Sys_DictionaryList" VALUES (151, NULL, 1, '超级管理员', '返单', '3', 64, 1, '超级管理员', NULL, 1, NULL, 'xx'); +INSERT INTO "public"."Sys_DictionaryList" VALUES (422, NULL, 1, '超级管理员', 'xx11', '2', 3, 0, NULL, NULL, NULL, 2, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (500, '2020-06-14 20:58:28.303638', 1, 'admin', 'tt', '1', 1, 0, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (501, '2020-06-14 20:58:28.35064', 1, 'admin', 't', '2', 1, 0, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (152, NULL, 1, '超级管理员', '家居', '家居', 65, 1, 'admin', '2020-08-06 19:12:10.271845', 1, NULL, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (153, NULL, 1, '超级管理员', '男装', '男装', 65, 1, 'admin', '2020-08-06 19:12:10.271774', 1, 4, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (154, NULL, 1, '超级管理员', '女装', '女装', 65, NULL, 'admin', '2020-08-06 19:12:10.271589', 1, 6, NULL); +INSERT INTO "public"."Sys_DictionaryList" VALUES (155, NULL, 1, '超级管理员', '食品', '食品', 65, NULL, 'admin', '2020-08-06 19:12:10.251886', 1, NULL, NULL); + +-- ---------------------------- +-- Table structure for Sys_Log +-- ---------------------------- +DROP TABLE IF EXISTS "public"."Sys_Log"; +CREATE TABLE "public"."Sys_Log" ( + "Id" int4 NOT NULL DEFAULT nextval('sys_log_id_seq'::regclass), + "BeginDate" timestamp(6), + "BrowserType" varchar(200) COLLATE "pg_catalog"."default", + "ElapsedTime" int4, + "EndDate" timestamp(6), + "ExceptionInfo" text COLLATE "pg_catalog"."default", + "LogType" varchar(50) COLLATE "pg_catalog"."default", + "RequestParameter" text COLLATE "pg_catalog"."default", + "ResponseParameter" text COLLATE "pg_catalog"."default", + "Role_Id" int4, + "ServiceIP" varchar(100) COLLATE "pg_catalog"."default", + "Success" int4, + "Url" varchar(4000) COLLATE "pg_catalog"."default", + "UserIP" varchar(100) COLLATE "pg_catalog"."default", + "UserName" varchar(4000) COLLATE "pg_catalog"."default", + "User_Id" int4 +) +; + +-- ---------------------------- +-- Records of Sys_Log +-- ---------------------------- +INSERT INTO "public"."Sys_Log" VALUES (31, '2020-08-07 19:40:07.532154', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36', 160, '2020-08-07 19:40:07.69194', NULL, 'System', NULL, NULL, 1, '127.0.0.1:9991', 3, 'http://127.0.0.1:9991/api/Sys_Log/getPageData', '127.0.0.1', 'admin', 1); +INSERT INTO "public"."Sys_Log" VALUES (32, '2020-08-07 19:40:07.597547', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36', 141, '2020-08-07 19:40:07.738682', NULL, 'System', NULL, NULL, 1, '127.0.0.1:9991', 3, 'http://127.0.0.1:9991/api/Sys_Log/getPageData', '127.0.0.1', 'admin', 1); +INSERT INTO "public"."Sys_Log" VALUES (33, '2020-08-07 19:40:07.955882', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36', 172, '2020-08-07 19:40:08.128259', NULL, 'System', NULL, NULL, 1, '127.0.0.1:9991', 3, 'http://127.0.0.1:9991/api/Sys_Log/getPageData', '127.0.0.1', 'admin', 1); +INSERT INTO "public"."Sys_Log" VALUES (34, '2020-08-07 19:40:14.293606', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36', 284, '2020-08-07 19:40:14.577677', NULL, 'Del', '[27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,10,9,8,7,6,5,4,3,2,1]', 'Ok', 1, '127.0.0.1:9991', 3, 'http://127.0.0.1:9991/api/Sys_Log/del', '127.0.0.1', 'admin', 1); +INSERT INTO "public"."Sys_Log" VALUES (35, '2020-08-07 19:40:14.293606', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36', 285, '2020-08-07 19:40:14.57828', NULL, 'System', NULL, NULL, 1, '127.0.0.1:9991', 3, 'http://127.0.0.1:9991/api/Sys_Log/del', '127.0.0.1', 'admin', 1); +INSERT INTO "public"."Sys_Log" VALUES (36, '2020-08-07 19:40:14.606022', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36', 194, '2020-08-07 19:40:14.800023', NULL, 'System', NULL, NULL, 1, '127.0.0.1:9991', 3, 'http://127.0.0.1:9991/api/Sys_Log/getPageData', '127.0.0.1', 'admin', 1); +INSERT INTO "public"."Sys_Log" VALUES (37, '2020-08-07 19:47:15.898516', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36', 3618, '2020-08-07 19:47:19.516318', NULL, 'System', NULL, NULL, 1, '127.0.0.1:9991', 3, 'http://127.0.0.1:9991/api/Sys_Log/getPageData', '127.0.0.1', 'admin', 1); +INSERT INTO "public"."Sys_Log" VALUES (38, '2020-08-07 19:47:18.476497', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36', 1040, '2020-08-07 19:47:19.516311', NULL, 'System', NULL, NULL, 1, '127.0.0.1:9991', 3, 'http://127.0.0.1:9991/api/Sys_Log/getPageData', '127.0.0.1', 'admin', 1); +INSERT INTO "public"."Sys_Log" VALUES (39, '2020-08-07 19:47:16.491604', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36', 3025, '2020-08-07 19:47:19.516336', NULL, 'System', NULL, NULL, 1, '127.0.0.1:9991', 3, 'http://127.0.0.1:9991/api/Sys_Log/getPageData', '127.0.0.1', 'admin', 1); +INSERT INTO "public"."Sys_Log" VALUES (40, '2020-08-07 19:47:16.80781', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36', 2709, '2020-08-07 19:47:19.516324', NULL, 'System', NULL, NULL, 1, '127.0.0.1:9991', 3, 'http://127.0.0.1:9991/api/Sys_Log/getPageData', '127.0.0.1', 'admin', 1); +INSERT INTO "public"."Sys_Log" VALUES (41, '2020-08-07 19:47:15.414562', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36', 4102, '2020-08-07 19:47:19.516334', NULL, 'System', NULL, NULL, 1, '127.0.0.1:9991', 3, 'http://127.0.0.1:9991/api/Sys_Log/getPageData', '127.0.0.1', 'admin', 1); +INSERT INTO "public"."Sys_Log" VALUES (42, '2020-08-07 19:47:17.404502', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36', 2112, '2020-08-07 19:47:19.516299', NULL, 'System', NULL, NULL, 1, '127.0.0.1:9991', 3, 'http://127.0.0.1:9991/api/Sys_Log/getPageData', '127.0.0.1', 'admin', 1); +INSERT INTO "public"."Sys_Log" VALUES (43, '2020-08-07 19:49:03.898232', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36', 425, '2020-08-07 19:49:04.323566', NULL, 'Exception', '主键类型【System.Int32[]】不正确 at VOL.Core.Dapper.SqlDapper.DelWithKey[T](Boolean beginTransaction, Object[] keys) in G:\jxx\Vue.NetCore\Vue.Net\VOL.Core\Dapper\SqlDapper.cs:line 343 + at VOL.Core.Dapper.SqlDapper.DelWithKey[T](Object[] keys) in G:\jxx\Vue.NetCore\Vue.Net\VOL.Core\Dapper\SqlDapper.cs:line 369 + at VOL.AppManager.Controllers.test2019Controller.Test() in G:\jxx\Vue.NetCore\Vue.Net\VOL.WebApi\Controllers\AppManager\Partial\test2019Controller.cs:line 37 + at lambda_method(Closure , Object , Object[] ) + at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters) + at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) + at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync() + at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) + at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync() +--- End of stack trace from previous location where exception was thrown --- + at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) + at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) + at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync() +--- End of stack trace from previous location where exception was thrown --- + at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) + at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context) + at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) + at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync() +--- End of stack trace from previous location where exception was thrown --- + at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) + at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) + at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) + at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) + at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext) + at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider) + at VOL.Core.Middleware.HttpRequestMiddleware.<>c__DisplayClass1_0.<b__1>d.MoveNext() in G:\jxx\Vue.NetCore\Vue.Net\VOL.Core\Middleware\HttpRequestMiddleware.cs:line 39 +--- End of stack trace from previous location where exception was thrown --- + at VOL.Core.Middleware.ExceptionHandlerMiddleWare.Invoke(HttpContext context) in G:\jxx\Vue.NetCore\Vue.Net\VOL.Core\Middleware\ExceptionHandlerMiddleWare.cs:line 28', NULL, 0, '0.0.0.1:9991', 2, 'http://localhost:9991/api/test2019/test', '::1', NULL, 0); +INSERT INTO "public"."Sys_Log" VALUES (44, '2020-08-07 19:51:45.032689', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36', 1256, '2020-08-07 19:51:46.288598', NULL, 'System', NULL, NULL, 0, '0.0.0.1:9991', 3, 'http://localhost:9991/api/test2019/test', '::1', NULL, 0); +INSERT INTO "public"."Sys_Log" VALUES (45, '2020-08-07 19:51:46.47603', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36', 22, '2020-08-07 19:51:46.498475', NULL, 'System', NULL, NULL, 0, '0.0.0.1:9991', 3, 'http://localhost:9991/favicon.ico', '::1', NULL, 0); + +-- ---------------------------- +-- Table structure for Sys_Menu +-- ---------------------------- +DROP TABLE IF EXISTS "public"."Sys_Menu"; +CREATE TABLE "public"."Sys_Menu" ( + "Menu_Id" int4 NOT NULL DEFAULT nextval('sys_menu_id_seq'::regclass), + "MenuName" varchar(50) COLLATE "pg_catalog"."default" NOT NULL, + "Auth" varchar(4000) COLLATE "pg_catalog"."default", + "Icon" varchar(50) COLLATE "pg_catalog"."default", + "Description" varchar(200) COLLATE "pg_catalog"."default", + "Enable" int2, + "OrderNo" int4, + "TableName" varchar(200) COLLATE "pg_catalog"."default", + "ParentId" int4 NOT NULL, + "Url" varchar(4000) COLLATE "pg_catalog"."default", + "CreateDate" timestamp(6), + "Creator" varchar(50) COLLATE "pg_catalog"."default", + "ModifyDate" timestamp(6), + "Modifier" varchar(50) COLLATE "pg_catalog"."default" +) +; + +-- ---------------------------- +-- Records of Sys_Menu +-- ---------------------------- +INSERT INTO "public"."Sys_Menu" VALUES (2, '用户基础信息', '[{"text":"查询","value":"Search"}]', 'ivu-icon ivu-icon-md-contact', NULL, 1, 1600, '.', 0, NULL, '2017-08-28 12:21:13', '2017-08-28 11:12:45', '2019-10-11 14:33:29', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (3, '角色管理', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"},{"text":"导出","value":"Export"}]', NULL, NULL, 1, 900, 'Sys_Role', 2, '/Sys_Role/Manager', '2017-09-12 16:20:02', '2017-08-28 14:19:13', '2019-08-15 10:27:41', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (5, '日志管理', '[{"text":"查询","value":"Search"}]', 'ivu-icon ivu-icon-ios-create', NULL, 1, 1300, 'xxx', 0, '/', '2017-09-22 17:59:37', '2017-09-22 17:59:37', '2019-10-11 14:34:00', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (6, '系统日志', '[{"text":"查询","value":"Search"},{"text":"删除","value":"Delete"},{"text":"导出","value":"Export"}]', NULL, NULL, 1, 0, 'Sys_Log', 5, '/Sys_Log/Manager', '2017-09-22 18:00:25', '2017-09-22 18:0:25', '2019-08-14 16:20:35', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (7, '角色权限分配', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"},{"text":"导出","value":"Export"}]', NULL, NULL, 0, 10, 'Sys_Role', 2, '/Sys_Role/TreeManager', NULL, NULL, '2019-09-19 15:15:54', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (9, '用户管理', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"},{"text":"导入","value":"Import"},{"text":"导出","value":"Export"},{"text":"上传","value":"Upload"},{"text":"审核","value":"Audit"}]', NULL, NULL, 1, 11110, 'Sys_User', 2, '/Sys_User/Manager', NULL, NULL, '2019-08-14 14:28:43', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (10, '表单与上传下载', '[{"text":"查询","value":"Search"}]', NULL, NULL, 1, 0, '/', 28, '/formUpload', NULL, NULL, '2019-12-07 11:16:47', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (11, 'api加载table数据', '[{"text":"查询","value":"Search"}]', NULL, NULL, 1, 600, 'table2', 12, '/table2', NULL, NULL, '2019-11-14 00:11:17', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (12, 'tables', '[{"text":"查询","value":"Search"}]', 'ios-grid', NULL, 1, 1710, '/', 0, NULL, '2017-08-28 14:22:10', 'null', '2019-11-15 14:32:32', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (16, '首页轮播图片', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"},{"text":"导入","value":"Import"},{"text":"导出","value":"Export"},{"text":"上传","value":"Upload"},{"text":"审核","value":"Audit"}]', NULL, NULL, 0, 2000, 'App_HomeHeadImages', 15, '/App_HomeHeadImages/Manager', NULL, NULL, '2019-08-12 16:26:44', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (17, '用户注册信息', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"},{"text":"导入","value":"Import"},{"text":"导出","value":"Export"},{"text":"上传","value":"Upload"},{"text":"审核","value":"Audit"}]', NULL, NULL, 0, 10, 'Sys_UserRegisterRecord', 2, '/Sys_UserRegisterRecord/Manager', NULL, NULL, '2019-09-18 15:31:24', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (24, '后台加载table数据', '[{"text":"查询","value":"Search"}]', NULL, NULL, 1, 750, '/', 56, '/table', NULL, NULL, '2019-09-20 14:59:25', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (25, '其他组件', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"},{"text":"导入","value":"Import"},{"text":"导出","value":"Export"},{"text":"上传","value":"Upload"},{"text":"审核","value":"Audit"}]', NULL, NULL, 1, 1100, '/', 29, '/form6', NULL, NULL, '2019-09-22 23:27:37', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (26, '文件上传', '[{"text":"查询","value":"Search"}]', NULL, NULL, 1, 1050, 'volUploadExample', 28, '/volUploadExample', NULL, NULL, '2019-12-17 18:29:50', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (27, '基础可编辑table', '[{"text":"查询","value":"Search"}]', NULL, NULL, 1, 1050, 'vtable', 12, '/table1', NULL, NULL, '2019-11-14 00:08:51', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (28, '文件上传与载', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"},{"text":"导入","value":"Import"},{"text":"导出","value":"Export"},{"text":"上传","value":"Upload"},{"text":"审核","value":"Audit"}]', 'ios-folder-open', NULL, 1, 1690, '/', 0, NULL, NULL, NULL, '2020-02-24 12:11:24', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (29, '其他组件', '[{"text":"查询","value":"Search"}]', 'ivu-icon ivu-icon-md-hammer', NULL, 1, 1670, '其他组件', 0, NULL, NULL, NULL, '2019-12-22 00:39:08', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (30, '图表', '[{"text":"查询","value":"Search"}]', NULL, NULL, 1, 100000, 'App_PriceTendency', 34, '/chart', NULL, NULL, '2019-11-14 00:07:26', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (31, '图表+表单', '[{"text":"查询","value":"Search"}]', NULL, NULL, 1, 950, 'App_Comment', 34, '/formChart', NULL, NULL, '2019-11-14 00:07:51', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (32, '表单一对多', '[{"text":"查询","value":"Search"}]', 'ios-podium', NULL, 1, 1740, '/', 0, NULL, NULL, NULL, '2019-11-15 14:33:07', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (33, '完整table+forms', '[{"text":"查询","value":"Search"}]', NULL, NULL, 1, 800, 'tableForms', 12, '/tableForms', NULL, NULL, '2020-04-03 22:58:27', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (34, '图表+表单', '[{"text":"查询","value":"Search"}]', 'ios-pie', NULL, 1, 1720, '/', 0, NULL, NULL, NULL, '2019-11-15 14:32:56', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (35, '可编辑的table', '[{"text":"查询","value":"Search"}]', NULL, NULL, 1, 730, 'editTable', 56, '/editTable', NULL, NULL, '2019-09-20 15:50:21', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (36, '表单一对多table', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"},{"text":"导入","value":"Import"},{"text":"导出","value":"Export"}]', NULL, NULL, 1, 950, 'App_TransactionAvgPrice1', 32, '/multi1', NULL, NULL, '2019-11-14 00:03:19', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (37, '表单+图表', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"},{"text":"导入","value":"Import"},{"text":"导出","value":"Export"},{"text":"上传","value":"Upload"},{"text":"审核","value":"Audit"}]', NULL, NULL, 1, 800, 'App_Transaction', 32, '/multi3', NULL, NULL, '2019-11-14 00:04:17', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (38, '省市列表', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"},{"text":"导出","value":"Export"}]', NULL, NULL, 1, 1000, 'vProvinceCity', 15, '/vProvinceCity', NULL, NULL, '2019-08-20 09:30:04', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (39, '用户Token生成记录', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"},{"text":"导入","value":"Import"},{"text":"导出","value":"Export"},{"text":"上传","value":"Upload"},{"text":"审核","value":"Audit"}]', NULL, NULL, 0, 10, 'x', 2, '/Sys_UserTokenLog/Manager', NULL, NULL, '2019-09-18 15:31:19', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (41, '可复用后台校验', '[{"text":"查询","value":"Search"}]', 'ios-switch', NULL, 1, 1700, '/', 0, NULL, NULL, NULL, '2020-02-02 20:01:16', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (42, '主从表单明细一对多', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"},{"text":"导出","value":"Export"}]', NULL, NULL, 1, 0, 'SellOrder1', 32, '/multi4', NULL, NULL, '2020-04-03 22:54:52', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (45, '不用节点放此处', NULL, NULL, NULL, 0, 0, '/', 0, NULL, NULL, NULL, '2020-05-05 12:02:07', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (46, '产业联盟', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"},{"text":"导出","value":"Export"},{"text":"审核","value":"Audit"}]', NULL, NULL, 1, 10, 'App_Alliance', 15, '/App_Alliance/Manager', NULL, NULL, '2019-08-13 13:12:42', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (47, 'test2019', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"},{"text":"导出","value":"Export"}]', NULL, NULL, 1, 0, 'test2019', 15, '/test2019', '2019-04-30 15:16:23', '超级管理员', '2019-08-13 13:12:50', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (48, 'Table+单表数据', '[{"text":"查询","value":"Search"}]', 'ivu-icon ivu-icon-md-grid', NULL, 1, 2000, 'Table+表单数据', 0, '/', '2019-07-12 13:26:32', '超级管理员', '2019-10-11 14:29:14', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (49, '基础表单+编辑只读', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"编辑","value":"Update"},{"text":"导入","value":"Import"},{"text":"导出","value":"Export"},{"text":"上传","value":"Upload"}]', NULL, NULL, 1, 1000, 'App_Appointment', 48, '/App_Appointment', '2019-07-12 13:28:17', '超级管理员', '2020-04-24 13:43:27', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (50, '自动绑定下拉框', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"}]', NULL, NULL, 1, 900, 'App_TransactionAvgPrice', 48, '/App_TransactionAvgPrice', '2019-07-12 13:53:32', '超级管理员', '2020-03-03 10:25:29', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (51, '自定义扩展一对多', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"},{"text":"导出","value":"Export"},{"text":"审核","value":"Audit"}]', NULL, NULL, 1, 800, 'App_ReportPrice', 74, '/App_ReportPrice', '2019-07-12 13:55:21', '超级管理员', '2020-04-03 22:56:32', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (52, '导入导出表单', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"},{"text":"导入","value":"Import"},{"text":"导出","value":"Export"}]', NULL, NULL, 1, 600, 'App_Transaction', 48, '/App_Transaction', '2019-07-12 13:56:15', '超级管理员', '2019-10-31 13:23:37', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (53, '主从基础表单', NULL, NULL, NULL, 1, 10, '/', 55, '/coding', '2019-07-12 13:57:05', '超级管理员', '2019-07-12 13:59:08', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (54, '可新增修改主从表单', NULL, NULL, NULL, 1, 10, '/', 55, '/coding', '2019-07-12 13:57:56', '超级管理员', '2019-07-12 13:59:12', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (55, 'Table+主从表单', '[{"text":"查询","value":"Search"}]', 'ivu-icon ivu-icon-ios-grid', NULL, 0, 1800, '/', 0, NULL, '2019-07-12 13:58:34', '超级管理员', '2019-10-11 14:31:11', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (56, '表单布局', '[{"text":"查询","value":"Search"}]', 'ivu-icon ivu-icon-ios-color-filter', NULL, 1, 1750, '/', 0, NULL, '2019-07-12 14:00:19', '超级管理员', '2020-01-08 13:54:41', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (57, '单列表单', '[{"text":"查询","value":"Search"}]', NULL, NULL, 1, 1000, '.', 56, '/form1', '2019-07-12 14:01:12', '超级管理员', '2019-09-20 13:59:00', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (58, '两列表单', '[{"text":"查询","value":"Search"}]', NULL, NULL, 1, 900, '两列表单', 56, '/form2', '2019-07-12 14:01:43', '超级管理员', '2019-09-20 13:59:03', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (59, '多列表单自动数据源', '[{"text":"查询","value":"Search"}]', NULL, NULL, 1, 800, '多列表单', 56, '/form3', '2019-07-12 14:02:17', '超级管理员', '2019-12-17 11:08:06', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (60, 'Table+表单', '[{"text":"查询","value":"Search"}]', NULL, NULL, 1, 700, 'Table+表单', 56, '/form4', '2019-07-12 14:03:14', '超级管理员', '2019-09-20 13:59:09', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (61, '系统', '[{"text":"查询","value":"Search"}]', 'ivu-icon ivu-icon-md-settings', NULL, 1, 1350, '系统', 0, '/', '2019-07-12 14:04:04', '超级管理员', '2019-11-27 13:30:08', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (62, '菜单设置', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"编辑","value":"Update"}]', NULL, NULL, 1, 10, 'Sys_Menu', 61, '/sysmenu', '2019-07-12 14:04:35', '超级管理员', '2019-10-31 13:23:09', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (63, '下拉框绑定设置', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"},{"text":"导出","value":"Export"}]', NULL, NULL, 1, 10, 'Sys_Dictionary', 61, '/Sys_Dictionary', '2019-07-12 14:05:58', '超级管理员', '2019-08-16 17:41:15', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (64, '代码在线生成器', '[{"text":"查询","value":"Search"}]', 'ivu-icon ivu-icon-ios-construct', NULL, 1, 1500, '代码在线生成器', 0, '/coding', '2019-07-12 14:07:55', '超级管理员', '2020-01-08 13:54:50', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (65, 'Vue+后台代码生成', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"}]', NULL, NULL, 1, 10, '/', 64, '/coder', '2019-07-12 14:08:58', '超级管理员', '2019-09-22 23:27:54', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (66, '编辑器与HTML', '[{"text":"查询","value":"Search"}]', 'ivu-icon ivu-icon-md-compass', NULL, 1, 1680, '静态页面发布', 0, '/coding', '2019-07-12 14:12:38', '超级管理员', '2019-12-22 00:40:19', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (67, '静态页面发布', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"},{"text":"导出","value":"Export"},{"text":"上传","value":"Upload"}]', NULL, NULL, 1, 10, 'App_News', 66, '/App_News', '2019-07-12 14:14:16', '超级管理员', '2019-12-22 00:40:46', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (68, '文件上传与图片显示', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"编辑","value":"Update"},{"text":"导出","value":"Export"},{"text":"审核","value":"Audit"}]', NULL, NULL, 1, 700, 'App_Expert', 48, '/App_Expert', '2019-07-12 14:24:15', '超级管理员', '2019-11-27 14:00:57', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (69, '前端自定义扩展', NULL, NULL, NULL, 0, 500, '前端自定义扩展', 48, '/coding', '2019-07-12 14:26:25', '超级管理员', '2019-09-25 17:22:22', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (70, '后台自定义扩展', NULL, NULL, NULL, 0, 400, '后台自定义扩展', 48, '/coding', '2019-07-12 14:28:45', '超级管理员', '2019-09-25 17:22:26', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (71, 'vue权限管理', '[{"text":"查询","value":"Search"},{"text":"编辑","value":"Update"}]', 'ivu-icon ivu-icon-ios-boat', NULL, 1, 1000, 'Sys_Role', 2, '/permission', '2019-08-10 10:25:36', '超级管理员', NULL, NULL); +INSERT INTO "public"."Sys_Menu" VALUES (72, '移动H5开发', '[{"text":"查询","value":"Search"}]', 'ivu-icon ivu-icon-logo-android', NULL, 1, 1650, '/', 0, NULL, '2019-08-14 13:16:06', '超级管理员', '2019-10-11 14:32:41', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (73, '移动H5开发打包介绍', '[{"text":"查询","value":"Search"}]', NULL, NULL, 1, NULL, '/', 72, '/app/guide', '2019-08-14 13:16:55', '超级管理员', NULL, NULL); +INSERT INTO "public"."Sys_Menu" VALUES (74, '一对一与一对多', '[{"text":"查询","value":"Search"}]', 'md-film', NULL, 1, 1770, '/', 0, '/', '2019-08-22 17:43:58', '超级管理员', '2020-04-07 23:57:06', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (75, '主从一对一', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"},{"text":"导入","value":"Import"},{"text":"导出","value":"Export"},{"text":"上传","value":"Upload"},{"text":"审核","value":"Audit"}]', NULL, NULL, 1, 1000, 'SellOrder', 74, '/SellOrder', '2019-08-22 18:12:43', '超级管理员', '2020-04-03 22:55:15', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (76, 'api加载table数据', '[{"text":"查询","value":"Search"}]', NULL, NULL, 0, 950, 'table2', 2, '/table2', '2019-08-26 11:57:51', '超级管理员', '2019-11-19 17:30:17', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (77, '表单只读', '[{"text":"查询","value":"Search"}]', NULL, NULL, 1, 600, '表单只读', 56, '/form7', '2019-08-26 11:58:55', '超级管理员', '2019-09-20 13:59:13', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (78, '混合表单一对多', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"},{"text":"导入","value":"Import"},{"text":"导出","value":"Export"},{"text":"上传","value":"Upload"},{"text":"审核","value":"Audit"}]', NULL, NULL, 1, 900, '32', 32, '/multi2', '2019-10-12 09:18:41', '超级管理员', '2019-11-14 00:03:51', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (79, 'KindEditor编辑器', '[{"text":"查询","value":"Search"}]', NULL, NULL, 1, 100, 'KindEditor编辑器', 66, '/kindEditor', '2019-12-22 00:36:10', '超级管理员', '2019-12-22 00:40:43', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (80, '静态页面列表', '[{"text":"查询","value":"Search"}]', NULL, NULL, 1, 0, 'htmlList', 66, '/htmlList', '2019-12-22 00:36:54', '超级管理员', '2019-12-21 22:50:41', NULL); +INSERT INTO "public"."Sys_Menu" VALUES (81, '后台参数校验', '[{"text":"查询","value":"Search"}]', NULL, NULL, 1, 0, '/', 41, '/validator', '2020-02-02 20:01:59', '超级管理员', '2020-02-02 20:01:16', NULL); +INSERT INTO "public"."Sys_Menu" VALUES (82, '数字排版', '[{"text":"查询","value":"Search"}]', NULL, NULL, 1, 0, 'flex', 34, '/flex', '2020-04-07 23:55:33', '超级管理员', '2019-11-15 14:32:56', NULL); +INSERT INTO "public"."Sys_Menu" VALUES (83, '从表图片上传', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"},{"text":"导出","value":"Export"}]', NULL, NULL, 1, 0, 'vSellorderImg', 74, '/vSellorderImg', '2020-04-07 23:56:22', '超级管理员', '2020-04-07 23:56:28', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (84, '树形菜单与table', '[{"text":"查询","value":"Search"}]', 'md-analytics', NULL, 1, 1705, '树形菜单与table', 0, NULL, '2020-04-26 20:19:42', '超级管理员', '2020-04-26 20:19:55', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (85, 'tree与代码生成页面', '[{"text":"查询","value":"Search"},{"text":"新建","value":"Add"},{"text":"删除","value":"Delete"},{"text":"编辑","value":"Update"}]', NULL, NULL, 1, 100, 'treetable1', 84, '/treetable1', '2020-04-26 20:20:28', '超级管理员', '2019-11-15 14:32:32', NULL); +INSERT INTO "public"."Sys_Menu" VALUES (86, 'tree自定义table数据', '[{"text":"查询","value":"Search"}]', NULL, NULL, 1, 10, 'treetable2', 84, '/treetable2', '2020-04-26 20:20:57', '超级管理员', '2020-04-26 20:21:34', '超级管理员'); +INSERT INTO "public"."Sys_Menu" VALUES (87, '不用节点父级id45', NULL, NULL, NULL, 1, 0, '/', 45, NULL, '2020-05-05 12:01:42', '超级管理员', '2020-05-05 12:01:59', '超级管理员'); + +-- ---------------------------- +-- Table structure for Sys_Province +-- ---------------------------- +DROP TABLE IF EXISTS "public"."Sys_Province"; +CREATE TABLE "public"."Sys_Province" ( + "ProvinceId" int4 NOT NULL DEFAULT nextval('sys_province1_id_seq'::regclass), + "ProvinceCode" varchar(20) COLLATE "pg_catalog"."default" NOT NULL, + "ProvinceName" varchar(30) COLLATE "pg_catalog"."default" NOT NULL, + "RegionCode" varchar(20) COLLATE "pg_catalog"."default" +) +; + +-- ---------------------------- +-- Records of Sys_Province +-- ---------------------------- +INSERT INTO "public"."Sys_Province" VALUES (1, '110000', '北京市', '华北'); +INSERT INTO "public"."Sys_Province" VALUES (2, '120000', '天津市', '华北'); +INSERT INTO "public"."Sys_Province" VALUES (3, '130000', '河北省', '华北'); +INSERT INTO "public"."Sys_Province" VALUES (4, '140000', '山西省', '华北'); +INSERT INTO "public"."Sys_Province" VALUES (5, '150000', '内蒙古自治区', '华北'); +INSERT INTO "public"."Sys_Province" VALUES (6, '210000', '辽宁省', '东北'); +INSERT INTO "public"."Sys_Province" VALUES (7, '220000', '吉林省', '东北'); +INSERT INTO "public"."Sys_Province" VALUES (8, '230000', '黑龙江省', '东北'); +INSERT INTO "public"."Sys_Province" VALUES (9, '310000', '上海市', '华东'); +INSERT INTO "public"."Sys_Province" VALUES (10, '320000', '江苏省', '华东'); +INSERT INTO "public"."Sys_Province" VALUES (11, '330000', '浙江省', '华东'); +INSERT INTO "public"."Sys_Province" VALUES (12, '340000', '安徽省', '华东'); +INSERT INTO "public"."Sys_Province" VALUES (13, '350000', '福建省', '华东'); +INSERT INTO "public"."Sys_Province" VALUES (14, '360000', '江西省', '华东'); +INSERT INTO "public"."Sys_Province" VALUES (15, '370000', '山东省', '华东'); +INSERT INTO "public"."Sys_Province" VALUES (16, '410000', '河南省', '华中'); +INSERT INTO "public"."Sys_Province" VALUES (17, '420000', '湖北省', '华中'); +INSERT INTO "public"."Sys_Province" VALUES (18, '430000', '湖南省', '华中'); +INSERT INTO "public"."Sys_Province" VALUES (19, '440000', '广东省', '华南'); +INSERT INTO "public"."Sys_Province" VALUES (20, '450000', '广西壮族自治区', '华南'); +INSERT INTO "public"."Sys_Province" VALUES (21, '460000', '海南省', '华南'); +INSERT INTO "public"."Sys_Province" VALUES (22, '500000', '重庆市', '西南'); +INSERT INTO "public"."Sys_Province" VALUES (23, '510000', '四川省', '西南'); +INSERT INTO "public"."Sys_Province" VALUES (24, '520000', '贵州省', '西南'); +INSERT INTO "public"."Sys_Province" VALUES (25, '530000', '云南省', '西南'); +INSERT INTO "public"."Sys_Province" VALUES (26, '540000', '西藏自治区', '西南'); +INSERT INTO "public"."Sys_Province" VALUES (27, '610000', '陕西省', '西北'); +INSERT INTO "public"."Sys_Province" VALUES (28, '620000', '甘肃省', '西北'); +INSERT INTO "public"."Sys_Province" VALUES (29, '630000', '青海省', '西北'); +INSERT INTO "public"."Sys_Province" VALUES (30, '640000', '宁夏回族自治区', '西北'); +INSERT INTO "public"."Sys_Province" VALUES (31, '650000', '新疆维吾尔自治区', '西北'); +INSERT INTO "public"."Sys_Province" VALUES (32, '710000', '台湾省', '港澳台'); +INSERT INTO "public"."Sys_Province" VALUES (33, '810000', '香港特别行政区', '港澳台'); +INSERT INTO "public"."Sys_Province" VALUES (34, '820000', '澳门特别行政区', '港澳台'); +INSERT INTO "public"."Sys_Province" VALUES (35, 'thd', '桃花岛', '东北'); +INSERT INTO "public"."Sys_Province" VALUES (43, '测试1', '测试1', '港澳台'); + +-- ---------------------------- +-- Table structure for Sys_Role +-- ---------------------------- +DROP TABLE IF EXISTS "public"."Sys_Role"; +CREATE TABLE "public"."Sys_Role" ( + "Role_Id" int4 NOT NULL DEFAULT nextval('sys_role_id_seq'::regclass), + "CreateDate" timestamp(6), + "Creator" varchar(50) COLLATE "pg_catalog"."default", + "DeleteBy" varchar(50) COLLATE "pg_catalog"."default", + "DeptName" varchar(50) COLLATE "pg_catalog"."default", + "Dept_Id" int4, + "Enable" int2, + "Modifier" varchar(50) COLLATE "pg_catalog"."default", + "ModifyDate" timestamp(6), + "OrderNo" int4, + "ParentId" int4 NOT NULL DEFAULT nextval('sys_role_id_seq1'::regclass), + "RoleName" varchar(50) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."Sys_Role"."Role_Id" IS 'id'; +COMMENT ON COLUMN "public"."Sys_Role"."CreateDate" IS '日期'; +COMMENT ON COLUMN "public"."Sys_Role"."Creator" IS '创建人'; + +-- ---------------------------- +-- Records of Sys_Role +-- ---------------------------- +INSERT INTO "public"."Sys_Role" VALUES (1, '2020-06-14 21:05:55', 'admin', NULL, NULL, NULL, 1, NULL, NULL, 1, 0, '超级管理员'); +INSERT INTO "public"."Sys_Role" VALUES (100, '2020-06-14 21:18:59', 'admin', NULL, NULL, NULL, 1, '', NULL, NULL, 1, '2'); +INSERT INTO "public"."Sys_Role" VALUES (101, '2020-06-14 21:22:18', 'admin', NULL, NULL, NULL, 1, 'admin', '2020-06-14 21:22:29', NULL, 100, '测试'); + +-- ---------------------------- +-- Table structure for Sys_RoleAuth +-- ---------------------------- +DROP TABLE IF EXISTS "public"."Sys_RoleAuth"; +CREATE TABLE "public"."Sys_RoleAuth" ( + "Auth_Id" int4 NOT NULL DEFAULT nextval('sys_roleauth_id_seq'::regclass), + "AuthValue" varchar(1000) COLLATE "pg_catalog"."default" NOT NULL, + "CreateDate" timestamp(6), + "Creator" varchar(1000) COLLATE "pg_catalog"."default", + "Menu_Id" int4 NOT NULL, + "Modifier" varchar(1000) COLLATE "pg_catalog"."default", + "ModifyDate" timestamp(6), + "Role_Id" int4, + "User_Id" int4 +) +; + +-- ---------------------------- +-- Records of Sys_RoleAuth +-- ---------------------------- +INSERT INTO "public"."Sys_RoleAuth" VALUES (151, 'Search', '2020-05-05 12:05:34', '超级管理员', 30, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (152, 'Search,Add,Delete,Update,Export', '2020-05-05 12:05:34', '超级管理员', 3, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (153, 'Search,Add,Delete,Update,Export,Audit', '2020-05-05 12:05:34', '超级管理员', 51, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (154, 'Search', '2020-05-05 12:05:34', '超级管理员', 59, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (155, 'Search,Add,Delete,Update,Import,Export,Upload,Audit', '2020-05-05 12:05:34', '超级管理员', 37, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (156, 'Search', '2020-05-05 12:05:34', '超级管理员', 33, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (157, 'Search', '2020-05-05 12:05:34', '超级管理员', 24, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (158, 'Search', '2020-05-05 12:05:34', '超级管理员', 35, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (159, 'Search', '2020-05-05 12:05:34', '超级管理员', 60, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (160, 'Search,Add,Update,Export,Audit', '2020-05-05 12:05:34', '超级管理员', 68, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (161, 'Search', '2020-05-05 12:05:34', '超级管理员', 77, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (162, 'Search,Add,Delete,Update,Import,Export', '2020-05-05 12:05:34', '超级管理员', 52, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (163, 'Search', '2020-05-05 12:05:34', '超级管理员', 11, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (164, 'Search,Add,Delete,Update', '2020-05-05 12:05:34', '超级管理员', 85, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (165, 'Search', '2020-05-05 12:05:34', '超级管理员', 79, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (166, 'Search', '2020-05-05 12:05:34', '超级管理员', 86, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (167, 'Search,Add,Delete,Update,Export,Upload', '2020-05-05 12:05:34', '超级管理员', 67, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (168, 'Search,Add,Delete,Update', '2020-05-05 12:05:34', '超级管理员', 65, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (169, 'Search,Add,Update', '2020-05-05 12:05:34', '超级管理员', 62, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (170, 'Search,Add,Delete,Update,Export', '2020-05-05 12:05:34', '超级管理员', 63, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (171, 'Search,Add,Delete,Update,Export', '2020-05-05 12:05:34', '超级管理员', 83, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (172, 'Search', '2020-05-05 12:05:34', '超级管理员', 80, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (173, 'Search', '2020-05-05 12:05:34', '超级管理员', 81, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (174, 'Search', '2020-05-05 12:05:34', '超级管理员', 82, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (175, 'Search,Add,Delete,Update,Export', '2020-05-05 12:05:34', '超级管理员', 42, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (176, 'Search', '2020-05-05 12:05:34', '超级管理员', 10, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (177, 'Search,Add,Delete,Update,Import,Export,Upload,Audit', '2020-05-05 12:05:34', '超级管理员', 78, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (178, 'Search,Delete,Export', '2020-05-05 12:05:34', '超级管理员', 6, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (179, 'Search,Add,Delete,Update', '2020-05-05 12:05:34', '超级管理员', 50, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (180, 'Search,Add,Delete,Update,Import,Export', '2020-05-05 12:05:34', '超级管理员', 36, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (181, 'Search,Add,Delete,Update,Import,Export,Upload,Audit', '2020-05-05 12:05:34', '超级管理员', 9, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (182, 'Search', '2020-05-05 12:05:34', '超级管理员', 48, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (183, 'Search', '2020-05-05 12:05:34', '超级管理员', 74, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (184, 'Search', '2020-05-05 12:05:34', '超级管理员', 56, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (185, 'Search', '2020-05-05 12:05:34', '超级管理员', 32, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (186, 'Search', '2020-05-05 12:05:34', '超级管理员', 34, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (187, 'Search', '2020-05-05 12:05:34', '超级管理员', 12, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (188, 'Search', '2020-05-05 12:05:34', '超级管理员', 84, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (189, 'Search', '2020-05-05 12:05:34', '超级管理员', 41, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (190, 'Search,Add,Delete,Update,Import,Export,Upload,Audit', '2020-05-05 12:05:34', '超级管理员', 28, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (191, 'Search', '2020-05-05 12:05:34', '超级管理员', 66, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (192, 'Search', '2020-05-05 12:05:34', '超级管理员', 29, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (193, 'Search', '2020-05-05 12:05:34', '超级管理员', 72, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (194, 'Search', '2020-05-05 12:05:34', '超级管理员', 2, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (195, 'Search', '2020-05-05 12:05:34', '超级管理员', 64, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (196, 'Search', '2020-05-05 12:05:34', '超级管理员', 61, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (197, 'Search', '2020-05-05 12:05:34', '超级管理员', 5, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (198, 'Search,Add,Delete,Update,Import,Export,Upload,Audit', '2020-05-05 12:05:34', '超级管理员', 25, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (199, 'Search', '2020-05-05 12:05:34', '超级管理员', 26, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (200, 'Search', '2020-05-05 12:05:34', '超级管理员', 27, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (201, 'Search,Add,Delete,Update,Import,Export,Upload,Audit', '2020-05-05 12:05:34', '超级管理员', 75, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (202, 'Search', '2020-05-05 12:05:34', '超级管理员', 57, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (203, 'Search,Import,Export,Upload', '2020-05-05 12:05:34', '超级管理员', 49, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (204, 'Search,Update', '2020-05-05 12:05:34', '超级管理员', 71, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (205, 'Search', '2020-05-05 12:05:34', '超级管理员', 31, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (206, 'Search', '2020-05-05 12:05:34', '超级管理员', 58, '超级管理员', '2020-05-05 12:05:34', 2, NULL); +INSERT INTO "public"."Sys_RoleAuth" VALUES (207, 'Search', '2020-05-05 12:05:34', '超级管理员', 73, '超级管理员', '2020-05-05 12:05:34', 2, NULL); + +-- ---------------------------- +-- Table structure for Sys_RoleAuthData +-- ---------------------------- +DROP TABLE IF EXISTS "public"."Sys_RoleAuthData"; +CREATE TABLE "public"."Sys_RoleAuthData" ( + "Auth_Id" int4 NOT NULL DEFAULT nextval('sys_roleauthdata_id_seq'::regclass), + "DataType_Id" int4, + "Role_Id" int4, + "User_Id" int4, + "Node_Id" varchar(50) COLLATE "pg_catalog"."default", + "LevelID" int4, + "AuthValue" varchar(4000) COLLATE "pg_catalog"."default", + "Creator" varchar(50) COLLATE "pg_catalog"."default", + "CreateDate" timestamp(6), + "Modifier" varchar(50) COLLATE "pg_catalog"."default", + "ModifyDate" timestamp(6) +) +; + +-- ---------------------------- +-- Records of Sys_RoleAuthData +-- ---------------------------- + +-- ---------------------------- +-- Table structure for Sys_TableColumn +-- ---------------------------- +DROP TABLE IF EXISTS "public"."Sys_TableColumn"; +CREATE TABLE "public"."Sys_TableColumn" ( + "ColumnId" int4 NOT NULL DEFAULT nextval('sys_tablecolumn_id_seq'::regclass), + "ApiInPut" int4, + "ApiIsNull" int4, + "ApiOutPut" int4, + "ColSize" int4, + "ColumnCnName" varchar(100) COLLATE "pg_catalog"."default", + "ColumnName" varchar(100) COLLATE "pg_catalog"."default", + "ColumnType" text COLLATE "pg_catalog"."default", + "ColumnWidth" int4, + "Columnformat" text COLLATE "pg_catalog"."default", + "CreateDate" timestamp(6), + "CreateID" int4, + "Creator" varchar(200) COLLATE "pg_catalog"."default", + "DropNo" varchar(50) COLLATE "pg_catalog"."default", + "EditColNo" int4, + "EditRowNo" int4, + "EditType" varchar(200) COLLATE "pg_catalog"."default", + "Enable" int4, + "IsColumnData" int4, + "IsDisplay" int4, + "IsImage" int4, + "IsKey" int4, + "IsNull" int4, + "IsReadDataset" int4, + "Maxlength" int4, + "Modifier" text COLLATE "pg_catalog"."default", + "ModifyDate" timestamp(6), + "ModifyID" int4, + "OrderNo" int4, + "Script" text COLLATE "pg_catalog"."default", + "SearchColNo" int4, + "SearchRowNo" int4, + "SearchType" varchar(200) COLLATE "pg_catalog"."default", + "Sortable" int4, + "TableName" varchar(200) COLLATE "pg_catalog"."default", + "Table_Id" int4 +) +; + +-- ---------------------------- +-- Records of Sys_TableColumn +-- ---------------------------- +INSERT INTO "public"."Sys_TableColumn" VALUES (20, NULL, NULL, NULL, NULL, '角色ID', 'Role_Id', 'int', 70, NULL, '2018-06-04 10:14:21', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 1, 0, 1, NULL, '超级管理员', '2019-08-15 10:49:04', 1, 1420, NULL, NULL, NULL, NULL, NULL, 'Sys_Role', 2); +INSERT INTO "public"."Sys_TableColumn" VALUES (21, NULL, NULL, NULL, NULL, '父级ID', 'ParentId', 'int', 70, NULL, '2018-06-04 10:14:21', NULL, NULL, NULL, NULL, 1, NULL, NULL, 1, 1, NULL, 0, 0, 0, NULL, '超级管理员', '2019-08-15 10:49:04', 1, 1410, NULL, NULL, NULL, NULL, NULL, 'Sys_Role', 2); +INSERT INTO "public"."Sys_TableColumn" VALUES (22, NULL, NULL, NULL, NULL, '角色名称', 'RoleName', 'string', 90, NULL, '2018-06-04 10:14:21', NULL, NULL, NULL, NULL, 1, NULL, NULL, 1, 1, NULL, 0, 1, 0, 50, '超级管理员', '2019-08-15 10:49:04', 1, 1400, NULL, NULL, 1, 'text', NULL, 'Sys_Role', 2); +INSERT INTO "public"."Sys_TableColumn" VALUES (23, NULL, NULL, NULL, NULL, '部门ID', 'Dept_Id', 'int', 90, NULL, '2018-06-04 10:14:21', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-08-15 10:49:04', 1, 1390, NULL, NULL, NULL, NULL, NULL, 'Sys_Role', 2); +INSERT INTO "public"."Sys_TableColumn" VALUES (24, NULL, NULL, NULL, NULL, '部门名称', 'DeptName', 'string', 90, NULL, '2018-06-04 10:14:21', NULL, NULL, NULL, NULL, 2, NULL, NULL, 1, 1, NULL, 0, 1, 0, 50, '超级管理员', '2019-08-15 10:49:04', 1, 1380, NULL, NULL, 1, 'text', NULL, 'Sys_Role', 2); +INSERT INTO "public"."Sys_TableColumn" VALUES (25, NULL, NULL, NULL, NULL, '排序', 'OrderNo', 'int', 90, NULL, '2018-06-04 10:14:21', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-08-15 10:49:04', 1, 1370, NULL, NULL, NULL, NULL, NULL, 'Sys_Role', 2); +INSERT INTO "public"."Sys_TableColumn" VALUES (26, NULL, NULL, NULL, NULL, '创建人', 'Creator', 'string', 130, NULL, '2018-06-04 10:14:21', NULL, NULL, NULL, NULL, 4, NULL, NULL, 1, 1, NULL, 0, 1, 1, 50, '超级管理员', '2019-08-15 10:49:04', 1, 1360, NULL, NULL, NULL, NULL, NULL, 'Sys_Role', 2); +INSERT INTO "public"."Sys_TableColumn" VALUES (27, NULL, NULL, NULL, NULL, '创建时间', 'CreateDate', 'DateTime', 90, NULL, '2018-06-04 10:14:21', NULL, NULL, NULL, NULL, 4, 'datetime', NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2019-08-15 10:49:04', 1, 1350, NULL, NULL, 2, 'datetime', NULL, 'Sys_Role', 2); +INSERT INTO "public"."Sys_TableColumn" VALUES (28, NULL, NULL, NULL, NULL, '修改人', 'Modifier', 'string', 130, NULL, '2018-06-04 10:14:21', NULL, NULL, NULL, NULL, 5, NULL, NULL, 1, 1, NULL, 0, 1, 1, 50, '超级管理员', '2019-08-15 10:49:04', 1, 1340, NULL, NULL, NULL, NULL, NULL, 'Sys_Role', 2); +INSERT INTO "public"."Sys_TableColumn" VALUES (29, NULL, NULL, NULL, NULL, '修改时间', 'ModifyDate', 'DateTime', 90, NULL, '2018-06-04 10:14:21', NULL, NULL, NULL, NULL, 5, NULL, NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2019-08-15 10:49:04', 1, 1330, NULL, NULL, 2, 'datetime', NULL, 'Sys_Role', 2); +INSERT INTO "public"."Sys_TableColumn" VALUES (30, NULL, NULL, NULL, NULL, NULL, 'DeleteBy', 'string', 90, NULL, '2018-06-04 10:14:21', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, NULL, 0, 1, 0, 50, '超级管理员', '2019-08-15 10:49:04', 1, 1320, NULL, NULL, NULL, NULL, NULL, 'Sys_Role', 2); +INSERT INTO "public"."Sys_TableColumn" VALUES (31, NULL, NULL, NULL, NULL, '是否启用', 'Enable', 'sbyte', 90, NULL, '2018-06-04 10:14:21', NULL, NULL, 'enable', NULL, 2, 'switch', NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2019-08-15 10:49:04', 1, 1375, NULL, NULL, 1, 'select', NULL, 'Sys_Role', 2); +INSERT INTO "public"."Sys_TableColumn" VALUES (32, NULL, NULL, NULL, NULL, '字典ID', 'Dic_ID', 'int', 90, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 1, 0, 1, NULL, '超级管理员', '2019-08-23 10:17:27', 1, 1300, NULL, NULL, NULL, NULL, NULL, 'Sys_Dictionary', 3); +INSERT INTO "public"."Sys_TableColumn" VALUES (33, NULL, NULL, NULL, NULL, '字典名称', 'DicName', 'string', 140, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, 1, NULL, NULL, 1, 1, NULL, 0, 0, 0, 100, '超级管理员', '2019-08-23 10:17:27', 1, 1290, NULL, NULL, 1, 'textarea', NULL, 'Sys_Dictionary', 3); +INSERT INTO "public"."Sys_TableColumn" VALUES (34, NULL, NULL, NULL, NULL, '父级ID', 'ParentId', 'int', 90, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, 1, NULL, NULL, 1, 1, NULL, 0, 0, 0, NULL, '超级管理员', '2019-08-23 10:17:27', 1, 1280, NULL, NULL, 1, NULL, NULL, 'Sys_Dictionary', 3); +INSERT INTO "public"."Sys_TableColumn" VALUES (35, NULL, NULL, NULL, NULL, '配置项', 'Config', 'string', 300, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, 4000, '超级管理员', '2019-08-23 10:17:27', 1, 1270, NULL, NULL, NULL, NULL, NULL, 'Sys_Dictionary', 3); +INSERT INTO "public"."Sys_TableColumn" VALUES (36, NULL, NULL, NULL, 8, 'sql语句', 'DbSql', 'string', 200, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, 6, 'textarea', NULL, 1, 1, NULL, 0, 1, 0, 4000, '超级管理员', '2019-08-23 10:17:27', 1, 1260, NULL, NULL, NULL, NULL, NULL, 'Sys_Dictionary', 3); +INSERT INTO "public"."Sys_TableColumn" VALUES (37, NULL, NULL, NULL, NULL, 'DBServer', 'DBServer', 'string', 90, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, 4000, '超级管理员', '2019-08-23 10:17:27', 1, 1250, NULL, NULL, NULL, NULL, NULL, 'Sys_Dictionary', 3); +INSERT INTO "public"."Sys_TableColumn" VALUES (38, NULL, NULL, NULL, NULL, '排序号', 'OrderNo', 'int', 90, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, 2, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2019-08-23 10:17:27', 1, 1240, NULL, NULL, NULL, NULL, NULL, 'Sys_Dictionary', 3); +INSERT INTO "public"."Sys_TableColumn" VALUES (39, NULL, NULL, NULL, NULL, '字典编号', 'DicNo', 'string', 90, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, 1, NULL, NULL, 1, 1, NULL, 0, 0, 0, 100, '超级管理员', '2019-08-23 10:17:27', 1, 1295, NULL, NULL, 1, NULL, NULL, 'Sys_Dictionary', 3); +INSERT INTO "public"."Sys_TableColumn" VALUES (40, NULL, NULL, NULL, NULL, '备注', 'Remark', 'string', 90, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, 6, 'textarea', NULL, 1, 1, NULL, 0, 1, 0, 2000, '超级管理员', '2019-08-23 10:17:27', 1, 1220, NULL, NULL, NULL, '无', NULL, 'Sys_Dictionary', 3); +INSERT INTO "public"."Sys_TableColumn" VALUES (41, NULL, NULL, NULL, NULL, '是否启用', 'Enable', 'byte', 90, NULL, '2018-06-06 14:05:43', NULL, NULL, 'enable', NULL, 2, 'select', NULL, 1, 1, NULL, 0, 0, 0, NULL, '超级管理员', '2019-08-23 10:17:27', 1, 1210, NULL, NULL, 2, 'drop', NULL, 'Sys_Dictionary', 3); +INSERT INTO "public"."Sys_TableColumn" VALUES (42, NULL, NULL, NULL, NULL, NULL, 'CreateID', 'int', 90, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-08-23 10:17:27', 1, 1200, NULL, NULL, NULL, NULL, NULL, 'Sys_Dictionary', 3); +INSERT INTO "public"."Sys_TableColumn" VALUES (43, NULL, NULL, NULL, NULL, '创建人', 'Creator', 'string', 130, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 1, 30, '超级管理员', '2019-08-23 10:17:27', 1, 1190, NULL, NULL, NULL, NULL, NULL, 'Sys_Dictionary', 3); +INSERT INTO "public"."Sys_TableColumn" VALUES (44, NULL, NULL, NULL, NULL, '创建时间', 'CreateDate', 'DateTime', 150, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, 2, 'datetime', NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2019-08-23 10:17:27', 1, 1180, NULL, NULL, 2, 'datetime', NULL, 'Sys_Dictionary', 3); +INSERT INTO "public"."Sys_TableColumn" VALUES (45, NULL, NULL, NULL, NULL, NULL, 'ModifyID', 'int', 90, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-08-23 10:17:27', 1, 1170, NULL, NULL, NULL, NULL, NULL, 'Sys_Dictionary', 3); +INSERT INTO "public"."Sys_TableColumn" VALUES (46, NULL, NULL, NULL, NULL, '修改人', 'Modifier', 'string', 130, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 1, 30, '超级管理员', '2019-08-23 10:17:27', 1, 1160, NULL, NULL, NULL, NULL, NULL, 'Sys_Dictionary', 3); +INSERT INTO "public"."Sys_TableColumn" VALUES (47, NULL, NULL, NULL, NULL, '修改时间', 'ModifyDate', 'DateTime', 150, NULL, '2018-06-06 14:05:43', NULL, NULL, NULL, NULL, NULL, 'datetime', NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2019-08-23 10:17:27', 1, 1150, NULL, NULL, 2, 'datetime', NULL, 'Sys_Dictionary', 3); +INSERT INTO "public"."Sys_TableColumn" VALUES (48, NULL, NULL, NULL, NULL, NULL, 'DicList_ID', 'int', 90, NULL, '2018-06-06 14:12:18', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 1, 0, 1, NULL, '超级管理员', '2019-08-20 10:08:56', 1, 1140, NULL, NULL, NULL, NULL, NULL, 'Sys_DictionaryList', 4); +INSERT INTO "public"."Sys_TableColumn" VALUES (49, NULL, NULL, NULL, NULL, '数据源ID', 'Dic_ID', 'int', 90, NULL, '2018-06-06 14:12:18', NULL, NULL, NULL, NULL, 0, NULL, NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2019-08-20 10:08:56', 1, 1130, NULL, NULL, NULL, NULL, NULL, 'Sys_DictionaryList', 4); +INSERT INTO "public"."Sys_TableColumn" VALUES (50, NULL, NULL, NULL, NULL, '数据源Value', 'DicValue', 'string', 90, NULL, '2018-06-06 14:12:18', NULL, NULL, NULL, NULL, 1, 'text', NULL, 1, 1, NULL, 0, 1, 0, 100, '超级管理员', '2019-08-20 10:08:56', 1, 1120, NULL, NULL, NULL, NULL, NULL, 'Sys_DictionaryList', 4); +INSERT INTO "public"."Sys_TableColumn" VALUES (51, NULL, NULL, NULL, NULL, '数据源Text', 'DicName', 'string', 90, NULL, '2018-06-06 14:12:18', NULL, NULL, NULL, NULL, 1, 'text', NULL, 1, 1, NULL, 0, 1, 0, 100, '超级管理员', '2019-08-20 10:08:56', 1, 1110, NULL, NULL, NULL, NULL, NULL, 'Sys_DictionaryList', 4); +INSERT INTO "public"."Sys_TableColumn" VALUES (52, NULL, NULL, NULL, NULL, '排序号', 'OrderNo', 'int', 90, NULL, '2018-06-06 14:12:18', NULL, NULL, NULL, NULL, 1, 'text', NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2019-08-20 10:08:56', 1, 1100, NULL, NULL, NULL, NULL, NULL, 'Sys_DictionaryList', 4); +INSERT INTO "public"."Sys_TableColumn" VALUES (53, NULL, NULL, NULL, NULL, '备注', 'Remark', 'string', 90, NULL, '2018-06-06 14:12:18', NULL, NULL, NULL, NULL, 1, 'text', NULL, 1, 1, NULL, 0, 1, 0, 2000, '超级管理员', '2019-08-20 10:08:56', 1, 1090, NULL, NULL, NULL, NULL, NULL, 'Sys_DictionaryList', 4); +INSERT INTO "public"."Sys_TableColumn" VALUES (54, NULL, NULL, NULL, NULL, '是否可用', 'Enable', 'sbyte', 90, NULL, '2018-06-06 14:12:18', NULL, NULL, 'enable', NULL, 1, 'switch', NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2019-08-20 10:08:56', 1, 1080, NULL, NULL, NULL, NULL, NULL, 'Sys_DictionaryList', 4); +INSERT INTO "public"."Sys_TableColumn" VALUES (55, NULL, NULL, NULL, NULL, NULL, 'CreateID', 'int', 90, NULL, '2018-06-06 14:12:18', NULL, NULL, NULL, NULL, NULL, '无', NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-08-20 10:08:56', 1, 1070, NULL, NULL, NULL, NULL, NULL, 'Sys_DictionaryList', 4); +INSERT INTO "public"."Sys_TableColumn" VALUES (56, NULL, NULL, NULL, NULL, '创建人', 'Creator', 'string', 130, NULL, '2018-06-06 14:12:18', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 1, 30, '超级管理员', '2019-08-20 10:08:56', 1, 1060, NULL, NULL, NULL, NULL, NULL, 'Sys_DictionaryList', 4); +INSERT INTO "public"."Sys_TableColumn" VALUES (57, NULL, NULL, NULL, NULL, '创建时间', 'CreateDate', 'DateTime', 90, NULL, '2018-06-06 14:12:18', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2019-08-20 10:08:56', 1, 1050, NULL, NULL, NULL, NULL, NULL, 'Sys_DictionaryList', 4); +INSERT INTO "public"."Sys_TableColumn" VALUES (58, NULL, NULL, NULL, NULL, NULL, 'ModifyID', 'int', 90, NULL, '2018-06-06 14:12:18', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-08-20 10:08:56', 1, 1040, NULL, NULL, NULL, NULL, NULL, 'Sys_DictionaryList', 4); +INSERT INTO "public"."Sys_TableColumn" VALUES (59, NULL, NULL, NULL, NULL, '修改人', 'Modifier', 'string', 130, NULL, '2018-06-06 14:12:18', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 30, '超级管理员', '2019-08-20 10:08:56', 1, 1030, NULL, NULL, NULL, NULL, NULL, 'Sys_DictionaryList', 4); +INSERT INTO "public"."Sys_TableColumn" VALUES (60, NULL, NULL, NULL, NULL, '修改时间', 'ModifyDate', 'DateTime', 90, NULL, '2018-06-06 14:12:18', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2019-08-20 10:08:56', 1, 1020, NULL, NULL, NULL, NULL, NULL, 'Sys_DictionaryList', 4); +INSERT INTO "public"."Sys_TableColumn" VALUES (61, NULL, NULL, NULL, NULL, NULL, 'Id', 'int', 90, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 1, 0, 1, NULL, '超级管理员', '2020-03-02 19:22:18', 1, 10000, NULL, NULL, NULL, NULL, NULL, 'Sys_Log', 5); +INSERT INTO "public"."Sys_TableColumn" VALUES (62, NULL, NULL, NULL, 12, '日志类型', 'LogType', 'string', 120, NULL, '2018-06-11 18:22:16', NULL, NULL, 'log', NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 50, '超级管理员', '2020-03-02 19:22:18', 1, 8888, NULL, NULL, 3, 'checkbox', NULL, 'Sys_Log', 5); +INSERT INTO "public"."Sys_TableColumn" VALUES (63, NULL, NULL, NULL, NULL, '请求参数', 'RequestParameter', 'string', 300, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 0, '超级管理员', '2020-03-02 19:22:18', 1, 7990, NULL, NULL, NULL, NULL, NULL, 'Sys_Log', 5); +INSERT INTO "public"."Sys_TableColumn" VALUES (64, NULL, NULL, NULL, NULL, '响应参数', 'ResponseParameter', 'string', 250, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 0, '超级管理员', '2020-03-02 19:22:18', 1, 7980, NULL, NULL, NULL, NULL, NULL, 'Sys_Log', 5); +INSERT INTO "public"."Sys_TableColumn" VALUES (65, NULL, NULL, NULL, NULL, '异常信息', 'ExceptionInfo', 'string', 280, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 0, '超级管理员', '2020-03-02 19:22:18', 1, 7970, NULL, NULL, NULL, NULL, NULL, 'Sys_Log', 5); +INSERT INTO "public"."Sys_TableColumn" VALUES (66, NULL, NULL, NULL, NULL, '响应状态', 'Success', 'int', 90, NULL, '2018-06-11 18:22:16', NULL, NULL, 'restatus', NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2020-03-02 19:22:18', 1, 8700, NULL, NULL, 2, 'dropList', NULL, 'Sys_Log', 5); +INSERT INTO "public"."Sys_TableColumn" VALUES (67, NULL, NULL, NULL, NULL, '开始时间', 'BeginDate', 'DateTime', 150, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2020-03-02 19:22:18', 1, 9999, NULL, NULL, 2, 'datetime', NULL, 'Sys_Log', 5); +INSERT INTO "public"."Sys_TableColumn" VALUES (68, NULL, NULL, NULL, NULL, '结束时间', 'EndDate', 'DateTime', 150, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2020-03-02 19:22:18', 1, 880, NULL, NULL, NULL, NULL, NULL, 'Sys_Log', 5); +INSERT INTO "public"."Sys_TableColumn" VALUES (69, NULL, NULL, NULL, NULL, '时长(毫秒)', 'ElapsedTime', 'int', 90, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2020-03-02 19:22:18', 1, 8600, NULL, NULL, NULL, NULL, NULL, 'Sys_Log', 5); +INSERT INTO "public"."Sys_TableColumn" VALUES (70, NULL, NULL, NULL, NULL, '用户IP', 'UserIP', 'string', 90, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 100, '超级管理员', '2020-03-02 19:22:18', 1, 7920, NULL, NULL, 1, 'text', NULL, 'Sys_Log', 5); +INSERT INTO "public"."Sys_TableColumn" VALUES (71, NULL, NULL, NULL, NULL, '服务器IP', 'ServiceIP', 'string', 90, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 100, '超级管理员', '2020-03-02 19:22:18', 1, 7910, NULL, NULL, 1, 'text', NULL, 'Sys_Log', 5); +INSERT INTO "public"."Sys_TableColumn" VALUES (72, NULL, NULL, NULL, NULL, '浏览器类型', 'BrowserType', 'string', 90, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 200, '超级管理员', '2020-03-02 19:22:18', 1, 7900, NULL, NULL, NULL, NULL, NULL, 'Sys_Log', 5); +INSERT INTO "public"."Sys_TableColumn" VALUES (73, NULL, NULL, NULL, NULL, '请求地址', 'Url', 'string', 300, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 4000, '超级管理员', '2020-03-02 19:22:18', 1, 9000, NULL, NULL, 1, 'text', NULL, 'Sys_Log', 5); +INSERT INTO "public"."Sys_TableColumn" VALUES (74, NULL, NULL, NULL, NULL, '用户ID', 'User_Id', 'int', 90, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2020-03-02 19:22:18', 1, 7880, NULL, NULL, NULL, '无', NULL, 'Sys_Log', 5); +INSERT INTO "public"."Sys_TableColumn" VALUES (75, NULL, NULL, NULL, NULL, '用户名称', 'UserName', 'string', 90, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 4000, '超级管理员', '2020-03-02 19:22:18', 1, 7870, NULL, NULL, NULL, NULL, NULL, 'Sys_Log', 5); +INSERT INTO "public"."Sys_TableColumn" VALUES (76, NULL, NULL, NULL, NULL, '角色ID', 'Role_Id', 'int', 90, NULL, '2018-06-11 18:22:16', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2020-03-02 19:22:18', 1, 7860, NULL, NULL, 2, 'text', NULL, 'Sys_Log', 5); +INSERT INTO "public"."Sys_TableColumn" VALUES (77, NULL, NULL, NULL, NULL, NULL, 'User_Id', 'int', 90, NULL, '2018-06-14 16:44:15', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 1, 0, 1, NULL, '超级管理员', '2019-12-08 22:22:13', 1, 7850, NULL, NULL, NULL, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (78, NULL, NULL, NULL, NULL, NULL, 'Dept_Id', 'int', 90, NULL, '2018-06-14 16:44:15', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-12-08 22:22:13', 1, 7840, NULL, NULL, NULL, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (79, 0, NULL, 1, NULL, '部门', 'DeptName', 'string', 150, NULL, '2018-06-14 16:44:15', NULL, NULL, NULL, NULL, 0, 'text', NULL, 1, 0, NULL, 0, 1, 0, 150, '超级管理员', '2019-12-08 22:22:13', 1, 7830, NULL, NULL, 2, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (80, 0, 0, 1, NULL, '角色', 'Role_Id', 'int', 150, NULL, '2018-06-14 16:44:15', NULL, NULL, 'roles', NULL, 2, 'drop', NULL, 1, 1, NULL, 0, 0, 0, NULL, '超级管理员', '2019-12-08 22:22:13', 1, 7820, NULL, NULL, 2, 'drop', NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (81, NULL, NULL, NULL, NULL, NULL, 'RoleName', 'string', 90, NULL, '2018-06-14 16:44:15', NULL, NULL, NULL, NULL, 0, NULL, NULL, 1, 0, NULL, 0, 0, 0, 150, '超级管理员', '2019-12-08 22:22:13', 1, 7810, NULL, NULL, NULL, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (82, 1, 0, 1, NULL, '用户名', 'UserName', 'string', 120, NULL, '2018-06-14 16:44:15', NULL, NULL, NULL, NULL, 1, NULL, NULL, 1, 1, NULL, 0, 0, 1, 100, '超级管理员', '2019-12-08 22:22:13', 1, 7945, NULL, NULL, 1, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (83, 1, 0, NULL, NULL, '密码', 'UserPwd', 'string', 90, NULL, '2018-06-14 16:44:15', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, NULL, 0, 1, 0, 200, '超级管理员', '2019-12-08 22:22:13', 1, 7790, NULL, NULL, NULL, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (84, NULL, NULL, NULL, NULL, '用户真实姓名', 'UserTrueName', 'string', 150, NULL, '2018-06-14 16:44:15', NULL, NULL, NULL, NULL, 1, 'text', NULL, 1, 1, NULL, 0, 0, 0, 20, '超级管理员', '2019-12-08 22:22:13', 1, 7792, NULL, NULL, 1, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (85, NULL, NULL, NULL, NULL, '地址', 'Address', 'string', 190, NULL, '2018-06-14 16:44:15', NULL, NULL, NULL, NULL, 3, 'text', NULL, 1, 1, NULL, 0, 1, 0, 200, '超级管理员', '2019-12-08 22:22:13', 1, 7270, NULL, NULL, 4, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (86, NULL, NULL, NULL, NULL, '电话', 'Mobile', 'string', 140, NULL, '2018-06-14 16:44:15', NULL, NULL, NULL, NULL, 3, 'text', NULL, 1, 1, NULL, 0, 1, 0, 100, '超级管理员', '2019-12-08 22:22:13', 1, 7260, NULL, NULL, NULL, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (87, NULL, NULL, NULL, NULL, 'Email', 'Email', 'string', 140, NULL, '2018-06-14 16:44:15', NULL, NULL, NULL, NULL, 5, 'text', NULL, 1, 1, NULL, 0, 1, 0, 100, '超级管理员', '2019-12-08 22:22:13', 1, 7250, NULL, NULL, 4, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (88, NULL, NULL, NULL, NULL, NULL, 'Tel', 'string', 90, NULL, '2018-06-14 16:44:15', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, 20, '超级管理员', '2019-12-08 22:22:13', 1, 7740, NULL, NULL, NULL, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (89, NULL, NULL, NULL, 12, '备注', 'Remark', 'string', 180, NULL, '2018-06-14 16:44:15', NULL, NULL, NULL, NULL, 7, 'textarea', NULL, 1, 1, NULL, 0, 1, 0, 200, '超级管理员', '2019-12-08 22:22:13', 1, 7230, NULL, NULL, NULL, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (90, NULL, NULL, NULL, NULL, '排序号', 'OrderNo', 'int', 90, NULL, '2018-06-14 16:44:15', NULL, NULL, NULL, NULL, 0, 'text', NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2019-12-08 22:22:13', 1, 7220, NULL, NULL, NULL, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (91, NULL, NULL, NULL, NULL, '是否可用', 'Enable', 'sbyte', 90, NULL, '2018-06-14 16:44:15', NULL, NULL, 'enable', NULL, 5, 'drop', NULL, 1, 1, NULL, 0, 0, 0, NULL, '超级管理员', '2019-12-08 22:22:13', 1, 7670, NULL, NULL, 4, 'drop', NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (92, NULL, NULL, NULL, NULL, NULL, 'CreateID', 'int', 90, NULL, '2018-06-14 16:44:15', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-12-08 22:22:13', 1, 7700, NULL, NULL, NULL, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (93, NULL, NULL, NULL, NULL, '创建人', 'Creator', 'string', 130, NULL, '2018-06-14 16:44:15', NULL, NULL, NULL, NULL, 6, NULL, NULL, 1, 1, NULL, 0, 1, 1, 200, '超级管理员', '2019-12-08 22:22:13', 1, 7690, NULL, NULL, NULL, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (94, NULL, NULL, NULL, NULL, '注册时间', 'CreateDate', 'DateTime', 150, NULL, '2018-06-14 16:44:15', NULL, NULL, NULL, NULL, 6, NULL, NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2019-12-08 22:22:13', 1, 7780, NULL, NULL, 5, 'datetime', NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (95, NULL, NULL, NULL, NULL, NULL, 'ModifyID', 'int', 90, NULL, '2018-06-14 16:44:15', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-12-08 22:22:13', 1, 7670, NULL, NULL, NULL, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (96, NULL, NULL, NULL, NULL, '修改人', 'Modifier', 'string', 130, NULL, '2018-06-14 16:44:15', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 1, 200, '超级管理员', '2019-12-08 22:22:13', 1, 7660, NULL, NULL, NULL, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (97, NULL, NULL, NULL, NULL, '修改时间', 'ModifyDate', 'DateTime', 90, NULL, '2018-06-14 16:44:15', NULL, NULL, NULL, NULL, NULL, 'datetime', NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2019-12-08 22:22:13', 1, 7650, NULL, NULL, NULL, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (98, NULL, NULL, NULL, NULL, '审核状态', 'AuditStatus', 'int', 90, NULL, '2018-06-14 16:44:15', NULL, NULL, 'audit', NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2019-12-08 22:22:13', 1, 7640, NULL, NULL, NULL, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (99, NULL, NULL, NULL, NULL, '审核人', 'Auditor', 'string', 90, NULL, '2018-06-14 16:44:15', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 200, '超级管理员', '2019-12-08 22:22:13', 1, 7630, NULL, NULL, NULL, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (100, NULL, NULL, NULL, NULL, '审核时间', 'AuditDate', 'DateTime', 150, NULL, '2018-06-14 16:44:15', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2019-12-08 22:22:13', 1, 7620, NULL, NULL, NULL, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (101, NULL, NULL, NULL, NULL, '最后登陆时间', 'LastLoginDate', 'DateTime', 150, NULL, '2018-06-14 16:44:15', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2019-12-08 22:22:13', 1, 7610, NULL, NULL, 5, 'datetime', NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (102, NULL, NULL, NULL, NULL, '最后密码修改时间', 'LastModifyPwdDate', 'DateTime', 150, NULL, '2018-06-14 16:44:15', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2019-12-08 22:22:13', 1, 7600, NULL, NULL, NULL, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (114, NULL, NULL, NULL, NULL, '头像', 'HeadImageUrl', 'string', 150, NULL, NULL, NULL, NULL, NULL, NULL, 9, 'img', NULL, 1, 1, 1, NULL, 1, 0, 200, '超级管理员', '2019-12-08 22:22:13', 1, 7842, NULL, NULL, NULL, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (142, NULL, NULL, NULL, NULL, '主键ID', 'Id', 'int', 90, NULL, '2018-07-10 13:57:15', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 1, 0, 1, NULL, '超级管理员', '2020-05-03 01:07:54', 1, 8570, NULL, NULL, NULL, NULL, NULL, 'App_TransactionAvgPrice', 15); +INSERT INTO "public"."Sys_TableColumn" VALUES (143, NULL, NULL, NULL, 12, '品种', 'Variety', 'string', 90, NULL, '2018-07-10 13:57:15', NULL, NULL, 'pz', NULL, 1, 'checkbox', NULL, 1, 1, NULL, 0, 0, 0, 20, '超级管理员', '2020-05-03 01:07:54', 1, 8560, NULL, NULL, 1, 'select', NULL, 'App_TransactionAvgPrice', 15); +INSERT INTO "public"."Sys_TableColumn" VALUES (144, NULL, NULL, NULL, 12, '月龄', 'AgeRange', 'string', 90, NULL, '2018-07-10 13:57:15', NULL, NULL, 'age', NULL, 10, 'select', NULL, 1, 1, NULL, 0, 0, 0, 50, '超级管理员', '2020-05-03 01:07:54', 1, 8550, NULL, NULL, 1, 'select', NULL, 'App_TransactionAvgPrice', 15); +INSERT INTO "public"."Sys_TableColumn" VALUES (145, NULL, NULL, NULL, 12, '城市', 'City', 'string', 90, NULL, '2018-07-10 13:57:15', NULL, NULL, 'city', NULL, 15, 'select', NULL, 1, 1, NULL, 0, 0, 0, 15, '超级管理员', '2020-05-03 01:07:54', 1, 8540, NULL, NULL, 1, 'select', NULL, 'App_TransactionAvgPrice', 15); +INSERT INTO "public"."Sys_TableColumn" VALUES (146, NULL, NULL, NULL, 12, '成交均价', 'AvgPrice', 'decimal', 80, NULL, '2018-07-10 13:57:15', NULL, NULL, NULL, NULL, 20, NULL, NULL, 1, 1, NULL, 0, 0, 0, NULL, '超级管理员', '2020-05-03 01:07:54', 1, 8530, NULL, NULL, NULL, NULL, NULL, 'App_TransactionAvgPrice', 15); +INSERT INTO "public"."Sys_TableColumn" VALUES (147, NULL, NULL, NULL, 12, '成交日期', 'Date', 'DateTime', 90, NULL, '2018-07-10 13:57:15', NULL, NULL, NULL, NULL, 25, 'date', NULL, 1, 1, NULL, 0, 0, 0, NULL, '超级管理员', '2020-05-03 01:07:54', 1, 8520, NULL, NULL, 2, 'datetime', NULL, 'App_TransactionAvgPrice', 15); +INSERT INTO "public"."Sys_TableColumn" VALUES (148, NULL, NULL, NULL, NULL, '是否启用', 'Enable', 'sbyte', 90, NULL, '2018-07-10 13:57:15', NULL, NULL, 'enable', NULL, NULL, 'select', NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2020-05-03 01:07:54', 1, 8510, NULL, NULL, 2, 'select', NULL, 'App_TransactionAvgPrice', 15); +INSERT INTO "public"."Sys_TableColumn" VALUES (149, NULL, NULL, NULL, NULL, '创建人Id', 'CreateID', 'int', 90, NULL, '2018-07-10 13:57:15', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2020-05-03 01:07:54', 1, 8500, NULL, NULL, NULL, NULL, NULL, 'App_TransactionAvgPrice', 15); +INSERT INTO "public"."Sys_TableColumn" VALUES (150, NULL, NULL, NULL, NULL, '创建人', 'Creator', 'string', 130, NULL, '2018-07-10 13:57:15', NULL, NULL, NULL, NULL, 40, NULL, NULL, 1, 1, NULL, 0, 1, 1, 30, '超级管理员', '2020-05-03 01:07:54', 1, 8490, NULL, NULL, NULL, NULL, NULL, 'App_TransactionAvgPrice', 15); +INSERT INTO "public"."Sys_TableColumn" VALUES (151, NULL, NULL, NULL, NULL, '创建时间', 'CreateDate', 'DateTime', 90, NULL, '2018-07-10 13:57:15', NULL, NULL, NULL, NULL, 40, NULL, NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2020-05-03 01:07:54', 1, 8480, NULL, NULL, NULL, 'datetime', NULL, 'App_TransactionAvgPrice', 15); +INSERT INTO "public"."Sys_TableColumn" VALUES (152, NULL, NULL, NULL, NULL, '修改人ID', 'ModifyID', 'int', 90, NULL, '2018-07-10 13:57:15', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2020-05-03 01:07:54', 1, 8470, NULL, NULL, NULL, NULL, NULL, 'App_TransactionAvgPrice', 15); +INSERT INTO "public"."Sys_TableColumn" VALUES (153, NULL, NULL, NULL, NULL, '修改人', 'Modifier', 'string', 130, NULL, '2018-07-10 13:57:15', NULL, NULL, NULL, NULL, 50, NULL, NULL, 1, 1, NULL, 0, 1, 1, 30, '超级管理员', '2020-05-03 01:07:54', 1, 8460, NULL, NULL, NULL, NULL, NULL, 'App_TransactionAvgPrice', 15); +INSERT INTO "public"."Sys_TableColumn" VALUES (154, NULL, NULL, NULL, NULL, '修改时间', 'ModifyDate', 'DateTime', 90, NULL, '2018-07-10 13:57:15', NULL, NULL, NULL, NULL, 50, NULL, NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2020-05-03 01:07:54', 1, 8450, NULL, NULL, NULL, NULL, NULL, 'App_TransactionAvgPrice', 15); +INSERT INTO "public"."Sys_TableColumn" VALUES (155, NULL, NULL, NULL, NULL, '主键ID', 'Id', 'int', 90, NULL, '2018-07-10 15:02:46', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 1, 0, 1, NULL, '超级管理员', '2019-09-18 18:36:03', 1, 8440, NULL, NULL, NULL, NULL, NULL, 'App_ReportPrice', 16); +INSERT INTO "public"."Sys_TableColumn" VALUES (156, NULL, NULL, NULL, NULL, '品种', 'Variety', 'string', 90, NULL, '2018-07-10 15:02:46', NULL, NULL, 'pz', NULL, 1, 'select', NULL, 1, 1, NULL, 0, 0, 0, 20, '超级管理员', '2019-09-18 18:36:03', 1, 8430, NULL, NULL, 1, 'drop', NULL, 'App_ReportPrice', 16); +INSERT INTO "public"."Sys_TableColumn" VALUES (157, NULL, NULL, NULL, NULL, '月龄', 'Age', 'string', 100, NULL, '2018-07-10 15:02:46', NULL, NULL, 'age', NULL, 1, 'select', NULL, 1, 1, NULL, 0, 0, 0, 50, '超级管理员', '2019-09-18 18:36:03', 1, 8420, NULL, NULL, 1, 'drop', NULL, 'App_ReportPrice', 16); +INSERT INTO "public"."Sys_TableColumn" VALUES (158, NULL, NULL, NULL, NULL, '报价城市', 'City', 'string', 120, NULL, '2018-07-10 15:02:46', NULL, NULL, 'city', NULL, 1, 'select', NULL, 1, 1, NULL, 0, 0, 0, 15, '超级管理员', '2019-09-18 18:36:03', 1, 8410, NULL, NULL, 1, 'dropList', NULL, 'App_ReportPrice', 16); +INSERT INTO "public"."Sys_TableColumn" VALUES (159, NULL, NULL, NULL, NULL, '上报价格', 'Price', 'decimal', 90, NULL, '2018-07-10 15:02:46', NULL, NULL, NULL, NULL, 2, NULL, NULL, 1, 1, NULL, 0, 0, 0, NULL, '超级管理员', '2019-09-18 18:36:03', 1, 8400, NULL, NULL, NULL, NULL, NULL, 'App_ReportPrice', 16); +INSERT INTO "public"."Sys_TableColumn" VALUES (160, 0, NULL, NULL, NULL, '审核状态', 'AuditStatus', 'int', 90, NULL, '2018-07-10 15:02:46', NULL, NULL, 'audit', NULL, NULL, 'select', NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2019-09-18 18:36:03', 1, 8382, NULL, NULL, 2, 'select', NULL, 'App_ReportPrice', 16); +INSERT INTO "public"."Sys_TableColumn" VALUES (161, NULL, NULL, NULL, NULL, '审核人Id', 'AuditId', 'int', 90, NULL, '2018-07-10 15:02:46', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-09-18 18:36:03', 1, 8380, NULL, NULL, NULL, NULL, NULL, 'App_ReportPrice', 16); +INSERT INTO "public"."Sys_TableColumn" VALUES (162, NULL, NULL, NULL, NULL, '审核人', 'Auditor', 'string', 90, NULL, '2018-07-10 15:02:46', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 20, '超级管理员', '2019-09-18 18:36:03', 1, 8370, NULL, NULL, NULL, NULL, NULL, 'App_ReportPrice', 16); +INSERT INTO "public"."Sys_TableColumn" VALUES (163, NULL, NULL, NULL, NULL, '是否启用', 'Enable', 'sbyte', 90, NULL, '2018-07-10 15:02:46', NULL, NULL, 'enable', NULL, 2, 'switch', NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2019-09-18 18:36:03', 1, 8360, NULL, NULL, NULL, NULL, NULL, 'App_ReportPrice', 16); +INSERT INTO "public"."Sys_TableColumn" VALUES (164, NULL, NULL, NULL, NULL, '创建人Id', 'CreateID', 'int', 90, NULL, '2018-07-10 15:02:46', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-09-18 18:36:03', 1, 8350, NULL, NULL, NULL, NULL, NULL, 'App_ReportPrice', 16); +INSERT INTO "public"."Sys_TableColumn" VALUES (165, NULL, NULL, NULL, NULL, '上报人', 'Creator', 'string', 100, NULL, '2018-07-10 15:02:46', NULL, NULL, NULL, NULL, 2, NULL, NULL, 1, 1, NULL, 0, 1, 1, 30, '超级管理员', '2019-09-18 18:36:03', 1, 8388, NULL, NULL, NULL, NULL, NULL, 'App_ReportPrice', 16); +INSERT INTO "public"."Sys_TableColumn" VALUES (166, NULL, 0, NULL, NULL, '上报时间', 'CreateDate', 'DateTime', 150, NULL, '2018-07-10 15:02:46', NULL, NULL, NULL, NULL, 5, 'datetime', NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2019-09-18 18:36:03', 1, 8387, NULL, NULL, 2, 'datetime', NULL, 'App_ReportPrice', 16); +INSERT INTO "public"."Sys_TableColumn" VALUES (167, NULL, NULL, NULL, NULL, '修改人ID', 'ModifyID', 'int', 90, NULL, '2018-07-10 15:02:46', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-09-18 18:36:03', 1, 8320, NULL, NULL, NULL, NULL, NULL, 'App_ReportPrice', 16); +INSERT INTO "public"."Sys_TableColumn" VALUES (168, NULL, NULL, NULL, 12, '测试', 'Modifier', 'string', 100, NULL, '2018-07-10 15:02:46', NULL, NULL, NULL, NULL, 8, NULL, NULL, 1, 1, NULL, 0, 1, 0, 30, '超级管理员', '2019-09-18 18:36:03', 1, 8310, NULL, NULL, NULL, NULL, NULL, 'App_ReportPrice', 16); +INSERT INTO "public"."Sys_TableColumn" VALUES (169, NULL, NULL, NULL, NULL, '修改时间', 'ModifyDate', 'DateTime', 90, NULL, '2018-07-10 15:02:46', NULL, NULL, NULL, NULL, 5, '无', NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2019-09-18 18:36:03', 1, 8300, NULL, NULL, NULL, NULL, NULL, 'App_ReportPrice', 16); +INSERT INTO "public"."Sys_TableColumn" VALUES (170, NULL, NULL, NULL, NULL, '审核时间', 'AuditDate', 'DateTime', 110, NULL, NULL, NULL, NULL, NULL, NULL, 5, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, '超级管理员', '2019-09-18 18:36:03', 1, 8381, NULL, NULL, NULL, NULL, NULL, 'App_ReportPrice', 16); +INSERT INTO "public"."Sys_TableColumn" VALUES (193, NULL, NULL, NULL, NULL, '主键ID', 'Id', 'int', 90, NULL, '2018-07-10 15:12:25', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 1, 0, 1, NULL, '超级管理员', '2019-09-18 17:40:42', 1, 8060, NULL, NULL, NULL, NULL, NULL, 'App_Transaction', 19); +INSERT INTO "public"."Sys_TableColumn" VALUES (194, NULL, NULL, NULL, NULL, '姓名', 'Name', 'string', 120, NULL, '2018-07-10 15:12:25', NULL, NULL, NULL, NULL, 1, NULL, NULL, 1, 1, NULL, 0, 0, 0, 50, '超级管理员', '2019-09-18 17:40:42', 1, 8050, NULL, NULL, 1, 'text', NULL, 'App_Transaction', 19); +INSERT INTO "public"."Sys_TableColumn" VALUES (195, NULL, NULL, NULL, NULL, '电话', 'PhoneNo', 'string', 150, NULL, '2018-07-10 15:12:25', NULL, NULL, NULL, NULL, 1, NULL, NULL, 1, 1, NULL, 0, 0, 0, 15, '超级管理员', '2019-09-18 17:40:42', 1, 8040, NULL, NULL, 1, 'text', NULL, 'App_Transaction', 19); +INSERT INTO "public"."Sys_TableColumn" VALUES (196, NULL, NULL, NULL, NULL, '数量', 'Quantity', 'int', 90, NULL, '2018-07-10 15:12:25', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 0, 0, NULL, '超级管理员', '2019-09-18 17:40:42', 1, 8030, NULL, NULL, NULL, NULL, NULL, 'App_Transaction', 19); +INSERT INTO "public"."Sys_TableColumn" VALUES (197, NULL, NULL, NULL, NULL, '购买类型', 'CowType', 'string', 90, NULL, '2018-07-10 15:12:25', NULL, NULL, 'nav', NULL, 2, 'select', NULL, 1, 1, NULL, 0, 1, 0, 100, '超级管理员', '2019-09-18 17:40:42', 1, 8020, NULL, NULL, 2, 'dropList', NULL, 'App_Transaction', 19); +INSERT INTO "public"."Sys_TableColumn" VALUES (198, NULL, NULL, NULL, NULL, '描述', 'Describe', 'string', 190, NULL, '2018-07-10 15:12:25', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 0, 0, 500, '超级管理员', '2019-09-18 17:40:42', 1, 8010, NULL, NULL, NULL, NULL, NULL, 'App_Transaction', 19); +INSERT INTO "public"."Sys_TableColumn" VALUES (199, NULL, NULL, NULL, NULL, '是否启用', 'Enable', 'sbyte', 90, NULL, '2018-07-10 15:12:25', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-09-18 17:40:42', 1, 8000, NULL, NULL, NULL, NULL, NULL, 'App_Transaction', 19); +INSERT INTO "public"."Sys_TableColumn" VALUES (200, NULL, NULL, NULL, NULL, '创建人Id', 'CreateID', 'int', 90, NULL, '2018-07-10 15:12:25', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-09-18 17:40:42', 1, 7990, NULL, NULL, NULL, NULL, NULL, 'App_Transaction', 19); +INSERT INTO "public"."Sys_TableColumn" VALUES (201, NULL, NULL, NULL, NULL, '提交人', 'Creator', 'string', 130, NULL, '2018-07-10 15:12:25', NULL, NULL, NULL, NULL, 3, NULL, NULL, 1, 1, NULL, 0, 1, 0, 30, '超级管理员', '2019-09-18 17:40:42', 1, 7980, NULL, NULL, 2, NULL, NULL, 'App_Transaction', 19); +INSERT INTO "public"."Sys_TableColumn" VALUES (202, NULL, NULL, NULL, NULL, '提交时间', 'CreateDate', 'DateTime', 150, NULL, '2018-07-10 15:12:25', NULL, NULL, NULL, NULL, 3, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2019-09-18 17:40:42', 1, 7970, NULL, NULL, 2, 'datetime', NULL, 'App_Transaction', 19); +INSERT INTO "public"."Sys_TableColumn" VALUES (203, NULL, NULL, NULL, NULL, '修改人ID', 'ModifyID', 'int', 90, NULL, '2018-07-10 15:12:25', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-09-18 17:40:42', 1, 7960, NULL, NULL, NULL, NULL, NULL, 'App_Transaction', 19); +INSERT INTO "public"."Sys_TableColumn" VALUES (204, NULL, NULL, NULL, NULL, '修改人', 'Modifier', 'string', 130, NULL, '2018-07-10 15:12:25', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, 30, '超级管理员', '2019-09-18 17:40:42', 1, 7950, NULL, NULL, NULL, NULL, NULL, 'App_Transaction', 19); +INSERT INTO "public"."Sys_TableColumn" VALUES (205, NULL, NULL, NULL, NULL, '修改时间', 'ModifyDate', 'DateTime', 150, NULL, '2018-07-10 15:12:25', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-09-18 17:40:42', 1, 7940, NULL, NULL, NULL, NULL, NULL, 'App_Transaction', 19); +INSERT INTO "public"."Sys_TableColumn" VALUES (206, 1, 1, 0, NULL, '主键ID', 'ExpertId', 'int', 80, NULL, '2018-07-10 15:29:01', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 1, 0, 1, NULL, '超级管理员', '2019-09-18 16:46:51', 1, 7930, NULL, NULL, NULL, NULL, NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (207, NULL, NULL, NULL, NULL, '专家名称', 'ExpertName', 'string', 150, NULL, '2018-07-10 15:29:01', NULL, NULL, NULL, NULL, 1, NULL, NULL, 1, 1, NULL, 0, 1, 0, 20, '超级管理员', '2019-09-18 16:46:51', 1, 7920, NULL, NULL, 1, NULL, NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (208, NULL, NULL, NULL, NULL, '真实姓名', 'ReallyName', 'string', 150, NULL, '2018-07-10 15:29:01', NULL, NULL, NULL, NULL, 1, NULL, NULL, 1, 1, NULL, 0, 1, 0, 20, '超级管理员', '2019-09-18 16:46:51', 1, 7910, NULL, NULL, 1, NULL, NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (209, NULL, NULL, NULL, NULL, '身份证号', 'IDNumber', 'string', 200, NULL, '2018-07-10 15:29:01', NULL, NULL, NULL, NULL, 2, NULL, NULL, 1, 1, NULL, 0, 1, 0, 18, '超级管理员', '2019-09-18 16:46:51', 1, 7900, NULL, NULL, 1, NULL, NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (210, NULL, NULL, NULL, NULL, '专家头像', 'HeadImageUrl', 'string', 220, NULL, '2018-07-10 15:29:01', NULL, NULL, NULL, NULL, 10, NULL, NULL, 1, 1, 1, 0, 1, 0, 500, '超级管理员', '2019-09-18 16:46:51', 1, 7920, NULL, NULL, NULL, NULL, NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (211, NULL, NULL, NULL, NULL, '学历', 'Education', 'string', 120, NULL, '2018-07-10 15:29:01', NULL, NULL, NULL, NULL, 2, NULL, NULL, 1, 1, NULL, 0, 1, 0, 50, '超级管理员', '2019-09-18 16:46:51', 1, 7880, NULL, NULL, 2, 'text', NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (212, NULL, NULL, NULL, NULL, '职业', 'Professional', 'string', 120, NULL, '2018-07-10 15:29:01', NULL, NULL, NULL, NULL, 3, NULL, NULL, 1, 1, NULL, 0, 1, 0, 50, '超级管理员', '2019-09-18 16:46:51', 1, 7870, NULL, NULL, 2, NULL, NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (213, NULL, NULL, NULL, NULL, '所在公司', 'Company', 'string', 150, NULL, '2018-07-10 15:29:01', NULL, NULL, NULL, NULL, 6, NULL, NULL, 1, 1, NULL, 0, 1, 0, 50, '超级管理员', '2019-09-18 16:46:51', 1, 7860, NULL, NULL, 2, '无', NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (214, NULL, NULL, NULL, NULL, '服务地区', 'City', 'string', 120, NULL, '2018-07-10 15:29:01', NULL, NULL, 'city', NULL, 3, 'drop', NULL, 1, 1, NULL, 0, 1, 0, 50, '超级管理员', '2019-09-18 16:46:51', 1, 7850, NULL, NULL, 3, 'dropList', NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (215, NULL, NULL, NULL, NULL, '擅长领域', 'SpecialField', 'string', 120, NULL, '2018-07-10 15:29:01', NULL, NULL, NULL, NULL, 9, 'textarea', NULL, 1, 1, NULL, 0, 1, 0, 800, '超级管理员', '2019-09-18 16:46:51', 1, 7840, NULL, NULL, NULL, NULL, NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (216, NULL, NULL, NULL, NULL, '个人简介', 'Resume', 'string', 220, NULL, '2018-07-10 15:29:01', NULL, NULL, NULL, NULL, 9, 'textarea', NULL, 1, 1, NULL, 0, 1, 0, 500, '超级管理员', '2019-09-18 16:46:51', 1, 7830, NULL, NULL, NULL, NULL, NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (217, NULL, NULL, NULL, NULL, '审核状态', 'AuditStatus', 'int', 120, NULL, '2018-07-10 15:29:01', NULL, NULL, 'audit', NULL, 0, 'drop', NULL, 1, 1, NULL, 0, 0, 0, NULL, '超级管理员', '2019-09-18 16:46:51', 1, 7919, NULL, NULL, 3, 'dropList', NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (218, NULL, NULL, NULL, NULL, '审核人Id', 'AuditId', 'int', 80, NULL, '2018-07-10 15:29:01', NULL, NULL, NULL, NULL, 0, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-09-18 16:46:51', 1, 7810, NULL, NULL, NULL, NULL, NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (219, NULL, NULL, NULL, NULL, '审核人', 'Auditor', 'string', 150, NULL, '2018-07-10 15:29:01', NULL, NULL, NULL, NULL, 0, NULL, NULL, 1, 1, NULL, 0, 1, 0, 20, '超级管理员', '2019-09-18 16:46:51', 1, 7919, NULL, NULL, NULL, NULL, NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (220, NULL, NULL, NULL, NULL, '审核时间', 'AuditDate', 'DateTime', 150, NULL, '2018-07-10 15:29:01', NULL, NULL, NULL, NULL, 0, 'datetime', NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2019-09-18 16:46:51', 1, 7790, NULL, NULL, 3, 'datetime', NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (221, NULL, NULL, NULL, NULL, '是否启用', 'Enable', 'sbyte', 90, NULL, '2018-07-10 15:29:01', NULL, NULL, 'enable', NULL, 7, 'drop', NULL, 1, 1, NULL, 0, 0, 0, NULL, '超级管理员', '2019-09-18 16:46:51', 1, 7919, NULL, NULL, NULL, NULL, NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (222, NULL, NULL, NULL, NULL, '创建人Id', 'CreateID', 'int', 80, NULL, '2018-07-10 15:29:01', NULL, NULL, NULL, NULL, 0, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-09-18 16:46:51', 1, 7770, NULL, NULL, NULL, NULL, NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (223, NULL, NULL, NULL, NULL, '创建人', 'Creator', 'string', 130, NULL, '2018-07-10 15:29:01', NULL, NULL, NULL, NULL, 0, NULL, NULL, 1, 0, NULL, 0, 1, 0, 30, '超级管理员', '2019-09-18 16:46:51', 1, 7760, NULL, NULL, NULL, NULL, NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (224, NULL, NULL, NULL, NULL, '申请时间', 'CreateDate', 'DateTime', 150, NULL, '2018-07-10 15:29:01', NULL, NULL, NULL, NULL, 7, NULL, NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2019-09-18 16:46:51', 1, 7750, NULL, NULL, NULL, NULL, NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (225, NULL, NULL, NULL, NULL, '修改人ID', 'ModifyID', 'int', 80, NULL, '2018-07-10 15:29:01', NULL, NULL, NULL, NULL, 0, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-09-18 16:46:51', 1, 7740, NULL, NULL, NULL, NULL, NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (226, NULL, NULL, NULL, NULL, '修改人', 'Modifier', 'string', 130, NULL, '2018-07-10 15:29:01', NULL, NULL, NULL, NULL, 0, NULL, NULL, 1, 1, NULL, 0, 1, 0, 30, '超级管理员', '2019-09-18 16:46:51', 1, 7730, NULL, NULL, NULL, NULL, NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (227, NULL, NULL, NULL, NULL, '修改时间', 'ModifyDate', 'DateTime', 150, NULL, '2018-07-10 15:29:01', NULL, NULL, NULL, NULL, 0, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2019-09-18 16:46:51', 1, 7720, NULL, NULL, NULL, NULL, NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (308, NULL, NULL, NULL, NULL, '主键ID', 'Id', 'int', 80, NULL, '2018-07-10 16:11:59', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 1, 0, 1, NULL, '超级管理员', '2019-08-16 09:31:10', 1, 6910, NULL, NULL, NULL, NULL, NULL, 'App_News', 28); +INSERT INTO "public"."Sys_TableColumn" VALUES (309, NULL, NULL, NULL, 12, '标题', 'Title', 'string', 250, NULL, '2018-07-10 16:11:59', NULL, NULL, NULL, NULL, 1, NULL, NULL, 1, 1, NULL, 0, 0, 0, 50, '超级管理员', '2019-08-16 09:31:10', 1, 6900, NULL, NULL, 1, NULL, NULL, 'App_News', 28); +INSERT INTO "public"."Sys_TableColumn" VALUES (310, NULL, NULL, NULL, NULL, '发布人', 'Author', 'string', 120, NULL, '2018-07-10 16:11:59', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 1, 50, '超级管理员', '2019-08-16 09:31:10', 1, 6890, NULL, NULL, NULL, NULL, NULL, 'App_News', 28); +INSERT INTO "public"."Sys_TableColumn" VALUES (311, 0, NULL, NULL, NULL, '发布时间', 'ReleaseDate', 'DateTime', 150, NULL, '2018-07-10 16:11:59', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 1, NULL, '超级管理员', '2019-08-16 09:31:10', 1, 6880, NULL, NULL, 3, 'datetime', NULL, 'App_News', 28); +INSERT INTO "public"."Sys_TableColumn" VALUES (312, NULL, NULL, NULL, 12, '封面图片', 'ImageUrl', 'string', 220, NULL, '2018-07-10 16:11:59', NULL, NULL, NULL, NULL, 9, NULL, NULL, 1, 1, 1, 0, 1, 0, 500, '超级管理员', '2019-08-16 09:31:10', 1, 6870, NULL, NULL, NULL, NULL, NULL, 'App_News', 28); +INSERT INTO "public"."Sys_TableColumn" VALUES (313, NULL, NULL, NULL, NULL, '图片(大图)', 'BigImageUrls', 'string', 220, NULL, '2018-07-10 16:11:59', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, 500, '超级管理员', '2019-08-16 09:31:10', 1, 6860, NULL, NULL, NULL, NULL, NULL, 'App_News', 28); +INSERT INTO "public"."Sys_TableColumn" VALUES (314, NULL, NULL, NULL, 12, '新闻地址', 'DetailUrl', 'string', 90, NULL, '2018-07-10 16:11:59', NULL, NULL, NULL, NULL, 8, NULL, NULL, 1, 1, NULL, 0, 1, 0, 200, '超级管理员', '2019-08-16 09:31:10', 1, 6850, NULL, NULL, NULL, NULL, NULL, 'App_News', 28); +INSERT INTO "public"."Sys_TableColumn" VALUES (315, NULL, NULL, NULL, NULL, '浏览次数', 'ViewCount', 'int', 110, NULL, '2018-07-10 16:11:59', NULL, NULL, NULL, 2, 3, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2019-08-16 09:31:10', 1, 6840, NULL, NULL, NULL, NULL, NULL, 'App_News', 28); +INSERT INTO "public"."Sys_TableColumn" VALUES (316, NULL, NULL, NULL, NULL, '新闻类型', 'NewsType', 'int', 110, NULL, '2018-07-10 16:11:59', NULL, NULL, 'news', 1, 3, 'drop', NULL, 1, 1, NULL, 0, 0, 0, NULL, '超级管理员', '2019-08-16 09:31:10', 1, 6830, NULL, NULL, 1, 'drop', NULL, 'App_News', 28); +INSERT INTO "public"."Sys_TableColumn" VALUES (317, NULL, NULL, NULL, NULL, '是否启用', 'Enable', 'sbyte', 90, NULL, '2018-07-10 16:11:59', NULL, NULL, 'enable', NULL, 7, 'drop', NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2019-08-16 09:31:10', 1, 6820, NULL, NULL, 3, 'drop', NULL, 'App_News', 28); +INSERT INTO "public"."Sys_TableColumn" VALUES (318, NULL, NULL, NULL, NULL, '创建人Id', 'CreateID', 'int', 80, NULL, '2018-07-10 16:11:59', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-08-16 09:31:10', 1, 6810, NULL, NULL, NULL, NULL, NULL, 'App_News', 28); +INSERT INTO "public"."Sys_TableColumn" VALUES (319, NULL, NULL, NULL, NULL, '发布人', 'Creator', 'string', 130, NULL, '2018-07-10 16:11:59', NULL, NULL, NULL, NULL, 6, NULL, NULL, 1, 1, NULL, 0, 1, 1, 30, '超级管理员', '2019-08-16 09:31:10', 1, 6800, NULL, NULL, 3, '无', NULL, 'App_News', 28); +INSERT INTO "public"."Sys_TableColumn" VALUES (320, NULL, NULL, NULL, NULL, '发布时间', 'CreateDate', 'DateTime', 150, NULL, '2018-07-10 16:11:59', NULL, NULL, NULL, NULL, 6, NULL, NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2019-08-16 09:31:10', 1, 6790, NULL, NULL, NULL, NULL, NULL, 'App_News', 28); +INSERT INTO "public"."Sys_TableColumn" VALUES (321, NULL, NULL, NULL, NULL, '修改人ID', 'ModifyID', 'int', 80, NULL, '2018-07-10 16:11:59', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-08-16 09:31:10', 1, 6780, NULL, NULL, NULL, NULL, NULL, 'App_News', 28); +INSERT INTO "public"."Sys_TableColumn" VALUES (322, NULL, NULL, NULL, NULL, '修改人', 'Modifier', 'string', 130, NULL, '2018-07-10 16:11:59', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 30, '超级管理员', '2019-08-16 09:31:10', 1, 6770, NULL, NULL, NULL, NULL, NULL, 'App_News', 28); +INSERT INTO "public"."Sys_TableColumn" VALUES (323, NULL, NULL, NULL, NULL, '修改时间', 'ModifyDate', 'DateTime', 150, NULL, '2018-07-10 16:11:59', NULL, NULL, NULL, NULL, 7, NULL, NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2019-08-16 09:31:10', 1, 6760, NULL, NULL, NULL, 'datetime', NULL, 'App_News', 28); +INSERT INTO "public"."Sys_TableColumn" VALUES (324, NULL, NULL, NULL, 12, '新闻内容', 'Content', 'string', 300, NULL, NULL, NULL, NULL, NULL, NULL, 10, NULL, NULL, 1, 0, NULL, NULL, 1, 0, 0, '超级管理员', '2019-08-16 09:31:10', 1, 6896, NULL, NULL, NULL, NULL, NULL, 'App_News', 28); +INSERT INTO "public"."Sys_TableColumn" VALUES (429, 1, 0, NULL, NULL, '手机号', 'PhoneNo', 'string', 150, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, NULL, 1, 0, 11, '超级管理员', '2019-12-08 22:22:13', 1, 7760, NULL, NULL, 3, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (431, NULL, NULL, NULL, NULL, 'Token', 'Token', 'string', 180, NULL, NULL, NULL, NULL, NULL, NULL, 4, NULL, NULL, 1, 1, NULL, NULL, 1, 0, 500, '超级管理员', '2019-12-08 22:22:13', 1, 7810, NULL, NULL, 2, NULL, NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (446, NULL, NULL, NULL, 12, '是否推荐价格', 'IsTop', 'int', 90, NULL, NULL, NULL, NULL, 'top', NULL, 30, 'select', NULL, 1, 1, NULL, NULL, 0, 0, NULL, '超级管理员', '2020-05-03 01:07:54', 1, 8515, NULL, NULL, 2, 'select', NULL, 'App_TransactionAvgPrice', 15); +INSERT INTO "public"."Sys_TableColumn" VALUES (457, NULL, NULL, NULL, NULL, '是否买入', 'TransactionType', 'int', 120, NULL, NULL, NULL, NULL, 'cq', NULL, 2, 'select', NULL, 1, 1, NULL, NULL, NULL, 0, NULL, '超级管理员', '2019-09-18 17:40:42', 1, 8021, NULL, NULL, 1, 'select', NULL, 'App_Transaction', 19); +INSERT INTO "public"."Sys_TableColumn" VALUES (506, NULL, NULL, NULL, NULL, '性别', 'Gender', 'int', 100, NULL, NULL, NULL, NULL, 'gender', NULL, 4, 'drop', NULL, 1, 1, NULL, NULL, 1, 0, NULL, '超级管理员', '2019-12-08 22:22:13', 1, 7843, NULL, NULL, 1, 'drop', NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (523, NULL, NULL, NULL, NULL, '电话', 'PhoneNo', 'string', 150, NULL, NULL, NULL, NULL, NULL, NULL, 6, NULL, NULL, 1, 1, NULL, NULL, 1, 0, 11, '超级管理员', '2019-09-18 16:46:51', 1, 7900, NULL, NULL, NULL, NULL, NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (550, NULL, NULL, NULL, NULL, '申请人帐号Id', 'User_Id', 'int', 90, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, 1, 0, NULL, NULL, 1, 0, NULL, '超级管理员', '2019-09-18 16:46:51', 1, 7921, NULL, NULL, NULL, NULL, NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (551, NULL, NULL, NULL, NULL, '申请人帐号', 'UserName', 'string', 120, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, 1, 1, NULL, NULL, 1, 0, 30, '超级管理员', '2019-09-18 16:46:51', 1, 7920, NULL, NULL, NULL, NULL, NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (552, NULL, NULL, NULL, NULL, '申请人', 'UserTrueName', 'string', 120, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, 1, 1, NULL, NULL, 1, 0, 50, '超级管理员', '2019-09-18 16:46:51', 1, 7920, NULL, NULL, NULL, NULL, NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (654, NULL, NULL, NULL, NULL, '登陆设备类型', 'AppType', 'int', 150, NULL, NULL, NULL, NULL, 'ut', NULL, 0, NULL, NULL, 1, 1, NULL, NULL, 1, 0, NULL, '超级管理员', '2019-12-08 22:22:13', 1, 7809, NULL, NULL, 3, 'dropList', NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (659, NULL, NULL, NULL, NULL, '是否手机用户', 'IsRegregisterPhone', 'int', 120, NULL, NULL, NULL, NULL, 'isphone', NULL, 2, 'drop', NULL, 1, 0, NULL, NULL, 0, 0, NULL, '超级管理员', '2019-12-08 22:22:13', 1, 7771, NULL, NULL, 3, 'drop', NULL, 'Sys_User', 6); +INSERT INTO "public"."Sys_TableColumn" VALUES (663, NULL, NULL, NULL, NULL, '是否今日推荐', 'DailyRecommend', 'sbyte', 120, NULL, NULL, NULL, NULL, 'dr', NULL, 5, 'drop', NULL, 1, 1, NULL, NULL, 0, 0, NULL, '超级管理员', '2019-08-16 09:31:10', 1, 6825, NULL, NULL, 1, 'drop', NULL, 'App_News', 28); +INSERT INTO "public"."Sys_TableColumn" VALUES (664, NULL, NULL, NULL, NULL, '推荐排序', 'OrderNo', 'int', 120, NULL, NULL, NULL, NULL, NULL, NULL, 5, NULL, NULL, 1, 1, NULL, NULL, 1, 0, NULL, '超级管理员', '2019-08-16 09:31:10', 1, 6822, NULL, NULL, NULL, '无', NULL, 'App_News', 28); +INSERT INTO "public"."Sys_TableColumn" VALUES (714, NULL, NULL, NULL, NULL, 'Id', 'Order_Id', 'string', 90, NULL, '2019-08-22 17:26:55', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 1, 0, 1, 36, '超级管理员', '2019-09-19 14:55:02', 1, 2850, NULL, NULL, NULL, NULL, NULL, 'SellOrder', 77); +INSERT INTO "public"."Sys_TableColumn" VALUES (715, NULL, NULL, NULL, NULL, '订单类型', 'OrderType', 'int', 90, NULL, '2019-08-22 17:26:55', 1, '超级管理员', 'ordertype', 1, 1, 'select', NULL, 1, 1, NULL, 0, 0, 0, NULL, '超级管理员', '2019-09-19 14:55:02', 1, 2840, NULL, 1, 1, 'select', NULL, 'SellOrder', 77); +INSERT INTO "public"."Sys_TableColumn" VALUES (716, NULL, NULL, NULL, NULL, '运单号', 'TranNo', 'string', 150, NULL, '2019-08-22 17:26:55', 1, '超级管理员', NULL, 1, 1, NULL, NULL, 1, 1, NULL, 0, 0, 0, 100, '超级管理员', '2019-09-19 14:55:02', 1, 2830, NULL, NULL, 1, NULL, NULL, 'SellOrder', 77); +INSERT INTO "public"."Sys_TableColumn" VALUES (717, NULL, NULL, NULL, NULL, '销售订单号', 'SellNo', 'string', 200, NULL, '2019-08-22 17:26:55', 1, '超级管理员', NULL, 2, 2, NULL, NULL, 1, 1, NULL, 0, 0, 0, 255, '超级管理员', '2019-09-19 14:55:02', 1, 2820, NULL, NULL, 1, NULL, NULL, 'SellOrder', 77); +INSERT INTO "public"."Sys_TableColumn" VALUES (718, NULL, NULL, NULL, NULL, '销售数量', 'Qty', 'int', 90, NULL, '2019-08-22 17:26:55', 1, '超级管理员', NULL, 2, 1, NULL, NULL, 1, 1, NULL, 0, 0, 0, NULL, '超级管理员', '2019-09-19 14:55:02', 1, 2810, NULL, NULL, NULL, NULL, NULL, 'SellOrder', 77); +INSERT INTO "public"."Sys_TableColumn" VALUES (719, NULL, NULL, NULL, 8, '备注', 'Remark', 'string', 100, NULL, '2019-08-22 17:26:55', 1, '超级管理员', NULL, NULL, 2, 'textarea', NULL, 1, 1, NULL, 0, 1, 0, 1000, '超级管理员', '2019-09-19 14:55:02', 1, 2800, NULL, NULL, NULL, NULL, NULL, 'SellOrder', 77); +INSERT INTO "public"."Sys_TableColumn" VALUES (720, NULL, NULL, NULL, NULL, NULL, 'CreateID', 'int', 80, NULL, '2019-08-22 17:26:55', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-09-19 14:55:02', 1, 2790, NULL, NULL, NULL, NULL, NULL, 'SellOrder', 77); +INSERT INTO "public"."Sys_TableColumn" VALUES (721, NULL, NULL, NULL, NULL, '创建人', 'Creator', 'string', 100, NULL, '2019-08-22 17:26:55', 1, '超级管理员', NULL, 3, 3, NULL, NULL, 1, 1, NULL, 0, 1, 1, 255, '超级管理员', '2019-09-19 14:55:02', 1, 2780, NULL, NULL, 3, NULL, NULL, 'SellOrder', 77); +INSERT INTO "public"."Sys_TableColumn" VALUES (722, NULL, NULL, NULL, NULL, '创建时间', 'CreateDate', 'DateTime', 90, NULL, '2019-08-22 17:26:55', 1, '超级管理员', NULL, 3, 3, NULL, NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2019-09-19 14:55:02', 1, 2770, NULL, NULL, 3, 'datetime', NULL, 'SellOrder', 77); +INSERT INTO "public"."Sys_TableColumn" VALUES (723, NULL, NULL, NULL, NULL, NULL, 'ModifyID', 'int', 80, NULL, '2019-08-22 17:26:55', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-09-19 14:55:02', 1, 2760, NULL, NULL, NULL, NULL, NULL, 'SellOrder', 77); +INSERT INTO "public"."Sys_TableColumn" VALUES (724, NULL, NULL, NULL, NULL, '修改人', 'Modifier', 'string', 100, NULL, '2019-08-22 17:26:55', 1, '超级管理员', NULL, 4, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 1, 255, '超级管理员', '2019-09-19 14:55:02', 1, 2750, NULL, NULL, NULL, NULL, NULL, 'SellOrder', 77); +INSERT INTO "public"."Sys_TableColumn" VALUES (725, NULL, NULL, NULL, NULL, '修改时间', 'ModifyDate', 'DateTime', 90, NULL, '2019-08-22 17:26:55', 1, '超级管理员', NULL, 4, 3, NULL, NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2019-09-19 14:55:02', 1, 2740, NULL, NULL, 3, 'datetime', NULL, 'SellOrder', 77); +INSERT INTO "public"."Sys_TableColumn" VALUES (726, NULL, NULL, NULL, NULL, NULL, 'OrderList_Id', 'string', 90, NULL, '2019-08-28 09:17:39', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 1, 0, 0, 36, '超级管理员', '2019-09-19 14:54:58', 1, 2730, NULL, NULL, NULL, NULL, NULL, 'SellOrderList', 78); +INSERT INTO "public"."Sys_TableColumn" VALUES (727, NULL, NULL, NULL, NULL, '订单Id', 'Order_Id', 'string', 90, NULL, '2019-08-28 09:17:39', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 0, 1, 36, '超级管理员', '2019-09-19 14:54:58', 1, 2720, NULL, NULL, NULL, NULL, NULL, 'SellOrderList', 78); +INSERT INTO "public"."Sys_TableColumn" VALUES (728, NULL, NULL, NULL, NULL, '商品名称', 'ProductName', 'string', 150, NULL, '2019-08-28 09:17:39', 1, '超级管理员', 'pn', NULL, 1, 'select', NULL, 1, 1, NULL, 0, 0, 0, 200, '超级管理员', '2019-09-19 14:54:58', 1, 2710, NULL, NULL, NULL, NULL, NULL, 'SellOrderList', 78); +INSERT INTO "public"."Sys_TableColumn" VALUES (729, NULL, NULL, NULL, NULL, '批次', 'MO', 'string', 100, NULL, '2019-08-28 09:17:39', 1, '超级管理员', NULL, NULL, 1, NULL, NULL, 1, 1, NULL, 0, 0, 0, 255, '超级管理员', '2019-09-19 14:54:58', 1, 2700, NULL, NULL, NULL, NULL, NULL, 'SellOrderList', 78); +INSERT INTO "public"."Sys_TableColumn" VALUES (730, NULL, NULL, NULL, NULL, '数量', 'Qty', 'int', 90, NULL, '2019-08-28 09:17:39', 1, '超级管理员', NULL, NULL, 1, 'drop', NULL, 1, 1, NULL, 0, 0, 0, NULL, '超级管理员', '2019-09-19 14:54:58', 1, 2690, NULL, NULL, NULL, NULL, NULL, 'SellOrderList', 78); +INSERT INTO "public"."Sys_TableColumn" VALUES (731, NULL, NULL, NULL, NULL, '重量', 'Weight', 'decimal', 90, NULL, '2019-08-28 09:17:39', 1, '超级管理员', NULL, NULL, 2, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2019-09-19 14:54:58', 1, 2680, NULL, NULL, NULL, NULL, NULL, 'SellOrderList', 78); +INSERT INTO "public"."Sys_TableColumn" VALUES (732, NULL, NULL, NULL, NULL, '备注', 'Remark', 'string', 120, NULL, '2019-08-28 09:17:39', 1, '超级管理员', NULL, NULL, 2, NULL, NULL, 1, 1, NULL, 0, 1, 0, 1000, '超级管理员', '2019-09-19 14:54:58', 1, 2670, NULL, NULL, NULL, NULL, NULL, 'SellOrderList', 78); +INSERT INTO "public"."Sys_TableColumn" VALUES (733, NULL, NULL, NULL, NULL, NULL, 'CreateID', 'int', 80, NULL, '2019-08-28 09:17:39', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-09-19 14:54:58', 1, 2660, NULL, NULL, NULL, NULL, NULL, 'SellOrderList', 78); +INSERT INTO "public"."Sys_TableColumn" VALUES (734, NULL, NULL, NULL, NULL, '创建人', 'Creator', 'string', 130, NULL, '2019-08-28 09:17:39', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 255, '超级管理员', '2019-09-19 14:54:58', 1, 2650, NULL, NULL, NULL, NULL, NULL, 'SellOrderList', 78); +INSERT INTO "public"."Sys_TableColumn" VALUES (735, NULL, NULL, NULL, NULL, '创建时间', 'CreateDate', 'DateTime', 90, NULL, '2019-08-28 09:17:39', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2019-09-19 14:54:58', 1, 2640, NULL, NULL, NULL, NULL, NULL, 'SellOrderList', 78); +INSERT INTO "public"."Sys_TableColumn" VALUES (736, NULL, NULL, NULL, NULL, NULL, 'ModifyID', 'int', 80, NULL, '2019-08-28 09:17:39', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2019-09-19 14:54:58', 1, 2630, NULL, NULL, NULL, NULL, NULL, 'SellOrderList', 78); +INSERT INTO "public"."Sys_TableColumn" VALUES (737, NULL, NULL, NULL, NULL, '修改人', 'Modifier', 'string', 100, NULL, '2019-08-28 09:17:39', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 255, '超级管理员', '2019-09-19 14:54:58', 1, 2620, NULL, NULL, NULL, NULL, NULL, 'SellOrderList', 78); +INSERT INTO "public"."Sys_TableColumn" VALUES (738, NULL, NULL, NULL, NULL, '修改时间', 'ModifyDate', 'DateTime', 90, NULL, '2019-08-28 09:17:39', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, NULL, '超级管理员', '2019-09-19 14:54:58', 1, 2610, NULL, NULL, NULL, NULL, NULL, 'SellOrderList', 78); +INSERT INTO "public"."Sys_TableColumn" VALUES (739, NULL, NULL, NULL, NULL, '审核时间', 'AuditDate', 'DateTime', 120, NULL, '2019-08-28 09:32:29', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, NULL, 1, 0, NULL, '超级管理员', '2019-09-19 14:55:02', 1, 2805, NULL, NULL, 2, 'datetime', NULL, 'SellOrder', 77); +INSERT INTO "public"."Sys_TableColumn" VALUES (740, NULL, NULL, NULL, NULL, '审核人', 'Auditor', 'string', NULL, NULL, '2019-08-28 09:32:29', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, NULL, 1, 0, 100, '超级管理员', '2019-09-19 14:55:02', 1, 2803, NULL, NULL, 2, NULL, NULL, 'SellOrder', 77); +INSERT INTO "public"."Sys_TableColumn" VALUES (741, NULL, NULL, NULL, NULL, '审核人Id', 'AuditId', 'int', NULL, NULL, '2019-08-28 09:32:29', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, NULL, 1, 0, NULL, '超级管理员', '2019-09-19 14:55:02', 1, 2801, NULL, NULL, NULL, NULL, NULL, 'SellOrder', 77); +INSERT INTO "public"."Sys_TableColumn" VALUES (742, NULL, NULL, NULL, NULL, '审核状态', 'AuditStatus', 'int', NULL, NULL, '2019-08-28 09:32:29', 1, '超级管理员', 'audit', NULL, NULL, NULL, NULL, 1, 1, NULL, NULL, 0, 0, NULL, '超级管理员', '2019-09-19 14:55:02', 1, 2808, NULL, NULL, 2, 'select', NULL, 'SellOrder', 77); +INSERT INTO "public"."Sys_TableColumn" VALUES (743, NULL, NULL, NULL, NULL, NULL, 'Id', 'string', 90, NULL, '2019-09-18 15:46:43', 1, '超级管理员', NULL, 5, 1, NULL, NULL, 1, 0, NULL, 1, 0, 1, 36, '超级管理员', '2020-04-24 13:47:36', 1, 2560, NULL, NULL, NULL, NULL, NULL, 'App_Appointment', 80); +INSERT INTO "public"."Sys_TableColumn" VALUES (744, NULL, NULL, NULL, NULL, '创建时间', 'CreateDate', 'DateTime', 120, NULL, '2019-09-18 15:46:43', 1, '超级管理员', NULL, 1, 3, NULL, NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2020-04-24 13:47:36', 1, 2550, NULL, NULL, 1, 'datetime', NULL, 'App_Appointment', 80); +INSERT INTO "public"."Sys_TableColumn" VALUES (745, NULL, NULL, NULL, NULL, NULL, 'CreateID', 'int', 80, NULL, '2019-09-18 15:46:43', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2020-04-24 13:47:36', 1, 2540, NULL, NULL, NULL, NULL, NULL, 'App_Appointment', 80); +INSERT INTO "public"."Sys_TableColumn" VALUES (746, NULL, NULL, NULL, NULL, '创建人', 'Creator', 'string', 130, NULL, '2019-09-18 15:46:43', 1, '超级管理员', NULL, 2, 3, NULL, NULL, 1, 1, NULL, 0, 1, 1, 30, '超级管理员', '2020-04-24 13:47:36', 1, 2530, NULL, NULL, 1, NULL, NULL, 'App_Appointment', 80); +INSERT INTO "public"."Sys_TableColumn" VALUES (747, NULL, NULL, NULL, NULL, '描述', 'Describe', 'string', 180, NULL, '2019-09-18 15:46:43', 1, '超级管理员', NULL, NULL, 2, NULL, NULL, 1, 1, NULL, 0, 0, 1, 250, '超级管理员', '2020-04-24 13:47:36', 1, 3490, NULL, NULL, NULL, NULL, NULL, 'App_Appointment', 80); +INSERT INTO "public"."Sys_TableColumn" VALUES (748, NULL, NULL, NULL, NULL, '修改人', 'Modifier', 'string', 130, NULL, '2019-09-18 15:46:43', 1, '超级管理员', NULL, NULL, 4, NULL, NULL, 1, 1, NULL, 0, 1, 1, 30, '超级管理员', '2020-04-24 13:47:36', 1, 2510, NULL, NULL, NULL, NULL, NULL, 'App_Appointment', 80); +INSERT INTO "public"."Sys_TableColumn" VALUES (749, NULL, NULL, NULL, NULL, '修改时间', 'ModifyDate', 'DateTime', 90, NULL, '2019-09-18 15:46:43', 1, '超级管理员', NULL, 1, 4, NULL, NULL, 1, 1, NULL, 0, 1, 1, NULL, '超级管理员', '2020-04-24 13:47:36', 1, 2500, NULL, NULL, NULL, NULL, NULL, 'App_Appointment', 80); +INSERT INTO "public"."Sys_TableColumn" VALUES (750, NULL, NULL, NULL, NULL, NULL, 'ModifyID', 'int', 80, NULL, '2019-09-18 15:46:43', 1, '超级管理员', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 0, 1, 0, NULL, '超级管理员', '2020-04-24 13:47:36', 1, 2490, NULL, NULL, NULL, NULL, NULL, 'App_Appointment', 80); +INSERT INTO "public"."Sys_TableColumn" VALUES (751, NULL, NULL, NULL, NULL, '姓名', 'Name', 'string', 100, NULL, '2019-09-18 15:46:43', 1, '超级管理员', NULL, NULL, 1, NULL, NULL, 1, 1, NULL, 0, 0, 1, 50, '超级管理员', '2020-04-24 13:47:36', 1, 3500, NULL, NULL, 1, NULL, NULL, 'App_Appointment', 80); +INSERT INTO "public"."Sys_TableColumn" VALUES (752, NULL, NULL, NULL, NULL, '电话', 'PhoneNo', 'string', 130, NULL, '2019-09-18 15:46:43', 1, '超级管理员', NULL, NULL, 2, NULL, NULL, 1, 1, NULL, 0, 0, 1, 15, '超级管理员', '2020-04-24 13:47:36', 1, 3470, NULL, NULL, 1, NULL, NULL, 'App_Appointment', 80); +INSERT INTO "public"."Sys_TableColumn" VALUES (763, NULL, NULL, NULL, NULL, NULL, 'Certificate', 'string', 120, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 2500, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, 'App_Expert', 20); +INSERT INTO "public"."Sys_TableColumn" VALUES (826, NULL, NULL, NULL, NULL, NULL, 'Remark', 'string', 220, NULL, '2020-08-07 17:21:30', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 1000, 'admin', '2020-08-07 19:39:32.144945', 1, 850, NULL, NULL, NULL, NULL, NULL, 'SellOrder_copy1', 103); +INSERT INTO "public"."Sys_TableColumn" VALUES (817, NULL, NULL, NULL, NULL, '测试key', 'Order_Id', 'guid', 220, NULL, '2020-08-07 17:21:30', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 1, 0, 1, 1024, 'admin', '2020-08-07 19:39:32.143741', 1, 1300, NULL, NULL, NULL, NULL, NULL, 'SellOrder_copy1', 103); +INSERT INTO "public"."Sys_TableColumn" VALUES (818, NULL, NULL, NULL, NULL, '测试1', 'OrderType', 'long', 90, NULL, '2020-08-07 17:21:30', 1, 'admin', NULL, 0, NULL, NULL, NULL, 1, 1, NULL, 0, 0, 0, 64, 'admin', '2020-08-07 19:39:32.144178', 1, 1250, NULL, NULL, NULL, NULL, NULL, 'SellOrder_copy1', 103); +INSERT INTO "public"."Sys_TableColumn" VALUES (819, NULL, NULL, NULL, NULL, '测试2', 'TranNo', 'string', 120, NULL, '2020-08-07 17:21:30', 1, 'admin', NULL, 0, NULL, NULL, NULL, 1, 1, NULL, 0, 0, 0, 100, 'admin', '2020-08-07 19:39:32.144434', 1, 1200, NULL, NULL, NULL, NULL, NULL, 'SellOrder_copy1', 103); +INSERT INTO "public"."Sys_TableColumn" VALUES (820, NULL, NULL, NULL, NULL, NULL, 'SellNo', 'string', 220, NULL, '2020-08-07 17:21:30', 1, 'admin', NULL, 0, NULL, NULL, NULL, 1, 1, NULL, 0, 0, 0, 255, 'admin', '2020-08-07 19:39:32.144618', 1, 1150, NULL, NULL, NULL, NULL, NULL, 'SellOrder_copy1', 103); +INSERT INTO "public"."Sys_TableColumn" VALUES (821, NULL, NULL, NULL, NULL, NULL, 'Qty', 'int', 90, NULL, '2020-08-07 17:21:30', 1, 'admin', NULL, 0, NULL, NULL, NULL, 1, 1, NULL, 0, 0, 0, 32, 'admin', '2020-08-07 19:39:32.144781', 1, 1100, NULL, NULL, NULL, NULL, NULL, 'SellOrder_copy1', 103); +INSERT INTO "public"."Sys_TableColumn" VALUES (827, NULL, NULL, NULL, NULL, NULL, 'CreateID', 'int', 80, NULL, '2020-08-07 17:21:30', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 32, 'admin', '2020-08-07 19:39:32.145139', 1, 800, NULL, NULL, NULL, NULL, NULL, 'SellOrder_copy1', 103); +INSERT INTO "public"."Sys_TableColumn" VALUES (828, NULL, NULL, NULL, NULL, NULL, 'Creator', 'string', 130, NULL, '2020-08-07 17:21:30', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 255, 'admin', '2020-08-07 19:39:32.145311', 1, 750, NULL, NULL, NULL, NULL, NULL, 'SellOrder_copy1', 103); +INSERT INTO "public"."Sys_TableColumn" VALUES (829, NULL, NULL, NULL, NULL, NULL, 'CreateDate', 'string ', 220, NULL, '2020-08-07 17:21:30', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 1024, 'admin', '2020-08-07 19:39:32.145479', 1, 700, NULL, NULL, NULL, NULL, NULL, 'SellOrder_copy1', 103); +INSERT INTO "public"."Sys_TableColumn" VALUES (830, NULL, NULL, NULL, NULL, NULL, 'ModifyID', 'int', 80, NULL, '2020-08-07 17:21:30', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 32, 'admin', '2020-08-07 19:39:32.14565', 1, 650, NULL, NULL, NULL, NULL, NULL, 'SellOrder_copy1', 103); +INSERT INTO "public"."Sys_TableColumn" VALUES (831, NULL, NULL, NULL, NULL, NULL, 'Modifier', 'string', 130, NULL, '2020-08-07 17:21:30', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 255, 'admin', '2020-08-07 19:39:32.145983', 1, 600, NULL, NULL, NULL, NULL, NULL, 'SellOrder_copy1', 103); +INSERT INTO "public"."Sys_TableColumn" VALUES (832, NULL, NULL, NULL, NULL, NULL, 'ModifyDate', 'string ', 220, NULL, '2020-08-07 17:21:30', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 1024, 'admin', '2020-08-07 19:39:32.146177', 1, 550, NULL, NULL, NULL, NULL, NULL, 'SellOrder_copy1', 103); +INSERT INTO "public"."Sys_TableColumn" VALUES (873, NULL, NULL, NULL, NULL, NULL, 'AuditStatus', 'int', 80, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, 1, 1, NULL, 0, 0, 0, 32, 'admin', '2020-08-07 19:39:32.146559', 1, 0, NULL, NULL, NULL, NULL, NULL, 'SellOrder_copy1', 103); +INSERT INTO "public"."Sys_TableColumn" VALUES (874, NULL, NULL, NULL, NULL, NULL, 'AuditId', 'int', 80, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 32, 'admin', '2020-08-07 19:39:32.146736', 1, 0, NULL, NULL, NULL, NULL, NULL, 'SellOrder_copy1', 103); +INSERT INTO "public"."Sys_TableColumn" VALUES (875, NULL, NULL, NULL, NULL, NULL, 'Auditor', 'string', 120, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 100, 'admin', '2020-08-07 19:39:32.147283', 1, 0, NULL, NULL, NULL, NULL, NULL, 'SellOrder_copy1', 103); +INSERT INTO "public"."Sys_TableColumn" VALUES (894, NULL, NULL, NULL, NULL, NULL, 'ViewCount', 'int', 90, NULL, '2020-08-07 17:40:03', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 32, 'admin', '2020-08-07 17:40:05.800926', 1, 550, NULL, NULL, NULL, NULL, NULL, 'App_News_copy1', 105); +INSERT INTO "public"."Sys_TableColumn" VALUES (876, NULL, NULL, NULL, NULL, NULL, 'Id', 'int', 90, NULL, '2020-08-07 17:40:03', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 1, 0, 1, 32, 'admin', '2020-08-07 17:40:05.791716', 1, 1450, NULL, NULL, NULL, NULL, NULL, 'App_News_copy1', 105); +INSERT INTO "public"."Sys_TableColumn" VALUES (877, NULL, NULL, NULL, NULL, NULL, 'ReleaseDate', 'string ', 220, NULL, '2020-08-07 17:40:03', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 1024, 'admin', '2020-08-07 17:40:05.800404', 1, 650, NULL, NULL, NULL, NULL, NULL, 'App_News_copy1', 105); +INSERT INTO "public"."Sys_TableColumn" VALUES (878, NULL, NULL, NULL, NULL, NULL, 'OrderNo', 'int', 90, NULL, '2020-08-07 17:40:03', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 32, 'admin', '2020-08-07 17:40:05.800154', 1, 700, NULL, NULL, NULL, NULL, NULL, 'App_News_copy1', 105); +INSERT INTO "public"."Sys_TableColumn" VALUES (879, NULL, NULL, NULL, NULL, NULL, 'NewsType', 'int', 90, NULL, '2020-08-07 17:40:03', 1, 'admin', NULL, 0, NULL, NULL, NULL, 1, 1, NULL, 0, 0, 0, 32, 'admin', '2020-08-07 17:40:05.799878', 1, 750, NULL, NULL, NULL, NULL, NULL, 'App_News_copy1', 105); +INSERT INTO "public"."Sys_TableColumn" VALUES (880, NULL, NULL, NULL, NULL, NULL, 'ModifyID', 'int', 80, NULL, '2020-08-07 17:40:03', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 32, 'admin', '2020-08-07 17:40:05.799591', 1, 800, NULL, NULL, NULL, NULL, NULL, 'App_News_copy1', 105); +INSERT INTO "public"."Sys_TableColumn" VALUES (881, NULL, NULL, NULL, NULL, NULL, 'ModifyDate', 'string ', 220, NULL, '2020-08-07 17:40:03', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 1024, 'admin', '2020-08-07 17:40:05.799293', 1, 850, NULL, NULL, NULL, NULL, NULL, 'App_News_copy1', 105); +INSERT INTO "public"."Sys_TableColumn" VALUES (882, NULL, NULL, NULL, NULL, NULL, 'Modifier', 'string', 130, NULL, '2020-08-07 17:40:03', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 30, 'admin', '2020-08-07 17:40:05.798971', 1, 900, NULL, NULL, NULL, NULL, NULL, 'App_News_copy1', 105); +INSERT INTO "public"."Sys_TableColumn" VALUES (883, NULL, NULL, NULL, NULL, NULL, 'ImageUrl', 'string', 220, NULL, '2020-08-07 17:40:03', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 500, 'admin', '2020-08-07 17:40:05.798616', 1, 950, NULL, NULL, NULL, NULL, NULL, 'App_News_copy1', 105); +INSERT INTO "public"."Sys_TableColumn" VALUES (884, NULL, NULL, NULL, NULL, NULL, 'Title', 'string', 90, NULL, '2020-08-07 17:40:03', 1, 'admin', NULL, 0, NULL, NULL, NULL, 1, 1, NULL, 0, 0, 0, 50, 'admin', '2020-08-07 17:40:05.800672', 1, 600, NULL, NULL, NULL, NULL, NULL, 'App_News_copy1', 105); +INSERT INTO "public"."Sys_TableColumn" VALUES (885, NULL, NULL, NULL, NULL, NULL, 'Enable', 'int', 90, NULL, '2020-08-07 17:40:03', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 16, 'admin', '2020-08-07 17:40:05.798257', 1, 1000, NULL, NULL, NULL, NULL, NULL, 'App_News_copy1', 105); +INSERT INTO "public"."Sys_TableColumn" VALUES (886, NULL, NULL, NULL, NULL, NULL, 'DailyRecommend', 'int', 90, NULL, '2020-08-07 17:40:03', 1, 'admin', NULL, 0, NULL, NULL, NULL, 1, 1, NULL, 0, 0, 0, 16, 'admin', '2020-08-07 17:40:05.797067', 1, 1100, NULL, NULL, NULL, NULL, NULL, 'App_News_copy1', 105); +INSERT INTO "public"."Sys_TableColumn" VALUES (887, NULL, NULL, NULL, NULL, NULL, 'Creator', 'string', 130, NULL, '2020-08-07 17:40:03', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 30, 'admin', '2020-08-07 17:40:05.796564', 1, 1150, NULL, NULL, NULL, NULL, NULL, 'App_News_copy1', 105); +INSERT INTO "public"."Sys_TableColumn" VALUES (888, NULL, NULL, NULL, NULL, NULL, 'CreateID', 'int', 80, NULL, '2020-08-07 17:40:03', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 32, 'admin', '2020-08-07 17:40:05.79598', 1, 1200, NULL, NULL, NULL, NULL, NULL, 'App_News_copy1', 105); +INSERT INTO "public"."Sys_TableColumn" VALUES (889, NULL, NULL, NULL, NULL, NULL, 'CreateDate', 'string ', 220, NULL, '2020-08-07 17:40:03', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 1024, 'admin', '2020-08-07 17:40:05.795425', 1, 1250, NULL, NULL, NULL, NULL, NULL, 'App_News_copy1', 105); +INSERT INTO "public"."Sys_TableColumn" VALUES (890, NULL, NULL, NULL, NULL, NULL, 'Content', 'string', 220, NULL, '2020-08-07 17:40:03', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 1024, 'admin', '2020-08-07 17:40:05.794806', 1, 1300, NULL, NULL, NULL, NULL, NULL, 'App_News_copy1', 105); +INSERT INTO "public"."Sys_TableColumn" VALUES (891, NULL, NULL, NULL, NULL, NULL, 'BigImageUrls', 'string', 220, NULL, '2020-08-07 17:40:03', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 500, 'admin', '2020-08-07 17:40:05.794169', 1, 1350, NULL, NULL, NULL, NULL, NULL, 'App_News_copy1', 105); +INSERT INTO "public"."Sys_TableColumn" VALUES (892, NULL, NULL, NULL, NULL, NULL, 'Author', 'string', 90, NULL, '2020-08-07 17:40:03', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 50, 'admin', '2020-08-07 17:40:05.793411', 1, 1400, NULL, NULL, NULL, NULL, NULL, 'App_News_copy1', 105); +INSERT INTO "public"."Sys_TableColumn" VALUES (893, NULL, NULL, NULL, NULL, NULL, 'DetailUrl', 'string', 180, NULL, '2020-08-07 17:40:03', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 200, 'admin', '2020-08-07 17:40:05.797815', 1, 1050, NULL, NULL, NULL, NULL, NULL, 'App_News_copy1', 105); +INSERT INTO "public"."Sys_TableColumn" VALUES (895, NULL, NULL, NULL, NULL, NULL, 'Id', 'int', 90, NULL, '2020-08-07 17:41:33', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 1, 0, 1, 32, 'admin', '2020-08-07 17:41:35.023525', 1, 1450, NULL, NULL, NULL, NULL, NULL, 'App_news_copy1_copy1', 106); +INSERT INTO "public"."Sys_TableColumn" VALUES (896, NULL, NULL, NULL, NULL, NULL, 'ReleaseDate', 'string ', 220, NULL, '2020-08-07 17:41:33', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 1024, 'admin', '2020-08-07 17:41:35.024409', 1, 650, NULL, NULL, NULL, NULL, NULL, 'App_news_copy1_copy1', 106); +INSERT INTO "public"."Sys_TableColumn" VALUES (897, NULL, NULL, NULL, NULL, NULL, 'OrderNo', 'int', 90, NULL, '2020-08-07 17:41:33', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 32, 'admin', '2020-08-07 17:41:35.024367', 1, 700, NULL, NULL, NULL, NULL, NULL, 'App_news_copy1_copy1', 106); +INSERT INTO "public"."Sys_TableColumn" VALUES (898, NULL, NULL, NULL, NULL, NULL, 'NewsType', 'int', 90, NULL, '2020-08-07 17:41:33', 1, 'admin', NULL, 0, NULL, NULL, NULL, 1, 1, NULL, 0, 0, 0, 32, 'admin', '2020-08-07 17:41:35.024325', 1, 750, NULL, NULL, NULL, NULL, NULL, 'App_news_copy1_copy1', 106); +INSERT INTO "public"."Sys_TableColumn" VALUES (899, NULL, NULL, NULL, NULL, NULL, 'ModifyID', 'int', 80, NULL, '2020-08-07 17:41:33', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 32, 'admin', '2020-08-07 17:41:35.02428', 1, 800, NULL, NULL, NULL, NULL, NULL, 'App_news_copy1_copy1', 106); +INSERT INTO "public"."Sys_TableColumn" VALUES (900, NULL, NULL, NULL, NULL, NULL, 'ModifyDate', 'string ', 220, NULL, '2020-08-07 17:41:33', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 1024, 'admin', '2020-08-07 17:41:35.024238', 1, 850, NULL, NULL, NULL, NULL, NULL, 'App_news_copy1_copy1', 106); +INSERT INTO "public"."Sys_TableColumn" VALUES (901, NULL, NULL, NULL, NULL, NULL, 'Modifier', 'string', 130, NULL, '2020-08-07 17:41:33', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 30, 'admin', '2020-08-07 17:41:35.024195', 1, 900, NULL, NULL, NULL, NULL, NULL, 'App_news_copy1_copy1', 106); +INSERT INTO "public"."Sys_TableColumn" VALUES (902, NULL, NULL, NULL, NULL, NULL, 'ImageUrl', 'string', 220, NULL, '2020-08-07 17:41:33', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 500, 'admin', '2020-08-07 17:41:35.024152', 1, 950, NULL, NULL, NULL, NULL, NULL, 'App_news_copy1_copy1', 106); +INSERT INTO "public"."Sys_TableColumn" VALUES (903, NULL, NULL, NULL, NULL, NULL, 'Title', 'string', 90, NULL, '2020-08-07 17:41:33', 1, 'admin', NULL, 0, NULL, NULL, NULL, 1, 1, NULL, 0, 0, 0, 50, 'admin', '2020-08-07 17:41:35.024452', 1, 600, NULL, NULL, NULL, NULL, NULL, 'App_news_copy1_copy1', 106); +INSERT INTO "public"."Sys_TableColumn" VALUES (906, NULL, NULL, NULL, NULL, NULL, 'Creator', 'string', 130, NULL, '2020-08-07 17:41:33', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 30, 'admin', '2020-08-07 17:41:35.02395', 1, 1150, NULL, NULL, NULL, NULL, NULL, 'App_news_copy1_copy1', 106); +INSERT INTO "public"."Sys_TableColumn" VALUES (904, NULL, NULL, NULL, NULL, NULL, 'Enable', 'short', 90, NULL, '2020-08-07 17:41:33', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 16, 'admin', '2020-08-07 17:41:35.024109', 1, 1000, NULL, NULL, NULL, NULL, NULL, 'App_news_copy1_copy1', 106); +INSERT INTO "public"."Sys_TableColumn" VALUES (905, NULL, NULL, NULL, NULL, NULL, 'DailyRecommend', 'short', 90, NULL, '2020-08-07 17:41:33', 1, 'admin', NULL, 0, NULL, NULL, NULL, 1, 1, NULL, 0, 0, 0, 16, 'admin', '2020-08-07 17:41:35.024004', 1, 1100, NULL, NULL, NULL, NULL, NULL, 'App_news_copy1_copy1', 106); +INSERT INTO "public"."Sys_TableColumn" VALUES (872, NULL, NULL, NULL, NULL, NULL, 'AuditDate', 'string ', 220, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 1024, 'admin', '2020-08-07 19:39:32.146342', 1, 0, NULL, NULL, NULL, NULL, NULL, 'SellOrder_copy1', 103); +INSERT INTO "public"."Sys_TableColumn" VALUES (907, NULL, NULL, NULL, NULL, NULL, 'CreateID', 'int', 80, NULL, '2020-08-07 17:41:33', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 32, 'admin', '2020-08-07 17:41:35.023895', 1, 1200, NULL, NULL, NULL, NULL, NULL, 'App_news_copy1_copy1', 106); +INSERT INTO "public"."Sys_TableColumn" VALUES (908, NULL, NULL, NULL, NULL, NULL, 'CreateDate', 'string ', 220, NULL, '2020-08-07 17:41:33', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 1024, 'admin', '2020-08-07 17:41:35.023851', 1, 1250, NULL, NULL, NULL, NULL, NULL, 'App_news_copy1_copy1', 106); +INSERT INTO "public"."Sys_TableColumn" VALUES (909, NULL, NULL, NULL, NULL, NULL, 'Content', 'string', 220, NULL, '2020-08-07 17:41:33', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 1024, 'admin', '2020-08-07 17:41:35.0238', 1, 1300, NULL, NULL, NULL, NULL, NULL, 'App_news_copy1_copy1', 106); +INSERT INTO "public"."Sys_TableColumn" VALUES (910, NULL, NULL, NULL, NULL, NULL, 'BigImageUrls', 'string', 220, NULL, '2020-08-07 17:41:33', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 500, 'admin', '2020-08-07 17:41:35.023745', 1, 1350, NULL, NULL, NULL, NULL, NULL, 'App_news_copy1_copy1', 106); +INSERT INTO "public"."Sys_TableColumn" VALUES (911, NULL, NULL, NULL, NULL, NULL, 'Author', 'string', 90, NULL, '2020-08-07 17:41:33', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 50, 'admin', '2020-08-07 17:41:35.023681', 1, 1400, NULL, NULL, NULL, NULL, NULL, 'App_news_copy1_copy1', 106); +INSERT INTO "public"."Sys_TableColumn" VALUES (912, NULL, NULL, NULL, NULL, NULL, 'DetailUrl', 'string', 180, NULL, '2020-08-07 17:41:33', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 200, 'admin', '2020-08-07 17:41:35.024063', 1, 1050, NULL, NULL, NULL, NULL, NULL, 'App_news_copy1_copy1', 106); +INSERT INTO "public"."Sys_TableColumn" VALUES (913, NULL, NULL, NULL, NULL, NULL, 'ViewCount', 'int', 90, NULL, '2020-08-07 17:41:33', 1, 'admin', NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 32, 'admin', '2020-08-07 17:41:35.024495', 1, 550, NULL, NULL, NULL, NULL, NULL, 'App_news_copy1_copy1', 106); +INSERT INTO "public"."Sys_TableColumn" VALUES (914, NULL, NULL, NULL, NULL, NULL, 'OrderList_Id', 'guid', 220, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, NULL, 1, 0, 1, 1024, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, 'SellOrderList_copy1', 104); +INSERT INTO "public"."Sys_TableColumn" VALUES (915, NULL, NULL, NULL, NULL, NULL, 'Order_Id', 'guid', 220, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, 1, 1, NULL, 0, 0, 0, 1024, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, 'SellOrderList_copy1', 104); +INSERT INTO "public"."Sys_TableColumn" VALUES (916, NULL, NULL, NULL, NULL, NULL, 'ProductName', 'string', 90, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, 1, 1, NULL, 0, 0, 0, 200, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, 'SellOrderList_copy1', 104); +INSERT INTO "public"."Sys_TableColumn" VALUES (917, NULL, NULL, NULL, NULL, NULL, 'MO', 'string', 220, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, 1, 1, NULL, 0, 0, 0, 255, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, 'SellOrderList_copy1', 104); +INSERT INTO "public"."Sys_TableColumn" VALUES (918, NULL, NULL, NULL, NULL, NULL, 'Qty', 'int', 80, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, 1, 1, NULL, 0, 0, 0, 32, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, 'SellOrderList_copy1', 104); +INSERT INTO "public"."Sys_TableColumn" VALUES (919, NULL, NULL, NULL, NULL, NULL, 'Weight', 'decimal', 220, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 1024, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, 'SellOrderList_copy1', 104); +INSERT INTO "public"."Sys_TableColumn" VALUES (920, NULL, NULL, NULL, NULL, NULL, 'Remark', 'string', 220, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 1000, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, 'SellOrderList_copy1', 104); +INSERT INTO "public"."Sys_TableColumn" VALUES (921, NULL, NULL, NULL, NULL, NULL, 'CreateID', 'int', 80, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 32, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, 'SellOrderList_copy1', 104); +INSERT INTO "public"."Sys_TableColumn" VALUES (922, NULL, NULL, NULL, NULL, NULL, 'Creator', 'string', 220, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 255, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, 'SellOrderList_copy1', 104); +INSERT INTO "public"."Sys_TableColumn" VALUES (923, NULL, NULL, NULL, NULL, NULL, 'CreateDate', 'string ', 220, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 1024, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, 'SellOrderList_copy1', 104); +INSERT INTO "public"."Sys_TableColumn" VALUES (924, NULL, NULL, NULL, NULL, NULL, 'ModifyID', 'int', 80, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 32, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, 'SellOrderList_copy1', 104); +INSERT INTO "public"."Sys_TableColumn" VALUES (925, NULL, NULL, NULL, NULL, NULL, 'Modifier', 'string', 220, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 255, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, 'SellOrderList_copy1', 104); +INSERT INTO "public"."Sys_TableColumn" VALUES (926, NULL, NULL, NULL, NULL, NULL, 'ModifyDate', 'string ', 220, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, NULL, 0, 1, 0, 1024, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, 'SellOrderList_copy1', 104); + +-- ---------------------------- +-- Table structure for Sys_TableInfo +-- ---------------------------- +DROP TABLE IF EXISTS "public"."Sys_TableInfo"; +CREATE TABLE "public"."Sys_TableInfo" ( + "Table_Id" int4 NOT NULL DEFAULT nextval('sys_tableinfo_id_seq'::regclass), + "CnName" varchar(50) COLLATE "pg_catalog"."default", + "ColumnCNName" varchar(100) COLLATE "pg_catalog"."default", + "DBServer" varchar(2000) COLLATE "pg_catalog"."default", + "DataTableType" varchar(200) COLLATE "pg_catalog"."default", + "DetailCnName" varchar(200) COLLATE "pg_catalog"."default", + "DetailName" varchar(200) COLLATE "pg_catalog"."default", + "EditorType" varchar(100) COLLATE "pg_catalog"."default", + "Enable" int4, + "ExpressField" varchar(200) COLLATE "pg_catalog"."default", + "FolderName" varchar(200) COLLATE "pg_catalog"."default", + "Namespace" varchar(200) COLLATE "pg_catalog"."default", + "OrderNo" int4, + "ParentId" int4, + "RichText" varchar(100) COLLATE "pg_catalog"."default", + "SortName" varchar(50) COLLATE "pg_catalog"."default", + "TableName" varchar(50) COLLATE "pg_catalog"."default", + "TableTrueName" varchar(100) COLLATE "pg_catalog"."default", + "UploadField" varchar(100) COLLATE "pg_catalog"."default", + "UploadMaxCount" int4 +) +; + +-- ---------------------------- +-- Records of Sys_TableInfo +-- ---------------------------- +INSERT INTO "public"."Sys_TableInfo" VALUES (2, '角色管理', '角色管理', NULL, NULL, NULL, NULL, NULL, 1, 'RoleName', 'System', 'VOL.System', NULL, 8, NULL, NULL, 'Sys_Role', NULL, NULL, NULL); +INSERT INTO "public"."Sys_TableInfo" VALUES (3, '字典数据', '字典数据', NULL, NULL, '字典明细', 'Sys_DictionaryList', NULL, 1, 'DicName', 'System', 'VOL.System', NULL, 11, NULL, NULL, 'Sys_Dictionary', NULL, NULL, NULL); +INSERT INTO "public"."Sys_TableInfo" VALUES (4, '字典明细', '字典明细', NULL, NULL, NULL, NULL, NULL, 1, NULL, 'System', 'VOL.System', NULL, 11, NULL, NULL, 'Sys_DictionaryList', NULL, NULL, NULL); +INSERT INTO "public"."Sys_TableInfo" VALUES (5, '系统日志', '系统日志', NULL, NULL, NULL, NULL, NULL, 1, NULL, 'System', 'VOL.System', NULL, 10, NULL, NULL, 'Sys_Log', 'Sys_Log', NULL, NULL); +INSERT INTO "public"."Sys_TableInfo" VALUES (6, NULL, '用户管理', NULL, NULL, NULL, NULL, NULL, 1, 'UserName', 'System', 'VOL.System', NULL, 8, NULL, NULL, 'Sys_User', 'Sys_User', 'HeadImageUrl', 1); +INSERT INTO "public"."Sys_TableInfo" VALUES (8, '用户基础信息', '用户基础信息', NULL, NULL, NULL, NULL, NULL, 1, NULL, 'System', 'VOL.System', 200, 0, NULL, NULL, '无', NULL, NULL, NULL); +INSERT INTO "public"."Sys_TableInfo" VALUES (10, '日志管理', '日志管理', NULL, NULL, NULL, NULL, NULL, 1, NULL, 'System', 'VOL.System', NULL, 0, NULL, '170', '日志管理', NULL, NULL, NULL); +INSERT INTO "public"."Sys_TableInfo" VALUES (11, '配置管理', '配置管理', NULL, NULL, NULL, NULL, NULL, 1, NULL, 'System', 'VOL.System', NULL, 0, NULL, '250', '配置管理', NULL, NULL, NULL); +INSERT INTO "public"."Sys_TableInfo" VALUES (15, '成交均价', '自动绑定下拉框', NULL, NULL, NULL, NULL, NULL, 1, 'AvgPrice', 'App', 'VOL.AppManager', NULL, 79, NULL, NULL, 'App_TransactionAvgPrice', 'App_TransactionAvgPrice', NULL, NULL); +INSERT INTO "public"."Sys_TableInfo" VALUES (16, NULL, '新增编辑表单', NULL, NULL, NULL, NULL, NULL, 1, 'Price', 'App', 'VOL.AppManager', NULL, 79, NULL, NULL, 'App_ReportPrice', NULL, NULL, NULL); +INSERT INTO "public"."Sys_TableInfo" VALUES (19, NULL, '导入导出', NULL, NULL, NULL, NULL, NULL, 1, '姓名', 'App', 'VOL.AppManager', NULL, 79, NULL, NULL, 'App_Transaction', NULL, NULL, NULL); +INSERT INTO "public"."Sys_TableInfo" VALUES (20, NULL, '启用图片支持', NULL, NULL, NULL, NULL, NULL, 1, 'UserName', 'App', 'VOL.AppManager', NULL, 79, NULL, NULL, 'App_Expert', NULL, 'HeadImageUrl', 1); +INSERT INTO "public"."Sys_TableInfo" VALUES (27, ' 资讯', '静态页面发布', NULL, NULL, NULL, NULL, NULL, 1, NULL, 'News', 'VOL.AppManager', NULL, 0, NULL, NULL, ' 资讯', NULL, NULL, NULL); +INSERT INTO "public"."Sys_TableInfo" VALUES (28, NULL, '新闻列表', NULL, NULL, NULL, NULL, NULL, 1, 'Title', 'News', 'VOL.AppManager', NULL, 27, 'Content', 'CreateDate', 'App_News', NULL, 'ImageUrl', 3); +INSERT INTO "public"."Sys_TableInfo" VALUES (76, '订单管理', '测试完整示例', NULL, NULL, NULL, NULL, NULL, 1, NULL, '订单管理', 'VOL.Order', NULL, 0, NULL, NULL, '订单管理', NULL, NULL, NULL); +INSERT INTO "public"."Sys_TableInfo" VALUES (77, '销售订单', '销售订单', NULL, NULL, '订单明细', 'SellOrderList', NULL, 1, 'TranNo', 'Sell', 'VOL.Order', NULL, 76, NULL, 'CreateDate', 'SellOrder', NULL, NULL, NULL); +INSERT INTO "public"."Sys_TableInfo" VALUES (78, '订单明细', '订单明细', NULL, NULL, NULL, NULL, NULL, 1, NULL, 'Order', 'VOL.Order', NULL, 76, NULL, 'CreateDate', 'SellOrderList', NULL, NULL, NULL); +INSERT INTO "public"."Sys_TableInfo" VALUES (79, 'Table 单表数据', 'Table+单表数据', NULL, NULL, NULL, NULL, NULL, 1, NULL, 'Order', 'VOL.Order', NULL, 0, NULL, NULL, 'Table+单表数据', NULL, NULL, NULL); +INSERT INTO "public"."Sys_TableInfo" VALUES (80, '基础表单查询', '基础表单+编辑只读', NULL, NULL, NULL, NULL, NULL, 1, 'Name', 'Appointment', 'VOL.Order', NULL, 79, NULL, 'CreateDate', 'App_Appointment', 'App_Appointment', NULL, NULL); +INSERT INTO "public"."Sys_TableInfo" VALUES (101, 'PGSQL测试', 'PGSQL测试', NULL, NULL, NULL, NULL, NULL, 1, NULL, 'PGSQL测试', 'VOL.AppManager', NULL, 0, NULL, NULL, 'PGSQL测试', NULL, NULL, NULL); +INSERT INTO "public"."Sys_TableInfo" VALUES (105, 'App_News_copy1', 'App_News_copy1', NULL, NULL, NULL, NULL, NULL, 1, NULL, 'Order', 'VOL.AppManager', NULL, 101, NULL, NULL, 'App_News_copy1', 'App_News_copy1', NULL, NULL); +INSERT INTO "public"."Sys_TableInfo" VALUES (106, 'app_news_copy1_copy1', 'app_news_copy1_copy1', NULL, NULL, NULL, NULL, NULL, 1, NULL, 'Order', 'VOL.AppManager', NULL, 101, NULL, NULL, 'App_news_copy1_copy1', 'App_news_copy1_copy1', NULL, NULL); +INSERT INTO "public"."Sys_TableInfo" VALUES (104, 'SellOrderList_copy1', 'SellOrderList_copy1', NULL, NULL, NULL, NULL, NULL, 1, NULL, 'Order', 'VOL.AppManager', NULL, 101, NULL, 'CreateDate', 'SellOrderList_copy1', 'SellOrderList_copy1', NULL, NULL); +INSERT INTO "public"."Sys_TableInfo" VALUES (103, 'SellOrder_copy1', 'SellOrder_copy1', NULL, NULL, 'SellOrderList_copy1', 'SellOrderList_copy1', NULL, 1, NULL, 'Order', 'VOL.AppManager', NULL, 101, NULL, 'CreateDate', 'SellOrder_copy1', 'SellOrder_copy1', NULL, NULL); + +-- ---------------------------- +-- Table structure for Sys_User +-- ---------------------------- +DROP TABLE IF EXISTS "public"."Sys_User"; +CREATE TABLE "public"."Sys_User" ( + "User_Id" int4 NOT NULL DEFAULT nextval('sys_user_id_seq'::regclass), + "Address" varchar(200) COLLATE "pg_catalog"."default", + "AppType" int4, + "AuditDate" timestamp(6), + "AuditStatus" int4, + "Auditor" varchar(200) COLLATE "pg_catalog"."default", + "CreateDate" timestamp(6), + "CreateID" int4, + "Creator" varchar(200) COLLATE "pg_catalog"."default", + "DeptName" varchar(150) COLLATE "pg_catalog"."default", + "Dept_Id" int4, + "Email" varchar(100) COLLATE "pg_catalog"."default", + "Enable" int2 NOT NULL, + "Gender" int4, + "HeadImageUrl" varchar(200) COLLATE "pg_catalog"."default", + "IsRegregisterPhone" int4 NOT NULL, + "LastLoginDate" timestamp(6), + "LastModifyPwdDate" timestamp(6), + "Mobile" varchar(100) COLLATE "pg_catalog"."default", + "Modifier" varchar(200) COLLATE "pg_catalog"."default", + "ModifyDate" timestamp(6), + "ModifyID" int4, + "OrderNo" int4, + "Role_Id" int4 NOT NULL, + "RoleName" varchar(150) COLLATE "pg_catalog"."default" NOT NULL, + "PhoneNo" varchar(11) COLLATE "pg_catalog"."default", + "Remark" varchar(200) COLLATE "pg_catalog"."default", + "Tel" varchar(20) COLLATE "pg_catalog"."default", + "UserName" varchar(100) COLLATE "pg_catalog"."default" NOT NULL, + "UserPwd" varchar(200) COLLATE "pg_catalog"."default", + "UserTrueName" varchar(20) COLLATE "pg_catalog"."default" NOT NULL, + "Token" varchar(500) COLLATE "pg_catalog"."default" +) +; + +-- ---------------------------- +-- Records of Sys_User +-- ---------------------------- +INSERT INTO "public"."Sys_User" VALUES (1, NULL, NULL, NULL, 1, NULL, '2020-06-14 20:14:58', NULL, NULL, NULL, NULL, NULL, 1, NULL, 'http://132.232.2.109:9991/Upload/Tables/Sys_User/202006191408112343/1111s.jpg', 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, '超级管理员', '12345678', NULL, NULL, 'admin', 'j79rYYvCz4vdhcboB1Ausg==', 'admin', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIxIiwiaWF0IjoiMTU5Njc5Nzc1OCIsIm5iZiI6IjE1OTY3OTc3NTgiLCJleHAiOiIxNTk2ODA0OTU4IiwiaXNzIjoidm9sLmNvcmUub3duZXIiLCJhdWQiOiJ2b2wuY29yZSJ9.NMHykN6HMwOQbOfD0qFNiM2b_CXtW7BYl6x6jIJX7LQ'); + +-- ---------------------------- +-- Table structure for news_article +-- ---------------------------- +DROP TABLE IF EXISTS "public"."news_article"; +CREATE TABLE "public"."news_article" ( + "Id" char(36) COLLATE "pg_catalog"."default" NOT NULL, + "CreateID" int4, + "Creator" varchar(30) COLLATE "pg_catalog"."default", + "CreateDate" timestamp(6), + "ModifyID" int4, + "Modifier" varchar(30) COLLATE "pg_catalog"."default", + "ModifyDate" timestamp(6), + "Author" varchar(50) COLLATE "pg_catalog"."default", + "Content" text COLLATE "pg_catalog"."default", + "Title" varchar(50) COLLATE "pg_catalog"."default" NOT NULL +) +; + +-- ---------------------------- +-- Records of news_article +-- ---------------------------- + +-- ---------------------------- +-- View structure for testview +-- ---------------------------- +DROP VIEW IF EXISTS "public"."testview"; +CREATE VIEW "public"."testview" AS SELECT "Sys_Log"."Id", + "Sys_Log"."BeginDate", + "Sys_Log"."BrowserType", + "Sys_Log"."ElapsedTime", + "Sys_Log"."EndDate", + "Sys_Log"."ExceptionInfo", + "Sys_Log"."LogType", + "Sys_Log"."RequestParameter", + "Sys_Log"."ResponseParameter", + "Sys_Log"."Role_Id", + "Sys_Log"."ServiceIP", + "Sys_Log"."Success", + "Sys_Log"."Url", + "Sys_Log"."UserIP", + "Sys_Log"."UserName", + "Sys_Log"."User_Id" + FROM "Sys_Log"; + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."app_expert_id_seq1"', 102, false); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."app_news111seq_id_seq"', 13, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."app_news_id_seq"', 3, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."app_reportprice_id1_seq"', 102, false); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."app_reportprice_id2_seq"', 102, false); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."app_reportprice_id_seq"', 9, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."app_transaction_id_seq"', 28, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."app_transactionavgprice_id_seq"', 17, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."appnews_id_seq"', 7, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."apptest_id_seq"', 6, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."city_id_seq"', 3, false); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."dic_id_seq"', 3, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."sellorder_id_seq"', 3, false); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."sellorderlist_id1_seq"', 3, false); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."sellorderlist_id_seq"', 3, false); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."sys_dictionary_id_seq1"', 102, false); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."sys_dictionarylist_id_seq"', 503, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."sys_log_id_seq"', 46, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."sys_menu_id_seq"', 102, false); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."sys_province1_id_seq"', 502, false); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."sys_province_id_seq"', 102, false); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."sys_role_id_seq"', 103, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."sys_role_id_seq1"', 3, false); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."sys_roleauth_id_seq"', 102, false); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."sys_roleauthdata_id_seq"', 102, false); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."sys_tablecolumn_id_seq"', 927, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."sys_tableinfo_id_seq"', 107, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +SELECT setval('"public"."sys_user_id_seq"', 5, true); + +-- ---------------------------- +-- Primary Key structure for table App_Expert +-- ---------------------------- +ALTER TABLE "public"."App_Expert" ADD CONSTRAINT "app_expert_pkey" PRIMARY KEY ("ExpertId"); + +-- ---------------------------- +-- Primary Key structure for table App_News +-- ---------------------------- +ALTER TABLE "public"."App_News" ADD CONSTRAINT "app_news_pkey" PRIMARY KEY ("Id"); + +-- ---------------------------- +-- Primary Key structure for table App_Reportprice +-- ---------------------------- +ALTER TABLE "public"."App_Reportprice" ADD CONSTRAINT "app_reportprice_pkey" PRIMARY KEY ("Id"); + +-- ---------------------------- +-- Primary Key structure for table App_Transaction +-- ---------------------------- +ALTER TABLE "public"."App_Transaction" ADD CONSTRAINT "app_transaction_pkey" PRIMARY KEY ("Id"); + +-- ---------------------------- +-- Primary Key structure for table App_TransactionAvgPrice +-- ---------------------------- +ALTER TABLE "public"."App_TransactionAvgPrice" ADD CONSTRAINT "app_transactionavgprice_pkey" PRIMARY KEY ("Id"); + +-- ---------------------------- +-- Primary Key structure for table SellOrder +-- ---------------------------- +ALTER TABLE "public"."SellOrder" ADD CONSTRAINT "SellOrder_pkey" PRIMARY KEY ("Order_Id"); + +-- ---------------------------- +-- Primary Key structure for table SellOrderList +-- ---------------------------- +ALTER TABLE "public"."SellOrderList" ADD CONSTRAINT "sellorderlist_pkey" PRIMARY KEY ("OrderList_Id"); + +-- ---------------------------- +-- Primary Key structure for table Sys_City +-- ---------------------------- +ALTER TABLE "public"."Sys_City" ADD CONSTRAINT "sys_city_pkey" PRIMARY KEY ("CityId"); + +-- ---------------------------- +-- Primary Key structure for table Sys_Dictionary +-- ---------------------------- +ALTER TABLE "public"."Sys_Dictionary" ADD CONSTRAINT "Sys_Dictionary_pkey" PRIMARY KEY ("Dic_ID"); + +-- ---------------------------- +-- Primary Key structure for table Sys_DictionaryList +-- ---------------------------- +ALTER TABLE "public"."Sys_DictionaryList" ADD CONSTRAINT "Sys_DictionaryList_pkey" PRIMARY KEY ("DicList_ID"); + +-- ---------------------------- +-- Primary Key structure for table Sys_Log +-- ---------------------------- +ALTER TABLE "public"."Sys_Log" ADD CONSTRAINT "sys_log_pkey" PRIMARY KEY ("Id"); + +-- ---------------------------- +-- Primary Key structure for table Sys_Menu +-- ---------------------------- +ALTER TABLE "public"."Sys_Menu" ADD CONSTRAINT "sys_menu_pkey" PRIMARY KEY ("Menu_Id"); + +-- ---------------------------- +-- Primary Key structure for table Sys_Province +-- ---------------------------- +ALTER TABLE "public"."Sys_Province" ADD CONSTRAINT "sys_province_pkey" PRIMARY KEY ("ProvinceId"); + +-- ---------------------------- +-- Primary Key structure for table Sys_Role +-- ---------------------------- +ALTER TABLE "public"."Sys_Role" ADD CONSTRAINT "sys_role_pkey" PRIMARY KEY ("Role_Id"); + +-- ---------------------------- +-- Primary Key structure for table Sys_RoleAuth +-- ---------------------------- +ALTER TABLE "public"."Sys_RoleAuth" ADD CONSTRAINT "sys_roleauth_pkey" PRIMARY KEY ("Auth_Id"); + +-- ---------------------------- +-- Primary Key structure for table Sys_RoleAuthData +-- ---------------------------- +ALTER TABLE "public"."Sys_RoleAuthData" ADD CONSTRAINT "sys_roleauthdata_pkey" PRIMARY KEY ("Auth_Id"); + +-- ---------------------------- +-- Primary Key structure for table Sys_TableColumn +-- ---------------------------- +ALTER TABLE "public"."Sys_TableColumn" ADD CONSTRAINT "sys_tablecolumn_pkey" PRIMARY KEY ("ColumnId"); + +-- ---------------------------- +-- Primary Key structure for table Sys_TableInfo +-- ---------------------------- +ALTER TABLE "public"."Sys_TableInfo" ADD CONSTRAINT "sys_tableinfo_pkey" PRIMARY KEY ("Table_Id"); + +-- ---------------------------- +-- Primary Key structure for table Sys_User +-- ---------------------------- +ALTER TABLE "public"."Sys_User" ADD CONSTRAINT "sys_user_pkey" PRIMARY KEY ("User_Id"); +ALTER TABLE "public"."Sys_Menu" ADD "MenuType" int4 diff --git "a/Pure_Vite_Net7/DB/pgsql/pgsql\344\275\277\347\224\250\350\257\264\346\230\216.txt" "b/Pure_Vite_Net7/DB/pgsql/pgsql\344\275\277\347\224\250\350\257\264\346\230\216.txt" new file mode 100644 index 0000000000000000000000000000000000000000..5682465e1308aa468b06dff5280e7077de509ff3 --- /dev/null +++ "b/Pure_Vite_Net7/DB/pgsql/pgsql\344\275\277\347\224\250\350\257\264\346\230\216.txt" @@ -0,0 +1,4 @@ +1.ݱȫСд + Ҫʹôд޸:Sys_TableInfoService.cs + tableTrueName = tableTrueName.ToLower(); Ϊ tableTrueName = tableTrueName.ToUpper() + ֶVOL.Entity->DomainModelsʵֵtableԸΪд diff --git "a/Pure_Vite_Net7/DB/sqlserver/\350\241\250\347\273\223\346\236\204\344\270\216\346\225\260\346\215\256.sql" "b/Pure_Vite_Net7/DB/sqlserver/\350\241\250\347\273\223\346\236\204\344\270\216\346\225\260\346\215\256.sql" new file mode 100644 index 0000000000000000000000000000000000000000..201db807bef7cc07d47bf5400d30d735e054b6ce Binary files /dev/null and "b/Pure_Vite_Net7/DB/sqlserver/\350\241\250\347\273\223\346\236\204\344\270\216\346\225\260\346\215\256.sql" differ diff --git a/Pure_Vite_Net7/Vue3Vite/.browserslistrc b/Pure_Vite_Net7/Vue3Vite/.browserslistrc new file mode 100644 index 0000000000000000000000000000000000000000..214388fe43cdfd7ce1c29cd3e401541ded620dba --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/.browserslistrc @@ -0,0 +1,3 @@ +> 1% +last 2 versions +not dead diff --git a/Pure_Vite_Net7/Vue3Vite/.env b/Pure_Vite_Net7/Vue3Vite/.env new file mode 100644 index 0000000000000000000000000000000000000000..e29fda95c31346f0552464494678c0e5d5a567c9 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/.env @@ -0,0 +1 @@ +VITE_WEBAPI_BASE_URL = 'http://127.0.0.1:9991/' \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/.eslintrc.cjs b/Pure_Vite_Net7/Vue3Vite/.eslintrc.cjs new file mode 100644 index 0000000000000000000000000000000000000000..6f40582dda70241afd3bbd38da6853278bef4aaf --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/.eslintrc.cjs @@ -0,0 +1,15 @@ +/* eslint-env node */ +require('@rushstack/eslint-patch/modern-module-resolution') + +module.exports = { + root: true, + 'extends': [ + 'plugin:vue/vue3-essential', + 'eslint:recommended', + '@vue/eslint-config-typescript', + '@vue/eslint-config-prettier/skip-formatting' + ], + parserOptions: { + ecmaVersion: 'latest' + } +} diff --git a/Pure_Vite_Net7/Vue3Vite/.eslintrc.js b/Pure_Vite_Net7/Vue3Vite/.eslintrc.js new file mode 100644 index 0000000000000000000000000000000000000000..0051744e0eed83eedd0d257dfab9fcccc4c3ebc8 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/.eslintrc.js @@ -0,0 +1,28 @@ +export default { + root: true, + env: { + node: true + }, + 'extends': [ + 'plugin:vue/vue3-essential', + 'eslint:recommended' + ], + parserOptions: { + parser: 'babel-eslint', + }, + rules: { + 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', + 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off' + }, + overrides: [ + { + files: [ + '**/__tests__/*.{j,t}s?(x)', + '**/tests/unit/**/*.spec.{j,t}s?(x)' + ], + env: { + mocha: true + } + } + ] +} diff --git a/Pure_Vite_Net7/Vue3Vite/.gitignore b/Pure_Vite_Net7/Vue3Vite/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..403adbc1e527906a4aa59558cd582c20bcd1d738 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/.gitignore @@ -0,0 +1,23 @@ +.DS_Store +node_modules +/dist + + +# local env files +.env.local +.env.*.local + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/Pure_Vite_Net7/Vue3Vite/.prettierrc.json b/Pure_Vite_Net7/Vue3Vite/.prettierrc.json new file mode 100644 index 0000000000000000000000000000000000000000..66e23359c3dabfe3929b4e2fa049c41037afb15f --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/.prettierrc.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/prettierrc", + "semi": false, + "tabWidth": 2, + "singleQuote": true, + "printWidth": 100, + "trailingComma": "none" +} \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/README.md b/Pure_Vite_Net7/Vue3Vite/README.md new file mode 100644 index 0000000000000000000000000000000000000000..06bd5874ec6e9a03b027320015765c35b0745d46 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/README.md @@ -0,0 +1,29 @@ +# vol.vue3 + +## Project setup +``` +npm install +``` + +### Compiles and hot-reloads for development +``` +npm run serve +``` + +### Compiles and minifies for production +``` +npm run build +``` + +### Run your unit tests +``` +npm run test:unit +``` + +### Lints and fixes files +``` +npm run lint +``` + +### Customize configuration +See [Configuration Reference](https://cli.vuejs.org/config/). diff --git a/Pure_Vite_Net7/Vue3Vite/babel.config.js b/Pure_Vite_Net7/Vue3Vite/babel.config.js new file mode 100644 index 0000000000000000000000000000000000000000..e9558405fdcc02f12d757acb308e02937a7444f1 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/babel.config.js @@ -0,0 +1,5 @@ +module.exports = { + presets: [ + '@vue/cli-plugin-babel/preset' + ] +} diff --git a/Pure_Vite_Net7/Vue3Vite/build.bat b/Pure_Vite_Net7/Vue3Vite/build.bat new file mode 100644 index 0000000000000000000000000000000000000000..10da9ff7d4e65f49e3b1823a4b79e55a11c14a19 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/build.bat @@ -0,0 +1 @@ +npm run build \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/env.d.ts b/Pure_Vite_Net7/Vue3Vite/env.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..11f02fe2a0061d6e6e1f271b21da95423b448b32 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/Pure_Vite_Net7/Vue3Vite/index.html b/Pure_Vite_Net7/Vue3Vite/index.html new file mode 100644 index 0000000000000000000000000000000000000000..65db55570f7736c23d75274ed86582f6edc59199 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/index.html @@ -0,0 +1,133 @@ + + + + + + + + vol + + + + +
+ + + + + + + + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/install.bat b/Pure_Vite_Net7/Vue3Vite/install.bat new file mode 100644 index 0000000000000000000000000000000000000000..be01f16dc97a2f0dc34a9f7734c0dc36037e2fef --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/install.bat @@ -0,0 +1 @@ +npm cache clear --force & npm install \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/package-lock.json b/Pure_Vite_Net7/Vue3Vite/package-lock.json new file mode 100644 index 0000000000000000000000000000000000000000..9d7f3b329c53d574488143e90232bd55c06420a9 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/package-lock.json @@ -0,0 +1,6656 @@ +{ + "name": "vol-vue3vite", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "vol-vue3vite", + "version": "0.0.1", + "dependencies": { + "@microsoft/signalr": "^7.0.3", + "axios": "^1.3.4", + "core-js": "^3.29.0", + "echarts": "^5.4.1", + "element-plus": "^2.2.32", + "less": "^4.1.3", + "pinia": "^2.0.32", + "vue": "^3.2.47", + "vue-draggable-next": "^2.1.1", + "vue-router": "^4.1.6", + "vuex": "^4.1.0", + "wangeditor": "^4.7.15" + }, + "devDependencies": { + "@babel/eslint-parser": "^7.21.3", + "@rushstack/eslint-patch": "^1.2.0", + "@types/jsdom": "^21.1.0", + "@types/node": "^18.14.2", + "@vitejs/plugin-vue": "^4.0.0", + "@vitejs/plugin-vue-jsx": "^3.0.0", + "@vue/eslint-config-prettier": "^7.1.0", + "@vue/eslint-config-typescript": "^11.0.2", + "@vue/test-utils": "^2.3.0", + "@vue/tsconfig": "^0.1.3", + "eslint": "^8.36.0", + "eslint-plugin-vue": "^9.9.0", + "jsdom": "^21.1.0", + "npm-run-all": "^4.1.5", + "prettier": "^2.8.4", + "rimraf": "^4.1.2", + "rollup-plugin-visualizer": "^5.9.0", + "stylus": "^0.59.0", + "typescript": "~4.8.4", + "vite": "^4.2.0", + "vitest": "^0.29.1", + "vue-tsc": "^1.2.0" + } + }, + "node_modules/@adobe/css-tools": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@adobe/css-tools/-/css-tools-4.2.0.tgz", + "integrity": "sha512-E09FiIft46CmH5Qnjb0wsW54/YQd69LsxeKUOWawmws1XWvyFGURnAChH0mlr7YPFR1ofwvUQfcL0J3lMxXqPA==", + "dev": true + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.21.0", + "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.21.0.tgz", + "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.21.0", + "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.21.0.tgz", + "integrity": "sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.21.0", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-module-transforms": "^7.21.0", + "@babel/helpers": "^7.21.0", + "@babel/parser": "^7.21.0", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.21.0", + "@babel/types": "^7.21.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/eslint-parser": { + "version": "7.21.3", + "resolved": "https://registry.npmmirror.com/@babel/eslint-parser/-/eslint-parser-7.21.3.tgz", + "integrity": "sha512-kfhmPimwo6k4P8zxNs8+T7yR44q1LdpsZdE1NkCsVlfiuTPRfnGgjaF8Qgug9q9Pou17u6wneYF0lDCZJATMFg==", + "dev": true, + "dependencies": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.11.0", + "eslint": "^7.5.0 || ^8.0.0" + } + }, + "node_modules/@babel/eslint-parser/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@babel/generator": { + "version": "7.21.1", + "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.21.1.tgz", + "integrity": "sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.21.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.20.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", + "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.20.5", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.21.3", + "lru-cache": "^5.1.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.21.0", + "resolved": "https://registry.npmmirror.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.0.tgz", + "integrity": "sha512-Q8wNiMIdwsv5la5SPxNYzzkPnjgC0Sy0i7jLkVOCdllu/xcVNkr3TeZzbHBJrj+XXRqzX5uCyCoV9eu6xUG7KQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.21.0", + "@babel/helper-member-expression-to-functions": "^7.21.0", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.20.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/helper-split-export-declaration": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmmirror.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.21.0", + "resolved": "https://registry.npmmirror.com/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", + "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.20.7", + "@babel/types": "^7.21.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.21.0", + "resolved": "https://registry.npmmirror.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.0.tgz", + "integrity": "sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.21.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.21.2", + "resolved": "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", + "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.20.2", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.19.1", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.21.2", + "@babel/types": "^7.21.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.20.2", + "resolved": "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", + "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.20.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz", + "integrity": "sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.20.7", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.7", + "@babel/types": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.20.2", + "resolved": "https://registry.npmmirror.com/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", + "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.20.0", + "resolved": "https://registry.npmmirror.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz", + "integrity": "sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.19.4", + "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", + "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.19.1", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.21.0", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", + "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.21.0", + "resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.21.0.tgz", + "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", + "dev": true, + "dependencies": { + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.21.0", + "@babel/types": "^7.21.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmmirror.com/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.21.2", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.21.2.tgz", + "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.18.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", + "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.20.0", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz", + "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.21.0", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.21.0.tgz", + "integrity": "sha512-xo///XTPp3mDzTtrqXoBlK9eiAYW3wv9JXglcn/u1bi60RW11dEUxIgA8cbnDhutS1zacjMRmAwxE0gMklLnZg==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-typescript": "^7.20.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.21.0", + "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.21.0.tgz", + "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", + "dependencies": { + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime-corejs3": { + "version": "7.21.0", + "resolved": "https://registry.npmmirror.com/@babel/runtime-corejs3/-/runtime-corejs3-7.21.0.tgz", + "integrity": "sha512-TDD4UJzos3JJtM+tHX+w2Uc+KWj7GV+VKKFdMVd2Rx8sdA19hcc3P3AHFYd5LVOw+pYuSd5lICC3gm52B6Rwxw==", + "dependencies": { + "core-js-pure": "^3.25.1", + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.20.7", + "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.20.7.tgz", + "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.21.2", + "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.21.2.tgz", + "integrity": "sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.21.1", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.21.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.21.2", + "@babel/types": "^7.21.2", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.21.2", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.21.2.tgz", + "integrity": "sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-validator-identifier": "^7.19.1", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@ctrl/tinycolor": { + "version": "3.6.0", + "resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.6.0.tgz", + "integrity": "sha512-/Z3l6pXthq0JvMYdUFyX9j0MaCltlIn6mfh9jLyQwg5aPKxkyNa0PTHtU1AlFXLNk55ZuAeJRcpvq+tmLfKmaQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@element-plus/icons-vue": { + "version": "2.0.10", + "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.0.10.tgz", + "integrity": "sha512-ygEZ1mwPjcPo/OulhzLE7mtDrQBWI8vZzEWSNB2W/RNCRjoQGwbaK4N8lV4rid7Ts4qvySU3njMN7YCiSlSaTQ==", + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.17.12", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.17.12.tgz", + "integrity": "sha512-E/sgkvwoIfj4aMAPL2e35VnUJspzVYl7+M1B2cqeubdBhADV4uPon0KCc8p2G+LqSJ6i8ocYPCqY3A4GGq0zkQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.17.12", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.17.12.tgz", + "integrity": "sha512-WQ9p5oiXXYJ33F2EkE3r0FRDFVpEdcDiwNX3u7Xaibxfx6vQE0Sb8ytrfQsA5WO6kDn6mDfKLh6KrPBjvkk7xA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.17.12", + "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.17.12.tgz", + "integrity": "sha512-m4OsaCr5gT+se25rFPHKQXARMyAehHTQAz4XX1Vk3d27VtqiX0ALMBPoXZsGaB6JYryCLfgGwUslMqTfqeLU0w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.17.12", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.12.tgz", + "integrity": "sha512-O3GCZghRIx+RAN0NDPhyyhRgwa19MoKlzGonIb5hgTj78krqp9XZbYCvFr9N1eUxg0ZQEpiiZ4QvsOQwBpP+lg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.17.12", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.17.12.tgz", + "integrity": "sha512-5D48jM3tW27h1qjaD9UNRuN+4v0zvksqZSPZqeSWggfMlsVdAhH3pwSfQIFJwcs9QJ9BRibPS4ViZgs3d2wsCA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.17.12", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.12.tgz", + "integrity": "sha512-OWvHzmLNTdF1erSvrfoEBGlN94IE6vCEaGEkEH29uo/VoONqPnoDFfShi41Ew+yKimx4vrmmAJEGNoyyP+OgOQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.17.12", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.12.tgz", + "integrity": "sha512-A0Xg5CZv8MU9xh4a+7NUpi5VHBKh1RaGJKqjxe4KG87X+mTjDE6ZvlJqpWoeJxgfXHT7IMP9tDFu7IZ03OtJAw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.17.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.17.12.tgz", + "integrity": "sha512-WsHyJ7b7vzHdJ1fv67Yf++2dz3D726oO3QCu8iNYik4fb5YuuReOI9OtA+n7Mk0xyQivNTPbl181s+5oZ38gyA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.17.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.17.12.tgz", + "integrity": "sha512-cK3AjkEc+8v8YG02hYLQIQlOznW+v9N+OI9BAFuyqkfQFR+DnDLhEM5N8QRxAUz99cJTo1rLNXqRrvY15gbQUg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.17.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.17.12.tgz", + "integrity": "sha512-jdOBXJqcgHlah/nYHnj3Hrnl9l63RjtQ4vn9+bohjQPI2QafASB5MtHAoEv0JQHVb/xYQTFOeuHnNYE1zF7tYw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.17.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.17.12.tgz", + "integrity": "sha512-GTOEtj8h9qPKXCyiBBnHconSCV9LwFyx/gv3Phw0pa25qPYjVuuGZ4Dk14bGCfGX3qKF0+ceeQvwmtI+aYBbVA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.17.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.12.tgz", + "integrity": "sha512-o8CIhfBwKcxmEENOH9RwmUejs5jFiNoDw7YgS0EJTF6kgPgcqLFjgoc5kDey5cMHRVCIWc6kK2ShUePOcc7RbA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.17.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.12.tgz", + "integrity": "sha512-biMLH6NR/GR4z+ap0oJYb877LdBpGac8KfZoEnDiBKd7MD/xt8eaw1SFfYRUeMVx519kVkAOL2GExdFmYnZx3A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.17.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.12.tgz", + "integrity": "sha512-jkphYUiO38wZGeWlfIBMB72auOllNA2sLfiZPGDtOBb1ELN8lmqBrlMiucgL8awBw1zBXN69PmZM6g4yTX84TA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.17.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.17.12.tgz", + "integrity": "sha512-j3ucLdeY9HBcvODhCY4b+Ds3hWGO8t+SAidtmWu/ukfLLG/oYDMaA+dnugTVAg5fnUOGNbIYL9TOjhWgQB8W5g==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.17.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.17.12.tgz", + "integrity": "sha512-uo5JL3cgaEGotaqSaJdRfFNSCUJOIliKLnDGWaVCgIKkHxwhYMm95pfMbWZ9l7GeW9kDg0tSxcy9NYdEtjwwmA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.17.12", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.12.tgz", + "integrity": "sha512-DNdoRg8JX+gGsbqt2gPgkgb00mqOgOO27KnrWZtdABl6yWTST30aibGJ6geBq3WM2TIeW6COs5AScnC7GwtGPg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.17.12", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.12.tgz", + "integrity": "sha512-aVsENlr7B64w8I1lhHShND5o8cW6sB9n9MUtLumFlPhG3elhNWtE7M1TFpj3m7lT3sKQUMkGFjTQBrvDDO1YWA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.17.12", + "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.17.12.tgz", + "integrity": "sha512-qbHGVQdKSwi0JQJuZznS4SyY27tYXYF0mrgthbxXrZI3AHKuRvU+Eqbg/F0rmLDpW/jkIZBlCO1XfHUBMNJ1pg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.17.12", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.17.12.tgz", + "integrity": "sha512-zsCp8Ql+96xXTVTmm6ffvoTSZSV2B/LzzkUXAY33F/76EajNw1m+jZ9zPfNJlJ3Rh4EzOszNDHsmG/fZOhtqDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.17.12", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.17.12.tgz", + "integrity": "sha512-FfrFjR4id7wcFYOdqbDfDET3tjxCozUgbqdkOABsSFzoZGFC92UK7mg4JKRc/B3NNEf1s2WHxJ7VfTdVDPN3ng==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.17.12", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.17.12.tgz", + "integrity": "sha512-JOOxw49BVZx2/5tW3FqkdjSD/5gXYeVGPDcB0lvap0gLQshkh1Nyel1QazC+wNxus3xPlsYAgqU1BUmrmCvWtw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.3.0.tgz", + "integrity": "sha512-v3oplH6FYCULtFuCeqyuTd9D2WKO937Dxdq+GmHOLL72TTRriLxz2VLlNfkZRsvj6PKnOPAtuT6dwrs/pA5DvA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.4.0", + "resolved": "https://registry.npmmirror.com/@eslint-community/regexpp/-/regexpp-4.4.0.tgz", + "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", + "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.5.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmmirror.com/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@eslint/js": { + "version": "8.36.0", + "resolved": "https://registry.npmmirror.com/@eslint/js/-/js-8.36.0.tgz", + "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.2.1.tgz", + "integrity": "sha512-LSqwPZkK3rYfD7GKoIeExXOyYx6Q1O4iqZWwIehDNuv3Dv425FIAE8PRwtAx1imEolFTHgBEcoFHm9MDnYgPCg==" + }, + "node_modules/@floating-ui/dom": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.2.1.tgz", + "integrity": "sha512-Rt45SmRiV8eU+xXSB9t0uMYiQ/ZWGE/jumse2o3i5RGlyvcbqOF4q+1qBnzLE2kZ5JGhq0iMkcGXUKbFe7MpTA==", + "dependencies": { + "@floating-ui/core": "^1.2.1" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmmirror.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.17", + "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "node_modules/@microsoft/signalr": { + "version": "7.0.3", + "resolved": "https://registry.npmmirror.com/@microsoft/signalr/-/signalr-7.0.3.tgz", + "integrity": "sha512-gQbrCQxvC/djy+/GBHFpNnAqubGLe0Hrp3ZO8x8NRGAU8jhj3QcHuxhq6N5Z3A0zI6IE/fMfX2xSheQxOwA3ZA==", + "dependencies": { + "abort-controller": "^3.0.0", + "eventsource": "^2.0.2", + "fetch-cookie": "^2.0.3", + "node-fetch": "^2.6.7", + "ws": "^7.4.5" + } + }, + "node_modules/@microsoft/signalr/node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmmirror.com/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmmirror.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dev": true, + "dependencies": { + "eslint-scope": "5.1.1" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@popperjs/core": { + "name": "@sxzz/popperjs-es", + "version": "2.11.7", + "resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz", + "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==" + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz", + "integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==", + "dev": true + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/chai": { + "version": "4.3.4", + "resolved": "https://registry.npmmirror.com/@types/chai/-/chai-4.3.4.tgz", + "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", + "dev": true + }, + "node_modules/@types/chai-subset": { + "version": "1.3.3", + "resolved": "https://registry.npmmirror.com/@types/chai-subset/-/chai-subset-1.3.3.tgz", + "integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==", + "dev": true, + "dependencies": { + "@types/chai": "*" + } + }, + "node_modules/@types/jsdom": { + "version": "21.1.0", + "resolved": "https://registry.npmmirror.com/@types/jsdom/-/jsdom-21.1.0.tgz", + "integrity": "sha512-leWreJOdnuIxq9Y70tBVm/bvTuh31DSlF/r4l7Cfi4uhVQqLHD0Q4v301GMisEMwwbMgF7ZKxuZ+Jbd4NcdmRw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "node_modules/@types/lodash": { + "version": "4.14.191", + "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.14.191.tgz", + "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.6", + "resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.6.tgz", + "integrity": "sha512-R+zTeVUKDdfoRxpAryaQNRKk3105Rrgx2CFRClIgRGaqDTdjsm8h6IYA8ir584W3ePzkZfst5xIgDwYrlh9HLg==", + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/node": { + "version": "18.14.2", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-18.14.2.tgz", + "integrity": "sha512-1uEQxww3DaghA0RxqHx0O0ppVlo43pJhepY51OxuQIKHpjbnYLA7vcdwioNPzIqmC2u3I/dmylcqjlh0e7AyUA==", + "dev": true + }, + "node_modules/@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmmirror.com/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/@types/tough-cookie/-/tough-cookie-4.0.2.tgz", + "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==", + "dev": true + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.16", + "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", + "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.54.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.0.tgz", + "integrity": "sha512-+hSN9BdSr629RF02d7mMtXhAJvDTyCbprNYJKrXETlul/Aml6YZwd90XioVbjejQeHbb3R8Dg0CkRgoJDxo8aw==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.54.0", + "@typescript-eslint/type-utils": "5.54.0", + "@typescript-eslint/utils": "5.54.0", + "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.54.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-5.54.0.tgz", + "integrity": "sha512-aAVL3Mu2qTi+h/r04WI/5PfNWvO6pdhpeMRWk9R7rEV4mwJNzoWf5CCU5vDKBsPIFQFjEq1xg7XBI2rjiMXQbQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.54.0", + "@typescript-eslint/types": "5.54.0", + "@typescript-eslint/typescript-estree": "5.54.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.54.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-5.54.0.tgz", + "integrity": "sha512-VTPYNZ7vaWtYna9M4oD42zENOBrb+ZYyCNdFs949GcN8Miwn37b8b7eMj+EZaq7VK9fx0Jd+JhmkhjFhvnovhg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.54.0", + "@typescript-eslint/visitor-keys": "5.54.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.54.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-5.54.0.tgz", + "integrity": "sha512-WI+WMJ8+oS+LyflqsD4nlXMsVdzTMYTxl16myXPaCXnSgc7LWwMsjxQFZCK/rVmTZ3FN71Ct78ehO9bRC7erYQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.54.0", + "@typescript-eslint/utils": "5.54.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.54.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-5.54.0.tgz", + "integrity": "sha512-nExy+fDCBEgqblasfeE3aQ3NuafBUxZxgxXcYfzYRZFHdVvk5q60KhCSkG0noHgHRo/xQ/BOzURLZAafFpTkmQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.54.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.0.tgz", + "integrity": "sha512-X2rJG97Wj/VRo5YxJ8Qx26Zqf0RRKsVHd4sav8NElhbZzhpBI8jU54i6hfo9eheumj4oO4dcRN1B/zIVEqR/MQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.54.0", + "@typescript-eslint/visitor-keys": "5.54.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.54.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-5.54.0.tgz", + "integrity": "sha512-cuwm8D/Z/7AuyAeJ+T0r4WZmlnlxQ8wt7C7fLpFlKMR+dY6QO79Cq1WpJhvZbMA4ZeZGHiRWnht7ZJ8qkdAunw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.54.0", + "@typescript-eslint/types": "5.54.0", + "@typescript-eslint/typescript-estree": "5.54.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.54.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.0.tgz", + "integrity": "sha512-xu4wT7aRCakGINTLGeyGqDn+78BwFlggwBjnHa1ar/KaGagnmwLYmlrXIrgAaQ3AE1Vd6nLfKASm7LrFHNbKGA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.54.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@vitejs/plugin-vue": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-4.0.0.tgz", + "integrity": "sha512-e0X4jErIxAB5oLtDqbHvHpJe/uWNkdpYV83AOG2xo2tEVSzCzewgJMtREZM30wXnM5ls90hxiOtAuVU6H5JgbA==", + "dev": true, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vitejs/plugin-vue-jsx": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue-jsx/-/plugin-vue-jsx-3.0.0.tgz", + "integrity": "sha512-vurkuzgac5SYuxd2HUZqAFAWGTF10diKBwJNbCvnWijNZfXd+7jMtqjPFbGt7idOJUn584fP1Ar9j/GN2jQ3Ew==", + "dev": true, + "dependencies": { + "@babel/core": "^7.20.5", + "@babel/plugin-transform-typescript": "^7.20.2", + "@vue/babel-plugin-jsx": "^1.1.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.0.0", + "vue": "^3.0.0" + } + }, + "node_modules/@vitest/expect": { + "version": "0.29.2", + "resolved": "https://registry.npmmirror.com/@vitest/expect/-/expect-0.29.2.tgz", + "integrity": "sha512-wjrdHB2ANTch3XKRhjWZN0UueFocH0cQbi2tR5Jtq60Nb3YOSmakjdAvUa2JFBu/o8Vjhj5cYbcMXkZxn1NzmA==", + "dev": true, + "dependencies": { + "@vitest/spy": "0.29.2", + "@vitest/utils": "0.29.2", + "chai": "^4.3.7" + } + }, + "node_modules/@vitest/runner": { + "version": "0.29.2", + "resolved": "https://registry.npmmirror.com/@vitest/runner/-/runner-0.29.2.tgz", + "integrity": "sha512-A1P65f5+6ru36AyHWORhuQBJrOOcmDuhzl5RsaMNFe2jEkoj0faEszQS4CtPU/LxUYVIazlUtZTY0OEZmyZBnA==", + "dev": true, + "dependencies": { + "@vitest/utils": "0.29.2", + "p-limit": "^4.0.0", + "pathe": "^1.1.0" + } + }, + "node_modules/@vitest/runner/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/@vitest/runner/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + } + }, + "node_modules/@vitest/spy": { + "version": "0.29.2", + "resolved": "https://registry.npmmirror.com/@vitest/spy/-/spy-0.29.2.tgz", + "integrity": "sha512-Hc44ft5kaAytlGL2PyFwdAsufjbdOvHklwjNy/gy/saRbg9Kfkxfh+PklLm1H2Ib/p586RkQeNFKYuJInUssyw==", + "dev": true, + "dependencies": { + "tinyspy": "^1.0.2" + } + }, + "node_modules/@vitest/utils": { + "version": "0.29.2", + "resolved": "https://registry.npmmirror.com/@vitest/utils/-/utils-0.29.2.tgz", + "integrity": "sha512-F14/Uc+vCdclStS2KEoXJlOLAEyqRhnw0gM27iXw9bMTcyKRPJrQ+rlC6XZ125GIPvvKYMPpVxNhiou6PsEeYQ==", + "dev": true, + "dependencies": { + "cli-truncate": "^3.1.0", + "diff": "^5.1.0", + "loupe": "^2.3.6", + "picocolors": "^1.0.0", + "pretty-format": "^27.5.1" + } + }, + "node_modules/@volar/language-core": { + "version": "1.3.0-alpha.0", + "resolved": "https://registry.npmmirror.com/@volar/language-core/-/language-core-1.3.0-alpha.0.tgz", + "integrity": "sha512-W3uMzecHPcbwddPu4SJpUcPakRBK/y/BP+U0U6NiPpUX1tONLC4yCawt+QBJqtgJ+sfD6ztf5PyvPL3hQRqfOA==", + "dev": true, + "dependencies": { + "@volar/source-map": "1.3.0-alpha.0" + } + }, + "node_modules/@volar/source-map": { + "version": "1.3.0-alpha.0", + "resolved": "https://registry.npmmirror.com/@volar/source-map/-/source-map-1.3.0-alpha.0.tgz", + "integrity": "sha512-jSdizxWFvDTvkPYZnO6ew3sBZUnS0abKCbuopkc0JrIlFbznWC/fPH3iPFIMS8/IIkRxq1Jh9VVG60SmtsdaMQ==", + "dev": true, + "dependencies": { + "muggle-string": "^0.2.2" + } + }, + "node_modules/@volar/typescript": { + "version": "1.3.0-alpha.0", + "resolved": "https://registry.npmmirror.com/@volar/typescript/-/typescript-1.3.0-alpha.0.tgz", + "integrity": "sha512-5UItyW2cdH2mBLu4RrECRNJRgtvvzKrSCn2y3v/D61QwIDkGx4aeil6x8RFuUL5TFtV6QvVHXnsOHxNgd+sCow==", + "dev": true, + "dependencies": { + "@volar/language-core": "1.3.0-alpha.0" + } + }, + "node_modules/@volar/vue-language-core": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/@volar/vue-language-core/-/vue-language-core-1.2.0.tgz", + "integrity": "sha512-w7yEiaITh2WzKe6u8ZdeLKCUz43wdmY/OqAmsB/PGDvvhTcVhCJ6f0W/RprZL1IhqH8wALoWiwEh/Wer7ZviMQ==", + "dev": true, + "dependencies": { + "@volar/language-core": "1.3.0-alpha.0", + "@volar/source-map": "1.3.0-alpha.0", + "@vue/compiler-dom": "^3.2.47", + "@vue/compiler-sfc": "^3.2.47", + "@vue/reactivity": "^3.2.47", + "@vue/shared": "^3.2.47", + "minimatch": "^6.1.6", + "muggle-string": "^0.2.2", + "vue-template-compiler": "^2.7.14" + } + }, + "node_modules/@volar/vue-language-core/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@volar/vue-language-core/node_modules/minimatch": { + "version": "6.2.0", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-6.2.0.tgz", + "integrity": "sha512-sauLxniAmvnhhRjFwPNnJKaPFYyddAgbYdeUpHULtCT/GhzdCx/MDNy+Y40lBxTQUrMzDE8e0S43Z5uqfO0REg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@volar/vue-typescript": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/@volar/vue-typescript/-/vue-typescript-1.2.0.tgz", + "integrity": "sha512-zjmRi9y3J1EkG+pfuHp8IbHmibihrKK485cfzsHjiuvJMGrpkWvlO5WVEk8oslMxxeGC5XwBFE9AOlvh378EPA==", + "dev": true, + "dependencies": { + "@volar/typescript": "1.3.0-alpha.0", + "@volar/vue-language-core": "1.2.0" + } + }, + "node_modules/@vue/babel-helper-vue-transform-on": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.0.2.tgz", + "integrity": "sha512-hz4R8tS5jMn8lDq6iD+yWL6XNB699pGIVLk7WSJnn1dbpjaazsjZQkieJoRX6gW5zpYSCFqQ7jUquPNY65tQYA==", + "dev": true + }, + "node_modules/@vue/babel-plugin-jsx": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.1.1.tgz", + "integrity": "sha512-j2uVfZjnB5+zkcbc/zsOc0fSNGCMMjaEXP52wdwdIfn0qjFfEYpYZBFKFg+HHnQeJCVrjOeO0YxgaL7DMrym9w==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/plugin-syntax-jsx": "^7.0.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "@vue/babel-helper-vue-transform-on": "^1.0.2", + "camelcase": "^6.0.0", + "html-tags": "^3.1.0", + "svg-tags": "^1.0.0" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.2.47", + "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.2.47.tgz", + "integrity": "sha512-p4D7FDnQb7+YJmO2iPEv0SQNeNzcbHdGByJDsT4lynf63AFkOTFN07HsiRSvjGo0QrxR/o3d0hUyNCUnBU2Tig==", + "dependencies": { + "@babel/parser": "^7.16.4", + "@vue/shared": "3.2.47", + "estree-walker": "^2.0.2", + "source-map": "^0.6.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.2.47", + "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.2.47.tgz", + "integrity": "sha512-dBBnEHEPoftUiS03a4ggEig74J2YBZ2UIeyfpcRM2tavgMWo4bsEfgCGsu+uJIL/vax9S+JztH8NmQerUo7shQ==", + "dependencies": { + "@vue/compiler-core": "3.2.47", + "@vue/shared": "3.2.47" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.2.47", + "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.2.47.tgz", + "integrity": "sha512-rog05W+2IFfxjMcFw10tM9+f7i/+FFpZJJ5XHX72NP9eC2uRD+42M3pYcQqDXVYoj74kHMSEdQ/WmCjt8JFksQ==", + "dependencies": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.47", + "@vue/compiler-dom": "3.2.47", + "@vue/compiler-ssr": "3.2.47", + "@vue/reactivity-transform": "3.2.47", + "@vue/shared": "3.2.47", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7", + "postcss": "^8.1.10", + "source-map": "^0.6.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.2.47", + "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.2.47.tgz", + "integrity": "sha512-wVXC+gszhulcMD8wpxMsqSOpvDZ6xKXSVWkf50Guf/S+28hTAXPDYRTbLQ3EDkOP5Xz/+SY37YiwDquKbJOgZw==", + "dependencies": { + "@vue/compiler-dom": "3.2.47", + "@vue/shared": "3.2.47" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.5.0", + "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.5.0.tgz", + "integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==" + }, + "node_modules/@vue/eslint-config-prettier": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/@vue/eslint-config-prettier/-/eslint-config-prettier-7.1.0.tgz", + "integrity": "sha512-Pv/lVr0bAzSIHLd9iz0KnvAr4GKyCEl+h52bc4e5yWuDVtLgFwycF7nrbWTAQAS+FU6q1geVd07lc6EWfJiWKQ==", + "dev": true, + "dependencies": { + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-prettier": "^4.0.0" + }, + "peerDependencies": { + "eslint": ">= 7.28.0", + "prettier": ">= 2.0.0" + } + }, + "node_modules/@vue/eslint-config-typescript": { + "version": "11.0.2", + "resolved": "https://registry.npmmirror.com/@vue/eslint-config-typescript/-/eslint-config-typescript-11.0.2.tgz", + "integrity": "sha512-EiKud1NqlWmSapBFkeSrE994qpKx7/27uCGnhdqzllYDpQZroyX/O6bwjEpeuyKamvLbsGdO6PMR2faIf+zFnw==", + "dev": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "^5.0.0", + "@typescript-eslint/parser": "^5.0.0", + "vue-eslint-parser": "^9.0.0" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0", + "eslint-plugin-vue": "^9.0.0", + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/reactivity": { + "version": "3.2.47", + "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.2.47.tgz", + "integrity": "sha512-7khqQ/75oyyg+N/e+iwV6lpy1f5wq759NdlS1fpAhFXa8VeAIKGgk2E/C4VF59lx5b+Ezs5fpp/5WsRYXQiKxQ==", + "dependencies": { + "@vue/shared": "3.2.47" + } + }, + "node_modules/@vue/reactivity-transform": { + "version": "3.2.47", + "resolved": "https://registry.npmmirror.com/@vue/reactivity-transform/-/reactivity-transform-3.2.47.tgz", + "integrity": "sha512-m8lGXw8rdnPVVIdIFhf0LeQ/ixyHkH5plYuS83yop5n7ggVJU+z5v0zecwEnX7fa7HNLBhh2qngJJkxpwEEmYA==", + "dependencies": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.47", + "@vue/shared": "3.2.47", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.2.47", + "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.2.47.tgz", + "integrity": "sha512-RZxbLQIRB/K0ev0K9FXhNbBzT32H9iRtYbaXb0ZIz2usLms/D55dJR2t6cIEUn6vyhS3ALNvNthI+Q95C+NOpA==", + "dependencies": { + "@vue/reactivity": "3.2.47", + "@vue/shared": "3.2.47" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.2.47", + "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.2.47.tgz", + "integrity": "sha512-ArXrFTjS6TsDei4qwNvgrdmHtD930KgSKGhS5M+j8QxXrDJYLqYw4RRcDy1bz1m1wMmb6j+zGLifdVHtkXA7gA==", + "dependencies": { + "@vue/runtime-core": "3.2.47", + "@vue/shared": "3.2.47", + "csstype": "^2.6.8" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.2.47", + "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.2.47.tgz", + "integrity": "sha512-dN9gc1i8EvmP9RCzvneONXsKfBRgqFeFZLurmHOveL7oH6HiFXJw5OGu294n1nHc/HMgTy6LulU/tv5/A7f/LA==", + "dependencies": { + "@vue/compiler-ssr": "3.2.47", + "@vue/shared": "3.2.47" + }, + "peerDependencies": { + "vue": "3.2.47" + } + }, + "node_modules/@vue/shared": { + "version": "3.2.47", + "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.2.47.tgz", + "integrity": "sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ==" + }, + "node_modules/@vue/test-utils": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/@vue/test-utils/-/test-utils-2.3.0.tgz", + "integrity": "sha512-S8/9Z+B4VSsTUNtZtzS7J1TfxJbf10n+gcH9X8cASbG0Tp7qD6vqs/sUNlmpzk6i7+pP00ptauJp9rygyW89Ww==", + "dev": true, + "dependencies": { + "js-beautify": "1.14.6" + }, + "optionalDependencies": { + "@vue/compiler-dom": "^3.0.1", + "@vue/server-renderer": "^3.0.1" + }, + "peerDependencies": { + "@vue/compiler-dom": "^3.0.1", + "@vue/server-renderer": "^3.0.1", + "vue": "^3.0.1" + } + }, + "node_modules/@vue/tsconfig": { + "version": "0.1.3", + "resolved": "https://registry.npmmirror.com/@vue/tsconfig/-/tsconfig-0.1.3.tgz", + "integrity": "sha512-kQVsh8yyWPvHpb8gIc9l/HIDiiVUy1amynLNpCy8p+FoCiZXCo6fQos5/097MmnNZc9AtseDsCrfkhqCrJ8Olg==", + "dev": true, + "peerDependencies": { + "@types/node": "*" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@vueuse/core": { + "version": "9.13.0", + "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-9.13.0.tgz", + "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==", + "dependencies": { + "@types/web-bluetooth": "^0.0.16", + "@vueuse/metadata": "9.13.0", + "@vueuse/shared": "9.13.0", + "vue-demi": "*" + } + }, + "node_modules/@vueuse/core/node_modules/vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vueuse/metadata": { + "version": "9.13.0", + "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.13.0.tgz", + "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==" + }, + "node_modules/@vueuse/shared": { + "version": "9.13.0", + "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.13.0.tgz", + "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==", + "dependencies": { + "vue-demi": "*" + } + }, + "node_modules/@vueuse/shared/node_modules/vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "dev": true + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/acorn-globals/-/acorn-globals-7.0.1.tgz", + "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "dev": true, + "dependencies": { + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmmirror.com/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/async-validator": { + "version": "4.2.5", + "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz", + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/axios": { + "version": "1.3.4", + "resolved": "https://registry.npmmirror.com/axios/-/axios-1.3.4.tgz", + "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.21.5", + "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "dev": true, + "dependencies": { + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmmirror.com/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmmirror.com/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001458", + "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001458.tgz", + "integrity": "sha512-lQ1VlUUq5q9ro9X+5gOEyH7i3vm+AYVT1WDCVB69XOZ17KZRhnZ9J0Sqz7wTHQaLBJccNCHq8/Ww5LlOIZbB0w==", + "dev": true + }, + "node_modules/chai": { + "version": "4.3.7", + "resolved": "https://registry.npmmirror.com/chai/-/chai-4.3.7.tgz", + "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^4.1.2", + "get-func-name": "^2.0.0", + "loupe": "^2.3.1", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/cli-truncate": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/cli-truncate/-/cli-truncate-3.1.0.tgz", + "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "dev": true, + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmmirror.com/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmmirror.com/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "node_modules/copy-anything": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-2.0.6.tgz", + "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", + "dependencies": { + "is-what": "^3.14.1" + } + }, + "node_modules/core-js": { + "version": "3.29.0", + "resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.29.0.tgz", + "integrity": "sha512-VG23vuEisJNkGl6XQmFJd3rEG/so/CNatqeE+7uZAwTSwFeB/qaO0be8xZYUNWprJ/GIwL8aMt9cj1kvbpTZhg==", + "hasInstallScript": true + }, + "node_modules/core-js-pure": { + "version": "3.29.0", + "resolved": "https://registry.npmmirror.com/core-js-pure/-/core-js-pure-3.29.0.tgz", + "integrity": "sha512-v94gUjN5UTe1n0yN/opTihJ8QBWD2O8i19RfTZR7foONPWArnjB96QA/wk5ozu1mm6ja3udQCzOzwQXTxi3xOQ==", + "hasInstallScript": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssom": { + "version": "0.5.0", + "resolved": "https://registry.npmmirror.com/cssom/-/cssom-0.5.0.tgz", + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", + "dev": true + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmmirror.com/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "node_modules/csstype": { + "version": "2.6.21", + "resolved": "https://registry.npmmirror.com/csstype/-/csstype-2.6.21.tgz", + "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" + }, + "node_modules/data-urls": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/data-urls/-/data-urls-3.0.2.tgz", + "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", + "dev": true, + "dependencies": { + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dayjs": { + "version": "1.11.7", + "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.7.tgz", + "integrity": "sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==" + }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmmirror.com/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true + }, + "node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmmirror.com/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dev": true, + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/diff": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/diff/-/diff-5.1.0.tgz", + "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/domexception": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/domexception/-/domexception-4.0.0.tgz", + "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "dev": true, + "dependencies": { + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/echarts": { + "version": "5.4.1", + "resolved": "https://registry.npmmirror.com/echarts/-/echarts-5.4.1.tgz", + "integrity": "sha512-9ltS3M2JB0w2EhcYjCdmtrJ+6haZcW6acBolMGIuf01Hql1yrIV01L1aRj7jsaaIULJslEP9Z3vKlEmnJaWJVQ==", + "dependencies": { + "tslib": "2.3.0", + "zrender": "5.4.1" + } + }, + "node_modules/echarts/node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" + }, + "node_modules/editorconfig": { + "version": "0.15.3", + "resolved": "https://registry.npmmirror.com/editorconfig/-/editorconfig-0.15.3.tgz", + "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", + "dev": true, + "dependencies": { + "commander": "^2.19.0", + "lru-cache": "^4.1.5", + "semver": "^5.6.0", + "sigmund": "^1.0.1" + }, + "bin": { + "editorconfig": "bin/editorconfig" + } + }, + "node_modules/editorconfig/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/editorconfig/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/editorconfig/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.4.314", + "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.314.tgz", + "integrity": "sha512-+3RmNVx9hZLlc0gW//4yep0K5SYKmIvB5DXg1Yg6varsuAHlHwTeqeygfS8DWwLCsNOWrgj+p9qgM5WYjw1lXQ==", + "dev": true + }, + "node_modules/element-plus": { + "version": "2.2.32", + "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.2.32.tgz", + "integrity": "sha512-DTJMhYOy6MApbmh6z/95hPTK5WrBiNHGzV4IN+uEkup1WoimQ+Qyt8RxKdTe/X1LWEJ8YgWv/Cl8P4ocrt5z5g==", + "dependencies": { + "@ctrl/tinycolor": "^3.4.1", + "@element-plus/icons-vue": "^2.0.6", + "@floating-ui/dom": "^1.0.1", + "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7", + "@types/lodash": "^4.14.182", + "@types/lodash-es": "^4.17.6", + "@vueuse/core": "^9.1.0", + "async-validator": "^4.2.5", + "dayjs": "^1.11.3", + "escape-html": "^1.0.3", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "lodash-unified": "^1.0.2", + "memoize-one": "^6.0.0", + "normalize-wheel-es": "^1.2.0" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/entities": { + "version": "4.4.0", + "resolved": "https://registry.npmmirror.com/entities/-/entities-4.4.0.tgz", + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", + "dev": true, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://registry.npmmirror.com/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "optional": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmmirror.com/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.21.1", + "resolved": "https://registry.npmmirror.com/es-abstract/-/es-abstract-1.21.1.tgz", + "integrity": "sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.3", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.4", + "is-array-buffer": "^3.0.1", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.2", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.17.12", + "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.17.12.tgz", + "integrity": "sha512-bX/zHl7Gn2CpQwcMtRogTTBf9l1nl+H6R8nUbjk+RuKqAE3+8FDulLA+pHvX7aA7Xe07Iwa+CWvy9I8Y2qqPKQ==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.17.12", + "@esbuild/android-arm64": "0.17.12", + "@esbuild/android-x64": "0.17.12", + "@esbuild/darwin-arm64": "0.17.12", + "@esbuild/darwin-x64": "0.17.12", + "@esbuild/freebsd-arm64": "0.17.12", + "@esbuild/freebsd-x64": "0.17.12", + "@esbuild/linux-arm": "0.17.12", + "@esbuild/linux-arm64": "0.17.12", + "@esbuild/linux-ia32": "0.17.12", + "@esbuild/linux-loong64": "0.17.12", + "@esbuild/linux-mips64el": "0.17.12", + "@esbuild/linux-ppc64": "0.17.12", + "@esbuild/linux-riscv64": "0.17.12", + "@esbuild/linux-s390x": "0.17.12", + "@esbuild/linux-x64": "0.17.12", + "@esbuild/netbsd-x64": "0.17.12", + "@esbuild/openbsd-x64": "0.17.12", + "@esbuild/sunos-x64": "0.17.12", + "@esbuild/win32-arm64": "0.17.12", + "@esbuild/win32-ia32": "0.17.12", + "@esbuild/win32-x64": "0.17.12" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/escodegen/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmmirror.com/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.36.0", + "resolved": "https://registry.npmmirror.com/eslint/-/eslint-8.36.0.tgz", + "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.1", + "@eslint/js": "8.36.0", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.5.0", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.6.0", + "resolved": "https://registry.npmmirror.com/eslint-config-prettier/-/eslint-config-prettier-8.6.0.tgz", + "integrity": "sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmmirror.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-vue": { + "version": "9.9.0", + "resolved": "https://registry.npmmirror.com/eslint-plugin-vue/-/eslint-plugin-vue-9.9.0.tgz", + "integrity": "sha512-YbubS7eK0J7DCf0U2LxvVP7LMfs6rC6UltihIgval3azO3gyDwEGVgsCMe1TmDiEkl6GdMKfRpaME6QxIYtzDQ==", + "dev": true, + "dependencies": { + "eslint-utils": "^3.0.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.0.1", + "postcss-selector-parser": "^6.0.9", + "semver": "^7.3.5", + "vue-eslint-parser": "^9.0.1", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-plugin-vue/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-plugin-vue/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-plugin-vue/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmmirror.com/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "9.5.0", + "resolved": "https://registry.npmmirror.com/espree/-/espree-9.5.0.tgz", + "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==", + "dev": true, + "dependencies": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.4.2", + "resolved": "https://registry.npmmirror.com/esquery/-/esquery-1.4.2.tgz", + "integrity": "sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/eventsource": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/eventsource/-/eventsource-2.0.2.tgz", + "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmmirror.com/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fetch-cookie": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/fetch-cookie/-/fetch-cookie-2.1.0.tgz", + "integrity": "sha512-39+cZRbWfbibmj22R2Jy6dmTbAWC+oqun1f1FzQaNurkPDUP4C38jpeZbiXCR88RKRVDp8UcDrbFXkNhN+NjYg==", + "dependencies": { + "set-cookie-parser": "^2.4.8", + "tough-cookie": "^4.0.0" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flat-cache/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/flat-cache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmmirror.com/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmmirror.com/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmmirror.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmmirror.com/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmmirror.com/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmmirror.com/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmmirror.com/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "devOptional": true + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmmirror.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dev": true, + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-tags": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/html-tags/-/html-tags-3.2.0.tgz", + "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "devOptional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmmirror.com/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", + "optional": true, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmmirror.com/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/is-array-buffer/-/is-array-buffer-3.0.1.tgz", + "integrity": "sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-typed-array": "^1.1.10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmmirror.com/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-core-module": { + "version": "2.11.0", + "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmmirror.com/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmmirror.com/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + } + }, + "node_modules/is-what": { + "version": "3.14.1", + "resolved": "https://registry.npmmirror.com/is-what/-/is-what-3.14.1.tgz", + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==" + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/js-beautify": { + "version": "1.14.6", + "resolved": "https://registry.npmmirror.com/js-beautify/-/js-beautify-1.14.6.tgz", + "integrity": "sha512-GfofQY5zDp+cuHc+gsEXKPpNw2KbPddreEo35O6jT6i0RVK6LhsoYBhq5TvK4/n74wnA0QbK8gGd+jUZwTMKJw==", + "dev": true, + "dependencies": { + "config-chain": "^1.1.13", + "editorconfig": "^0.15.3", + "glob": "^8.0.3", + "nopt": "^6.0.0" + }, + "bin": { + "css-beautify": "js/bin/css-beautify.js", + "html-beautify": "js/bin/html-beautify.js", + "js-beautify": "js/bin/js-beautify.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "dev": true + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdom": { + "version": "21.1.0", + "resolved": "https://registry.npmmirror.com/jsdom/-/jsdom-21.1.0.tgz", + "integrity": "sha512-m0lzlP7qOtthD918nenK3hdItSd2I+V3W9IrBcB36sqDwG+KnUs66IF5GY7laGWUnlM9vTsD0W1QwSEBYWWcJg==", + "dev": true, + "dependencies": { + "abab": "^2.0.6", + "acorn": "^8.8.1", + "acorn-globals": "^7.0.0", + "cssom": "^0.5.0", + "cssstyle": "^2.3.0", + "data-urls": "^3.0.2", + "decimal.js": "^10.4.2", + "domexception": "^4.0.0", + "escodegen": "^2.0.0", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.2", + "parse5": "^7.1.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.2", + "w3c-xmlserializer": "^4.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0", + "ws": "^8.11.0", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, + "node_modules/less": { + "version": "4.1.3", + "resolved": "https://registry.npmmirror.com/less/-/less-4.1.3.tgz", + "integrity": "sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==", + "dependencies": { + "copy-anything": "^2.0.1", + "parse-node-version": "^1.0.1", + "tslib": "^2.3.0" + }, + "bin": { + "lessc": "bin/lessc" + }, + "engines": { + "node": ">=6" + }, + "optionalDependencies": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^3.1.0", + "source-map": "~0.6.0" + } + }, + "node_modules/less/node_modules/tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/local-pkg": { + "version": "0.4.3", + "resolved": "https://registry.npmmirror.com/local-pkg/-/local-pkg-0.4.3.tgz", + "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, + "node_modules/lodash-unified": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.3.tgz", + "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==", + "peerDependencies": { + "@types/lodash-es": "*", + "lodash": "*", + "lodash-es": "*" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/loupe": { + "version": "2.3.6", + "resolved": "https://registry.npmmirror.com/loupe/-/loupe-2.3.6.tgz", + "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.0" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, + "node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "optional": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/make-dir/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "optional": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmmirror.com/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mlly": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/mlly/-/mlly-1.1.1.tgz", + "integrity": "sha512-Jnlh4W/aI4GySPo6+DyTN17Q75KKbLTyFK8BrGhjNP4rxuUjbRWhE6gHg3bs33URWAF44FRm7gdQA348i3XxRw==", + "dev": true, + "dependencies": { + "acorn": "^8.8.2", + "pathe": "^1.1.0", + "pkg-types": "^1.0.1", + "ufo": "^1.1.0" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "devOptional": true + }, + "node_modules/muggle-string": { + "version": "0.2.2", + "resolved": "https://registry.npmmirror.com/muggle-string/-/muggle-string-0.2.2.tgz", + "integrity": "sha512-YVE1mIJ4VpUMqZObFndk9CJu6DBJR/GB13p3tXuNbwD4XExaI5EOuRl6BHeIDxIqXZVxSfAC+y6U1Z/IxCfKUg==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, + "node_modules/needle": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/needle/-/needle-3.2.0.tgz", + "integrity": "sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==", + "optional": true, + "dependencies": { + "debug": "^3.2.6", + "iconv-lite": "^0.6.3", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/needle/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmmirror.com/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "optional": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/node-fetch": { + "version": "2.6.9", + "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.6.9.tgz", + "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.10", + "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.10.tgz", + "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", + "dev": true + }, + "node_modules/nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "dev": true, + "dependencies": { + "abbrev": "^1.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmmirror.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/normalize-wheel-es": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz", + "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==" + }, + "node_modules/npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmmirror.com/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/npm-run-all/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/npm-run-all/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/npm-run-all/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmmirror.com/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + } + }, + "node_modules/nwsapi": { + "version": "2.2.2", + "resolved": "https://registry.npmmirror.com/nwsapi/-/nwsapi-2.2.2.tgz", + "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==", + "dev": true + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "dev": true + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmmirror.com/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmmirror.com/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmmirror.com/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "dependencies": { + "entities": "^4.4.0" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/pathe/-/pathe-1.1.0.tgz", + "integrity": "sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==", + "dev": true + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmmirror.com/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pinia": { + "version": "2.0.32", + "resolved": "https://registry.npmmirror.com/pinia/-/pinia-2.0.32.tgz", + "integrity": "sha512-8Tw4OrpCSJ028UUyp0gYPP/wyjigLoEceuO/x1G+FlHVf73337e5vLm4uDmrRIoBG1hvaed/eSHnrCFjOc4nkA==", + "dependencies": { + "@vue/devtools-api": "^6.5.0", + "vue-demi": "*" + }, + "peerDependencies": { + "@vue/composition-api": "^1.4.0", + "typescript": ">=4.4.4", + "vue": "^2.6.14 || ^3.2.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/pinia/node_modules/vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/pkg-types": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/pkg-types/-/pkg-types-1.0.2.tgz", + "integrity": "sha512-hM58GKXOcj8WTqUXnsQyJYXdeAPbythQgEF3nTcEo+nkD49chjQ9IKm/QJy9xf6JakXptz86h7ecP2024rrLaQ==", + "dev": true, + "dependencies": { + "jsonc-parser": "^3.2.0", + "mlly": "^1.1.1", + "pathe": "^1.1.0" + } + }, + "node_modules/postcss": { + "version": "8.4.21", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.11", + "resolved": "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz", + "integrity": "sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.4", + "resolved": "https://registry.npmmirror.com/prettier/-/prettier-2.8.4.tgz", + "integrity": "sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmmirror.com/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "optional": true + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", + "dev": true + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmmirror.com/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg/node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmmirror.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "4.1.2", + "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-4.1.2.tgz", + "integrity": "sha512-BlIbgFryTbw3Dz6hyoWFhKk+unCcHMSkZGrTFVAx2WmttdBSonsdtRlwiuTbDqTKr+UlXIUqJVS4QT5tUzGENQ==", + "dev": true, + "bin": { + "rimraf": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/rollup": { + "version": "3.19.1", + "resolved": "https://registry.npmmirror.com/rollup/-/rollup-3.19.1.tgz", + "integrity": "sha512-lAbrdN7neYCg/8WaoWn/ckzCtz+jr70GFfYdlf50OF7387HTg+wiuiqJRFYawwSPpqfqDNYqK7smY/ks2iAudg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-visualizer": { + "version": "5.9.0", + "resolved": "https://registry.npmmirror.com/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.9.0.tgz", + "integrity": "sha512-bbDOv47+Bw4C/cgs0czZqfm8L82xOZssk4ayZjG40y9zbXclNk7YikrZTDao6p7+HDiGxrN0b65SgZiVm9k1Cg==", + "dev": true, + "dependencies": { + "open": "^8.4.0", + "picomatch": "^2.3.1", + "source-map": "^0.7.4", + "yargs": "^17.5.1" + }, + "bin": { + "rollup-plugin-visualizer": "dist/bin/cli.js" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "rollup": "2.x || 3.x" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/rollup-plugin-visualizer/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "devOptional": true + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "devOptional": true + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/set-cookie-parser": { + "version": "2.5.1", + "resolved": "https://registry.npmmirror.com/set-cookie-parser/-/set-cookie-parser-2.5.1.tgz", + "integrity": "sha512-1jeBGaKNGdEq4FgIrORu/N570dwoPYio8lSoYLWmX7sQ//0JY08Xh9o5pBcgmHQ/MbsYp/aZnOe1s1lIsbLprQ==" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.0", + "resolved": "https://registry.npmmirror.com/shell-quote/-/shell-quote-1.8.0.tgz", + "integrity": "sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ==", + "dev": true + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true + }, + "node_modules/sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha512-fCvEXfh6NWpm+YSuY2bpXb/VIihqWA6hLsgboC+0nl71Q7N7o2eaCW8mJa/NLvQhs6jpd3VZV4UiUQlV6+lc8g==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/sortablejs": { + "version": "1.15.0", + "resolved": "https://registry.npmmirror.com/sortablejs/-/sortablejs-1.15.0.tgz", + "integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w==", + "peer": true + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmmirror.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead" + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.12", + "resolved": "https://registry.npmmirror.com/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", + "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", + "dev": true + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmmirror.com/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true + }, + "node_modules/std-env": { + "version": "3.3.2", + "resolved": "https://registry.npmmirror.com/std-env/-/std-env-3.3.2.tgz", + "integrity": "sha512-uUZI65yrV2Qva5gqE0+A7uVAvO40iPo6jGhs7s8keRfHCmtg+uB2X6EiLGCI9IgL1J17xGhvoOqSz79lzICPTA==", + "dev": true + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/string.prototype.padend": { + "version": "3.1.4", + "resolved": "https://registry.npmmirror.com/string.prototype.padend/-/string.prototype.padend-3.1.4.tgz", + "integrity": "sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-literal": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/strip-literal/-/strip-literal-1.0.1.tgz", + "integrity": "sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==", + "dev": true, + "dependencies": { + "acorn": "^8.8.2" + } + }, + "node_modules/stylus": { + "version": "0.59.0", + "resolved": "https://registry.npmmirror.com/stylus/-/stylus-0.59.0.tgz", + "integrity": "sha512-lQ9w/XIOH5ZHVNuNbWW8D822r+/wBSO/d6XvtyHLF7LW4KaCIDeVbvn5DF8fGCJAUCwVhVi/h6J0NUcnylUEjg==", + "dev": true, + "dependencies": { + "@adobe/css-tools": "^4.0.1", + "debug": "^4.3.2", + "glob": "^7.1.6", + "sax": "~1.2.4", + "source-map": "^0.7.3" + }, + "bin": { + "stylus": "bin/stylus" + }, + "engines": { + "node": "*" + } + }, + "node_modules/stylus/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/stylus/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", + "dev": true + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmmirror.com/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/tinybench": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/tinybench/-/tinybench-2.3.1.tgz", + "integrity": "sha512-hGYWYBMPr7p4g5IarQE7XhlyWveh1EKhy4wUBS1LrHXCKYgvz+4/jCqgmJqZxxldesn05vccrtME2RLLZNW7iA==", + "dev": true + }, + "node_modules/tinypool": { + "version": "0.3.1", + "resolved": "https://registry.npmmirror.com/tinypool/-/tinypool-0.3.1.tgz", + "integrity": "sha512-zLA1ZXlstbU2rlpA4CIeVaqvWq41MTWqLY3FfsAXgC8+f7Pk7zroaJQxDgxn1xNudKW6Kmj4808rPFShUlIRmQ==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/tinyspy/-/tinyspy-1.1.1.tgz", + "integrity": "sha512-UVq5AXt/gQlti7oxoIg5oi/9r0WpF7DGEVwXgqWSMmyN16+e3tl5lIvTaOpJ3TAtu5xFzWccFRM4R5NaWHF+4g==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.2", + "resolved": "https://registry.npmmirror.com/tough-cookie/-/tough-cookie-4.1.2.tgz", + "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dev": true, + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmmirror.com/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmmirror.com/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + } + }, + "node_modules/typescript": { + "version": "4.8.4", + "resolved": "https://registry.npmmirror.com/typescript/-/typescript-4.8.4.tgz", + "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", + "devOptional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/ufo": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/ufo/-/ufo-1.1.1.tgz", + "integrity": "sha512-MvlCc4GHrmZdAllBc0iUDowff36Q9Ndw/UzqmEKyrfSzokTd9ZCy1i+IIk5hrYKkjoYVQyNbrw7/F8XJ2rEwTg==", + "dev": true + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + }, + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.10", + "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", + "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "dev": true, + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmmirror.com/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/vite": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/vite/-/vite-4.2.0.tgz", + "integrity": "sha512-AbDTyzzwuKoRtMIRLGNxhLRuv1FpRgdIw+1y6AQG73Q5+vtecmvzKo/yk8X/vrHDpETRTx01ABijqUHIzBXi0g==", + "dev": true, + "dependencies": { + "esbuild": "^0.17.5", + "postcss": "^8.4.21", + "resolve": "^1.22.1", + "rollup": "^3.18.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "0.29.2", + "resolved": "https://registry.npmmirror.com/vite-node/-/vite-node-0.29.2.tgz", + "integrity": "sha512-5oe1z6wzI3gkvc4yOBbDBbgpiWiApvuN4P55E8OI131JGrSuo4X3SOZrNmZYo4R8Zkze/dhi572blX0zc+6SdA==", + "dev": true, + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "mlly": "^1.1.0", + "pathe": "^1.1.0", + "picocolors": "^1.0.0", + "vite": "^3.0.0 || ^4.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": ">=v14.16.0" + } + }, + "node_modules/vitest": { + "version": "0.29.2", + "resolved": "https://registry.npmmirror.com/vitest/-/vitest-0.29.2.tgz", + "integrity": "sha512-ydK9IGbAvoY8wkg29DQ4ivcVviCaUi3ivuPKfZEVddMTenFHUfB8EEDXQV8+RasEk1ACFLgMUqAaDuQ/Nk+mQA==", + "dev": true, + "dependencies": { + "@types/chai": "^4.3.4", + "@types/chai-subset": "^1.3.3", + "@types/node": "*", + "@vitest/expect": "0.29.2", + "@vitest/runner": "0.29.2", + "@vitest/spy": "0.29.2", + "@vitest/utils": "0.29.2", + "acorn": "^8.8.1", + "acorn-walk": "^8.2.0", + "cac": "^6.7.14", + "chai": "^4.3.7", + "debug": "^4.3.4", + "local-pkg": "^0.4.2", + "pathe": "^1.1.0", + "picocolors": "^1.0.0", + "source-map": "^0.6.1", + "std-env": "^3.3.1", + "strip-literal": "^1.0.0", + "tinybench": "^2.3.1", + "tinypool": "^0.3.1", + "tinyspy": "^1.0.2", + "vite": "^3.0.0 || ^4.0.0", + "vite-node": "0.29.2", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": ">=v14.16.0" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@vitest/browser": "*", + "@vitest/ui": "*", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.2.47", + "resolved": "https://registry.npmmirror.com/vue/-/vue-3.2.47.tgz", + "integrity": "sha512-60188y/9Dc9WVrAZeUVSDxRQOZ+z+y5nO2ts9jWXSTkMvayiWxCWOWtBQoYjLeccfXkiiPZWAHcV+WTPhkqJHQ==", + "dependencies": { + "@vue/compiler-dom": "3.2.47", + "@vue/compiler-sfc": "3.2.47", + "@vue/runtime-dom": "3.2.47", + "@vue/server-renderer": "3.2.47", + "@vue/shared": "3.2.47" + } + }, + "node_modules/vue-draggable-next": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/vue-draggable-next/-/vue-draggable-next-2.1.1.tgz", + "integrity": "sha512-f5lmA7t6LMaL4viR7dU30zzvqJzaKQs0ymL0Jy9UDT9uiZ2tXF3MzPzEvpTH2UODXZJkT+SnjeV1fXHMsgXLYA==", + "peerDependencies": { + "sortablejs": "^1.14.0", + "vue": "^3.2.2" + } + }, + "node_modules/vue-eslint-parser": { + "version": "9.1.0", + "resolved": "https://registry.npmmirror.com/vue-eslint-parser/-/vue-eslint-parser-9.1.0.tgz", + "integrity": "sha512-NGn/iQy8/Wb7RrRa4aRkokyCZfOUWk19OP5HP6JEozQFX5AoS/t+Z0ZN7FY4LlmWc4FNI922V7cvX28zctN8dQ==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.6" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/vue-eslint-parser/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/vue-eslint-parser/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/vue-eslint-parser/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/vue-eslint-parser/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/vue-eslint-parser/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/vue-router": { + "version": "4.1.6", + "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.1.6.tgz", + "integrity": "sha512-DYWYwsG6xNPmLq/FmZn8Ip+qrhFEzA14EI12MsMgVxvHFDYvlr4NXpVF5hrRH1wVcDP8fGi5F4rxuJSl8/r+EQ==", + "dependencies": { + "@vue/devtools-api": "^6.4.5" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/vue-template-compiler": { + "version": "2.7.14", + "resolved": "https://registry.npmmirror.com/vue-template-compiler/-/vue-template-compiler-2.7.14.tgz", + "integrity": "sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==", + "dev": true, + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, + "node_modules/vue-tsc": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-1.2.0.tgz", + "integrity": "sha512-rIlzqdrhyPYyLG9zxsVRa+JEseeS9s8F2BbVVVWRRsTZvJO2BbhLEb2HW3MY+DFma0378tnIqs+vfTzbcQtRFw==", + "dev": true, + "dependencies": { + "@volar/vue-language-core": "1.2.0", + "@volar/vue-typescript": "1.2.0" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": "*" + } + }, + "node_modules/vuex": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/vuex/-/vuex-4.1.0.tgz", + "integrity": "sha512-hmV6UerDrPcgbSy9ORAtNXDr9M4wlNP4pEFKye4ujJF8oqgFFuxDCdOLS3eNoRTtq5O3hoBDh9Doj1bQMYHRbQ==", + "dependencies": { + "@vue/devtools-api": "^6.0.0-beta.11" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", + "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", + "dev": true, + "dependencies": { + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/wangeditor": { + "version": "4.7.15", + "resolved": "https://registry.npmmirror.com/wangeditor/-/wangeditor-4.7.15.tgz", + "integrity": "sha512-aPTdREd8BxXVyJ5MI+LU83FQ7u1EPd341iXIorRNYSOvoimNoZ4nPg+yn3FGbB93/owEa6buLw8wdhYnMCJQLg==", + "dependencies": { + "@babel/runtime": "^7.11.2", + "@babel/runtime-corejs3": "^7.11.2", + "tslib": "^2.1.0" + } + }, + "node_modules/wangeditor/node_modules/tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dev": true, + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmmirror.com/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/why-is-node-running": { + "version": "2.2.2", + "resolved": "https://registry.npmmirror.com/why-is-node-running/-/why-is-node-running-2.2.2.tgz", + "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==", + "dev": true, + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/ws": { + "version": "8.12.1", + "resolved": "https://registry.npmmirror.com/ws/-/ws-8.12.1.tgz", + "integrity": "sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yargs": { + "version": "17.7.1", + "resolved": "https://registry.npmmirror.com/yargs/-/yargs-17.7.1.tgz", + "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/zrender": { + "version": "5.4.1", + "resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.4.1.tgz", + "integrity": "sha512-M4Z05BHWtajY2241EmMPHglDQAJ1UyHQcYsxDNzD9XLSkPDqMq4bB28v9Pb4mvHnVQ0GxyTklZ/69xCFP6RXBA==", + "dependencies": { + "tslib": "2.3.0" + } + }, + "node_modules/zrender/node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" + } + } +} diff --git a/Pure_Vite_Net7/Vue3Vite/package.json b/Pure_Vite_Net7/Vue3Vite/package.json new file mode 100644 index 0000000000000000000000000000000000000000..fa306ba55e744e77eee81473584947af62d9e802 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/package.json @@ -0,0 +1,54 @@ +{ + "name": "vol-vue3vite", + "version": "0.0.1", + "private": true, + "scripts": { + "dev": "vite --host", + "buildWithCheck": "run-p type-check build-only", + "preview": "vite preview", + "test:unit": "vitest", + "build": "vite build", + "type-check": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false", + "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore", + "format": "prettier --write src/", + "clean": "rimraf node_modules" + }, + "dependencies": { + "@microsoft/signalr": "^7.0.3", + "axios": "^1.3.4", + "core-js": "^3.29.0", + "echarts": "^5.4.1", + "element-plus": "^2.2.32", + "less": "^4.1.3", + "pinia": "^2.0.32", + "vue": "^3.2.47", + "vue-draggable-next": "^2.1.1", + "vue-router": "^4.1.6", + "vuex": "^4.1.0", + "wangeditor": "^4.7.15" + }, + "devDependencies": { + "@babel/eslint-parser": "^7.21.3", + "@rushstack/eslint-patch": "^1.2.0", + "@types/jsdom": "^21.1.0", + "@types/node": "^18.14.2", + "@vitejs/plugin-vue": "^4.0.0", + "@vitejs/plugin-vue-jsx": "^3.0.0", + "@vue/eslint-config-prettier": "^7.1.0", + "@vue/eslint-config-typescript": "^11.0.2", + "@vue/test-utils": "^2.3.0", + "@vue/tsconfig": "^0.1.3", + "eslint": "^8.36.0", + "eslint-plugin-vue": "^9.9.0", + "jsdom": "^21.1.0", + "npm-run-all": "^4.1.5", + "prettier": "^2.8.4", + "rimraf": "^4.1.2", + "rollup-plugin-visualizer": "^5.9.0", + "stylus": "^0.59.0", + "typescript": "~4.8.4", + "vite": "^4.2.0", + "vitest": "^0.29.1", + "vue-tsc": "^1.2.0" + } +} diff --git a/Pure_Vite_Net7/Vue3Vite/public/favicon.ico b/Pure_Vite_Net7/Vue3Vite/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 Binary files /dev/null and b/Pure_Vite_Net7/Vue3Vite/public/favicon.ico differ diff --git a/Pure_Vite_Net7/Vue3Vite/run.bat b/Pure_Vite_Net7/Vue3Vite/run.bat new file mode 100644 index 0000000000000000000000000000000000000000..b896a088e192ee3a9dbe560c544fcccce3e854a3 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/run.bat @@ -0,0 +1 @@ +npm run dev \ No newline at end of file diff --git "a/Pure_Vite_Net7/Vue3Vite/run\345\220\257\345\212\250\345\274\202\345\270\270\350\257\264\346\230\216.txt" "b/Pure_Vite_Net7/Vue3Vite/run\345\220\257\345\212\250\345\274\202\345\270\270\350\257\264\346\230\216.txt" new file mode 100644 index 0000000000000000000000000000000000000000..585f16fcb50d30766d280a4e893a55d2221fb435 --- /dev/null +++ "b/Pure_Vite_Net7/Vue3Vite/run\345\220\257\345\212\250\345\274\202\345\270\270\350\257\264\346\230\216.txt" @@ -0,0 +1,10 @@ +双击run.bat启动异常: + 使用cmd输入node -v查看版本,如果是18.+版本,请将package.json中第五行scripts中的内容替换为: + +"scripts": { + "serve": " SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve", + "build": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service build", + "test:unit": "vue-cli-service test:unit", + "lint": "vue-cli-service lint" +} + diff --git a/Pure_Vite_Net7/Vue3Vite/src/App.vue b/Pure_Vite_Net7/Vue3Vite/src/App.vue new file mode 100644 index 0000000000000000000000000000000000000000..1645abfeee743b1e0af7633e08b904e0d5a9a5b2 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/App.vue @@ -0,0 +1,63 @@ + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/api/http.js b/Pure_Vite_Net7/Vue3Vite/src/api/http.js new file mode 100644 index 0000000000000000000000000000000000000000..b7d19948cc9cdbc29a28910ab3ade11fcfcedb68 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/api/http.js @@ -0,0 +1,319 @@ +import axios from 'axios' +import store from '../store/index' +// import {getCurrentInstance} from 'vue' +import { useRouter, useRoute } from 'vue-router' +const router = useRouter() +axios.defaults.timeout = 50000 +axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8' + +import { ElLoading as Loading, ElMessage as Message } from 'element-plus' + +let loadingInstance +let loadingStatus = false + + +console.info('WEBAPI_BASE_URL:',import.meta.env.VITE_WEBAPI_BASE_URL) + +axios.defaults.baseURL= import.meta.env.VITE_WEBAPI_BASE_URL +if (!axios.defaults.baseURL.endsWith('/')) { + axios.defaults.baseURL += '/' +} +let ipAddress = axios.defaults.baseURL +axios.interceptors.request.use( + (config) => { + return config + }, + (error) => { + return Promise.reject(error) + } +) + +axios.interceptors.response.use( + (res) => { + closeLoading() + + checkResponse(res) + + return Promise.resolve(res) + }, + (error) => { + closeLoading() + let httpMessage = '' + if (error.response) { + if (error.response.status == '401') { + if (error.response.data && error.response.data.code == 401) { + if (!localStorage.getItem('user')) { + Message.error({ + showClose: true, + message: '登陆已过期', + type: 'error' + }) + } + toLogin() + return + } + } + if (error.response.status == '404') { + httpMessage = '未找到请求地址' + } else if (error.response.data && error.response.data.message) { + httpMessage = error.response.data.message + } + } else { + httpMessage = '服务器处理异常' + } + redirect(httpMessage) + return Promise.reject(error.response || {}, httpMessage) + } +) +function closeLoading() { + if (loadingInstance) { + loadingInstance.close() + } + if (loadingStatus) { + loadingStatus = false + if (loadingInstance) { + loadingInstance.close() + } + } +} +function checkResponse(res) { + //刷新token + if (!res.headers) { + if (res.getResponseHeader('vol_exp') == '1') { + replaceToken() + } + } else if (res.headers.vol_exp == '1') { + replaceToken() + } +} + +const _Authorization = 'Authorization' + +function showLoading(loading) { + if (!loading || loadingStatus) { + return + } + loadingInstance = Loading.service({ + lock: true, + text: 'Loading', + customClass: 'http-loading', + background: typeof loading == 'string' ? loading : '正在处理.....', + background: 'rgba(58, 61, 63, 0.32)' + }) +} + +function getToken() { + return store.getters.getToken() +} + +/* + url + params请求后台的参数,如:{name:123,values:['a','b','c']} + loading是否显示遮罩层,可以传入true.false.及提示文本 + config配置信息,如{timeout:3000,headers:{token:123}} +*/ +function post(url, params, loading, config) { + showLoading(loading) + return new Promise((resolve, reject) => { + axios + .post(url, params, config) + .then( + (response) => { + resolve(response.data) + }, + (err) => { + reject(err && err.data && err.data.message ? err.data.message : '服务器处理异常') + } + ) + .catch((error) => { + reject(error) + }) + }) +} + +//=true异步请求时会显示遮罩层,=字符串,异步请求时遮罩层显示当前字符串 +function get(url, param, loading, config) { + showLoading(loading) + axios.defaults.headers[_Authorization] = getToken() + return new Promise((resolve, reject) => { + axios + .get(url, config) + .then( + (response) => { + resolve(response.data) + }, + (err) => { + reject(err) + } + ) + .catch((error) => { + reject(error) + }) + }) +} + +//url:url地址 +//params:请求参数 +//fileName:下载的文件名 +//loading:是否显示加载状态 +function download(url, params, fileName, loading, callback) { + fileName = fileName.replace('>', '>').replace('<', '<') + post(url, params, loading, { responseType: 'blob' }).then((content) => { + const blob = new Blob([content]) + if ('download' in document.createElement('a')) { + // 非IE下载 + const elink = document.createElement('a') + elink.download = fileName + elink.style.display = 'none' + elink.href = URL.createObjectURL(blob) + document.body.appendChild(elink) + elink.click() + URL.revokeObjectURL(elink.href) // 释放URL 对象 + document.body.removeChild(elink) + } else { + // IE10+下载 + navigator.msSaveBlob(blob, fileName) + } + callback && callback() + }) +} + +function createXHR() { + if (XMLHttpRequest) { + return new XMLHttpRequest() + } + if (ActiveXObject) { + if (typeof arguments.callee.activeXString != 'string') { + var versions = ['MSXML2.XMLHttp.6.0', 'MSXML2.XMLHttp', 'MSXML2.XMLHttp.3.0'] + for (var i = 0; i < versions.length; i++) { + try { + new ActiveXObject(versions[i]) + arguments.callee.activeXString = versions[i] + break + } catch (e) { + console.log(e) + } + } + } + return new ActiveXObject(arguments.callee.activeXString) + } +} + +function redirect(responseText, message) { + try { + let responseData = typeof responseText == 'string' ? JSON.parse(responseText) : responseText + if ( + (responseData.hasOwnProperty('code') && responseData.code == 401) || + (responseData.data && responseData.data.code == 401) + ) { + closeLoading() + toLogin() + } else { + if (message) { + Message.error({ + showClose: true, + message: message, + type: 'error' + }) + } + } + } catch (error) { + console.log(error) + Message.error({ + showClose: true, + message: responseText, + type: 'error' + }) + } +} + +function toLogin() { + // const vueinstance= getCurrentInstance(); + if (window.location.hash) { + window.location.href = window.location.origin + '/#/login' + return + } + window.location.href = window.location.origin + '/login' + // router.push({ path: '/login', params: { r: Math.random() } }); +} +//动态刷新token +function replaceToken() { + ajax({ + url: '/api/User/replaceToken', + param: {}, + json: true, + success: function (x) { + if (x.status) { + let userInfo = store.getters.getUserInfo() + userInfo.token = x.data + store.commit('setUserInfo', userInfo) + } else { + console.log(x.message) + toLogin() + } + }, + errror: function (ex) { + console.log(ex) + toLogin() + }, + type: 'post', + async: false + }) +} + +function ajax(param) { + let httpParam = Object.assign( + { + url: '', + headers: {}, + param: {}, + json: true, + success: function () {}, + errror: function () {}, + type: 'post', + async: true + }, + param + ) + + httpParam.url = axios.defaults.baseURL + httpParam.url.replace(/\/?/, '') + httpParam.headers[_Authorization] = getToken() + var xhr = createXHR() + xhr.onreadystatechange = function () { + if (xhr.status == 403 || xhr.status == 401) { + redirect(xhr.responseText) + return + } + checkResponse(xhr) + if (xhr.readyState == 4 && xhr.status == 200) { + httpParam.success(httpParam.json ? JSON.parse(xhr.responseText) : xhr.responseText) + return + } + if (xhr.status != 0 && xhr.readyState != 1) { + httpParam.errror(xhr) + } + } + //初始化请求 + xhr.open(httpParam.type, httpParam.url, httpParam.async) + xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded') + for (const key in httpParam.headers) { + xhr.setRequestHeader(key, httpParam.headers[key]) + } + let dataStr = '' + for (const key in httpParam.param) { + dataStr += key + '=' + httpParam.param[key] + } + try { + xhr.send(dataStr) + } catch (error) { + toLogin() + } +} + +ajax.post = function (url, param, success, errror) { + ajax({ url: url, param: param, success: success, error: errror, type: 'post' }) +} +ajax.get = function (url, param, success, errror) { + ajax({ url: url, param: param, success: success, error: errror, type: 'get' }) +} +export default { post, get, download, ajax, ipAddress } diff --git a/Pure_Vite_Net7/Vue3Vite/src/api/permission.js b/Pure_Vite_Net7/Vue3Vite/src/api/permission.js new file mode 100644 index 0000000000000000000000000000000000000000..c5db03ce1f45f5957d52f7c10343335c88f16e64 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/api/permission.js @@ -0,0 +1,47 @@ +import http from '@/api/http.js' +import buttons from '@/assets/script/buttons.js' +import store from '@/store/index.js' +import { useRouter } from 'vue-router' +let permission = { + getMenu() { + return http.get('/api/getTreeMenu') + }, + getButtons(path, extra, table, tableName) { + //extra自定额外按钮 + //table获取指定表的权限 + if (table) { + table = '/' + table + } + let permission = store.getters.getPermission(table || path) + if (!permission) { + permission = store.getters.getPermission(path.substring(1)) + if (!permission) { + permission = store.getters.getPermission('/' + tableName) + if (!permission) { + to401() + return + } + } + } + + let permissions = permission.permission //.split(','); + let gridButtons = buttons.filter((item) => { + return !item.value || permissions.indexOf(item.value) != -1 + }) + if (extra && extra instanceof Array) { + gridButtons.push(...extra) + } + return gridButtons + }, + to401() { + to401() + } +} +function to401() { + const router = useRouter() + router.push({ + path: '/401' + }) +} + +export default permission diff --git a/Pure_Vite_Net7/Vue3Vite/src/api/useTest.js b/Pure_Vite_Net7/Vue3Vite/src/api/useTest.js new file mode 100644 index 0000000000000000000000000000000000000000..2874e76ff5f01ff3c7b79b172f105b844b2cc19b --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/api/useTest.js @@ -0,0 +1,9 @@ +const tipxx = { + install: function (vue) { + alert(1) + vue.prototype.$tip = function () { + alert('测试use') + } + } +} +export default { tipxx } diff --git a/Pure_Vite_Net7/Vue3Vite/src/assets/css/common.less b/Pure_Vite_Net7/Vue3Vite/src/assets/css/common.less new file mode 100644 index 0000000000000000000000000000000000000000..ac7a1793fea94dfcea7eb9572ddc799b6fed3871 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/assets/css/common.less @@ -0,0 +1,75 @@ +*{ + box-sizing:border-box; + -moz-box-sizing:border-box; /* Firefox */ + -webkit-box-sizing:border-box; /* Safari */ +} +.el-pager li{ + font-weight: 100; + margin-right: 9px; + border: 1px solid #eee; + border-radius: 3px; + min-width: 28px; +} +.el-pager li.active,.el-pager li:hover{ + background: #ed4014; + color: white; +} +.el-pagination__editor.el-input .el-input__inner{ + height: 23px; +} + + +.animated { + -webkit-animation-duration: 0.5s; + animation-duration: 0.5s; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; + } + + @media (print), (prefers-reduced-motion) { + .animated { + -webkit-animation: unset !important; + animation: unset !important; + -webkit-transition: none !important; + transition: none !important; + } + } + + @-webkit-keyframes fadeInDown { + from { + opacity: 1; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + } + + @keyframes fadeInDown { + from { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } + + to { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + } + + .fadeInDown { + -webkit-animation-name: fadeInDown; + animation-name: fadeInDown; + } + .ivu-message{ + z-index: 999999999 !important; + } + .ivu-form-item-content{ + text-align: left; + } \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/assets/element-icon/fonts/element-icons.ttf b/Pure_Vite_Net7/Vue3Vite/src/assets/element-icon/fonts/element-icons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..91b74de36778b0ff8958d37d07ce70fb3b26f50b Binary files /dev/null and b/Pure_Vite_Net7/Vue3Vite/src/assets/element-icon/fonts/element-icons.ttf differ diff --git a/Pure_Vite_Net7/Vue3Vite/src/assets/element-icon/fonts/element-icons.woff b/Pure_Vite_Net7/Vue3Vite/src/assets/element-icon/fonts/element-icons.woff new file mode 100644 index 0000000000000000000000000000000000000000..02b9a2539e425a7a8c244faba92527602be76212 Binary files /dev/null and b/Pure_Vite_Net7/Vue3Vite/src/assets/element-icon/fonts/element-icons.woff differ diff --git a/Pure_Vite_Net7/Vue3Vite/src/assets/element-icon/icon.css b/Pure_Vite_Net7/Vue3Vite/src/assets/element-icon/icon.css new file mode 100644 index 0000000000000000000000000000000000000000..bf3ae3ef05dbcd805d4b63939cee84dee79e43d3 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/assets/element-icon/icon.css @@ -0,0 +1 @@ +@font-face{font-family:element-icons;src:url(fonts/element-icons.woff) format("woff"),url(fonts/element-icons.ttf) format("truetype");font-weight:400;font-display:"auto";font-style:normal}[class*=" el-icon-"],[class^=el-icon-]{font-family:element-icons!important;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;vertical-align:baseline;display:inline-block;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.el-icon-ice-cream-round:before{content:"\e6a0"}.el-icon-ice-cream-square:before{content:"\e6a3"}.el-icon-lollipop:before{content:"\e6a4"}.el-icon-potato-strips:before{content:"\e6a5"}.el-icon-milk-tea:before{content:"\e6a6"}.el-icon-ice-drink:before{content:"\e6a7"}.el-icon-ice-tea:before{content:"\e6a9"}.el-icon-coffee:before{content:"\e6aa"}.el-icon-orange:before{content:"\e6ab"}.el-icon-pear:before{content:"\e6ac"}.el-icon-apple:before{content:"\e6ad"}.el-icon-cherry:before{content:"\e6ae"}.el-icon-watermelon:before{content:"\e6af"}.el-icon-grape:before{content:"\e6b0"}.el-icon-refrigerator:before{content:"\e6b1"}.el-icon-goblet-square-full:before{content:"\e6b2"}.el-icon-goblet-square:before{content:"\e6b3"}.el-icon-goblet-full:before{content:"\e6b4"}.el-icon-goblet:before{content:"\e6b5"}.el-icon-cold-drink:before{content:"\e6b6"}.el-icon-coffee-cup:before{content:"\e6b8"}.el-icon-water-cup:before{content:"\e6b9"}.el-icon-hot-water:before{content:"\e6ba"}.el-icon-ice-cream:before{content:"\e6bb"}.el-icon-dessert:before{content:"\e6bc"}.el-icon-sugar:before{content:"\e6bd"}.el-icon-tableware:before{content:"\e6be"}.el-icon-burger:before{content:"\e6bf"}.el-icon-knife-fork:before{content:"\e6c1"}.el-icon-fork-spoon:before{content:"\e6c2"}.el-icon-chicken:before{content:"\e6c3"}.el-icon-food:before{content:"\e6c4"}.el-icon-dish-1:before{content:"\e6c5"}.el-icon-dish:before{content:"\e6c6"}.el-icon-moon-night:before{content:"\e6ee"}.el-icon-moon:before{content:"\e6f0"}.el-icon-cloudy-and-sunny:before{content:"\e6f1"}.el-icon-partly-cloudy:before{content:"\e6f2"}.el-icon-cloudy:before{content:"\e6f3"}.el-icon-sunny:before{content:"\e6f6"}.el-icon-sunset:before{content:"\e6f7"}.el-icon-sunrise-1:before{content:"\e6f8"}.el-icon-sunrise:before{content:"\e6f9"}.el-icon-heavy-rain:before{content:"\e6fa"}.el-icon-lightning:before{content:"\e6fb"}.el-icon-light-rain:before{content:"\e6fc"}.el-icon-wind-power:before{content:"\e6fd"}.el-icon-baseball:before{content:"\e712"}.el-icon-soccer:before{content:"\e713"}.el-icon-football:before{content:"\e715"}.el-icon-basketball:before{content:"\e716"}.el-icon-ship:before{content:"\e73f"}.el-icon-truck:before{content:"\e740"}.el-icon-bicycle:before{content:"\e741"}.el-icon-mobile-phone:before{content:"\e6d3"}.el-icon-service:before{content:"\e6d4"}.el-icon-key:before{content:"\e6e2"}.el-icon-unlock:before{content:"\e6e4"}.el-icon-lock:before{content:"\e6e5"}.el-icon-watch:before{content:"\e6fe"}.el-icon-watch-1:before{content:"\e6ff"}.el-icon-timer:before{content:"\e702"}.el-icon-alarm-clock:before{content:"\e703"}.el-icon-map-location:before{content:"\e704"}.el-icon-delete-location:before{content:"\e705"}.el-icon-add-location:before{content:"\e706"}.el-icon-location-information:before{content:"\e707"}.el-icon-location-outline:before{content:"\e708"}.el-icon-location:before{content:"\e79e"}.el-icon-place:before{content:"\e709"}.el-icon-discover:before{content:"\e70a"}.el-icon-first-aid-kit:before{content:"\e70b"}.el-icon-trophy-1:before{content:"\e70c"}.el-icon-trophy:before{content:"\e70d"}.el-icon-medal:before{content:"\e70e"}.el-icon-medal-1:before{content:"\e70f"}.el-icon-stopwatch:before{content:"\e710"}.el-icon-mic:before{content:"\e711"}.el-icon-copy-document:before{content:"\e718"}.el-icon-full-screen:before{content:"\e719"}.el-icon-switch-button:before{content:"\e71b"}.el-icon-aim:before{content:"\e71c"}.el-icon-crop:before{content:"\e71d"}.el-icon-odometer:before{content:"\e71e"}.el-icon-time:before{content:"\e71f"}.el-icon-bangzhu:before{content:"\e724"}.el-icon-close-notification:before{content:"\e726"}.el-icon-microphone:before{content:"\e727"}.el-icon-turn-off-microphone:before{content:"\e728"}.el-icon-position:before{content:"\e729"}.el-icon-postcard:before{content:"\e72a"}.el-icon-message:before{content:"\e72b"}.el-icon-chat-line-square:before{content:"\e72d"}.el-icon-chat-dot-square:before{content:"\e72e"}.el-icon-chat-dot-round:before{content:"\e72f"}.el-icon-chat-square:before{content:"\e730"}.el-icon-chat-line-round:before{content:"\e731"}.el-icon-chat-round:before{content:"\e732"}.el-icon-set-up:before{content:"\e733"}.el-icon-turn-off:before{content:"\e734"}.el-icon-open:before{content:"\e735"}.el-icon-connection:before{content:"\e736"}.el-icon-link:before{content:"\e737"}.el-icon-cpu:before{content:"\e738"}.el-icon-thumb:before{content:"\e739"}.el-icon-female:before{content:"\e73a"}.el-icon-male:before{content:"\e73b"}.el-icon-guide:before{content:"\e73c"}.el-icon-news:before{content:"\e73e"}.el-icon-price-tag:before{content:"\e744"}.el-icon-discount:before{content:"\e745"}.el-icon-wallet:before{content:"\e747"}.el-icon-coin:before{content:"\e748"}.el-icon-money:before{content:"\e749"}.el-icon-bank-card:before{content:"\e74a"}.el-icon-box:before{content:"\e74b"}.el-icon-present:before{content:"\e74c"}.el-icon-sell:before{content:"\e6d5"}.el-icon-sold-out:before{content:"\e6d6"}.el-icon-shopping-bag-2:before{content:"\e74d"}.el-icon-shopping-bag-1:before{content:"\e74e"}.el-icon-shopping-cart-2:before{content:"\e74f"}.el-icon-shopping-cart-1:before{content:"\e750"}.el-icon-shopping-cart-full:before{content:"\e751"}.el-icon-smoking:before{content:"\e752"}.el-icon-no-smoking:before{content:"\e753"}.el-icon-house:before{content:"\e754"}.el-icon-table-lamp:before{content:"\e755"}.el-icon-school:before{content:"\e756"}.el-icon-office-building:before{content:"\e757"}.el-icon-toilet-paper:before{content:"\e758"}.el-icon-notebook-2:before{content:"\e759"}.el-icon-notebook-1:before{content:"\e75a"}.el-icon-files:before{content:"\e75b"}.el-icon-collection:before{content:"\e75c"}.el-icon-receiving:before{content:"\e75d"}.el-icon-suitcase-1:before{content:"\e760"}.el-icon-suitcase:before{content:"\e761"}.el-icon-film:before{content:"\e763"}.el-icon-collection-tag:before{content:"\e765"}.el-icon-data-analysis:before{content:"\e766"}.el-icon-pie-chart:before{content:"\e767"}.el-icon-data-board:before{content:"\e768"}.el-icon-data-line:before{content:"\e76d"}.el-icon-reading:before{content:"\e769"}.el-icon-magic-stick:before{content:"\e76a"}.el-icon-coordinate:before{content:"\e76b"}.el-icon-mouse:before{content:"\e76c"}.el-icon-brush:before{content:"\e76e"}.el-icon-headset:before{content:"\e76f"}.el-icon-umbrella:before{content:"\e770"}.el-icon-scissors:before{content:"\e771"}.el-icon-mobile:before{content:"\e773"}.el-icon-attract:before{content:"\e774"}.el-icon-monitor:before{content:"\e775"}.el-icon-search:before{content:"\e778"}.el-icon-takeaway-box:before{content:"\e77a"}.el-icon-paperclip:before{content:"\e77d"}.el-icon-printer:before{content:"\e77e"}.el-icon-document-add:before{content:"\e782"}.el-icon-document:before{content:"\e785"}.el-icon-document-checked:before{content:"\e786"}.el-icon-document-copy:before{content:"\e787"}.el-icon-document-delete:before{content:"\e788"}.el-icon-document-remove:before{content:"\e789"}.el-icon-tickets:before{content:"\e78b"}.el-icon-folder-checked:before{content:"\e77f"}.el-icon-folder-delete:before{content:"\e780"}.el-icon-folder-remove:before{content:"\e781"}.el-icon-folder-add:before{content:"\e783"}.el-icon-folder-opened:before{content:"\e784"}.el-icon-folder:before{content:"\e78a"}.el-icon-edit-outline:before{content:"\e764"}.el-icon-edit:before{content:"\e78c"}.el-icon-date:before{content:"\e78e"}.el-icon-c-scale-to-original:before{content:"\e7c6"}.el-icon-view:before{content:"\e6ce"}.el-icon-loading:before{content:"\e6cf"}.el-icon-rank:before{content:"\e6d1"}.el-icon-sort-down:before{content:"\e7c4"}.el-icon-sort-up:before{content:"\e7c5"}.el-icon-sort:before{content:"\e6d2"}.el-icon-finished:before{content:"\e6cd"}.el-icon-refresh-left:before{content:"\e6c7"}.el-icon-refresh-right:before{content:"\e6c8"}.el-icon-refresh:before{content:"\e6d0"}.el-icon-video-play:before{content:"\e7c0"}.el-icon-video-pause:before{content:"\e7c1"}.el-icon-d-arrow-right:before{content:"\e6dc"}.el-icon-d-arrow-left:before{content:"\e6dd"}.el-icon-arrow-up:before{content:"\e6e1"}.el-icon-arrow-down:before{content:"\e6df"}.el-icon-arrow-right:before{content:"\e6e0"}.el-icon-arrow-left:before{content:"\e6de"}.el-icon-top-right:before{content:"\e6e7"}.el-icon-top-left:before{content:"\e6e8"}.el-icon-top:before{content:"\e6e6"}.el-icon-bottom:before{content:"\e6eb"}.el-icon-right:before{content:"\e6e9"}.el-icon-back:before{content:"\e6ea"}.el-icon-bottom-right:before{content:"\e6ec"}.el-icon-bottom-left:before{content:"\e6ed"}.el-icon-caret-top:before{content:"\e78f"}.el-icon-caret-bottom:before{content:"\e790"}.el-icon-caret-right:before{content:"\e791"}.el-icon-caret-left:before{content:"\e792"}.el-icon-d-caret:before{content:"\e79a"}.el-icon-share:before{content:"\e793"}.el-icon-menu:before{content:"\e798"}.el-icon-s-grid:before{content:"\e7a6"}.el-icon-s-check:before{content:"\e7a7"}.el-icon-s-data:before{content:"\e7a8"}.el-icon-s-opportunity:before{content:"\e7aa"}.el-icon-s-custom:before{content:"\e7ab"}.el-icon-s-claim:before{content:"\e7ad"}.el-icon-s-finance:before{content:"\e7ae"}.el-icon-s-comment:before{content:"\e7af"}.el-icon-s-flag:before{content:"\e7b0"}.el-icon-s-marketing:before{content:"\e7b1"}.el-icon-s-shop:before{content:"\e7b4"}.el-icon-s-open:before{content:"\e7b5"}.el-icon-s-management:before{content:"\e7b6"}.el-icon-s-ticket:before{content:"\e7b7"}.el-icon-s-release:before{content:"\e7b8"}.el-icon-s-home:before{content:"\e7b9"}.el-icon-s-promotion:before{content:"\e7ba"}.el-icon-s-operation:before{content:"\e7bb"}.el-icon-s-unfold:before{content:"\e7bc"}.el-icon-s-fold:before{content:"\e7a9"}.el-icon-s-platform:before{content:"\e7bd"}.el-icon-s-order:before{content:"\e7be"}.el-icon-s-cooperation:before{content:"\e7bf"}.el-icon-bell:before{content:"\e725"}.el-icon-message-solid:before{content:"\e799"}.el-icon-video-camera:before{content:"\e772"}.el-icon-video-camera-solid:before{content:"\e796"}.el-icon-camera:before{content:"\e779"}.el-icon-camera-solid:before{content:"\e79b"}.el-icon-download:before{content:"\e77c"}.el-icon-upload2:before{content:"\e77b"}.el-icon-upload:before{content:"\e7c3"}.el-icon-picture-outline-round:before{content:"\e75f"}.el-icon-picture-outline:before{content:"\e75e"}.el-icon-picture:before{content:"\e79f"}.el-icon-close:before{content:"\e6db"}.el-icon-check:before{content:"\e6da"}.el-icon-plus:before{content:"\e6d9"}.el-icon-minus:before{content:"\e6d8"}.el-icon-help:before{content:"\e73d"}.el-icon-s-help:before{content:"\e7b3"}.el-icon-circle-close:before{content:"\e78d"}.el-icon-circle-check:before{content:"\e720"}.el-icon-circle-plus-outline:before{content:"\e723"}.el-icon-remove-outline:before{content:"\e722"}.el-icon-zoom-out:before{content:"\e776"}.el-icon-zoom-in:before{content:"\e777"}.el-icon-error:before{content:"\e79d"}.el-icon-success:before{content:"\e79c"}.el-icon-circle-plus:before{content:"\e7a0"}.el-icon-remove:before{content:"\e7a2"}.el-icon-info:before{content:"\e7a1"}.el-icon-question:before{content:"\e7a4"}.el-icon-warning-outline:before{content:"\e6c9"}.el-icon-warning:before{content:"\e7a3"}.el-icon-goods:before{content:"\e7c2"}.el-icon-s-goods:before{content:"\e7b2"}.el-icon-star-off:before{content:"\e717"}.el-icon-star-on:before{content:"\e797"}.el-icon-more-outline:before{content:"\e6cc"}.el-icon-more:before{content:"\e794"}.el-icon-phone-outline:before{content:"\e6cb"}.el-icon-phone:before{content:"\e795"}.el-icon-user:before{content:"\e6e3"}.el-icon-user-solid:before{content:"\e7a5"}.el-icon-setting:before{content:"\e6ca"}.el-icon-s-tools:before{content:"\e7ac"}.el-icon-delete:before{content:"\e6d7"}.el-icon-delete-solid:before{content:"\e7c9"}.el-icon-eleme:before{content:"\e7c7"}.el-icon-platform-eleme:before{content:"\e7ca"}.el-icon-loading{-webkit-animation:rotating 2s linear infinite;animation:rotating 2s linear infinite}.el-icon--right{margin-left:5px}.el-icon--left{margin-right:5px}@-webkit-keyframes rotating{0%{-webkit-transform:rotateZ(0);transform:rotateZ(0)}100%{-webkit-transform:rotateZ(360deg);transform:rotateZ(360deg)}}@keyframes rotating{0%{-webkit-transform:rotateZ(0);transform:rotateZ(0)}100%{-webkit-transform:rotateZ(360deg);transform:rotateZ(360deg)}} \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/error-img.png b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/error-img.png new file mode 100644 index 0000000000000000000000000000000000000000..efe8ccb98a500f4a301ac69bfc9a198f67f27820 Binary files /dev/null and b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/error-img.png differ diff --git a/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/error.png b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/error.png new file mode 100644 index 0000000000000000000000000000000000000000..efe8ccb98a500f4a301ac69bfc9a198f67f27820 Binary files /dev/null and b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/error.png differ diff --git a/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/favicon.ico b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..9215c8930c51ccc9924ffde84b50f5e31b98d5f9 Binary files /dev/null and b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/favicon.ico differ diff --git a/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/h5/01.jpg b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/h5/01.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e0b3351318a180382ae42635e8e84a1be40ab6a1 Binary files /dev/null and b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/h5/01.jpg differ diff --git a/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/h5/02.jpg b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/h5/02.jpg new file mode 100644 index 0000000000000000000000000000000000000000..980d84ce4b6e5e488e0d0859c4f62e00c518e650 Binary files /dev/null and b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/h5/02.jpg differ diff --git a/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/h5/03.jpg b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/h5/03.jpg new file mode 100644 index 0000000000000000000000000000000000000000..60e1e4ca793a9dd87d4c31215637e5ece72e9c32 Binary files /dev/null and b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/h5/03.jpg differ diff --git a/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/h5/04.jpg b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/h5/04.jpg new file mode 100644 index 0000000000000000000000000000000000000000..69a4fb9918def775b5b7666d301e2e8f44df0710 Binary files /dev/null and b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/h5/04.jpg differ diff --git a/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/h5/05.jpg b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/h5/05.jpg new file mode 100644 index 0000000000000000000000000000000000000000..324d4039e7ddfe7c0366837ec61ce414ed0791c5 Binary files /dev/null and b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/h5/05.jpg differ diff --git a/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/h5/06.jpg b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/h5/06.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e7e56f76e1b06b27a44eb8bb76d0d3946c762780 Binary files /dev/null and b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/h5/06.jpg differ diff --git a/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/h5/07.jpg b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/h5/07.jpg new file mode 100644 index 0000000000000000000000000000000000000000..00797c6dd5f398dd194235a3ba618a9602d37a20 Binary files /dev/null and b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/h5/07.jpg differ diff --git a/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/log.png b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/log.png new file mode 100644 index 0000000000000000000000000000000000000000..83973304bede1760ad1b120ae338114c40841182 Binary files /dev/null and b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/log.png differ diff --git a/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/logo.png b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..165d86a27055aca1aeee1b03ed5d73155a0ac4b7 Binary files /dev/null and b/Pure_Vite_Net7/Vue3Vite/src/assets/imgs/logo.png differ diff --git a/Pure_Vite_Net7/Vue3Vite/src/assets/logo.png b/Pure_Vite_Net7/Vue3Vite/src/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..f3d2503fc2a44b5053b0837ebea6e87a2d339a43 Binary files /dev/null and b/Pure_Vite_Net7/Vue3Vite/src/assets/logo.png differ diff --git a/Pure_Vite_Net7/Vue3Vite/src/assets/script/buttons.js b/Pure_Vite_Net7/Vue3Vite/src/assets/script/buttons.js new file mode 100644 index 0000000000000000000000000000000000000000..119932e1b8fc054b412b0a872fcb2828565c3933 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/assets/script/buttons.js @@ -0,0 +1,84 @@ + +let buttons = [{ + name: "查 询", + value: 'Search', + icon: 'el-icon-search', + class: '', + type: 'primary', + onClick: function () { + this.search(); + } +}, +{ + name: "新 建", + icon: 'el-icon-plus', + value: 'Add', + class: '', + // plain:true, + type: 'success', + // plain:true, + onClick: function () { + this.add(); + } +},{ + name: "编 辑", + icon: 'el-icon-edit', + value: 'Update', + // plain:true, + class: '', + type: 'primary', + onClick: function () { + this.edit(); + } +}, { + name: "删 除", + icon: 'el-icon-delete', + class: '', + value: 'Delete', + type: 'danger', + onClick: function () { + this.del(); + } +}, { + name: "审 核", + icon: 'el-icon-check', + class: '', + value: 'Audit', + plain:true, + type: 'primary', + onClick: function () { + this.audit(); + } +}, +{ + name: "导 入", + icon: 'el-icon-top', + class: '', + type:'success', + plain:true, + value: 'Import', + onClick: function () { + this.import(); + } +}, { + name: "导 出", + icon: 'el-icon-bottom', + type:'success', + plain:true, + value: 'Export', + onClick: function () { + this.export(); + } +} +// , { +// name: "数据结构", +// icon: 'ios-cog', +// class: '', +// value: '', +// onClick: function () { +// this.openViewColumns(); +// } +// } +] + +export default buttons \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/assets/script/common.js b/Pure_Vite_Net7/Vue3Vite/src/assets/script/common.js new file mode 100644 index 0000000000000000000000000000000000000000..bf17bf0dfb118d41716f054df68b26ad35875a36 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/assets/script/common.js @@ -0,0 +1,4 @@ +var test1 = function () { + alert(11) +} +export { test1 } diff --git a/Pure_Vite_Net7/Vue3Vite/src/assets/script/extend.js b/Pure_Vite_Net7/Vue3Vite/src/assets/script/extend.js new file mode 100644 index 0000000000000000000000000000000000000000..5a43ebe02e163a1b4adea040ab386203343a77c1 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/assets/script/extend.js @@ -0,0 +1,5 @@ +//对vue参数进行扩展 +var extend = function (param) { + console.log(param) +} +export { extend } diff --git a/Pure_Vite_Net7/Vue3Vite/src/assets/script/require_image.js b/Pure_Vite_Net7/Vue3Vite/src/assets/script/require_image.js new file mode 100644 index 0000000000000000000000000000000000000000..51c71abfc817b7234940605f642cfa64b234fdbe --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/assets/script/require_image.js @@ -0,0 +1,16 @@ + +import errImgUrl from '@/assets/imgs/error.png' +import logoImgUrl from '@/assets/imgs/logo.png' + +var req =function (relationPath) { + var rst= new URL( relationPath, import.meta.url).href + return rst; +} + +var errImgRequire= req(errImgUrl) +var logoImgRequire= req(logoImgUrl) + + + +export { errImgRequire, logoImgRequire} + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/assets/script/testFormExtend.js b/Pure_Vite_Net7/Vue3Vite/src/assets/script/testFormExtend.js new file mode 100644 index 0000000000000000000000000000000000000000..833385f310a20911066c1b6d2c1b2b4167f8e3d9 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/assets/script/testFormExtend.js @@ -0,0 +1,20 @@ +//对vue参数进行扩展 +var extend = function ($vueParam) { + $vueParam.methods.volBoxFrom = function () { + this.$Message.info('扩展js,增加弹出消息') + this.$refs.volBoxFrom.show() + } + //修改data属性: + let data = $vueParam.data() + data.formFileds['extend'] = '动态扩展字段' + data.formOptions.splice(0, 0, { + filed: 'extend', + title: '动态增加字段', + type: 'text', + required: true + }) + $vueParam.data = function () { + return data + } +} +export { extend } diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/AsyncLoading.vue b/Pure_Vite_Net7/Vue3Vite/src/components/basic/AsyncLoading.vue new file mode 100644 index 0000000000000000000000000000000000000000..1ccf5c79af32674ccac6ccd37c567679932cc4b8 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/AsyncLoading.vue @@ -0,0 +1,10 @@ + + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/Audit.vue b/Pure_Vite_Net7/Vue3Vite/src/components/basic/Audit.vue new file mode 100644 index 0000000000000000000000000000000000000000..431d6c598da238cfb8e92c388969faae9e397633 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/Audit.vue @@ -0,0 +1,59 @@ + + + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/Empty.vue b/Pure_Vite_Net7/Vue3Vite/src/components/basic/Empty.vue new file mode 100644 index 0000000000000000000000000000000000000000..e5e6a79dc962c265fde954000274e407d6118a64 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/Empty.vue @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/ErrorMsg.vue b/Pure_Vite_Net7/Vue3Vite/src/components/basic/ErrorMsg.vue new file mode 100644 index 0000000000000000000000000000000000000000..3885ed5778ab93c16b8f7260d17e85143342ff6c --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/ErrorMsg.vue @@ -0,0 +1,3 @@ + diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/Icons.vue b/Pure_Vite_Net7/Vue3Vite/src/components/basic/Icons.vue new file mode 100644 index 0000000000000000000000000000000000000000..afd4250d1a1eea4fccda1a88f7a99c0bbdc97029 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/Icons.vue @@ -0,0 +1,345 @@ + + + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/QuickSearch.vue b/Pure_Vite_Net7/Vue3Vite/src/components/basic/QuickSearch.vue new file mode 100644 index 0000000000000000000000000000000000000000..185cbf2d8f849e887d0996ce1ea07511717525ff --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/QuickSearch.vue @@ -0,0 +1,152 @@ + + + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/RouterLoading.vue b/Pure_Vite_Net7/Vue3Vite/src/components/basic/RouterLoading.vue new file mode 100644 index 0000000000000000000000000000000000000000..134a454fab18ec69f61e0e02eb266e7dcd5be93c --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/RouterLoading.vue @@ -0,0 +1,105 @@ + + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/UploadExcel.vue b/Pure_Vite_Net7/Vue3Vite/src/components/basic/UploadExcel.vue new file mode 100644 index 0000000000000000000000000000000000000000..230fdadbb50373974ca7db801474614d607043cf --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/UploadExcel.vue @@ -0,0 +1,221 @@ + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/AuditHis.vue b/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/AuditHis.vue new file mode 100644 index 0000000000000000000000000000000000000000..d1fcb4871c8e70f2a442ee2cea5938cad4f64ac0 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/AuditHis.vue @@ -0,0 +1,46 @@ + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/ViewGrid.less b/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/ViewGrid.less new file mode 100644 index 0000000000000000000000000000000000000000..adc13c3e2ef085250169365183f098d238866992 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/ViewGrid.less @@ -0,0 +1,178 @@ +.view-container { + // padding: 15px; + background: white; + .grid-search { + padding-top: 15px; + //padding: 15px 15px 0 15px; + } + .grid-container, + .grid-body { + padding: 0 15px; + } + .view-header { + padding-left: 15px; + padding-right: 15px; + } + .fs-line { + height: 9px; + background: #f1f1f1; + margin-top: -10px; + margin-bottom: 10px; + } +} +.view-header { + height: 45px; + position: relative; + padding-bottom: 11px; + display: flex; + .search-line { + min-width: 150px; + } + .search-line > div { + margin-left: 5px; + margin-right: 10px; + } + .search-line > div > div { + width: 200px; + text-align: left; + } + .search-line > div:first-child { + flex: 1; + } + .search-line > div .ivu-select-dropdown { + max-height: 300px; + } + .btn-group { + white-space: nowrap; + button { + margin-left: 10px; + // padding: 5px 16px; + } + } + .btn-group .ivu-dropdown-item { + text-align: left !important; + } + .btn-group .ivu-dropdown-item:not(:last-child) { + border-bottom: 1px dotted #eee; + } + .desc-text { + margin-top: 5px; + font-weight: bold; + margin-bottom: 3px; + font-size: 14px; + color: #313131; + white-space: nowrap; + border-bottom: 2px solid #646565; + i { + font-size: 16px; + position: relative; + top: 1px; + margin-right: 2px; + } + } + .search-box { + background: #fefefe; + margin-top: 45px; + border: 1px solid #ececec; + position: absolute; + z-index: 999; + left: 0; + right: 0; + padding: 25px 40px; + padding-bottom: 0; + box-shadow: 0px 7px 18px -12px #bdc0bb; + } + .notice { + font-size: 13px; + color: #6b6b6b; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + position: relative; + top: 12px; + flex: 1; + left: 10px; + margin-right: 20px; + } +} + +.table-info-cell-title { + background-color: #f5f5f5 !important; +} +.box-com { + > div.item { + // margin-bottom: 10px; + padding: 15px 17px 0 8px; + margin-bottom: 12px; + background: white; + } + > div.form-item { + padding: 19px 16px 0px 5px; + //box-shadow: 0 1px 7px rgb(199, 199, 199); + } + > div.table-item { + padding: 0 10px; + border-top: 1.5px solid #eaeaea; + } + .v-text { + line-height: 27px; + } + .form-text { + position: relative; + border-bottom: 1px solid #eee; + font-size: 14px; + margin-bottom: 14px; + } +} + +.form-closex { + text-align: right; + padding-bottom: 24px; +} +.form-closex button { + margin-left: 10px; + padding: 4px 13px; +} +.toolbar { + padding: 3px 0px; + width: 100%; + display: flex; + .title { + line-height: 29px; + border-bottom: none; + font-size: 13px; + font-weight: bolder; + margin-bottom: 0; + color: #5d5c5c; + .icon { + color: #009688; + font-size: 18px; + } + + i { + line-height: 29px; + border-bottom: none; + font-weight: bolder; + margin-bottom: 0; + color: #5d5c5c; + position: relative; + margin-top: -4px; + font-size: 14px; + } + } + .btns { + line-height: 28px; + flex: 1; + text-align: right; + button { + // border: none; + // margin-left:15px; + border: 0px; + padding: 0px 9px; + color: #292929; + } + button:hover{ + color: #0089f6; + } + } +} diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/ViewGrid.vue b/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/ViewGrid.vue new file mode 100644 index 0000000000000000000000000000000000000000..d0abe9ed853583a952a0ae882795f35e226916bf --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/ViewGrid.vue @@ -0,0 +1,869 @@ + + + + + + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/ViewGridCustomColumn.js b/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/ViewGridCustomColumn.js new file mode 100644 index 0000000000000000000000000000000000000000..16a49e023b7a29f961259cf029dc61213b6547cf --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/ViewGridCustomColumn.js @@ -0,0 +1,151 @@ +export default { + initViewColumns(isReset) { + //初始化自定列配置 + if (isReset) { + this.resetViewColumns(); + } + if (!this.orginColumnFields) { + this.orginColumnFields = this.columns.map((c) => { + return c.field; + }); + } + this.viewColumns = this.columns + .filter((c) => { + return !c.hidden && !c.render; + }) + .map((c) => { + return { field: c.field, title: c.title, show: !c.hidden }; + }); + if (isReset) { + return; + } + this.getCacheViewColumn(); + }, + getViewCacheKey(){ + return 'custom:column'+this.table.name; + }, + getCacheViewColumn() { + try { + let columns = localStorage.getItem(this.getViewCacheKey()); + if (!columns) return; + columns = JSON.parse(columns); + if (columns.some(x=>{return !this.viewColumns.some(c=> {return c.field==x.field})})|| + this.viewColumns.some(x=>{return !columns.some(c=> {return c.field==x.field})}) + ) { + localStorage.removeItem(this.getViewCacheKey()) + return; + } + let sortTableColumns = []; + //弹出框的列 + let _viewColumns = []; + columns.forEach((column) => { + let _column = this.viewColumns.find((c) => { + return c.field == column.field; + }); + if (_column) { + _column.show = column.show; + _viewColumns.push(_column); + } + let tableColumn = this.columns.find((c) => { + return c.field == column.field; + }); + if (tableColumn) { + tableColumn.hidden = !column.show; + sortTableColumns.push(tableColumn); + } + }); + //重新排版弹出框自定义列 + let otherColumns = this.viewColumns.filter((c) => { + return !_viewColumns.some((s) => { + return c.field == s.field; + }); + }); + //重新排版弹出框自定义列 + _viewColumns.push(...otherColumns); + this.viewColumns.splice(0); + this.viewColumns.push(..._viewColumns); + + this.sortViewColumns(sortTableColumns); + } catch (error) { + console.log('设置默认自定义列异常:' + error.message); + } + }, + sortViewColumns(sortColumns) { + if (sortColumns.length) { + let hiddenColumns = this.columns.filter((c) => { + return !sortColumns.some((s) => { + return c.field == s.field; + }); + }); + sortColumns.push(...hiddenColumns); + this.columns.splice(0); + this.columns.push(...sortColumns); + } + }, + resetViewColumns() { + if (!this.orginColumnFields) { + return; + } + let _columns = []; + this.orginColumnFields.forEach((x) => { + _columns.push( + this.columns.find((c) => { + return c.field == x; + }) + ); + }); + let otherColumns = this.columns.filter((c) => { + return !this.orginColumnFields.some((s) => { + return c.field == s; + }); + }); + _columns.push(...otherColumns); + this.columns.splice(0); + this.columns.push(..._columns); + }, + showCustomModel() { + if (!this.viewColumns.length) { + this.initViewColumns(); + } + this.viewColumnsClone = JSON.parse(JSON.stringify(this.viewColumns)); + this.viewModel = true; + }, + closeCustomModel() { + this.viewModel=false; + if (this.checkColumnChanged()) { + this.viewColumns = JSON.parse(JSON.stringify(this.viewColumnsClone)); + } + }, + checkColumnChanged() { + return ( + JSON.stringify(this.viewColumns) != JSON.stringify(this.viewColumnsClone) + ); + }, + saveColumnConfig() { + let hasShowColumn = this.viewColumns.some((x) => { + return x.show; + }); + if (!hasShowColumn) { + return this.$message.error('至少选择一列显示'); + } + this.viewModel = false; + if (this.checkColumnChanged()) { + let sortColumns = []; + this.viewColumns.forEach((column) => { + let _column = this.columns.find((c) => { + return c.field == column.field; + }); + if (_column) { + _column.hidden = !column.show; + sortColumns.push(_column); + } + }); + this.sortViewColumns(sortColumns); + } + try { + localStorage.setItem(this.getViewCacheKey(), JSON.stringify(this.viewColumns)); + } catch (error) { + console.log('获取自定义列异常:' + error.message); + } + } +}; diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/ViewGridCustomColumn.vue b/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/ViewGridCustomColumn.vue new file mode 100644 index 0000000000000000000000000000000000000000..97feb802b30e34a195a3aabec9531925aa6ef976 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/ViewGridCustomColumn.vue @@ -0,0 +1,95 @@ + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/detailMethods.js b/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/detailMethods.js new file mode 100644 index 0000000000000000000000000000000000000000..88d5961ebb484d291d34b01b8f0b1b0425e12746 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/detailMethods.js @@ -0,0 +1,98 @@ +//从表方法 +let detailMethods = { + //查询从表前先做内部处理 + loadInternalDetailTableBefore(param, callBack) { + //加载明细表数据之前,需要设定查询的主表的ID + //每次只要加载明细表格数据就重置删除明细的值 + if (this.detailOptions.delKeys.length > 0) { + this.detailOptions.delKeys = []; + } + let key = this.table.key; + if (this.currentRow && this.currentRow.hasOwnProperty(key)) { + param.value = this.currentRow[key]; + } + return this.loadDetailTableBefore(param, callBack); + }, + detailRowOnChange(row) { + this.detailRowChange(row); + }, + detailRowChange(row) { + //checkbox选中行事件 + }, + detailRowOnClick({ row, column, event }) { + //明细表点击行事件2020.11.07 + this.detailRowClick({ row, column, event }); + }, + detailRowClick({ row, column, event }) {}, + resetDetailTable(row) { + //编辑和查看明细时重置从表数据 + if (!this.detailOptions.columns || this.detailOptions.columns.length == 0) { + return; + } + let key = this.table.key; + let query = { value: row ? row[key] : this.currentRow[key] }; + this.$nextTick(() => { + if (this.$refs.detail) { + this.$refs.detail.reset(); + this.$refs.detail.load(query); + } + }); + }, + //从后面加载从表数据 + refreshRow() { + this.resetDetailTable(); + }, + addRow() { + this.$refs.detail.addRow({}); + this.$refs.detail.edit.rowIndex=-1; + this.updateDetailTableSummaryTotal(); + }, + delRow() { + let rows = this.$refs.detail.getSelected(); + if (!rows || rows.length == 0) { + return this.$message.error('请选择要删除的行!'); + } + if (!this.delDetailRow(rows)) { + return false; + } + + let tigger = false; + this.$confirm('确认要删除选择的数据吗?', '警告', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + center: true + }).then(() => { + if (tigger) return; + tigger = true; + rows = this.$refs.detail.delRow(); + let key = this.detailOptions.key; + //记录删除的行数据 + rows.forEach((x) => { + if (x.hasOwnProperty(key) && x[key]) { + this.detailOptions.delKeys.push(x[key]); + } + }); + this.updateDetailTableSummaryTotal(); + }); + }, + updateDetailTableSummaryTotal() { + //2021.09.25增加明细表删除、修改时重新计算行数与汇总 + //2021.12.12增加明细表判断(强制刷新合计时会用到) + if (!this.$refs.detail) { + return; + } + //删除或新增行时重新设置显示的总行数 + this.$refs.detail.paginations.total = this.$refs.detail.rowData.length; + //重新设置合计 + if (this.$refs.detail.summary) { + this.$refs.detail.columns.forEach((column) => { + if (column.summary) { + this.$refs.detail.getInputSummaries(null, null, null, column); + } + }); + } + } +}; + +export default detailMethods; diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/index.js b/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/index.js new file mode 100644 index 0000000000000000000000000000000000000000..bd90205c82366606f5101ead658820142804da72 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/index.js @@ -0,0 +1,7 @@ +import Grid from './ViewGrid.vue' +const ViewGrid = { + install: function (app) { + app.component('ViewGrid', Grid) + } +} +export default ViewGrid \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/methods.js b/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/methods.js new file mode 100644 index 0000000000000000000000000000000000000000..799059285aa2a649982a7217c64bdbdbaa46c12b --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/methods.js @@ -0,0 +1,1691 @@ +import detailMethods from './detailMethods.js'; +//业务处理方法,全部可以由开发覆盖 +import serviceFilter from './serviceFilter.js'; +let methods = { + //当添加扩展组件gridHeader/gridBody/gridFooter及明细modelHeader/modelBody/modelFooter时, + //如果要获取父级Vue对象,请使用此方法进行回调 + parentCall(fun) { + if (typeof fun != 'function') { + return console.log('扩展组件需要传入一个回调方法才能获取父级Vue对象'); + } + fun(this); + }, + getCurrentAction() { + if (this.currentReadonly) { + return ''; + } + return '--' + (this.currentAction == this.const.ADD ? '新增' : '编辑'); + }, + quickSearchKeyPress($event) { + //查询字段为input时,按回车查询 + if ($event.keyCode == 13) { + if (this.searchFormFields[this.singleSearch.field] != '') { + this.search(); + } + } + }, + getButtons() { + //生成ViewGrid界面的操作按钮及更多选项 + let searchIndex = this.buttons.findIndex((x) => { + return x.value == 'Search'; + }); + //添加高级查询 + let hasOneFormItem = + this.searchFormOptions.length == 1 && + this.searchFormOptions[0].length == 1; + if (searchIndex != -1 && !hasOneFormItem) { + this.buttons.splice(searchIndex + 1, 0, { + icon: this.fiexdSearchForm ? 'el-icon-refresh-left' : 'el-icon-search', + name: this.fiexdSearchForm ? '重置' : '高级查询', + plain: true, + type: this.buttons[searchIndex].type, + onClick: () => { + if (this.fiexdSearchForm) { + return this.resetSearch(); + } + this.searchBoxShow = !this.searchBoxShow; + } + }); + } + if (hasOneFormItem) { + this.fiexdSearchForm = false; + } + this.maxBtnLength += searchIndex == -1 ? 0 : 1; + // if (this.buttons.length <= this.maxBtnLength) { + // return this.buttons; + // } + // let btns = this.buttons.slice(0, this.maxBtnLength); + // btns[this.maxBtnLength - 1].last = true; + // return btns; + }, + extendBtn(btns, source) { + //btns权限按钮,source为扩展按钮 + if (!btns || !(source && source instanceof Array)) { + return; + } + //source通过在表的扩展js文件中buttons对应按钮的属性index决定按钮所放位置 + source.forEach((x) => { + //通过按钮的Index属性,放到指定的位置 + btns.splice(x.index == undefined ? btns.length : x.index, 0, x); + }); + // if (this.extend.buttons.view) { + // this.extend.buttons.view.forEach((x) => { + // //通过按钮的Index属性,放到指定的位置 + // this.buttons.splice(x.index == undefined ? this.buttons.length : x.index, 0, x); + // }) + // } + }, + initBoxButtons() { + //初始化ViewGird与弹出框/明细表按钮 + let path = this.$route.path; + //通过菜单获取用户所对应菜单需要显示的按钮 + let permissionButtons = this.permission.getButtons( + path, + null, + this.extend.tableAction, + this.table.name + ); + if (permissionButtons) { + //2020.03.31添加深拷贝按钮组 + permissionButtons.forEach((p) => { + let _obj = {}; + for (const key in p) { + _obj[key] = p[key]; + } + this.buttons.push(_obj); + }); + // this.buttons.push(...permissionButtons); + } + if (!this.extend) { + this.extend = {}; + } + if (!this.extend.buttons) { + this.extend.buttons = {}; + } + //查询界面扩展按钮(扩展按钮可自行通过设置按钮的Index属性显示到具体位置) + if (this.extend.buttons.view) { + this.extendBtn(this.buttons, this.extend.buttons.view); + } + + //弹出框按钮 + let boxButtons = []; + + let saveBtn = this.buttons.some((x) => { + if ( + x.value && + (x.value.toLowerCase() == this.const.ADD.toLowerCase() || + x.value.toLowerCase() == this.const.EDIT.toLowerCase()) + ) + return true; + }); + this.currentReadonly = !saveBtn; + //从表表格操作按钮 + let detailGridButtons = { + name: '刷新', + type: 'info', + icon: 'el-icon-refresh', + onClick() { + //如果明细表当前的状态为新建时,禁止刷新 + if (this.currentAction == this.const.ADD) { + return; + } + this.refreshRow(); + } + }; + + let importExcel = this.buttons.some((x) => { + if (x.value == this.const.IMPORT) return true; + }); + //如果有导入权限,则需要初始化导入组件 + if (importExcel) { + this.upload.url = this.getUrl(this.const.IMPORT); + //定义下载模板的文件名 + this.upload.template.fileName = this.table.cnName; + //定义下载模板的Url路径 + this.upload.template.url = + this.http.ipAddress + this.getUrl(this.const.DOWNLOADTEMPLATE, true); + } + + // disabled + //如果当前角色没有编辑或新建功能,查看明细时字段设置全部只读 + //只有明细表,将明细表也设置为不可能编辑,并且不显示添加行、删除行 + if (!saveBtn) { + this.editFormOptions.forEach((row) => { + row.forEach((x) => { + x.disabled = true; + }); + }); + //没有新增编辑权限的,弹出框都设置为只读 + this.detail.columns.forEach((row) => { + if (row.hasOwnProperty('edit')) { + row['edit'] = false; + } + }); + //弹出框扩展按钮 + this.extendBtn(boxButtons, this.extend.buttons.box); + //弹出弹框按钮(2020.04.21),没有编辑或新建权限时,也可以通过buttons属性添加自定义弹出框按钮 + this.boxButtons.push(...boxButtons); + this.detailOptions.buttons.push(detailGridButtons); + this.detailOptions.buttons.forEach((button) => { + if (!button.hasOwnProperty('hidden')) { + button.hidden = false; + } + }); + //弹出框扩展明细表按钮 + this.extendBtn(this.detailOptions.buttons, this.extend.buttons.detail); + + return boxButtons; + } + + this.detailOptions.edit = true; + boxButtons.push( + ...[ + { + name: '保 存', + icon: 'el-icon-check', + type: 'danger', + disabled: false, + value: 'save', + onClick() { + this.save(); + } + } + // { + // name: '重 置', + // icon: 'el-icon-refresh-right', + // type: 'primary', + // disabled: false, + // onClick() { + // this.resetEdit(); + // } + // } + ] + ); + //从表表格操作按钮 + this.detailOptions.buttons.push( + ...[ + { + name: '添加行', + icon: 'el-icon-plus', + type: 'primary', + hidden: false, + plain: true, + onClick() { + this.addRow(); + } + }, + { + type: 'danger', + plain: true, + name: '删除行', + hidden: false, + icon: 'el-icon-delete', + onClick() { + this.delRow(); + } + }, + //2022.01.08增加明细表导入导出功能 + //注意需要重写后台明细表接口的导入与下载模板、导出的权限,Sys_DictionaryListController.cs/SellOrderListController.cs + { + type: 'danger', + plain: true, + name: '导入', + value: 'import', + hidden: false, + icon: 'el-icon-upload2', + onClick() { + this.upload.url = `${this.http.ipAddress}api/${this.detail.table}/${this.const.IMPORT}?table=1`; + this.upload.template.url = `${this.http.ipAddress}api/${this.detail.table}/${this.const.DOWNLOADTEMPLATE}`; + //定义下载模板的文件名 + this.upload.template.fileName = this.detail.cnName; + this.upload.excel = true; + } + }, + { + type: 'danger', + plain: true, + name: '导出', + value: 'export', + icon: 'el-icon-download', + hidden: false, + onClick() { + this.export(true); + } + } + ] + ); + this.detailOptions.buttons.forEach((button) => { + if (button.hasOwnProperty('hidden')) { + button.hidden = false; + } + }); + //弹出框扩展按钮 + this.extendBtn(boxButtons, this.extend.buttons.box); + + //弹出框扩展明细表按钮 + this.detailOptions.buttons.push(detailGridButtons); + this.extendBtn(this.detailOptions.buttons, this.extend.buttons.detail); + + //弹出弹框按钮 + this.boxButtons.push(...boxButtons); + }, + onClick(click) { + click.apply(this); + }, + changeDropdown(btnName, v1) { + let button = this.buttons.filter((x) => { + return x.name == btnName; + }); + if (button && button.length > 0) { + button[0].onClick.apply(this); + } + }, + emptyValue(value) { + if (typeof value == 'string' && value.trim() === '') { + return true; + } + if (value instanceof Array && !value.length) { + return true; + } + return value === null || value === undefined || value === ''; + }, + getSearchParameters() { + //获取查询参数 + // 2020.09.11增加固定查询表单,如果设置固定了查询表单,点击查询时,不再关闭 + if (!this.fiexdSearchForm) { + this.searchBoxShow = false; + } + + let query = { wheres: [] }; + for (const key in this.searchFormFields) { + let value = this.searchFormFields[key]; + if (this.emptyValue(value)) continue; + + if (typeof value == 'number') { + value = value + ''; + } + let displayType = this.getSearchItem(key); + + //联级只保留选中节点的最后一个值 + if (displayType == 'cascader') { + //查询下面所有的子节点,如:选中的是父节点,应该查询下面所有的节点数据--待完 + value = value.length ? value[value.length - 1] + '' : ''; + } + //2021.05.02增加区间查询 + if ( + typeof value == 'string' || + ['date', 'datetime', 'range'].indexOf(displayType) == -1 + ) { + query.wheres.push({ + name: key, + value: + typeof value == 'string' ? (value + '').trim() : value.join(','), + displayType: displayType + }); + continue; + } + for (let index = 0; index < value.length; index++) { + if (!this.emptyValue(value[index])) { + query.wheres.push({ + name: key, + value: (value[index] + '').trim(), + displayType: (() => { + if (['date', 'datetime', 'range'].indexOf(displayType) != -1) { + return index ? 'lessorequal' : 'thanorequal'; + } + return displayType; + })() + }); + } + } + } + return query; + }, + search() { + //查询 + // let query = this.getSearchParameters(); + // this.$refs.table.load(query, true); + this.$refs.table.load(null, true); + }, + loadTableBefore(param, callBack) { + //查询前设置查询条件及分页信息 + let query = this.getSearchParameters(); + if (query) { + param = Object.assign(param, query); + } + if (this.isViewFlow() && this.$route.query.id) { + param.wheres.push({ + name: this.table.key, + value: this.$route.query.id + }); + } + let status = this.searchBefore(param); + callBack(status); + }, + + loadTableAfter(data, callBack, result) { + //查询后 + //2020.10.30增加查询后返回所有的查询信息 + let status = this.searchAfter(data, result); + callBack(status); + //自动弹出框审批详情 + if (this.isViewFlow() && data && data.length) { + let query = JSON.parse(JSON.stringify(this.$route.query)); + query.viewflow = 0; + this.$router.replace({ path: this.$route.path, query: query }); + this.$nextTick(() => { + this.getWorkFlowSteps(data[0]); + }); + } + }, + loadDetailTableBefore(param, callBack) { + //明细查询前 + //新建时禁止加载明细 + if (this.currentAction == this.const.ADD) { + callBack(false); + return false; + } + let status = this.searchDetailBefore(param); + callBack(status); + }, + loadDetailTableAfter(data, callBack) { + //明细查询后 + let status = this.searchDetailAfter(data); + callBack(status); + }, + getSearchItem(field) { + //获取查询的参数 + let data; + for (let index = 0; index < this.searchFormOptions.length; index++) { + if (data) return data.type; + const item = this.searchFormOptions[index]; + data = item.find((x) => { + return x.field == field; + }); + } + + return (data || {}).type; + }, + resetSearch() { + //重置查询对象 + this.resetSearchForm(); + //2020.10.17增加重置后方法 + this.resetSearchFormAfter && this.resetSearchFormAfter(); + }, + resetEdit() { + //重置编辑的数据 + let isEdit = this.currentAction != this.const.ADD; + //重置之前 + if (!this[isEdit ? 'resetUpdateFormBefore' : 'resetAddFormBefore']()) { + return; + } + let objKey = {}; + //编辑状态下,不需要重置主键,创建时间创建人 + if (isEdit) { + objKey[this.table.key] = this.editFormFields[this.table.key]; + } + this.resetEditForm(objKey); + //重置之后 + + if (!this[isEdit ? 'resetUpdateFormAfter' : 'resetAddFormAfter']()) { + return; + } + }, + resetSearchForm(sourceObj) { + //重置查询表 + this.resetForm('searchForm', sourceObj); + }, + resetEditForm(sourceObj) { + if (this.hasDetail && this.$refs.detail) { + // this.$refs.detail.rowData.splice(0); + this.$refs.detail.reset(); + } + this.resetForm('form', sourceObj); + if (this.$refs.form && this.$refs.form.$refs.volform) { + setTimeout(() => { + this.$refs.form.$refs.volform.clearValidate(); + }, 100); + } + }, + getKeyValueType(formData, isEditForm) { + try { + let keyLeft = (isEditForm ? 'e' : 's') + '_b_'; + formData.forEach((item) => { + item.forEach((x) => { + if (this.keyValueType.hasOwnProperty(keyLeft + x.field)) { + return true; + } + let data; + if (x.type == 'switch') { + this.keyValueType[x.field] = 1; + } else if (x.bind && x.bind.data) { + data = x.bind.data; + } else if (x.data) { + if (x.data instanceof Array) { + data = x.data; + } else if (x.data.data && x.data.data instanceof Array) { + data = x.data.data; + } + } + if ( + data && + data.length > 0 && + !this.keyValueType.hasOwnProperty(x.field) + ) { + this.keyValueType[x.field] = data[0].key; + this.keyValueType[keyLeft + x.field] = x.type; + } + }); + }); + } catch (error) { + console.log(error.message); + } + }, + resetForm(formName, sourceObj) { + // return; + //重置表单数据 + if (this.$refs[formName]) { + this.$refs[formName].reset(); + } + + if (!sourceObj) return; + let form, keyLeft; + if (formName == 'searchForm') { + form = this.searchFormFields; + keyLeft = 's' + '_b_'; + } else { + form = this.editFormFields; + keyLeft = 'e' + '_b_'; + } + //获取数据源的data类型,否则如果数据源data的key是数字,重置的值是字符串就无法绑定值 + if (!this.keyValueType._dinit) { + this.getKeyValueType(this.editFormOptions, true); + this.getKeyValueType(this.searchFormOptions, false); + this.keyValueType._dinit = true; + } + var _cascaderParentTree; + for (const key in form) { + if (sourceObj.hasOwnProperty(key)) { + let newVal = sourceObj[key]; + let kv_type = this.keyValueType[keyLeft + key]; + + if ( + kv_type == 'selectList' || + kv_type == 'checkbox' || + kv_type == 'cascader' + ) { + // 2020.05.31增加iview组件Cascader + // 2020.11.01增加iview组件Cascader表单重置时查询所有的父节点 + if (kv_type == 'cascader') { + var treeDic = this.dicKeys.find((dic) => { + return dic.fileds && dic.fileds.indexOf(key) != -1; + }); + if (treeDic && treeDic.orginData && treeDic.orginData.length) { + if (typeof treeDic.orginData[0].id == 'number') { + newVal = newVal * 1 || 0; + } else { + newVal = newVal + ''; + } + _cascaderParentTree = this.base.getTreeAllParent( + newVal, + treeDic.orginData + ); + if (_cascaderParentTree) { + newVal = _cascaderParentTree.map((x) => { + return x.id; + }); + } + } else { + newVal = [newVal]; + } + } else if ( + newVal != '' && + newVal != undefined && + typeof newVal == 'string' + ) { + newVal = newVal.split(','); + } else if (kv_type == 'checkbox') { + newVal = []; + } + } else if ( + this.keyValueType.hasOwnProperty(key) && + typeof this.keyValueType[key] == 'number' && + newVal * 1 == newVal + ) { + newVal = newVal * 1; + } else { + if (newVal == null || newVal == undefined) { + newVal = ''; + } else if (this.numberFields.indexOf(key) != -1) { + newVal = newVal * 1 || 0; + } else { + newVal += ''; + } + } + if (newVal instanceof Array) { + if (form[key]) { + form[key] = []; + } + form[key] = newVal; + } else { + form[key] = newVal; + } + } else { + form[key] = form[key] instanceof Array ? [] : ''; + } + } + }, + onBtnClick(param) { + this[param.method](param.data); + }, + refresh() { + //刷新 + this.search(); + // this.$refs.table.load(); + }, + saveBefore(formData) { + return true; + }, + saveAfter(formData, result) { + return true; + }, + save() { + //新增或编辑时保存 + // if (!this.$refs.form.validate()) return; + this.$refs.form.validate((result) => { + if (result) { + this.saveExecute(); + } + }); + }, + async saveExecute() { + let editFormFields = {}; + //上传文件以逗号隔开 + for (const key in this.editFormFields) { + if ( + this.uploadfiled && + this.uploadfiled.length > 0 && + this.uploadfiled.indexOf(key) != -1 && + this.editFormFields[key] instanceof Array + ) { + let allPath = this.editFormFields[key].map((x) => { + return x.path; + }); + editFormFields[key] = allPath.join(','); + } else if (typeof this.editFormFields[key] == 'function') { + try { + editFormFields[key] = this.editFormFields[key](); + } catch (error) { } + } else { + //2021.05.30修复下拉框清除数据后后台不能保存的问题 + if ( + this.editFormFields[key] === undefined && + this.dicKeys.some((x) => { + return x.fileds && x.fileds.indexOf(key) != -1; + }) + ) { + editFormFields[key] = null; + } else { + editFormFields[key] = this.editFormFields[key]; + } + } + } + //将数组转换成string + //2020.11.01增加级联处理 + for (const key in editFormFields) { + if (editFormFields[key] instanceof Array) { + var iscascader = this.dicKeys.some((x) => { + return ( + x.type == 'cascader' && x.fileds && x.fileds.indexOf(key) != -1 + ); + }); + if (iscascader && editFormFields[key].length) { + editFormFields[key] = + editFormFields[key][editFormFields[key].length - 1]; + } else { + editFormFields[key] = editFormFields[key].join(','); + } + } + } + + let formData = { + mainData: editFormFields, + detailData: null, + delKeys: null + }; + + //获取明细数据(前台数据明细未做校验,待完.后台已经校验) + if (this.hasDetail) { + formData.detailData = this.$refs.detail.rowData; + let _fields = this.detail.columns + .filter((c) => { + return ( + c.type == 'selectList' || (c.edit && c.edit.type == 'selectList') + ); + }) + .map((c) => { + return c.field; + }); + //2022.06.20增加保存时对明细表下拉框多选的判断 + if (_fields.length) { + formData.detailData = JSON.parse(JSON.stringify(formData.detailData)); + formData.detailData.forEach((row) => { + for (let index = 0; index < _fields.length; index++) { + const _field = _fields[index]; + if (Array.isArray(row[_field])) { + row[_field] = row[_field].join(','); + } + } + }); + } + } + if (this.detailOptions.delKeys.length > 0) { + formData.delKeys = this.detailOptions.delKeys; + } + //保存前拦截 + let _currentIsAdd = this.currentAction == this.const.ADD; + if (_currentIsAdd) { + //2020.12.06增加新建前异步处理方法 + //2021.08.16修复异步语法写错的问题 + if (!this.addBefore(formData) || !(await this.addBeforeAsync(formData))) + return; + } else { + //2020.12.06增加修改前异步处理方法 + if ( + !this.updateBefore(formData) || + !(await this.updateBeforeAsync(formData)) + ) + return; + } + let url = this.getUrl(this.currentAction); + this.http.post(url, formData, true).then((x) => { + //保存后 + if (_currentIsAdd) { + if (!this.addAfter(x)) return; + //连续添加 + if (this.continueAdd && x.status) { + this.$success(x.message); + //新建 + this.currentAction = this.const.ADD; + this.currentRow = {}; + this.resetAdd(); + this.refresh(); + return; + } + } else { + if (!this.updateAfter(x)) return; + } + if (!x.status) return this.$error(x.message); + this.$success(x.message || '操作成功'); + //如果保存成功后需要关闭编辑框,直接返回不处理后面 + if (this.boxOptions.saveClose) { + this.boxModel = false; + //2020.12.27如果是编辑保存后不重置分页页数,刷新页面时还是显示当前页的数据 + this.$refs.table.load(null, _currentIsAdd); + //this.refresh(); + return; + } + let resultRow; + if (typeof x.data == 'string' && x.data != '') { + resultRow = JSON.parse(x.data); + } else { + resultRow = x.data; + } + + if (this.currentAction == this.const.ADD) { + // this.currentRow=x.data; + this.editFormFields[this.table.key] = ''; + this.currentAction = this.const.EDIT; + this.currentRow = resultRow.data; + } + this.resetEditForm(resultRow.data); + // console.log(resultRow); + if (this.hasDetail) { + this.detailOptions.delKeys = []; + if (resultRow.list) { + this.$refs.detail.rowData.push(...resultRow.list); + } + } + this.$refs.table.load(null, _currentIsAdd); + // this.refresh(); + }); + }, + del(rows) { + if (rows) { + if (!(rows instanceof Array)) { + rows = [rows]; + } + } else { + rows = this.$refs.table.getSelected(); + } + //删除数据 + + if (!rows || rows.length == 0) return this.$error('请选择要删除的行!'); + let delKeys = rows.map((x) => { + return x[this.table.key]; + }); + if (!delKeys || delKeys.length == 0) + return this.$error('没有获取要删除的行数据!'); + //删除前 + if (!this.delBefore(delKeys, rows)) { + return; + } + let tigger = false; + this.$confirm('确认要删除选择的数据吗?', '警告', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + center: true + }).then(() => { + if (tigger) return; + tigger = true; + let url = this.getUrl(this.const.DEL); + this.http.post(url, delKeys, '正在删除数据....').then((x) => { + if (!x.status) return this.$error(x.message); + this.$success(x.message); + //删除后 + if (!this.delAfter(x)) { + return; + } + this.refresh(); + }); + }); + }, + async modelOpenBeforeAsync(row) { + return true; + }, + async initBox() { + //2022.01.08增加新建时隐藏明细表导出功能 + this.detailOptions.buttons.forEach((x) => { + if (x.value == 'export') { + x.hidden = this.currentAction == 'Add'; + } + }); + //初始化新建、编辑的弹出框 + if (!(await this.modelOpenBeforeAsync(this.currentRow))) return false; + this.modelOpenBefore(this.currentRow); + if (!this.boxInit) { + this.boxInit = true; + this.boxModel = true; + // this.detailUrl = this.url; + } + return true; + }, + setEditForm(row) { + // if (this.remoteColumns.length == 0 || !rows || rows.length == 0) return; + let remoteColumns = this.$refs.table.remoteColumns; + remoteColumns.forEach((column) => { + this.editFormOptions.forEach((option) => { + option.forEach((x) => { + if (x.field == column.field) { + x.data.data = Object.assign([], x.data, column.bind.data); + } + }); + }); + }); + this.editFormFields; + //重置编辑表单数据 + this.editFormFields[this.table.key] = row[this.table.key]; + + this.resetEditForm(row); + this.currentAction = this.const.EDIT; + this.boxModel = true; + }, + async linkData(row, column) { + this.boxOptions.title = this.table.cnName + '(编辑)'; + //点击table单元格快捷链接显示编辑数据 + this.currentAction = this.const.EDIT; + this.currentRow = row; + if (!(await this.initBox())) return; + this.resetDetailTable(row); + this.setEditForm(row); + this.setContinueAdd(false); + //设置远程查询表单的默认key/value + this.getRemoteFormDefaultKeyValue(); + //点击编辑按钮弹出框后,可以在此处写逻辑,如,从后台获取数据 + this.modelOpenProcess(row); + }, + setContinueAdd(isAdd) { + if (!this.continueAdd) return; + var _button = this.boxButtons.find((x) => { + return x.value == 'save'; + }); + if (_button) { + _button.name = isAdd ? this.continueAddName : '保 存'; + } + }, + resetAdd() { + if (this.hasDetail) { + this.$refs.detail && + // this.$refs.detail.rowData && + this.$refs.detail.reset(); + } + let obj = {}; + //如果有switch标签,默认都设置为否 + this.editFormOptions.forEach((x) => { + x.forEach((item) => { + if (item.type == 'switch') { + obj[item.field] = 0; + } + }); + }); + this.resetEditForm(obj); + }, + async add() { + this.boxOptions.title = this.table.cnName + '(新建)'; + //新建 + this.currentAction = this.const.ADD; + this.currentRow = {}; + if (!(await this.initBox())) return; + + this.resetAdd(); + this.setContinueAdd(true); + // this.resetEditForm(); + this.boxModel = true; + //点击新建按钮弹出框后,可以在此处写逻辑,如,从后台获取数据 + this.modelOpenProcess(); + // this.modelOpenAfter(); + }, + async edit(rows) { + this.boxOptions.title = '编辑'; + //编辑 + this.currentAction = this.const.EDIT; + if (rows) { + if (!(rows instanceof Array)) { + rows = [rows]; + } + } else { + rows = this.$refs.table.getSelected(); + } + if (rows.length == 0) { + return this.$error('请选择要编辑的行!'); + } + if (rows.length != 1) { + return this.$error('只能选择一行数据进行编辑!'); + } + //记录当前编辑的行 + this.currentRow = rows[0]; + //初始化弹出框 + if (!(await this.initBox())) return; + this.setContinueAdd(false); + //重置表单 + this.resetDetailTable(); + + //设置当前的数据到表单上 + this.setEditForm(rows[0]); + //设置远程查询表单的默认key/value + this.getRemoteFormDefaultKeyValue(); + //点击编辑按钮弹出框后,可以在此处写逻辑,如,从后台获取数据 + this.modelOpenProcess(rows[0]); + // this.modelOpenAfter(rows[0]); + }, + getRemoteFormDefaultKeyValue() { + //设置表单远程数据源的默认key.value + if (this.currentAction != this.const.EDIT || this.remoteKeys.length == 0) + return; + this.editFormOptions.forEach((x, xIndex) => { + x.forEach((item, yIndex) => { + if (item.remote) { + let column = this.columns.find((x) => { + return x.bind && x.bind.key == item.dataKey; + }); + if (!column) return; + let key = this.currentRow[item.field]; + let obj = column.bind.data.find((x) => { + return x.key == key; + }); + // obj ? obj.value : key如果没有查到数据源,直接使用原数据 + item.data = [{ key: key, value: obj ? obj.value : key }]; + this.editFormOptions[xIndex].splice(yIndex, 1, item); + // this.$set(item, 'data', [{ key: key + '', value: obj.value }]) + // item.data = [{ key: key + '', value: obj.value }]; + } + }); + }); + }, + modelOpenProcess(row) { + this.$nextTick(() => { + this.modelOpenAfter(row); + }); + return; + // if (!this.$refs.form) { + // let timeOut = setTimeout(x => { + // this.modelOpenAfter(row); + // }, 500) + // return; + // } + // this.modelOpenAfter(row); + }, + import() { + //导入(上传excel),弹出导入组件UploadExcel.vue + this.upload.excel = true; + this.$refs.upload_excel && this.$refs.upload_excel.reset(); + }, + download(url, fileName) { + //下载导出的文件 + let xmlResquest = new XMLHttpRequest(); + xmlResquest.open('GET', url, true); + xmlResquest.setRequestHeader('Content-type', 'application/json'); + xmlResquest.setRequestHeader( + 'Authorization', + this.$store.getters.getToken() + ); + let elink = this.$refs.export; + xmlResquest.responseType = 'blob'; + xmlResquest.onload = function (oEvent) { + if (xmlResquest.status != 200) { + this.$error('下载文件出错了..'); + return; + } + let content = xmlResquest.response; + // let elink = this.$refs.export;//document.createElement("a"); + elink.download = fileName; //+".xlsx"; + // elink.style.display = "none"; + let blob = new Blob([content]); + elink.href = URL.createObjectURL(blob); + // document.body.appendChild(elink); + elink.click(); + // document.body.removeChild(elink); + }; + xmlResquest.send(); + }, + getFileName(isDetail) { + //2021.01.08增加导出excel时自定义文件名 + if (isDetail) { + return this.detail.cnName + '.xlsx'; + } + return this.table.cnName + '.xlsx'; + }, + export(isDetail) { + //导出 + let url, query, param; + if (isDetail) { + //明细表导出时如果是新建状态,禁止导出 + if (this.currentAction == 'Add') { + return; + } + url = `api/${this.detail.table}/${this.const.EXPORT}`; + param = { + wheres: [ + { name: this.table.key, value: this.editFormFields[this.table.key] } + ] + }; + } else { + //主表导出 + url = this.getUrl(this.const.EXPORT); + query = this.getSearchParameters(); + param = { order: this.pagination.order, wheres: query.wheres || [] }; + } + //2020.06.25增加导出前处理 + if (!isDetail && !this.exportBefore(param)) { + return; + } + + if (param.wheres && typeof param.wheres == 'object') { + param.wheres = JSON.stringify(param.wheres); + } + let $http = this.http; + //2022.09.26增加自定义导出文件名 + let fileName = this.downloadFileName || this.getFileName(isDetail); + //2021.01.08优化导出功能 + $http + .post(url, param, '正在导出数据....', { responseType: 'blob' }) + .then((content) => { + const blob = new Blob([content]); + if ('download' in document.createElement('a')) { + // 非IE下载 + const elink = document.createElement('a'); + elink.download = fileName; + elink.style.display = 'none'; + elink.href = URL.createObjectURL(blob); + document.body.appendChild(elink); + elink.click(); + URL.revokeObjectURL(elink.href); + document.body.removeChild(elink); + } else { + // IE10+下载 + navigator.msSaveBlob(blob, fileName); + } + }); + //.then(result => { + // if (!result.status) { + // return this.$error(result.message); + // } + // let path = this.getUrl(this.const.DOWNLOAD); + // path = path[0] == "/" ? path.substring(1) : path; + // this.download( + // $http.ipAddress + path + "?path=" + result.data, + // this.table.cnName + ".xlsx" // filePath + // ); + /// window.open($http.ipAddress + path + "?fileName=" + filePath, "_self"); + // }); + }, + getSelectRows() { + //获取选中的行 + return this.$refs.table.getSelected(); + }, + getDetailSelectRows() { + //或获取明细选中的行 + if (!this.$refs.detail) { + return []; + } + return this.$refs.detail.getSelected(); + }, + audit() { + //审核弹出框 + let rows = this.$refs.table.getSelected(); + if (rows.length == 0) return this.$error('请选择要审核的行!'); + let checkStatus = rows.every((x) => { + return x.AuditStatus > 0; + }); + if (checkStatus) return this.$error('只能选择审核中的数据!'); + this.auditParam.rows = rows.length; + this.auditParam.model = true; + }, + saveAudit() { + if (this.auditParam.status == -1 && this.auditParam.value == -1) { + this.$message.error('请选择审批状态'); + return; + } + //保存审核 + let keys = [this.editFormFields[this.table.key]]; + if (!this.auditBefore(keys, this.currentRow)) { + return; + } + let url = + this.getUrl(this.const.AUDIT) + + '?auditReason=' + + this.auditParam.reason + + '&auditStatus=' + + (this.auditParam.status < 0 + ? this.auditParam.value + : this.auditParam.status); + this.http.post(url, keys, '审核中....').then((x) => { + if (!this.auditAfter(x, keys)) { + return; + } + if (!x.status) return this.$error(x.message); + this.auditParam.rows = 0; + this.auditParam.status = -1; + this.auditParam.value = -1; + this.auditParam.reason = ''; + this.auditParam.model = false; + this.boxModel = false; + this.$success(x.message); + this.refresh(); + }); + }, + viewModelCancel() { + //查看表结构 + this.viewModel = false; + }, + initFormOptions(formOptions, keys, formFields, isEdit) { + //初始化查询、编辑对象的下拉框数据源、图片上传链接地址 + //let defaultOption = { key: "", value: "请选择" }; + //有上传的字段 + //2020.05.03新增 + //编辑数据源的类型 + formOptions.forEach((item) => { + item.forEach((d) => { + if (d.type == 'number') { + //2022.08.22优化表单类型为number时的默认值 + if (formFields[d.field] === '') { + formFields[d.field] = undefined; + } + this.numberFields.push(d.field); + } + if ( + d.type == 'img' || + d.type == 'excel' || + d.type == 'file' || + d.columnType == 'img' + ) { + d.url = this.http.ipAddress + 'api' + this.table.url + 'Upload'; + this.uploadfiled.push(d.field); + } + if (!d.dataKey) return true; + //2022.02.20强制开启联级可以选择某个节点 + if (d.type == 'cascader' && !d.hasOwnProperty('changeOnSelect')) { + //强制开启联级可以选择某个节点 + d.changeOnSelect = true; + } + //开启远程搜索 + if (d.remote) { + this.remoteKeys.push(d.dataKey); + d.data = []; //{ dicNo: d.dataKey, data: [] }; + return true; + } + //2020.05.03增加编辑表单对checkbox的支持 + if (d.type == 'checkbox' && !(formFields[d.field] instanceof Array)) { + formFields[d.field] = []; + } + if (keys.indexOf(d.dataKey) == -1) { + //2020.05.03增加记录编辑字段的数据源类型 + + keys.push(d.dataKey); + //2020.05.03修复查询表单与编辑表单type类型变成强一致性的问题 + //this.dicKeys.push({ dicNo: d.dataKey, data: [], type: d.type }); + // 2020.11.01增加iview组件Cascader数据源存储 + let _dic = { + dicNo: d.dataKey, + data: [], + fileds: [d.field], + orginData: [] + }; + if (d.type == 'cascader') { + _dic.type = 'cascader'; + } + if (isEdit) { + _dic['e_type'] = d.type; + } + this.dicKeys.push(_dic); + } else if (d.type == 'cascader') { + this.dicKeys.forEach((x) => { + if (x.dicNo == d.dataKey) { + x.type = 'cascader'; + x.fileds.push(d.field); + } + }); + } + if (d.type != 'cascader') { + //2020.01.30移除内部表单formOptions数据源配置格式data.data,所有参数改为与组件api格式相同 + Object.assign( + d, + this.dicKeys.filter((f) => { + return f.dicNo == d.dataKey; + })[0], + { type: d.type } + ); + } + }); + }); + }, + //初始table与明细表的数据源指向dicKeys对象,再去后台加载数据源 + initColumns(scoure, dicKeys, keys) { + if (!scoure || !(scoure instanceof Array)) return; + scoure.forEach((item) => { + if (!item.bind || (item.bind.data && item.bind.data.length > 0)) + return true; + let key = item.bind.key || item.bind.dicNo; + if (this.remoteKeys.indexOf(key) != -1) { + item.bind.remote = true; + return true; + } + if (this.hasKeyField.indexOf(item.field) == -1) { + this.hasKeyField.push(item.field); + } + var dic = dicKeys.filter((x) => { + return x.dicNo == key; + }); + if (!dic || dic.length == 0) { + dicKeys.push({ dicNo: key, data: [] }); + dic = [dicKeys[dicKeys.length - 1]]; + keys.push(key); + } + //2020.11.01增加级联处理 + if (dic[0].type == 'cascader') { + item.bind = { data: dic[0].orginData, type: 'select', key: key }; + } else { + item.bind = dic[0]; + } + //2020.05.03优化table数据源checkbox与select类型从编辑列中选取 + item.bind.type = item.bind.e_type || 'string'; + }); + }, + bindOptions(dic) { + //绑定下拉框的数据源 + //绑定后台的字典数据 + dic.forEach((d) => { + if (d.data.length >= (this.select2Count || 500)) { + if ( + !this.dicKeys.some((x) => { + return x.dicNo == d.dicNo && x.type == 'cascader'; + }) + ) { + d.data.forEach((item) => { + item.label = item.value; + item.value = item.key; + }); + } + } + this.dicKeys.forEach((x) => { + if (x.dicNo != d.dicNo) return true; + //2020.10.26增加级联数据源绑定处理 + if (x.type == 'cascader') { + // x.data=d.data; + //生成tree结构 + let _data = JSON.parse(JSON.stringify(d.data)); + //2022.04.04增加级联字典数据源刷新后table没有变化的问题 + this.columns.forEach((column) => { + if (column.bind && column.bind.key == d.dicNo) { + column.bind.data = d.data; + } + }); + let arr = this.base.convertTree(_data, (node, data, isRoot) => { + if (!node.inited) { + node.inited = true; + node.label = node.value; + node.value = node.key; + } + }); + x.data.push(...arr); + x.orginData.push(...d.data); + //2021.10.17修复查询级联不能绑定数据源的问题 + this.searchFormOptions.forEach((searhcOption) => { + searhcOption.forEach((_option) => { + if (_option.type == 'cascader' && _option.dataKey == x.dicNo) { + _option.data = arr; + _option.orginData = d.data; + } + }); + }); + //2021.10.17修复级联不能二级刷新的问题 + this.editFormOptions.forEach((editOption) => { + editOption.forEach((_option) => { + if (_option.type == 'cascader' && _option.dataKey == x.dicNo) { + _option.data = arr; + _option.orginData = d.data; + } + }); + }); + } else if (d.data.length > 0 && !d.data[0].hasOwnProperty('key')) { + let source = d.data, + newSource = new Array(source.length); + for (let index = 0; index < source.length; index++) { + newSource[index] = { + //默认从字典数据读出来的key都是string类型,但如果数据从sql中查询的可能为非string,否是async-validator需要重置设置格式 + key: source['key'] + '', //source[index][x.config.valueField] + "", + value: source['value'] //source[index][x.config.textField] + }; + } + + x.data.push(...newSource); + } else { + //2020.06.06,如果是selectList数据源使用的自定义sql并且key是数字,强制转换成字符串 + if ( + x.e_type == 'selectList' && + d.data.length > 0 && + typeof d.data[0].key == 'number' + ) { + d.data.forEach((c) => { + c.key = c.key + ''; + }); + } + x.data.push(...d.data); + } + if ( + this.singleSearch && + this.singleSearch.dataKey && + this.singleSearch.dataKey == x.dicNo + ) { + this.singleSearch.data.splice(0, 1, ...x.data); + } + }); + }); + }, + getUrl(action, ingorPrefix) { + //是否忽略前缀/ 获取操作的url + return (!ingorPrefix ? '/' : '') + 'api' + this.table.url + action; + }, + initDicKeys() { + //初始化字典数据 + let keys = []; + //2022.04.17优化重新加载数据源 + this.dicKeys.forEach((item) => { + item.data.splice(0); + item.orginData && item.orginData.splice(0); + }); + //this.dicKeys.splice(0); + //初始化编辑数据源,默认为一个空数组,如果要求必填设置type=number/decimal的最小值 + this.initFormOptions(this.editFormOptions, keys, this.editFormFields, true); + //初始化查询数据源,默认为一个空数组 + this.initFormOptions( + this.searchFormOptions, + keys, + this.searchFormFields, + false + ); + //查询日期设置为可选开始与结果日期 + this.searchFormOptions.forEach((item) => { + item.forEach((x) => { + if (x.type == 'date' || x.type == 'datetime') x.range = true; + }); + }); + //初始化datatable表数据源,默认为一个空数组,dicKeys为界面所有的数据字典编号 + this.initColumns(this.columns, this.dicKeys, keys); + //2021.05.23默认开启查询页面所有字段排序,如果不需要排序,在onInited遍历columns设置sort=false + //2021.09.25移除强制排序功能 + // this.columns.forEach(x => { + // x.sort = x.render ? false : true; + // }) + if (this.detailOptions && this.detailOptions.columns) { + this.initColumns(this.detailOptions.columns, this.dicKeys, keys); + } + //初始化快速查询字段,默认使用代码生成器配置的第一个查询字段 + if (this.searchFormOptions.length > 0) { + this.singleSearch = { + dataKey: this.searchFormOptions[0][0].dataKey, + dicNo: this.searchFormOptions[0][0].dicNo, + field: this.searchFormOptions[0][0].field, + title: this.searchFormOptions[0][0].title, + type: this.searchFormOptions[0][0].type, + data: [] + }; + // this.singleSearch = this.searchFormOptions[0][0]; + } + if (keys.length == 0) return; + let $this = this; + this.http.post('/api/Sys_Dictionary/GetVueDictionary', keys).then((dic) => { + $this.bindOptions(dic); + //2022.04.04增加字典加载完成方法 + $this.dicInited && $this.dicInited(dic); + }); + }, + setFiexdColumn(columns, containerWidth) { + //计算整个table的宽度,根据宽度决定是否启用第一行显示的列为固定列 + //2021.09.21移除强制固定第一列 + // let columnsWidth = 0; + // columns.forEach(x => { + // if (!x.hidden && x.width) { + // columnsWidth += x.width; + // } + // }); + // //启用第一列为固定列 + // if (columnsWidth > containerWidth) { + // let firstColumn = columns.find(x => !x.hidden); + // if (firstColumn) { + // firstColumn.fixed = true; + // } + // } + }, + initBoxHeightWidth() { + //初始化弹出框的高度与宽度 + let clientHeight = document.documentElement.clientHeight; + //弹出框高度至少250px + clientHeight = clientHeight < 250 ? 250 : clientHeight; + let clientWidth = document.documentElement.clientWidth; + if ( + this.editFormOptions.some((x) => { + return x.some((item) => { + return item.type == 'editor'; + }); + }) + ) { + this.editor.uploadImgUrl = this.getUrl('upload'); + this.boxOptions.height = clientHeight * 0.8; + this.boxOptions.width = clientWidth * 0.8; + } else { + if (this.boxOptions.height) { + //如果高度与宽度超过了获取到的可见高宽度,则设为默认的90%高宽 + if (this.boxOptions.height > clientHeight * 0.8) { + this.boxOptions.height = clientHeight * 0.8; + } + } + if (this.boxOptions.width) { + //如果高度与宽度超过了获取到的可见高宽度,则设为默认的90%高宽 + if (this.boxOptions.width > clientWidth * 0.8) { + this.boxOptions.width = clientWidth * 0.8; + } + } + } + //计算整个table的宽度,根据宽度决定是否启用第一行显示的列为固定列 + let maxTableWidth = clientWidth - 270; + this.setFiexdColumn(this.columns, maxTableWidth); + + this.height = this.tableHeight || clientHeight - 206; + this.url = this.getUrl(this.const.PAGE); + //计算弹出框的高与宽度 + //如果有明细表,高度与宽带设置为0.9/0.82 + if (this.detail.columns && this.detail.columns.length > 0) { + this.hasDetail = true; + clientWidth = clientWidth * 0.8; + clientHeight = clientHeight * 0.85; + if (!this.detailOptions.height) { + this.detailOptions.height = + clientHeight - this.editFormOptions.length * 36 - 234; + this.detailOptions.height = + this.detailOptions.height < 240 ? 240 : this.detailOptions.height; + } + + this.detailOptions.columns = this.detail.columns; + this.detailOptions.pagination.sortName = this.detail.sortName; + this.detailOptions.cnName = this.detail.cnName; + this.detailOptions.key = this.detail.key; + this.detailOptions.url = this.getUrl('getDetailPage'); + //计算弹出框整个table的宽度,根据宽度决定是否启用第一行显示的列为固定列 + this.setFiexdColumn(this.detail.columns, clientWidth); + } else { + let maxColumns = 1; //最大列数,根据列计算弹框的宽度 + this.editFormOptions.forEach((x) => { + if (x.length > maxColumns) maxColumns = x.length; + }); + let maxHeightRate = 0.7, + maxWidthRate = 0.5; + maxWidthRate = maxColumns / 10 + 0.3; + maxHeightRate = (this.editFormOptions.length || 1) * 0.1 + 0.03; + maxHeightRate = maxHeightRate > 0.9 ? 0.9 : maxHeightRate; + clientWidth = clientWidth * maxWidthRate; + clientHeight = clientHeight * maxHeightRate; + // this.boxOptions.width = clientWidth * maxWidthRate; + // this.boxOptions.height = clientHeight * maxHeightRate; + } + if (!this.boxOptions.height) { + this.boxOptions.height = clientHeight + 10; + } + if (!this.boxOptions.width) { + this.boxOptions.width = clientWidth + 30; + } + }, + rowOnChange(row) { + this.rowChange(row); + }, + rowChange(row) { + //选中行checkbox行事件 + }, + rowOnClick({ row, column, event }) { + this.rowClick({ row, column, event }); + }, + rowClick({ row, column, event }) { + // 点击行事件(2020.11.07) + }, + rowOnDbClick({ row, column, event }) { + this.rowDbClick({ row, column, event }); + }, + rowDbClick({ row, column, event }) { + // 双击击行事件(2021.05.23) + }, + $error(message) { + this.$message.error(message); + // this.$message({ + // type: 'error', + // content: message, + // duration: 5 + // }); + }, + $success(message) { + this.$message.success(message); + }, + setFiexdSearchForm(visiable) { + //2020.09.011增加固定查询表单功能,visiable=true默认将查询表单展开 + this.fiexdSearchForm = true; + let refreshBtn = this.buttons.find((x) => x.name == '刷 新'); + if (visiable) { + this.searchBoxShow = true; + } + if (refreshBtn) { + refreshBtn.name = '重 置'; + refreshBtn.onClick = function () { + this.resetSearch(); + }; + } + }, + tableBeginEdit(row, column, index) { + //2021.03.19是否开启查询界面表格双击编辑结束方法,返回false不会结束编辑 + return this.beginEdit(row, column, index); + }, + beginEdit(row, column, index) { + //2021.03.19是否开启查询界面表格双击编辑结束方法,返回false不会结束编辑 + return true; + }, + tableEndEditBefore(row, column, index) { + return this.endEditBefore(row, column, index); + }, + endEditBefore(row, column, index) { + //2021.03.19是否开启查询界面表格双击编辑结束方法,返回false不会结束编辑 + return true; + }, + filterPermission(tableName, permission) { + //2021.03.19判断是否有某个表的按钮权限 + //:["Search","Add","Delete","Update","Import","Export","Upload","Audit"] + const _result = (this.$store.state.permission || []).find((x) => { + return x.url == '/' + tableName; + }); + return _result && _result.permission.some((x) => x == permission); + }, + destroyed() { + //2021.04.11增加vue页面销毁方法,路由必须设置keepLive:false,设置方法见:前端开发文档-》[禁用页面缓存keepAlive] + }, + loadTreeTableChildren(tree, treeNode, resolve) { + this.loadTreeChildren.call(this, tree, treeNode, resolve); + }, + loadTreeChildren(tree, treeNode, resolve) { + //树形结构加载子节点(2021.05.02),在onInit中设置了rowKey主键字段后才会生效 + return resolve([]); + }, + importDetailAfter(data) { + //2022.01.08增加明细表导入后处理 + }, + importExcelAfter(data) { + //2022.01.08增加明细表导入后方法判断 + + if (!data.status) { + return; // this.$message.error(data.message); + } + //明细表导入 + if (this.boxModel) { + if (data.data) { + data.data = JSON.parse(data.data); + } else { + data.data = []; + } + data.data.forEach((x) => { + x[this.detail.key] = undefined; + x[this.table.key] = undefined; + }); + this.importDetailAfter(data); //增加明细表导入后处理 + this.$refs.detail.rowData.unshift(...data.data); + this.upload.excel = false; + return; + } + this.importAfter(data); + }, + onGridModelClose(iconClick) { + if (this.isBoxAudit) { + this.initFormOptionType(false); + } + this.isBoxAudit = false; + this.onModelClose(iconClick); + }, + initAuditColumn() { + let _btn = this.buttons.find((x) => { + return x.value == 'Audit'; + }); + let auditField = this.columns + .map((m) => { + return m.field; + }) + .find((name) => { + return (name || '').toLowerCase() == 'auditstatus'; + }); + if (!_btn || !auditField) return; + + _btn.hidden = true; + this.columns.push({ + field: '操作', + title: '操作', + width: 70, + fixed: 'right', + align: 'center', + formatter: (row) => { + return ( + '查看' + : 'class="el-icon-edit">审核') + ); + }, + click: (row) => { + this.getWorkFlowSteps(row); + } + }); + }, + getWorkFlowSteps(row) { + let table = this.table.url.replaceAll('/', ''); + let url = `api/Sys_WorkFlow/getSteps?tableName=${table}&id=${row[this.table.key] + }`; + this.http.get(url, {}, true).then((result) => { + this.workFlowSteps.splice(0); + //有可能没有配置审批流程 + if (!result.list || !result.list.length) { + result.list = []; + this.auditParam.showAction = true; + this.auditParam.height = 240; + this.auditParam.showViewButton = row.AuditStatus == 0; + } else { + this.auditParam.showAction = result.list.some((c) => { + return c.isCurrentUser; + }); + this.auditParam.height = 511; + this.auditParam.showViewButton = true; + } + this.auditParam.reason = ''; + this.auditParam.status = -1; + this.auditParam.value = -1; + if (result.his) { + result.his.forEach((item) => { + item.auditStatus = this.getAuditStatus(item.auditStatus); + }); + } + + this.auditParam.auditHis = result.his; + this.workFlowSteps.push(...result.list); + this.isBoxAudit = true; + this.initFormOptionType(true); + this.edit(row); + this.boxOptions.title = '审核'; + }); + }, + initFormOptionType(isReadonly) { + this.editFormOptions.forEach((options) => { + options.forEach((option) => { + if (isReadonly) { + if (!option.readonly) { + this.formFieldsType.push(option.field); + option.readonly = true; + } + } else { + if (this.formFieldsType.indexOf(option.field) != -1) { + option.readonly = false; + } + } + }); + }); + }, + getAuditStatus(status) { + let data = this.auditParam.data.find((x) => { + return x.value == status; + }); + if (!data) { + return '-'; + // return `审核值不正确:${status}` + } + return data.text; + }, + isViewFlow() { + return this.$route.query.viewflow == '1'; + } +}; +import customColumns from './ViewGridCustomColumn.js'; +//合并扩展方法 +methods = Object.assign(methods, detailMethods, serviceFilter, customColumns); +export default methods; diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/props.js b/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/props.js new file mode 100644 index 0000000000000000000000000000000000000000..5d0ebc62453180d8a87f4269330b7bedc1e1c365 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/props.js @@ -0,0 +1,55 @@ +let props = { + columns: {//当前表的配置信息 + type: Array, + default: () => { + return []; + } + }, + detail: {//从表明细配置 + type: Object, + default: () => { + return { + columns: [],//从表列 + sortName: ""//从表排序字段 + }; + } + }, + editFormFields: {//新建、编辑字段(key/value) + type: Object, + default: () => { + return {}; + } + }, + editFormOptions: {//新建、编辑配置信息 + type: Array, + default: () => { + return []; + } + }, + searchFormFields: {//查询字段(key/value) + type: Object, + default: () => { + return {}; + } + }, + searchFormOptions: {//查询配置信息(key/value) + type: Array, + default: () => { + return []; + } + }, + table: {//表的配置信息:主键、排序等 + type: Object, + default: () => { + return {}; + } + }, + extend: {//表的扩展方法与组件都合并到此属性中 + type: Object, + default: () => { + return {}; + } + } +} + +export default props; \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/serviceFilter.js b/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/serviceFilter.js new file mode 100644 index 0000000000000000000000000000000000000000..101d1a65dfce03b0d8dc9e50cce79b5d5f7223a3 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/ViewGrid/serviceFilter.js @@ -0,0 +1,106 @@ + + +let serviceFilter = { + onInit () { //对应created + console.log('Create执行前') + }, + onInited () { //对应created,在onInit与onInited中间会初始化界面数据对象 + console.log('Create执行后') + }, + mounted () { + console.log('mounted'); + }, + searchBefore (param) { //查询ViewGird表数据前,param查询参数 + // console.log('表' + this.table.cnName + '触发loadTableBefore'); + return true; + }, + //2020.10.30增加查询后返回所有的查询信息 + searchAfter (param, result) { //查询ViewGird表数据后param查询参数,result回返查询的结果 + // console.log('表' + this.table.cnName + '触发loadTableAfter'); + return true; + }, + searchDetailBefore (param) {//查询从表表数据前,param查询参数 + //console.log(this.detailOptions.cnName + '触发loadDetailTableBefore'); + return true; + }, + searchDetailAfter (param, data) {//查询从表后param查询参数,result回返查询的结果 + // console.log(this.detailOptions.cnName + '触发loadDetailTableAfter'); + return true; + }, + delBefore (ids, rows) { //查询界面的表删除前 ids为删除的id数组,,rows删除的行 + return true; + }, + delAfter (result) {//查询界面的表删除后 + return true; + }, + delDetailRow (rows) { //弹出框删除明细表的行数据(只是对table操作,并没有操作后台) + return true; + }, + addBefore (formData) { //新建保存前formData为对象,包括明细表 + return true; + }, + async addBeforeAsync (formData) { //异步处理,功能同上(2020.12.06) + return true; + }, + addAfter (result) {//新建保存后result返回的状态及表单对象 + return true; + }, + updateBefore (formData) { //编辑保存前formData为对象,包括明细表、删除行的Id + return true; + }, + async updateBeforeAsync (formData) { //异步处理,功能同上(2020.12.06) + return true; + }, + updateAfter (result) {//编辑保存后result返回的状态及表单对象 + return true; + }, + auditBefore (ids, rows) {//审核前 + return true; + }, + auditAfter (result, rows) {// 审核后 + return true; + }, + resetAddFormBefore () { //重置新建表单前的内容 + return true; + }, + resetAddFormAfter () { //重置新建表单后的内容 + return true; + }, + resetUpdateFormBefore () { //重置编辑表单前的内容 + return true; + }, + resetUpdateFormAfter () { //重置编辑表单后的内容 + return true; + }, + modelOpenBefore (row) { //点击编辑/新建按钮弹出框前,可以在此处写逻辑,如,从后台获取数据 + + }, + modelOpenAfter (row) { //点击编辑/新建按钮弹出框后,可以在此处写逻辑,如,从后台获取数据 + + }, + importAfter (data) { //导入excel后刷新table表格数据 + this.search(); + }, + //2020.10.31添加导入前的方法 + importExcelBefore (formData) { //导入excel导入前 + //往formData写一些其他参数提交到后台, + // formData.append("val2", "xxx"); + //后台按下面方法获取请求的参数 + // Core.Utilities.HttpContext.Current.Request("val2"); + return true; + }, + reloadDicSource () { //重新加载字典绑定的数据源 + this.initDicKeys(); + }, + exportBefore (param) { //2020.06.25增加导出前处理 + return true; + }, + onModelClose(iconClick){ + //iconClick=true为点击左中上角X触发的关闭事件 + //如果返回 false不会关闭弹出框 + //return false; + this.boxModel=false; + } + +} +export default serviceFilter; diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolBox.vue b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolBox.vue new file mode 100644 index 0000000000000000000000000000000000000000..06ca7ad9b520bed619a1c48418a6f4d4dd16fc83 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolBox.vue @@ -0,0 +1,156 @@ + + + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolElementMenu.vue b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolElementMenu.vue new file mode 100644 index 0000000000000000000000000000000000000000..d04173075855d564e778d837e02db8a17c32ffc8 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolElementMenu.vue @@ -0,0 +1,198 @@ + + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolElementMenuChild.vue b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolElementMenuChild.vue new file mode 100644 index 0000000000000000000000000000000000000000..ccea3218d5909a19ae82d37b2fe812f251b690b2 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolElementMenuChild.vue @@ -0,0 +1,56 @@ + + + + + + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolForm.vue b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolForm.vue new file mode 100644 index 0000000000000000000000000000000000000000..0a94b5d64aae57818c7673e61f4b6309ec2ab404 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolForm.vue @@ -0,0 +1,1438 @@ + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolForm/VolFormRender.js b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolForm/VolFormRender.js new file mode 100644 index 0000000000000000000000000000000000000000..ef7459e9ec081236039be444aa2d1de8ee4771be --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolForm/VolFormRender.js @@ -0,0 +1,14 @@ +import { h } from 'vue'; + +export default { + name: "FormExpand", + functional: true, + props: { + render: Function, + par: {}//测试参数 + }, + render: ({ render, par }) => { + return render(h, { par }); //h(); + } +}; + diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolFormDraggable/DownloadForm.js b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolFormDraggable/DownloadForm.js new file mode 100644 index 0000000000000000000000000000000000000000..69bf098fcc8408df0ea8e97b4760e3f2f78b8e4c --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolFormDraggable/DownloadForm.js @@ -0,0 +1,156 @@ +import templateCode from './templateCode' +export default function () { + let code = templateCode; + let _formOptions = this.options.formOptions.map(m => { + let _op = m.map((m1, i) => { + let _obj; + //.data[0].hasOwnProperty("key") + if (m1.data && m1.data.length && !m1.dataKey) { + let m2 = JSON.parse(JSON.stringify(m1)); + m2.data = m2.data.map(c => { + return { key: c.label || c.key, value: c.label } + }) + _obj = JSON.stringify(m2) + } else { + _obj = JSON.stringify(m1) + } + return (i === 0 ? '' : '\n\t\t\t\t') + _obj + }).join(','); + //return JSON.stringify(m, null, '') + return _op; + }) + code = code.replace('{#fields}', JSON.stringify(this.options.fields)) + .replace('{#formOptions}', '[' + _formOptions.join('],\n\t\t\t\t[') + ']'); + code = code.replace('}],', '\t\t\t\t\t}],') + .replace("[{#tableOptions}]", JSON.stringify(this.options.tables, null, '\t')) + .replace("[{#tabsOptions}]", JSON.stringify(this.options.tabs, null, '\t')) + // fields: {#fields}, + // formOptions: [{#formOptions}], + // tables: [{#tables}], + // tabs: [{#tabs}] + var tabsText = this.options.tabs.length ? `
+ + +
+
+ {{ item.name }} +
+
+ + {{ btnItem.name }} + +
+
+ +
+
+
`: '' + code = code.replace('{#tabs}', tabsText); + if (this.options.tables.length || this.options.tabs.length) { + code = code.replace("{import_VolTable}", "import VolTable from '@/components/basic/VolTable'") + code = code.replace(",{component_table}", ",'vol-table': VolTable") + } else { + code = code.replace("{import_VolTable}", '') + code = code.replace("{component_table}", '') + } + + if (this.options.tables.length) { + + code = code.replace('{table_ms}', ` + tableBtnClick (item, btnIndex, index) { + if (item.buttons[btnIndex].value == "add") { + this.$refs["table" + index][0].addRow({}); + return; + } + if (item.buttons[btnIndex].value == "del") { + this.$refs["table" + index][0].delRow(); + return; + } + }, + tabsTableBtnClick (item, btnIndex, index) { + if (item.buttons[btnIndex].value == "add") { + this.$refs["tabsTable" + index][0].addRow({}); + return; + } + if (item.buttons[btnIndex].value == "del") { + this.$refs["tabsTable" + index][0].delRow(); + return; + } + },`) + code = code.replace('{#tables}', + ` + +
+
+
+
+ {{ item.name }} +
+
+ + {{ btnItem.name }} + +
+
+ +
+
`); + + } else { + + code = code.replace('{table_ms}', '') + code = code.replace('{#tables}', ''); + } + const blob = new Blob([code], { type: "text/plain;charset=utf-8" }) + if ('download' in document.createElement('a')) { // 非IE下载 + const elink = document.createElement('a') + elink.download = `code${new Date().valueOf()}.vue`; + elink.style.display = 'none' + elink.href = URL.createObjectURL(blob) + document.body.appendChild(elink) + elink.click() + URL.revokeObjectURL(elink.href) // 释放URL 对象 + document.body.removeChild(elink) + } else { + navigator.msSaveBlob(blob, fileName) + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolFormDraggable/VolFormDraggable.vue b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolFormDraggable/VolFormDraggable.vue new file mode 100644 index 0000000000000000000000000000000000000000..b57d697c5d9986956b485caca13955a30651edf5 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolFormDraggable/VolFormDraggable.vue @@ -0,0 +1,1155 @@ + + + + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolFormDraggable/VolFormPreview.vue b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolFormDraggable/VolFormPreview.vue new file mode 100644 index 0000000000000000000000000000000000000000..c228cc695a558f84422f9b4fa7457b6691fdbb13 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolFormDraggable/VolFormPreview.vue @@ -0,0 +1,206 @@ + + + + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolFormDraggable/formTemplate.js b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolFormDraggable/formTemplate.js new file mode 100644 index 0000000000000000000000000000000000000000..e8dca271838c43c4d3fd1c20fe87310d756d154c --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolFormDraggable/formTemplate.js @@ -0,0 +1,664 @@ + + +let options1 = [ + { + "id": 1, + "name": "输入框", + "type": "text", + "value": "", + "icon": "el-icon-document", + "field": "field1630258884671", + "width": 20, + "readonly": false, + "required": false + }, + { + "id": 3, + "name": "日期", + "type": "date", + "icon": "el-icon-date", + "value": null, + "field": "field1630258891760", + "width": 20, + "readonly": false, + "required": false + }, + { + "id": 7, + "name": "下拉框", + "value": null, + "key": "", + "data": [ + { + "label": "请设置数据源", + "value": "请设置数据源" + } + ], + "type": "select", + "icon": "el-icon-arrow-down", + "field": "field1630258904862", + "width": 30, + "readonly": false, + "required": false + }, + { + "id": 8, + "name": "下拉多选", + "type": "selectList", + "key": "", + "values": [], + "data": [ + { + "label": "请设置数据源", + "value": "请设置数据源" + } + ], + "icon": "el-icon-arrow-down", + "field": "field1630258924442", + "width": 30, + "readonly": false, + "required": false + }, + { + "id": 81, + "name": "级联", + "type": "cascader", + "icon": "el-icon-share", + "values": [], + "key": "", + "data": [ + { + "value": "请配置数据源", + "label": "请配置数据源", + "children": [ + { + "value": "具体", + "label": "菜单:下拉框绑定设置" + }, + { + "value": "color", + "label": "可参照字典编号[tree_roles]" + } + ] + } + ], + "field": "field1630259518082", + "width": 20, + "readonly": false, + "required": false + }, + { + "id": 6, + "name": "多选", + "values": [ + "发货" + ], + "type": "checkbox", + "key": "ordertype", + "data": [ + { + "key": "1", + "value": "发货" + }, + { + "key": "2", + "value": "退货" + }, + { + "key": "3", + "value": "返单" + } + ], + "icon": "el-icon-circle-check", + "field": "field1630259033241", + "width": 30, + "readonly": false, + "required": false + }, + { + "id": 5, + "name": "单选", + "type": "radio", + "icon": "el-icon-aim", + "value": 0, + "data": [ + { + "key": "0", + "value": "否" + }, + { + "key": "2", + "value": "xx11" + }, + { + "key": "1", + "value": "是" + } + ], + "key": "enable", + "field": "field1630259538490", + "width": 30, + "readonly": false, + "required": false, + "values": [ + "否" + ] + }, + { + "id": 4, + "name": "switch", + "type": "switch", + "icon": "el-icon-turn-off", + "value": 0, + "field": "field1630259172794", + "width": 20, + "readonly": false, + "required": false + }, + { + "id": 12, + "name": "分段信息", + "type": "line", + "icon": "el-icon-guide", + "field": "field1630259600186", + "width": 100, + "readonly": false, + "required": false + }, + { + "id": 9, + "name": "图片", + "type": "img", + "url": "api/SellOrder/upload", + "maxSize": 3, + "fileInfo": [], + "multiple": false, + "autoUpload": false, + "maxFile": 5, + "icon": "el-icon-picture-outline", + "field": "field1630259295154", + "width": 100, + "readonly": false, + "required": false + }, + { + "id": 10, + "name": "excel", + "url": "api/SellOrder/upload", + "maxSize": 3, + "multiple": false, + "autoUpload": true, + "maxFile": 5, + "fileInfo": [], + "type": "excel", + "icon": "el-icon-upload", + "field": "field1630259610476", + "width": 100, + "readonly": false, + "required": false + }, + { + "id": 5, + "name": "单选", + "type": "radio", + "icon": "el-icon-aim", + "value": 0, + "data": [ + { + "key": "0", + "value": "审核中" + }, + { + "key": "1", + "value": "审核通过" + }, + { + "key": "2", + "value": "审核未通过" + } + ], + "key": "audit", + "field": "field1630258969346", + "width": 40, + "readonly": false, + "required": false, + "values": [ + "审核中" + ] + } +]; +let options2=[ + { + "id": 1, + "name": "输入框", + "type": "text", + "value": "", + "icon": "el-icon-document", + "field": "field1630258884671", + "width": 20, + "readonly": false, + "required": false + }, + { + "id": 3, + "name": "日期", + "type": "date", + "icon": "el-icon-date", + "value": null, + "field": "field1630258891760", + "width": 20, + "readonly": false, + "required": false + }, + { + "id": 7, + "name": "下拉框", + "value": null, + "key": "", + "data": [ + { + "label": "请设置数据源", + "value": "请设置数据源" + } + ], + "type": "select", + "icon": "el-icon-arrow-down", + "field": "field1630258904862", + "width": 30, + "readonly": false, + "required": false + }, + { + "id": 8, + "name": "下拉多选", + "type": "selectList", + "key": "", + "values": [], + "data": [ + { + "label": "请设置数据源", + "value": "请设置数据源" + } + ], + "icon": "el-icon-arrow-down", + "field": "field1630258924442", + "width": 30, + "readonly": false, + "required": false + }, + { + "id": 2, + "name": "textarea", + "type": "textarea", + "value": "", + "icon": "el-icon-document-copy", + "field": "field1630260207393", + "width": 100, + "readonly": false, + "required": false + }, + { + "id": 13, + "name": "表格", + "type": "table", + "tabs": true, + "columns": [ + { + "title": "运单号", + "field": "TranNo", + "show": true, + "required": false, + "edit": true, + "dataType": null, + "dataSource": null, + "width": "140", + "orderNo": null, + "elementIndex": 0 + }, + { + "title": "销售订单号", + "field": "SellNo", + "show": true, + "required": false, + "edit": true, + "dataType": null, + "dataSource": null, + "width": "140", + "orderNo": null, + "elementIndex": 1 + }, + { + "title": "订单类型", + "field": "OrderType", + "show": true, + "required": false, + "edit": true, + "dataType": null, + "dataSource": "ordertype", + "width": 120, + "orderNo": null, + "elementIndex": 2, + "editType": "select" + }, + { + "title": "销售数量", + "field": "Qty", + "show": true, + "required": false, + "edit": true, + "dataType": null, + "dataSource": null, + "width": "80", + "orderNo": null, + "elementIndex": 3 + }, + { + "field": "CreateDate", + "elementIndex": 4, + "show": 1, + "required": 0, + "edit": 0, + "title": "订单时间", + "dataType": "date", + "width": "100" + } + ], + "tableData": [ + { + "field1": "field1", + "field2": "field2", + "field3": "field3", + "field4": "field4" + }, + { + "field1": "field1", + "field2": "field2", + "field3": "field3", + "field4": "field4" + }, + { + "field1": "field1", + "field2": "field2", + "field3": "field3", + "field4": "field4" + } + ], + "height": 200, + "icon": "el-icon-c-scale-to-original", + "url": "api/SellOrder/getPageData", + "index": false, + "columnIndex": false, + "ck": true, + "buttons": [ + { + "name": "添加行", + "ck": false, + "icon": "el-icon-plus", + "value": "add" + }, + { + "name": "删除行", + "ck": false, + "icon": "el-icon-delete", + "value": "del" + }, + { + "name": "刷新", + "ck": false, + "icon": "el-icon-refresh-right", + "value": "ref" + } + ], + "field": "field1630260242867", + "width": 100, + "readonly": false, + "required": false, + "pagination": false + }, + { + "id": 13, + "name": "表格", + "type": "table", + "tabs": true, + "columns": [ + { + "title": "字段1", + "field": "field1", + "show": true, + "required": false, + "edit": false, + "dataType": null, + "dataSource": null, + "width": 120, + "orderNo": null + }, + { + "title": "字段2", + "field": "field2", + "show": true, + "required": false, + "edit": false, + "dataType": null, + "dataSource": null, + "width": 120, + "orderNo": null + }, + { + "title": "字段3", + "field": "field3", + "show": true, + "required": false, + "edit": false, + "dataType": null, + "dataSource": null, + "width": 120, + "orderNo": null + }, + { + "title": "字段4", + "field": "field4", + "show": true, + "required": false, + "edit": false, + "dataType": null, + "dataSource": null, + "width": 120, + "orderNo": null + } + ], + "tableData": [ + { + "field1": "field1", + "field2": "field2", + "field3": "field3", + "field4": "field4" + }, + { + "field1": "field1", + "field2": "field2", + "field3": "field3", + "field4": "field4" + }, + { + "field1": "field1", + "field2": "field2", + "field3": "field3", + "field4": "field4" + } + ], + "height": 200, + "icon": "el-icon-c-scale-to-original", + "url": null, + "index": false, + "columnIndex": false, + "ck": true, + "buttons": [ + { + "name": "添加行", + "ck": false, + "icon": "el-icon-plus", + "value": "add" + }, + { + "name": "删除行", + "ck": false, + "icon": "el-icon-delete", + "value": "del" + }, + { + "name": "刷新", + "ck": false, + "icon": "el-icon-refresh-right", + "value": "ref" + } + ], + "field": "field1630260481283", + "width": 100, + "readonly": false, + "required": false, + "pagination": true + } +] + +let options3=[ + { + "id": 1, + "name": "输入框", + "type": "text", + "value": "", + "icon": "el-icon-document", + "field": "field1630258884671", + "width": 20, + "readonly": false, + "required": false + }, + { + "id": 3, + "name": "日期", + "type": "date", + "icon": "el-icon-date", + "value": null, + "field": "field1630258891760", + "width": 20, + "readonly": false, + "required": false + }, + { + "id": 7, + "name": "下拉框", + "value": null, + "key": "", + "data": [ + { + "label": "请设置数据源", + "value": "请设置数据源" + } + ], + "type": "select", + "icon": "el-icon-arrow-down", + "field": "field1630258904862", + "width": 30, + "readonly": false, + "required": false + }, + { + "id": 8, + "name": "下拉多选", + "type": "selectList", + "key": "", + "values": [], + "data": [ + { + "label": "请设置数据源", + "value": "请设置数据源" + } + ], + "icon": "el-icon-arrow-down", + "field": "field1630258924442", + "width": 30, + "readonly": false, + "required": false + }, + { + "id": 5, + "name": "单选", + "type": "radio", + "icon": "el-icon-aim", + "value": 0, + "data": [ + { + "key": "0", + "value": "否" + }, + { + "key": "2", + "value": "xx11" + }, + { + "key": "1", + "value": "是" + } + ], + "key": "enable", + "field": "field1630260669595", + "width": 50, + "readonly": false, + "required": false, + "values": [ + "否" + ] + }, + { + "id": 6, + "name": "多选", + "values": [ + "否" + ], + "type": "checkbox", + "key": "enable", + "data": [ + { + "key": "0", + "value": "否" + }, + { + "key": "2", + "value": "xx11" + }, + { + "key": "1", + "value": "是" + } + ], + "icon": "el-icon-circle-check", + "field": "field1630260695322", + "width": 50, + "readonly": false, + "required": false + }, + { + "id": 2, + "name": "textarea", + "type": "textarea", + "value": "", + "icon": "el-icon-document-copy", + "field": "field1630260207393", + "width": 100, + "readonly": false, + "required": false + }, + { + "id": 13, + "name": "编辑器", + "type": "editor", + "value": "", + "url": "", + "height": 200, + "icon": "el-icon-notebook-2", + "field": "field1630260646842", + "width": 100, + "readonly": false, + "required": false + } +] +export { options1, options2,options3 } diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolFormDraggable/index.js b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolFormDraggable/index.js new file mode 100644 index 0000000000000000000000000000000000000000..6e1ef89e2efb2d57ee0f8f744d06e08061d4da14 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolFormDraggable/index.js @@ -0,0 +1,3 @@ +import VolFormDraggable from './VolFormDraggable.vue' + +export default VolFormDraggable; \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolFormDraggable/options.js b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolFormDraggable/options.js new file mode 100644 index 0000000000000000000000000000000000000000..c60047c786d84510d6432cb68fb1c945b359ae94 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolFormDraggable/options.js @@ -0,0 +1,226 @@ +const components = [ + { + id: 1, + name: "输入框", + type: "text", + value: "", + icon: "el-icon-document", + }, + { + id: 2, + name: "textarea", + type: "textarea", + value: "", + icon: "el-icon-document-copy", + }, + { + id: 3, + name: "日期", + type: "date", + icon: "el-icon-date", + value: null, + }, + { + id: 4, + name: "switch", + type: "switch", + icon: "el-icon-turn-off", + value: 0, + }, + { id: 5, name: "单选", type: "radio", icon: "el-icon-aim", value: 0, data: [{ label: "0", value: "请设置数据源1" }, { label: "1", value: "请设置数据源2" }], key: "" }, + { + id: 6, + name: "多选", + values: [], + type: "checkbox", + key: "", + data: [{ label: "请设置数据源", value: "请设置数据源" }], + icon: "el-icon-circle-check", + }, + { + id: 7, + name: "下拉框", + value: null, + key: "", + data: [{ label: "请设置数据源", value: "请设置数据源" }], + type: "select", + icon: "el-icon-arrow-down", + }, + { + id: 8, + name: "下拉框多选", + type: "selectList", + key: "", + values: [], + data: [{ label: "请设置数据源", value: "请设置数据源" }], + icon: "el-icon-arrow-down", + }, + { + id: 81, + name: "级联", + type: "cascader", + icon: "el-icon-share", + values: [], + key: "", + data: [ + { + value: "请配置数据源", + label: "请配置数据源", + children: [ + { + value: "具体", + label: "菜单:下拉框绑定设置", + }, + { + value: "color", + label: "可参照字典编号[tree_roles]", + } + ], + }, + ], + }, + { + id: 9, + name: "图片上传", + type: "img", + url: "", + maxSize: 3, + fileInfo: [], + multiple: false, + autoUpload: false, + maxFile: 5, + icon: "el-icon-picture-outline", + }, + { + id: 10, + name: "excel上传", + url: "", + maxSize: 3, + multiple: false, + autoUpload: false, + maxFile: 5, //最多可上传5个文件 + fileInfo: [], + type: "excel", + icon: "el-icon-upload", + }, + { + id: 11, + name: "文件上传", + type: "file", + url: "", + maxSize: 3, + multiple: false, + autoUpload: false, + maxFile: 5, + fileInfo: [], + icon: "el-icon-folder-opened", + }, + { + id: 12, + name: "分段信息", + type: "line", + icon: "el-icon-guide", + }, + { + id: 13, + name: "编辑器", + type: "editor", + value: "", + url: "", + height: 200, + icon: "el-icon-notebook-2", + }, + { + id: 13, + name: "弹出框", + type: "box", + value: "", + url: "", + height: 250, + icon: "el-icon-notebook-2", + }, + { + id: 13, + name: "表格", + type: "table", + tabs: false, + columns: [ + { title: "字段1", field: "field1", show: true, required: false, edit: false, dataType: null, dataSource: null, width: 120, orderNo: null }, + { title: "字段2", field: "field2", show: true, required: false, edit: false, dataType: null, dataSource: null, width: 120, orderNo: null }, + { title: "字段3", field: "field3", show: true, required: false, edit: false, dataType: null, dataSource: null, width: 120, orderNo: null }, + { title: "字段4", field: "field4", show: true, required: false, edit: false, dataType: null, dataSource: null, width: 120, orderNo: null }, + // { title: "字段5", field: "Field5", width: 120 }, + ], + tableData: [ + { + field1: "field1", + field2: "field2", + field3: "field3", + field4: "field4", + }, + { + field1: "field1", + field2: "field2", + field3: "field3", + field4: "field4", + }, + { + field1: "field1", + field2: "field2", + field3: "field3", + field4: "field4", + }, + ], + height: 150, + icon: "el-icon-c-scale-to-original", + url: null, + index: false, //item.index, + height: 200, + index: false, + columnIndex: false, + ck: true, + buttons: [ + { name: '添加行', ck: false, icon: 'el-icon-plus',value:'add' }, + { name: '删除行', ck: false, icon: 'el-icon-delete',value:'del' }, + { name: '刷新', ck: false ,icon:'el-icon-refresh-right',value:'ref'}], + }, +] +const tableOption = [ + { field: 'field', title: '字段', edit: { type: "text", keep: true }, width: 160 }, + { field: 'title', title: '字段中文名', edit: { type: "text", keep: true }, width: 120 }, + { field: 'show', title: '是否显示', edit: { type: "switch", keep: true }, width: 90 }, + { + field: 'dataType', title: '显示类型', edit: { type: "select", keep: true }, width: 120, bind: { + key: '', data: [ + { "key": "switch", "value": "单选" }, + { "key": "date", "value": "年月日" }, + { "key": "img", "value": "图片" }, + { "key": "excel", "value": "excel" }, + { "key": "file", "value": "文件" } + ] + } + }, + + { field: 'required', title: '是否必填', edit: { type: "switch", keep: true }, width: 90 }, + { field: 'edit', title: '是否可编辑', edit: { type: "switch", keep: true }, width: 90 }, + { + field: 'editType', title: '编辑类型', edit: { type: "select", keep: true, }, width: 120, bind: { + key: '', data: [{ "key": "text", "value": "输入框" }, + { "key": "switch", "value": "单选" }, + { "key": "select", "value": "下拉框" }, + { "key": "selectList", "value": "下拉框多选" }, + { "key": "date", "value": "日期" }, + { "key": "datetime", "value": "日期时分秒" }, + { "key": "checkbox", "value": "复选框多选" }, + { "key": "mail", "value": "邮箱地址" }, + { "key": "number", "value": "数字" }, + { "key": "decimal", "value": "小数" }, + { "key": "phone", "value": "手机号" }, + ] + } + }, + { field: 'dataSource', title: '数据源', edit: { type: "select", keep: true, data: [] }, bind: { key: '', data: [] }, width: 120 }, + { field: 'width', title: '列宽度', edit: { type: "text", keep: true }, width: 80 }, + { field: 'orderNo', title: '列显示顺序', edit: { type: "text", keep: true }, width: 100 } +]; +export { components, tableOption } \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolFormDraggable/templateCode.js b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolFormDraggable/templateCode.js new file mode 100644 index 0000000000000000000000000000000000000000..41b874487255980bc738e30e9b166e0a075ef4d1 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolFormDraggable/templateCode.js @@ -0,0 +1,95 @@ +var code = ` + + +` + +export default code \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolHeader.vue b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolHeader.vue new file mode 100644 index 0000000000000000000000000000000000000000..cbe64e73ca9fff8aff3d5c7169283ea806b0d316 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolHeader.vue @@ -0,0 +1,67 @@ + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolTable.vue b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolTable.vue new file mode 100644 index 0000000000000000000000000000000000000000..c104f4d9d61a5a6850ca45992d341515b98201cf --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolTable.vue @@ -0,0 +1,1667 @@ + + + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolTable/VolTableRender.js b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolTable/VolTableRender.js new file mode 100644 index 0000000000000000000000000000000000000000..988a672e915e649dc90b1a764fa1145ee31abf1e --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolTable/VolTableRender.js @@ -0,0 +1,14 @@ +import { h } from 'vue'; +export default { + name: "TableExpand", + functional: true, + props: { + render: Function, + row: {},//当前行的数据 + column: {},//当前行的配置信息 + index: { type: Number, default: 0 }//当前所在行 + }, + render: ({ render,row ,column,index }) => { + return render(h, {row ,column,index}); //h(); + } +}; diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolUpload.vue b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolUpload.vue new file mode 100644 index 0000000000000000000000000000000000000000..3a8bfa8a0bd65cfec83ae9fce0d2497e8abaa7b9 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/basic/VolUpload.vue @@ -0,0 +1,806 @@ + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/editor/KindEditor.vue b/Pure_Vite_Net7/Vue3Vite/src/components/editor/KindEditor.vue new file mode 100644 index 0000000000000000000000000000000000000000..8c8e7045410c68359730617c8326cb4d3550c897 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/editor/KindEditor.vue @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/editor/VolWangEditor.vue b/Pure_Vite_Net7/Vue3Vite/src/components/editor/VolWangEditor.vue new file mode 100644 index 0000000000000000000000000000000000000000..3a898b46b98123bb3c11958e0b39193ead569114 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/editor/VolWangEditor.vue @@ -0,0 +1,151 @@ + + + + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/redirect/401.vue b/Pure_Vite_Net7/Vue3Vite/src/components/redirect/401.vue new file mode 100644 index 0000000000000000000000000000000000000000..ed11c1a9be77c5e4023be8b4aa3a806c97806229 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/redirect/401.vue @@ -0,0 +1,19 @@ + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/redirect/404.vue b/Pure_Vite_Net7/Vue3Vite/src/components/redirect/404.vue new file mode 100644 index 0000000000000000000000000000000000000000..73d5a5104fdb4fc69a1df48e78da37a03dbcba82 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/redirect/404.vue @@ -0,0 +1,21 @@ + + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/redirect/Message.vue b/Pure_Vite_Net7/Vue3Vite/src/components/redirect/Message.vue new file mode 100644 index 0000000000000000000000000000000000000000..8952162e0fda77bf6ef337b48ccca7a2f5c2d279 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/redirect/Message.vue @@ -0,0 +1,39 @@ + + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/redirect/RedirectError.vue b/Pure_Vite_Net7/Vue3Vite/src/components/redirect/RedirectError.vue new file mode 100644 index 0000000000000000000000000000000000000000..8ba5280b735bb90ff5a0c4f941597d53f6e0feae --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/redirect/RedirectError.vue @@ -0,0 +1,57 @@ + + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/redirect/coding.vue b/Pure_Vite_Net7/Vue3Vite/src/components/redirect/coding.vue new file mode 100644 index 0000000000000000000000000000000000000000..d74987ce2fdade84aedc2a2ef6f4351c000e64ec --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/redirect/coding.vue @@ -0,0 +1,25 @@ + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/workflow/data_default.js b/Pure_Vite_Net7/Vue3Vite/src/components/workflow/data_default.js new file mode 100644 index 0000000000000000000000000000000000000000..606ed430e053736c416abdb7cf41d20eca502d46 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/workflow/data_default.js @@ -0,0 +1,33 @@ +let dataDefault = { + name: '流程A', + nodeList: [ + { + id: '1659276275052', + name: '流程C-节点A', + type: 'task', + left: '230px', + top: '15px', + ico: 'el-icon-user-solid' + }, + { + id: '1659276282115', + name: '流程C-节点B', + type: 'task', + left: '225px', + top: '165px', + ico: 'el-icon-goods' + } + ], + lineList: [ + { + from: '1659276275052', + to: '1659276282115' + // connector: 'Straight', + // paintStyle: {strokeWidth: 1, stroke: '#827f7f'} + } + ] +}; + +export function getDataDefault() { + return dataDefault; +} diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/workflow/force-directed.js b/Pure_Vite_Net7/Vue3Vite/src/components/workflow/force-directed.js new file mode 100644 index 0000000000000000000000000000000000000000..f144365f9358743dd5effc39f5f4f2b231d289c1 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/workflow/force-directed.js @@ -0,0 +1,182 @@ +/** + * 感谢 https://github.com/chaangliu/ForceDirectedLayout/blob/master/javascript/force-directed.js + * A force directed graph layout implementation by liuchang on 2018/05/10. + */ +const CANVAS_WIDTH = 1000 +const CANVAS_HEIGHT = 1000 +let k +let mNodeList = [] +let mEdgeList = [] +let mDxMap = {} +let mDyMap = {} +let mNodeMap = {} + +export function ForceDirected(data = {}) { + // generate nodes and edges + // for (let i = 0; i < 20; i++) { + // mNodeList.push(new Node(i)) + // } + k = 0 + mNodeList = [] + mEdgeList = [] + mDxMap = {} + mDyMap = {} + mNodeMap = {} + + let nodeList = data.nodeList + for (let i = 0; i < nodeList.length; i++) { + let node = nodeList[i] + mNodeList.push(node) + } + + // for (let i = 0; i < 20; i++) { + // let edgeCount = Math.random() * 8 + 1 + // for (let j = 0; j < edgeCount; j++) { + // let targetId = Math.floor(Math.random() * 20) + // let edge = new Edge(i, targetId) + // mEdgeList.push(edge) + // } + // } + // line 转 edge + let lineList = data.lineList + for (let i = 0; i < lineList.length; i++) { + let line = lineList[i] + let edge = new Edge(line.from, line.to) + mEdgeList.push(edge) + } + + if (mNodeList && mEdgeList) { + k = Math.sqrt(CANVAS_WIDTH * CANVAS_HEIGHT / mNodeList.length) + } + for (let i = 0; i < mNodeList.length; i++) { + let node = mNodeList[i] + if (node) { + mNodeMap[node.id] = node + } + } + + // 随机生成坐标. Generate coordinates randomly. + let initialX, initialY, initialSize = 40.0 + for (let i in mNodeList) { + initialX = CANVAS_WIDTH * 0.5 + initialY = CANVAS_HEIGHT * 0.5 + mNodeList[i].x = initialX + initialSize * (Math.random() - 0.5) + mNodeList[i].y = initialY + initialSize * (Math.random() - 0.5) + } + + // 迭代200次. Iterate 200 times. + for (let i = 0; i < 200; i++) { + calculateRepulsive() + calculateTraction() + updateCoordinates() + } + // console.log(JSON.stringify(new Result(mNodeList, mEdgeList))) + // 坐标添加px + for (let i = 0; i < mNodeList.length; i++) { + let node = mNodeList[i] + node.left = node.x + 'px' + node.top = node.y + 'px' + node.x = undefined + node.y = undefined + } + + data.nodeList = mNodeList + + // console.log(data) + return data +} + +function Node(id = null) { + this.id = id + this.x = 22 + this.y = null +} + +function Edge(source = null, target = null) { + this.source = source + this.target = target +} + +/** + * 计算两个Node的斥力产生的单位位移。 + * Calculate the displacement generated by the repulsive force between two nodes.* + */ +function calculateRepulsive() { + let ejectFactor = 6 + let distX, distY, dist + for (let i = 0; i < mNodeList.length; i++) { + mDxMap[mNodeList[i].id] = 0.0 + mDyMap[mNodeList[i].id] = 0.0 + for (let j = 0; j < mNodeList.length; j++) { + if (i !== j) { + distX = mNodeList[i].x - mNodeList[j].x + distY = mNodeList[i].y - mNodeList[j].y + dist = Math.sqrt(distX * distX + distY * distY) + } + if (dist < 30) { + ejectFactor = 5 + } + if (dist > 0 && dist < 250) { + let id = mNodeList[i].id + mDxMap[id] = mDxMap[id] + distX / dist * k * k / dist * ejectFactor + mDyMap[id] = mDyMap[id] + distY / dist * k * k / dist * ejectFactor + } + } + } +} + +/** + * 计算Edge的引力对两端Node产生的引力。 + * Calculate the traction force generated by the edge acted on the two nodes of its two ends. + */ +function calculateTraction() { + let condenseFactor = 3 + let startNode, endNode + for (let e = 0; e < mEdgeList.length; e++) { + let eStartID = mEdgeList[e].source + let eEndID = mEdgeList[e].target + startNode = mNodeMap[eStartID] + endNode = mNodeMap[eEndID] + if (!startNode) { + console.log('Cannot find start node id: ' + eStartID + ', please check it out.') + return + } + if (!endNode) { + console.log('Cannot find end node id: ' + eEndID + ', please check it out.') + return + } + let distX, distY, dist + distX = startNode.x - endNode.x + distY = startNode.y - endNode.y + dist = Math.sqrt(distX * distX + distY * distY) + mDxMap[eStartID] = mDxMap[eStartID] - distX * dist / k * condenseFactor + mDyMap[eStartID] = mDyMap[eStartID] - distY * dist / k * condenseFactor + mDxMap[eEndID] = mDxMap[eEndID] + distX * dist / k * condenseFactor + mDyMap[eEndID] = mDyMap[eEndID] + distY * dist / k * condenseFactor + } +} + +/** + * 更新坐标。 + * update the coordinates. + */ +function updateCoordinates() { + let maxt = 4, maxty = 3 // Additional coefficients. + for (let v = 0; v < mNodeList.length; v++) { + let node = mNodeList[v] + let dx = Math.floor(mDxMap[node.id]) + let dy = Math.floor(mDyMap[node.id]) + + if (dx < -maxt) dx = -maxt + if (dx > maxt) dx = maxt + if (dy < -maxty) dy = -maxty + if (dy > maxty) dy = maxty + node.x = node.x + dx >= CANVAS_WIDTH || node.x + dx <= 0 ? node.x - dx : node.x + dx + node.y = node.y + dy >= CANVAS_HEIGHT || node.y + dy <= 0 ? node.y - dy : node.y + dy + } +} + +function Result(nodes = null, links = null) { + this.nodes = nodes + this.links = links +} diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/workflow/index.css b/Pure_Vite_Net7/Vue3Vite/src/components/workflow/index.css new file mode 100644 index 0000000000000000000000000000000000000000..966d18e66f6ab2b0afea3dd40fe811a8896056af --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/workflow/index.css @@ -0,0 +1,225 @@ +/*画布容器*/ +#efContainer { + position: relative; + overflow: scroll; + flex: 1; +} + +/*顶部工具栏*/ +.ef-tooltar { + padding-left: 10px; + box-sizing: border-box; + height: 42px; + line-height: 42px; + z-index: 3; + border-bottom: 1px solid #DADCE0; +} + +.jtk-overlay { + cursor: pointer; + color: #4A4A4A; +} + + +/*节点菜单*/ +.ef-node-pmenu { + cursor: pointer; + height: 32px; + line-height: 32px; + width: 225px; + display: block; + font-weight: bold; + color: #4A4A4A; + padding-left: 5px; +} + +.ef-node-pmenu:hover { + background-color: #E0E0E0; +} + +.ef-node-menu-li { + color: #565758; + width: 150px; + border: 1px dashed #E0E3E7; + margin: 5px 0 5px 0; + padding: 5px; + border-radius: 5px; + padding-left: 8px; +} + +.ef-node-menu-li:hover { + /* 设置移动样式*/ + cursor: move; + background-color: #F0F7FF; + border: 1px dashed #1879FF; + border-left: 4px solid #1879FF; + padding-left: 5px; +} + +.ef-node-menu-ul { + list-style: none; + padding-left: 20px +} + +/*节点的最外层容器*/ +.ef-node-container { + position: absolute; + display: flex; + width: 170px; + height: 32px; + border: 1px solid #E0E3E7; + border-radius: 5px; + background-color: #fff; +} + +.ef-node-container:hover { + /* 设置移动样式*/ + cursor: move; + background-color: #F0F7FF; + /*box-shadow: #1879FF 0px 0px 12px 0px;*/ + background-color: #F0F7FF; + border: 1px dashed #1879FF; +} + +/*节点激活样式*/ +.ef-node-active { + background-color: #F0F7FF; + /*box-shadow: #1879FF 0px 0px 12px 0px;*/ + background-color: #F0F7FF; + border: 1px solid #1879FF; +} + +/*节点左侧的竖线*/ +.ef-node-left { + width: 4px; + background-color: #1879FF; + border-radius: 4px 0 0 4px; +} + +/*节点左侧的图标*/ +.ef-node-left-ico { + line-height: 32px; + margin-left: 8px; +} + +.ef-node-left-ico:hover { + /* 设置拖拽的样式 */ + cursor: crosshair; +} + +/*节点显示的文字*/ +.ef-node-text { + color: #565758; + font-size: 12px; + line-height: 32px; + margin-left: 8px; + width: 100px; + /* 设置超出宽度文本显示方式*/ + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + text-align: center; +} + +/*节点右侧的图标*/ +.ef-node-right-ico { + line-height: 32px; + position: absolute; + right: 5px; + color: #84CF65; + cursor: default; +} + +/*节点的几种状态样式*/ +.el-node-state-success { + line-height: 32px; + position: absolute; + right: 5px; + color: #84CF65; + cursor: default; +} + +.el-node-state-error { + line-height: 32px; + position: absolute; + right: 5px; + color: #F56C6C; + cursor: default; +} + +.el-node-state-warning { + line-height: 32px; + position: absolute; + right: 5px; + color: #E6A23C; + cursor: default; +} + +.el-node-state-running { + line-height: 32px; + position: absolute; + right: 5px; + color: #84CF65; + cursor: default; +} + + +/*node-form*/ +.ef-node-form-header { + height: 32px; + border-top: 1px solid #dce3e8; + border-bottom: 1px solid #dce3e8; + background: #F1F3F4; + color: #000; + line-height: 32px; + padding-left: 12px; + font-size: 14px; +} + +.ef-node-form-body { + margin-top: 10px; + padding-right: 10px; + padding-bottom: 20px; +} + +/* 连线中的label 样式*/ +.jtk-overlay.flowLabel:not(.aLabel) { + padding: 4px 10px; + background-color: white; + color: #565758 !important; + border: 1px solid #E0E3E7; + border-radius: 5px; +} + +/* label 为空的样式 */ +.emptyFlowLabel { +} + + +.ef-dot { + background-color: #1879FF; + border-radius: 10px; +} + +.ef-dot-hover { + background-color: red; +} + +.ef-rectangle { + background-color: #1879FF; +} + +.ef-rectangle-hover { + background-color: red; +} + +.ef-img { +} + +.ef-img-hover { +} + + +.ef-drop-hover{ + border: 1px dashed #1879FF; +} diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/workflow/jsplumb.js b/Pure_Vite_Net7/Vue3Vite/src/components/workflow/jsplumb.js new file mode 100644 index 0000000000000000000000000000000000000000..9cd1055e4023058c07af10c194b2b30fc3c4b0cf --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/workflow/jsplumb.js @@ -0,0 +1,15711 @@ +/** + * jsBezier + * + * Copyright (c) 2010 - 2017 jsPlumb (hello@jsplumbtoolkit.com) + * + * licensed under the MIT license. + * + * a set of Bezier curve functions that deal with Beziers, used by jsPlumb, and perhaps useful for other people. These functions work with Bezier + * curves of arbitrary degree. + * + * - functions are all in the 'jsBezier' namespace. + * + * - all input points should be in the format {x:.., y:..}. all output points are in this format too. + * + * - all input curves should be in the format [ {x:.., y:..}, {x:.., y:..}, {x:.., y:..}, {x:.., y:..} ] + * + * - 'location' as used as an input here refers to a decimal in the range 0-1 inclusive, which indicates a point some proportion along the length + * of the curve. location as output has the same format and meaning. + * + * + * Function List: + * -------------- + * + * distanceFromCurve(point, curve) + * + * Calculates the distance that the given point lies from the given Bezier. Note that it is computed relative to the center of the Bezier, + * so if you have stroked the curve with a wide pen you may wish to take that into account! The distance returned is relative to the values + * of the curve and the point - it will most likely be pixels. + * + * gradientAtPoint(curve, location) + * + * Calculates the gradient to the curve at the given location, as a decimal between 0 and 1 inclusive. + * + * gradientAtPointAlongCurveFrom (curve, location) + * + * Calculates the gradient at the point on the given curve that is 'distance' units from location. + * + * nearestPointOnCurve(point, curve) + * + * Calculates the nearest point to the given point on the given curve. The return value of this is a JS object literal, containing both the + *point's coordinates and also the 'location' of the point (see above), for example: { point:{x:551,y:150}, location:0.263365 }. + * + * pointOnCurve(curve, location) + * + * Calculates the coordinates of the point on the given Bezier curve at the given location. + * + * pointAlongCurveFrom(curve, location, distance) + * + * Calculates the coordinates of the point on the given curve that is 'distance' units from location. 'distance' should be in the same coordinate + * space as that used to construct the Bezier curve. For an HTML Canvas usage, for example, distance would be a measure of pixels. + * + * locationAlongCurveFrom(curve, location, distance) + * + * Calculates the location on the given curve that is 'distance' units from location. 'distance' should be in the same coordinate + * space as that used to construct the Bezier curve. For an HTML Canvas usage, for example, distance would be a measure of pixels. + * + * perpendicularToCurveAt(curve, location, length, distance) + * + * Calculates the perpendicular to the given curve at the given location. length is the length of the line you wish for (it will be centered + * on the point at 'location'). distance is optional, and allows you to specify a point along the path from the given location as the center of + * the perpendicular returned. The return value of this is an array of two points: [ {x:...,y:...}, {x:...,y:...} ]. + * + * + */ + +(function() { + + var root = this; + + if(typeof Math.sgn == "undefined") { + Math.sgn = function(x) { return x == 0 ? 0 : x > 0 ? 1 :-1; }; + } + + var Vectors = { + subtract : function(v1, v2) { return {x:v1.x - v2.x, y:v1.y - v2.y }; }, + dotProduct : function(v1, v2) { return (v1.x * v2.x) + (v1.y * v2.y); }, + square : function(v) { return Math.sqrt((v.x * v.x) + (v.y * v.y)); }, + scale : function(v, s) { return {x:v.x * s, y:v.y * s }; } + }, + + maxRecursion = 64, + flatnessTolerance = Math.pow(2.0,-maxRecursion-1); + + /** + * Calculates the distance that the point lies from the curve. + * + * @param point a point in the form {x:567, y:3342} + * @param curve a Bezier curve in the form [{x:..., y:...}, {x:..., y:...}, {x:..., y:...}, {x:..., y:...}]. note that this is currently + * hardcoded to assume cubiz beziers, but would be better off supporting any degree. + * @return a JS object literal containing location and distance, for example: {location:0.35, distance:10}. Location is analogous to the location + * argument you pass to the pointOnPath function: it is a ratio of distance travelled along the curve. Distance is the distance in pixels from + * the point to the curve. + */ + var _distanceFromCurve = function(point, curve) { + var candidates = [], + w = _convertToBezier(point, curve), + degree = curve.length - 1, higherDegree = (2 * degree) - 1, + numSolutions = _findRoots(w, higherDegree, candidates, 0), + v = Vectors.subtract(point, curve[0]), dist = Vectors.square(v), t = 0.0; + + for (var i = 0; i < numSolutions; i++) { + v = Vectors.subtract(point, _bezier(curve, degree, candidates[i], null, null)); + var newDist = Vectors.square(v); + if (newDist < dist) { + dist = newDist; + t = candidates[i]; + } + } + v = Vectors.subtract(point, curve[degree]); + newDist = Vectors.square(v); + if (newDist < dist) { + dist = newDist; + t = 1.0; + } + return {location:t, distance:dist}; + }; + /** + * finds the nearest point on the curve to the given point. + */ + var _nearestPointOnCurve = function(point, curve) { + var td = _distanceFromCurve(point, curve); + return {point:_bezier(curve, curve.length - 1, td.location, null, null), location:td.location}; + }; + var _convertToBezier = function(point, curve) { + var degree = curve.length - 1, higherDegree = (2 * degree) - 1, + c = [], d = [], cdTable = [], w = [], + z = [ [1.0, 0.6, 0.3, 0.1], [0.4, 0.6, 0.6, 0.4], [0.1, 0.3, 0.6, 1.0] ]; + + for (var i = 0; i <= degree; i++) c[i] = Vectors.subtract(curve[i], point); + for (var i = 0; i <= degree - 1; i++) { + d[i] = Vectors.subtract(curve[i+1], curve[i]); + d[i] = Vectors.scale(d[i], 3.0); + } + for (var row = 0; row <= degree - 1; row++) { + for (var column = 0; column <= degree; column++) { + if (!cdTable[row]) cdTable[row] = []; + cdTable[row][column] = Vectors.dotProduct(d[row], c[column]); + } + } + for (i = 0; i <= higherDegree; i++) { + if (!w[i]) w[i] = []; + w[i].y = 0.0; + w[i].x = parseFloat(i) / higherDegree; + } + var n = degree, m = degree-1; + for (var k = 0; k <= n + m; k++) { + var lb = Math.max(0, k - m), + ub = Math.min(k, n); + for (i = lb; i <= ub; i++) { + var j = k - i; + w[i+j].y += cdTable[j][i] * z[j][i]; + } + } + return w; + }; + /** + * counts how many roots there are. + */ + var _findRoots = function(w, degree, t, depth) { + var left = [], right = [], + left_count, right_count, + left_t = [], right_t = []; + + switch (_getCrossingCount(w, degree)) { + case 0 : { + return 0; + } + case 1 : { + if (depth >= maxRecursion) { + t[0] = (w[0].x + w[degree].x) / 2.0; + return 1; + } + if (_isFlatEnough(w, degree)) { + t[0] = _computeXIntercept(w, degree); + return 1; + } + break; + } + } + _bezier(w, degree, 0.5, left, right); + left_count = _findRoots(left, degree, left_t, depth+1); + right_count = _findRoots(right, degree, right_t, depth+1); + for (var i = 0; i < left_count; i++) t[i] = left_t[i]; + for (var i = 0; i < right_count; i++) t[i+left_count] = right_t[i]; + return (left_count+right_count); + }; + var _getCrossingCount = function(curve, degree) { + var n_crossings = 0, sign, old_sign; + sign = old_sign = Math.sgn(curve[0].y); + for (var i = 1; i <= degree; i++) { + sign = Math.sgn(curve[i].y); + if (sign != old_sign) n_crossings++; + old_sign = sign; + } + return n_crossings; + }; + var _isFlatEnough = function(curve, degree) { + var error, + intercept_1, intercept_2, left_intercept, right_intercept, + a, b, c, det, dInv, a1, b1, c1, a2, b2, c2; + a = curve[0].y - curve[degree].y; + b = curve[degree].x - curve[0].x; + c = curve[0].x * curve[degree].y - curve[degree].x * curve[0].y; + + var max_distance_above, max_distance_below; + max_distance_above = max_distance_below = 0.0; + + for (var i = 1; i < degree; i++) { + var value = a * curve[i].x + b * curve[i].y + c; + if (value > max_distance_above) + max_distance_above = value; + else if (value < max_distance_below) + max_distance_below = value; + } + + a1 = 0.0; b1 = 1.0; c1 = 0.0; a2 = a; b2 = b; + c2 = c - max_distance_above; + det = a1 * b2 - a2 * b1; + dInv = 1.0/det; + intercept_1 = (b1 * c2 - b2 * c1) * dInv; + a2 = a; b2 = b; c2 = c - max_distance_below; + det = a1 * b2 - a2 * b1; + dInv = 1.0/det; + intercept_2 = (b1 * c2 - b2 * c1) * dInv; + left_intercept = Math.min(intercept_1, intercept_2); + right_intercept = Math.max(intercept_1, intercept_2); + error = right_intercept - left_intercept; + return (error < flatnessTolerance)? 1 : 0; + }; + var _computeXIntercept = function(curve, degree) { + var XLK = 1.0, YLK = 0.0, + XNM = curve[degree].x - curve[0].x, YNM = curve[degree].y - curve[0].y, + XMK = curve[0].x - 0.0, YMK = curve[0].y - 0.0, + det = XNM*YLK - YNM*XLK, detInv = 1.0/det, + S = (XNM*YMK - YNM*XMK) * detInv; + return 0.0 + XLK * S; + }; + var _bezier = function(curve, degree, t, left, right) { + var temp = [[]]; + for (var j =0; j <= degree; j++) temp[0][j] = curve[j]; + for (var i = 1; i <= degree; i++) { + for (var j =0 ; j <= degree - i; j++) { + if (!temp[i]) temp[i] = []; + if (!temp[i][j]) temp[i][j] = {}; + temp[i][j].x = (1.0 - t) * temp[i-1][j].x + t * temp[i-1][j+1].x; + temp[i][j].y = (1.0 - t) * temp[i-1][j].y + t * temp[i-1][j+1].y; + } + } + if (left != null) + for (j = 0; j <= degree; j++) left[j] = temp[j][0]; + if (right != null) + for (j = 0; j <= degree; j++) right[j] = temp[degree-j][j]; + + return (temp[degree][0]); + }; + + var _curveFunctionCache = {}; + var _getCurveFunctions = function(order) { + var fns = _curveFunctionCache[order]; + if (!fns) { + fns = []; + var f_term = function() { return function(t) { return Math.pow(t, order); }; }, + l_term = function() { return function(t) { return Math.pow((1-t), order); }; }, + c_term = function(c) { return function(t) { return c; }; }, + t_term = function() { return function(t) { return t; }; }, + one_minus_t_term = function() { return function(t) { return 1-t; }; }, + _termFunc = function(terms) { + return function(t) { + var p = 1; + for (var i = 0; i < terms.length; i++) p = p * terms[i](t); + return p; + }; + }; + + fns.push(new f_term()); // first is t to the power of the curve order + for (var i = 1; i < order; i++) { + var terms = [new c_term(order)]; + for (var j = 0 ; j < (order - i); j++) terms.push(new t_term()); + for (var j = 0 ; j < i; j++) terms.push(new one_minus_t_term()); + fns.push(new _termFunc(terms)); + } + fns.push(new l_term()); // last is (1-t) to the power of the curve order + + _curveFunctionCache[order] = fns; + } + + return fns; + }; + + + /** + * calculates a point on the curve, for a Bezier of arbitrary order. + * @param curve an array of control points, eg [{x:10,y:20}, {x:50,y:50}, {x:100,y:100}, {x:120,y:100}]. For a cubic bezier this should have four points. + * @param location a decimal indicating the distance along the curve the point should be located at. this is the distance along the curve as it travels, taking the way it bends into account. should be a number from 0 to 1, inclusive. + */ + var _pointOnPath = function(curve, location) { + var cc = _getCurveFunctions(curve.length - 1), + _x = 0, _y = 0; + for (var i = 0; i < curve.length ; i++) { + _x = _x + (curve[i].x * cc[i](location)); + _y = _y + (curve[i].y * cc[i](location)); + } + + return {x:_x, y:_y}; + }; + + var _dist = function(p1,p2) { + return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2)); + }; + + var _isPoint = function(curve) { + return curve[0].x === curve[1].x && curve[0].y === curve[1].y; + }; + + /** + * finds the point that is 'distance' along the path from 'location'. this method returns both the x,y location of the point and also + * its 'location' (proportion of travel along the path); the method below - _pointAlongPathFrom - calls this method and just returns the + * point. + */ + var _pointAlongPath = function(curve, location, distance) { + + if (_isPoint(curve)) { + return { + point:curve[0], + location:location + }; + } + + var prev = _pointOnPath(curve, location), + tally = 0, + curLoc = location, + direction = distance > 0 ? 1 : -1, + cur = null; + + while (tally < Math.abs(distance)) { + curLoc += (0.005 * direction); + cur = _pointOnPath(curve, curLoc); + tally += _dist(cur, prev); + prev = cur; + } + return {point:cur, location:curLoc}; + }; + + var _length = function(curve) { + if (_isPoint(curve)) return 0; + + var prev = _pointOnPath(curve, 0), + tally = 0, + curLoc = 0, + direction = 1, + cur = null; + + while (curLoc < 1) { + curLoc += (0.005 * direction); + cur = _pointOnPath(curve, curLoc); + tally += _dist(cur, prev); + prev = cur; + } + return tally; + }; + + /** + * finds the point that is 'distance' along the path from 'location'. + */ + var _pointAlongPathFrom = function(curve, location, distance) { + return _pointAlongPath(curve, location, distance).point; + }; + + /** + * finds the location that is 'distance' along the path from 'location'. + */ + var _locationAlongPathFrom = function(curve, location, distance) { + return _pointAlongPath(curve, location, distance).location; + }; + + /** + * returns the gradient of the curve at the given location, which is a decimal between 0 and 1 inclusive. + * + * thanks // http://bimixual.org/AnimationLibrary/beziertangents.html + */ + var _gradientAtPoint = function(curve, location) { + var p1 = _pointOnPath(curve, location), + p2 = _pointOnPath(curve.slice(0, curve.length - 1), location), + dy = p2.y - p1.y, dx = p2.x - p1.x; + return dy === 0 ? Infinity : Math.atan(dy / dx); + }; + + /** + returns the gradient of the curve at the point which is 'distance' from the given location. + if this point is greater than location 1, the gradient at location 1 is returned. + if this point is less than location 0, the gradient at location 0 is returned. + */ + var _gradientAtPointAlongPathFrom = function(curve, location, distance) { + var p = _pointAlongPath(curve, location, distance); + if (p.location > 1) p.location = 1; + if (p.location < 0) p.location = 0; + return _gradientAtPoint(curve, p.location); + }; + + /** + * calculates a line that is 'length' pixels long, perpendicular to, and centered on, the path at 'distance' pixels from the given location. + * if distance is not supplied, the perpendicular for the given location is computed (ie. we set distance to zero). + */ + var _perpendicularToPathAt = function(curve, location, length, distance) { + distance = distance == null ? 0 : distance; + var p = _pointAlongPath(curve, location, distance), + m = _gradientAtPoint(curve, p.location), + _theta2 = Math.atan(-1 / m), + y = length / 2 * Math.sin(_theta2), + x = length / 2 * Math.cos(_theta2); + return [{x:p.point.x + x, y:p.point.y + y}, {x:p.point.x - x, y:p.point.y - y}]; + }; + + /** + * Calculates all intersections of the given line with the given curve. + * @param x1 + * @param y1 + * @param x2 + * @param y2 + * @param curve + * @returns {Array} + */ + var _lineIntersection = function(x1, y1, x2, y2, curve) { + var a = y2 - y1, + b = x1 - x2, + c = (x1 * (y1 - y2)) + (y1 * (x2-x1)), + coeffs = _computeCoefficients(curve), + p = [ + (a*coeffs[0][0]) + (b * coeffs[1][0]), + (a*coeffs[0][1])+(b*coeffs[1][1]), + (a*coeffs[0][2])+(b*coeffs[1][2]), + (a*coeffs[0][3])+(b*coeffs[1][3]) + c + ], + r = _cubicRoots.apply(null, p), + intersections = []; + + if (r != null) { + + for (var i = 0; i < 3; i++) { + var t = r[i], + t2 = Math.pow(t, 2), + t3 = Math.pow(t, 3), + x = [ + (coeffs[0][0] * t3) + (coeffs[0][1] * t2) + (coeffs[0][2] * t) + coeffs[0][3], + (coeffs[1][0] * t3) + (coeffs[1][1] * t2) + (coeffs[1][2] * t) + coeffs[1][3] + ]; + + // check bounds of the line + var s; + if ((x2 - x1) !== 0) { + s = (x[0] - x1) / (x2 - x1); + } + else { + s = (x[1] - y1) / (y2 - y1); + } + + if (t >= 0 && t <= 1.0 && s >= 0 && s <= 1.0) { + intersections.push(x); + } + } + } + + return intersections; + }; + + /** + * Calculates all intersections of the given box with the given curve. + * @param x X position of top left corner of box + * @param y Y position of top left corner of box + * @param w width of box + * @param h height of box + * @param curve + * @returns {Array} + */ + var _boxIntersection = function(x, y, w, h, curve) { + var i = []; + i.push.apply(i, _lineIntersection(x, y, x + w, y, curve)); + i.push.apply(i, _lineIntersection(x + w, y, x + w, y + h, curve)); + i.push.apply(i, _lineIntersection(x + w, y + h, x, y + h, curve)); + i.push.apply(i, _lineIntersection(x, y + h, x, y, curve)); + return i; + }; + + /** + * Calculates all intersections of the given bounding box with the given curve. + * @param boundingBox Bounding box, in { x:.., y:..., w:..., h:... } format. + * @param curve + * @returns {Array} + */ + var _boundingBoxIntersection = function(boundingBox, curve) { + var i = []; + i.push.apply(i, _lineIntersection(boundingBox.x, boundingBox.y, boundingBox.x + boundingBox.w, boundingBox.y, curve)); + i.push.apply(i, _lineIntersection(boundingBox.x + boundingBox.w, boundingBox.y, boundingBox.x + boundingBox.w, boundingBox.y + boundingBox.h, curve)); + i.push.apply(i, _lineIntersection(boundingBox.x + boundingBox.w, boundingBox.y + boundingBox.h, boundingBox.x, boundingBox.y + boundingBox.h, curve)); + i.push.apply(i, _lineIntersection(boundingBox.x, boundingBox.y + boundingBox.h, boundingBox.x, boundingBox.y, curve)); + return i; + }; + + + function _computeCoefficientsForAxis(curve, axis) { + return [ + -(curve[0][axis]) + (3*curve[1][axis]) + (-3 * curve[2][axis]) + curve[3][axis], + (3*(curve[0][axis])) - (6*(curve[1][axis])) + (3*(curve[2][axis])), + -3*curve[0][axis] + 3*curve[1][axis], + curve[0][axis] + ]; + } + + function _computeCoefficients(curve) + { + return [ + _computeCoefficientsForAxis(curve, "x"), + _computeCoefficientsForAxis(curve, "y") + ]; + } + + function sgn(x) { + return x < 0 ? -1 : x > 0 ? 1 : 0; + } + + function _cubicRoots(a, b, c, d) { + var A = b / a, + B = c / a, + C = d / a, + Q = (3*B - Math.pow(A, 2))/9, + R = (9*A*B - 27*C - 2*Math.pow(A, 3))/54, + D = Math.pow(Q, 3) + Math.pow(R, 2), + S, + T, + t = []; + + if (D >= 0) // complex or duplicate roots + { + S = sgn(R + Math.sqrt(D))*Math.pow(Math.abs(R + Math.sqrt(D)),(1/3)); + T = sgn(R - Math.sqrt(D))*Math.pow(Math.abs(R - Math.sqrt(D)),(1/3)); + + t[0] = -A/3 + (S + T); + t[1] = -A/3 - (S + T)/2; + t[2] = -A/3 - (S + T)/2; + + /*discard complex roots*/ + if (Math.abs(Math.sqrt(3)*(S - T)/2) !== 0) { + t[1] = -1; + t[2] = -1; + } + } + else // distinct real roots + { + var th = Math.acos(R/Math.sqrt(-Math.pow(Q, 3))); + t[0] = 2*Math.sqrt(-Q)*Math.cos(th/3) - A/3; + t[1] = 2*Math.sqrt(-Q)*Math.cos((th + 2*Math.PI)/3) - A/3; + t[2] = 2*Math.sqrt(-Q)*Math.cos((th + 4*Math.PI)/3) - A/3; + } + + // discard out of spec roots + for (var i = 0; i < 3; i++) { + if (t[i] < 0 || t[i] > 1.0) { + t[i] = -1; + } + } + + return t; + } + + var jsBezier = this.jsBezier = { + distanceFromCurve : _distanceFromCurve, + gradientAtPoint : _gradientAtPoint, + gradientAtPointAlongCurveFrom : _gradientAtPointAlongPathFrom, + nearestPointOnCurve : _nearestPointOnCurve, + pointOnCurve : _pointOnPath, + pointAlongCurveFrom : _pointAlongPathFrom, + perpendicularToCurveAt : _perpendicularToPathAt, + locationAlongCurveFrom:_locationAlongPathFrom, + getLength:_length, + lineIntersection:_lineIntersection, + boxIntersection:_boxIntersection, + boundingBoxIntersection:_boundingBoxIntersection, + version:"0.9.0" + }; + + if (typeof exports !== "undefined") { + exports.jsBezier = jsBezier; + } + +}).call(typeof window !== 'undefined' ? window : this); + +/** + * Biltong v0.4.0 + * + * Various geometry functions written as part of jsPlumb and perhaps useful for others. + * + * Copyright (c) 2017 jsPlumb + * https://jsplumbtoolkit.com + * + * 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. + */ +;(function() { + + "use strict"; + var root = this; + + var Biltong = root.Biltong = { + version:"0.4.0" + }; + + if (typeof exports !== "undefined") { + exports.Biltong = Biltong; + } + + var _isa = function(a) { return Object.prototype.toString.call(a) === "[object Array]"; }, + _pointHelper = function(p1, p2, fn) { + p1 = _isa(p1) ? p1 : [p1.x, p1.y]; + p2 = _isa(p2) ? p2 : [p2.x, p2.y]; + return fn(p1, p2); + }, + /** + * @name Biltong.gradient + * @function + * @desc Calculates the gradient of a line between the two points. + * @param {Point} p1 First point, either as a 2 entry array or object with `left` and `top` properties. + * @param {Point} p2 Second point, either as a 2 entry array or object with `left` and `top` properties. + * @return {Float} The gradient of a line between the two points. + */ + _gradient = Biltong.gradient = function(p1, p2) { + return _pointHelper(p1, p2, function(_p1, _p2) { + if (_p2[0] == _p1[0]) + return _p2[1] > _p1[1] ? Infinity : -Infinity; + else if (_p2[1] == _p1[1]) + return _p2[0] > _p1[0] ? 0 : -0; + else + return (_p2[1] - _p1[1]) / (_p2[0] - _p1[0]); + }); + }, + /** + * @name Biltong.normal + * @function + * @desc Calculates the gradient of a normal to a line between the two points. + * @param {Point} p1 First point, either as a 2 entry array or object with `left` and `top` properties. + * @param {Point} p2 Second point, either as a 2 entry array or object with `left` and `top` properties. + * @return {Float} The gradient of a normal to a line between the two points. + */ + _normal = Biltong.normal = function(p1, p2) { + return -1 / _gradient(p1, p2); + }, + /** + * @name Biltong.lineLength + * @function + * @desc Calculates the length of a line between the two points. + * @param {Point} p1 First point, either as a 2 entry array or object with `left` and `top` properties. + * @param {Point} p2 Second point, either as a 2 entry array or object with `left` and `top` properties. + * @return {Float} The length of a line between the two points. + */ + _lineLength = Biltong.lineLength = function(p1, p2) { + return _pointHelper(p1, p2, function(_p1, _p2) { + return Math.sqrt(Math.pow(_p2[1] - _p1[1], 2) + Math.pow(_p2[0] - _p1[0], 2)); + }); + }, + /** + * @name Biltong.quadrant + * @function + * @desc Calculates the quadrant in which the angle between the two points lies. + * @param {Point} p1 First point, either as a 2 entry array or object with `left` and `top` properties. + * @param {Point} p2 Second point, either as a 2 entry array or object with `left` and `top` properties. + * @return {Integer} The quadrant - 1 for upper right, 2 for lower right, 3 for lower left, 4 for upper left. + */ + _quadrant = Biltong.quadrant = function(p1, p2) { + return _pointHelper(p1, p2, function(_p1, _p2) { + if (_p2[0] > _p1[0]) { + return (_p2[1] > _p1[1]) ? 2 : 1; + } + else if (_p2[0] == _p1[0]) { + return _p2[1] > _p1[1] ? 2 : 1; + } + else { + return (_p2[1] > _p1[1]) ? 3 : 4; + } + }); + }, + /** + * @name Biltong.theta + * @function + * @desc Calculates the angle between the two points. + * @param {Point} p1 First point, either as a 2 entry array or object with `left` and `top` properties. + * @param {Point} p2 Second point, either as a 2 entry array or object with `left` and `top` properties. + * @return {Float} The angle between the two points. + */ + _theta = Biltong.theta = function(p1, p2) { + return _pointHelper(p1, p2, function(_p1, _p2) { + var m = _gradient(_p1, _p2), + t = Math.atan(m), + s = _quadrant(_p1, _p2); + if ((s == 4 || s== 3)) t += Math.PI; + if (t < 0) t += (2 * Math.PI); + + return t; + }); + }, + /** + * @name Biltong.intersects + * @function + * @desc Calculates whether or not the two rectangles intersect. + * @param {Rectangle} r1 First rectangle, as a js object in the form `{x:.., y:.., w:.., h:..}` + * @param {Rectangle} r2 Second rectangle, as a js object in the form `{x:.., y:.., w:.., h:..}` + * @return {Boolean} True if the rectangles intersect, false otherwise. + */ + _intersects = Biltong.intersects = function(r1, r2) { + var x1 = r1.x, x2 = r1.x + r1.w, y1 = r1.y, y2 = r1.y + r1.h, + a1 = r2.x, a2 = r2.x + r2.w, b1 = r2.y, b2 = r2.y + r2.h; + + return ( (x1 <= a1 && a1 <= x2) && (y1 <= b1 && b1 <= y2) ) || + ( (x1 <= a2 && a2 <= x2) && (y1 <= b1 && b1 <= y2) ) || + ( (x1 <= a1 && a1 <= x2) && (y1 <= b2 && b2 <= y2) ) || + ( (x1 <= a2 && a1 <= x2) && (y1 <= b2 && b2 <= y2) ) || + ( (a1 <= x1 && x1 <= a2) && (b1 <= y1 && y1 <= b2) ) || + ( (a1 <= x2 && x2 <= a2) && (b1 <= y1 && y1 <= b2) ) || + ( (a1 <= x1 && x1 <= a2) && (b1 <= y2 && y2 <= b2) ) || + ( (a1 <= x2 && x1 <= a2) && (b1 <= y2 && y2 <= b2) ); + }, + /** + * @name Biltong.encloses + * @function + * @desc Calculates whether or not r2 is completely enclosed by r1. + * @param {Rectangle} r1 First rectangle, as a js object in the form `{x:.., y:.., w:.., h:..}` + * @param {Rectangle} r2 Second rectangle, as a js object in the form `{x:.., y:.., w:.., h:..}` + * @param {Boolean} [allowSharedEdges=false] If true, the concept of enclosure allows for one or more edges to be shared by the two rectangles. + * @return {Boolean} True if r1 encloses r2, false otherwise. + */ + _encloses = Biltong.encloses = function(r1, r2, allowSharedEdges) { + var x1 = r1.x, x2 = r1.x + r1.w, y1 = r1.y, y2 = r1.y + r1.h, + a1 = r2.x, a2 = r2.x + r2.w, b1 = r2.y, b2 = r2.y + r2.h, + c = function(v1, v2, v3, v4) { return allowSharedEdges ? v1 <= v2 && v3>= v4 : v1 < v2 && v3 > v4; }; + + return c(x1,a1,x2,a2) && c(y1,b1,y2,b2); + }, + _segmentMultipliers = [null, [1, -1], [1, 1], [-1, 1], [-1, -1] ], + _inverseSegmentMultipliers = [null, [-1, -1], [-1, 1], [1, 1], [1, -1] ], + /** + * @name Biltong.pointOnLine + * @function + * @desc Calculates a point on the line from `fromPoint` to `toPoint` that is `distance` units along the length of the line. + * @param {Point} p1 First point, either as a 2 entry array or object with `left` and `top` properties. + * @param {Point} p2 Second point, either as a 2 entry array or object with `left` and `top` properties. + * @return {Point} Point on the line, in the form `{ x:..., y:... }`. + */ + _pointOnLine = Biltong.pointOnLine = function(fromPoint, toPoint, distance) { + var m = _gradient(fromPoint, toPoint), + s = _quadrant(fromPoint, toPoint), + segmentMultiplier = distance > 0 ? _segmentMultipliers[s] : _inverseSegmentMultipliers[s], + theta = Math.atan(m), + y = Math.abs(distance * Math.sin(theta)) * segmentMultiplier[1], + x = Math.abs(distance * Math.cos(theta)) * segmentMultiplier[0]; + return { x:fromPoint.x + x, y:fromPoint.y + y }; + }, + /** + * @name Biltong.perpendicularLineTo + * @function + * @desc Calculates a line of length `length` that is perpendicular to the line from `fromPoint` to `toPoint` and passes through `toPoint`. + * @param {Point} p1 First point, either as a 2 entry array or object with `left` and `top` properties. + * @param {Point} p2 Second point, either as a 2 entry array or object with `left` and `top` properties. + * @return {Line} Perpendicular line, in the form `[ { x:..., y:... }, { x:..., y:... } ]`. + */ + _perpendicularLineTo = Biltong.perpendicularLineTo = function(fromPoint, toPoint, length) { + var m = _gradient(fromPoint, toPoint), + theta2 = Math.atan(-1 / m), + y = length / 2 * Math.sin(theta2), + x = length / 2 * Math.cos(theta2); + return [{x:toPoint.x + x, y:toPoint.y + y}, {x:toPoint.x - x, y:toPoint.y - y}]; + }; +}).call(typeof window !== 'undefined' ? window : this); +; +(function () { + + "use strict"; + + /** + * Creates a Touch object. + * @param view + * @param target + * @param pageX + * @param pageY + * @param screenX + * @param screenY + * @param clientX + * @param clientY + * @returns {Touch} + * @private + */ + function _touch(view, target, pageX, pageY, screenX, screenY, clientX, clientY) { + + return new Touch({ + target:target, + identifier:_uuid(), + pageX: pageX, + pageY: pageY, + screenX: screenX, + screenY: screenY, + clientX: clientX || screenX, + clientY: clientY || screenY + }); + } + + /** + * Create a synthetic touch list from the given list of Touch objects. + * @returns {Array} + * @private + */ + function _touchList() { + var list = []; + Array.prototype.push.apply(list, arguments); + list.item = function(index) { return this[index]; }; + return list; + } + + /** + * Create a Touch object and then insert it into a synthetic touch list, returning the list.s + * @param view + * @param target + * @param pageX + * @param pageY + * @param screenX + * @param screenY + * @param clientX + * @param clientY + * @returns {Array} + * @private + */ + function _touchAndList(view, target, pageX, pageY, screenX, screenY, clientX, clientY) { + return _touchList(_touch.apply(null, arguments)); + } + + var root = this, + matchesSelector = function (el, selector, ctx) { + ctx = ctx || el.parentNode; + var possibles = ctx.querySelectorAll(selector); + for (var i = 0; i < possibles.length; i++) { + if (possibles[i] === el) { + return true; + } + } + return false; + }, + _gel = function (el) { + return (typeof el == "string" || el.constructor === String) ? document.getElementById(el) : el; + }, + _t = function (e) { + return e.srcElement || e.target; + }, + // + // gets path info for the given event - the path from target to obj, in the event's bubble chain. if doCompute + // is false we just return target for the path. + // + _pi = function(e, target, obj, doCompute) { + if (!doCompute) return { path:[target], end:1 }; + else if (typeof e.path !== "undefined" && e.path.indexOf) { + return { path: e.path, end: e.path.indexOf(obj) }; + } else { + var out = { path:[], end:-1 }, _one = function(el) { + out.path.push(el); + if (el === obj) { + out.end = out.path.length - 1; + } + else if (el.parentNode != null) { + _one(el.parentNode) + } + }; + _one(target); + return out; + } + }, + _d = function (l, fn) { + for (var i = 0, j = l.length; i < j; i++) { + if (l[i] == fn) break; + } + if (i < l.length) l.splice(i, 1); + }, + guid = 1, + // + // this function generates a guid for every handler, sets it on the handler, then adds + // it to the associated object's map of handlers for the given event. this is what enables us + // to unbind all events of some type, or all events (the second of which can be requested by the user, + // but it also used by Mottle when an element is removed.) + _store = function (obj, event, fn) { + var g = guid++; + obj.__ta = obj.__ta || {}; + obj.__ta[event] = obj.__ta[event] || {}; + // store each handler with a unique guid. + obj.__ta[event][g] = fn; + // set the guid on the handler. + fn.__tauid = g; + return g; + }, + _unstore = function (obj, event, fn) { + obj.__ta && obj.__ta[event] && delete obj.__ta[event][fn.__tauid]; + // a handler might have attached extra functions, so we unbind those too. + if (fn.__taExtra) { + for (var i = 0; i < fn.__taExtra.length; i++) { + _unbind(obj, fn.__taExtra[i][0], fn.__taExtra[i][1]); + } + fn.__taExtra.length = 0; + } + // a handler might have attached an unstore callback + fn.__taUnstore && fn.__taUnstore(); + }, + _curryChildFilter = function (children, obj, fn, evt) { + if (children == null) return fn; + else { + var c = children.split(","), + _fn = function (e) { + _fn.__tauid = fn.__tauid; + var t = _t(e), target = t; // t is the target element on which the event occurred. it is the + // element we will wish to pass to any callbacks. + var pathInfo = _pi(e, t, obj, children != null) + if (pathInfo.end != -1) { + for (var p = 0; p < pathInfo.end; p++) { + target = pathInfo.path[p]; + for (var i = 0; i < c.length; i++) { + if (matchesSelector(target, c[i], obj)) { + fn.apply(target, arguments); + } + } + } + } + }; + registerExtraFunction(fn, evt, _fn); + return _fn; + } + }, + // + // registers an 'extra' function on some event listener function we were given - a function that we + // created and bound to the element as part of our housekeeping, and which we want to unbind and remove + // whenever the given function is unbound. + registerExtraFunction = function (fn, evt, newFn) { + fn.__taExtra = fn.__taExtra || []; + fn.__taExtra.push([evt, newFn]); + }, + DefaultHandler = function (obj, evt, fn, children) { + if (isTouchDevice && touchMap[evt]) { + var tfn = _curryChildFilter(children, obj, fn, touchMap[evt]); + _bind(obj, touchMap[evt], tfn , fn); + } + if (evt === "focus" && obj.getAttribute("tabindex") == null) { + obj.setAttribute("tabindex", "1"); + } + _bind(obj, evt, _curryChildFilter(children, obj, fn, evt), fn); + }, + SmartClickHandler = function (obj, evt, fn, children) { + if (obj.__taSmartClicks == null) { + var down = function (e) { + obj.__tad = _pageLocation(e); + }, + up = function (e) { + obj.__tau = _pageLocation(e); + }, + click = function (e) { + if (obj.__tad && obj.__tau && obj.__tad[0] === obj.__tau[0] && obj.__tad[1] === obj.__tau[1]) { + for (var i = 0; i < obj.__taSmartClicks.length; i++) + obj.__taSmartClicks[i].apply(_t(e), [ e ]); + } + }; + DefaultHandler(obj, "mousedown", down, children); + DefaultHandler(obj, "mouseup", up, children); + DefaultHandler(obj, "click", click, children); + obj.__taSmartClicks = []; + } + + // store in the list of callbacks + obj.__taSmartClicks.push(fn); + // the unstore function removes this function from the object's listener list for this type. + fn.__taUnstore = function () { + _d(obj.__taSmartClicks, fn); + }; + }, + _tapProfiles = { + "tap": {touches: 1, taps: 1}, + "dbltap": {touches: 1, taps: 2}, + "contextmenu": {touches: 2, taps: 1} + }, + TapHandler = function (clickThreshold, dblClickThreshold) { + return function (obj, evt, fn, children) { + // if event is contextmenu, for devices which are mouse only, we want to + // use the default bind. + if (evt == "contextmenu" && isMouseDevice) + DefaultHandler(obj, evt, fn, children); + else { + // the issue here is that this down handler gets registered only for the + // child nodes in the first registration. in fact it should be registered with + // no child selector and then on down we should cycle through the registered + // functions to see if one of them matches. on mouseup we should execute ALL of + // the functions whose children are either null or match the element. + if (obj.__taTapHandler == null) { + var tt = obj.__taTapHandler = { + tap: [], + dbltap: [], + contextmenu: [], + down: false, + taps: 0, + downSelectors: [] + }; + var down = function (e) { + var target = _t(e), pathInfo = _pi(e, target, obj, children != null), finished = false; + for (var p = 0; p < pathInfo.end; p++) { + if (finished) return; + target = pathInfo.path[p]; + for (var i = 0; i < tt.downSelectors.length; i++) { + if (tt.downSelectors[i] == null || matchesSelector(target, tt.downSelectors[i], obj)) { + tt.down = true; + setTimeout(clearSingle, clickThreshold); + setTimeout(clearDouble, dblClickThreshold); + finished = true; + break; // we only need one match on mousedown + } + } + } + }, + up = function (e) { + if (tt.down) { + var target = _t(e), currentTarget, pathInfo; + tt.taps++; + var tc = _touchCount(e); + for (var eventId in _tapProfiles) { + if (_tapProfiles.hasOwnProperty(eventId)) { + var p = _tapProfiles[eventId]; + if (p.touches === tc && (p.taps === 1 || p.taps === tt.taps)) { + for (var i = 0; i < tt[eventId].length; i++) { + pathInfo = _pi(e, target, obj, tt[eventId][i][1] != null); + for (var pLoop = 0; pLoop < pathInfo.end; pLoop++) { + currentTarget = pathInfo.path[pLoop]; + // this is a single event registration handler. + if (tt[eventId][i][1] == null || matchesSelector(currentTarget, tt[eventId][i][1], obj)) { + tt[eventId][i][0].apply(currentTarget, [ e ]); + break; + } + } + } + } + } + } + } + }, + clearSingle = function () { + tt.down = false; + }, + clearDouble = function () { + tt.taps = 0; + }; + + DefaultHandler(obj, "mousedown", down); + DefaultHandler(obj, "mouseup", up); + } + // add this child selector (it can be null, that's fine). + obj.__taTapHandler.downSelectors.push(children); + + obj.__taTapHandler[evt].push([fn, children]); + // the unstore function removes this function from the object's listener list for this type. + fn.__taUnstore = function () { + _d(obj.__taTapHandler[evt], fn); + }; + } + }; + }, + meeHelper = function (type, evt, obj, target) { + for (var i in obj.__tamee[type]) { + if (obj.__tamee[type].hasOwnProperty(i)) { + obj.__tamee[type][i].apply(target, [ evt ]); + } + } + }, + MouseEnterExitHandler = function () { + var activeElements = []; + return function (obj, evt, fn, children) { + if (!obj.__tamee) { + // __tamee holds a flag saying whether the mouse is currently "in" the element, and a list of + // both mouseenter and mouseexit functions. + obj.__tamee = { over: false, mouseenter: [], mouseexit: [] }; + // register over and out functions + var over = function (e) { + var t = _t(e); + if ((children == null && (t == obj && !obj.__tamee.over)) || (matchesSelector(t, children, obj) && (t.__tamee == null || !t.__tamee.over))) { + meeHelper("mouseenter", e, obj, t); + t.__tamee = t.__tamee || {}; + t.__tamee.over = true; + activeElements.push(t); + } + }, + out = function (e) { + var t = _t(e); + // is the current target one of the activeElements? and is the + // related target NOT a descendant of it? + for (var i = 0; i < activeElements.length; i++) { + if (t == activeElements[i] && !matchesSelector((e.relatedTarget || e.toElement), "*", t)) { + t.__tamee.over = false; + activeElements.splice(i, 1); + meeHelper("mouseexit", e, obj, t); + } + } + }; + + _bind(obj, "mouseover", _curryChildFilter(children, obj, over, "mouseover"), over); + _bind(obj, "mouseout", _curryChildFilter(children, obj, out, "mouseout"), out); + } + + fn.__taUnstore = function () { + delete obj.__tamee[evt][fn.__tauid]; + }; + + _store(obj, evt, fn); + obj.__tamee[evt][fn.__tauid] = fn; + }; + }, + isTouchDevice = "ontouchstart" in document.documentElement, + isMouseDevice = "onmousedown" in document.documentElement, + touchMap = { "mousedown": "touchstart", "mouseup": "touchend", "mousemove": "touchmove" }, + touchstart = "touchstart", touchend = "touchend", touchmove = "touchmove", + iev = (function () { + var rv = -1; + if (navigator.appName == 'Microsoft Internet Explorer') { + var ua = navigator.userAgent, + re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})"); + if (re.exec(ua) != null) + rv = parseFloat(RegExp.$1); + } + return rv; + })(), + isIELT9 = iev > -1 && iev < 9, + _genLoc = function (e, prefix) { + if (e == null) return [ 0, 0 ]; + var ts = _touches(e), t = _getTouch(ts, 0); + return [t[prefix + "X"], t[prefix + "Y"]]; + }, + _pageLocation = function (e) { + if (e == null) return [ 0, 0 ]; + if (isIELT9) { + return [ e.clientX + document.documentElement.scrollLeft, e.clientY + document.documentElement.scrollTop ]; + } + else { + return _genLoc(e, "page"); + } + }, + _screenLocation = function (e) { + return _genLoc(e, "screen"); + }, + _clientLocation = function (e) { + return _genLoc(e, "client"); + }, + _getTouch = function (touches, idx) { + return touches.item ? touches.item(idx) : touches[idx]; + }, + _touches = function (e) { + return e.touches && e.touches.length > 0 ? e.touches : + e.changedTouches && e.changedTouches.length > 0 ? e.changedTouches : + e.targetTouches && e.targetTouches.length > 0 ? e.targetTouches : + [ e ]; + }, + _touchCount = function (e) { + return _touches(e).length; + }, + //http://www.quirksmode.org/blog/archives/2005/10/_and_the_winner_1.html + _bind = function (obj, type, fn, originalFn) { + _store(obj, type, fn); + originalFn.__tauid = fn.__tauid; + if (obj.addEventListener) + obj.addEventListener(type, fn, false); + else if (obj.attachEvent) { + var key = type + fn.__tauid; + obj["e" + key] = fn; + // TODO look at replacing with .call(..) + obj[key] = function () { + obj["e" + key] && obj["e" + key](window.event); + }; + obj.attachEvent("on" + type, obj[key]); + } + }, + _unbind = function (obj, type, fn) { + if (fn == null) return; + _each(obj, function () { + var _el = _gel(this); + _unstore(_el, type, fn); + // it has been bound if there is a tauid. otherwise it was not bound and we can ignore it. + if (fn.__tauid != null) { + if (_el.removeEventListener) { + _el.removeEventListener(type, fn, false); + if (isTouchDevice && touchMap[type]) _el.removeEventListener(touchMap[type], fn, false); + } + else if (this.detachEvent) { + var key = type + fn.__tauid; + _el[key] && _el.detachEvent("on" + type, _el[key]); + _el[key] = null; + _el["e" + key] = null; + } + } + + // if a touch event was also registered, deregister now. + if (fn.__taTouchProxy) { + _unbind(obj, fn.__taTouchProxy[1], fn.__taTouchProxy[0]); + } + }); + }, + _each = function (obj, fn) { + if (obj == null) return; + // if a list (or list-like), use it. if a string, get a list + // by running the string through querySelectorAll. else, assume + // it's an Element. + // obj.top is "unknown" in IE8. + obj = (typeof Window !== "undefined" && (typeof obj.top !== "unknown" && obj == obj.top)) ? [ obj ] : + (typeof obj !== "string") && (obj.tagName == null && obj.length != null) ? obj : + typeof obj === "string" ? document.querySelectorAll(obj) + : [ obj ]; + + for (var i = 0; i < obj.length; i++) + fn.apply(obj[i]); + }, + _uuid = function () { + return ('xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + })); + }; + + /** + * Mottle offers support for abstracting out the differences + * between touch and mouse devices, plus "smart click" functionality + * (don't fire click if the mouse has moved between mousedown and mouseup), + * and synthesized click/tap events. + * @class Mottle + * @constructor + * @param {Object} params Constructor params + * @param {Number} [params.clickThreshold=250] Threshold, in milliseconds beyond which a touchstart followed by a touchend is not considered to be a click. + * @param {Number} [params.dblClickThreshold=450] Threshold, in milliseconds beyond which two successive tap events are not considered to be a click. + * @param {Boolean} [params.smartClicks=false] If true, won't fire click events if the mouse has moved between mousedown and mouseup. Note that this functionality + * requires that Mottle consume the mousedown event, and so may not be viable in all use cases. + */ + root.Mottle = function (params) { + params = params || {}; + var clickThreshold = params.clickThreshold || 250, + dblClickThreshold = params.dblClickThreshold || 450, + mouseEnterExitHandler = new MouseEnterExitHandler(), + tapHandler = new TapHandler(clickThreshold, dblClickThreshold), + _smartClicks = params.smartClicks, + _doBind = function (obj, evt, fn, children) { + if (fn == null) return; + _each(obj, function () { + var _el = _gel(this); + if (_smartClicks && evt === "click") + SmartClickHandler(_el, evt, fn, children); + else if (evt === "tap" || evt === "dbltap" || evt === "contextmenu") { + tapHandler(_el, evt, fn, children); + } + else if (evt === "mouseenter" || evt == "mouseexit") + mouseEnterExitHandler(_el, evt, fn, children); + else + DefaultHandler(_el, evt, fn, children); + }); + }; + + /** + * Removes an element from the DOM, and deregisters all event handlers for it. You should use this + * to ensure you don't leak memory. + * @method remove + * @param {String|Element} el Element, or id of the element, to remove. + * @return {Mottle} The current Mottle instance; you can chain this method. + */ + this.remove = function (el) { + _each(el, function () { + var _el = _gel(this); + if (_el.__ta) { + for (var evt in _el.__ta) { + if (_el.__ta.hasOwnProperty(evt)) { + for (var h in _el.__ta[evt]) { + if (_el.__ta[evt].hasOwnProperty(h)) + _unbind(_el, evt, _el.__ta[evt][h]); + } + } + } + } + _el.parentNode && _el.parentNode.removeChild(_el); + }); + return this; + }; + + /** + * Register an event handler, optionally as a delegate for some set of descendant elements. Note + * that this method takes either 3 or 4 arguments - if you supply 3 arguments it is assumed you have + * omitted the `children` parameter, and that the event handler should be bound directly to the given element. + * @method on + * @param {Element[]|Element|String} el Either an Element, or a CSS spec for a list of elements, or an array of Elements. + * @param {String} [children] Comma-delimited list of selectors identifying allowed children. + * @param {String} event Event ID. + * @param {Function} fn Event handler function. + * @return {Mottle} The current Mottle instance; you can chain this method. + */ + this.on = function (el, event, children, fn) { + var _el = arguments[0], + _c = arguments.length == 4 ? arguments[2] : null, + _e = arguments[1], + _f = arguments[arguments.length - 1]; + + _doBind(_el, _e, _f, _c); + return this; + }; + + /** + * Cancel delegate event handling for the given function. Note that unlike with 'on' you do not supply + * a list of child selectors here: it removes event delegation from all of the child selectors for which the + * given function was registered (if any). + * @method off + * @param {Element[]|Element|String} el Element - or ID of element - from which to remove event listener. + * @param {String} event Event ID. + * @param {Function} fn Event handler function. + * @return {Mottle} The current Mottle instance; you can chain this method. + */ + this.off = function (el, event, fn) { + _unbind(el, event, fn); + return this; + }; + + /** + * Triggers some event for a given element. + * @method trigger + * @param {Element} el Element for which to trigger the event. + * @param {String} event Event ID. + * @param {Event} originalEvent The original event. Should be optional of course, but currently is not, due + * to the jsPlumb use case that caused this method to be added. + * @param {Object} [payload] Optional object to set as `payload` on the generated event; useful for message passing. + * @return {Mottle} The current Mottle instance; you can chain this method. + */ + this.trigger = function (el, event, originalEvent, payload) { + // MouseEvent undefined in old IE; that's how we know it's a mouse event. A fine Microsoft paradox. + var originalIsMouse = isMouseDevice && (typeof MouseEvent === "undefined" || originalEvent == null || originalEvent.constructor === MouseEvent); + + var eventToBind = (isTouchDevice && !isMouseDevice && touchMap[event]) ? touchMap[event] : event, + bindingAMouseEvent = !(isTouchDevice && !isMouseDevice && touchMap[event]); + + var pl = _pageLocation(originalEvent), sl = _screenLocation(originalEvent), cl = _clientLocation(originalEvent); + _each(el, function () { + var _el = _gel(this), evt; + originalEvent = originalEvent || { + screenX: sl[0], + screenY: sl[1], + clientX: cl[0], + clientY: cl[1] + }; + + var _decorate = function (_evt) { + if (payload) _evt.payload = payload; + }; + + var eventGenerators = { + "TouchEvent": function (evt) { + + var touchList = _touchAndList(window, _el, 0, pl[0], pl[1], sl[0], sl[1], cl[0], cl[1]), + init = evt.initTouchEvent || evt.initEvent; + + init(eventToBind, true, true, window, null, sl[0], sl[1], + cl[0], cl[1], false, false, false, false, + touchList, touchList, touchList, 1, 0); + }, + "MouseEvents": function (evt) { + evt.initMouseEvent(eventToBind, true, true, window, 0, + sl[0], sl[1], + cl[0], cl[1], + false, false, false, false, 1, _el); + } + }; + + if (document.createEvent) { + + var ite = !bindingAMouseEvent && !originalIsMouse && (isTouchDevice && touchMap[event]), + evtName = ite ? "TouchEvent" : "MouseEvents"; + + evt = document.createEvent(evtName); + eventGenerators[evtName](evt); + _decorate(evt); + _el.dispatchEvent(evt); + } + else if (document.createEventObject) { + evt = document.createEventObject(); + evt.eventType = evt.eventName = eventToBind; + evt.screenX = sl[0]; + evt.screenY = sl[1]; + evt.clientX = cl[0]; + evt.clientY = cl[1]; + _decorate(evt); + _el.fireEvent('on' + eventToBind, evt); + } + }); + return this; + } + }; + + /** + * Static method to assist in 'consuming' an element: uses `stopPropagation` where available, or sets + * `e.returnValue=false` where it is not. + * @method Mottle.consume + * @param {Event} e Event to consume + * @param {Boolean} [doNotPreventDefault=false] If true, does not call `preventDefault()` on the event. + */ + root.Mottle.consume = function (e, doNotPreventDefault) { + if (e.stopPropagation) + e.stopPropagation(); + else + e.returnValue = false; + + if (!doNotPreventDefault && e.preventDefault) + e.preventDefault(); + }; + + /** + * Gets the page location corresponding to the given event. For touch events this means get the page location of the first touch. + * @method Mottle.pageLocation + * @param {Event} e Event to get page location for. + * @return {Number[]} [left, top] for the given event. + */ + root.Mottle.pageLocation = _pageLocation; + + /** + * Forces touch events to be turned "on". Useful for testing: even if you don't have a touch device, you can still + * trigger a touch event when this is switched on and it will be captured and acted on. + * @method setForceTouchEvents + * @param {Boolean} value If true, force touch events to be on. + */ + root.Mottle.setForceTouchEvents = function (value) { + isTouchDevice = value; + }; + + /** + * Forces mouse events to be turned "on". Useful for testing: even if you don't have a mouse, you can still + * trigger a mouse event when this is switched on and it will be captured and acted on. + * @method setForceMouseEvents + * @param {Boolean} value If true, force mouse events to be on. + */ + root.Mottle.setForceMouseEvents = function (value) { + isMouseDevice = value; + }; + + root.Mottle.version = "0.8.0"; + + if (typeof exports !== "undefined") { + exports.Mottle = root.Mottle; + } + +}).call(typeof window === "undefined" ? this : window); + +/** + drag/drop functionality for use with jsPlumb but with + no knowledge of jsPlumb. supports multiple scopes (separated by whitespace), dragging + multiple elements, constrain to parent, drop filters, drag start filters, custom + css classes. + + a lot of the functionality of this script is expected to be plugged in: + + addClass + removeClass + + addEvent + removeEvent + + getPosition + setPosition + getSize + + indexOf + intersects + + the name came from here: + + http://mrsharpoblunto.github.io/foswig.js/ + + copyright 2016 jsPlumb + */ + +;(function() { + + "use strict"; + var root = this; + + var _suggest = function(list, item, head) { + if (list.indexOf(item) === -1) { + head ? list.unshift(item) : list.push(item); + return true; + } + return false; + }; + + var _vanquish = function(list, item) { + var idx = list.indexOf(item); + if (idx !== -1) list.splice(idx, 1); + }; + + var _difference = function(l1, l2) { + var d = []; + for (var i = 0; i < l1.length; i++) { + if (l2.indexOf(l1[i]) === -1) + d.push(l1[i]); + } + return d; + }; + + var _isString = function(f) { + return f == null ? false : (typeof f === "string" || f.constructor === String); + }; + + var getOffsetRect = function (elem) { + // (1) + var box = elem.getBoundingClientRect(), + body = document.body, + docElem = document.documentElement, + // (2) + scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop, + scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft, + // (3) + clientTop = docElem.clientTop || body.clientTop || 0, + clientLeft = docElem.clientLeft || body.clientLeft || 0, + // (4) + top = box.top + scrollTop - clientTop, + left = box.left + scrollLeft - clientLeft; + + return { top: Math.round(top), left: Math.round(left) }; + }; + + var matchesSelector = function(el, selector, ctx) { + ctx = ctx || el.parentNode; + var possibles = ctx.querySelectorAll(selector); + for (var i = 0; i < possibles.length; i++) { + if (possibles[i] === el) + return true; + } + return false; + }; + + var findDelegateElement = function(parentElement, childElement, selector) { + if (matchesSelector(childElement, selector, parentElement)) { + return childElement; + } else { + var currentParent = childElement.parentNode; + while (currentParent != null && currentParent !== parentElement) { + if (matchesSelector(currentParent, selector, parentElement)) { + return currentParent; + } else { + currentParent = currentParent.parentNode; + } + } + } + }; + + /** + * Finds all elements matching the given selector, for the given parent. In order to support "scoped root" selectors, + * ie. things like "> .someClass", that is .someClass elements that are direct children of `parentElement`, we have to + * jump through a small hoop here: when a delegate draggable is registered, we write a `katavorio-draggable` attribute + * on the element on which the draggable is registered. Then when this method runs, we grab the value of that attribute and + * prepend it as part of the selector we're looking for. So "> .someClass" ends up being written as + * "[katavorio-draggable='...' > .someClass]", which works with querySelectorAll. + * + * @param availableSelectors + * @param parentElement + * @param childElement + * @returns {*} + */ + var findMatchingSelector = function(availableSelectors, parentElement, childElement) { + var el = null; + var draggableId = parentElement.getAttribute("katavorio-draggable"), + prefix = draggableId != null ? "[katavorio-draggable='" + draggableId + "'] " : ""; + + for (var i = 0; i < availableSelectors.length; i++) { + el = findDelegateElement(parentElement, childElement, prefix + availableSelectors[i].selector); + if (el != null) { + if (availableSelectors[i].filter) { + var matches = matchesSelector(childElement, availableSelectors[i].filter, el), + exclude = availableSelectors[i].filterExclude === true; + + if ( (exclude && !matches) || matches) { + return null; + } + + } + return [ availableSelectors[i], el ]; + } + } + return null; + }; + + var iev = (function() { + var rv = -1; + if (navigator.appName === 'Microsoft Internet Explorer') { + var ua = navigator.userAgent, + re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})"); + if (re.exec(ua) != null) + rv = parseFloat(RegExp.$1); + } + return rv; + })(), + DEFAULT_GRID_X = 10, + DEFAULT_GRID_Y = 10, + isIELT9 = iev > -1 && iev < 9, + isIE9 = iev === 9, + _pl = function(e) { + if (isIELT9) { + return [ e.clientX + document.documentElement.scrollLeft, e.clientY + document.documentElement.scrollTop ]; + } + else { + var ts = _touches(e), t = _getTouch(ts, 0); + // for IE9 pageX might be null if the event was synthesized. We try for pageX/pageY first, + // falling back to clientX/clientY if necessary. In every other browser we want to use pageX/pageY. + return isIE9 ? [t.pageX || t.clientX, t.pageY || t.clientY] : [t.pageX, t.pageY]; + } + }, + _getTouch = function(touches, idx) { return touches.item ? touches.item(idx) : touches[idx]; }, + _touches = function(e) { + return e.touches && e.touches.length > 0 ? e.touches : + e.changedTouches && e.changedTouches.length > 0 ? e.changedTouches : + e.targetTouches && e.targetTouches.length > 0 ? e.targetTouches : + [ e ]; + }, + _classes = { + delegatedDraggable:"katavorio-delegated-draggable", // elements that are the delegated drag handler for a bunch of other elements + draggable:"katavorio-draggable", // draggable elements + droppable:"katavorio-droppable", // droppable elements + drag : "katavorio-drag", // elements currently being dragged + selected:"katavorio-drag-selected", // elements in current drag selection + active : "katavorio-drag-active", // droppables that are targets of a currently dragged element + hover : "katavorio-drag-hover", // droppables over which a matching drag element is hovering + noSelect : "katavorio-drag-no-select", // added to the body to provide a hook to suppress text selection + ghostProxy:"katavorio-ghost-proxy", // added to a ghost proxy element in use when a drag has exited the bounds of its parent. + clonedDrag:"katavorio-clone-drag" // added to a node that is a clone of an element created at the start of a drag + }, + _defaultScope = "katavorio-drag-scope", + _events = [ "stop", "start", "drag", "drop", "over", "out", "beforeStart" ], + _devNull = function() {}, + _true = function() { return true; }, + _foreach = function(l, fn, from) { + for (var i = 0; i < l.length; i++) { + if (l[i] != from) + fn(l[i]); + } + }, + _setDroppablesActive = function(dd, val, andHover, drag) { + _foreach(dd, function(e) { + e.setActive(val); + if (val) e.updatePosition(); + if (andHover) e.setHover(drag, val); + }); + }, + _each = function(obj, fn) { + if (obj == null) return; + obj = !_isString(obj) && (obj.tagName == null && obj.length != null) ? obj : [ obj ]; + for (var i = 0; i < obj.length; i++) + fn.apply(obj[i], [ obj[i] ]); + }, + _consume = function(e) { + if (e.stopPropagation) { + e.stopPropagation(); + e.preventDefault(); + } + else { + e.returnValue = false; + } + }, + _defaultInputFilterSelector = "input,textarea,select,button,option", + // + // filters out events on all input elements, like textarea, checkbox, input, select. + _inputFilter = function(e, el, _katavorio) { + var t = e.srcElement || e.target; + return !matchesSelector(t, _katavorio.getInputFilterSelector(), el); + }; + + var Super = function(el, params, css, scope) { + this.params = params || {}; + this.el = el; + this.params.addClass(this.el, this._class); + this.uuid = _uuid(); + var enabled = true; + this.setEnabled = function(e) { enabled = e; }; + this.isEnabled = function() { return enabled; }; + this.toggleEnabled = function() { enabled = !enabled; }; + this.setScope = function(scopes) { + this.scopes = scopes ? scopes.split(/\s+/) : [ scope ]; + }; + this.addScope = function(scopes) { + var m = {}; + _each(this.scopes, function(s) { m[s] = true;}); + _each(scopes ? scopes.split(/\s+/) : [], function(s) { m[s] = true;}); + this.scopes = []; + for (var i in m) this.scopes.push(i); + }; + this.removeScope = function(scopes) { + var m = {}; + _each(this.scopes, function(s) { m[s] = true;}); + _each(scopes ? scopes.split(/\s+/) : [], function(s) { delete m[s];}); + this.scopes = []; + for (var i in m) this.scopes.push(i); + }; + this.toggleScope = function(scopes) { + var m = {}; + _each(this.scopes, function(s) { m[s] = true;}); + _each(scopes ? scopes.split(/\s+/) : [], function(s) { + if (m[s]) delete m[s]; + else m[s] = true; + }); + this.scopes = []; + for (var i in m) this.scopes.push(i); + }; + this.setScope(params.scope); + this.k = params.katavorio; + return params.katavorio; + }; + + var TRUE = function() { return true; }; + var FALSE = function() { return false; }; + + var Drag = function(el, params, css, scope) { + this._class = css.draggable; + var k = Super.apply(this, arguments); + this.rightButtonCanDrag = this.params.rightButtonCanDrag; + var downAt = [0,0], posAtDown = null, pagePosAtDown = null, pageDelta = [0,0], moving = false, initialScroll = [0,0], + consumeStartEvent = this.params.consumeStartEvent !== false, + dragEl = this.el, + clone = this.params.clone, + scroll = this.params.scroll, + _multipleDrop = params.multipleDrop !== false, + isConstrained = false, + useGhostProxy = params.ghostProxy === true ? TRUE : params.ghostProxy && typeof params.ghostProxy === "function" ? params.ghostProxy : FALSE, + ghostProxy = function(el) { return el.cloneNode(true); }, + elementToDrag = null, + availableSelectors = [], + activeSelectorParams = null, // which, if any, selector config is currently active. + ghostProxyParent = params.ghostProxyParent, + currentParentPosition, + ghostParentPosition, + ghostDx, + ghostDy; + + // if an initial selector was provided, push the entire set of params as a selector config. + if (params.selector) { + var draggableId = el.getAttribute("katavorio-draggable"); + if (draggableId == null) { + draggableId = "" + new Date().getTime(); + el.setAttribute("katavorio-draggable", draggableId); + } + + availableSelectors.push(params); + } + + var snapThreshold = params.snapThreshold, + _snap = function(pos, gridX, gridY, thresholdX, thresholdY) { + var _dx = Math.floor(pos[0] / gridX), + _dxl = gridX * _dx, + _dxt = _dxl + gridX, + _x = Math.abs(pos[0] - _dxl) <= thresholdX ? _dxl : Math.abs(_dxt - pos[0]) <= thresholdX ? _dxt : pos[0]; + + var _dy = Math.floor(pos[1] / gridY), + _dyl = gridY * _dy, + _dyt = _dyl + gridY, + _y = Math.abs(pos[1] - _dyl) <= thresholdY ? _dyl : Math.abs(_dyt - pos[1]) <= thresholdY ? _dyt : pos[1]; + + return [ _x, _y]; + }; + + this.posses = []; + this.posseRoles = {}; + + this.toGrid = function(pos) { + if (this.params.grid == null) { + return pos; + } + else { + var tx = this.params.grid ? this.params.grid[0] / 2 : snapThreshold ? snapThreshold : DEFAULT_GRID_X / 2, + ty = this.params.grid ? this.params.grid[1] / 2 : snapThreshold ? snapThreshold : DEFAULT_GRID_Y / 2; + + return _snap(pos, this.params.grid[0], this.params.grid[1], tx, ty); + } + }; + + this.snap = function(x, y) { + if (dragEl == null) return; + x = x || (this.params.grid ? this.params.grid[0] : DEFAULT_GRID_X); + y = y || (this.params.grid ? this.params.grid[1] : DEFAULT_GRID_Y); + var p = this.params.getPosition(dragEl), + tx = this.params.grid ? this.params.grid[0] / 2 : snapThreshold, + ty = this.params.grid ? this.params.grid[1] / 2 : snapThreshold, + snapped = _snap(p, x, y, tx, ty); + + this.params.setPosition(dragEl, snapped); + return snapped; + }; + + this.setUseGhostProxy = function(val) { + useGhostProxy = val ? TRUE : FALSE; + }; + + var constrain; + var negativeFilter = function(pos) { + return (params.allowNegative === false) ? [ Math.max (0, pos[0]), Math.max(0, pos[1]) ] : pos; + }; + + var _setConstrain = function(value) { + constrain = typeof value === "function" ? value : value ? function(pos, dragEl, _constrainRect, _size) { + return negativeFilter([ + Math.max(0, Math.min(_constrainRect.w - _size[0], pos[0])), + Math.max(0, Math.min(_constrainRect.h - _size[1], pos[1])) + ]); + }.bind(this) : function(pos) { return negativeFilter(pos); }; + }.bind(this); + + _setConstrain(typeof this.params.constrain === "function" ? this.params.constrain : (this.params.constrain || this.params.containment)); + + + /** + * Sets whether or not the Drag is constrained. A value of 'true' means constrain to parent bounds; a function + * will be executed and returns true if the position is allowed. + * @param value + */ + this.setConstrain = function(value) { + _setConstrain(value); + }; + + var revertFunction; + /** + * Sets a function to call on drag stop, which, if it returns true, indicates that the given element should + * revert to its position before the previous drag. + * @param fn + */ + this.setRevert = function(fn) { + revertFunction = fn; + }; + + if (this.params.revert) { + revertFunction = this.params.revert; + } + + var _assignId = function(obj) { + if (typeof obj === "function") { + obj._katavorioId = _uuid(); + return obj._katavorioId; + } else { + return obj; + } + }, + // a map of { spec -> [ fn, exclusion ] } entries. + _filters = {}, + _testFilter = function(e) { + for (var key in _filters) { + var f = _filters[key]; + var rv = f[0](e); + if (f[1]) rv = !rv; + if (!rv) return false; + } + return true; + }, + _setFilter = this.setFilter = function(f, _exclude) { + if (f) { + var key = _assignId(f); + _filters[key] = [ + function(e) { + var t = e.srcElement || e.target, m; + if (_isString(f)) { + m = matchesSelector(t, f, el); + } + else if (typeof f === "function") { + m = f(e, el); + } + return m; + }, + _exclude !== false + ]; + + } + }, + _addFilter = this.addFilter = _setFilter, + _removeFilter = this.removeFilter = function(f) { + var key = typeof f === "function" ? f._katavorioId : f; + delete _filters[key]; + }; + + this.clearAllFilters = function() { + _filters = {}; + }; + + this.canDrag = this.params.canDrag || _true; + + var constrainRect, + matchingDroppables = [], + intersectingDroppables = []; + + this.addSelector = function(params) { + if (params.selector) { + availableSelectors.push(params); + } + }; + + this.downListener = function(e) { + if (e.defaultPrevented) { return; } + var isNotRightClick = this.rightButtonCanDrag || (e.which !== 3 && e.button !== 2); + if (isNotRightClick && this.isEnabled() && this.canDrag()) { + + var _f = _testFilter(e) && _inputFilter(e, this.el, this.k); + if (_f) { + + activeSelectorParams = null; + elementToDrag = null; + + // if (selector) { + // elementToDrag = findDelegateElement(this.el, e.target || e.srcElement, selector); + // if(elementToDrag == null) { + // return; + // } + // } + if (availableSelectors.length > 0) { + var match = findMatchingSelector(availableSelectors, this.el, e.target || e.srcElement); + if (match != null) { + activeSelectorParams = match[0]; + elementToDrag = match[1]; + } + // elementToDrag = findDelegateElement(this.el, e.target || e.srcElement, selector); + if(elementToDrag == null) { + return; + } + } + else { + elementToDrag = this.el; + } + + if (clone) { + dragEl = elementToDrag.cloneNode(true); + this.params.addClass(dragEl, _classes.clonedDrag); + + dragEl.setAttribute("id", null); + dragEl.style.position = "absolute"; + + if (this.params.parent != null) { + var p = this.params.getPosition(this.el); + dragEl.style.left = p[0] + "px"; + dragEl.style.top = p[1] + "px"; + this.params.parent.appendChild(dragEl); + } else { + // the clone node is added to the body; getOffsetRect gives us a value + // relative to the body. + var b = getOffsetRect(elementToDrag); + dragEl.style.left = b.left + "px"; + dragEl.style.top = b.top + "px"; + + document.body.appendChild(dragEl); + } + + } else { + dragEl = elementToDrag; + } + + consumeStartEvent && _consume(e); + downAt = _pl(e); + if (dragEl && dragEl.parentNode) + { + initialScroll = [dragEl.parentNode.scrollLeft, dragEl.parentNode.scrollTop]; + } + // + this.params.bind(document, "mousemove", this.moveListener); + this.params.bind(document, "mouseup", this.upListener); + k.markSelection(this); + k.markPosses(this); + this.params.addClass(document.body, css.noSelect); + _dispatch("beforeStart", {el:this.el, pos:posAtDown, e:e, drag:this}); + } + else if (this.params.consumeFilteredEvents) { + _consume(e); + } + } + }.bind(this); + + this.moveListener = function(e) { + if (downAt) { + if (!moving) { + var _continue = _dispatch("start", {el:this.el, pos:posAtDown, e:e, drag:this}); + if (_continue !== false) { + if (!downAt) { + return; + } + this.mark(true); + moving = true; + } else { + this.abort(); + } + } + + // it is possible that the start event caused the drag to be aborted. So we check + // again that we are currently dragging. + if (downAt) { + intersectingDroppables.length = 0; + var pos = _pl(e), dx = pos[0] - downAt[0], dy = pos[1] - downAt[1], + z = this.params.ignoreZoom ? 1 : k.getZoom(); + if (dragEl && dragEl.parentNode) + { + dx += dragEl.parentNode.scrollLeft - initialScroll[0]; + dy += dragEl.parentNode.scrollTop - initialScroll[1]; + } + dx /= z; + dy /= z; + this.moveBy(dx, dy, e); + k.updateSelection(dx, dy, this); + k.updatePosses(dx, dy, this); + } + } + }.bind(this); + + this.upListener = function(e) { + if (downAt) { + downAt = null; + this.params.unbind(document, "mousemove", this.moveListener); + this.params.unbind(document, "mouseup", this.upListener); + this.params.removeClass(document.body, css.noSelect); + this.unmark(e); + k.unmarkSelection(this, e); + k.unmarkPosses(this, e); + this.stop(e); + + k.notifyPosseDragStop(this, e); + moving = false; + intersectingDroppables.length = 0; + + if (clone) { + dragEl && dragEl.parentNode && dragEl.parentNode.removeChild(dragEl); + dragEl = null; + } else { + if (revertFunction && revertFunction(dragEl, this.params.getPosition(dragEl)) === true) { + this.params.setPosition(dragEl, posAtDown); + _dispatch("revert", dragEl); + } + } + + } + }.bind(this); + + this.getFilters = function() { return _filters; }; + + this.abort = function() { + if (downAt != null) { + this.upListener(); + } + }; + + /** + * Returns the element that was last dragged. This may be some original element from the DOM, or if `clone` is + * set, then its actually a copy of some original DOM element. In some client calls to this method, it is the + * actual element that was dragged that is desired. In others, it is the original DOM element that the user + * wishes to get - in which case, pass true for `retrieveOriginalElement`. + * + * @returns {*} + */ + this.getDragElement = function(retrieveOriginalElement) { + return retrieveOriginalElement ? elementToDrag || this.el : dragEl || this.el; + }; + + var listeners = {"start":[], "drag":[], "stop":[], "over":[], "out":[], "beforeStart":[], "revert":[] }; + if (params.events.start) listeners.start.push(params.events.start); + if (params.events.beforeStart) listeners.beforeStart.push(params.events.beforeStart); + if (params.events.stop) listeners.stop.push(params.events.stop); + if (params.events.drag) listeners.drag.push(params.events.drag); + if (params.events.revert) listeners.revert.push(params.events.revert); + + this.on = function(evt, fn) { + if (listeners[evt]) listeners[evt].push(fn); + }; + + this.off = function(evt, fn) { + if (listeners[evt]) { + var l = []; + for (var i = 0; i < listeners[evt].length; i++) { + if (listeners[evt][i] !== fn) l.push(listeners[evt][i]); + } + listeners[evt] = l; + } + }; + + var _dispatch = function(evt, value) { + var result = null; + if (activeSelectorParams && activeSelectorParams[evt]) { + result = activeSelectorParams[evt](value); + } else if (listeners[evt]) { + for (var i = 0; i < listeners[evt].length; i++) { + try { + var v = listeners[evt][i](value); + if (v != null) { + result = v; + } + } + catch (e) { } + } + } + return result; + }; + + this.notifyStart = function(e) { + _dispatch("start", {el:this.el, pos:this.params.getPosition(dragEl), e:e, drag:this}); + }; + + this.stop = function(e, force) { + if (force || moving) { + var positions = [], + sel = k.getSelection(), + dPos = this.params.getPosition(dragEl); + + if (sel.length > 0) { + for (var i = 0; i < sel.length; i++) { + var p = this.params.getPosition(sel[i].el); + positions.push([ sel[i].el, { left: p[0], top: p[1] }, sel[i] ]); + } + } + else { + positions.push([ dragEl, {left:dPos[0], top:dPos[1]}, this ]); + } + + _dispatch("stop", { + el: dragEl, + pos: ghostProxyOffsets || dPos, + finalPos:dPos, + e: e, + drag: this, + selection:positions + }); + } + }; + + this.mark = function(andNotify) { + posAtDown = this.params.getPosition(dragEl); + pagePosAtDown = this.params.getPosition(dragEl, true); + pageDelta = [pagePosAtDown[0] - posAtDown[0], pagePosAtDown[1] - posAtDown[1]]; + this.size = this.params.getSize(dragEl); + matchingDroppables = k.getMatchingDroppables(this); + _setDroppablesActive(matchingDroppables, true, false, this); + this.params.addClass(dragEl, this.params.dragClass || css.drag); + + var cs; + if (this.params.getConstrainingRectangle) { + cs = this.params.getConstrainingRectangle(dragEl) + } else { + cs = this.params.getSize(dragEl.parentNode); + } + constrainRect = {w: cs[0], h: cs[1]}; + + ghostDx = 0; + ghostDy = 0; + + if (andNotify) { + k.notifySelectionDragStart(this); + } + }; + var ghostProxyOffsets; + this.unmark = function(e, doNotCheckDroppables) { + _setDroppablesActive(matchingDroppables, false, true, this); + + if (isConstrained && useGhostProxy(elementToDrag, dragEl)) { + ghostProxyOffsets = [dragEl.offsetLeft - ghostDx, dragEl.offsetTop - ghostDy]; + dragEl.parentNode.removeChild(dragEl); + dragEl = elementToDrag; + } + else { + ghostProxyOffsets = null; + } + + this.params.removeClass(dragEl, this.params.dragClass || css.drag); + matchingDroppables.length = 0; + isConstrained = false; + if (!doNotCheckDroppables) { + if (intersectingDroppables.length > 0 && ghostProxyOffsets) { + params.setPosition(elementToDrag, ghostProxyOffsets); + } + intersectingDroppables.sort(_rankSort); + for (var i = 0; i < intersectingDroppables.length; i++) { + var retVal = intersectingDroppables[i].drop(this, e); + if (retVal === true) break; + } + } + }; + this.moveBy = function(dx, dy, e) { + intersectingDroppables.length = 0; + + var desiredLoc = this.toGrid([posAtDown[0] + dx, posAtDown[1] + dy]), + cPos = constrain(desiredLoc, dragEl, constrainRect, this.size); + + // if we should use a ghost proxy... + if (useGhostProxy(this.el, dragEl)) { + // and the element has been dragged outside of its parent bounds + if (desiredLoc[0] !== cPos[0] || desiredLoc[1] !== cPos[1]) { + + // ...if ghost proxy not yet created + if (!isConstrained) { + // create it + var gp = ghostProxy(elementToDrag); + params.addClass(gp, _classes.ghostProxy); + + if (ghostProxyParent) { + ghostProxyParent.appendChild(gp); + // find offset between drag el's parent the ghost parent + currentParentPosition = params.getPosition(elementToDrag.parentNode, true); + ghostParentPosition = params.getPosition(params.ghostProxyParent, true); + ghostDx = currentParentPosition[0] - ghostParentPosition[0]; + ghostDy = currentParentPosition[1] - ghostParentPosition[1]; + + } else { + elementToDrag.parentNode.appendChild(gp); + } + + // the ghost proxy is the drag element + dragEl = gp; + // set this flag so we dont recreate the ghost proxy + isConstrained = true; + } + // now the drag position can be the desired position, as the ghost proxy can support it. + cPos = desiredLoc; + } + else { + // if the element is not outside of its parent bounds, and ghost proxy is in place, + if (isConstrained) { + // remove the ghost proxy from the dom + dragEl.parentNode.removeChild(dragEl); + // reset the drag element to the original element + dragEl = elementToDrag; + // clear this flag. + isConstrained = false; + currentParentPosition = null; + ghostParentPosition = null; + ghostDx = 0; + ghostDy = 0; + } + } + } + + var rect = { x:cPos[0], y:cPos[1], w:this.size[0], h:this.size[1]}, + pageRect = { x:rect.x + pageDelta[0], y:rect.y + pageDelta[1], w:rect.w, h:rect.h}, + focusDropElement = null; + + this.params.setPosition(dragEl, [cPos[0] + ghostDx, cPos[1] + ghostDy]); + + for (var i = 0; i < matchingDroppables.length; i++) { + var r2 = { x:matchingDroppables[i].pagePosition[0], y:matchingDroppables[i].pagePosition[1], w:matchingDroppables[i].size[0], h:matchingDroppables[i].size[1]}; + if (this.params.intersects(pageRect, r2) && (_multipleDrop || focusDropElement == null || focusDropElement === matchingDroppables[i].el) && matchingDroppables[i].canDrop(this)) { + if (!focusDropElement) focusDropElement = matchingDroppables[i].el; + intersectingDroppables.push(matchingDroppables[i]); + matchingDroppables[i].setHover(this, true, e); + } + else if (matchingDroppables[i].isHover()) { + matchingDroppables[i].setHover(this, false, e); + } + } + + _dispatch("drag", {el:this.el, pos:cPos, e:e, drag:this}); + + /* test to see if the parent needs to be scrolled (future) + if (scroll) { + var pnsl = dragEl.parentNode.scrollLeft, pnst = dragEl.parentNode.scrollTop; + console.log("scroll!", pnsl, pnst); + }*/ + }; + this.destroy = function() { + this.params.unbind(this.el, "mousedown", this.downListener); + this.params.unbind(document, "mousemove", this.moveListener); + this.params.unbind(document, "mouseup", this.upListener); + this.downListener = null; + this.upListener = null; + this.moveListener = null; + }; + + // init:register mousedown, and perhaps set a filter + this.params.bind(this.el, "mousedown", this.downListener); + + // if handle provided, use that. otherwise, try to set a filter. + // note that a `handle` selector always results in filterExclude being set to false, ie. + // the selector defines the handle element(s). + if (this.params.handle) + _setFilter(this.params.handle, false); + else + _setFilter(this.params.filter, this.params.filterExclude); + }; + + var Drop = function(el, params, css, scope) { + this._class = css.droppable; + this.params = params || {}; + this.rank = params.rank || 0; + this._activeClass = this.params.activeClass || css.active; + this._hoverClass = this.params.hoverClass || css.hover; + Super.apply(this, arguments); + var hover = false; + this.allowLoopback = this.params.allowLoopback !== false; + + this.setActive = function(val) { + this.params[val ? "addClass" : "removeClass"](this.el, this._activeClass); + }; + + this.updatePosition = function() { + this.position = this.params.getPosition(this.el); + this.pagePosition = this.params.getPosition(this.el, true); + this.size = this.params.getSize(this.el); + }; + + this.canDrop = this.params.canDrop || function(drag) { + return true; + }; + + this.isHover = function() { return hover; }; + + this.setHover = function(drag, val, e) { + // if turning off hover but this was not the drag that caused the hover, ignore. + if (val || this.el._katavorioDragHover == null || this.el._katavorioDragHover === drag.el._katavorio) { + this.params[val ? "addClass" : "removeClass"](this.el, this._hoverClass); + this.el._katavorioDragHover = val ? drag.el._katavorio : null; + if (hover !== val) { + this.params.events[val ? "over" : "out"]({el: this.el, e: e, drag: drag, drop: this}); + } + hover = val; + } + }; + + /** + * A drop event. `drag` is the corresponding Drag object, which may be a Drag for some specific element, or it + * may be a Drag on some element acting as a delegate for elements contained within it. + * @param drag + * @param event + * @returns {*} + */ + this.drop = function(drag, event) { + return this.params.events["drop"]({ drag:drag, e:event, drop:this }); + }; + + this.destroy = function() { + this._class = null; + this._activeClass = null; + this._hoverClass = null; + hover = null; + }; + }; + + var _uuid = function() { + return ('xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8); + return v.toString(16); + })); + }; + + var _rankSort = function(a,b) { + return a.rank < b.rank ? 1 : a.rank > b.rank ? -1 : 0; + }; + + var _gel = function(el) { + if (el == null) return null; + el = (typeof el === "string" || el.constructor === String) ? document.getElementById(el) : el; + if (el == null) return null; + el._katavorio = el._katavorio || _uuid(); + return el; + }; + + root.Katavorio = function(katavorioParams) { + + var _selection = [], + _selectionMap = {}; + + this._dragsByScope = {}; + this._dropsByScope = {}; + var _zoom = 1, + _reg = function(obj, map) { + _each(obj, function(_obj) { + for(var i = 0; i < _obj.scopes.length; i++) { + map[_obj.scopes[i]] = map[_obj.scopes[i]] || []; + map[_obj.scopes[i]].push(_obj); + } + }); + }, + _unreg = function(obj, map) { + var c = 0; + _each(obj, function(_obj) { + for(var i = 0; i < _obj.scopes.length; i++) { + if (map[_obj.scopes[i]]) { + var idx = katavorioParams.indexOf(map[_obj.scopes[i]], _obj); + if (idx !== -1) { + map[_obj.scopes[i]].splice(idx, 1); + c++; + } + } + } + }); + + return c > 0 ; + }, + _getMatchingDroppables = this.getMatchingDroppables = function(drag) { + var dd = [], _m = {}; + for (var i = 0; i < drag.scopes.length; i++) { + var _dd = this._dropsByScope[drag.scopes[i]]; + if (_dd) { + for (var j = 0; j < _dd.length; j++) { + if (_dd[j].canDrop(drag) && !_m[_dd[j].uuid] && (_dd[j].allowLoopback || _dd[j].el !== drag.el)) { + _m[_dd[j].uuid] = true; + dd.push(_dd[j]); + } + } + } + } + dd.sort(_rankSort); + return dd; + }, + _prepareParams = function(p) { + p = p || {}; + var _p = { + events:{} + }, i; + for (i in katavorioParams) _p[i] = katavorioParams[i]; + for (i in p) _p[i] = p[i]; + // events + + for (i = 0; i < _events.length; i++) { + _p.events[_events[i]] = p[_events[i]] || _devNull; + } + _p.katavorio = this; + return _p; + }.bind(this), + _mistletoe = function(existingDrag, params) { + for (var i = 0; i < _events.length; i++) { + if (params[_events[i]]) { + existingDrag.on(_events[i], params[_events[i]]); + } + } + }.bind(this), + _css = {}, + overrideCss = katavorioParams.css || {}, + _scope = katavorioParams.scope || _defaultScope; + + // prepare map of css classes based on defaults frst, then optional overrides + for (var i in _classes) _css[i] = _classes[i]; + for (var i in overrideCss) _css[i] = overrideCss[i]; + + var inputFilterSelector = katavorioParams.inputFilterSelector || _defaultInputFilterSelector; + /** + * Gets the selector identifying which input elements to filter from drag events. + * @method getInputFilterSelector + * @return {String} Current input filter selector. + */ + this.getInputFilterSelector = function() { return inputFilterSelector; }; + + /** + * Sets the selector identifying which input elements to filter from drag events. + * @method setInputFilterSelector + * @param {String} selector Input filter selector to set. + * @return {Katavorio} Current instance; method may be chained. + */ + this.setInputFilterSelector = function(selector) { + inputFilterSelector = selector; + return this; + }; + + /** + * Either makes the given element draggable, or identifies it as an element inside which some identified list + * of elements may be draggable. + * @param el + * @param params + * @returns {Array} + */ + this.draggable = function(el, params) { + var o = []; + _each(el, function (_el) { + _el = _gel(_el); + if (_el != null) { + if (_el._katavorioDrag == null) { + var p = _prepareParams(params); + _el._katavorioDrag = new Drag(_el, p, _css, _scope); + _reg(_el._katavorioDrag, this._dragsByScope); + o.push(_el._katavorioDrag); + katavorioParams.addClass(_el, p.selector ? _css.delegatedDraggable : _css.draggable); + } + else { + _mistletoe(_el._katavorioDrag, params); + } + } + }.bind(this)); + return o; + }; + + this.droppable = function(el, params) { + var o = []; + _each(el, function(_el) { + _el = _gel(_el); + if (_el != null) { + var drop = new Drop(_el, _prepareParams(params), _css, _scope); + _el._katavorioDrop = _el._katavorioDrop || []; + _el._katavorioDrop.push(drop); + _reg(drop, this._dropsByScope); + o.push(drop); + katavorioParams.addClass(_el, _css.droppable); + } + }.bind(this)); + return o; + }; + + /** + * @name Katavorio#select + * @function + * @desc Adds an element to the current selection (for multiple node drag) + * @param {Element|String} DOM element - or id of the element - to add. + */ + this.select = function(el) { + _each(el, function() { + var _el = _gel(this); + if (_el && _el._katavorioDrag) { + if (!_selectionMap[_el._katavorio]) { + _selection.push(_el._katavorioDrag); + _selectionMap[_el._katavorio] = [ _el, _selection.length - 1 ]; + katavorioParams.addClass(_el, _css.selected); + } + } + }); + return this; + }; + + /** + * @name Katavorio#deselect + * @function + * @desc Removes an element from the current selection (for multiple node drag) + * @param {Element|String} DOM element - or id of the element - to remove. + */ + this.deselect = function(el) { + _each(el, function() { + var _el = _gel(this); + if (_el && _el._katavorio) { + var e = _selectionMap[_el._katavorio]; + if (e) { + var _s = []; + for (var i = 0; i < _selection.length; i++) + if (_selection[i].el !== _el) _s.push(_selection[i]); + _selection = _s; + delete _selectionMap[_el._katavorio]; + katavorioParams.removeClass(_el, _css.selected); + } + } + }); + return this; + }; + + this.deselectAll = function() { + for (var i in _selectionMap) { + var d = _selectionMap[i]; + katavorioParams.removeClass(d[0], _css.selected); + } + + _selection.length = 0; + _selectionMap = {}; + }; + + this.markSelection = function(drag) { + _foreach(_selection, function(e) { e.mark(); }, drag); + }; + + this.markPosses = function(drag) { + if (drag.posses) { + _each(drag.posses, function(p) { + if (drag.posseRoles[p] && _posses[p]) { + _foreach(_posses[p].members, function (d) { + d.mark(); + }, drag); + } + }) + } + }; + + this.unmarkSelection = function(drag, event) { + _foreach(_selection, function(e) { e.unmark(event); }, drag); + }; + + this.unmarkPosses = function(drag, event) { + if (drag.posses) { + _each(drag.posses, function(p) { + if (drag.posseRoles[p] && _posses[p]) { + _foreach(_posses[p].members, function (d) { + d.unmark(event, true); + }, drag); + } + }); + } + }; + + this.getSelection = function() { return _selection.slice(0); }; + + this.updateSelection = function(dx, dy, drag) { + _foreach(_selection, function(e) { e.moveBy(dx, dy); }, drag); + }; + + var _posseAction = function(fn, drag) { + if (drag.posses) { + _each(drag.posses, function(p) { + if (drag.posseRoles[p] && _posses[p]) { + _foreach(_posses[p].members, function (e) { + fn(e); + }, drag); + } + }); + } + }; + + this.updatePosses = function(dx, dy, drag) { + _posseAction(function(e) { e.moveBy(dx, dy); }, drag); + }; + + this.notifyPosseDragStop = function(drag, evt) { + _posseAction(function(e) { e.stop(evt, true); }, drag); + }; + + this.notifySelectionDragStop = function(drag, evt) { + _foreach(_selection, function(e) { e.stop(evt, true); }, drag); + }; + + this.notifySelectionDragStart = function(drag, evt) { + _foreach(_selection, function(e) { e.notifyStart(evt);}, drag); + }; + + this.setZoom = function(z) { _zoom = z; }; + this.getZoom = function() { return _zoom; }; + + // does the work of changing scopes + var _scopeManip = function(kObj, scopes, map, fn) { + _each(kObj, function(_kObj) { + _unreg(_kObj, map); // deregister existing scopes + _kObj[fn](scopes); // set scopes + _reg(_kObj, map); // register new ones + }); + }; + + _each([ "set", "add", "remove", "toggle"], function(v) { + this[v + "Scope"] = function(el, scopes) { + _scopeManip(el._katavorioDrag, scopes, this._dragsByScope, v + "Scope"); + _scopeManip(el._katavorioDrop, scopes, this._dropsByScope, v + "Scope"); + }.bind(this); + this[v + "DragScope"] = function(el, scopes) { + _scopeManip(el.constructor === Drag ? el : el._katavorioDrag, scopes, this._dragsByScope, v + "Scope"); + }.bind(this); + this[v + "DropScope"] = function(el, scopes) { + _scopeManip(el.constructor === Drop ? el : el._katavorioDrop, scopes, this._dropsByScope, v + "Scope"); + }.bind(this); + }.bind(this)); + + this.snapToGrid = function(x, y) { + for (var s in this._dragsByScope) { + _foreach(this._dragsByScope[s], function(d) { d.snap(x, y); }); + } + }; + + this.getDragsForScope = function(s) { return this._dragsByScope[s]; }; + this.getDropsForScope = function(s) { return this._dropsByScope[s]; }; + + var _destroy = function(el, type, map) { + el = _gel(el); + if (el[type]) { + + // remove from selection, if present. + var selIdx = _selection.indexOf(el[type]); + if (selIdx >= 0) { + _selection.splice(selIdx, 1); + } + + if (_unreg(el[type], map)) { + _each(el[type], function(kObj) { kObj.destroy() }); + } + + delete el[type]; + } + }; + + var _removeListener = function(el, type, evt, fn) { + el = _gel(el); + if (el[type]) { + el[type].off(evt, fn); + } + }; + + this.elementRemoved = function(el) { + this.destroyDraggable(el); + this.destroyDroppable(el); + }; + + /** + * Either completely remove drag functionality from the given element, or remove a specific event handler. If you + * call this method with a single argument - the element - all drag functionality is removed from it. Otherwise, if + * you provide an event name and listener function, this function is de-registered (if found). + * @param el Element to update + * @param {string} [evt] Optional event name to unsubscribe + * @param {Function} [fn] Optional function to unsubscribe + */ + this.destroyDraggable = function(el, evt, fn) { + if (arguments.length === 1) { + _destroy(el, "_katavorioDrag", this._dragsByScope); + } else { + _removeListener(el, "_katavorioDrag", evt, fn); + } + }; + + /** + * Either completely remove drop functionality from the given element, or remove a specific event handler. If you + * call this method with a single argument - the element - all drop functionality is removed from it. Otherwise, if + * you provide an event name and listener function, this function is de-registered (if found). + * @param el Element to update + * @param {string} [evt] Optional event name to unsubscribe + * @param {Function} [fn] Optional function to unsubscribe + */ + this.destroyDroppable = function(el, evt, fn) { + if (arguments.length === 1) { + _destroy(el, "_katavorioDrop", this._dropsByScope); + } else { + _removeListener(el, "_katavorioDrop", evt, fn); + } + }; + + this.reset = function() { + this._dragsByScope = {}; + this._dropsByScope = {}; + _selection = []; + _selectionMap = {}; + _posses = {}; + }; + + // ----- groups + var _posses = {}; + + var _processOneSpec = function(el, _spec, dontAddExisting) { + var posseId = _isString(_spec) ? _spec : _spec.id; + var active = _isString(_spec) ? true : _spec.active !== false; + var posse = _posses[posseId] || (function() { + var g = {name:posseId, members:[]}; + _posses[posseId] = g; + return g; + })(); + _each(el, function(_el) { + if (_el._katavorioDrag) { + + if (dontAddExisting && _el._katavorioDrag.posseRoles[posse.name] != null) return; + + _suggest(posse.members, _el._katavorioDrag); + _suggest(_el._katavorioDrag.posses, posse.name); + _el._katavorioDrag.posseRoles[posse.name] = active; + } + }); + return posse; + }; + + /** + * Add the given element to the posse with the given id, creating the group if it at first does not exist. + * @method addToPosse + * @param {Element} el Element to add. + * @param {String...|Object...} spec Variable args parameters. Each argument can be a either a String, indicating + * the ID of a Posse to which the element should be added as an active participant, or an Object containing + * `{ id:"posseId", active:false/true}`. In the latter case, if `active` is not provided it is assumed to be + * true. + * @returns {Posse|Posse[]} The Posse(s) to which the element(s) was/were added. + */ + this.addToPosse = function(el, spec) { + + var posses = []; + + for (var i = 1; i < arguments.length; i++) { + posses.push(_processOneSpec(el, arguments[i])); + } + + return posses.length === 1 ? posses[0] : posses; + }; + + /** + * Sets the posse(s) for the element with the given id, creating those that do not yet exist, and removing from + * the element any current Posses that are not specified by this method call. This method will not change the + * active/passive state if it is given a posse in which the element is already a member. + * @method setPosse + * @param {Element} el Element to set posse(s) on. + * @param {String...|Object...} spec Variable args parameters. Each argument can be a either a String, indicating + * the ID of a Posse to which the element should be added as an active participant, or an Object containing + * `{ id:"posseId", active:false/true}`. In the latter case, if `active` is not provided it is assumed to be + * true. + * @returns {Posse|Posse[]} The Posse(s) to which the element(s) now belongs. + */ + this.setPosse = function(el, spec) { + + var posses = []; + + for (var i = 1; i < arguments.length; i++) { + posses.push(_processOneSpec(el, arguments[i], true).name); + } + + _each(el, function(_el) { + if (_el._katavorioDrag) { + var diff = _difference(_el._katavorioDrag.posses, posses); + var p = []; + Array.prototype.push.apply(p, _el._katavorioDrag.posses); + for (var i = 0; i < diff.length; i++) { + this.removeFromPosse(_el, diff[i]); + } + } + }.bind(this)); + + return posses.length === 1 ? posses[0] : posses; + }; + + /** + * Remove the given element from the given posse(s). + * @method removeFromPosse + * @param {Element} el Element to remove. + * @param {String...} posseId Varargs parameter: one value for each posse to remove the element from. + */ + this.removeFromPosse = function(el, posseId) { + if (arguments.length < 2) throw new TypeError("No posse id provided for remove operation"); + for(var i = 1; i < arguments.length; i++) { + posseId = arguments[i]; + _each(el, function (_el) { + if (_el._katavorioDrag && _el._katavorioDrag.posses) { + var d = _el._katavorioDrag; + _each(posseId, function (p) { + _vanquish(_posses[p].members, d); + _vanquish(d.posses, p); + delete d.posseRoles[p]; + }); + } + }); + } + }; + + /** + * Remove the given element from all Posses to which it belongs. + * @method removeFromAllPosses + * @param {Element|Element[]} el Element to remove from Posses. + */ + this.removeFromAllPosses = function(el) { + _each(el, function(_el) { + if (_el._katavorioDrag && _el._katavorioDrag.posses) { + var d = _el._katavorioDrag; + _each(d.posses, function(p) { + _vanquish(_posses[p].members, d); + }); + d.posses.length = 0; + d.posseRoles = {}; + } + }); + }; + + /** + * Changes the participation state for the element in the Posse with the given ID. + * @param {Element|Element[]} el Element(s) to change state for. + * @param {String} posseId ID of the Posse to change element state for. + * @param {Boolean} state True to make active, false to make passive. + */ + this.setPosseState = function(el, posseId, state) { + var posse = _posses[posseId]; + if (posse) { + _each(el, function(_el) { + if (_el._katavorioDrag && _el._katavorioDrag.posses) { + _el._katavorioDrag.posseRoles[posse.name] = state; + } + }); + } + }; + + }; + + root.Katavorio.version = "1.0.0"; + + if (typeof exports !== "undefined") { + exports.Katavorio = root.Katavorio; + } + +}).call(typeof window !== 'undefined' ? window : this); + + +(function() { + + var root = this; + root.jsPlumbUtil = root.jsPlumbUtil || {}; + var jsPlumbUtil = root.jsPlumbUtil; + + if (typeof exports !=='undefined') { exports.jsPlumbUtil = jsPlumbUtil;} + + + /** + * Tests if the given object is an Array. + * @param a + */ + function isArray(a) { + return Object.prototype.toString.call(a) === "[object Array]"; + } + jsPlumbUtil.isArray = isArray; + /** + * Tests if the given object is a Number. + * @param n + */ + function isNumber(n) { + return Object.prototype.toString.call(n) === "[object Number]"; + } + jsPlumbUtil.isNumber = isNumber; + function isString(s) { + return typeof s === "string"; + } + jsPlumbUtil.isString = isString; + function isBoolean(s) { + return typeof s === "boolean"; + } + jsPlumbUtil.isBoolean = isBoolean; + function isNull(s) { + return s == null; + } + jsPlumbUtil.isNull = isNull; + function isObject(o) { + return o == null ? false : Object.prototype.toString.call(o) === "[object Object]"; + } + jsPlumbUtil.isObject = isObject; + function isDate(o) { + return Object.prototype.toString.call(o) === "[object Date]"; + } + jsPlumbUtil.isDate = isDate; + function isFunction(o) { + return Object.prototype.toString.call(o) === "[object Function]"; + } + jsPlumbUtil.isFunction = isFunction; + function isNamedFunction(o) { + return isFunction(o) && o.name != null && o.name.length > 0; + } + jsPlumbUtil.isNamedFunction = isNamedFunction; + function isEmpty(o) { + for (var i in o) { + if (o.hasOwnProperty(i)) { + return false; + } + } + return true; + } + jsPlumbUtil.isEmpty = isEmpty; + function clone(a) { + if (isString(a)) { + return "" + a; + } + else if (isBoolean(a)) { + return !!a; + } + else if (isDate(a)) { + return new Date(a.getTime()); + } + else if (isFunction(a)) { + return a; + } + else if (isArray(a)) { + var b = []; + for (var i = 0; i < a.length; i++) { + b.push(clone(a[i])); + } + return b; + } + else if (isObject(a)) { + var c = {}; + for (var j in a) { + c[j] = clone(a[j]); + } + return c; + } + else { + return a; + } + } + jsPlumbUtil.clone = clone; + function merge(a, b, collations, overwrites) { + // first change the collations array - if present - into a lookup table, because its faster. + var cMap = {}, ar, i, oMap = {}; + collations = collations || []; + overwrites = overwrites || []; + for (i = 0; i < collations.length; i++) { + cMap[collations[i]] = true; + } + for (i = 0; i < overwrites.length; i++) { + oMap[overwrites[i]] = true; + } + var c = clone(a); + for (i in b) { + if (c[i] == null || oMap[i]) { + c[i] = b[i]; + } + else if (isString(b[i]) || isBoolean(b[i])) { + if (!cMap[i]) { + c[i] = b[i]; // if we dont want to collate, just copy it in. + } + else { + ar = []; + // if c's object is also an array we can keep its values. + ar.push.apply(ar, isArray(c[i]) ? c[i] : [c[i]]); + ar.push.apply(ar, isBoolean(b[i]) ? b[i] : [b[i]]); + c[i] = ar; + } + } + else { + if (isArray(b[i])) { + ar = []; + // if c's object is also an array we can keep its values. + if (isArray(c[i])) { + ar.push.apply(ar, c[i]); + } + ar.push.apply(ar, b[i]); + c[i] = ar; + } + else if (isObject(b[i])) { + // overwrite c's value with an object if it is not already one. + if (!isObject(c[i])) { + c[i] = {}; + } + for (var j in b[i]) { + c[i][j] = b[i][j]; + } + } + } + } + return c; + } + jsPlumbUtil.merge = merge; + function replace(inObj, path, value) { + if (inObj == null) { + return; + } + var q = inObj, t = q; + path.replace(/([^\.])+/g, function (term, lc, pos, str) { + var array = term.match(/([^\[0-9]+){1}(\[)([0-9+])/), last = pos + term.length >= str.length, _getArray = function () { + return t[array[1]] || (function () { + t[array[1]] = []; + return t[array[1]]; + })(); + }; + if (last) { + // set term = value on current t, creating term as array if necessary. + if (array) { + _getArray()[array[3]] = value; + } + else { + t[term] = value; + } + } + else { + // set to current t[term], creating t[term] if necessary. + if (array) { + var a_1 = _getArray(); + t = a_1[array[3]] || (function () { + a_1[array[3]] = {}; + return a_1[array[3]]; + })(); + } + else { + t = t[term] || (function () { + t[term] = {}; + return t[term]; + })(); + } + } + return ""; + }); + return inObj; + } + jsPlumbUtil.replace = replace; + // + // chain a list of functions, supplied by [ object, method name, args ], and return on the first + // one that returns the failValue. if none return the failValue, return the successValue. + // + function functionChain(successValue, failValue, fns) { + for (var i = 0; i < fns.length; i++) { + var o = fns[i][0][fns[i][1]].apply(fns[i][0], fns[i][2]); + if (o === failValue) { + return o; + } + } + return successValue; + } + jsPlumbUtil.functionChain = functionChain; + /** + * + * Take the given model and expand out any parameters. 'functionPrefix' is optional, and if present, helps jsplumb figure out what to do if a value is a Function. + * if you do not provide it (and doNotExpandFunctions is null, or false), jsplumb will run the given values through any functions it finds, and use the function's + * output as the value in the result. if you do provide the prefix, only functions that are named and have this prefix + * will be executed; other functions will be passed as values to the output. + * + * @param model + * @param values + * @param functionPrefix + * @param doNotExpandFunctions + * @returns {any} + */ + function populate(model, values, functionPrefix, doNotExpandFunctions) { + // for a string, see if it has parameter matches, and if so, try to make the substitutions. + var getValue = function (fromString) { + var matches = fromString.match(/(\${.*?})/g); + if (matches != null) { + for (var i = 0; i < matches.length; i++) { + var val = values[matches[i].substring(2, matches[i].length - 1)] || ""; + if (val != null) { + fromString = fromString.replace(matches[i], val); + } + } + } + return fromString; + }; + // process one entry. + var _one = function (d) { + if (d != null) { + if (isString(d)) { + return getValue(d); + } + else if (isFunction(d) && !doNotExpandFunctions && (functionPrefix == null || (d.name || "").indexOf(functionPrefix) === 0)) { + return d(values); + } + else if (isArray(d)) { + var r = []; + for (var i = 0; i < d.length; i++) { + r.push(_one(d[i])); + } + return r; + } + else if (isObject(d)) { + var s = {}; + for (var j in d) { + s[j] = _one(d[j]); + } + return s; + } + else { + return d; + } + } + }; + return _one(model); + } + jsPlumbUtil.populate = populate; + /** + * Find the index of a given object in an array. + * @param a The array to search + * @param f The function to run on each element. Return true if the element matches. + * @returns {number} -1 if not found, otherwise the index in the array. + */ + function findWithFunction(a, f) { + if (a) { + for (var i = 0; i < a.length; i++) { + if (f(a[i])) { + return i; + } + } + } + return -1; + } + jsPlumbUtil.findWithFunction = findWithFunction; + /** + * Remove some element from an array by matching each element in the array against some predicate function. Note that this + * is an in-place removal; the array is altered. + * @param a The array to search + * @param f The function to run on each element. Return true if the element matches. + * @returns {boolean} true if removed, false otherwise. + */ + function removeWithFunction(a, f) { + var idx = findWithFunction(a, f); + if (idx > -1) { + a.splice(idx, 1); + } + return idx !== -1; + } + jsPlumbUtil.removeWithFunction = removeWithFunction; + /** + * Remove some element from an array by simple lookup in the array for the given element. Note that this + * is an in-place removal; the array is altered. + * @param l The array to search + * @param v The value to remove. + * @returns {boolean} true if removed, false otherwise. + */ + function remove(l, v) { + var idx = l.indexOf(v); + if (idx > -1) { + l.splice(idx, 1); + } + return idx !== -1; + } + jsPlumbUtil.remove = remove; + /** + * Add some element to the given array, unless it is determined that it is already in the array. + * @param list The array to add the element to. + * @param item The item to add. + * @param hashFunction A function to use to determine if the given item already exists in the array. + */ + function addWithFunction(list, item, hashFunction) { + if (findWithFunction(list, hashFunction) === -1) { + list.push(item); + } + } + jsPlumbUtil.addWithFunction = addWithFunction; + /** + * Add some element to a list that is contained in a map of lists. + * @param map The map of [ key -> list ] entries + * @param key The name of the list to insert into + * @param value The value to insert + * @param insertAtStart Whether or not to insert at the start; defaults to false. + */ + function addToList(map, key, value, insertAtStart) { + var l = map[key]; + if (l == null) { + l = []; + map[key] = l; + } + l[insertAtStart ? "unshift" : "push"](value); + return l; + } + jsPlumbUtil.addToList = addToList; + /** + * Add an item to a list, unless it is already in the list. The test for pre-existence is a simple list lookup. + * If you want to do something more complex, perhaps #addWithFunction might help. + * @param list List to add the item to + * @param item Item to add + * @param insertAtHead Whether or not to insert at the start; defaults to false. + */ + function suggest(list, item, insertAtHead) { + if (list.indexOf(item) === -1) { + if (insertAtHead) { + list.unshift(item); + } + else { + list.push(item); + } + return true; + } + return false; + } + jsPlumbUtil.suggest = suggest; + /** + * Extends the given obj (which can be an array) with the given constructor function, prototype functions, and class members, any of which may be null. + * @param child + * @param parent + * @param _protoFn + */ + function extend(child, parent, _protoFn) { + var i; + parent = isArray(parent) ? parent : [parent]; + var _copyProtoChain = function (focus) { + var proto = focus.__proto__; + while (proto != null) { + if (proto.prototype != null) { + for (var j in proto.prototype) { + if (proto.prototype.hasOwnProperty(j) && !child.prototype.hasOwnProperty(j)) { + child.prototype[j] = proto.prototype[j]; + } + } + proto = proto.prototype.__proto__; + } + else { + proto = null; + } + } + }; + for (i = 0; i < parent.length; i++) { + for (var j in parent[i].prototype) { + if (parent[i].prototype.hasOwnProperty(j) && !child.prototype.hasOwnProperty(j)) { + child.prototype[j] = parent[i].prototype[j]; + } + } + _copyProtoChain(parent[i]); + } + var _makeFn = function (name, protoFn) { + return function () { + for (i = 0; i < parent.length; i++) { + if (parent[i].prototype[name]) { + parent[i].prototype[name].apply(this, arguments); + } + } + return protoFn.apply(this, arguments); + }; + }; + var _oneSet = function (fns) { + for (var k in fns) { + child.prototype[k] = _makeFn(k, fns[k]); + } + }; + if (arguments.length > 2) { + for (i = 2; i < arguments.length; i++) { + _oneSet(arguments[i]); + } + } + return child; + } + jsPlumbUtil.extend = extend; + /** + * Generate a UUID. + */ + function uuid() { + return ('xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + })); + } + jsPlumbUtil.uuid = uuid; + /** + * Trim a string. + * @param s String to trim + * @returns the String with leading and trailing whitespace removed. + */ + function fastTrim(s) { + if (s == null) { + return null; + } + var str = s.replace(/^\s\s*/, ''), ws = /\s/, i = str.length; + while (ws.test(str.charAt(--i))) { + } + return str.slice(0, i + 1); + } + jsPlumbUtil.fastTrim = fastTrim; + function each(obj, fn) { + obj = obj.length == null || typeof obj === "string" ? [obj] : obj; + for (var i = 0; i < obj.length; i++) { + fn(obj[i]); + } + } + jsPlumbUtil.each = each; + function map(obj, fn) { + var o = []; + for (var i = 0; i < obj.length; i++) { + o.push(fn(obj[i])); + } + return o; + } + jsPlumbUtil.map = map; + function mergeWithParents(type, map, parentAttribute) { + parentAttribute = parentAttribute || "parent"; + var _def = function (id) { + return id ? map[id] : null; + }; + var _parent = function (def) { + return def ? _def(def[parentAttribute]) : null; + }; + var _one = function (parent, def) { + if (parent == null) { + return def; + } + else { + var overrides = ["anchor", "anchors", "cssClass", "connector", "paintStyle", "hoverPaintStyle", "endpoint", "endpoints"]; + if (def.mergeStrategy === "override") { + Array.prototype.push.apply(overrides, ["events", "overlays"]); + } + var d_1 = merge(parent, def, [], overrides); + return _one(_parent(parent), d_1); + } + }; + var _getDef = function (t) { + if (t == null) { + return {}; + } + if (typeof t === "string") { + return _def(t); + } + else if (t.length) { + var done = false, i = 0, _dd = void 0; + while (!done && i < t.length) { + _dd = _getDef(t[i]); + if (_dd) { + done = true; + } + else { + i++; + } + } + return _dd; + } + }; + var d = _getDef(type); + if (d) { + return _one(_parent(d), d); + } + else { + return {}; + } + } + jsPlumbUtil.mergeWithParents = mergeWithParents; + jsPlumbUtil.logEnabled = true; + function log() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + if (jsPlumbUtil.logEnabled && typeof console !== "undefined") { + try { + var msg = arguments[arguments.length - 1]; + console.log(msg); + } + catch (e) { + } + } + } + jsPlumbUtil.log = log; + /** + * Wraps one function with another, creating a placeholder for the + * wrapped function if it was null. this is used to wrap the various + * drag/drop event functions - to allow jsPlumb to be notified of + * important lifecycle events without imposing itself on the user's + * drag/drop functionality. + * @method jsPlumbUtil.wrap + * @param {Function} wrappedFunction original function to wrap; may be null. + * @param {Function} newFunction function to wrap the original with. + * @param {Object} [returnOnThisValue] Optional. Indicates that the wrappedFunction should + * not be executed if the newFunction returns a value matching 'returnOnThisValue'. + * note that this is a simple comparison and only works for primitives right now. + */ + function wrap(wrappedFunction, newFunction, returnOnThisValue) { + return function () { + var r = null; + try { + if (newFunction != null) { + r = newFunction.apply(this, arguments); + } + } + catch (e) { + log("jsPlumb function failed : " + e); + } + if ((wrappedFunction != null) && (returnOnThisValue == null || (r !== returnOnThisValue))) { + try { + r = wrappedFunction.apply(this, arguments); + } + catch (e) { + log("wrapped function failed : " + e); + } + } + return r; + }; + } + jsPlumbUtil.wrap = wrap; + var EventGenerator = /** @class */ (function () { + function EventGenerator() { + var _this = this; + this._listeners = {}; + this.eventsSuspended = false; + this.tick = false; + // this is a list of events that should re-throw any errors that occur during their dispatch. + this.eventsToDieOn = { "ready": true }; + this.queue = []; + this.bind = function (event, listener, insertAtStart) { + var _one = function (evt) { + addToList(_this._listeners, evt, listener, insertAtStart); + listener.__jsPlumb = listener.__jsPlumb || {}; + listener.__jsPlumb[uuid()] = evt; + }; + if (typeof event === "string") { + _one(event); + } + else if (event.length != null) { + for (var i = 0; i < event.length; i++) { + _one(event[i]); + } + } + return _this; + }; + this.fire = function (event, value, originalEvent) { + if (!this.tick) { + this.tick = true; + if (!this.eventsSuspended && this._listeners[event]) { + var l = this._listeners[event].length, i = 0, _gone = false, ret = null; + if (!this.shouldFireEvent || this.shouldFireEvent(event, value, originalEvent)) { + while (!_gone && i < l && ret !== false) { + // doing it this way rather than catching and then possibly re-throwing means that an error propagated by this + // method will have the whole call stack available in the debugger. + if (this.eventsToDieOn[event]) { + this._listeners[event][i].apply(this, [value, originalEvent]); + } + else { + try { + ret = this._listeners[event][i].apply(this, [value, originalEvent]); + } + catch (e) { + log("jsPlumb: fire failed for event " + event + " : " + e); + } + } + i++; + if (this._listeners == null || this._listeners[event] == null) { + _gone = true; + } + } + } + } + this.tick = false; + this._drain(); + } + else { + this.queue.unshift(arguments); + } + return this; + }; + this._drain = function () { + var n = _this.queue.pop(); + if (n) { + _this.fire.apply(_this, n); + } + }; + this.unbind = function (eventOrListener, listener) { + if (arguments.length === 0) { + this._listeners = {}; + } + else if (arguments.length === 1) { + if (typeof eventOrListener === "string") { + delete this._listeners[eventOrListener]; + } + else if (eventOrListener.__jsPlumb) { + var evt = void 0; + for (var i in eventOrListener.__jsPlumb) { + evt = eventOrListener.__jsPlumb[i]; + remove(this._listeners[evt] || [], eventOrListener); + } + } + } + else if (arguments.length === 2) { + remove(this._listeners[eventOrListener] || [], listener); + } + return this; + }; + this.getListener = function (forEvent) { + return _this._listeners[forEvent]; + }; + this.setSuspendEvents = function (val) { + _this.eventsSuspended = val; + }; + this.isSuspendEvents = function () { + return _this.eventsSuspended; + }; + this.silently = function (fn) { + _this.setSuspendEvents(true); + try { + fn(); + } + catch (e) { + log("Cannot execute silent function " + e); + } + _this.setSuspendEvents(false); + }; + this.cleanupListeners = function () { + for (var i in _this._listeners) { + _this._listeners[i] = null; + } + }; + } + return EventGenerator; + }()); + jsPlumbUtil.EventGenerator = EventGenerator; + +}).call(typeof window !== 'undefined' ? window : this); +/* + * This file contains utility functions that run in browsers only. + * + * Copyright (c) 2010 - 2018 jsPlumb (hello@jsplumbtoolkit.com) + * + * https://jsplumbtoolkit.com + * https://github.com/jsplumb/jsplumb + * + * Dual licensed under the MIT and GPL2 licenses. + */ +;(function() { + + "use strict"; + + var root = this; + + root.jsPlumbUtil.matchesSelector = function(el, selector, ctx) { + ctx = ctx || el.parentNode; + var possibles = ctx.querySelectorAll(selector); + for (var i = 0; i < possibles.length; i++) { + if (possibles[i] === el) { + return true; + } + } + return false; + }; + + root.jsPlumbUtil.consume = function(e, doNotPreventDefault) { + if (e.stopPropagation) { + e.stopPropagation(); + } + else { + e.returnValue = false; + } + + if (!doNotPreventDefault && e.preventDefault){ + e.preventDefault(); + } + }; + + /* + * Function: sizeElement + * Helper to size and position an element. You would typically use + * this when writing your own Connector or Endpoint implementation. + * + * Parameters: + * x - [int] x position for the element origin + * y - [int] y position for the element origin + * w - [int] width of the element + * h - [int] height of the element + * + */ + root.jsPlumbUtil.sizeElement = function(el, x, y, w, h) { + if (el) { + el.style.height = h + "px"; + el.height = h; + el.style.width = w + "px"; + el.width = w; + el.style.left = x + "px"; + el.style.top = y + "px"; + } + }; + +}).call(typeof window !== 'undefined' ? window : this); + +;(function() { + + var DEFAULT_OPTIONS = { + deriveAnchor:function(edge, index, ep, conn) { + return { + top:["TopRight", "TopLeft"], + bottom:["BottomRight", "BottomLeft"] + }[edge][index]; + } + }; + + var root = this; + + var ListManager = function(jsPlumbInstance) { + + this.count = 0; + this.instance = jsPlumbInstance; + this.lists = {}; + + this.instance.addList = function(el, options) { + return this.listManager.addList(el, options); + }; + + this.instance.removeList = function(el) { + this.listManager.removeList(el); + }; + + this.instance.bind("manageElement", function(p) { + + //look for [jtk-scrollable-list] elements and attach scroll listeners if necessary + var scrollableLists = this.instance.getSelector(p.el, "[jtk-scrollable-list]"); + for (var i = 0; i < scrollableLists.length; i++) { + this.addList(scrollableLists[i]); + } + + }.bind(this)); + + this.instance.bind("unmanageElement", function(p) { + this.removeList(p.el); + }); + + + this.instance.bind("connection", function(c, evt) { + if (evt == null) { + // not added by mouse. look for an ancestor of the source and/or target element that is a scrollable list, and run + // its scroll method. + this._maybeUpdateParentList(c.source); + this._maybeUpdateParentList(c.target); + } + }.bind(this)); + }; + + root.jsPlumbListManager = ListManager; + + ListManager.prototype = { + + addList : function(el, options) { + var dp = this.instance.extend({}, DEFAULT_OPTIONS); + options = this.instance.extend(dp, options || {}); + var id = [this.instance.getInstanceIndex(), this.count++].join("_"); + this.lists[id] = new List(this.instance, el, options, id); + }, + + removeList:function(el) { + var list = this.lists[el._jsPlumbList]; + if (list) { + list.destroy(); + delete this.lists[el._jsPlumbList]; + } + }, + + _maybeUpdateParentList:function (el) { + var parent = el.parentNode, container = this.instance.getContainer(); + while(parent != null && parent !== container) { + if (parent._jsPlumbList != null && this.lists[parent._jsPlumbList] != null) { + parent._jsPlumbScrollHandler(); + return + } + parent = parent.parentNode; + } + } + + + }; + + var List = function(instance, el, options, id) { + + el["_jsPlumbList"] = id; + + // + // Derive an anchor to use for the current situation. In contrast to the way we derive an endpoint, here we use `anchor` from the options, if present, as + // our first choice, and then `deriveAnchor` as our next choice. There is a default `deriveAnchor` implementation that uses TopRight/TopLeft for top and + // BottomRight/BottomLeft for bottom. + // + // edge - "top" or "bottom" + // index - 0 when endpoint is connection source, 1 when endpoint is connection target + // ep - the endpoint that is being proxied + // conn - the connection that is being proxied + // + function deriveAnchor(edge, index, ep, conn) { + return options.anchor ? options.anchor : options.deriveAnchor(edge, index, ep, conn); + } + + // + // Derive an endpoint to use for the current situation. We'll use a `deriveEndpoint` function passed in to the options as our first choice, + // followed by `endpoint` (an endpoint spec) from the options, and failing either of those we just use the `type` of the endpoint that is being proxied. + // + // edge - "top" or "bottom" + // index - 0 when endpoint is connection source, 1 when endpoint is connection target + // endpoint - the endpoint that is being proxied + // connection - the connection that is being proxied + // + function deriveEndpoint(edge, index, ep, conn) { + return options.deriveEndpoint ? options.deriveEndpoint(edge, index, ep, conn) : options.endpoint ? options.endpoint : ep.type; + } + + // + // look for a parent of the given scrollable list that is draggable, and then update the child offsets for it. this should not + // be necessary in the delegated drag stuff from the upcoming 3.0.0 release. + // + function _maybeUpdateDraggable(el) { + var parent = el.parentNode, container = instance.getContainer(); + while(parent != null && parent !== container) { + if (instance.hasClass(parent, "jtk-managed")) { + instance.recalculateOffsets(parent); + return + } + parent = parent.parentNode; + } + } + + var scrollHandler = function(e) { + + var children = instance.getSelector(el, ".jtk-managed"); + var elId = instance.getId(el); + + for (var i = 0; i < children.length; i++) { + + if (children[i].offsetTop < el.scrollTop) { + if (!children[i]._jsPlumbProxies) { + children[i]._jsPlumbProxies = children[i]._jsPlumbProxies || []; + instance.select({source: children[i]}).each(function (c) { + + + instance.proxyConnection(c, 0, el, elId, function () { + return deriveEndpoint("top", 0, c.endpoints[0], c); + }, function () { + return deriveAnchor("top", 0, c.endpoints[0], c); + }); + children[i]._jsPlumbProxies.push([c, 0]); + }); + + instance.select({target: children[i]}).each(function (c) { + instance.proxyConnection(c, 1, el, elId, function () { + return deriveEndpoint("top", 1, c.endpoints[1], c); + }, function () { + return deriveAnchor("top", 1, c.endpoints[1], c); + }); + children[i]._jsPlumbProxies.push([c, 1]); + }); + } + } + // + else if (children[i].offsetTop > el.scrollTop + el.offsetHeight) { + if (!children[i]._jsPlumbProxies) { + children[i]._jsPlumbProxies = children[i]._jsPlumbProxies || []; + + instance.select({source: children[i]}).each(function (c) { + instance.proxyConnection(c, 0, el, elId, function () { + return deriveEndpoint("bottom", 0, c.endpoints[0], c); + }, function () { + return deriveAnchor("bottom", 0, c.endpoints[0], c); + }); + children[i]._jsPlumbProxies.push([c, 0]); + }); + + instance.select({target: children[i]}).each(function (c) { + instance.proxyConnection(c, 1, el, elId, function () { + return deriveEndpoint("bottom", 1, c.endpoints[1], c); + }, function () { + return deriveAnchor("bottom", 1, c.endpoints[1], c); + }); + children[i]._jsPlumbProxies.push([c, 1]); + }); + } + } else if (children[i]._jsPlumbProxies) { + for (var j = 0; j < children[i]._jsPlumbProxies.length; j++) { + instance.unproxyConnection(children[i]._jsPlumbProxies[j][0], children[i]._jsPlumbProxies[j][1], elId); + } + + delete children[i]._jsPlumbProxies; + } + + instance.revalidate(children[i]); + } + + _maybeUpdateDraggable(el); + }; + + instance.setAttribute(el, "jtk-scrollable-list", "true"); + el._jsPlumbScrollHandler = scrollHandler; + instance.on(el, "scroll", scrollHandler); + scrollHandler(); // run it once; there may be connections already. + + this.destroy = function() { + instance.off(el, "scroll", scrollHandler); + delete el._jsPlumbScrollHandler; + + var children = instance.getSelector(el, ".jtk-managed"); + var elId = instance.getId(el); + + for (var i = 0; i < children.length; i++) { + if (children[i]._jsPlumbProxies) { + for (var j = 0; j < children[i]._jsPlumbProxies.length; j++) { + instance.unproxyConnection(children[i]._jsPlumbProxies[j][0], children[i]._jsPlumbProxies[j][1], elId); + } + + delete children[i]._jsPlumbProxies; + } + } + }; + }; + + +}).call(typeof window !== 'undefined' ? window : this); +/* + * This file contains the core code. + * + * Copyright (c) 2010 - 2018 jsPlumb (hello@jsplumbtoolkit.com) + * + * https://jsplumbtoolkit.com + * https://github.com/jsplumb/jsplumb + * + * Dual licensed under the MIT and GPL2 licenses. + */ +;(function () { + + "use strict"; + + var root = this; + + var _ju = root.jsPlumbUtil, + + /** + * creates a timestamp, using milliseconds since 1970, but as a string. + */ + _timestamp = function () { + return "" + (new Date()).getTime(); + }, + + // helper method to update the hover style whenever it, or paintStyle, changes. + // we use paintStyle as the foundation and merge hoverPaintStyle over the + // top. + _updateHoverStyle = function (component) { + if (component._jsPlumb.paintStyle && component._jsPlumb.hoverPaintStyle) { + var mergedHoverStyle = {}; + jsPlumb.extend(mergedHoverStyle, component._jsPlumb.paintStyle); + jsPlumb.extend(mergedHoverStyle, component._jsPlumb.hoverPaintStyle); + delete component._jsPlumb.hoverPaintStyle; + // we want the fill of paintStyle to override a gradient, if possible. + if (mergedHoverStyle.gradient && component._jsPlumb.paintStyle.fill) { + delete mergedHoverStyle.gradient; + } + component._jsPlumb.hoverPaintStyle = mergedHoverStyle; + } + }, + events = ["tap", "dbltap", "click", "dblclick", "mouseover", "mouseout", "mousemove", "mousedown", "mouseup", "contextmenu" ], + eventFilters = { "mouseout": "mouseleave", "mouseexit": "mouseleave" }, + _updateAttachedElements = function (component, state, timestamp, sourceElement) { + var affectedElements = component.getAttachedElements(); + if (affectedElements) { + for (var i = 0, j = affectedElements.length; i < j; i++) { + if (!sourceElement || sourceElement !== affectedElements[i]) { + affectedElements[i].setHover(state, true, timestamp); // tell the attached elements not to inform their own attached elements. + } + } + } + }, + _splitType = function (t) { + return t == null ? null : t.split(" "); + }, + _mapType = function(map, obj, typeId) { + for (var i in obj) { + map[i] = typeId; + } + }, + _each = function(fn, obj) { + obj = _ju.isArray(obj) || (obj.length != null && !_ju.isString(obj)) ? obj : [ obj ]; + for (var i = 0; i < obj.length; i++) { + try { + fn.apply(obj[i], [ obj[i] ]); + } + catch (e) { + _ju.log(".each iteration failed : " + e); + } + } + }, + _applyTypes = function (component, params, doNotRepaint) { + if (component.getDefaultType) { + var td = component.getTypeDescriptor(), map = {}; + var defType = component.getDefaultType(); + var o = _ju.merge({}, defType); + _mapType(map, defType, "__default"); + for (var i = 0, j = component._jsPlumb.types.length; i < j; i++) { + var tid = component._jsPlumb.types[i]; + if (tid !== "__default") { + var _t = component._jsPlumb.instance.getType(tid, td); + if (_t != null) { + + var overrides = ["anchor", "anchors", "connector", "paintStyle", "hoverPaintStyle", "endpoint", "endpoints", "connectorOverlays", "connectorStyle", "connectorHoverStyle", "endpointStyle", "endpointHoverStyle"]; + var collations = [ ]; + + if (_t.mergeStrategy === "override") { + Array.prototype.push.apply(overrides, ["events", "overlays", "cssClass"]); + } else { + collations.push("cssClass"); + } + + o = _ju.merge(o, _t, collations, overrides); + _mapType(map, _t, tid); + } + } + } + + if (params) { + o = _ju.populate(o, params, "_"); + } + + component.applyType(o, doNotRepaint, map); + if (!doNotRepaint) { + component.repaint(); + } + } + }, + +// ------------------------------ BEGIN jsPlumbUIComponent -------------------------------------------- + + jsPlumbUIComponent = root.jsPlumbUIComponent = function (params) { + + _ju.EventGenerator.apply(this, arguments); + + var self = this, + a = arguments, + idPrefix = self.idPrefix, + id = idPrefix + (new Date()).getTime(); + + this._jsPlumb = { + instance: params._jsPlumb, + parameters: params.parameters || {}, + paintStyle: null, + hoverPaintStyle: null, + paintStyleInUse: null, + hover: false, + beforeDetach: params.beforeDetach, + beforeDrop: params.beforeDrop, + overlayPlacements: [], + hoverClass: params.hoverClass || params._jsPlumb.Defaults.HoverClass, + types: [], + typeCache:{} + }; + + this.cacheTypeItem = function(key, item, typeId) { + this._jsPlumb.typeCache[typeId] = this._jsPlumb.typeCache[typeId] || {}; + this._jsPlumb.typeCache[typeId][key] = item; + }; + this.getCachedTypeItem = function(key, typeId) { + return this._jsPlumb.typeCache[typeId] ? this._jsPlumb.typeCache[typeId][key] : null; + }; + + this.getId = function () { + return id; + }; + +// ----------------------------- default type -------------------------------------------- + + + var o = params.overlays || [], oo = {}; + if (this.defaultOverlayKeys) { + for (var i = 0; i < this.defaultOverlayKeys.length; i++) { + Array.prototype.push.apply(o, this._jsPlumb.instance.Defaults[this.defaultOverlayKeys[i]] || []); + } + + for (i = 0; i < o.length; i++) { + // if a string, convert to object representation so that we can store the typeid on it. + // also assign an id. + var fo = jsPlumb.convertToFullOverlaySpec(o[i]); + oo[fo[1].id] = fo; + } + } + + var _defaultType = { + overlays:oo, + parameters: params.parameters || {}, + scope: params.scope || this._jsPlumb.instance.getDefaultScope() + }; + this.getDefaultType = function() { + return _defaultType; + }; + this.appendToDefaultType = function(obj) { + for (var i in obj) { + _defaultType[i] = obj[i]; + } + }; + +// ----------------------------- end default type -------------------------------------------- + + // all components can generate events + + if (params.events) { + for (var evtName in params.events) { + self.bind(evtName, params.events[evtName]); + } + } + + // all components get this clone function. + // TODO issue 116 showed a problem with this - it seems 'a' that is in + // the clone function's scope is shared by all invocations of it, the classic + // JS closure problem. for now, jsPlumb does a version of this inline where + // it used to call clone. but it would be nice to find some time to look + // further at this. + this.clone = function () { + var o = Object.create(this.constructor.prototype); + this.constructor.apply(o, a); + return o; + }.bind(this); + + // user can supply a beforeDetach callback, which will be executed before a detach + // is performed; returning false prevents the detach. + this.isDetachAllowed = function (connection) { + var r = true; + if (this._jsPlumb.beforeDetach) { + try { + r = this._jsPlumb.beforeDetach(connection); + } + catch (e) { + _ju.log("jsPlumb: beforeDetach callback failed", e); + } + } + return r; + }; + + // user can supply a beforeDrop callback, which will be executed before a dropped + // connection is confirmed. user can return false to reject connection. + this.isDropAllowed = function (sourceId, targetId, scope, connection, dropEndpoint, source, target) { + var r = this._jsPlumb.instance.checkCondition("beforeDrop", { + sourceId: sourceId, + targetId: targetId, + scope: scope, + connection: connection, + dropEndpoint: dropEndpoint, + source: source, target: target + }); + if (this._jsPlumb.beforeDrop) { + try { + r = this._jsPlumb.beforeDrop({ + sourceId: sourceId, + targetId: targetId, + scope: scope, + connection: connection, + dropEndpoint: dropEndpoint, + source: source, target: target + }); + } + catch (e) { + _ju.log("jsPlumb: beforeDrop callback failed", e); + } + } + return r; + }; + + var domListeners = []; + + // sets the component associated with listener events. for instance, an overlay delegates + // its events back to a connector. but if the connector is swapped on the underlying connection, + // then this component must be changed. This is called by setConnector in the Connection class. + this.setListenerComponent = function (c) { + for (var i = 0; i < domListeners.length; i++) { + domListeners[i][3] = c; + } + }; + + + }; + + var _removeTypeCssHelper = function (component, typeIndex) { + var typeId = component._jsPlumb.types[typeIndex], + type = component._jsPlumb.instance.getType(typeId, component.getTypeDescriptor()); + + if (type != null && type.cssClass && component.canvas) { + component._jsPlumb.instance.removeClass(component.canvas, type.cssClass); + } + }; + + _ju.extend(root.jsPlumbUIComponent, _ju.EventGenerator, { + + getParameter: function (name) { + return this._jsPlumb.parameters[name]; + }, + + setParameter: function (name, value) { + this._jsPlumb.parameters[name] = value; + }, + + getParameters: function () { + return this._jsPlumb.parameters; + }, + + setParameters: function (p) { + this._jsPlumb.parameters = p; + }, + + getClass:function() { + return jsPlumb.getClass(this.canvas); + }, + + hasClass:function(clazz) { + return jsPlumb.hasClass(this.canvas, clazz); + }, + + addClass: function (clazz) { + jsPlumb.addClass(this.canvas, clazz); + }, + + removeClass: function (clazz) { + jsPlumb.removeClass(this.canvas, clazz); + }, + + updateClasses: function (classesToAdd, classesToRemove) { + jsPlumb.updateClasses(this.canvas, classesToAdd, classesToRemove); + }, + + setType: function (typeId, params, doNotRepaint) { + this.clearTypes(); + this._jsPlumb.types = _splitType(typeId) || []; + _applyTypes(this, params, doNotRepaint); + }, + + getType: function () { + return this._jsPlumb.types; + }, + + reapplyTypes: function (params, doNotRepaint) { + _applyTypes(this, params, doNotRepaint); + }, + + hasType: function (typeId) { + return this._jsPlumb.types.indexOf(typeId) !== -1; + }, + + addType: function (typeId, params, doNotRepaint) { + var t = _splitType(typeId), _cont = false; + if (t != null) { + for (var i = 0, j = t.length; i < j; i++) { + if (!this.hasType(t[i])) { + this._jsPlumb.types.push(t[i]); + _cont = true; + } + } + if (_cont) { + _applyTypes(this, params, doNotRepaint); + } + } + }, + + removeType: function (typeId, params, doNotRepaint) { + var t = _splitType(typeId), _cont = false, _one = function (tt) { + var idx = this._jsPlumb.types.indexOf(tt); + if (idx !== -1) { + // remove css class if necessary + _removeTypeCssHelper(this, idx); + this._jsPlumb.types.splice(idx, 1); + return true; + } + return false; + }.bind(this); + + if (t != null) { + for (var i = 0, j = t.length; i < j; i++) { + _cont = _one(t[i]) || _cont; + } + if (_cont) { + _applyTypes(this, params, doNotRepaint); + } + } + }, + clearTypes: function (params, doNotRepaint) { + var i = this._jsPlumb.types.length; + for (var j = 0; j < i; j++) { + _removeTypeCssHelper(this, 0); + this._jsPlumb.types.splice(0, 1); + } + _applyTypes(this, params, doNotRepaint); + }, + + toggleType: function (typeId, params, doNotRepaint) { + var t = _splitType(typeId); + if (t != null) { + for (var i = 0, j = t.length; i < j; i++) { + var idx = this._jsPlumb.types.indexOf(t[i]); + if (idx !== -1) { + _removeTypeCssHelper(this, idx); + this._jsPlumb.types.splice(idx, 1); + } + else { + this._jsPlumb.types.push(t[i]); + } + } + + _applyTypes(this, params, doNotRepaint); + } + }, + applyType: function (t, doNotRepaint) { + this.setPaintStyle(t.paintStyle, doNotRepaint); + this.setHoverPaintStyle(t.hoverPaintStyle, doNotRepaint); + if (t.parameters) { + for (var i in t.parameters) { + this.setParameter(i, t.parameters[i]); + } + } + this._jsPlumb.paintStyleInUse = this.getPaintStyle(); + }, + setPaintStyle: function (style, doNotRepaint) { + // this._jsPlumb.paintStyle = jsPlumb.extend({}, style); + // TODO figure out if we want components to clone paintStyle so as not to share it. + this._jsPlumb.paintStyle = style; + this._jsPlumb.paintStyleInUse = this._jsPlumb.paintStyle; + _updateHoverStyle(this); + if (!doNotRepaint) { + this.repaint(); + } + }, + getPaintStyle: function () { + return this._jsPlumb.paintStyle; + }, + setHoverPaintStyle: function (style, doNotRepaint) { + //this._jsPlumb.hoverPaintStyle = jsPlumb.extend({}, style); + // TODO figure out if we want components to clone paintStyle so as not to share it. + this._jsPlumb.hoverPaintStyle = style; + _updateHoverStyle(this); + if (!doNotRepaint) { + this.repaint(); + } + }, + getHoverPaintStyle: function () { + return this._jsPlumb.hoverPaintStyle; + }, + destroy: function (force) { + if (force || this.typeId == null) { + this.cleanupListeners(); // this is on EventGenerator + this.clone = null; + this._jsPlumb = null; + } + }, + + isHover: function () { + return this._jsPlumb.hover; + }, + + setHover: function (hover, ignoreAttachedElements, timestamp) { + // while dragging, we ignore these events. this keeps the UI from flashing and + // swishing and whatevering. + if (this._jsPlumb && !this._jsPlumb.instance.currentlyDragging && !this._jsPlumb.instance.isHoverSuspended()) { + + this._jsPlumb.hover = hover; + var method = hover ? "addClass" : "removeClass"; + + if (this.canvas != null) { + if (this._jsPlumb.instance.hoverClass != null) { + this._jsPlumb.instance[method](this.canvas, this._jsPlumb.instance.hoverClass); + } + if (this._jsPlumb.hoverClass != null) { + this._jsPlumb.instance[method](this.canvas, this._jsPlumb.hoverClass); + } + } + if (this._jsPlumb.hoverPaintStyle != null) { + this._jsPlumb.paintStyleInUse = hover ? this._jsPlumb.hoverPaintStyle : this._jsPlumb.paintStyle; + if (!this._jsPlumb.instance.isSuspendDrawing()) { + timestamp = timestamp || _timestamp(); + this.repaint({timestamp: timestamp, recalc: false}); + } + } + // get the list of other affected elements, if supported by this component. + // for a connection, its the endpoints. for an endpoint, its the connections! surprise. + if (this.getAttachedElements && !ignoreAttachedElements) { + _updateAttachedElements(this, hover, _timestamp(), this); + } + } + } + }); + +// ------------------------------ END jsPlumbUIComponent -------------------------------------------- + + var _jsPlumbInstanceIndex = 0, + getInstanceIndex = function () { + var i = _jsPlumbInstanceIndex + 1; + _jsPlumbInstanceIndex++; + return i; + }; + + var jsPlumbInstance = root.jsPlumbInstance = function (_defaults) { + + this.version = "2.12.6"; + + this.Defaults = { + Anchor: "Bottom", + Anchors: [ null, null ], + ConnectionsDetachable: true, + ConnectionOverlays: [ ], + Connector: "Bezier", + Container: null, + DoNotThrowErrors: false, + DragOptions: { }, + DropOptions: { }, + Endpoint: "Dot", + EndpointOverlays: [ ], + Endpoints: [ null, null ], + EndpointStyle: { fill: "#456" }, + EndpointStyles: [ null, null ], + EndpointHoverStyle: null, + EndpointHoverStyles: [ null, null ], + HoverPaintStyle: null, + LabelStyle: { color: "black" }, + LogEnabled: false, + Overlays: [ ], + MaxConnections: 1, + PaintStyle: { "stroke-width": 4, stroke: "#456" }, + ReattachConnections: false, + RenderMode: "svg", + Scope: "jsPlumb_DefaultScope" + }; + + if (_defaults) { + jsPlumb.extend(this.Defaults, _defaults); + } + + this.logEnabled = this.Defaults.LogEnabled; + this._connectionTypes = {}; + this._endpointTypes = {}; + + _ju.EventGenerator.apply(this); + + var _currentInstance = this, + _instanceIndex = getInstanceIndex(), + _bb = _currentInstance.bind, + _initialDefaults = {}, + _zoom = 1, + _info = function (el) { + if (el == null) { + return null; + } + else if (el.nodeType === 3 || el.nodeType === 8) { + return { el:el, text:true }; + } + else { + var _el = _currentInstance.getElement(el); + return { el: _el, id: (_ju.isString(el) && _el == null) ? el : _getId(_el) }; + } + }; + + this.getInstanceIndex = function () { + return _instanceIndex; + }; + + // CONVERTED + this.setZoom = function (z, repaintEverything) { + _zoom = z; + _currentInstance.fire("zoom", _zoom); + if (repaintEverything) { + _currentInstance.repaintEverything(); + } + return true; + }; + // CONVERTED + this.getZoom = function () { + return _zoom; + }; + + for (var i in this.Defaults) { + _initialDefaults[i] = this.Defaults[i]; + } + + var _container, _containerDelegations = []; + this.unbindContainer = function() { + if (_container != null && _containerDelegations.length > 0) { + for (var i = 0; i < _containerDelegations.length; i++) { + _currentInstance.off(_container, _containerDelegations[i][0], _containerDelegations[i][1]); + } + } + }; + this.setContainer = function (c) { + + this.unbindContainer(); + + // get container as dom element. + c = this.getElement(c); + // move existing connections and endpoints, if any. + this.select().each(function (conn) { + conn.moveParent(c); + }); + this.selectEndpoints().each(function (ep) { + ep.moveParent(c); + }); + + // set container. + var previousContainer = _container; + _container = c; + _containerDelegations.length = 0; + var eventAliases = { + "endpointclick":"endpointClick", + "endpointdblclick":"endpointDblClick" + }; + + var _oneDelegateHandler = function (id, e, componentType) { + var t = e.srcElement || e.target, + jp = (t && t.parentNode ? t.parentNode._jsPlumb : null) || (t ? t._jsPlumb : null) || (t && t.parentNode && t.parentNode.parentNode ? t.parentNode.parentNode._jsPlumb : null); + if (jp) { + jp.fire(id, jp, e); + var alias = componentType ? eventAliases[componentType + id] || id : id; + // jsplumb also fires every event coming from components/overlays. That's what the test for `jp.component` is for. + _currentInstance.fire(alias, jp.component || jp, e); + } + }; + + var _addOneDelegate = function(eventId, selector, fn) { + _containerDelegations.push([eventId, fn]); + _currentInstance.on(_container, eventId, selector, fn); + }; + + // delegate one event on the container to jsplumb elements. it might be possible to + // abstract this out: each of endpoint, connection and overlay could register themselves with + // jsplumb as "component types" or whatever, and provide a suitable selector. this would be + // done by the renderer (although admittedly from 2.0 onwards we're not supporting vml anymore) + var _oneDelegate = function (id) { + // connections. + _addOneDelegate(id, ".jtk-connector", function (e) { + _oneDelegateHandler(id, e); + }); + // endpoints. note they can have an enclosing div, or not. + _addOneDelegate(id, ".jtk-endpoint", function (e) { + _oneDelegateHandler(id, e, "endpoint"); + }); + // overlays + _addOneDelegate(id, ".jtk-overlay", function (e) { + _oneDelegateHandler(id, e); + }); + }; + + for (var i = 0; i < events.length; i++) { + _oneDelegate(events[i]); + } + + // managed elements + for (var elId in managedElements) { + var el = managedElements[elId].el; + if (el.parentNode === previousContainer) { + previousContainer.removeChild(el); + _container.appendChild(el); + } + } + + }; + this.getContainer = function () { + return _container; + }; + + this.bind = function (event, fn) { + if ("ready" === event && initialized) { + fn(); + } + else { + _bb.apply(_currentInstance, [event, fn]); + } + }; + + _currentInstance.importDefaults = function (d) { + for (var i in d) { + _currentInstance.Defaults[i] = d[i]; + } + if (d.Container) { + _currentInstance.setContainer(d.Container); + } + + return _currentInstance; + }; + + _currentInstance.restoreDefaults = function () { + _currentInstance.Defaults = jsPlumb.extend({}, _initialDefaults); + return _currentInstance; + }; + + var log = null, + initialized = false, + // TODO remove from window scope + connections = [], + // map of element id -> endpoint lists. an element can have an arbitrary + // number of endpoints on it, and not all of them have to be connected + // to anything. + endpointsByElement = {}, + endpointsByUUID = {}, + managedElements = {}, + offsets = {}, + offsetTimestamps = {}, + draggableStates = {}, + connectionBeingDragged = false, + sizes = [], + _suspendDrawing = false, + _suspendedAt = null, + DEFAULT_SCOPE = this.Defaults.Scope, + _curIdStamp = 1, + _idstamp = function () { + return "" + _curIdStamp++; + }, + + // + // appends an element to some other element, which is calculated as follows: + // + // 1. if Container exists, use that element. + // 2. if the 'parent' parameter exists, use that. + // 3. otherwise just use the root element. + // + // + _appendElement = function (el, parent) { + if (_container) { + _container.appendChild(el); + } + else if (!parent) { + this.appendToRoot(el); + } + else { + this.getElement(parent).appendChild(el); + } + }.bind(this), + + // + // Draws an endpoint and its connections. this is the main entry point into drawing connections as well + // as endpoints, since jsPlumb is endpoint-centric under the hood. + // + // @param element element to draw (of type library specific element object) + // @param ui UI object from current library's event system. optional. + // @param timestamp timestamp for this paint cycle. used to speed things up a little by cutting down the amount of offset calculations we do. + // @param clearEdits defaults to false; indicates that mouse edits for connectors should be cleared + /// + _draw = function (element, ui, timestamp, clearEdits) { + + if (!_suspendDrawing) { + var id = _getId(element), + repaintEls, + dm = _currentInstance.getDragManager(); + + if (dm) { + repaintEls = dm.getElementsForDraggable(id); + } + + if (timestamp == null) { + timestamp = _timestamp(); + } + + // update the offset of everything _before_ we try to draw anything. + var o = _updateOffset({ elId: id, offset: ui, recalc: false, timestamp: timestamp }); + + if (repaintEls && o && o.o) { + for (var i in repaintEls) { + _updateOffset({ + elId: repaintEls[i].id, + offset: { + left: o.o.left + repaintEls[i].offset.left, + top: o.o.top + repaintEls[i].offset.top + }, + recalc: false, + timestamp: timestamp + }); + } + } + + _currentInstance.anchorManager.redraw(id, ui, timestamp, null, clearEdits); + + if (repaintEls) { + for (var j in repaintEls) { + _currentInstance.anchorManager.redraw(repaintEls[j].id, ui, timestamp, repaintEls[j].offset, clearEdits, true); + } + } + } + }, + + // + // gets an Endpoint by uuid. + // + _getEndpoint = function (uuid) { + return endpointsByUUID[uuid]; + }, + + /** + * inits a draggable if it's not already initialised. + * TODO: somehow abstract this to the adapter, because the concept of "draggable" has no + * place on the server. + */ + + + _scopeMatch = function (e1, e2) { + var s1 = e1.scope.split(/\s/), s2 = e2.scope.split(/\s/); + for (var i = 0; i < s1.length; i++) { + for (var j = 0; j < s2.length; j++) { + if (s2[j] === s1[i]) { + return true; + } + } + } + + return false; + }, + + _mergeOverrides = function (def, values) { + var m = jsPlumb.extend({}, def); + for (var i in values) { + if (values[i]) { + m[i] = values[i]; + } + } + return m; + }, + + /* + * prepares a final params object that can be passed to _newConnection, taking into account defaults, events, etc. + */ + _prepareConnectionParams = function (params, referenceParams) { + var _p = jsPlumb.extend({ }, params); + if (referenceParams) { + jsPlumb.extend(_p, referenceParams); + } + + // hotwire endpoints passed as source or target to sourceEndpoint/targetEndpoint, respectively. + if (_p.source) { + if (_p.source.endpoint) { + _p.sourceEndpoint = _p.source; + } + else { + _p.source = _currentInstance.getElement(_p.source); + } + } + if (_p.target) { + if (_p.target.endpoint) { + _p.targetEndpoint = _p.target; + } + else { + _p.target = _currentInstance.getElement(_p.target); + } + } + + // test for endpoint uuids to connect + if (params.uuids) { + _p.sourceEndpoint = _getEndpoint(params.uuids[0]); + _p.targetEndpoint = _getEndpoint(params.uuids[1]); + } + + // now ensure that if we do have Endpoints already, they're not full. + // source: + if (_p.sourceEndpoint && _p.sourceEndpoint.isFull()) { + _ju.log(_currentInstance, "could not add connection; source endpoint is full"); + return; + } + + // target: + if (_p.targetEndpoint && _p.targetEndpoint.isFull()) { + _ju.log(_currentInstance, "could not add connection; target endpoint is full"); + return; + } + + // if source endpoint mandates connection type and nothing specified in our params, use it. + if (!_p.type && _p.sourceEndpoint) { + _p.type = _p.sourceEndpoint.connectionType; + } + + // copy in any connectorOverlays that were specified on the source endpoint. + // it doesnt copy target endpoint overlays. i'm not sure if we want it to or not. + if (_p.sourceEndpoint && _p.sourceEndpoint.connectorOverlays) { + _p.overlays = _p.overlays || []; + for (var i = 0, j = _p.sourceEndpoint.connectorOverlays.length; i < j; i++) { + _p.overlays.push(_p.sourceEndpoint.connectorOverlays[i]); + } + } + + // scope + if (_p.sourceEndpoint && _p.sourceEndpoint.scope) { + _p.scope = _p.sourceEndpoint.scope; + } + + // pointer events + if (!_p["pointer-events"] && _p.sourceEndpoint && _p.sourceEndpoint.connectorPointerEvents) { + _p["pointer-events"] = _p.sourceEndpoint.connectorPointerEvents; + } + + + var _addEndpoint = function (el, def, idx) { + var params = _mergeOverrides(def, { + anchor: _p.anchors ? _p.anchors[idx] : _p.anchor, + endpoint: _p.endpoints ? _p.endpoints[idx] : _p.endpoint, + paintStyle: _p.endpointStyles ? _p.endpointStyles[idx] : _p.endpointStyle, + hoverPaintStyle: _p.endpointHoverStyles ? _p.endpointHoverStyles[idx] : _p.endpointHoverStyle + }); + return _currentInstance.addEndpoint(el, params); + }; + + // check for makeSource/makeTarget specs. + + var _oneElementDef = function (type, idx, defs, matchType) { + if (_p[type] && !_p[type].endpoint && !_p[type + "Endpoint"] && !_p.newConnection) { + var tid = _getId(_p[type]), tep = defs[tid]; + + tep = tep ? tep[matchType] : null; + + if (tep) { + // if not enabled, return. + if (!tep.enabled) { + return false; + } + + var epDef = jsPlumb.extend({}, tep.def); + delete epDef.label; + + var newEndpoint = tep.endpoint != null && tep.endpoint._jsPlumb ? tep.endpoint : _addEndpoint(_p[type], epDef, idx); + if (newEndpoint.isFull()) { + return false; + } + _p[type + "Endpoint"] = newEndpoint; + if (!_p.scope && epDef.scope) { + _p.scope = epDef.scope; + } // provide scope if not already provided and endpoint def has one. + if (tep.uniqueEndpoint) { + if (!tep.endpoint) { + tep.endpoint = newEndpoint; + newEndpoint.setDeleteOnEmpty(false); + } + else { + newEndpoint.finalEndpoint = tep.endpoint; + } + } else { + newEndpoint.setDeleteOnEmpty(true); + } + + // + // copy in connector overlays if present on the source definition. + // + if (idx === 0 && tep.def.connectorOverlays) { + _p.overlays = _p.overlays || []; + Array.prototype.push.apply(_p.overlays, tep.def.connectorOverlays); + } + } + } + }; + + if (_oneElementDef("source", 0, this.sourceEndpointDefinitions, _p.type || "default") === false) { + return; + } + if (_oneElementDef("target", 1, this.targetEndpointDefinitions, _p.type || "default") === false) { + return; + } + + // last, ensure scopes match + if (_p.sourceEndpoint && _p.targetEndpoint) { + if (!_scopeMatch(_p.sourceEndpoint, _p.targetEndpoint)) { + _p = null; + } + } + + return _p; + }.bind(_currentInstance), + + _newConnection = function (params) { + var connectionFunc = _currentInstance.Defaults.ConnectionType || _currentInstance.getDefaultConnectionType(); + + params._jsPlumb = _currentInstance; + params.newConnection = _newConnection; + params.newEndpoint = _newEndpoint; + params.endpointsByUUID = endpointsByUUID; + params.endpointsByElement = endpointsByElement; + params.finaliseConnection = _finaliseConnection; + params.id = "con_" + _idstamp(); + var con = new connectionFunc(params); + + // if the connection is draggable, then maybe we need to tell the target endpoint to init the + // dragging code. it won't run again if it already configured to be draggable. + if (con.isDetachable()) { + con.endpoints[0].initDraggable("_jsPlumbSource"); + con.endpoints[1].initDraggable("_jsPlumbTarget"); + } + + return con; + }, + + // + // adds the connection to the backing model, fires an event if necessary and then redraws + // + _finaliseConnection = _currentInstance.finaliseConnection = function (jpc, params, originalEvent, doInformAnchorManager) { + params = params || {}; + // add to list of connections (by scope). + if (!jpc.suspendedEndpoint) { + connections.push(jpc); + } + + jpc.pending = null; + + // turn off isTemporarySource on the source endpoint (only viable on first draw) + jpc.endpoints[0].isTemporarySource = false; + + // always inform the anchor manager + // except that if jpc has a suspended endpoint it's not true to say the + // connection is new; it has just (possibly) moved. the question is whether + // to make that call here or in the anchor manager. i think perhaps here. + if (doInformAnchorManager !== false) { + _currentInstance.anchorManager.newConnection(jpc); + } + + // force a paint + _draw(jpc.source); + + // fire an event + if (!params.doNotFireConnectionEvent && params.fireEvent !== false) { + + var eventArgs = { + connection: jpc, + source: jpc.source, target: jpc.target, + sourceId: jpc.sourceId, targetId: jpc.targetId, + sourceEndpoint: jpc.endpoints[0], targetEndpoint: jpc.endpoints[1] + }; + + _currentInstance.fire("connection", eventArgs, originalEvent); + } + }, + + /* + factory method to prepare a new endpoint. this should always be used instead of creating Endpoints + manually, since this method attaches event listeners and an id. + */ + _newEndpoint = function (params, id) { + var endpointFunc = _currentInstance.Defaults.EndpointType || jsPlumb.Endpoint; + var _p = jsPlumb.extend({}, params); + //delete _p.label; // not supported by endpoint. + _p._jsPlumb = _currentInstance; + _p.newConnection = _newConnection; + _p.newEndpoint = _newEndpoint; + _p.endpointsByUUID = endpointsByUUID; + _p.endpointsByElement = endpointsByElement; + _p.fireDetachEvent = fireDetachEvent; + _p.elementId = id || _getId(_p.source); + var ep = new endpointFunc(_p); + ep.id = "ep_" + _idstamp(); + _manage(_p.elementId, _p.source); + + if (!jsPlumb.headless) { + _currentInstance.getDragManager().endpointAdded(_p.source, id); + } + + return ep; + }, + + /* + * performs the given function operation on all the connections found + * for the given element id; this means we find all the endpoints for + * the given element, and then for each endpoint find the connectors + * connected to it. then we pass each connection in to the given + * function. + */ + _operation = function (elId, func, endpointFunc) { + var endpoints = endpointsByElement[elId]; + if (endpoints && endpoints.length) { + for (var i = 0, ii = endpoints.length; i < ii; i++) { + for (var j = 0, jj = endpoints[i].connections.length; j < jj; j++) { + var retVal = func(endpoints[i].connections[j]); + // if the function passed in returns true, we exit. + // most functions return false. + if (retVal) { + return; + } + } + if (endpointFunc) { + endpointFunc(endpoints[i]); + } + } + } + }, + + _setDraggable = function (element, draggable) { + return jsPlumb.each(element, function (el) { + if (_currentInstance.isDragSupported(el)) { + draggableStates[_currentInstance.getAttribute(el, "id")] = draggable; + _currentInstance.setElementDraggable(el, draggable); + } + }); + }, + /* + * private method to do the business of hiding/showing. + * + * @param el + * either Id of the element in question or a library specific + * object for the element. + * @param state + * String specifying a value for the css 'display' property + * ('block' or 'none'). + */ + _setVisible = function (el, state, alsoChangeEndpoints) { + state = state === "block"; + var endpointFunc = null; + if (alsoChangeEndpoints) { + endpointFunc = function (ep) { + ep.setVisible(state, true, true); + }; + } + var info = _info(el); + _operation(info.id, function (jpc) { + if (state && alsoChangeEndpoints) { + // this test is necessary because this functionality is new, and i wanted to maintain backwards compatibility. + // this block will only set a connection to be visible if the other endpoint in the connection is also visible. + var oidx = jpc.sourceId === info.id ? 1 : 0; + if (jpc.endpoints[oidx].isVisible()) { + jpc.setVisible(true); + } + } + else { // the default behaviour for show, and what always happens for hide, is to just set the visibility without getting clever. + jpc.setVisible(state); + } + }, endpointFunc); + }, + /** + * private method to do the business of toggling hiding/showing. + */ + _toggleVisible = function (elId, changeEndpoints) { + var endpointFunc = null; + if (changeEndpoints) { + endpointFunc = function (ep) { + var state = ep.isVisible(); + ep.setVisible(!state); + }; + } + _operation(elId, function (jpc) { + var state = jpc.isVisible(); + jpc.setVisible(!state); + }, endpointFunc); + }, + + // TODO comparison performance + _getCachedData = function (elId) { + var o = offsets[elId]; + if (!o) { + return _updateOffset({elId: elId}); + } + else { + return {o: o, s: sizes[elId]}; + } + }, + + /** + * gets an id for the given element, creating and setting one if + * necessary. the id is of the form + * + * jsPlumb__ + * + * where "index in instance" is a monotonically increasing integer that starts at 0, + * for each instance. this method is used not only to assign ids to elements that do not + * have them but also to connections and endpoints. + */ + _getId = function (element, uuid, doNotCreateIfNotFound) { + if (_ju.isString(element)) { + return element; + } + if (element == null) { + return null; + } + var id = _currentInstance.getAttribute(element, "id"); + if (!id || id === "undefined") { + // check if fixed uuid parameter is given + if (arguments.length === 2 && arguments[1] !== undefined) { + id = uuid; + } + else if (arguments.length === 1 || (arguments.length === 3 && !arguments[2])) { + id = "jsPlumb_" + _instanceIndex + "_" + _idstamp(); + } + + if (!doNotCreateIfNotFound) { + _currentInstance.setAttribute(element, "id", id); + } + } + return id; + }; + + this.setConnectionBeingDragged = function (v) { + connectionBeingDragged = v; + }; + this.isConnectionBeingDragged = function () { + return connectionBeingDragged; + }; + + /** + * Returns a map of all the elements this jsPlumbInstance is currently managing. + * @returns {Object} Map of [id-> {el, endpoint[], connection, position}] information. + */ + this.getManagedElements = function() { + return managedElements; + }; + + this.connectorClass = "jtk-connector"; + this.connectorOutlineClass = "jtk-connector-outline"; + this.connectedClass = "jtk-connected"; + this.hoverClass = "jtk-hover"; + this.endpointClass = "jtk-endpoint"; + this.endpointConnectedClass = "jtk-endpoint-connected"; + this.endpointFullClass = "jtk-endpoint-full"; + this.endpointDropAllowedClass = "jtk-endpoint-drop-allowed"; + this.endpointDropForbiddenClass = "jtk-endpoint-drop-forbidden"; + this.overlayClass = "jtk-overlay"; + this.draggingClass = "jtk-dragging";// CONVERTED + this.elementDraggingClass = "jtk-element-dragging";// CONVERTED + this.sourceElementDraggingClass = "jtk-source-element-dragging"; // CONVERTED + this.targetElementDraggingClass = "jtk-target-element-dragging";// CONVERTED + this.endpointAnchorClassPrefix = "jtk-endpoint-anchor"; + this.hoverSourceClass = "jtk-source-hover"; + this.hoverTargetClass = "jtk-target-hover"; + this.dragSelectClass = "jtk-drag-select"; + + this.Anchors = {}; + this.Connectors = { "svg": {} }; + this.Endpoints = { "svg": {} }; + this.Overlays = { "svg": {} } ; + this.ConnectorRenderers = {}; + this.SVG = "svg"; + +// --------------------------- jsPlumbInstance public API --------------------------------------------------------- + + + this.addEndpoint = function (el, params, referenceParams) { + referenceParams = referenceParams || {}; + var p = jsPlumb.extend({}, referenceParams); + jsPlumb.extend(p, params); + p.endpoint = p.endpoint || _currentInstance.Defaults.Endpoint; + p.paintStyle = p.paintStyle || _currentInstance.Defaults.EndpointStyle; + + var results = [], + inputs = (_ju.isArray(el) || (el.length != null && !_ju.isString(el))) ? el : [ el ]; + + for (var i = 0, j = inputs.length; i < j; i++) { + p.source = _currentInstance.getElement(inputs[i]); + _ensureContainer(p.source); + + var id = _getId(p.source), e = _newEndpoint(p, id); + + // ensure element is managed. + var myOffset = _manage(id, p.source).info.o; + _ju.addToList(endpointsByElement, id, e); + + if (!_suspendDrawing) { + e.paint({ + anchorLoc: e.anchor.compute({ xy: [ myOffset.left, myOffset.top ], wh: sizes[id], element: e, timestamp: _suspendedAt }), + timestamp: _suspendedAt + }); + } + + results.push(e); + } + + return results.length === 1 ? results[0] : results; + }; + + this.addEndpoints = function (el, endpoints, referenceParams) { + var results = []; + for (var i = 0, j = endpoints.length; i < j; i++) { + var e = _currentInstance.addEndpoint(el, endpoints[i], referenceParams); + if (_ju.isArray(e)) { + Array.prototype.push.apply(results, e); + } + else { + results.push(e); + } + } + return results; + }; + + this.animate = function (el, properties, options) { + if (!this.animationSupported) { + return false; + } + + options = options || {}; + var del = _currentInstance.getElement(el), + id = _getId(del), + stepFunction = jsPlumb.animEvents.step, + completeFunction = jsPlumb.animEvents.complete; + + options[stepFunction] = _ju.wrap(options[stepFunction], function () { + _currentInstance.revalidate(id); + }); + + // onComplete repaints, just to make sure everything looks good at the end of the animation. + options[completeFunction] = _ju.wrap(options[completeFunction], function () { + _currentInstance.revalidate(id); + }); + + _currentInstance.doAnimate(del, properties, options); + }; + + /** + * checks for a listener for the given condition, executing it if found, passing in the given value. + * condition listeners would have been attached using "bind" (which is, you could argue, now overloaded, since + * firing click events etc is a bit different to what this does). i thought about adding a "bindCondition" + * or something, but decided against it, for the sake of simplicity. jsPlumb will never fire one of these + * condition events anyway. + */ + this.checkCondition = function (conditionName, args) { + var l = _currentInstance.getListener(conditionName), + r = true; + + if (l && l.length > 0) { + var values = Array.prototype.slice.call(arguments, 1); + try { + for (var i = 0, j = l.length; i < j; i++) { + r = r && l[i].apply(l[i], values); + } + } + catch (e) { + _ju.log(_currentInstance, "cannot check condition [" + conditionName + "]" + e); + } + } + return r; + }; + + this.connect = function (params, referenceParams) { + // prepare a final set of parameters to create connection with + var _p = _prepareConnectionParams(params, referenceParams), jpc; + // TODO probably a nicer return value if the connection was not made. _prepareConnectionParams + // will return null (and log something) if either endpoint was full. what would be nicer is to + // create a dedicated 'error' object. + if (_p) { + if (_p.source == null && _p.sourceEndpoint == null) { + _ju.log("Cannot establish connection - source does not exist"); + return; + } + if (_p.target == null && _p.targetEndpoint == null) { + _ju.log("Cannot establish connection - target does not exist"); + return; + } + _ensureContainer(_p.source); + // create the connection. it is not yet registered + jpc = _newConnection(_p); + // now add it the model, fire an event, and redraw + _finaliseConnection(jpc, _p); + } + return jpc; + }; + + var stTypes = [ + { el: "source", elId: "sourceId", epDefs: "sourceEndpointDefinitions" }, + { el: "target", elId: "targetId", epDefs: "targetEndpointDefinitions" } + ]; + + var _set = function (c, el, idx, doNotRepaint) { + var ep, _st = stTypes[idx], cId = c[_st.elId], cEl = c[_st.el], sid, sep, + oldEndpoint = c.endpoints[idx]; + + var evtParams = { + index: idx, + originalSourceId: idx === 0 ? cId : c.sourceId, + newSourceId: c.sourceId, + originalTargetId: idx === 1 ? cId : c.targetId, + newTargetId: c.targetId, + connection: c + }; + + if (el.constructor === jsPlumb.Endpoint) { + ep = el; + ep.addConnection(c); + el = ep.element; + } + else { + sid = _getId(el); + sep = this[_st.epDefs][sid]; + + if (sid === c[_st.elId]) { + ep = null; // dont change source/target if the element is already the one given. + } + else if (sep) { + for (var t in sep) { + if (!sep[t].enabled) { + return; + } + ep = sep[t].endpoint != null && sep[t].endpoint._jsPlumb ? sep[t].endpoint : this.addEndpoint(el, sep[t].def); + if (sep[t].uniqueEndpoint) { + sep[t].endpoint = ep; + } + ep.addConnection(c); + } + } + else { + ep = c.makeEndpoint(idx === 0, el, sid); + } + } + + if (ep != null) { + oldEndpoint.detachFromConnection(c); + c.endpoints[idx] = ep; + c[_st.el] = ep.element; + c[_st.elId] = ep.elementId; + evtParams[idx === 0 ? "newSourceId" : "newTargetId"] = ep.elementId; + + fireMoveEvent(evtParams); + + if (!doNotRepaint) { + c.repaint(); + } + } + + evtParams.element = el; + return evtParams; + + }.bind(this); + + this.setSource = function (connection, el, doNotRepaint) { + var p = _set(connection, el, 0, doNotRepaint); + this.anchorManager.sourceChanged(p.originalSourceId, p.newSourceId, connection, p.el); + }; + this.setTarget = function (connection, el, doNotRepaint) { + var p = _set(connection, el, 1, doNotRepaint); + this.anchorManager.updateOtherEndpoint(p.originalSourceId, p.originalTargetId, p.newTargetId, connection); + }; + + this.deleteEndpoint = function (object, dontUpdateHover, deleteAttachedObjects) { + var endpoint = (typeof object === "string") ? endpointsByUUID[object] : object; + if (endpoint) { + _currentInstance.deleteObject({ endpoint: endpoint, dontUpdateHover: dontUpdateHover, deleteAttachedObjects:deleteAttachedObjects }); + } + return _currentInstance; + }; + + this.deleteEveryEndpoint = function () { + var _is = _currentInstance.setSuspendDrawing(true); + for (var id in endpointsByElement) { + var endpoints = endpointsByElement[id]; + if (endpoints && endpoints.length) { + for (var i = 0, j = endpoints.length; i < j; i++) { + _currentInstance.deleteEndpoint(endpoints[i], true); + } + } + } + endpointsByElement = {}; + managedElements = {}; + endpointsByUUID = {}; + offsets = {}; + offsetTimestamps = {}; + _currentInstance.anchorManager.reset(); + var dm = _currentInstance.getDragManager(); + if (dm) { + dm.reset(); + } + if (!_is) { + _currentInstance.setSuspendDrawing(false); + } + return _currentInstance; + }; + + var fireDetachEvent = function (jpc, doFireEvent, originalEvent) { + // may have been given a connection, or in special cases, an object + var connType = _currentInstance.Defaults.ConnectionType || _currentInstance.getDefaultConnectionType(), + argIsConnection = jpc.constructor === connType, + params = argIsConnection ? { + connection: jpc, + source: jpc.source, target: jpc.target, + sourceId: jpc.sourceId, targetId: jpc.targetId, + sourceEndpoint: jpc.endpoints[0], targetEndpoint: jpc.endpoints[1] + } : jpc; + + if (doFireEvent) { + _currentInstance.fire("connectionDetached", params, originalEvent); + } + + // always fire this. used by internal jsplumb stuff. + _currentInstance.fire("internal.connectionDetached", params, originalEvent); + + _currentInstance.anchorManager.connectionDetached(params); + }; + + var fireMoveEvent = _currentInstance.fireMoveEvent = function (params, evt) { + _currentInstance.fire("connectionMoved", params, evt); + }; + + this.unregisterEndpoint = function (endpoint) { + if (endpoint._jsPlumb.uuid) { + endpointsByUUID[endpoint._jsPlumb.uuid] = null; + } + _currentInstance.anchorManager.deleteEndpoint(endpoint); + // TODO at least replace this with a removeWithFunction call. + for (var e in endpointsByElement) { + var endpoints = endpointsByElement[e]; + if (endpoints) { + var newEndpoints = []; + for (var i = 0, j = endpoints.length; i < j; i++) { + if (endpoints[i] !== endpoint) { + newEndpoints.push(endpoints[i]); + } + } + + endpointsByElement[e] = newEndpoints; + } + if (endpointsByElement[e].length < 1) { + delete endpointsByElement[e]; + } + } + }; + + var IS_DETACH_ALLOWED = "isDetachAllowed"; + var BEFORE_DETACH = "beforeDetach"; + var CHECK_CONDITION = "checkCondition"; + + /** + * Deletes a Connection. + * @method deleteConnection + * @param connection Connection to delete + * @param {Object} [params] Optional delete parameters + * @param {Boolean} [params.doNotFireEvent=false] If true, a connection detached event will not be fired. Otherwise one will. + * @param {Boolean} [params.force=false] If true, the connection will be deleted even if a beforeDetach interceptor tries to stop the deletion. + * @returns {Boolean} True if the connection was deleted, false otherwise. + */ + this.deleteConnection = function(connection, params) { + + if (connection != null) { + params = params || {}; + + if (params.force || _ju.functionChain(true, false, [ + [ connection.endpoints[0], IS_DETACH_ALLOWED, [ connection ] ], + [ connection.endpoints[1], IS_DETACH_ALLOWED, [ connection ] ], + [ connection, IS_DETACH_ALLOWED, [ connection ] ], + [ _currentInstance, CHECK_CONDITION, [ BEFORE_DETACH, connection ] ] + ])) { + + connection.setHover(false); + fireDetachEvent(connection, !connection.pending && params.fireEvent !== false, params.originalEvent); + + connection.endpoints[0].detachFromConnection(connection); + connection.endpoints[1].detachFromConnection(connection); + _ju.removeWithFunction(connections, function (_c) { + return connection.id === _c.id; + }); + + connection.cleanup(); + connection.destroy(); + return true; + } + } + return false; + }; + + /** + * Remove all Connections from all elements, but leaves Endpoints in place ((unless a connection is set to auto delete its Endpoints). + * @method deleteEveryConnection + * @param {Object} [params] optional params object for the call + * @param {Boolean} [params.fireEvent=true] Whether or not to fire detach events + * @param {Boolean} [params.forceDetach=false] If true, this call will ignore any `beforeDetach` interceptors. + * @returns {Number} The number of connections that were deleted. + */ + this.deleteEveryConnection = function (params) { + params = params || {}; + var count = connections.length, deletedCount = 0; + _currentInstance.batch(function () { + for (var i = 0; i < count; i++) { + deletedCount += _currentInstance.deleteConnection(connections[0], params) ? 1 : 0; + } + }); + return deletedCount; + }; + + /** + * Removes all an element's Connections. + * @method deleteConnectionsForElement + * @param {Object} el Either the id of the element, or a selector for the element. + * @param {Object} [params] Optional parameters. + * @param {Boolean} [params.fireEvent=true] Whether or not to fire the detach event. + * @param {Boolean} [params.forceDetach=false] If true, this call will ignore any `beforeDetach` interceptors. + * @return {jsPlumbInstance} The current jsPlumb instance. + */ + this.deleteConnectionsForElement = function (el, params) { + params = params || {}; + el = _currentInstance.getElement(el); + var id = _getId(el), endpoints = endpointsByElement[id]; + if (endpoints && endpoints.length) { + for (var i = 0, j = endpoints.length; i < j; i++) { + endpoints[i].deleteEveryConnection(params); + } + } + return _currentInstance; + }; + + /// not public. but of course its exposed. how to change this. + this.deleteObject = function (params) { + var result = { + endpoints: {}, + connections: {}, + endpointCount: 0, + connectionCount: 0 + }, + deleteAttachedObjects = params.deleteAttachedObjects !== false; + + var unravelConnection = function (connection) { + if (connection != null && result.connections[connection.id] == null) { + if (!params.dontUpdateHover && connection._jsPlumb != null) { + connection.setHover(false); + } + result.connections[connection.id] = connection; + result.connectionCount++; + } + }; + var unravelEndpoint = function (endpoint) { + if (endpoint != null && result.endpoints[endpoint.id] == null) { + if (!params.dontUpdateHover && endpoint._jsPlumb != null) { + endpoint.setHover(false); + } + result.endpoints[endpoint.id] = endpoint; + result.endpointCount++; + + if (deleteAttachedObjects) { + for (var i = 0; i < endpoint.connections.length; i++) { + var c = endpoint.connections[i]; + unravelConnection(c); + } + } + } + }; + + if (params.connection) { + unravelConnection(params.connection); + } + else { + unravelEndpoint(params.endpoint); + } + + // loop through connections + for (var i in result.connections) { + var c = result.connections[i]; + if (c._jsPlumb) { + _ju.removeWithFunction(connections, function (_c) { + return c.id === _c.id; + }); + + fireDetachEvent(c, params.fireEvent === false ? false : !c.pending, params.originalEvent); + var doNotCleanup = params.deleteAttachedObjects == null ? null : !params.deleteAttachedObjects; + + c.endpoints[0].detachFromConnection(c, null, doNotCleanup); + c.endpoints[1].detachFromConnection(c, null, doNotCleanup); + + c.cleanup(true); + c.destroy(true); + } + } + + // loop through endpoints + for (var j in result.endpoints) { + var e = result.endpoints[j]; + if (e._jsPlumb) { + _currentInstance.unregisterEndpoint(e); + // FIRE some endpoint deleted event? + e.cleanup(true); + e.destroy(true); + } + } + + return result; + }; + + + // helpers for select/selectEndpoints + var _setOperation = function (list, func, args, selector) { + for (var i = 0, j = list.length; i < j; i++) { + list[i][func].apply(list[i], args); + } + return selector(list); + }, + _getOperation = function (list, func, args) { + var out = []; + for (var i = 0, j = list.length; i < j; i++) { + out.push([ list[i][func].apply(list[i], args), list[i] ]); + } + return out; + }, + setter = function (list, func, selector) { + return function () { + return _setOperation(list, func, arguments, selector); + }; + }, + getter = function (list, func) { + return function () { + return _getOperation(list, func, arguments); + }; + }, + prepareList = function (input, doNotGetIds) { + var r = []; + if (input) { + if (typeof input === 'string') { + if (input === "*") { + return input; + } + r.push(input); + } + else { + if (doNotGetIds) { + r = input; + } + else { + if (input.length) { + for (var i = 0, j = input.length; i < j; i++) { + r.push(_info(input[i]).id); + } + } + else { + r.push(_info(input).id); + } + } + } + } + return r; + }, + filterList = function (list, value, missingIsFalse) { + if (list === "*") { + return true; + } + return list.length > 0 ? list.indexOf(value) !== -1 : !missingIsFalse; + }; + + // get some connections, specifying source/target/scope + this.getConnections = function (options, flat) { + if (!options) { + options = {}; + } else if (options.constructor === String) { + options = { "scope": options }; + } + var scope = options.scope || _currentInstance.getDefaultScope(), + scopes = prepareList(scope, true), + sources = prepareList(options.source), + targets = prepareList(options.target), + results = (!flat && scopes.length > 1) ? {} : [], + _addOne = function (scope, obj) { + if (!flat && scopes.length > 1) { + var ss = results[scope]; + if (ss == null) { + ss = results[scope] = []; + } + ss.push(obj); + } else { + results.push(obj); + } + }; + + for (var j = 0, jj = connections.length; j < jj; j++) { + var c = connections[j], + sourceId = c.proxies && c.proxies[0] ? c.proxies[0].originalEp.elementId : c.sourceId, + targetId = c.proxies && c.proxies[1] ? c.proxies[1].originalEp.elementId : c.targetId; + + if (filterList(scopes, c.scope) && filterList(sources, sourceId) && filterList(targets, targetId)) { + _addOne(c.scope, c); + } + } + + return results; + }; + + var _curryEach = function (list, executor) { + return function (f) { + for (var i = 0, ii = list.length; i < ii; i++) { + f(list[i]); + } + return executor(list); + }; + }, + _curryGet = function (list) { + return function (idx) { + return list[idx]; + }; + }; + + var _makeCommonSelectHandler = function (list, executor) { + var out = { + length: list.length, + each: _curryEach(list, executor), + get: _curryGet(list) + }, + setters = ["setHover", "removeAllOverlays", "setLabel", "addClass", "addOverlay", "removeOverlay", + "removeOverlays", "showOverlay", "hideOverlay", "showOverlays", "hideOverlays", "setPaintStyle", + "setHoverPaintStyle", "setSuspendEvents", "setParameter", "setParameters", "setVisible", + "repaint", "addType", "toggleType", "removeType", "removeClass", "setType", "bind", "unbind" ], + + getters = ["getLabel", "getOverlay", "isHover", "getParameter", "getParameters", "getPaintStyle", + "getHoverPaintStyle", "isVisible", "hasType", "getType", "isSuspendEvents" ], + i, ii; + + for (i = 0, ii = setters.length; i < ii; i++) { + out[setters[i]] = setter(list, setters[i], executor); + } + + for (i = 0, ii = getters.length; i < ii; i++) { + out[getters[i]] = getter(list, getters[i]); + } + + return out; + }; + + var _makeConnectionSelectHandler = function (list) { + var common = _makeCommonSelectHandler(list, _makeConnectionSelectHandler); + return jsPlumb.extend(common, { + // setters + setDetachable: setter(list, "setDetachable", _makeConnectionSelectHandler), + setReattach: setter(list, "setReattach", _makeConnectionSelectHandler), + setConnector: setter(list, "setConnector", _makeConnectionSelectHandler), + delete: function () { + for (var i = 0, ii = list.length; i < ii; i++) { + _currentInstance.deleteConnection(list[i]); + } + }, + // getters + isDetachable: getter(list, "isDetachable"), + isReattach: getter(list, "isReattach") + }); + }; + + var _makeEndpointSelectHandler = function (list) { + var common = _makeCommonSelectHandler(list, _makeEndpointSelectHandler); + return jsPlumb.extend(common, { + setEnabled: setter(list, "setEnabled", _makeEndpointSelectHandler), + setAnchor: setter(list, "setAnchor", _makeEndpointSelectHandler), + isEnabled: getter(list, "isEnabled"), + deleteEveryConnection: function () { + for (var i = 0, ii = list.length; i < ii; i++) { + list[i].deleteEveryConnection(); + } + }, + "delete": function () { + for (var i = 0, ii = list.length; i < ii; i++) { + _currentInstance.deleteEndpoint(list[i]); + } + } + }); + }; + + this.select = function (params) { + params = params || {}; + params.scope = params.scope || "*"; + return _makeConnectionSelectHandler(params.connections || _currentInstance.getConnections(params, true)); + }; + + this.selectEndpoints = function (params) { + params = params || {}; + params.scope = params.scope || "*"; + var noElementFilters = !params.element && !params.source && !params.target, + elements = noElementFilters ? "*" : prepareList(params.element), + sources = noElementFilters ? "*" : prepareList(params.source), + targets = noElementFilters ? "*" : prepareList(params.target), + scopes = prepareList(params.scope, true); + + var ep = []; + + for (var el in endpointsByElement) { + var either = filterList(elements, el, true), + source = filterList(sources, el, true), + sourceMatchExact = sources !== "*", + target = filterList(targets, el, true), + targetMatchExact = targets !== "*"; + + // if they requested 'either' then just match scope. otherwise if they requested 'source' (not as a wildcard) then we have to match only endpoints that have isSource set to to true, and the same thing with isTarget. + if (either || source || target) { + inner: + for (var i = 0, ii = endpointsByElement[el].length; i < ii; i++) { + var _ep = endpointsByElement[el][i]; + if (filterList(scopes, _ep.scope, true)) { + + var noMatchSource = (sourceMatchExact && sources.length > 0 && !_ep.isSource), + noMatchTarget = (targetMatchExact && targets.length > 0 && !_ep.isTarget); + + if (noMatchSource || noMatchTarget) { + continue inner; + } + + ep.push(_ep); + } + } + } + } + + return _makeEndpointSelectHandler(ep); + }; + + // get all connections managed by the instance of jsplumb. + this.getAllConnections = function () { + return connections; + }; + this.getDefaultScope = function () { + return DEFAULT_SCOPE; + }; + // get an endpoint by uuid. + this.getEndpoint = _getEndpoint; + /** + * Gets the list of Endpoints for a given element. + * @method getEndpoints + * @param {String|Element|Selector} el The element to get endpoints for. + * @return {Endpoint[]} An array of Endpoints for the specified element. + */ + this.getEndpoints = function (el) { + return endpointsByElement[_info(el).id] || []; + }; + // gets the default endpoint type. used when subclassing. see wiki. + this.getDefaultEndpointType = function () { + return jsPlumb.Endpoint; + }; + // gets the default connection type. used when subclassing. see wiki. + this.getDefaultConnectionType = function () { + return jsPlumb.Connection; + }; + /* + * Gets an element's id, creating one if necessary. really only exposed + * for the lib-specific functionality to access; would be better to pass + * the current instance into the lib-specific code (even though this is + * a static call. i just don't want to expose it to the public API). + */ + this.getId = _getId; + this.draw = _draw; + this.info = _info; + + this.appendElement = _appendElement; + + var _hoverSuspended = false; + this.isHoverSuspended = function () { + return _hoverSuspended; + }; + this.setHoverSuspended = function (s) { + _hoverSuspended = s; + }; + + // set an element's connections to be hidden + this.hide = function (el, changeEndpoints) { + _setVisible(el, "none", changeEndpoints); + return _currentInstance; + }; + + // exposed for other objects to use to get a unique id. + this.idstamp = _idstamp; + + // ensure that, if the current container exists, it is a DOM element and not a selector. + // if it does not exist and `candidate` is supplied, the offset parent of that element will be set as the Container. + // this is used to do a better default behaviour for the case that the user has not set a container: + // addEndpoint, makeSource, makeTarget and connect all call this method with the offsetParent of the + // element in question (for connect it is the source element). So if no container is set, it is inferred + // to be the offsetParent of the first element the user tries to connect. + var _ensureContainer = function (candidate) { + if (!_container && candidate) { + var can = _currentInstance.getElement(candidate); + if (can.offsetParent) { + _currentInstance.setContainer(can.offsetParent); + } + } + }; + + var _getContainerFromDefaults = function () { + if (_currentInstance.Defaults.Container) { + _currentInstance.setContainer(_currentInstance.Defaults.Container); + } + }; + + // check if a given element is managed or not. if not, add to our map. if drawing is not suspended then + // we'll also stash its dimensions; otherwise we'll do this in a lazy way through updateOffset. + var _manage = _currentInstance.manage = function (id, element, _transient) { + if (!managedElements[id]) { + managedElements[id] = { + el: element, + endpoints: [], + connections: [] + }; + + managedElements[id].info = _updateOffset({ elId: id, timestamp: _suspendedAt }); + _currentInstance.addClass(element, "jtk-managed"); + + if (!_transient) { + _currentInstance.fire("manageElement", { id:id, info:managedElements[id].info, el:element }); + } + } + + return managedElements[id]; + }; + + var _unmanage = _currentInstance.unmanage = function(id) { + if (managedElements[id]) { + var el = managedElements[id].el; + _currentInstance.removeClass(el, "jtk-managed"); + delete managedElements[id]; + _currentInstance.fire("unmanageElement", {id:id, el:el}); + } + }; + + /** + * updates the offset and size for a given element, and stores the + * values. if 'offset' is not null we use that (it would have been + * passed in from a drag call) because it's faster; but if it is null, + * or if 'recalc' is true in order to force a recalculation, we get the current values. + * @method updateOffset + */ + var _updateOffset = function (params) { + + var timestamp = params.timestamp, recalc = params.recalc, offset = params.offset, elId = params.elId, s; + if (_suspendDrawing && !timestamp) { + timestamp = _suspendedAt; + } + if (!recalc) { + if (timestamp && timestamp === offsetTimestamps[elId]) { + return {o: params.offset || offsets[elId], s: sizes[elId]}; + } + } + if (recalc || (!offset && offsets[elId] == null)) { // if forced repaint or no offset available, we recalculate. + + // get the current size and offset, and store them + s = managedElements[elId] ? managedElements[elId].el : null; + if (s != null) { + sizes[elId] = _currentInstance.getSize(s); + offsets[elId] = _currentInstance.getOffset(s); + offsetTimestamps[elId] = timestamp; + } + } else { + offsets[elId] = offset || offsets[elId]; + if (sizes[elId] == null) { + s = managedElements[elId].el; + if (s != null) { + sizes[elId] = _currentInstance.getSize(s); + } + } + offsetTimestamps[elId] = timestamp; + } + + if (offsets[elId] && !offsets[elId].right) { + offsets[elId].right = offsets[elId].left + sizes[elId][0]; + offsets[elId].bottom = offsets[elId].top + sizes[elId][1]; + offsets[elId].width = sizes[elId][0]; + offsets[elId].height = sizes[elId][1]; + offsets[elId].centerx = offsets[elId].left + (offsets[elId].width / 2); + offsets[elId].centery = offsets[elId].top + (offsets[elId].height / 2); + } + + return {o: offsets[elId], s: sizes[elId]}; + }; + + this.updateOffset = _updateOffset; + + /** + * callback from the current library to tell us to prepare ourselves (attach + * mouse listeners etc; can't do that until the library has provided a bind method) + */ + this.init = function () { + if (!initialized) { + _getContainerFromDefaults(); + _currentInstance.anchorManager = new root.jsPlumb.AnchorManager({jsPlumbInstance: _currentInstance}); + initialized = true; + _currentInstance.fire("ready", _currentInstance); + } + }.bind(this); + + this.log = log; + this.jsPlumbUIComponent = jsPlumbUIComponent; + + /* + * Creates an anchor with the given params. + * + * + * Returns: The newly created Anchor. + * Throws: an error if a named anchor was not found. + */ + this.makeAnchor = function () { + var pp, _a = function (t, p) { + if (root.jsPlumb.Anchors[t]) { + return new root.jsPlumb.Anchors[t](p); + } + if (!_currentInstance.Defaults.DoNotThrowErrors) { + throw { msg: "jsPlumb: unknown anchor type '" + t + "'" }; + } + }; + if (arguments.length === 0) { + return null; + } + var specimen = arguments[0], elementId = arguments[1], jsPlumbInstance = arguments[2], newAnchor = null; + // if it appears to be an anchor already... + if (specimen.compute && specimen.getOrientation) { + return specimen; + } //TODO hazy here about whether it should be added or is already added somehow. + // is it the name of an anchor type? + else if (typeof specimen === "string") { + newAnchor = _a(arguments[0], {elementId: elementId, jsPlumbInstance: _currentInstance}); + } + // is it an array? it will be one of: + // an array of [spec, params] - this defines a single anchor, which may be dynamic, but has parameters. + // an array of arrays - this defines some dynamic anchors + // an array of numbers - this defines a single anchor. + else if (_ju.isArray(specimen)) { + if (_ju.isArray(specimen[0]) || _ju.isString(specimen[0])) { + // if [spec, params] format + if (specimen.length === 2 && _ju.isObject(specimen[1])) { + // if first arg is a string, its a named anchor with params + if (_ju.isString(specimen[0])) { + pp = root.jsPlumb.extend({elementId: elementId, jsPlumbInstance: _currentInstance}, specimen[1]); + newAnchor = _a(specimen[0], pp); + } + // otherwise first arg is array, second is params. we treat as a dynamic anchor, which is fine + // even if the first arg has only one entry. you could argue all anchors should be implicitly dynamic in fact. + else { + pp = root.jsPlumb.extend({elementId: elementId, jsPlumbInstance: _currentInstance, anchors: specimen[0]}, specimen[1]); + newAnchor = new root.jsPlumb.DynamicAnchor(pp); + } + } + else { + newAnchor = new jsPlumb.DynamicAnchor({anchors: specimen, selector: null, elementId: elementId, jsPlumbInstance: _currentInstance}); + } + + } + else { + var anchorParams = { + x: specimen[0], y: specimen[1], + orientation: (specimen.length >= 4) ? [ specimen[2], specimen[3] ] : [0, 0], + offsets: (specimen.length >= 6) ? [ specimen[4], specimen[5] ] : [ 0, 0 ], + elementId: elementId, + jsPlumbInstance: _currentInstance, + cssClass: specimen.length === 7 ? specimen[6] : null + }; + newAnchor = new root.jsPlumb.Anchor(anchorParams); + newAnchor.clone = function () { + return new root.jsPlumb.Anchor(anchorParams); + }; + } + } + + if (!newAnchor.id) { + newAnchor.id = "anchor_" + _idstamp(); + } + return newAnchor; + }; + + /** + * makes a list of anchors from the given list of types or coords, eg + * ["TopCenter", "RightMiddle", "BottomCenter", [0, 1, -1, -1] ] + */ + this.makeAnchors = function (types, elementId, jsPlumbInstance) { + var r = []; + for (var i = 0, ii = types.length; i < ii; i++) { + if (typeof types[i] === "string") { + r.push(root.jsPlumb.Anchors[types[i]]({elementId: elementId, jsPlumbInstance: jsPlumbInstance})); + } + else if (_ju.isArray(types[i])) { + r.push(_currentInstance.makeAnchor(types[i], elementId, jsPlumbInstance)); + } + } + return r; + }; + + /** + * Makes a dynamic anchor from the given list of anchors (which may be in shorthand notation as strings or dimension arrays, or Anchor + * objects themselves) and the given, optional, anchorSelector function (jsPlumb uses a default if this is not provided; most people will + * not need to provide this - i think). + */ + this.makeDynamicAnchor = function (anchors, anchorSelector) { + return new root.jsPlumb.DynamicAnchor({anchors: anchors, selector: anchorSelector, elementId: null, jsPlumbInstance: _currentInstance}); + }; + +// --------------------- makeSource/makeTarget ---------------------------------------------- + + this.targetEndpointDefinitions = {}; + this.sourceEndpointDefinitions = {}; + + var selectorFilter = function (evt, _el, selector, _instance, negate) { + var t = evt.target || evt.srcElement, ok = false, + sel = _instance.getSelector(_el, selector); + for (var j = 0; j < sel.length; j++) { + if (sel[j] === t) { + ok = true; + break; + } + } + return negate ? !ok : ok; + }; + + var _makeElementDropHandler = function (elInfo, p, dropOptions, isSource, isTarget) { + var proxyComponent = new jsPlumbUIComponent(p); + var _drop = p._jsPlumb.EndpointDropHandler({ + jsPlumb: _currentInstance, + enabled: function () { + return elInfo.def.enabled; + }, + isFull: function () { + var targetCount = _currentInstance.select({target: elInfo.id}).length; + return elInfo.def.maxConnections > 0 && targetCount >= elInfo.def.maxConnections; + }, + element: elInfo.el, + elementId: elInfo.id, + isSource: isSource, + isTarget: isTarget, + addClass: function (clazz) { + _currentInstance.addClass(elInfo.el, clazz); + }, + removeClass: function (clazz) { + _currentInstance.removeClass(elInfo.el, clazz); + }, + onDrop: function (jpc) { + var source = jpc.endpoints[0]; + source.anchor.unlock(); + }, + isDropAllowed: function () { + return proxyComponent.isDropAllowed.apply(proxyComponent, arguments); + }, + isRedrop:function(jpc) { + return (jpc.suspendedElement != null && jpc.suspendedEndpoint != null && jpc.suspendedEndpoint.element === elInfo.el); + }, + getEndpoint: function (jpc) { + + // make a new Endpoint for the target, or get it from the cache if uniqueEndpoint + // is set. if its a redrop the new endpoint will be immediately cleaned up. + + var newEndpoint = elInfo.def.endpoint; + + // if no cached endpoint, or there was one but it has been cleaned up + // (ie. detached), create a new one + if (newEndpoint == null || newEndpoint._jsPlumb == null) { + var eps = _currentInstance.deriveEndpointAndAnchorSpec(jpc.getType().join(" "), true); + var pp = eps.endpoints ? root.jsPlumb.extend(p, { + endpoint:elInfo.def.def.endpoint || eps.endpoints[1] + }) :p; + if (eps.anchors) { + pp = root.jsPlumb.extend(pp, { + anchor:elInfo.def.def.anchor || eps.anchors[1] + }); + } + newEndpoint = _currentInstance.addEndpoint(elInfo.el, pp); + newEndpoint._mtNew = true; + } + + if (p.uniqueEndpoint) { + elInfo.def.endpoint = newEndpoint; + } + + newEndpoint.setDeleteOnEmpty(true); + + // if connection is detachable, init the new endpoint to be draggable, to support that happening. + if (jpc.isDetachable()) { + newEndpoint.initDraggable(); + } + + // if the anchor has a 'positionFinder' set, then delegate to that function to find + // out where to locate the anchor. + if (newEndpoint.anchor.positionFinder != null) { + var dropPosition = _currentInstance.getUIPosition(arguments, _currentInstance.getZoom()), + elPosition = _currentInstance.getOffset(elInfo.el), + elSize = _currentInstance.getSize(elInfo.el), + ap = dropPosition == null ? [0,0] : newEndpoint.anchor.positionFinder(dropPosition, elPosition, elSize, newEndpoint.anchor.constructorParams); + + newEndpoint.anchor.x = ap[0]; + newEndpoint.anchor.y = ap[1]; + // now figure an orientation for it..kind of hard to know what to do actually. probably the best thing i can do is to + // support specifying an orientation in the anchor's spec. if one is not supplied then i will make the orientation + // be what will cause the most natural link to the source: it will be pointing at the source, but it needs to be + // specified in one axis only, and so how to make that choice? i think i will use whichever axis is the one in which + // the target is furthest away from the source. + } + + return newEndpoint; + }, + maybeCleanup: function (ep) { + if (ep._mtNew && ep.connections.length === 0) { + _currentInstance.deleteObject({endpoint: ep}); + } + else { + delete ep._mtNew; + } + } + }); + + // wrap drop events as needed and initialise droppable + var dropEvent = root.jsPlumb.dragEvents.drop; + dropOptions.scope = dropOptions.scope || (p.scope || _currentInstance.Defaults.Scope); + dropOptions[dropEvent] = _ju.wrap(dropOptions[dropEvent], _drop, true); + dropOptions.rank = p.rank || 0; + + // if target, return true from the over event. this will cause katavorio to stop setting drops to hover + // if multipleDrop is set to false. + if (isTarget) { + dropOptions[root.jsPlumb.dragEvents.over] = function () { return true; }; + } + + // vanilla jsplumb only + if (p.allowLoopback === false) { + dropOptions.canDrop = function (_drag) { + var de = _drag.getDragElement()._jsPlumbRelatedElement; + return de !== elInfo.el; + }; + } + _currentInstance.initDroppable(elInfo.el, dropOptions, "internal"); + + return _drop; + + }; + + // see API docs + this.makeTarget = function (el, params, referenceParams) { + + // put jsplumb ref into params without altering the params passed in + var p = root.jsPlumb.extend({_jsPlumb: this}, referenceParams); + root.jsPlumb.extend(p, params); + + var maxConnections = p.maxConnections || -1, + + _doOne = function (el) { + + // get the element's id and store the endpoint definition for it. jsPlumb.connect calls will look for one of these, + // and use the endpoint definition if found. + // decode the info for this element (id and element) + var elInfo = _info(el), + elid = elInfo.id, + dropOptions = root.jsPlumb.extend({}, p.dropOptions || {}), + type = p.connectionType || "default"; + + this.targetEndpointDefinitions[elid] = this.targetEndpointDefinitions[elid] || {}; + + _ensureContainer(elid); + + // if this is a group and the user has not mandated a rank, set to -1 so that Nodes takes + // precedence. + if (elInfo.el._isJsPlumbGroup && dropOptions.rank == null) { + dropOptions.rank = -1; + } + + // store the definition + var _def = { + def: root.jsPlumb.extend({}, p), + uniqueEndpoint: p.uniqueEndpoint, + maxConnections: maxConnections, + enabled: true + }; + + if (p.createEndpoint) { + _def.uniqueEndpoint = true; + _def.endpoint = _currentInstance.addEndpoint(el, _def.def); + _def.endpoint.setDeleteOnEmpty(false); + } + + elInfo.def = _def; + this.targetEndpointDefinitions[elid][type] = _def; + _makeElementDropHandler(elInfo, p, dropOptions, p.isSource === true, true); + // stash the definition on the drop + elInfo.el._katavorioDrop[elInfo.el._katavorioDrop.length - 1].targetDef = _def; + + }.bind(this); + + // make an array if only given one element + var inputs = el.length && el.constructor !== String ? el : [ el ]; + + // register each one in the list. + for (var i = 0, ii = inputs.length; i < ii; i++) { + _doOne(inputs[i]); + } + + return this; + }; + + // see api docs + this.unmakeTarget = function (el, doNotClearArrays) { + var info = _info(el); + _currentInstance.destroyDroppable(info.el, "internal"); + if (!doNotClearArrays) { + delete this.targetEndpointDefinitions[info.id]; + } + + return this; + }; + + // see api docs + this.makeSource = function (el, params, referenceParams) { + var p = root.jsPlumb.extend({_jsPlumb: this}, referenceParams); + root.jsPlumb.extend(p, params); + var type = p.connectionType || "default"; + var aae = _currentInstance.deriveEndpointAndAnchorSpec(type); + p.endpoint = p.endpoint || aae.endpoints[0]; + p.anchor = p.anchor || aae.anchors[0]; + var maxConnections = p.maxConnections || -1, + onMaxConnections = p.onMaxConnections, + _doOne = function (elInfo) { + // get the element's id and store the endpoint definition for it. jsPlumb.connect calls will look for one of these, + // and use the endpoint definition if found. + var elid = elInfo.id, + _del = this.getElement(elInfo.el); + + this.sourceEndpointDefinitions[elid] = this.sourceEndpointDefinitions[elid] || {}; + _ensureContainer(elid); + + var _def = { + def:root.jsPlumb.extend({}, p), + uniqueEndpoint: p.uniqueEndpoint, + maxConnections: maxConnections, + enabled: true + }; + + if (p.createEndpoint) { + _def.uniqueEndpoint = true; + _def.endpoint = _currentInstance.addEndpoint(el, _def.def); + _def.endpoint.setDeleteOnEmpty(false); + } + + this.sourceEndpointDefinitions[elid][type] = _def; + elInfo.def = _def; + + var stopEvent = root.jsPlumb.dragEvents.stop, + dragEvent = root.jsPlumb.dragEvents.drag, + dragOptions = root.jsPlumb.extend({ }, p.dragOptions || {}), + existingDrag = dragOptions.drag, + existingStop = dragOptions.stop, + ep = null, + endpointAddedButNoDragYet = false; + + // set scope if its not set in dragOptions but was passed in in params + dragOptions.scope = dragOptions.scope || p.scope; + + dragOptions[dragEvent] = _ju.wrap(dragOptions[dragEvent], function () { + if (existingDrag) { + existingDrag.apply(this, arguments); + } + endpointAddedButNoDragYet = false; + }); + + dragOptions[stopEvent] = _ju.wrap(dragOptions[stopEvent], function () { + + if (existingStop) { + existingStop.apply(this, arguments); + } + this.currentlyDragging = false; + if (ep._jsPlumb != null) { // if not cleaned up... + + // reset the anchor to the anchor that was initially provided. the one we were using to drag + // the connection was just a placeholder that was located at the place the user pressed the + // mouse button to initiate the drag. + var anchorDef = p.anchor || this.Defaults.Anchor, + oldAnchor = ep.anchor, + oldConnection = ep.connections[0]; + + var newAnchor = this.makeAnchor(anchorDef, elid, this), + _el = ep.element; + + // if the anchor has a 'positionFinder' set, then delegate to that function to find + // out where to locate the anchor. issue 117. + if (newAnchor.positionFinder != null) { + var elPosition = _currentInstance.getOffset(_el), + elSize = this.getSize(_el), + dropPosition = { left: elPosition.left + (oldAnchor.x * elSize[0]), top: elPosition.top + (oldAnchor.y * elSize[1]) }, + ap = newAnchor.positionFinder(dropPosition, elPosition, elSize, newAnchor.constructorParams); + + newAnchor.x = ap[0]; + newAnchor.y = ap[1]; + } + + ep.setAnchor(newAnchor, true); + ep.repaint(); + this.repaint(ep.elementId); + if (oldConnection != null) { + this.repaint(oldConnection.targetId); + } + } + }.bind(this)); + + // when the user presses the mouse, add an Endpoint, if we are enabled. + var mouseDownListener = function (e) { + // on right mouse button, abort. + if (e.which === 3 || e.button === 2) { + return; + } + + // TODO store def on element. + var def = this.sourceEndpointDefinitions[elid][type]; + + // if disabled, return. + if (!def.enabled) { + return; + } + + elid = this.getId(this.getElement(elInfo.el)); // elid might have changed since this method was called to configure the element. + + // if a filter was given, run it, and return if it says no. + if (p.filter) { + var r = _ju.isString(p.filter) ? selectorFilter(e, elInfo.el, p.filter, this, p.filterExclude) : p.filter(e, elInfo.el); + if (r === false) { + return; + } + } + + // if maxConnections reached + var sourceCount = this.select({source: elid}).length; + if (def.maxConnections >= 0 && (sourceCount >= def.maxConnections)) { + if (onMaxConnections) { + onMaxConnections({ + element: elInfo.el, + maxConnections: maxConnections + }, e); + } + return false; + } + + // find the position on the element at which the mouse was pressed; this is where the endpoint + // will be located. + var elxy = root.jsPlumb.getPositionOnElement(e, _del, _zoom); + + // we need to override the anchor in here, and force 'isSource', but we don't want to mess with + // the params passed in, because after a connection is established we're going to reset the endpoint + // to have the anchor we were given. + var tempEndpointParams = {}; + root.jsPlumb.extend(tempEndpointParams, def.def); + tempEndpointParams.isTemporarySource = true; + tempEndpointParams.anchor = [ elxy[0], elxy[1] , 0, 0]; + tempEndpointParams.dragOptions = dragOptions; + + if (def.def.scope) { + tempEndpointParams.scope = def.def.scope; + } + + ep = this.addEndpoint(elid, tempEndpointParams); + endpointAddedButNoDragYet = true; + ep.setDeleteOnEmpty(true); + + // if unique endpoint and it's already been created, push it onto the endpoint we create. at the end + // of a successful connection we'll switch to that endpoint. + // TODO this is the same code as the programmatic endpoints create on line 1050 ish + if (def.uniqueEndpoint) { + if (!def.endpoint) { + def.endpoint = ep; + ep.setDeleteOnEmpty(false); + } + else { + ep.finalEndpoint = def.endpoint; + } + } + + var _delTempEndpoint = function () { + // this mouseup event is fired only if no dragging occurred, by jquery and yui, but for mootools + // it is fired even if dragging has occurred, in which case we would blow away a perfectly + // legitimate endpoint, were it not for this check. the flag is set after adding an + // endpoint and cleared in a drag listener we set in the dragOptions above. + _currentInstance.off(ep.canvas, "mouseup", _delTempEndpoint); + _currentInstance.off(elInfo.el, "mouseup", _delTempEndpoint); + if (endpointAddedButNoDragYet) { + endpointAddedButNoDragYet = false; + _currentInstance.deleteEndpoint(ep); + } + }; + + _currentInstance.on(ep.canvas, "mouseup", _delTempEndpoint); + _currentInstance.on(elInfo.el, "mouseup", _delTempEndpoint); + + // optionally check for attributes to extract from the source element + var payload = {}; + if (def.def.extract) { + for (var att in def.def.extract) { + var v = (e.srcElement || e.target).getAttribute(att); + if (v) { + payload[def.def.extract[att]] = v; + } + } + } + + // and then trigger its mousedown event, which will kick off a drag, which will start dragging + // a new connection from this endpoint. + _currentInstance.trigger(ep.canvas, "mousedown", e, payload); + + _ju.consume(e); + + }.bind(this); + + this.on(elInfo.el, "mousedown", mouseDownListener); + _def.trigger = mouseDownListener; + + // if a filter was provided, set it as a dragFilter on the element, + // to prevent the element drag function from kicking in when we want to + // drag a new connection + if (p.filter && (_ju.isString(p.filter) || _ju.isFunction(p.filter))) { + _currentInstance.setDragFilter(elInfo.el, p.filter); + } + + var dropOptions = root.jsPlumb.extend({}, p.dropOptions || {}); + + _makeElementDropHandler(elInfo, p, dropOptions, true, p.isTarget === true); + + }.bind(this); + + var inputs = el.length && el.constructor !== String ? el : [ el ]; + for (var i = 0, ii = inputs.length; i < ii; i++) { + _doOne(_info(inputs[i])); + } + + return this; + }; + + // see api docs + this.unmakeSource = function (el, connectionType, doNotClearArrays) { + var info = _info(el); + _currentInstance.destroyDroppable(info.el, "internal"); + var eldefs = this.sourceEndpointDefinitions[info.id]; + if (eldefs) { + for (var def in eldefs) { + if (connectionType == null || connectionType === def) { + var mouseDownListener = eldefs[def].trigger; + if (mouseDownListener) { + _currentInstance.off(info.el, "mousedown", mouseDownListener); + } + if (!doNotClearArrays) { + delete this.sourceEndpointDefinitions[info.id][def]; + } + } + } + } + + return this; + }; + + // see api docs + this.unmakeEverySource = function () { + for (var i in this.sourceEndpointDefinitions) { + _currentInstance.unmakeSource(i, null, true); + } + + this.sourceEndpointDefinitions = {}; + return this; + }; + + var _getScope = function (el, types, connectionType) { + types = _ju.isArray(types) ? types : [ types ]; + var id = _getId(el); + connectionType = connectionType || "default"; + for (var i = 0; i < types.length; i++) { + var eldefs = this[types[i]][id]; + if (eldefs && eldefs[connectionType]) { + return eldefs[connectionType].def.scope || this.Defaults.Scope; + } + } + }.bind(this); + + var _setScope = function (el, scope, types, connectionType) { + types = _ju.isArray(types) ? types : [ types ]; + var id = _getId(el); + connectionType = connectionType || "default"; + for (var i = 0; i < types.length; i++) { + var eldefs = this[types[i]][id]; + if (eldefs && eldefs[connectionType]) { + eldefs[connectionType].def.scope = scope; + } + } + + }.bind(this); + + this.getScope = function (el, scope) { + return _getScope(el, [ "sourceEndpointDefinitions", "targetEndpointDefinitions" ]); + }; + this.getSourceScope = function (el) { + return _getScope(el, "sourceEndpointDefinitions"); + }; + this.getTargetScope = function (el) { + return _getScope(el, "targetEndpointDefinitions"); + }; + this.setScope = function (el, scope, connectionType) { + this.setSourceScope(el, scope, connectionType); + this.setTargetScope(el, scope, connectionType); + }; + this.setSourceScope = function (el, scope, connectionType) { + _setScope(el, scope, "sourceEndpointDefinitions", connectionType); + // we get the source scope during the mousedown event, but we also want to set this. + this.setDragScope(el, scope); + }; + this.setTargetScope = function (el, scope, connectionType) { + _setScope(el, scope, "targetEndpointDefinitions", connectionType); + this.setDropScope(el, scope); + }; + + // see api docs + this.unmakeEveryTarget = function () { + for (var i in this.targetEndpointDefinitions) { + _currentInstance.unmakeTarget(i, true); + } + + this.targetEndpointDefinitions = {}; + return this; + }; + + // does the work of setting a source enabled or disabled. + var _setEnabled = function (type, el, state, toggle, connectionType) { + var a = type === "source" ? this.sourceEndpointDefinitions : this.targetEndpointDefinitions, + originalState, info, newState; + + connectionType = connectionType || "default"; + + // a selector or an array + if (el.length && !_ju.isString(el)) { + originalState = []; + for (var i = 0, ii = el.length; i < ii; i++) { + info = _info(el[i]); + if (a[info.id] && a[info.id][connectionType]) { + originalState[i] = a[info.id][connectionType].enabled; + newState = toggle ? !originalState[i] : state; + a[info.id][connectionType].enabled = newState; + _currentInstance[newState ? "removeClass" : "addClass"](info.el, "jtk-" + type + "-disabled"); + } + } + } + // otherwise a DOM element or a String ID. + else { + info = _info(el); + var id = info.id; + if (a[id] && a[id][connectionType]) { + originalState = a[id][connectionType].enabled; + newState = toggle ? !originalState : state; + a[id][connectionType].enabled = newState; + _currentInstance[newState ? "removeClass" : "addClass"](info.el, "jtk-" + type + "-disabled"); + } + } + return originalState; + }.bind(this); + + var _first = function (el, fn) { + if (_ju.isString(el) || !el.length) { + return fn.apply(this, [ el ]); + } + else if (el.length) { + return fn.apply(this, [ el[0] ]); + } + + }.bind(this); + + this.toggleSourceEnabled = function (el, connectionType) { + _setEnabled("source", el, null, true, connectionType); + return this.isSourceEnabled(el, connectionType); + }; + + this.setSourceEnabled = function (el, state, connectionType) { + return _setEnabled("source", el, state, null, connectionType); + }; + this.isSource = function (el, connectionType) { + connectionType = connectionType || "default"; + return _first(el, function (_el) { + var eldefs = this.sourceEndpointDefinitions[_info(_el).id]; + return eldefs != null && eldefs[connectionType] != null; + }.bind(this)); + }; + this.isSourceEnabled = function (el, connectionType) { + connectionType = connectionType || "default"; + return _first(el, function (_el) { + var sep = this.sourceEndpointDefinitions[_info(_el).id]; + return sep && sep[connectionType] && sep[connectionType].enabled === true; + }.bind(this)); + }; + + this.toggleTargetEnabled = function (el, connectionType) { + _setEnabled("target", el, null, true, connectionType); + return this.isTargetEnabled(el, connectionType); + }; + + this.isTarget = function (el, connectionType) { + connectionType = connectionType || "default"; + return _first(el, function (_el) { + var eldefs = this.targetEndpointDefinitions[_info(_el).id]; + return eldefs != null && eldefs[connectionType] != null; + }.bind(this)); + }; + this.isTargetEnabled = function (el, connectionType) { + connectionType = connectionType || "default"; + return _first(el, function (_el) { + var tep = this.targetEndpointDefinitions[_info(_el).id]; + return tep && tep[connectionType] && tep[connectionType].enabled === true; + }.bind(this)); + }; + this.setTargetEnabled = function (el, state, connectionType) { + return _setEnabled("target", el, state, null, connectionType); + }; + +// --------------------- end makeSource/makeTarget ---------------------------------------------- + + this.ready = function (fn) { + _currentInstance.bind("ready", fn); + }; + + var _elEach = function(el, fn) { + // support both lists... + if (typeof el === 'object' && el.length) { + for (var i = 0, ii = el.length; i < ii; i++) { + fn(el[i]); + } + } + else {// ...and single strings or elements. + fn(el); + } + + return _currentInstance; + }; + + // repaint some element's endpoints and connections + this.repaint = function (el, ui, timestamp) { + return _elEach(el, function(_el) { + _draw(_el, ui, timestamp); + }); + }; + + this.revalidate = function (el, timestamp, isIdAlready) { + return _elEach(el, function(_el) { + var elId = isIdAlready ? _el : _currentInstance.getId(_el); + _currentInstance.updateOffset({ elId: elId, recalc: true, timestamp:timestamp }); + var dm = _currentInstance.getDragManager(); + if (dm) { + dm.updateOffsets(elId); + } + _currentInstance.repaint(_el); + }); + }; + + // repaint every endpoint and connection. + this.repaintEverything = function () { + // TODO this timestamp causes continuous anchors to not repaint properly. + // fix this. do not just take out the timestamp. it runs a lot faster with + // the timestamp included. + var timestamp = _timestamp(), elId; + + for (elId in endpointsByElement) { + _currentInstance.updateOffset({ elId: elId, recalc: true, timestamp: timestamp }); + } + + for (elId in endpointsByElement) { + _draw(elId, null, timestamp); + } + + return this; + }; + + this.removeAllEndpoints = function (el, recurse, affectedElements) { + affectedElements = affectedElements || []; + var _one = function (_el) { + var info = _info(_el), + ebe = endpointsByElement[info.id], + i, ii; + + if (ebe) { + affectedElements.push(info); + for (i = 0, ii = ebe.length; i < ii; i++) { + _currentInstance.deleteEndpoint(ebe[i], false); + } + } + delete endpointsByElement[info.id]; + + if (recurse) { + if (info.el && info.el.nodeType !== 3 && info.el.nodeType !== 8) { + for (i = 0, ii = info.el.childNodes.length; i < ii; i++) { + _one(info.el.childNodes[i]); + } + } + } + + }; + _one(el); + return this; + }; + + var _doRemove = function(info, affectedElements) { + _currentInstance.removeAllEndpoints(info.id, true, affectedElements); + var dm = _currentInstance.getDragManager(); + var _one = function(_info) { + + if (dm) { + dm.elementRemoved(_info.id); + } + _currentInstance.anchorManager.clearFor(_info.id); + _currentInstance.anchorManager.removeFloatingConnection(_info.id); + + if (_currentInstance.isSource(_info.el)) { + _currentInstance.unmakeSource(_info.el); + } + if (_currentInstance.isTarget(_info.el)) { + _currentInstance.unmakeTarget(_info.el); + } + _currentInstance.destroyDraggable(_info.el); + _currentInstance.destroyDroppable(_info.el); + + + delete _currentInstance.floatingConnections[_info.id]; + delete managedElements[_info.id]; + delete offsets[_info.id]; + if (_info.el) { + _currentInstance.removeElement(_info.el); + _info.el._jsPlumb = null; + } + }; + + // remove all affected child elements + for (var ae = 1; ae < affectedElements.length; ae++) { + _one(affectedElements[ae]); + } + // and always remove the requested one from the dom. + _one(info); + }; + + /** + * Remove the given element, including cleaning up all endpoints registered for it. + * This is exposed in the public API but also used internally by jsPlumb when removing the + * element associated with a connection drag. + */ + this.remove = function (el, doNotRepaint) { + var info = _info(el), affectedElements = []; + if (info.text && info.el.parentNode) { + info.el.parentNode.removeChild(info.el); + } + else if (info.id) { + _currentInstance.batch(function () { + _doRemove(info, affectedElements); + }, doNotRepaint === true); + } + return _currentInstance; + }; + + this.empty = function (el, doNotRepaint) { + var affectedElements = []; + var _one = function(el, dontRemoveFocus) { + var info = _info(el); + if (info.text) { + info.el.parentNode.removeChild(info.el); + } + else if (info.el) { + while(info.el.childNodes.length > 0) { + _one(info.el.childNodes[0]); + } + if (!dontRemoveFocus) { + _doRemove(info, affectedElements); + } + } + }; + + _currentInstance.batch(function() { + _one(el, true); + }, doNotRepaint === false); + + return _currentInstance; + }; + + this.reset = function (doNotUnbindInstanceEventListeners) { + _currentInstance.silently(function() { + _hoverSuspended = false; + _currentInstance.removeAllGroups(); + _currentInstance.removeGroupManager(); + _currentInstance.deleteEveryEndpoint(); + if (!doNotUnbindInstanceEventListeners) { + _currentInstance.unbind(); + } + this.targetEndpointDefinitions = {}; + this.sourceEndpointDefinitions = {}; + connections.length = 0; + if (this.doReset) { + this.doReset(); + } + }.bind(this)); + }; + + var _clearObject = function (obj) { + if (obj.canvas && obj.canvas.parentNode) { + obj.canvas.parentNode.removeChild(obj.canvas); + } + obj.cleanup(); + obj.destroy(); + }; + + this.clear = function () { + _currentInstance.select().each(_clearObject); + _currentInstance.selectEndpoints().each(_clearObject); + + endpointsByElement = {}; + endpointsByUUID = {}; + }; + + this.setDefaultScope = function (scope) { + DEFAULT_SCOPE = scope; + return _currentInstance; + }; + + this.deriveEndpointAndAnchorSpec = function(type, dontPrependDefault) { + var bits = ((dontPrependDefault ? "" : "default ") + type).split(/[\s]/), eps = null, ep = null, a = null, as = null; + for (var i = 0; i < bits.length; i++) { + var _t = _currentInstance.getType(bits[i], "connection"); + if (_t) { + if (_t.endpoints) { + eps = _t.endpoints; + } + if (_t.endpoint) { + ep = _t.endpoint; + } + if (_t.anchors) { + as = _t.anchors; + } + if (_t.anchor) { + a = _t.anchor; + } + } + } + return { endpoints: eps ? eps : [ ep, ep ], anchors: as ? as : [a, a ]}; + }; + + // sets the id of some element, changing whatever we need to to keep track. + this.setId = function (el, newId, doNotSetAttribute) { + // + var id; + + if (_ju.isString(el)) { + id = el; + } + else { + el = this.getElement(el); + id = this.getId(el); + } + + var sConns = this.getConnections({source: id, scope: '*'}, true), + tConns = this.getConnections({target: id, scope: '*'}, true); + + newId = "" + newId; + + if (!doNotSetAttribute) { + el = this.getElement(id); + this.setAttribute(el, "id", newId); + } + else { + el = this.getElement(newId); + } + + endpointsByElement[newId] = endpointsByElement[id] || []; + for (var i = 0, ii = endpointsByElement[newId].length; i < ii; i++) { + endpointsByElement[newId][i].setElementId(newId); + endpointsByElement[newId][i].setReferenceElement(el); + } + delete endpointsByElement[id]; + + this.sourceEndpointDefinitions[newId] = this.sourceEndpointDefinitions[id]; + delete this.sourceEndpointDefinitions[id]; + this.targetEndpointDefinitions[newId] = this.targetEndpointDefinitions[id]; + delete this.targetEndpointDefinitions[id]; + + this.anchorManager.changeId(id, newId); + var dm = this.getDragManager(); + if (dm) { + dm.changeId(id, newId); + } + managedElements[newId] = managedElements[id]; + delete managedElements[id]; + + var _conns = function (list, epIdx, type) { + for (var i = 0, ii = list.length; i < ii; i++) { + list[i].endpoints[epIdx].setElementId(newId); + list[i].endpoints[epIdx].setReferenceElement(el); + list[i][type + "Id"] = newId; + list[i][type] = el; + } + }; + _conns(sConns, 0, "source"); + _conns(tConns, 1, "target"); + + this.repaint(newId); + }; + + this.setDebugLog = function (debugLog) { + log = debugLog; + }; + + this.setSuspendDrawing = function (val, repaintAfterwards) { + var curVal = _suspendDrawing; + _suspendDrawing = val; + if (val) { + _suspendedAt = new Date().getTime(); + } else { + _suspendedAt = null; + } + if (repaintAfterwards) { + this.repaintEverything(); + } + return curVal; + }; + + // returns whether or not drawing is currently suspended. + this.isSuspendDrawing = function () { + return _suspendDrawing; + }; + + // return timestamp for when drawing was suspended. + this.getSuspendedAt = function () { + return _suspendedAt; + }; + + this.batch = function (fn, doNotRepaintAfterwards) { + var _wasSuspended = this.isSuspendDrawing(); + if (!_wasSuspended) { + this.setSuspendDrawing(true); + } + try { + fn(); + } + catch (e) { + _ju.log("Function run while suspended failed", e); + } + if (!_wasSuspended) { + this.setSuspendDrawing(false, !doNotRepaintAfterwards); + } + }; + + this.doWhileSuspended = this.batch; + + this.getCachedData = _getCachedData; + this.timestamp = _timestamp; + this.show = function (el, changeEndpoints) { + _setVisible(el, "block", changeEndpoints); + return _currentInstance; + }; + + // TODO: update this method to return the current state. + this.toggleVisible = _toggleVisible; + this.addListener = this.bind; + + var floatingConnections = []; + this.registerFloatingConnection = function(info, conn, ep) { + floatingConnections[info.id] = conn; + // only register for the target endpoint; we will not be dragging the source at any time + // before this connection is either discarded or made into a permanent connection. + _ju.addToList(endpointsByElement, info.id, ep); + }; + this.getFloatingConnectionFor = function(id) { + return floatingConnections[id]; + }; + + this.listManager = new root.jsPlumbListManager(this); + }; + + _ju.extend(root.jsPlumbInstance, _ju.EventGenerator, { + setAttribute: function (el, a, v) { + this.setAttribute(el, a, v); + }, + getAttribute: function (el, a) { + return this.getAttribute(root.jsPlumb.getElement(el), a); + }, + convertToFullOverlaySpec: function(spec) { + if (_ju.isString(spec)) { + spec = [ spec, { } ]; + } + spec[1].id = spec[1].id || _ju.uuid(); + return spec; + }, + registerConnectionType: function (id, type) { + this._connectionTypes[id] = root.jsPlumb.extend({}, type); + if (type.overlays) { + var to = {}; + for (var i = 0; i < type.overlays.length; i++) { + // if a string, convert to object representation so that we can store the typeid on it. + // also assign an id. + var fo = this.convertToFullOverlaySpec(type.overlays[i]); + to[fo[1].id] = fo; + } + this._connectionTypes[id].overlays = to; + } + }, + registerConnectionTypes: function (types) { + for (var i in types) { + this.registerConnectionType(i, types[i]); + } + }, + registerEndpointType: function (id, type) { + this._endpointTypes[id] = root.jsPlumb.extend({}, type); + if (type.overlays) { + var to = {}; + for (var i = 0; i < type.overlays.length; i++) { + // if a string, convert to object representation so that we can store the typeid on it. + // also assign an id. + var fo = this.convertToFullOverlaySpec(type.overlays[i]); + to[fo[1].id] = fo; + } + this._endpointTypes[id].overlays = to; + } + }, + registerEndpointTypes: function (types) { + for (var i in types) { + this.registerEndpointType(i, types[i]); + } + }, + getType: function (id, typeDescriptor) { + return typeDescriptor === "connection" ? this._connectionTypes[id] : this._endpointTypes[id]; + }, + setIdChanged: function (oldId, newId) { + this.setId(oldId, newId, true); + }, + // set parent: change the parent for some node and update all the registrations we need to. + setParent: function (el, newParent) { + var _dom = this.getElement(el), + _id = this.getId(_dom), + _pdom = this.getElement(newParent), + _pid = this.getId(_pdom), + dm = this.getDragManager(); + + _dom.parentNode.removeChild(_dom); + _pdom.appendChild(_dom); + if (dm) { + dm.setParent(_dom, _id, _pdom, _pid); + } + }, + extend: function (o1, o2, names) { + var i; + if (names) { + for (i = 0; i < names.length; i++) { + o1[names[i]] = o2[names[i]]; + } + } + else { + for (i in o2) { + o1[i] = o2[i]; + } + } + + return o1; + }, + floatingConnections: {}, + getFloatingAnchorIndex: function (jpc) { + return jpc.endpoints[0].isFloating() ? 0 : jpc.endpoints[1].isFloating() ? 1 : -1; + }, + proxyConnection :function(connection, index, proxyEl, proxyElId, endpointGenerator, anchorGenerator) { + var proxyEp, + originalElementId = connection.endpoints[index].elementId, + originalEndpoint = connection.endpoints[index]; + + connection.proxies = connection.proxies || []; + if(connection.proxies[index]) { + proxyEp = connection.proxies[index].ep; + }else { + proxyEp = this.addEndpoint(proxyEl, { + endpoint:endpointGenerator(connection, index), + anchor:anchorGenerator(connection, index), + parameters:{ + isProxyEndpoint:true + } + }); + } + proxyEp.setDeleteOnEmpty(true); + + // for this index, stash proxy info: the new EP, the original EP. + connection.proxies[index] = { ep:proxyEp, originalEp: originalEndpoint }; + + // and advise the anchor manager + if (index === 0) { + // TODO why are there two differently named methods? Why is there not one method that says "some end of this + // connection changed (you give the index), and here's the new element and element id." + this.anchorManager.sourceChanged(originalElementId, proxyElId, connection, proxyEl); + } + else { + this.anchorManager.updateOtherEndpoint(connection.endpoints[0].elementId, originalElementId, proxyElId, connection); + connection.target = proxyEl; + connection.targetId = proxyElId; + } + + // detach the original EP from the connection. + originalEndpoint.detachFromConnection(connection, null, true); + + // set the proxy as the new ep + proxyEp.connections = [ connection ]; + connection.endpoints[index] = proxyEp; + + originalEndpoint.setVisible(false); + + connection.setVisible(true); + + this.revalidate(proxyEl); + }, + unproxyConnection : function(connection, index, proxyElId) { + // if connection cleaned up, no proxies, or none for this end of the connection, abort. + if (connection._jsPlumb == null || connection.proxies == null || connection.proxies[index] == null) { + return; + } + + var originalElement = connection.proxies[index].originalEp.element, + originalElementId = connection.proxies[index].originalEp.elementId; + + connection.endpoints[index] = connection.proxies[index].originalEp; + // and advise the anchor manager + if (index === 0) { + // TODO why are there two differently named methods? Why is there not one method that says "some end of this + // connection changed (you give the index), and here's the new element and element id." + this.anchorManager.sourceChanged(proxyElId, originalElementId, connection, originalElement); + } + else { + this.anchorManager.updateOtherEndpoint(connection.endpoints[0].elementId, proxyElId, originalElementId, connection); + connection.target = originalElement; + connection.targetId = originalElementId; + } + + // detach the proxy EP from the connection (which will cause it to be removed as we no longer need it) + connection.proxies[index].ep.detachFromConnection(connection, null); + + connection.proxies[index].originalEp.addConnection(connection); + if(connection.isVisible()) { + connection.proxies[index].originalEp.setVisible(true); + } + + // cleanup + delete connection.proxies[index]; + } + }); + +// --------------------- static instance + module registration ------------------------------------------- + +// create static instance and assign to window if window exists. + var jsPlumb = new jsPlumbInstance(); + // register on 'root' (lets us run on server or browser) + root.jsPlumb = jsPlumb; + // add 'getInstance' method to static instance + jsPlumb.getInstance = function (_defaults, overrideFns) { + var j = new jsPlumbInstance(_defaults); + if (overrideFns) { + for (var ovf in overrideFns) { + j[ovf] = overrideFns[ovf]; + } + } + j.init(); + return j; + }; + jsPlumb.each = function (spec, fn) { + if (spec == null) { + return; + } + if (typeof spec === "string") { + fn(jsPlumb.getElement(spec)); + } + else if (spec.length != null) { + for (var i = 0; i < spec.length; i++) { + fn(jsPlumb.getElement(spec[i])); + } + } + else { + fn(spec); + } // assume it's an element. + }; + + // CommonJS + if (typeof exports !== 'undefined') { + exports.jsPlumb = jsPlumb; + } + +// --------------------- end static instance + AMD registration ------------------------------------------- + +}).call(typeof window !== 'undefined' ? window : this); + +/* + * 2010 - 2018 jsPlumb (hello@jsplumbtoolkit.com) + * + * https://jsplumbtoolkit.com + * https://github.com/jsplumb/jsplumb + * + * Dual licensed under the MIT and GPL2 licenses. + */ +;(function() { + + "use strict"; + var root = this, _jp = root.jsPlumb, _ju = root.jsPlumbUtil; + + // ------------------------------ BEGIN OverlayCapablejsPlumbUIComponent -------------------------------------------- + + var _internalLabelOverlayId = "__label", + // this is a shortcut helper method to let people add a label as + // overlay. + _makeLabelOverlay = function (component, params) { + + var _params = { + cssClass: params.cssClass, + labelStyle: component.labelStyle, + id: _internalLabelOverlayId, + component: component, + _jsPlumb: component._jsPlumb.instance // TODO not necessary, since the instance can be accessed through the component. + }, + mergedParams = _jp.extend(_params, params); + + return new _jp.Overlays[component._jsPlumb.instance.getRenderMode()].Label(mergedParams); + }, + _processOverlay = function (component, o) { + var _newOverlay = null; + if (_ju.isArray(o)) { // this is for the shorthand ["Arrow", { width:50 }] syntax + // there's also a three arg version: + // ["Arrow", { width:50 }, {location:0.7}] + // which merges the 3rd arg into the 2nd. + var type = o[0], + // make a copy of the object so as not to mess up anyone else's reference... + p = _jp.extend({component: component, _jsPlumb: component._jsPlumb.instance}, o[1]); + if (o.length === 3) { + _jp.extend(p, o[2]); + } + _newOverlay = new _jp.Overlays[component._jsPlumb.instance.getRenderMode()][type](p); + } else if (o.constructor === String) { + _newOverlay = new _jp.Overlays[component._jsPlumb.instance.getRenderMode()][o]({component: component, _jsPlumb: component._jsPlumb.instance}); + } else { + _newOverlay = o; + } + + _newOverlay.id = _newOverlay.id || _ju.uuid(); + component.cacheTypeItem("overlay", _newOverlay, _newOverlay.id); + component._jsPlumb.overlays[_newOverlay.id] = _newOverlay; + + return _newOverlay; + }; + + _jp.OverlayCapableJsPlumbUIComponent = function (params) { + + root.jsPlumbUIComponent.apply(this, arguments); + this._jsPlumb.overlays = {}; + this._jsPlumb.overlayPositions = {}; + + if (params.label) { + this.getDefaultType().overlays[_internalLabelOverlayId] = ["Label", { + label: params.label, + location: params.labelLocation || this.defaultLabelLocation || 0.5, + labelStyle: params.labelStyle || this._jsPlumb.instance.Defaults.LabelStyle, + id:_internalLabelOverlayId + }]; + }else if(params.id){ + // 新增 label 为空时设置的cssClass无效问题,可以使用 emptyLabelStyle: {cssClass: 'emptyFlowLabel'} 进行设置 by_ 萌级小菜鸟 + this.getDefaultType().overlays[_internalLabelOverlayId] = ["Label", { + label: params.label, + location: params.labelLocation || this.defaultLabelLocation || 0.5, + labelStyle: params.emptyLabelStyle || this._jsPlumb.instance.Defaults.emptyLabelStyle, + id:_internalLabelOverlayId + }]; + } + + this.setListenerComponent = function (c) { + if (this._jsPlumb) { + for (var i in this._jsPlumb.overlays) { + this._jsPlumb.overlays[i].setListenerComponent(c); + } + } + }; + }; + + _jp.OverlayCapableJsPlumbUIComponent.applyType = function (component, t) { + if (t.overlays) { + // loop through the ones in the type. if already present on the component, + // dont remove or re-add. + var keep = {}, i; + + for (i in t.overlays) { + + var existing = component._jsPlumb.overlays[t.overlays[i][1].id]; + if (existing) { + // maybe update from data, if there were parameterised values for instance. + existing.updateFrom(t.overlays[i][1]); + keep[t.overlays[i][1].id] = true; + } + else { + var c = component.getCachedTypeItem("overlay", t.overlays[i][1].id); + if (c != null) { + c.reattach(component._jsPlumb.instance, component); + c.setVisible(true); + // maybe update from data, if there were parameterised values for instance. + c.updateFrom(t.overlays[i][1]); + component._jsPlumb.overlays[c.id] = c; + } + else { + c = component.addOverlay(t.overlays[i], true); + } + keep[c.id] = true; + } + } + + // now loop through the full overlays and remove those that we dont want to keep + for (i in component._jsPlumb.overlays) { + if (keep[component._jsPlumb.overlays[i].id] == null) { + component.removeOverlay(component._jsPlumb.overlays[i].id, true); // remove overlay but dont clean it up. + // that would remove event listeners etc; overlays are never discarded by the types stuff, they are + // just detached/reattached. + } + } + } + }; + + _ju.extend(_jp.OverlayCapableJsPlumbUIComponent, root.jsPlumbUIComponent, { + + setHover: function (hover, ignoreAttachedElements) { + if (this._jsPlumb && !this._jsPlumb.instance.isConnectionBeingDragged()) { + for (var i in this._jsPlumb.overlays) { + this._jsPlumb.overlays[i][hover ? "addClass" : "removeClass"](this._jsPlumb.instance.hoverClass); + } + } + }, + addOverlay: function (overlay, doNotRepaint) { + var o = _processOverlay(this, overlay); + + if (this.getData && o.type === "Label" && _ju.isArray(overlay)) { + // + // component data might contain label location - look for it here. + var d = this.getData(), p = overlay[1]; + if (d) { + var locationAttribute = p.labelLocationAttribute || "labelLocation"; + var loc = d ? d[locationAttribute] : null; + + if (loc) { + o.loc = loc; + } + } + } + + if (!doNotRepaint) { + this.repaint(); + } + return o; + }, + getOverlay: function (id) { + return this._jsPlumb.overlays[id]; + }, + getOverlays: function () { + return this._jsPlumb.overlays; + }, + hideOverlay: function (id) { + var o = this.getOverlay(id); + if (o) { + o.hide(); + } + }, + hideOverlays: function () { + for (var i in this._jsPlumb.overlays) { + this._jsPlumb.overlays[i].hide(); + } + }, + showOverlay: function (id) { + var o = this.getOverlay(id); + if (o) { + o.show(); + } + }, + showOverlays: function () { + for (var i in this._jsPlumb.overlays) { + this._jsPlumb.overlays[i].show(); + } + }, + removeAllOverlays: function (doNotRepaint) { + for (var i in this._jsPlumb.overlays) { + if (this._jsPlumb.overlays[i].cleanup) { + this._jsPlumb.overlays[i].cleanup(); + } + } + + this._jsPlumb.overlays = {}; + this._jsPlumb.overlayPositions = null; + this._jsPlumb.overlayPlacements= {}; + if (!doNotRepaint) { + this.repaint(); + } + }, + removeOverlay: function (overlayId, dontCleanup) { + var o = this._jsPlumb.overlays[overlayId]; + if (o) { + o.setVisible(false); + if (!dontCleanup && o.cleanup) { + o.cleanup(); + } + delete this._jsPlumb.overlays[overlayId]; + if (this._jsPlumb.overlayPositions) { + delete this._jsPlumb.overlayPositions[overlayId]; + } + + if (this._jsPlumb.overlayPlacements) { + delete this._jsPlumb.overlayPlacements[overlayId]; + } + } + }, + removeOverlays: function () { + for (var i = 0, j = arguments.length; i < j; i++) { + this.removeOverlay(arguments[i]); + } + }, + moveParent: function (newParent) { + if (this.bgCanvas) { + this.bgCanvas.parentNode.removeChild(this.bgCanvas); + newParent.appendChild(this.bgCanvas); + } + + if (this.canvas && this.canvas.parentNode) { + this.canvas.parentNode.removeChild(this.canvas); + newParent.appendChild(this.canvas); + + for (var i in this._jsPlumb.overlays) { + if (this._jsPlumb.overlays[i].isAppendedAtTopLevel) { + var el = this._jsPlumb.overlays[i].getElement(); + el.parentNode.removeChild(el); + newParent.appendChild(el); + } + } + } + }, + getLabel: function () { + var lo = this.getOverlay(_internalLabelOverlayId); + return lo != null ? lo.getLabel() : null; + }, + getLabelOverlay: function () { + return this.getOverlay(_internalLabelOverlayId); + }, + setLabel: function (l) { + var lo = this.getOverlay(_internalLabelOverlayId); + if (!lo) { + var params = l.constructor === String || l.constructor === Function ? { label: l } : l; + lo = _makeLabelOverlay(this, params); + this._jsPlumb.overlays[_internalLabelOverlayId] = lo; + } + else { + if (l.constructor === String || l.constructor === Function) { + lo.setLabel(l); + } + else { + // 修复设置label为空时原来的值无法替换,by_萌级小菜鸟 2020年05月08日21:26:15 + if (!l.label) { + l.label = '' + } + lo.setLabel(l.label); + if (l.location) { + lo.setLocation(l.location); + } + } + } + + if (!this._jsPlumb.instance.isSuspendDrawing()) { + this.repaint(); + } + }, + cleanup: function (force) { + for (var i in this._jsPlumb.overlays) { + this._jsPlumb.overlays[i].cleanup(force); + this._jsPlumb.overlays[i].destroy(force); + } + if (force) { + this._jsPlumb.overlays = {}; + this._jsPlumb.overlayPositions = null; + } + }, + setVisible: function (v) { + this[v ? "showOverlays" : "hideOverlays"](); + }, + setAbsoluteOverlayPosition: function (overlay, xy) { + this._jsPlumb.overlayPositions[overlay.id] = xy; + }, + getAbsoluteOverlayPosition: function (overlay) { + return this._jsPlumb.overlayPositions ? this._jsPlumb.overlayPositions[overlay.id] : null; + }, + _clazzManip:function(action, clazz, dontUpdateOverlays) { + if (!dontUpdateOverlays) { + for (var i in this._jsPlumb.overlays) { + this._jsPlumb.overlays[i][action + "Class"](clazz); + } + } + }, + addClass:function(clazz, dontUpdateOverlays) { + this._clazzManip("add", clazz, dontUpdateOverlays); + }, + removeClass:function(clazz, dontUpdateOverlays) { + this._clazzManip("remove", clazz, dontUpdateOverlays); + } + }); + +// ------------------------------ END OverlayCapablejsPlumbUIComponent -------------------------------------------- + +}).call(typeof window !== 'undefined' ? window : this); + +/* + * This file contains the code for Endpoints. + * + * Copyright (c) 2010 - 2018 jsPlumb (hello@jsplumbtoolkit.com) + * + * https://jsplumbtoolkit.com + * https://github.com/jsplumb/jsplumb + * + * Dual licensed under the MIT and GPL2 licenses. + */ +;(function () { + + "use strict"; + var root = this, _jp = root.jsPlumb, _ju = root.jsPlumbUtil; + + // create the drag handler for a connection + var _makeConnectionDragHandler = function (endpoint, placeholder, _jsPlumb) { + var stopped = false; + return { + drag: function () { + if (stopped) { + stopped = false; + return true; + } + + if (placeholder.element) { + var _ui = _jsPlumb.getUIPosition(arguments, _jsPlumb.getZoom()); + if (_ui != null) { + _jsPlumb.setPosition(placeholder.element, _ui); + } + _jsPlumb.repaint(placeholder.element, _ui); + // always repaint the source endpoint, because only continuous/dynamic anchors cause the endpoint + // to be repainted, so static anchors need to be told (or the endpoint gets dragged around) + endpoint.paint({anchorPoint:endpoint.anchor.getCurrentLocation({element:endpoint})}); + } + }, + stopDrag: function () { + stopped = true; + } + }; + }; + + // creates a placeholder div for dragging purposes, adds it, and pre-computes its offset. + var _makeDraggablePlaceholder = function (placeholder, _jsPlumb, ipco, ips) { + var n = _jsPlumb.createElement("div", { position : "absolute" }); + _jsPlumb.appendElement(n); + var id = _jsPlumb.getId(n); + _jsPlumb.setPosition(n, ipco); + n.style.width = ips[0] + "px"; + n.style.height = ips[1] + "px"; + _jsPlumb.manage(id, n, true); // TRANSIENT MANAGE + // create and assign an id, and initialize the offset. + placeholder.id = id; + placeholder.element = n; + }; + + // create a floating endpoint (for drag connections) + var _makeFloatingEndpoint = function (paintStyle, referenceAnchor, endpoint, referenceCanvas, sourceElement, _jsPlumb, _newEndpoint, scope) { + var floatingAnchor = new _jp.FloatingAnchor({ reference: referenceAnchor, referenceCanvas: referenceCanvas, jsPlumbInstance: _jsPlumb }); + //setting the scope here should not be the way to fix that mootools issue. it should be fixed by not + // adding the floating endpoint as a droppable. that makes more sense anyway! + // TRANSIENT MANAGE + return _newEndpoint({ + paintStyle: paintStyle, + endpoint: endpoint, + anchor: floatingAnchor, + source: sourceElement, + scope: scope + }); + }; + + var typeParameters = [ "connectorStyle", "connectorHoverStyle", "connectorOverlays", + "connector", "connectionType", "connectorClass", "connectorHoverClass" ]; + + // a helper function that tries to find a connection to the given element, and returns it if so. if elementWithPrecedence is null, + // or no connection to it is found, we return the first connection in our list. + var findConnectionToUseForDynamicAnchor = function (ep, elementWithPrecedence) { + var idx = 0; + if (elementWithPrecedence != null) { + for (var i = 0; i < ep.connections.length; i++) { + if (ep.connections[i].sourceId === elementWithPrecedence || ep.connections[i].targetId === elementWithPrecedence) { + idx = i; + break; + } + } + } + + return ep.connections[idx]; + }; + + _jp.Endpoint = function (params) { + var _jsPlumb = params._jsPlumb, + _newConnection = params.newConnection, + _newEndpoint = params.newEndpoint; + + this.idPrefix = "_jsplumb_e_"; + this.defaultLabelLocation = [ 0.5, 0.5 ]; + this.defaultOverlayKeys = ["Overlays", "EndpointOverlays"]; + _jp.OverlayCapableJsPlumbUIComponent.apply(this, arguments); + +// TYPE + + this.appendToDefaultType({ + connectionType:params.connectionType, + maxConnections: params.maxConnections == null ? this._jsPlumb.instance.Defaults.MaxConnections : params.maxConnections, // maximum number of connections this endpoint can be the source of., + paintStyle: params.endpointStyle || params.paintStyle || params.style || this._jsPlumb.instance.Defaults.EndpointStyle || _jp.Defaults.EndpointStyle, + hoverPaintStyle: params.endpointHoverStyle || params.hoverPaintStyle || this._jsPlumb.instance.Defaults.EndpointHoverStyle || _jp.Defaults.EndpointHoverStyle, + connectorStyle: params.connectorStyle, + connectorHoverStyle: params.connectorHoverStyle, + connectorClass: params.connectorClass, + connectorHoverClass: params.connectorHoverClass, + connectorOverlays: params.connectorOverlays, + connector: params.connector, + connectorTooltip: params.connectorTooltip + }); + +// END TYPE + + this._jsPlumb.enabled = !(params.enabled === false); + this._jsPlumb.visible = true; + this.element = _jp.getElement(params.source); + this._jsPlumb.uuid = params.uuid; + this._jsPlumb.floatingEndpoint = null; + var inPlaceCopy = null; + if (this._jsPlumb.uuid) { + params.endpointsByUUID[this._jsPlumb.uuid] = this; + } + this.elementId = params.elementId; + this.dragProxy = params.dragProxy; + + this._jsPlumb.connectionCost = params.connectionCost; + this._jsPlumb.connectionsDirected = params.connectionsDirected; + this._jsPlumb.currentAnchorClass = ""; + this._jsPlumb.events = {}; + + var deleteOnEmpty = params.deleteOnEmpty === true; + this.setDeleteOnEmpty = function(d) { + deleteOnEmpty = d; + }; + + var _updateAnchorClass = function () { + // stash old, get new + var oldAnchorClass = _jsPlumb.endpointAnchorClassPrefix + "-" + this._jsPlumb.currentAnchorClass; + this._jsPlumb.currentAnchorClass = this.anchor.getCssClass(); + var anchorClass = _jsPlumb.endpointAnchorClassPrefix + (this._jsPlumb.currentAnchorClass ? "-" + this._jsPlumb.currentAnchorClass : ""); + + this.removeClass(oldAnchorClass); + this.addClass(anchorClass); + // add and remove at the same time to reduce the number of reflows. + _jp.updateClasses(this.element, anchorClass, oldAnchorClass); + }.bind(this); + + this.prepareAnchor = function(anchorParams) { + var a = this._jsPlumb.instance.makeAnchor(anchorParams, this.elementId, _jsPlumb); + a.bind("anchorChanged", function (currentAnchor) { + this.fire("anchorChanged", {endpoint: this, anchor: currentAnchor}); + _updateAnchorClass(); + }.bind(this)); + return a; + }; + + this.setPreparedAnchor = function(anchor, doNotRepaint) { + this._jsPlumb.instance.continuousAnchorFactory.clear(this.elementId); + this.anchor = anchor; + _updateAnchorClass(); + + if (!doNotRepaint) { + this._jsPlumb.instance.repaint(this.elementId); + } + + return this; + }; + + this.setAnchor = function (anchorParams, doNotRepaint) { + var a = this.prepareAnchor(anchorParams); + this.setPreparedAnchor(a, doNotRepaint); + return this; + }; + + var internalHover = function (state) { + if (this.connections.length > 0) { + for (var i = 0; i < this.connections.length; i++) { + this.connections[i].setHover(state, false); + } + } + else { + this.setHover(state); + } + }.bind(this); + + this.bind("mouseover", function () { + internalHover(true); + }); + this.bind("mouseout", function () { + internalHover(false); + }); + + // ANCHOR MANAGER + if (!params._transient) { // in place copies, for example, are transient. they will never need to be retrieved during a paint cycle, because they dont move, and then they are deleted. + this._jsPlumb.instance.anchorManager.add(this, this.elementId); + } + + this.prepareEndpoint = function(ep, typeId) { + var _e = function (t, p) { + var rm = _jsPlumb.getRenderMode(); + if (_jp.Endpoints[rm][t]) { + return new _jp.Endpoints[rm][t](p); + } + if (!_jsPlumb.Defaults.DoNotThrowErrors) { + throw { msg: "jsPlumb: unknown endpoint type '" + t + "'" }; + } + }; + + var endpointArgs = { + _jsPlumb: this._jsPlumb.instance, + cssClass: params.cssClass, + container: params.container, + tooltip: params.tooltip, + connectorTooltip: params.connectorTooltip, + endpoint: this + }; + + var endpoint; + + if (_ju.isString(ep)) { + endpoint = _e(ep, endpointArgs); + } + else if (_ju.isArray(ep)) { + endpointArgs = _ju.merge(ep[1], endpointArgs); + endpoint = _e(ep[0], endpointArgs); + } + else { + endpoint = ep.clone(); + } + + // assign a clone function using a copy of endpointArgs. this is used when a drag starts: the endpoint that was dragged is cloned, + // and the clone is left in its place while the original one goes off on a magical journey. + // the copy is to get around a closure problem, in which endpointArgs ends up getting shared by + // the whole world. + //var argsForClone = jsPlumb.extend({}, endpointArgs); + endpoint.clone = function () { + // TODO this, and the code above, can be refactored to be more dry. + if (_ju.isString(ep)) { + return _e(ep, endpointArgs); + } + else if (_ju.isArray(ep)) { + endpointArgs = _ju.merge(ep[1], endpointArgs); + return _e(ep[0], endpointArgs); + } + }.bind(this); + + endpoint.typeId = typeId; + return endpoint; + }; + + this.setEndpoint = function(ep, doNotRepaint) { + var _ep = this.prepareEndpoint(ep); + this.setPreparedEndpoint(_ep, true); + }; + + this.setPreparedEndpoint = function (ep, doNotRepaint) { + if (this.endpoint != null) { + this.endpoint.cleanup(); + this.endpoint.destroy(); + } + this.endpoint = ep; + this.type = this.endpoint.type; + this.canvas = this.endpoint.canvas; + }; + + _jp.extend(this, params, typeParameters); + + this.isSource = params.isSource || false; + this.isTemporarySource = params.isTemporarySource || false; + this.isTarget = params.isTarget || false; + + this.connections = params.connections || []; + this.connectorPointerEvents = params["connector-pointer-events"]; + + this.scope = params.scope || _jsPlumb.getDefaultScope(); + this.timestamp = null; + this.reattachConnections = params.reattach || _jsPlumb.Defaults.ReattachConnections; + this.connectionsDetachable = _jsPlumb.Defaults.ConnectionsDetachable; + if (params.connectionsDetachable === false || params.detachable === false) { + this.connectionsDetachable = false; + } + this.dragAllowedWhenFull = params.dragAllowedWhenFull !== false; + + if (params.onMaxConnections) { + this.bind("maxConnections", params.onMaxConnections); + } + + // + // add a connection. not part of public API. + // + this.addConnection = function (connection) { + this.connections.push(connection); + this[(this.connections.length > 0 ? "add" : "remove") + "Class"](_jsPlumb.endpointConnectedClass); + this[(this.isFull() ? "add" : "remove") + "Class"](_jsPlumb.endpointFullClass); + }; + + this.detachFromConnection = function (connection, idx, doNotCleanup) { + idx = idx == null ? this.connections.indexOf(connection) : idx; + if (idx >= 0) { + this.connections.splice(idx, 1); + this[(this.connections.length > 0 ? "add" : "remove") + "Class"](_jsPlumb.endpointConnectedClass); + this[(this.isFull() ? "add" : "remove") + "Class"](_jsPlumb.endpointFullClass); + } + + if (!doNotCleanup && deleteOnEmpty && this.connections.length === 0) { + _jsPlumb.deleteObject({ + endpoint: this, + fireEvent: false, + deleteAttachedObjects: doNotCleanup !== true + }); + } + }; + + this.deleteEveryConnection = function(params) { + var c = this.connections.length; + for (var i = 0; i < c; i++) { + _jsPlumb.deleteConnection(this.connections[0], params); + } + }; + + this.detachFrom = function (targetEndpoint, fireEvent, originalEvent) { + var c = []; + for (var i = 0; i < this.connections.length; i++) { + if (this.connections[i].endpoints[1] === targetEndpoint || this.connections[i].endpoints[0] === targetEndpoint) { + c.push(this.connections[i]); + } + } + for (var j = 0, count = c.length; j < count; j++) { + _jsPlumb.deleteConnection(c[0]); + } + return this; + }; + + this.getElement = function () { + return this.element; + }; + + this.setElement = function (el) { + var parentId = this._jsPlumb.instance.getId(el), + curId = this.elementId; + // remove the endpoint from the list for the current endpoint's element + _ju.removeWithFunction(params.endpointsByElement[this.elementId], function (e) { + return e.id === this.id; + }.bind(this)); + this.element = _jp.getElement(el); + this.elementId = _jsPlumb.getId(this.element); + _jsPlumb.anchorManager.rehomeEndpoint(this, curId, this.element); + _jsPlumb.dragManager.endpointAdded(this.element); + _ju.addToList(params.endpointsByElement, parentId, this); + return this; + }; + + /** + * private but must be exposed. + */ + this.makeInPlaceCopy = function () { + var loc = this.anchor.getCurrentLocation({element: this}), + o = this.anchor.getOrientation(this), + acc = this.anchor.getCssClass(), + inPlaceAnchor = { + bind: function () { + }, + compute: function () { + return [ loc[0], loc[1] ]; + }, + getCurrentLocation: function () { + return [ loc[0], loc[1] ]; + }, + getOrientation: function () { + return o; + }, + getCssClass: function () { + return acc; + } + }; + + return _newEndpoint({ + dropOptions: params.dropOptions, + anchor: inPlaceAnchor, + source: this.element, + paintStyle: this.getPaintStyle(), + endpoint: params.hideOnDrag ? "Blank" : this.endpoint, + _transient: true, + scope: this.scope, + reference:this + }); + }; + + /** + * returns a connection from the pool; used when dragging starts. just gets the head of the array if it can. + */ + this.connectorSelector = function () { + return this.connections[0]; + }; + + this.setStyle = this.setPaintStyle; + + this.paint = function (params) { + params = params || {}; + var timestamp = params.timestamp, recalc = !(params.recalc === false); + if (!timestamp || this.timestamp !== timestamp) { + + var info = _jsPlumb.updateOffset({ elId: this.elementId, timestamp: timestamp }); + + var xy = params.offset ? params.offset.o : info.o; + if (xy != null) { + var ap = params.anchorPoint, connectorPaintStyle = params.connectorPaintStyle; + if (ap == null) { + var wh = params.dimensions || info.s, + anchorParams = { xy: [ xy.left, xy.top ], wh: wh, element: this, timestamp: timestamp }; + if (recalc && this.anchor.isDynamic && this.connections.length > 0) { + var c = findConnectionToUseForDynamicAnchor(this, params.elementWithPrecedence), + oIdx = c.endpoints[0] === this ? 1 : 0, + oId = oIdx === 0 ? c.sourceId : c.targetId, + oInfo = _jsPlumb.getCachedData(oId), + oOffset = oInfo.o, oWH = oInfo.s; + + anchorParams.index = oIdx === 0 ? 1 : 0; + anchorParams.connection = c; + anchorParams.txy = [ oOffset.left, oOffset.top ]; + anchorParams.twh = oWH; + anchorParams.tElement = c.endpoints[oIdx]; + } else if (this.connections.length > 0) { + anchorParams.connection = this.connections[0]; + } + ap = this.anchor.compute(anchorParams); + } + + this.endpoint.compute(ap, this.anchor.getOrientation(this), this._jsPlumb.paintStyleInUse, connectorPaintStyle || this.paintStyleInUse); + this.endpoint.paint(this._jsPlumb.paintStyleInUse, this.anchor); + this.timestamp = timestamp; + + // paint overlays + for (var i in this._jsPlumb.overlays) { + if (this._jsPlumb.overlays.hasOwnProperty(i)) { + var o = this._jsPlumb.overlays[i]; + if (o.isVisible()) { + this._jsPlumb.overlayPlacements[i] = o.draw(this.endpoint, this._jsPlumb.paintStyleInUse); + o.paint(this._jsPlumb.overlayPlacements[i]); + } + } + } + } + } + }; + + this.getTypeDescriptor = function () { + return "endpoint"; + }; + this.isVisible = function () { + return this._jsPlumb.visible; + }; + + this.repaint = this.paint; + + var draggingInitialised = false; + this.initDraggable = function () { + + // is this a connection source? we make it draggable and have the + // drag listener maintain a connection with a floating endpoint. + if (!draggingInitialised && _jp.isDragSupported(this.element)) { + var placeholderInfo = { id: null, element: null }, + jpc = null, + existingJpc = false, + existingJpcParams = null, + _dragHandler = _makeConnectionDragHandler(this, placeholderInfo, _jsPlumb), + dragOptions = params.dragOptions || {}, + defaultOpts = {}, + startEvent = _jp.dragEvents.start, + stopEvent = _jp.dragEvents.stop, + dragEvent = _jp.dragEvents.drag, + beforeStartEvent = _jp.dragEvents.beforeStart, + payload; + + // respond to beforeStart from katavorio; this will have, optionally, a payload of attribute values + // that were placed there by the makeSource mousedown listener. + var beforeStart = function(beforeStartParams) { + payload = beforeStartParams.e.payload || {}; + }; + + var start = function (startParams) { + +// ------------- first, get a connection to drag. this may be null, in which case we are dragging a new one. + + jpc = this.connectorSelector(); + +// -------------------------------- now a bunch of tests about whether or not to proceed ------------------------- + + var _continue = true; + // if not enabled, return + if (!this.isEnabled()) { + _continue = false; + } + // if no connection and we're not a source - or temporarily a source, as is the case with makeSource - return. + if (jpc == null && !this.isSource && !this.isTemporarySource) { + _continue = false; + } + // otherwise if we're full and not allowed to drag, also return false. + if (this.isSource && this.isFull() && !(jpc != null && this.dragAllowedWhenFull)) { + _continue = false; + } + // if the connection was setup as not detachable or one of its endpoints + // was setup as connectionsDetachable = false, or Defaults.ConnectionsDetachable + // is set to false... + if (jpc != null && !jpc.isDetachable(this)) { + // .. and the endpoint is full + if (this.isFull()) { + _continue = false; + } else { + // otherwise, if not full, set the connection to null, and we will now proceed + // to drag a new connection. + jpc = null; + } + } + + var beforeDrag = _jsPlumb.checkCondition(jpc == null ? "beforeDrag" : "beforeStartDetach", { + endpoint:this, + source:this.element, + sourceId:this.elementId, + connection:jpc + }); + if (beforeDrag === false) { + _continue = false; + } + // else we might have been given some data. we'll pass it in to a new connection as 'data'. + // here we also merge in the optional payload we were given on mousedown. + else if (typeof beforeDrag === "object") { + _jp.extend(beforeDrag, payload || {}); + } + else { + // or if no beforeDrag data, maybe use the payload on its own. + beforeDrag = payload || {}; + } + + if (_continue === false) { + // this is for mootools and yui. returning false from this causes jquery to stop drag. + // the events are wrapped in both mootools and yui anyway, but i don't think returning + // false from the start callback would stop a drag. + if (_jsPlumb.stopDrag) { + _jsPlumb.stopDrag(this.canvas); + } + _dragHandler.stopDrag(); + return false; + } + +// --------------------------------------------------------------------------------------------------------------------- + + // ok to proceed. + + // clear hover for all connections for this endpoint before continuing. + for (var i = 0; i < this.connections.length; i++) { + this.connections[i].setHover(false); + } + + this.addClass("endpointDrag"); + _jsPlumb.setConnectionBeingDragged(true); + + // if we're not full but there was a connection, make it null. we'll create a new one. + if (jpc && !this.isFull() && this.isSource) { + jpc = null; + } + + _jsPlumb.updateOffset({ elId: this.elementId }); + +// ---------------- make the element we will drag around, and position it ----------------------------- + + var ipco = this._jsPlumb.instance.getOffset(this.canvas), + canvasElement = this.canvas, + ips = this._jsPlumb.instance.getSize(this.canvas); + + _makeDraggablePlaceholder(placeholderInfo, _jsPlumb, ipco, ips); + + // store the id of the dragging div and the source element. the drop function will pick these up. + _jsPlumb.setAttributes(this.canvas, { + "dragId": placeholderInfo.id, + "elId": this.elementId + }); + +// ------------------- create an endpoint that will be our floating endpoint ------------------------------------ + + var endpointToFloat = this.dragProxy || this.endpoint; + if (this.dragProxy == null && this.connectionType != null) { + var aae = this._jsPlumb.instance.deriveEndpointAndAnchorSpec(this.connectionType); + if (aae.endpoints[1]) { + endpointToFloat = aae.endpoints[1]; + } + } + var centerAnchor = this._jsPlumb.instance.makeAnchor("Center"); + centerAnchor.isFloating = true; + this._jsPlumb.floatingEndpoint = _makeFloatingEndpoint(this.getPaintStyle(), centerAnchor, endpointToFloat, this.canvas, placeholderInfo.element, _jsPlumb, _newEndpoint, this.scope); + var _savedAnchor = this._jsPlumb.floatingEndpoint.anchor; + + + if (jpc == null) { + + this.setHover(false, false); + // create a connection. one end is this endpoint, the other is a floating endpoint. + jpc = _newConnection({ + sourceEndpoint: this, + targetEndpoint: this._jsPlumb.floatingEndpoint, + source: this.element, // for makeSource with parent option. ensure source element is represented correctly. + target: placeholderInfo.element, + anchors: [ this.anchor, this._jsPlumb.floatingEndpoint.anchor ], + paintStyle: params.connectorStyle, // this can be null. Connection will use the default. + hoverPaintStyle: params.connectorHoverStyle, + connector: params.connector, // this can also be null. Connection will use the default. + overlays: params.connectorOverlays, + type: this.connectionType, + cssClass: this.connectorClass, + hoverClass: this.connectorHoverClass, + scope:params.scope, + data:beforeDrag + }); + jpc.pending = true; + jpc.addClass(_jsPlumb.draggingClass); + this._jsPlumb.floatingEndpoint.addClass(_jsPlumb.draggingClass); + this._jsPlumb.floatingEndpoint.anchor = _savedAnchor; + // fire an event that informs that a connection is being dragged + _jsPlumb.fire("connectionDrag", jpc); + + // register the new connection on the drag manager. This connection, at this point, is 'pending', + // and has as its target a temporary element (the 'placeholder'). If the connection subsequently + // becomes established, the anchor manager is informed that the target of the connection has + // changed. + + _jsPlumb.anchorManager.newConnection(jpc); + + } else { + existingJpc = true; + jpc.setHover(false); + // new anchor idx + var anchorIdx = jpc.endpoints[0].id === this.id ? 0 : 1; + this.detachFromConnection(jpc, null, true); // detach from the connection while dragging is occurring. but dont cleanup automatically. + + // store the original scope (issue 57) + var dragScope = _jsPlumb.getDragScope(canvasElement); + _jsPlumb.setAttribute(this.canvas, "originalScope", dragScope); + + // fire an event that informs that a connection is being dragged. we do this before + // replacing the original target with the floating element info. + _jsPlumb.fire("connectionDrag", jpc); + + // now we replace ourselves with the temporary div we created above: + if (anchorIdx === 0) { + existingJpcParams = [ jpc.source, jpc.sourceId, canvasElement, dragScope ]; + _jsPlumb.anchorManager.sourceChanged(jpc.endpoints[anchorIdx].elementId, placeholderInfo.id, jpc, placeholderInfo.element); + + } else { + existingJpcParams = [ jpc.target, jpc.targetId, canvasElement, dragScope ]; + jpc.target = placeholderInfo.element; + jpc.targetId = placeholderInfo.id; + + _jsPlumb.anchorManager.updateOtherEndpoint(jpc.sourceId, jpc.endpoints[anchorIdx].elementId, jpc.targetId, jpc); + } + + // store the original endpoint and assign the new floating endpoint for the drag. + jpc.suspendedEndpoint = jpc.endpoints[anchorIdx]; + + // PROVIDE THE SUSPENDED ELEMENT, BE IT A SOURCE OR TARGET (ISSUE 39) + jpc.suspendedElement = jpc.endpoints[anchorIdx].getElement(); + jpc.suspendedElementId = jpc.endpoints[anchorIdx].elementId; + jpc.suspendedElementType = anchorIdx === 0 ? "source" : "target"; + + jpc.suspendedEndpoint.setHover(false); + this._jsPlumb.floatingEndpoint.referenceEndpoint = jpc.suspendedEndpoint; + jpc.endpoints[anchorIdx] = this._jsPlumb.floatingEndpoint; + + jpc.addClass(_jsPlumb.draggingClass); + this._jsPlumb.floatingEndpoint.addClass(_jsPlumb.draggingClass); + } + + _jsPlumb.registerFloatingConnection(placeholderInfo, jpc, this._jsPlumb.floatingEndpoint); + + // // register it and register connection on it. + // _jsPlumb.floatingConnections[placeholderInfo.id] = jpc; + // + // // only register for the target endpoint; we will not be dragging the source at any time + // // before this connection is either discarded or made into a permanent connection. + // _ju.addToList(params.endpointsByElement, placeholderInfo.id, this._jsPlumb.floatingEndpoint); + + + // tell jsplumb about it + _jsPlumb.currentlyDragging = true; + }.bind(this); + + var stop = function () { + _jsPlumb.setConnectionBeingDragged(false); + + if (jpc && jpc.endpoints != null) { + // get the actual drop event (decode from library args to stop function) + var originalEvent = _jsPlumb.getDropEvent(arguments); + // unlock the other endpoint (if it is dynamic, it would have been locked at drag start) + var idx = _jsPlumb.getFloatingAnchorIndex(jpc); + jpc.endpoints[idx === 0 ? 1 : 0].anchor.unlock(); + // TODO: Dont want to know about css classes inside jsplumb, ideally. + jpc.removeClass(_jsPlumb.draggingClass); + + // if we have the floating endpoint then the connection has not been dropped + // on another endpoint. If it is a new connection we throw it away. If it is an + // existing connection we check to see if we should reattach it, throwing it away + // if not. + if (this._jsPlumb && (jpc.deleteConnectionNow || jpc.endpoints[idx] === this._jsPlumb.floatingEndpoint)) { + // 6a. if the connection was an existing one... + if (existingJpc && jpc.suspendedEndpoint) { + // fix for issue35, thanks Sylvain Gizard: when firing the detach event make sure the + // floating endpoint has been replaced. + if (idx === 0) { + jpc.floatingElement = jpc.source; + jpc.floatingId = jpc.sourceId; + jpc.floatingEndpoint = jpc.endpoints[0]; + jpc.floatingIndex = 0; + jpc.source = existingJpcParams[0]; + jpc.sourceId = existingJpcParams[1]; + } else { + // keep a copy of the floating element; the anchor manager will want to clean up. + jpc.floatingElement = jpc.target; + jpc.floatingId = jpc.targetId; + jpc.floatingEndpoint = jpc.endpoints[1]; + jpc.floatingIndex = 1; + jpc.target = existingJpcParams[0]; + jpc.targetId = existingJpcParams[1]; + } + + var fe = this._jsPlumb.floatingEndpoint; // store for later removal. + // restore the original scope (issue 57) + _jsPlumb.setDragScope(existingJpcParams[2], existingJpcParams[3]); + jpc.endpoints[idx] = jpc.suspendedEndpoint; + // if the connection should be reattached, or the other endpoint refuses detach, then + // reset the connection to its original state + if (jpc.isReattach() || jpc._forceReattach || jpc._forceDetach || !_jsPlumb.deleteConnection(jpc, {originalEvent: originalEvent})) { + + jpc.setHover(false); + jpc._forceDetach = null; + jpc._forceReattach = null; + this._jsPlumb.floatingEndpoint.detachFromConnection(jpc); + jpc.suspendedEndpoint.addConnection(jpc); + + // TODO this code is duplicated in lots of places...and there is nothing external + // in the code; it all refers to the connection itself. we could add a + // `checkSanity(connection)` method to anchorManager that did this. + if (idx === 1) { + _jsPlumb.anchorManager.updateOtherEndpoint(jpc.sourceId, jpc.floatingId, jpc.targetId, jpc); + } + else { + _jsPlumb.anchorManager.sourceChanged(jpc.floatingId, jpc.sourceId, jpc, jpc.source); + } + + _jsPlumb.repaint(existingJpcParams[1]); + } + else { + _jsPlumb.deleteObject({endpoint: fe}); + } + } + } + + // makeTargets sets this flag, to tell us we have been replaced and should delete this object. + if (this.deleteAfterDragStop) { + _jsPlumb.deleteObject({endpoint: this}); + } + else { + if (this._jsPlumb) { + this.paint({recalc: false}); + } + } + + // although the connection is no longer valid, there are use cases where this is useful. + _jsPlumb.fire("connectionDragStop", jpc, originalEvent); + // fire this event to give people more fine-grained control (connectionDragStop fires a lot) + if (jpc.pending) { + _jsPlumb.fire("connectionAborted", jpc, originalEvent); + } + // tell jsplumb that dragging is finished. + _jsPlumb.currentlyDragging = false; + jpc.suspendedElement = null; + jpc.suspendedEndpoint = null; + jpc = null; + } + + // if no endpoints, jpc already cleaned up. but still we want to ensure we're reset properly. + // remove the element associated with the floating endpoint + // (and its associated floating endpoint and visual artefacts) + if (placeholderInfo && placeholderInfo.element) { + _jsPlumb.remove(placeholderInfo.element, false, false); + } + // remove the inplace copy + if (inPlaceCopy) { + _jsPlumb.deleteObject({endpoint: inPlaceCopy}); + } + + if (this._jsPlumb) { + // make our canvas visible (TODO: hand off to library; we should not know about DOM) + this.canvas.style.visibility = "visible"; + // unlock our anchor + this.anchor.unlock(); + // clear floating anchor. + this._jsPlumb.floatingEndpoint = null; + } + + }.bind(this); + + dragOptions = _jp.extend(defaultOpts, dragOptions); + dragOptions.scope = this.scope || dragOptions.scope; + dragOptions[beforeStartEvent] = _ju.wrap(dragOptions[beforeStartEvent], beforeStart, false); + dragOptions[startEvent] = _ju.wrap(dragOptions[startEvent], start, false); + // extracted drag handler function so can be used by makeSource + dragOptions[dragEvent] = _ju.wrap(dragOptions[dragEvent], _dragHandler.drag); + dragOptions[stopEvent] = _ju.wrap(dragOptions[stopEvent], stop); + dragOptions.multipleDrop = false; + + dragOptions.canDrag = function () { + return this.isSource || this.isTemporarySource || (this.connections.length > 0 && this.connectionsDetachable !== false); + }.bind(this); + + _jsPlumb.initDraggable(this.canvas, dragOptions, "internal"); + + this.canvas._jsPlumbRelatedElement = this.element; + + draggingInitialised = true; + } + }; + + var ep = params.endpoint || this._jsPlumb.instance.Defaults.Endpoint || _jp.Defaults.Endpoint; + this.setEndpoint(ep, true); + var anchorParamsToUse = params.anchor ? params.anchor : params.anchors ? params.anchors : (_jsPlumb.Defaults.Anchor || "Top"); + this.setAnchor(anchorParamsToUse, true); + + // finally, set type if it was provided + var type = [ "default", (params.type || "")].join(" "); + this.addType(type, params.data, true); + this.canvas = this.endpoint.canvas; + this.canvas._jsPlumb = this; + + this.initDraggable(); + + // pulled this out into a function so we can reuse it for the inPlaceCopy canvas; you can now drop detached connections + // back onto the endpoint you detached it from. + var _initDropTarget = function (canvas, isTransient, endpoint, referenceEndpoint) { + + if (_jp.isDropSupported(this.element)) { + var dropOptions = params.dropOptions || _jsPlumb.Defaults.DropOptions || _jp.Defaults.DropOptions; + dropOptions = _jp.extend({}, dropOptions); + dropOptions.scope = dropOptions.scope || this.scope; + var dropEvent = _jp.dragEvents.drop, + overEvent = _jp.dragEvents.over, + outEvent = _jp.dragEvents.out, + _ep = this, + drop = _jsPlumb.EndpointDropHandler({ + getEndpoint: function () { + return _ep; + }, + jsPlumb: _jsPlumb, + enabled: function () { + return endpoint != null ? endpoint.isEnabled() : true; + }, + isFull: function () { + return endpoint.isFull(); + }, + element: this.element, + elementId: this.elementId, + isSource: this.isSource, + isTarget: this.isTarget, + addClass: function (clazz) { + _ep.addClass(clazz); + }, + removeClass: function (clazz) { + _ep.removeClass(clazz); + }, + isDropAllowed: function () { + return _ep.isDropAllowed.apply(_ep, arguments); + }, + reference:referenceEndpoint, + isRedrop:function(jpc, dhParams) { + return jpc.suspendedEndpoint && dhParams.reference && (jpc.suspendedEndpoint.id === dhParams.reference.id); + } + }); + + dropOptions[dropEvent] = _ju.wrap(dropOptions[dropEvent], drop, true); + dropOptions[overEvent] = _ju.wrap(dropOptions[overEvent], function () { + var draggable = _jp.getDragObject(arguments), + id = _jsPlumb.getAttribute(_jp.getElement(draggable), "dragId"), + _jpc = _jsPlumb.getFloatingConnectionFor(id);//_jsPlumb.floatingConnections[id]; + + if (_jpc != null) { + var idx = _jsPlumb.getFloatingAnchorIndex(_jpc); + // here we should fire the 'over' event if we are a target and this is a new connection, + // or we are the same as the floating endpoint. + var _cont = (this.isTarget && idx !== 0) || (_jpc.suspendedEndpoint && this.referenceEndpoint && this.referenceEndpoint.id === _jpc.suspendedEndpoint.id); + if (_cont) { + var bb = _jsPlumb.checkCondition("checkDropAllowed", { + sourceEndpoint: _jpc.endpoints[idx], + targetEndpoint: this, + connection: _jpc + }); + this[(bb ? "add" : "remove") + "Class"](_jsPlumb.endpointDropAllowedClass); + this[(bb ? "remove" : "add") + "Class"](_jsPlumb.endpointDropForbiddenClass); + _jpc.endpoints[idx].anchor.over(this.anchor, this); + } + } + }.bind(this)); + + dropOptions[outEvent] = _ju.wrap(dropOptions[outEvent], function () { + var draggable = _jp.getDragObject(arguments), + id = draggable == null ? null : _jsPlumb.getAttribute(_jp.getElement(draggable), "dragId"), + _jpc = id ? _jsPlumb.getFloatingConnectionFor(id) : null; + + if (_jpc != null) { + var idx = _jsPlumb.getFloatingAnchorIndex(_jpc); + var _cont = (this.isTarget && idx !== 0) || (_jpc.suspendedEndpoint && this.referenceEndpoint && this.referenceEndpoint.id === _jpc.suspendedEndpoint.id); + if (_cont) { + this.removeClass(_jsPlumb.endpointDropAllowedClass); + this.removeClass(_jsPlumb.endpointDropForbiddenClass); + _jpc.endpoints[idx].anchor.out(); + } + } + }.bind(this)); + + _jsPlumb.initDroppable(canvas, dropOptions, "internal", isTransient); + } + }.bind(this); + + // Initialise the endpoint's canvas as a drop target. The drop handler will take care of the logic of whether + // something can actually be dropped. + if (!this.anchor.isFloating) { + _initDropTarget(this.canvas, !(params._transient || this.anchor.isFloating), this, params.reference); + } + + return this; + }; + + _ju.extend(_jp.Endpoint, _jp.OverlayCapableJsPlumbUIComponent, { + + setVisible: function (v, doNotChangeConnections, doNotNotifyOtherEndpoint) { + this._jsPlumb.visible = v; + if (this.canvas) { + this.canvas.style.display = v ? "block" : "none"; + } + this[v ? "showOverlays" : "hideOverlays"](); + if (!doNotChangeConnections) { + for (var i = 0; i < this.connections.length; i++) { + this.connections[i].setVisible(v); + if (!doNotNotifyOtherEndpoint) { + var oIdx = this === this.connections[i].endpoints[0] ? 1 : 0; + // only change the other endpoint if this is its only connection. + if (this.connections[i].endpoints[oIdx].connections.length === 1) { + this.connections[i].endpoints[oIdx].setVisible(v, true, true); + } + } + } + } + }, + getAttachedElements: function () { + return this.connections; + }, + applyType: function (t, doNotRepaint) { + this.setPaintStyle(t.endpointStyle || t.paintStyle, doNotRepaint); + this.setHoverPaintStyle(t.endpointHoverStyle || t.hoverPaintStyle, doNotRepaint); + if (t.maxConnections != null) { + this._jsPlumb.maxConnections = t.maxConnections; + } + if (t.scope) { + this.scope = t.scope; + } + _jp.extend(this, t, typeParameters); + if (t.cssClass != null && this.canvas) { + this._jsPlumb.instance.addClass(this.canvas, t.cssClass); + } + _jp.OverlayCapableJsPlumbUIComponent.applyType(this, t); + }, + isEnabled: function () { + return this._jsPlumb.enabled; + }, + setEnabled: function (e) { + this._jsPlumb.enabled = e; + }, + cleanup: function () { + var anchorClass = this._jsPlumb.instance.endpointAnchorClassPrefix + (this._jsPlumb.currentAnchorClass ? "-" + this._jsPlumb.currentAnchorClass : ""); + _jp.removeClass(this.element, anchorClass); + this.anchor = null; + this.endpoint.cleanup(true); + this.endpoint.destroy(); + this.endpoint = null; + // drag/drop + this._jsPlumb.instance.destroyDraggable(this.canvas, "internal"); + this._jsPlumb.instance.destroyDroppable(this.canvas, "internal"); + }, + setHover: function (h) { + if (this.endpoint && this._jsPlumb && !this._jsPlumb.instance.isConnectionBeingDragged()) { + this.endpoint.setHover(h); + } + }, + isFull: function () { + return this._jsPlumb.maxConnections === 0 ? true : !(this.isFloating() || this._jsPlumb.maxConnections < 0 || this.connections.length < this._jsPlumb.maxConnections); + }, + /** + * private but needs to be exposed. + */ + isFloating: function () { + return this.anchor != null && this.anchor.isFloating; + }, + isConnectedTo: function (endpoint) { + var found = false; + if (endpoint) { + for (var i = 0; i < this.connections.length; i++) { + if (this.connections[i].endpoints[1] === endpoint || this.connections[i].endpoints[0] === endpoint) { + found = true; + break; + } + } + } + return found; + }, + getConnectionCost: function () { + return this._jsPlumb.connectionCost; + }, + setConnectionCost: function (c) { + this._jsPlumb.connectionCost = c; + }, + areConnectionsDirected: function () { + return this._jsPlumb.connectionsDirected; + }, + setConnectionsDirected: function (b) { + this._jsPlumb.connectionsDirected = b; + }, + setElementId: function (_elId) { + this.elementId = _elId; + this.anchor.elementId = _elId; + }, + setReferenceElement: function (_el) { + this.element = _jp.getElement(_el); + }, + setDragAllowedWhenFull: function (allowed) { + this.dragAllowedWhenFull = allowed; + }, + equals: function (endpoint) { + return this.anchor.equals(endpoint.anchor); + }, + getUuid: function () { + return this._jsPlumb.uuid; + }, + computeAnchor: function (params) { + return this.anchor.compute(params); + } + }); + + root.jsPlumbInstance.prototype.EndpointDropHandler = function (dhParams) { + return function (e) { + + var _jsPlumb = dhParams.jsPlumb; + + // remove the classes that are added dynamically. drop is neither forbidden nor allowed now that + // the drop is finishing. + dhParams.removeClass(_jsPlumb.endpointDropAllowedClass); + dhParams.removeClass(_jsPlumb.endpointDropForbiddenClass); + + var originalEvent = _jsPlumb.getDropEvent(arguments), + draggable = _jsPlumb.getDragObject(arguments), + id = _jsPlumb.getAttribute(draggable, "dragId"), + elId = _jsPlumb.getAttribute(draggable, "elId"), + scope = _jsPlumb.getAttribute(draggable, "originalScope"), + jpc = _jsPlumb.getFloatingConnectionFor(id); + + // if no active connection, bail. + if (jpc == null) { + return; + } + + // calculate if this is an existing connection. + var existingConnection = jpc.suspendedEndpoint != null; + + // if suspended endpoint exists but has been cleaned up, bail. This means it's an existing connection + // that has been detached and will shortly be discarded. + if (existingConnection && jpc.suspendedEndpoint._jsPlumb == null) { + return; + } + + // get the drop endpoint. for a normal connection this is just the one that would replace the currently + // floating endpoint. for a makeTarget this is a new endpoint that is created on drop. But we leave that to + // the handler to figure out. + var _ep = dhParams.getEndpoint(jpc); + + // If we're not given an endpoint to use, bail. + if (_ep == null) { + return; + } + + // if this is a drop back where the connection came from, mark it force reattach and + // return; the stop handler will reattach. without firing an event. + if (dhParams.isRedrop(jpc, dhParams)) { + jpc._forceReattach = true; + jpc.setHover(false); + if (dhParams.maybeCleanup) { + dhParams.maybeCleanup(_ep); + } + return; + } + + // ensure we dont bother trying to drop sources on non-source eps, and same for target. + var idx = _jsPlumb.getFloatingAnchorIndex(jpc); + if ((idx === 0 && !dhParams.isSource)|| (idx === 1 && !dhParams.isTarget)){ + if (dhParams.maybeCleanup) { + dhParams.maybeCleanup(_ep); + } + return; + } + + if (dhParams.onDrop) { + dhParams.onDrop(jpc); + } + + // restore the original scope if necessary (issue 57) + if (scope) { + _jsPlumb.setDragScope(draggable, scope); + } + + // if the target of the drop is full, fire an event (we abort below) + // makeTarget: keep. + var isFull = dhParams.isFull(e); + if (isFull) { + _ep.fire("maxConnections", { + endpoint: this, + connection: jpc, + maxConnections: _ep._jsPlumb.maxConnections + }, originalEvent); + } + // + // if endpoint enabled, not full, and matches the index of the floating endpoint... + if (!isFull && dhParams.enabled()) { + var _doContinue = true; + + // before testing for beforeDrop, reset the connection's source/target to be the actual DOM elements + // involved (that is, stash any temporary stuff used for dragging. but we need to keep it around in + // order that the anchor manager can clean things up properly). + if (idx === 0) { + jpc.floatingElement = jpc.source; + jpc.floatingId = jpc.sourceId; + jpc.floatingEndpoint = jpc.endpoints[0]; + jpc.floatingIndex = 0; + jpc.source = dhParams.element; + jpc.sourceId = dhParams.elementId; + } else { + jpc.floatingElement = jpc.target; + jpc.floatingId = jpc.targetId; + jpc.floatingEndpoint = jpc.endpoints[1]; + jpc.floatingIndex = 1; + jpc.target = dhParams.element; + jpc.targetId = dhParams.elementId; + } + + // if this is an existing connection and detach is not allowed we won't continue. The connection's + // endpoints have been reinstated; everything is back to how it was. + if (existingConnection && jpc.suspendedEndpoint.id !== _ep.id) { + if (!jpc.isDetachAllowed(jpc) || !jpc.endpoints[idx].isDetachAllowed(jpc) || !jpc.suspendedEndpoint.isDetachAllowed(jpc) || !_jsPlumb.checkCondition("beforeDetach", jpc)) { + _doContinue = false; + } + } + +// ------------ wrap the execution path in a function so we can support asynchronous beforeDrop + + var continueFunction = function (optionalData) { + // remove this jpc from the current endpoint, which is a floating endpoint that we will + // subsequently discard. + jpc.endpoints[idx].detachFromConnection(jpc); + + // if there's a suspended endpoint, detach it from the connection. + if (jpc.suspendedEndpoint) { + jpc.suspendedEndpoint.detachFromConnection(jpc); + } + + jpc.endpoints[idx] = _ep; + _ep.addConnection(jpc); + + // copy our parameters in to the connection: + var params = _ep.getParameters(); + for (var aParam in params) { + jpc.setParameter(aParam, params[aParam]); + } + + if (!existingConnection) { + // if not an existing connection and + if (params.draggable) { + _jsPlumb.initDraggable(this.element, dhParams.dragOptions, "internal", _jsPlumb); + } + } + else { + var suspendedElementId = jpc.suspendedEndpoint.elementId; + _jsPlumb.fireMoveEvent({ + index: idx, + originalSourceId: idx === 0 ? suspendedElementId : jpc.sourceId, + newSourceId: idx === 0 ? _ep.elementId : jpc.sourceId, + originalTargetId: idx === 1 ? suspendedElementId : jpc.targetId, + newTargetId: idx === 1 ? _ep.elementId : jpc.targetId, + originalSourceEndpoint: idx === 0 ? jpc.suspendedEndpoint : jpc.endpoints[0], + newSourceEndpoint: idx === 0 ? _ep : jpc.endpoints[0], + originalTargetEndpoint: idx === 1 ? jpc.suspendedEndpoint : jpc.endpoints[1], + newTargetEndpoint: idx === 1 ? _ep : jpc.endpoints[1], + connection: jpc + }, originalEvent); + } + + if (idx === 1) { + _jsPlumb.anchorManager.updateOtherEndpoint(jpc.sourceId, jpc.floatingId, jpc.targetId, jpc); + } + else { + _jsPlumb.anchorManager.sourceChanged(jpc.floatingId, jpc.sourceId, jpc, jpc.source); + } + + // when makeSource has uniqueEndpoint:true, we want to create connections with new endpoints + // that are subsequently deleted. So makeSource sets `finalEndpoint`, which is the Endpoint to + // which the connection should be attached. The `detachFromConnection` call below results in the + // temporary endpoint being cleaned up. + if (jpc.endpoints[0].finalEndpoint) { + var _toDelete = jpc.endpoints[0]; + _toDelete.detachFromConnection(jpc); + jpc.endpoints[0] = jpc.endpoints[0].finalEndpoint; + jpc.endpoints[0].addConnection(jpc); + } + + // if optionalData was given, merge it onto the connection's data. + if (_ju.isObject(optionalData)) { + jpc.mergeData(optionalData); + } + // finalise will inform the anchor manager and also add to + // connectionsByScope if necessary. + _jsPlumb.finaliseConnection(jpc, null, originalEvent, false); + jpc.setHover(false); + + // SP continuous anchor flush + _jsPlumb.revalidate(jpc.endpoints[0].element); + + }.bind(this); + + var dontContinueFunction = function () { + // otherwise just put it back on the endpoint it was on before the drag. + if (jpc.suspendedEndpoint) { + jpc.endpoints[idx] = jpc.suspendedEndpoint; + jpc.setHover(false); + jpc._forceDetach = true; + if (idx === 0) { + jpc.source = jpc.suspendedEndpoint.element; + jpc.sourceId = jpc.suspendedEndpoint.elementId; + } else { + jpc.target = jpc.suspendedEndpoint.element; + jpc.targetId = jpc.suspendedEndpoint.elementId; + } + jpc.suspendedEndpoint.addConnection(jpc); + + // TODO checkSanity + if (idx === 1) { + _jsPlumb.anchorManager.updateOtherEndpoint(jpc.sourceId, jpc.floatingId, jpc.targetId, jpc); + } + else { + _jsPlumb.anchorManager.sourceChanged(jpc.floatingId, jpc.sourceId, jpc, jpc.source); + } + + _jsPlumb.repaint(jpc.sourceId); + jpc._forceDetach = false; + } + }; + +// -------------------------------------- + // now check beforeDrop. this will be available only on Endpoints that are setup to + // have a beforeDrop condition (although, secretly, under the hood all Endpoints and + // the Connection have them, because they are on jsPlumbUIComponent. shhh!), because + // it only makes sense to have it on a target endpoint. + _doContinue = _doContinue && dhParams.isDropAllowed(jpc.sourceId, jpc.targetId, jpc.scope, jpc, _ep);// && jpc.pending; + + if (_doContinue) { + continueFunction(_doContinue); + return true; + } + else { + dontContinueFunction(); + } + } + + if (dhParams.maybeCleanup) { + dhParams.maybeCleanup(_ep); + } + + _jsPlumb.currentlyDragging = false; + }; + }; +}).call(typeof window !== 'undefined' ? window : this); + +/* + * This file contains the code for Connections. + * + * Copyright (c) 2010 - 2018 jsPlumb (hello@jsplumbtoolkit.com) + * + * https://jsplumbtoolkit.com + * https://github.com/jsplumb/jsplumb + * + * Dual licensed under the MIT and GPL2 licenses. + */ +; +(function () { + + "use strict"; + var root = this, + _jp = root.jsPlumb, + _ju = root.jsPlumbUtil; + + var makeConnector = function (_jsPlumb, renderMode, connectorName, connectorArgs, forComponent) { + // first make sure we have a cache for the specified renderer + _jp.Connectors[renderMode] = _jp.Connectors[renderMode] || {}; + + // now see if the one we want exists; if not we will try to make it + if (_jp.Connectors[renderMode][connectorName] == null) { + + if (_jp.Connectors[connectorName] == null) { + if (!_jsPlumb.Defaults.DoNotThrowErrors) { + throw new TypeError("jsPlumb: unknown connector type '" + connectorName + "'"); + } else { + return null; + } + } + + _jp.Connectors[renderMode][connectorName] = function() { + _jp.Connectors[connectorName].apply(this, arguments); + _jp.ConnectorRenderers[renderMode].apply(this, arguments); + }; + + _ju.extend(_jp.Connectors[renderMode][connectorName], [ _jp.Connectors[connectorName], _jp.ConnectorRenderers[renderMode]]); + + } + + return new _jp.Connectors[renderMode][connectorName](connectorArgs, forComponent); + }, + _makeAnchor = function (anchorParams, elementId, _jsPlumb) { + return (anchorParams) ? _jsPlumb.makeAnchor(anchorParams, elementId, _jsPlumb) : null; + }, + _updateConnectedClass = function (conn, element, _jsPlumb, remove) { + if (element != null) { + element._jsPlumbConnections = element._jsPlumbConnections || {}; + if (remove) { + delete element._jsPlumbConnections[conn.id]; + } + else { + element._jsPlumbConnections[conn.id] = true; + } + + if (_ju.isEmpty(element._jsPlumbConnections)) { + _jsPlumb.removeClass(element, _jsPlumb.connectedClass); + } + else { + _jsPlumb.addClass(element, _jsPlumb.connectedClass); + } + } + }; + + _jp.Connection = function (params) { + var _newEndpoint = params.newEndpoint; + + this.id = params.id; + this.connector = null; + this.idPrefix = "_jsplumb_c_"; + this.defaultLabelLocation = 0.5; + this.defaultOverlayKeys = ["Overlays", "ConnectionOverlays"]; + // if a new connection is the result of moving some existing connection, params.previousConnection + // will have that Connection in it. listeners for the jsPlumbConnection event can look for that + // member and take action if they need to. + this.previousConnection = params.previousConnection; + this.source = _jp.getElement(params.source); + this.target = _jp.getElement(params.target); + + + _jp.OverlayCapableJsPlumbUIComponent.apply(this, arguments); + + // sourceEndpoint and targetEndpoint override source/target, if they are present. but + // source is not overridden if the Endpoint has declared it is not the final target of a connection; + // instead we use the source that the Endpoint declares will be the final source element. + if (params.sourceEndpoint) { + this.source = params.sourceEndpoint.getElement(); + this.sourceId = params.sourceEndpoint.elementId; + } else { + this.sourceId = this._jsPlumb.instance.getId(this.source); + } + + if (params.targetEndpoint) { + this.target = params.targetEndpoint.getElement(); + this.targetId = params.targetEndpoint.elementId; + } else { + this.targetId = this._jsPlumb.instance.getId(this.target); + } + + + this.scope = params.scope; // scope may have been passed in to the connect call. if it wasn't, we will pull it from the source endpoint, after having initialised the endpoints. + this.endpoints = []; + this.endpointStyles = []; + + var _jsPlumb = this._jsPlumb.instance; + + _jsPlumb.manage(this.sourceId, this.source); + _jsPlumb.manage(this.targetId, this.target); + + this._jsPlumb.visible = true; + + this._jsPlumb.params = { + cssClass: params.cssClass, + container: params.container, + "pointer-events": params["pointer-events"], + editorParams: params.editorParams, + overlays: params.overlays + }; + this._jsPlumb.lastPaintedAt = null; + + // listen to mouseover and mouseout events passed from the container delegate. + this.bind("mouseover", function () { + this.setHover(true); + }.bind(this)); + this.bind("mouseout", function () { + this.setHover(false); + }.bind(this)); + + +// INITIALISATION CODE + + this.makeEndpoint = function (isSource, el, elId, ep, definition) { + elId = elId || this._jsPlumb.instance.getId(el); + return this.prepareEndpoint(_jsPlumb, _newEndpoint, this, ep, isSource ? 0 : 1, params, el, elId, definition); + }; + + // if type given, get the endpoint definitions mapping to that type from the jsplumb instance, and use those. + // we apply types at the end of this constructor but endpoints are only honoured in a type definition at + // create time. + if (params.type) { + params.endpoints = params.endpoints || this._jsPlumb.instance.deriveEndpointAndAnchorSpec(params.type).endpoints; + } + + var eS = this.makeEndpoint(true, this.source, this.sourceId, params.sourceEndpoint), + eT = this.makeEndpoint(false, this.target, this.targetId, params.targetEndpoint); + + if (eS) { + _ju.addToList(params.endpointsByElement, this.sourceId, eS); + } + if (eT) { + _ju.addToList(params.endpointsByElement, this.targetId, eT); + } + // if scope not set, set it to be the scope for the source endpoint. + if (!this.scope) { + this.scope = this.endpoints[0].scope; + } + + // if explicitly told to (or not to) delete endpoints when empty, override endpoint's preferences + if (params.deleteEndpointsOnEmpty != null) { + this.endpoints[0].setDeleteOnEmpty(params.deleteEndpointsOnEmpty); + this.endpoints[1].setDeleteOnEmpty(params.deleteEndpointsOnEmpty); + } + +// -------------------------- DEFAULT TYPE --------------------------------------------- + + // DETACHABLE + var _detachable = _jsPlumb.Defaults.ConnectionsDetachable; + if (params.detachable === false) { + _detachable = false; + } + if (this.endpoints[0].connectionsDetachable === false) { + _detachable = false; + } + if (this.endpoints[1].connectionsDetachable === false) { + _detachable = false; + } + // REATTACH + var _reattach = params.reattach || this.endpoints[0].reattachConnections || this.endpoints[1].reattachConnections || _jsPlumb.Defaults.ReattachConnections; + + this.appendToDefaultType({ + detachable: _detachable, + reattach: _reattach, + paintStyle:this.endpoints[0].connectorStyle || this.endpoints[1].connectorStyle || params.paintStyle || _jsPlumb.Defaults.PaintStyle || _jp.Defaults.PaintStyle, + hoverPaintStyle:this.endpoints[0].connectorHoverStyle || this.endpoints[1].connectorHoverStyle || params.hoverPaintStyle || _jsPlumb.Defaults.HoverPaintStyle || _jp.Defaults.HoverPaintStyle + }); + + var _suspendedAt = _jsPlumb.getSuspendedAt(); + if (!_jsPlumb.isSuspendDrawing()) { + // paint the endpoints + var myInfo = _jsPlumb.getCachedData(this.sourceId), + myOffset = myInfo.o, myWH = myInfo.s, + otherInfo = _jsPlumb.getCachedData(this.targetId), + otherOffset = otherInfo.o, + otherWH = otherInfo.s, + initialTimestamp = _suspendedAt || _jsPlumb.timestamp(), + anchorLoc = this.endpoints[0].anchor.compute({ + xy: [ myOffset.left, myOffset.top ], wh: myWH, element: this.endpoints[0], + elementId: this.endpoints[0].elementId, + txy: [ otherOffset.left, otherOffset.top ], twh: otherWH, tElement: this.endpoints[1], + timestamp: initialTimestamp + }); + + this.endpoints[0].paint({ anchorLoc: anchorLoc, timestamp: initialTimestamp }); + + anchorLoc = this.endpoints[1].anchor.compute({ + xy: [ otherOffset.left, otherOffset.top ], wh: otherWH, element: this.endpoints[1], + elementId: this.endpoints[1].elementId, + txy: [ myOffset.left, myOffset.top ], twh: myWH, tElement: this.endpoints[0], + timestamp: initialTimestamp + }); + this.endpoints[1].paint({ anchorLoc: anchorLoc, timestamp: initialTimestamp }); + } + + this.getTypeDescriptor = function () { + return "connection"; + }; + this.getAttachedElements = function () { + return this.endpoints; + }; + + this.isDetachable = function (ep) { + return this._jsPlumb.detachable === false ? false : ep != null ? ep.connectionsDetachable === true : this._jsPlumb.detachable === true; + }; + this.setDetachable = function (detachable) { + this._jsPlumb.detachable = detachable === true; + }; + this.isReattach = function () { + return this._jsPlumb.reattach === true || this.endpoints[0].reattachConnections === true || this.endpoints[1].reattachConnections === true; + }; + this.setReattach = function (reattach) { + this._jsPlumb.reattach = reattach === true; + }; + +// END INITIALISATION CODE + + +// COST + DIRECTIONALITY + // if cost not supplied, try to inherit from source endpoint + this._jsPlumb.cost = params.cost || this.endpoints[0].getConnectionCost(); + this._jsPlumb.directed = params.directed; + // inherit directed flag if set no source endpoint + if (params.directed == null) { + this._jsPlumb.directed = this.endpoints[0].areConnectionsDirected(); + } +// END COST + DIRECTIONALITY + +// PARAMETERS + // merge all the parameters objects into the connection. parameters set + // on the connection take precedence; then source endpoint params, then + // finally target endpoint params. + var _p = _jp.extend({}, this.endpoints[1].getParameters()); + _jp.extend(_p, this.endpoints[0].getParameters()); + _jp.extend(_p, this.getParameters()); + this.setParameters(_p); +// END PARAMETERS + +// PAINTING + + this.setConnector(this.endpoints[0].connector || this.endpoints[1].connector || params.connector || _jsPlumb.Defaults.Connector || _jp.Defaults.Connector, true); + var data = params.data == null || !_ju.isObject(params.data) ? {} : params.data; + this.getData = function() { return data; }; + this.setData = function(d) { data = d || {}; }; + this.mergeData = function(d) { data = _jp.extend(data, d); }; + + // the very last thing we do is apply types, if there are any. + var _types = [ "default", this.endpoints[0].connectionType, this.endpoints[1].connectionType, params.type ].join(" "); + if (/[^\s]/.test(_types)) { + this.addType(_types, params.data, true); + } + + this.updateConnectedClass(); + +// END PAINTING + }; + + _ju.extend(_jp.Connection, _jp.OverlayCapableJsPlumbUIComponent, { + applyType: function (t, doNotRepaint, typeMap) { + + var _connector = null; + if (t.connector != null) { + _connector = this.getCachedTypeItem("connector", typeMap.connector); + if (_connector == null) { + _connector = this.prepareConnector(t.connector, typeMap.connector); + this.cacheTypeItem("connector", _connector, typeMap.connector); + } + this.setPreparedConnector(_connector); + } + + // none of these things result in the creation of objects so can be ignored. + if (t.detachable != null) { + this.setDetachable(t.detachable); + } + if (t.reattach != null) { + this.setReattach(t.reattach); + } + if (t.scope) { + this.scope = t.scope; + } + + if (t.cssClass != null && this.canvas) { + this._jsPlumb.instance.addClass(this.canvas, t.cssClass); + } + + var _anchors = null; + // this also results in the creation of objects. + if (t.anchor) { + // note that even if the param was anchor, we store `anchors`. + _anchors = this.getCachedTypeItem("anchors", typeMap.anchor); + if (_anchors == null) { + _anchors = [ this._jsPlumb.instance.makeAnchor(t.anchor), this._jsPlumb.instance.makeAnchor(t.anchor) ]; + this.cacheTypeItem("anchors", _anchors, typeMap.anchor); + } + } + else if (t.anchors) { + _anchors = this.getCachedTypeItem("anchors", typeMap.anchors); + if (_anchors == null) { + _anchors = [ + this._jsPlumb.instance.makeAnchor(t.anchors[0]), + this._jsPlumb.instance.makeAnchor(t.anchors[1]) + ]; + this.cacheTypeItem("anchors", _anchors, typeMap.anchors); + } + } + if (_anchors != null) { + this.endpoints[0].anchor = _anchors[0]; + this.endpoints[1].anchor = _anchors[1]; + if (this.endpoints[1].anchor.isDynamic) { + this._jsPlumb.instance.repaint(this.endpoints[1].elementId); + } + } + + _jp.OverlayCapableJsPlumbUIComponent.applyType(this, t); + }, + addClass: function (c, informEndpoints) { + if (informEndpoints) { + this.endpoints[0].addClass(c); + this.endpoints[1].addClass(c); + if (this.suspendedEndpoint) { + this.suspendedEndpoint.addClass(c); + } + } + if (this.connector) { + this.connector.addClass(c); + } + }, + removeClass: function (c, informEndpoints) { + if (informEndpoints) { + this.endpoints[0].removeClass(c); + this.endpoints[1].removeClass(c); + if (this.suspendedEndpoint) { + this.suspendedEndpoint.removeClass(c); + } + } + if (this.connector) { + this.connector.removeClass(c); + } + }, + isVisible: function () { + return this._jsPlumb.visible; + }, + setVisible: function (v) { + this._jsPlumb.visible = v; + if (this.connector) { + this.connector.setVisible(v); + } + this.repaint(); + }, + cleanup: function () { + this.updateConnectedClass(true); + this.endpoints = null; + this.source = null; + this.target = null; + if (this.connector != null) { + this.connector.cleanup(true); + this.connector.destroy(true); + } + this.connector = null; + }, + updateConnectedClass:function(remove) { + if (this._jsPlumb) { + _updateConnectedClass(this, this.source, this._jsPlumb.instance, remove); + _updateConnectedClass(this, this.target, this._jsPlumb.instance, remove); + } + }, + setHover: function (state) { + if (this.connector && this._jsPlumb && !this._jsPlumb.instance.isConnectionBeingDragged()) { + this.connector.setHover(state); + root.jsPlumb[state ? "addClass" : "removeClass"](this.source, this._jsPlumb.instance.hoverSourceClass); + root.jsPlumb[state ? "addClass" : "removeClass"](this.target, this._jsPlumb.instance.hoverTargetClass); + } + }, + getUuids:function() { + return [ this.endpoints[0].getUuid(), this.endpoints[1].getUuid() ]; + }, + getCost: function () { + return this._jsPlumb ? this._jsPlumb.cost : -Infinity; + }, + setCost: function (c) { + this._jsPlumb.cost = c; + }, + isDirected: function () { + return this._jsPlumb.directed; + }, + getConnector: function () { + return this.connector; + }, + prepareConnector:function(connectorSpec, typeId) { + var connectorArgs = { + _jsPlumb: this._jsPlumb.instance, + cssClass: this._jsPlumb.params.cssClass, + container: this._jsPlumb.params.container, + "pointer-events": this._jsPlumb.params["pointer-events"] + }, + renderMode = this._jsPlumb.instance.getRenderMode(), + connector; + + if (_ju.isString(connectorSpec)) { + connector = makeConnector(this._jsPlumb.instance, renderMode, connectorSpec, connectorArgs, this); + } // lets you use a string as shorthand. + else if (_ju.isArray(connectorSpec)) { + if (connectorSpec.length === 1) { + connector = makeConnector(this._jsPlumb.instance, renderMode, connectorSpec[0], connectorArgs, this); + } + else { + connector = makeConnector(this._jsPlumb.instance, renderMode, connectorSpec[0], _ju.merge(connectorSpec[1], connectorArgs), this); + } + } + if (typeId != null) { + connector.typeId = typeId; + } + return connector; + }, + setPreparedConnector: function(connector, doNotRepaint, doNotChangeListenerComponent, typeId) { + + if (this.connector !== connector) { + + var previous, previousClasses = ""; + // the connector will not be cleaned up if it was set as part of a type, because `typeId` will be set on it + // and we havent passed in `true` for "force" here. + if (this.connector != null) { + previous = this.connector; + previousClasses = previous.getClass(); + this.connector.cleanup(); + this.connector.destroy(); + } + + this.connector = connector; + if (typeId) { + this.cacheTypeItem("connector", connector, typeId); + } + + this.canvas = this.connector.canvas; + this.bgCanvas = this.connector.bgCanvas; + + this.connector.reattach(this._jsPlumb.instance); + + // put classes from prior connector onto the canvas + this.addClass(previousClasses); + + // new: instead of binding listeners per connector, we now just have one delegate on the container. + // so for that handler we set the connection as the '_jsPlumb' member of the canvas element, and + // bgCanvas, if it exists, which it does right now in the VML renderer, so it won't from v 2.0.0 onwards. + if (this.canvas) { + this.canvas._jsPlumb = this; + } + if (this.bgCanvas) { + this.bgCanvas._jsPlumb = this; + } + + if (previous != null) { + var o = this.getOverlays(); + for (var i = 0; i < o.length; i++) { + if (o[i].transfer) { + o[i].transfer(this.connector); + } + } + } + + if (!doNotChangeListenerComponent) { + this.setListenerComponent(this.connector); + } + if (!doNotRepaint) { + this.repaint(); + } + } + }, + setConnector: function (connectorSpec, doNotRepaint, doNotChangeListenerComponent, typeId) { + var connector = this.prepareConnector(connectorSpec, typeId); + this.setPreparedConnector(connector, doNotRepaint, doNotChangeListenerComponent, typeId); + }, + paint: function (params) { + + if (!this._jsPlumb.instance.isSuspendDrawing() && this._jsPlumb.visible) { + params = params || {}; + var timestamp = params.timestamp, + // if the moving object is not the source we must transpose the two references. + swap = false, + tId = swap ? this.sourceId : this.targetId, sId = swap ? this.targetId : this.sourceId, + tIdx = swap ? 0 : 1, sIdx = swap ? 1 : 0; + + if (timestamp == null || timestamp !== this._jsPlumb.lastPaintedAt) { + var sourceInfo = this._jsPlumb.instance.updateOffset({elId:sId}).o, + targetInfo = this._jsPlumb.instance.updateOffset({elId:tId}).o, + sE = this.endpoints[sIdx], tE = this.endpoints[tIdx]; + + var sAnchorP = sE.anchor.getCurrentLocation({xy: [sourceInfo.left, sourceInfo.top], wh: [sourceInfo.width, sourceInfo.height], element: sE, timestamp: timestamp}), + tAnchorP = tE.anchor.getCurrentLocation({xy: [targetInfo.left, targetInfo.top], wh: [targetInfo.width, targetInfo.height], element: tE, timestamp: timestamp}); + + this.connector.resetBounds(); + + this.connector.compute({ + sourcePos: sAnchorP, + targetPos: tAnchorP, + sourceOrientation:sE.anchor.getOrientation(sE), + targetOrientation:tE.anchor.getOrientation(tE), + sourceEndpoint: this.endpoints[sIdx], + targetEndpoint: this.endpoints[tIdx], + "stroke-width": this._jsPlumb.paintStyleInUse.strokeWidth, + sourceInfo: sourceInfo, + targetInfo: targetInfo + }); + + var overlayExtents = { minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity }; + + // compute overlays. we do this first so we can get their placements, and adjust the + // container if needs be (if an overlay would be clipped) + for (var i in this._jsPlumb.overlays) { + if (this._jsPlumb.overlays.hasOwnProperty(i)) { + var o = this._jsPlumb.overlays[i]; + if (o.isVisible()) { + this._jsPlumb.overlayPlacements[i] = o.draw(this.connector, this._jsPlumb.paintStyleInUse, this.getAbsoluteOverlayPosition(o)); + overlayExtents.minX = Math.min(overlayExtents.minX, this._jsPlumb.overlayPlacements[i].minX); + overlayExtents.maxX = Math.max(overlayExtents.maxX, this._jsPlumb.overlayPlacements[i].maxX); + overlayExtents.minY = Math.min(overlayExtents.minY, this._jsPlumb.overlayPlacements[i].minY); + overlayExtents.maxY = Math.max(overlayExtents.maxY, this._jsPlumb.overlayPlacements[i].maxY); + } + } + } + + var lineWidth = parseFloat(this._jsPlumb.paintStyleInUse.strokeWidth || 1) / 2, + outlineWidth = parseFloat(this._jsPlumb.paintStyleInUse.strokeWidth || 0), + extents = { + xmin: Math.min(this.connector.bounds.minX - (lineWidth + outlineWidth), overlayExtents.minX), + ymin: Math.min(this.connector.bounds.minY - (lineWidth + outlineWidth), overlayExtents.minY), + xmax: Math.max(this.connector.bounds.maxX + (lineWidth + outlineWidth), overlayExtents.maxX), + ymax: Math.max(this.connector.bounds.maxY + (lineWidth + outlineWidth), overlayExtents.maxY) + }; + // paint the connector. + this.connector.paintExtents = extents; + this.connector.paint(this._jsPlumb.paintStyleInUse, null, extents); + // and then the overlays + for (var j in this._jsPlumb.overlays) { + if (this._jsPlumb.overlays.hasOwnProperty(j)) { + var p = this._jsPlumb.overlays[j]; + if (p.isVisible()) { + p.paint(this._jsPlumb.overlayPlacements[j], extents); + } + } + } + } + this._jsPlumb.lastPaintedAt = timestamp; + } + }, + repaint: function (params) { + var p = jsPlumb.extend(params || {}, {}); + p.elId = this.sourceId; + this.paint(p); + }, + prepareEndpoint: function (_jsPlumb, _newEndpoint, conn, existing, index, params, element, elementId, definition) { + var e; + if (existing) { + conn.endpoints[index] = existing; + existing.addConnection(conn); + } else { + if (!params.endpoints) { + params.endpoints = [ null, null ]; + } + var ep = definition || params.endpoints[index] || params.endpoint || _jsPlumb.Defaults.Endpoints[index] || _jp.Defaults.Endpoints[index] || _jsPlumb.Defaults.Endpoint || _jp.Defaults.Endpoint; + if (!params.endpointStyles) { + params.endpointStyles = [ null, null ]; + } + if (!params.endpointHoverStyles) { + params.endpointHoverStyles = [ null, null ]; + } + var es = params.endpointStyles[index] || params.endpointStyle || _jsPlumb.Defaults.EndpointStyles[index] || _jp.Defaults.EndpointStyles[index] || _jsPlumb.Defaults.EndpointStyle || _jp.Defaults.EndpointStyle; + // Endpoints derive their fill from the connector's stroke, if no fill was specified. + if (es.fill == null && params.paintStyle != null) { + es.fill = params.paintStyle.stroke; + } + + if (es.outlineStroke == null && params.paintStyle != null) { + es.outlineStroke = params.paintStyle.outlineStroke; + } + if (es.outlineWidth == null && params.paintStyle != null) { + es.outlineWidth = params.paintStyle.outlineWidth; + } + + var ehs = params.endpointHoverStyles[index] || params.endpointHoverStyle || _jsPlumb.Defaults.EndpointHoverStyles[index] || _jp.Defaults.EndpointHoverStyles[index] || _jsPlumb.Defaults.EndpointHoverStyle || _jp.Defaults.EndpointHoverStyle; + // endpoint hover fill style is derived from connector's hover stroke style + if (params.hoverPaintStyle != null) { + if (ehs == null) { + ehs = {}; + } + if (ehs.fill == null) { + ehs.fill = params.hoverPaintStyle.stroke; + } + } + var a = params.anchors ? params.anchors[index] : + params.anchor ? params.anchor : + _makeAnchor(_jsPlumb.Defaults.Anchors[index], elementId, _jsPlumb) || + _makeAnchor(_jp.Defaults.Anchors[index], elementId, _jsPlumb) || + _makeAnchor(_jsPlumb.Defaults.Anchor, elementId, _jsPlumb) || + _makeAnchor(_jp.Defaults.Anchor, elementId, _jsPlumb), + u = params.uuids ? params.uuids[index] : null; + + e = _newEndpoint({ + paintStyle: es, hoverPaintStyle: ehs, endpoint: ep, connections: [ conn ], + uuid: u, anchor: a, source: element, scope: params.scope, + reattach: params.reattach || _jsPlumb.Defaults.ReattachConnections, + detachable: params.detachable || _jsPlumb.Defaults.ConnectionsDetachable + }); + if (existing == null) { + e.setDeleteOnEmpty(true); + } + conn.endpoints[index] = e; + + if (params.drawEndpoints === false) { + e.setVisible(false, true, true); + } + + } + return e; + }, + replaceEndpoint:function(idx, endpointDef) { + + var current = this.endpoints[idx], + elId = current.elementId, + ebe = this._jsPlumb.instance.getEndpoints(elId), + _idx = ebe.indexOf(current), + _new = this.makeEndpoint(idx === 0, current.element, elId, null, endpointDef); + + this.endpoints[idx] = _new; + + ebe.splice(_idx, 1, _new); + this._jsPlumb.instance.deleteObject({endpoint:current, deleteAttachedObjects:false}); + this._jsPlumb.instance.fire("endpointReplaced", {previous:current, current:_new}); + + this._jsPlumb.instance.anchorManager.updateOtherEndpoint(this.endpoints[0].elementId, this.endpoints[1].elementId, this.endpoints[1].elementId, this); + + } + + }); // END Connection class +}).call(typeof window !== 'undefined' ? window : this); + +/* + * This file contains the code for creating and manipulating anchors. + * + * Copyright (c) 2010 - 2018 jsPlumb (hello@jsplumbtoolkit.com) + * + * https://jsplumbtoolkit.com + * https://github.com/jsplumb/jsplumb + * + * Dual licensed under the MIT and GPL2 licenses. + */ +; +(function () { + + "use strict"; + + var root = this, + _ju = root.jsPlumbUtil, + _jp = root.jsPlumb; + + // + // manages anchors for all elements. + // + _jp.AnchorManager = function (params) { + var _amEndpoints = {}, + continuousAnchorLocations = {}, + continuousAnchorOrientations = {}, + connectionsByElementId = {}, + self = this, + anchorLists = {}, + jsPlumbInstance = params.jsPlumbInstance, + floatingConnections = {}, + // used by placeAnchors function + placeAnchorsOnLine = function (desc, elementDimensions, elementPosition, connections, horizontal, otherMultiplier, reverse) { + var a = [], step = elementDimensions[horizontal ? 0 : 1] / (connections.length + 1); + + for (var i = 0; i < connections.length; i++) { + var val = (i + 1) * step, other = otherMultiplier * elementDimensions[horizontal ? 1 : 0]; + if (reverse) { + val = elementDimensions[horizontal ? 0 : 1] - val; + } + + var dx = (horizontal ? val : other), x = elementPosition[0] + dx, xp = dx / elementDimensions[0], + dy = (horizontal ? other : val), y = elementPosition[1] + dy, yp = dy / elementDimensions[1]; + + a.push([ x, y, xp, yp, connections[i][1], connections[i][2] ]); + } + + return a; + }, + // used by edgeSortFunctions + currySort = function (reverseAngles) { + return function (a, b) { + var r = true; + if (reverseAngles) { + r = a[0][0] < b[0][0]; + } + else { + r = a[0][0] > b[0][0]; + } + return r === false ? -1 : 1; + }; + }, + // used by edgeSortFunctions + leftSort = function (a, b) { + // first get adjusted values + var p1 = a[0][0] < 0 ? -Math.PI - a[0][0] : Math.PI - a[0][0], + p2 = b[0][0] < 0 ? -Math.PI - b[0][0] : Math.PI - b[0][0]; + if (p1 > p2) { + return 1; + } + else { + return -1; + } + }, + // used by placeAnchors + edgeSortFunctions = { + "top": function (a, b) { + return a[0] > b[0] ? 1 : -1; + }, + "right": currySort(true), + "bottom": currySort(true), + "left": leftSort + }, + // used by placeAnchors + _sortHelper = function (_array, _fn) { + return _array.sort(_fn); + }, + // used by AnchorManager.redraw + placeAnchors = function (elementId, _anchorLists) { + var cd = jsPlumbInstance.getCachedData(elementId), sS = cd.s, sO = cd.o, + placeSomeAnchors = function (desc, elementDimensions, elementPosition, unsortedConnections, isHorizontal, otherMultiplier, orientation) { + if (unsortedConnections.length > 0) { + var sc = _sortHelper(unsortedConnections, edgeSortFunctions[desc]), // puts them in order based on the target element's pos on screen + reverse = desc === "right" || desc === "top", + anchors = placeAnchorsOnLine(desc, elementDimensions, + elementPosition, sc, + isHorizontal, otherMultiplier, reverse); + + // takes a computed anchor position and adjusts it for parent offset and scroll, then stores it. + var _setAnchorLocation = function (endpoint, anchorPos) { + continuousAnchorLocations[endpoint.id] = [ anchorPos[0], anchorPos[1], anchorPos[2], anchorPos[3] ]; + continuousAnchorOrientations[endpoint.id] = orientation; + }; + + for (var i = 0; i < anchors.length; i++) { + var c = anchors[i][4], weAreSource = c.endpoints[0].elementId === elementId, weAreTarget = c.endpoints[1].elementId === elementId; + if (weAreSource) { + _setAnchorLocation(c.endpoints[0], anchors[i]); + } + if (weAreTarget) { + _setAnchorLocation(c.endpoints[1], anchors[i]); + } + } + } + }; + + placeSomeAnchors("bottom", sS, [sO.left, sO.top], _anchorLists.bottom, true, 1, [0, 1]); + placeSomeAnchors("top", sS, [sO.left, sO.top], _anchorLists.top, true, 0, [0, -1]); + placeSomeAnchors("left", sS, [sO.left, sO.top], _anchorLists.left, false, 0, [-1, 0]); + placeSomeAnchors("right", sS, [sO.left, sO.top], _anchorLists.right, false, 1, [1, 0]); + }; + + this.reset = function () { + _amEndpoints = {}; + connectionsByElementId = {}; + anchorLists = {}; + }; + this.addFloatingConnection = function (key, conn) { + floatingConnections[key] = conn; + }; + this.removeFloatingConnection = function (key) { + delete floatingConnections[key]; + }; + this.newConnection = function (conn) { + var sourceId = conn.sourceId, targetId = conn.targetId, + ep = conn.endpoints, + doRegisterTarget = true, + registerConnection = function (otherIndex, otherEndpoint, otherAnchor, elId, c) { + if ((sourceId === targetId) && otherAnchor.isContinuous) { + // remove the target endpoint's canvas. we dont need it. + conn._jsPlumb.instance.removeElement(ep[1].canvas); + doRegisterTarget = false; + } + _ju.addToList(connectionsByElementId, elId, [c, otherEndpoint, otherAnchor.constructor === _jp.DynamicAnchor]); + }; + + registerConnection(0, ep[0], ep[0].anchor, targetId, conn); + if (doRegisterTarget) { + registerConnection(1, ep[1], ep[1].anchor, sourceId, conn); + } + }; + var removeEndpointFromAnchorLists = function (endpoint) { + (function (list, eId) { + if (list) { // transient anchors dont get entries in this list. + var f = function (e) { + return e[4] === eId; + }; + _ju.removeWithFunction(list.top, f); + _ju.removeWithFunction(list.left, f); + _ju.removeWithFunction(list.bottom, f); + _ju.removeWithFunction(list.right, f); + } + })(anchorLists[endpoint.elementId], endpoint.id); + }; + this.connectionDetached = function (connInfo, doNotRedraw) { + var connection = connInfo.connection || connInfo, + sourceId = connInfo.sourceId, + targetId = connInfo.targetId, + ep = connection.endpoints, + removeConnection = function (otherIndex, otherEndpoint, otherAnchor, elId, c) { + _ju.removeWithFunction(connectionsByElementId[elId], function (_c) { + return _c[0].id === c.id; + }); + }; + + removeConnection(1, ep[1], ep[1].anchor, sourceId, connection); + removeConnection(0, ep[0], ep[0].anchor, targetId, connection); + if (connection.floatingId) { + removeConnection(connection.floatingIndex, connection.floatingEndpoint, connection.floatingEndpoint.anchor, connection.floatingId, connection); + removeEndpointFromAnchorLists(connection.floatingEndpoint); + } + + // remove from anchorLists + removeEndpointFromAnchorLists(connection.endpoints[0]); + removeEndpointFromAnchorLists(connection.endpoints[1]); + + if (!doNotRedraw) { + self.redraw(connection.sourceId); + if (connection.targetId !== connection.sourceId) { + self.redraw(connection.targetId); + } + } + }; + this.add = function (endpoint, elementId) { + _ju.addToList(_amEndpoints, elementId, endpoint); + }; + this.changeId = function (oldId, newId) { + connectionsByElementId[newId] = connectionsByElementId[oldId]; + _amEndpoints[newId] = _amEndpoints[oldId]; + delete connectionsByElementId[oldId]; + delete _amEndpoints[oldId]; + }; + this.getConnectionsFor = function (elementId) { + return connectionsByElementId[elementId] || []; + }; + this.getEndpointsFor = function (elementId) { + return _amEndpoints[elementId] || []; + }; + this.deleteEndpoint = function (endpoint) { + _ju.removeWithFunction(_amEndpoints[endpoint.elementId], function (e) { + return e.id === endpoint.id; + }); + removeEndpointFromAnchorLists(endpoint); + }; + this.clearFor = function (elementId) { + delete _amEndpoints[elementId]; + _amEndpoints[elementId] = []; + }; + // updates the given anchor list by either updating an existing anchor's info, or adding it. this function + // also removes the anchor from its previous list, if the edge it is on has changed. + // all connections found along the way (those that are connected to one of the faces this function + // operates on) are added to the connsToPaint list, as are their endpoints. in this way we know to repaint + // them wthout having to calculate anything else about them. + var _updateAnchorList = function (lists, theta, order, conn, aBoolean, otherElId, idx, reverse, edgeId, elId, connsToPaint, endpointsToPaint) { + // first try to find the exact match, but keep track of the first index of a matching element id along the way.s + var exactIdx = -1, + firstMatchingElIdx = -1, + endpoint = conn.endpoints[idx], + endpointId = endpoint.id, + oIdx = [1, 0][idx], + values = [ + [ theta, order ], + conn, + aBoolean, + otherElId, + endpointId + ], + listToAddTo = lists[edgeId], + listToRemoveFrom = endpoint._continuousAnchorEdge ? lists[endpoint._continuousAnchorEdge] : null, + i, + candidate; + + if (listToRemoveFrom) { + var rIdx = _ju.findWithFunction(listToRemoveFrom, function (e) { + return e[4] === endpointId; + }); + if (rIdx !== -1) { + listToRemoveFrom.splice(rIdx, 1); + // get all connections from this list + for (i = 0; i < listToRemoveFrom.length; i++) { + candidate = listToRemoveFrom[i][1]; + _ju.addWithFunction(connsToPaint, candidate, function (c) { + return c.id === candidate.id; + }); + _ju.addWithFunction(endpointsToPaint, listToRemoveFrom[i][1].endpoints[idx], function (e) { + return e.id === candidate.endpoints[idx].id; + }); + _ju.addWithFunction(endpointsToPaint, listToRemoveFrom[i][1].endpoints[oIdx], function (e) { + return e.id === candidate.endpoints[oIdx].id; + }); + } + } + } + + for (i = 0; i < listToAddTo.length; i++) { + candidate = listToAddTo[i][1]; + if (params.idx === 1 && listToAddTo[i][3] === otherElId && firstMatchingElIdx === -1) { + firstMatchingElIdx = i; + } + _ju.addWithFunction(connsToPaint, candidate, function (c) { + return c.id === candidate.id; + }); + _ju.addWithFunction(endpointsToPaint, listToAddTo[i][1].endpoints[idx], function (e) { + return e.id === candidate.endpoints[idx].id; + }); + _ju.addWithFunction(endpointsToPaint, listToAddTo[i][1].endpoints[oIdx], function (e) { + return e.id === candidate.endpoints[oIdx].id; + }); + } + if (exactIdx !== -1) { + listToAddTo[exactIdx] = values; + } + else { + var insertIdx = reverse ? firstMatchingElIdx !== -1 ? firstMatchingElIdx : 0 : listToAddTo.length; // of course we will get this from having looked through the array shortly. + listToAddTo.splice(insertIdx, 0, values); + } + + // store this for next time. + endpoint._continuousAnchorEdge = edgeId; + }; + + // + // find the entry in an endpoint's list for this connection and update its target endpoint + // with the current target in the connection. + // This method and sourceChanged need to be folder into one. + // + this.updateOtherEndpoint = function (sourceElId, oldTargetId, newTargetId, connection) { + var sIndex = _ju.findWithFunction(connectionsByElementId[sourceElId], function (i) { + return i[0].id === connection.id; + }), + tIndex = _ju.findWithFunction(connectionsByElementId[oldTargetId], function (i) { + return i[0].id === connection.id; + }); + + // update or add data for source + if (sIndex !== -1) { + connectionsByElementId[sourceElId][sIndex][0] = connection; + connectionsByElementId[sourceElId][sIndex][1] = connection.endpoints[1]; + connectionsByElementId[sourceElId][sIndex][2] = connection.endpoints[1].anchor.constructor === _jp.DynamicAnchor; + } + + // remove entry for previous target (if there) + if (tIndex > -1) { + connectionsByElementId[oldTargetId].splice(tIndex, 1); + // add entry for new target + _ju.addToList(connectionsByElementId, newTargetId, [connection, connection.endpoints[0], connection.endpoints[0].anchor.constructor === _jp.DynamicAnchor]); + } + + connection.updateConnectedClass(); + }; + + // + // notification that the connection given has changed source from the originalId to the newId. + // This involves: + // 1. removing the connection from the list of connections stored for the originalId + // 2. updating the source information for the target of the connection + // 3. re-registering the connection in connectionsByElementId with the newId + // + this.sourceChanged = function (originalId, newId, connection, newElement) { + if (originalId !== newId) { + + connection.sourceId = newId; + connection.source = newElement; + + // remove the entry that points from the old source to the target + _ju.removeWithFunction(connectionsByElementId[originalId], function (info) { + return info[0].id === connection.id; + }); + // find entry for target and update it + var tIdx = _ju.findWithFunction(connectionsByElementId[connection.targetId], function (i) { + return i[0].id === connection.id; + }); + if (tIdx > -1) { + connectionsByElementId[connection.targetId][tIdx][0] = connection; + connectionsByElementId[connection.targetId][tIdx][1] = connection.endpoints[0]; + connectionsByElementId[connection.targetId][tIdx][2] = connection.endpoints[0].anchor.constructor === _jp.DynamicAnchor; + } + // add entry for new source + _ju.addToList(connectionsByElementId, newId, [connection, connection.endpoints[1], connection.endpoints[1].anchor.constructor === _jp.DynamicAnchor]); + + // TODO SP not final on this yet. when a user drags an existing connection and it turns into a self + // loop, then this code hides the target endpoint (by removing it from the DOM) But I think this should + // occur only if the anchor is Continuous + if (connection.endpoints[1].anchor.isContinuous) { + if (connection.source === connection.target) { + connection._jsPlumb.instance.removeElement(connection.endpoints[1].canvas); + } + else { + if (connection.endpoints[1].canvas.parentNode == null) { + connection._jsPlumb.instance.appendElement(connection.endpoints[1].canvas); + } + } + } + + connection.updateConnectedClass(); + } + }; + + // + // moves the given endpoint from `currentId` to `element`. + // This involves: + // + // 1. changing the key in _amEndpoints under which the endpoint is stored + // 2. changing the source or target values in all of the endpoint's connections + // 3. changing the array in connectionsByElementId in which the endpoint's connections + // are stored (done by either sourceChanged or updateOtherEndpoint) + // + this.rehomeEndpoint = function (ep, currentId, element) { + var eps = _amEndpoints[currentId] || [], + elementId = jsPlumbInstance.getId(element); + + if (elementId !== currentId) { + var idx = eps.indexOf(ep); + if (idx > -1) { + var _ep = eps.splice(idx, 1)[0]; + self.add(_ep, elementId); + } + } + + for (var i = 0; i < ep.connections.length; i++) { + if (ep.connections[i].sourceId === currentId) { + self.sourceChanged(currentId, ep.elementId, ep.connections[i], ep.element); + } + else if (ep.connections[i].targetId === currentId) { + ep.connections[i].targetId = ep.elementId; + ep.connections[i].target = ep.element; + self.updateOtherEndpoint(ep.connections[i].sourceId, currentId, ep.elementId, ep.connections[i]); + } + } + }; + + this.redraw = function (elementId, ui, timestamp, offsetToUI, clearEdits, doNotRecalcEndpoint) { + + if (!jsPlumbInstance.isSuspendDrawing()) { + // get all the endpoints for this element + var ep = _amEndpoints[elementId] || [], + endpointConnections = connectionsByElementId[elementId] || [], + connectionsToPaint = [], + endpointsToPaint = [], + anchorsToUpdate = []; + + timestamp = timestamp || jsPlumbInstance.timestamp(); + // offsetToUI are values that would have been calculated in the dragManager when registering + // an endpoint for an element that had a parent (somewhere in the hierarchy) that had been + // registered as draggable. + offsetToUI = offsetToUI || {left: 0, top: 0}; + if (ui) { + ui = { + left: ui.left + offsetToUI.left, + top: ui.top + offsetToUI.top + }; + } + + // valid for one paint cycle. + var myOffset = jsPlumbInstance.updateOffset({ elId: elementId, offset: ui, recalc: false, timestamp: timestamp }), + orientationCache = {}; + + // actually, first we should compute the orientation of this element to all other elements to which + // this element is connected with a continuous anchor (whether both ends of the connection have + // a continuous anchor or just one) + + for (var i = 0; i < endpointConnections.length; i++) { + var conn = endpointConnections[i][0], + sourceId = conn.sourceId, + targetId = conn.targetId, + sourceContinuous = conn.endpoints[0].anchor.isContinuous, + targetContinuous = conn.endpoints[1].anchor.isContinuous; + + if (sourceContinuous || targetContinuous) { + var oKey = sourceId + "_" + targetId, + o = orientationCache[oKey], + oIdx = conn.sourceId === elementId ? 1 : 0; + + if (sourceContinuous && !anchorLists[sourceId]) { + anchorLists[sourceId] = { top: [], right: [], bottom: [], left: [] }; + } + if (targetContinuous && !anchorLists[targetId]) { + anchorLists[targetId] = { top: [], right: [], bottom: [], left: [] }; + } + + if (elementId !== targetId) { + jsPlumbInstance.updateOffset({ elId: targetId, timestamp: timestamp }); + } + if (elementId !== sourceId) { + jsPlumbInstance.updateOffset({ elId: sourceId, timestamp: timestamp }); + } + + var td = jsPlumbInstance.getCachedData(targetId), + sd = jsPlumbInstance.getCachedData(sourceId); + + if (targetId === sourceId && (sourceContinuous || targetContinuous)) { + // here we may want to improve this by somehow determining the face we'd like + // to put the connector on. ideally, when drawing, the face should be calculated + // by determining which face is closest to the point at which the mouse button + // was released. for now, we're putting it on the top face. + _updateAnchorList( anchorLists[sourceId], -Math.PI / 2, 0, conn, false, targetId, 0, false, "top", sourceId, connectionsToPaint, endpointsToPaint); + _updateAnchorList( anchorLists[targetId], -Math.PI / 2, 0, conn, false, sourceId, 1, false, "top", targetId, connectionsToPaint, endpointsToPaint); + } + else { + if (!o) { + o = this.calculateOrientation(sourceId, targetId, sd.o, td.o, conn.endpoints[0].anchor, conn.endpoints[1].anchor, conn); + orientationCache[oKey] = o; + // this would be a performance enhancement, but the computed angles need to be clamped to + //the (-PI/2 -> PI/2) range in order for the sorting to work properly. + /* orientationCache[oKey2] = { + orientation:o.orientation, + a:[o.a[1], o.a[0]], + theta:o.theta + Math.PI, + theta2:o.theta2 + Math.PI + };*/ + } + if (sourceContinuous) { + _updateAnchorList(anchorLists[sourceId], o.theta, 0, conn, false, targetId, 0, false, o.a[0], sourceId, connectionsToPaint, endpointsToPaint); + } + if (targetContinuous) { + _updateAnchorList(anchorLists[targetId], o.theta2, -1, conn, true, sourceId, 1, true, o.a[1], targetId, connectionsToPaint, endpointsToPaint); + } + } + + if (sourceContinuous) { + _ju.addWithFunction(anchorsToUpdate, sourceId, function (a) { + return a === sourceId; + }); + } + if (targetContinuous) { + _ju.addWithFunction(anchorsToUpdate, targetId, function (a) { + return a === targetId; + }); + } + _ju.addWithFunction(connectionsToPaint, conn, function (c) { + return c.id === conn.id; + }); + if ((sourceContinuous && oIdx === 0) || (targetContinuous && oIdx === 1)) { + _ju.addWithFunction(endpointsToPaint, conn.endpoints[oIdx], function (e) { + return e.id === conn.endpoints[oIdx].id; + }); + } + } + } + + // place Endpoints whose anchors are continuous but have no Connections + for (i = 0; i < ep.length; i++) { + if (ep[i].connections.length === 0 && ep[i].anchor.isContinuous) { + if (!anchorLists[elementId]) { + anchorLists[elementId] = { top: [], right: [], bottom: [], left: [] }; + } + _updateAnchorList(anchorLists[elementId], -Math.PI / 2, 0, {endpoints: [ep[i], ep[i]], paint: function () { + }}, false, elementId, 0, false, ep[i].anchor.getDefaultFace(), elementId, connectionsToPaint, endpointsToPaint); + _ju.addWithFunction(anchorsToUpdate, elementId, function (a) { + return a === elementId; + }); + } + } + + // now place all the continuous anchors we need to; + for (i = 0; i < anchorsToUpdate.length; i++) { + placeAnchors(anchorsToUpdate[i], anchorLists[anchorsToUpdate[i]]); + } + + // now that continuous anchors have been placed, paint all the endpoints for this element + for (i = 0; i < ep.length; i++) { + ep[i].paint({ timestamp: timestamp, offset: myOffset, dimensions: myOffset.s, recalc: doNotRecalcEndpoint !== true }); + } + + // ... and any other endpoints we came across as a result of the continuous anchors. + for (i = 0; i < endpointsToPaint.length; i++) { + var cd = jsPlumbInstance.getCachedData(endpointsToPaint[i].elementId); + //endpointsToPaint[i].paint({ timestamp: timestamp, offset: cd, dimensions: cd.s }); + endpointsToPaint[i].paint({ timestamp: null, offset: cd, dimensions: cd.s }); + } + + // paint all the standard and "dynamic connections", which are connections whose other anchor is + // static and therefore does need to be recomputed; we make sure that happens only one time. + + // TODO we could have compiled a list of these in the first pass through connections; might save some time. + for (i = 0; i < endpointConnections.length; i++) { + var otherEndpoint = endpointConnections[i][1]; + if (otherEndpoint.anchor.constructor === _jp.DynamicAnchor) { + otherEndpoint.paint({ elementWithPrecedence: elementId, timestamp: timestamp }); + _ju.addWithFunction(connectionsToPaint, endpointConnections[i][0], function (c) { + return c.id === endpointConnections[i][0].id; + }); + // all the connections for the other endpoint now need to be repainted + for (var k = 0; k < otherEndpoint.connections.length; k++) { + if (otherEndpoint.connections[k] !== endpointConnections[i][0]) { + _ju.addWithFunction(connectionsToPaint, otherEndpoint.connections[k], function (c) { + return c.id === otherEndpoint.connections[k].id; + }); + } + } + } else { + _ju.addWithFunction(connectionsToPaint, endpointConnections[i][0], function (c) { + return c.id === endpointConnections[i][0].id; + }); + } + } + + // paint current floating connection for this element, if there is one. + var fc = floatingConnections[elementId]; + if (fc) { + fc.paint({timestamp: timestamp, recalc: false, elId: elementId}); + } + + // paint all the connections + for (i = 0; i < connectionsToPaint.length; i++) { + connectionsToPaint[i].paint({elId: elementId, timestamp: null, recalc: false, clearEdits: clearEdits}); + } + } + }; + + var ContinuousAnchor = function (anchorParams) { + _ju.EventGenerator.apply(this); + this.type = "Continuous"; + this.isDynamic = true; + this.isContinuous = true; + var faces = anchorParams.faces || ["top", "right", "bottom", "left"], + clockwise = !(anchorParams.clockwise === false), + availableFaces = { }, + opposites = { "top": "bottom", "right": "left", "left": "right", "bottom": "top" }, + clockwiseOptions = { "top": "right", "right": "bottom", "left": "top", "bottom": "left" }, + antiClockwiseOptions = { "top": "left", "right": "top", "left": "bottom", "bottom": "right" }, + secondBest = clockwise ? clockwiseOptions : antiClockwiseOptions, + lastChoice = clockwise ? antiClockwiseOptions : clockwiseOptions, + cssClass = anchorParams.cssClass || "", + _currentFace = null, _lockedFace = null, X_AXIS_FACES = ["left", "right"], Y_AXIS_FACES = ["top", "bottom"], + _lockedAxis = null; + + for (var i = 0; i < faces.length; i++) { + availableFaces[faces[i]] = true; + } + + this.getDefaultFace = function () { + return faces.length === 0 ? "top" : faces[0]; + }; + + this.isRelocatable = function() { return true; }; + this.isSnapOnRelocate = function() { return true; }; + + // if the given edge is supported, returns it. otherwise looks for a substitute that _is_ + // supported. if none supported we also return the request edge. + this.verifyEdge = function (edge) { + if (availableFaces[edge]) { + return edge; + } + else if (availableFaces[opposites[edge]]) { + return opposites[edge]; + } + else if (availableFaces[secondBest[edge]]) { + return secondBest[edge]; + } + else if (availableFaces[lastChoice[edge]]) { + return lastChoice[edge]; + } + return edge; // we have to give them something. + }; + + this.isEdgeSupported = function (edge) { + return _lockedAxis == null ? + + (_lockedFace == null ? availableFaces[edge] === true : _lockedFace === edge) + + : _lockedAxis.indexOf(edge) !== -1; + }; + + this.setCurrentFace = function(face, overrideLock) { + _currentFace = face; + // if currently locked, and the user wants to override, do that. + if (overrideLock && _lockedFace != null) { + _lockedFace = _currentFace; + } + }; + + this.getCurrentFace = function() { return _currentFace; }; + this.getSupportedFaces = function() { + var af = []; + for (var k in availableFaces) { + if (availableFaces[k]) { + af.push(k); + } + } + return af; + }; + + this.lock = function() { + _lockedFace = _currentFace; + }; + this.unlock = function() { + _lockedFace = null; + }; + this.isLocked = function() { + return _lockedFace != null; + }; + + this.lockCurrentAxis = function() { + if (_currentFace != null) { + _lockedAxis = (_currentFace === "left" || _currentFace === "right") ? X_AXIS_FACES : Y_AXIS_FACES; + } + }; + + this.unlockCurrentAxis = function() { + _lockedAxis = null; + }; + + this.compute = function (params) { + return continuousAnchorLocations[params.element.id] || [0, 0]; + }; + this.getCurrentLocation = function (params) { + return continuousAnchorLocations[params.element.id] || [0, 0]; + }; + this.getOrientation = function (endpoint) { + return continuousAnchorOrientations[endpoint.id] || [0, 0]; + }; + this.getCssClass = function () { + return cssClass; + }; + }; + + // continuous anchors + jsPlumbInstance.continuousAnchorFactory = { + get: function (params) { + return new ContinuousAnchor(params); + }, + clear: function (elementId) { + delete continuousAnchorLocations[elementId]; + } + }; + }; + + _jp.AnchorManager.prototype.calculateOrientation = function (sourceId, targetId, sd, td, sourceAnchor, targetAnchor) { + + var Orientation = { HORIZONTAL: "horizontal", VERTICAL: "vertical", DIAGONAL: "diagonal", IDENTITY: "identity" }, + axes = ["left", "top", "right", "bottom"]; + + if (sourceId === targetId) { + return { + orientation: Orientation.IDENTITY, + a: ["top", "top"] + }; + } + + var theta = Math.atan2((td.centery - sd.centery), (td.centerx - sd.centerx)), + theta2 = Math.atan2((sd.centery - td.centery), (sd.centerx - td.centerx)); + +// -------------------------------------------------------------------------------------- + + // improved face calculation. get midpoints of each face for source and target, then put in an array with all combinations of + // source/target faces. sort this array by distance between midpoints. the entry at index 0 is our preferred option. we can + // go through the array one by one until we find an entry in which each requested face is supported. + var candidates = [], midpoints = { }; + (function (types, dim) { + for (var i = 0; i < types.length; i++) { + midpoints[types[i]] = { + "left": [ dim[i].left, dim[i].centery ], + "right": [ dim[i].right, dim[i].centery ], + "top": [ dim[i].centerx, dim[i].top ], + "bottom": [ dim[i].centerx , dim[i].bottom] + }; + } + })([ "source", "target" ], [ sd, td ]); + + for (var sf = 0; sf < axes.length; sf++) { + for (var tf = 0; tf < axes.length; tf++) { + candidates.push({ + source: axes[sf], + target: axes[tf], + dist: Biltong.lineLength(midpoints.source[axes[sf]], midpoints.target[axes[tf]]) + }); + } + } + + candidates.sort(function (a, b) { + return a.dist < b.dist ? -1 : a.dist > b.dist ? 1 : 0; + }); + + // now go through this list and try to get an entry that satisfies both (there will be one, unless one of the anchors + // declares no available faces) + var sourceEdge = candidates[0].source, targetEdge = candidates[0].target; + for (var i = 0; i < candidates.length; i++) { + + if (!sourceAnchor.isContinuous || sourceAnchor.isEdgeSupported(candidates[i].source)) { + sourceEdge = candidates[i].source; + } + else { + sourceEdge = null; + } + + if (!targetAnchor.isContinuous || targetAnchor.isEdgeSupported(candidates[i].target)) { + targetEdge = candidates[i].target; + } + else { + targetEdge = null; + } + + if (sourceEdge != null && targetEdge != null) { + break; + } + } + + if (sourceAnchor.isContinuous) { + sourceAnchor.setCurrentFace(sourceEdge); + } + + if (targetAnchor.isContinuous) { + targetAnchor.setCurrentFace(targetEdge); + } + +// -------------------------------------------------------------------------------------- + + return { + a: [ sourceEdge, targetEdge ], + theta: theta, + theta2: theta2 + }; + }; + + /** + * Anchors model a position on some element at which an Endpoint may be located. They began as a first class citizen of jsPlumb, ie. a user + * was required to create these themselves, but over time this has been replaced by the concept of referring to them either by name (eg. "TopMiddle"), + * or by an array describing their coordinates (eg. [ 0, 0.5, 0, -1 ], which is the same as "TopMiddle"). jsPlumb now handles all of the + * creation of Anchors without user intervention. + */ + _jp.Anchor = function (params) { + this.x = params.x || 0; + this.y = params.y || 0; + this.elementId = params.elementId; + this.cssClass = params.cssClass || ""; + this.userDefinedLocation = null; + this.orientation = params.orientation || [ 0, 0 ]; + this.lastReturnValue = null; + this.offsets = params.offsets || [ 0, 0 ]; + this.timestamp = null; + + var relocatable = params.relocatable !== false; + this.isRelocatable = function() { return relocatable; }; + this.setRelocatable = function(_relocatable) { relocatable = _relocatable; }; + var snapOnRelocate = params.snapOnRelocate !== false; + this.isSnapOnRelocate = function() { return snapOnRelocate; }; + + var locked = false; + this.lock = function() { locked = true; }; + this.unlock = function() { locked = false; }; + this.isLocked = function() { return locked; }; + + _ju.EventGenerator.apply(this); + + this.compute = function (params) { + + var xy = params.xy, wh = params.wh, timestamp = params.timestamp; + + if (params.clearUserDefinedLocation) { + this.userDefinedLocation = null; + } + + if (timestamp && timestamp === this.timestamp) { + return this.lastReturnValue; + } + + if (this.userDefinedLocation != null) { + this.lastReturnValue = this.userDefinedLocation; + } + else { + this.lastReturnValue = [ xy[0] + (this.x * wh[0]) + this.offsets[0], xy[1] + (this.y * wh[1]) + this.offsets[1], this.x, this.y ]; + } + + this.timestamp = timestamp; + return this.lastReturnValue; + }; + + this.getCurrentLocation = function (params) { + params = params || {}; + return (this.lastReturnValue == null || (params.timestamp != null && this.timestamp !== params.timestamp)) ? this.compute(params) : this.lastReturnValue; + }; + + this.setPosition = function(x, y, ox, oy, overrideLock) { + if (!locked || overrideLock) { + this.x = x; + this.y = y; + this.orientation = [ ox, oy ]; + this.lastReturnValue = null; + } + }; + }; + _ju.extend(_jp.Anchor, _ju.EventGenerator, { + equals: function (anchor) { + if (!anchor) { + return false; + } + var ao = anchor.getOrientation(), + o = this.getOrientation(); + return this.x === anchor.x && this.y === anchor.y && this.offsets[0] === anchor.offsets[0] && this.offsets[1] === anchor.offsets[1] && o[0] === ao[0] && o[1] === ao[1]; + }, + getUserDefinedLocation: function () { + return this.userDefinedLocation; + }, + setUserDefinedLocation: function (l) { + this.userDefinedLocation = l; + }, + clearUserDefinedLocation: function () { + this.userDefinedLocation = null; + }, + getOrientation: function () { + return this.orientation; + }, + getCssClass: function () { + return this.cssClass; + } + }); + + /** + * An Anchor that floats. its orientation is computed dynamically from + * its position relative to the anchor it is floating relative to. It is used when creating + * a connection through drag and drop. + * + * TODO FloatingAnchor could totally be refactored to extend Anchor just slightly. + */ + _jp.FloatingAnchor = function (params) { + + _jp.Anchor.apply(this, arguments); + + // this is the anchor that this floating anchor is referenced to for + // purposes of calculating the orientation. + var ref = params.reference, + // the canvas this refers to. + refCanvas = params.referenceCanvas, + size = _jp.getSize(refCanvas), + // these are used to store the current relative position of our + // anchor wrt the reference anchor. they only indicate + // direction, so have a value of 1 or -1 (or, very rarely, 0). these + // values are written by the compute method, and read + // by the getOrientation method. + xDir = 0, yDir = 0, + // temporary member used to store an orientation when the floating + // anchor is hovering over another anchor. + orientation = null, + _lastResult = null; + + // clear from parent. we want floating anchor orientation to always be computed. + this.orientation = null; + + // set these to 0 each; they are used by certain types of connectors in the loopback case, + // when the connector is trying to clear the element it is on. but for floating anchor it's not + // very important. + this.x = 0; + this.y = 0; + + this.isFloating = true; + + this.compute = function (params) { + var xy = params.xy, + result = [ xy[0] + (size[0] / 2), xy[1] + (size[1] / 2) ]; // return origin of the element. we may wish to improve this so that any object can be the drag proxy. + _lastResult = result; + return result; + }; + + this.getOrientation = function (_endpoint) { + if (orientation) { + return orientation; + } + else { + var o = ref.getOrientation(_endpoint); + // here we take into account the orientation of the other + // anchor: if it declares zero for some direction, we declare zero too. this might not be the most awesome. perhaps we can come + // up with a better way. it's just so that the line we draw looks like it makes sense. maybe this wont make sense. + return [ Math.abs(o[0]) * xDir * -1, + Math.abs(o[1]) * yDir * -1 ]; + } + }; + + /** + * notification the endpoint associated with this anchor is hovering + * over another anchor; we want to assume that anchor's orientation + * for the duration of the hover. + */ + this.over = function (anchor, endpoint) { + orientation = anchor.getOrientation(endpoint); + }; + + /** + * notification the endpoint associated with this anchor is no + * longer hovering over another anchor; we should resume calculating + * orientation as we normally do. + */ + this.out = function () { + orientation = null; + }; + + this.getCurrentLocation = function (params) { + return _lastResult == null ? this.compute(params) : _lastResult; + }; + }; + _ju.extend(_jp.FloatingAnchor, _jp.Anchor); + + var _convertAnchor = function (anchor, jsPlumbInstance, elementId) { + return anchor.constructor === _jp.Anchor ? anchor : jsPlumbInstance.makeAnchor(anchor, elementId, jsPlumbInstance); + }; + + /* + * A DynamicAnchor is an Anchor that contains a list of other Anchors, which it cycles + * through at compute time to find the one that is located closest to + * the center of the target element, and returns that Anchor's compute + * method result. this causes endpoints to follow each other with + * respect to the orientation of their target elements, which is a useful + * feature for some applications. + * + */ + _jp.DynamicAnchor = function (params) { + _jp.Anchor.apply(this, arguments); + + this.isDynamic = true; + this.anchors = []; + this.elementId = params.elementId; + this.jsPlumbInstance = params.jsPlumbInstance; + + for (var i = 0; i < params.anchors.length; i++) { + this.anchors[i] = _convertAnchor(params.anchors[i], this.jsPlumbInstance, this.elementId); + } + + this.getAnchors = function () { + return this.anchors; + }; + + var _curAnchor = this.anchors.length > 0 ? this.anchors[0] : null, + _lastAnchor = _curAnchor, + self = this, + + // helper method to calculate the distance between the centers of the two elements. + _distance = function (anchor, cx, cy, xy, wh) { + var ax = xy[0] + (anchor.x * wh[0]), ay = xy[1] + (anchor.y * wh[1]), + acx = xy[0] + (wh[0] / 2), acy = xy[1] + (wh[1] / 2); + return (Math.sqrt(Math.pow(cx - ax, 2) + Math.pow(cy - ay, 2)) + + Math.sqrt(Math.pow(acx - ax, 2) + Math.pow(acy - ay, 2))); + }, + // default method uses distance between element centers. you can provide your own method in the dynamic anchor + // constructor (and also to jsPlumb.makeDynamicAnchor). the arguments to it are four arrays: + // xy - xy loc of the anchor's element + // wh - anchor's element's dimensions + // txy - xy loc of the element of the other anchor in the connection + // twh - dimensions of the element of the other anchor in the connection. + // anchors - the list of selectable anchors + _anchorSelector = params.selector || function (xy, wh, txy, twh, anchors) { + var cx = txy[0] + (twh[0] / 2), cy = txy[1] + (twh[1] / 2); + var minIdx = -1, minDist = Infinity; + for (var i = 0; i < anchors.length; i++) { + var d = _distance(anchors[i], cx, cy, xy, wh); + if (d < minDist) { + minIdx = i + 0; + minDist = d; + } + } + return anchors[minIdx]; + }; + + this.compute = function (params) { + var xy = params.xy, wh = params.wh, txy = params.txy, twh = params.twh; + + this.timestamp = params.timestamp; + + var udl = self.getUserDefinedLocation(); + if (udl != null) { + return udl; + } + + // if anchor is locked or an opposite element was not given, we + // maintain our state. anchor will be locked + // if it is the source of a drag and drop. + if (this.isLocked() || txy == null || twh == null) { + return _curAnchor.compute(params); + } + else { + params.timestamp = null; // otherwise clear this, i think. we want the anchor to compute. + } + + _curAnchor = _anchorSelector(xy, wh, txy, twh, this.anchors); + this.x = _curAnchor.x; + this.y = _curAnchor.y; + + if (_curAnchor !== _lastAnchor) { + this.fire("anchorChanged", _curAnchor); + } + + _lastAnchor = _curAnchor; + + return _curAnchor.compute(params); + }; + + this.getCurrentLocation = function (params) { + return this.getUserDefinedLocation() || (_curAnchor != null ? _curAnchor.getCurrentLocation(params) : null); + }; + + this.getOrientation = function (_endpoint) { + return _curAnchor != null ? _curAnchor.getOrientation(_endpoint) : [ 0, 0 ]; + }; + this.over = function (anchor, endpoint) { + if (_curAnchor != null) { + _curAnchor.over(anchor, endpoint); + } + }; + this.out = function () { + if (_curAnchor != null) { + _curAnchor.out(); + } + }; + + this.setAnchor = function(a) { + _curAnchor = a; + }; + + this.getCssClass = function () { + return (_curAnchor && _curAnchor.getCssClass()) || ""; + }; + + /** + * Attempt to match an anchor with the given coordinates and then set it. + * @param coords + * @returns true if matching anchor found, false otherwise. + */ + this.setAnchorCoordinates = function(coords) { + var idx = jsPlumbUtil.findWithFunction(this.anchors, function(a) { + return a.x === coords[0] && a.y === coords[1]; + }); + if (idx !== -1) { + this.setAnchor(this.anchors[idx]); + return true; + } else { + return false; + } + }; + }; + _ju.extend(_jp.DynamicAnchor, _jp.Anchor); + +// -------- basic anchors ------------------ + var _curryAnchor = function (x, y, ox, oy, type, fnInit) { + _jp.Anchors[type] = function (params) { + var a = params.jsPlumbInstance.makeAnchor([ x, y, ox, oy, 0, 0 ], params.elementId, params.jsPlumbInstance); + a.type = type; + if (fnInit) { + fnInit(a, params); + } + return a; + }; + }; + + _curryAnchor(0.5, 0, 0, -1, "TopCenter"); + _curryAnchor(0.5, 1, 0, 1, "BottomCenter"); + _curryAnchor(0, 0.5, -1, 0, "LeftMiddle"); + _curryAnchor(1, 0.5, 1, 0, "RightMiddle"); + + _curryAnchor(0.5, 0, 0, -1, "Top"); + _curryAnchor(0.5, 1, 0, 1, "Bottom"); + _curryAnchor(0, 0.5, -1, 0, "Left"); + _curryAnchor(1, 0.5, 1, 0, "Right"); + _curryAnchor(0.5, 0.5, 0, 0, "Center"); + _curryAnchor(1, 0, 0, -1, "TopRight"); + _curryAnchor(1, 1, 0, 1, "BottomRight"); + _curryAnchor(0, 0, 0, -1, "TopLeft"); + _curryAnchor(0, 1, 0, 1, "BottomLeft"); + +// ------- dynamic anchors ------------------- + + // default dynamic anchors chooses from Top, Right, Bottom, Left + _jp.Defaults.DynamicAnchors = function (params) { + return params.jsPlumbInstance.makeAnchors(["TopCenter", "RightMiddle", "BottomCenter", "LeftMiddle"], params.elementId, params.jsPlumbInstance); + }; + + // default dynamic anchors bound to name 'AutoDefault' + _jp.Anchors.AutoDefault = function (params) { + var a = params.jsPlumbInstance.makeDynamicAnchor(_jp.Defaults.DynamicAnchors(params)); + a.type = "AutoDefault"; + return a; + }; + +// ------- continuous anchors ------------------- + + var _curryContinuousAnchor = function (type, faces) { + _jp.Anchors[type] = function (params) { + var a = params.jsPlumbInstance.makeAnchor(["Continuous", { faces: faces }], params.elementId, params.jsPlumbInstance); + a.type = type; + return a; + }; + }; + + _jp.Anchors.Continuous = function (params) { + return params.jsPlumbInstance.continuousAnchorFactory.get(params); + }; + + _curryContinuousAnchor("ContinuousLeft", ["left"]); + _curryContinuousAnchor("ContinuousTop", ["top"]); + _curryContinuousAnchor("ContinuousBottom", ["bottom"]); + _curryContinuousAnchor("ContinuousRight", ["right"]); + +// ------- position assign anchors ------------------- + + // this anchor type lets you assign the position at connection time. + _curryAnchor(0, 0, 0, 0, "Assign", function (anchor, params) { + // find what to use as the "position finder". the user may have supplied a String which represents + // the id of a position finder in jsPlumb.AnchorPositionFinders, or the user may have supplied the + // position finder as a function. we find out what to use and then set it on the anchor. + var pf = params.position || "Fixed"; + anchor.positionFinder = pf.constructor === String ? params.jsPlumbInstance.AnchorPositionFinders[pf] : pf; + // always set the constructor params; the position finder might need them later (the Grid one does, + // for example) + anchor.constructorParams = params; + }); + + // these are the default anchor positions finders, which are used by the makeTarget function. supplying + // a position finder argument to that function allows you to specify where the resulting anchor will + // be located + root.jsPlumbInstance.prototype.AnchorPositionFinders = { + "Fixed": function (dp, ep, es) { + return [ (dp.left - ep.left) / es[0], (dp.top - ep.top) / es[1] ]; + }, + "Grid": function (dp, ep, es, params) { + var dx = dp.left - ep.left, dy = dp.top - ep.top, + gx = es[0] / (params.grid[0]), gy = es[1] / (params.grid[1]), + mx = Math.floor(dx / gx), my = Math.floor(dy / gy); + return [ ((mx * gx) + (gx / 2)) / es[0], ((my * gy) + (gy / 2)) / es[1] ]; + } + }; + +// ------- perimeter anchors ------------------- + + _jp.Anchors.Perimeter = function (params) { + params = params || {}; + var anchorCount = params.anchorCount || 60, + shape = params.shape; + + if (!shape) { + throw new Error("no shape supplied to Perimeter Anchor type"); + } + + var _circle = function () { + var r = 0.5, step = Math.PI * 2 / anchorCount, current = 0, a = []; + for (var i = 0; i < anchorCount; i++) { + var x = r + (r * Math.sin(current)), + y = r + (r * Math.cos(current)); + a.push([ x, y, 0, 0 ]); + current += step; + } + return a; + }, + _path = function (segments) { + var anchorsPerFace = anchorCount / segments.length, a = [], + _computeFace = function (x1, y1, x2, y2, fractionalLength, ox, oy) { + anchorsPerFace = anchorCount * fractionalLength; + var dx = (x2 - x1) / anchorsPerFace, dy = (y2 - y1) / anchorsPerFace; + for (var i = 0; i < anchorsPerFace; i++) { + a.push([ + x1 + (dx * i), + y1 + (dy * i), + ox == null ? 0 : ox, + oy == null ? 0 : oy + ]); + } + }; + + for (var i = 0; i < segments.length; i++) { + _computeFace.apply(null, segments[i]); + } + + return a; + }, + _shape = function (faces) { + var s = []; + for (var i = 0; i < faces.length; i++) { + s.push([faces[i][0], faces[i][1], faces[i][2], faces[i][3], 1 / faces.length, faces[i][4], faces[i][5]]); + } + return _path(s); + }, + _rectangle = function () { + return _shape([ + [ 0, 0, 1, 0, 0, -1 ], + [ 1, 0, 1, 1, 1, 0 ], + [ 1, 1, 0, 1, 0, 1 ], + [ 0, 1, 0, 0, -1, 0 ] + ]); + }; + + var _shapes = { + "Circle": _circle, + "Ellipse": _circle, + "Diamond": function () { + return _shape([ + [ 0.5, 0, 1, 0.5 ], + [ 1, 0.5, 0.5, 1 ], + [ 0.5, 1, 0, 0.5 ], + [ 0, 0.5, 0.5, 0 ] + ]); + }, + "Rectangle": _rectangle, + "Square": _rectangle, + "Triangle": function () { + return _shape([ + [ 0.5, 0, 1, 1 ], + [ 1, 1, 0, 1 ], + [ 0, 1, 0.5, 0] + ]); + }, + "Path": function (params) { + var points = params.points, p = [], tl = 0; + for (var i = 0; i < points.length - 1; i++) { + var l = Math.sqrt(Math.pow(points[i][2] - points[i][0]) + Math.pow(points[i][3] - points[i][1])); + tl += l; + p.push([points[i][0], points[i][1], points[i + 1][0], points[i + 1][1], l]); + } + for (var j = 0; j < p.length; j++) { + p[j][4] = p[j][4] / tl; + } + return _path(p); + } + }, + _rotate = function (points, amountInDegrees) { + var o = [], theta = amountInDegrees / 180 * Math.PI; + for (var i = 0; i < points.length; i++) { + var _x = points[i][0] - 0.5, + _y = points[i][1] - 0.5; + + o.push([ + 0.5 + ((_x * Math.cos(theta)) - (_y * Math.sin(theta))), + 0.5 + ((_x * Math.sin(theta)) + (_y * Math.cos(theta))), + points[i][2], + points[i][3] + ]); + } + return o; + }; + + if (!_shapes[shape]) { + throw new Error("Shape [" + shape + "] is unknown by Perimeter Anchor type"); + } + + var da = _shapes[shape](params); + if (params.rotation) { + da = _rotate(da, params.rotation); + } + var a = params.jsPlumbInstance.makeDynamicAnchor(da); + a.type = "Perimeter"; + return a; + }; +}).call(typeof window !== 'undefined' ? window : this); +/* + * This file contains the default Connectors, Endpoint and Overlay definitions. + * + * Copyright (c) 2010 - 2018 jsPlumb (hello@jsplumbtoolkit.com) + * + * https://jsplumbtoolkit.com + * https://github.com/jsplumb/jsplumb + * + * Dual licensed under the MIT and GPL2 licenses. + */ +; +(function () { + + "use strict"; + var root = this, _jp = root.jsPlumb, _ju = root.jsPlumbUtil, _jg = root.Biltong; + + _jp.Segments = { + + /* + * Class: AbstractSegment + * A Connector is made up of 1..N Segments, each of which has a Type, such as 'Straight', 'Arc', + * 'Bezier'. This is new from 1.4.2, and gives us a lot more flexibility when drawing connections: things such + * as rounded corners for flowchart connectors, for example, or a straight line stub for Bezier connections, are + * much easier to do now. + * + * A Segment is responsible for providing coordinates for painting it, and also must be able to report its length. + * + */ + AbstractSegment: function (params) { + this.params = params; + + /** + * Function: findClosestPointOnPath + * Finds the closest point on this segment to the given [x, y], + * returning both the x and y of the point plus its distance from + * the supplied point, and its location along the length of the + * path inscribed by the segment. This implementation returns + * Infinity for distance and null values for everything else; + * subclasses are expected to override. + */ + this.findClosestPointOnPath = function (x, y) { + return { + d: Infinity, + x: null, + y: null, + l: null + }; + }; + + this.getBounds = function () { + return { + minX: Math.min(params.x1, params.x2), + minY: Math.min(params.y1, params.y2), + maxX: Math.max(params.x1, params.x2), + maxY: Math.max(params.y1, params.y2) + }; + }; + + /** + * Computes the list of points on the segment that intersect the given line. + * @method lineIntersection + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @returns {Array<[number, number]>} + */ + this.lineIntersection = function(x1, y1, x2, y2) { + return []; + }; + + /** + * Computes the list of points on the segment that intersect the box with the given origin and size. + * @method boxIntersection + * @param {number} x1 + * @param {number} y1 + * @param {number} w + * @param {number} h + * @returns {Array<[number, number]>} + */ + this.boxIntersection = function(x, y, w, h) { + var a = []; + a.push.apply(a, this.lineIntersection(x, y, x + w, y)); + a.push.apply(a, this.lineIntersection(x + w, y, x + w, y + h)); + a.push.apply(a, this.lineIntersection(x + w, y + h, x, y + h)); + a.push.apply(a, this.lineIntersection(x, y + h, x, y)); + return a; + }; + + /** + * Computes the list of points on the segment that intersect the given bounding box, which is an object of the form { x:.., y:.., w:.., h:.. }. + * @method lineIntersection + * @param {BoundingRectangle} box + * @returns {Array<[number, number]>} + */ + this.boundingBoxIntersection = function(box) { + return this.boxIntersection(box.x, box.y, box.w, box.y); + }; + }, + Straight: function (params) { + var _super = _jp.Segments.AbstractSegment.apply(this, arguments), + length, m, m2, x1, x2, y1, y2, + _recalc = function () { + length = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); + m = _jg.gradient({x: x1, y: y1}, {x: x2, y: y2}); + m2 = -1 / m; + }; + + this.type = "Straight"; + + this.getLength = function () { + return length; + }; + this.getGradient = function () { + return m; + }; + + this.getCoordinates = function () { + return { x1: x1, y1: y1, x2: x2, y2: y2 }; + }; + this.setCoordinates = function (coords) { + x1 = coords.x1; + y1 = coords.y1; + x2 = coords.x2; + y2 = coords.y2; + _recalc(); + }; + this.setCoordinates({x1: params.x1, y1: params.y1, x2: params.x2, y2: params.y2}); + + this.getBounds = function () { + return { + minX: Math.min(x1, x2), + minY: Math.min(y1, y2), + maxX: Math.max(x1, x2), + maxY: Math.max(y1, y2) + }; + }; + + /** + * returns the point on the segment's path that is 'location' along the length of the path, where 'location' is a decimal from + * 0 to 1 inclusive. for the straight line segment this is simple maths. + */ + this.pointOnPath = function (location, absolute) { + if (location === 0 && !absolute) { + return { x: x1, y: y1 }; + } + else if (location === 1 && !absolute) { + return { x: x2, y: y2 }; + } + else { + var l = absolute ? location > 0 ? location : length + location : location * length; + return _jg.pointOnLine({x: x1, y: y1}, {x: x2, y: y2}, l); + } + }; + + /** + * returns the gradient of the segment at the given point - which for us is constant. + */ + this.gradientAtPoint = function (_) { + return m; + }; + + /** + * returns the point on the segment's path that is 'distance' along the length of the path from 'location', where + * 'location' is a decimal from 0 to 1 inclusive, and 'distance' is a number of pixels. + * this hands off to jsPlumbUtil to do the maths, supplying two points and the distance. + */ + this.pointAlongPathFrom = function (location, distance, absolute) { + var p = this.pointOnPath(location, absolute), + farAwayPoint = distance <= 0 ? {x: x1, y: y1} : {x: x2, y: y2 }; + + /* + location == 1 ? { + x:x1 + ((x2 - x1) * 10), + y:y1 + ((y1 - y2) * 10) + } : + */ + + if (distance <= 0 && Math.abs(distance) > 1) { + distance *= -1; + } + + return _jg.pointOnLine(p, farAwayPoint, distance); + }; + + // is c between a and b? + var within = function (a, b, c) { + return c >= Math.min(a, b) && c <= Math.max(a, b); + }; + // find which of a and b is closest to c + var closest = function (a, b, c) { + return Math.abs(c - a) < Math.abs(c - b) ? a : b; + }; + + /** + Function: findClosestPointOnPath + Finds the closest point on this segment to [x,y]. See + notes on this method in AbstractSegment. + */ + this.findClosestPointOnPath = function (x, y) { + var out = { + d: Infinity, + x: null, + y: null, + l: null, + x1: x1, + x2: x2, + y1: y1, + y2: y2 + }; + + if (m === 0) { + out.y = y1; + out.x = within(x1, x2, x) ? x : closest(x1, x2, x); + } + else if (m === Infinity || m === -Infinity) { + out.x = x1; + out.y = within(y1, y2, y) ? y : closest(y1, y2, y); + } + else { + // closest point lies on normal from given point to this line. + var b = y1 - (m * x1), + b2 = y - (m2 * x), + // y1 = m.x1 + b and y1 = m2.x1 + b2 + // so m.x1 + b = m2.x1 + b2 + // x1(m - m2) = b2 - b + // x1 = (b2 - b) / (m - m2) + _x1 = (b2 - b) / (m - m2), + _y1 = (m * _x1) + b; + + out.x = within(x1, x2, _x1) ? _x1 : closest(x1, x2, _x1);//_x1; + out.y = within(y1, y2, _y1) ? _y1 : closest(y1, y2, _y1);//_y1; + } + + var fractionInSegment = _jg.lineLength([ out.x, out.y ], [ x1, y1 ]); + out.d = _jg.lineLength([x, y], [out.x, out.y]); + out.l = fractionInSegment / length; + return out; + }; + + var _pointLiesBetween = function(q, p1, p2) { + return (p2 > p1) ? (p1 <= q && q <= p2) : (p1 >= q && q >= p2); + }, _plb = _pointLiesBetween; + + /** + * Calculates all intersections of the given line with this segment. + * @param _x1 + * @param _y1 + * @param _x2 + * @param _y2 + * @returns {Array} + */ + this.lineIntersection = function(_x1, _y1, _x2, _y2) { + var m2 = Math.abs(_jg.gradient({x: _x1, y: _y1}, {x: _x2, y: _y2})), + m1 = Math.abs(m), + b = m1 === Infinity ? x1 : y1 - (m1 * x1), + out = [], + b2 = m2 === Infinity ? _x1 : _y1 - (m2 * _x1); + + // if lines parallel, no intersection + if (m2 !== m1) { + // perpendicular, segment horizontal + if(m2 === Infinity && m1 === 0) { + if (_plb(_x1, x1, x2) && _plb(y1, _y1, _y2)) { + out = [ _x1, y1 ]; // we return X on the incident line and Y from the segment + } + } else if(m2 === 0 && m1 === Infinity) { + // perpendicular, segment vertical + if(_plb(_y1, y1, y2) && _plb(x1, _x1, _x2)) { + out = [x1, _y1]; // we return X on the segment and Y from the incident line + } + } else { + var X, Y; + if (m2 === Infinity) { + // test line is a vertical line. where does it cross the segment? + X = _x1; + if (_plb(X, x1, x2)) { + Y = (m1 * _x1) + b; + if (_plb(Y, _y1, _y2)) { + out = [ X, Y ]; + } + } + } else if (m2 === 0) { + Y = _y1; + // test line is a horizontal line. where does it cross the segment? + if (_plb(Y, y1, y2)) { + X = (_y1 - b) / m1; + if (_plb(X, _x1, _x2)) { + out = [ X, Y ]; + } + } + } else { + // mX + b = m2X + b2 + // mX - m2X = b2 - b + // X(m - m2) = b2 - b + // X = (b2 - b) / (m - m2) + // Y = mX + b + X = (b2 - b) / (m1 - m2); + Y = (m1 * X) + b; + if(_plb(X, x1, x2) && _plb(Y, y1, y2)) { + out = [ X, Y]; + } + } + } + } + + return out; + }; + + /** + * Calculates all intersections of the given box with this segment. By default this method simply calls `lineIntersection` with each of the four + * faces of the box; subclasses can override this if they think there's a faster way to compute the entire box at once. + * @param x X position of top left corner of box + * @param y Y position of top left corner of box + * @param w width of box + * @param h height of box + * @returns {Array} + */ + this.boxIntersection = function(x, y, w, h) { + var a = []; + a.push.apply(a, this.lineIntersection(x, y, x + w, y)); + a.push.apply(a, this.lineIntersection(x + w, y, x + w, y + h)); + a.push.apply(a, this.lineIntersection(x + w, y + h, x, y + h)); + a.push.apply(a, this.lineIntersection(x, y + h, x, y)); + return a; + }; + + /** + * Calculates all intersections of the given bounding box with this segment. By default this method simply calls `lineIntersection` with each of the four + * faces of the box; subclasses can override this if they think there's a faster way to compute the entire box at once. + * @param box Bounding box, in { x:.., y:..., w:..., h:... } format. + * @returns {Array} + */ + this.boundingBoxIntersection = function(box) { + return this.boxIntersection(box.x, box.y, box.w, box.h); + }; + }, + + /* + Arc Segment. You need to supply: + + r - radius + cx - center x for the arc + cy - center y for the arc + ac - whether the arc is anticlockwise or not. default is clockwise. + + and then either: + + startAngle - startAngle for the arc. + endAngle - endAngle for the arc. + + or: + + x1 - x for start point + y1 - y for start point + x2 - x for end point + y2 - y for end point + + */ + Arc: function (params) { + var _super = _jp.Segments.AbstractSegment.apply(this, arguments), + _calcAngle = function (_x, _y) { + return _jg.theta([params.cx, params.cy], [_x, _y]); + }, + _calcAngleForLocation = function (segment, location) { + if (segment.anticlockwise) { + var sa = segment.startAngle < segment.endAngle ? segment.startAngle + TWO_PI : segment.startAngle, + s = Math.abs(sa - segment.endAngle); + return sa - (s * location); + } + else { + var ea = segment.endAngle < segment.startAngle ? segment.endAngle + TWO_PI : segment.endAngle, + ss = Math.abs(ea - segment.startAngle); + + return segment.startAngle + (ss * location); + } + }, + TWO_PI = 2 * Math.PI; + + this.radius = params.r; + this.anticlockwise = params.ac; + this.type = "Arc"; + + if (params.startAngle && params.endAngle) { + this.startAngle = params.startAngle; + this.endAngle = params.endAngle; + this.x1 = params.cx + (this.radius * Math.cos(params.startAngle)); + this.y1 = params.cy + (this.radius * Math.sin(params.startAngle)); + this.x2 = params.cx + (this.radius * Math.cos(params.endAngle)); + this.y2 = params.cy + (this.radius * Math.sin(params.endAngle)); + } + else { + this.startAngle = _calcAngle(params.x1, params.y1); + this.endAngle = _calcAngle(params.x2, params.y2); + this.x1 = params.x1; + this.y1 = params.y1; + this.x2 = params.x2; + this.y2 = params.y2; + } + + if (this.endAngle < 0) { + this.endAngle += TWO_PI; + } + if (this.startAngle < 0) { + this.startAngle += TWO_PI; + } + + // segment is used by vml + //this.segment = _jg.quadrant([this.x1, this.y1], [this.x2, this.y2]); + + // we now have startAngle and endAngle as positive numbers, meaning the + // absolute difference (|d|) between them is the sweep (s) of this arc, unless the + // arc is 'anticlockwise' in which case 's' is given by 2PI - |d|. + + var ea = this.endAngle < this.startAngle ? this.endAngle + TWO_PI : this.endAngle; + this.sweep = Math.abs(ea - this.startAngle); + if (this.anticlockwise) { + this.sweep = TWO_PI - this.sweep; + } + var circumference = 2 * Math.PI * this.radius, + frac = this.sweep / TWO_PI, + length = circumference * frac; + + this.getLength = function () { + return length; + }; + + this.getBounds = function () { + return { + minX: params.cx - params.r, + maxX: params.cx + params.r, + minY: params.cy - params.r, + maxY: params.cy + params.r + }; + }; + + var VERY_SMALL_VALUE = 0.0000000001, + gentleRound = function (n) { + var f = Math.floor(n), r = Math.ceil(n); + if (n - f < VERY_SMALL_VALUE) { + return f; + } + else if (r - n < VERY_SMALL_VALUE) { + return r; + } + return n; + }; + + /** + * returns the point on the segment's path that is 'location' along the length of the path, where 'location' is a decimal from + * 0 to 1 inclusive. + */ + this.pointOnPath = function (location, absolute) { + + if (location === 0) { + return { x: this.x1, y: this.y1, theta: this.startAngle }; + } + else if (location === 1) { + return { x: this.x2, y: this.y2, theta: this.endAngle }; + } + + if (absolute) { + location = location / length; + } + + var angle = _calcAngleForLocation(this, location), + _x = params.cx + (params.r * Math.cos(angle)), + _y = params.cy + (params.r * Math.sin(angle)); + + return { x: gentleRound(_x), y: gentleRound(_y), theta: angle }; + }; + + /** + * returns the gradient of the segment at the given point. + */ + this.gradientAtPoint = function (location, absolute) { + var p = this.pointOnPath(location, absolute); + var m = _jg.normal([ params.cx, params.cy ], [p.x, p.y ]); + if (!this.anticlockwise && (m === Infinity || m === -Infinity)) { + m *= -1; + } + return m; + }; + + this.pointAlongPathFrom = function (location, distance, absolute) { + var p = this.pointOnPath(location, absolute), + arcSpan = distance / circumference * 2 * Math.PI, + dir = this.anticlockwise ? -1 : 1, + startAngle = p.theta + (dir * arcSpan), + startX = params.cx + (this.radius * Math.cos(startAngle)), + startY = params.cy + (this.radius * Math.sin(startAngle)); + + return {x: startX, y: startY}; + }; + + // TODO: lineIntersection + }, + + Bezier: function (params) { + this.curve = [ + { x: params.x1, y: params.y1}, + { x: params.cp1x, y: params.cp1y }, + { x: params.cp2x, y: params.cp2y }, + { x: params.x2, y: params.y2 } + ]; + + var _super = _jp.Segments.AbstractSegment.apply(this, arguments); + // although this is not a strictly rigorous determination of bounds + // of a bezier curve, it works for the types of curves that this segment + // type produces. + this.bounds = { + minX: Math.min(params.x1, params.x2, params.cp1x, params.cp2x), + minY: Math.min(params.y1, params.y2, params.cp1y, params.cp2y), + maxX: Math.max(params.x1, params.x2, params.cp1x, params.cp2x), + maxY: Math.max(params.y1, params.y2, params.cp1y, params.cp2y) + }; + + this.type = "Bezier"; + + var _translateLocation = function (_curve, location, absolute) { + if (absolute) { + location = root.jsBezier.locationAlongCurveFrom(_curve, location > 0 ? 0 : 1, location); + } + + return location; + }; + + /** + * returns the point on the segment's path that is 'location' along the length of the path, where 'location' is a decimal from + * 0 to 1 inclusive. + */ + this.pointOnPath = function (location, absolute) { + location = _translateLocation(this.curve, location, absolute); + return root.jsBezier.pointOnCurve(this.curve, location); + }; + + /** + * returns the gradient of the segment at the given point. + */ + this.gradientAtPoint = function (location, absolute) { + location = _translateLocation(this.curve, location, absolute); + return root.jsBezier.gradientAtPoint(this.curve, location); + }; + + this.pointAlongPathFrom = function (location, distance, absolute) { + location = _translateLocation(this.curve, location, absolute); + return root.jsBezier.pointAlongCurveFrom(this.curve, location, distance); + }; + + this.getLength = function () { + return root.jsBezier.getLength(this.curve); + }; + + this.getBounds = function () { + return this.bounds; + }; + + this.findClosestPointOnPath = function (x, y) { + var p = root.jsBezier.nearestPointOnCurve({x:x,y:y}, this.curve); + return { + d:Math.sqrt(Math.pow(p.point.x - x, 2) + Math.pow(p.point.y - y, 2)), + x:p.point.x, + y:p.point.y, + l:1 - p.location, + s:this + }; + }; + + this.lineIntersection = function(x1, y1, x2, y2) { + return root.jsBezier.lineIntersection(x1, y1, x2, y2, this.curve); + }; + } + }; + + _jp.SegmentRenderer = { + getPath: function (segment, isFirstSegment) { + return ({ + "Straight": function (isFirstSegment) { + var d = segment.getCoordinates(); + return (isFirstSegment ? "M " + d.x1 + " " + d.y1 + " " : "") + "L " + d.x2 + " " + d.y2; + }, + "Bezier": function (isFirstSegment) { + var d = segment.params; + return (isFirstSegment ? "M " + d.x2 + " " + d.y2 + " " : "") + + "C " + d.cp2x + " " + d.cp2y + " " + d.cp1x + " " + d.cp1y + " " + d.x1 + " " + d.y1; + }, + "Arc": function (isFirstSegment) { + var d = segment.params, + laf = segment.sweep > Math.PI ? 1 : 0, + sf = segment.anticlockwise ? 0 : 1; + + return (isFirstSegment ? "M" + segment.x1 + " " + segment.y1 + " " : "") + "A " + segment.radius + " " + d.r + " 0 " + laf + "," + sf + " " + segment.x2 + " " + segment.y2; + } + })[segment.type](isFirstSegment); + } + }; + + /* + Class: UIComponent + Superclass for Connector and AbstractEndpoint. + */ + var AbstractComponent = function () { + this.resetBounds = function () { + this.bounds = { minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity }; + }; + this.resetBounds(); + }; + + /* + * Class: Connector + * Superclass for all Connectors; here is where Segments are managed. This is exposed on jsPlumb just so it + * can be accessed from other files. You should not try to instantiate one of these directly. + * + * When this class is asked for a pointOnPath, or gradient etc, it must first figure out which segment to dispatch + * that request to. This is done by keeping track of the total connector length as segments are added, and also + * their cumulative ratios to the total length. Then when the right segment is found it is a simple case of dispatching + * the request to it (and adjusting 'location' so that it is relative to the beginning of that segment.) + */ + _jp.Connectors.AbstractConnector = function (params) { + + AbstractComponent.apply(this, arguments); + + var segments = [], + totalLength = 0, + segmentProportions = [], + segmentProportionalLengths = [], + stub = params.stub || 0, + sourceStub = _ju.isArray(stub) ? stub[0] : stub, + targetStub = _ju.isArray(stub) ? stub[1] : stub, + gap = params.gap || 0, + sourceGap = _ju.isArray(gap) ? gap[0] : gap, + targetGap = _ju.isArray(gap) ? gap[1] : gap, + userProvidedSegments = null, + paintInfo = null; + + this.getPathData = function() { + var p = ""; + for (var i = 0; i < segments.length; i++) { + p += _jp.SegmentRenderer.getPath(segments[i], i === 0); + p += " "; + } + return p; + }; + + /** + * Function: findSegmentForPoint + * Returns the segment that is closest to the given [x,y], + * null if nothing found. This function returns a JS + * object with: + * + * d - distance from segment + * l - proportional location in segment + * x - x point on the segment + * y - y point on the segment + * s - the segment itself. + * connectorLocation - the location on the connector of the point, expressed as a decimal between 0 and 1 inclusive. + */ + this.findSegmentForPoint = function (x, y) { + var out = { d: Infinity, s: null, x: null, y: null, l: null }; + for (var i = 0; i < segments.length; i++) { + var _s = segments[i].findClosestPointOnPath(x, y); + if (_s.d < out.d) { + out.d = _s.d; + out.l = _s.l; + out.x = _s.x; + out.y = _s.y; + out.s = segments[i]; + out.x1 = _s.x1; + out.x2 = _s.x2; + out.y1 = _s.y1; + out.y2 = _s.y2; + out.index = i; + out.connectorLocation = segmentProportions[i][0] + (_s.l * (segmentProportions[i][1] - segmentProportions[i][0])); + } + } + + return out; + }; + + this.lineIntersection = function(x1, y1, x2, y2) { + var out = []; + for (var i = 0; i < segments.length; i++) { + out.push.apply(out, segments[i].lineIntersection(x1, y1, x2, y2)); + } + return out; + }; + + this.boxIntersection = function(x, y, w, h) { + var out = []; + for (var i = 0; i < segments.length; i++) { + out.push.apply(out, segments[i].boxIntersection(x, y, w, h)); + } + return out; + }; + + this.boundingBoxIntersection = function(box) { + var out = []; + for (var i = 0; i < segments.length; i++) { + out.push.apply(out, segments[i].boundingBoxIntersection(box)); + } + return out; + }; + + var _updateSegmentProportions = function () { + var curLoc = 0; + for (var i = 0; i < segments.length; i++) { + var sl = segments[i].getLength(); + segmentProportionalLengths[i] = sl / totalLength; + segmentProportions[i] = [curLoc, (curLoc += (sl / totalLength)) ]; + } + }, + + /** + * returns [segment, proportion of travel in segment, segment index] for the segment + * that contains the point which is 'location' distance along the entire path, where + * 'location' is a decimal between 0 and 1 inclusive. in this connector type, paths + * are made up of a list of segments, each of which contributes some fraction to + * the total length. + * From 1.3.10 this also supports the 'absolute' property, which lets us specify a location + * as the absolute distance in pixels, rather than a proportion of the total path. + */ + _findSegmentForLocation = function (location, absolute) { + if (absolute) { + location = location > 0 ? location / totalLength : (totalLength + location) / totalLength; + } + var idx = segmentProportions.length - 1, inSegmentProportion = 1; + for (var i = 0; i < segmentProportions.length; i++) { + if (segmentProportions[i][1] >= location) { + idx = i; + // todo is this correct for all connector path types? + inSegmentProportion = location === 1 ? 1 : location === 0 ? 0 : (location - segmentProportions[i][0]) / segmentProportionalLengths[i]; + break; + } + } + return { segment: segments[idx], proportion: inSegmentProportion, index: idx }; + }, + _addSegment = function (conn, type, params) { + if (params.x1 === params.x2 && params.y1 === params.y2) { + return; + } + var s = new _jp.Segments[type](params); + segments.push(s); + totalLength += s.getLength(); + conn.updateBounds(s); + }, + _clearSegments = function () { + totalLength = segments.length = segmentProportions.length = segmentProportionalLengths.length = 0; + }; + + this.setSegments = function (_segs) { + userProvidedSegments = []; + totalLength = 0; + for (var i = 0; i < _segs.length; i++) { + userProvidedSegments.push(_segs[i]); + totalLength += _segs[i].getLength(); + } + }; + + this.getLength = function() { + return totalLength; + }; + + var _prepareCompute = function (params) { + this.strokeWidth = params.strokeWidth; + var segment = _jg.quadrant(params.sourcePos, params.targetPos), + swapX = params.targetPos[0] < params.sourcePos[0], + swapY = params.targetPos[1] < params.sourcePos[1], + lw = params.strokeWidth || 1, + so = params.sourceEndpoint.anchor.getOrientation(params.sourceEndpoint), + to = params.targetEndpoint.anchor.getOrientation(params.targetEndpoint), + x = swapX ? params.targetPos[0] : params.sourcePos[0], + y = swapY ? params.targetPos[1] : params.sourcePos[1], + w = Math.abs(params.targetPos[0] - params.sourcePos[0]), + h = Math.abs(params.targetPos[1] - params.sourcePos[1]); + + // if either anchor does not have an orientation set, we derive one from their relative + // positions. we fix the axis to be the one in which the two elements are further apart, and + // point each anchor at the other element. this is also used when dragging a new connection. + if (so[0] === 0 && so[1] === 0 || to[0] === 0 && to[1] === 0) { + var index = w > h ? 0 : 1, oIndex = [1, 0][index]; + so = []; + to = []; + so[index] = params.sourcePos[index] > params.targetPos[index] ? -1 : 1; + to[index] = params.sourcePos[index] > params.targetPos[index] ? 1 : -1; + so[oIndex] = 0; + to[oIndex] = 0; + } + + var sx = swapX ? w + (sourceGap * so[0]) : sourceGap * so[0], + sy = swapY ? h + (sourceGap * so[1]) : sourceGap * so[1], + tx = swapX ? targetGap * to[0] : w + (targetGap * to[0]), + ty = swapY ? targetGap * to[1] : h + (targetGap * to[1]), + oProduct = ((so[0] * to[0]) + (so[1] * to[1])); + + var result = { + sx: sx, sy: sy, tx: tx, ty: ty, lw: lw, + xSpan: Math.abs(tx - sx), + ySpan: Math.abs(ty - sy), + mx: (sx + tx) / 2, + my: (sy + ty) / 2, + so: so, to: to, x: x, y: y, w: w, h: h, + segment: segment, + startStubX: sx + (so[0] * sourceStub), + startStubY: sy + (so[1] * sourceStub), + endStubX: tx + (to[0] * targetStub), + endStubY: ty + (to[1] * targetStub), + isXGreaterThanStubTimes2: Math.abs(sx - tx) > (sourceStub + targetStub), + isYGreaterThanStubTimes2: Math.abs(sy - ty) > (sourceStub + targetStub), + opposite: oProduct === -1, + perpendicular: oProduct === 0, + orthogonal: oProduct === 1, + sourceAxis: so[0] === 0 ? "y" : "x", + points: [x, y, w, h, sx, sy, tx, ty ], + stubs:[sourceStub, targetStub] + }; + result.anchorOrientation = result.opposite ? "opposite" : result.orthogonal ? "orthogonal" : "perpendicular"; + return result; + }; + + this.getSegments = function () { + return segments; + }; + + this.updateBounds = function (segment) { + var segBounds = segment.getBounds(); + this.bounds.minX = Math.min(this.bounds.minX, segBounds.minX); + this.bounds.maxX = Math.max(this.bounds.maxX, segBounds.maxX); + this.bounds.minY = Math.min(this.bounds.minY, segBounds.minY); + this.bounds.maxY = Math.max(this.bounds.maxY, segBounds.maxY); + }; + + var dumpSegmentsToConsole = function () { + console.log("SEGMENTS:"); + for (var i = 0; i < segments.length; i++) { + console.log(segments[i].type, segments[i].getLength(), segmentProportions[i]); + } + }; + + this.pointOnPath = function (location, absolute) { + var seg = _findSegmentForLocation(location, absolute); + return seg.segment && seg.segment.pointOnPath(seg.proportion, false) || [0, 0]; + }; + + this.gradientAtPoint = function (location, absolute) { + var seg = _findSegmentForLocation(location, absolute); + return seg.segment && seg.segment.gradientAtPoint(seg.proportion, false) || 0; + }; + + this.pointAlongPathFrom = function (location, distance, absolute) { + var seg = _findSegmentForLocation(location, absolute); + // TODO what happens if this crosses to the next segment? + return seg.segment && seg.segment.pointAlongPathFrom(seg.proportion, distance, false) || [0, 0]; + }; + + this.compute = function (params) { + paintInfo = _prepareCompute.call(this, params); + + _clearSegments(); + this._compute(paintInfo, params); + this.x = paintInfo.points[0]; + this.y = paintInfo.points[1]; + this.w = paintInfo.points[2]; + this.h = paintInfo.points[3]; + this.segment = paintInfo.segment; + _updateSegmentProportions(); + }; + + return { + addSegment: _addSegment, + prepareCompute: _prepareCompute, + sourceStub: sourceStub, + targetStub: targetStub, + maxStub: Math.max(sourceStub, targetStub), + sourceGap: sourceGap, + targetGap: targetGap, + maxGap: Math.max(sourceGap, targetGap) + }; + }; + _ju.extend(_jp.Connectors.AbstractConnector, AbstractComponent); + + + // ********************************* END OF CONNECTOR TYPES ******************************************************************* + + // ********************************* ENDPOINT TYPES ******************************************************************* + + _jp.Endpoints.AbstractEndpoint = function (params) { + AbstractComponent.apply(this, arguments); + var compute = this.compute = function (anchorPoint, orientation, endpointStyle, connectorPaintStyle) { + var out = this._compute.apply(this, arguments); + this.x = out[0]; + this.y = out[1]; + this.w = out[2]; + this.h = out[3]; + this.bounds.minX = this.x; + this.bounds.minY = this.y; + this.bounds.maxX = this.x + this.w; + this.bounds.maxY = this.y + this.h; + return out; + }; + return { + compute: compute, + cssClass: params.cssClass + }; + }; + _ju.extend(_jp.Endpoints.AbstractEndpoint, AbstractComponent); + + /** + * Class: Endpoints.Dot + * A round endpoint, with default radius 10 pixels. + */ + + /** + * Function: Constructor + * + * Parameters: + * + * radius - radius of the endpoint. defaults to 10 pixels. + */ + _jp.Endpoints.Dot = function (params) { + this.type = "Dot"; + var _super = _jp.Endpoints.AbstractEndpoint.apply(this, arguments); + params = params || {}; + this.radius = params.radius || 10; + this.defaultOffset = 0.5 * this.radius; + this.defaultInnerRadius = this.radius / 3; + + this._compute = function (anchorPoint, orientation, endpointStyle, connectorPaintStyle) { + this.radius = endpointStyle.radius || this.radius; + var x = anchorPoint[0] - this.radius, + y = anchorPoint[1] - this.radius, + w = this.radius * 2, + h = this.radius * 2; + + if (endpointStyle.stroke) { + var lw = endpointStyle.strokeWidth || 1; + x -= lw; + y -= lw; + w += (lw * 2); + h += (lw * 2); + } + return [ x, y, w, h, this.radius ]; + }; + }; + _ju.extend(_jp.Endpoints.Dot, _jp.Endpoints.AbstractEndpoint); + + _jp.Endpoints.Rectangle = function (params) { + this.type = "Rectangle"; + var _super = _jp.Endpoints.AbstractEndpoint.apply(this, arguments); + params = params || {}; + this.width = params.width || 20; + this.height = params.height || 20; + + this._compute = function (anchorPoint, orientation, endpointStyle, connectorPaintStyle) { + var width = endpointStyle.width || this.width, + height = endpointStyle.height || this.height, + x = anchorPoint[0] - (width / 2), + y = anchorPoint[1] - (height / 2); + + return [ x, y, width, height]; + }; + }; + _ju.extend(_jp.Endpoints.Rectangle, _jp.Endpoints.AbstractEndpoint); + + var DOMElementEndpoint = function (params) { + _jp.jsPlumbUIComponent.apply(this, arguments); + this._jsPlumb.displayElements = []; + }; + _ju.extend(DOMElementEndpoint, _jp.jsPlumbUIComponent, { + getDisplayElements: function () { + return this._jsPlumb.displayElements; + }, + appendDisplayElement: function (el) { + this._jsPlumb.displayElements.push(el); + } + }); + + /** + * Class: Endpoints.Image + * Draws an image as the Endpoint. + */ + /** + * Function: Constructor + * + * Parameters: + * + * src - location of the image to use. + + TODO: multiple references to self. not sure quite how to get rid of them entirely. perhaps self = null in the cleanup + function will suffice + + TODO this class still might leak memory. + + */ + _jp.Endpoints.Image = function (params) { + + this.type = "Image"; + DOMElementEndpoint.apply(this, arguments); + _jp.Endpoints.AbstractEndpoint.apply(this, arguments); + + var _onload = params.onload, + src = params.src || params.url, + clazz = params.cssClass ? " " + params.cssClass : ""; + + this._jsPlumb.img = new Image(); + this._jsPlumb.ready = false; + this._jsPlumb.initialized = false; + this._jsPlumb.deleted = false; + this._jsPlumb.widthToUse = params.width; + this._jsPlumb.heightToUse = params.height; + this._jsPlumb.endpoint = params.endpoint; + + this._jsPlumb.img.onload = function () { + if (this._jsPlumb != null) { + this._jsPlumb.ready = true; + this._jsPlumb.widthToUse = this._jsPlumb.widthToUse || this._jsPlumb.img.width; + this._jsPlumb.heightToUse = this._jsPlumb.heightToUse || this._jsPlumb.img.height; + if (_onload) { + _onload(this); + } + } + }.bind(this); + + /* + Function: setImage + Sets the Image to use in this Endpoint. + + Parameters: + img - may be a URL or an Image object + onload - optional; a callback to execute once the image has loaded. + */ + this._jsPlumb.endpoint.setImage = function (_img, onload) { + var s = _img.constructor === String ? _img : _img.src; + _onload = onload; + this._jsPlumb.img.src = s; + + if (this.canvas != null) { + this.canvas.setAttribute("src", this._jsPlumb.img.src); + } + }.bind(this); + + this._jsPlumb.endpoint.setImage(src, _onload); + this._compute = function (anchorPoint, orientation, endpointStyle, connectorPaintStyle) { + this.anchorPoint = anchorPoint; + if (this._jsPlumb.ready) { + return [anchorPoint[0] - this._jsPlumb.widthToUse / 2, anchorPoint[1] - this._jsPlumb.heightToUse / 2, + this._jsPlumb.widthToUse, this._jsPlumb.heightToUse]; + } + else { + return [0, 0, 0, 0]; + } + }; + + this.canvas = _jp.createElement("img", { + position:"absolute", + margin:0, + padding:0, + outline:0 + }, this._jsPlumb.instance.endpointClass + clazz); + + if (this._jsPlumb.widthToUse) { + this.canvas.setAttribute("width", this._jsPlumb.widthToUse); + } + if (this._jsPlumb.heightToUse) { + this.canvas.setAttribute("height", this._jsPlumb.heightToUse); + } + this._jsPlumb.instance.appendElement(this.canvas); + + this.actuallyPaint = function (d, style, anchor) { + if (!this._jsPlumb.deleted) { + if (!this._jsPlumb.initialized) { + this.canvas.setAttribute("src", this._jsPlumb.img.src); + this.appendDisplayElement(this.canvas); + this._jsPlumb.initialized = true; + } + var x = this.anchorPoint[0] - (this._jsPlumb.widthToUse / 2), + y = this.anchorPoint[1] - (this._jsPlumb.heightToUse / 2); + _ju.sizeElement(this.canvas, x, y, this._jsPlumb.widthToUse, this._jsPlumb.heightToUse); + } + }; + + this.paint = function (style, anchor) { + if (this._jsPlumb != null) { // may have been deleted + if (this._jsPlumb.ready) { + this.actuallyPaint(style, anchor); + } + else { + root.setTimeout(function () { + this.paint(style, anchor); + }.bind(this), 200); + } + } + }; + }; + _ju.extend(_jp.Endpoints.Image, [ DOMElementEndpoint, _jp.Endpoints.AbstractEndpoint ], { + cleanup: function (force) { + if (force) { + this._jsPlumb.deleted = true; + if (this.canvas) { + this.canvas.parentNode.removeChild(this.canvas); + } + this.canvas = null; + } + } + }); + + /* + * Class: Endpoints.Blank + * An Endpoint that paints nothing (visible) on the screen. Supports cssClass and hoverClass parameters like all Endpoints. + */ + _jp.Endpoints.Blank = function (params) { + var _super = _jp.Endpoints.AbstractEndpoint.apply(this, arguments); + this.type = "Blank"; + DOMElementEndpoint.apply(this, arguments); + this._compute = function (anchorPoint, orientation, endpointStyle, connectorPaintStyle) { + return [anchorPoint[0], anchorPoint[1], 10, 0]; + }; + + var clazz = params.cssClass ? " " + params.cssClass : ""; + + this.canvas = _jp.createElement("div", { + display: "block", + width: "1px", + height: "1px", + background: "transparent", + position: "absolute" + }, this._jsPlumb.instance.endpointClass + clazz); + + this._jsPlumb.instance.appendElement(this.canvas); + + this.paint = function (style, anchor) { + _ju.sizeElement(this.canvas, this.x, this.y, this.w, this.h); + }; + }; + _ju.extend(_jp.Endpoints.Blank, [_jp.Endpoints.AbstractEndpoint, DOMElementEndpoint], { + cleanup: function () { + if (this.canvas && this.canvas.parentNode) { + this.canvas.parentNode.removeChild(this.canvas); + } + } + }); + + /* + * Class: Endpoints.Triangle + * A triangular Endpoint. + */ + /* + * Function: Constructor + * + * Parameters: + * + * width width of the triangle's base. defaults to 55 pixels. + * height height of the triangle from base to apex. defaults to 55 pixels. + */ + _jp.Endpoints.Triangle = function (params) { + this.type = "Triangle"; + _jp.Endpoints.AbstractEndpoint.apply(this, arguments); + var self = this; + params = params || { }; + params.width = params.width || 55; + params.height = params.height || 55; + this.width = params.width; + this.height = params.height; + this._compute = function (anchorPoint, orientation, endpointStyle, connectorPaintStyle) { + var width = endpointStyle.width || self.width, + height = endpointStyle.height || self.height, + x = anchorPoint[0] - (width / 2), + y = anchorPoint[1] - (height / 2); + return [ x, y, width, height ]; + }; + }; +// ********************************* END OF ENDPOINT TYPES ******************************************************************* + + +// ********************************* OVERLAY DEFINITIONS *********************************************************************** + + var AbstractOverlay = _jp.Overlays.AbstractOverlay = function (params) { + this.visible = true; + this.isAppendedAtTopLevel = true; + this.component = params.component; + this.loc = params.location == null ? 0.5 : params.location; + this.endpointLoc = params.endpointLocation == null ? [ 0.5, 0.5] : params.endpointLocation; + this.visible = params.visible !== false; + }; + AbstractOverlay.prototype = { + cleanup: function (force) { + if (force) { + this.component = null; + this.canvas = null; + this.endpointLoc = null; + } + }, + reattach:function(instance, component) { }, + setVisible: function (val) { + this.visible = val; + this.component.repaint(); + }, + isVisible: function () { + return this.visible; + }, + hide: function () { + this.setVisible(false); + }, + show: function () { + this.setVisible(true); + }, + incrementLocation: function (amount) { + this.loc += amount; + this.component.repaint(); + }, + setLocation: function (l) { + this.loc = l; + this.component.repaint(); + }, + getLocation: function () { + return this.loc; + }, + updateFrom:function() { } + }; + + + /* + * Class: Overlays.Arrow + * + * An arrow overlay, defined by four points: the head, the two sides of the tail, and a 'foldback' point at some distance along the length + * of the arrow that lines from each tail point converge into. The foldback point is defined using a decimal that indicates some fraction + * of the length of the arrow and has a default value of 0.623. A foldback point value of 1 would mean that the arrow had a straight line + * across the tail. + */ + /* + * @constructor + * + * @param {Object} params Constructor params. + * @param {Number} [params.length] Distance in pixels from head to tail baseline. default 20. + * @param {Number} [params.width] Width in pixels of the tail baseline. default 20. + * @param {String} [params.fill] Style to use when filling the arrow. defaults to "black". + * @param {String} [params.stroke] Style to use when stroking the arrow. defaults to null, which means the arrow is not stroked. + * @param {Number} [params.stroke-width] Line width to use when stroking the arrow. defaults to 1, but only used if stroke is not null. + * @param {Number} [params.foldback] Distance (as a decimal from 0 to 1 inclusive) along the length of the arrow marking the point the tail points should fold back to. defaults to 0.623. + * @param {Number} [params.location] Distance (as a decimal from 0 to 1 inclusive) marking where the arrow should sit on the connector. defaults to 0.5. + * @param {NUmber} [params.direction] Indicates the direction the arrow points in. valid values are -1 and 1; 1 is default. + */ + _jp.Overlays.Arrow = function (params) { + this.type = "Arrow"; + AbstractOverlay.apply(this, arguments); + this.isAppendedAtTopLevel = false; + params = params || {}; + var self = this; + + this.length = params.length || 20; + this.width = params.width || 20; + this.id = params.id; + this.direction = (params.direction || 1) < 0 ? -1 : 1; + var paintStyle = params.paintStyle || { "stroke-width": 1 }, + // how far along the arrow the lines folding back in come to. default is 62.3%. + foldback = params.foldback || 0.623; + + this.computeMaxSize = function () { + return self.width * 1.5; + }; + + this.elementCreated = function(p, component) { + this.path = p; + if (params.events) { + for (var i in params.events) { + _jp.on(p, i, params.events[i]); + } + } + }; + + this.draw = function (component, currentConnectionPaintStyle) { + + var hxy, mid, txy, tail, cxy; + if (component.pointAlongPathFrom) { + + if (_ju.isString(this.loc) || this.loc > 1 || this.loc < 0) { + var l = parseInt(this.loc, 10), + fromLoc = this.loc < 0 ? 1 : 0; + hxy = component.pointAlongPathFrom(fromLoc, l, false); + mid = component.pointAlongPathFrom(fromLoc, l - (this.direction * this.length / 2), false); + txy = _jg.pointOnLine(hxy, mid, this.length); + } + else if (this.loc === 1) { + hxy = component.pointOnPath(this.loc); + mid = component.pointAlongPathFrom(this.loc, -(this.length)); + txy = _jg.pointOnLine(hxy, mid, this.length); + + if (this.direction === -1) { + var _ = txy; + txy = hxy; + hxy = _; + } + } + else if (this.loc === 0) { + txy = component.pointOnPath(this.loc); + mid = component.pointAlongPathFrom(this.loc, this.length); + hxy = _jg.pointOnLine(txy, mid, this.length); + if (this.direction === -1) { + var __ = txy; + txy = hxy; + hxy = __; + } + } + else { + hxy = component.pointAlongPathFrom(this.loc, this.direction * this.length / 2); + mid = component.pointOnPath(this.loc); + txy = _jg.pointOnLine(hxy, mid, this.length); + } + + tail = _jg.perpendicularLineTo(hxy, txy, this.width); + cxy = _jg.pointOnLine(hxy, txy, foldback * this.length); + + var d = { hxy: hxy, tail: tail, cxy: cxy }, + stroke = paintStyle.stroke || currentConnectionPaintStyle.stroke, + fill = paintStyle.fill || currentConnectionPaintStyle.stroke, + lineWidth = paintStyle.strokeWidth || currentConnectionPaintStyle.strokeWidth; + + return { + component: component, + d: d, + "stroke-width": lineWidth, + stroke: stroke, + fill: fill, + minX: Math.min(hxy.x, tail[0].x, tail[1].x), + maxX: Math.max(hxy.x, tail[0].x, tail[1].x), + minY: Math.min(hxy.y, tail[0].y, tail[1].y), + maxY: Math.max(hxy.y, tail[0].y, tail[1].y) + }; + } + else { + return {component: component, minX: 0, maxX: 0, minY: 0, maxY: 0}; + } + }; + }; + _ju.extend(_jp.Overlays.Arrow, AbstractOverlay, { + updateFrom:function(d) { + this.length = d.length || this.length; + this.width = d.width|| this.width; + this.direction = d.direction != null ? d.direction : this.direction; + this.foldback = d.foldback|| this.foldback; + }, + cleanup:function() { + if (this.path && this.canvas) { + this.canvas.removeChild(this.path); + } + } + }); + + /* + * Class: Overlays.PlainArrow + * + * A basic arrow. This is in fact just one instance of the more generic case in which the tail folds back on itself to some + * point along the length of the arrow: in this case, that foldback point is the full length of the arrow. so it just does + * a 'call' to Arrow with foldback set appropriately. + */ + /* + * Function: Constructor + * See for allowed parameters for this overlay. + */ + _jp.Overlays.PlainArrow = function (params) { + params = params || {}; + var p = _jp.extend(params, {foldback: 1}); + _jp.Overlays.Arrow.call(this, p); + this.type = "PlainArrow"; + }; + _ju.extend(_jp.Overlays.PlainArrow, _jp.Overlays.Arrow); + + /* + * Class: Overlays.Diamond + * + * A diamond. Like PlainArrow, this is a concrete case of the more generic case of the tail points converging on some point...it just + * happens that in this case, that point is greater than the length of the the arrow. + * + * this could probably do with some help with positioning...due to the way it reuses the Arrow paint code, what Arrow thinks is the + * center is actually 1/4 of the way along for this guy. but we don't have any knowledge of pixels at this point, so we're kind of + * stuck when it comes to helping out the Arrow class. possibly we could pass in a 'transpose' parameter or something. the value + * would be -l/4 in this case - move along one quarter of the total length. + */ + /* + * Function: Constructor + * See for allowed parameters for this overlay. + */ + _jp.Overlays.Diamond = function (params) { + params = params || {}; + var l = params.length || 40, + p = _jp.extend(params, {length: l / 2, foldback: 2}); + _jp.Overlays.Arrow.call(this, p); + this.type = "Diamond"; + }; + _ju.extend(_jp.Overlays.Diamond, _jp.Overlays.Arrow); + + var _getDimensions = function (component, forceRefresh) { + if (component._jsPlumb.cachedDimensions == null || forceRefresh) { + component._jsPlumb.cachedDimensions = component.getDimensions(); + } + return component._jsPlumb.cachedDimensions; + }; + + // abstract superclass for overlays that add an element to the DOM. + var AbstractDOMOverlay = function (params) { + _jp.jsPlumbUIComponent.apply(this, arguments); + AbstractOverlay.apply(this, arguments); + + // hand off fired events to associated component. + var _f = this.fire; + this.fire = function () { + _f.apply(this, arguments); + if (this.component) { + this.component.fire.apply(this.component, arguments); + } + }; + + this.detached=false; + this.id = params.id; + this._jsPlumb.div = null; + this._jsPlumb.initialised = false; + this._jsPlumb.component = params.component; + this._jsPlumb.cachedDimensions = null; + this._jsPlumb.create = params.create; + this._jsPlumb.initiallyInvisible = params.visible === false; + + this.getElement = function () { + if (this._jsPlumb.div == null) { + var div = this._jsPlumb.div = _jp.getElement(this._jsPlumb.create(this._jsPlumb.component)); + div.style.position = "absolute"; + jsPlumb.addClass(div, this._jsPlumb.instance.overlayClass + " " + + (this.cssClass ? this.cssClass : + params.cssClass ? params.cssClass : "")); + this._jsPlumb.instance.appendElement(div); + this._jsPlumb.instance.getId(div); + this.canvas = div; + + // in IE the top left corner is what it placed at the desired location. This will not + // be fixed. IE8 is not going to be supported for much longer. + var ts = "translate(-50%, -50%)"; + div.style.webkitTransform = ts; + div.style.mozTransform = ts; + div.style.msTransform = ts; + div.style.oTransform = ts; + div.style.transform = ts; + + // write the related component into the created element + div._jsPlumb = this; + + if (params.visible === false) { + div.style.display = "none"; + } + } + return this._jsPlumb.div; + }; + + this.draw = function (component, currentConnectionPaintStyle, absolutePosition) { + var td = _getDimensions(this); + if (td != null && td.length === 2) { + var cxy = { x: 0, y: 0 }; + + // absolutePosition would have been set by a call to connection.setAbsoluteOverlayPosition. + if (absolutePosition) { + cxy = { x: absolutePosition[0], y: absolutePosition[1] }; + } + else if (component.pointOnPath) { + var loc = this.loc, absolute = false; + if (_ju.isString(this.loc) || this.loc < 0 || this.loc > 1) { + loc = parseInt(this.loc, 10); + absolute = true; + } + cxy = component.pointOnPath(loc, absolute); // a connection + } + else { + var locToUse = this.loc.constructor === Array ? this.loc : this.endpointLoc; + cxy = { x: locToUse[0] * component.w, + y: locToUse[1] * component.h }; + } + + var minx = cxy.x - (td[0] / 2), + miny = cxy.y - (td[1] / 2); + + return { + component: component, + d: { minx: minx, miny: miny, td: td, cxy: cxy }, + minX: minx, + maxX: minx + td[0], + minY: miny, + maxY: miny + td[1] + }; + } + else { + return {minX: 0, maxX: 0, minY: 0, maxY: 0}; + } + }; + }; + _ju.extend(AbstractDOMOverlay, [_jp.jsPlumbUIComponent, AbstractOverlay], { + getDimensions: function () { + return [1,1]; + }, + setVisible: function (state) { + if (this._jsPlumb.div) { + this._jsPlumb.div.style.display = state ? "block" : "none"; + // if initially invisible, dimensions are 0,0 and never get updated + if (state && this._jsPlumb.initiallyInvisible) { + _getDimensions(this, true); + this.component.repaint(); + this._jsPlumb.initiallyInvisible = false; + } + } + }, + /* + * Function: clearCachedDimensions + * Clears the cached dimensions for the label. As a performance enhancement, label dimensions are + * cached from 1.3.12 onwards. The cache is cleared when you change the label text, of course, but + * there are other reasons why the text dimensions might change - if you make a change through CSS, for + * example, you might change the font size. in that case you should explicitly call this method. + */ + clearCachedDimensions: function () { + this._jsPlumb.cachedDimensions = null; + }, + cleanup: function (force) { + if (force) { + if (this._jsPlumb.div != null) { + this._jsPlumb.div._jsPlumb = null; + this._jsPlumb.instance.removeElement(this._jsPlumb.div); + } + } + else { + // if not a forced cleanup, just detach child from parent for now. + if (this._jsPlumb && this._jsPlumb.div && this._jsPlumb.div.parentNode) { + this._jsPlumb.div.parentNode.removeChild(this._jsPlumb.div); + } + this.detached = true; + } + + }, + reattach:function(instance, component) { + if (this._jsPlumb.div != null) { + instance.getContainer().appendChild(this._jsPlumb.div); + } + this.detached = false; + }, + computeMaxSize: function () { + var td = _getDimensions(this); + return Math.max(td[0], td[1]); + }, + paint: function (p, containerExtents) { + if (!this._jsPlumb.initialised) { + this.getElement(); + p.component.appendDisplayElement(this._jsPlumb.div); + this._jsPlumb.initialised = true; + if (this.detached) { + this._jsPlumb.div.parentNode.removeChild(this._jsPlumb.div); + } + } + this._jsPlumb.div.style.left = (p.component.x + p.d.minx) + "px"; + this._jsPlumb.div.style.top = (p.component.y + p.d.miny) + "px"; + } + }); + + /* + * Class: Overlays.Custom + * A Custom overlay. You supply a 'create' function which returns some DOM element, and jsPlumb positions it. + * The 'create' function is passed a Connection or Endpoint. + */ + /* + * Function: Constructor + * + * Parameters: + * create - function for jsPlumb to call that returns a DOM element. + * location - distance (as a decimal from 0 to 1 inclusive) marking where the label should sit on the connector. defaults to 0.5. + * id - optional id to use for later retrieval of this overlay. + * + */ + _jp.Overlays.Custom = function (params) { + this.type = "Custom"; + AbstractDOMOverlay.apply(this, arguments); + }; + _ju.extend(_jp.Overlays.Custom, AbstractDOMOverlay); + + _jp.Overlays.GuideLines = function () { + var self = this; + self.length = 50; + self.strokeWidth = 5; + this.type = "GuideLines"; + AbstractOverlay.apply(this, arguments); + _jp.jsPlumbUIComponent.apply(this, arguments); + this.draw = function (connector, currentConnectionPaintStyle) { + + var head = connector.pointAlongPathFrom(self.loc, self.length / 2), + mid = connector.pointOnPath(self.loc), + tail = _jg.pointOnLine(head, mid, self.length), + tailLine = _jg.perpendicularLineTo(head, tail, 40), + headLine = _jg.perpendicularLineTo(tail, head, 20); + + return { + connector: connector, + head: head, + tail: tail, + headLine: headLine, + tailLine: tailLine, + minX: Math.min(head.x, tail.x, headLine[0].x, headLine[1].x), + minY: Math.min(head.y, tail.y, headLine[0].y, headLine[1].y), + maxX: Math.max(head.x, tail.x, headLine[0].x, headLine[1].x), + maxY: Math.max(head.y, tail.y, headLine[0].y, headLine[1].y) + }; + }; + + // this.cleanup = function() { }; // nothing to clean up for GuideLines + }; + + /* + * Class: Overlays.Label + + */ + /* + * Function: Constructor + * + * Parameters: + * cssClass - optional css class string to append to css class. This string is appended "as-is", so you can of course have multiple classes + * defined. This parameter is preferred to using labelStyle, borderWidth and borderStyle. + * label - the label to paint. May be a string or a function that returns a string. Nothing will be painted if your label is null or your + * label function returns null. empty strings _will_ be painted. + * location - distance (as a decimal from 0 to 1 inclusive) marking where the label should sit on the connector. defaults to 0.5. + * id - optional id to use for later retrieval of this overlay. + * + * + */ + _jp.Overlays.Label = function (params) { + this.labelStyle = params.labelStyle; + + var labelWidth = null, labelHeight = null, labelText = null, labelPadding = null; + this.cssClass = this.labelStyle != null ? this.labelStyle.cssClass : null; + var p = _jp.extend({ + create: function () { + return _jp.createElement("div"); + }}, params); + _jp.Overlays.Custom.call(this, p); + this.type = "Label"; + this.label = params.label || ""; + this.labelText = null; + if (this.labelStyle) { + var el = this.getElement(); + this.labelStyle.font = this.labelStyle.font || "12px sans-serif"; + el.style.font = this.labelStyle.font; + el.style.color = this.labelStyle.color || "black"; + if (this.labelStyle.fill) { + el.style.background = this.labelStyle.fill; + } + if (this.labelStyle.borderWidth > 0) { + var dStyle = this.labelStyle.borderStyle ? this.labelStyle.borderStyle : "black"; + el.style.border = this.labelStyle.borderWidth + "px solid " + dStyle; + } + if (this.labelStyle.padding) { + el.style.padding = this.labelStyle.padding; + } + } + + }; + _ju.extend(_jp.Overlays.Label, _jp.Overlays.Custom, { + cleanup: function (force) { + if (force) { + this.div = null; + this.label = null; + this.labelText = null; + this.cssClass = null; + this.labelStyle = null; + } + }, + getLabel: function () { + return this.label; + }, + /* + * Function: setLabel + * sets the label's, um, label. you would think i'd call this function + * 'setText', but you can pass either a Function or a String to this, so + * it makes more sense as 'setLabel'. This uses innerHTML on the label div, so keep + * that in mind if you need escaped HTML. + */ + setLabel: function (l) { + this.label = l; + this.labelText = null; + this.clearCachedDimensions(); + this.update(); + this.component.repaint(); + }, + getDimensions: function () { + this.update(); + return AbstractDOMOverlay.prototype.getDimensions.apply(this, arguments); + }, + update: function () { + if (typeof this.label === "function") { + var lt = this.label(this); + this.getElement().innerHTML = lt.replace(/\r\n/g, "
"); + } + else { + if (this.labelText == null) { + this.labelText = this.label; + this.getElement().innerHTML = this.labelText.replace(/\r\n/g, "
"); + } + } + }, + updateFrom:function(d) { + if(d.label != null){ + this.setLabel(d.label); + } + } + }); + + // ********************************* END OF OVERLAY DEFINITIONS *********************************************************************** + +}).call(typeof window !== 'undefined' ? window : this); + +/* + * Copyright (c) 2010 - 2018 jsPlumb (hello@jsplumbtoolkit.com) + * + * https://jsplumbtoolkit.com + * https://github.com/jsplumb/jsplumb + * + * Dual licensed under the MIT and GPL2 licenses. + */ +;(function() { + "use strict"; + + var root = this, + _ju = root.jsPlumbUtil, + _jpi = root.jsPlumbInstance; + + var GROUP_COLLAPSED_CLASS = "jtk-group-collapsed"; + var GROUP_EXPANDED_CLASS = "jtk-group-expanded"; + var GROUP_CONTAINER_SELECTOR = "[jtk-group-content]"; + var ELEMENT_DRAGGABLE_EVENT = "elementDraggable"; + var STOP = "stop"; + var REVERT = "revert"; + var GROUP_MANAGER = "_groupManager"; + var GROUP = "_jsPlumbGroup"; + var GROUP_DRAG_SCOPE = "_jsPlumbGroupDrag"; + var EVT_CHILD_ADDED = "group:addMember"; + var EVT_CHILD_REMOVED = "group:removeMember"; + var EVT_GROUP_ADDED = "group:add"; + var EVT_GROUP_REMOVED = "group:remove"; + var EVT_EXPAND = "group:expand"; + var EVT_COLLAPSE = "group:collapse"; + var EVT_GROUP_DRAG_STOP = "groupDragStop"; + var EVT_CONNECTION_MOVED = "connectionMoved"; + var EVT_INTERNAL_CONNECTION_DETACHED = "internal.connectionDetached"; + + var CMD_REMOVE_ALL = "removeAll"; + var CMD_ORPHAN_ALL = "orphanAll"; + var CMD_SHOW = "show"; + var CMD_HIDE = "hide"; + + var GroupManager = function(_jsPlumb) { + var _managedGroups = {}, _connectionSourceMap = {}, _connectionTargetMap = {}, self = this; + + _jsPlumb.bind("connection", function(p) { + if (p.source[GROUP] != null && p.target[GROUP] != null && p.source[GROUP] === p.target[GROUP]) { + _connectionSourceMap[p.connection.id] = p.source[GROUP]; + _connectionTargetMap[p.connection.id] = p.source[GROUP]; + } + else { + if (p.source[GROUP] != null) { + _ju.suggest(p.source[GROUP].connections.source, p.connection); + _connectionSourceMap[p.connection.id] = p.source[GROUP]; + } + if (p.target[GROUP] != null) { + _ju.suggest(p.target[GROUP].connections.target, p.connection); + _connectionTargetMap[p.connection.id] = p.target[GROUP]; + } + } + }); + + function _cleanupDetachedConnection(conn) { + delete conn.proxies; + var group = _connectionSourceMap[conn.id], f; + if (group != null) { + f = function(c) { return c.id === conn.id; }; + _ju.removeWithFunction(group.connections.source, f); + _ju.removeWithFunction(group.connections.target, f); + delete _connectionSourceMap[conn.id]; + } + + group = _connectionTargetMap[conn.id]; + if (group != null) { + f = function(c) { return c.id === conn.id; }; + _ju.removeWithFunction(group.connections.source, f); + _ju.removeWithFunction(group.connections.target, f); + delete _connectionTargetMap[conn.id]; + } + } + + _jsPlumb.bind(EVT_INTERNAL_CONNECTION_DETACHED, function(p) { + _cleanupDetachedConnection(p.connection); + }); + + _jsPlumb.bind(EVT_CONNECTION_MOVED, function(p) { + var connMap = p.index === 0 ? _connectionSourceMap : _connectionTargetMap; + var group = connMap[p.connection.id]; + if (group) { + var list = group.connections[p.index === 0 ? "source" : "target"]; + var idx = list.indexOf(p.connection); + if (idx !== -1) { + list.splice(idx, 1); + } + } + }); + + this.addGroup = function(group) { + _jsPlumb.addClass(group.getEl(), GROUP_EXPANDED_CLASS); + _managedGroups[group.id] = group; + group.manager = this; + _updateConnectionsForGroup(group); + _jsPlumb.fire(EVT_GROUP_ADDED, { group:group }); + }; + + this.addToGroup = function(group, el, doNotFireEvent) { + group = this.getGroup(group); + if (group) { + var groupEl = group.getEl(); + + if (el._isJsPlumbGroup) { + return; + } + var currentGroup = el._jsPlumbGroup; + // if already a member of this group, do nothing + if (currentGroup !== group) { + var elpos = _jsPlumb.getOffset(el, true); + var cpos = group.collapsed ? _jsPlumb.getOffset(groupEl, true) : _jsPlumb.getOffset(group.getDragArea(), true); + + // otherwise, transfer to this group. + if (currentGroup != null) { + currentGroup.remove(el, false, doNotFireEvent, false, group); + self.updateConnectionsForGroup(currentGroup); + } + group.add(el, doNotFireEvent/*, currentGroup*/); + + var handleDroppedConnections = function (list, index) { + var oidx = index === 0 ? 1 : 0; + list.each(function (c) { + c.setVisible(false); + if (c.endpoints[oidx].element._jsPlumbGroup === group) { + c.endpoints[oidx].setVisible(false); + _expandConnection(c, oidx, group); + } + else { + c.endpoints[index].setVisible(false); + _collapseConnection(c, index, group); + } + }); + }; + + if (group.collapsed) { + handleDroppedConnections(_jsPlumb.select({source: el}), 0); + handleDroppedConnections(_jsPlumb.select({target: el}), 1); + } + + var elId = _jsPlumb.getId(el); + _jsPlumb.dragManager.setParent(el, elId, groupEl, _jsPlumb.getId(groupEl), elpos); + + var newPosition = { left: elpos.left - cpos.left, top: elpos.top - cpos.top }; + + _jsPlumb.setPosition(el, newPosition); + + _jsPlumb.dragManager.revalidateParent(el, elId, elpos); + + self.updateConnectionsForGroup(group); + + _jsPlumb.revalidate(elId); + + if (!doNotFireEvent) { + var p = {group: group, el: el, pos:newPosition}; + if (currentGroup) { + p.sourceGroup = currentGroup; + } + _jsPlumb.fire(EVT_CHILD_ADDED, p); + } + } + } + }; + + this.removeFromGroup = function(group, el, doNotFireEvent) { + group = this.getGroup(group); + if (group) { + group.remove(el, null, doNotFireEvent); + } + }; + + this.getGroup = function(groupId) { + var group = groupId; + if (_ju.isString(groupId)) { + group = _managedGroups[groupId]; + if (group == null) { + throw new TypeError("No such group [" + groupId + "]"); + } + } + return group; + }; + + this.getGroups = function() { + var o = []; + for (var g in _managedGroups) { + o.push(_managedGroups[g]); + } + return o; + }; + + this.removeGroup = function(group, deleteMembers, manipulateDOM, doNotFireEvent) { + group = this.getGroup(group); + this.expandGroup(group, true); // this reinstates any original connections and removes all proxies, but does not fire an event. + var newPositions = group[deleteMembers ? CMD_REMOVE_ALL : CMD_ORPHAN_ALL](manipulateDOM, doNotFireEvent); + _jsPlumb.remove(group.getEl()); + delete _managedGroups[group.id]; + delete _jsPlumb._groups[group.id]; + _jsPlumb.fire(EVT_GROUP_REMOVED, { group:group }); + return newPositions; // this will be null in the case or remove, but be a map of {id->[x,y]} in the case of orphan + }; + + this.removeAllGroups = function(deleteMembers, manipulateDOM, doNotFireEvent) { + for (var g in _managedGroups) { + this.removeGroup(_managedGroups[g], deleteMembers, manipulateDOM, doNotFireEvent); + } + }; + + function _setVisible(group, state) { + var m = group.getMembers(); + for (var i = 0; i < m.length; i++) { + _jsPlumb[state ? CMD_SHOW : CMD_HIDE](m[i], true); + } + } + + var _collapseConnection = function(c, index, group) { + + var otherEl = c.endpoints[index === 0 ? 1 : 0].element; + if (otherEl[GROUP] && (!otherEl[GROUP].shouldProxy() && otherEl[GROUP].collapsed)) { + return; + } + + var groupEl = group.getEl(), groupElId = _jsPlumb.getId(groupEl); + + _jsPlumb.proxyConnection(c, index, groupEl, groupElId, function(c, index) { return group.getEndpoint(c, index); }, function(c, index) { return group.getAnchor(c, index); }); + }; + + this.collapseGroup = function(group) { + group = this.getGroup(group); + if (group == null || group.collapsed) { + return; + } + var groupEl = group.getEl(); + + // todo remove old proxy endpoints first, just in case? + //group.proxies.length = 0; + + // hide all connections + _setVisible(group, false); + + if (group.shouldProxy()) { + // collapses all connections in a group. + var _collapseSet = function (conns, index) { + for (var i = 0; i < conns.length; i++) { + var c = conns[i]; + _collapseConnection(c, index, group); + } + }; + + // setup proxies for sources and targets + _collapseSet(group.connections.source, 0); + _collapseSet(group.connections.target, 1); + } + + group.collapsed = true; + _jsPlumb.removeClass(groupEl, GROUP_EXPANDED_CLASS); + _jsPlumb.addClass(groupEl, GROUP_COLLAPSED_CLASS); + _jsPlumb.revalidate(groupEl); + _jsPlumb.fire(EVT_COLLAPSE, { group:group }); + }; + + var _expandConnection = function(c, index, group) { + _jsPlumb.unproxyConnection(c, index, _jsPlumb.getId(group.getEl())); + }; + + this.expandGroup = function(group, doNotFireEvent) { + + group = this.getGroup(group); + + if (group == null || !group.collapsed) { + return; + } + var groupEl = group.getEl(); + + _setVisible(group, true); + + if (group.shouldProxy()) { + // collapses all connections in a group. + var _expandSet = function (conns, index) { + for (var i = 0; i < conns.length; i++) { + var c = conns[i]; + _expandConnection(c, index, group); + } + }; + + // setup proxies for sources and targets + _expandSet(group.connections.source, 0); + _expandSet(group.connections.target, 1); + } + + group.collapsed = false; + _jsPlumb.addClass(groupEl, GROUP_EXPANDED_CLASS); + _jsPlumb.removeClass(groupEl, GROUP_COLLAPSED_CLASS); + _jsPlumb.revalidate(groupEl); + this.repaintGroup(group); + if (!doNotFireEvent) { + _jsPlumb.fire(EVT_EXPAND, { group: group}); + } + }; + + this.repaintGroup = function(group) { + group = this.getGroup(group); + var m = group.getMembers(); + for (var i = 0; i < m.length; i++) { + _jsPlumb.revalidate(m[i]); + } + }; + + // TODO refactor this with the code that responds to `connection` events. + function _updateConnectionsForGroup(group) { + var members = group.getMembers(); + var c1 = _jsPlumb.getConnections({source:members, scope:"*"}, true); + var c2 = _jsPlumb.getConnections({target:members, scope:"*"}, true); + var processed = {}; + group.connections.source.length = 0; + group.connections.target.length = 0; + var oneSet = function(c) { + for (var i = 0; i < c.length; i++) { + if (processed[c[i].id]) { + continue; + } + processed[c[i].id] = true; + if (c[i].source._jsPlumbGroup === group) { + if (c[i].target._jsPlumbGroup !== group) { + group.connections.source.push(c[i]); + } + _connectionSourceMap[c[i].id] = group; + } + else if (c[i].target._jsPlumbGroup === group) { + group.connections.target.push(c[i]); + _connectionTargetMap[c[i].id] = group; + } + } + }; + oneSet(c1); oneSet(c2); + } + + this.updateConnectionsForGroup = _updateConnectionsForGroup; + this.refreshAllGroups = function() { + for (var g in _managedGroups) { + _updateConnectionsForGroup(_managedGroups[g]); + _jsPlumb.dragManager.updateOffsets(_jsPlumb.getId(_managedGroups[g].getEl())); + } + }; + }; + + /** + * + * @param {jsPlumbInstance} _jsPlumb Associated jsPlumb instance. + * @param {Object} params + * @param {Element} params.el The DOM element representing the Group. + * @param {String} [params.id] Optional ID for the Group. A UUID will be assigned as the Group's ID if you do not provide one. + * @param {Boolean} [params.constrain=false] If true, child elements will not be able to be dragged outside of the Group container. + * @param {Boolean} [params.revert=true] By default, child elements revert to the container if dragged outside. You can change this by setting `revert:false`. This behaviour is also overridden if you set `orphan` or `prune`. + * @param {Boolean} [params.orphan=false] If true, child elements dropped outside of the Group container will be removed from the Group (but not from the DOM). + * @param {Boolean} [params.prune=false] If true, child elements dropped outside of the Group container will be removed from the Group and also from the DOM. + * @param {Boolean} [params.dropOverride=false] If true, a child element that has been dropped onto some other Group will not be subject to the controls imposed by `prune`, `revert` or `orphan`. + * @constructor + */ + var Group = function(_jsPlumb, params) { + var self = this; + var el = params.el; + this.getEl = function() { return el; }; + this.id = params.id || _ju.uuid(); + el._isJsPlumbGroup = true; + + var getDragArea = this.getDragArea = function() { + var da = _jsPlumb.getSelector(el, GROUP_CONTAINER_SELECTOR); + return da && da.length > 0 ? da[0] : el; + }; + + var ghost = params.ghost === true; + var constrain = ghost || (params.constrain === true); + var revert = params.revert !== false; + var orphan = params.orphan === true; + var prune = params.prune === true; + var dropOverride = params.dropOverride === true; + var proxied = params.proxied !== false; + var elements = []; + this.connections = { source:[], target:[], internal:[] }; + + // this function, and getEndpoint below, are stubs for a future setup in which we can choose endpoint + // and anchor based upon the connection and the index (source/target) of the endpoint to be proxied. + this.getAnchor = function(conn, endpointIndex) { + return params.anchor || "Continuous"; + }; + + this.getEndpoint = function(conn, endpointIndex) { + return params.endpoint || [ "Dot", { radius:10 }]; + }; + + this.collapsed = false; + if (params.draggable !== false) { + var opts = { + stop:function(params) { + _jsPlumb.fire(EVT_GROUP_DRAG_STOP, jsPlumb.extend(params, {group:self})); + }, + scope:GROUP_DRAG_SCOPE + }; + if (params.dragOptions) { + root.jsPlumb.extend(opts, params.dragOptions); + } + _jsPlumb.draggable(params.el, opts); + } + if (params.droppable !== false) { + _jsPlumb.droppable(params.el, { + drop:function(p) { + var el = p.drag.el; + if (el._isJsPlumbGroup) { + return; + } + var currentGroup = el._jsPlumbGroup; + if (currentGroup !== self) { + if (currentGroup != null) { + if (currentGroup.overrideDrop(el, self)) { + return; + } + } + _jsPlumb.getGroupManager().addToGroup(self, el, false); + } + + } + }); + } + var _each = function(_el, fn) { + var els = _el.nodeType == null ? _el : [ _el ]; + for (var i = 0; i < els.length; i++) { + fn(els[i]); + } + }; + + this.overrideDrop = function(_el, targetGroup) { + return dropOverride && (revert || prune || orphan); + }; + + this.add = function(_el, doNotFireEvent/*, sourceGroup*/) { + var dragArea = getDragArea(); + _each(_el, function(__el) { + + if (__el._jsPlumbGroup != null) { + if (__el._jsPlumbGroup === self) { + return; + } else { + __el._jsPlumbGroup.remove(__el, true, doNotFireEvent, false); + } + } + + __el._jsPlumbGroup = self; + elements.push(__el); + // test if draggable and add handlers if so. + if (_jsPlumb.isAlreadyDraggable(__el)) { + _bindDragHandlers(__el); + } + + if (__el.parentNode !== dragArea) { + dragArea.appendChild(__el); + } + + // if (!doNotFireEvent) { + // var p = {group: self, el: __el}; + // if (sourceGroup) { + // p.sourceGroup = sourceGroup; + // } + // //_jsPlumb.fire(EVT_CHILD_ADDED, p); + // } + }); + + _jsPlumb.getGroupManager().updateConnectionsForGroup(self); + }; + + this.remove = function(el, manipulateDOM, doNotFireEvent, doNotUpdateConnections, targetGroup) { + + _each(el, function(__el) { + if (__el._jsPlumbGroup === self) { + delete __el._jsPlumbGroup; + _ju.removeWithFunction(elements, function (e) { + return e === __el; + }); + + if (manipulateDOM) { + try { + self.getDragArea().removeChild(__el); + } catch (e) { + jsPlumbUtil.log("Could not remove element from Group " + e); + } + } + _unbindDragHandlers(__el); + if (!doNotFireEvent) { + var p = {group: self, el: __el}; + if (targetGroup) { + p.targetGroup = targetGroup; + } + _jsPlumb.fire(EVT_CHILD_REMOVED, p); + } + } + }); + if (!doNotUpdateConnections) { + _jsPlumb.getGroupManager().updateConnectionsForGroup(self); + } + }; + this.removeAll = function(manipulateDOM, doNotFireEvent) { + for (var i = 0, l = elements.length; i < l; i++) { + var el = elements[0]; + self.remove(el, manipulateDOM, doNotFireEvent, true); + _jsPlumb.remove(el, true); + } + elements.length = 0; + _jsPlumb.getGroupManager().updateConnectionsForGroup(self); + }; + this.orphanAll = function() { + var orphanedPositions = {}; + for (var i = 0; i < elements.length; i++) { + var newPosition = _orphan(elements[i]); + orphanedPositions[newPosition[0]] = newPosition[1]; + } + elements.length = 0; + + return orphanedPositions; + }; + this.getMembers = function() { return elements; }; + + el[GROUP] = this; + + _jsPlumb.bind(ELEMENT_DRAGGABLE_EVENT, function(dragParams) { + // if its for the current group, + if (dragParams.el._jsPlumbGroup === this) { + _bindDragHandlers(dragParams.el); + } + }.bind(this)); + + function _findParent(_el) { + return _el.offsetParent; + } + + function _isInsideParent(_el, pos) { + var p = _findParent(_el), + s = _jsPlumb.getSize(p), + ss = _jsPlumb.getSize(_el), + leftEdge = pos[0], + rightEdge = leftEdge + ss[0], + topEdge = pos[1], + bottomEdge = topEdge + ss[1]; + + return rightEdge > 0 && leftEdge < s[0] && bottomEdge > 0 && topEdge < s[1]; + } + + // + // orphaning an element means taking it out of the group and adding it to the main jsplumb container. + // we return the new calculated position from this method and the element's id. + // + function _orphan(_el) { + var id = _jsPlumb.getId(_el); + var pos = _jsPlumb.getOffset(_el); + _el.parentNode.removeChild(_el); + _jsPlumb.getContainer().appendChild(_el); + _jsPlumb.setPosition(_el, pos); + _unbindDragHandlers(_el); + _jsPlumb.dragManager.clearParent(_el, id); + return [id, pos]; + } + + // + // remove an element from the group, then either prune it from the jsplumb instance, or just orphan it. + // + function _pruneOrOrphan(p) { + + var out = []; + + function _one(el, left, top) { + var orphanedPosition = null; + if (!_isInsideParent(el, [left, top])) { + var group = el._jsPlumbGroup; + if (prune) { + _jsPlumb.remove(el); + } else { + orphanedPosition = _orphan(el); + } + + group.remove(el); + } + + return orphanedPosition; + } + + for (var i = 0; i < p.selection.length; i++) { + out.push(_one(p.selection[i][0], p.selection[i][1].left, p.selection[i][1].top)); + } + + return out.length === 1 ? out[0] : out; + + } + + // + // redraws the element + // + function _revalidate(_el) { + var id = _jsPlumb.getId(_el); + _jsPlumb.revalidate(_el); + _jsPlumb.dragManager.revalidateParent(_el, id); + } + + // + // unbind the group specific drag/revert handlers. + // + function _unbindDragHandlers(_el) { + if (!_el._katavorioDrag) { + return; + } + if (prune || orphan) { + _el._katavorioDrag.off(STOP, _pruneOrOrphan); + } + if (!prune && !orphan && revert) { + _el._katavorioDrag.off(REVERT, _revalidate); + _el._katavorioDrag.setRevert(null); + } + } + + function _bindDragHandlers(_el) { + if (!_el._katavorioDrag) { + return; + } + if (prune || orphan) { + _el._katavorioDrag.on(STOP, _pruneOrOrphan); + } + + if (constrain) { + _el._katavorioDrag.setConstrain(true); + } + + if (ghost) { + _el._katavorioDrag.setUseGhostProxy(true); + } + + if (!prune && !orphan && revert) { + _el._katavorioDrag.on(REVERT, _revalidate); + _el._katavorioDrag.setRevert(function(__el, pos) { + return !_isInsideParent(__el, pos); + }); + } + } + + this.shouldProxy = function() { + return proxied; + }; + + _jsPlumb.getGroupManager().addGroup(this); + }; + + /** + * Adds a group to the jsPlumb instance. + * @method addGroup + * @param {Object} params + * @return {Group} The newly created Group. + */ + _jpi.prototype.addGroup = function(params) { + var j = this; + j._groups = j._groups || {}; + if (j._groups[params.id] != null) { + throw new TypeError("cannot create Group [" + params.id + "]; a Group with that ID exists"); + } + if (params.el[GROUP] != null) { + throw new TypeError("cannot create Group [" + params.id + "]; the given element is already a Group"); + } + var group = new Group(j, params); + j._groups[group.id] = group; + if (params.collapsed) { + this.collapseGroup(group); + } + return group; + }; + + /** + * Add an element to a group. + * @method addToGroup + * @param {String} group Group, or ID of the group, to add the element to. + * @param {Element} el Element to add to the group. + */ + _jpi.prototype.addToGroup = function(group, el, doNotFireEvent) { + + var _one = function(_el) { + var id = this.getId(_el); + this.manage(id, _el); + this.getGroupManager().addToGroup(group, _el, doNotFireEvent); + }.bind(this); + + if (Array.isArray(el)) { + for (var i = 0; i < el.length; i++) { + _one(el[i]); + } + } else { + _one(el); + } + }; + + /** + * Remove an element from a group. + * @method removeFromGroup + * @param {String} group Group, or ID of the group, to remove the element from. + * @param {Element} el Element to add to the group. + */ + _jpi.prototype.removeFromGroup = function(group, el, doNotFireEvent) { + this.getGroupManager().removeFromGroup(group, el, doNotFireEvent); + }; + + /** + * Remove a group, and optionally remove its members from the jsPlumb instance. + * @method removeGroup + * @param {String|Group} group Group to delete, or ID of Group to delete. + * @param {Boolean} [deleteMembers=false] If true, group members will be removed along with the group. Otherwise they will + * just be 'orphaned' (returned to the main container). + * @returns {Map[String, Position}} When deleteMembers is false, this method returns a map of {id->position} + */ + _jpi.prototype.removeGroup = function(group, deleteMembers, manipulateDOM, doNotFireEvent) { + return this.getGroupManager().removeGroup(group, deleteMembers, manipulateDOM, doNotFireEvent); + }; + + /** + * Remove all groups, and optionally remove their members from the jsPlumb instance. + * @method removeAllGroup + * @param {Boolean} [deleteMembers=false] If true, group members will be removed along with the groups. Otherwise they will + * just be 'orphaned' (returned to the main container). + */ + _jpi.prototype.removeAllGroups = function(deleteMembers, manipulateDOM, doNotFireEvent) { + this.getGroupManager().removeAllGroups(deleteMembers, manipulateDOM, doNotFireEvent); + }; + + /** + * Get a Group + * @method getGroup + * @param {String} groupId ID of the group to get + * @return {Group} Group with the given ID, null if not found. + */ + _jpi.prototype.getGroup = function(groupId) { + return this.getGroupManager().getGroup(groupId); + }; + + /** + * Gets all the Groups managed by the jsPlumb instance. + * @returns {Group[]} List of Groups. Empty if none. + */ + _jpi.prototype.getGroups = function() { + return this.getGroupManager().getGroups(); + }; + + /** + * Expands a group element. jsPlumb doesn't do "everything" for you here, because what it means to expand a Group + * will vary from application to application. jsPlumb does these things: + * + * - Hides any connections that are internal to the group (connections between members, and connections from member of + * the group to the group itself) + * - Proxies all connections for which the source or target is a member of the group. + * - Hides the proxied connections. + * - Adds the jtk-group-expanded class to the group's element + * - Removes the jtk-group-collapsed class from the group's element. + * + * @method expandGroup + * @param {String|Group} group Group to expand, or ID of Group to expand. + */ + _jpi.prototype.expandGroup = function(group) { + this.getGroupManager().expandGroup(group); + }; + + /** + * Collapses a group element. jsPlumb doesn't do "everything" for you here, because what it means to collapse a Group + * will vary from application to application. jsPlumb does these things: + * + * - Shows any connections that are internal to the group (connections between members, and connections from member of + * the group to the group itself) + * - Removes proxies for all connections for which the source or target is a member of the group. + * - Shows the previously proxied connections. + * - Adds the jtk-group-collapsed class to the group's element + * - Removes the jtk-group-expanded class from the group's element. + * + * @method expandGroup + * @param {String|Group} group Group to expand, or ID of Group to expand. + */ + _jpi.prototype.collapseGroup = function(groupId) { + this.getGroupManager().collapseGroup(groupId); + }; + + + _jpi.prototype.repaintGroup = function(group) { + this.getGroupManager().repaintGroup(group); + }; + + /** + * Collapses or expands a group element depending on its current state. See notes in the collapseGroup and expandGroup method. + * + * @method toggleGroup + * @param {String|Group} group Group to expand/collapse, or ID of Group to expand/collapse. + */ + _jpi.prototype.toggleGroup = function(group) { + group = this.getGroupManager().getGroup(group); + if (group != null) { + this.getGroupManager()[group.collapsed ? "expandGroup" : "collapseGroup"](group); + } + }; + + // + // lazy init a group manager for the given jsplumb instance. + // + _jpi.prototype.getGroupManager = function() { + var mgr = this[GROUP_MANAGER]; + if (mgr == null) { + mgr = this[GROUP_MANAGER] = new GroupManager(this); + } + return mgr; + }; + + _jpi.prototype.removeGroupManager = function() { + delete this[GROUP_MANAGER]; + }; + + /** + * Gets the Group that the given element belongs to, null if none. + * @method getGroupFor + * @param {String|Element} el Element, or element ID. + * @returns {Group} A Group, if found, or null. + */ + _jpi.prototype.getGroupFor = function(el) { + el = this.getElement(el); + if (el) { + return el[GROUP]; + } + }; + +}).call(typeof window !== 'undefined' ? window : this); + + +/* + * This file contains the 'flowchart' connectors, consisting of vertical and horizontal line segments. + * + * Copyright (c) 2010 - 2018 jsPlumb (hello@jsplumbtoolkit.com) + * + * https://jsplumbtoolkit.com + * https://github.com/jsplumb/jsplumb + * + * Dual licensed under the MIT and GPL2 licenses. + */ +; +(function () { + + "use strict"; + var root = this, _jp = root.jsPlumb, _ju = root.jsPlumbUtil; + var STRAIGHT = "Straight"; + var ARC = "Arc"; + + var Flowchart = function (params) { + this.type = "Flowchart"; + params = params || {}; + params.stub = params.stub == null ? 30 : params.stub; + var segments, + _super = _jp.Connectors.AbstractConnector.apply(this, arguments), + midpoint = params.midpoint == null ? 0.5 : params.midpoint, + alwaysRespectStubs = params.alwaysRespectStubs === true, + lastx = null, lasty = null, lastOrientation, + cornerRadius = params.cornerRadius != null ? params.cornerRadius : 0, + + // TODO now common between this and AbstractBezierEditor; refactor into superclass? + loopbackRadius = params.loopbackRadius || 25, + isLoopbackCurrently = false, + + sgn = function (n) { + return n < 0 ? -1 : n === 0 ? 0 : 1; + }, + segmentDirections = function(segment) { + return [ + sgn( segment[2] - segment[0] ), + sgn( segment[3] - segment[1] ) + ]; + }, + /** + * helper method to add a segment. + */ + addSegment = function (segments, x, y, paintInfo) { + if (lastx === x && lasty === y) { + return; + } + var lx = lastx == null ? paintInfo.sx : lastx, + ly = lasty == null ? paintInfo.sy : lasty, + o = lx === x ? "v" : "h"; + + lastx = x; + lasty = y; + segments.push([ lx, ly, x, y, o ]); + }, + segLength = function (s) { + return Math.sqrt(Math.pow(s[0] - s[2], 2) + Math.pow(s[1] - s[3], 2)); + }, + _cloneArray = function (a) { + var _a = []; + _a.push.apply(_a, a); + return _a; + }, + writeSegments = function (conn, segments, paintInfo) { + var current = null, next, currentDirection, nextDirection; + for (var i = 0; i < segments.length - 1; i++) { + + current = current || _cloneArray(segments[i]); + next = _cloneArray(segments[i + 1]); + + currentDirection = segmentDirections(current); + nextDirection = segmentDirections(next); + + if (cornerRadius > 0 && current[4] !== next[4]) { + + var minSegLength = Math.min(segLength(current), segLength(next)); + var radiusToUse = Math.min(cornerRadius, minSegLength / 2); + + current[2] -= currentDirection[0] * radiusToUse; + current[3] -= currentDirection[1] * radiusToUse; + next[0] += nextDirection[0] * radiusToUse; + next[1] += nextDirection[1] * radiusToUse; + + var ac = (currentDirection[1] === nextDirection[0] && nextDirection[0] === 1) || + ((currentDirection[1] === nextDirection[0] && nextDirection[0] === 0) && currentDirection[0] !== nextDirection[1]) || + (currentDirection[1] === nextDirection[0] && nextDirection[0] === -1), + sgny = next[1] > current[3] ? 1 : -1, + sgnx = next[0] > current[2] ? 1 : -1, + sgnEqual = sgny === sgnx, + cx = (sgnEqual && ac || (!sgnEqual && !ac)) ? next[0] : current[2], + cy = (sgnEqual && ac || (!sgnEqual && !ac)) ? current[3] : next[1]; + + _super.addSegment(conn, STRAIGHT, { + x1: current[0], y1: current[1], x2: current[2], y2: current[3] + }); + + _super.addSegment(conn, ARC, { + r: radiusToUse, + x1: current[2], + y1: current[3], + x2: next[0], + y2: next[1], + cx: cx, + cy: cy, + ac: ac + }); + } + else { + // dx + dy are used to adjust for line width. + var dx = (current[2] === current[0]) ? 0 : (current[2] > current[0]) ? (paintInfo.lw / 2) : -(paintInfo.lw / 2), + dy = (current[3] === current[1]) ? 0 : (current[3] > current[1]) ? (paintInfo.lw / 2) : -(paintInfo.lw / 2); + + _super.addSegment(conn, STRAIGHT, { + x1: current[0] - dx, y1: current[1] - dy, x2: current[2] + dx, y2: current[3] + dy + }); + } + current = next; + } + if (next != null) { + // last segment + _super.addSegment(conn, STRAIGHT, { + x1: next[0], y1: next[1], x2: next[2], y2: next[3] + }); + } + }; + + this._compute = function (paintInfo, params) { + + segments = []; + lastx = null; + lasty = null; + lastOrientation = null; + + var commonStubCalculator = function () { + return [paintInfo.startStubX, paintInfo.startStubY, paintInfo.endStubX, paintInfo.endStubY]; + }, + stubCalculators = { + perpendicular: commonStubCalculator, + orthogonal: commonStubCalculator, + opposite: function (axis) { + var pi = paintInfo, + idx = axis === "x" ? 0 : 1, + areInProximity = { + "x": function () { + return ( (pi.so[idx] === 1 && ( + ( (pi.startStubX > pi.endStubX) && (pi.tx > pi.startStubX) ) || + ( (pi.sx > pi.endStubX) && (pi.tx > pi.sx))))) || + + ( (pi.so[idx] === -1 && ( + ( (pi.startStubX < pi.endStubX) && (pi.tx < pi.startStubX) ) || + ( (pi.sx < pi.endStubX) && (pi.tx < pi.sx))))); + }, + "y": function () { + return ( (pi.so[idx] === 1 && ( + ( (pi.startStubY > pi.endStubY) && (pi.ty > pi.startStubY) ) || + ( (pi.sy > pi.endStubY) && (pi.ty > pi.sy))))) || + + ( (pi.so[idx] === -1 && ( + ( (pi.startStubY < pi.endStubY) && (pi.ty < pi.startStubY) ) || + ( (pi.sy < pi.endStubY) && (pi.ty < pi.sy))))); + } + }; + + if (!alwaysRespectStubs && areInProximity[axis]()) { + return { + "x": [(paintInfo.sx + paintInfo.tx) / 2, paintInfo.startStubY, (paintInfo.sx + paintInfo.tx) / 2, paintInfo.endStubY], + "y": [paintInfo.startStubX, (paintInfo.sy + paintInfo.ty) / 2, paintInfo.endStubX, (paintInfo.sy + paintInfo.ty) / 2] + }[axis]; + } + else { + return [paintInfo.startStubX, paintInfo.startStubY, paintInfo.endStubX, paintInfo.endStubY]; + } + } + }; + + // calculate Stubs. + var stubs = stubCalculators[paintInfo.anchorOrientation](paintInfo.sourceAxis), + idx = paintInfo.sourceAxis === "x" ? 0 : 1, + oidx = paintInfo.sourceAxis === "x" ? 1 : 0, + ss = stubs[idx], + oss = stubs[oidx], + es = stubs[idx + 2], + oes = stubs[oidx + 2]; + + // add the start stub segment. use stubs for loopback as it will look better, with the loop spaced + // away from the element. + addSegment(segments, stubs[0], stubs[1], paintInfo); + + // if its a loopback and we should treat it differently. + // if (false && params.sourcePos[0] === params.targetPos[0] && params.sourcePos[1] === params.targetPos[1]) { + // + // // we use loopbackRadius here, as statemachine connectors do. + // // so we go radius to the left from stubs[0], then upwards by 2*radius, to the right by 2*radius, + // // down by 2*radius, left by radius. + // addSegment(segments, stubs[0] - loopbackRadius, stubs[1], paintInfo); + // addSegment(segments, stubs[0] - loopbackRadius, stubs[1] - (2 * loopbackRadius), paintInfo); + // addSegment(segments, stubs[0] + loopbackRadius, stubs[1] - (2 * loopbackRadius), paintInfo); + // addSegment(segments, stubs[0] + loopbackRadius, stubs[1], paintInfo); + // addSegment(segments, stubs[0], stubs[1], paintInfo); + // + // } + // else { + + + var midx = paintInfo.startStubX + ((paintInfo.endStubX - paintInfo.startStubX) * midpoint), + midy = paintInfo.startStubY + ((paintInfo.endStubY - paintInfo.startStubY) * midpoint); + + var orientations = {x: [0, 1], y: [1, 0]}, + lineCalculators = { + perpendicular: function (axis) { + var pi = paintInfo, + sis = { + x: [ + [[1, 2, 3, 4], null, [2, 1, 4, 3]], + null, + [[4, 3, 2, 1], null, [3, 4, 1, 2]] + ], + y: [ + [[3, 2, 1, 4], null, [2, 3, 4, 1]], + null, + [[4, 1, 2, 3], null, [1, 4, 3, 2]] + ] + }, + stubs = { + x: [[pi.startStubX, pi.endStubX], null, [pi.endStubX, pi.startStubX]], + y: [[pi.startStubY, pi.endStubY], null, [pi.endStubY, pi.startStubY]] + }, + midLines = { + x: [[midx, pi.startStubY], [midx, pi.endStubY]], + y: [[pi.startStubX, midy], [pi.endStubX, midy]] + }, + linesToEnd = { + x: [[pi.endStubX, pi.startStubY]], + y: [[pi.startStubX, pi.endStubY]] + }, + startToEnd = { + x: [[pi.startStubX, pi.endStubY], [pi.endStubX, pi.endStubY]], + y: [[pi.endStubX, pi.startStubY], [pi.endStubX, pi.endStubY]] + }, + startToMidToEnd = { + x: [[pi.startStubX, midy], [pi.endStubX, midy], [pi.endStubX, pi.endStubY]], + y: [[midx, pi.startStubY], [midx, pi.endStubY], [pi.endStubX, pi.endStubY]] + }, + otherStubs = { + x: [pi.startStubY, pi.endStubY], + y: [pi.startStubX, pi.endStubX] + }, + soIdx = orientations[axis][0], toIdx = orientations[axis][1], + _so = pi.so[soIdx] + 1, + _to = pi.to[toIdx] + 1, + otherFlipped = (pi.to[toIdx] === -1 && (otherStubs[axis][1] < otherStubs[axis][0])) || (pi.to[toIdx] === 1 && (otherStubs[axis][1] > otherStubs[axis][0])), + stub1 = stubs[axis][_so][0], + stub2 = stubs[axis][_so][1], + segmentIndexes = sis[axis][_so][_to]; + + if (pi.segment === segmentIndexes[3] || (pi.segment === segmentIndexes[2] && otherFlipped)) { + return midLines[axis]; + } + else if (pi.segment === segmentIndexes[2] && stub2 < stub1) { + return linesToEnd[axis]; + } + else if ((pi.segment === segmentIndexes[2] && stub2 >= stub1) || (pi.segment === segmentIndexes[1] && !otherFlipped)) { + return startToMidToEnd[axis]; + } + else if (pi.segment === segmentIndexes[0] || (pi.segment === segmentIndexes[1] && otherFlipped)) { + return startToEnd[axis]; + } + }, + orthogonal: function (axis, startStub, otherStartStub, endStub, otherEndStub) { + var pi = paintInfo, + extent = { + "x": pi.so[0] === -1 ? Math.min(startStub, endStub) : Math.max(startStub, endStub), + "y": pi.so[1] === -1 ? Math.min(startStub, endStub) : Math.max(startStub, endStub) + }[axis]; + + return { + "x": [ + [extent, otherStartStub], + [extent, otherEndStub], + [endStub, otherEndStub] + ], + "y": [ + [otherStartStub, extent], + [otherEndStub, extent], + [otherEndStub, endStub] + ] + }[axis]; + }, + opposite: function (axis, ss, oss, es) { + var pi = paintInfo, + otherAxis = {"x": "y", "y": "x"}[axis], + dim = {"x": "height", "y": "width"}[axis], + comparator = pi["is" + axis.toUpperCase() + "GreaterThanStubTimes2"]; + + if (params.sourceEndpoint.elementId === params.targetEndpoint.elementId) { + var _val = oss + ((1 - params.sourceEndpoint.anchor[otherAxis]) * params.sourceInfo[dim]) + _super.maxStub; + return { + "x": [ + [ss, _val], + [es, _val] + ], + "y": [ + [_val, ss], + [_val, es] + ] + }[axis]; + + } + else if (!comparator || (pi.so[idx] === 1 && ss > es) || (pi.so[idx] === -1 && ss < es)) { + return { + "x": [ + [ss, midy], + [es, midy] + ], + "y": [ + [midx, ss], + [midx, es] + ] + }[axis]; + } + else if ((pi.so[idx] === 1 && ss < es) || (pi.so[idx] === -1 && ss > es)) { + return { + "x": [ + [midx, pi.sy], + [midx, pi.ty] + ], + "y": [ + [pi.sx, midy], + [pi.tx, midy] + ] + }[axis]; + } + } + }; + + // compute the rest of the line + var p = lineCalculators[paintInfo.anchorOrientation](paintInfo.sourceAxis, ss, oss, es, oes); + if (p) { + for (var i = 0; i < p.length; i++) { + addSegment(segments, p[i][0], p[i][1], paintInfo); + } + } + + // line to end stub + addSegment(segments, stubs[2], stubs[3], paintInfo); + + //} + + // end stub to end (common) + addSegment(segments, paintInfo.tx, paintInfo.ty, paintInfo); + + + + // write out the segments. + writeSegments(this, segments, paintInfo); + + }; + }; + + _jp.Connectors.Flowchart = Flowchart; + _ju.extend(_jp.Connectors.Flowchart, _jp.Connectors.AbstractConnector); + +}).call(typeof window !== 'undefined' ? window : this); +/* + * This file contains the code for the Bezier connector type. + * + * Copyright (c) 2010 - 2018 jsPlumb (hello@jsplumbtoolkit.com) + * + * https://jsplumbtoolkit.com + * https://github.com/jsplumb/jsplumb + * + * Dual licensed under the MIT and GPL2 licenses. + */ +; +(function () { + + "use strict"; + var root = this, _jp = root.jsPlumb, _ju = root.jsPlumbUtil; + + _jp.Connectors.AbstractBezierConnector = function(params) { + params = params || {}; + var showLoopback = params.showLoopback !== false, + curviness = params.curviness || 10, + margin = params.margin || 5, + proximityLimit = params.proximityLimit || 80, + clockwise = params.orientation && params.orientation === "clockwise", + loopbackRadius = params.loopbackRadius || 25, + isLoopbackCurrently = false, + _super; + + this._compute = function (paintInfo, p) { + + var sp = p.sourcePos, + tp = p.targetPos, + _w = Math.abs(sp[0] - tp[0]), + _h = Math.abs(sp[1] - tp[1]); + + if (!showLoopback || (p.sourceEndpoint.elementId !== p.targetEndpoint.elementId)) { + isLoopbackCurrently = false; + this._computeBezier(paintInfo, p, sp, tp, _w, _h); + } else { + isLoopbackCurrently = true; + // a loopback connector. draw an arc from one anchor to the other. + var x1 = p.sourcePos[0], y1 = p.sourcePos[1] - margin, + cx = x1, cy = y1 - loopbackRadius, + // canvas sizing stuff, to ensure the whole painted area is visible. + _x = cx - loopbackRadius, + _y = cy - loopbackRadius; + + _w = 2 * loopbackRadius; + _h = 2 * loopbackRadius; + + paintInfo.points[0] = _x; + paintInfo.points[1] = _y; + paintInfo.points[2] = _w; + paintInfo.points[3] = _h; + + // ADD AN ARC SEGMENT. + _super.addSegment(this, "Arc", { + loopback: true, + x1: (x1 - _x) + 4, + y1: y1 - _y, + startAngle: 0, + endAngle: 2 * Math.PI, + r: loopbackRadius, + ac: !clockwise, + x2: (x1 - _x) - 4, + y2: y1 - _y, + cx: cx - _x, + cy: cy - _y + }); + } + }; + + _super = _jp.Connectors.AbstractConnector.apply(this, arguments); + return _super; + }; + _ju.extend(_jp.Connectors.AbstractBezierConnector, _jp.Connectors.AbstractConnector); + + var Bezier = function (params) { + params = params || {}; + this.type = "Bezier"; + + var _super = _jp.Connectors.AbstractBezierConnector.apply(this, arguments), + majorAnchor = params.curviness || 150, + minorAnchor = 10; + + this.getCurviness = function () { + return majorAnchor; + }; + + this._findControlPoint = function (point, sourceAnchorPosition, targetAnchorPosition, sourceEndpoint, targetEndpoint, soo, too) { + // determine if the two anchors are perpendicular to each other in their orientation. we swap the control + // points around if so (code could be tightened up) + var perpendicular = soo[0] !== too[0] || soo[1] === too[1], + p = []; + + if (!perpendicular) { + if (soo[0] === 0) { + p.push(sourceAnchorPosition[0] < targetAnchorPosition[0] ? point[0] + minorAnchor : point[0] - minorAnchor); + } + else { + p.push(point[0] - (majorAnchor * soo[0])); + } + + if (soo[1] === 0) { + p.push(sourceAnchorPosition[1] < targetAnchorPosition[1] ? point[1] + minorAnchor : point[1] - minorAnchor); + } + else { + p.push(point[1] + (majorAnchor * too[1])); + } + } + else { + if (too[0] === 0) { + p.push(targetAnchorPosition[0] < sourceAnchorPosition[0] ? point[0] + minorAnchor : point[0] - minorAnchor); + } + else { + p.push(point[0] + (majorAnchor * too[0])); + } + + if (too[1] === 0) { + p.push(targetAnchorPosition[1] < sourceAnchorPosition[1] ? point[1] + minorAnchor : point[1] - minorAnchor); + } + else { + p.push(point[1] + (majorAnchor * soo[1])); + } + } + + return p; + }; + + this._computeBezier = function (paintInfo, p, sp, tp, _w, _h) { + + var _CP, _CP2, + _sx = sp[0] < tp[0] ? _w : 0, + _sy = sp[1] < tp[1] ? _h : 0, + _tx = sp[0] < tp[0] ? 0 : _w, + _ty = sp[1] < tp[1] ? 0 : _h; + + _CP = this._findControlPoint([_sx, _sy], sp, tp, p.sourceEndpoint, p.targetEndpoint, paintInfo.so, paintInfo.to); + _CP2 = this._findControlPoint([_tx, _ty], tp, sp, p.targetEndpoint, p.sourceEndpoint, paintInfo.to, paintInfo.so); + + + _super.addSegment(this, "Bezier", { + x1: _sx, y1: _sy, x2: _tx, y2: _ty, + cp1x: _CP[0], cp1y: _CP[1], cp2x: _CP2[0], cp2y: _CP2[1] + }); + }; + + + }; + + _jp.Connectors.Bezier = Bezier; + _ju.extend(Bezier, _jp.Connectors.AbstractBezierConnector); + +}).call(typeof window !== 'undefined' ? window : this); +/* + * This file contains the state machine connectors, which extend AbstractBezierConnector. + * + * Copyright (c) 2010 - 2018 jsPlumb (hello@jsplumbtoolkit.com) + * + * https://jsplumbtoolkit.com + * https://github.com/jsplumb/jsplumb + * + * Dual licensed under the MIT and GPL2 licenses. + */ +; +(function () { + + "use strict"; + var root = this, _jp = root.jsPlumb, _ju = root.jsPlumbUtil; + + var _segment = function (x1, y1, x2, y2) { + if (x1 <= x2 && y2 <= y1) { + return 1; + } + else if (x1 <= x2 && y1 <= y2) { + return 2; + } + else if (x2 <= x1 && y2 >= y1) { + return 3; + } + return 4; + }, + + // the control point we will use depends on the faces to which each end of the connection is assigned, specifically whether or not the + // two faces are parallel or perpendicular. if they are parallel then the control point lies on the midpoint of the axis in which they + // are parellel and varies only in the other axis; this variation is proportional to the distance that the anchor points lie from the + // center of that face. if the two faces are perpendicular then the control point is at some distance from both the midpoints; the amount and + // direction are dependent on the orientation of the two elements. 'seg', passed in to this method, tells you which segment the target element + // lies in with respect to the source: 1 is top right, 2 is bottom right, 3 is bottom left, 4 is top left. + // + // sourcePos and targetPos are arrays of info about where on the source and target each anchor is located. their contents are: + // + // 0 - absolute x + // 1 - absolute y + // 2 - proportional x in element (0 is left edge, 1 is right edge) + // 3 - proportional y in element (0 is top edge, 1 is bottom edge) + // + _findControlPoint = function (midx, midy, segment, sourceEdge, targetEdge, dx, dy, distance, proximityLimit) { + // TODO (maybe) + // - if anchor pos is 0.5, make the control point take into account the relative position of the elements. + if (distance <= proximityLimit) { + return [midx, midy]; + } + + if (segment === 1) { + if (sourceEdge[3] <= 0 && targetEdge[3] >= 1) { + return [ midx + (sourceEdge[2] < 0.5 ? -1 * dx : dx), midy ]; + } + else if (sourceEdge[2] >= 1 && targetEdge[2] <= 0) { + return [ midx, midy + (sourceEdge[3] < 0.5 ? -1 * dy : dy) ]; + } + else { + return [ midx + (-1 * dx) , midy + (-1 * dy) ]; + } + } + else if (segment === 2) { + if (sourceEdge[3] >= 1 && targetEdge[3] <= 0) { + return [ midx + (sourceEdge[2] < 0.5 ? -1 * dx : dx), midy ]; + } + else if (sourceEdge[2] >= 1 && targetEdge[2] <= 0) { + return [ midx, midy + (sourceEdge[3] < 0.5 ? -1 * dy : dy) ]; + } + else { + return [ midx + dx, midy + (-1 * dy) ]; + } + } + else if (segment === 3) { + if (sourceEdge[3] >= 1 && targetEdge[3] <= 0) { + return [ midx + (sourceEdge[2] < 0.5 ? -1 * dx : dx), midy ]; + } + else if (sourceEdge[2] <= 0 && targetEdge[2] >= 1) { + return [ midx, midy + (sourceEdge[3] < 0.5 ? -1 * dy : dy) ]; + } + else { + return [ midx + (-1 * dx) , midy + (-1 * dy) ]; + } + } + else if (segment === 4) { + if (sourceEdge[3] <= 0 && targetEdge[3] >= 1) { + return [ midx + (sourceEdge[2] < 0.5 ? -1 * dx : dx), midy ]; + } + else if (sourceEdge[2] <= 0 && targetEdge[2] >= 1) { + return [ midx, midy + (sourceEdge[3] < 0.5 ? -1 * dy : dy) ]; + } + else { + return [ midx + dx , midy + (-1 * dy) ]; + } + } + + }; + + var StateMachine = function (params) { + params = params || {}; + this.type = "StateMachine"; + + var _super = _jp.Connectors.AbstractBezierConnector.apply(this, arguments), + curviness = params.curviness || 10, + margin = params.margin || 5, + proximityLimit = params.proximityLimit || 80, + clockwise = params.orientation && params.orientation === "clockwise", + _controlPoint; + + this._computeBezier = function(paintInfo, params, sp, tp, w, h) { + var _sx = params.sourcePos[0] < params.targetPos[0] ? 0 : w, + _sy = params.sourcePos[1] < params.targetPos[1] ? 0 : h, + _tx = params.sourcePos[0] < params.targetPos[0] ? w : 0, + _ty = params.sourcePos[1] < params.targetPos[1] ? h : 0; + + // now adjust for the margin + if (params.sourcePos[2] === 0) { + _sx -= margin; + } + if (params.sourcePos[2] === 1) { + _sx += margin; + } + if (params.sourcePos[3] === 0) { + _sy -= margin; + } + if (params.sourcePos[3] === 1) { + _sy += margin; + } + if (params.targetPos[2] === 0) { + _tx -= margin; + } + if (params.targetPos[2] === 1) { + _tx += margin; + } + if (params.targetPos[3] === 0) { + _ty -= margin; + } + if (params.targetPos[3] === 1) { + _ty += margin; + } + + // + // these connectors are quadratic bezier curves, having a single control point. if both anchors + // are located at 0.5 on their respective faces, the control point is set to the midpoint and you + // get a straight line. this is also the case if the two anchors are within 'proximityLimit', since + // it seems to make good aesthetic sense to do that. outside of that, the control point is positioned + // at 'curviness' pixels away along the normal to the straight line connecting the two anchors. + // + // there may be two improvements to this. firstly, we might actually support the notion of avoiding nodes + // in the UI, or at least making a good effort at doing so. if a connection would pass underneath some node, + // for example, we might increase the distance the control point is away from the midpoint in a bid to + // steer it around that node. this will work within limits, but i think those limits would also be the likely + // limits for, once again, aesthetic good sense in the layout of a chart using these connectors. + // + // the second possible change is actually two possible changes: firstly, it is possible we should gradually + // decrease the 'curviness' as the distance between the anchors decreases; start tailing it off to 0 at some + // point (which should be configurable). secondly, we might slightly increase the 'curviness' for connectors + // with respect to how far their anchor is from the center of its respective face. this could either look cool, + // or stupid, and may indeed work only in a way that is so subtle as to have been a waste of time. + // + + var _midx = (_sx + _tx) / 2, + _midy = (_sy + _ty) / 2, + segment = _segment(_sx, _sy, _tx, _ty), + distance = Math.sqrt(Math.pow(_tx - _sx, 2) + Math.pow(_ty - _sy, 2)), + cp1x, cp2x, cp1y, cp2y; + + + // calculate the control point. this code will be where we'll put in a rudimentary element avoidance scheme; it + // will work by extending the control point to force the curve to be, um, curvier. + _controlPoint = _findControlPoint(_midx, + _midy, + segment, + params.sourcePos, + params.targetPos, + curviness, curviness, + distance, + proximityLimit); + + cp1x = _controlPoint[0]; + cp2x = _controlPoint[0]; + cp1y = _controlPoint[1]; + cp2y = _controlPoint[1]; + + _super.addSegment(this, "Bezier", { + x1: _tx, y1: _ty, x2: _sx, y2: _sy, + cp1x: cp1x, cp1y: cp1y, + cp2x: cp2x, cp2y: cp2y + }); + }; + }; + + _jp.Connectors.StateMachine = StateMachine; + _ju.extend(StateMachine, _jp.Connectors.AbstractBezierConnector); + +}).call(typeof window !== 'undefined' ? window : this); +/* + * This file contains the 'flowchart' connectors, consisting of vertical and horizontal line segments. + * + * Copyright (c) 2010 - 2018 jsPlumb (hello@jsplumbtoolkit.com) + * + * https://jsplumbtoolkit.com + * https://github.com/jsplumb/jsplumb + * + * Dual licensed under the MIT and GPL2 licenses. + */ +; +(function () { + + "use strict"; + var root = this, _jp = root.jsPlumb, _ju = root.jsPlumbUtil; + var STRAIGHT = "Straight"; + + var Straight = function (params) { + this.type = STRAIGHT; + var _super = _jp.Connectors.AbstractConnector.apply(this, arguments); + + this._compute = function (paintInfo, _) { + _super.addSegment(this, STRAIGHT, {x1: paintInfo.sx, y1: paintInfo.sy, x2: paintInfo.startStubX, y2: paintInfo.startStubY}); + _super.addSegment(this, STRAIGHT, {x1: paintInfo.startStubX, y1: paintInfo.startStubY, x2: paintInfo.endStubX, y2: paintInfo.endStubY}); + _super.addSegment(this, STRAIGHT, {x1: paintInfo.endStubX, y1: paintInfo.endStubY, x2: paintInfo.tx, y2: paintInfo.ty}); + }; + }; + + _jp.Connectors.Straight = Straight; + _ju.extend(Straight, _jp.Connectors.AbstractConnector); + +}).call(typeof window !== 'undefined' ? window : this); +/* + * This file contains the SVG renderers. + * + * Copyright (c) 2010 - 2018 jsPlumb (hello@jsplumbtoolkit.com) + * + * https://jsplumbtoolkit.com + * https://github.com/jsplumb/jsplumb + * + * Dual licensed under the MIT and GPL2 licenses. + */ +; +(function () { + +// ************************** SVG utility methods ******************************************** + + "use strict"; + var root = this, _jp = root.jsPlumb, _ju = root.jsPlumbUtil; + + var svgAttributeMap = { + "stroke-linejoin": "stroke-linejoin", + "stroke-dashoffset": "stroke-dashoffset", + "stroke-linecap": "stroke-linecap" + }, + STROKE_DASHARRAY = "stroke-dasharray", + DASHSTYLE = "dashstyle", + LINEAR_GRADIENT = "linearGradient", + RADIAL_GRADIENT = "radialGradient", + DEFS = "defs", + FILL = "fill", + STOP = "stop", + STROKE = "stroke", + STROKE_WIDTH = "stroke-width", + STYLE = "style", + NONE = "none", + JSPLUMB_GRADIENT = "jsplumb_gradient_", + LINE_WIDTH = "strokeWidth", + ns = { + svg: "http://www.w3.org/2000/svg" + }, + _attr = function (node, attributes) { + for (var i in attributes) { + node.setAttribute(i, "" + attributes[i]); + } + }, + _node = function (name, attributes) { + attributes = attributes || {}; + attributes.version = "1.1"; + attributes.xmlns = ns.svg; + return _jp.createElementNS(ns.svg, name, null, null, attributes); + }, + _pos = function (d) { + return "position:absolute;left:" + d[0] + "px;top:" + d[1] + "px"; + }, + _clearGradient = function (parent) { + var els = parent.querySelectorAll(" defs,linearGradient,radialGradient"); + for (var i = 0; i < els.length; i++) { + els[i].parentNode.removeChild(els[i]); + } + }, + _updateGradient = function (parent, node, style, dimensions, uiComponent) { + var id = JSPLUMB_GRADIENT + uiComponent._jsPlumb.instance.idstamp(); + // first clear out any existing gradient + _clearGradient(parent); + // this checks for an 'offset' property in the gradient, and in the absence of it, assumes + // we want a linear gradient. if it's there, we create a radial gradient. + // it is possible that a more explicit means of defining the gradient type would be + // better. relying on 'offset' means that we can never have a radial gradient that uses + // some default offset, for instance. + // issue 244 suggested the 'gradientUnits' attribute; without this, straight/flowchart connectors with gradients would + // not show gradients when the line was perfectly horizontal or vertical. + var g; + if (!style.gradient.offset) { + g = _node(LINEAR_GRADIENT, {id: id, gradientUnits: "userSpaceOnUse"}); + } + else { + g = _node(RADIAL_GRADIENT, { id: id }); + } + + var defs = _node(DEFS); + parent.appendChild(defs); + defs.appendChild(g); + + // the svg radial gradient seems to treat stops in the reverse + // order to how canvas does it. so we want to keep all the maths the same, but + // iterate the actual style declarations in reverse order, if the x indexes are not in order. + for (var i = 0; i < style.gradient.stops.length; i++) { + var styleToUse = uiComponent.segment === 1 || uiComponent.segment === 2 ? i : style.gradient.stops.length - 1 - i, + stopColor = style.gradient.stops[styleToUse][1], + s = _node(STOP, {"offset": Math.floor(style.gradient.stops[i][0] * 100) + "%", "stop-color": stopColor}); + + g.appendChild(s); + } + var applyGradientTo = style.stroke ? STROKE : FILL; + node.setAttribute(applyGradientTo, "url(#" + id + ")"); + }, + _applyStyles = function (parent, node, style, dimensions, uiComponent) { + + node.setAttribute(FILL, style.fill ? style.fill : NONE); + node.setAttribute(STROKE, style.stroke ? style.stroke : NONE); + + if (style.gradient) { + _updateGradient(parent, node, style, dimensions, uiComponent); + } + else { + // make sure we clear any existing gradient + _clearGradient(parent); + node.setAttribute(STYLE, ""); + } + + if (style.strokeWidth) { + node.setAttribute(STROKE_WIDTH, style.strokeWidth); + } + + // in SVG there is a stroke-dasharray attribute we can set, and its syntax looks like + // the syntax in VML but is actually kind of nasty: values are given in the pixel + // coordinate space, whereas in VML they are multiples of the width of the stroked + // line, which makes a lot more sense. for that reason, jsPlumb is supporting both + // the native svg 'stroke-dasharray' attribute, and also the 'dashstyle' concept from + // VML, which will be the preferred method. the code below this converts a dashstyle + // attribute given in terms of stroke width into a pixel representation, by using the + // stroke's lineWidth. + if (style[DASHSTYLE] && style[LINE_WIDTH] && !style[STROKE_DASHARRAY]) { + var sep = style[DASHSTYLE].indexOf(",") === -1 ? " " : ",", + parts = style[DASHSTYLE].split(sep), + styleToUse = ""; + parts.forEach(function (p) { + styleToUse += (Math.floor(p * style.strokeWidth) + sep); + }); + node.setAttribute(STROKE_DASHARRAY, styleToUse); + } + else if (style[STROKE_DASHARRAY]) { + node.setAttribute(STROKE_DASHARRAY, style[STROKE_DASHARRAY]); + } + + // extra attributes such as join type, dash offset. + for (var i in svgAttributeMap) { + if (style[i]) { + node.setAttribute(svgAttributeMap[i], style[i]); + } + } + }, + _appendAtIndex = function (svg, path, idx) { + if (svg.childNodes.length > idx) { + svg.insertBefore(path, svg.childNodes[idx]); + } + else { + svg.appendChild(path); + } + }; + + /** + utility methods for other objects to use. + */ + _ju.svg = { + node: _node, + attr: _attr, + pos: _pos + }; + + // ************************** / SVG utility methods ******************************************** + + /* + * Base class for SVG components. + */ + var SvgComponent = function (params) { + var pointerEventsSpec = params.pointerEventsSpec || "all", renderer = {}; + + _jp.jsPlumbUIComponent.apply(this, params.originalArgs); + this.canvas = null; + this.path = null; + this.svg = null; + this.bgCanvas = null; + + var clazz = params.cssClass + " " + (params.originalArgs[0].cssClass || ""), + svgParams = { + "style": "", + "width": 0, + "height": 0, + "pointer-events": pointerEventsSpec, + "position": "absolute" + }; + + this.svg = _node("svg", svgParams); + + if (params.useDivWrapper) { + this.canvas = _jp.createElement("div", { position : "absolute" }); + _ju.sizeElement(this.canvas, 0, 0, 1, 1); + this.canvas.className = clazz; + } + else { + _attr(this.svg, { "class": clazz }); + this.canvas = this.svg; + } + + params._jsPlumb.appendElement(this.canvas, params.originalArgs[0].parent); + if (params.useDivWrapper) { + this.canvas.appendChild(this.svg); + } + + var displayElements = [ this.canvas ]; + this.getDisplayElements = function () { + return displayElements; + }; + + this.appendDisplayElement = function (el) { + displayElements.push(el); + }; + + this.paint = function (style, anchor, extents) { + if (style != null) { + + var xy = [ this.x, this.y ], wh = [ this.w, this.h ], p; + if (extents != null) { + if (extents.xmin < 0) { + xy[0] += extents.xmin; + } + if (extents.ymin < 0) { + xy[1] += extents.ymin; + } + wh[0] = extents.xmax + ((extents.xmin < 0) ? -extents.xmin : 0); + wh[1] = extents.ymax + ((extents.ymin < 0) ? -extents.ymin : 0); + } + + if (params.useDivWrapper) { + _ju.sizeElement(this.canvas, xy[0], xy[1], wh[0], wh[1]); + xy[0] = 0; + xy[1] = 0; + p = _pos([ 0, 0 ]); + } + else { + p = _pos([ xy[0], xy[1] ]); + } + + renderer.paint.apply(this, arguments); + + _attr(this.svg, { + "style": p, + "width": wh[0] || 0, + "height": wh[1] || 0 + }); + } + }; + + return { + renderer: renderer + }; + }; + + _ju.extend(SvgComponent, _jp.jsPlumbUIComponent, { + cleanup: function (force) { + if (force || this.typeId == null) { + if (this.canvas) { + this.canvas._jsPlumb = null; + } + if (this.svg) { + this.svg._jsPlumb = null; + } + if (this.bgCanvas) { + this.bgCanvas._jsPlumb = null; + } + + if (this.canvas && this.canvas.parentNode) { + this.canvas.parentNode.removeChild(this.canvas); + } + if (this.bgCanvas && this.bgCanvas.parentNode) { + this.canvas.parentNode.removeChild(this.canvas); + } + + this.svg = null; + this.canvas = null; + this.path = null; + this.group = null; + } + else { + // if not a forced cleanup, just detach from DOM for now. + if (this.canvas && this.canvas.parentNode) { + this.canvas.parentNode.removeChild(this.canvas); + } + if (this.bgCanvas && this.bgCanvas.parentNode) { + this.bgCanvas.parentNode.removeChild(this.bgCanvas); + } + } + }, + reattach:function(instance) { + var c = instance.getContainer(); + if (this.canvas && this.canvas.parentNode == null) { + c.appendChild(this.canvas); + } + if (this.bgCanvas && this.bgCanvas.parentNode == null) { + c.appendChild(this.bgCanvas); + } + }, + setVisible: function (v) { + if (this.canvas) { + this.canvas.style.display = v ? "block" : "none"; + } + } + }); + + /* + * Base class for SVG connectors. + */ + _jp.ConnectorRenderers.svg = function (params) { + var self = this, + _super = SvgComponent.apply(this, [ + { + cssClass: params._jsPlumb.connectorClass, + originalArgs: arguments, + pointerEventsSpec: "none", + _jsPlumb: params._jsPlumb + } + ]); + + _super.renderer.paint = function (style, anchor, extents) { + + var segments = self.getSegments(), p = "", offset = [0, 0]; + if (extents.xmin < 0) { + offset[0] = -extents.xmin; + } + if (extents.ymin < 0) { + offset[1] = -extents.ymin; + } + + if (segments.length > 0) { + + p = self.getPathData(); + + var a = { + d: p, + transform: "translate(" + offset[0] + "," + offset[1] + ")", + "pointer-events": params["pointer-events"] || "visibleStroke" + }, + outlineStyle = null, + d = [self.x, self.y, self.w, self.h]; + + // outline style. actually means drawing an svg object underneath the main one. + if (style.outlineStroke) { + var outlineWidth = style.outlineWidth || 1, + outlineStrokeWidth = style.strokeWidth + (2 * outlineWidth); + outlineStyle = _jp.extend({}, style); + delete outlineStyle.gradient; + outlineStyle.stroke = style.outlineStroke; + outlineStyle.strokeWidth = outlineStrokeWidth; + + if (self.bgPath == null) { + self.bgPath = _node("path", a); + _jp.addClass(self.bgPath, _jp.connectorOutlineClass); + _appendAtIndex(self.svg, self.bgPath, 0); + } + else { + _attr(self.bgPath, a); + } + + _applyStyles(self.svg, self.bgPath, outlineStyle, d, self); + } + + if (self.path == null) { + self.path = _node("path", a); + _appendAtIndex(self.svg, self.path, style.outlineStroke ? 1 : 0); + } + else { + _attr(self.path, a); + } + + _applyStyles(self.svg, self.path, style, d, self); + } + }; + }; + _ju.extend(_jp.ConnectorRenderers.svg, SvgComponent); + +// ******************************* svg segment renderer ***************************************************** + + +// ******************************* /svg segments ***************************************************** + + /* + * Base class for SVG endpoints. + */ + var SvgEndpoint = _jp.SvgEndpoint = function (params) { + var _super = SvgComponent.apply(this, [ + { + cssClass: params._jsPlumb.endpointClass, + originalArgs: arguments, + pointerEventsSpec: "all", + useDivWrapper: true, + _jsPlumb: params._jsPlumb + } + ]); + + _super.renderer.paint = function (style) { + var s = _jp.extend({}, style); + if (s.outlineStroke) { + s.stroke = s.outlineStroke; + } + + if (this.node == null) { + this.node = this.makeNode(s); + this.svg.appendChild(this.node); + } + else if (this.updateNode != null) { + this.updateNode(this.node); + } + _applyStyles(this.svg, this.node, s, [ this.x, this.y, this.w, this.h ], this); + _pos(this.node, [ this.x, this.y ]); + }.bind(this); + + }; + _ju.extend(SvgEndpoint, SvgComponent); + + /* + * SVG Dot Endpoint + */ + _jp.Endpoints.svg.Dot = function () { + _jp.Endpoints.Dot.apply(this, arguments); + SvgEndpoint.apply(this, arguments); + this.makeNode = function (style) { + return _node("circle", { + "cx": this.w / 2, + "cy": this.h / 2, + "r": this.radius + }); + }; + this.updateNode = function (node) { + _attr(node, { + "cx": this.w / 2, + "cy": this.h / 2, + "r": this.radius + }); + }; + }; + _ju.extend(_jp.Endpoints.svg.Dot, [_jp.Endpoints.Dot, SvgEndpoint]); + + /* + * SVG Rectangle Endpoint + */ + _jp.Endpoints.svg.Rectangle = function () { + _jp.Endpoints.Rectangle.apply(this, arguments); + SvgEndpoint.apply(this, arguments); + this.makeNode = function (style) { + return _node("rect", { + "width": this.w, + "height": this.h + }); + }; + this.updateNode = function (node) { + _attr(node, { + "width": this.w, + "height": this.h + }); + }; + }; + _ju.extend(_jp.Endpoints.svg.Rectangle, [_jp.Endpoints.Rectangle, SvgEndpoint]); + + /* + * SVG Image Endpoint is the default image endpoint. + */ + _jp.Endpoints.svg.Image = _jp.Endpoints.Image; + /* + * Blank endpoint in svg renderer is the default Blank endpoint. + */ + _jp.Endpoints.svg.Blank = _jp.Endpoints.Blank; + /* + * Label overlay in svg renderer is the default Label overlay. + */ + _jp.Overlays.svg.Label = _jp.Overlays.Label; + /* + * Custom overlay in svg renderer is the default Custom overlay. + */ + _jp.Overlays.svg.Custom = _jp.Overlays.Custom; + + var AbstractSvgArrowOverlay = function (superclass, originalArgs) { + superclass.apply(this, originalArgs); + _jp.jsPlumbUIComponent.apply(this, originalArgs); + this.isAppendedAtTopLevel = false; + var self = this; + this.path = null; + this.paint = function (params, containerExtents) { + // only draws on connections, not endpoints. + if (params.component.svg && containerExtents) { + if (this.path == null) { + this.path = _node("path", { + "pointer-events": "all" + }); + params.component.svg.appendChild(this.path); + if (this.elementCreated) { + this.elementCreated(this.path, params.component); + } + + this.canvas = params.component.svg; // for the sake of completeness; this behaves the same as other overlays + } + var clazz = originalArgs && (originalArgs.length === 1) ? (originalArgs[0].cssClass || "") : "", + offset = [0, 0]; + + if (containerExtents.xmin < 0) { + offset[0] = -containerExtents.xmin; + } + if (containerExtents.ymin < 0) { + offset[1] = -containerExtents.ymin; + } + + _attr(this.path, { + "d": makePath(params.d), + "class": clazz, + stroke: params.stroke ? params.stroke : null, + fill: params.fill ? params.fill : null, + transform: "translate(" + offset[0] + "," + offset[1] + ")" + }); + } + }; + var makePath = function (d) { + return (isNaN(d.cxy.x) || isNaN(d.cxy.y)) ? "" : "M" + d.hxy.x + "," + d.hxy.y + + " L" + d.tail[0].x + "," + d.tail[0].y + + " L" + d.cxy.x + "," + d.cxy.y + + " L" + d.tail[1].x + "," + d.tail[1].y + + " L" + d.hxy.x + "," + d.hxy.y; + }; + this.transfer = function(target) { + if (target.canvas && this.path && this.path.parentNode) { + this.path.parentNode.removeChild(this.path); + target.canvas.appendChild(this.path); + } + }; + }; + _ju.extend(AbstractSvgArrowOverlay, [_jp.jsPlumbUIComponent, _jp.Overlays.AbstractOverlay], { + cleanup: function (force) { + if (this.path != null) { + if (force) { + this._jsPlumb.instance.removeElement(this.path); + } + else { + if (this.path.parentNode) { + this.path.parentNode.removeChild(this.path); + } + } + } + }, + reattach:function(instance, component) { + if (this.path && component.canvas) { + component.canvas.appendChild(this.path); + } + }, + setVisible: function (v) { + if (this.path != null) { + (this.path.style.display = (v ? "block" : "none")); + } + } + }); + + _jp.Overlays.svg.Arrow = function () { + AbstractSvgArrowOverlay.apply(this, [_jp.Overlays.Arrow, arguments]); + }; + _ju.extend(_jp.Overlays.svg.Arrow, [ _jp.Overlays.Arrow, AbstractSvgArrowOverlay ]); + + _jp.Overlays.svg.PlainArrow = function () { + AbstractSvgArrowOverlay.apply(this, [_jp.Overlays.PlainArrow, arguments]); + }; + _ju.extend(_jp.Overlays.svg.PlainArrow, [ _jp.Overlays.PlainArrow, AbstractSvgArrowOverlay ]); + + _jp.Overlays.svg.Diamond = function () { + AbstractSvgArrowOverlay.apply(this, [_jp.Overlays.Diamond, arguments]); + }; + _ju.extend(_jp.Overlays.svg.Diamond, [ _jp.Overlays.Diamond, AbstractSvgArrowOverlay ]); + + // a test + _jp.Overlays.svg.GuideLines = function () { + var path = null, self = this, p1_1, p1_2; + _jp.Overlays.GuideLines.apply(this, arguments); + this.paint = function (params, containerExtents) { + if (path == null) { + path = _node("path"); + params.connector.svg.appendChild(path); + self.attachListeners(path, params.connector); + self.attachListeners(path, self); + + p1_1 = _node("path"); + params.connector.svg.appendChild(p1_1); + self.attachListeners(p1_1, params.connector); + self.attachListeners(p1_1, self); + + p1_2 = _node("path"); + params.connector.svg.appendChild(p1_2); + self.attachListeners(p1_2, params.connector); + self.attachListeners(p1_2, self); + } + + var offset = [0, 0]; + if (containerExtents.xmin < 0) { + offset[0] = -containerExtents.xmin; + } + if (containerExtents.ymin < 0) { + offset[1] = -containerExtents.ymin; + } + + _attr(path, { + "d": makePath(params.head, params.tail), + stroke: "red", + fill: null, + transform: "translate(" + offset[0] + "," + offset[1] + ")" + }); + + _attr(p1_1, { + "d": makePath(params.tailLine[0], params.tailLine[1]), + stroke: "blue", + fill: null, + transform: "translate(" + offset[0] + "," + offset[1] + ")" + }); + + _attr(p1_2, { + "d": makePath(params.headLine[0], params.headLine[1]), + stroke: "green", + fill: null, + transform: "translate(" + offset[0] + "," + offset[1] + ")" + }); + }; + + var makePath = function (d1, d2) { + return "M " + d1.x + "," + d1.y + + " L" + d2.x + "," + d2.y; + }; + }; + _ju.extend(_jp.Overlays.svg.GuideLines, _jp.Overlays.GuideLines); +}).call(typeof window !== 'undefined' ? window : this); + +/* + * This file contains code used when jsPlumb is being rendered in a DOM. + * + * Copyright (c) 2010 - 2019 jsPlumb (hello@jsplumbtoolkit.com) + * + * https://jsplumbtoolkit.com + * https://github.com/jsplumb/jsplumb + * + * Dual licensed under the MIT and GPL2 licenses. + */ +; +(function () { + + "use strict"; + + var root = this, _jp = root.jsPlumb, _ju = root.jsPlumbUtil, + _jk = root.Katavorio, _jg = root.Biltong; + + var _getEventManager = function(instance) { + var e = instance._mottle; + if (!e) { + e = instance._mottle = new root.Mottle(); + } + return e; + }; + + var _getDragManager = function (instance, category) { + + category = category || "main"; + var key = "_katavorio_" + category; + var k = instance[key], + e = instance.getEventManager(); + + if (!k) { + k = new _jk({ + bind: e.on, + unbind: e.off, + getSize: _jp.getSize, + getConstrainingRectangle:function(el) { + return [ el.parentNode.scrollWidth, el.parentNode.scrollHeight ]; + }, + getPosition: function (el, relativeToRoot) { + // if this is a nested draggable then compute the offset against its own offsetParent, otherwise + // compute against the Container's origin. see also the getUIPosition method below. + var o = instance.getOffset(el, relativeToRoot, el._katavorioDrag ? el.offsetParent : null); + return [o.left, o.top]; + }, + setPosition: function (el, xy) { + el.style.left = xy[0] + "px"; + el.style.top = xy[1] + "px"; + }, + addClass: _jp.addClass, + removeClass: _jp.removeClass, + intersects: _jg.intersects, + indexOf: function(l, i) { return l.indexOf(i); }, + scope:instance.getDefaultScope(), + css: { + noSelect: instance.dragSelectClass, + droppable: "jtk-droppable", + draggable: "jtk-draggable", + drag: "jtk-drag", + selected: "jtk-drag-selected", + active: "jtk-drag-active", + hover: "jtk-drag-hover", + ghostProxy:"jtk-ghost-proxy" + } + }); + k.setZoom(instance.getZoom()); + instance[key] = k; + instance.bind("zoom", k.setZoom); + } + return k; + }; + + var _dragStart=function(params) { + var options = params.el._jsPlumbDragOptions; + var cont = true; + if (options.canDrag) { + cont = options.canDrag(); + } + if (cont) { + this.setHoverSuspended(true); + this.select({source: params.el}).addClass(this.elementDraggingClass + " " + this.sourceElementDraggingClass, true); + this.select({target: params.el}).addClass(this.elementDraggingClass + " " + this.targetElementDraggingClass, true); + this.setConnectionBeingDragged(true); + } + return cont; + }; + var _dragMove=function(params) { + var ui = this.getUIPosition(arguments, this.getZoom()); + if (ui != null) { + var o = params.el._jsPlumbDragOptions; + this.draw(params.el, ui, null, true); + if (o._dragging) { + this.addClass(params.el, "jtk-dragged"); + } + o._dragging = true; + } + }; + var _dragStop=function(params) { + var elements = params.selection, uip; + + var _one = function (_e) { + if (_e[1] != null) { + // run the reported offset through the code that takes parent containers + // into account, to adjust if necessary (issue 554) + uip = this.getUIPosition([{ + el:_e[2].el, + pos:[_e[1].left, _e[1].top] + }]); + this.draw(_e[2].el, uip); + } + + if (_e[0]._jsPlumbDragOptions != null) { + delete _e[0]._jsPlumbDragOptions._dragging; + } + + this.removeClass(_e[0], "jtk-dragged"); + this.select({source: _e[2].el}).removeClass(this.elementDraggingClass + " " + this.sourceElementDraggingClass, true); + this.select({target: _e[2].el}).removeClass(this.elementDraggingClass + " " + this.targetElementDraggingClass, true); + this.getDragManager().dragEnded(_e[2].el); + }.bind(this); + + for (var i = 0; i < elements.length; i++) { + _one(elements[i]); + } + + this.setHoverSuspended(false); + this.setConnectionBeingDragged(false); + }; + + var _animProps = function (o, p) { + var _one = function (pName) { + if (p[pName] != null) { + if (_ju.isString(p[pName])) { + var m = p[pName].match(/-=/) ? -1 : 1, + v = p[pName].substring(2); + return o[pName] + (m * v); + } + else { + return p[pName]; + } + } + else { + return o[pName]; + } + }; + return [ _one("left"), _one("top") ]; + }; + + var _genLoc = function (prefix, e) { + if (e == null) { + return [ 0, 0 ]; + } + var ts = _touches(e), t = _getTouch(ts, 0); + return [t[prefix + "X"], t[prefix + "Y"]]; + }, + _pageLocation = _genLoc.bind(this, "page"), + _screenLocation = _genLoc.bind(this, "screen"), + _clientLocation = _genLoc.bind(this, "client"), + _getTouch = function (touches, idx) { + return touches.item ? touches.item(idx) : touches[idx]; + }, + _touches = function (e) { + return e.touches && e.touches.length > 0 ? e.touches : + e.changedTouches && e.changedTouches.length > 0 ? e.changedTouches : + e.targetTouches && e.targetTouches.length > 0 ? e.targetTouches : + [ e ]; + }; + + /** + Manages dragging for some instance of jsPlumb. + + TODO instead of this being accessed directly, it should subscribe to events on the jsPlumb instance: every method + in here is called directly by jsPlumb. But what should happen is that we have unpublished events that this listens + to. The only trick is getting one of these instantiated with every jsPlumb instance: it needs to have a hook somehow. + Basically the general idea is to pull ALL the drag code out (prototype method registrations plus this) into a + dedicated drag script), that does not necessarily need to be included. + + + */ + var DragManager = function (_currentInstance) { + var _draggables = {}, _dlist = [], _delements = {}, _elementsWithEndpoints = {}, + // elementids mapped to the draggable to which they belong. + _draggablesForElements = {}; + + /** + register some element as draggable. right now the drag init stuff is done elsewhere, and it is + possible that will continue to be the case. + */ + this.register = function (el) { + var id = _currentInstance.getId(el), + parentOffset; + + if (!_draggables[id]) { + _draggables[id] = el; + _dlist.push(el); + _delements[id] = {}; + } + + // look for child elements that have endpoints and register them against this draggable. + var _oneLevel = function (p) { + if (p) { + for (var i = 0; i < p.childNodes.length; i++) { + if (p.childNodes[i].nodeType !== 3 && p.childNodes[i].nodeType !== 8) { + var cEl = jsPlumb.getElement(p.childNodes[i]), + cid = _currentInstance.getId(p.childNodes[i], null, true); + if (cid && _elementsWithEndpoints[cid] && _elementsWithEndpoints[cid] > 0) { + if (!parentOffset) { + parentOffset = _currentInstance.getOffset(el); + } + var cOff = _currentInstance.getOffset(cEl); + _delements[id][cid] = { + id: cid, + offset: { + left: cOff.left - parentOffset.left, + top: cOff.top - parentOffset.top + } + }; + _draggablesForElements[cid] = id; + } + _oneLevel(p.childNodes[i]); + } + } + } + }; + + _oneLevel(el); + }; + + // refresh the offsets for child elements of this element. + this.updateOffsets = function (elId, childOffsetOverrides) { + if (elId != null) { + childOffsetOverrides = childOffsetOverrides || {}; + var domEl = jsPlumb.getElement(elId), + id = _currentInstance.getId(domEl), + children = _delements[id], + parentOffset; + + if (children) { + for (var i in children) { + if (children.hasOwnProperty(i)) { + var cel = jsPlumb.getElement(i), + cOff = childOffsetOverrides[i] || _currentInstance.getOffset(cel); + + // do not update if we have a value already and we'd just be writing 0,0 + if (cel.offsetParent == null && _delements[id][i] != null) { + continue; + } + + if (!parentOffset) { + parentOffset = _currentInstance.getOffset(domEl); + } + + _delements[id][i] = { + id: i, + offset: { + left: cOff.left - parentOffset.left, + top: cOff.top - parentOffset.top + } + }; + _draggablesForElements[i] = id; + } + } + } + } + }; + + /** + notification that an endpoint was added to the given el. we go up from that el's parent + node, looking for a parent that has been registered as a draggable. if we find one, we add this + el to that parent's list of elements to update on drag (if it is not there already) + */ + this.endpointAdded = function (el, id) { + + id = id || _currentInstance.getId(el); + + var b = document.body, + p = el.parentNode; + + _elementsWithEndpoints[id] = _elementsWithEndpoints[id] ? _elementsWithEndpoints[id] + 1 : 1; + + while (p != null && p !== b) { + var pid = _currentInstance.getId(p, null, true); + if (pid && _draggables[pid]) { + var pLoc = _currentInstance.getOffset(p); + + if (_delements[pid][id] == null) { + var cLoc = _currentInstance.getOffset(el); + _delements[pid][id] = { + id: id, + offset: { + left: cLoc.left - pLoc.left, + top: cLoc.top - pLoc.top + } + }; + _draggablesForElements[id] = pid; + } + break; + } + p = p.parentNode; + } + }; + + this.endpointDeleted = function (endpoint) { + if (_elementsWithEndpoints[endpoint.elementId]) { + _elementsWithEndpoints[endpoint.elementId]--; + if (_elementsWithEndpoints[endpoint.elementId] <= 0) { + for (var i in _delements) { + if (_delements.hasOwnProperty(i) && _delements[i]) { + delete _delements[i][endpoint.elementId]; + delete _draggablesForElements[endpoint.elementId]; + } + } + } + } + }; + + this.changeId = function (oldId, newId) { + _delements[newId] = _delements[oldId]; + _delements[oldId] = {}; + _draggablesForElements[newId] = _draggablesForElements[oldId]; + _draggablesForElements[oldId] = null; + }; + + this.getElementsForDraggable = function (id) { + return _delements[id]; + }; + + this.elementRemoved = function (elementId) { + var elId = _draggablesForElements[elementId]; + if (elId) { + delete _delements[elId][elementId]; + delete _draggablesForElements[elementId]; + } + }; + + this.reset = function () { + _draggables = {}; + _dlist = []; + _delements = {}; + _elementsWithEndpoints = {}; + }; + + // + // notification drag ended. We check automatically if need to update some + // ancestor's offsets. + // + this.dragEnded = function (el) { + if (el.offsetParent != null) { + var id = _currentInstance.getId(el), + ancestor = _draggablesForElements[id]; + + if (ancestor) { + this.updateOffsets(ancestor); + } + } + }; + + this.setParent = function (el, elId, p, pId, currentChildLocation) { + var current = _draggablesForElements[elId]; + if (!_delements[pId]) { + _delements[pId] = {}; + } + var pLoc = _currentInstance.getOffset(p), + cLoc = currentChildLocation || _currentInstance.getOffset(el); + + if (current && _delements[current]) { + delete _delements[current][elId]; + } + + _delements[pId][elId] = { + id:elId, + offset : { + left: cLoc.left - pLoc.left, + top: cLoc.top - pLoc.top + } + }; + _draggablesForElements[elId] = pId; + }; + + this.clearParent = function(el, elId) { + var current = _draggablesForElements[elId]; + if (current) { + delete _delements[current][elId]; + delete _draggablesForElements[elId]; + } + }; + + this.revalidateParent = function(el, elId, childOffset) { + var current = _draggablesForElements[elId]; + if (current) { + var co = {}; + co[elId] = childOffset; + this.updateOffsets(current, co); + _currentInstance.revalidate(current); + } + }; + + this.getDragAncestor = function (el) { + var de = jsPlumb.getElement(el), + id = _currentInstance.getId(de), + aid = _draggablesForElements[id]; + + if (aid) { + return jsPlumb.getElement(aid); + } + else { + return null; + } + }; + + }; + + var _setClassName = function (el, cn, classList) { + cn = _ju.fastTrim(cn); + if (typeof el.className.baseVal !== "undefined") { + el.className.baseVal = cn; + } + else { + el.className = cn; + } + + // recent (i currently have 61.0.3163.100) version of chrome do not update classList when you set the base val + // of an svg element's className. in the long run we'd like to move to just using classList anyway + try { + var cl = el.classList; + if (cl != null) { + while (cl.length > 0) { + cl.remove(cl.item(0)); + } + for (var i = 0; i < classList.length; i++) { + if (classList[i]) { + cl.add(classList[i]); + } + } + } + } + catch(e) { + // not fatal + _ju.log("JSPLUMB: cannot set class list", e); + } + }, + _getClassName = function (el) { + return (typeof el.className.baseVal === "undefined") ? el.className : el.className.baseVal; + }, + _classManip = function (el, classesToAdd, classesToRemove) { + classesToAdd = classesToAdd == null ? [] : _ju.isArray(classesToAdd) ? classesToAdd : classesToAdd.split(/\s+/); + classesToRemove = classesToRemove == null ? [] : _ju.isArray(classesToRemove) ? classesToRemove : classesToRemove.split(/\s+/); + + var className = _getClassName(el), + curClasses = className.split(/\s+/); + + var _oneSet = function (add, classes) { + for (var i = 0; i < classes.length; i++) { + if (add) { + if (curClasses.indexOf(classes[i]) === -1) { + curClasses.push(classes[i]); + } + } + else { + var idx = curClasses.indexOf(classes[i]); + if (idx !== -1) { + curClasses.splice(idx, 1); + } + } + } + }; + + _oneSet(true, classesToAdd); + _oneSet(false, classesToRemove); + + _setClassName(el, curClasses.join(" "), curClasses); + }; + + root.jsPlumb.extend(root.jsPlumbInstance.prototype, { + + headless: false, + + pageLocation: _pageLocation, + screenLocation: _screenLocation, + clientLocation: _clientLocation, + + getDragManager:function() { + if (this.dragManager == null) { + this.dragManager = new DragManager(this); + } + + return this.dragManager; + }, + + recalculateOffsets:function(elId) { + this.getDragManager().updateOffsets(elId); + }, + + createElement:function(tag, style, clazz, atts) { + return this.createElementNS(null, tag, style, clazz, atts); + }, + + createElementNS:function(ns, tag, style, clazz, atts) { + var e = ns == null ? document.createElement(tag) : document.createElementNS(ns, tag); + var i; + style = style || {}; + for (i in style) { + e.style[i] = style[i]; + } + + if (clazz) { + e.className = clazz; + } + + atts = atts || {}; + for (i in atts) { + e.setAttribute(i, "" + atts[i]); + } + + return e; + }, + + getAttribute: function (el, attName) { + return el.getAttribute != null ? el.getAttribute(attName) : null; + }, + + setAttribute: function (el, a, v) { + if (el.setAttribute != null) { + el.setAttribute(a, v); + } + }, + + setAttributes: function (el, atts) { + for (var i in atts) { + if (atts.hasOwnProperty(i)) { + el.setAttribute(i, atts[i]); + } + } + }, + appendToRoot: function (node) { + document.body.appendChild(node); + }, + getRenderModes: function () { + return [ "svg" ]; + }, + getClass:_getClassName, + addClass: function (el, clazz) { + jsPlumb.each(el, function (e) { + _classManip(e, clazz); + }); + }, + hasClass: function (el, clazz) { + el = jsPlumb.getElement(el); + if (el.classList) { + return el.classList.contains(clazz); + } + else { + return _getClassName(el).indexOf(clazz) !== -1; + } + }, + removeClass: function (el, clazz) { + jsPlumb.each(el, function (e) { + _classManip(e, null, clazz); + }); + }, + toggleClass:function(el, clazz) { + if (jsPlumb.hasClass(el, clazz)) { + jsPlumb.removeClass(el, clazz); + } else { + jsPlumb.addClass(el, clazz); + } + }, + updateClasses: function (el, toAdd, toRemove) { + jsPlumb.each(el, function (e) { + _classManip(e, toAdd, toRemove); + }); + }, + setClass: function (el, clazz) { + if (clazz != null) { + jsPlumb.each(el, function (e) { + _setClassName(e, clazz, clazz.split(/\s+/)); + }); + } + }, + setPosition: function (el, p) { + el.style.left = p.left + "px"; + el.style.top = p.top + "px"; + }, + getPosition: function (el) { + var _one = function (prop) { + var v = el.style[prop]; + return v ? v.substring(0, v.length - 2) : 0; + }; + return { + left: _one("left"), + top: _one("top") + }; + }, + getStyle:function(el, prop) { + if (typeof window.getComputedStyle !== 'undefined') { + return getComputedStyle(el, null).getPropertyValue(prop); + } else { + return el.currentStyle[prop]; + } + }, + getSelector: function (ctx, spec) { + var sel = null; + if (arguments.length === 1) { + sel = ctx.nodeType != null ? ctx : document.querySelectorAll(ctx); + } + else { + sel = ctx.querySelectorAll(spec); + } + + return sel; + }, + getOffset:function(el, relativeToRoot, container) { + el = jsPlumb.getElement(el); + container = container || this.getContainer(); + var out = { + left: el.offsetLeft, + top: el.offsetTop + }, + op = (relativeToRoot || (container != null && (el !== container && el.offsetParent !== container))) ? el.offsetParent : null, + _maybeAdjustScroll = function(offsetParent) { + if (offsetParent != null && offsetParent !== document.body && (offsetParent.scrollTop > 0 || offsetParent.scrollLeft > 0)) { + out.left -= offsetParent.scrollLeft; + out.top -= offsetParent.scrollTop; + } + }.bind(this); + + while (op != null) { + out.left += op.offsetLeft; + out.top += op.offsetTop; + _maybeAdjustScroll(op); + op = relativeToRoot ? op.offsetParent : + op.offsetParent === container ? null : op.offsetParent; + } + + // if container is scrolled and the element (or its offset parent) is not absolute or fixed, adjust accordingly. + if (container != null && !relativeToRoot && (container.scrollTop > 0 || container.scrollLeft > 0)) { + var pp = el.offsetParent != null ? this.getStyle(el.offsetParent, "position") : "static", + p = this.getStyle(el, "position"); + if (p !== "absolute" && p !== "fixed" && pp !== "absolute" && pp !== "fixed") { + out.left -= container.scrollLeft; + out.top -= container.scrollTop; + } + } + return out; + }, + // + // return x+y proportion of the given element's size corresponding to the location of the given event. + // + getPositionOnElement: function (evt, el, zoom) { + var box = typeof el.getBoundingClientRect !== "undefined" ? el.getBoundingClientRect() : { left: 0, top: 0, width: 0, height: 0 }, + body = document.body, + docElem = document.documentElement, + scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop, + scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft, + clientTop = docElem.clientTop || body.clientTop || 0, + clientLeft = docElem.clientLeft || body.clientLeft || 0, + pst = 0, + psl = 0, + top = box.top + scrollTop - clientTop + (pst * zoom), + left = box.left + scrollLeft - clientLeft + (psl * zoom), + cl = jsPlumb.pageLocation(evt), + w = box.width || (el.offsetWidth * zoom), + h = box.height || (el.offsetHeight * zoom), + x = (cl[0] - left) / w, + y = (cl[1] - top) / h; + + return [ x, y ]; + }, + + /** + * Gets the absolute position of some element as read from the left/top properties in its style. + * @method getAbsolutePosition + * @param {Element} el The element to retrieve the absolute coordinates from. **Note** this is a DOM element, not a selector from the underlying library. + * @return {Number[]} [left, top] pixel values. + */ + getAbsolutePosition: function (el) { + var _one = function (s) { + var ss = el.style[s]; + if (ss) { + return parseFloat(ss.substring(0, ss.length - 2)); + } + }; + return [ _one("left"), _one("top") ]; + }, + + /** + * Sets the absolute position of some element by setting the left/top properties in its style. + * @method setAbsolutePosition + * @param {Element} el The element to set the absolute coordinates on. **Note** this is a DOM element, not a selector from the underlying library. + * @param {Number[]} xy x and y coordinates + * @param {Number[]} [animateFrom] Optional previous xy to animate from. + * @param {Object} [animateOptions] Options for the animation. + */ + setAbsolutePosition: function (el, xy, animateFrom, animateOptions) { + if (animateFrom) { + this.animate(el, { + left: "+=" + (xy[0] - animateFrom[0]), + top: "+=" + (xy[1] - animateFrom[1]) + }, animateOptions); + } + else { + el.style.left = xy[0] + "px"; + el.style.top = xy[1] + "px"; + } + }, + /** + * gets the size for the element, in an array : [ width, height ]. + */ + getSize: function (el) { + return [ el.offsetWidth, el.offsetHeight ]; + }, + getWidth: function (el) { + return el.offsetWidth; + }, + getHeight: function (el) { + return el.offsetHeight; + }, + getRenderMode : function() { return "svg"; }, + draggable : function (el, options) { + var info; + el = _ju.isArray(el) || (el.length != null && !_ju.isString(el)) ? el: [ el ]; + Array.prototype.slice.call(el).forEach(function(_el) { + info = this.info(_el); + if (info.el) { + this._initDraggableIfNecessary(info.el, true, options, info.id, true); + } + }.bind(this)); + return this; + }, + snapToGrid : function(el, x, y) { + var out = []; + var _oneEl = function(_el) { + var info = this.info(_el); + if (info.el != null && info.el._katavorioDrag) { + var snapped = info.el._katavorioDrag.snap(x, y); + this.revalidate(info.el); + out.push([info.el, snapped]); + } + }.bind(this); + + // if you call this method with 0 arguments or 2 arguments it is assumed you want to snap all managed elements to + // a grid. if you supply one argument or 3, then you are assumed to be specifying one element. + if(arguments.length === 1 || arguments.length === 3) { + _oneEl(el, x, y); + } else { + var _me = this.getManagedElements(); + for (var mel in _me) { + _oneEl(mel, arguments[0], arguments[1]); + } + } + + return out; + }, + initDraggable: function (el, options, category) { + _getDragManager(this, category).draggable(el, options); + el._jsPlumbDragOptions = options; + }, + destroyDraggable: function (el, category) { + _getDragManager(this, category).destroyDraggable(el); + delete el._jsPlumbDragOptions; + }, + unbindDraggable: function (el, evt, fn, category) { + _getDragManager(this, category).destroyDraggable(el, evt, fn); + }, + setDraggable : function (element, draggable) { + return jsPlumb.each(element, function (el) { + if (this.isDragSupported(el)) { + this._draggableStates[this.getAttribute(el, "id")] = draggable; + this.setElementDraggable(el, draggable); + } + }.bind(this)); + }, + _draggableStates : {}, + /* + * toggles the draggable state of the given element(s). + * el is either an id, or an element object, or a list of ids/element objects. + */ + toggleDraggable : function (el) { + var state; + jsPlumb.each(el, function (el) { + var elId = this.getAttribute(el, "id"); + state = this._draggableStates[elId] == null ? false : this._draggableStates[elId]; + state = !state; + this._draggableStates[elId] = state; + this.setDraggable(el, state); + return state; + }.bind(this)); + return state; + }, + _initDraggableIfNecessary : function (element, isDraggable, dragOptions, id, fireEvent) { + // TODO FIRST: move to DragManager. including as much of the decision to init dragging as possible. + if (!jsPlumb.headless) { + var _draggable = isDraggable == null ? false : isDraggable; + if (_draggable) { + if (jsPlumb.isDragSupported(element, this)) { + var options = dragOptions || this.Defaults.DragOptions; + options = jsPlumb.extend({}, options); // make a copy. + if (!jsPlumb.isAlreadyDraggable(element, this)) { + var dragEvent = jsPlumb.dragEvents.drag, + stopEvent = jsPlumb.dragEvents.stop, + startEvent = jsPlumb.dragEvents.start; + + this.manage(id, element); + + options[startEvent] = _ju.wrap(options[startEvent], _dragStart.bind(this)); + + options[dragEvent] = _ju.wrap(options[dragEvent], _dragMove.bind(this)); + + options[stopEvent] = _ju.wrap(options[stopEvent], _dragStop.bind(this)); + + var elId = this.getId(element); // need ID + + this._draggableStates[elId] = true; + var draggable = this._draggableStates[elId]; + + options.disabled = draggable == null ? false : !draggable; + this.initDraggable(element, options); + this.getDragManager().register(element); + if (fireEvent) { + this.fire("elementDraggable", {el:element, options:options}); + } + } + else { + // already draggable. attach any start, drag or stop listeners to the current Drag. + if (dragOptions.force) { + this.initDraggable(element, options); + } + } + } + } + } + }, + animationSupported:true, + getElement: function (el) { + if (el == null) { + return null; + } + // here we pluck the first entry if el was a list of entries. + // this is not my favourite thing to do, but previous versions of + // jsplumb supported jquery selectors, and it is possible a selector + // will be passed in here. + el = typeof el === "string" ? el : el.length != null && el.enctype == null ? el[0] : el; + return typeof el === "string" ? document.getElementById(el) : el; + }, + removeElement: function (element) { + _getDragManager(this).elementRemoved(element); + this.getEventManager().remove(element); + }, + // + // this adapter supports a rudimentary animation function. no easing is supported. only + // left/top properties are supported. property delta args are expected to be in the form + // + // +=x.xxxx + // + // or + // + // -=x.xxxx + // + doAnimate: function (el, properties, options) { + options = options || {}; + var o = this.getOffset(el), + ap = _animProps(o, properties), + ldist = ap[0] - o.left, + tdist = ap[1] - o.top, + d = options.duration || 250, + step = 15, steps = d / step, + linc = (step / d) * ldist, + tinc = (step / d) * tdist, + idx = 0, + _int = setInterval(function () { + _jp.setPosition(el, { + left: o.left + (linc * (idx + 1)), + top: o.top + (tinc * (idx + 1)) + }); + if (options.step != null) { + options.step(idx, Math.ceil(steps)); + } + idx++; + if (idx >= steps) { + window.clearInterval(_int); + if (options.complete != null) { + options.complete(); + } + } + }, step); + }, + // DRAG/DROP + + + destroyDroppable: function (el, category) { + _getDragManager(this, category).destroyDroppable(el); + }, + unbindDroppable: function (el, evt, fn, category) { + _getDragManager(this, category).destroyDroppable(el, evt, fn); + }, + + droppable :function(el, options) { + el = _ju.isArray(el) || (el.length != null && !_ju.isString(el)) ? el: [ el ]; + var info; + options = options || {}; + options.allowLoopback = false; + Array.prototype.slice.call(el).forEach(function(_el) { + info = this.info(_el); + if (info.el) { + this.initDroppable(info.el, options); + } + }.bind(this)); + return this; + }, + + initDroppable: function (el, options, category) { + _getDragManager(this, category).droppable(el, options); + }, + isAlreadyDraggable: function (el) { + return el._katavorioDrag != null; + }, + isDragSupported: function (el, options) { + return true; + }, + isDropSupported: function (el, options) { + return true; + }, + isElementDraggable: function (el) { + el = _jp.getElement(el); + return el._katavorioDrag && el._katavorioDrag.isEnabled(); + }, + getDragObject: function (eventArgs) { + return eventArgs[0].drag.getDragElement(); + }, + getDragScope: function (el) { + return el._katavorioDrag && el._katavorioDrag.scopes.join(" ") || ""; + }, + getDropEvent: function (args) { + return args[0].e; + }, + getUIPosition: function (eventArgs, zoom) { + // here the position reported to us by Katavorio is relative to the element's offsetParent. For top + // level nodes that is fine, but if we have a nested draggable then its offsetParent is actually + // not going to be the jsplumb container; it's going to be some child of that element. In that case + // we want to adjust the UI position to account for the offsetParent's position relative to the Container + // origin. + var el = eventArgs[0].el; + if (el.offsetParent == null) { + return null; + } + var finalPos = eventArgs[0].finalPos || eventArgs[0].pos; + var p = { left:finalPos[0], top:finalPos[1] }; + if (el._katavorioDrag && el.offsetParent !== this.getContainer()) { + var oc = this.getOffset(el.offsetParent); + p.left += oc.left; + p.top += oc.top; + } + return p; + }, + setDragFilter: function (el, filter, _exclude) { + if (el._katavorioDrag) { + el._katavorioDrag.setFilter(filter, _exclude); + } + }, + setElementDraggable: function (el, draggable) { + el = _jp.getElement(el); + if (el._katavorioDrag) { + el._katavorioDrag.setEnabled(draggable); + } + }, + setDragScope: function (el, scope) { + if (el._katavorioDrag) { + el._katavorioDrag.k.setDragScope(el, scope); + } + }, + setDropScope:function(el, scope) { + if (el._katavorioDrop && el._katavorioDrop.length > 0) { + el._katavorioDrop[0].k.setDropScope(el, scope); + } + }, + addToPosse:function(el, spec) { + var specs = Array.prototype.slice.call(arguments, 1); + var dm = _getDragManager(this); + _jp.each(el, function(_el) { + _el = [ _jp.getElement(_el) ]; + _el.push.apply(_el, specs ); + dm.addToPosse.apply(dm, _el); + }); + }, + setPosse:function(el, spec) { + var specs = Array.prototype.slice.call(arguments, 1); + var dm = _getDragManager(this); + _jp.each(el, function(_el) { + _el = [ _jp.getElement(_el) ]; + _el.push.apply(_el, specs ); + dm.setPosse.apply(dm, _el); + }); + }, + removeFromPosse:function(el, posseId) { + var specs = Array.prototype.slice.call(arguments, 1); + var dm = _getDragManager(this); + _jp.each(el, function(_el) { + _el = [ _jp.getElement(_el) ]; + _el.push.apply(_el, specs ); + dm.removeFromPosse.apply(dm, _el); + }); + }, + removeFromAllPosses:function(el) { + var dm = _getDragManager(this); + _jp.each(el, function(_el) { dm.removeFromAllPosses(_jp.getElement(_el)); }); + }, + setPosseState:function(el, posseId, state) { + var dm = _getDragManager(this); + _jp.each(el, function(_el) { dm.setPosseState(_jp.getElement(_el), posseId, state); }); + }, + dragEvents: { + 'start': 'start', 'stop': 'stop', 'drag': 'drag', 'step': 'step', + 'over': 'over', 'out': 'out', 'drop': 'drop', 'complete': 'complete', + 'beforeStart':'beforeStart' + }, + animEvents: { + 'step': "step", 'complete': 'complete' + }, + stopDrag: function (el) { + if (el._katavorioDrag) { + el._katavorioDrag.abort(); + } + }, + addToDragSelection: function (spec) { + _getDragManager(this).select(spec); + }, + removeFromDragSelection: function (spec) { + _getDragManager(this).deselect(spec); + }, + clearDragSelection: function () { + _getDragManager(this).deselectAll(); + }, + trigger: function (el, event, originalEvent, payload) { + this.getEventManager().trigger(el, event, originalEvent, payload); + }, + doReset:function() { + // look for katavorio instances and reset each one if found. + for (var key in this) { + if (key.indexOf("_katavorio_") === 0) { + this[key].reset(); + } + } + }, + getEventManager:function() { + return _getEventManager(this); + }, + on : function(el, event, callback) { + // TODO: here we would like to map the tap event if we know its + // an internal bind to a click. we have to know its internal because only + // then can we be sure that the UP event wont be consumed (tap is a synthesized + // event from a mousedown followed by a mouseup). + //event = { "click":"tap", "dblclick":"dbltap"}[event] || event; + this.getEventManager().on.apply(this, arguments); + return this; + }, + off : function(el, event, callback) { + this.getEventManager().off.apply(this, arguments); + return this; + } + + }); + + var ready = function (f) { + var _do = function () { + if (/complete|loaded|interactive/.test(document.readyState) && typeof(document.body) !== "undefined" && document.body != null) { + f(); + } + else { + setTimeout(_do, 9); + } + }; + + _do(); + }; + ready(_jp.init); + +}).call(typeof window !== 'undefined' ? window : this); diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/workflow/mixins.js b/Pure_Vite_Net7/Vue3Vite/src/components/workflow/mixins.js new file mode 100644 index 0000000000000000000000000000000000000000..37b0d582882facfc347fc72d4c3c604278c0298f --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/workflow/mixins.js @@ -0,0 +1,157 @@ +export const easyFlowMixin = { + data() { + return { + jsplumbSetting: { + // 动态锚点、位置自适应 + Anchors: ['Top', 'TopCenter', 'TopRight', 'TopLeft', 'Right', 'RightMiddle', 'Bottom', 'BottomCenter', 'BottomRight', 'BottomLeft', 'Left', 'LeftMiddle'], + // 容器ID + Container: 'efContainer', + // 连线的样式,直线或者曲线等,可选值: StateMachine、Flowchart,Bezier、Straight + Connector: ['Bezier', {curviness: 100}], + // Connector: ['Straight', {stub: 20, gap: 1}], + // Connector: ['Flowchart', {stub: 30, gap: 1, alwaysRespectStubs: false, midpoint: 0.5, cornerRadius: 10}], + // Connector: ['StateMachine', {margin: 5, curviness: 10, proximityLimit: 80}], + // 鼠标不能拖动删除线 + ConnectionsDetachable: false, + // 删除线的时候节点不删除 + DeleteEndpointsOnDetach: false, + /** + * 连线的两端端点类型:圆形 + * radius: 圆的半径,越大圆越大 + */ + // Endpoint: ['Dot', {radius: 5, cssClass: 'ef-dot', hoverClass: 'ef-dot-hover'}], + /** + * 连线的两端端点类型:矩形 + * height: 矩形的高 + * width: 矩形的宽 + */ + // Endpoint: ['Rectangle', {height: 20, width: 20, cssClass: 'ef-rectangle', hoverClass: 'ef-rectangle-hover'}], + /** + * 图像端点 + */ + // Endpoint: ['Image', {src: 'https://www.easyicon.net/api/resizeApi.php?id=1181776&size=32', cssClass: 'ef-img', hoverClass: 'ef-img-hover'}], + /** + * 空白端点 + */ + Endpoint: ['Blank', {Overlays: ''}], + // Endpoints: [['Dot', {radius: 5, cssClass: 'ef-dot', hoverClass: 'ef-dot-hover'}], ['Rectangle', {height: 20, width: 20, cssClass: 'ef-rectangle', hoverClass: 'ef-rectangle-hover'}]], + /** + * 连线的两端端点样式 + * fill: 颜色值,如:#12aabb,为空不显示 + * outlineWidth: 外边线宽度 + */ + EndpointStyle: {fill: '#1879ffa1', outlineWidth: 1}, + // 是否打开jsPlumb的内部日志记录 + LogEnabled: true, + /** + * 连线的样式 + */ + PaintStyle: { + // 线的颜色 + stroke: '#E0E3E7', + // 线的粗细,值越大线越粗 + strokeWidth: 1, + // 设置外边线的颜色,默认设置透明,这样别人就看不见了,点击线的时候可以不用精确点击,参考 https://blog.csdn.net/roymno2/article/details/72717101 + outlineStroke: 'transparent', + // 线外边的宽,值越大,线的点击范围越大 + outlineWidth: 10 + }, + DragOptions: {cursor: 'pointer', zIndex: 2000}, + /** + * 叠加 参考: https://www.jianshu.com/p/d9e9918fd928 + */ + Overlays: [ + // 箭头叠加 + ['Arrow', { + width: 10, // 箭头尾部的宽度 + length: 8, // 从箭头的尾部到头部的距离 + location: 1, // 位置,建议使用0~1之间 + direction: 1, // 方向,默认值为1(表示向前),可选-1(表示向后) + foldback: 0.623 // 折回,也就是尾翼的角度,默认0.623,当为1时,为正三角 + }], + // ['Diamond', { + // events: { + // dblclick: function (diamondOverlay, originalEvent) { + // console.log('double click on diamond overlay for : ' + diamondOverlay.component) + // } + // } + // }], + ['Label', { + label: '', + location: 0.1, + cssClass: 'aLabel' + }] + ], + // 绘制图的模式 svg、canvas + RenderMode: 'svg', + // 鼠标滑过线的样式 + HoverPaintStyle: {stroke: '#b0b2b5', strokeWidth: 1}, + // 滑过锚点效果 + // EndpointHoverStyle: {fill: 'red'} + Scope: 'jsPlumb_DefaultScope' // 范围,具有相同scope的点才可连接 + }, + /** + * 连线参数 + */ + jsplumbConnectOptions: { + isSource: true, + isTarget: true, + // 动态锚点、提供了4个方向 Continuous、AutoDefault + anchor: 'Continuous', + // 设置连线上面的label样式 + labelStyle: { + cssClass: 'flowLabel' + }, + // 修改了jsplumb 源码,支持label 为空传入自定义style + emptyLabelStyle: { + cssClass: 'emptyFlowLabel' + } + }, + /** + * 源点配置参数 + */ + jsplumbSourceOptions: { + // 设置可以拖拽的类名,只要鼠标移动到该类名上的DOM,就可以拖拽连线 + filter: '.flow-node-drag', + filterExclude: false, + anchor: 'Continuous', + // 是否允许自己连接自己 + allowLoopback: true, + maxConnections: -1, + onMaxConnections: function (info, e) { + console.log(`超过了最大值连线: ${info.maxConnections}`) + } + }, + // 参考 https://www.cnblogs.com/mq0036/p/7942139.html + jsplumbSourceOptions2: { + // 设置可以拖拽的类名,只要鼠标移动到该类名上的DOM,就可以拖拽连线 + filter: '.flow-node-drag', + filterExclude: false, + // anchor: 'Continuous', + // 是否允许自己连接自己 + allowLoopback: true, + connector: ['Flowchart', {curviness: 50}], + connectorStyle: { + // 线的颜色 + stroke: 'red', + // 线的粗细,值越大线越粗 + strokeWidth: 1, + // 设置外边线的颜色,默认设置透明,这样别人就看不见了,点击线的时候可以不用精确点击,参考 https://blog.csdn.net/roymno2/article/details/72717101 + outlineStroke: 'transparent', + // 线外边的宽,值越大,线的点击范围越大 + outlineWidth: 10 + }, + connectorHoverStyle: {stroke: 'red', strokeWidth: 2} + }, + jsplumbTargetOptions: { + // 设置可以拖拽的类名,只要鼠标移动到该类名上的DOM,就可以拖拽连线 + filter: '.flow-node-drag', + filterExclude: false, + // 是否允许自己连接自己 + anchor: 'Continuous', + allowLoopback: true, + dropOptions: {hoverClass: 'ef-drop-hover'} + } + } + } +} diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/workflow/node.vue b/Pure_Vite_Net7/Vue3Vite/src/components/workflow/node.vue new file mode 100644 index 0000000000000000000000000000000000000000..cfc2ce1239caed5a06078c37334ee76d3801642b --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/workflow/node.vue @@ -0,0 +1,108 @@ + + + + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/workflow/node_form.vue b/Pure_Vite_Net7/Vue3Vite/src/components/workflow/node_form.vue new file mode 100644 index 0000000000000000000000000000000000000000..bdbbf74d6804875ba4757cf87d934a9b9161bcb0 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/workflow/node_form.vue @@ -0,0 +1,261 @@ + + + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/workflow/node_menu.vue b/Pure_Vite_Net7/Vue3Vite/src/components/workflow/node_menu.vue new file mode 100644 index 0000000000000000000000000000000000000000..df1d7846dd09740738ba157c39409b87dfc6f4cc --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/workflow/node_menu.vue @@ -0,0 +1,111 @@ + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/workflow/utils.js b/Pure_Vite_Net7/Vue3Vite/src/components/workflow/utils.js new file mode 100644 index 0000000000000000000000000000000000000000..2874a4155840a3ee45d22710c84d5b8352e2524a --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/workflow/utils.js @@ -0,0 +1,29 @@ +// 是否具有该线 +export function hasLine(data, from, to) { + for (let i = 0; i < data.lineList.length; i++) { + let line = data.lineList[i] + if (line.from === from && line.to === to) { + return true + } + } + return false +} + +// 是否含有相反的线 +export function hashOppositeLine(data, from, to) { + return hasLine(data, to, from) +} + +// 获取连线 +export function getConnector(jsp, from, to) { + let connection = jsp.getConnections({ + source: from, + target: to + })[0] + return connection +} + +// 获取唯一标识 +export function uuid() { + return Math.random().toString(36).substr(3, 10) +} diff --git a/Pure_Vite_Net7/Vue3Vite/src/components/workflow/workflow.vue b/Pure_Vite_Net7/Vue3Vite/src/components/workflow/workflow.vue new file mode 100644 index 0000000000000000000000000000000000000000..7eefb9d5a69b3d0e37f017614b4831ee34406f1d --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/components/workflow/workflow.vue @@ -0,0 +1,677 @@ + + + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_Expert.js b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_Expert.js new file mode 100644 index 0000000000000000000000000000000000000000..fbbfeee3e429167c5719add9c140c64159f06e63 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_Expert.js @@ -0,0 +1,160 @@ + +import gridHeader from './App_Expert/App_ExpertGridHeader' + +//自定义选择数据源页面 +import App_ExpertModelBody from './App_Expert/App_ExpertModelBody' +import { h, resolveComponent } from 'vue'; +//声明vue对象 +let $this; +let extension = { + components: { + gridHeader: gridHeader, + gridBody: { + render() { + return h(resolveComponent('ElAlert'), { + style: { 'margin-bottom': '12px' }, + 'show-icon': true, + closable: false, + }, [h('p', {}, '1、多个弹出框:手动创建一个页面,接着在表对应的js文件中引入页面放到gridHeader中'), + h('p', {}, ' 2、在手动创建的页面中,可以写任意代码,在js中通过this.$refs.gridHeader.xx即可访问页面的内容,具体见:App_Expert.js、App_ExpertGridHeader.vue')]); + } + }, + gridFooter: '', + modelHeader: '', + modelBody: App_ExpertModelBody, //将选择数据源页面App_ExpertModelBody注册到弹出框中 + modelFooter: '' + }, //动态扩充组件或组件路径 + buttons: { + view: [{ + name: "弹出框1", + icon: 'md-add', + index: 1,//添加到第一个按钮后面 + type: 'primary', + onClick: function () { + $this.$refs.gridHeader.open1() + } + }] + }, + + methods: { //事件扩展 + onInited() { + $this = this; + //手动调度弹出框的高度 + this.boxOptions.height = this.boxOptions.height + 90; + //手动设置表高度自动适应 + this.height = this.height - 100; + }, + onInit() { + + //选择数据源功能 + this.editFormOptions.forEach(x => { + x.forEach(item => { + if (item.field == 'CreateDate') { + //给编辑表单设置[选择数据]操作,extra具体配置见volform组件api + item.extra = { + icon: "el-icon-zoom-out", + text: "选择数据", + style: "color:red;font-size: 12px;cursor: pointer;", + click: item => { + this.$refs.modelBody.openDemo(); + } + } + } + }) + }) + + + //设置保存后继续添加 ,不关闭当前窗口 + //2021.04.11需要更新methods.js,ViewGrid.vue + this.continueAdd = true; + this.continueAddName = "连续添加"; + + //将编辑表单第一行第一列【名称】字段添加一个额外提示属性 + this.editFormOptions[0][0].extra = { + render: h => { + return h( + resolveComponent("el-tooltip"), + { + content: "这里是提示的内容", + props: { effect: "dark", placement: "top-start" }, + style: {} + }, [ + h('a', { style: { color: '#2a92ff' } }, '提示信息') + ] + ) + } + } + + //设置界面上最多可显示的按钮数量 + this.maxBtnLength = 6; + + // 第2个弹出框操作 + this.buttons.splice(2, 0, ...[{ + name: "弹出框2", + icon: 'md-add', + type: 'success', + onClick: function () { + $this.$refs.gridHeader.open2() + } + }, + { + name: "获取子组件对象", + icon: 'md-add', + type: 'warning', + onClick: function () { + this.$Message.info(this.$refs.gridHeader.getTestData()) + } + }]) + + + // 第3个弹出框操作 + this.columns.forEach(x => { + if (x.field == "Resume") { + x.formatter = (row, column, event) => { + return '(弹出框3)' + row.Resume + '' + }; + //绑定点击事件 + x.click = (row, column, event) => { + $this.$refs.gridHeader.open3(row) + }; + } + }) + + //启用多图上传,其他上传参数,参照volupload组件api + this.editFormOptions.forEach(x => { + x.forEach(item => { + if (item.field == 'HeadImageUrl') { + //item.type = 'file'; + //设置成100%宽度 + item.colSize = 12; + item.multiple = true; + //最多可以上传3张照片 + item.maxFile = 3; + //限制图片大小,默认3M + item.maxSize = 3; + // item.append = true; + } + }) + }) + + //动态添加一行表单配置 + this.editFormOptions[2].splice(0, 1, ...[{ + colSize: 12, + render: h => { + return h( + 'div', { style: { 'padding-left': '60px' } }, + [h(resolveComponent('ElAlert'), { + style: {}, + type: 'success', + 'show-icon': true, + title: "这里是render动态渲染的内容", + closable: false, + }, [h('div', { style: { 'margin-top': '-20px' } }, '代码生成器中编辑类型选择file/excel/img类型文件上传,同时可以设置上传文件数量、大小等,具体见App_Expert.js配置')])] + ) + } + }]) + + }, + } +}; +export default extension; \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_Expert/App_ExpertGridHeader.vue b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_Expert/App_ExpertGridHeader.vue new file mode 100644 index 0000000000000000000000000000000000000000..ae1dac357a04ca206b2887b80fa1fc48781aabdd --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_Expert/App_ExpertGridHeader.vue @@ -0,0 +1,106 @@ + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_Expert/App_ExpertModelBody.vue b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_Expert/App_ExpertModelBody.vue new file mode 100644 index 0000000000000000000000000000000000000000..98ef547ad0b11b265472e9b1baf98de12692411f --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_Expert/App_ExpertModelBody.vue @@ -0,0 +1,130 @@ + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_Expert2.js b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_Expert2.js new file mode 100644 index 0000000000000000000000000000000000000000..9cce4d84010f5c825250f00b39e5fbe71a87b6aa --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_Expert2.js @@ -0,0 +1,144 @@ + + +import { h, resolveComponent } from 'vue'; +let extension = { + components: { + gridHeader: ``, + gridBody: { + render() { + return [ + h(resolveComponent('el-alert'), { + style: { 'margin-bottom': '12px' }, + 'show-icon': true, type: 'warning', + closable: false, title: '复杂table内容,适用于table列较多的情况可以将列合并在一起显示(代码生成后,在对应js文件中设置合并显示信息),只需几行代码即可实现,见:App_Expert2.js' + }, ''), + ] + } + }, + gridFooter: '', + modelHeader: '', + modelBody: '', + modelFooter: '' + }, //动态扩充组件或组件路径 + buttons: { + view: [] + }, + methods: { //事件扩展 + onInit() { + //设置单单元格合并 + this.initFirstColumn(); + //动态添加【状态】列 + this.initColor(); + //在表最后添加操作列 + this.initColumnButton(); + }, + onInited() { + //手动调整界面表高度 + this.height = this.height - 50; + this.boxOptions.height = this.boxOptions.height + 40; + }, + initColor() { + var _index = this.columns.findIndex(x => { return x.field == "Enable" }); + if (_index == -1) { + return; + } + //动态添加一列【状态】 + this.columns.splice(_index, 1, { + title: "状态", + field: "状态", + with: 60, + formatter: (row) => { + var _color = row.Enable == 1 ? '#ff1212' : '#04c966'; + return ` ` + } + }) + }, + initFirstColumn() { + //在第一行后面动态添加一行 + this.columns.splice(1, 0, { + title: "用户信息", + field: "用户信息", + width: 220, + render: (h, { row, column, index }) => { + //下面所有需要显示的信息都从row里面取出来 + return h( + "div", + { + style: { display: "flex", cursor: 'pointer', }, + }, + [ + h( + "img", + { + src: this.http.ipAddress + row.HeadImageUrl, + style: { "width": "70px", height: "90px", "object-fit": "cover" }, + }, + ), + h( + "div", + { + props: {}, + style: { "margin-left": "15px" }, + }, + [ + h("div", { style: { "font-size": "12px", "color": "#459fff", "margin-bottom": "8px", "font-weight": "bold" } }, + [h("span", {}, row.ReallyName), + h("span", { style: { "margin-left": "20px" } }, row.Enable == "1" ? '在线' : "离线")] + ), + h("div", { style: { "font-size": "12px", "color": "#459fff", 'line-height': '20px' } }, row.IDNumber || '无身份证信息'), + h("div", { style: { "font-size": "12px", "color": "#459fff", 'line-height': '20px' } }, "电话:" + row.PhoneNo), + h("div", { style: { "font-size": "12px", "color": "#459fff", 'line-height': '20px' } }, "城市:" + row.City), + ] + )]) + } + }) + }, + initColumnButton() { + //在表最后添加操作列 + this.columns.push({ + title: '操作', + fixed: 'right', + align: "center", + width: 130, + render: (h, { row, column, index }) => { + return h( + "div", { style: { cursor: 'pointer' } }, [ + h( + resolveComponent("el-button"), { + style: { padding: '0 7px' }, + type: "danger", + plain: true, + size: 'mini', + onClick: (e) => { + e.stopPropagation() + this.del([row]); + }, + }, + [h('i', { class: 'el-icon-delete' }, '删除')] + ), + h( + resolveComponent("el-button"), { + style: { padding: '0 7px' }, + type: "primary", + plain: true, + size: 'mini', + onClick: (e) => { + e.stopPropagation() + this.linkData(row); + }, + }, + [h('i', { class: 'el-icon-edit' }, '修改')] + ), + ]) + } + }) + } + + } +}; +export default extension; \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_News.js b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_News.js new file mode 100644 index 0000000000000000000000000000000000000000..f475b0a73b8b5a35318564f7330177e6da501771 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_News.js @@ -0,0 +1,144 @@ +import gridHeader from './App_News/App_NewGirdHeader' + +import { h, resolveComponent } from 'vue'; +let extension = { + components: {//动态扩充组件或组件路径 + gridHeader: gridHeader, + gridBody: { + render() { + return [ + h(resolveComponent('el-alert'), { + style: { 'margin-bottom': '12px' }, + 'show-icon': true, type: 'warning', + closable: false, title: '发布静态页面、页面预览见:App_News.js' + }, ''), + ] + } + }, + gridFooter: '', + modelHeader: '', + modelFooter: '' + }, + text: "静态文件没有提交到github,本地重新生成下静态页面与设置封面即可预览", + buttons: { + view: [//ViewGrid查询界面扩展的按钮 + ] + }, + methods: { + initButton() { + //当前用户是否有编辑或新建权限 + if (this.currentReadonly) { return; } + + this.buttons.splice(2, 0, { + name: "设置封面", icon: 'el-icon-picture', value: 'Edit', type: 'primary', + onClick: function () { this.setCover(); } + }) + //添加弹出框生成静态页面的按钮 + this.boxButtons.splice(0, 0, ...[{ + name: "生成静态页面", icon: 'el-icon-tickets', type: 'primary', + onClick: function () { this.publish(); } + }, + { + name: "预览页面", icon: 'el-icon-view', type: 'primary', + onClick: function () { + if (!this.currentRow + || !this.currentRow.Content + || !this.currentRow.DetailUrl) { + return this.$Message.error("请先【保存】,再点击【生成静态页面】") + } + this.preview(this.currentRow); + } + }]) + }, + onInit() { //初始化预览与弹出框大小 + //设置表格内容超出换行 + this.textInline=false; + //根据用户权限初始化按钮 + this.initButton(); + //设置保存成功后,不关闭弹出框 + this.boxOptions.saveClose = false; + //设置查询表格只能单选 + this.single = true; + + //设置table表格DetailUrl字段点击预览静态页面 + this.editFormOptions.forEach(x => { + x.forEach(item => { + this.columns.forEach(item => { + //设置url点击事件 + if (item.field == 'DetailUrl') { + item.title = "页面预览"; + item.formatter = (row) => { return '预览' } + item.click = (row, column, event) => { + this.preview(row); + } + } + }) + }) + }) + }, + onInited(){ + this.height = this.height - 50; + }, + addBefore(formData) {//新建前验证 + return this.validContent(formData); + }, + updateBefore(formData) { //修改前验证 + return this.validContent(formData); + }, + validContent(formData) { + if (!this.editFormFields.Content) { + this.$Message.error("请编辑要发布的内容"); + return false; + } + return true; + }, + preview(row) { //预览html页面 + if (!row.DetailUrl || row.DetailUrl.indexOf('.html') == -1 || !this.base.isUrl(this.http.ipAddress + row.DetailUrl)) { + return this.$Message.error("请先发布静态页面") + } + window.open(this.http.ipAddress + row.DetailUrl + '?r=' + Math.random()); + }, + publish() { //生成静态页面 + if (!this.currentRow || !this.currentRow[this.table.key]) { + return this.$Message.error("请先保存数据") + } + if (!this.currentRow.Content) { + return this.$Message.error("请编辑要发布的内容") + } + this.http.post("api/news/createPage", this.currentRow).then(x => { + if (x.status) { + // this.editFormFields.DetailUrl = x.data.url; + this.currentRow.DetailUrl = x.data.url; + } + this.refresh(); + return this.$Message.info(x.message) + }) + }, + setCover() { //设置封面图片 + let rows = this.getSelectRows(); + if (rows.length == 0) { + return this.$Message.error("请选中要设置封面的行") + } + //设置封面图片,先获取当前已经图片fileInfo格式见volupdate组件参数说明 + let fileInfo = this.getFilePath(rows[0].ImageUrl) || []; + this.$refs.gridHeader.open(fileInfo) + }, + getFilePath(pathSring) {//拆分url并初始化图片到上传组件中 + //获取表的图片与文件显示 + if (!pathSring) return ""; + let fileInfo = [], filePath = pathSring.replace(/\\/g, "/").split(","); + for (let index = 0; index < filePath.length; index++) { + let file = filePath[index]; + if (file.indexOf(".") == -1) { continue; } + let splitFile = file.split("/"); + if (splitFile.length == 0) { continue; } + fileInfo.push({ + name: splitFile[splitFile.length - 1], + path: this.base.isUrl(file) ? file : this.http.ipAddress + file + }); + } + return fileInfo; + } + } +}; +export default extension; \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_News/App_NewGirdHeader.vue b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_News/App_NewGirdHeader.vue new file mode 100644 index 0000000000000000000000000000000000000000..419bcaca14857c2a5f3ed14cd77daffb09b097e8 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_News/App_NewGirdHeader.vue @@ -0,0 +1,77 @@ + + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_NewsEditor.js b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_NewsEditor.js new file mode 100644 index 0000000000000000000000000000000000000000..f9d868ad358f3937fae0d72a352162c56eb75153 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_NewsEditor.js @@ -0,0 +1,50 @@ + +import { h, resolveComponent } from 'vue'; +let extension = { + components: {//动态扩充组件或组件路径 + gridHeader: '', + gridBody: { + render() { + return [ + h(resolveComponent('el-alert'), { + style: { 'margin-bottom': '12px' }, + 'show-icon': true, type: 'warning', + closable: false, title: '设置属性后textInline,表格超出换行onInit(){ this.textInline = false};代码生成器编辑类型选择editor即可默认生成编辑器:App_NewsEditor.js或App_News.js' + }, ''), + ] + } + }, + gridFooter: '', + modelHeader: '', + modelBody: '', + modelFooter: '' + }, //动态扩充组件或组件路径 + buttons: { + view: [] + }, + tableAction: "App_News", + methods: { //事件扩展 + onInit() { + //设置表的最大高度 + this.tableMaxHeight = 400; + //table内容超出后自动换行 + this.textInline = false; + //添加预览操作 + this.columns.forEach(item => { + //设置url点击事件 + if (item.field == 'DetailUrl') { + item.title = "页面预览"; + item.formatter = (row) => { return '预览' } + item.click = (row, column, event) => { + if (!row.DetailUrl || row.DetailUrl.indexOf('.html') == -1 || !this.base.isUrl(this.http.ipAddress + row.DetailUrl)) { + return this.$Message.error("请先发布静态页面") + } + window.open(this.http.ipAddress + row.DetailUrl); + } + } + }) + } + + } +}; +export default extension; \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_ReportPrice.js b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_ReportPrice.js new file mode 100644 index 0000000000000000000000000000000000000000..8f00fedd2f480a1169c8ba7e556981541a14f4de --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_ReportPrice.js @@ -0,0 +1,71 @@ + +import { h, resolveComponent, defineAsyncComponent } from 'vue'; +import modelBody from "./App_ReportPrice/App_ReportPriceModelBody.vue" +let extension = { + components: {//动态扩充组件或组件路径 + gridHeader: "", + gridBody: { + render() { + return h(resolveComponent('ElAlert'), { + style: { 'margin-bottom': '12px' }, + 'show-icon': true, + closable: false, + }, [h('p', {}, '1、此界面与上面的区别是:多个明细表在弹出框进行的扩展,见App_ReportPrice.js(点击新建或编辑即可查看效果)'), + h('p', {}, ' 2、手动创建一个页面(可以写任意代码),引入到App_ReportPrice.js的modelBody位置')]); + } + }, + gridFooter: '', + modelHeader: '', + //通过defineAsyncComponent异步引用 + modelBody: modelBody, + // defineAsyncComponent(() => (import("./App_ReportPrice/App_ReportPriceModelBody.vue"))), + modelFooter: '' + }, + buttons: [],//扩展的按钮 + text: "弹出框一对多明细", + methods: {//事件扩展 + onInit() { + }, + onInited() { + //初始化后将table高度减少85,因为gridHeader加了提示会导致页面有滚动条 + this.height = this.height - 100; + //自定义弹出框的高与宽 + this.boxOptions.height = document.body.clientHeight * 0.9; + this.boxOptions.width = document.body.clientWidth * 0.8; + }, + modelOpenAfter() {//打开弹出框时 + //是否子组件渲染完成 + //新建功时,清空 清空,从表1,从表2的数据 + this.$nextTick(() => { + //这里没有给弹出框中的表格传参,如果需要参数可以通过 this.$emit("parentCall", 获取页面的参数 + //具体见自定义页面App_ReportPriceModelBody.vue中的modelOpen方法的使用 this.$emit("parentCall", ($this) => { + this.$refs.modelBody.modelOpen(); + }) + }, + addBefore(formData) { //弹出框新建或编辑功能点保存时可以将从表1,从表2的数据提到后台 + this.setFormData(formData); + return true; + }, + updateBefore(formData) { //编辑时功能点保存时可以将从表1,从表2的数据提到后台 + this.setFormData(formData); + return true; + }, + setFormData(formData) { //新建或编辑时,将从表1、2的数据提交到后台,见后台App_ReportPriceService的新建方法 + //后台从对象里直接取extra的值 + let extra = { + table1List: this.$refs.modelBody.$refs.table1.rowData,//获取从表1的行数据 + table2List: this.$refs.modelBody.$refs.table2.rowData//获取从表2的行数据 + } + formData.extra = JSON.stringify(extra); + }, + resetUpdateFormAfter() { //编辑弹出框时,点重置时,可自定义重置 + console.log('resetUpdateFormAfter') + return true; + }, + resetAddFormAfter() { //新建弹出框时,点重置时,可自定义重置 + console.log('resetAddFormAfter') + return true; + } + } +}; +export default extension; diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_ReportPrice/App_ReportPriceModelBody.vue b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_ReportPrice/App_ReportPriceModelBody.vue new file mode 100644 index 0000000000000000000000000000000000000000..a1412c3a971d713706efc2db9d38f5685812aef3 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_ReportPrice/App_ReportPriceModelBody.vue @@ -0,0 +1,281 @@ + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_Transaction.js b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_Transaction.js new file mode 100644 index 0000000000000000000000000000000000000000..276527c9dd356b0d035c9ceb70b81862bd843369 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_Transaction.js @@ -0,0 +1,56 @@ +import { h, resolveComponent } from 'vue'; +let extension = { + components: {//动态扩充组件或组件路径 + //表单header、content、footer对应位置扩充的组件 + gridHeader: '',//{ template: "
扩展组xx件
" }, + // gridBody: { + // template: '\ + // 查询默认/显示所有查询条件\ + // ' }, + gridBody: { + render() { + return h(resolveComponent('ElAlert'), { + style: { 'margin-bottom': '12px' }, + 'show-icon': true, + type: 'success', + closable: false, + }, [h('p', {},'1、默认界面上显示的列都可以导入,也可以在后台指定导入与导出的列,见后台开发文档->后台基础代码扩展实现导入方法说明'), + h('p', {}, ' 2、设置默认查询值(下拉框、默认日期)、查询界面表高度等,App_Transaction.js配置与说明')]); + } + }, + gridFooter: '', + //弹出框(修改、编辑、查看)header、content、footer对应位置扩充的组件 + modelHeader: '', + modelBody: '', + modelFooter: '' + }, + tableAction:"App_Appointment",//指定菜单权限,其他任何页面引用时都会走对应权限 + text: "目前导入导出的字段为代码生成器中配置[是否显示与编辑列],可自行添加配置字段处理", + buttons: [],//扩展的按钮 + methods: {//事件扩展 + + //事件扩展 + onInit() { + //设置查询条件 + // this.searchFormFields.Name = "林"; + //设置下拉框的字段(是否买入)的默认值(注意下拉框key如要是数字同样也要设置为字符类型数字,如果是自定sql数据源的key则需要设置成数字类型) + this.searchFormFields.TransactionType = "1"; + //注意日期设置默认值的时候 ,如果查询类型选择的是datetime后面一定要写上,00:00:00 + //如果查询类型是date直接写年月日即可 + this.searchFormFields.CreateDate = ['2015-01-01 00:00:00', '2030-12-31 00:00:00'] + //设置页面上显示的按钮个数(不是必须的) + this.maxBtnLength = 6; + //设置显示所有查询条件 + this.setFiexdSearchForm(true); + }, + onInited() { + //设置查询界面表最大高度 + this.tableMaxHeight = 500; + //移除快捷查询 + this.singleSearch = null; + + }, + } +}; +export default extension; diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_Transaction2.js b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_Transaction2.js new file mode 100644 index 0000000000000000000000000000000000000000..62c3a61f4545edf05d30a47291c0a4409622f638 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_Transaction2.js @@ -0,0 +1,103 @@ +let extension = { + components: {//动态扩充组件或组件路径 + //表单header、content、footer对应位置扩充的组件 + gridHeader: '',//{ template: "
扩展组xx件
" }, + gridBody: '', + gridFooter: '', + //弹出框(修改、编辑、查看)header、content、footer对应位置扩充的组件 + modelHeader: '', + modelBody: '', + modelFooter: '' + }, + text: "点击行或者点击表格的编辑即可开启编辑功能", + tableAction: 'App_Transaction', + buttons: [],//扩展的按钮 + methods: {//事件扩展 + onInit() {//手动设置弹出框的高度与宽度 + //判断有没有App_Transaction表修改的权限 ,无权限不开启编辑功能 + if (!this.filterPermission('App_Transaction', 'Update')) { + return; + } + //开启编辑功能 + this.doubleEdit = true; + //开启指定列可以编辑 + //**注意,开启字段的编辑信息,如果调用框架的保存方法,代码生成器中必须设置了编辑行并生成了model否则验证通不过 + this.columns.forEach(column => { + if (column.field == "Describe" || column.field == "Name") { + column.edit = { type: "text" } + } + if (column.field == "TransactionType") { + column.edit = { type: "switch" } + } + if (column.field == "CowType") { + column.edit = { type: "select" } + } + }) + //动态添加操作列 + this.columns.push({ field: "操作", title: "操作",align:"center", width: 120, render: this.getRender() }) + }, + endEditBefore(row, column, index) { + //可以自动结束编辑时,自动执行保存,下面getRender的保存按钮去掉 + // this.editSave(); + return true; + }, + editSave(row) { + //调用框架的默认保存方法 + this.http.post("/api/App_Transaction/update", { mainData: row }, true).then(x => { + this.$Message.info("保存成功") + console.log('保存结果:' + JSON.stringify(x)); + }) + }, + getRender() {//生成最后一列操作列 + return (h, { row, column, index }) => { + return h("div", { style: { color: '#0c83ff', 'font-size': '13px', cursor: 'pointer' } }, [ + h( + "a", + { + props: {}, + style: { "border-bottom": "1px solid" }, + onClick: (e) => { + e.stopPropagation(); + //取消其他行选中 + this.$refs.table.$refs.table.clearSelection(); + //设置当前后选中 + this.$refs.table.$refs.table.toggleRowSelection(row); + this.del([row]); + } + }, + "删除" + ), + h( + "a", + { + props: {}, + style: { "margin-left": "9px", "border-bottom": "1px solid" }, + onClick: (e) => { + e.stopPropagation(); + //将当前行设置为编辑行 + this.$refs.table.edit.rowIndex = index; + } + }, + "编辑" + ), + h( + "a", + { + props: {}, + style: { "margin-left": "9px", "border-bottom": "1px solid" }, + onClick: (e) => { + e.stopPropagation(); + //强制结束编辑 + this.$refs.table.edit.rowIndex = -1; + //执行保存方法 + this.editSave(row); + }, + }, + "保存" + ), + ]); + }; + }, + } +}; +export default extension; diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_TransactionAvgPrice.js b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_TransactionAvgPrice.js new file mode 100644 index 0000000000000000000000000000000000000000..666536a195c3ba055e3a45f29c46073f9188719f --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/App_TransactionAvgPrice.js @@ -0,0 +1,64 @@ + +import { h, resolveComponent } from 'vue'; +let extension = { + components: { + //动态扩充组件或组件路径 + //表单header、content、footer对应位置扩充的组件 + gridHeader: '', //{ template: "
扩展组xx件
" }, + gridBody: { + render() { + return [ + h(resolveComponent('el-alert'), { + style: { 'margin-bottom': '12px' }, + 'show-icon': true, type: 'warning', + closable: false, title: 'onInit中设置this.maxBtnLength = 7;指定按钮显示的个数。见代码:App_TransactionAvgPrice.js' + }, ''), + ] + } + }, + gridFooter: "", + //弹出框(修改、编辑、查看)header、content、footer对应位置扩充的组件 + modelHeader: "", + modelBody: "", + modelFooter: "" + }, + text: + "还没想好", + buttons: [], //扩展的按钮 + methods: { + //事件扩展 + onInit() { + //设置页面上显示的按钮个数(不是必须的) + this.maxBtnLength = 7; + //this.boxButtons弹出框的按钮,this.detailOptions.buttons,同样适用上面上方法 + //2021.07.17更新volform.vue组件后才能使用 + this.editFormOptions.forEach(x => { + x.forEach(option => { + if (option.field == "Date") { + option.min = "2021-07-01 00:00"; + option.max = Date.now();//日期最大值"2021-07-20 00:00" + } + + }) + }) + this.columns.forEach(option => { + if (option.field == 'AgeRange') { + option.normal = true; + } + }) + //如果要设置查询的日期范围选择同上 + //this.searchFormOptions.forEach + + //设置显示所有查询条件 + // this.setFiexdSearchForm(true); + }, + onInited() { + //设置表高度 + this.height = this.height - 50; + }, + rowClick({ row, column, event }) { //查询界面table点击行时选中当前行 + this.$refs.table.$refs.table.toggleRowSelection(row); + }, + } +}; +export default extension; diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/news_article.js b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/news_article.js new file mode 100644 index 0000000000000000000000000000000000000000..394bb4bf645a17abdc64442e2225dbd783825e05 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/news_article.js @@ -0,0 +1,17 @@ +let extension = { + components: {//动态扩充组件或组件路径 + //表单header、content、footer对应位置扩充的组件 + gridHeader:'',//{ template: "
扩展组xx件
" }, + gridBody: '', + gridFooter: '', + //弹出框(修改、编辑、查看)header、content、footer对应位置扩充的组件 + modelHeader: '', + modelBody: '', + modelFooter: '' + }, + buttons: [],//扩展的按钮 + methods: {//事件扩展 + + } +}; +export default extension; \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/vProvinceCity.js b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/vProvinceCity.js new file mode 100644 index 0000000000000000000000000000000000000000..394bb4bf645a17abdc64442e2225dbd783825e05 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/appmanager/vProvinceCity.js @@ -0,0 +1,17 @@ +let extension = { + components: {//动态扩充组件或组件路径 + //表单header、content、footer对应位置扩充的组件 + gridHeader:'',//{ template: "
扩展组xx件
" }, + gridBody: '', + gridFooter: '', + //弹出框(修改、编辑、查看)header、content、footer对应位置扩充的组件 + modelHeader: '', + modelBody: '', + modelFooter: '' + }, + buttons: [],//扩展的按钮 + methods: {//事件扩展 + + } +}; +export default extension; \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/order/App_Appointment.js b/Pure_Vite_Net7/Vue3Vite/src/extension/order/App_Appointment.js new file mode 100644 index 0000000000000000000000000000000000000000..b7ed6baa4d92e67cdd575b92ffd38c78d4f5ca7e --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/order/App_Appointment.js @@ -0,0 +1,70 @@ + +import { h, resolveComponent } from 'vue'; +let extension = { + components: {//动态扩充组件或组件路径 + //表单header、content、footer对应位置扩充的组件 + gridHeader: '', + gridBody: { + render() { + return h(resolveComponent('ElAlert'), { + style: { 'margin-bottom': '12px' }, + 'show-icon': true, + type: 'success', + closable: false, + }, [h('p', {}, '1、 onInit(){ this.setFiexdSearchForm(true); //设置固定显示所有查询条件}'), + h('p', {}, ' 2、 可在扩展js中的onInit方法设置this.tableHeight/tableMaxHeight属性,指定table高度(默认自适应),如果设置 了tableMaxHeight属性,tableHeight则不会生效)')]); + } + }, + gridFooter: '', + //弹出框(修改、编辑、查看)header、content、footer对应位置扩充的组件 + modelHeader: '', + modelBody: '', + modelFooter: '' + }, + buttons: [],//扩展的按钮 + tableAction: "App_Appointment",//指定菜单权限,其他任何页面引用时都会走对应权限 + text: "可在代码生成器中设置[是否只读]或如果没有编辑或新建权限,弹出框都是只读的", + methods: {//事件扩展 + onInit() { + //设置表的最大高度 + this.tableMaxHeight = 300; + + + //设置显示所有查询条件 + this.setFiexdSearchForm(true); + this.searchFormOptions[0][0].onKeyPress = ($event) => { + if ($event.keyCode == 13) { + + } + console.log($event) + } + + //格式化单格颜色 + this.columns.forEach(x => { + if (x.field == "PhoneNo") { + x.cellStyle = (row, rowIndex, columnIndex) => { + if (row.PhoneNo == "138888887698" && rowIndex == 0) { + return { background: "#ddecfd" } + } + } + } + if (x.field == "Creator") { + x.cellStyle = (row, rowIndex, columnIndex) => { + if (row.Creator == "超级管理员") { + return { background: "#f3f3f3" } + } + } + } + }) + }, + onInited() { + //多页签打开时,重新设置表格的最大高度 + if (this.$route.path == "/tabsTable") { + this.tableMaxHeight = document.body.clientHeight - 415; + } + //移除快捷查询 + this.singleSearch = null; + }, + } +}; +export default extension; \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/order/App_Appointment/App_AppointmentGridFooter.vue b/Pure_Vite_Net7/Vue3Vite/src/extension/order/App_Appointment/App_AppointmentGridFooter.vue new file mode 100644 index 0000000000000000000000000000000000000000..575972a65b8ec91d8acb6205ef094d48728db66a --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/order/App_Appointment/App_AppointmentGridFooter.vue @@ -0,0 +1,205 @@ + + + + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/order/App_Appointment2.js b/Pure_Vite_Net7/Vue3Vite/src/extension/order/App_Appointment2.js new file mode 100644 index 0000000000000000000000000000000000000000..1e5ff7ab0c3f3356aa10045c7c2b37585ce8b3a2 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/order/App_Appointment2.js @@ -0,0 +1,60 @@ + +import { h, resolveComponent } from 'vue'; +let extension = { + components: {//动态扩充组件或组件路径 + //表单header、content、footer对应位置扩充的组件 + gridHeader: '', + gridBody: { + render() { + return h(resolveComponent('ElAlert'), { + style: { 'margin-bottom': '12px' }, + 'show-icon': true, + type: 'success', + closable: false, + }, [h('p', {}, '1、 onInited中重新定义表头数据,2021.01.08更新voltable.vue后才能使用'), + h('p', {}, ' 2、具体见:App_Appointment2.js中配置(现在只支持到二级表头、不支持编辑与复杂操作)')]); + } + }, + gridFooter: '', + //弹出框(修改、编辑、查看)header、content、footer对应位置扩充的组件 + modelHeader: '', + modelBody: '', + modelFooter: '' + }, + tableAction:"App_Appointment", + text: "页面全部由代码生成器生成,只需要在onInited中重新配置表头数据", + methods: {//事件扩展 + onInit() { + //设置表的最大高度 + this.tableMaxHeight = 300; + }, + onInited() { + this.columns.splice(0); + this.columns.push(...[ + { + field: 'Name', title: '基础信息', type: 'string', align: 'center', + children: [ + { field: 'Name', title: '用户姓名', type: 'string', link: true, width: 100, sortable: true }, + { field: 'PhoneNo', title: '电话', type: 'string', width: 130 }, + { field: 'Describe', title: '描述信息', type: 'string', width: 180 }, + ] + }, + { + field: 'Name', title: '创建人信息', type: 'string', align: 'center', + children: [ + { field: 'Id', title: '主键ID', type: 'string', width: 90, hidden: true }, + { field: 'CreateDate', title: '创建时间', type: 'datetime', width: 120, sortable: true }, + { field: 'Creator', title: '创建人', type: 'string', width: 130, align: 'left' }] + }, + { + field: 'Name', title: '修改人信息', type: 'string', align: 'center', + children: [ + { field: 'Modifier', title: '修 改 人', type: 'string', width: 130, align: 'left' }, + { field: 'ModifyDate', title: '修改时间', type: 'datetime', width: 150, sortable: true }] + } + ] + ) + } + } +}; +export default extension; \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrder.js b/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrder.js new file mode 100644 index 0000000000000000000000000000000000000000..452ea6cb1f0274f1a47362faf37653a3f11b5400 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrder.js @@ -0,0 +1,375 @@ +//1、此文件中的代码都是对基础业务进行扩展,也只能在此处编写代码,其他地方编写的代码会被代码生成器生成的代码覆盖 +//2、此文件中的方法会与serviceFilter.js进行合并,终终执行的就是此文件中的方法 +//3、components为扩展组件,可自定义页面的头部、body及尾部的额外显示的内容,分别对应的组件为: +//gridHeader、gridBody、gridFooter、modelHeader、modelBody、modelFooter共6个组件位置,如果不需要扩展组件,请忽略此处 +//4、text为界面显示额外描述信息 +//5、buttons->view/box/detail分别为查询界面、弹出框、弹出框明细表额外扩展的按钮 +//6、methods为整个页面所有方法的业务代码扩展,如果需要在界面上的操作前、后编写业务,请覆盖此方法 +//7、methods方法中可获取任意vue对象、方法、属性,可查看ViewGridConfig路径下的js文件及ViewGrid.vue的data属性 +//如手动刷新表数据:this.search(); +//获取表的列配置信息:this.columns 明细表表的配置信息this.detail.columns +//8、获取子组件gridHeader、gridBody、gridFooter、modelHeader、modelBody、modelFooter则使用 +//this.$refs.gridHeader获取gridHeader为自己扩展的对象 +//9、在子组件gridHeader、gridBody、gridFooter、modelHeader、modelBody、modelFooter的方法中调用并获得父组件 +// this.$emit("parentCall", $vue => {}) //$vue为父组件对象,具体使用参考order->GridHeaderExtend.vue文件 + +//10、子父件传参除8、9方式,另可使用已封装的vuex,使用方式:this.$store.getters.data().xxx = this;使用实例:App_News.js + +//此处的下面的属性与方法都是对基础业务代码的扩展,如果不需要扩展则忽略对应的方法也不要写在下面 +//serviceFilter.js +//所的文件都最终会合并到ViewGrid.vue文件中 + +import { h, resolveComponent } from 'vue'; +import gridHeader from "./SellOrderComponents/GridHeaderExtend.vue" +import gridFooter from "./SellOrderComponents/GridFooterExtend.vue" +import modelFooter from "./SellOrderComponents/ModelFooter.vue" +import modelBody from "./SellOrderComponents/ModelBody.vue" +let extension = { + components: {//动态扩充组件或组件路径 + //表单header、content、footer对应位置扩充的组件 + gridHeader: gridHeader, + gridBody: { + render() { + return [ + h(resolveComponent('el-alert'), { + style: { 'margin-bottom': '12px' }, + 'show-icon': true, type: 'warning', + closable: false, title: '一对一全部由代码生成不需要写任何代码,点击新建或编辑查看明细表,可根据需要实现扩展gridHeader、gridBody、gridFooter、modelHeader、modelBody、modelFooter任意位置' + }, ''), + ] + } + }, + gridFooter: gridFooter, + //弹出框(修改、编辑、查看)header、content、footer对应位置扩充的组件 + modelHeader: "", + modelBody: modelBody, + modelFooter: modelFooter, + }, + text: "示例覆盖全部可扩展方法,前台扩展文件SellOrder.js,后台Partial->SellOrdeService.cs", + //this.filterPermission('表名','权限值,如:Add')来判断页面上是否有某个按钮的权限 + buttons: { //根据需要自行实现扩展按钮 + //注:没有编辑或新建权限的情况下,是不会显示此处添加的扩展按钮,如果仍需要显示此处的按钮,可以把按钮在methods的onInited方法中添加,如:this.boxButtons.push(...) + view: [//ViewGrid查询界面按钮 + { + name: "点我", + icon: 'md-create', + value: 'Edit', + class: '', + type: 'primary', + index: 1,//显示的位置 + onClick: function () { //扩展按钮执行事件 + //this可以获取所有属性,包括this.$refs.gridHeader/gridBody等获取扩展组件对象 + // this.$message("测试扩展按钮"); + this.$refs.gridHeader.model = true; + } + }, { + name: "调用后台", + icon: 'md-create', + value: 'Edit', + class: '', + type: 'primary', + index: 1,//显示的位置 + onClick: function () { //扩展按钮执行事件 + this.getServiceDate(); + } + } + ], + box: //新建、编辑弹出框按钮 + [//ViewGrid查询界面按钮 + { + name: "点我1", + icon: 'el-icon-delete', + value: 'Edit', + class: '', + type: 'success', + index: 1,//显示的位置 + onClick: function () { + this.$message.error("扩展的明细Box按钮,可设置index值指定显示位置,可使用this.$refs拿到包括自定义扩展的所有组件"); + } + }], + detail: //新建、编辑弹出框明细表table表按钮 + [//ViewGrid查询界面按钮 + { + name: "点我2", + icon: 'el-icon-delete', + value: 'Edit', + class: '', + type: 'success', + index: 1,//显示的位置 + onClick: function () { + this.$message.error("扩展的明细table按钮,可设置index值指定显示位置"); + } + }] + },//扩展的按钮 + methods: { + //扩展方法使用示例,根据需要实行下面的方法 + getServiceDate() { + this.http.post("/api/SellOrder/getServiceDate", {}, '正在调用后台数据').then(date => { + this.$message.error("从后台获取的服务器时间是:" + date); + }) + }, + mounted() { + this.$message.success('mounted方法执行时,你可以此处编写业务逻辑'); + }, + //方式1,通过select选择触发显示与隐藏 + onInit() { + //获取订单类型select配置,当前订单类型select改变值时,动态设置Remark,SellNo两个字段是否显示 + var orderTypeOption = this.getFormOption("OrderType"); + orderTypeOption.onChange = (val) => { + //当订单类型select改变值时,如果选中的是发货(对应字典编号为2),emark,SellNo隐藏,否则显示出来 + var remarkOption = this.getFormOption("Remark").hidden = val == "2" + var sellNoOption = this.getFormOption("SellNo").hidden = val == "2" + } + + //点击单元格编辑与结束编辑(默认是点击单元格编辑,鼠标离开结束编辑) + this.detailOptions.clickEdit = true; + + //设置主表合计 + this.summary = true; + //设置明细表合计 + this.detailOptions.summary = true; + //表格设置为单选 + // this.single=true; + // this.detailOptions.single=true; + //设置编辑表单数量字段的最小与最大值 + this.editFormOptions.forEach(x => { + x.forEach(item => { + //设置输入的数量的最小值与最大值(默认是1) + if (item.field == "Qty") { + item.min = 10; + item.max = 200; + } + }); + }) + + //动态修改table并给列添加事件 + this.columns.forEach(x => { + if (x.field == "Qty") { + x.formatter = (row) => { + return '' + row.Qty + "(弹出框)" + '' + } + x.click = (row, column, event) => { + this.$refs.gridHeader.model = true; + } + } + }) + + //动态设置查询界面table高度 + this.tableMaxHeight = 300; + + }, + onInited() { + //设置主表求字段,后台需要实现SummaryExpress方法 + this.columns.forEach(x => { + if (x.field == 'Qty') { + x.summary = true; + } + }) + //设置明细表高度 + this.detailOptions.height = 220; + this.boxOptions.height=document.body.clientHeight*0.90; + //设置明细表求字和段,后台需要实现GetDetailSummary方法 + this.detailOptions.columns.forEach(x => { + if (x.field == 'Weight' || x.field == 'Qty') { + x.summary = true; + } + }) + // this.$message.success('create方法执行后', desc: '你可以SellOrder.js中编写业务逻辑,其他方法同样适用' }); + }, + searchBefore(param) { //查询ViewGird表数据前,param查询参数 + //你可以指定param查询的参数,处如果返回false,则不会执行查询 + // this.$message.success(this.table.cnName + ',查询前' }); + // console.log("扩展的"this.detailOptions.cnName + '触发loadDetailTableBefore'); + return true; + }, + searchAfter(result) { //查询ViewGird表数据后param查询参数,result回返查询的结果 + this.$notify({ + title: '查询结果', + message: '返回的对象:' + JSON.stringify(result), + type: 'success' + }); + return true; + }, + searchDetailBefore(param) {//查询从表表数据前,param查询参数 + // this.$message.success(this.detailOptions.cnName + '查询前' }); + return true; + }, + searchDetailAfter(data) {//查询从表后param查询参数,result回返查询的结果 + this.$notify({ + title: '明细查询结果', + message: '返回的对象:' + JSON.stringify(data), + type: 'success' + }); + return true; + }, + delBefore(ids, rows) { //查询界面的表删除前 ids为删除的id数组,rows删除的行 + let auditStatus = rows.some(x => { return x.AuditStatus > 0 }); + if (auditStatus) { + this.$message.error('只能删除未审核的数据') + return false; + } + this.$message.success('删除前,选择的Id:' + ids.join(',')); + return true; + }, + delAfter(result) {//查询界面的表删除后 + return true; + }, + delDetailRow(rows) { //弹出框删除明细表的行数据(只是对table操作,并没有操作后台) + console.log(rows) + return true; + }, + addBefore(formData) { //新建保存前formData为对象,包括明细表 + //formData格式: + // { + // mainData: { 主表字段1: 'x1', 主表字段2: 'x2' }, + // detailData: [{ 明细表字段1: d1 }], + // delKeys: null //删除明细表行数据的id + // } + + //formData.mainData.xxx="xxxx";//还可以继续手动添加值 + + //如果需要同时提交其他数据到后台,请设置formData.extra=xxxx + //后台在表xxxxService.cs中重写Add方法即可从saveDataModel参数中拿到extra提交的对象 + this.$message.success(this.detailOptions.cnName + '新建前,提交的数据:' + JSON.stringify(formData)); + return true; + }, + async addBeforeAsync(formData) { + //2020.12.06增加新建前异步方法同步处理 + //功能同上,区别在于此处可以做一些异步请求处理,全: + // var _result = await this.http.post("/api/SellOrder/getPageData", {}, true).then(result => { + // console.log("1、异步请求前") + // return result; + // }) + // console.log("2、异步请求,同步处理结果:" + JSON.stringify(_result)) + return true; + }, + addAfter(result) {//新建保存后result返回的状态及表单对象 + this.$message.success(this.detailOptions.cnName + '新建完成后,返回的数据' + JSON.stringify(result)); + return true; + }, + updateBefore(formData) { //编辑保存前formData为对象,包括明细表、删除行的Id + //formData格式:(自己调试出输看) + // { + // mainData: { 主表字段1: 'x1', 主表字段2: 'x2' }, + // detailData: [{ 明细表字段1: d1 }], + // delKeys: null //删除明细表行数据的id + // } + + //formData.mainData.xxx="xxxx";//还可以继续手动添加值 + + //如果需要同时提交其他数据到后台,请设置formData.extra=xxxx + //后台在表xxxxService.cs中重写Update方法即可从saveDataModel参数中拿到extra提交的对象 + + this.$message.success(this.detailOptions.cnName + '编辑前,提交的数据:' + JSON.stringify(formData)); + //获取扩展的modelFooter属性text + console.log(this.$refs.modelFooter.text) + return true; + }, + async updateBeforeAsync(formData) { + //2020.12.06增加修改前异步方法同步处理 + //功能同上,区别在于此处可以做一些异步请求处理,全: + var _result = await this.http.post("/api/SellOrder/getPageData", {}, true).then(result => { + console.log("1、异步请求前") + return result; + }) + console.log("2、异步请求,同步处理结果:" + JSON.stringify(_result)) + return true; + }, + updateAfter(result) {//编辑保存后result返回的状态及表单对象 + this.$message.success(this.detailOptions.cnName + '编辑完成后,返回的数据' + JSON.stringify(result)); + return true; + }, + auditBefore(ids, rows) {//审核前 + if (rows.length > 2) {//每次最多只能审核2条数据 + this.$message.error('最多只能选择两条数据'); + return false; + } + return true; + }, + auditAfter(result, rows) {// 审核后 + if (result.status) { + result.message = "审核成功。。。。。" + result.message; + } + return true; + }, + resetAddFormBefore() { //重置新建表单前的内容 + return true; + }, + resetAddFormAfter() { //重置新建表单后的内容 + //如果某些字段不需要重置,则可以重新赋值 + this.editFormFields.Remark = '新建重置默认值66666'; + //给明细表添加默认一行 + this.$refs.detail.rowData.push({ Remark: "新建666666" }); + return true; + }, + resetUpdateFormBefore() { //重置编辑表单前的内容 + //this.editFormFields当前值 + console.log(this.editFormFields) + //当前明细表的行 + console.log(this.$refs.detail.rowData) + return true; + }, + resetUpdateFormAfter() { //重置编辑表单后的内容 + //如果某些字段不需要重置,则可以重新赋值 + this.editFormFields.Remark = '编辑重置默认值66666'; + //给明细表添加默认一行 + this.$refs.detail.rowData.push({ Remark: "编辑666666" }); + return true; + }, + importAfter(data) { //导入excel后刷新table表格数据 + this.search(); //刷新table + }, + modelOpenBefore(row) { //点击编辑/新建按钮弹出框前,可以在此处写逻辑,如,从后台获取数据 + + }, + async modelOpenBeforeAsync(row) { //点击编辑/新建按钮弹出框前,可以在此处写逻辑,如,从后台获取数据 + //2021.01.10 + if (row) { + console.log("编辑操作") + } else { + console.log("新建操作") + } + //打开弹出框前,http请求同步执行 + // var _result = await this.http.post("url", {}, true).then(result => { + + // _result = result; + // }) + // console.log(result); + //返回false不会弹出框 + //this.$message.error("不能打开弹出框 "); + return true; + }, + getFormOption(field) { + let option; + this.editFormOptions.forEach(x => { + x.forEach(item => { + if (item.field == field) { + option = item; + } + }) + }) + return option; + }, + + //方式2,通过打开弹出框时触发显示与隐藏 + modelOpenAfter(row) { //编辑或新建时,根据不同的情况控制字段是否显示 + // this.editFormOptions.forEach(x => { + // x.forEach(item => { + // if (item.field == "Remark" || item.field == "SellNo") { + // //如果不是新建,则隐藏Remark,SellNo两个字段是否显示 + // //也可以根据row当前编辑行的值来处理 + // this.$set(item, "hidden", this.currentAction != "Add") + // } + // }) + // }) + }, + rowClick({ row, column, event }) { //查询界面table点击行选中当前行 + this.$refs.table.$refs.table.toggleRowSelection(row); + }, + // detailRowClick ({ row, column, event }) { + // //编辑弹出框从表table点击行选中当前行,没有从表的不用管 + // this.$refs.detail.$refs.table.toggleRowSelection(row); + // } + } +}; +export default extension; diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrder2.js b/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrder2.js new file mode 100644 index 0000000000000000000000000000000000000000..f746c38d59f341fa3d6056870eb91443533c0c88 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrder2.js @@ -0,0 +1,96 @@ +import gridFooter from "./SellOrder2/SellOrder2GridFooter.vue" + +//自定义从表选择数据源页面 +import modelBody from "./SellOrder2/SellOrder2ModelBody.vue" +import { h, resolveComponent } from 'vue'; +let extension = { + components: {//动态扩充组件或组件路径 + //表单header、content、footer对应位置扩充的组件 + gridHeader: '',//{ template: "
扩展组xx件
" }, + gridBody: { + render() { + return [ + h(resolveComponent('el-alert'), { + style: { 'margin-bottom': '12px' }, + 'show-icon': true, type: 'success', + closable: false, title: '界面由代码生成器生成,只需几行代码即可实现点击主表行显示明细表数据(直接扩展gridFooter位置的代码,具体代码见此示例:SellOrder2.js)' + }, ''), + ] + } + }, + gridFooter: gridFooter, + //弹出框(修改、编辑、查看)header、content、footer对应位置扩充的组件 + modelHeader: "", + modelBody: modelBody,//自定义从表选择数据源页面 + modelFooter: "", + }, + text: "点击主表行加载明细表数据,如果本地看不到此菜单,可以按照演示环境配置下此页面菜单", + buttons: { //根据需要自行实现扩展按钮 + },//扩展的按钮 + methods: { + mounted() { + }, + //方式1,通过select选择触发显示与隐藏 + onInit() { + //点击单元格编辑与结束编辑(默认是点击单元格编辑,鼠标离开结束编辑) + this.detailOptions.clickEdit = true; + //设置主表合计 + this.summary = true; + }, + onInited() { + //调整界面table高度 + this.height = this.height - 310; + + //明细表选择数据源操作 + //获取明细表备注列,给备注列添加选择数据操作 + let _column = this.detailOptions.columns.find(x => { return x.field == "Remark" }); + _column.title="(备注)点击选择数据" + //移除编辑操作 + _column.edit = null; + //给备注列添加选择数据操作 + _column.render = (h, { row, column, index }) => { + return h("div", { style: {} }, + [ + h("i", { + class: ["el-icon-zoom-out"], + style: { + cursor: "pointer", + "margin-right": "8px", + color: "#409eff", + }, + onClick: (e) => { + e.stopPropagation(); + //弹出选择数据源 + this.$refs.modelBody.open(row); + }, + }), + ], row.Remark) + }; + }, + // rowDbClick({ row, column, event }){//双击事件 + // }, + rowClick({ row, column, event }) { //查询界面table点击行选中当前行 + //取消其他行选中 + this.$refs.table.$refs.table.clearSelection(); + //设置选中当前行 + this.$refs.table.$refs.table.toggleRowSelection(row); + if (this.$refs.gridFooter && this.$refs.gridFooter.$refs.tableList) { + //load方法可参照voltable组件api文档 + this.$refs.gridFooter.$refs.tableList.load({ value: row.Order_Id, sort: "CreateDate" }) + } + }, + searchAfter(rows) { + //页面加载或者刷新数据后直接显示第一行的明细 + if (rows.length) { + // this.$nextTick(() => { + this.$refs.gridFooter.$refs.tableList.load({ value: rows[0].Order_Id, sort: "CreateDate" }) + // }) + } else { + //没有数据时,清空明细数据 + this.$refs.gridFooter.$refs.tableList.rowData.splice(0) + } + return true; + } + } +}; +export default extension; diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrder2/SellOrder2GridFooter.vue b/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrder2/SellOrder2GridFooter.vue new file mode 100644 index 0000000000000000000000000000000000000000..a53cb3c80c4ea5b0887dae22f51ad3b5c162ad5e --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrder2/SellOrder2GridFooter.vue @@ -0,0 +1,59 @@ + + + + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrder2/SellOrder2ModelBody.vue b/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrder2/SellOrder2ModelBody.vue new file mode 100644 index 0000000000000000000000000000000000000000..8ad9432b1dfc01dbc58d91936efc9a53f5bf5abc --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrder2/SellOrder2ModelBody.vue @@ -0,0 +1,131 @@ + + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrder3.js b/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrder3.js new file mode 100644 index 0000000000000000000000000000000000000000..b348fabeac349a211123a32fb187b80993292175 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrder3.js @@ -0,0 +1,69 @@ + +import SellOrder3GridFooter from "./SellOrder3/SellOrder3GridFooter.vue" +let extension = { + components: {//动态扩充组件或组件路径 + //表单header、content、footer对应位置扩充的组件 + gridHeader: '',//{ template: "
扩展组xx件
" }, + gridBody:'', + gridFooter: SellOrder3GridFooter, //() => import("./SellOrder3/SellOrder3GridFooter.vue"), + //弹出框(修改、编辑、查看)header、content、footer对应位置扩充的组件 + modelHeader: "", + modelBody: '', + modelFooter: "", //() => import("./SellOrderComponents/ModelFooter.vue"), + }, + text: "用法与【主从一对一(2)】一致(见SellOrder3.js)", + buttons: { //根据需要自行实现扩展按钮 + },//扩展的按钮 + methods: { + mounted() { + }, + //方式1,通过select选择触发显示与隐藏 + onInit() { + //设置为单选,用于明细表加载数据时获取主表选行的id + this.single = true; + }, + onInited() { + this.height = this.height - 350; + }, + + rowClick({ row, column, event }) { //查询界面table点击行选中当前行 + this.$refs.table.$refs.table.toggleRowSelection(row); + if (this.$refs.gridFooter && this.$refs.gridFooter.$refs.tableList) { + //添加明细表的数据(触发明细表加载数据,见SellOrder3GridFooter方法loadBefore) + //load方法可参照voltable组件api文档 + this.$refs.gridFooter.$refs.tableList.load() + } + }, + searchAfter(rows) { + //页面加载或者刷新数据后直接显示第一行的明细 + if (rows.length) { + // this.$nextTick(() => { + this.$refs.gridFooter.$refs.tableList.load({ value: rows[0].Order_Id, sort: "CreateDate" }) + // }) + } else { + //没有数据时,清空明细数据 + this.$refs.gridFooter.$refs.tableList.rowData.splice(0) + } + return true; + }, + modelOpenAfter() { + //新建弹出框时,设置设置默认订单类型 + if (this.currentAction == "Add") { + this.editFormOptions.forEach(item => { + item.forEach(x => { + //如果是编辑帐号设置为只读 + if (x.field == "OrderType") { + //新建时默认选择中第一个下拉框的值,如果要选中其他的值,请遍历x.data获取key + /*注意:如果下拉框的数据源是自定义sql,并且key是数字,请将(x.data[0].key*1)转换成数字*/ + this.editFormFields.OrderType = x.data[0].key; + //可以指定其他input标签的默认值 + this.editFormFields.TranNo="8888" + } + }) + + }) + } + } + } +}; +export default extension; diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrder3/SellOrder3GridFooter.vue b/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrder3/SellOrder3GridFooter.vue new file mode 100644 index 0000000000000000000000000000000000000000..ec38f3a4288ba87e816999aee687da763049d725 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrder3/SellOrder3GridFooter.vue @@ -0,0 +1,235 @@ + + + + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrderComponents/GridBodyExtend.vue b/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrderComponents/GridBodyExtend.vue new file mode 100644 index 0000000000000000000000000000000000000000..180762adb52495b3c1b10ca1798db5bfcd3d5261 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrderComponents/GridBodyExtend.vue @@ -0,0 +1,33 @@ + + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrderComponents/GridFooterExtend.vue b/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrderComponents/GridFooterExtend.vue new file mode 100644 index 0000000000000000000000000000000000000000..c1c6b521b91e02705641be158fcd817f8e8cb127 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrderComponents/GridFooterExtend.vue @@ -0,0 +1,20 @@ + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrderComponents/GridHeaderExtend.vue b/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrderComponents/GridHeaderExtend.vue new file mode 100644 index 0000000000000000000000000000000000000000..6135891e2757af3f7a83a6278a2e34e5a07223fd --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrderComponents/GridHeaderExtend.vue @@ -0,0 +1,39 @@ + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrderComponents/ModelBody.vue b/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrderComponents/ModelBody.vue new file mode 100644 index 0000000000000000000000000000000000000000..7e72696878009f81328a15207ae1fa6d47b4c3a5 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrderComponents/ModelBody.vue @@ -0,0 +1,40 @@ + + + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrderComponents/ModelFooter.vue b/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrderComponents/ModelFooter.vue new file mode 100644 index 0000000000000000000000000000000000000000..96cc2e61b282250b0a4ed1c946ebaec0bfbbca3f --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/order/SellOrderComponents/ModelFooter.vue @@ -0,0 +1,17 @@ + + + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/order/vSellOrderImg.js b/Pure_Vite_Net7/Vue3Vite/src/extension/order/vSellOrderImg.js new file mode 100644 index 0000000000000000000000000000000000000000..5db7a37ac8977001d46638fdeca03b55cd0d0517 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/order/vSellOrderImg.js @@ -0,0 +1,76 @@ + +import { h, resolveComponent } from 'vue'; +import modelBody from "./vSellOrderImg/vSellOrderImgModelBody.vue" +let extension = { + components: {//动态扩充组件或组件路径 + gridHeader: '', + gridBody: { + render() { + return h(resolveComponent('el-alert'), { + type: "success", + style: { 'margin-bottom': '12px' }, + 'show-icon': false, + closable: false, + }, '点击新建、编辑弹出框,可以对明细表进行上传文件或者图片操作,见vSellOrderImg.js') + } + }, + gridFooter: '', + modelHeader: "", + //点击上传图片的弹出框 + modelBody: modelBody, + modelFooter: "", + }, + text: "一对一从表编辑上传图片", + methods: { + onInit() { + }, + onInited() { + this.height = this.height - 56; + //获取图片位置,在图片后面加一个上传按钮,这里只是演示随便找的一个字段存图片 + let _index = this.detailOptions.columns.findIndex(x => { return x.field == 'Remark' }); + + //这里只是演示,实际操作在代码生成器table显示类型设置为图片后这里就不用操作了 + //代码生成器中编辑行号设置为0,不要设置为大于0的数据 + this.detailOptions.columns[_index].edit = null; + this.detailOptions.columns[_index].type = 'img'; + this.detailOptions.columns[_index].title = '图片'; + + //从表动态添加一列(上传图片列),生成上传图片、与删除图片操作 + this.detailOptions.columns.splice(_index, 0, { + field: "随便写", + title: "上传图片", + width: 150, + align: "center", + render: (h, { row, column, index }) => { + //下面所有需要显示的信息都从row里面取出来 + return h( + "div", { style: { color: '#0c83ff', 'font-size': '13px', cursor: 'pointer' } }, + [ + h( + "i", { + style: { 'margin-right': '10px' }, + class:['el-icon-upload'], + onClick: (e) => { + e.stopPropagation(); + //记住当前操作的明细表行数据 + //如果原来有图片,上传图片界面把原来的图片也显示出来 + let fileInfo = (row.Remark || '').split(",").filter(x => { return x }).map(img => { + //(生成文件格式) fileInfo格式参数,见volupload组件 + return { path: img, name: "" }; + }) + this.$refs.modelBody.open(fileInfo, row) + } + }, [], '上传图片' + ), + h('i', { + class: ['el-icon-delete'], onClick: (e) => { + e.stopPropagation(); row.Remark = '' + } + }, '删除图片') + ]) + }, + }) + } + } +}; +export default extension; diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/order/vSellOrderImg/vSellOrderImgModelBody.vue b/Pure_Vite_Net7/Vue3Vite/src/extension/order/vSellOrderImg/vSellOrderImgModelBody.vue new file mode 100644 index 0000000000000000000000000000000000000000..fc7ac32fbe07cba96c2c4c21f0bc25bf7a42e82d --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/order/vSellOrderImg/vSellOrderImgModelBody.vue @@ -0,0 +1,70 @@ + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/system/Sys_Dictionary.js b/Pure_Vite_Net7/Vue3Vite/src/extension/system/Sys_Dictionary.js new file mode 100644 index 0000000000000000000000000000000000000000..22d104a303206fad74f96f70e888e17c7b035a87 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/system/Sys_Dictionary.js @@ -0,0 +1,75 @@ +import { h, resolveComponent } from 'vue'; +let extension = { + components: { //动态扩充组件或组件路径 + //表单header、content、footer对应位置扩充的组件 + //扩展组件引入方式 + gridHeader: '', + gridBody: { + render () { + return [ + h(resolveComponent('el-alert'), { + style: { 'margin-bottom': '12px' }, + 'show-icon': true, type: 'error', + closable: false, title: '界面下拉框、多选、checkbox等数据源都在此处维护,也是代码生成器中的数据源' + }, ''), + ] + } + }, + gridFooter: '', + //弹出框(修改、编辑、查看)header、content、footer对应位置扩充的组件 + modelHeader: '', + modelBody: '', + modelFooter: '' + }, + buttons: [], //扩展的按钮 + methods: { //事件扩展 + onInit () { + //点击单元格编辑与结束编辑(默认是点击单元格编辑,鼠标离开结束编辑) + this.detailOptions.clickEdit = true; + this.editFormOptions.forEach(x => { + x.forEach(item => { + if (item.field == 'ParentId') { + item.min = 0; + } + if (item.field == "DbSql") { + item.placeholder = "如果从数据库加载数据源,请按此格式配置sql语句:select orderType as key,orderName as value from order 如果需要根据用户信息加载数据源,请配置好此sql,再修改后台DictionaryHandler.GetCustomDBSql方法"; + } + }) + }) + this.detailOptions.columns.forEach(x => { + if (x.field == 'OrderNo') { + x.summary = true; + } + }) + //保存后不关闭编辑框 + this.boxOptions.saveClose = false; + }, + onInited () { + this.boxOptions.height = document.body.clientHeight * 0.87 + this.height = this.height - 45; + }, + addBefore (formData) { + return this.saveBefore(formData); + }, + updateBefore (formData) { + return this.saveBefore(formData); + }, + saveBefore (formData) { + if (this.editFormFields.DbSql && + (this.editFormFields.DbSql.indexOf('value') == -1 || + this.editFormFields.DbSql.indexOf('key') == -1) + ) { + this.$message.error("sql语句必须包括key/value字段,如:select orderType as key,orderName as value from order"); + return false; + } + return true; + }, + searchBefore (param) { + return true; + }, + searchAfter (result) { + return true; + } + } +}; +export default extension; \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/system/Sys_DictionaryList.js b/Pure_Vite_Net7/Vue3Vite/src/extension/system/Sys_DictionaryList.js new file mode 100644 index 0000000000000000000000000000000000000000..da944871b3b573badf07cfe078f0fec1773b0bce --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/system/Sys_DictionaryList.js @@ -0,0 +1,22 @@ + + +let extension = { + components: {//动态扩充组件或组件路径 + //表单header、content、footer对应位置扩充的组件 + gridHeader:'', + gridbody:'', + gridFooter: '', + //弹出框(修改、编辑、查看)header、content、footer对应位置扩充的组件 + modelHeader: '', + modelBody: '', + modelFooter: '' + }, + buttons: [],//扩展的按钮 + methods: {//事件扩展 + onInit() { + }, + onInited() { + } + } +}; +export default extension; \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/system/Sys_Log.js b/Pure_Vite_Net7/Vue3Vite/src/extension/system/Sys_Log.js new file mode 100644 index 0000000000000000000000000000000000000000..5f3d9401082c1397b392bb87908c793e17883bd9 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/system/Sys_Log.js @@ -0,0 +1,26 @@ +import { h, resolveComponent } from 'vue'; +let extension = { + components: { + //动态扩充组件或组件路径 + //表单header、content、footer对应位置扩充的组件 + gridHeader: "", //{ template: "
扩展组xx件
" }, + gridBody: '', + gridFooter: "", + //弹出框(修改、编辑、查看)header、content、footer对应位置扩充的组件 + modelHeader: "", + modelBody: "", + modelFooter: "" + }, + buttons: [], //扩展的按钮 + methods: { + //事件扩展 + onInit() { + console.log("sys_log") + this.setFiexdSearchForm(true); + }, + onInited() { + this.height = this.height - 195; + } + } +}; +export default extension; diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/system/Sys_Role.js b/Pure_Vite_Net7/Vue3Vite/src/extension/system/Sys_Role.js new file mode 100644 index 0000000000000000000000000000000000000000..191d7c0d916d71c2b9882de8c0761accfec478d6 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/system/Sys_Role.js @@ -0,0 +1,38 @@ + + +let extension = { + components: {//动态扩充组件或组件路径 + //表单header、content、footer对应位置扩充的组件 + gridHeader: '', + gridBody: '', + gridFooter: '', + //弹出框(修改、编辑、查看)header、content、footer对应位置扩充的组件 + modelHeader: '', + modelBody: '', + modelFooter: '' + }, + buttons: [],//扩展的按钮 + methods: {//事件扩展 + onInit () { + this.columns.forEach(x => { + if (x.field == 'ParentId') { + x.title = "上级角色"; + } + }); + + //这些配置不是必须的 + this.editFormOptions.forEach(x => { + x.forEach(item => { + if (item.field == 'ParentId') { + item.title = "上级角色"; + //设置任意节点都能选中(默认只能选中最后一个节点) + item.changeOnSelect = true; + } + }) + }) + }, + onInited () { + } + } +}; +export default extension; diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/system/Sys_Role1.js b/Pure_Vite_Net7/Vue3Vite/src/extension/system/Sys_Role1.js new file mode 100644 index 0000000000000000000000000000000000000000..d6715be6dbe2c85a4f49cab12f9a9f0e7a73416c --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/system/Sys_Role1.js @@ -0,0 +1,61 @@ + +import { h, resolveComponent } from 'vue'; +let extension = { + components: {//动态扩充组件或组件路径 + //表单header、content、footer对应位置扩充的组件 + gridHeader: '', + gridBody: { + render () { + return [ + h(resolveComponent('el-alert'), { + style: { 'margin-bottom': '12px' }, + 'show-icon': true, type: 'error', + closable: false, title: '关于TreeTable使用' + }, ' treetable同样全部代码自动生成,页面生成后设置this.rowKe="xxx" tree主键字段,即可完成树形table配置,具体说明见Sys_Role1.js'), + ] + } + }, + + gridFooter: '', + //弹出框(修改、编辑、查看)header、content、footer对应位置扩充的组件 + modelHeader: '', + modelBody: '', + modelFooter: '' + }, + buttons: [],//扩展的按钮 + tableAction:"Sys_Role", + methods: {//事件扩展 + onInited () { + this.height = this.height - 80; + this.editFormOptions.forEach(x => { + x.forEach(item => { + if (item.field == 'ParentId') { + item.title = "上级角色"; + //设置任意节点都能选中(默认只能选中最后一个节点) + item.changeOnSelect = true; + } + }) + }) + }, + onInit() { + //设置treetable的唯一值字段(这个字段的值在表里面必须是唯一的) + this.rowKey="Role_Id"; + }, + /***加载后台数据见Sys_RoleController.cs文件***/ + loadTreeChildren(tree, treeNode, resolve) { //加载子节点 + let url=`api/role/getTreeTableChildrenData?roleId=${tree.Role_Id}`; + this.http.post(url,{}).then(result=>{ + resolve(result.rows) + }) + }, + /***加载后台数据见Sys_RoleController.cs文件***/ + searchBefore(params){//判断加载根节点或子节点 + //没有查询条件,默认查询返回所有根节点数据 + if (!params.wheres.length) { + params.value=1; + } + return true; + } + } +}; +export default extension; diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/system/Sys_User.js b/Pure_Vite_Net7/Vue3Vite/src/extension/system/Sys_User.js new file mode 100644 index 0000000000000000000000000000000000000000..4be71555dd1e943aa8fd2ff6f6ffbecdf7b138ff --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/system/Sys_User.js @@ -0,0 +1,86 @@ +import { defineAsyncComponent } from "vue"; +let extension = { + components: { //动态扩充组件或组件路径 + //表单header、content、footer对应位置扩充的组件 + gridHeader: defineAsyncComponent(() => + import("./Sys_User/Sys_UserGridHeader.vue")), + gridBody: '', + gridFooter: '', + //弹出框(修改、编辑、查看)header、content、footer对应位置扩充的组件 + modelHeader: '', + modelBody: '', + modelFooter: '' + }, + text: "只能看到当前角色下的所有帐号", + buttons: [], //扩展的按钮 + methods: { //事件扩展 + onInit() { + this.boxOptions.height = 530; + this.columns.push({ + title: '操作', + hidden: false, + align: "center", + fixed: 'right', + width: 120, + render: (h, { row, column, index }) => { + return h( + "div", { style: { 'font-size': '13px', 'cursor': 'pointer', 'color': '#409eff' } }, [ + h( + "a", { + style: { 'margin-right': '15px' }, + onClick: (e) => { + e.stopPropagation() + this.$refs.gridHeader.open(row); + } + }, "修改密码" + ), + h( + "a", { + style: {}, + onClick: (e) => { + e.stopPropagation() + this.edit(row); + } + }, + "编辑" + ), + ]) + } + }) + }, + onInited() { }, + addAfter(result) { //用户新建后,显示随机生成的密码 + if (!result.status) { + return true; + } + //显示新建用户的密码 + //2020.08.28优化新建成后提示方式 + this.$confirm(result.message, '新建用户成功', { + confirmButtonText: '确定', + type: 'success', + center: true + }).then(() => { }) + + this.boxModel = false; + this.refresh(); + return false; + }, + modelOpenAfter() { + //点击弹出框后,如果是编辑状态,禁止编辑用户名,如果新建状态,将用户名字段设置为可编辑 + let isEDIT = this.currentAction == this.const.EDIT; + this.editFormOptions.forEach(item => { + item.forEach(x => { + if (x.field == "UserName") { + x.disabled=isEDIT; + } + }) + //不是新建,性别默认值设置为男 + if (!isEDIT) { + this.editFormFields.Gender = "0"; + } + }) + } + + } +}; +export default extension; \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/system/Sys_User/Sys_UserGridHeader.vue b/Pure_Vite_Net7/Vue3Vite/src/extension/system/Sys_User/Sys_UserGridHeader.vue new file mode 100644 index 0000000000000000000000000000000000000000..9b1b965bd49c659e90923267e8bd5a0ce32ece56 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/system/Sys_User/Sys_UserGridHeader.vue @@ -0,0 +1,90 @@ + + + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/system/flow/Sys_WorkFlow.js b/Pure_Vite_Net7/Vue3Vite/src/extension/system/flow/Sys_WorkFlow.js new file mode 100644 index 0000000000000000000000000000000000000000..ae8e77f04c4619cc29491daec6085bfbfa8424a6 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/system/flow/Sys_WorkFlow.js @@ -0,0 +1,90 @@ +/***************************************************************************************** + ** Author:jxx 2022 + ** QQ:283591387 + **完整文档见:http://v2.volcore.xyz/document/api 【代码生成页面ViewGrid】 + **常用示例见:http://v2.volcore.xyz/document/vueDev + **后台操作见:http://v2.volcore.xyz/document/netCoreDev + *****************************************************************************************/ +//此js文件是用来自定义扩展业务代码,可以扩展一些自定义页面或者重新配置生成的代码 +import gridHader from './Sys_WorkFlow/WorkFlowGridHeader.vue'; +import { h, resolveComponent } from 'vue'; +let extension = { + components: { + //查询界面扩展组件 + gridHeader: gridHader, + gridBody: { + render() { + return [ + h( + resolveComponent('el-alert'), + { + style: { 'margin-bottom': '12px' }, + 'show-icon': true, + type: 'success', + closable: false, + title: '流程设计器根据easy-flow修改' + }, + '' + ) + ]; + } + }, + gridFooter: '', + //新建、编辑弹出框扩展组件 + modelHeader: '', + modelBody: '', + modelFooter: '' + }, + tableAction: '', //指定某张表的权限(这里填写表名,默认不用填写) + buttons: { view: [], box: [], detail: [] }, //扩展的按钮 + methods: { + //下面这些方法可以保留也可以删除 + onInit() { + //框架初始化配置前, + //示例:在按钮的最前面添加一个按钮 + // this.buttons.unshift({ //也可以用push或者splice方法来修改buttons数组 + // name: '按钮', //按钮名称 + // icon: 'el-icon-document', //按钮图标vue2版本见iview文档icon,vue3版本见element ui文档icon(注意不是element puls文档) + // type: 'primary', //按钮样式vue2版本见iview文档button,vue3版本见element ui文档button + // onClick: function () { + // this.$Message.success('点击了按钮'); + // } + // }); + //示例:设置修改新建、编辑弹出框字段标签的长度 + // this.boxOptions.labelWidth = 150; + }, + onInited() { + this.height = this.height - 50; + //框架初始化配置后 + //如果要配置明细表,在此方法操作 + //this.detailOptions.columns.forEach(column=>{ }); + }, + searchBefore(param) { + //界面查询前,可以给param.wheres添加查询参数 + //返回false,则不会执行查询 + return true; + }, + searchAfter(result) { + //查询后,result返回的查询数据,可以在显示到表格前处理表格的值 + return true; + }, + addBefore(formData) { + //新建保存前formData为对象,包括明细表,可以给给表单设置值,自己输出看formData的值 + return true; + }, + updateBefore(formData) { + //编辑保存前formData为对象,包括明细表、删除行的Id + return true; + }, + rowClick({ row, column, event }) { + //查询界面点击行事件 + // this.$refs.table.$refs.table.toggleRowSelection(row); //单击行时选中当前行; + }, + async modelOpenBeforeAsync(row) { + //点击编辑/新建按钮弹出框前,可以在此处写逻辑,如,从后台获取数据 + this.$refs.gridHeader.open(row); + return false; + } + } +}; +export default extension; diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/system/flow/Sys_WorkFlow/WorkFlowGridHeader.vue b/Pure_Vite_Net7/Vue3Vite/src/extension/system/flow/Sys_WorkFlow/WorkFlowGridHeader.vue new file mode 100644 index 0000000000000000000000000000000000000000..9f75874cebcfee6ae597e32fd54e288b94a40f77 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/system/flow/Sys_WorkFlow/WorkFlowGridHeader.vue @@ -0,0 +1,194 @@ + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/system/flow/Sys_WorkFlowStep.js b/Pure_Vite_Net7/Vue3Vite/src/extension/system/flow/Sys_WorkFlowStep.js new file mode 100644 index 0000000000000000000000000000000000000000..8935403f2807fbe44aef099e975ff1ea78b450ae --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/system/flow/Sys_WorkFlowStep.js @@ -0,0 +1,75 @@ +/***************************************************************************************** +** Author:jxx 2022 +** QQ:283591387 +**完整文档见:http://v2.volcore.xyz/document/api 【代码生成页面ViewGrid】 +**常用示例见:http://v2.volcore.xyz/document/vueDev +**后台操作见:http://v2.volcore.xyz/document/netCoreDev +*****************************************************************************************/ +//此js文件是用来自定义扩展业务代码,可以扩展一些自定义页面或者重新配置生成的代码 + +let extension = { + components: { + //查询界面扩展组件 + gridHeader: '', + gridBody: '', + gridFooter: '', + //新建、编辑弹出框扩展组件 + modelHeader: '', + modelBody: '', + modelFooter: '' + }, + tableAction: '', //指定某张表的权限(这里填写表名,默认不用填写) + buttons: { view: [], box: [], detail: [] }, //扩展的按钮 + methods: { + //下面这些方法可以保留也可以删除 + onInit() { //框架初始化配置前, + //示例:在按钮的最前面添加一个按钮 + // this.buttons.unshift({ //也可以用push或者splice方法来修改buttons数组 + // name: '按钮', //按钮名称 + // icon: 'el-icon-document', //按钮图标vue2版本见iview文档icon,vue3版本见element ui文档icon(注意不是element puls文档) + // type: 'primary', //按钮样式vue2版本见iview文档button,vue3版本见element ui文档button + // onClick: function () { + // this.$Message.success('点击了按钮'); + // } + // }); + + //示例:设置修改新建、编辑弹出框字段标签的长度 + // this.boxOptions.labelWidth = 150; + }, + onInited() { + //框架初始化配置后 + //如果要配置明细表,在此方法操作 + //this.detailOptions.columns.forEach(column=>{ }); + }, + searchBefore(param) { + //界面查询前,可以给param.wheres添加查询参数 + //返回false,则不会执行查询 + return true; + }, + searchAfter(result) { + //查询后,result返回的查询数据,可以在显示到表格前处理表格的值 + return true; + }, + addBefore(formData) { + //新建保存前formData为对象,包括明细表,可以给给表单设置值,自己输出看formData的值 + return true; + }, + updateBefore(formData) { + //编辑保存前formData为对象,包括明细表、删除行的Id + return true; + }, + rowClick({ row, column, event }) { + //查询界面点击行事件 + // this.$refs.table.$refs.table.toggleRowSelection(row); //单击行时选中当前行; + }, + modelOpenAfter(row) { + //点击编辑、新建按钮弹出框后,可以在此处写逻辑,如,从后台获取数据 + //(1)判断是编辑还是新建操作: this.currentAction=='Add'; + //(2)给弹出框设置默认值 + //(3)this.editFormFields.字段='xxx'; + //如果需要给下拉框设置默认值,请遍历this.editFormOptions找到字段配置对应data属性的key值 + //看不懂就把输出看:console.log(this.editFormOptions) + } + } +}; +export default extension; diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/system/flow/Sys_WorkFlowTable.js b/Pure_Vite_Net7/Vue3Vite/src/extension/system/flow/Sys_WorkFlowTable.js new file mode 100644 index 0000000000000000000000000000000000000000..35cd7a655b635595f6d727ff5b3f3745e75e6f4e --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/system/flow/Sys_WorkFlowTable.js @@ -0,0 +1,79 @@ +/***************************************************************************************** + ** Author:jxx 2022 + ** QQ:283591387 + **完整文档见:http://v2.volcore.xyz/document/api 【代码生成页面ViewGrid】 + **常用示例见:http://v2.volcore.xyz/document/vueDev + **后台操作见:http://v2.volcore.xyz/document/netCoreDev + *****************************************************************************************/ +//此js文件是用来自定义扩展业务代码,可以扩展一些自定义页面或者重新配置生成的代码 + +let extension = { + components: { + //查询界面扩展组件 + gridHeader: '', + gridBody: '', + gridFooter: '', + //新建、编辑弹出框扩展组件 + modelHeader: '', + modelBody: '', + modelFooter: '' + }, + tableAction: '', //指定某张表的权限(这里填写表名,默认不用填写) + buttons: { view: [], box: [], detail: [] }, //扩展的按钮 + methods: { + //下面这些方法可以保留也可以删除 + onInit() { + this.columns.push({ + field: '操作', + title: '查看', + width: 100, + align: 'center', + formatter: (row) => { + return '查看详情'; + }, + click: (row) => { + this.$tabs.open({ + text: row.WorkTableName, + path: '/' + row.WorkTable, + query: { id: row.WorkTableKey, viewflow: 1 } + }); + } + }); + }, + onInited() { + //框架初始化配置后 + //如果要配置明细表,在此方法操作 + //this.detailOptions.columns.forEach(column=>{ }); + }, + searchBefore(param) { + //界面查询前,可以给param.wheres添加查询参数 + //返回false,则不会执行查询 + return true; + }, + searchAfter(result) { + //查询后,result返回的查询数据,可以在显示到表格前处理表格的值 + return true; + }, + addBefore(formData) { + //新建保存前formData为对象,包括明细表,可以给给表单设置值,自己输出看formData的值 + return true; + }, + updateBefore(formData) { + //编辑保存前formData为对象,包括明细表、删除行的Id + return true; + }, + rowClick({ row, column, event }) { + //查询界面点击行事件 + // this.$refs.table.$refs.table.toggleRowSelection(row); //单击行时选中当前行; + }, + modelOpenAfter(row) { + //点击编辑、新建按钮弹出框后,可以在此处写逻辑,如,从后台获取数据 + //(1)判断是编辑还是新建操作: this.currentAction=='Add'; + //(2)给弹出框设置默认值 + //(3)this.editFormFields.字段='xxx'; + //如果需要给下拉框设置默认值,请遍历this.editFormOptions找到字段配置对应data属性的key值 + //看不懂就把输出看:console.log(this.editFormOptions) + } + } +}; +export default extension; diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/system/flow/Sys_WorkFlowTableStep.js b/Pure_Vite_Net7/Vue3Vite/src/extension/system/flow/Sys_WorkFlowTableStep.js new file mode 100644 index 0000000000000000000000000000000000000000..8935403f2807fbe44aef099e975ff1ea78b450ae --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/system/flow/Sys_WorkFlowTableStep.js @@ -0,0 +1,75 @@ +/***************************************************************************************** +** Author:jxx 2022 +** QQ:283591387 +**完整文档见:http://v2.volcore.xyz/document/api 【代码生成页面ViewGrid】 +**常用示例见:http://v2.volcore.xyz/document/vueDev +**后台操作见:http://v2.volcore.xyz/document/netCoreDev +*****************************************************************************************/ +//此js文件是用来自定义扩展业务代码,可以扩展一些自定义页面或者重新配置生成的代码 + +let extension = { + components: { + //查询界面扩展组件 + gridHeader: '', + gridBody: '', + gridFooter: '', + //新建、编辑弹出框扩展组件 + modelHeader: '', + modelBody: '', + modelFooter: '' + }, + tableAction: '', //指定某张表的权限(这里填写表名,默认不用填写) + buttons: { view: [], box: [], detail: [] }, //扩展的按钮 + methods: { + //下面这些方法可以保留也可以删除 + onInit() { //框架初始化配置前, + //示例:在按钮的最前面添加一个按钮 + // this.buttons.unshift({ //也可以用push或者splice方法来修改buttons数组 + // name: '按钮', //按钮名称 + // icon: 'el-icon-document', //按钮图标vue2版本见iview文档icon,vue3版本见element ui文档icon(注意不是element puls文档) + // type: 'primary', //按钮样式vue2版本见iview文档button,vue3版本见element ui文档button + // onClick: function () { + // this.$Message.success('点击了按钮'); + // } + // }); + + //示例:设置修改新建、编辑弹出框字段标签的长度 + // this.boxOptions.labelWidth = 150; + }, + onInited() { + //框架初始化配置后 + //如果要配置明细表,在此方法操作 + //this.detailOptions.columns.forEach(column=>{ }); + }, + searchBefore(param) { + //界面查询前,可以给param.wheres添加查询参数 + //返回false,则不会执行查询 + return true; + }, + searchAfter(result) { + //查询后,result返回的查询数据,可以在显示到表格前处理表格的值 + return true; + }, + addBefore(formData) { + //新建保存前formData为对象,包括明细表,可以给给表单设置值,自己输出看formData的值 + return true; + }, + updateBefore(formData) { + //编辑保存前formData为对象,包括明细表、删除行的Id + return true; + }, + rowClick({ row, column, event }) { + //查询界面点击行事件 + // this.$refs.table.$refs.table.toggleRowSelection(row); //单击行时选中当前行; + }, + modelOpenAfter(row) { + //点击编辑、新建按钮弹出框后,可以在此处写逻辑,如,从后台获取数据 + //(1)判断是编辑还是新建操作: this.currentAction=='Add'; + //(2)给弹出框设置默认值 + //(3)this.editFormFields.字段='xxx'; + //如果需要给下拉框设置默认值,请遍历this.editFormOptions找到字段配置对应data属性的key值 + //看不懂就把输出看:console.log(this.editFormOptions) + } + } +}; +export default extension; diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/system/form/FormCollectionObject.js b/Pure_Vite_Net7/Vue3Vite/src/extension/system/form/FormCollectionObject.js new file mode 100644 index 0000000000000000000000000000000000000000..f2a01480438eb01394f27769938268224ed81aea --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/system/form/FormCollectionObject.js @@ -0,0 +1,74 @@ +//author:jxx +//此处是对表单的方法,组件,权限操作按钮等进行任意扩展(方法扩展可参照SellOrder.js) +let extension = { + components: {//动态扩充组件或组件路径 + //表单header、content、footer对应位置扩充的组件 + gridHeader: '',//{ template: "
扩展组xx件
" }, + gridBody: '', + gridFooter: '', + //弹出框(修改、编辑、查看)header、content、footer对应位置扩充的组件 + modelHeader: '', + modelBody: '', + modelFooter: '' + }, + text: "点击左侧表单名名字即可加载收集的数据", + tableAction: "formCollectionResultTree", + buttons: { view: [], box: [], detail: [] },//扩展的按钮 + methods: {//事件扩展 + onInit() { + this.textInline = false; + // this.ck = false; + this.load = false; + this.setFiexdSearchForm(true); + + }, + onInited() { + this.height = this.height - 74; + }, + loadById(item) { + let columns = [ + { + title: "提交人", + field: "Creator" + }, + { + title: "提交时间", + field: "CreateDate" + }]; + JSON.parse(item.formOptions).formOptions.forEach(x => { + columns.push(...x.map(m => { + return { + title: m.title, + field: m.field, + type: m.type + } + })) + }) + this.formId = item.formId; + this.columns.splice(0); + this.columns.push(...columns); + this.search(); + }, + exportBefore(formData) { + formData.Value = this.formId; + return true; + }, + searchBefore(formData) { + // formData.Value = this.formId; + formData.wheres.push({name:'FormId',value:this.formId}) + return true; + }, + searchAfter(rows) { + rows.forEach(row => { + if (row.FormData) { + let data = JSON.parse(row.FormData); + for (const key in data) { + row[key] = Array.isArray(data[key]) ? data[key].filter(x => { return x != null && x != undefined }).join(',') : data[key]; + } + } + }) + return true; + } + } +}; +export default extension; \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/system/form/FormCollectionOptionsGridHeader.vue b/Pure_Vite_Net7/Vue3Vite/src/extension/system/form/FormCollectionOptionsGridHeader.vue new file mode 100644 index 0000000000000000000000000000000000000000..6ceb684f98cd69c18e71ac3a4e4a4eed1eb60dbf --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/system/form/FormCollectionOptionsGridHeader.vue @@ -0,0 +1,83 @@ + + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/system/form/FormDesignOptions.js b/Pure_Vite_Net7/Vue3Vite/src/extension/system/form/FormDesignOptions.js new file mode 100644 index 0000000000000000000000000000000000000000..a35b606f47d9ade13e1822082d040f7fd490839c --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/system/form/FormDesignOptions.js @@ -0,0 +1,68 @@ +//author:jxx +//此处是对表单的方法,组件,权限操作按钮等进行任意扩展(方法扩展可参照SellOrder.js) +import gridHeader from './FormCollectionOptionsGridHeader.vue' +import { h, resolveComponent } from 'vue'; +let extension = { + components: {//动态扩充组件或组件路径 + //表单header、content、footer对应位置扩充的组件 + gridHeader:gridHeader,//{ template: "
扩展组xx件
" }, + gridBody: { + render() { + return [ + h(resolveComponent('el-alert'), { + style: { 'margin-bottom': '12px' }, + 'show-icon': true, type: 'success', + closable: false, title: '1、点击新建随便输入,2、点击表格[表单设计]然后保存,3、点击预览(页面打开后提交数据),4、数据采集页面看查结果' + }, ''), + ] + } + }, + gridFooter: '', + //弹出框(修改、编辑、查看)header、content、footer对应位置扩充的组件 + modelHeader: '', + modelBody: '', + modelFooter: '' + }, + buttons: {view: [], box:[], detail:[]},//扩展的按钮 + methods: {//事件扩展 + onInit() { + this.boxOptions.height=200; + this.initFormButton(); + }, + onInited(){ + this.height= this.height-40; + }, + initFormButton() { + this.columns.splice(this.columns.findIndex(x => { return x.field == 'FormFields' }), 1, ...[{ + title: "操作", + field: "表单设计", + with: 80, + sort: false, + formatter: () => { + return '表单设计' + }, + click: (row) => { + this.$refs.gridHeader.open(row); + } + }, + { + title: "预览", + field: "预览", + with: 85, + sort: false, + formatter: () => { + return '预览' + }, + click: (row) => { + this.$tabs.open({ + path: "/formSubmit", text: row.Title, query: { + id: row.FormId + } + }) + // this.$refs.gridHeader.open(row); + } + }]) + } + } +}; +export default extension; \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/system/quartz/Sys_QuartzLog.js b/Pure_Vite_Net7/Vue3Vite/src/extension/system/quartz/Sys_QuartzLog.js new file mode 100644 index 0000000000000000000000000000000000000000..9bea996c58755f14f9e5362847357d85ed77f3c9 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/system/quartz/Sys_QuartzLog.js @@ -0,0 +1,84 @@ +/***************************************************************************************** + ** Author:jxx 2022 + ** QQ:283591387 + **完整文档见:http://v2.volcore.xyz/document/api 【代码生成页面ViewGrid】 + **常用示例见:http://v2.volcore.xyz/document/vueDev + **后台操作见:http://v2.volcore.xyz/document/netCoreDev + *****************************************************************************************/ +//此js文件是用来自定义扩展业务代码,可以扩展一些自定义页面或者重新配置生成的代码 + +let extension = { + components: { + //查询界面扩展组件 + gridHeader: '', + gridBody: '', + gridFooter: '', + //新建、编辑弹出框扩展组件 + modelHeader: '', + modelBody: '', + modelFooter: '' + }, + tableAction: 'Sys_QuartzLog', //指定某张表的权限(这里填写表名,默认不用填写) + buttons: { view: [], box: [], detail: [] }, //扩展的按钮 + methods: { + //下面这些方法可以保留也可以删除 + onInit() { + //框架初始化配置前, + //示例:在按钮的最前面添加一个按钮 + // this.buttons.unshift({ //也可以用push或者splice方法来修改buttons数组 + // name: '按钮', //按钮名称 + // icon: 'el-icon-document', //按钮图标vue2版本见iview文档icon,vue3版本见element ui文档icon(注意不是element puls文档) + // type: 'primary', //按钮样式vue2版本见iview文档button,vue3版本见element ui文档button + // onClick: function () { + // this.$Message.success('点击了按钮'); + // } + // }); + if (this.$route.path != '/Sys_QuartzLog') { + this.tableHeight = 345; + } + //示例:设置修改新建、编辑弹出框字段标签的长度 + // this.boxOptions.labelWidth = 150; + }, + onInited() { + //框架初始化配置后 + //如果要配置明细表,在此方法操作 + //this.detailOptions.columns.forEach(column=>{ }); + }, + searchBefore(param) { + //界面查询前,可以给param.wheres添加查询参数 + //返回false,则不会执行查询 + if (this.$route.path != '/Sys_QuartzLog') { + param.wheres.push({ + name: 'Id', + value: this.$store.getters.data().quartzId + }); + } + return true; + }, + searchAfter(result) { + //查询后,result返回的查询数据,可以在显示到表格前处理表格的值 + return true; + }, + addBefore(formData) { + //新建保存前formData为对象,包括明细表,可以给给表单设置值,自己输出看formData的值 + return true; + }, + updateBefore(formData) { + //编辑保存前formData为对象,包括明细表、删除行的Id + return true; + }, + rowClick({ row, column, event }) { + //查询界面点击行事件 + // this.$refs.table.$refs.table.toggleRowSelection(row); //单击行时选中当前行; + }, + modelOpenAfter(row) { + //点击编辑、新建按钮弹出框后,可以在此处写逻辑,如,从后台获取数据 + //(1)判断是编辑还是新建操作: this.currentAction=='Add'; + //(2)给弹出框设置默认值 + //(3)this.editFormFields.字段='xxx'; + //如果需要给下拉框设置默认值,请遍历this.editFormOptions找到字段配置对应data属性的key值 + //看不懂就把输出看:console.log(this.editFormOptions) + } + } +}; +export default extension; diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/system/quartz/Sys_QuartzOptions.js b/Pure_Vite_Net7/Vue3Vite/src/extension/system/quartz/Sys_QuartzOptions.js new file mode 100644 index 0000000000000000000000000000000000000000..539ecaf13df0a49b88a56d70dfb1e9de354ffe9a --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/system/quartz/Sys_QuartzOptions.js @@ -0,0 +1,156 @@ +/***************************************************************************************** + ** Author:jxx 2022 + ** QQ:283591387 + **完整文档见:http://v2.volcore.xyz/document/api 【代码生成页面ViewGrid】 + **常用示例见:http://v2.volcore.xyz/document/vueDev + **后台操作见:http://v2.volcore.xyz/document/netCoreDev + *****************************************************************************************/ +//此js文件是用来自定义扩展业务代码,可以扩展一些自定义页面或者重新配置生成的代码 +import gridBody from './Sys_QuartzOptionsGridBody.vue'; +let extension = { + components: { + //查询界面扩展组件 + gridHeader: '', + gridBody: gridBody, + gridFooter: '', + //新建、编辑弹出框扩展组件 + modelHeader: '', + modelBody: '', + modelFooter: '' + }, + tableAction: '', //指定某张表的权限(这里填写表名,默认不用填写) + buttons: { view: [], box: [], detail: [] }, //扩展的按钮 + methods: { + //下面这些方法可以保留也可以删除 + onInit() { + this.textInline = false; + this.columns.push({ + field: '操作', + title: '操作', + width: 150, + fixed: 'right', + align: 'center', + render: (h, { row, column, index }) => { + return h('div', { style: { color: '#0e84ff' } }, [ + h( + 'span', + { + style: { + cursor: 'pointer', + 'margin-right': '8px', + 'border-bottom': '1px solid' + }, + onClick: (e) => { + this.request('start', row); + } + }, + '执行' + ), + h( + 'span', + { + style: { + cursor: 'pointer', + 'margin-right': '8px', + 'border-bottom': '1px solid' + }, + onClick: (e) => { + this.request('pause', row); + } + }, + '暂停' + ), + h( + 'span', + { + style: { + cursor: 'pointer', + 'border-bottom': '1px solid' + }, + onClick: (e) => { + this.$store.getters.data().quartzId = row.Id; + this.$refs.gridBody.open(); + } + }, + '日志' + ) + ]); + } + }); + //示例:设置修改新建、编辑弹出框字段标签的长度 + // this.boxOptions.labelWidth = 150; + }, + request(action, row) { + let url = `api/Sys_QuartzOptions/${action}`; + this.http.post(url, row, true).then((result) => { + this.$message.success('执行成功'); + this.search(); + }); + }, + onInited() { + this.height= this.height-50; + this.columns.forEach((col) => { + if (col.field == 'Status') { + col.align = 'center'; + col.formatter = (row) => { + // return row.Status; + if (row.Status == 1) { + return '暂停'; + } + return '正常'; + }; + } + }); + //框架初始化配置后 + //如果要配置明细表,在此方法操作 + //this.detailOptions.columns.forEach(column=>{ }); + this.editFormOptions.forEach((options) => { + options.forEach((option) => { + if (option.field == 'CronExpression') { + option.extra = { + style: 'color: #0e84ff;cursor: pointer;', + text: '查看', + click: () => { + window.open('https://cron.qqe2.com/', '_blank'); + } + }; + } + }); + }); + }, + searchBefore(param) { + //界面查询前,可以给param.wheres添加查询参数 + //返回false,则不会执行查询 + return true; + }, + searchAfter(result) { + //查询后,result返回的查询数据,可以在显示到表格前处理表格的值 + return true; + }, + addBefore(formData) { + //新建保存前formData为对象,包括明细表,可以给给表单设置值,自己输出看formData的值 + return true; + }, + updateBefore(formData) { + //编辑保存前formData为对象,包括明细表、删除行的Id + return true; + }, + rowClick({ row, column, event }) { + //查询界面点击行事件 + // this.$refs.table.$refs.table.toggleRowSelection(row); //单击行时选中当前行; + }, + modelOpenAfter(row) { + if (this.currentAction == 'Add' || !this.editFormFields.TimeOut) { + this.editFormFields.TimeOut = 180; + } + this.editFormOptions.forEach((options) => { + options.forEach((option) => { + if (option.field == 'GroupName') { + option.readonly = this.currentAction != 'Add'; + } + }); + }); + } + } +}; +export default extension; diff --git a/Pure_Vite_Net7/Vue3Vite/src/extension/system/quartz/Sys_QuartzOptionsGridBody.vue b/Pure_Vite_Net7/Vue3Vite/src/extension/system/quartz/Sys_QuartzOptionsGridBody.vue new file mode 100644 index 0000000000000000000000000000000000000000..9ee24df4e8809da678e75e486c72beba6fac8619 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/extension/system/quartz/Sys_QuartzOptionsGridBody.vue @@ -0,0 +1,55 @@ + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/main.js b/Pure_Vite_Net7/Vue3Vite/src/main.js new file mode 100644 index 0000000000000000000000000000000000000000..5f69d9d165105fe0d243f162983e0603018ac940 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/main.js @@ -0,0 +1,40 @@ +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' +import store from './store' +import ElementPlus from 'element-plus' +// import 'element-plus/lib/theme-chalk/index.css'; +import 'element-plus/dist/index.css' +import './assets/element-icon/icon.css' +import base from './uitils/common' +import http from './api/http' +// import 'dayjs/locale/zh-cn' +// import locale from 'element-plus/lib/locale/lang/zh-cn' + +import permission from './api/permission' +import viewgird from './components/basic/ViewGrid' + +import { createPinia } from 'pinia' + +const app = createApp(App) +app.config.globalProperties.base = base +app.config.globalProperties.http = http +app.config.globalProperties.$tabs = {} +app.config.globalProperties.permission = permission +app.config.globalProperties.$global = { + signalR: false //是否开启signalR +} +app.use(createPinia()) +app.use(store) +app.use(ElementPlus, { size: 'default' }) +app.use(router) +app.use(viewgird) + +app.mount('#app') +app.config.globalProperties.$Message = app.config.globalProperties.$message + + + + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/router/index.js b/Pure_Vite_Net7/Vue3Vite/src/router/index.js new file mode 100644 index 0000000000000000000000000000000000000000..88a2c92bba3c64c1ee3858438f0e14b139079284 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/router/index.js @@ -0,0 +1,105 @@ +import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router' +import viewgird from './viewGird' +import store from '../store/index' +import redirect from './redirect' +const routes = [ + { + path: '/', + name: 'Index', + component: () => import('@/views/Index.vue'), + redirect: '/home', + children: [ + ...viewgird, + ...redirect, + { + path: '/home', + name: 'home', + component: () => import('@/views/Home.vue') + }, { + path: '/UserInfo', + name: 'UserInfo', + component: () => import('@/views/system/UserInfo.vue') + }, + { + path: '/sysMenu', + name: 'sysMenu', + component: () => import('@/views/system/Sys_Menu.vue') + }, { + path: '/coder', + name: 'coder', + component: () => import('@/views/builder/coder.vue') + }, + { + path: '/formDraggable', //表单设计 + name: 'formDraggable', + component: () => import('@/views/formDraggable/formDraggable.vue') + }, + { + path: '/formSubmit', //表单提交页面 + name: 'formSubmit', + component: () => import('@/views/formDraggable/FormSubmit.vue'), + meta:{ + keepAlive:false + } + }, + { + path: '/formCollectionResultTree', //显示收集的数据表单 + name: 'formCollectionResultTree', + component: () => import('@/views/formDraggable/FormCollectionResultTree.vue'), + meta:{ + keepAlive:false + } + }, + { + path: '/signalR', //消息推送 + name: 'signalR', + component: () => import('@/views/signalR/Index.vue'), + meta:{ + keepAlive:false + } + } + ] + }, + { + path: '/login', + name: 'login', + component: () => import('@/views/Login.vue'), + meta:{ + anonymous:true + } + } +] + +const router = createRouter({ + history: createWebHashHistory(), //createWebHistory(process.env.BASE_URL), + routes +}) + + +router.beforeEach((to, from, next) => { + if (to.matched.length == 0) return next({ path: '/404' }); + //2020.06.03增加路由切换时加载提示 + store.dispatch("onLoading", true); + if ((to.hasOwnProperty('meta') && to.meta.anonymous) || store.getters.isLogin() || to.path == '/login') { + return next(); + } + + next({ path: '/login', query: { redirect: Math.random() } }); +}) +router.afterEach((to, from) => { + store.dispatch("onLoading", false); +}) +router.onError((error) => { + // const targetPath = router.currentRoute.value.matched; + try { + console.log(error.message); + if (process.env.NODE_ENV == 'development') { + alert(error.message) + } + localStorage.setItem("route_error", error.message) + } catch (e) { + + } + window.location.href = '/' +}); +export default router diff --git a/Pure_Vite_Net7/Vue3Vite/src/router/redirect.js b/Pure_Vite_Net7/Vue3Vite/src/router/redirect.js new file mode 100644 index 0000000000000000000000000000000000000000..5c49a5a8cf306940bf2662a727bd2725055590a2 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/router/redirect.js @@ -0,0 +1,26 @@ +let redirect = [ + { + path: '/404', + name: '404', + component: () => import('@/components/redirect/404.vue'), + meta: { + anonymous: true + } + }, + { + path: '/401', + name: '401', + component: () => import('@/components/redirect/401.vue') + }, + { + path: '/coding', + name: 'coding', + component: () => import('@/components/redirect/coding.vue') + }, + { + path: '/message', + name: 'message', + component: () => import('@/components/redirect/Message.vue') + } +] +export default redirect diff --git a/Pure_Vite_Net7/Vue3Vite/src/router/viewGird.js b/Pure_Vite_Net7/Vue3Vite/src/router/viewGird.js new file mode 100644 index 0000000000000000000000000000000000000000..45a09e69c3ead4e4c68f6af8b7b6ea50f39d9dc1 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/router/viewGird.js @@ -0,0 +1,71 @@ + +let viewgird = [ + { + path: '/Sys_Log', + name: 'sys_Log', + component: () => import('@/views/system/Sys_Log.vue' ) + }, + { + path: '/Sys_User', + name: 'Sys_User', + component: () => import('@/views/system/Sys_User.vue' ) + }, + { + path: '/permission', + name: 'permission', + component: () => import('@/views/system/Permission.vue' ) + }, + + { + path: '/Sys_Dictionary', + name: 'Sys_Dictionary', + component: () => import('@/views/system/Sys_Dictionary.vue' ) + }, + { + path: '/Sys_Role', + name: 'Sys_Role', + component: () => import('@/views/system/Sys_Role.vue' ) + }, { + path: '/Sys_Role1', + name: 'Sys_Role1', + component: () => import('@/views/system/Sys_Role1.vue' ) + } + , { + path: '/Sys_DictionaryList', + name: 'Sys_DictionaryList', + component: () => import('@/views/system/Sys_DictionaryList.vue' ) + } ,{ + path: '/FormDesignOptions', + name: 'FormDesignOptions', + component: () => import('@/views/system/form/FormDesignOptions.vue') + } ,{ + path: '/FormCollectionObject', + name: 'FormCollectionObject', + component: () => import('@/views/system/form/FormCollectionObject.vue') + } ,{ + path: '/Sys_WorkFlow', + name: 'Sys_WorkFlow', + component: () => import('@/views/system/flow/Sys_WorkFlow.vue') + } ,{ + path: '/Sys_WorkFlowStep', + name: 'Sys_WorkFlowStep', + component: () => import('@/views/system/flow/Sys_WorkFlowStep.vue') + } ,{ + path: '/Sys_WorkFlowTable', + name: 'Sys_WorkFlowTable', + component: () => import('@/views/system/flow/Sys_WorkFlowTable.vue') + } ,{ + path: '/Sys_WorkFlowTableStep', + name: 'Sys_WorkFlowTableStep', + component: () => import('@/views/system/flow/Sys_WorkFlowTableStep.vue') + } ,{ + path: '/Sys_QuartzOptions', + name: 'Sys_QuartzOptions', + component: () => import('@/views/system/quartz/Sys_QuartzOptions.vue') + } ,{ + path: '/Sys_QuartzLog', + name: 'Sys_QuartzLog', + component: () => import('@/views/system/quartz/Sys_QuartzLog.vue') + }] + +export default viewgird diff --git a/Pure_Vite_Net7/Vue3Vite/src/store/index.js b/Pure_Vite_Net7/Vue3Vite/src/store/index.js new file mode 100644 index 0000000000000000000000000000000000000000..94d49358b3a91d838f41036ae062733537d54abd --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/store/index.js @@ -0,0 +1,89 @@ +import { createStore } from 'vuex' +const keys = { USER: 'user' } +function getUserInfo(state) { + if (state.userInfo) return state.userInfo; + let userInfo = localStorage.getItem(keys.USER); + if (userInfo) { + state.userInfo = JSON.parse(userInfo); + } + return state.userInfo; +} +export default createStore({ + state: { + data: {}, + permission: [], + isLoading: false,//2020.06.03增加路由切换时加载提示 + userInfo: null + }, + mutations: { + setPermission(state, data) { //调用方式 this.$store.commit('setPermission', data) + if (!data || typeof data != 'object') return; + if (data instanceof Array) { + state.permission.push(...data); + } else { + state.permission = data; + } + }, setUserInfo(state, data) { + state.userInfo = data; + localStorage.setItem(keys.USER, JSON.stringify(data)); + }, + clearUserInfo(state) { + state.permission = []; + state.userInfo = null; + localStorage.removeItem(keys.USER); + }, + test(state) { + return 113344; + }, + updateLoadingState(state, flag) { + state.isLoading = flag + } + }, getters: { + getPermission: (state) => (path) => { //调用方式 store.getters.getPermission('sys_User') + if (!path) return state.permission; + return state.permission.find(x => x.path == path); + }, + getUserInfo: (state) => () => { + getUserInfo(state); + return state.userInfo; + }, getUserName: (state) => () => { + getUserInfo(state); + if (state.userInfo) { + return state.userInfo.userName; + } + return '未获取到登陆信息'; + }, + getToken: (state) => () => { + getUserInfo(state); + if (state.userInfo) { + return 'Bearer ' + state.userInfo.token; + } + return ''; + }, + isLogin: (state) => () => { + if (getUserInfo(state)) { + return true; + } + return false; + }, + isLoading: (state) => () => { + return state.isLoading; + }, + data: (state) => () => { + return state.data; + }, + getData: (state) => () => { + return state.data; + }, + }, actions: { + setPermission(context, data) { + context.commit('setPermission', data); //调用方式 store.dispatch('push') + }, + toDo(context) { + return context.Store.m; + }, + onLoading(context, flag) { + context.commit("updateLoadingState", flag); + } + } +}) diff --git a/Pure_Vite_Net7/Vue3Vite/src/uitils/common.js b/Pure_Vite_Net7/Vue3Vite/src/uitils/common.js new file mode 100644 index 0000000000000000000000000000000000000000..a745d8de99a16358f6aa1b5dc3fb05c284ad7a25 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/uitils/common.js @@ -0,0 +1,344 @@ +let base = { + addDays(date, days) { + //给指定日期增加天数 + if (!days) { + return date; + } + let dateArr = date.split(' '); + date = new Date(new Date(date).setDate(new Date(date).getDate() + days)); + var year = date.getFullYear(); + var month = date.getMonth() + 1; + if (month < 10) { + month = '0' + month; + } + var day = date.getDate(); + if (day < 10) { + day = '0' + day; + } + date = year + '-' + month + '-' + day; + if (dateArr.length == 1) { + return date; + } + return date + ' ' + dateArr[1]; + }, + //获取当前时间,time是否带时分秒 + getDate(time) { + let date = new Date(); + let year = date.getFullYear(); + let month = date.getMonth() + 1; + let day = date.getDate(); + + let datetime = + year + + '-' + + (month < 10 ? '0' + month : month) + + '-' + + (day < 10 ? '0' + day : day); + + if (!time) { + return datetime; + } + + let hour = date.getHours(); + let minutes = date.getMinutes(); + let second = date.getSeconds(); + + return ( + datetime + + '' + + ' ' + + (hour < 10 ? '0' + hour : hour) + + ':' + + (minutes < 10 ? '0' + minutes : minutes) + + ':' + + (second < 10 ? '0' + second : second) + ); + }, + isPhone(val) { + return /^[1][3,4,5,6,7,8,9][0-9]{9}$/.test(val); + }, + isDecimal(val) { + return /(^[\-0-9][0-9]*(.[0-9]+)?)$/.test(val); + }, + isNumber(val) { + return /(^[\-0-9][0-9]*([0-9]+)?)$/.test(val); + }, + isMail(val) { + return /^(\w-*\.*)+@(\w-?)+(\.\w{2,})+$/.test(val); + }, + isUrl(url) { + return this.checkUrl(url); + }, + checkUrl(url) { + // url= 协议://(ftp的登录信息)[IP|域名](:端口号)(/或?请求参数) + var strRegex = + '^((https|http|ftp)://)?' + // (https或http或ftp):// 可有可无 + "(([\\w_!~*'()\\.&=+$%-]+: )?[\\w_!~*'()\\.&=+$%-]+@)?" + // ftp的user@ 可有可无 + '(([0-9]{1,3}\\.){3}[0-9]{1,3}' + // IP形式的URL- 3位数字.3位数字.3位数字.3位数字 + '|' + // 允许IP和DOMAIN(域名) + '(localhost)|' + // 匹配localhost + "([\\w_!~*'()-]+\\.)*" + // 域名- 至少一个[英文或数字_!~*\'()-]加上. + '\\w+\\.' + // 一级域名 -英文或数字 加上. + '[a-zA-Z]{1,6})' + // 顶级域名- 1-6位英文 + '(:[0-9]{1,5})?' + // 端口- :80 ,1-5位数字 + '((/?)|' + // url无参数结尾 - 斜杆或这没有 + "(/[\\w_!~*'()\\.;?:@&=+$,%#-]+)+/?)$"; // 请求参数结尾- 英文或数字和[]内的各种字符 + var re = new RegExp(strRegex, 'i'); // i不区分大小写 + // 将url做uri转码后再匹配,解除请求参数中的中文和空字符影响 + if (re.test(encodeURI(url))) { + return true; + } + return false; + }, + matchUrlIp(url, ip) { + // url使用是否使用的当前ip + if (!url || !ip) { + return false; + } + return url.indexOf(ip.replace('https://', '').replace('http://', '')) >= 0; + }, + getImgSrc(src, httpUrl) { + if (this.isUrl(src)) { + return src; + } + if (httpUrl) { + return httpUrl + src; + } + return src; + }, + previewImg(src, httpUrl) { + // 图片预览,目前只支持单图片预览 + if (src && !this.isUrl(src) && httpUrl) { + if ( + src.substr(0, 1) == '/' && + httpUrl.substr(httpUrl.length - 1, 1) == '/' + ) { + src = src.substr(1); + } + src = httpUrl + src; + } + let id = 'vol-preview'; + let $div = document.getElementById(id); + if (!$div) { + $div = document.createElement('div'); + $div.setAttribute('id', 'vol-preview'); + let $mask = document.createElement('div'); + $mask.style.position = 'absolute'; + $mask.style.width = '100%'; + $mask.style.height = '100%'; + $mask.style.background = 'black'; + $mask.style.opacity = '0.6'; + $div.appendChild($mask); + $div.style.position = 'fixed'; + $div.style.width = '100%'; + $div.style.height = '100%'; + // $div.style.overflow = "scroll"; + $div.style.top = 0; + $div.style['z-index'] = 9999999; + let $img = document.createElement('img'); + $img.setAttribute('class', 'vol-preview-img'); + $img.style.position = 'absolute'; + $img.style.top = '50%'; + $img.style.left = '50%'; + $img.style['max-width'] = '90%'; + $img.style['max-height'] = '90%'; + $img.style.transform = 'translate(-50%,-50%)'; + // $img.src = src; + $img.setAttribute('src', src); + $div.appendChild($img); + $div.addEventListener('click', function() { + this.style.display = 'none'; + }); + document.body.appendChild($div); + return; + } + let $img1 = document.body + .appendChild($div) + .querySelector('.vol-preview-img'); + // img.src = src; + $img1.setAttribute('src', src); + $div.style.display = 'block'; + }, + // 下载文件 $element 标签, url完整url, fileName 文件名, header 以key/value传值 + // backGroundUrl 后台url,如果后台url直接从后台下载,其他全部通过点击a标签下载 + dowloadFile(url, fileName, header, backGroundUrl) { + if (!url) return alert('此文件没有url不能下载'); + if (!this.isUrl(url)) { + url = backGroundUrl + url; + } + window.open(url); + }, + downloadImg(data) { + if (!data.url || !data.callback || typeof data.callback !== 'function') { + return; + } + // url, backGroundUrl, header, callback + if ( + this.isUrl(data.url) && + !this.matchUrlIp(data.url, data.backGroundUrl) + ) { + return data.url; + } + // 通过后台api服务器下载 + if (!this.isUrl(data.url)) { + if (!this.isUrl(data.backGroundUrl + data.url)) { + return; + } + data.url = data.backGroundUrl + data.url; + } + var xmlResquest = new XMLHttpRequest(); + xmlResquest.open('get', data.url, true); + xmlResquest.responseType = 'blob'; + xmlResquest.setRequestHeader('Content-Type', 'application/json'); + if (data.header && typeof data.header === 'object') { + for (const key in data.header) { + xmlResquest.setRequestHeader(key, data.header[key]); + } + } + xmlResquest.onload = function() { + if (this.status == 200) { + var blob = this.response; + callback(window.URL.createObjectURL(blob)); + } + }; + xmlResquest.send(); + }, + // 2020.06.01增加通用方法,将普通对象转换为tree结构 + // data数据格式[ + // { name: 'tree1', id: 1, parentId: 0 }, + // { name: 'tree2', id: 2, parentId: 0 }] + + // 1、id与parentId这两个字段必须有 + // 2、树形tree需要注意Id与parentId循环依赖的问题 + // 3、callback每次生成一新的节点的时回调的方法 + + convertTree(data, callback) { + var treeIds = []; + var root_data = []; + if (data.length>100) { + data = JSON.parse(JSON.stringify(data)); + } + data.forEach((x) => { + // if (!x.children) { + // x.children = [] + // } + if ( + !x.hidden && + x.id !== undefined && + x.id !== x.parentId && + !data.some((s) => { + return x.parentId == s.id; + }) + ) { + x.isRoot = true; + callback && callback(x, data, true, treeIds); + root_data.push(x); + getTree(x.id, x, data, callback, treeIds); + } else { + callback && callback(x, data, true, treeIds); + } + }); + var exceptionNodes = data.filter((f) => { + return treeIds.indexOf(f.id) == -1 && !f.hidden; + }); + + root_data.push(...exceptionNodes); + return root_data; + }, + getTreeAllParent(id, data) { + // 获取某个节点的所有父节点信息2020.11.01 + var nodes = []; + if (!(data instanceof Array)) { + return nodes; + } + if (data.length>100) { + data = JSON.parse(JSON.stringify(data)); + } + data.forEach((x) => { + if (x.id === x.parentId) { + x.parentId = 0; + } else if (data.some((c) => c.parentId === x.id && c.id === x.parentId)) { + x.parentId = 0; + } + }); + + var _child = data.find((x) => { + return x.id === id; + }); + if (!_child) { + return []; + } + nodes.push(_child); + var _parentIds = [_child.parentId]; + for (let index = 0; index < _parentIds.length; index++) { + var _node = data.find((x) => { + return x.id === _parentIds[index] && x.id !== x.parentId; + }); + if (!_node) { + return nodes; + } + _parentIds.push(_node.parentId); + nodes.unshift(_node); + } + return nodes; + }, + //获取所有节点的子节点 + // data数据格式[ + // { name: 'tree1', id: 1, parentId: 0 }, + // { name: 'tree2', id: 2, parentId: 0 }] + getTreeAllChildren(id, data) { + //递归获取某个节点的所有子节点信息 + var nodes = []; + if (!(data instanceof Array)) { + return nodes; + } + if (data.length>100) { + data = JSON.parse(JSON.stringify(data)); + } + var _child = data.find((x) => { + return x.id === id; + }); + if (!_child) { + return []; + } + nodes.push(_child); + var _parentIds = [_child.id]; + for (let index = 0; index < _parentIds.length; index++) { + data.forEach((_node) => { + if ( + _node.parentId === _parentIds[index] && + _node.parentId !== _node.id + ) { + _parentIds.push(_node.id); + nodes.unshift(_node); + } + }); + } + return nodes; + }, + //获取所有子节点的id + // data数据格式[ + // { name: 'tree1', id: 1, parentId: 0 }, + // { name: 'tree2', id: 2, parentId: 0 }] + getTreeAllChildrenId(id, data) { + return this.getTreeAllChildren(id, data).map((c) => { + return c.id; + }); + } +}; +export default base; + +// 2020.06.01增加通用方法,将普通对象转换为tree结构 +function getTree(id, node, data, callback, treeIds) { + if (treeIds.indexOf(id) == -1) { + treeIds.push(id); + } + data.forEach((x) => { + if (!x.hidden && x.parentId == id) { + if (!node.children) node.children = []; + callback && callback(x, node, false); + node.children.push(x); + getTree(x.id, x, data, callback, treeIds); + } + }); +} diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/Home.vue b/Pure_Vite_Net7/Vue3Vite/src/views/Home.vue new file mode 100644 index 0000000000000000000000000000000000000000..e8857008d6fb69a0c67002cbaa7f6b57b077c063 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/Home.vue @@ -0,0 +1,382 @@ + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/Index.vue b/Pure_Vite_Net7/Vue3Vite/src/views/Index.vue new file mode 100644 index 0000000000000000000000000000000000000000..cb1a4c2ce91f493145f7db32e8ce3b73b3de65f7 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/Index.vue @@ -0,0 +1,787 @@ + + + + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/Login.vue b/Pure_Vite_Net7/Vue3Vite/src/views/Login.vue new file mode 100644 index 0000000000000000000000000000000000000000..68a75d70248c87de5c8e0705d9100129bedd7ceb --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/Login.vue @@ -0,0 +1,559 @@ + + + + + + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/builder/builderData.js b/Pure_Vite_Net7/Vue3Vite/src/views/builder/builderData.js new file mode 100644 index 0000000000000000000000000000000000000000..1e0dfea96402335813866a4d864bba91707c7951 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/builder/builderData.js @@ -0,0 +1,193 @@ +let columnType = [{ "key": 1, "value": "img" }, +{ "key": 2, "value": "excel" }, +{ "key": 3, "value": "file" }, +//2021.07.27增加table列显示类型date(自动格式化) +{ "key": 4, "value": "date" } +] + +let dataType = [ + { "key": "text", "value": "input" }, + { "key": "textarea", "value": "textarea" }, + { "key": "switch", "value": "switch" }, + // { "key": "dropList", "value": "dropList" }, + { "key": "select", "value": "select" }, + { "key": "selectList", "value": "select多选" }, + { "key": "date", "value": "date" }, + { "key": "datetime", "value": "datetime" }, + { "key": "month", "value": "年月日" }, + { "key": "rate", "value": "rate评分" }, + { "key": "time", "value": "time" }, + { "key": "checkbox", "value": "checkbox" }, + // 2021.05.16集成iview radio组件 + { "key": "radio", "value": "radio" }, + { "key": "cascader", "value": "级联" },//2020.11.01增加级联选择 + { "key": "editor", "value": "富文本编辑器" }, + { "key": "mail", "value": "mail" }, + { "key": "number", "value": "number" }, + { "key": "decimal", "value": "decimal" }, + { "key": "phone", "value": "phone" }, + { "key": "img", "value": "img" }, + { "key": "excel", "value": "excel" }, + { "key": "file", "value": "file" } +]; + +let searchDataType = [ + { "key": "text", "value": "input" }, + { "key": "like", "value": "模糊查询" }, + { "key": "textarea", "value": "textarea" }, + { "key": "switch", "value": "switch" }, + { "key": "select", "value": "select" }, + { "key": "selectList", "value": "select多选" }, + { "key": "date", "value": "date" }, + { "key": "datetime", "value": "datetime" }, + { "key": "month", "value": "year_month" }, + { "key": "time", "value": "time" }, + { "key": "cascader", "value": "级联" },//2020.11.01增加级联选择 + { "key": "checkbox", "value": "checkbox" }, + // 2021.05.16集成iview radio组件 + { "key": "radio", "value": "radio" }, + { "key": "range", "value": "区间查询" }, + { "key": "mail", "value": "mail" }, + { "key": "number", "value": "number" }, + { "key": "decimal", "value": "decimal" }, + { "key": "phone", "value": "phone" } +]; +let data = { + form: { + fields: { + table_Id: '', + parentId: null, + namespace: '', + columnCNName: '', + tableName: '', + tableTrueName: '', + folderName: '', + detailCnName: '', + detailName: '', + expressField: '', + sortName: '', + richtitle: '', + uploadField: '', + uploadMaxCount: '', + enable: 0, + vuePath: '', + appPath: "", + userPermissionDesc: '开启后当前用户只能操作自己(与下级角色)创建的数据,如:查询、删除、修改等操作' + }, + addOptions: [ + [{ "title": "父 级 ID", min: 0, "field": "parentId", "required": true, type: 'number', placeholder: '放在【代码生成配置】列表的文件夹ID下,如果填入【0】就是一级目录' }], + [{ + "title": "项目类库", + "field": "namespace", + "placeholder": "代码生成后的所在类库(可以自己提前在后台项目中创建一个.netcore类库)", + "type": "select", + "required": true, + data: [] + }], + [{ "title": "表中文名", "field": "columnCNName", "required": true, placeholder: "表对应的中文名字,界面上显示会用到" }], + [{ "title": "实际表名", "field": "tableName", "required": true, placeholder: "数据库实际表名或者视图名(多表关联请创建视图再生成代码)" }], + [{ "title": "文件夹名", placeholder: "生成文件所在类库中的文件夹名(文件夹可以不存在);注意只需要填写文件夹名,不是路径", "field": "folderName", "required": true }] + ], + options: [ + [ + { "title": "主 键 ID", "field": "table_Id", "dataSource": [], readonly: true, disabled: true, columnType: 'int' }, + { "title": "父 级 ID", "field": "parentId", min: 0, "required": true, type: 'number' }, + { + "title": "项目类库", + "placeholder": "代码生成存放的位置", + "field": "namespace", + "type": "select", + "required": true, + data: [] + } + ], + [ + { "title": "表中文名", "field": "columnCNName", "dataSource": [], "required": true }, + { "title": "表 别 名", placeholder: "默认与实际表名相同", "field": "tableName", "required": true }, + { "title": "实际表名", "field": "tableTrueName" }, + + ], + [ + { "title": "文件夹名", placeholder: "生成文件所在类库中的文件夹名(文件夹可以不存在)", "field": "folderName", "required": true }, + { "title": "明细表名", "field": "detailCnName", placeholder: "明细表中文名字" }, + { "title": "明 细 表", "field": "detailName", placeholder: "数据库的表名" }, + + ], + [ + { "title": "快捷编辑", "field": "expressField", placeholder: "快捷编辑字段" }, + { "title": "排序字段", "field": "sortName", "placeholder": "多个排序字段逗号隔开(默认降序排序),如:Name,Age", colSize: 8 }, + + // { "title": "还没想好", "field": "richtitle" } + ], + [{ "title": "Vue路径", "field": "vuePath", type: "text", placeholder: 'Vue项目所在绝对路径,到views文件夹,如:E:/app/src/views', colSize: 6 }, + { "title": "app路径", "field": "appPath", type: "text", placeholder: 'uniapp项目所在绝对路径,到pages文件夹,如:E:/uniapp/pages', colSize: 6 }] + // [ //待完 + // { "title": "开启用户权限数据", "field": "enable", bind: { data: [{ key: 1, value: '是', key: 0, value: '否' }] }, type: 'switch', colSize: 2 }, + // { "title": "提示", "required": true, "field": "userPermissionDesc", colSize: 10, "placeholder": "非自增主键需要输入排序字段",readonly:true } + // ], + // [ + + // ], + // [ + // { "title": "富文本编辑字段", "field": "richtitle", "displayType": "title" }, + // { "title": "文件上传字段", "field": "uploadField", "displayType": "title" }, + // { "title": "文件上传数量限制", "field": "uploadMaxCount", "displayType": "title", columnType: 'int' } + // ], + // [ + // { "title": "Vue视图绝对路径", "field": "vuePath", "displayType": "title", colSize: 12, placeholder: 'Vue项目所在绝对路径,到views文件夹,如:E:/app/src/views' }, + // ] + ] + }, + //2021.01.09增加代码生成器设置table排序功能 + columns: [ + { field: 'columnId', title: 'ColumnId', width: 120, align: 'left', edit: { type: "text" }, hidden: true }, + { field: 'table_Id', title: 'Table_Id', width: 120, align: 'left', editor: 'text', hidden: true }, + { field: 'columnCnName', title: '列显示名称', fixed: true, width: 120, align: 'left', edit: { type: "text" } }, + { field: 'columnName', title: '列名', fixed: true, width: 120, align: 'left', edit: { type: "text" } }, + { field: 'isKey', title: '主键', width: 90, align: 'left', edit: { type: "switch" } }, + { field: 'sortable', title: '是否排序', width: 90, align: 'left', edit: { type: "switch", keep: true } }, + { + field: 'enable', title: 'app列', width: 140, align: 'left', edit: { type: "select" }, + bind: { + data: [ + { key: 1, value: "显示/查询/编辑" }, + { key: 2, value: "显示/编辑" }, + { key: 3, value: "显示/查询" }, + { key: 4, value: "显示" }, + { key: 5, value: "查询/编辑" }, + { key: 6, value: "查询" }, + { key: 7, value: "编辑" }, + ] + } + }, + { field: 'searchRowNo', title: '查询行', width: 90, align: 'left', edit: { type: "text" } }, + { field: 'searchColNo', title: '查询列', width: 90, align: 'left', edit: { type: "text" } }, + { field: 'searchType', title: '查询类型', width: 150, align: 'left', edit: { type: "select" }, bind: { data: searchDataType } }, + { field: 'editRowNo', title: '编辑行', width: 90, align: 'numberbox', edit: { type: "text" } }, + { field: 'editColNo', title: '编辑列', width: 90, align: 'numberbox', edit: { type: "text" } }, + { field: 'editType', title: '编辑类型', width: 150, align: 'left', edit: { type: "select" }, bind: { data: dataType } }, + { field: 'dropNo', title: '数据源', width: 120, align: 'left', bind: { data: [] }, edit: { type: "select", data: [] } }, + { field: 'isImage', title: 'table列显示类型', hidden: false, width: 130, align: 'left', edit: { type: "select" }, bind: { data: columnType } }, + { field: 'orderNo', title: '列显示顺序', width: 120, align: 'left', edit: { type: "text" } }, + { field: 'maxlength', title: '字段最大长度', width: 130, align: 'left', edit: { type: "text" } }, + { field: 'columnType', title: '数据类型', width: 120, align: 'left', edit: { type: "text" } }, + { field: 'isNull', title: '可为空', width: 120, align: 'left', edit: { type: "switch", keep: true } }, + { field: 'isReadDataset', title: '是否只读', width: 120, align: 'left', edit: { type: "switch", keep: true } }, + { field: 'isColumnData', title: '数据列', width: 120, align: 'left', edit: { type: "switch", keep: true } }, + { field: 'isDisplay', title: '是否显示', width: 120, align: 'left', edit: { type: "switch", keep: true } }, + { field: 'columnWidth', title: 'table列宽度', width: 120, align: 'left', edit: { type: "text" } }, + { field: 'colSize', title: '编辑列标签宽度colSize', width: 180, align: 'left', edit: { type: "text" } }, + // { field: 'import', title: '导入列', hidden: true, width: 100, align: 'left', edit: { type: "switch" } }, + // { field: 'apiInPut', title: 'Api输入列(待实现)', width: 100, align: 'left', edit: { type: "switch" } }, + // { field: 'apiIsNull', title: 'Api输入列可为空(待实现)', width: 130, align: 'left', edit: { type: "switch" } }, + // { field: 'apiOutPut', title: 'Api输出列(待实现)', width: 100, align: 'left', edit: { type: "switch" } }, + // { field: 'columnformat', title: '显示格式', width: 120, align: 'left', editor: 'text', editor: 'textarea' }, + // { field: 'script', title: '脚本', width: 120, align: 'left', editor: 'textarea' }, + // { field: 'creator', title: '创建人', width: 120, align: 'left' }, + { field: 'createDate', title: '创建时间', width: 120, align: 'left' }, + // { field: 'modifier', title: '修改人', width: 120, align: 'left' }, + // { field: 'modifyDate', title: '修改时间', width: 120, align: 'left' } + ] +} + +export default data \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/builder/coder.vue b/Pure_Vite_Net7/Vue3Vite/src/views/builder/coder.vue new file mode 100644 index 0000000000000000000000000000000000000000..f30ade4f37228f8d56dfedec858113fe3cf86112 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/builder/coder.vue @@ -0,0 +1,658 @@ + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/formDraggable/FormCollectionResultTree.vue b/Pure_Vite_Net7/Vue3Vite/src/views/formDraggable/FormCollectionResultTree.vue new file mode 100644 index 0000000000000000000000000000000000000000..e1f4635ba7f51cd470c34a13e2445c2a0a33484e --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/formDraggable/FormCollectionResultTree.vue @@ -0,0 +1,95 @@ + + + + + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/formDraggable/FormSubmit.vue b/Pure_Vite_Net7/Vue3Vite/src/views/formDraggable/FormSubmit.vue new file mode 100644 index 0000000000000000000000000000000000000000..ddbe170c02848a653c5677434fa56c186ab421e0 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/formDraggable/FormSubmit.vue @@ -0,0 +1,173 @@ + + + + + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/formDraggable/formDraggable.vue b/Pure_Vite_Net7/Vue3Vite/src/views/formDraggable/formDraggable.vue new file mode 100644 index 0000000000000000000000000000000000000000..c8eac6a912f8c2797fc207209e492425be673033 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/formDraggable/formDraggable.vue @@ -0,0 +1,31 @@ + + + + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/home/home-chart-options.js b/Pure_Vite_Net7/Vue3Vite/src/views/home/home-chart-options.js new file mode 100644 index 0000000000000000000000000000000000000000..3eaf63def666e9a4e5855cfdca1e4415ee6576b1 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/home/home-chart-options.js @@ -0,0 +1,248 @@ +var chart1 = { + title: { + text: "框架集成及开发环境", + left: 'center', + padding: 15, + }, + tooltip: { + trigger: 'item' + }, + legend: { + top: 'bottom', + icon: "circle", // 这个字段控制形状 类型包括 circle,rect ,roundRect,triangle,diamond,pin,arrow,none + itemWidth: 10, // 设置宽度 + itemHeight: 10, // 设置高度 + itemGap: 7,// 设置间距 + padding: [0, 0, 15, 0] //图例距离 + }, + series: [ + { + name: '框架', + type: 'pie', + radius: ['40%', '65%'], + avoidLabelOverlap: false, + itemStyle: { + borderRadius: 10, + borderColor: '#fff', + borderWidth: 2 + }, + label: { + show: false, + position: 'center' + }, + emphasis: { + label: { + show: true, + fontSize: '40', + fontWeight: 'bold' + } + }, + labelLine: { + show: false + }, + data: [ + { value: 1048, name: '.NetCore' }, + { value: 735, name: 'Dapper' }, + + { value: 735, name: 'EntityFramework' }, + // { value: 735, name: 'JWT' }, + { value: 735, name: 'Redis' }, + { value: 735, name: 'Vue3.0' }, + { value: 580, name: 'Vuex' }, + { value: 484, name: 'Element plus' } + ] + } + ] +} + +var chart2 = { + title: { + text: '这里是首页' + }, + tooltip: { + trigger: 'axis', + axisPointer: { // 坐标轴指示器,坐标轴触发有效 + type: 'shadow' // 默认为直线,可选为:'line' | 'shadow' + } + }, + legend: { + data: ['2.0下载量', '3.0下载量'], + padding: [0, 0, 15, 0] //图例距离 + }, + grid: { + left: '3%', + right: '4%', + bottom: '3%', + top:'13%', + containLabel: true + }, + xAxis: [ + { + type: 'category', + data: [ '2015', '2016', '2017', '2018', '2019', '2020', '2021'] + } + ], + yAxis: [ + { + type: 'value' + } + ], + series: [ + { + name: '2.0下载量', + type: 'bar', + showBackground: true, + backgroundStyle: { + color: 'rgba(180, 180, 180, 0.2)' + }, + itemStyle: { + + normal: { + barBorderRadius: [4, 4, 0, 0] + } + }, + data: [ 730, 620, 420, 932, 701, 834, 890] + }, + { + name: '3.0下载量', + type: 'bar', + + showBackground: true, + backgroundStyle: { + color: 'rgba(180, 180, 180, 0.2)' + }, + data: [230, 210, 120, 132, 101, 134, 90] + } + ] +} +var chart3 = { + title: { + text: '框架支持功能(Vue2.0、Vue3.0版本)', + left: 'center' + }, + tooltip: { + trigger: 'item' + }, + legend: { + top: 'bottom', + icon: "circle", // 这个字段控制形状 类型包括 circle,rect ,roundRect,triangle,diamond,pin,arrow,none + itemWidth: 10, // 设置宽度 + itemHeight: 10, // 设置高度 + itemGap: 7,// 设置间距 + padding: [0, 0, 10, 0] //图例距离 + }, + series: [ + { + + name: '框架支持功能(Vue2.0、Vue3版本)', + type: 'pie', + radius: '55%', + data: [ + { value: 748, name: '多租户' }, + { value: 435, name: '多角色' }, + { value: 580, name: '多数据库' }, + { value: 280, name: '主从分库' }, + { value: 284, name: '国际化' }, + { value: 300, name: 'App/H5开发' }, + { value: 200, name: 'Redis' }, + { value: 600, name: 'Sqlserver' }, + { value: 400, name: 'Mysql' }, + { value: 100, name: 'Oracle' }, + ], + emphasis: { + itemStyle: { + shadowBlur: 10, + shadowOffsetX: 0, + shadowColor: 'rgba(0, 0, 0, 0.5)' + } + } + } + ] +} +var chart4={ + tooltip: { + trigger: 'axis', + axisPointer: { + // Use axis to trigger tooltip + type: 'shadow' // 'shadow' as default; can also be 'line' or 'shadow' + } + }, + legend: {}, + grid: { + left: '3%', + right: '4%', + bottom: '3%', + top:'13%', + containLabel: true + }, + xAxis: { + type: 'value' + }, + yAxis: { + type: 'category', + data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] + }, + series: [ + { + name: 'Direct', + type: 'bar', + stack: 'total', + label: { + show: true + }, + emphasis: { + focus: 'series' + }, + data: [320, 302, 301, 334, 390, 330, 320] + }, + { + name: 'Mail Ad', + type: 'bar', + stack: 'total', + label: { + show: true + }, + emphasis: { + focus: 'series' + }, + data: [120, 132, 101, 134, 90, 230, 210] + }, + { + name: 'Affiliate Ad', + type: 'bar', + stack: 'total', + label: { + show: true + }, + emphasis: { + focus: 'series' + }, + data: [220, 182, 191, 234, 290, 330, 310] + }, + { + name: 'Video Ad', + type: 'bar', + stack: 'total', + label: { + show: true + }, + emphasis: { + focus: 'series' + }, + data: [150, 212, 201, 154, 190, 330, 410] + }, + { + name: 'Search Engine', + type: 'bar', + stack: 'total', + label: { + show: true + }, + emphasis: { + focus: 'series' + }, + data: [820, 832, 901, 934, 1290, 1330, 1320] + } + ] + } +export { chart1, chart2, chart3,chart4 } \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/index/Message.vue b/Pure_Vite_Net7/Vue3Vite/src/views/index/Message.vue new file mode 100644 index 0000000000000000000000000000000000000000..2c77447a208520cb1e8e16a03bdb8bdcef42b89c --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/index/Message.vue @@ -0,0 +1,45 @@ + + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/index/MessageConfig.js b/Pure_Vite_Net7/Vue3Vite/src/views/index/MessageConfig.js new file mode 100644 index 0000000000000000000000000000000000000000..a78f8e82e6b7425d03e6e190f5f8481ce7862d75 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/index/MessageConfig.js @@ -0,0 +1,28 @@ +import * as signalR from '@microsoft/signalr'; +import { ElNotification } from 'element-plus'; + +export default function (http, receive) { + let connection; + http.post('api/user/GetCurrentUserInfo').then((result) => { + connection = new signalR.HubConnectionBuilder() + .withAutomaticReconnect() + .withUrl(`${http.ipAddress}message?userName=${result.data.userName}`) + //.withUrl(`${http.ipAddress}message`) + .build(); + + connection.start().catch((err) => console.log(ex.message)); + //自动重连成功后的处理 + connection.onreconnected((connectionId) => { + console.log(connectionId); + }); + connection.on('ReceiveHomePageMessage', function (data) { + console.log(data) + ElNotification.success({ + title:data.title, + message: data.message + '', + type: 'info' + }); + receive && receive(data); + }); + }); +} diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/index/index.less b/Pure_Vite_Net7/Vue3Vite/src/views/index/index.less new file mode 100644 index 0000000000000000000000000000000000000000..8a414a276c4d8bab8279cfc095f3537c1a2fb09a --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/index/index.less @@ -0,0 +1,641 @@ +.vol-aside { + height: 100%; + position: absolute; + float: left; + overflow: hidden; +} + +.vol-menu { + border: 0 !important; +} + +.vol-aside .tac { + text-align: left; +} + +.vol-aside .header { + text-align: center; + position: absolute; + height: 60px; + position: relative; + line-height: 60px; +} + +.vol-aside .vol-menu { + position: absolute; + width: 100%; + top: 60px; + bottom: 0; + background: white; + border-right: 1px solid #e3e3e3; +} + +.vol-aside .vol-menu ::v-deep(.ivu-menu) { + text-align: left; + position: unset; + width: 100% !important; +} + +.vol-aside .vol-menu ::v-deep(.is-horizontal) { + display: none !important; +} + +.vol-aside .vol-menu ::v-deep(.is-vertical) { + width: 2px; + right: -1px; +} + +.vol-container { + min-width: 800px; + right: 0; + display: inline-block; + position: absolute; + margin: 0; + box-sizing: border-box; + height: 100%; +} + +.vol-container .vol-path { + position: relative; + width: 100%; + display: inline-block; + border-bottom: 1px solid #eee; +} + +.vol-container .vol-path span { + position: relative; + margin-right: 10px; + color: #969696; +} + +.vol-header { + height: 61px; + width: 100%; + position: relative; + display: flex; + border-bottom: 1px solid #eee; +} + +.vol-main { + border-left: 1px solid #eee; + position: absolute; + width: 100%; + bottom: 0; + top: 95px; + margin: 0; + overflow: auto; +} + +.header { + padding: 5px; +} + +.header img { + height: 100%; + margin-right: 25px; +} + +.header-info { + padding-right: 20px; + display: inline-block; + // position: absolute; + height: 100%; +} + +.header-info>div { + float: left; + height: 100%; +} + +.user-header { + background: white; + height: 52px; + width: 52px; + border-radius: 50%; + margin-right: 0px; + top: 4px; + left: 7px; + position: relative; + border: 1px solid #dfdfdf; +} + +.project-name { + line-height: 60px; + padding: 0 50px 0 20px; + color: #fff; + font-size: 14px; +} + +.header-text { + vertical-align: middle; + height: 100%; + // position: absolute; + flex: 1; + text-align: left; + font-size: 15px; + left: 21px; + line-height: 60px; + letter-spacing: 1px; +} + +.vol-header .user { + text-align: left; + padding: 12px; + position: relative; + display: inline-block; + height: 100%; + + span:last-child { + font-size: 12px; + } +} + +.vol-header .settings { + padding-top: 10px; + color: #d4d2d2; +} + +.vol-header .user span { + position: relative; +} + +.header-info:hover { + cursor: pointer; +} + +.header-navigation { + cursor: pointer; + box-shadow: none; + border-bottom: 1px solid #eee; + height: 34px; + /* overflow: hidden; */ + line-height: 35px; + display: block; + margin: 0; + padding: 0; + outline: 0; + list-style: none; + position: relative; + z-index: 900; + font-weight: initial; + margin-top: -1px; +} + +.el-tabs--border-card { + border: none; +} + +.header-navigation ::v-deep(.el-tabs__item) { + height: 34px; + font-size: 14px; + line-height: 34px; + padding-bottom: 6px; + color: #525252 !important; + position: relative; + margin: 0 4px; + border: 1px solid #e2e2e2; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + // border-bottom: 0px; +} + +.header-navigation ::v-deep(.el-tabs__item.is-active) { + color: #1a81ea !important; +} + +.header-navigation ::v-deep(.el-tabs__nav-prev), +.header-navigation ::v-deep(.el-tabs__nav-next) { + line-height: 35px; + padding-left: 4px; +} + +.vol-header .user span:first-child { + font-size: 15px; + font-weight: bolder; +} + +.h-link { + line-height: 59px; +} + +.h-link a { + font-size: 14px; + text-decoration: none; + padding: 0px 15px; + /* height: 60px; */ + display: inline-block; +} + +img[src=''], +img:not([src]) { + opacity: 0; +} + +//黑色 +.vol-theme-dark { + .header { + background: #101010; + } + + .header-text { + color: white; + } + + .vol-header { + background-color: #272929; + } + + .h-link a:hover { + background: #0c0202; + } + + a { + color: #f2f2f2; + } + + .h-link a:hover { + color: #dfdfdf; + } + + .h-link .actived { + border-bottom: 2px solid white; + } + + .h-link .actived a { + color: white !important; + } + + .vol-header .user { + color: #ececec; + } + + .vol-header .settings { + color: #d4d2d2; + } + + .vol-aside .vol-menu { + background: black; + } +} + +.vol-theme-white .vol-aside ::v-deep(.vol-el-menu-item) { + background: #2e333b; + color: white; +} + +.vol-theme-dark .vol-aside ::v-deep(.vol-menu .el-submenu) { + background: black; +} + +.vol-theme-dark .vol-aside ::v-deep(.vol-menu .el-sub-menu__title *) { + color: #d6d6d6; +} + +.vol-theme-dark .vol-aside ::v-deep(.vol-el-menu-item .el-menu-item) { + color: #eee; + background: #1f1f1f; +} + +.vol-theme-dark .vol-aside ::v-deep(.vol-el-menu-item .el-menu-item.is-active), +.vol-theme-dark .vol-aside ::v-deep(.menu-item-lv1) { + background: black; +} + +.vol-theme-dark .vol-aside ::v-deep(.menu-item-lv1) { + background: black; + color: #d6d6d6; +} + +.vol-theme-dark .vol-aside ::v-deep(.vol-el-menu-item .el-menu-item:hover) { + background: black; +} + +.vol-theme-dark .vol-aside ::v-deep(.el-sub-menu__title) { + background-color: black; +} + +.vol-theme-dark .vol-aside ::v-deep(.el-sub-menu__title:hover) { + background-color: rgb(25, 25, 25); +} + +.vol-theme-dark .vol-aside ::v-deep(.el-sub-menu__title:hover *) { + color: white; +} + +.vol-theme-red, +.vol-theme-red2 { + .vol-header { + background-color: rgb(237, 64, 20); + } + + .header-text { + color: #dcdfe6; + } + + .h-link a:hover { + background: #d71212; + } + + .h-link .actived { + border-bottom: 2px solid white; + } + + .h-link a, + .h-link .actived a, + .vol-header .settings, + .vol-header .user { + color: white; + } + + .vol-header .header-text { + color: #fbfbfb; + } +} + +.vol-theme-red { + .header { + background-color: rgb(237, 64, 20); + } +} + +.vol-theme-red2 { + .header { + background-color: #a90000; + } +} + +.vol-theme-orange, +.vol-theme-orange2 { + .header-text { + color: #dcdfe6; + } + + .vol-header { + background-color: rgb(255, 153, 0); + } + + .h-link a:hover { + background: #c97901; + } + + .h-link .actived { + border-bottom: 2px solid white; + } + + .h-link a, + .h-link .actived a, + .vol-header .settings, + .vol-header .user { + color: white; + } + + .vol-header .header-text { + color: #fbfbfb; + } +} + +.vol-theme-orange { + .header { + background: rgb(255, 153, 0); + } +} + +.vol-theme-orange2 { + .header { + background-color: rgb(232, 141, 5); + } +} + +//绿色 +.vol-theme-green, +.vol-theme-green2 { + .header-text { + color: #dcdfe6; + } + + .vol-header { + background-color: rgb(25, 190, 107); + } + + .h-link a:hover { + background: #329103; + } + + .h-link .actived { + border-bottom: 2px solid white; + } + + .h-link a, + .h-link .actived a, + .vol-header .settings, + .vol-header .user { + color: white; + } + + .vol-header .header-text { + color: #fbfbfb; + } +} + +.vol-theme-green { + .header { + background: rgb(25, 190, 107); + } +} + +.vol-theme-green2 { + .header { + background-color: rgb(1, 158, 79); + } +} + +//蓝色 +.vol-theme-blue, +.vol-theme-blue2 { + .header-text { + color: #dcdfe6; + } + + .vol-header { + background-color: rgb(45, 140, 240); + } + + .h-link a:hover { + background: #0170e3; + } + + .h-link .actived { + border-bottom: 2px solid white; + } + + .h-link a, + .h-link .actived a, + .vol-header .settings, + .vol-header .user { + color: white; + } + + .vol-header .header-text { + color: #fbfbfb; + } +} + +.vol-theme-blue { + .header { + background-color: rgb(45, 140, 240); + } +} + +.vol-theme-blue2 { + .header { + background-color: rgb(0, 104, 214); + } +} + +//白色 +.vol-theme-white { + .header { + background-color: #434956; + } + + .h-link a:hover { + background: #eeeeee; + } + + .h-link a { + color: #211f1f; + } + + .header-navigation { + // box-shadow: -7px 11px 10px -13px #678aa7; + border-bottom: 1px solid #eee; + height: 32px; + overflow: hidden; + line-height: 32px; + display: block; + margin: 0; + padding: 0; + outline: 0; + list-style: none; + position: relative; + z-index: 900; + font-weight: 400; + } + + .vol-aside .vol-menu { + background: #353941; + } +} + +.vol-theme-white .project-name { + color: #505050; +} + +.vol-theme-white .vol-aside::v-deep(.vol-el-menu-item .el-menu-item.is-active), +.vol-theme-white .vol-aside ::v-deep(.menu-item-lv1) { + background: #353941; +} + +.vol-theme-white .vol-aside ::v-deep(.menu-item-lv1) { + background: #353941; + color: #d6d6d6; +} + +.vol-theme-white .vol-aside ::v-deep(.vol-el-menu-item .el-menu-item:hover) { + background: #353941; +} + +.vol-theme-white .vol-aside ::v-deep(.el-sub-menu__title) { + background-color: #353941; +} + +.vol-theme-white .vol-aside ::v-deep(.el-sub-menu__title:hover) { + background-color: rgb(47, 46, 46); +} + +.vol-theme-white .vol-aside ::v-deep(.el-sub-menu__title), +.vol-theme-white .vol-aside ::v-deep(.el-menu-item), +.vol-theme-white .vol-aside ::v-deep(.el-sub-menu__title:hover *) { + color: #bababa; +} + +// .vol-theme-white .vol-aside ::v-deep(.vol-el-menu-item) { +// background: #363e4f; +// color: white; +// } +// .vol-theme-white .vol-aside ::v-deep(.vol-menu .el-submenu), +// .vol-theme-white .vol-aside ::v-deep(.menu-item-lv1) { +// background: #515a6e; +// } +// .vol-theme-white .vol-aside ::v-deep(.vol-menu) { +// background: #515a6e; +// } +// .vol-theme-white .vol-aside ::v-deep(.vol-menu .el-sub-menu__title *), +// .vol-theme-white .vol-aside ::v-deep(.menu-item-lv1 *) { +// color: #d6d6d6; +// } +// .vol-theme-white .vol-aside ::v-deep(.vol-el-menu-item .el-menu-item) { +// color: #eee; +// } +// .vol-theme-white .vol-aside ::v-deep(.vol-el-menu-item .el-menu-item.is-active), +// .vol-theme-white .vol-aside ::v-deep(.menu-item-lv1.is-active) { +// background: #59647b; +// color: #fff; +// } +// .vol-theme-white .vol-aside ::v-deep(.vol-el-menu-item .el-menu-item:hover) { +// background: #6a758c; +// } +// .vol-theme-white .vol-aside ::v-deep(.el-sub-menu__title:hover) { +// background-color: #525865; +// } +// .vol-theme-white .vol-aside ::v-deep(.el-sub-menu__title:hover *) { +// color: white; +// } + +// .vol-theme-red ::v-deep(.el-menu-item.is-active), +// .vol-theme-red2 ::v-deep(.el-menu-item.is-active) +// { +// background-color: #d71212; +// } +// .vol-theme-blue ::v-deep(.el-menu-item.is-active), +// .vol-theme-blue2 ::v-deep(.el-menu-item.is-active) +// { +// background-color: #2d8cf0; +// } +// .vol-theme-orange ::v-deep(.el-menu-item.is-active), +// .vol-theme-orange2 ::v-deep(.el-menu-item.is-active) +// { +// background-color: #ff9900; +// } + +// .vol-theme-green ::v-deep(.el-menu-item.is-active), +// .vol-theme-green2 ::v-deep(.el-menu-item.is-active) +// { +// background-color: #19be6b; +// } + +.theme-selector { + height: 100%; + padding-left: 16px; + + .item { + cursor: pointer; + width: 60px; + height: 60px; + border-radius: 5px; + margin-bottom: 17px; + border: 1px solid #d4d2d2; + float: left; + margin-right: 13px; + } +} + +.collapse-menu { + font-size: 21px; + color: #fff; + line-height: 60px; + position: absolute; + top: 0; + right: 5px; + cursor: pointer; +} \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/signalR/Index.vue b/Pure_Vite_Net7/Vue3Vite/src/views/signalR/Index.vue new file mode 100644 index 0000000000000000000000000000000000000000..92d93bf366cce05c8f986bd723d2cdcba553fea7 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/signalR/Index.vue @@ -0,0 +1,114 @@ + + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/system/Permission.vue b/Pure_Vite_Net7/Vue3Vite/src/views/system/Permission.vue new file mode 100644 index 0000000000000000000000000000000000000000..c10b9b215ba6d5ea178df4e4cf364e47b63afe81 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/system/Permission.vue @@ -0,0 +1,357 @@ + + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/system/Permission/RoleTree.vue b/Pure_Vite_Net7/Vue3Vite/src/views/system/Permission/RoleTree.vue new file mode 100644 index 0000000000000000000000000000000000000000..efe199347c3785661269b6e9b2ff87f10beac0a0 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/system/Permission/RoleTree.vue @@ -0,0 +1,152 @@ + + + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/system/Sys_Dictionary.vue b/Pure_Vite_Net7/Vue3Vite/src/views/system/Sys_Dictionary.vue new file mode 100644 index 0000000000000000000000000000000000000000..8f2b5f734781a6ca92d559ad3c83eb0c87ad2511 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/system/Sys_Dictionary.vue @@ -0,0 +1,90 @@ + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/system/Sys_DictionaryList.vue b/Pure_Vite_Net7/Vue3Vite/src/views/system/Sys_DictionaryList.vue new file mode 100644 index 0000000000000000000000000000000000000000..02427fbdf487a653adba31f21f960badc15d378c --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/system/Sys_DictionaryList.vue @@ -0,0 +1,65 @@ + + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/system/Sys_Log.vue b/Pure_Vite_Net7/Vue3Vite/src/views/system/Sys_Log.vue new file mode 100644 index 0000000000000000000000000000000000000000..9742628d993006f7fcf8e764aaa78dad6e009444 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/system/Sys_Log.vue @@ -0,0 +1,70 @@ + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/system/Sys_Menu.vue b/Pure_Vite_Net7/Vue3Vite/src/views/system/Sys_Menu.vue new file mode 100644 index 0000000000000000000000000000000000000000..52cee54207633aa7bc71047022bacb918d097758 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/system/Sys_Menu.vue @@ -0,0 +1,630 @@ + + + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/system/Sys_Role.vue b/Pure_Vite_Net7/Vue3Vite/src/views/system/Sys_Role.vue new file mode 100644 index 0000000000000000000000000000000000000000..6a0a1da125b90c5fb64bba364e4d0bb56dd767f8 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/system/Sys_Role.vue @@ -0,0 +1,72 @@ + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/system/Sys_Role1.vue b/Pure_Vite_Net7/Vue3Vite/src/views/system/Sys_Role1.vue new file mode 100644 index 0000000000000000000000000000000000000000..19ed48a823ff749316394262b51395678ab0dec9 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/system/Sys_Role1.vue @@ -0,0 +1,72 @@ + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/system/Sys_User.vue b/Pure_Vite_Net7/Vue3Vite/src/views/system/Sys_User.vue new file mode 100644 index 0000000000000000000000000000000000000000..68f64294376f10db7fb70bbefc1bd98153336cc2 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/system/Sys_User.vue @@ -0,0 +1,94 @@ + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/system/UserInfo.vue b/Pure_Vite_Net7/Vue3Vite/src/views/system/UserInfo.vue new file mode 100644 index 0000000000000000000000000000000000000000..67fe117679ec8f574da82c9779bc3544b5c74efb --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/system/UserInfo.vue @@ -0,0 +1,331 @@ + + + + + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/system/flow/Sys_WorkFlow.js b/Pure_Vite_Net7/Vue3Vite/src/views/system/flow/Sys_WorkFlow.js new file mode 100644 index 0000000000000000000000000000000000000000..ae8e77f04c4619cc29491daec6085bfbfa8424a6 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/system/flow/Sys_WorkFlow.js @@ -0,0 +1,90 @@ +/***************************************************************************************** + ** Author:jxx 2022 + ** QQ:283591387 + **完整文档见:http://v2.volcore.xyz/document/api 【代码生成页面ViewGrid】 + **常用示例见:http://v2.volcore.xyz/document/vueDev + **后台操作见:http://v2.volcore.xyz/document/netCoreDev + *****************************************************************************************/ +//此js文件是用来自定义扩展业务代码,可以扩展一些自定义页面或者重新配置生成的代码 +import gridHader from './Sys_WorkFlow/WorkFlowGridHeader.vue'; +import { h, resolveComponent } from 'vue'; +let extension = { + components: { + //查询界面扩展组件 + gridHeader: gridHader, + gridBody: { + render() { + return [ + h( + resolveComponent('el-alert'), + { + style: { 'margin-bottom': '12px' }, + 'show-icon': true, + type: 'success', + closable: false, + title: '流程设计器根据easy-flow修改' + }, + '' + ) + ]; + } + }, + gridFooter: '', + //新建、编辑弹出框扩展组件 + modelHeader: '', + modelBody: '', + modelFooter: '' + }, + tableAction: '', //指定某张表的权限(这里填写表名,默认不用填写) + buttons: { view: [], box: [], detail: [] }, //扩展的按钮 + methods: { + //下面这些方法可以保留也可以删除 + onInit() { + //框架初始化配置前, + //示例:在按钮的最前面添加一个按钮 + // this.buttons.unshift({ //也可以用push或者splice方法来修改buttons数组 + // name: '按钮', //按钮名称 + // icon: 'el-icon-document', //按钮图标vue2版本见iview文档icon,vue3版本见element ui文档icon(注意不是element puls文档) + // type: 'primary', //按钮样式vue2版本见iview文档button,vue3版本见element ui文档button + // onClick: function () { + // this.$Message.success('点击了按钮'); + // } + // }); + //示例:设置修改新建、编辑弹出框字段标签的长度 + // this.boxOptions.labelWidth = 150; + }, + onInited() { + this.height = this.height - 50; + //框架初始化配置后 + //如果要配置明细表,在此方法操作 + //this.detailOptions.columns.forEach(column=>{ }); + }, + searchBefore(param) { + //界面查询前,可以给param.wheres添加查询参数 + //返回false,则不会执行查询 + return true; + }, + searchAfter(result) { + //查询后,result返回的查询数据,可以在显示到表格前处理表格的值 + return true; + }, + addBefore(formData) { + //新建保存前formData为对象,包括明细表,可以给给表单设置值,自己输出看formData的值 + return true; + }, + updateBefore(formData) { + //编辑保存前formData为对象,包括明细表、删除行的Id + return true; + }, + rowClick({ row, column, event }) { + //查询界面点击行事件 + // this.$refs.table.$refs.table.toggleRowSelection(row); //单击行时选中当前行; + }, + async modelOpenBeforeAsync(row) { + //点击编辑/新建按钮弹出框前,可以在此处写逻辑,如,从后台获取数据 + this.$refs.gridHeader.open(row); + return false; + } + } +}; +export default extension; diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/system/flow/Sys_WorkFlow.vue b/Pure_Vite_Net7/Vue3Vite/src/views/system/flow/Sys_WorkFlow.vue new file mode 100644 index 0000000000000000000000000000000000000000..04bf10de8beb583ef75ff78e3d5a0af073d78335 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/system/flow/Sys_WorkFlow.vue @@ -0,0 +1,85 @@ + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/system/flow/Sys_WorkFlow/WorkFlowGridHeader.vue b/Pure_Vite_Net7/Vue3Vite/src/views/system/flow/Sys_WorkFlow/WorkFlowGridHeader.vue new file mode 100644 index 0000000000000000000000000000000000000000..7a48b7ff6c8004133c29eed40f1558c2e6c7fd89 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/system/flow/Sys_WorkFlow/WorkFlowGridHeader.vue @@ -0,0 +1,194 @@ + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/system/flow/Sys_WorkFlowStep.vue b/Pure_Vite_Net7/Vue3Vite/src/views/system/flow/Sys_WorkFlowStep.vue new file mode 100644 index 0000000000000000000000000000000000000000..a687a0e7a162bf067a9ab662b20a2ae4d2abeb31 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/system/flow/Sys_WorkFlowStep.vue @@ -0,0 +1,70 @@ + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/system/flow/Sys_WorkFlowTable.js b/Pure_Vite_Net7/Vue3Vite/src/views/system/flow/Sys_WorkFlowTable.js new file mode 100644 index 0000000000000000000000000000000000000000..35cd7a655b635595f6d727ff5b3f3745e75e6f4e --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/system/flow/Sys_WorkFlowTable.js @@ -0,0 +1,79 @@ +/***************************************************************************************** + ** Author:jxx 2022 + ** QQ:283591387 + **完整文档见:http://v2.volcore.xyz/document/api 【代码生成页面ViewGrid】 + **常用示例见:http://v2.volcore.xyz/document/vueDev + **后台操作见:http://v2.volcore.xyz/document/netCoreDev + *****************************************************************************************/ +//此js文件是用来自定义扩展业务代码,可以扩展一些自定义页面或者重新配置生成的代码 + +let extension = { + components: { + //查询界面扩展组件 + gridHeader: '', + gridBody: '', + gridFooter: '', + //新建、编辑弹出框扩展组件 + modelHeader: '', + modelBody: '', + modelFooter: '' + }, + tableAction: '', //指定某张表的权限(这里填写表名,默认不用填写) + buttons: { view: [], box: [], detail: [] }, //扩展的按钮 + methods: { + //下面这些方法可以保留也可以删除 + onInit() { + this.columns.push({ + field: '操作', + title: '查看', + width: 100, + align: 'center', + formatter: (row) => { + return '查看详情'; + }, + click: (row) => { + this.$tabs.open({ + text: row.WorkTableName, + path: '/' + row.WorkTable, + query: { id: row.WorkTableKey, viewflow: 1 } + }); + } + }); + }, + onInited() { + //框架初始化配置后 + //如果要配置明细表,在此方法操作 + //this.detailOptions.columns.forEach(column=>{ }); + }, + searchBefore(param) { + //界面查询前,可以给param.wheres添加查询参数 + //返回false,则不会执行查询 + return true; + }, + searchAfter(result) { + //查询后,result返回的查询数据,可以在显示到表格前处理表格的值 + return true; + }, + addBefore(formData) { + //新建保存前formData为对象,包括明细表,可以给给表单设置值,自己输出看formData的值 + return true; + }, + updateBefore(formData) { + //编辑保存前formData为对象,包括明细表、删除行的Id + return true; + }, + rowClick({ row, column, event }) { + //查询界面点击行事件 + // this.$refs.table.$refs.table.toggleRowSelection(row); //单击行时选中当前行; + }, + modelOpenAfter(row) { + //点击编辑、新建按钮弹出框后,可以在此处写逻辑,如,从后台获取数据 + //(1)判断是编辑还是新建操作: this.currentAction=='Add'; + //(2)给弹出框设置默认值 + //(3)this.editFormFields.字段='xxx'; + //如果需要给下拉框设置默认值,请遍历this.editFormOptions找到字段配置对应data属性的key值 + //看不懂就把输出看:console.log(this.editFormOptions) + } + } +}; +export default extension; diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/system/flow/Sys_WorkFlowTable.vue b/Pure_Vite_Net7/Vue3Vite/src/views/system/flow/Sys_WorkFlowTable.vue new file mode 100644 index 0000000000000000000000000000000000000000..60daa8fba315fbb32560927d7298e0459e71481b --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/system/flow/Sys_WorkFlowTable.vue @@ -0,0 +1,89 @@ + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/system/flow/Sys_WorkFlowTableStep.vue b/Pure_Vite_Net7/Vue3Vite/src/views/system/flow/Sys_WorkFlowTableStep.vue new file mode 100644 index 0000000000000000000000000000000000000000..a6b43dafefe489c5b99f242e354f5eae1a3f05ef --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/system/flow/Sys_WorkFlowTableStep.vue @@ -0,0 +1,75 @@ + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/system/form/FormCollectionObject.vue b/Pure_Vite_Net7/Vue3Vite/src/views/system/form/FormCollectionObject.vue new file mode 100644 index 0000000000000000000000000000000000000000..82a091eaedb23787f4383b00162ac195034fbdcb --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/system/form/FormCollectionObject.vue @@ -0,0 +1,65 @@ + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/system/form/FormDesignOptions.vue b/Pure_Vite_Net7/Vue3Vite/src/views/system/form/FormDesignOptions.vue new file mode 100644 index 0000000000000000000000000000000000000000..cbed56e7883afe035b9c919f15090693e27b63ae --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/system/form/FormDesignOptions.vue @@ -0,0 +1,67 @@ + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/system/quartz/Sys_QuartzLog.vue b/Pure_Vite_Net7/Vue3Vite/src/views/system/quartz/Sys_QuartzLog.vue new file mode 100644 index 0000000000000000000000000000000000000000..70878cb61faff214200f086a4130014af2d76e48 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/system/quartz/Sys_QuartzLog.vue @@ -0,0 +1,70 @@ + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/system/quartz/Sys_QuartzOptions.vue b/Pure_Vite_Net7/Vue3Vite/src/views/system/quartz/Sys_QuartzOptions.vue new file mode 100644 index 0000000000000000000000000000000000000000..bbbdf0471ec70fc2073b58324434259c826b819a --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/system/quartz/Sys_QuartzOptions.vue @@ -0,0 +1,85 @@ + + + diff --git a/Pure_Vite_Net7/Vue3Vite/src/views/system/test.vue b/Pure_Vite_Net7/Vue3Vite/src/views/system/test.vue new file mode 100644 index 0000000000000000000000000000000000000000..64786be84cbac7c7a2ebc7613c7d7a89c148152b --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/src/views/system/test.vue @@ -0,0 +1,18 @@ + + + + + \ No newline at end of file diff --git a/Pure_Vite_Net7/Vue3Vite/tests/unit/example.spec.js b/Pure_Vite_Net7/Vue3Vite/tests/unit/example.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..bc9939b6544732007500d7340e0c9c830084d273 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/tests/unit/example.spec.js @@ -0,0 +1,13 @@ +import { expect } from 'chai' +import { shallowMount } from '@vue/test-utils' +import HelloWorld from '@/components/HelloWorld.vue' + +describe('HelloWorld.vue', () => { + it('renders props.msg when passed', () => { + const msg = 'new message' + const wrapper = shallowMount(HelloWorld, { + props: { msg } + }) + expect(wrapper.text()).to.include(msg) + }) +}) diff --git a/Pure_Vite_Net7/Vue3Vite/tsconfig.json b/Pure_Vite_Net7/Vue3Vite/tsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..cb2043bce62ddf911bdca4e0baebdd1eb01d211a --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "@vue/tsconfig/tsconfig.web.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + }, + + "references": [ + { + "path": "./tsconfig.node.json" + } + ] +} diff --git a/Pure_Vite_Net7/Vue3Vite/tsconfig.node.json b/Pure_Vite_Net7/Vue3Vite/tsconfig.node.json new file mode 100644 index 0000000000000000000000000000000000000000..424084aa55cdea61f25b1f974f77f37e4a846113 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/tsconfig.node.json @@ -0,0 +1,8 @@ +{ + "extends": "@vue/tsconfig/tsconfig.node.json", + "include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "playwright.config.*"], + "compilerOptions": { + "composite": true, + "types": ["node"] + } +} diff --git a/Pure_Vite_Net7/Vue3Vite/vite.config.ts b/Pure_Vite_Net7/Vue3Vite/vite.config.ts new file mode 100644 index 0000000000000000000000000000000000000000..994d4582dcc4dac463e15b7300a078d84db680c7 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/vite.config.ts @@ -0,0 +1,19 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' +import { visualizer } from "rollup-plugin-visualizer"; +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [vue(), vueJsx(), visualizer({ + filename:'report_form_rollup-plugin-visualizer.html' + })], + + resolve: { + //extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'], + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + }, +}) diff --git a/Pure_Vite_Net7/Vue3Vite/volar.config.js b/Pure_Vite_Net7/Vue3Vite/volar.config.js new file mode 100644 index 0000000000000000000000000000000000000000..3c918ff8bd4e10375162a8bc4b5bfce652409190 --- /dev/null +++ b/Pure_Vite_Net7/Vue3Vite/volar.config.js @@ -0,0 +1,5 @@ +module.exports = { + plugins: [ + require('@volar-plugins/vetur')(), + ], +}; \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/.gitignore b/Pure_Vite_Net7/WebNet7/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..5a83aa3f28d5caa240d2776ef510f5dbefb24e20 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/.gitignore @@ -0,0 +1,364 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ +todel_*/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Builder/Class1.cs b/Pure_Vite_Net7/WebNet7/VOL.Builder/Class1.cs new file mode 100644 index 0000000000000000000000000000000000000000..6de12abb25c9fa61e71acb2f99f0b3bf6fe1ed09 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Builder/Class1.cs @@ -0,0 +1,8 @@ +using System; + +namespace VOL.Builder +{ + public class Class1 + { + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Builder/IRepositories/Core/ISys_TableInfoRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.Builder/IRepositories/Core/ISys_TableInfoRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..b2e0e8761a217ea53ecdf526e51414ec4c1952a6 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Builder/IRepositories/Core/ISys_TableInfoRepository.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; +using VOL.Core.Extensions.AutofacManager; +namespace VOL.Builder.IRepositories +{ + public partial interface ISys_TableInfoRepository : IDependency,IRepository + { + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.Builder/IServices/Core/ISys_TableInfoService.cs b/Pure_Vite_Net7/WebNet7/VOL.Builder/IServices/Core/ISys_TableInfoService.cs new file mode 100644 index 0000000000000000000000000000000000000000..8ced98b6cf0b0f0963b740bd4ed703b48bbbd2ec --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Builder/IServices/Core/ISys_TableInfoService.cs @@ -0,0 +1,10 @@ +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; + +namespace VOL.Builder.IServices +{ + public partial interface ISys_TableInfoService : IService + { + } + } + diff --git a/Pure_Vite_Net7/WebNet7/VOL.Builder/IServices/Core/Partial/ISys_TableInfoService.cs b/Pure_Vite_Net7/WebNet7/VOL.Builder/IServices/Core/Partial/ISys_TableInfoService.cs new file mode 100644 index 0000000000000000000000000000000000000000..47680abe3e80151aada3c2481f54715707c41fd3 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Builder/IServices/Core/Partial/ISys_TableInfoService.cs @@ -0,0 +1,25 @@ +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; +using System.Collections.Generic; +using System.Threading.Tasks; +using VOL.Core.Utilities; + +namespace VOL.Builder.IServices +{ + public partial interface ISys_TableInfoService + { + Task<(string, string)> GetTableTree(); + + string CreateEntityModel(Sys_TableInfo tableInfo); + + WebResponseContent SaveEidt(Sys_TableInfo sysTableInfo); + + string CreateServices(string tableName, string nameSpace, string foldername, bool webController, bool apiController); + + string CreateVuePage(Sys_TableInfo sysTableInfo, string vuePath); + + object LoadTable(int parentId, string tableName, string columnCNName, string nameSpace, string foldername, int table_Id, bool isTreeLoad); + Task SyncTable(string tableName); + Task DelTree(int table_Id); + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Builder/Properties/launchSettings.json b/Pure_Vite_Net7/WebNet7/VOL.Builder/Properties/launchSettings.json new file mode 100644 index 0000000000000000000000000000000000000000..3183d52c219cd4b4d5df8403333fba5fd062a22f --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Builder/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:34188/", + "sslPort": 44309 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "VOL.Builder": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:5001;http://localhost:5000" + } + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Builder/Repositories/Core/Sys_TableInfoRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.Builder/Repositories/Core/Sys_TableInfoRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..b7770f9278f089227cbedaeeb61ced2b403de70e --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Builder/Repositories/Core/Sys_TableInfoRepository.cs @@ -0,0 +1,22 @@ +using VOL.Builder.IRepositories; +using VOL.Core.BaseProvider; +using VOL.Core.EFDbContext; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.Builder.Repositories +{ + public partial class Sys_TableInfoRepository : RepositoryBase, ISys_TableInfoRepository + { + public Sys_TableInfoRepository(VOLContext dbContext) + : base(dbContext) + { + + } + public static ISys_TableInfoRepository GetService + { + get { return AutofacContainerModule.GetService(); } + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.Builder/Services/Core/Partial/Sys_TableInfoService.cs b/Pure_Vite_Net7/WebNet7/VOL.Builder/Services/Core/Partial/Sys_TableInfoService.cs new file mode 100644 index 0000000000000000000000000000000000000000..f031fff75ac3911076b67b496d2317cf510df404 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Builder/Services/Core/Partial/Sys_TableInfoService.cs @@ -0,0 +1,1956 @@ +using VOL.Builder.Utility; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyModel; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.Loader; +using System.Text; +using System.Threading.Tasks; +using VOL.Core.Const; +using VOL.Core.DBManager; +using VOL.Core.Enums; +using VOL.Core.Extensions; +using VOL.Core.ManageUser; +using VOL.Core.Utilities; +using VOL.Entity.DomainModels; +using VOL.Entity.DomainModels.Sys; +using VOL.Entity.SystemModels; + +namespace VOL.Builder.Services +{ + public partial class Sys_TableInfoService + { + private int totalWidth = 0; + private int totalCol = 0; + private string webProject = null; + private string apiNameSpace = null; + private string startName = ""; + private string StratName + { + get + { + if (startName == "") + { + startName = WebProject.Substring(0, webProject.LastIndexOf('.')); + } + return startName; + } + } + private string WebProject + { + get + { + if (webProject != null) + return webProject; + webProject = ProjectPath.GetLastIndexOfDirectoryName(".WebApi") ?? ProjectPath.GetLastIndexOfDirectoryName("Api") ?? ProjectPath.GetLastIndexOfDirectoryName(".Web"); + if (webProject == null) + { + throw new Exception("未获取到以.WebApi结尾的项目名称,无法创建页面"); + } + return webProject; + } + } + private string ApiNameSpace + { + get + { + if (apiNameSpace != null) + return apiNameSpace; + apiNameSpace = ProjectPath.GetLastIndexOfDirectoryName(".WebApi"); + if (apiNameSpace == null) + { + throw new Exception("未获取到以.WebApi,无法创建Api控制器"); + } + return apiNameSpace; + } + } + + /// + /// 获取生成配置的树开菜单 + /// + /// + public async Task<(string, string)> GetTableTree() + { + var treeData = await repository.FindAsIQueryable(x => 1 == 1) + .Select(c => new + { + id = c.Table_Id, + pId = c.ParentId, + parentId = c.ParentId, + name = c.ColumnCNName, + orderNo = c.OrderNo + }).OrderByDescending(c => c.orderNo).ToListAsync(); + var treeList = treeData.Select(a => new + { + a.id, + a.pId, + a.parentId, + a.name, + isParent = treeData.Select(x => x.pId).Contains(a.id) + }); + string startsWith = WebProject.Substring(0, WebProject.IndexOf('.')); + return (treeList.Count() == 0 ? "[]" : treeList.Serialize() ?? "", ProjectPath.GetProjectFileName(startsWith)); + ; + + } + + /// + /// 2020.05.17增加mysql获取表结构时区分当前所在数据库 + /// + /// + private string GetMysqlTableSchema() + { + try + { + string dbName = DBServerProvider.GetConnectionString().Split("Database=")[1].Split(";")[0]?.Trim(); + if (!string.IsNullOrEmpty(dbName)) + { + dbName = $" and table_schema = '{dbName}' "; + } + return dbName; + } + catch (Exception ex) + { + Console.WriteLine($"获取mysql数据库名异常:{ex.Message}"); + return ""; + } + } + + /// + /// 获取Mysql表结构信息 + /// 2020.06.14增加对mysql数据类型double区分 + /// + /// + private string GetMySqlModelInfo() + { + return $@"SELECT +DISTINCT + CONCAT(NUMERIC_PRECISION,',',NUMERIC_SCALE) as Prec_Scale, + CASE + WHEN data_type IN( 'BIT', 'BOOL','bit', 'bool') THEN + 'bool' + WHEN data_type in('smallint','SMALLINT') THEN 'short' + WHEN data_type in('tinyint', 'TINYINT') THEN 'sbyte' + WHEN data_type IN('MEDIUMINT','mediumint', 'int','INT','year', 'Year') THEN + 'int' + WHEN data_type in ( 'BIGINT','bigint') THEN + 'bigint' + WHEN data_type IN('FLOAT', 'DECIMAL','float', 'decimal') THEN + 'decimal' + WHEN data_type IN( 'DOUBLE', 'double') THEN + 'double' + WHEN data_type IN('CHAR', 'VARCHAR', 'TINY TEXT', 'TEXT', 'MEDIUMTEXT', 'LONGTEXT', 'TINYBLOB', 'BLOB', 'MEDIUMBLOB', 'LONGBLOB', 'Time','char', 'varchar', 'tiny text', 'text', 'mediumtext', 'longtext', 'tinyblob', 'blob', 'mediumblob', 'longblob', 'time') THEN + 'nvarchar' + WHEN data_type IN('Date', 'DateTime', 'TimeStamp','date', 'datetime', 'timestamp') THEN + 'datetime' ELSE 'nvarchar' + END AS ColumnType, Column_Name AS ColumnName + FROM + information_schema.COLUMNS + WHERE + table_name = ?tableName {GetMysqlTableSchema()};"; + } + + + /// + /// 获取SqlServer表结构信息 + /// + /// + private string GetSqlServerModelInfo() + { + return $@" + SELECT CASE WHEN t.ColumnType IN ('DECIMAL','smallmoney','money') THEN + CONVERT(VARCHAR(30),t.Prec)+','+CONVERT(VARCHAR(30),t.Scale) ELSE '' + END + AS Prec_Scale,t.ColumnType,t.ColumnName + FROM ( + SELECT col.prec AS 'Prec',col.scale AS 'Scale',t.name AS ColumnType,col.name AS ColumnName FROM dbo.syscolumns col + LEFT JOIN dbo.systypes t ON col.xtype = t.xusertype + INNER JOIN dbo.sysobjects obj ON col.id = obj.id + AND obj.xtype IN ('U','V') + AND obj.status >= 0 + LEFT JOIN dbo.syscomments comm ON col.cdefault = comm.id + LEFT JOIN sys.extended_properties ep ON col.id = ep.major_id + AND col.colid = ep.minor_id + AND ep.name = 'MS_Description' + LEFT JOIN sys.extended_properties epTwo ON obj.id = epTwo.major_id + AND epTwo.minor_id = 0 + AND epTwo.name = 'MS_Description' + WHERE obj.name =@tableName) AS t"; + } + /// + /// 获取PgSQl表结构信息 + /// 2020.08.07完善PGSQL + /// + /// + /// + /// + /// + private string GetPgSqlModelInfo() + { + StringBuilder stringBuilder = new StringBuilder(); + + stringBuilder.Append(" SELECT "); + stringBuilder.Append(" col.COLUMN_NAME AS \"ColumnName\", "); + stringBuilder.Append(" CASE "); + stringBuilder.Append(" WHEN col.udt_name = 'uuid' THEN "); + stringBuilder.Append(" 'guid' "); + stringBuilder.Append(" WHEN col.udt_name IN ( 'int2') THEN "); + stringBuilder.Append(" 'short' "); + stringBuilder.Append(" WHEN col.udt_name IN ( 'int4' ) THEN "); + stringBuilder.Append(" 'int' "); + stringBuilder.Append(" WHEN col.udt_name = 'int8' THEN "); + stringBuilder.Append(" 'long' "); + stringBuilder.Append(" WHEN col.udt_name IN ( 'char', 'varchar', 'text', 'xml', 'bytea' ) THEN "); + stringBuilder.Append(" 'string' "); + stringBuilder.Append(" WHEN col.udt_name IN ( 'bool' ) THEN "); + stringBuilder.Append(" 'bool' "); + stringBuilder.Append(" WHEN col.udt_name IN ( 'date','timestamp' ) THEN "); + stringBuilder.Append(" 'DateTime' "); + stringBuilder.Append(" WHEN col.udt_name IN ( 'decimal', 'money','numeric' ) THEN "); + stringBuilder.Append(" 'decimal' "); + stringBuilder.Append(" WHEN col.udt_name IN ( 'float4', 'float8' ) THEN "); + stringBuilder.Append(" 'float' ELSE'string ' "); + stringBuilder.Append(" END as ColumnType "); + stringBuilder.Append("from information_schema.COLUMNS col "); + stringBuilder.Append("WHERE \"lower\" ( TABLE_NAME ) = \"lower\" (@tableName ) "); + return stringBuilder.ToString(); + } + + private WebResponseContent ExistsTable(string tableName, string tableTrueName) + { + WebResponseContent webResponse = new WebResponseContent(true); + //如果是第一次创建model,此处反射获取到的是已经缓存过的文件,必须重新运行项目否则新增的文件无法做判断文件是否创建,需要重新做反射实际文件,待修改... + var compilationLibrary = DependencyContext + .Default + .CompileLibraries + .Where(x => !x.Serviceable && x.Type == "project"); + foreach (var _compilation in compilationLibrary) + { + try + { + foreach (var entity in AssemblyLoadContext.Default + .LoadFromAssemblyName(new AssemblyName(_compilation.Name)) + .GetTypes().Where(x => x.GetTypeInfo().BaseType != null + && x.BaseType == typeof(BaseEntity))) + { + if (entity.Name == tableTrueName && !string.IsNullOrEmpty(tableName) && tableName != tableTrueName) + return webResponse.Error($"实际表名【{tableTrueName }】已创建实体,不能创建别名【{tableName}】实体"); + + if (entity.Name != tableName) + { + var tableAttr = entity.GetCustomAttribute(); + if (tableAttr != null && tableAttr.Name == tableTrueName) + { + return webResponse.Error($"实际表名【{tableTrueName }】已被【{entity.Name}】创建建实体,不能创建别名【{tableName}】实体,请将别名更换为【{entity.Name}】"); + } + } + } + } + catch (Exception ex) + { + + Console.WriteLine("查找文件异常:" + ex.Message); + } + } + return webResponse; + + } + + /// + /// 生成实体Model + /// + /// + /// + public string CreateEntityModel(Sys_TableInfo sysTableInfo) + { + if (sysTableInfo == null + || sysTableInfo.TableColumns == null + || sysTableInfo.TableColumns.Count == 0) + return "提交的配置数据不完整"; + + WebResponseContent webResponse = ValidColumnString(sysTableInfo); + if (!webResponse.Status) + return webResponse.Message; + + string tableName = sysTableInfo.TableName; + webResponse = ExistsTable(tableName, sysTableInfo.TableTrueName); + if (!webResponse.Status) + { + return webResponse.Message; + } + if (!string.IsNullOrEmpty(sysTableInfo.TableTrueName) && sysTableInfo.TableTrueName != tableName) + { + tableName = sysTableInfo.TableTrueName; + } + + string sql = ""; + switch (DBType.Name) + { + case "MySql": + sql = GetMySqlModelInfo(); + break; + case "PgSql": + sql = GetPgSqlModelInfo(); + break; + default: + sql = GetSqlServerModelInfo(); + break; + } + List tableColumnInfoList = repository.DapperContext.QueryList(sql, new { tableName }); + List list = sysTableInfo.TableColumns; + string msg = CreateEntityModel(list, sysTableInfo, tableColumnInfoList, 1); + if (msg != "") + return msg; + //if (list.Any(c => c.ApiInPut > 0)) + //{ + // CreateEntityModel(list.Where(c => c.ApiInPut > 0).ToList(), sysTableInfo, tableColumnInfoList, 2); + //} + //if (list.Any(c => c.ApiOutPut > 0)) + //{ + // CreateEntityModel(list.Where(c => c.ApiOutPut > 0).ToList(), sysTableInfo, tableColumnInfoList, 3); + //} + return "Model创建成功!"; + } + + /// + /// 保存配置信息 + /// + /// + /// + public WebResponseContent SaveEidt(Sys_TableInfo sysTableInfo) + { + WebResponseContent webResponse = ValidColumnString(sysTableInfo); + if (!webResponse.Status) return webResponse; + //2020.05.07新增禁止选择上级角色为自己 + if (sysTableInfo.Table_Id == sysTableInfo.ParentId) + { + return WebResponseContent.Instance.Error($"父级id不能为自己"); + } + if (sysTableInfo.TableColumns != null && sysTableInfo.TableColumns.Any(x => !string.IsNullOrEmpty(x.DropNo) && x.ColumnName == sysTableInfo.ExpressField)) + { + return WebResponseContent.Instance.Error($"不能将字段【{sysTableInfo.ExpressField}】设置为快捷编辑,因为已经设置了数据源"); + } + if (sysTableInfo.TableColumns != null) + { + sysTableInfo.TableColumns.ForEach(x => + { + x.TableName = sysTableInfo.TableName; + }); + } + + sysTableInfo.TableColumns?.ForEach(x => + { + if (x.IsReadDataset == null) + { + x.IsReadDataset = 0; + } + }); + return repository.UpdateRange(sysTableInfo, true, true, null, null, true); + } + + /// + /// 2020.08.07完善PGSQL + /// + /// + /// + private string GetCurrentSql(string tableName) + { + string sql; + if (DBType.Name.ToLower() == DbCurrentType.MySql.ToString().ToLower()) + { + sql = GetMySqlStructure(tableName); + } + else if (DBType.Name.ToLower() == DbCurrentType.PgSql.ToString().ToLower()) + { + sql = GetPgSqlStructure(tableName); + } + else + { + sql = GetSqlServerStructure(tableName); + } + return sql; + } + + /// + /// 将表结构重新同步到代码生成配置 + /// + /// + /// + public async Task SyncTable(string tableName) + { + WebResponseContent webResponse = new WebResponseContent(); + if (string.IsNullOrEmpty(tableName)) return webResponse.OK("表名不能为空"); + + Sys_TableInfo tableInfo = repository.FindAsIQueryable(x => x.TableName == tableName) + .Include(o => o.TableColumns).FirstOrDefault(); + if (tableInfo == null) + return webResponse.Error("未获取到【" + tableName + "】的配置信息,请使用新建功能"); + if (!string.IsNullOrEmpty(tableInfo.TableTrueName) && tableInfo.TableTrueName != tableName) + { + tableName = tableInfo.TableTrueName; + } + + string sql = GetCurrentSql(tableName); + + //获取表结构 + List columns = repository.DapperContext + .QueryList(sql, new { tableName }); + if (columns == null || columns.Count == 0) + return webResponse.Error("未获取到【" + tableName + "】表结构信息,请确认表是否存在"); + + + //获取现在配置好的表结构 + List detailList = tableInfo.TableColumns ?? new List(); + List addColumns = new List(); + List updateColumns = new List(); + foreach (Sys_TableColumn item in columns) + { + Sys_TableColumn tableColumn = detailList.Where(x => x.ColumnName == item.ColumnName) + .FirstOrDefault(); + //新加的列 + if (tableColumn == null) + { + item.TableName = tableInfo.TableName; + item.Table_Id = tableInfo.Table_Id; + addColumns.Add(item); + continue; + } + //修改了数据类库或字段长度 + if (item.ColumnType != tableColumn.ColumnType || item.Maxlength != tableColumn.Maxlength || (item.IsNull ?? 0) != (tableColumn.IsNull ?? 0)) + { + tableColumn.ColumnType = item.ColumnType; + tableColumn.Maxlength = item.Maxlength; + tableColumn.IsNull = item.IsNull; + updateColumns.Add(tableColumn); + } + } + //删除的列 + List delColumns = detailList.Where(a => !columns.Select(c => c.ColumnName).Contains(a.ColumnName)).ToList(); + if (addColumns.Count + delColumns.Count + updateColumns.Count == 0) + { + return webResponse.Error("【" + tableName + "】表结构未发生变化"); + } + repository.AddRange(addColumns); + repository.DbContext.Set().RemoveRange(delColumns); + repository.UpdateRange(updateColumns, x => new { x.ColumnType, x.Maxlength, x.IsNull }); + await repository.DbContext.SaveChangesAsync(); + + return webResponse.OK($"新加字段【{addColumns.Count}】个,删除字段【{delColumns.Count}】,修改字段【{updateColumns.Count}】"); + } + + /// + /// 生成Services/Repository与对应的Partial类 + /// + /// + /// + /// + /// + /// + /// + public string CreateServices(string tableName, string nameSpace, string foldername, bool webController, bool apiController) + { + var tableColumn = repository.FindAsyncFirst(x => x.TableName == tableName).Result; + + if (tableColumn == null) + { + return $"没有查到{tableName}表信息"; + } + + if (string.IsNullOrEmpty(nameSpace) || string.IsNullOrEmpty(foldername)) + { + return $"命名空间、项目文件夹都不能为空"; + } + + string domainContent = ""; + + string frameworkFolder = ProjectPath.GetProjectDirectoryInfo()?.FullName; + string[] splitArr = nameSpace.Split('.'); + string projectName = splitArr.Length > 1 ? splitArr[splitArr.Length - 1] : splitArr[0]; + string baseOptions = "\"" + projectName + "\"," + "\"" + foldername + "\"," + "\"" + tableName + "\""; + + if (apiController) + { + string apiPath = ProjectPath.GetProjectDirectoryInfo().GetDirectories().Where(x => x.Name.ToLower().EndsWith(".webapi")).FirstOrDefault()?.FullName; + if (string.IsNullOrEmpty(apiPath)) + { + return "未找到webapi类库,请确认是存在weiapi类库命名以.webapi结尾"; + } + apiPath += $"\\Controllers\\{projectName}\\"; + //生成Partial Api控制器 + if (!File.Exists($"{apiPath}Partial\\{tableName}Controller.cs")) + { + string partialController = FileHelper.ReadFile(@"Template\\Controller\\ControllerApiPartial.html") + .Replace("{Namespace}", nameSpace).Replace("{TableName}", tableName).Replace("{StartName}", StratName); + FileHelper.WriteFile($"{apiPath}Partial\\", tableName + "Controller.cs", partialController); + } + //生成Api控制器 + domainContent = FileHelper.ReadFile(@"Template\\Controller\\ControllerApi.html") + .Replace("{Namespace}", nameSpace).Replace("{TableName}", tableName).Replace("{StartName}", StratName).Replace("{BaseOptions}", baseOptions); + FileHelper.WriteFile(apiPath, tableName + "Controller.cs", domainContent); + } + + //生成Repository类 + domainContent = FileHelper.ReadFile("Template\\Repositorys\\BaseRepository.html").Replace("{Namespace}", nameSpace).Replace("{TableName}", tableName).Replace("{StartName}", StratName); + FileHelper.WriteFile( + frameworkFolder + string.Format("\\{0}\\Repositories\\{1}\\", nameSpace, foldername) + , tableName + "Repository.cs", domainContent); + //生成IRepository类 + domainContent = FileHelper.ReadFile("Template\\IRepositorys\\BaseIRepositorie.html").Replace("{Namespace}", nameSpace).Replace("{TableName}", tableName).Replace("{StartName}", StratName); + FileHelper.WriteFile( + frameworkFolder + string.Format("\\{0}\\IRepositories\\{1}\\", nameSpace, foldername), + "I" + tableName + "Repository.cs", domainContent); + + + string path = $"{frameworkFolder}\\{nameSpace}\\IServices\\{ foldername}\\"; + + string fileName = "I" + tableName + "Service.cs"; + + //生成Partial IService类 + if (!File.Exists(path + "Partial\\" + fileName)) + { + domainContent = FileHelper.ReadFile("Template\\IServices\\IServiceBasePartial.html").Replace("{Namespace}", nameSpace).Replace("{TableName}", tableName).Replace("{StartName}", StratName); + FileHelper.WriteFile(path + "Partial\\", fileName, domainContent); + } + + //生成IService类 + domainContent = FileHelper.ReadFile("Template\\IServices\\IServiceBase.html").Replace("{Namespace}", nameSpace).Replace("{TableName}", tableName).Replace("{StartName}", StratName); + FileHelper.WriteFile(path, fileName, domainContent); + + + path = $"{frameworkFolder}\\{nameSpace}\\Services\\{ foldername}\\"; + fileName = tableName + "Service.cs"; + //生成Partial Service类 + domainContent = FileHelper.ReadFile("Template\\Services\\ServiceBasePartial.html").Replace("{Namespace}", nameSpace).Replace("{TableName}", tableName).Replace("{StartName}", StratName); + if (!File.Exists(path + "Partial\\" + fileName)) + { + domainContent = FileHelper.ReadFile("Template\\Services\\ServiceBasePartial.html").Replace("{Namespace}", nameSpace).Replace("{TableName}", tableName).Replace("{StartName}", StratName); + FileHelper.WriteFile(path + "Partial\\", fileName, domainContent); + } + + //生成Service类 + domainContent = FileHelper.ReadFile("Template\\Services\\ServiceBase.html") + .Replace("{Namespace}", nameSpace).Replace("{TableName}", tableName) + .Replace("{StartName}", StratName); + FileHelper.WriteFile(path, fileName, domainContent); + + + if (webController) + { + path = $"{frameworkFolder}\\{nameSpace}\\Controllers\\{ foldername}\\"; + fileName = tableName + "Controller.cs"; + //生成Partial web控制器 + if (!File.Exists(path + "Partial\\" + fileName)) + { + domainContent = FileHelper.ReadFile("Template\\Controller\\ControllerPartial.html").Replace("{Namespace}", nameSpace).Replace("{TableName}", tableName).Replace("{BaseOptions}", baseOptions).Replace("{StartName}", StratName); + FileHelper.WriteFile(path + "Partial\\", tableName + "Controller.cs", domainContent); + } + + //生成web控制器 + domainContent = FileHelper.ReadFile("Template\\Controller\\Controller.html").Replace("{Namespace}", nameSpace).Replace("{TableName}", tableName).Replace("{BaseOptions}", baseOptions).Replace("{StartName}", StratName); + FileHelper.WriteFile(path, tableName + "Controller.cs", domainContent); + } + return "业务类创建成功!"; + } + + /// + /// 获取界面查询字段 + /// + /// + /// + /// + /// + /// + private List GetSearchData(List> panelHtml, List sysColumnList, bool vue = false, bool edit = false, bool app = false) + { + if (edit) + { + GetPanelData(sysColumnList, panelHtml, x => x.EditRowNo, c => c.EditRowNo != null && c.EditRowNo > 0, false, q => q.EditRowNo, vue, app: app); + } + else + { + GetPanelData(sysColumnList, panelHtml, x => x.SearchRowNo, c => c.SearchRowNo != null, true, q => q.SearchRowNo, vue, app: app); + } + + List list = new List(); + + int index = 0; + bool group = panelHtml.Exists(x => x.Count > 1); + panelHtml.ForEach(x => + { + index++; + List> keyValuePairs = new List>(); + //List> keyValuePairs = new List>(); + x.ForEach(s => + { + Dictionary keyValues = new Dictionary(); + if (vue) + { + // keyValues.Add("columnType", s.columnType); + if (!string.IsNullOrEmpty(s.dataSource) && s.dataSource != "''") + { + if (app) + { + keyValues.Add("key", s.dataSource); + } + else + { + keyValues.Add("dataKey", s.dataSource); + } + //2020.09.11增加vue页面数据源配置默认空数据源 + keyValues.Add("data", new string[] { }); + } + keyValues.Add("title", s.text); + if (s.require) + { + keyValues.Add("required", s.require); + } + + keyValues.Add("field", s.id); + if (s.disabled) + { + keyValues.Add("disabled", true); + } + if (s.colSize > 0 && !app) + { + keyValues.Add("colSize", s.colSize); + } + if (!string.IsNullOrEmpty(s.displayType) && s.displayType != "''") + { + keyValues.Add("type", s.columnType == "img" ? s.columnType : s.displayType); + } + } + else + { + keyValues.Add("columnType", s.columnType); + if (!string.IsNullOrEmpty(s.dataSource)) + { + keyValues.Add("dataSource", s.dataSource); + } + keyValues.Add("text", s.text); + if (s.require) + { + keyValues.Add("require", s.require); + } + keyValues.Add("id", s.id); + } + if (!app) + { + keyValuePairs.Add(keyValues); + } + else + { + list.Add(keyValues); + } + }); + if (!app) + { + list.Add(keyValuePairs); + } + else + { + //app页面添加分组 + if (index != panelHtml.Count() && group) + { + list.Add(new { type = "group" }); + } + } + }); + return list; + } + + /// + /// 生成Vue页面 + /// + /// + /// 为本地Vue项目Views所在的绝对路径:E:/web/myProject/Views + /// + public string CreateVuePage(Sys_TableInfo sysTableInfo, string vuePath) + { + bool isApp = HttpContext.Current.Request.Query["app"].GetInt() > 0; + if (string.IsNullOrEmpty(vuePath)) + { + return isApp ? "请设置App路径" : "请设置Vue所在Views的绝对路径!"; + } + + if (!FileHelper.DirectoryExists(vuePath)) return $"未找项目路径{vuePath}!"; + + if (sysTableInfo == null + || sysTableInfo.TableColumns == null + || sysTableInfo.TableColumns.Count == 0) + return "提交的配置数据不完整"; + + vuePath = vuePath.Trim().TrimEnd('/').TrimEnd('\\'); + + List sysColumnList = sysTableInfo.TableColumns; + string[] eidtTye = new string[] { "select", "selectList", "drop", "dropList", "checkbox" }; + if (sysColumnList.Exists(x => eidtTye.Contains(x.EditType) && string.IsNullOrEmpty(x.DropNo))) + { + return $"编辑类型为[{string.Join(',', eidtTye)}]时必须选择数据源"; + } + if (sysColumnList.Exists(x => eidtTye.Contains(x.SearchType) && string.IsNullOrEmpty(x.DropNo))) + { + return $"查询类型为[{string.Join(',', eidtTye)}]时必须选择数据源"; + } + if (isApp && !sysColumnList.Exists(x => x.Enable > 0)) + { + return $"请设置[app列]"; + } + StringBuilder sb = GetGridColumns(sysColumnList, sysTableInfo.ExpressField, false, true, app: isApp); + if (sb.Length == 0) return "未获取到数据!"; + string columns = sb.ToString().Trim(); + columns = columns.Substring(0, columns.Length - 1); + string key = sysColumnList.Where(c => c.IsKey == 1).Select(x => x.ColumnName).First() ?? ""; + + //{ key: 1, value: "显示/查询/编辑" }, + //{ key: 2, value: "显示/编辑" }, + //{ key: 3, value: "显示/查询" }, + //{ key: 4, value: "显示" }, + //{ key: 5, value: "查询/编辑" }, + //{ key: 6, value: "查询" }, + //{ key: 7, value: "编辑" }, + Func editFunc = c => c.EditRowNo != null && c.EditRowNo > 0; + if (isApp) + { + editFunc = x => new int[] { 1, 2, 5, 7 }.Any(c => c == x.Enable); + } + var formFileds = sysColumnList.Where(editFunc) + .OrderBy(o => o.EditRowNo) + .ThenByDescending(t => t.OrderNo) + .Select(x => new KeyValuePair(x.ColumnName, x.EditType == "checkbox" || x.EditType == "selectList" || x.EditType == "cascader" ? new string[0] : "" as object)) + .ToList().ToDictionary(x => x.Key, x => x.Value).Serialize(); + + List> panelHtml = new List>(); + + List list = GetSearchData(panelHtml, sysColumnList, true, app: isApp); + + string pageContent = null; + + if (isApp) + { + pageContent = FileHelper.ReadFile("Template\\Page\\app\\options.html"); + } + else if (HttpContext.Current.Request.Query.ContainsKey("v3")) //2021.08.01增加vue3页面模板 + { + pageContent = FileHelper.ReadFile("Template\\Page\\Vue3SearchPage.html"); + } + else + { + pageContent = FileHelper.ReadFile("Template\\Page\\VueSearchPage.html"); + } + + + if (string.IsNullOrEmpty(pageContent)) + { + return "未找到Template模板文件"; + } + + //{ key: 1, value: "显示/查询/编辑" }, + //{ key: 2, value: "显示/编辑" }, + //{ key: 3, value: "显示/查询" }, + //{ key: 4, value: "显示" }, + //{ key: 5, value: "查询/编辑" }, + //{ key: 6, value: "查询" }, + //{ key: 7, value: "编辑" }, + Func func = c => c.SearchRowNo != null && c.SearchRowNo > 0; + + if (isApp) + { + func = x => new int[] { 1, 3, 5, 6 }.Any(c => c == x.Enable); + } + var searchFormFileds = sysColumnList.Where(func) + .Select(x => new KeyValuePair(x.ColumnName, x.SearchType == "checkbox" + || x.SearchType == "selectList" || x.EditType == "cascader" ? new string[0] : x.SearchType == "range" ? new string[] { null, null } : "" as object)) + .ToList().ToDictionary(x => x.Key, x => x.Value).Serialize(); + + pageContent = pageContent.Replace("#searchFormFileds", searchFormFileds) + .Replace("#searchFormOptions", list.Serialize() ?? "" + .Replace("},{", "},\r\n {") + .Replace("],[", "],\r\n [") + ); + panelHtml = new List>(); + //编辑 + string formOptions = GetSearchData(panelHtml, sysColumnList.Where(editFunc).ToList(), true, true, app: isApp).Serialize() ?? ""; + + string[] arr = sysTableInfo.Namespace.Split("."); + string spaceFolder = (arr.Length > 1 ? arr[arr.Length - 1] : arr[0]).ToLower(); + + pageContent = pageContent.Replace("#columns", columns). + Replace("#SortName", string.IsNullOrEmpty(sysTableInfo.SortName) ? key : sysTableInfo.SortName). + Replace("#key", key). + Replace("#Foots", " "). + Replace("#cnName", sysTableInfo.ColumnCNName). + Replace("#url", "/" + sysTableInfo.TableName + "/"). + Replace("#folder", spaceFolder). + Replace("#editFormFileds", formFileds). + Replace("#editFormOptions", formOptions. + Replace("},{", "},\r\n {"). + Replace("],[", "],\r\n [")); + vuePath = vuePath.Replace("//", "\\").Trim('\\'); + + + + //如果有明细,加载明细的数据 + if (!string.IsNullOrEmpty(sysTableInfo.DetailName) && !isApp) + { + Sys_TableInfo detailTable = repository.FindAsIQueryable(x => x.TableName == sysTableInfo.DetailName) + .Include(x => x.TableColumns).FirstOrDefault(); + if (detailTable == null) + return $"请先生成明细表{ sysTableInfo.DetailName}的配置!"; + if (detailTable.TableColumns == null || detailTable.TableColumns.Count == 0) + return $"明细表{ sysTableInfo.DetailName}没有列的信息,请确认是否有列数据或列数据是否被删除!"; + var _name = detailTable.TableColumns.Where(x => x.IsImage < 4 && x.EditRowNo > 0).Select(s => s.ColumnName).FirstOrDefault(); + if (!string.IsNullOrEmpty(_name)) + { + return $"明细表【{_name}】字段【table显示类型】设置为了【文件或图片】,编辑行只能设置为0或不设置"; + } + //明细列数据 + List detailList = detailTable.TableColumns; + //替换明细列数据 + sb = GetGridColumns(detailList, detailTable.ExpressField, true, true); + key = detailList.Where(c => c.IsKey == 1).Select(x => x.ColumnName).First(); + columns = sb.ToString().Trim(); + columns = columns.Substring(0, columns.Length - 1); + pageContent = pageContent.Replace("#detailColumns", columns). + Replace("#detailCnName", detailTable.ColumnCNName). + Replace("#detailTable", detailTable.TableName). + Replace("#detailKey", detailTable.TableColumns.Where(c => c.IsKey == 1).Select(x => x.ColumnName).First()). + Replace("#detailSortName", string.IsNullOrEmpty(detailTable.SortName) ? key : detailTable.SortName); + } + else + { + pageContent = pageContent.Replace("#detailColumns", "") + .Replace("#detailKey", "") + .Replace("#detailSortName", ""); + } + + + //生成扩展逻辑页面(只创建一次) + //获取view的上一级目录 + string srcPath = new DirectoryInfo(vuePath.MapPath()).Parent.FullName; + string extensionPath = isApp ? $"{srcPath}\\pages\\{spaceFolder}\\" : $"{srcPath}\\extension\\{spaceFolder}\\"; + // sysTableInfo.TableName = sysTableInfo.TableName.ToLower(); + string exFileName = sysTableInfo.TableName + ".js"; + string tableName = sysTableInfo.TableName; + + if (!isApp) + { + if (!FileHelper.FileExists(extensionPath + exFileName) + || FileHelper.FileExists($"{extensionPath}+\\{ sysTableInfo.FolderName.ToLower()}\\{ exFileName}")) + { + //2021.03.06增加前端生成文件到指定文件夹(以前生成过的文件不受影响) + extensionPath = $"{srcPath}\\extension\\{spaceFolder}\\{ sysTableInfo.FolderName.ToLower()}\\"; + spaceFolder = spaceFolder + "\\" + sysTableInfo.FolderName.ToLower(); + tableName = sysTableInfo.FolderName.ToLower() + "/" + tableName; + } + } + + + if (!isApp && !FileHelper.FileExists(extensionPath + exFileName)) + { + + string exContent = FileHelper.ReadFile("Template\\Page\\VueExtension.html"); + FileHelper.WriteFile(extensionPath, exFileName, exContent); + } + + pageContent = pageContent.Replace("#TableName", tableName); + + if (isApp) + { + if (!FileHelper.FileExists($"{vuePath}\\{ spaceFolder}\\{sysTableInfo.TableName}\\{sysTableInfo.TableName}Extend.js")) + { + //生成扩展文件 + string pageContentEx = FileHelper.ReadFile("Template\\Page\\app\\extension.html"); + FileHelper.WriteFile($"{vuePath}\\{ spaceFolder}\\{sysTableInfo.TableName}\\", sysTableInfo.TableName + "Extend.js", pageContentEx); + } + //生成app配置options.js文件 + FileHelper.WriteFile($"{vuePath}\\{ spaceFolder}\\{sysTableInfo.TableName}\\", sysTableInfo.TableName + "Options.js", pageContent); + + if (!FileHelper.FileExists($"{vuePath}\\{ spaceFolder}\\{sysTableInfo.TableName}\\{sysTableInfo.TableName}.vue")) + { + //生成vue文件 + pageContent = FileHelper.ReadFile("Template\\Page\\app\\page.html").Replace("#TableName", sysTableInfo.TableName); + FileHelper.WriteFile($"{vuePath}\\{ spaceFolder}\\{sysTableInfo.TableName}\\", sysTableInfo.TableName + ".vue", pageContent); + } + + string name = FileHelper.ReadFile(@$"{srcPath}\pages.json"); + string appPath = $"pages/{spaceFolder}/{sysTableInfo.TableName}/{sysTableInfo.TableName}"; + if (!name.Contains(appPath)) + { + int index = name.IndexOf("]"); + string fragment1 = name.Substring(0, index); + string fragment2 = name.Substring(index); + + StringBuilder builder = new StringBuilder(); + builder.AppendLine(" ,{"); + builder.AppendLine(" \"path\": \"" + appPath + "\","); + builder.AppendLine(" \"style\": {"); + builder.AppendLine(" \"navigationBarTitleText\": \"" + sysTableInfo.ColumnCNName + "\""); + builder.AppendLine(" }"); + builder.AppendLine(" }"); + + string fragment = fragment1 + builder.ToString() + " " + fragment2; + FileHelper.WriteFile(srcPath, "\\pages.json", fragment); + } + } + else + { + // spaceFolder = spaceFolder; //+ "\\" + sysTableInfo.FolderName.ToLower(); + //生成vue页面 + FileHelper.WriteFile($"{vuePath}\\{ spaceFolder}\\", sysTableInfo.TableName + ".vue", pageContent); + + //生成路由 + string routerPath = $"{srcPath}\\router\\viewGird.js"; + string routerContent = FileHelper.ReadFile(routerPath); + if (!routerContent.Contains($"path: '/{sysTableInfo.TableName}'")) + { + string routerTemplate = FileHelper.ReadFile("Template\\Page\\router.html") + .Replace("#TableName", sysTableInfo.TableName) + .Replace("#folder", spaceFolder.Replace("\\", "/")); + routerContent = routerContent.Replace("]", routerTemplate); + FileHelper.WriteFile($"{srcPath}\\router\\", "viewGird.js", routerContent); + } + } + return "页面创建成功!"; + } + + + /// + /// + /// + /// + /// + public string CreateExtensionPage(Sys_TableInfo tableInfo) + { + return "开发中。。。"; + } + + /// + /// 获取Mysql表结构信息 + /// + /// + /// + private string GetMySqlStructure(string tableName) + { + return $@"SELECT DISTINCT + Column_Name AS ColumnName, + '{ tableName}' as tableName, + Column_Comment AS ColumnCnName, + CASE + WHEN data_type IN( 'BIT', 'BOOL', 'bit', 'bool') THEN + 'bool' + WHEN data_type in('smallint','SMALLINT') THEN 'short' + WHEN data_type in('tinyint','TINYINT') THEN 'sbyte' + WHEN data_type IN('MEDIUMINT','mediumint', 'int','INT','year', 'Year') THEN + 'int' + WHEN data_type in ( 'BIGINT','bigint') THEN + 'bigint' + WHEN data_type IN('FLOAT', 'DOUBLE', 'DECIMAL','float', 'double', 'decimal') THEN + 'decimal' + WHEN data_type IN('CHAR', 'VARCHAR', 'TINY TEXT', 'TEXT', 'MEDIUMTEXT', 'LONGTEXT', 'TINYBLOB', 'BLOB', 'MEDIUMBLOB', 'LONGBLOB', 'Time','char', 'varchar', 'tiny text', 'text', 'mediumtext', 'longtext', 'tinyblob', 'blob', 'mediumblob', 'longblob', 'time') THEN + 'string' + WHEN data_type IN('Date', 'DateTime', 'TimeStamp','date', 'datetime', 'timestamp') THEN + 'DateTime' ELSE 'string' + END AS ColumnType, + case WHEN CHARACTER_MAXIMUM_LENGTH>8000 THEN 0 ELSE CHARACTER_MAXIMUM_LENGTH end AS Maxlength, + CASE + WHEN COLUMN_KEY <> '' THEN + 1 ELSE 0 + END AS IsKey, + CASE + WHEN Column_Name IN( 'CreateID', 'ModifyID', '' ) + OR COLUMN_KEY<> '' THEN + 0 ELSE 1 + END AS IsDisplay, + 1 AS IsColumnData, + 120 AS ColumnWidth, + 0 AS OrderNo, + CASE + WHEN IS_NULLABLE = 'NO' THEN + 0 ELSE 1 + END AS IsNull, + CASE + WHEN COLUMN_KEY <> '' THEN + 1 ELSE 0 + END AS IsReadDataset, + ordinal_position + FROM + information_schema.COLUMNS + WHERE + table_name = ?tableName {GetMysqlTableSchema()} + order by ordinal_position"; + } + + /// + /// 获取SqlServer表结构信息 + /// + /// + /// + private string GetSqlServerStructure(string tableName) + { + return $@" + SELECT TableName, + LTRIM(RTRIM(ColumnName)) AS ColumnName, + ColumnCNName, + CASE WHEN ColumnType = 'uniqueidentifier' THEN 'guid' + WHEN ColumnType IN('smallint', 'INT') THEN 'int' + WHEN ColumnType = 'BIGINT' THEN 'long' + WHEN ColumnType IN('CHAR', 'VARCHAR', 'NVARCHAR', + 'text', 'xml', 'varbinary', 'image') + THEN 'string' + WHEN ColumnType IN('tinyint') + THEN 'byte' + + WHEN ColumnType IN('bit') THEN 'bool' + WHEN ColumnType IN('time', 'date', 'DATETIME', 'smallDATETIME') + THEN 'DateTime' + WHEN ColumnType IN('smallmoney', 'DECIMAL', 'numeric', + 'money') THEN 'decimal' + WHEN ColumnType = 'float' THEN 'float' + ELSE 'string ' + END ColumnType, + CASE WHEN ColumnType IN ('NVARCHAR','NCHAR') THEN [Maxlength]/2 ELSE [Maxlength] END [Maxlength], + IsKey, + CASE WHEN ColumnName IN('CreateID', 'ModifyID', '') + OR IsKey = 1 THEN 0 + ELSE 1 + END AS IsDisplay , + 1 AS IsColumnData, + + CASE WHEN ColumnType IN('time', 'date', 'DATETIME', 'smallDATETIME') THEN 150 + + WHEN ColumnName IN('Modifier', 'Creator') THEN 130 + + WHEN ColumnType IN('int', 'bigint') OR ColumnName IN('CreateID', 'ModifyID', '') THEN 80 + WHEN[Maxlength] < 110 AND[Maxlength] > 60 THEN 120 + + WHEN[Maxlength] < 200 AND[Maxlength] >= 110 THEN 180 + + WHEN[Maxlength] > 200 THEN 220 + ELSE 110 + END AS ColumnWidth , + 0 AS OrderNo, + --CASE WHEN IsKey = 1 OR t.[IsNull]=0 THEN 0 + -- ELSE 1 END + t.[IsNull] AS + [IsNull], + CASE WHEN IsKey = 1 THEN 1 ELSE 0 END IsReadDataset, + CASE WHEN IsKey!=1 AND t.[IsNull] = 0 THEN 0 ELSE NULL END AS EditColNo + FROM (SELECT obj.name AS TableName , + col.name AS ColumnName , + CONVERT(NVARCHAR(100),ISNULL(ep.[value], '')) AS ColumnCNName, + t.name AS ColumnType , + CASE WHEN col.length<1 THEN 0 ELSE col.length END AS[Maxlength], + CASE WHEN EXISTS (SELECT 1 + FROM dbo.sysindexes si + INNER JOIN dbo.sysindexkeys sik ON si.id = sik.id + AND si.indid = sik.indid + INNER JOIN dbo.syscolumns sc ON sc.id = sik.id + AND sc.colid = sik.colid + INNER JOIN dbo.sysobjects so ON so.name = si.name + AND so.xtype = 'PK' + WHERE sc.id = col.id + AND sc.colid = col.colid) + THEN 1 + ELSE 0 + END AS IsKey , + CASE WHEN col.isnullable = 1 THEN 1 + ELSE 0 + END AS[IsNull], + col.colorder + FROM dbo.syscolumns col + LEFT JOIN dbo.systypes t ON col.xtype = t.xusertype + INNER JOIN dbo.sysobjects obj ON col.id = obj.id + + AND obj.xtype IN ( 'U','V') + -- AND obj.status >= 01 + LEFT JOIN dbo.syscomments comm ON col.cdefault = comm.id + LEFT JOIN sys.extended_properties ep ON col.id = ep.major_id + AND col.colid = ep.minor_id + AND ep.name = 'MS_Description' + LEFT JOIN sys.extended_properties epTwo ON obj.id = epTwo.major_id + AND epTwo.minor_id = 0 + AND epTwo.name = 'MS_Description' + WHERE obj.name = @tableName--表名 + ) AS t + ORDER BY t.colorder"; + } + + /// + /// 2020.08.07完善PGSQL + /// + /// + /// + private string GetPgSqlStructure(string tableName) + { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.Append("SELECT "); + stringBuilder.Append(" MM.\"TableName\", "); + stringBuilder.Append(" MM.\"ColumnName\", "); + stringBuilder.Append(" MM.\"ColumnCNName\", "); + stringBuilder.Append(" MM.\"ColumnType\", "); + stringBuilder.Append(" MM.\"Maxlength\", "); + stringBuilder.Append(" MM.\"IsKey\", "); + stringBuilder.Append(" MM.\"IsDisplay\", "); + stringBuilder.Append(" MM.\"IsColumnData\", "); + stringBuilder.Append("CASE "); + stringBuilder.Append(" "); + stringBuilder.Append(" WHEN MM.\"ColumnType\" = 'DateTime' THEN "); + stringBuilder.Append(" 150 "); + stringBuilder.Append(" WHEN MM.\"ColumnType\" = 'int' THEN "); + stringBuilder.Append(" 80 "); + stringBuilder.Append(" WHEN MM.\"Maxlength\" < 110 "); + stringBuilder.Append(" AND MM.\"Maxlength\" > 60 THEN "); + stringBuilder.Append(" 120 "); + stringBuilder.Append(" WHEN MM.\"Maxlength\" < 200 "); + stringBuilder.Append(" AND MM.\"Maxlength\" >= 110 THEN "); + stringBuilder.Append(" 180 "); + stringBuilder.Append(" WHEN MM.\"Maxlength\" > 200 THEN "); + stringBuilder.Append(" 220 ELSE 110 "); + stringBuilder.Append(" END AS \"ColumnWidth\", "); + stringBuilder.Append(" MM.\"OrderNo\", "); + stringBuilder.Append(" case WHEN MM.\"IsKey\"=1 or \"lower\"(MM.\"IsNull\")='no' then 0 else 1 end as \"IsNull\" , "); + stringBuilder.Append(" MM.\"IsReadDataset\", "); + stringBuilder.Append(" MM.\"EditColNo\" "); + stringBuilder.Append(" FROM "); + stringBuilder.Append(" ( "); + stringBuilder.Append(" SELECT "); + stringBuilder.Append(" col.TABLE_NAME AS \"TableName\", "); + stringBuilder.Append(" col.COLUMN_NAME AS \"ColumnName\", "); + stringBuilder.Append(" attr.description AS \"ColumnCNName\", "); + stringBuilder.Append(" CASE "); + stringBuilder.Append(" "); + stringBuilder.Append(" WHEN col.udt_name = 'uuid' THEN "); + stringBuilder.Append(" 'guid' "); + stringBuilder.Append(" WHEN col.udt_name IN ( 'int2') THEN "); + stringBuilder.Append(" 'short' "); + stringBuilder.Append(" WHEN col.udt_name IN ( 'int4' ) THEN "); + stringBuilder.Append(" 'int' "); + stringBuilder.Append(" WHEN col.udt_name = 'int8' THEN "); + stringBuilder.Append(" 'long' "); + stringBuilder.Append(" WHEN col.udt_name = 'BIGINT' THEN "); + stringBuilder.Append(" 'long' "); + stringBuilder.Append(" WHEN col.udt_name IN ( 'char', 'varchar', 'text', 'xml', 'bytea' ) THEN "); + stringBuilder.Append(" 'string' "); + stringBuilder.Append(" WHEN col.udt_name IN ( 'bool' ) THEN "); + stringBuilder.Append(" 'bool' "); + stringBuilder.Append(" WHEN col.udt_name IN ( 'date','timestamp' ) THEN "); + stringBuilder.Append(" 'DateTime' "); + stringBuilder.Append(" WHEN col.udt_name IN ( 'decimal', 'money','numeric' ) THEN "); + stringBuilder.Append(" 'decimal' "); + stringBuilder.Append(" WHEN col.udt_name IN ( 'float4', 'float8' ) THEN "); + stringBuilder.Append(" 'float' ELSE'string ' "); + stringBuilder.Append(" END \"ColumnType\", "); + stringBuilder.Append("CASE "); + stringBuilder.Append(" "); + stringBuilder.Append(" WHEN col.udt_name = 'varchar' THEN "); + stringBuilder.Append(" col.character_maximum_length "); + stringBuilder.Append(" WHEN col.udt_name IN ( 'int2', 'int4', 'int8', 'float4', 'float8' ) THEN "); + stringBuilder.Append(" col.numeric_precision ELSE 1024 "); + stringBuilder.Append(" END \"Maxlength\", "); + stringBuilder.Append("CASE "); + stringBuilder.Append(" "); + stringBuilder.Append(" WHEN keyTable.IsKey = 1 THEN "); + stringBuilder.Append(" 1 ELSE 0 "); + stringBuilder.Append(" END \"IsKey\", "); + stringBuilder.Append("CASE "); + stringBuilder.Append(" "); + stringBuilder.Append(" WHEN keyTable.IsKey = 1 THEN "); + stringBuilder.Append(" 0 ELSE 1 "); + stringBuilder.Append(" END \"IsDisplay\", "); + stringBuilder.Append(" 1 AS \"IsColumnData\", "); + stringBuilder.Append(" 0 AS \"OrderNo\", "); + stringBuilder.Append(" col.is_nullable AS \"IsNull\", "); + stringBuilder.Append("CASE "); + stringBuilder.Append(" "); + stringBuilder.Append(" WHEN keyTable.IsKey = 1 THEN "); + stringBuilder.Append(" 1 ELSE 0 "); + stringBuilder.Append(" END \"IsReadDataset\", "); + stringBuilder.Append("CASE "); + stringBuilder.Append(" "); + stringBuilder.Append(" WHEN keyTable.IsKey IS NULL "); + stringBuilder.Append(" AND col.is_nullable = 'NO' THEN "); + stringBuilder.Append(" 0 ELSE NULL "); + stringBuilder.Append(" END AS \"EditColNo\" "); + stringBuilder.Append("FROM "); + stringBuilder.Append(" information_schema.COLUMNS col "); + stringBuilder.Append(" LEFT JOIN ( "); + stringBuilder.Append(" SELECT col_description(a.attrelid,a.attnum) as description,a.attname as name "); + stringBuilder.Append("FROM pg_class as c,pg_attribute as a "); + stringBuilder.Append("where \"lower\"(c.relname) = \"lower\"(@tableName) and a.attrelid = c.oid and a.attnum>0 "); + stringBuilder.Append(" ) as attr on attr.name=col.COLUMN_NAME "); + stringBuilder.Append(" LEFT JOIN ( "); + stringBuilder.Append(" SELECT "); + stringBuilder.Append(" pg_attribute.attname AS colname, "); + stringBuilder.Append(" 1 AS IsKey "); + stringBuilder.Append(" FROM "); + stringBuilder.Append(" pg_constraint "); + stringBuilder.Append(" INNER JOIN pg_class ON pg_constraint.conrelid = pg_class.oid "); + stringBuilder.Append(" INNER JOIN pg_attribute ON pg_attribute.attrelid = pg_class.oid "); + stringBuilder.Append(" AND pg_attribute.attnum = pg_constraint.conkey [1] "); + stringBuilder.Append(" WHERE "); + stringBuilder.Append(" \"lower\" ( pg_class.relname ) = \"lower\" ( @tableName ) "); + stringBuilder.Append(" AND pg_constraint.contype = 'p' "); + stringBuilder.Append(" ) keyTable ON col.COLUMN_NAME = keyTable.colname "); + stringBuilder.Append("WHERE "); + stringBuilder.Append(" \"lower\" ( TABLE_NAME ) = \"lower\" ( @tableName ) "); + stringBuilder.Append("ORDER BY "); + stringBuilder.Append(" ordinal_position "); + stringBuilder.Append(" ) MM; "); + return stringBuilder.ToString(); + } + + /// + /// 设置界面table td单元格的宽度 + /// + /// + private void SetMaxLength(List columns) + { + columns.ForEach(x => + { + if (x.ColumnType.ToLower() == "datetime") + { + x.ColumnWidth = 150; + } + else if (x.ColumnName.ToLower() == "modifier" || x.ColumnName.ToLower() == "creator") + { + x.ColumnWidth = 100; + } + else if (x.ColumnName.ToLower() == "modifyid" || x.ColumnName.ToLower() == "createid") + { + x.ColumnWidth = 100; + } + else if (x.Maxlength > 200) + { + x.ColumnWidth = 220; + } + else if (x.Maxlength > 110 && x.Maxlength <= 200) + { + x.ColumnWidth = 180; + } + else if (x.Maxlength > 60 && x.Maxlength <= 110) + { + x.ColumnWidth = 120; + } + else + { + x.ColumnWidth = 110; + } + }); + } + + /// + /// 初始化生成配置对应表的数据信息 + /// + /// + /// + /// + /// + /// + /// + /// + /// + private int InitTable(int parentId, string tableName, string columnCNName, string nameSpace, string foldername, int tableId, bool isTreeLoad) + { + if (isTreeLoad) + return tableId; + if (string.IsNullOrEmpty(tableName)) + return -1; + tableId = repository.Find(x => x.TableName == tableName, s => s.Table_Id).FirstOrDefault(); + if (tableId > 0) + return tableId; + bool isMySql = DBType.Name == DbCurrentType.MySql.ToString(); + Sys_TableInfo tableInfo = new Sys_TableInfo() + { + ParentId = parentId, + ColumnCNName = columnCNName, + CnName = columnCNName, + TableName = tableName, + Namespace = nameSpace, + FolderName = foldername, + Enable = 1 + }; + List columns = repository.DapperContext + .QueryList(GetCurrentSql(tableName), new { tableName }); + + int orderNo = (columns.Count + 10) * 50; + for (int i = 0; i < columns.Count; i++) + { + columns[i].OrderNo = orderNo; + orderNo = orderNo - 50; + columns[i].EditRowNo = 0; + } + + SetMaxLength(columns); + var result= base.Add(tableInfo, columns, false); + if (!result.Status) + { + throw new Exception($"加载表结构写入异常:{result.Message}"); + } + return tableInfo.Table_Id; + } + + /// + /// 界面加载表的配置信息 + /// + /// + /// + /// + /// + /// + /// + /// true只加载表数据 + /// + public object LoadTable(int parentId, string tableName, string columnCNName, string nameSpace, string foldername, int tableId, bool isTreeLoad) + { + if (!UserContext.Current.IsSuperAdmin && !isTreeLoad) + { + return new WebResponseContent().Error("只有超级管理员才能进行此操作"); + } + tableId = InitTable(parentId, tableName?.Trim(), columnCNName, nameSpace, foldername, tableId, isTreeLoad); + Sys_TableInfo tableInfo = repository + .FindAsIQueryable(x => x.Table_Id == tableId) + .Include(c => c.TableColumns) + .FirstOrDefault(); + if (tableInfo.TableColumns != null) + { + tableInfo.TableColumns = tableInfo.TableColumns.OrderByDescending(x => x.OrderNo).ToList(); + } + return new WebResponseContent().OK(null, tableInfo); + } + + public async Task DelTree(int table_Id) + { + if (table_Id == 0) return new WebResponseContent().Error("没有传入参数"); + Sys_TableInfo tableInfo = await repository.FindAsIQueryable(x => x.Table_Id == table_Id) + .Include(c => c.TableColumns) + .FirstOrDefaultAsync(); + if (tableInfo == null) return new WebResponseContent().OK(); + if (tableInfo.TableColumns != null && tableInfo.TableColumns.Count > 0) + { + return new WebResponseContent().Error("当前删除的节点存在表结构信息,只能删除空节点"); + } + if (repository.Exists(x => x.ParentId == table_Id)) + { + return new WebResponseContent().Error("当前删除的节点存在子节点,不能删除"); + } + repository.Delete(tableInfo, true); + return new WebResponseContent().OK(); + } + + /// + /// 生成表格的columns的配置信息 + /// + /// + /// + /// + /// + /// + private StringBuilder GetGridColumns(List list, string expressField, bool detail, bool vue = false, bool app = false) + { + totalCol = 0; + totalWidth = 0; + StringBuilder sb = new StringBuilder(); + + //{ key: 1, value: "显示/查询/编辑" }, + //{ key: 2, value: "显示/编辑" }, + //{ key: 3, value: "显示/查询" }, + //{ key: 4, value: "显示" }, + //{ key: 5, value: "查询/编辑" }, + //{ key: 6, value: "查询" }, + //{ key: 7, value: "编辑" }, + Func func = x => true; + bool sort = false; + if (app) + { + func = x => new int[] { 1, 2, 3, 4 }.Any(c => c == x.Enable) && (x.IsDisplay == null || x.IsDisplay == 1); + } + foreach (Sys_TableColumn item in list.Where(func).OrderByDescending(x => x.OrderNo)) + { + if (item.IsColumnData == 0) { continue; } + sb.Append("{field:'" + item.ColumnName + "',"); + sb.Append("title:'" + (string.IsNullOrEmpty(item.ColumnCnName) ? item.ColumnName : item.ColumnCnName) + "',"); + if (vue) + { + string colType = item.ColumnType.ToLower(); + if (item.IsImage == 1) + { + colType = "img"; + } + else if (item.IsImage == 2) + { + colType = "excel"; + } + else if (item.IsImage == 3) + { + colType = "file"; + } + //2021.07.27增加table列显示类型date(自动格式化) + else if (item.IsImage == 4) + { + colType = "date"; + } + sb.Append("type:'" + colType + "',"); + if (!string.IsNullOrEmpty(item.DropNo)) + { + sb.Append("bind:{ key:'" + item.DropNo + "',data:[]},"); + } + if (expressField != null && expressField.ToLower() == item.ColumnName.ToLower()) + { + sb.Append("link:true,"); + } + //2021.01.09增加代码生成器设置table排序功能 + if (item.Sortable == 1 && !app) + { + sb.Append("sort:true,"); + } + } + else + { + sb.Append("datatype:'" + item.ColumnType + "',"); + } + + if (!app) + { + sb.Append("width:" + (item.ColumnWidth ?? 90) + ","); + } + if (item.IsDisplay == 0) + { + sb.Append("hidden:true,"); + } + else + { + totalCol++; + totalWidth += item.ColumnWidth == null ? 0 : Convert.ToInt32(item.ColumnWidth); + } + if (item.IsReadDataset == 1) + { + sb.Append("readonly:true,"); + } + //detail明细才启用表格编辑 + if (item.EditRowNo != null && item.EditRowNo > 0 && detail)//!string.IsNullOrEmpty(item.EditType)) + { + string editText = vue ? "edit" : "editor"; + if (vue) + { + sb.Append("edit:{type:'" + item.EditType + "'},"); + } + else + { + + switch (item.EditType) + { + case "date": + sb.Append("editor:'datebox',"); + break; + case "datetime": + sb.Append("editor:'datetimebox',"); + break; + case "drop": + case "dropList": + case "select": + case "selectList": + if (!vue && !string.IsNullOrEmpty(item.DropNo)) + { + sb.Append(editText + ": { type: 'combobox', options: optionConfig" + item.DropNo + " },"); + } + else + { + sb.Append(editText + ": 'text',"); + } + break; + default: + sb.Append(editText + ":'text',"); + break; + } + } + } + if (!vue) + { + //快速查看字段 + if (expressField != null && expressField.ToLower() == item.ColumnName.ToLower()) + { + sb.Append("formatter:function (val, row, index) { return $.fn.layOut('createViewField',{row:row,val:val,index:index})},"); + } + else if (!string.IsNullOrEmpty(item.Script)) + { + sb.Append("formatter:" + item.Script + ","); + } + else if (item.IsImage == 1)//启用图片 + { + sb.Append("formatter:function (val, row, index) { return $.fn.layOut('createImageUrl',{row:row,key:'" + item.ColumnName + "'})},"); + } + else if (!string.IsNullOrEmpty(item.DropNo) && !detail) + { + sb.AppendLine("formatter: function (val, row, index) {"); + sb.AppendLine(string.Format(" return dataSource{0}.textFormatter(optionConfig{0}, val, row, index);", item.DropNo)); + sb.AppendLine(" },"); + } + } + + if (item.IsNull == 0 && !app) + { + sb.Append("require:true,"); + } + + if (!app && (item.ColumnType.ToLower() == "datetime" || (item.IsDisplay == 1 & !sort))) + { + //2021.09.05修改排序名称 + sb.Append("align:'left',sort:true},"); + if (item.IsDisplay == 1) + { + sort = true; + } + } + else + { + if (!app) + { + sb.Append("align:'left'},"); + } + } + if (app) + { + sb.Append("},").Replace(",},", "},"); + } + + sb.AppendLine(); + sb.Append(" "); + } + return sb; + } + + /// + /// 创建实体类 + /// + /// + /// + /// 1、创建实体类,2创建apiinput类,3、创建apioutput类 + private string CreateEntityModel(List sysColumn, Sys_TableInfo tableInfo, List tableColumnInfoList, int createType) + { + string template = ""; + if (createType == 1) + { + template = "DomainModel.html"; + } + else if (createType == 2) + { + template = "ApiInputDomainModel.html"; + } + else + { + template = "ApiOutputDomainModel.html"; + } + string domainContent = FileHelper.ReadFile("Template\\DomianModel\\" + template); + string partialContent = domainContent; + StringBuilder AttributeBuilder = new StringBuilder(); + sysColumn = sysColumn.OrderByDescending(c => c.OrderNo).ToList(); + bool addIgnore = false; + foreach (Sys_TableColumn column in sysColumn) + { + column.ColumnType = (column.ColumnType ?? "").Trim(); + AttributeBuilder.Append("/// "); + AttributeBuilder.Append("\r\n"); + AttributeBuilder.Append(" ///" + column.ColumnCnName + ""); + AttributeBuilder.Append("\r\n"); + AttributeBuilder.Append(" /// "); + AttributeBuilder.Append("\r\n"); + if (column.IsKey == 1) { AttributeBuilder.Append(@" [Key]" + ""); AttributeBuilder.Append("\r\n"); } + AttributeBuilder.Append(" [Display(Name =\"" + ( + string.IsNullOrEmpty(column.ColumnCnName) ? column.ColumnName : column.ColumnCnName + ) + "\")]"); + AttributeBuilder.Append("\r\n"); + + TableColumnInfo tableColumnInfo = tableColumnInfoList.Where(x => x.ColumnName.ToLower().Trim() == column.ColumnName.ToLower().Trim()).FirstOrDefault(); + if (tableColumnInfo != null && (tableColumnInfo.ColumnType == "varchar" && column.Maxlength > 8000) + || (tableColumnInfo.ColumnType == "nvarchar" && column.Maxlength > 4000)) + { + column.Maxlength = 0; + } + + if (column.ColumnType == "string" && column.Maxlength > 0 && column.Maxlength < 8000) + { + + AttributeBuilder.Append(" [MaxLength(" + column.Maxlength + ")]"); + AttributeBuilder.Append("\r\n"); + } + //不是数据列的,返回页面数据前不包含此列的数据 + if (column.IsColumnData == 0 && createType == 1) + { + addIgnore = true; + AttributeBuilder.Append(" [JsonIgnore]"); + AttributeBuilder.Append("\r\n"); + } + //[Column(TypeName="bigint")]如果与字段类型不同会产生异常 + + if (tableColumnInfo != null) + { + if (!string.IsNullOrEmpty(tableColumnInfo.Prec_Scale) && !tableColumnInfo.Prec_Scale.EndsWith(",0")) + { + AttributeBuilder.Append(" [DisplayFormat(DataFormatString=\"" + tableColumnInfo.Prec_Scale + "\")]"); + AttributeBuilder.Append("\r\n"); + } + + if ((column.IsKey == 1 && (column.ColumnType == "string" || column.ColumnType == "uniqueidentifier")) || + tableColumnInfo.ColumnType.ToLower() == "guid" + || (IsMysql() && column.ColumnType == "string" && column.Maxlength == 36)) + { + tableColumnInfo.ColumnType = "uniqueidentifier"; + } + + string maxLength = string.Empty; + if (tableColumnInfo.ColumnType != "uniqueidentifier") + { + if (column.IsKey != 1 && column.ColumnType.ToLower() == "string") + { + //没有指定长度的字符串字段 ,如varchar,nvarchar,text等都默认生成varchar(max),nvarchar(max) + if (column.Maxlength <= 0 + || (tableColumnInfo.ColumnType == "varchar" && column.Maxlength > 8000) + || (tableColumnInfo.ColumnType == "nvarchar" && column.Maxlength > 4000)) + { + maxLength = "(max)"; + } + else + { + maxLength = "(" + column.Maxlength + ")"; + } + + } + } + AttributeBuilder.Append(" [Column(TypeName=\"" + tableColumnInfo.ColumnType + maxLength + "\")]"); + AttributeBuilder.Append("\r\n"); + + + //if ((tableColumnInfo.ColumnType == "int" || tableColumnInfo.ColumnType == "bigint" || tableColumnInfo.ColumnType == "long") && column.ColumnType.ToLower() == "string") + if (tableColumnInfo.ColumnType == "int" || tableColumnInfo.ColumnType == "bigint" || tableColumnInfo.ColumnType == "long") + { + column.ColumnType = tableColumnInfo.ColumnType == "int" ? "int" : "long"; + } + if (tableColumnInfo.ColumnType == "bool") + { + column.ColumnType = "bit"; + } + } + + if (column.EditRowNo != null) + { + AttributeBuilder.Append(" [Editable(true)]"); + AttributeBuilder.Append("\r\n"); + } + // && column.ColumnType.ToLower() == "string" + if (column.IsNull == 0 || (createType == 2 && column.ApiIsNull == 0)) + { + AttributeBuilder.Append(" [Required(AllowEmptyStrings=false)]"); + AttributeBuilder.Append("\r\n"); + } + string columnType = (column.ColumnType == "Date" ? "DateTime" : column.ColumnType).Trim(); + if (tableColumnInfo?.ColumnType?.ToLower() == "guid") + { + columnType = "Guid"; + } + if (column.ColumnType.ToLower() != "string" && column.IsNull == 1) + { + columnType = columnType + "?"; + } + //如果主键是string,则默认为是Guid或者使用的是mysql数据,字段类型是字符串并且长度是36则默认为是Guid + if ((column.IsKey == 1 + && (column.ColumnType == "string" + || column.ColumnType == "uniqueidentifier")) + || column.ColumnType == "guid" + || (IsMysql() && column.ColumnType == "string" && column.Maxlength == 36)) + { + columnType = "Guid" + (column.IsNull == 1 ? "?" : ""); + } + AttributeBuilder.Append(" public " + columnType + " " + column.ColumnName + " { get; set; }"); + AttributeBuilder.Append("\r\n\r\n "); + } + if (!string.IsNullOrEmpty(tableInfo.DetailName) && createType == 1) + { + AttributeBuilder.Append("[Display(Name =\"" + tableInfo.DetailCnName + "\")]"); + AttributeBuilder.Append("\r\n "); + //2019.12.20增加明细表属性的ForeignKey配置(EF Core 3.1配项) + AttributeBuilder.Append("[ForeignKey(\"" + sysColumn.Where(x => x.IsKey == 1).FirstOrDefault().ColumnName + "\")]"); + AttributeBuilder.Append("\r\n "); + AttributeBuilder.Append("public List<" + tableInfo.DetailName + "> " + tableInfo.DetailName + " { get; set; }"); + AttributeBuilder.Append("\r\n"); + } + if (addIgnore && createType == 1) + { + domainContent = "using Newtonsoft.Json;\r\n" + domainContent + "\r\n"; + } + //获取的是本地开发代码所在目录,不是布后的目录 + string mapPath = ProjectPath.GetProjectDirectoryInfo()?.FullName; //new DirectoryInfo(("~/").MapPath()).Parent.FullName; + // string folderPath= string.Format("\\VOL.Framework.Core.\\DomainModels\\{0}\\", foldername); + if (string.IsNullOrEmpty(mapPath)) + { + return "未找到生成的目录!"; + } + string[] splitArrr = tableInfo.Namespace.Split('.'); + // foldername = splitArrr.Length == 2 ? splitArrr[1] : foldername; + domainContent = domainContent.Replace("{TableName}", tableInfo.TableName).Replace("{AttributeList}", AttributeBuilder.ToString()).Replace("{StartName}", StratName); + // {AttributeManager} + + List entityAttribute = new List(); + entityAttribute.Add("TableCnName = \"" + tableInfo.ColumnCNName + "\""); + if (!string.IsNullOrEmpty(tableInfo.TableTrueName)) + { + //如果使用的是pgsql数据库,并且数据库表都是小写,请将下面的.ToLower()这段开启.2020.08.07 + //entityAttribute.Add("TableName = \"" + tableInfo.TableTrueName.ToLower() + "\""); + entityAttribute.Add("TableName = \"" + tableInfo.TableTrueName + "\""); + } + if (!string.IsNullOrEmpty(tableInfo.DetailName) && createType == 1) + { + // 'typeof('+[1,2].join('),typeof(')+')' + string typeArr = " new Type[] { typeof(" + string.Join("),typeof(", tableInfo.DetailName.Split(',')) + ")}"; + entityAttribute.Add("DetailTable = " + typeArr + ""); + } + if (!string.IsNullOrEmpty(tableInfo.DetailCnName)) + { + + entityAttribute.Add("DetailTableCnName = \"" + tableInfo.DetailCnName + "\""); + } + if (!string.IsNullOrEmpty(tableInfo.DBServer) && createType == 1) + { + entityAttribute.Add("DBServer = \"" + tableInfo.DBServer + "\""); + } + + if (createType == 1) + { + if (sysColumn.Any(x => x.ApiInPut > 0)) + { + entityAttribute.Add("ApiInput = typeof(Api" + tableInfo.TableName + "Input)"); + } + if (sysColumn.Any(x => x.ApiOutPut > 0)) + { + entityAttribute.Add("ApiOutput = typeof(Api" + tableInfo.TableName + "Output)"); + } + } + string modelNameSpace = StratName + ".Entity"; + string tableAttr = string.Join(",", entityAttribute); + if (tableAttr != "") + { + tableAttr = "[Entity(" + tableAttr + ")]"; + } + //entityAttribute.Add("TableCnName = \"" + tableInfo.ColumnCNName + "\""); + //if (!string.IsNullOrEmpty(tableInfo.TableTrueName) && tableInfo.TableName != tableInfo.TableTrueName) + //{ + // entityAttribute.Add("TableName = \"" + tableInfo.TableTrueName + "\""); + // entityAttribute.Add("Table(\"" + tableInfo.TableTrueName + "\")"); + //} + if (!string.IsNullOrEmpty(tableInfo.TableTrueName) && tableInfo.TableName != tableInfo.TableTrueName) + { + string tableTrueName = tableInfo.TableTrueName; + //2020.06.14 pgsql数据库,设置表名为小写(数据库创建表的时候也要使用小写) + if (DBType.Name == DbCurrentType.PgSql.ToString()) + { + tableTrueName = tableTrueName.ToLower(); + } + tableAttr = tableAttr + "\r\n[Table(\"" + tableInfo.TableTrueName + "\")]"; + } + domainContent = domainContent.Replace("{AttributeManager}", tableAttr).Replace("{Namespace}", modelNameSpace); + + string folderName = tableInfo.FolderName; + string tableName = tableInfo.TableName; + if (createType == 2) + { + folderName = "ApiEntity\\Input"; + tableName = "Api" + tableInfo.TableName + "Input"; + } + else if (createType == 3) + { + folderName = "ApiEntity\\OutPut"; + tableName = "Api" + tableInfo.TableName + "Output"; + } + //mapPath + + // string.Format( + // "\\" + modelNameSpace + "\\DomainModels\\{0}\\", folderName + // ) + string modelPath = $"{mapPath}\\{modelNameSpace}\\DomainModels\\{folderName}\\"; + FileHelper.WriteFile(modelPath, tableName + ".cs", domainContent); + //partialContent + modelPath += "partial\\"; + if (!FileHelper.FileExists(modelPath + tableName + ".cs")) + { + partialContent = partialContent.Replace("{AttributeManager}", "") + .Replace("{AttributeList}", @"//此处配置字段(字段配置见此model的另一个partial),如果表中没有此字段请加上 [NotMapped]属性,否则会异常") + .Replace(":BaseEntity", "") + .Replace("{TableName}", tableInfo.TableName).Replace("{Namespace}", modelNameSpace); + FileHelper.WriteFile(modelPath, tableName + ".cs", partialContent); + } + if (createType == 1) + { + string mappingConfiguration = FileHelper. + ReadFile("Template\\DomianModel\\MappingConfiguration.html") + .Replace("{TableName}", tableInfo.TableName).Replace("{Namespace}", modelNameSpace).Replace("{StartName}", StratName); + FileHelper.WriteFile( + mapPath + + string.Format("\\" + modelNameSpace + "\\MappingConfiguration\\{0}\\" + , tableInfo.FolderName) + , tableInfo.TableName + "MapConfig.cs", + mappingConfiguration); + } + return ""; + } + + private static string[] formType = new string[] { "bigint", "int", "decimal", "float", "byte" }; + private string GetDisplayType(bool search, string searchType, string editType, string columnType) + { + string type = ""; + if (search) + { + type = searchType == "无" ? "" : searchType ?? ""; + } + else + { + type = editType == "无" ? "" : editType ?? ""; + } + if (type == "" && formType.Contains(columnType)) + { + if (columnType == "decimal" || columnType == "float") + { + type = "decimal"; + } + else + { + type = "number"; + } + } + return type; + } + + private string GetDropString(string dropNo, bool vue) + { + if (string.IsNullOrEmpty(dropNo)) + return vue ? "''" : "__[]__"; + if (vue) + return dropNo; + return "__" + "optionConfig" + dropNo + "__"; + } + + /// + /// 生成查询面板的数据对象结构 + /// + /// + /// + /// + /// + /// + /// + /// + private void GetPanelData(List list, List> panelHtml, Func keySelector, Func predicate, bool search, Func orderBy, bool vue = false, bool app = false) + { + //{ key: 1, value: "显示/查询/编辑" }, + //{ key: 2, value: "显示/编辑" }, + //{ key: 3, value: "显示/查询" }, + //{ key: 4, value: "显示" }, + //{ key: 5, value: "查询/编辑" }, + //{ key: 6, value: "查询" }, + //{ key: 7, value: "编辑" }, + + if (app) + { + list.ForEach(x => + { + if (x.EditRowNo == 0) + { + x.EditRowNo = 99999; + } + }); + var arr = search ? new int[] { 1, 3, 5, 6 } : new int[] { 1, 2, 5, 7 }; + predicate = x => arr.Any(c => c == x.Enable); + } + + var whereReslut = list.Where(predicate).OrderBy(orderBy).ThenByDescending(c => c.OrderNo).ToList(); + foreach (var item in whereReslut.GroupBy(keySelector)) + { + panelHtml.Add(item.OrderBy(c => search ? c.SearchColNo : c.EditColNo).Select( + x => new PanelHtml + { + text = x.ColumnCnName ?? x.ColumnName, + id = x.ColumnName, + displayType = GetDisplayType(search, x.SearchType, x.EditType, x.ColumnType), + require = !search && x.IsNull == 0 ? true : false, + columnType = vue && x.IsImage == 1 ? "img" : (x.ColumnType ?? "string").ToLower(), + disabled = !search && x.IsReadDataset == 1 ? true : false, + dataSource = GetDropString(x.DropNo, vue), + colSize = search && x.SearchType != "checkbox" ? 0 : (x.ColSize ?? 0) + }).ToList()); + } + } + + + private static bool IsMysql() + { + return DBType.Name.ToLower() == DbCurrentType.MySql.ToString().ToLower(); + } + private WebResponseContent ValidColumnString(Sys_TableInfo tableInfo) + { + WebResponseContent webResponse = new WebResponseContent(true); + if (tableInfo.TableColumns == null || tableInfo.TableColumns.Count == 0) return webResponse; + + if (!string.IsNullOrEmpty(tableInfo.DetailName)) + { + Sys_TableColumn mainTableColumn = tableInfo.TableColumns + .Where(x => x.IsKey == 1) + // .Select(s => s.ColumnName) + .FirstOrDefault(); + if (mainTableColumn == null) + return webResponse.Error($"请勾选表[{tableInfo.TableName}]的主键"); + + string key = mainTableColumn.ColumnName; + + //明细表外键列的配置信息 + Sys_TableColumn tableColumn = repository + .Find(x => x.TableName == tableInfo.DetailName && x.ColumnName == key) + ?.FirstOrDefault(); + + if (tableColumn == null) + return webResponse.Error($"明细表必须包括[{tableInfo.TableName}]主键字段[{key}]"); + + if (mainTableColumn.ColumnType?.ToLower() != tableColumn.ColumnType?.ToLower()) + { + return webResponse.Error($"明细表的字段[{tableColumn.ColumnName}]类型必须与主表的主键的类型相同"); + } + + if (!IsMysql()) return webResponse; + + if (mainTableColumn.ColumnType?.ToLower() == "string" + && tableColumn.Maxlength != 36) + { + return webResponse.Error($"主表主键类型为Guid,明细表[{tableInfo.DetailName}]配置的字段[{key}]长度必须是36,请重将明细表字段[{key}]长度设置为36,点击保存与生成Model"); + } + + + //mysql如果主键使用的是guid,需要判断明细表的外键是否配置正确 + + + } + + //if (tableInfo.TableColumns.Exists(x => x.ColumnType == "string" && (x.Maxlength ?? 0) <= 0)) + //{ + // webResponse.Error("数据类型为string的列,必须输入[列最大长度]的值"); + //} + return webResponse; + } + + + } + public class PanelHtml + { + public string text { get; set; } + + public string id { get; set; } + public string displayType { get; set; } + public string dataSource { get; set; } + public string columnType { get; set; } + public bool require { get; set; } + public bool disabled { get; set; } + public int colSize { get; set; } + public int fileMaxCount { get; set; } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.Builder/Services/Core/Sys_TableInfoService.cs b/Pure_Vite_Net7/WebNet7/VOL.Builder/Services/Core/Sys_TableInfoService.cs new file mode 100644 index 0000000000000000000000000000000000000000..0945997def3ce843d795746a71e51616311b9361 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Builder/Services/Core/Sys_TableInfoService.cs @@ -0,0 +1,22 @@ +using VOL.Builder.IRepositories; +using VOL.Builder.IServices; +using VOL.Core.BaseProvider; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.Builder.Services +{ + public partial class Sys_TableInfoService : ServiceBase, ISys_TableInfoService, IDependency + { + public Sys_TableInfoService(ISys_TableInfoRepository repository) + : base(repository) + { + Init(repository); + } + public static ISys_TableInfoService Instance + { + get { return AutofacContainerModule.GetService(); } + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.Builder/Utility/ProjectPath.cs b/Pure_Vite_Net7/WebNet7/VOL.Builder/Utility/ProjectPath.cs new file mode 100644 index 0000000000000000000000000000000000000000..ccaea577b773b56567e0409f65d0470403fbc8b8 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Builder/Utility/ProjectPath.cs @@ -0,0 +1,93 @@ +using System.IO; +using System.Linq; +using VOL.Core.Extensions; + +namespace VOL.Builder.Utility +{ + public class ProjectPath + { + // private int findCount = 1; + + /// + /// 获取web父目录所在位置 + /// + /// + public static DirectoryInfo GetProjectDirectoryInfo() + { + return GetProjectDirectoryInfo(new DirectoryInfo("".MapPath()), 1); + } + public static string GetProjectFileName(string startsWith) + { + string fileNames = GetProjectDirectoryInfo()?.GetDirectories() + .Where( + c => + //c.Name.StartsWith(startsWith)&& + c.Name != startsWith + ".Core" + && c.Name != startsWith + ".Entity" + && !c.Name.ToLower().EndsWith(".web") + && !c.Name.ToLower().EndsWith(".webapi") + && !c.Name.ToLower().EndsWith(".builder") + && c.Name.ToLower()!=".vs" + ).Select(x => x.Name).ToList().Serialize(); + if (string.IsNullOrEmpty(fileNames)) + { + fileNames = new DirectoryInfo("".MapPath()).GetFiles().Where(x => x.Name.EndsWith(".dll") + //&& x.Name.StartsWith(startsWith) + && !x.Name.EndsWith(".Core.dll") + && !x.Name.EndsWith(".Entity.dll") + && !x.Name.EndsWith(".Builder.dll") + && !x.Name.ToLower().EndsWith(".web") + && !x.Name.ToLower().EndsWith(".webapi") + && !x.Name.ToLower().EndsWith(".builder") + ).Select(x => x.Name.Replace(".dll", "")).ToList().Serialize(); + } + return fileNames ?? "''"; + } + /// + /// 获取指定结尾的项目名称 + /// + /// + /// + public static string GetLastIndexOfDirectoryName(string lastIndexOfName) + { + string projectName = GetProjectDirectoryInfo()?.GetDirectories() + .Where(c => c.Name.LastIndexOf(lastIndexOfName) != -1).Select(x => x.Name).FirstOrDefault(); + if (string.IsNullOrEmpty(projectName)) + { + projectName = new DirectoryInfo("".MapPath()).GetFiles().Where(x => x.Name.LastIndexOf(lastIndexOfName + ".dll") != -1).FirstOrDefault().Name; + if (!string.IsNullOrEmpty(projectName)) + { + projectName = projectName.Replace(".dll", ""); + } + } + return projectName; + } + /// + /// 获取项目所在路径 + /// + /// + /// + private static DirectoryInfo GetProjectDirectoryInfo(DirectoryInfo directoryInfo, int findCount) + { + if (directoryInfo == null) + { + return null; + } + if (directoryInfo.Exists + && directoryInfo.GetDirectories().Where(x => x.Name.LastIndexOf(".Web") != -1).FirstOrDefault() != null) + { + return directoryInfo; + } + if (findCount < 7) + { + findCount++; + DirectoryInfo dir = GetProjectDirectoryInfo(directoryInfo.Parent, findCount); + if (dir != null) + { + return dir; + } + } + return null; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Builder/VOL.Builder.csproj b/Pure_Vite_Net7/WebNet7/VOL.Builder/VOL.Builder.csproj new file mode 100644 index 0000000000000000000000000000000000000000..69e661796db9d2a3d6b50a7c7c89cbbed8c67501 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Builder/VOL.Builder.csproj @@ -0,0 +1,32 @@ + + + + + + + + + + + net7.0 + + Library + + + + + + + + + + + + + + + + + + + diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/BaseInterface/IServices.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/BaseInterface/IServices.cs new file mode 100644 index 0000000000000000000000000000000000000000..2a6954ec312cf9c8869cde97d2090ffb7507f7a3 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/BaseInterface/IServices.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.BaseInterface +{ + public interface IServices + { + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/BaseProvider/DictionaryComponent/DictionaryViewComponent.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/BaseProvider/DictionaryComponent/DictionaryViewComponent.cs new file mode 100644 index 0000000000000000000000000000000000000000..0da5c528235566de14ff16b78e5f87c5a39be34e --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/BaseProvider/DictionaryComponent/DictionaryViewComponent.cs @@ -0,0 +1,60 @@ +using VOL.Core.Dapper; +using VOL.Core.DBManager; +using VOL.Core.EFDbContext; +using VOL.Core.Extensions; +using VOL.Entity.DomainModels; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Newtonsoft.Json; +using System; +using System.Data; +using System.Data.SqlClient; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VOL.Core.BaseProvider.DictionaryComponent +{ + /// + /// 组件视图,参照:https://docs.microsoft.com/en-us/aspnet/core/mvc/views/view-components?view=aspnetcore-2.1 + /// 与Controller命名一样必须以ViewComponent结尾 + /// + public class DictionaryViewComponent : ViewComponent + { + public async Task InvokeAsync(string dropDownIds) + { + if (string.IsNullOrEmpty(dropDownIds)) + return null; + + string[] dicNos = dropDownIds.Split(','); + StringBuilder stringBuilder = new StringBuilder(); + VOLContext context = DBServerProvider.GetEFDbContext(); + var dicData =await (from d in context.Set() + join list in context.Set() + on d.Dic_ID equals list.Dic_ID + into t + from list in t.DefaultIfEmpty() + where dicNos.Contains(d.DicNo) + select new { list.DicValue, list.DicName, d.Config, d.DbSql, list.OrderNo, d.DicNo }).ToListAsync(); + + foreach (var item in dicData.GroupBy(x => x.DicNo)) + { + stringBuilder.AppendLine($" var optionConfig{item.Key} = {item.Select(x => x.Config).FirstOrDefault()}"); + + string dbSql = item.Select(s => s.DbSql).FirstOrDefault(); + + stringBuilder.AppendLine($@" var dataSource{item.Key} = { + (!string.IsNullOrEmpty(dbSql) + ? DBServerProvider.GetSqlDapper().QueryList(dbSql, null).Serialize() + : item.OrderByDescending(o => o.OrderNo). + Select(s => new { s.DicName, s.DicValue }).ToList() + .Serialize()) + }.convertToValueText(optionConfig{item.Key})"); + stringBuilder.AppendLine($" optionConfig{item.Key}.data = dataSource{item.Key};"); + } + ViewBag.Dic = stringBuilder.ToString(); + return View("~/Views/Shared/Dictionary.cshtml"); + } + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/BaseProvider/IRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/BaseProvider/IRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..2e6b05ca493318165c27507eb80c3c3d43f8c1cb --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/BaseProvider/IRepository.cs @@ -0,0 +1,287 @@ +using Microsoft.Data.SqlClient; +using Microsoft.EntityFrameworkCore.Query; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading.Tasks; +using VOL.Core.Dapper; +using VOL.Core.EFDbContext; +using VOL.Core.Enums; +using VOL.Core.Utilities; +using VOL.Entity.SystemModels; + +namespace VOL.Core.BaseProvider +{ + public interface IRepository where TEntity : BaseEntity + { + + /// + /// EF DBContext + /// + VOLContext DbContext { get; } + + ISqlDapper DapperContext { get; } + /// + /// 执行事务。将在执行的方法带入Action + /// + /// + /// + WebResponseContent DbContextBeginTransaction(Func action); + + + /// + /// 通过条件查询数据 + /// + /// + /// + List Find(Expression> where); + + /// + /// + /// + /// + /// 排序字段,数据格式如: + /// orderBy = x => new Dictionary() { + /// { x.BalconyName,QueryOrderBy.Asc}, + /// { x.TranCorpCode1,QueryOrderBy.Desc} + /// }; + /// + /// + /// + TEntity FindFirst(Expression> predicate, Expression>> orderBy = null); + + + + /// + /// + /// + /// where条件 + /// 排序字段,数据格式如: + /// orderBy = x => new Dictionary() { + /// { x.BalconyName,QueryOrderBy.Asc}, + /// { x.TranCorpCode1,QueryOrderBy.Desc} + /// }; + /// + /// + IQueryable FindAsIQueryable(Expression> predicate, Expression>> orderBy = null); + /// + /// 通过条件查询数据 + /// + /// + /// 查询条件 + /// 返回类型如:Find(x => x.UserName == loginInfo.userName, p => new { uname = p.UserName }); + /// + List Find(Expression> predicate, Expression> selector); + + + + /// + /// 根据条件,返回查询的类 + /// + /// + /// + /// + List Find(Expression> predicate) where TFind : class; + + Task FindAsyncFirst(Expression> predicate) where TFind : class; + + Task FindAsyncFirst(Expression> predicate); + + Task> FindAsync(Expression> predicate) where TFind : class; + Task FindFirstAsync(Expression> predicate); + + Task> FindAsync(Expression> predicate); + + Task> FindAsync(Expression> predicate, Expression> selector); + + Task FindFirstAsync(Expression> predicate, Expression> selector); + + /// + /// 多条件查询 + /// + /// + /// 要查询的多个条件的数据源 + /// 生成的查询条件 + /// + List Find(IEnumerable sources, + Func>> predicate) + where Source : class; + /// + /// 多条件查询 + /// + /// + /// 要查询的多个条件的数据源 + /// 生成的查询条件 + /// 自定义返回结果 + /// + List Find(IEnumerable sources, + Func>> predicate, + Expression> selector) + where Source : class; + + /// + /// 多条件查询 + /// + /// + /// 要查询的多个条件的数据源 + /// 生成的查询条件 + /// + IQueryable FindAsIQueryable(IEnumerable sources, + Func>> predicate) + where Source : class; + + Task ExistsAsync(Expression> predicate); + + bool Exists(Expression> predicate); + + bool Exists(Expression> predicate) where TExists : class; + + Task ExistsAsync(Expression> predicate) where TExists : class; + + IIncludableQueryable Include(Expression> incluedProperty); + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// 通过多个字段排序Expression>> + /// orderBy = x => new Dictionary() { + /// { x.BalconyName,QueryOrderBy.Asc}, + /// { x.TranCorpCode1,QueryOrderBy.Desc} + /// }; + /// 查询返回的对象 + /// + List QueryByPage(int pageIndex, int pagesize, out int rowcount, Expression> predicate, Expression>> orderBySelector, Expression> selectorResult, bool returnRowCount = true); + + List QueryByPage(int pageIndex, int pagesize, Expression> predicate, Expression>> orderBy, Expression> selectorResult = null); + /// + /// + /// + /// + /// + /// + /// + /// + /// /// 通过多个字段排序Expression>> + /// orderBy = x => new Dictionary() { + /// { x.BalconyName,QueryOrderBy.Asc}, + /// { x.TranCorpCode1,QueryOrderBy.Desc} + /// }; + /// + List QueryByPage(int pageIndex, int pagesize, out int rowcount, Expression> predicate, Expression>> orderBy, bool returnRowCount = true); + + IQueryable IQueryablePage(int pageIndex, int pagesize, out int rowcount, Expression> predicate, Expression>> orderBy, bool returnRowCount = true) where TFind : class; + + + IQueryable IQueryablePage(IQueryable queryable, int pageIndex, int pagesize, out int rowcount, Dictionary orderBy, bool returnRowCount = true); + + /// + /// + /// + /// + /// 指定更新字段:x=>new {x.Name,x.Enable} + /// 是否保存 + /// + + int Update(TEntity entity, Expression> properties, bool saveChanges = false); + + /// + /// + /// + /// + /// 指定更新字段:x=>new {x.Name,x.Enable} + /// 是否保存 + /// + int Update(TSource entity, Expression> properties, bool saveChanges = false) where TSource : class; + + int Update(TSource entity, bool saveChanges = false) where TSource : class; + + int Update(TSource entity, string[] properties, bool saveChanges = false) where TSource : class; + + int UpdateRange(IEnumerable entities, bool saveChanges = false) where TSource : class; + /// + /// + /// + /// + /// 指定更新字段:x=>new {x.Name,x.Enable} + /// 是否保存 + /// + int UpdateRange(IEnumerable models, Expression> properties, bool saveChanges = false) where TSource : class; + + int UpdateRange(IEnumerable entities, string[] properties, bool saveChanges = false) where TSource : class; + + + /// + ///修改时同时对明细的添加、删除、修改 + /// + /// + /// 是否修改明细 + /// 是否删除明细不存在的数据 + /// 主表指定修改字段 + /// 明细指定修改字段 + /// 是否保存 + /// + WebResponseContent UpdateRange(TEntity entity, + bool updateDetail = false, + bool delNotExist = false, + Expression> updateMainFields = null, + Expression> updateDetailFields = null, + bool saveChange = false) where Detail : class; + + void Delete(TEntity model, bool saveChanges=false); + + /// + /// + /// + /// + /// 是否将子表的数据也删除 + /// + int DeleteWithKeys(object[] keys, bool delList = false); + + void Add(TEntity entities, bool SaveChanges = false); + void AddRange(IEnumerable entities, bool SaveChanges = false); + + Task AddAsync(TEntity entities); + Task AddRangeAsync(IEnumerable entities); + + void AddRange(IEnumerable entities, bool saveChanges = false) + where T : class; + + + void BulkInsert(IEnumerable entities, bool setOutputIdentity = false); + + int SaveChanges(); + + Task SaveChangesAsync(); + + + + int ExecuteSqlCommand(string sql, params SqlParameter[] sqlParameters); + + List FromSql(string sql, params SqlParameter[] sqlParameters); + + /// + /// 执行sql + /// 使用方式 FormattableString sql=$"select * from xx where name ={xx} and pwd={xx1} ", + /// FromSqlInterpolated内部处理sql注入的问题,直接在{xx}写对应的值即可 + /// 注意:sql必须 select * 返回所有TEntity字段, + /// + /// + /// + IQueryable FromSqlInterpolated([System.Diagnostics.CodeAnalysis.NotNull] FormattableString sql); + + + /// + /// 取消上下文跟踪(2021.08.22) + /// 更新报错时,请调用此方法:The instance of entity type 'XXX' cannot be tracked because another instance with the same key value for {'XX'} is already being tracked. + /// + /// + void Detached(TEntity entity); + void DetachedRange(IEnumerable entities); + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/BaseProvider/IService.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/BaseProvider/IService.cs new file mode 100644 index 0000000000000000000000000000000000000000..00ab4f810d33d4a79f7bafb1ac2dc6ce9710c00b --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/BaseProvider/IService.cs @@ -0,0 +1,138 @@ + +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using VOL.Core.CacheManager; +using VOL.Core.Utilities; +using VOL.Entity.DomainModels; +using VOL.Entity.SystemModels; + +namespace VOL.Core.BaseProvider +{ + public interface IService where T : BaseEntity + { + + ICacheService CacheContext { get; } + Microsoft.AspNetCore.Http.HttpContext Context { get; } + /// + /// 查询 + /// + /// + /// + PageGridData GetPageData(PageDataOptions pageData); + + object GetDetailPage(PageDataOptions pageData); + + WebResponseContent Upload(List files); + + WebResponseContent DownLoadTemplate(); + + WebResponseContent Import(List files); + /// + /// 导出 + /// + /// + /// + WebResponseContent Export(PageDataOptions pageData); + + /// + /// 新增 + /// + /// 主表与子表的数据 + /// + WebResponseContent Add(SaveModel saveDataModel); + + /// + /// + /// + /// 保存的实体 + /// 是否对实体进行校验 + /// + WebResponseContent AddEntity(T entity, bool validationEntity = true); + + /// + /// + /// + /// + /// 保存的实体 + /// 保存的明细 + /// 是否对实体进行校验 + /// + WebResponseContent Add(T entity, List list = null, bool validationEntity = true) where TDetail : class; + /// + /// 编辑 + /// + /// 主表与子表的数据 + /// + WebResponseContent Update(SaveModel saveDataModel); + + + /// + /// 删除数据 + /// + /// 删除的主键 + /// 是否删除对应明细(默认会删除明细) + /// + WebResponseContent Del(object[] keys, bool delList = true); + + WebResponseContent Audit(object[] id, int? auditStatus, string auditReason); + + + (string, T, bool) ApiValidate(string bizContent, Expression> expression = null); + + + /// + /// + /// + /// + /// + /// 对指属性验证格式如:x=>new { x.UserName,x.Value } + /// (string,TInput, bool) string:返回验证消息,TInput:bizContent序列化后的对象,bool:验证是否通过 + (string, TInput, bool) ApiValidateInput(string bizContent, Expression> expression); + + /// + /// + /// + /// + /// + /// 对指属性验证格式如:x=>new { x.UserName,x.Value } + /// 对指定的字段只做合法性判断比如长度是是否超长 + /// (string,TInput, bool) string:返回验证消息,TInput:bizContent序列化后的对象,bool:验证是否通过 + (string, TInput, bool) ApiValidateInput(string bizContent, Expression> expression, Expression> validateExpression); + + + /// + /// 将数据源映射到新的数据中,List映射到List或TSource映射到TResult + /// 目前只支持Dictionary或实体类型 + /// + /// + /// + /// + /// 只映射返回对象的指定字段 + /// 只映射数据源对象的指定字段 + /// 过滤条件表达式调用方式:List表达式x => new { x[0].MenuName, x[0].Menu_Id},表示指定映射MenuName,Menu_Id字段 + /// List list = new List(); + /// list.MapToObject, List>(x => new { x[0].MenuName, x[0].Menu_Id}, null); + /// + ///过滤条件表达式调用方式:实体表达式x => new { x.MenuName, x.Menu_Id},表示指定映射MenuName,Menu_Id字段 + /// Sys_Menu sysMenu = new Sys_Menu(); + /// sysMenu.MapToObject(x => new { x.MenuName, x.Menu_Id}, null); + /// + TResult MapToEntity(TSource source, Expression> resultExpression, + Expression> sourceExpression = null) where TResult : class; + + /// + /// 将一个实体的赋到另一个实体上,应用场景: + /// 两个实体,a a1= new a();b b1= new b(); a1.P=b1.P; a1.Name=b1.Name; + /// + /// + /// + /// + /// + /// 指定对需要的字段赋值,格式x=>new {x.Name,x.P},返回的结果只会对Name与P赋值 + void MapValueToEntity(TSource source, TResult result, Expression> expression = null) where TResult : class; + + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/BaseProvider/RepositoryBase.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/BaseProvider/RepositoryBase.cs new file mode 100644 index 0000000000000000000000000000000000000000..e0913aa43f910c2f34ff2b073de81bdcca35ddb2 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/BaseProvider/RepositoryBase.cs @@ -0,0 +1,631 @@ +using Microsoft.Data.SqlClient; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Storage; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Threading.Tasks; +using VOL.Core.Dapper; +using VOL.Core.DBManager; +using VOL.Core.EFDbContext; +using VOL.Core.Enums; +using VOL.Core.Extensions; +using VOL.Core.Utilities; +using VOL.Entity; +using VOL.Entity.SystemModels; + +namespace VOL.Core.BaseProvider +{ + public abstract class RepositoryBase where TEntity : BaseEntity + { + public RepositoryBase() + { + } + public RepositoryBase(VOLContext dbContext) + { + this.DefaultDbContext = dbContext ?? throw new Exception("dbContext未实例化。"); + } + + private VOLContext DefaultDbContext { get; set; } + private VOLContext EFContext + { + get + { + DBServerProvider.GetDbContextConnection(DefaultDbContext); + return DefaultDbContext; + } + } + + public virtual VOLContext DbContext + { + get { return DefaultDbContext; } + } + private DbSet DBSet + { + get { return EFContext.Set(); } + } + public ISqlDapper DapperContext + { + get { return DBServerProvider.GetSqlDapper(); } + } + /// + /// 执行事务 + /// + /// 如果返回false则回滚事务(可自行定义规则) + /// + public virtual WebResponseContent DbContextBeginTransaction(Func action) + { + WebResponseContent webResponse = new WebResponseContent(); + using (IDbContextTransaction transaction = DefaultDbContext.Database.BeginTransaction()) + { + try + { + webResponse = action(); + if (webResponse.Status) + { + transaction.Commit(); + } + else + { + transaction.Rollback(); + } + + return webResponse; + } + catch (Exception ex) + { + transaction.Rollback(); + return new WebResponseContent().Error(ex.Message); + } + } + } + + public virtual bool Exists(Expression> predicate) where TExists : class + { + return EFContext.Set().Any(predicate); + } + + public virtual Task ExistsAsync(Expression> predicate) where TExists : class + { + return EFContext.Set().AnyAsync(predicate); + } + + public virtual bool Exists(Expression> predicate) + { + return DBSet.Any(predicate); + } + + public virtual Task ExistsAsync(Expression> predicate) + { + return DBSet.AnyAsync(predicate); + } + public virtual List Find(Expression> predicate) where TFind : class + { + return EFContext.Set().Where(predicate).ToList(); + } + + public virtual Task FindAsyncFirst(Expression> predicate) where TFind : class + { + return FindAsIQueryable(predicate).FirstOrDefaultAsync(); + } + + public virtual Task FindAsyncFirst(Expression> predicate) + { + return FindAsIQueryable(predicate).FirstOrDefaultAsync(); + } + + public virtual Task> FindAsync(Expression> predicate) where TFind : class + { + return FindAsIQueryable(predicate).ToListAsync(); + } + + public virtual Task> FindAsync(Expression> predicate) + { + return FindAsIQueryable(predicate).ToListAsync(); + } + + public virtual Task FindFirstAsync(Expression> predicate) + { + return FindAsIQueryable(predicate).FirstOrDefaultAsync(); + } + + public virtual Task> FindAsync(Expression> predicate, Expression> selector) + { + return FindAsIQueryable(predicate).Select(selector).ToListAsync(); + } + + public virtual Task FindFirstAsync(Expression> predicate, Expression> selector) + { + return FindAsIQueryable(predicate).Select(selector).FirstOrDefaultAsync(); + } + + public virtual IQueryable FindAsIQueryable(Expression> predicate) where TFind : class + { + return EFContext.Set().Where(predicate); + } + + public virtual List Find(IEnumerable sources, + Func>> predicate) + where Source : class + { + return FindAsIQueryable(sources, predicate).ToList(); + } + public virtual List Find(IEnumerable sources, + Func>> predicate, + Expression> selector) + where Source : class + { + return FindAsIQueryable(sources, predicate).Select(selector).ToList(); + } + + /// + /// 多条件查询 + /// + /// + /// + /// + /// + public virtual IQueryable FindAsIQueryable(IEnumerable sources, + Func>> predicate) + where Source : class + { + // EFContext.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.TrackAll; + Expression> resultPredicate = x => 1 == 2; + foreach (Source source in sources) + { + Expression> expression = predicate(source); + resultPredicate = (resultPredicate).Or((expression)); + } + return EFContext.Set().Where(resultPredicate); + } + + public virtual List Find(Expression> predicate, Expression> selector) + { + return DBSet.Where(predicate).Select(selector).ToList(); + } + /// + /// 单表查询 + /// + /// + /// + public virtual List Find(Expression> predicate) + { + return FindAsIQueryable(predicate).ToList(); + } + /// + /// + /// + /// + /// + /// 排序字段 + /// + public virtual TEntity FindFirst(Expression> predicate, Expression>> orderBy = null) + { + return FindAsIQueryable(predicate, orderBy).FirstOrDefault(); + } + + + public IQueryable FindAsIQueryable(Expression> predicate, Expression>> orderBy = null) + { + if (orderBy != null) + return DbContext.Set().Where(predicate).GetIQueryableOrderBy(orderBy.GetExpressionToDic()); + return DbContext.Set().Where(predicate); + } + + public IIncludableQueryable Include(Expression> incluedProperty) + { + return DbContext.Set().Include(incluedProperty); + } + + /// + /// 通过条件查询返回指定列的数据(将TEntity映射到匿名或实体T) + ///var result = Sys_UserRepository.GetInstance.Find(x => x.UserName == loginInfo.userName, p => new { uname = p.UserName }); + /// + /// + /// + /// + /// + /// + /// + /// 查询条件 + /// 多个排序字段key为字段,value为升序/降序 + /// + public virtual IQueryable IQueryablePage(int pageIndex, int pagesize, out int rowcount, Expression> predicate, Expression>> orderBy, bool returnRowCount = true) where TFind : class + { + pageIndex = pageIndex <= 0 ? 1 : pageIndex; + pagesize = pagesize <= 0 ? 10 : pagesize; + if (predicate == null) + { + predicate = x => 1 == 1; + } + var _db = DbContext.Set(); + rowcount = returnRowCount ? _db.Count(predicate) : 0; + return DbContext.Set().Where(predicate) + .GetIQueryableOrderBy(orderBy.GetExpressionToDic()) + .Skip((pageIndex - 1) * pagesize) + .Take(pagesize); + } + + /// + /// 分页排序 + /// + /// + /// + /// + /// + /// + /// + public virtual IQueryable IQueryablePage(IQueryable queryable, int pageIndex, int pagesize, out int rowcount, Dictionary orderBy, bool returnRowCount = true) + { + pageIndex = pageIndex <= 0 ? 1 : pageIndex; + pagesize = pagesize <= 0 ? 10 : pagesize; + rowcount = returnRowCount ? queryable.Count() : 0; + return queryable.GetIQueryableOrderBy(orderBy) + .Skip((pageIndex - 1) * pagesize) + .Take(pagesize); + } + + public virtual List QueryByPage(int pageIndex, int pagesize, out int rowcount, Expression> predicate, Expression>> orderBy, Expression> selectorResult, bool returnRowCount = true) + { + return IQueryablePage(pageIndex, pagesize, out rowcount, predicate, orderBy, returnRowCount).Select(selectorResult).ToList(); + } + + public List QueryByPage(int pageIndex, int pagesize, out int rowcount, Expression> predicate, Expression>> orderBy, bool returnRowCount = true) + { + return IQueryablePage(pageIndex, pagesize, out rowcount, predicate, orderBy).ToList(); + } + + public virtual List QueryByPage(int pageIndex, int pagesize, Expression> predicate, Expression>> orderBy, Expression> selectorResult = null) + { + return IQueryablePage(pageIndex, pagesize, out int rowcount, predicate, orderBy).Select(selectorResult).ToList(); + } + + + /// + /// 更新表数据 + /// + /// + /// 是否保存 + /// 格式 Expression> expTree = x => new { x.字段1, x.字段2 }; + public virtual int Update(TEntity entity, Expression> properties, bool saveChanges = false) + { + return Update(entity, properties, saveChanges); + } + + public virtual int Update(TSource entity, Expression> properties, bool saveChanges = false) where TSource : class + { + return UpdateRange(new List + { + entity + }, properties, saveChanges); + } + + + public virtual int Update(TSource entity, string[] properties, bool saveChanges = false) where TSource : class + { + return UpdateRange(new List() { entity }, properties, saveChanges); + } + public virtual int Update(TSource entity, bool saveChanges = false) where TSource : class + { + return UpdateRange(new List() { entity }, new string[0], saveChanges); + } + public virtual int UpdateRange(IEnumerable entities, Expression> properties, bool saveChanges = false) where TSource : class + { + return UpdateRange(entities, properties?.GetExpressionProperty(), saveChanges); + } + public virtual int UpdateRange(IEnumerable entities, bool saveChanges = false) where TSource : class + { + return UpdateRange(entities, new string[0], saveChanges); + } + + /// + /// 更新表数据 + /// + /// + /// 格式 Expression> expTree = x => new { x.字段1, x.字段2 }; + public int UpdateRange(IEnumerable entities, string[] properties, bool saveChanges = false) where TSource : class + { + if (properties != null && properties.Length > 0) + { + PropertyInfo[] entityProperty = typeof(TSource).GetProperties(); + string keyName = entityProperty.GetKeyName(); + if (properties.Contains(keyName)) + { + properties = properties.Where(x => x != keyName).ToArray(); + } + properties = properties.Where(x => entityProperty.Select(s => s.Name).Contains(x)).ToArray(); + } + foreach (TSource item in entities) + { + if (properties == null || properties.Length == 0) + { + DbContext.Entry(item).State = EntityState.Modified; + continue; + } + var entry = DbContext.Entry(item); + properties.ToList().ForEach(x => + { + entry.Property(x).IsModified = true; + }); + } + if (!saveChanges) return 0; + + //2020.04.24增加更新时并行重试处理 + try + { + // Attempt to save changes to the database + return DbContext.SaveChanges(); + } + catch (DbUpdateConcurrencyException ex) + { + int affectedRows = 0; + foreach (var entry in ex.Entries) + { + var proposedValues = entry.CurrentValues; + + var databaseValues = entry.GetDatabaseValues(); + //databaseValues == null说明数据已被删除 + if (databaseValues != null) + { + foreach (var property in properties == null + || properties.Length == 0 ? proposedValues.Properties + : proposedValues.Properties.Where(x => properties.Contains(x.Name))) + { + var proposedValue = proposedValues[property]; + var databaseValue = databaseValues[property]; + } + affectedRows++; + entry.OriginalValues.SetValues(databaseValues); + } + } + if (affectedRows == 0) return 0; + + return DbContext.SaveChanges(); + } + } + + + + + /// + /// + /// + /// + /// 是否修改明细 + /// 是否删除明细不存在的数据 + /// 主表指定修改字段 + /// 明细指定修改字段 + /// 是否保存 + /// + public virtual WebResponseContent UpdateRange(TEntity entity, + bool updateDetail = false, + bool delNotExist = false, + Expression> updateMainFields = null, + Expression> updateDetailFields = null, + bool saveChange = false) where Detail : class + { + WebResponseContent webResponse = new WebResponseContent(); + Update(entity, updateMainFields); + string message = ""; + if (updateDetail) + { + string detailTypeName = typeof(List).FullName; + PropertyInfo[] properties = typeof(TEntity).GetProperties(); + PropertyInfo detail = properties.Where(x => x.PropertyType.FullName == detailTypeName).ToList().FirstOrDefault(); + if (detail != null) + { + PropertyInfo key = properties.GetKeyProperty(); + object obj = detail.GetValue(entity); + Type detailType = typeof(TEntity).GetCustomAttribute().DetailTable[0]; + message = UpdateDetail(obj as List, key.Name, key.GetValue(entity), updateDetailFields, delNotExist); + } + } + if (!saveChange) return webResponse.OK(); + + DbContext.SaveChanges(); + return webResponse.OK("修改成功,明细" + message, entity); + } + private string UpdateDetail(List list, + string keyName, + object keyValue, + Expression> updateDetailFields = null, + bool delNotExist = false) where TDetail : class + { + if (list == null) return ""; + PropertyInfo property = typeof(TDetail).GetKeyProperty(); + string detailKeyName = property.Name; + DbSet details = DbContext.Set(); + Expression> selectExpression = detailKeyName.GetExpression(); + Expression> whereExpression = keyName.CreateExpression(keyValue, LinqExpressionType.Equal); + + List detailKeys = details.Where(whereExpression).Select(selectExpression).ToList(); + + //获取主键默认值 + string keyDefaultVal = property.PropertyType + .Assembly + .CreateInstance(property.PropertyType.FullName).ToString(); + int addCount = 0; + int editCount = 0; + int delCount = 0; + PropertyInfo mainKeyProperty = typeof(TDetail).GetProperty(keyName); + List keys = new List(); + list.ForEach(x => + { + var set = DbContext.Set(); + object val = property.GetValue(x); + //主键是默认值的为新增的数据 + if (val.ToString() == keyDefaultVal) + { + x.SetCreateDefaultVal(); + //设置主表的值,也可以不设置 + mainKeyProperty.SetValue(x, keyValue); + details.Add(x); + addCount++; + } + else//修改的数据 + { + //获取所有修改的key,如果从数据库查来的key,不在修改中的key,则为删除的数据 + keys.Add(val); + x.SetModifyDefaultVal(); + Update(x, updateDetailFields); + // repository.DbContext.Entry(x).State = EntityState.Modified; + editCount++; + } + }); + //删除 + if (delNotExist) + { + detailKeys.Where(x => !keys.Contains(x)).ToList().ForEach(d => + { + delCount++; + TDetail detail = Activator.CreateInstance(); + property.SetValue(detail, d); + DbContext.Entry(detail).State = EntityState.Deleted; + for (int i = 0; i < list.Count(); i++) + { + if (property.GetValue(list[i]) == d) + { + list.RemoveAt(i); + } + } + }); + } + return $"修改[{editCount}]条,新增[{addCount}]条,删除[{delCount}]条"; + } + + public virtual void Delete(TEntity model, bool saveChanges) + { + DBSet.Remove(model); + if (saveChanges) + { + DbContext.SaveChanges(); + } + } + /// + /// 通过主键批量删除 + /// + /// 主键key + /// 是否连明细一起删除 + /// + public virtual int DeleteWithKeys(object[] keys, bool delList = false) + { + Type entityType = typeof(TEntity); + string tKey = entityType.GetKeyProperty().Name; + FieldType fieldType = entityType.GetFieldType(); + string joinKeys = (fieldType == FieldType.Int || fieldType == FieldType.BigInt) + ? string.Join(",", keys) + : $"'{string.Join("','", keys)}'"; + + string sql = $"DELETE FROM {entityType.GetEntityTableName() } where {tKey} in ({joinKeys});"; + if (delList) + { + Type detailType = entityType.GetCustomAttribute().DetailTable?[0]; + if (detailType != null) + sql = sql + $"DELETE FROM {detailType.GetEntityTableName()} where {tKey} in ({joinKeys});"; + } + return ExecuteSqlCommand(sql); + } + + + public virtual Task AddAsync(TEntity entities) + { + return DBSet.AddRangeAsync(entities); + } + + public virtual Task AddRangeAsync(IEnumerable entities) + { + return DBSet.AddRangeAsync(entities); + } + + public virtual void Add(TEntity entities, bool saveChanges = false) + { + AddRange(new List() { entities }, saveChanges); + } + public virtual void AddRange(IEnumerable entities, bool saveChanges = false) + { + DBSet.AddRange(entities); + if (saveChanges) DbContext.SaveChanges(); + } + + public virtual void AddRange(IEnumerable entities, bool saveChanges = false) + where T : class + { + DbContext.Set().AddRange(entities); + if (saveChanges) DbContext.SaveChanges(); + } + + /// + /// 注意List生成的table的列顺序必须要和数据库表的列顺序一致 + /// + /// + /// + public virtual void BulkInsert(IEnumerable entities, bool setOutputIdentity = false) + { + // EFContext.Model.FindEntityType("").Relational() + //Pomelo.EntityFrameworkCore.MySql + try + { + // EFContext.BulkInsert(entities.ToList()); + } + catch (DbUpdateException ex) + { + throw (ex.InnerException as Exception ?? ex); + } + // BulkInsert(entities.ToDataTable(), typeof(T).GetEntityTableName(), null); + } + + public virtual int SaveChanges() + { + return EFContext.SaveChanges(); + } + + public virtual Task SaveChangesAsync() + { + return EFContext.SaveChangesAsync(); + } + + public virtual int ExecuteSqlCommand(string sql, params SqlParameter[] sqlParameters) + { + return DbContext.Database.ExecuteSqlRaw(sql, sqlParameters); + } + + public virtual List FromSql(string sql, params SqlParameter[] sqlParameters) + { + return DBSet.FromSqlRaw(sql, sqlParameters).ToList(); + } + + /// + /// 执行sql + /// 使用方式 FormattableString sql=$"select * from xx where name ={xx} and pwd={xx1} ", + /// FromSqlInterpolated内部处理sql注入的问题,直接在{xx}写对应的值即可 + /// 注意:sql必须 select * 返回所有TEntity字段, + /// + /// + /// + public virtual IQueryable FromSqlInterpolated([NotNull] FormattableString sql) + { + //DBSet.FromSqlInterpolated(sql).Select(x => new { x,xxx}).ToList(); + return DBSet.FromSqlInterpolated(sql); + } + + /// + /// 取消上下文跟踪 + /// + /// + public virtual void Detached(TEntity entity) + { + DbContext.Entry(entity).State = EntityState.Detached; + } + public virtual void DetachedRange(IEnumerable entities) + { + foreach (var entity in entities) + { + DbContext.Entry(entity).State = EntityState.Detached; + } + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/BaseProvider/ServerMapPath/PathProvider.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/BaseProvider/ServerMapPath/PathProvider.cs new file mode 100644 index 0000000000000000000000000000000000000000..3a7ef298f7f4286efde2e874e0fc5e5e0beb4656 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/BaseProvider/ServerMapPath/PathProvider.cs @@ -0,0 +1,52 @@ + +using Microsoft.AspNetCore.Hosting; +using System.IO; +using VOL.Core.Extensions; +using VOL.Core.Extensions.AutofacManager; + +namespace VOL.Core.BaseProvider.ServerMapPath +{ + public interface IPathProvider : IDependency + { + string MapPath(string path); + string MapPath(string path, bool rootPath); + IWebHostEnvironment GetHostingEnvironment(); + } + + public class PathProvider : IPathProvider + { + private IWebHostEnvironment _hostingEnvironment; + + public PathProvider(IWebHostEnvironment environment) + { + _hostingEnvironment = environment; + } + public IWebHostEnvironment GetHostingEnvironment() + { + return _hostingEnvironment; + } + + public string MapPath(string path) + { + return MapPath(path, false); + } + /// + /// + /// + /// + /// 获取wwwroot路径 + /// + public string MapPath(string path, bool rootPath) + { + if (rootPath) + { + if (_hostingEnvironment.WebRootPath == null) + { + _hostingEnvironment.WebRootPath = _hostingEnvironment.ContentRootPath + "/wwwroot".ReplacePath(); + } + return Path.Combine(_hostingEnvironment.WebRootPath, path).ReplacePath(); + } + return Path.Combine(_hostingEnvironment.ContentRootPath, path).ReplacePath(); + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/BaseProvider/ServiceBase.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/BaseProvider/ServiceBase.cs new file mode 100644 index 0000000000000000000000000000000000000000..006052cbbcec43010a6a74f97b70a5c0fd8edaae --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/BaseProvider/ServiceBase.cs @@ -0,0 +1,1389 @@ +using Microsoft.EntityFrameworkCore; +using Newtonsoft.Json; +using OfficeOpenXml.FormulaParsing.Excel.Functions.Logical; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Runtime.CompilerServices; +using VOL.Core.CacheManager; +using VOL.Core.Configuration; +using VOL.Core.Const; +using VOL.Core.Enums; +using VOL.Core.Extensions; +using VOL.Core.Extensions.AutofacManager; +using VOL.Core.Filters; +using VOL.Core.ManageUser; +using VOL.Core.Services; +using VOL.Core.Tenancy; +using VOL.Core.Utilities; +using VOL.Core.WorkFlow; +using VOL.Entity; +using VOL.Entity.DomainModels; +using VOL.Entity.SystemModels; + +namespace VOL.Core.BaseProvider +{ + public abstract class ServiceBase : ServiceFunFilter + where T : BaseEntity + where TRepository : IRepository + { + public ICacheService CacheContext + { + get + { + return AutofacContainerModule.GetService(); + } + } + + public Microsoft.AspNetCore.Http.HttpContext Context + { + get + { + return HttpContext.Current; + } + } + private WebResponseContent Response { get; set; } + + protected IRepository repository; + + private PropertyInfo[] _propertyInfo { get; set; } = null; + private PropertyInfo[] TProperties + { + get + { + if (_propertyInfo != null) + { + return _propertyInfo; + } + _propertyInfo = typeof(T).GetProperties(); + return _propertyInfo; + } + } + + public ServiceBase() + { + } + + public ServiceBase(TRepository repository) + { + Response = new WebResponseContent(true); + this.repository = repository; + } + + protected virtual void Init(IRepository repository) + { + + } + + protected virtual Type GetRealDetailType() + { + return typeof(T).GetCustomAttribute()?.DetailTable?[0]; + } + + /// + /// 2020.08.15添加自定义原生查询sql或多租户(查询、导出) + /// + /// + private IQueryable GetSearchQueryable() + { + //2021.08.22移除数据隔离(租房管理)超级管理员的判断 + //没有自定sql与多租户执行默认查询 + if (QuerySql == null && !IsMultiTenancy) + // if ((QuerySql == null && !IsMultiTenancy) || UserContext.Current.IsSuperAdmin) + { + return repository.DbContext.Set(); + } + //自定sql,没有使用多租户,直接执行自定义sql + if (QuerySql != null && !IsMultiTenancy) + // if ((QuerySql != null && !IsMultiTenancy) || UserContext.Current.IsSuperAdmin) + { + return repository.DbContext.Set().FromSqlRaw(QuerySql); + } + string multiTenancyString = TenancyManager.GetSearchQueryable(typeof(T).GetEntityTableName()); + return repository.DbContext.Set().FromSqlRaw(multiTenancyString); + } + + /// + /// 2020.08.15添加获取多租户数据过滤sql(删除、编辑) + /// + /// + private string GetMultiTenancySql(string ids, string tableKey) + { + return TenancyManager.GetMultiTenancySql(typeof(T).GetEntityTableName(), ids, tableKey); + } + + /// + /// 2020.08.15添加多租户数据过滤(编辑) + /// + private void CheckUpdateMultiTenancy(string ids, string tableKey) + { + string sql = GetMultiTenancySql(ids, tableKey); + + //请接着过滤条件 + //例如sql,只能(编辑)自己创建的数据:判断数据是不是当前用户创建的 + //sql = $" {sql} and createid!={UserContext.Current.UserId}"; + object obj = repository.DapperContext.ExecuteScalar(sql, null); + if (obj == null || obj.GetInt() == 0) + { + Response.Error("不能编辑此数据"); + } + } + + + /// + /// 2020.08.15添加多租户数据过滤(删除) + /// + private void CheckDelMultiTenancy(string ids, string tableKey) + { + string sql = GetMultiTenancySql(ids, tableKey); + + //请接着过滤条件 + //例如sql,只能(删除)自己创建的数据:找出不是自己创建的数据 + //sql = $" {sql} and createid!={UserContext.Current.UserId}"; + object obj = repository.DapperContext.ExecuteScalar(sql, null); + int idsCount = ids.Split(",").Distinct().Count(); + if (obj == null || obj.GetInt() != idsCount) + { + Response.Error("不能删除此数据"); + } + } + + private const string _asc = "asc"; + /// + /// 生成排序字段 + /// + /// + /// + private Dictionary GetPageDataSort(PageDataOptions pageData, PropertyInfo[] propertyInfo) + { + if (base.OrderByExpression != null) + { + return base.OrderByExpression.GetExpressionToDic(); + } + if (!string.IsNullOrEmpty(pageData.Sort)) + { + if (pageData.Sort.Contains(",")) + { + var sortArr = pageData.Sort.Split(",").Where(x => propertyInfo.Any(c => c.Name == x)).Select(s => s).Distinct().ToList(); + Dictionary sortDic = new Dictionary(); + foreach (var name in sortArr) + { + sortDic[name] = pageData.Order?.ToLower() == _asc ? QueryOrderBy.Asc : QueryOrderBy.Desc; + } + return sortDic; + } + else if (propertyInfo.Any(x => x.Name == pageData.Sort)) + { + return new Dictionary() { { + pageData.Sort, + pageData.Order?.ToLower() == _asc? QueryOrderBy.Asc: QueryOrderBy.Desc + } }; + } + } + //如果没有排序字段,则使用主键作为排序字段 + + PropertyInfo property = propertyInfo.GetKeyProperty(); + //如果主键不是自增类型则使用appsettings.json中CreateMember->DateField配置的创建时间作为排序 + if (property.PropertyType == typeof(int) || property.PropertyType == typeof(long)) + { + if (!propertyInfo.Any(x => x.Name.ToLower() == pageData.Sort)) + { + pageData.Sort = propertyInfo.GetKeyName(); + } + } + else + { + if (!string.IsNullOrEmpty(AppSetting.CreateMember.DateField) + && propertyInfo.Any(x => x.Name == AppSetting.CreateMember.DateField)) + { + pageData.Sort = AppSetting.CreateMember.DateField; + } + else + { + pageData.Sort = propertyInfo.GetKeyName(); + } + } + return new Dictionary() { { + pageData.Sort, pageData.Order?.ToLower() == _asc? QueryOrderBy.Asc: QueryOrderBy.Desc + } }; + } + + + /// + /// 验证排序与查询字段合法性 + /// + /// + /// + /// + private PageDataOptions ValidatePageOptions(PageDataOptions options, out IQueryable queryable) + { + options = options ?? new PageDataOptions(); + + List searchParametersList = new List(); + if (!string.IsNullOrEmpty(options.Wheres)) + { + try + { + searchParametersList = options.Wheres.DeserializeObject>(); + } + catch { } + } + QueryRelativeList?.Invoke(searchParametersList); + // Connection + // queryable = repository.DbContext.Set(); + //2020.08.15添加自定义原生查询sql或多租户 + queryable = GetSearchQueryable(); + + //判断列的数据类型数字,日期的需要判断值的格式是否正确 + for (int i = 0; i < searchParametersList.Count; i++) + { + SearchParameters x = searchParametersList[i]; + x.DisplayType = x.DisplayType.GetDBCondition(); + if (string.IsNullOrEmpty(x.Value)) + { + continue; + } + PropertyInfo property = TProperties.Where(c => c.Name.ToUpper() == x.Name.ToUpper()).FirstOrDefault(); + //2020.06.25增加字段null处理 + if (property == null) continue; + // property + //移除查询的值与数据库类型不匹配的数据 + object[] values = property.ValidationValueForDbType(x.Value.Split(',')).Where(q => q.Item1).Select(s => s.Item3).ToArray(); + if (values == null || values.Length == 0) + { + continue; + } + if (x.DisplayType == HtmlElementType.Contains) + x.Value = string.Join(",", values); + LinqExpressionType expressionType = x.DisplayType.GetLinqCondition(); + queryable = LinqExpressionType.In == expressionType + ? queryable.Where(x.Name.CreateExpression(values, expressionType)) + : queryable.Where(x.Name.CreateExpression(x.Value, expressionType)); + } + options.TableName = base.TableName ?? typeof(T).Name; + return options; + } + + /// + /// 加载页面数据 + /// + /// + /// + public virtual PageGridData GetPageData(PageDataOptions options) + { + options = ValidatePageOptions(options, out IQueryable queryable); + //获取排序字段 + Dictionary orderbyDic = GetPageDataSort(options, TProperties); + + PageGridData pageGridData = new PageGridData(); + if (QueryRelativeExpression != null) + { + queryable = QueryRelativeExpression.Invoke(queryable); + } + if (options.Export) + { + queryable = queryable.GetIQueryableOrderBy(orderbyDic); + if (Limit > 0) + { + queryable = queryable.Take(Limit); + } + pageGridData.rows = queryable.ToList(); + } + else + { + pageGridData.rows = repository.IQueryablePage(queryable, + options.Page, + options.Rows, + out int rowCount, + orderbyDic).ToList(); + pageGridData.total = rowCount; + //查询界面统计求等字段 + if (SummaryExpress != null) + { + pageGridData.summary = SummaryExpress.Invoke(queryable); + //Func groupExpress = x =>x; + //pageGridData.summary = queryable.GroupBy(groupExpress).Select(SummaryExpress).FirstOrDefault(); + } + } + GetPageDataOnExecuted?.Invoke(pageGridData); + return pageGridData; + + } + + public virtual object GetDetailPage(PageDataOptions pageData) + { + Type detailType = typeof(T).GetCustomAttribute()?.DetailTable?[0]; + if (detailType == null) + { + return null; + } + object obj = typeof(ServiceBase) + .GetMethod("GetDetailPage", BindingFlags.Instance | BindingFlags.NonPublic) + .MakeGenericMethod(new Type[] { detailType }).Invoke(this, new object[] { pageData }); + return obj; + } + protected override object GetDetailSummary(IQueryable queryeable) + { + return null; + } + + private PageGridData GetDetailPage(PageDataOptions options) where Detail : class + { + //校验查询值,排序字段,分页大小规则待完 + PageGridData gridData = new PageGridData(); + if (options.Value == null) return gridData; + //主表主键字段 + string keyName = typeof(T).GetKeyName(); + + //生成查询条件 + Expression> whereExpression = keyName.CreateExpression(options.Value, LinqExpressionType.Equal); + + var queryeable = repository.DbContext.Set().Where(whereExpression); + + gridData.total = queryeable.Count(); + options.Sort = options.Sort ?? typeof(Detail).GetKeyName(); + Dictionary orderBy = GetPageDataSort(options, typeof(Detail).GetProperties()); + + gridData.rows = queryeable + .GetIQueryableOrderBy(orderBy) + .Skip((options.Page - 1) * options.Rows) + .Take(options.Rows) + .ToList(); + gridData.summary = GetDetailSummary(queryeable); + return gridData; + } + + + + /// + /// 上传文件 + /// + /// + /// + public virtual WebResponseContent Upload(List files) + { + if (files == null || files.Count == 0) return Response.Error("请上传文件"); + + string filePath; + if (!string.IsNullOrEmpty(UploadFolder)) + { + filePath = UploadFolder; + if (!filePath.EndsWith("/") || !filePath.EndsWith("\\")) + { + filePath += "/"; + } + } + else + { + filePath = $"Upload/Tables/{typeof(T).GetEntityTableName()}/{DateTime.Now.ToString("yyyMMddHHmmsss") + new Random().Next(1000, 9999)}/"; + } + + string fullPath = filePath.MapPath(true); + int i = 0; + try + { + if (!Directory.Exists(fullPath)) Directory.CreateDirectory(fullPath); + for (i = 0; i < files.Count; i++) + { + string fileName = files[i].FileName; + using (var stream = new FileStream(fullPath + fileName, FileMode.Create)) + { + files[i].CopyTo(stream); + } + } + } + catch (Exception ex) + { + Logger.Error($"上传文件失败:{typeof(T).GetEntityTableCnName()},路径:{filePath},失败文件:{files[i]},{ex.Message + ex.StackTrace}"); + return Response.Error("文件上传失败"); + } + return Response.OK("文件上传成功", filePath); + } + + private List GetIgnoreTemplate() + { + //忽略创建人、修改人、审核等字段 + List ignoreTemplate = UserIgnoreFields.ToList(); + ignoreTemplate.AddRange(auditFields.ToList()); + return ignoreTemplate; + } + + public virtual WebResponseContent DownLoadTemplate() + { + string tableName = typeof(T).GetEntityTableCnName(); + + string dicPath = $"Download/{DateTime.Now.ToString("yyyMMdd")}/Template/".MapPath(); + if (!Directory.Exists(dicPath)) Directory.CreateDirectory(dicPath); + string fileName = tableName + DateTime.Now.ToString("yyyyMMddHHssmm") + ".xlsx"; + //DownLoadTemplateColumns 2020.05.07增加扩展指定导出模板的列 + EPPlusHelper.ExportTemplate(DownLoadTemplateColumns, GetIgnoreTemplate(), dicPath, fileName); + return Response.OK(null, dicPath + fileName); + } + + /// + /// 导入表数据Excel文件夹 + /// + /// + /// + public virtual WebResponseContent Import(List files) + { + if (files == null || files.Count == 0) + return new WebResponseContent { Status = true, Message = "请选择上传的文件" }; + Microsoft.AspNetCore.Http.IFormFile formFile = files[0]; + string dicPath = $"Upload/{DateTime.Now.ToString("yyyMMdd")}/{typeof(T).Name}/".MapPath(); + if (!Directory.Exists(dicPath)) Directory.CreateDirectory(dicPath); + dicPath = $"{dicPath}{Guid.NewGuid().ToString()}_{formFile.FileName}"; + + using (var stream = new FileStream(dicPath, FileMode.Create)) + { + formFile.CopyTo(stream); + } + try + { + //2022.06.20增加原生excel读取方法(导入时可以自定义读取excel内容) + Response = EPPlusHelper.ReadToDataTable(dicPath, DownLoadTemplateColumns, GetIgnoreTemplate(), readValue: ImportOnReadCellValue); + } + catch (Exception ex) + { + Response.Error("未能处理导入的文件,请检查导入的文件是否正确"); + Logger.Error($"表{typeof(T).GetEntityTableCnName()}导入失败{ex.Message + ex.InnerException?.Message}"); + } + if (CheckResponseResult()) return Response; + List list = Response.Data as List; + if (ImportOnExecuting != null) + { + Response = ImportOnExecuting.Invoke(list); + if (CheckResponseResult()) return Response; + } + //2022.01.08增加明细表导入判断 + if (HttpContext.Current.Request.Query.ContainsKey("table")) + { + ImportOnExecuted?.Invoke(list); + return Response.OK("文件上传成功", list.Serialize()); + } + repository.AddRange(list, true); + if (ImportOnExecuted != null) + { + Response = ImportOnExecuted.Invoke(list); + if (CheckResponseResult()) return Response; + } + return Response.OK("文件上传成功"); + } + + /// + /// 导出 + /// + /// + /// + public virtual WebResponseContent Export(PageDataOptions pageData) + { + pageData.Export = true; + List list = GetPageData(pageData).rows; + string tableName = typeof(T).GetEntityTableCnName(); + string fileName = tableName + DateTime.Now.ToString("yyyyMMddHHssmm") + ".xlsx"; + string folder = DateTime.Now.ToString("yyyyMMdd"); + string savePath = $"Download/ExcelExport/{folder}/".MapPath(); + List ignoreColumn = new List(); + if (ExportOnExecuting != null) + { + Response = ExportOnExecuting(list, ignoreColumn); + if (CheckResponseResult()) return Response; + } + //ExportColumns 2020.05.07增加扩展指定导出模板的列 + EPPlusHelper.Export(list, ExportColumns?.GetExpressionToArray(), ignoreColumn, savePath, fileName); + //return Response.OK(null, (savePath + "/" + fileName).EncryptDES(AppSetting.Secret.ExportFile)); + //2022.01.08优化导出功能 + return Response.OK(null, (savePath + "/" + fileName)); + } + + /// + /// 新建 + /// + /// + /// + public virtual WebResponseContent Add(SaveModel saveDataModel) + { + if (AddOnExecute != null) + { + Response = AddOnExecute(saveDataModel); + if (CheckResponseResult()) return Response; + } + if (saveDataModel == null + || saveDataModel.MainData == null + || saveDataModel.MainData.Count == 0) + return Response.Set(ResponseType.ParametersLack, false); + + saveDataModel.DetailData = saveDataModel.DetailData?.Where(x => x.Count > 0).ToList(); + Type type = typeof(T); + + string validReslut = type.ValidateDicInEntity(saveDataModel.MainData, true, UserIgnoreFields); + + if (!string.IsNullOrEmpty(validReslut)) return Response.Error(validReslut); + + if (saveDataModel.MainData.Count == 0) + return Response.Error("保存的数据为空,请检查model是否配置正确!"); + + UserInfo userInfo = UserContext.Current.UserInfo; + saveDataModel.SetDefaultVal(AppSetting.CreateMember, userInfo); + + PropertyInfo keyPro = type.GetKeyProperty(); + if (keyPro.PropertyType == typeof(Guid)) + { + saveDataModel.MainData.Add(keyPro.Name, Guid.NewGuid()); + } + else + { + saveDataModel.MainData.Remove(keyPro.Name); + } + //没有明细直接保存返回 + if (saveDataModel.DetailData == null || saveDataModel.DetailData.Count == 0) + { + T mainEntity = saveDataModel.MainData.DicToEntity(); + SetAuditDefaultValue(mainEntity); + if (base.AddOnExecuting != null) + { + Response = base.AddOnExecuting(mainEntity, null); + if (CheckResponseResult()) return Response; + } + Response = repository.DbContextBeginTransaction(() => + { + repository.Add(mainEntity, true); + saveDataModel.MainData[keyPro.Name] = keyPro.GetValue(mainEntity); + Response.OK(ResponseType.SaveSuccess); + if (base.AddOnExecuted != null) + { + Response = base.AddOnExecuted(mainEntity, null); + } + return Response; + }); + if (Response.Status) Response.Data = new { data = saveDataModel.MainData }; + AddProcese(mainEntity); + return Response; + } + + Type detailType = GetRealDetailType(); + + return typeof(ServiceBase) + .GetMethod("Add", BindingFlags.Instance | BindingFlags.NonPublic) + .MakeGenericMethod(new Type[] { detailType }) + .Invoke(this, new object[] { saveDataModel }) + as WebResponseContent; + } + + public virtual WebResponseContent AddEntity(T entity, bool validationEntity = true) + { + return Add(entity, null, validationEntity); + } + + /// + /// 保存主、明细数据 + /// + /// + /// + /// + /// 是否进行实体验证 + /// + public WebResponseContent Add(T entity, List list = null, bool validationEntity = true) where TDetail : class + { + //设置用户默认值 + entity.SetCreateDefaultVal(); + SetAuditDefaultValue(entity); + if (validationEntity) + { + Response = entity.ValidationEntity(); + if (CheckResponseResult()) return Response; + if (list != null && list.Count > 0) + { + Response = list.ValidationEntity(); + if (CheckResponseResult()) return Response; + } + } + if (this.AddOnExecuting != null) + { + Response = AddOnExecuting(entity, list); + if (CheckResponseResult()) return Response; + } + Response = repository.DbContextBeginTransaction(() => + { + repository.Add(entity); + repository.DbContext.SaveChanges(); + //保存明细 + if (list != null && list.Count > 0) + { + //获取保存后的主键值 + PropertyInfo mainKey = typeof(T).GetKeyProperty(); + PropertyInfo detailMainKey = typeof(TDetail).GetProperties() + .Where(q => q.Name.ToLower() == mainKey.Name.ToLower()).FirstOrDefault(); + object keyValue = mainKey.GetValue(entity); + list.ForEach(x => + { + //设置用户默认值 + x.SetCreateDefaultVal(); + detailMainKey.SetValue(x, keyValue); + repository.DbContext.Entry(x).State = EntityState.Added; + }); + repository.DbContext.SaveChanges(); + } + Response.OK(ResponseType.SaveSuccess); + if (AddOnExecuted != null) + Response = AddOnExecuted(entity, list); + return Response; + }); + if (Response.Status && string.IsNullOrEmpty(Response.Message)) + { + Response.OK(ResponseType.SaveSuccess); + } + AddProcese(entity); + return Response; + } + + /// + /// 设置审批字段默认值 + /// + /// + private void SetAuditDefaultValue(T entity) + { + if (!WorkFlowManager.Exists()) + { + return; + } + var propertity = TProperties.Where(x => x.Name.ToLower() == "auditstatus").FirstOrDefault(); + if (propertity != null && propertity.GetValue(entity) == null) + { + propertity.SetValue(entity, 0); + } + } + /// + /// 写入流程 + /// + /// + /// + /// 是否修改原表的审批状态 + protected void RewriteFlow(T entity, bool changeTableStatus = true) + { + WorkFlowManager.AddProcese(entity, true, changeTableStatus); + } + private void AddProcese(T entity) + { + if (!CheckResponseResult() && WorkFlowManager.Exists()) + { + if (AddWorkFlowExecuting != null && !AddWorkFlowExecuting.Invoke(entity)) + { + return; + } + //写入流程 + WorkFlowManager.AddProcese(entity); + WorkFlowManager.Audit(entity, AuditStatus.审核中, null, null, null, null, init: true, initInvoke: AddWorkFlowExecuted); + } + } + + public void AddDetailToDBSet() where TDetail : class + { + List listChilds = TProperties.Where(x => x.PropertyType.Name == "List`1").ToList(); + // repository.DbContext.Set().AddRange(); + } + + private WebResponseContent Add(SaveModel saveDataModel) where TDetail : class + { + T mainEntity = saveDataModel.MainData.DicToEntity(); + //验证明细 + string reslut = typeof(TDetail).ValidateDicInEntity(saveDataModel.DetailData, true, false, new string[] { TProperties.GetKeyName() }); + if (reslut != string.Empty) + return Response.Error(reslut); + + List list = saveDataModel.DetailData.DicToList(); + Response = Add(mainEntity, list, false); + + //保存失败 + if (CheckResponseResult()) + { + Logger.Error(LoggerType.Add, saveDataModel.Serialize() + Response.Message); + return Response; + } + + PropertyInfo propertyKey = typeof(T).GetKeyProperty(); + saveDataModel.MainData[propertyKey.Name] = propertyKey.GetValue(mainEntity); + Response.Data = new { data = saveDataModel.MainData, list }; + return Response.Set(ResponseType.SaveSuccess); + } + + #region 编辑 + + /// + /// 获取编辑明细主键 + /// + /// + /// + /// + /// + /// + /// + public List GetUpdateDetailSelectKeys(string detailKeyName, string mainKeyName, string mainKeyValue) where DetailT : class + { + IQueryable queryable = repository.DbContext.Set(); + Expression> selectExpression = detailKeyName.GetExpression(); + Expression> whereExpression = mainKeyName.CreateExpression(mainKeyValue, LinqExpressionType.Equal); + List detailKeys = queryable.Where(whereExpression).Select(selectExpression).ToList(); + return detailKeys; + } + + /// + /// 将数据转换成对象后最终保存 + /// + /// + /// + /// + /// + /// + /// + public WebResponseContent UpdateToEntity(SaveModel saveModel, PropertyInfo mainKeyProperty, PropertyInfo detailKeyInfo, object keyDefaultVal) where DetailT : class + { + T mainEnity = saveModel.MainData.DicToEntity(); + List detailList = saveModel.DetailData.DicToList(); + //2021.08.21优化明细表删除 + //删除的主键 + //查出所有明细表数据的ID + //System.Collections.IList detailKeys = this.GetType().GetMethod("GetUpdateDetailSelectKeys") + // .MakeGenericMethod(new Type[] { typeof(DetailT), detailKeyInfo.PropertyType }) + // .Invoke(this, new object[] { + // detailKeyInfo.Name, mainKeyProperty.Name, + // saveModel.MainData[mainKeyProperty.Name].ToString() + // }) as System.Collections.IList; + + //新增对象 + List addList = new List(); + // List containsKeys = new List(); + //编辑对象 + List editList = new List(); + //删除的主键 + List delKeys = new List(); + mainKeyProperty = typeof(DetailT).GetProperties().Where(x => x.Name == mainKeyProperty.Name).FirstOrDefault(); + //获取新增与修改的对象 + foreach (DetailT item in detailList) + { + object value = detailKeyInfo.GetValue(item); + if (keyDefaultVal.Equals(value))//主键为默认值的,新增数据 + { + //设置新增的主表的值 + mainKeyProperty.SetValue(item, + saveModel.MainData[mainKeyProperty.Name] + .ChangeType(mainKeyProperty.PropertyType)); + + if (detailKeyInfo.PropertyType == typeof(Guid)) + { + detailKeyInfo.SetValue(item, Guid.NewGuid()); + } + addList.Add(item); + } + else //if (detailKeys.Contains(value)) + { + //containsKeys.Add(value); + editList.Add(item); + } + } + + //获取需要删除的对象的主键 + if (saveModel.DelKeys != null && saveModel.DelKeys.Count > 0) + { + //2021.08.21优化明细表删除 + delKeys = saveModel.DelKeys.Select(q => q.ChangeType(detailKeyInfo.PropertyType)).Where(x => x != null).ToList(); + //.Where(x => detailKeys.Contains(x.ChangeType(detailKeyInfo.PropertyType))) + //.Select(q => q.ChangeType(detailKeyInfo.PropertyType)).ToList(); + } + + if (UpdateOnExecuting != null) + { + Response = UpdateOnExecuting(mainEnity, addList, editList, delKeys); + if (CheckResponseResult()) + return Response; + } + mainEnity.SetModifyDefaultVal(); + //主表修改 + //不修改!CreateFields.Contains创建人信息 + repository.Update(mainEnity, typeof(T).GetEditField() + .Where(c => saveModel.MainData.Keys.Contains(c) && !CreateFields.Contains(c)) + .ToArray()); + //foreach (var item in saveModel.DetailData) + //{ + // item.SetModifyDefaultVal(); + //} + //明细修改 + editList.ForEach(x => + { + //获取编辑的字段 + var updateField = saveModel.DetailData + .Where(c => c[detailKeyInfo.Name].ChangeType(detailKeyInfo.PropertyType) + .Equal(detailKeyInfo.GetValue(x))) + .FirstOrDefault() + .Keys.Where(k => k != detailKeyInfo.Name) + .Where(r => !CreateFields.Contains(r)) + .ToList(); + updateField.AddRange(ModifyFields); + //設置默認值 + x.SetModifyDefaultVal(); + //添加修改字段 + repository.Update(x, updateField.ToArray()); + }); + + //明细新增 + addList.ForEach(x => + { + x.SetCreateDefaultVal(); + repository.DbContext.Entry(x).State = EntityState.Added; + }); + //明细删除 + delKeys.ForEach(x => + { + DetailT delT = Activator.CreateInstance(); + detailKeyInfo.SetValue(delT, x); + repository.DbContext.Entry(delT).State = EntityState.Deleted; + }); + + if (UpdateOnExecuted == null) + { + repository.DbContext.SaveChanges(); + Response.OK(ResponseType.SaveSuccess); + } + else + { + Response = repository.DbContextBeginTransaction(() => + { + repository.DbContext.SaveChanges(); + Response = UpdateOnExecuted(mainEnity, addList, editList, delKeys); + return Response; + }); + } + if (Response.Status) + { + addList.AddRange(editList); + Response.Data = new { data = mainEnity, list = addList }; + if (string.IsNullOrEmpty(Response.Message)) + Response.OK(ResponseType.SaveSuccess); + } + return Response; + } + + /// + /// 获取配置的创建人ID创建时间创建人,修改人ID修改时间、修改人与数据相同的字段 + /// + private static string[] _userIgnoreFields { get; set; } + + private static string[] UserIgnoreFields + { + get + { + if (_userIgnoreFields != null) return _userIgnoreFields; + List fields = new List(); + fields.AddRange(CreateFields); + fields.AddRange(ModifyFields); + _userIgnoreFields = fields.ToArray(); + return _userIgnoreFields; + } + } + private static string[] _createFields { get; set; } + private static string[] CreateFields + { + get + { + if (_createFields != null) return _createFields; + _createFields = AppSetting.CreateMember.GetType().GetProperties() + .Select(x => x.GetValue(AppSetting.CreateMember)?.ToString()) + .Where(w => !string.IsNullOrEmpty(w)).ToArray(); + return _createFields; + } + } + + private static string[] _modifyFields { get; set; } + private static string[] ModifyFields + { + get + { + if (_modifyFields != null) return _modifyFields; + _modifyFields = AppSetting.ModifyMember.GetType().GetProperties() + .Select(x => x.GetValue(AppSetting.ModifyMember)?.ToString()) + .Where(w => !string.IsNullOrEmpty(w)).ToArray(); + return _modifyFields; + } + } + + /// + /// 编辑 + /// 1、明细表必须把主表的主键字段也设置为可编辑 + /// 2、修改、增加只会操作设置为编辑列的数据 + /// + /// + /// + public virtual WebResponseContent Update(SaveModel saveModel) + { + if (UpdateOnExecute != null) + { + Response = UpdateOnExecute(saveModel); + if (CheckResponseResult()) return Response; + } + if (saveModel == null) + return Response.Error(ResponseType.ParametersLack); + + + //if (WorkFlowManager.Exists()) + //{ + // var auditProperty = TProperties.Where(x => x.Name.ToLower() == "auditstatus").FirstOrDefault(); + // string value = saveModel.MainData[auditProperty.Name]?.ToString(); + // if (WorkFlowManager.GetAuditStatus(value) != 1) + // { + // return Response.Error("数据已经在审核中,不能修改"); + // } + //} + Type type = typeof(T); + + //设置修改时间,修改人的默认值 + UserInfo userInfo = UserContext.Current.UserInfo; + saveModel.SetDefaultVal(AppSetting.ModifyMember, userInfo); + + + //判断提交的数据与实体格式是否一致 + string result = type.ValidateDicInEntity(saveModel.MainData, true, false, UserIgnoreFields); + if (result != string.Empty) + return Response.Error(result); + + PropertyInfo mainKeyProperty = type.GetKeyProperty(); + //验证明细 + Type detailType = null; + if (saveModel.DetailData != null || saveModel.DelKeys != null) + { + saveModel.DetailData = saveModel.DetailData == null + ? new List>() + : saveModel.DetailData.Where(x => x.Count > 0).ToList(); + + detailType = GetRealDetailType(); + + result = detailType.ValidateDicInEntity(saveModel.DetailData, true, false, new string[] { mainKeyProperty.Name }); + if (result != string.Empty) return Response.Error(result); + + //主从关系指定外键,即从表的外键可以不是主键的主表,还需要改下代码生成器设置属性外键,功能预留后面再开发(2020.04.25) + //string foreignKey = type.GetTypeCustomValue(x => new { x.Name }); + //if (!string.IsNullOrEmpty(foreignKey)) + //{ + // var _mainKeyProperty = detailType.GetProperties().Where(x => x.Name.ToLower() == foreignKey.ToLower()).FirstOrDefault(); + // if (_mainKeyProperty != null) + // { + // mainKeyProperty = _mainKeyProperty; + // } + //} + } + + //获取主建类型的默认值用于判断后面数据是否正确,int long默认值为0,guid :0000-000.... + object keyDefaultVal = mainKeyProperty.PropertyType.Assembly.CreateInstance(mainKeyProperty.PropertyType.FullName);//.ToString(); + //判断是否包含主键 + if (mainKeyProperty == null + || !saveModel.MainData.ContainsKey(mainKeyProperty.Name) + || saveModel.MainData[mainKeyProperty.Name] == null + ) + { + return Response.Error(ResponseType.NoKey); + } + + object mainKeyVal = saveModel.MainData[mainKeyProperty.Name]; + //判断主键类型是否正确 + (bool, string, object) validation = mainKeyProperty.ValidationValueForDbType(mainKeyVal).FirstOrDefault(); + if (!validation.Item1) + return Response.Error(ResponseType.KeyError); + + object valueType = mainKeyVal.ToString().ChangeType(mainKeyProperty.PropertyType); + //判断主键值是不是当前类型的默认值 + if (valueType == null || + (!valueType.GetType().Equals(mainKeyProperty.PropertyType) + || valueType.ToString() == keyDefaultVal.ToString() + )) + return Response.Error(ResponseType.KeyError); + + if (saveModel.MainData.Count <= 1) return Response.Error("系统没有配置好编辑的数据,请检查model!"); + + // 2020.08.15添加多租户数据过滤(编辑) + if (IsMultiTenancy && !UserContext.Current.IsSuperAdmin) + { + CheckUpdateMultiTenancy(mainKeyProperty.PropertyType == typeof(Guid) ? "'" + mainKeyVal.ToString() + "'" : mainKeyVal.ToString(), mainKeyProperty.Name); + if (CheckResponseResult()) + { + return Response; + } + } + + + Expression> expression = mainKeyProperty.Name.CreateExpression(mainKeyVal.ToString(), LinqExpressionType.Equal); + if (!repository.Exists(expression)) return Response.Error("保存的数据不存在!"); + //没有明细的直接保存主表数据 + if (detailType == null) + { + saveModel.SetDefaultVal(AppSetting.ModifyMember, userInfo); + T mainEntity = saveModel.MainData.DicToEntity(); + if (UpdateOnExecuting != null) + { + Response = UpdateOnExecuting(mainEntity, null, null, null); + if (CheckResponseResult()) return Response; + } + //不修改!CreateFields.Contains创建人信息 + repository.Update(mainEntity, type.GetEditField().Where(c => saveModel.MainData.Keys.Contains(c) && !CreateFields.Contains(c)).ToArray()); + if (base.UpdateOnExecuted == null) + { + repository.SaveChanges(); + Response.OK(ResponseType.SaveSuccess); + } + else + { + Response = repository.DbContextBeginTransaction(() => + { + repository.SaveChanges(); + Response = UpdateOnExecuted(mainEntity, null, null, null); + return Response; + }); + } + if (Response.Status) Response.Data = new { data = mainEntity }; + if (Response.Status && string.IsNullOrEmpty(Response.Message)) + Response.OK(ResponseType.SaveSuccess); + return Response; + } + + saveModel.DetailData = saveModel.DetailData.Where(x => x.Count > 0).ToList(); + + //明细操作 + PropertyInfo detailKeyInfo = detailType.GetKeyProperty(); + //主键类型 + // string detailKeyType = mainKeyProperty.GetTypeCustomValue(c => new { c.TypeName }); + //判断明细是否包含了主表的主键 + + string deatilDefaultVal = detailKeyInfo.PropertyType.Assembly.CreateInstance(detailKeyInfo.PropertyType.FullName).ToString(); + foreach (Dictionary dic in saveModel.DetailData) + { + //不包含主键的默认添加主键默认值,用于后面判断是否为新增数据 + if (!dic.ContainsKey(detailKeyInfo.Name)) + { + dic.Add(detailKeyInfo.Name, keyDefaultVal); + if (dic.ContainsKey(mainKeyProperty.Name)) + { + dic[mainKeyProperty.Name] = keyDefaultVal; + } + else + { + dic.Add(mainKeyProperty.Name, keyDefaultVal); + } + continue; + } + if (dic[detailKeyInfo.Name] == null) + return Response.Error(ResponseType.NoKey); + + //主键值是否正确 + string detailKeyVal = dic[detailKeyInfo.Name].ToString(); + if (!detailKeyInfo.ValidationValueForDbType(detailKeyVal).FirstOrDefault().Item1 + || deatilDefaultVal == detailKeyVal) + return Response.Error(ResponseType.KeyError); + + //判断主表的值是否正确 + if (detailKeyVal != keyDefaultVal.ToString() && (!dic.ContainsKey(mainKeyProperty.Name) || dic[mainKeyProperty.Name] == null || dic[mainKeyProperty.Name].ToString() == keyDefaultVal.ToString())) + { + return Response.Error(mainKeyProperty.Name + "是必填项!"); + } + } + + if (saveModel.DetailData.Exists(c => c.Count <= 2)) + return Response.Error("系统没有配置好明细编辑的数据,请检查model!"); + return this.GetType().GetMethod("UpdateToEntity") + .MakeGenericMethod(new Type[] { detailType }) + .Invoke(this, new object[] { saveModel, mainKeyProperty, detailKeyInfo, keyDefaultVal }) + as WebResponseContent; + } + + #endregion + + /// + /// + /// + /// + /// 是否删除明细数据(默认会删除明细) + /// + public virtual WebResponseContent Del(object[] keys, bool delList = true) + { + Type entityType = typeof(T); + var keyProperty = entityType.GetKeyProperty(); + if (keyProperty == null || keys == null || keys.Length == 0) return Response.Error(ResponseType.NoKeyDel); + + IEnumerable<(bool, string, object)> validation = keyProperty.ValidationValueForDbType(keys); + if (validation.Any(x => !x.Item1)) + { + return Response.Error(validation.Where(x => !x.Item1).Select(s => s.Item2 + "
").Serialize()); + } + string tKey = keyProperty.Name; + if (string.IsNullOrEmpty(tKey)) + return Response.Error("没有主键不能删除"); + + if (DelOnExecuting != null) + { + Response = DelOnExecuting(keys); + if (CheckResponseResult()) return Response; + } + + FieldType fieldType = entityType.GetFieldType(); + string joinKeys = (fieldType == FieldType.Int || fieldType == FieldType.BigInt) + ? string.Join(",", keys) + : $"'{string.Join("','", keys)}'"; + + // 2020.08.15添加判断多租户数据(删除) + if (IsMultiTenancy && !UserContext.Current.IsSuperAdmin) + { + CheckDelMultiTenancy(joinKeys, tKey); + if (CheckResponseResult()) + { + return Response; + } + } + + string sql = $"DELETE FROM {entityType.GetEntityTableName() } where {tKey} in ({joinKeys});"; + // 2020.08.06增加pgsql删除功能 + if (DBType.Name == DbCurrentType.PgSql.ToString()) + { + sql = $"DELETE FROM \"public\".\"{entityType.GetEntityTableName() }\" where \"{tKey}\" in ({joinKeys});"; + } + if (delList) + { + Type detailType = GetRealDetailType(); + if (detailType != null) + { + if (DBType.Name == DbCurrentType.PgSql.ToString()) + { + sql += $"DELETE FROM \"public\".\"{detailType.GetEntityTableName()}\" where \"{tKey}\" in ({joinKeys});"; + } + else + { + sql += $"DELETE FROM {detailType.GetEntityTableName()} where {tKey} in ({joinKeys});"; + } + } + + } + + //repository.DapperContext.ExcuteNonQuery(sql, CommandType.Text, null, true); + + //可能在删除后还要做一些其它数据库新增或删除操作,这样就可能需要与删除保持在同一个事务中处理 + //采用此方法 repository.DbContextBeginTransaction(()=>{//do delete......and other}); + //做的其他操作,在DelOnExecuted中加入委托实现 + Response = repository.DbContextBeginTransaction(() => + { + repository.ExecuteSqlCommand(sql); + if (DelOnExecuted != null) + { + Response = DelOnExecuted(keys); + } + return Response; + }); + if (Response.Status && string.IsNullOrEmpty(Response.Message)) Response.OK(ResponseType.DelSuccess); + return Response; + } + + private static string[] auditFields = new string[] { "auditid", "auditstatus", "auditor", "auditdate", "auditreason" }; + + /// + /// 审核默认对应数据库字段为AuditId审核人ID ,AuditStatus审核状态,Auditor审核人,Auditdate审核时间,Auditreason审核原因 + /// + /// + /// + /// + /// + public virtual WebResponseContent Audit(object[] keys, int? auditStatus, string auditReason) + { + if (keys == null || keys.Length == 0) + return Response.Error("未获取到参数!"); + + Expression> whereExpression = typeof(T).GetKeyName().CreateExpression(keys[0], LinqExpressionType.Equal); + T entity = repository.FindAsIQueryable(whereExpression).FirstOrDefault(); + + //进入流程审批 + if (WorkFlowManager.Exists(entity)) + { + var auditProperty = TProperties.Where(x => x.Name.ToLower() == "auditstatus").FirstOrDefault(); + if (auditProperty == null) + { + return Response.Error("表缺少审核状态字段:AuditStatus"); + } + + AuditStatus status = (AuditStatus)Enum.Parse(typeof(AuditStatus), auditStatus.ToString()); + if (auditProperty.GetValue(entity).GetInt() != (int)AuditStatus.审核中) + { + return Response.Error("只能审批审核中的数据"); + } + Response = repository.DbContextBeginTransaction(() => + { + return WorkFlowManager.Audit(entity, status, auditReason, auditProperty, AuditWorkFlowExecuting, AuditWorkFlowExecuted); + }); + if (Response.Status) + { + return Response.OK(ResponseType.AuditSuccess); + } + return Response.Error(Response.Message ?? "审批失败"); + } + + + //获取主键 + PropertyInfo property = TProperties.GetKeyProperty(); + if (property == null) + return Response.Error("没有配置好主键!"); + + UserInfo userInfo = UserContext.Current.UserInfo; + + //表如果有审核相关字段,设置默认审核 + + PropertyInfo[] updateFileds = TProperties.Where(x => auditFields.Contains(x.Name.ToLower())).ToArray(); + List auditList = new List(); + foreach (var value in keys) + { + object convertVal = value.ToString().ChangeType(property.PropertyType); + if (convertVal == null) continue; + + entity = Activator.CreateInstance(); + property.SetValue(entity, convertVal); + foreach (var item in updateFileds) + { + switch (item.Name.ToLower()) + { + case "auditid": + item.SetValue(entity, userInfo.User_Id); + break; + case "auditstatus": + item.SetValue(entity, auditStatus); + break; + case "auditor": + item.SetValue(entity, userInfo.UserTrueName); + break; + case "auditdate": + item.SetValue(entity, DateTime.Now); + break; + case "auditreason": + item.SetValue(entity, auditReason); + break; + } + } + auditList.Add(entity); + } + if (base.AuditOnExecuting != null) + { + Response = AuditOnExecuting(auditList); + if (CheckResponseResult()) return Response; + } + Response = repository.DbContextBeginTransaction(() => + { + repository.UpdateRange(auditList, updateFileds.Select(x => x.Name).ToArray(), true); + if (base.AuditOnExecuted != null) + { + Response = AuditOnExecuted(auditList); + if (CheckResponseResult()) return Response; + } + return Response.OK(); + }); + if (Response.Status) + { + return Response.OK(ResponseType.AuditSuccess); + } + return Response.Error(Response.Message); + } + + public virtual (string, T, bool) ApiValidate(string bizContent, Expression> expression = null) + { + return ApiValidateInput(bizContent, expression); + } + + /// + /// 对指定类与api的参数进行验证 + /// + /// + /// + /// + /// 对指属性验证 + /// (string,TInput, bool) string:返回验证消息,TInput:bizContent序列化后的对象,bool:验证是否通过 + public virtual (string, TInput, bool) ApiValidateInput(string bizContent, Expression> expression) + { + return ApiValidateInput(bizContent, expression, null); + } + + /// + /// + /// + /// + /// + /// 对指属性验证格式如:x=>new { x.UserName,x.Value } + /// 对指定的字段只做合法性判断比如长度是是否超长 + /// (string,TInput, bool) string:返回验证消息,TInput:bizContent序列化后的对象,bool:验证是否通过 + public virtual (string, TInput, bool) ApiValidateInput(string bizContent, Expression> expression, Expression> validateExpression) + { + try + { + TInput input = JsonConvert.DeserializeObject(bizContent); + if (!(input is System.Collections.IList)) + { + Response = input.ValidationEntity(expression, validateExpression); + return (Response.Message, input, Response.Status); + } + System.Collections.IList list = input as System.Collections.IList; + for (int i = 0; i < list.Count; i++) + { + Response = list[i].ValidationEntity(expression?.GetExpressionProperty(), + validateExpression?.GetExpressionProperty()); + if (CheckResponseResult()) + return (Response.Message, default(TInput), false); + } + return ("", input, true); + } + catch (Exception ex) + { + Response.Status = false; + Response.Message = ApiMessage.ParameterError; + Logger.Error(LoggerType.HandleError, bizContent, null, ex.Message); + } + return (Response.Message, default(TInput), Response.Status); + } + + /// + /// 将数据源映射到新的数据中,目前只支持List映射到List或TSource映射到TResult + /// 目前只支持Dictionary或实体类型 + /// + /// + /// + /// + /// 只映射返回对象的指定字段 + /// 只映射数据源对象的指定字段 + /// 过滤条件表达式调用方式:List表达式x => new { x[0].MenuName, x[0].Menu_Id},表示指定映射MenuName,Menu_Id字段 + /// List list = new List(); + /// list.MapToObject, List>(x => new { x[0].MenuName, x[0].Menu_Id}, null); + /// + ///过滤条件表达式调用方式:实体表达式x => new { x.MenuName, x.Menu_Id},表示指定映射MenuName,Menu_Id字段 + /// Sys_Menu sysMenu = new Sys_Menu(); + /// sysMenu.MapToObject(x => new { x.MenuName, x.Menu_Id}, null); + /// + public virtual TResult MapToEntity(TSource source, Expression> resultExpression, + Expression> sourceExpression = null) where TResult : class + { + return source.MapToObject(resultExpression, sourceExpression); + } + + /// + /// 将一个实体的赋到另一个实体上,应用场景: + /// 两个实体,a a1= new a();b b1= new b(); a1.P=b1.P; a1.Name=b1.Name; + /// + /// + /// + /// + /// + /// 指定对需要的字段赋值,格式x=>new {x.Name,x.P},返回的结果只会对Name与P赋值 + public virtual void MapValueToEntity(TSource source, TResult result, Expression> expression = null) where TResult : class + { + source.MapValueToEntity(result, expression); + } + /// + /// 2021.07.04增加code="-1"强制返回,具体使用见:后台开发文档->后台基础代码扩展实现 + /// + /// + private bool CheckResponseResult() + { + return !Response.Status || Response.Code == "-1"; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/CacheManager/IService/ICacheService.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/CacheManager/IService/ICacheService.cs new file mode 100644 index 0000000000000000000000000000000000000000..c868e76ee31fb67c40b568af06cabcc9399233b8 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/CacheManager/IService/ICacheService.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace VOL.Core.CacheManager +{ + public interface ICacheService : IDisposable + { + /// + /// 验证缓存项是否存在 + /// + /// 缓存Key + /// + bool Exists(string key); + + + + /// + /// List写入head + /// + /// + /// + void LPush(string key, string val); + + void RPush(string key, string val); + /// + /// List出队 lpop + /// + /// + /// + object ListDequeue(string key); + + /// + /// List出队 lpop + /// + /// + /// + T ListDequeue(string key) where T : class; + + /// + /// 移除list中的数据,keepIndex为保留的位置到最后一个元素如list 元素为1.2.3.....100 + /// 需要移除前3个数,keepindex应该为4 + /// + /// + /// + void ListRemove(string key, int keepIndex); + + /// + /// 添加缓存 + /// + /// 缓存Key + /// 缓存Value + /// 缓存时长 + /// 是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间) //new TimeSpan(0, 60, 0); + /// + bool AddObject(string key, object value, int expireSeconds = -1, bool isSliding = false); + + bool Add(string key, string value, int expireSeconds = -1, bool isSliding = false); + + /// + /// 删除缓存 + /// + /// 缓存Key + /// + bool Remove(string key); + + + /// + /// 批量删除缓存 + /// + /// 缓存Key集合 + /// + void RemoveAll(IEnumerable keys); + + + + + /// + /// 获取缓存 + /// + /// 缓存Key + /// + T Get(string key) where T : class; + + + + /// + /// 获取缓存 + /// + /// 缓存Key + /// + string Get(string key); + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/CacheManager/Service/MemoryCacheService .cs b/Pure_Vite_Net7/WebNet7/VOL.Core/CacheManager/Service/MemoryCacheService .cs new file mode 100644 index 0000000000000000000000000000000000000000..b3a673262669a47e447e576538ddd3f2d31b80a8 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/CacheManager/Service/MemoryCacheService .cs @@ -0,0 +1,189 @@ + +using Microsoft.Extensions.Caching.Memory; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace VOL.Core.CacheManager +{ + public class MemoryCacheService : ICacheService + { + protected IMemoryCache _cache; + public MemoryCacheService(IMemoryCache cache) + { + _cache = cache; + + } + /// + /// 验证缓存项是否存在 + /// + /// 缓存Key + /// + public bool Exists(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + return _cache.Get(key) != null; + } + + /// + /// 添加缓存 + /// + /// 缓存Key + /// 缓存Value + /// + public bool Add(string key, object value) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + _cache.Set(key, value); + return Exists(key); + } + + public bool AddObject(string key, object value, int expireSeconds = -1, bool isSliding = false) + { + if (expireSeconds != -1) + { + _cache.Set(key, + value, + new MemoryCacheEntryOptions() + .SetSlidingExpiration(new TimeSpan(0, 0, expireSeconds)) + ); + } + else + { + _cache.Set(key, value); + } + + return true; + } + public bool Add(string key, string value, int expireSeconds = -1, bool isSliding = false) + { + return AddObject(key, value, expireSeconds, isSliding); + } + public void LPush(string key, string val) + { + } + public void RPush(string key, string val) + { + } + public T ListDequeue(string key) where T : class + { + return null; + } + public object ListDequeue(string key) + { + return null; + } + public void ListRemove(string key, int keepIndex) + { + } + /// + /// 添加缓存 + /// + /// 缓存Key + /// 缓存Value + /// 滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间) + /// 绝对过期时长 + /// + public bool Add(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte) + { + _cache.Set(key, value, + new MemoryCacheEntryOptions() + .SetSlidingExpiration(expiresSliding) + .SetAbsoluteExpiration(expiressAbsoulte) + ); + + return Exists(key); + } + /// + /// 添加缓存 + /// + /// 缓存Key + /// 缓存Value + /// 缓存时长 + /// 是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间) + /// + public bool Add(string key, object value, TimeSpan expiresIn, bool isSliding = false) + { + if (isSliding) + _cache.Set(key, value, + new MemoryCacheEntryOptions() + .SetSlidingExpiration(expiresIn) + ); + else + _cache.Set(key, value, + new MemoryCacheEntryOptions() + .SetAbsoluteExpiration(expiresIn) + ); + + return Exists(key); + } + + + + /// + /// 删除缓存 + /// + /// 缓存Key + /// + public bool Remove(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + _cache.Remove(key); + + return !Exists(key); + } + /// + /// 批量删除缓存 + /// + /// 缓存Key集合 + /// + public void RemoveAll(IEnumerable keys) + { + if (keys == null) + { + throw new ArgumentNullException(nameof(keys)); + } + + keys.ToList().ForEach(item => _cache.Remove(item)); + } + public string Get(string key) + { + return _cache.Get(key)?.ToString(); + } + /// + /// 获取缓存 + /// + /// 缓存Key + /// + public T Get(string key) where T : class + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + return _cache.Get(key) as T; + } + + public void Dispose() + { + if (_cache != null) + _cache.Dispose(); + GC.SuppressFinalize(this); + } + + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/CacheManager/Service/RedisCacheService.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/CacheManager/Service/RedisCacheService.cs new file mode 100644 index 0000000000000000000000000000000000000000..163175c0954ef07abc058e11a3699f717e06af96 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/CacheManager/Service/RedisCacheService.cs @@ -0,0 +1,119 @@ +using CSRedis; +using Newtonsoft.Json; +using StackExchange.Redis; +using System; +using System.Collections.Generic; +using System.Linq; +using VOL.Core.Configuration; +using VOL.Core.Const; + +namespace VOL.Core.CacheManager +{ + public class RedisCacheService : ICacheService + { + public RedisCacheService() + { + var csredis = new CSRedisClient(AppSetting.RedisConnectionString); + RedisHelper.Initialization(csredis); + } + + /// + /// 验证缓存项是否存在 + /// + /// 缓存Key + /// + public bool Exists(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + return RedisHelper.Exists(key); + } + + public void LPush(string key, string val) + { + RedisHelper.LPush(key, val); + } + + public void RPush(string key, string val) + { + RedisHelper.RPush(key, val); + } + + public T ListDequeue(string key) where T : class + { + string value = RedisHelper.RPop(key); + if (string.IsNullOrEmpty(value)) + return null; + return JsonConvert.DeserializeObject(value); + } + public object ListDequeue(string key) + { + string value = RedisHelper.RPop(key); + if (string.IsNullOrEmpty(value)) + return null; + return value; + } + + /// + /// 移除list中的数据,keepIndex为保留的位置到最后一个元素如list 元素为1.2.3.....100 + /// 需要移除前3个数,keepindex应该为4 + /// + /// + /// + public void ListRemove(string key, int keepIndex) + { + RedisHelper.LTrim(key, keepIndex, -1); + } + public bool Add(string key, string value, int expireSeconds = -1, bool isSliding = false) + { + return RedisHelper.Set(key, value, expireSeconds); + } + public bool AddObject(string key, object value, int expireSeconds = -1, bool isSliding = false) + { + return RedisHelper.Set(key, value, expireSeconds); + } + + /// + /// 删除缓存 + /// + /// 缓存Key + /// + public bool Remove(string key) + { + RedisHelper.Del(key); + return true; + } + /// + /// 批量删除缓存 + /// + /// 缓存Key集合 + /// + public void RemoveAll(IEnumerable keys) + { + RedisHelper.Del(keys.ToArray()); + } + /// + /// 获取缓存 + /// + /// 缓存Key + /// + public T Get(string key) where T : class + { + return RedisHelper.Get(key); + } + /// + /// 获取缓存 + /// + /// 缓存Key + /// + public string Get(string key) + { + return RedisHelper.Get(key); + } + public void Dispose() + { + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Configuration/AppSetting.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Configuration/AppSetting.cs new file mode 100644 index 0000000000000000000000000000000000000000..9f3142c4e0a036996d8f55c6648aa0f2ed124dad --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Configuration/AppSetting.cs @@ -0,0 +1,183 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using System.IO; +using VOL.Core.Const; +using VOL.Core.Extensions; + +namespace VOL.Core.Configuration +{ + public static class AppSetting + { + public static IConfiguration Configuration { get; private set; } + + public static string DbConnectionString + { + get { return _connection.DbConnectionString; } + } + + public static string RedisConnectionString + { + get { return _connection.RedisConnectionString; } + } + + public static bool UseRedis + { + get { return _connection.UseRedis; } + } + public static bool UseSignalR + { + get { return _connection.UseSignalR; } + } + public static Secret Secret { get; private set; } + + public static CreateMember CreateMember { get; private set; } + + public static ModifyMember ModifyMember { get; private set; } + + private static Connection _connection; + + public static string TokenHeaderName = "Authorization"; + + /// + /// Actions权限过滤 + /// + public static GlobalFilter GlobalFilter { get; set; } + + /// + /// kafka配置 + /// + public static Kafka Kafka { get; set; } + + + /// + /// JWT有效期(分钟=默认120) + /// + public static int ExpMinutes { get; private set; } = 120; + + public static string CurrentPath { get; private set; } = null; + public static string DownLoadPath { get { return CurrentPath + "\\Download\\"; } } + public static void Init(IServiceCollection services, IConfiguration configuration) + { + Configuration = configuration; + services.Configure(configuration.GetSection("Secret")); + services.Configure(configuration.GetSection("Connection")); + services.Configure(configuration.GetSection("CreateMember")); + services.Configure(configuration.GetSection("ModifyMember")); + services.Configure(configuration.GetSection("GlobalFilter")); + services.Configure(configuration.GetSection("Kafka")); + + var provider = services.BuildServiceProvider(); + IWebHostEnvironment environment = provider.GetRequiredService(); + CurrentPath = Path.Combine(environment.ContentRootPath, "").ReplacePath(); + + Secret = provider.GetRequiredService>().Value; + + //设置修改或删除时需要设置为默认用户信息的字段 + CreateMember = provider.GetRequiredService>().Value ?? new CreateMember(); + ModifyMember = provider.GetRequiredService>().Value ?? new ModifyMember(); + + GlobalFilter = provider.GetRequiredService>().Value ?? new GlobalFilter(); + + GlobalFilter.Actions = GlobalFilter.Actions ?? new string[0]; + Kafka = provider.GetRequiredService>().Value ?? new Kafka(); + + _connection = provider.GetRequiredService>().Value; + + + + ExpMinutes = (configuration["ExpMinutes"] ?? "120").GetInt(); + + DBType.Name = _connection.DBType; + if (string.IsNullOrEmpty(_connection.DbConnectionString)) + throw new System.Exception("未配置好数据库默认连接"); + + try + { + _connection.DbConnectionString = _connection.DbConnectionString.DecryptDES(Secret.DB); + } + catch { } + + if (!string.IsNullOrEmpty(_connection.RedisConnectionString)) + { + try + { + _connection.RedisConnectionString = _connection.RedisConnectionString.DecryptDES(Secret.Redis); + } + catch { } + } + + } + // 多个节点name格式 :["key:key1"] + public static string GetSettingString(string key) + { + return Configuration[key]; + } + // 多个节点,通过.GetSection("key")["key1"]获取 + public static IConfigurationSection GetSection(string key) + { + return Configuration.GetSection(key); + } + } + + public class Connection + { + public string DBType { get; set; } + public string DbConnectionString { get; set; } + public string RedisConnectionString { get; set; } + public bool UseRedis { get; set; } + public bool UseSignalR { get; set; } + } + + public class CreateMember: TableDefaultColumns + { + } + public class ModifyMember: TableDefaultColumns + { + } + + public abstract class TableDefaultColumns + { + public string UserIdField { get; set; } + public string UserNameField { get; set; } + public string DateField { get; set; } + } + public class GlobalFilter + { + public string Message { get; set; } + public bool Enable { get; set; } + public string[] Actions { get; set; } + } + + public class Kafka + { + public bool UseProducer { get; set; } + public ProducerSettings ProducerSettings { get; set; } + public bool UseConsumer { get; set; } + public bool IsConsumerSubscribe { get; set; } + public ConsumerSettings ConsumerSettings { get; set; } + public Topics Topics { get; set; } + } + public class ProducerSettings + { + public string BootstrapServers { get; set; } + public string SaslMechanism { get; set; } + public string SecurityProtocol { get; set; } + public string SaslUsername { get; set; } + public string SaslPassword { get; set; } + } + public class ConsumerSettings + { + public string BootstrapServers { get; set; } + public string SaslMechanism { get; set; } + public string SecurityProtocol { get; set; } + public string SaslUsername { get; set; } + public string SaslPassword { get; set; } + public string GroupId { get; set; } + } + public class Topics + { + public string TestTopic { get; set; } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Const/ApplicationContentType.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Const/ApplicationContentType.cs new file mode 100644 index 0000000000000000000000000000000000000000..512ec8e7a5ff8205488aa6a96ea2228a926dfcc2 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Const/ApplicationContentType.cs @@ -0,0 +1,11 @@ +namespace VOL.Core.Const +{ + public class ApplicationContentType + { + public const string FORM = "application/x-www-form-urlencoded; charset=utf-8"; + public const string STREAM = "application/octet-stream; charset=utf-8"; + public const string JSON = "application/json; charset=utf-8"; + public const string XML = "application/xml; charset=utf-8"; + public const string TEXT = "application/text; charset=utf-8"; + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Const/DataBaseType.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Const/DataBaseType.cs new file mode 100644 index 0000000000000000000000000000000000000000..68f9062ce2280830ce8460b2bf09455a7702a4a1 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Const/DataBaseType.cs @@ -0,0 +1,7 @@ +namespace VOL.Core.Const +{ + public static class DBType + { + public static string Name { get; set; } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Const/HtmlElementType.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Const/HtmlElementType.cs new file mode 100644 index 0000000000000000000000000000000000000000..ce298d8bb2a2a229d662550c7bc9798b3efeca19 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Const/HtmlElementType.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.Const +{ + public struct HtmlElementType + { + public const string drop = "drop"; + public const string droplist = "droplist"; + public const string select = "select"; + public const string selectlist = "selectlist"; + public const string checkbox = "checkbox"; + public const string textarea = "textarea"; + public const string thanorequal = "thanorequal"; + public const string lessorequal = "lessorequal"; + + + public const string gt = "gt"; + public const string lt = "lt"; + public const string GT = ">"; + public const string LT = "<"; + public const string like = "like"; + + public const string ThanOrEqual = ">="; + public const string LessOrequal = "<="; + public const string Contains = "in"; + public const string Equal = "="; + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Const/Secret.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Const/Secret.cs new file mode 100644 index 0000000000000000000000000000000000000000..3f424f257fbb5a29445e93c34ec075352bd9042b --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Const/Secret.cs @@ -0,0 +1,36 @@ +namespace VOL.Core.Const +{ + /// + /// 加密对应密钥Key + /// + public class Secret + { + /// + /// 用户密码加密key + /// + public string User { get; set; } + /// + /// 数据库加密key + /// + public string DB { get; set; } + + /// + /// redis加密key + /// + public string Redis { get; set; } + + /// + /// jwt加密key + /// + public string JWT { get; set; } + + public string Audience { get; set; } + public string Issuer { get; set; } + + /// + /// 导出文件加密key + /// + public string ExportFile = "C5ABA9E202D94C13A3CB66002BF77FAF"; + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Const/SqlDbTypeName.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Const/SqlDbTypeName.cs new file mode 100644 index 0000000000000000000000000000000000000000..cf269ecb3626c50146eaccef7effec15a5422a65 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Const/SqlDbTypeName.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.Const +{ + public struct SqlDbTypeName + { + public const string NVarChar = "nvarchar"; + public const string VarChar = "varchar"; + public const string NChar = "nchar"; + public const string Char = "char"; + public const string Text = "text"; + public const string Int = "int"; + public const string BigInt = "bigint"; + public const string DateTime = "datetime"; + public const string Date = "date"; + public const string SmallDateTime = "smalldatetime"; + public const string SmallDate = "smalldate"; + public const string Float = "float"; + public const string Decimal = "decimal"; + public const string Double = "double"; + public const string Bit = "bit"; + public const string Bool = "bool"; + public const string UniqueIdentifier = "uniqueidentifier"; + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Controllers/Basic/ApiBaseController.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Controllers/Basic/ApiBaseController.cs new file mode 100644 index 0000000000000000000000000000000000000000..adec0941f38709ded1e1b6809418264ed0fd20c0 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Controllers/Basic/ApiBaseController.cs @@ -0,0 +1,247 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using VOL.Core.Configuration; +using VOL.Core.Extensions; +using VOL.Core.Filters; +using VOL.Core.Services; +using VOL.Core.Utilities; +using VOL.Entity.DomainModels; + +namespace VOL.Core.Controllers.Basic +{ + [JWTAuthorize, ApiController] + public class ApiBaseController : Controller + { + protected IServiceBase Service; + private WebResponseContent _baseWebResponseContent { get; set; } + public ApiBaseController() + { + } + public ApiBaseController(IServiceBase service) + { + Service = service; + } + public ApiBaseController(string projectName, string folder, string tablename, IServiceBase service) + { + Service = service; + } + /// + /// 2020.11.21增加json原格式返回数据(默认是驼峰格式) + /// + /// + /// + /// + protected JsonResult JsonNormal(object data, JsonSerializerSettings serializerSettings = null, bool formateDate = true) + { + serializerSettings = serializerSettings ?? new JsonSerializerSettings(); + serializerSettings.ContractResolver = null; + if (formateDate) + { + serializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss"; + } + return Json(data, serializerSettings); + } + + [ApiActionPermission(Enums.ActionPermissionOptions.Search)] + [HttpPost, Route("GetPageData")] + public virtual ActionResult GetPageData([FromBody] PageDataOptions loadData) + { + return JsonNormal(InvokeService("GetPageData", new object[] { loadData })); + } + + /// + /// 获取明细grid分页数据 + /// + /// + /// + [ApiActionPermission(Enums.ActionPermissionOptions.Search)] + [HttpPost, Route("GetDetailPage")] + [ApiExplorerSettings(IgnoreApi = true)] + public virtual ActionResult GetDetailPage([FromBody] PageDataOptions loadData) + { + return Content(InvokeService("GetDetailPage", new object[] { loadData }).Serialize()); + } + + /// + /// 上传文件 + /// + /// + /// + [HttpPost, Route("Upload")] + [ApiActionPermission(Enums.ActionPermissionOptions.Upload)] + [ApiExplorerSettings(IgnoreApi = true)] + public virtual IActionResult Upload(IEnumerable fileInput) + { + return Json(InvokeService("Upload", new object[] { fileInput })); + } + /// + /// 下载导入Excel模板 + /// + /// + [HttpGet, Route("DownLoadTemplate")] + [ApiActionPermission(Enums.ActionPermissionOptions.Import)] + [ApiExplorerSettings(IgnoreApi = true)] + public virtual ActionResult DownLoadTemplate() + { + _baseWebResponseContent = InvokeService("DownLoadTemplate", new object[] { }) as WebResponseContent; + if (!_baseWebResponseContent.Status) return Json(_baseWebResponseContent); + byte[] fileBytes = System.IO.File.ReadAllBytes(_baseWebResponseContent.Data.ToString()); + return File( + fileBytes, + System.Net.Mime.MediaTypeNames.Application.Octet, + Path.GetFileName(_baseWebResponseContent.Data.ToString()) + ); + } + /// + /// 导入表数据Excel + /// + /// + /// + [HttpPost, Route("Import")] + [ApiActionPermission(Enums.ActionPermissionOptions.Import)] + [ApiExplorerSettings(IgnoreApi = true)] + public virtual ActionResult Import(List fileInput) + { + return Json(InvokeService("Import", new object[] { fileInput })); + } + + /// + /// 导出文件,返回日期+文件名 + /// + /// + /// + [ApiActionPermission(Enums.ActionPermissionOptions.Export)] + [ApiExplorerSettings(IgnoreApi = true)] + [HttpPost, Route("Export")] + public virtual ActionResult Export([FromBody] PageDataOptions loadData) + { + var result = InvokeService("Export", new object[] { loadData }) as WebResponseContent; + return File( + System.IO.File.ReadAllBytes(result.Data.ToString().MapPath()), + System.Net.Mime.MediaTypeNames.Application.Octet, + Path.GetFileName(result.Data.ToString()) + ); + } + /// + /// 2022.01.08移除原来的导出功能 + /// + /// + /// + [Obsolete] + [ApiActionPermission(Enums.ActionPermissionOptions.Export)] + [HttpGet, Route("DownLoadFile")] + [ApiExplorerSettings(IgnoreApi = true)] + public virtual IActionResult DownLoadFile() + { + throw new Exception("原导出方法已停用"); + //string path = HttpContext.Request("path"); + //if (string.IsNullOrEmpty(path)) return Content("未找到文件"); + //try + //{ + // path = path.IndexOf("/") == -1 && path.IndexOf("\\") == -1 + // ?path.DecryptDES(AppSetting.Secret.ExportFile) + // : path.MapPath(); + // return File( + // System.IO.File.ReadAllBytes(path), + // System.Net.Mime.MediaTypeNames.Application.Octet, + // Path.GetFileName(path) + // ); + //} + //catch (Exception ex) + //{ + // Logger.Error($"文件下载出错:{path}{ex.Message}"); + //} + //return Content(""); + } + + /// + /// 通过key删除文件 + /// + /// + /// + [ApiActionPermission(Enums.ActionPermissionOptions.Delete)] + [HttpPost, Route("Del")] + [ApiExplorerSettings(IgnoreApi = true)] + public virtual ActionResult Del([FromBody] object[] keys) + { + _baseWebResponseContent = InvokeService("Del", new object[] { keys, true }) as WebResponseContent; + Logger.Info(Enums.LoggerType.Del, keys.Serialize(), _baseWebResponseContent.Status ? "Ok" : _baseWebResponseContent.Message); + return Json(_baseWebResponseContent); + } + /// + /// 审核 + /// + /// + /// + [ApiActionPermission(Enums.ActionPermissionOptions.Audit)] + [HttpPost, Route("Audit")] + [ApiExplorerSettings(IgnoreApi = true)] + public virtual ActionResult Audit([FromBody] object[] id, int? auditStatus, string auditReason) + { + _baseWebResponseContent = InvokeService("Audit", new object[] { id, auditStatus, auditReason }) as WebResponseContent; + Logger.Info(Enums.LoggerType.Del, id?.Serialize() + "," + (auditStatus ?? -1) + "," + auditReason, _baseWebResponseContent.Status ? "Ok" : _baseWebResponseContent.Message); + return Json(_baseWebResponseContent); + } + /// + /// 新增支持主子表 + /// + /// + /// + [ApiActionPermission(Enums.ActionPermissionOptions.Add)] + [HttpPost, Route("Add")] + [ApiExplorerSettings(IgnoreApi = true)] + public virtual ActionResult Add([FromBody] SaveModel saveModel) + { + _baseWebResponseContent = InvokeService("Add", + new Type[] { typeof(SaveModel) }, + new object[] { saveModel }) as WebResponseContent; + Logger.Info(Enums.LoggerType.Add, saveModel.Serialize(), _baseWebResponseContent.Status ? "Ok" : _baseWebResponseContent.Message); + _baseWebResponseContent.Data = _baseWebResponseContent.Data?.Serialize(); + return Json(_baseWebResponseContent); + } + /// + /// 编辑支持主子表 + /// [ModelBinder(BinderType =(typeof(ModelBinder.BaseModelBinder)))]可指定绑定modelbinder + /// + /// + /// + [ApiActionPermission(Enums.ActionPermissionOptions.Update)] + [HttpPost, Route("Update")] + [ApiExplorerSettings(IgnoreApi = true)] + public virtual ActionResult Update([FromBody] SaveModel saveModel) + { + _baseWebResponseContent = InvokeService("Update", new object[] { saveModel }) as WebResponseContent; + Logger.Info(Enums.LoggerType.Edit, saveModel.Serialize(), _baseWebResponseContent.Status ? "Ok" : _baseWebResponseContent.Message); + _baseWebResponseContent.Data = _baseWebResponseContent.Data?.Serialize(); + return Json(_baseWebResponseContent); + } + + /// + /// 调用service方法 + /// + /// + /// + /// + private object InvokeService(string methodName, object[] parameters) + { + return Service.GetType().GetMethod(methodName).Invoke(Service, parameters); + } + /// + /// 调用service方法 + /// + /// + /// 为要调用重载的方法参数类型:new Type[] { typeof(SaveDataModel) + /// + /// + private object InvokeService(string methodName, Type[] types, object[] parameters) + { + return Service.GetType().GetMethod(methodName, types).Invoke(Service, parameters); + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Controllers/Basic/BaseController.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Controllers/Basic/BaseController.cs new file mode 100644 index 0000000000000000000000000000000000000000..1ac8909446e4066a48abf7a3da52e9181e33e1a6 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Controllers/Basic/BaseController.cs @@ -0,0 +1,186 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using VOL.Core.Configuration; +using VOL.Core.Extensions; +using VOL.Core.Services; +using VOL.Core.Utilities; +using VOL.Entity.DomainModels; + +namespace VOL.Core.Controllers.Basic +{ + public class BaseController : Controller + { + protected IServiceBase Service; + private WebResponseContent ResponseContent { get; set; } + /// + /// + /// + public BaseController() + { + + } + public BaseController(IServiceBase service) + { + Service = service; + } + public BaseController(string projectName, string folder, string tablename, IServiceBase service) + { + Service = service; + } + /// + /// + /// + /// + [ApiExplorerSettings(IgnoreApi = true)] + public virtual ActionResult Manager() + { + return View(); + //if (System.IO.File.Exists(($"Views\\PageExtension\\{projectName }\\{TableName}Extension.cshtml").MapPath())) + //{ + // ViewBag.UrlExtension = $"~/Views/PageExtension/{projectName}/{TableName}Extension.cshtml"; + //} + // return View("~/Views/" + projectName + "/" + folder + "/" + TableName + ".cshtml"); + } + [ApiExplorerSettings(IgnoreApi = true)] + public virtual async Task GetPageData(PageDataOptions loadData) + { + string pageData = await Task.FromResult(InvokeService("GetPageData", new object[] { loadData }).Serialize()); + return Content(pageData); + } + [ApiExplorerSettings(IgnoreApi = true)] + public virtual async Task GetDetailPage(PageDataOptions loadData) + { + string pageData = await Task.FromResult(InvokeService("GetDetailPage", new object[] { loadData }).Serialize()); + return Content(pageData); + } + + /// + /// 上传文件 + /// + /// + /// + [ApiExplorerSettings(IgnoreApi = true)] + public virtual async Task Upload(List fileInput) + { + object result = await Task.FromResult(InvokeService("Upload", new object[] { fileInput })); + return Json(result); + } + + + /// + /// 导入表数据Excel + /// + /// + /// + [HttpPost] + public virtual async Task Import(List fileInput) + { + object result = await Task.FromResult(InvokeService("Import", new object[] { fileInput })); + return Json(result); + } + + + [ApiExplorerSettings(IgnoreApi = true)] + public virtual async Task Export(PageDataOptions loadData) + { + return Json(await Task.FromResult(InvokeService("Export", new object[] { loadData }))); + } + + [ApiExplorerSettings(IgnoreApi = true)] + public virtual ActionResult DownLoadFile(string path) + { + if (string.IsNullOrEmpty(path)) return Content("未找到文件"); + try + { + if (path.IndexOf("/") == -1 && path.IndexOf("\\") == -1) + { + path = path.DecryptDES(AppSetting.Secret.ExportFile); + } + else + { + path = path.MapPath(); + } + string fileName = Path.GetFileName(path); + return File(System.IO.File.ReadAllBytes(path), System.Net.Mime.MediaTypeNames.Application.Octet, fileName); + } + catch (Exception ex) + { + Logger.Error($"文件下载出错:{path}{ex.Message}"); + } + return Content(""); + } + + /// + /// 下载Excel导入的模板 + /// + /// + /// + [HttpGet] + [ApiExplorerSettings(IgnoreApi = true)] + public async virtual Task DownLoadTemplate() + { + ResponseContent = await Task.FromResult(InvokeService("DownLoadTemplate", new object[] { })) as WebResponseContent; + if (!ResponseContent.Status) + { + return Json(ResponseContent); + } + byte[] fileBytes = System.IO.File.ReadAllBytes(ResponseContent.Data.ToString()); + return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, Path.GetFileName(ResponseContent.Data.ToString())); + } + + [ApiExplorerSettings(IgnoreApi = true)] + public virtual async Task Del(object[] keys) + { + ResponseContent = await Task.FromResult(InvokeService("Del", new object[] { keys, true })) as WebResponseContent; + Logger.Info(Enums.LoggerType.Del, keys.Serialize(), ResponseContent.Status ? "Ok" : ResponseContent.Message); + return Json(ResponseContent); + } + [ApiExplorerSettings(IgnoreApi = true)] + public virtual async Task Audit(object[] id, int? auditStatus, string auditReason) + { + ResponseContent = await Task.FromResult(InvokeService("Audit", new object[] { id, auditStatus, auditReason })) as WebResponseContent; + Logger.Info(Enums.LoggerType.Del, id?.Serialize() + "," + (auditStatus ?? -1) + "," + auditReason, ResponseContent.Status ? "Ok" : ResponseContent.Message); + return Json(ResponseContent); + } + [ApiExplorerSettings(IgnoreApi = true)] + public virtual async Task Add(SaveModel saveModel) + { + ResponseContent = await Task.FromResult(InvokeService("Add", new Type[] { typeof(SaveModel) }, new object[] { saveModel })) as WebResponseContent; + Logger.Info(Enums.LoggerType.Add, saveModel.Serialize(), ResponseContent.Status ? "Ok" : ResponseContent.Message); + return ResponseContent; + } + [ApiExplorerSettings(IgnoreApi = true)] + public virtual async Task Update(SaveModel saveModel) + { + ResponseContent = await Task.FromResult(InvokeService("Update", new object[] { saveModel })) as WebResponseContent; + Logger.Info(Enums.LoggerType.Edit, saveModel.Serialize(), ResponseContent.Status ? "Ok" : ResponseContent.Message); + return ResponseContent; + } + + /// + /// 反射调用service方法 + /// + /// + /// + /// + private object InvokeService(string methodName, object[] parameters) + { + return Service.GetType().GetMethod(methodName).Invoke(Service, parameters); + } + /// + /// 反射调用service方法 + /// + /// + /// 为要调用重载的方法参数类型:new Type[] { typeof(SaveDataModel) + /// + /// + private object InvokeService(string methodName, Type[] types, object[] parameters) + { + return Service.GetType().GetMethod(methodName, types).Invoke(Service, parameters); + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Controllers/Basic/WebBaseController.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Controllers/Basic/WebBaseController.cs new file mode 100644 index 0000000000000000000000000000000000000000..bd85ab37b3614652d2fc899c56f32965082b5b58 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Controllers/Basic/WebBaseController.cs @@ -0,0 +1,112 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System.Threading.Tasks; +using VOL.Core.Filters; +using VOL.Entity.DomainModels; + +namespace VOL.Core.Controllers.Basic +{ + public class WebBaseController : BaseController + { + + public WebBaseController(string projectName, string folder, string tablename, IServiceBase service) + : base(projectName, folder, tablename, service) + { + } + /// + /// 获取grid分页数据 + /// + /// + /// + [ActionPermission(Enums.ActionPermissionOptions.Search)] + [HttpPost] + public override async Task GetPageData(PageDataOptions loadData) + { + return await base.GetPageData(loadData); + } + [HttpPost] + [ActionPermission(Enums.ActionPermissionOptions.Upload)] + public override async Task Upload(List fileInput) + { + return await base.Upload(fileInput); + } + + /// + /// 导出文件,返回日期+文件名 + /// + /// + /// + [ActionPermission(Enums.ActionPermissionOptions.Export)] + [HttpPost] + public override async Task Export(PageDataOptions loadData) + { + return await base.Export(loadData); + } + /// + /// 下载文件 + /// + /// + /// + [ActionPermission(Enums.ActionPermissionOptions.Export)] + [HttpGet] + public override ActionResult DownLoadFile(string fileName) + { + return base.DownLoadFile(fileName); + } + /// + /// 通过key删除文件 + /// + /// + /// + [ActionPermission(Enums.ActionPermissionOptions.Delete)] + [HttpPost] + public override async Task Del(object[] keys) + { + return await base.Del(keys); + } + /// + /// 审核 + /// + /// + /// + [ActionPermission(Enums.ActionPermissionOptions.Audit)] + [HttpPost] + public override async Task Audit(object[] id, int? auditStatus, string auditReason) + { + return await base.Audit(id, auditStatus, auditReason); + } + /// + /// 新增支持主子表 + /// + /// + /// + [ActionPermission(Enums.ActionPermissionOptions.Add)] + [HttpPost] + public async Task Add([ModelBinder]Dictionary mainData, [ModelBinder] List> detailData) + { + SaveModel saveModel = new SaveModel() { MainData = mainData, DetailData = detailData }; + return Json(await base.Add(saveModel)); + } + /// + /// 编辑支持主子表 + /// [ModelBinder(BinderType =(typeof(ModelBinder.BaseModelBinder)))]可指定绑定modelbinder + /// + /// + /// + [ActionPermission(Enums.ActionPermissionOptions.Update)] + [HttpPost] + public async Task Update([ModelBinder(BinderType = (typeof(ModelBinder.BaseModelBinder)))]Dictionary mainData, [ModelBinder] List> detailData, [ModelBinder] List delKeys) + { + SaveModel saveModel = new SaveModel() + { + DelKeys = delKeys, + MainData = mainData, + DetailData = detailData + }; + var data = await base.Update(saveModel); + return Json(data); + } + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/DBManager/DBConnectionAttribute.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/DBManager/DBConnectionAttribute.cs new file mode 100644 index 0000000000000000000000000000000000000000..9c73779c6540f02b4cbcedf44ed5b8e24b9821d3 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/DBManager/DBConnectionAttribute.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.DBManager +{ + public class DBConnectionAttribute : Attribute + { + public string DBName { get; set; } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/DBManager/DBServerProvider.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/DBManager/DBServerProvider.cs new file mode 100644 index 0000000000000000000000000000000000000000..3ce3df73cbcbbed367f95fbafc29396191513b95 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/DBManager/DBServerProvider.cs @@ -0,0 +1,183 @@ +using Microsoft.EntityFrameworkCore; +using MySqlConnector; +using Npgsql; +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using VOL.Core.Configuration; +using VOL.Core.Const; +using VOL.Core.Dapper; +using VOL.Core.EFDbContext; +using VOL.Core.Enums; +using VOL.Core.Extensions; + +namespace VOL.Core.DBManager +{ + public partial class DBServerProvider + { + private static Dictionary ConnectionPool = new Dictionary(StringComparer.OrdinalIgnoreCase); + + private static readonly string DefaultConnName = "defalut"; + + static DBServerProvider() + { + SetConnection(DefaultConnName, AppSetting.DbConnectionString); + } + public static void SetConnection(string key, string val) + { + if (ConnectionPool.ContainsKey(key)) + { + ConnectionPool[key] = val; + return; + } + ConnectionPool.Add(key, val); + } + /// + /// 设置默认数据库连接 + /// + /// + public static void SetDefaultConnection(string val) + { + SetConnection(DefaultConnName, val); + } + + public static string GetConnectionString(string key) + { + key = key ?? DefaultConnName; + if (ConnectionPool.ContainsKey(key)) + { + return ConnectionPool[key]; + } + return key; + } + /// + /// 获取默认数据库连接 + /// + /// + public static string GetConnectionString() + { + return GetConnectionString(DefaultConnName); + } + public static IDbConnection GetDbConnection(string connString = null) + { + if (connString==null) + { + connString = ConnectionPool[DefaultConnName]; + } + if (DBType.Name == DbCurrentType.MySql.ToString()) + { + return new MySqlConnection(connString); + } + if (DBType.Name == DbCurrentType.PgSql.ToString()) + { + return new NpgsqlConnection(connString); + } + return new SqlConnection(connString); + } + + + /// + /// 扩展dapper 获取MSSQL数据库DbConnection,默认系统获取配置文件的DBType数据库类型, + /// + /// 如果connString为null 执行重载GetDbConnection(string connString = null) + /// 指定连接数据库的类型:MySql/MsSql/PgSql + /// + public static IDbConnection GetDbConnection(string connString = null, DbCurrentType dbCurrentType=DbCurrentType.Default) + { + //默认获取DbConnection + if (connString.IsNullOrEmpty()|| DbCurrentType.Default== dbCurrentType) + { + return GetDbConnection(connString); + } + if (dbCurrentType==DbCurrentType.MySql) + { + return new MySqlConnection(connString); + } + if (dbCurrentType == DbCurrentType.PgSql) + { + return new NpgsqlConnection(connString); + } + return new SqlConnection(connString); + + } + + public static VOLContext DbContext + { + get { return GetEFDbContext(); } + } + public static VOLContext GetEFDbContext() + { + return GetEFDbContext(null); + } + public static VOLContext GetEFDbContext(string dbName) + { + VOLContext beefContext = Utilities.HttpContext.Current.RequestServices.GetService(typeof(VOLContext)) as VOLContext; + if (dbName != null) + { + if (!ConnectionPool.ContainsKey(dbName)) + { + throw new Exception("数据库连接名称错误"); + } + beefContext.Database.GetDbConnection().ConnectionString = ConnectionPool[dbName]; + } + return beefContext; + } + + public static void SetDbContextConnection(VOLContext beefContext, string dbName) + { + if (!ConnectionPool.ContainsKey(dbName)) + { + throw new Exception("数据库连接名称错误"); + } + beefContext.Database.GetDbConnection().ConnectionString = ConnectionPool[dbName]; + } + /// + /// 获取实体的数据库连接 + /// + /// + /// + /// + public static void GetDbContextConnection(VOLContext defaultDbContext) + { + //string connstr= defaultDbContext.Database.GetDbConnection().ConnectionString; + // if (connstr != ConnectionPool[DefaultConnName]) + // { + // defaultDbContext.Database.GetDbConnection().ConnectionString = ConnectionPool[DefaultConnName]; + // }; + } + + public static ISqlDapper SqlDapper + { + get + { + return new SqlDapper(DefaultConnName); + } + } + public static ISqlDapper GetSqlDapper(string dbName = null) + { + return new SqlDapper(dbName ?? DefaultConnName); + } + /// + /// + /// + /// 指定数据库类型:MySql/MsSql/PgSql + /// 指定数据连串名称 + /// + public static ISqlDapper GetSqlDapper(DbCurrentType dbCurrentType, string dbName = null) + { + if (dbName.IsNullOrEmpty()) + { + return new SqlDapper(dbName ?? DefaultConnName); + } + return new SqlDapper(dbName, dbCurrentType); + } + public static ISqlDapper GetSqlDapper() + { + //获取实体真实的数据库连接池对象名,如果不存在则用默认数据连接池名 + string dbName = typeof(TEntity).GetTypeCustomValue(x => x.DBName) ?? DefaultConnName; + return GetSqlDapper(dbName); + } + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/DBManager/DbName.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/DBManager/DbName.cs new file mode 100644 index 0000000000000000000000000000000000000000..8cf38c5c0305f0ab7684b42dc24801aec940b276 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/DBManager/DbName.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.DBManage +{ + public struct DbName + { + public static string Default = "default"; + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/DBManager/Partial/DBServerProvider.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/DBManager/Partial/DBServerProvider.cs new file mode 100644 index 0000000000000000000000000000000000000000..517b6ca65977613e05e439c50e56f682e6b6dfa8 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/DBManager/Partial/DBServerProvider.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Text; +using VOL.Core.Configuration; +using VOL.Core.Dapper; +using VOL.Core.Enums; + +namespace VOL.Core.DBManager.Partial +{ + /// + /// 2022.11.21增加其他数据库(sqlserver、mysql、pgsql、oracle)连接配置说明 + /// 需要把两个DBServerProvider.cs文件都更新下 + /// + public partial class DBServerProvider + { + ///// + ///// 单独配置mysql数据库 + ///// + //public static ISqlDapper SqlDapperMySql + //{ + // get + // { + // //读取appsettings.json中的配置 + // string 数据库连接字符串 = AppSetting.GetSettingString("key"); + // return new SqlDapper(数据库连接字符串, DbCurrentType.MySql); + + // //访问数据库方式 + // //DBServerProvider.SqlDapperMySql.xx + // } + //} + + + ///// + ///// 如果有多个不同的mysql数据库,这里再加一个配置 + ///// + //public static ISqlDapper SqlDapperMySql2 + //{ + // get + // { + // //读取appsettings.json中的配置 + // string 数据库连接字符串 = AppSetting.GetSettingString("key2"); + // return new SqlDapper(数据库连接字符串, DbCurrentType.MySql); + + // //访问数据库方式 + // //DBServerProvider.SqlDapperMySql2.xx + // } + //} + + ///// + ///// 单独配置SqlServer数据库 + ///// + //public static ISqlDapper SqlDapperSqlServer + //{ + // get + // { + // //读取appsettings.json中的配置 + // string 数据库连接字符串 = AppSetting.GetSettingString("key"); + // return new SqlDapper(数据库连接字符串, DbCurrentType.MsSql); + + // //访问数据库方式 + // //DBServerProvider.SqlDapperSqlServer.xx + // } + //} + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Dapper/DapperParseGuidTypeHandler.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Dapper/DapperParseGuidTypeHandler.cs new file mode 100644 index 0000000000000000000000000000000000000000..d4da38d5268a762b888fcb471b50913fca2803b3 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Dapper/DapperParseGuidTypeHandler.cs @@ -0,0 +1,29 @@ +using Dapper; +using System; +using System.Collections.Generic; +using System.Data; +using System.Text; + +namespace VOL.Core.Dapper +{ + public class DapperParseGuidTypeHandler : SqlMapper.TypeHandler + { + public override void SetValue(IDbDataParameter parameter, Guid? guid) + { + parameter.Value = guid.ToString(); + } + + public override Guid? Parse(object value) + { + if (value == null || value.ToString() == "") + { + return null; + } + if (value.GetType() == typeof(string)) + { + return new Guid((string)value); + } + return (Guid)value; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Dapper/ISqlDapper.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Dapper/ISqlDapper.cs new file mode 100644 index 0000000000000000000000000000000000000000..197e18dee66989b99cc6a059d553c8ae7551f110 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Dapper/ISqlDapper.cs @@ -0,0 +1,163 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Linq.Expressions; +using System.Threading.Tasks; +using Dapper; + +namespace VOL.Core.Dapper +{ + public interface ISqlDapper + { + /// + /// 超时时间(秒)2021.05.05 + /// + /// + /// + ISqlDapper SetTimout(int timeout); + void BeginTransaction(Func action, Action error); + List QueryList(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + Task> QueryListAsync(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + T QueryFirst(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) where T : class; + + Task QueryFirstAsync(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) where T : class; + + Task QueryDynamicFirstAsync(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + dynamic QueryDynamicFirst(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + Task QueryDynamicListAsync(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + List QueryDynamicList(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + + object ExecuteScalar(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + + Task ExecuteScalarAsync(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + int ExcuteNonQuery(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + Task ExcuteNonQueryAsync(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + IDataReader ExecuteReader(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + SqlMapper.GridReader QueryMultiple(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + Task<(IEnumerable, IEnumerable)> QueryMultipleAsync(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + (List, List) QueryMultiple(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + Task<(IEnumerable, IEnumerable, IEnumerable)> QueryMultipleAsync(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + (List, List, List) QueryMultiple(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + + Task<(IEnumerable, IEnumerable)> QueryDynamicMultipleAsync(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + (List, List) QueryDynamicMultiple(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + + Task<(IEnumerable, IEnumerable, IEnumerable, IEnumerable)> QueryMultipleAsync(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + (List, List, List, List) QueryMultiple(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + + Task<(IEnumerable, IEnumerable, IEnumerable, IEnumerable, IEnumerable)> QueryMultipleAsync(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + (List, List, List, List, List) QueryMultiple(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + + Task<(IEnumerable, IEnumerable)> QueryDynamicMultipleAsync2(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + (List, List) QueryDynamicMultiple2(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + Task<(IEnumerable, IEnumerable, IEnumerable)> QueryDynamicMultipleAsync3(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + (List, List, List) QueryDynamicMultiple3(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + + Task<(IEnumerable, IEnumerable, IEnumerable, IEnumerable, IEnumerable)> QueryDynamicMultipleAsync5(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + (List, List, List, List, List) QueryDynamicMultiple5(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false); + + + /// + /// + /// + /// + /// + /// 指定插入的字段 + /// 是否开启事务 + /// + int Add(T entity, Expression> updateFileds = null, bool beginTransaction = false); + /// + /// + /// + /// + /// + /// 指定插入的字段 + /// 是否开启事务 + /// + int AddRange(IEnumerable entities, Expression> updateFileds = null, bool beginTransaction = false); + + + /// + /// sqlserver使用的临时表参数化批量更新,mysql批量更新待发开 + /// + /// + /// 实体必须带主键 + /// 指定更新的字段x=new {x.a,x.b} + /// 是否开启事务 + /// + int Update(T entity, Expression> updateFileds = null, bool beginTransaction = false); + + /// + /// sqlserver使用的临时表参数化批量更新,mysql批量更新待发开 + /// + /// + /// 实体必须带主键 + /// 指定更新的字段x=new {x.a,x.b} + /// 是否开启事务 + /// + int UpdateRange(IEnumerable entities, Expression> updateFileds = null, bool beginTransaction = false); + + /// + /// 使用key批量删除 + /// 调用方式: + /// List keys = new List(); + /// DBServerProvider.SqlDapper.DelWithKey(keys); + /// + /// + /// + /// + int DelWithKey(IEnumerable keys); + /// + /// sqlserver批量写入 + /// 使用时DataTable table表字段顺序要和数据库字段顺序一致 + /// + /// mysql批量写入 + /// + /// + /// + /// 默认当前下载路径 + /// 默认$"{DateTime.Now.ToString("yyyyMMddHHmmss")}.csv" + /// + int BulkInsert(DataTable table, string tableName, SqlBulkCopyOptions? sqlBulkCopyOptions = null, string fileName = null, string tmpPath = null); + /// + /// + /// + /// + /// + /// + /// 所包含的列 + /// + /// + /// + /// + int BulkInsert(List entities, string tableName = null, + Expression> columns = null, + SqlBulkCopyOptions? sqlBulkCopyOptions = null); + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Dapper/SqlDapper.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Dapper/SqlDapper.cs new file mode 100644 index 0000000000000000000000000000000000000000..a7f20c44ec75e85d164276a5bc1d9898479a8cb1 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Dapper/SqlDapper.cs @@ -0,0 +1,862 @@ + +using Dapper; +using MySqlConnector; +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.IO; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; +using VOL.Core.Const; +using VOL.Core.DBManager; +using VOL.Core.Enums; +using VOL.Core.Extensions; +using VOL.Core.Utilities; + + +namespace VOL.Core.Dapper +{ + public class SqlDapper : ISqlDapper + { + private string _connectionString; + private int? commandTimeout = null; + private DbCurrentType _dbCurrentType; + public SqlDapper() + { + _connectionString = DBServerProvider.GetConnectionString(); + } + public SqlDapper(string connKeyName, DbCurrentType dbCurrentType) + { + _dbCurrentType = dbCurrentType; + _connectionString = DBServerProvider.GetConnectionString(connKeyName); + } + public SqlDapper(string connKeyName) + { + _connectionString = DBServerProvider.GetConnectionString(connKeyName); + } + + private bool _transaction { get; set; } + + private IDbConnection _transactionConnection = null; + + /// + /// 超时时间(秒) + /// + /// + /// + public ISqlDapper SetTimout(int timeout) + { + this.commandTimeout = timeout; + return this; + } + + + private T Execute(Func func, bool beginTransaction = false) + { + if (_transaction) + { + return func(_transactionConnection, dbTransaction); + } + if (beginTransaction) + { + return ExecuteTransaction(func); + } + using (var connection = DBServerProvider.GetDbConnection(_connectionString, _dbCurrentType)) + { + return func(connection, dbTransaction); + } + } + + private T ExecuteTransaction(Func func) + { + using (_transactionConnection = DBServerProvider.GetDbConnection(_connectionString, _dbCurrentType)) + { + try + { + _transactionConnection.Open(); + dbTransaction = _transactionConnection.BeginTransaction(); + T reslutT = func(_transactionConnection, dbTransaction); + dbTransaction.Commit(); + return reslutT; + } + catch (Exception ex) + { + dbTransaction?.Rollback(); + throw ex; + } + finally + { + dbTransaction?.Dispose(); + } + } + } + + private async Task ExecuteAsync(Func> funcAsync, bool beginTransaction = false) + { + if (_transaction) + { + return await funcAsync(_transactionConnection, dbTransaction); + } + if (beginTransaction) + { + return await ExecuteTransactionAsync(funcAsync); + } + using (var connection = DBServerProvider.GetDbConnection(_connectionString)) + { + T reslutT = await funcAsync(connection, dbTransaction); + if (!_transaction && dbTransaction != null) + { + dbTransaction.Commit(); + } + return reslutT; + } + } + + private async Task ExecuteTransactionAsync(Func> funcAsync) + { + using (var connection = DBServerProvider.GetDbConnection(_connectionString)) + { + try + { + connection.Open(); + dbTransaction = connection.BeginTransaction(); + T reslutT = await funcAsync(connection, dbTransaction); + if (!_transaction && dbTransaction != null) + { + dbTransaction.Commit(); + } + return reslutT; + } + catch (Exception ex) + { + dbTransaction?.Rollback(); + throw ex; + } + } + } + + /// + /// 2020.06.15增加Dapper事务处理 + /// + /// + public void BeginTransaction(Func action, Action error) + { + _transaction = true; + using (var connection = DBServerProvider.GetDbConnection(_connectionString, _dbCurrentType)) + { + try + { + _transactionConnection = connection; + _transactionConnection.Open(); + dbTransaction = _transactionConnection.BeginTransaction(); + bool result = action(this); + if (result) + { + dbTransaction?.Commit(); + } + else + { + dbTransaction?.Rollback(); + } + } + catch (Exception ex) + { + dbTransaction?.Rollback(); + error(ex); + } + finally + { + _transaction = false; + dbTransaction?.Dispose(); + } + } + } + + /// + /// var p = new object(); + // p.Add("@a", 11); + //p.Add("@b", dbType: DbType.Int32, direction: ParameterDirection.Output); + //p.Add("@c", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue); + // /// + /// + /// + /// + /// + /// + public List QueryList(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return Execute((conn, dbTransaction) => + { + return conn.Query(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout).ToList(); + }, beginTransaction); + } + public async Task> QueryListAsync(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return await ExecuteAsync(async (conn, dbTransaction) => + { + return await conn.QueryAsync(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout); + }, beginTransaction); + } + + public async Task QueryFirstAsync(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) where T : class + { + return await ExecuteAsync(async (conn, dbTransaction) => + { + return await conn.QueryFirstOrDefaultAsync(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout); + }, beginTransaction); + } + + + public T QueryFirst(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) where T : class + { + return Execute((conn, dbTransaction) => + { + return conn.QueryFirstOrDefault(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout); + }, beginTransaction); + } + + public async Task QueryDynamicFirstAsync(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return await ExecuteAsync(async (conn, dbTransaction) => + { + return await conn.QueryFirstOrDefaultAsync(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout); + }, beginTransaction); + } + + public dynamic QueryDynamicFirst(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return Execute((conn, dbTransaction) => + { + return conn.QueryFirstOrDefault(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout); + }, beginTransaction); + } + + public async Task QueryDynamicListAsync(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return await ExecuteAsync(async (conn, dbTransaction) => + { + return await conn.QueryAsync(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout); + }, beginTransaction); + } + + public List QueryDynamicList(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return Execute((conn, dbTransaction) => + { + return conn.Query(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout).ToList(); + }, beginTransaction); + } + + + public async Task ExecuteScalarAsync(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return await ExecuteAsync(async (conn, dbTransaction) => + { + return await conn.ExecuteScalarAsync(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout); + }, beginTransaction); + } + + public object ExecuteScalar(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return Execute((conn, dbTransaction) => + { + return conn.ExecuteScalar(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout); + }, beginTransaction); + } + + public async Task ExcuteNonQueryAsync(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return await ExecuteAsync(async (conn, dbTransaction) => + { + return await conn.ExecuteAsync(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout); + }, beginTransaction); + } + + public int ExcuteNonQuery(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return Execute((conn, dbTransaction) => + { + return conn.Execute(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout); + }, beginTransaction); + } + public IDataReader ExecuteReader(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return Execute((conn, dbTransaction) => + { + return conn.ExecuteReader(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout); + }, beginTransaction); + } + + + public SqlMapper.GridReader QueryMultiple(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return Execute((conn, dbTransaction) => + { + return conn.QueryMultiple(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout); + }, beginTransaction); + } + + + public async Task<(IEnumerable, IEnumerable)> QueryMultipleAsync(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return await ExecuteAsync(async (conn, dbTransaction) => + { + using (SqlMapper.GridReader reader = await conn.QueryMultipleAsync(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout)) + { + return (await reader.ReadAsync(), await reader.ReadAsync()); + } + }, beginTransaction); + } + + /// + /// 获取output值 param.Get("@b"); + /// + /// + /// + /// + /// + /// + /// + public (List, List) QueryMultiple(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return Execute((conn, dbTransaction) => + { + using (SqlMapper.GridReader reader = conn.QueryMultiple(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout)) + { + return (reader.Read().ToList(), reader.Read().ToList()); + } + }, beginTransaction); + } + + public async Task<(IEnumerable, IEnumerable)> QueryDynamicMultipleAsync(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return await ExecuteAsync(async (conn, dbTransaction) => + { + using (SqlMapper.GridReader reader = await conn.QueryMultipleAsync(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout)) + { + return (await reader.ReadAsync(), await reader.ReadAsync()); + } + }, beginTransaction); + } + + public (List, List) QueryDynamicMultiple(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return Execute((conn, dbTransaction) => + { + using (SqlMapper.GridReader reader = conn.QueryMultiple(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout)) + { + return (reader.Read().ToList(), reader.Read().ToList()); + } + }, beginTransaction); + } + + + public async Task<(IEnumerable, IEnumerable, IEnumerable)> QueryMultipleAsync(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return await ExecuteAsync(async (conn, dbTransaction) => + { + using (SqlMapper.GridReader reader = await conn.QueryMultipleAsync(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout)) + { + return (await reader.ReadAsync(), await reader.ReadAsync(), await reader.ReadAsync()); + } + }, beginTransaction); + } + + + public (List, List, List) QueryMultiple(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return Execute((conn, dbTransaction) => + { + using (SqlMapper.GridReader reader = conn.QueryMultiple(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout)) + { + return (reader.Read().ToList(), reader.Read().ToList(), reader.Read().ToList()); + } + }, beginTransaction); + } + + public async Task<(IEnumerable, IEnumerable)> QueryDynamicMultipleAsync2(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return await ExecuteAsync(async (conn, dbTransaction) => + { + using (SqlMapper.GridReader reader = await conn.QueryMultipleAsync(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout)) + { + return ( + await reader.ReadAsync(), + await reader.ReadAsync() + ); + } + }, beginTransaction); + } + + public (List, List) QueryDynamicMultiple2(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return Execute((conn, dbTransaction) => + { + using (SqlMapper.GridReader reader = conn.QueryMultiple(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout)) + { + return ( + reader.Read().ToList(), + reader.Read().ToList() + ); + } + }, beginTransaction); + } + + public async Task<(IEnumerable, IEnumerable, IEnumerable)> QueryDynamicMultipleAsync3(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return await ExecuteAsync(async (conn, dbTransaction) => + { + using (SqlMapper.GridReader reader = await conn.QueryMultipleAsync(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout)) + { + return ( + await reader.ReadAsync(), + await reader.ReadAsync(), + await reader.ReadAsync() + ); + } + }, beginTransaction); + } + + + public (List, List, List) QueryDynamicMultiple3(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return Execute((conn, dbTransaction) => + { + using (SqlMapper.GridReader reader = conn.QueryMultiple(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout)) + { + return (reader.Read().ToList(), + reader.Read().ToList(), + reader.Read().ToList() + ); + } + }, beginTransaction); + } + + + public async Task<(IEnumerable, IEnumerable, IEnumerable, IEnumerable, IEnumerable)> QueryDynamicMultipleAsync5(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return await ExecuteAsync(async (conn, dbTransaction) => + { + using (SqlMapper.GridReader reader = await conn.QueryMultipleAsync(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout)) + { + return ( + await reader.ReadAsync(), + await reader.ReadAsync(), + await reader.ReadAsync(), + await reader.ReadAsync(), + await reader.ReadAsync() + ); + } + }, beginTransaction); + } + + public (List, List, List, List, List) QueryDynamicMultiple5(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return Execute((conn, dbTransaction) => + { + using (SqlMapper.GridReader reader = conn.QueryMultiple(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout)) + { + return (reader.Read().ToList(), + reader.Read().ToList(), + reader.Read().ToList(), + reader.Read().ToList(), + reader.Read().ToList() + ); + } + }, beginTransaction); + } + + public async Task<(IEnumerable, IEnumerable, IEnumerable, IEnumerable)> QueryMultipleAsync(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return await ExecuteAsync(async (conn, dbTransaction) => + { + using (SqlMapper.GridReader reader = await conn.QueryMultipleAsync(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout)) + { + return (await reader.ReadAsync(), + await reader.ReadAsync(), + await reader.ReadAsync(), + await reader.ReadAsync() + ); + } + }, beginTransaction); + } + + public (List, List, List, List) QueryMultiple(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return Execute((conn, dbTransaction) => + { + using (SqlMapper.GridReader reader = conn.QueryMultiple(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout)) + { + return (reader.Read().ToList(), + reader.Read().ToList(), + reader.Read().ToList(), + reader.Read().ToList() + ); + } + }, beginTransaction); + } + + + public async Task<(IEnumerable, IEnumerable, IEnumerable, IEnumerable, IEnumerable)> QueryMultipleAsync(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return await ExecuteAsync(async (conn, dbTransaction) => + { + using (SqlMapper.GridReader reader = await conn.QueryMultipleAsync(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout)) + { + return (await reader.ReadAsync(), + await reader.ReadAsync(), + await reader.ReadAsync(), + await reader.ReadAsync(), + await reader.ReadAsync() + ); + } + }, beginTransaction); + } + + public (List, List, List, List, List) QueryMultiple(string cmd, object param, CommandType? commandType = null, bool beginTransaction = false) + { + return Execute((conn, dbTransaction) => + { + using (SqlMapper.GridReader reader = conn.QueryMultiple(cmd, param, dbTransaction, commandType: commandType ?? CommandType.Text, commandTimeout: commandTimeout)) + { + return (reader.Read().ToList(), + reader.Read().ToList(), + reader.Read().ToList(), + reader.Read().ToList(), + reader.Read().ToList() + ); + } + }, beginTransaction); + } + IDbTransaction dbTransaction = null; + + + + /// + /// + /// + /// + /// + /// 指定插入的字段 + /// 是否开启事务 + /// + public int Add(T entity, Expression> addFileds = null, bool beginTransaction = false) + { + return AddRange(new T[] { entity }, addFileds, beginTransaction); + } + /// + /// + /// + /// + /// + /// 指定插入的字段 + /// 是否开启事务 + /// + public int AddRange(IEnumerable entities, Expression> addFileds = null, bool beginTransaction = true) + { + Type entityType = typeof(T); + var key = entityType.GetKeyProperty(); + if (key == null) + { + throw new Exception("实体必须包括主键才能批量更新"); + } + string[] columns; + + //指定插入的字段 + if (addFileds != null) + { + columns = addFileds.GetExpressionToArray(); + } + else + { + var properties = entityType.GetGenericProperties(); + if (key.PropertyType != typeof(Guid)) + { + properties = properties.Where(x => x.Name != key.Name).ToArray(); + } + columns = properties.Select(x => x.Name).ToArray(); + } + string sql = null; + if (DBType.Name == DbCurrentType.MySql.ToString()) + { + //mysql批量写入待优化 + sql = $"insert into {entityType.GetEntityTableName()}({string.Join(",", columns)})" + + $"values(@{string.Join(",@", columns)});"; + } + else if (DBType.Name == DbCurrentType.PgSql.ToString()) + { + //todo pgsql批量写入 待检查是否正确 + sql = $"insert into {entityType.GetEntityTableName()}({"\"" + string.Join("\",\"", columns) + "\""})" + + $"values(@{string.Join(",@", columns)});"; + } + else + { + //sqlserver通过临时表批量写入 + sql = $"insert into {entityType.GetEntityTableName()}({string.Join(",", columns)})" + + $"select {string.Join(",", columns)} from {EntityToSqlTempName.TempInsert};"; + //2020.11.21修复sqlserver批量写入主键类型判断错误 + sql = entities.GetEntitySql(key.PropertyType == typeof(Guid), sql, null, addFileds, null); + } + return Execute((conn, dbTransaction) => + { + //todo pgsql待实现 + return conn.Execute(sql, (DBType.Name == DbCurrentType.MySql.ToString() || DBType.Name == DbCurrentType.PgSql.ToString()) ? entities.ToList() : null, dbTransaction); + }, beginTransaction); + } + + + /// + /// sqlserver使用的临时表参数化批量更新,mysql批量更新待发开 + /// + /// + /// 实体必须带主键 + /// 指定更新的字段x=new {x.a,x.b} + /// 是否开启事务 + /// + public int Update(T entity, Expression> updateFileds = null, bool beginTransaction = false) + { + return UpdateRange(new T[] { entity }, updateFileds, beginTransaction); + } + + /// + ///(根据主键批量更新实体) sqlserver使用的临时表参数化批量更新,mysql待优化 + /// + /// + /// 实体必须带主键 + /// 批定更新字段 + /// + /// + public int UpdateRange(IEnumerable entities, Expression> updateFileds = null, bool beginTransaction = false) + { + Type entityType = typeof(T); + var key = entityType.GetKeyProperty(); + if (key == null) + { + throw new Exception("实体必须包括主键才能批量更新"); + } + + var properties = entityType.GetGenericProperties() + .Where(x => x.Name != key.Name); + if (updateFileds != null) + { + properties = properties.Where(x => updateFileds.GetExpressionToArray().Contains(x.Name)); + } + + if (DBType.Name == DbCurrentType.MySql.ToString()) + { + List paramsList = new List(); + foreach (var item in properties) + { + paramsList.Add(item.Name + "=@" + item.Name); + } + string sqltext = $@"UPDATE { entityType.GetEntityTableName()} SET {string.Join(",", paramsList)} WHERE {entityType.GetKeyName()} = @{entityType.GetKeyName()} ;"; + + return ExcuteNonQuery(sqltext, entities, CommandType.Text, beginTransaction); + // throw new Exception("mysql批量更新未实现"); + } + string fileds = string.Join(",", properties.Select(x => $" a.{x.Name}=b.{x.Name}").ToArray()); + string sql = $"update a set {fileds} from {entityType.GetEntityTableName()} as a inner join {EntityToSqlTempName.TempInsert.ToString()} as b on a.{key.Name}=b.{key.Name}"; + sql = entities.ToList().GetEntitySql(true, sql, null, updateFileds, null); + return ExcuteNonQuery(sql, null, CommandType.Text, beginTransaction); + } + + + /// + /// 使用key批量删除 + /// 调用方式: + /// List keys = new List(); + /// DBServerProvider.SqlDapper.DelWithKey(keys); + /// + /// + /// + /// + public int DelWithKey(IEnumerable keys) + { + Type entityType = typeof(T); + var keyProperty = entityType.GetKeyProperty(); + string sql = $"DELETE FROM {entityType.GetEntityTableName() } where {keyProperty.Name} in @keys "; + return ExcuteNonQuery(sql, new { keys }).GetInt(); + } + /// + /// 通过Bulk批量插入 + /// + /// + /// + /// + /// + /// + private int MSSqlBulkInsert(DataTable table, string tableName, SqlBulkCopyOptions sqlBulkCopyOptions = SqlBulkCopyOptions.UseInternalTransaction, string dbKeyName = null) + { + using (var Connection = DBServerProvider.GetDbConnection(_connectionString, _dbCurrentType)) + { + if (!string.IsNullOrEmpty(dbKeyName)) + { + Connection.ConnectionString = DBServerProvider.GetConnectionString(dbKeyName); + } + using (SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(Connection.ConnectionString, sqlBulkCopyOptions)) + { + sqlBulkCopy.DestinationTableName = tableName; + sqlBulkCopy.BatchSize = table.Rows.Count; + for (int i = 0; i < table.Columns.Count; i++) + { + sqlBulkCopy.ColumnMappings.Add(table.Columns[i].ColumnName, table.Columns[i].ColumnName); + } + sqlBulkCopy.WriteToServer(table); + return table.Rows.Count; + } + } + } + public int BulkInsert(List entities, string tableName = null, + Expression> columns = null, + SqlBulkCopyOptions? sqlBulkCopyOptions = null) + { + DataTable table = entities.ToDataTable(columns, false); + return BulkInsert(table, tableName ?? typeof(T).GetEntityTableName(), sqlBulkCopyOptions); + } + public int BulkInsert(DataTable table, string tableName, SqlBulkCopyOptions? sqlBulkCopyOptions = null, string fileName = null, string tmpPath = null) + { + if (!string.IsNullOrEmpty(tmpPath)) + { + tmpPath = tmpPath.ReplacePath(); + } + if (DBType.Name == "MySql") + { + return MySqlBulkInsert(table, tableName, fileName, tmpPath); + } + + if (DBType.Name == "PgSql") + { + PGSqlBulkInsert(table, tableName); + return table.Rows.Count; + } + return MSSqlBulkInsert(table, tableName, sqlBulkCopyOptions ?? SqlBulkCopyOptions.KeepIdentity); + } + + /// + ///大批量数据插入,返回成功插入行数 + //// + /// + /// 数据库连接字符串 + /// 数据表 + /// 返回成功插入行数 + private int MySqlBulkInsert(DataTable table, string tableName, string fileName = null, string tmpPath = null) + { + if (table.Rows.Count == 0) return 0; + // tmpPath = tmpPath ?? FileHelper.GetCurrentDownLoadPath(); + int insertCount = 0; + string csv = DataTableToCsv(table); + string text = $"当前行:{table.Rows.Count}"; + MemoryStream stream = null; + try + { + using (var Connection = DBServerProvider.GetDbConnection(_connectionString, _dbCurrentType)) + { + if (Connection.State == ConnectionState.Closed) + { + Connection.Open(); + } + using (IDbTransaction tran = Connection.BeginTransaction()) + { + var bulk = new MySqlBulkLoader(Connection as MySqlConnection) + { + LineTerminator = "\n", + TableName = tableName, + CharacterSet = "UTF8", + FieldQuotationCharacter = '"', + FieldQuotationOptional = true + }; + var array = Encoding.UTF8.GetBytes(csv); + using (stream = new MemoryStream(array)) + { + stream = new MemoryStream(array); + bulk.SourceStream = stream; //File.OpenRead(fileName); + bulk.Columns.AddRange(table.Columns.Cast().Select(colum => colum.ColumnName).ToList()); + insertCount = bulk.Load(); + tran.Commit(); + } + } + } + + } + catch (Exception ex) + { + throw ex; + } + return insertCount; + // File.Delete(path); + } + /// + ///将DataTable转换为标准的CSV + /// + /// 数据表 + /// 返回标准的CSV + private string DataTableToCsv(DataTable table) + { + //以半角逗号(即,)作分隔符,列为空也要表达其存在。 + //列内容如存在半角逗号(即,)则用半角引号(即"")将该字段值包含起来。 + //列内容如存在半角引号(即")则应替换成半角双引号("")转义,并用半角引号(即"")将该字段值包含起来。 + StringBuilder sb = new StringBuilder(); + DataColumn colum; + Type typeString = typeof(string); + Type typeDate = typeof(DateTime); + + foreach (DataRow row in table.Rows) + { + for (int i = 0; i < table.Columns.Count; i++) + { + colum = table.Columns[i]; + if (i != 0) sb.Append("\t"); + if (colum.DataType == typeString) + { + var data = $"\"{row[colum].ToString().Replace("\"", "\"\"")}\""; + sb.Append(data); + } + else if (colum.DataType == typeDate) + { + //centos系统里把datatable里的日期转换成了10/18/18 3:26:15 PM格式 + bool b = DateTime.TryParse(row[colum].ToString(), out DateTime dt); + sb.Append(b ? dt.ToString("yyyy-MM-dd HH:mm:ss") : ""); + } + else sb.Append(row[colum].ToString()); + } + sb.Append("\n"); + } + + return sb.ToString(); + } + /// + /// 2020.08.07增加PGSQL批量写入 + /// + /// + /// + private void PGSqlBulkInsert(DataTable table, string tableName) + { + List columns = new List(); + for (int i = 0; i < table.Columns.Count; i++) + { + columns.Add("\"" + table.Columns[i].ColumnName + "\""); + } + string copySql = $"copy \"public\".\"{tableName}\"({string.Join(',', columns)}) FROM STDIN (FORMAT BINARY)"; + using (var conn = new Npgsql.NpgsqlConnection(_connectionString)) + { + conn.Open(); + using (var writer = conn.BeginBinaryImport(copySql)) + { + foreach (DataRow row in table.Rows) + { + writer.StartRow(); + for (int i = 0; i < table.Columns.Count; i++) + { + writer.Write(row[i]); + } + } + writer.Complete(); + } + } + } + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/EFDbContext/EFLoggerProvider.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/EFDbContext/EFLoggerProvider.cs new file mode 100644 index 0000000000000000000000000000000000000000..123093dcb94a717bd9700187b966ad8e1a5b8f87 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/EFDbContext/EFLoggerProvider.cs @@ -0,0 +1,34 @@ +using VOL.Core.Utilities; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.EFDbContext +{ + public class EFLoggerProvider : ILoggerProvider + { + public ILogger CreateLogger(string categoryName) => new EFLogger(categoryName); + public void Dispose() { } + } + public class EFLogger : ILogger + { + private readonly string categoryName; + + public EFLogger(string categoryName) => this.categoryName = categoryName; + + public bool IsEnabled(LogLevel logLevel) => true; + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + { + //ef core执行数据库查询时的categoryName为Microsoft.EntityFrameworkCore.Database.Command,日志级别为Information + if (categoryName == "Microsoft.EntityFrameworkCore.Database.Command" + && logLevel == LogLevel.Information) + { + var logContent = formatter(state, exception); + Console.WriteLine(logContent); + } + } + public IDisposable BeginScope(TState state) => null; + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/EFDbContext/VOLContext.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/EFDbContext/VOLContext.cs new file mode 100644 index 0000000000000000000000000000000000000000..b4e2bf6653af40bc1e1310fa928deb5a7b77851a --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/EFDbContext/VOLContext.cs @@ -0,0 +1,132 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyModel; +using Microsoft.Extensions.Logging; +using System; +using System.Linq; +using System.Reflection; +using System.Runtime.Loader; +using VOL.Core.DBManager; +using VOL.Core.Extensions; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.SystemModels; + +namespace VOL.Core.EFDbContext +{ + public class VOLContext : DbContext, IDependency + { + /// + /// 数据库连接名称 + /// + public string DataBaseName = null; + public VOLContext() + : base() + { + } + public VOLContext(string connction) + : base() + { + DataBaseName = connction; + } + + public VOLContext(DbContextOptions options) + : base(options) + { + + } + public override void Dispose() + { + base.Dispose(); + } + public override int SaveChanges() + { + try + { + return base.SaveChanges(); + } + catch (Exception ex)//DbUpdateException + { + throw (ex.InnerException as Exception ?? ex); + } + } + public override DbSet Set() + { + return base.Set(); + } + //public DbSet Set(bool trackAll = false) where TEntity : class + //{ + // return base.Set(); + //} + /// + /// 设置跟踪状态 + /// + public bool QueryTracking + { + set + { + this.ChangeTracker.QueryTrackingBehavior = + value ? QueryTrackingBehavior.TrackAll + : QueryTrackingBehavior.NoTracking; + } + } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + string connectionString = DBServerProvider.GetConnectionString(null); + if (Const.DBType.Name == Enums.DbCurrentType.MySql.ToString()) + { + optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)); + } + else if (Const.DBType.Name == Enums.DbCurrentType.PgSql.ToString()) + { + optionsBuilder.UseNpgsql(connectionString); + } + else + { + optionsBuilder.UseSqlServer(connectionString); + } + //默认禁用实体跟踪 + optionsBuilder = optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking); + //var loggerFactory = new LoggerFactory(); + //loggerFactory.AddProvider(new EFLoggerProvider()); + // optionsBuilder.UseLoggerFactory(loggerFactory); + base.OnConfiguring(optionsBuilder); + } + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + Type type = null; + try + { + //获取所有类库 + var compilationLibrary = DependencyContext + .Default + .RuntimeLibraries + .Where(x => !x.Serviceable && x.Type != "package" && x.Type == "project"); + foreach (var _compilation in compilationLibrary) + { + //加载指定类 + AssemblyLoadContext.Default + .LoadFromAssemblyName(new AssemblyName(_compilation.Name)) + .GetTypes() + .Where(x => + x.GetTypeInfo().BaseType != null + && x.BaseType == (typeof(BaseEntity))) + .ToList().ForEach(t => + { + modelBuilder.Entity(t); + // modelBuilder.Model.AddEntityType(t); + }); + } + //modelBuilder.AddEntityConfigurationsFromAssembly(GetType().Assembly); + base.OnModelCreating(modelBuilder); + } + catch (Exception ex) + { + string mapPath = ($"Log/").MapPath(); + Utilities.FileHelper.WriteFile(mapPath, + $"syslog_{DateTime.Now.ToString("yyyyMMddHHmmss")}.txt", + type?.Name + "--------" + ex.Message + ex.StackTrace + ex.Source); + } + + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/ActionPermissionOptions.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/ActionPermissionOptions.cs new file mode 100644 index 0000000000000000000000000000000000000000..5b2163675a63c6380753bc6edbafd17c69e1b934 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/ActionPermissionOptions.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.Enums +{ + public enum ActionPermissionOptions + { + Add = 0, + Delete = 1, + Update = 2, + Search=3, + Export=4, + Audit, + Upload,//上传文件 + Import //导入表数据Excel + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/ApiMessage.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/ApiMessage.cs new file mode 100644 index 0000000000000000000000000000000000000000..d7526a6b0b3763f3c4c30907eb22efdd3b0b80af --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/ApiMessage.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.Enums +{ + public struct ApiMessage + { + + /// + /// 参数有误 + /// + public const string ParameterError = "请求参数不正确!"; + /// + /// 没有配置好输入参数 + /// + public const string NotInputEntity = "没有配置好输入参数!"; + /// + /// token丢失 + /// + public const string TokenLose = "token丢失!"; + + /// + /// 版本号不能为空 + /// + + public const string VersionEmpty = "版本号不能为空!"; + /// + /// content不能为空 + /// + + public const string ContentEmpty = "biz_content不能为空!"; + /// + /// content不能为空 + /// + public const string TokenError = "token不正确"; + + public const string AccountLocked = "帐号已被锁定!"; + + public const string PhoneNoInvalid = "输入的不是手机号"; + + + public const string PINTypeNotRange= "获取验证的类型不正确"; + public const string OperToBusy = "操作太频繁,请稍后再试"; + + public const string SendSTKError = "短信发送异常,请稍后再试"; + public const string SendSTKSuccess = "短信发送成功"; + public const string STKNotSend = "请先获取验证码"; + public const string AccountExists = "手机号已经被注册"; + + public const string AccountNotExists = "手机号没有注册"; + + public const string PINExpire = "验证码已过期,请重新获取"; + + public const string PINError = "验证码不正确"; + + public const string ParameterEmpty = "参数不能为空"; + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/ApiStatutsCode.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/ApiStatutsCode.cs new file mode 100644 index 0000000000000000000000000000000000000000..b16fe4cb64d7abbab5bea4d05f4e255ae77b5b67 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/ApiStatutsCode.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.Enums +{ + public enum ApiStatutsCode + { + False = 0, + Ok = 1, + TokenExpire = 2 + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/CPrefix.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/CPrefix.cs new file mode 100644 index 0000000000000000000000000000000000000000..b36345d378fc22b7ebb77a4a2728b322a3fb3fcc --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/CPrefix.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VOL.Core.Enums +{ + public enum CPrefix + { + Role = 0, + //UserIDkey + UID = 1, + /// + /// 头像KEY + /// + HDImg = 2, + Token = 3, + CityList + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/DbCurrentType.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/DbCurrentType.cs new file mode 100644 index 0000000000000000000000000000000000000000..a703fbaa0638d6a3073bb1b6fdf45e9b3c07fea8 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/DbCurrentType.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.Enums +{ + public enum DbCurrentType + { + Default = 0, + MySql = 1, + MsSql = 2,//2020.08.08修改sqlserver拼写 + PgSql = 3 + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/LinqExpressionType.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/LinqExpressionType.cs new file mode 100644 index 0000000000000000000000000000000000000000..cb9fb32e26cf49e383993b7b9dd36ab96ce8ead4 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/LinqExpressionType.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.Enums +{ + public enum LinqExpressionType + { + Equal=0,//= + NotEqual=1,//!= + GreaterThan,//> + LessThan,//< + ThanOrEqual,//>= + LessThanOrEqual,//<= + In, + Contains,//Contains + NotContains//NotContains + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/LoggerType.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/LoggerType.cs new file mode 100644 index 0000000000000000000000000000000000000000..c9ebd9a49c6b664dc59c717d2df04b680b28d5e6 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/LoggerType.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.Enums +{ + public enum LoggerType + { + System = 0, + Info, + Success, + Error, + Authorzie, + Global, + Login, + Exception, + ApiException, + HandleError, + OnActionExecuted, + GetUserInfo, + Edit, + Search, + Add, + Del, + AppHome, + ApiLogin, + ApiPINLogin, + ApiRegister, + ApiModifyPwd, + ApiSendPIN, + ApiAuthorize, + Ask, + JoinMeeting, + JoinUs, + EditUserInfo, + Sell, + Buy, + ReportPrice, + Reply, + TechData, + TechSecondData, + DelPublicQuestion, + DelexpertQuestion, + CreateTokenError, + IPhoneTest, + SDKSuccess, + SDKSendError, + ExpertAuthority, + ParEmpty, + NoToken, + ReplaceToeken, + KafkaException + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/QueryOrderBy.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/QueryOrderBy.cs new file mode 100644 index 0000000000000000000000000000000000000000..ab63f4debc7dd08034fcb1dbcaae97c53c1a66c7 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/QueryOrderBy.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.Enums +{ + public enum QueryOrderBy + { + Desc=1, + Asc=2 + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/ResponseType.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/ResponseType.cs new file mode 100644 index 0000000000000000000000000000000000000000..aa5ea5b227b3252da6936e9dcbda2b1e0f953c74 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/ResponseType.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.Enums +{ + public enum ResponseType + { + ServerError = 1, + LoginExpiration = 302, + ParametersLack = 303, + TokenExpiration, + PINError, + NoPermissions, + NoRolePermissions, + LoginError, + AccountLocked, + LoginSuccess, + SaveSuccess, + AuditSuccess, + OperSuccess, + RegisterSuccess, + ModifyPwdSuccess, + EidtSuccess, + DelSuccess, + NoKey, + NoKeyDel, + KeyError, + Other + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/UserAgent.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/UserAgent.cs new file mode 100644 index 0000000000000000000000000000000000000000..34d5ad99ac3e699f9bf3c7f6cbdfb53ab1e8fc34 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Enums/UserAgent.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.Enums +{ + public enum UserAgent + { + IOS = 0, + Android = 1, + Windows = 2, + Linux + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/AuthorizationResponse.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/AuthorizationResponse.cs new file mode 100644 index 0000000000000000000000000000000000000000..55ccbbb73eb7bf73aa8af1100d786e48656374b7 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/AuthorizationResponse.cs @@ -0,0 +1,44 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using System.IdentityModel.Tokens.Jwt; +using System.Net; +using System.Security.Claims; +using VOL.Core.Configuration; +using VOL.Core.Enums; +using VOL.Core.Services; +using VOL.Core.Utilities; + +namespace VOL.Core.Extensions +{ + public static class AuthorizationResponse + { + public static AuthorizationFilterContext FilterResult( + this AuthorizationFilterContext context, + HttpStatusCode statusCode, + string message = null) + { + context.Result = new ContentResult() + { + Content = new { message, status = false, code = (int)statusCode }.Serialize(), + ContentType = "application/json", + StatusCode = (int)statusCode + }; + Logger.Info(LoggerType.ApiAuthorize, message); + return context; + } + public static AuthorizationFilterContext Unauthorized(this AuthorizationFilterContext context, string message = null) + { + return context.FilterResult(HttpStatusCode.Unauthorized, message); + } + //不通过JWT验证的,直接将用户信息缓存起来 + public static void AddIdentity(this AuthorizationFilterContext context, int? userId=null) + { + int _userId = userId ?? JwtHelper.GetUserId(context.HttpContext.Request.Headers[AppSetting.TokenHeaderName]); + if (_userId <= 0) return; + //将用户Id缓存到上下文(或者自定一个对象,通过DI以AddScoped方式注入上下文来管理用户信息) + var claims = new Claim[] { new Claim(JwtRegisteredClaimNames.Jti, _userId.ToString()) }; + context.HttpContext.User.AddIdentity(new ClaimsIdentity(claims)); + } + } + +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/AutofacManager/AutofacContainerModule.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/AutofacManager/AutofacContainerModule.cs new file mode 100644 index 0000000000000000000000000000000000000000..105bad3b34a01656d242431c97bcf2bc5e7b027f --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/AutofacManager/AutofacContainerModule.cs @@ -0,0 +1,14 @@ +using VOL.Core.Extensions; +using System; +using VOL.Core.Configuration; + +namespace VOL.Core.Extensions.AutofacManager +{ + public class AutofacContainerModule + { + public static TService GetService() where TService:class + { + return typeof(TService).GetService() as TService; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/AutofacManager/AutofacContainerModuleExtension.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/AutofacManager/AutofacContainerModuleExtension.cs new file mode 100644 index 0000000000000000000000000000000000000000..da7f44dfabf384044551b86caf25ede49c462457 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/AutofacManager/AutofacContainerModuleExtension.cs @@ -0,0 +1,105 @@ +using Autofac; +using Autofac.Extensions.DependencyInjection; +using Dapper; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyModel; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Runtime.Loader; +using VOL.Core.CacheManager; +using VOL.Core.Configuration; +using VOL.Core.Const; +using VOL.Core.Dapper; +using VOL.Core.DBManager; +using VOL.Core.EFDbContext; +using VOL.Core.Enums; +using VOL.Core.Extensions.AutofacManager; +//using VOL.Core.KafkaManager.IService; +//using VOL.Core.KafkaManager.Service; +using VOL.Core.ManageUser; +using VOL.Core.ObjectActionValidator; +using VOL.Core.Services; + +namespace VOL.Core.Extensions +{ + public static class AutofacContainerModuleExtension + { + // private static bool _isMysql = false; + public static IServiceCollection AddModule(this IServiceCollection services, ContainerBuilder builder, IConfiguration configuration) + { + //services.AddSession(); + //services.AddMemoryCache(); + //初始化配置文件 + AppSetting.Init(services, configuration); + Type baseType = typeof(IDependency); + var compilationLibrary = DependencyContext.Default + .RuntimeLibraries + .Where(x => !x.Serviceable + && x.Type == "project") + .ToList(); + var count1 = compilationLibrary.Count; + List assemblyList = new List(); + + foreach (var _compilation in compilationLibrary) + { + try + { + assemblyList.Add(AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(_compilation.Name))); + } + catch (Exception ex) + { + Console.WriteLine(_compilation.Name + ex.Message); + } + } + builder.RegisterAssemblyTypes(assemblyList.ToArray()) + .Where(type => baseType.IsAssignableFrom(type) && !type.IsAbstract) + .AsSelf().AsImplementedInterfaces() + .InstancePerLifetimeScope(); + builder.RegisterType().InstancePerLifetimeScope(); + builder.RegisterType().InstancePerLifetimeScope(); + //model校验结果 + builder.RegisterType().InstancePerLifetimeScope(); + string connectionString = DBServerProvider.GetConnectionString(null); + + if (DBType.Name == DbCurrentType.MySql.ToString()) + { + //2020.03.31增加dapper对mysql字段Guid映射 + SqlMapper.AddTypeHandler(new DapperParseGuidTypeHandler()); + SqlMapper.RemoveTypeMap(typeof(Guid?)); + + //services.AddDbContext(); + //mysql8.x的版本使用Pomelo.EntityFrameworkCore.MySql 3.1会产生异常,需要在字符串连接上添加allowPublicKeyRetrieval=true + services.AddDbContextPool(optionsBuilder => { optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)); }, 64); + } + else if (DBType.Name == DbCurrentType.PgSql.ToString()) + { + services.AddDbContextPool(optionsBuilder => { optionsBuilder.UseNpgsql(connectionString); }, 64); + } + else + { + services.AddDbContextPool(optionsBuilder => { optionsBuilder.UseSqlServer(connectionString); }, 64); + } + //启用缓存 + if (AppSetting.UseRedis) + { + builder.RegisterType().As().SingleInstance(); + } + else + { + builder.RegisterType().As().SingleInstance(); + } + //kafka注入 + //if (AppSetting.Kafka.UseConsumer) + // builder.RegisterType>().As>().SingleInstance(); + //if (AppSetting.Kafka.UseProducer) + // builder.RegisterType>().As>().SingleInstance(); + return services; + } + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/AutofacManager/IDependency.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/AutofacManager/IDependency.cs new file mode 100644 index 0000000000000000000000000000000000000000..76814fc7af854c62f9f13909af1cc1b39be35c84 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/AutofacManager/IDependency.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VOL.Core.Extensions.AutofacManager +{ + public interface IDependency + { + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/CacheKeyExtensions.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/CacheKeyExtensions.cs new file mode 100644 index 0000000000000000000000000000000000000000..b9cc16c083ac4adc5bd980140ec0e1b08a74f6d9 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/CacheKeyExtensions.cs @@ -0,0 +1,23 @@ +using VOL.Core.Enums; +using System; + +namespace VOL.Core.Extensions +{ + public static class CacheKeyExtensions + { + public static string GetKey(this CPrefix prefix, object value) + { + return prefix.ToString() + value; + } + + public static string GetUserIdKey(this int userId) + { + return CPrefix.UID.ToString() + userId; + } + + public static string GetRoleIdKey(this int roleId) + { + return CPrefix.Role.ToString() + roleId; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/ConvertJsonExtension.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/ConvertJsonExtension.cs new file mode 100644 index 0000000000000000000000000000000000000000..ffd204e5d1b00d835128b5b51deb12828d311ac3 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/ConvertJsonExtension.cs @@ -0,0 +1,360 @@ +using Newtonsoft.Json; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Reflection; +using System.Text; +namespace VOL.Core.Extensions +{ + public static class ConvertJsonExtension + { + #region 私有方法 + /// + /// 过滤特殊字符 + /// + /// 字符串 + /// json字符串 + private static string String2Json(String s) + { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < s.Length; i++) + { + char c = s.ToCharArray()[i]; + switch (c) + { + case '\"': + sb.Append("\\\""); break; + case '\\': + sb.Append("\\\\"); break; + case '/': + sb.Append("\\/"); break; + case '\b': + sb.Append("\\b"); break; + case '\f': + sb.Append("\\f"); break; + case '\n': + sb.Append("\\n"); break; + case '\r': + sb.Append("\\r"); break; + case '\t': + sb.Append("\\t"); break; + default: + sb.Append(c); break; + } + } + return sb.ToString(); + } + /// + /// 格式化字符型、日期型、布尔型 + /// + /// + /// + /// + private static string StringFormat(string str, Type type) + { + if (type == typeof(string)) + { + str = String2Json(str); + str = "\"" + str + "\""; + } + else if (type == typeof(DateTime)) + { + str = "\"" + str + "\""; + } + else if (type == typeof(bool)) + { + str = str.ToLower(); + } + else if (type != typeof(string) && string.IsNullOrEmpty(str)) + { + str = "\"" + str + "\""; + } + return str; + } + + #endregion + + #region list转换成JSON + /// + /// list转换为Json + /// + /// + /// + /// + public static string ListToJson(this IList list) + { + object obj = list[0]; + return ListToJson(list, obj.GetType().Name); + } + /// + /// list转换为json + /// + /// + /// + /// + /// + private static string ListToJson(this IList list, string JsonName) + { + if (list.Count == 0) + { + return ""; + } + StringBuilder Json = new StringBuilder(); + if (string.IsNullOrEmpty(JsonName)) + JsonName = list[0].GetType().Name; + Json.Append("{\"" + JsonName + "\":["); + + for (int i = 0; i < list.Count; i++) + { + T obj = Activator.CreateInstance(); + PropertyInfo[] pi = obj.GetType().GetProperties(); + Json.Append("{"); + for (int j = 0; j < pi.Length; j++) + { + Type type = pi[j].GetValue(list[i], null).GetType(); + Json.Append("\"" + pi[j].Name.ToString() + "\":" + StringFormat(pi[j].GetValue(list[i], null).ToString(), type)); + if (j < pi.Length - 1) + { + Json.Append(","); + } + } + Json.Append("}"); + if (i < list.Count - 1) + { + Json.Append(","); + } + } + Json.Append("]}"); + return Json.ToString(); + } + #endregion + + #region 对象转换为Json + /// + /// 对象转换为json + /// + /// json对象 + /// json字符串 + public static string ToJson(this object jsonObject) + { + string jsonString = "{"; + PropertyInfo[] propertyInfo = jsonObject.GetType().GetProperties(); + for (int i = 0; i < propertyInfo.Length; i++) + { + object objectValue = propertyInfo[i].GetGetMethod().Invoke(jsonObject, null); + string value = string.Empty; + if (objectValue is DateTime || objectValue is Guid || objectValue is TimeSpan) + { + value = "'" + objectValue.ToString() + "'"; + } + else if (objectValue is string) + { + value = "'" + ToJson(objectValue.ToString()) + "'"; + } + else if (objectValue is IEnumerable) + { + value = ToJson((IEnumerable)objectValue); + } + else + { + value = ToJson(objectValue.ToString()); + } + jsonString += "\"" + ToJson(propertyInfo[i].Name) + "\":" + value + ","; + } + jsonString.Remove(jsonString.Length - 1, jsonString.Length); + return jsonString + "}"; + } + + #endregion + + #region 对象集合转换为json + /// + /// 对象集合转换为json + /// + /// 对象集合 + /// json字符串 + public static string ToJson(this IEnumerable array) + { + string jsonString = "{"; + foreach (object item in array) + { + jsonString += ToJson(item) + ","; + } + jsonString.Remove(jsonString.Length - 1, jsonString.Length); + return jsonString + "]"; + } + #endregion + + #region 普通集合转换Json + /// + /// 普通集合转换Json + /// + /// 集合对象 + /// Json字符串 + public static string ToArrayString(this IEnumerable array) + { + string jsonString = "["; + foreach (object item in array) + { + jsonString = ToJson(item.ToString()) + ","; + } + jsonString.Remove(jsonString.Length - 1, jsonString.Length); + return jsonString + "]"; + } + #endregion + + #region DataSet转换为Json + /// + /// DataSet转换为Json + /// + /// DataSet对象 + /// Json字符串 + public static string ToJson(this DataSet dataSet) + { + string jsonString = "{"; + foreach (DataTable table in dataSet.Tables) + { + jsonString += "\"" + table.TableName + "\":" + ToJson(table) + ","; + } + jsonString = jsonString.TrimEnd(','); + return jsonString + "}"; + } + #endregion + + #region Datatable转换为Json + /// + /// Datatable转换为Json + /// + /// Datatable对象 + /// Json字符串 + public static string ToJson(this DataTable dt) + { + StringBuilder jsonString = new StringBuilder(); + jsonString.Append("["); + DataRowCollection drc = dt.Rows; + for (int i = 0; i < drc.Count; i++) + { + jsonString.Append("{"); + for (int j = 0; j < dt.Columns.Count; j++) + { + string strKey = dt.Columns[j].ColumnName; + string strValue = drc[i][j].ToString(); + Type type = dt.Columns[j].DataType; + jsonString.Append("\"" + strKey + "\":"); + strValue = StringFormat(strValue, type); + if (j < dt.Columns.Count - 1) + { + jsonString.Append(strValue + ","); + } + else + { + jsonString.Append(strValue); + } + } + jsonString.Append("},"); + } + jsonString.Remove(jsonString.Length - 1, 1); + jsonString.Append("]"); + return jsonString.ToString(); + } + /// + /// DataTable转换为Json + /// + public static string ToJson(this DataTable dt, string jsonName) + { + StringBuilder Json = new StringBuilder(); + if (string.IsNullOrEmpty(jsonName)) + jsonName = dt.TableName; + Json.Append("{\"" + jsonName + "\":["); + if (dt.Rows.Count > 0) + { + for (int i = 0; i < dt.Rows.Count; i++) + { + Json.Append("{"); + for (int j = 0; j < dt.Columns.Count; j++) + { + Type type = dt.Rows[i][j].GetType(); + Json.Append("\"" + dt.Columns[j].ColumnName.ToString() + "\":" + StringFormat(dt.Rows[i][j].ToString(), type)); + if (j < dt.Columns.Count - 1) + { + Json.Append(","); + } + } + Json.Append("}"); + if (i < dt.Rows.Count - 1) + { + Json.Append(","); + } + } + } + Json.Append("]}"); + return Json.ToString(); + } + + #endregion + + #region DataReader转换为Json + /// + /// DataReader转换为Json + /// + /// DataReader对象 + /// Json字符串 + public static string ReaderJson(this IDataReader dataReader) + { + StringBuilder jsonString = new StringBuilder(); + Dictionary ModelField = new Dictionary(); + for (int i = 0; i < dataReader.FieldCount; i++) + { + ModelField.Add(dataReader.GetName(i), dataReader.GetFieldType(i)); + } + jsonString.Append("["); + while (dataReader.Read()) + { + jsonString.Append("{"); + foreach (KeyValuePair keyVal in ModelField) + { + Type type = keyVal.Value; + string strKey = keyVal.Key; + string strValue = dataReader[strKey].ToString(); + jsonString.Append("\"" + strKey + "\":"); + strValue = StringFormat(strValue, type); + jsonString.Append(strValue + ","); + } + jsonString.Remove(jsonString.Length - 1, 1); + jsonString.Append("},"); + } + dataReader.Close(); + jsonString.Remove(jsonString.Length - 1, 1); + jsonString.Append("]"); + return jsonString.ToString(); + } + #endregion + + + public static T DeserializeObject(this string entityString) + { + if (string.IsNullOrEmpty(entityString)) + { + return default(T); + } + if (entityString == "{}") + { + entityString = "[]"; + } + return JsonConvert.DeserializeObject(entityString); + } + + public static string Serialize(this object obj, JsonSerializerSettings formatDate = null) + { + if (obj == null) return null; + formatDate = formatDate ?? new JsonSerializerSettings + { + DateFormatString = "yyyy-MM-dd HH:mm:ss" + }; + return JsonConvert.SerializeObject(obj, formatDate); + } + + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/EntityProperties.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/EntityProperties.cs new file mode 100644 index 0000000000000000000000000000000000000000..d4667cd212fe62c7179775f52b43a89843857fd8 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/EntityProperties.cs @@ -0,0 +1,1454 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Data; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using VOL.Core.Configuration; +using VOL.Core.Const; +using VOL.Core.Enums; +using VOL.Core.Utilities; +using VOL.Entity; +using VOL.Entity.DomainModels; +/* +* jxx 2017-08-09 +* 通用实体属操作 +*/ + +namespace VOL.Core.Extensions +{ + public static class EntityProperties + { + public static IQueryable Where(this IQueryable queryable, [NotNull] Expression> field, string value) + { + if (value == null) + { + value = ""; + } + return queryable.Where(field.GetExpressionPropertyFirst().CreateExpression(value, LinqExpressionType.Equal)); + } + + public static IQueryable Where(this IQueryable queryable, string field, string value) + { + if (value == null) + { + value = ""; + } + return queryable.Where(field.CreateExpression(value, LinqExpressionType.Equal)); + } + + public static IQueryable Where(this IQueryable queryable, string field, string[] values) + { + if (values == null || values.Length == 0) + { + return queryable.Where(x => false); + } + return queryable.Where(field.CreateExpression(values, LinqExpressionType.In)); + } + + /// + /// 如果值为null则不生成条件 + /// + /// + /// + /// + /// + /// + /// + public static IQueryable WhereNotEmpty(this IQueryable queryable, string field, string value, LinqExpressionType linqExpression = LinqExpressionType.Equal) + { + if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(field)) return queryable; + return queryable.Where(field.CreateExpression(value, linqExpression)); + } + + public static IQueryable WhereNotEmpty(this IQueryable queryable, [NotNull] Expression> field, string value, LinqExpressionType linqExpression = LinqExpressionType.Equal) + { + if (string.IsNullOrEmpty(value)) return queryable; + return queryable.Where(field.GetExpressionPropertyFirst().CreateExpression(value, linqExpression)); + } + + public static string GetExpressionPropertyFirst(this Expression> properties) + { + string[] arr = properties.GetExpressionProperty(); + if (arr.Length > 0) + return arr[0]; + return ""; + } + /// + /// 获取对象里指定成员名称 + /// + /// + /// 格式 Expression> exp = x => new { x.字段1, x.字段2 };或x=>x.Name + /// + public static string[] GetExpressionProperty(this Expression> properties) + { + if (properties == null) + return new string[] { }; + if (properties.Body is NewExpression) + return ((NewExpression)properties.Body).Members.Select(x => x.Name).ToArray(); + if (properties.Body is MemberExpression) + return new string[] { ((MemberExpression)properties.Body).Member.Name }; + if (properties.Body is UnaryExpression) + return new string[] { ((properties.Body as UnaryExpression).Operand as MemberExpression).Member.Name }; + throw new Exception("未实现的表达式"); + } + public static string ValidateHashInEntity(this Type typeinfo, Dictionary dic) + { + return typeinfo.ValidateDicInEntity(dic, false); + } + + public static void RemoveNotExistColumns(this Type typeinfo, List cols) + { + + } + + /// + /// 获取所有字段的名称 + /// + /// + /// + public static List GetAtrrNames(this Type typeinfo) + { + return typeinfo.GetProperties().Select(c => c.Name).ToList(); + } + public static void IsExistColumns(this Type typeinfo) + { + + } + public static Dictionary GetColumType(this PropertyInfo[] properties) + { + return properties.GetColumType(false); + } + public static Dictionary GetColumType(this PropertyInfo[] properties, bool containsKey) + { + Dictionary dictionary = new Dictionary(); + foreach (PropertyInfo property in properties) + { + if (!containsKey && property.IsKey()) + { + continue; + } + var keyVal = GetColumnType(property, true); + dictionary.Add(keyVal.Key, keyVal.Value); + } + return dictionary; + } + + private static readonly Dictionary entityMapDbColumnType = new Dictionary() { + {typeof(int),SqlDbTypeName.Int }, + {typeof(int?),SqlDbTypeName.Int }, + {typeof(long),SqlDbTypeName.BigInt }, + {typeof(long?),SqlDbTypeName.BigInt }, + {typeof(decimal),"decimal(18, 5)" }, + {typeof(decimal?),"decimal(18, 5)" }, + {typeof(double),"decimal(18, 5)" }, + {typeof(double?),"decimal(18, 5)" }, + {typeof(float),"decimal(18, 5)" }, + {typeof(float?),"decimal(18, 5)" }, + {typeof(Guid),"UniqueIdentifier" }, + {typeof(Guid?),"UniqueIdentifier" }, + {typeof(byte),"tinyint" }, + {typeof(byte?),"tinyint" }, + {typeof(string),"nvarchar" } + }; + /// + /// 返回属性的字段及数据库类型 + /// + /// + /// 是否包括后字段具体长度:nvarchar(100) + /// + public static KeyValuePair GetColumnType(this PropertyInfo property, bool lenght = false) + { + string colType = ""; + object objAtrr = property.GetTypeCustomAttributes(typeof(ColumnAttribute), out bool asType); + if (asType) + { + colType = ((ColumnAttribute)objAtrr).TypeName.ToLower(); + if (!string.IsNullOrEmpty(colType)) + { + //不需要具体长度直接返回 + if (!lenght) + { + return new KeyValuePair(property.Name, colType); + } + if (colType == "decimal" || colType == "double" || colType == "float") + { + objAtrr = property.GetTypeCustomAttributes(typeof(DisplayFormatAttribute), out asType); + colType += "(" + (asType ? ((DisplayFormatAttribute)objAtrr).DataFormatString : "18,5") + ")"; + + } + ///如果是string,根据 varchar或nvarchar判断最大长度 + if (property.PropertyType.ToString() == "System.String") + { + colType = colType.Split("(")[0]; + objAtrr = property.GetTypeCustomAttributes(typeof(MaxLengthAttribute), out asType); + if (asType) + { + int length = ((MaxLengthAttribute)objAtrr).Length; + colType += "(" + (length < 1 || length > (colType.StartsWith("n") ? 8000 : 4000) ? "max" : length.ToString()) + ")"; + } + else + { + colType += "(max)"; + } + } + return new KeyValuePair(property.Name, colType); + } + } + if (entityMapDbColumnType.TryGetValue(property.PropertyType, out string value)) + { + colType = value; + } + else + { + colType = SqlDbTypeName.NVarChar; + } + if (lenght && colType == SqlDbTypeName.NVarChar) + { + colType = "nvarchar(max)"; + } + return new KeyValuePair(property.Name, colType); + } + + /// + /// + /// + /// 将数组转换成sql语句 + /// 指定FieldType数据库字段类型 + /// + /// + public static string GetArraySql(this object[] array, FieldType fieldType) + { + if (array == null || array.Count() == 0) + { + return string.Empty; + } + string columnType = string.Empty; + List arrrayEntityList = array.Select(x => new ArrayEntity { column1 = x.ToString() }).ToList(); + return arrrayEntityList.GetEntitySql(false, null, null, null, fieldType); + } + /// + ///要执行的sql语句如:通过EntityToSqlTempName.Temp_Insert0.ToString()字符串占位,生成的的sql语句会把EntityToSqlTempName.Temp_Insert0.ToString()替换成生成的sql临时表数据 + /// string sql = " ;DELETE FROM " + typeEntity.Name + " where " + typeEntity.GetKeyName() + + /// " in (select * from " + EntityToSqlTempName.Temp_Insert0.ToString() + ")"; + /// + /// + /// + /// 指定生成的数组值的类型 + /// + /// + public static string GetArraySql(this object[] array, FieldType fieldType, string sql) + { + if (array == null || array.Count() == 0) + { + return string.Empty; + } + string columnType = string.Empty; + List arrrayEntityList = array.Select(x => new ArrayEntity { column1 = x.ToString() }).ToList(); + return arrrayEntityList.GetEntitySql(false, sql, null, null, fieldType); + } + public static string GetArraySql(this object[] array, string sql) + { + return array.GetArraySql(typeof(T).GetFieldType(), sql); + } + /// + /// 根据实体获取key的类型,用于update或del操作 + /// + /// + /// + public static FieldType GetFieldType(this Type typeEntity) + { + FieldType fieldType; + string columnType = typeEntity.GetProperties().Where(x => x.Name == typeEntity.GetKeyName()).ToList()[0].GetColumnType(false).Value; + switch (columnType) + { + case SqlDbTypeName.Int: fieldType = FieldType.Int; break; + case SqlDbTypeName.BigInt: fieldType = FieldType.BigInt; break; + case SqlDbTypeName.VarChar: fieldType = FieldType.VarChar; break; + case SqlDbTypeName.UniqueIdentifier: fieldType = FieldType.UniqueIdentifier; break; + default: fieldType = FieldType.NvarChar; break; + } + return fieldType; + } + public static string GetEntitySql(this IEnumerable entityList, + bool containsKey = false, + string sql = null, + Expression> ignoreFileds = null, + Expression> fixedColumns = null, + FieldType? fieldType = null + ) + { + + if (entityList == null || entityList.Count() == 0) return ""; + PropertyInfo[] propertyInfo = typeof(T).GetProperties().ToArray(); + if (propertyInfo.Count() == 0) + { + propertyInfo = entityList.ToArray()[0].GetType().GetGenericProperties().ToArray(); + } + propertyInfo = propertyInfo.GetGenericProperties().ToArray(); + + string[] arr = null; + if (fixedColumns != null) + { + arr = fixedColumns.GetExpressionToArray(); + PropertyInfo keyProperty = typeof(T).GetKeyProperty(); + propertyInfo = propertyInfo.Where(x => (containsKey && x.Name == keyProperty.Name) || arr.Contains(x.Name)).ToArray(); + } + if (ignoreFileds != null) + { + arr = ignoreFileds.GetExpressionToArray(); + propertyInfo = propertyInfo.Where(x => !arr.Contains(x.Name)).ToArray(); + } + + Dictionary dictProperties = propertyInfo.GetColumType(containsKey); + if (fieldType != null) + { + string realType = fieldType.ToString(); + if ((int)fieldType == 0 || (int)fieldType == 1) + { + realType += "(max)"; + } + dictProperties = new Dictionary { { dictProperties.Select(x => x.Key).ToList()[0], realType } }; + } + if (dictProperties.Keys.Count * entityList.Count() > 50 * 3000) + { + throw new Exception("写入数据太多,请分开写入。"); + } + + string cols = string.Join(",", dictProperties.Select(c => "[" + c.Key + "]" + " " + c.Value)); + StringBuilder declareTable = new StringBuilder(); + + string tempTablbe = "#" + EntityToSqlTempName.TempInsert.ToString(); + + declareTable.Append("CREATE TABLE " + tempTablbe + " (" + cols + ")"); + declareTable.Append("\r\n"); + + //参数总数量 + int parCount = (dictProperties.Count) * (entityList.Count()); + int takeCount = 0; + int maxParsCount = 2050; + if (parCount > maxParsCount) + { + //如果参数总数量超过2100,设置每次分批循环写入表的大小 + takeCount = maxParsCount / dictProperties.Count; + } + + int count = 0; + StringBuilder stringLeft = new StringBuilder(); + StringBuilder stringCenter = new StringBuilder(); + StringBuilder stringRight = new StringBuilder(); + + int index = 0; + foreach (T entity in entityList) + { + //每1000行需要分批写入(数据库限制每批至多写入1000行数据) + if (index == 0 || index >= 1000 || takeCount - index == 0) + { + if (stringLeft.Length > 0) + { + declareTable.AppendLine( + stringLeft.Remove(stringLeft.Length - 2, 2).Append("',").ToString() + + stringCenter.Remove(stringCenter.Length - 1, 1).Append("',").ToString() + + stringRight.Remove(stringRight.Length - 1, 1).ToString()); + + stringLeft.Clear(); stringCenter.Clear(); stringRight.Clear(); + } + + stringLeft.AppendLine("exec sp_executesql N'SET NOCOUNT ON;"); + stringCenter.Append("N'"); + + index = 0; count = 0; + } + stringLeft.Append(index == 0 ? "; INSERT INTO " + tempTablbe + " values (" : " "); + index++; + foreach (PropertyInfo property in propertyInfo) + { + if (!containsKey && property.IsKey()) { continue; } + string par = "@v" + count; + stringLeft.Append(par + ","); + stringCenter.Append(par + " " + dictProperties[property.Name] + ","); + object val = property.GetValue(entity); + if (val == null) + { + stringRight.Append(par + "=NUll,"); + } + else + { + stringRight.Append(par + "='" + val.ToString().Replace("'", "''''") + "',"); + } + count++; + } + stringLeft.Remove(stringLeft.Length - 1, 1); + stringLeft.Append("),("); + } + + if (stringLeft.Length > 0) + { + declareTable.AppendLine( + stringLeft.Remove(stringLeft.Length - 2, 2).Append("',").ToString() + + stringCenter.Remove(stringCenter.Length - 1, 1).Append("',").ToString() + + stringRight.Remove(stringRight.Length - 1, 1).ToString()); + + stringLeft.Clear(); stringCenter.Clear(); stringRight.Clear(); + } + if (!string.IsNullOrEmpty(sql)) + { + sql = sql.Replace(EntityToSqlTempName.TempInsert.ToString(), tempTablbe); + declareTable.AppendLine(sql); + } + else + { + declareTable.AppendLine(" SELECT " + (string.Join(",", fixedColumns?.GetExpressionToArray() ?? new string[] { "*" })) + " FROM " + tempTablbe); + } + + + if (tempTablbe.Substring(0, 1) == "#") + { + declareTable.AppendLine("; drop table " + tempTablbe); + } + return declareTable.ToString(); + } + + + /// + ///此方法适用于数据量少,只有几列数据,不超过1W行,或几十列数据不超过1000行的情况下使用 + /// 大批量的数据考虑其他方式 + /// 將datatable生成sql語句,替換datatable作為參數傳入存儲過程 + /// + /// + /// + public static string GetDataTableSql(this DataTable table) + { + Dictionary dictCloumn = new Dictionary(); + for (int i = 0; i < table.Columns.Count; i++) + { + dictCloumn.Add(table.Columns[i].ColumnName, " nvarchar(max)"); + } + + + //参数总数量 + int parCount = (dictCloumn.Count) * (table.Rows.Count); + int takeCount = 0; + int maxParsCount = 2050; + if (parCount > maxParsCount) + { + //如果参数总数量超过2100,设置每次分批循环写入表的大小 + takeCount = maxParsCount / dictCloumn.Count; + } + + if (dictCloumn.Keys.Count * table.Rows.Count > 50 * 3000) + { + throw new Exception("写入数据太多,请分开写入。"); + } + + string cols = string.Join(",", dictCloumn.Select(c => "[" + c.Key + "]" + " " + c.Value)); + StringBuilder declareTable = new StringBuilder(); + + string tempTablbe = "#Temp_Insert0"; + declareTable.Append("CREATE TABLE " + tempTablbe + " (" + cols + ")"); + declareTable.Append("\r\n"); + int count = 0; + StringBuilder stringLeft = new StringBuilder(); + StringBuilder stringCenter = new StringBuilder(); + StringBuilder stringRight = new StringBuilder(); + + int index = 0; + + foreach (DataRow row in table.Rows) + { + //每1000行需要分批写入(数据库限制每批至多写入1000行数据) + if (index == 0 || index >= 1000 || takeCount - index == 0) + { + if (stringLeft.Length > 0) + { + declareTable.AppendLine( + stringLeft.Remove(stringLeft.Length - 2, 2).Append("',").ToString() + + stringCenter.Remove(stringCenter.Length - 1, 1).Append("',").ToString() + + stringRight.Remove(stringRight.Length - 1, 1).ToString()); + + stringLeft.Clear(); stringCenter.Clear(); stringRight.Clear(); + } + // sbLeft.AppendLine(" INSERT INTO @toInsert0"); + stringLeft.AppendLine("exec sp_executesql N'SET NOCOUNT ON;"); + stringCenter.Append("N'"); + + index = 0; count = 0; + } + stringLeft.Append(index == 0 ? "; INSERT INTO " + tempTablbe + " values (" : " "); + index++; + foreach (KeyValuePair keyValue in dictCloumn) + { + string par = "@v" + count; + stringLeft.Append(par + ","); + stringCenter.Append(par + " " + keyValue.Value + ","); + object val = row[keyValue.Key]; + if (val == null) + { + stringRight.Append(par + "=NUll,"); + } + else + { + stringRight.Append(par + "='" + val.ToString().Replace("'", "''''") + "',"); + } + count++; + } + stringLeft.Remove(stringLeft.Length - 1, 1); + stringLeft.Append("),("); + } + + + + + if (stringLeft.Length > 0) + { + + declareTable.AppendLine( + stringLeft.Remove(stringLeft.Length - 2, 2).Append("',").ToString() + + stringCenter.Remove(stringCenter.Length - 1, 1).Append("',").ToString() + + stringRight.Remove(stringRight.Length - 1, 1).ToString()); + + stringLeft.Clear(); stringCenter.Clear(); stringRight.Clear(); + } + declareTable.AppendLine(" SELECT * FROM " + tempTablbe); + if (tempTablbe.Substring(0, 1) == "#") + { + declareTable.AppendLine("; drop table " + tempTablbe); + } + return declareTable.ToString(); + } + + + + public static string GetKeyName(this Type typeinfo) + { + return typeinfo.GetProperties().GetKeyName(); + } + public static string GetKeyType(this Type typeinfo) + { + string keyType = typeinfo.GetProperties().GetKeyName(true); + if (keyType == "varchar") + { + return "varchar(max)"; + } + else if (keyType != "nvarchar") + { + return keyType; + } + else + { + return "nvarchar(max)"; + } + } + public static string GetKeyName(this PropertyInfo[] properties) + { + return properties.GetKeyName(false); + } + /// + /// 获取key列名 + /// + /// + /// true获取key对应类型,false返回对象Key的名称 + /// + public static string GetKeyName(this PropertyInfo[] properties, bool keyType) + { + string keyName = string.Empty; + foreach (PropertyInfo propertyInfo in properties) + { + if (!propertyInfo.IsKey()) + continue; + if (!keyType) + return propertyInfo.Name; + var attributes = propertyInfo.GetCustomAttributes(typeof(ColumnAttribute), false); + //如果没有ColumnAttribute的需要单独再验证,下面只验证有属性的 + if (attributes.Length > 0) + return ((ColumnAttribute)attributes[0]).TypeName.ToLower(); + else + return GetColumType(new PropertyInfo[] { propertyInfo }, true)[propertyInfo.Name]; + } + return keyName; + } + + /// + /// 获取主键字段 + /// + /// + /// + public static PropertyInfo GetKeyProperty(this Type entity) + { + return entity.GetProperties().GetKeyProperty(); + } + public static PropertyInfo GetKeyProperty(this PropertyInfo[] properties) + { + return properties.Where(c => c.IsKey()).FirstOrDefault(); + } + public static bool IsKey(this PropertyInfo propertyInfo) + { + object[] keyAttributes = propertyInfo.GetCustomAttributes(typeof(KeyAttribute), false); + if (keyAttributes.Length > 0) + return true; + return false; + } + + + private static string[] _userEditFields { get; set; } + + private static string[] UserEditFields + { + get + { + if (_userEditFields != null) return _userEditFields; + _userEditFields = AppSetting.CreateMember.GetType().GetProperties() + .Select(x => x.GetValue(AppSetting.ModifyMember)?.ToString()?.ToLower()) + .Where(w => !string.IsNullOrEmpty(w)).ToArray(); + return _userEditFields; + } + } + /// + /// 获取实体所有可以编辑的列 + /// + /// + /// + public static string[] GetEditField(this Type type) + { + Type editType = typeof(EditableAttribute); + PropertyInfo[] propertyInfo = type.GetProperties(); + string keyName = propertyInfo.GetKeyName(); + return propertyInfo.Where(x => x.Name != keyName && (UserEditFields.Contains(x.Name.ToLower()) || x.ContainsCustomAttributes(editType))).Select(s => s.Name).ToArray(); + } + + + /// + /// 判断是否包含某个属性: + /// 如 [Editable(true)] + // public string MO { get; set; }包含Editable + /// + /// + /// + /// + public static bool ContainsCustomAttributes(this PropertyInfo propertyInfo, Type type) + { + propertyInfo.GetTypeCustomAttributes(type, out bool contains); + return contains; + } + + public static List ContainsCustomAttributes(this Type obj, Type containType) + { + List proList = new List(); + foreach (PropertyInfo pro in obj.GetProperties()) + { + if (pro.GetTypeCustomAttributes(containType) != null) + { + proList.Add(pro); + } + } + return proList; + } + + /// + /// 获取PropertyInfo指定属性 + /// + /// + /// + /// + public static object GetTypeCustomAttributes(this PropertyInfo propertyInfo, Type type, out bool asType) + { + object[] attributes = propertyInfo.GetCustomAttributes(type, false); + if (attributes.Length == 0) + { + asType = false; + return new string[0]; + } + asType = true; + return attributes[0]; + } + + /// + /// 验证集合的属性 + /// + /// + /// + /// + /// + public static WebResponseContent ValidationEntityList(this List entityList, Expression> expression = null) + { + WebResponseContent responseData = new WebResponseContent(); + foreach (T entity in entityList) + { + responseData = entity.ValidationEntity(expression); + if (!responseData.Status) + { + return responseData; + } + } + responseData.Status = true; + return responseData; + } + /// + /// 指定需要验证的字段 + /// + /// + /// + /// 对指定属性进行验证x=>{x.Name,x.Size} + /// + public static WebResponseContent ValidationEntity(this T entity, Expression> expression = null, Expression> validateProperties = null) + { + return ValidationEntity(entity, expression?.GetExpressionProperty(), validateProperties?.GetExpressionProperty()); + } + /// + /// specificProperties=null并且validateProperties=null,对所有属性验证,只验证其是否合法,不验证是否为空(除属性标识指定了不能为空外) + /// specificProperties!=null,对指定属性校验,并且都必须有值 + /// null并且validateProperties!=null,对指定属性校验,不判断是否有值 + /// + /// + /// + /// 验证指定的属性,并且非空判断 + /// 验证指定属性,只对字段合法性判断,不验证是否为空 + /// + public static WebResponseContent ValidationEntity(this T entity, string[] specificProperties, string[] validateProperties = null) + { + WebResponseContent responseData = new WebResponseContent(); + if (entity == null) return responseData.Error("对象不能为null"); + + PropertyInfo[] propertyArray = typeof(T).GetProperties(); + //若T为object取不到属性 + if (propertyArray.Length == 0) + { + propertyArray = entity.GetType().GetProperties(); + } + List compareProper = new List(); + + //只验证数据合法性,验证非空 + if (specificProperties != null && specificProperties.Length > 0) + { + compareProper.AddRange(propertyArray.Where(x => specificProperties.Contains(x.Name))); + } + + //只验证数据合法性,不验证非空 + if (validateProperties != null && validateProperties.Length > 0) + { + compareProper.AddRange(propertyArray.Where(x => validateProperties.Contains(x.Name))); + } + if (compareProper.Count() > 0) + { + propertyArray = compareProper.ToArray(); + } + foreach (PropertyInfo propertyInfo in propertyArray) + { + object value = propertyInfo.GetValue(entity); + //设置默认状态的值 + if (propertyInfo.Name == "Enable" || propertyInfo.Name == "AuditStatus") + { + if (value == null) + { + propertyInfo.SetValue(entity, 0); + continue; + } + } + //若存在specificProperties并且属性为数组specificProperties中的值,校验时就需要判断是否为空 + var reslut = propertyInfo.ValidationProperty(value, + specificProperties != null && specificProperties.Contains(propertyInfo.Name) ? true : false + ); + if (!reslut.Item1) + return responseData.Error(reslut.Item2); + } + return responseData.OK(); + } + + /// + /// 获取数据库类型,不带长度,如varchar(100),只返回的varchar + /// + /// + /// + public static string GetSqlDbType(this PropertyInfo propertyInfo) + { + string dbType = propertyInfo.GetTypeCustomValue(x => new { x.TypeName }); + + if (string.IsNullOrEmpty(dbType)) + { + return dbType; + } + dbType = dbType.ToLower(); + if (dbType.Contains(SqlDbTypeName.NVarChar)) + { + dbType = SqlDbTypeName.NVarChar; + } + else if (dbType.Contains(SqlDbTypeName.VarChar)) + { + dbType = SqlDbTypeName.VarChar; + } + else if (dbType.Contains(SqlDbTypeName.NChar)) + { + dbType = SqlDbTypeName.NChar; + } + else if (dbType.Contains(SqlDbTypeName.Char)) + { + dbType = SqlDbTypeName.Char; + } + + return dbType; + } + + /// + /// 验证数据库字段类型与值是否正确, + /// + /// propertyInfo为当字段,当前字段必须有ColumnAttribute属性, + /// 如字段:标识为数据库int类型[Column(TypeName="int")] public int Id { get; set; } + /// 如果是小数float或Decimal必须对propertyInfo字段加DisplayFormatAttribute属性 + /// + /// + /// IEnumerable<(bool, string, object)> bool成否校验成功,string校验失败信息,object,当前校验的值 + public static IEnumerable<(bool, string, object)> ValidationValueForDbType(this PropertyInfo propertyInfo, params object[] values) + { + string dbTypeName = propertyInfo.GetTypeCustomValue(c => c.TypeName); + foreach (object value in values) + { + yield return dbTypeName.ValidationVal(value, propertyInfo); + } + } + + public static bool ValidationRquiredValueForDbType(this PropertyInfo propertyInfo, object value, out string message) + { + if (value == null || value?.ToString()?.Trim() == "") + { + message = $"{propertyInfo.GetDisplayName()}不能为空"; + return false; + } + var result = propertyInfo.GetProperWithDbType().ValidationVal(value, propertyInfo); + message = result.Item2; + return result.Item1; + } + + private static readonly Dictionary ProperWithDbType = new Dictionary() { + { typeof(string),SqlDbTypeName.NVarChar }, + { typeof(DateTime),SqlDbTypeName.DateTime}, + {typeof(long),SqlDbTypeName.BigInt }, + {typeof(int),SqlDbTypeName.Int}, + { typeof(decimal),SqlDbTypeName.Decimal }, + { typeof(float),SqlDbTypeName.Float }, + { typeof(double),SqlDbTypeName.Double }, + { typeof(byte),SqlDbTypeName.Int },//类型待完 + { typeof(Guid),SqlDbTypeName.UniqueIdentifier} + }; + public static string GetProperWithDbType(this PropertyInfo propertyInfo) + { + bool result = ProperWithDbType.TryGetValue(propertyInfo.PropertyType, out string value); + if (result) + { + return value; + } + return SqlDbTypeName.NVarChar; + } + + /// + /// 验证数据库字段类型与值是否正确, + /// + /// 数据库字段类型(如varchar,nvarchar,decimal,不要带后面长度如:varchar(50)) + /// 值 + /// 要验证的类的属性,若不为null,则会判断字符串的长度是否正确 + /// (bool, string, object)bool成否校验成功,string校验失败信息,object,当前校验的值 + public static (bool, string, object) ValidationVal(this string dbType, object value, PropertyInfo propertyInfo = null) + { + if (string.IsNullOrEmpty(dbType)) + { + dbType = propertyInfo != null ? propertyInfo.GetProperWithDbType() : SqlDbTypeName.NVarChar; + } + dbType = dbType.ToLower(); + string val = value?.ToString(); + //验证长度 + string reslutMsg = string.Empty; + if (dbType == SqlDbTypeName.Int) + { + if (!value.IsInt()) + reslutMsg = "只能为有效整数"; + } //2021.10.12增加属性校验long类型的支持 + else if (dbType == SqlDbTypeName.BigInt) + { + if (!long.TryParse(val, out _)) + { + reslutMsg = "只能为有效整数"; + } + } + else if (dbType == SqlDbTypeName.DateTime + || dbType == SqlDbTypeName.Date + || dbType == SqlDbTypeName.SmallDateTime + || dbType == SqlDbTypeName.SmallDate + ) + { + if (!value.IsDate()) + reslutMsg = "必须为日期格式"; + } + else if (dbType == SqlDbTypeName.Float || dbType == SqlDbTypeName.Decimal || dbType == SqlDbTypeName.Double) + { + //string formatString = string.Empty; + //if (propertyInfo != null) + // formatString = propertyInfo.GetTypeCustomValue(x => x.DataFormatString); + //if (string.IsNullOrEmpty(formatString)) + // throw new Exception("请对字段" + propertyInfo?.Name + "添加DisplayFormat属性标识"); + + if (!val.IsNumber(null)) + { + // string[] arr = (formatString ?? "10,0").Split(','); + // reslutMsg = $"整数{arr[0]}最多位,小数最多{arr[1]}位"; + reslutMsg = "不是有效数字"; + } + } + else if (dbType == SqlDbTypeName.UniqueIdentifier) + { + if (!val.IsGuid()) + { + reslutMsg = propertyInfo.Name + "Guid不正确"; + } + } + else if (propertyInfo != null + && (dbType == SqlDbTypeName.VarChar + || dbType == SqlDbTypeName.NVarChar + || dbType == SqlDbTypeName.NChar + || dbType == SqlDbTypeName.Char + || dbType == SqlDbTypeName.Text)) + { + + //默认nvarchar(max) 、text 长度不能超过20000 + if (val.Length > 200000) + { + reslutMsg = $"字符长度最多【200000】"; + } + else + { + int length = propertyInfo.GetTypeCustomValue(x => new { x.Length }).GetInt(); + if (length == 0) { return (true, null, null); } + //判断双字节与单字段 + else if (length < 8000 && + ((dbType.Substring(0, 1) != "n" + && Encoding.UTF8.GetBytes(val.ToCharArray()).Length > length) + || val.Length > length) + ) + { + reslutMsg = $"最多只能【{length}】个字符。"; + } + } + } + if (!string.IsNullOrEmpty(reslutMsg) && propertyInfo != null) + { + reslutMsg = propertyInfo.GetDisplayName() + reslutMsg; + } + return (reslutMsg == "" ? true : false, reslutMsg, value); + } + + public static string GetDisplayName(this PropertyInfo property) + { + string displayName = property.GetTypeCustomValue(x => new { x.Name }); + if (string.IsNullOrEmpty(displayName)) + { + return property.Name; + } + return displayName; + } + + /// + /// 验证每个属性的值是否正确 + /// + /// + /// 属性的值 + /// 是否指定当前属性必须有值 + /// + public static (bool, string, object) ValidationProperty(this PropertyInfo propertyInfo, object objectVal, bool required) + { + if (propertyInfo.IsKey()) { return (true, null, objectVal); } + + string val = objectVal == null ? "" : objectVal.ToString().Trim(); + + string requiredMsg = string.Empty; + if (!required) + { + var reuireVal = propertyInfo.GetTypeCustomValues(x => new { x.AllowEmptyStrings, x.ErrorMessage }); + if (reuireVal != null && !Convert.ToBoolean(reuireVal["AllowEmptyStrings"])) + { + required = true; + requiredMsg = reuireVal["ErrorMessage"]; + } + } + //如果不要求为必填项并且值为空,直接返回 + if (!required && string.IsNullOrEmpty(val)) + return (true, null, objectVal); + + if ((required && val == string.Empty)) + { + if (requiredMsg != "") return (false, requiredMsg, objectVal); + string propertyName = propertyInfo.GetTypeCustomValue(x => new { x.Name }); + return (false, requiredMsg + (string.IsNullOrEmpty(propertyName) ? propertyInfo.Name : propertyName) + "不能为空", objectVal); + } + //列名 + string typeName = propertyInfo.GetSqlDbType(); + + //如果没有ColumnAttribute的需要单独再验证,下面只验证有属性的 + if (typeName == null) { return (true, null, objectVal); } + //验证长度 + return typeName.ValidationVal(val, propertyInfo); + } + /// + /// 获取属性的指定属性 + /// + /// + /// + /// + public static object GetTypeCustomAttributes(this MemberInfo member, Type type) + { + object[] obj = member.GetCustomAttributes(type, false); + if (obj.Length == 0) return null; + return obj[0]; + } + + /// + /// 获取类的指定属性 + /// + /// + /// + /// + public static object GetTypeCustomAttributes(this Type entity, Type type) + { + object[] obj = entity.GetCustomAttributes(type, false); + if (obj.Length == 0) return null; + return obj[0]; + } + /// + /// 获取类的多个指定属性的值 + /// + /// 当前类 + /// 指定的类 + /// 指定属性的值 格式 Expression> exp = x => new { x.字段1, x.字段2 }; + /// 返回的是字段+value + public static Dictionary GetTypeCustomValues(this MemberInfo member, Expression> expression) + { + var attr = member.GetTypeCustomAttributes(typeof(TEntity)); + if (attr == null) + { + return null; + } + + string[] propertyName = expression.GetExpressionProperty(); + Dictionary propertyKeyValues = new Dictionary(); + + foreach (PropertyInfo property in attr.GetType().GetProperties()) + { + if (propertyName.Contains(property.Name)) + { + propertyKeyValues[property.Name] = (property.GetValue(attr) ?? string.Empty).ToString(); + } + } + return propertyKeyValues; + } + + /// + /// 获取类的单个指定属性的值(只会返回第一个属性的值) + /// + /// 当前类 + /// 指定的类 + /// 指定属性的值 格式 Expression> exp = x => new { x.字段1, x.字段2 }; + /// + public static string GetTypeCustomValue(this MemberInfo member, Expression> expression) + { + var propertyKeyValues = member.GetTypeCustomValues(expression); + if (propertyKeyValues == null || propertyKeyValues.Count == 0) + { + return null; + } + return propertyKeyValues.First().Value ?? ""; + } + /// + /// 判断hash的列是否为对应的实体,并且值是否有效 + /// + /// + /// + /// 移除不存在字段 + /// + public static string ValidateDicInEntity(this Type typeinfo, Dictionary dic, bool removeNotContains, string[] ignoreFields = null) + { + return typeinfo.ValidateDicInEntity(dic, removeNotContains, true, ignoreFields); + } + + public static string ValidateDicInEntity(this Type type, List> dicList, bool removeNotContains, bool removerKey, string[] ignoreFields = null) + { + PropertyInfo[] propertyInfo = type.GetProperties(); + string reslutMsg = string.Empty; + foreach (Dictionary dic in dicList) + { + reslutMsg = type.ValidateDicInEntity(dic, propertyInfo, removeNotContains, removerKey, ignoreFields); + if (!string.IsNullOrEmpty(reslutMsg)) + return reslutMsg; + } + return reslutMsg; + } + public static string ValidateDicInEntity(this Type type, Dictionary dic, bool removeNotContains, bool removerKey, string[] ignoreFields = null) + { + return type.ValidateDicInEntity(dic, null, removeNotContains, removerKey, ignoreFields); + } + /// + /// 判断hash的列是否为对应的实体,并且值是否有效 + /// + /// + /// + /// 移除不存在字段 + /// 移除主键 + /// + private static string ValidateDicInEntity(this Type typeinfo, Dictionary dic, PropertyInfo[] propertyInfo, bool removeNotContains, bool removerKey, string[] ignoreFields = null) + { + if (dic == null || dic.Count == 0) { return "参数无效"; } + if (propertyInfo == null) + propertyInfo = typeinfo.GetProperties().Where(x => x.PropertyType.Name != "List`1").ToArray(); + if (removeNotContains) + { + // 不存在的字段直接移除 + dic.Where(x => !propertyInfo.Any(p => p.Name == x.Key)).Select(s => s.Key).ToList().ForEach(f => + { + dic.Remove(f); + }); + } + string keyName = typeinfo.GetKeyName(); + //移除主键 + if (removerKey) + { + dic.Remove(keyName); + } + foreach (PropertyInfo property in propertyInfo) + { + //忽略与主键的字段不做验证 + if (property.Name == keyName || (ignoreFields != null && ignoreFields.Contains(property.Name))) + continue; + + //不在编辑中的列,是否也要必填 + if (!dic.ContainsKey(property.Name)) + { + //移除主键默认为新增数据,将不在编辑列中的有默认值的数据设置为默认值 + //如果为true默认为添加功能,添加操作所有不能为空的列也必须要提交 + if (property.GetCustomAttributes(typeof(RequiredAttribute)).Count() > 0 + && property.PropertyType != typeof(int) + && property.PropertyType != typeof(long) + && property.PropertyType != typeof(byte) + && property.PropertyType != typeof(decimal) + ) + { + return property.GetTypeCustomValue(x => x.Name) + "为必须提交项"; + } + continue; + } + bool isEdit = property.ContainsCustomAttributes(typeof(EditableAttribute)); + //不是编辑列的直接移除,并且不是主键 + //removerKey=true,不保留主键,直接移除 + //removerKey=false,保留主键,属性与主键不同的直接移除 + // if (!isEdit && (removerKey || (!removerKey && property.Name != keyName))) + if (!isEdit) + { + if (property.GetCustomAttributes(typeof(RequiredAttribute)).Count() > 0) + { + return property.GetTypeCustomValue(x => x.Name) + "没有配置好Model为编辑列"; + } + dic.Remove(property.Name); + continue; + } + ////移除忽略的不保存的数据 + //if (property.ContainsCustomAttributes(typeof(JsonIgnoreAttribute))) + //{ + // hash.Remove(property.Name); + // continue; + //} + //验证数据类型,不验证是否为空 + var result = property.ValidationProperty(dic[property.Name], false); + if (!result.Item1) + return result.Item2; + + //将所有空值设置为null + if (dic[property.Name] != null && dic[property.Name].ToString() == string.Empty) + dic[property.Name] = null; + } + return string.Empty; + } + /// + /// 获取表带有EntityAttribute属性的真实表名 + /// + /// + /// + public static string GetEntityTableName(this Type type) + { + Attribute attribute = type.GetCustomAttribute(typeof(EntityAttribute)); + if (attribute != null && attribute is EntityAttribute) + { + return (attribute as EntityAttribute).TableName ?? type.Name; + } + return type.Name; + } + /// + /// 获取表带有EntityAttribute属性的表中文名 + /// + /// + /// + public static string GetEntityTableCnName(this Type type) + { + Attribute attribute = type.GetCustomAttribute(typeof(EntityAttribute)); + if (attribute != null && attribute is EntityAttribute) + { + return (attribute as EntityAttribute).TableCnName; + } + return string.Empty; + } + + /// + /// 将实体映射到输出到ApiOutput实体上,如果没有输入实体,则返回null + /// + /// + /// + //public static object MapToOutput( this T entity, Type type = null) + //{ + // Type sourceType = typeof(T); + // //list转换 + // if (sourceType is System.Collections.IList) + // { + // System.Collections.IList list = entity as System.Collections.IList; + // sourceType = list[0].GetType(); + // } + // if (type == null) + // { + // EntityAttribute attribute = sourceType.GetCustomAttribute(); + // if (attribute == null || attribute.ApiOutput == null) + // return null; + // type = attribute.ApiOutput; + // } + + // object outPutObject = Activator.CreateInstance(type); + // PropertyInfo[] outPutPropertyInfo = type.GetProperties(); + + // PropertyInfo[] propertyInfo = sourceType.GetProperties(); + // foreach (var property in outPutPropertyInfo) + // { + // PropertyInfo info= propertyInfo.Where(x => x.Name == property.Name).FirstOrDefault(); + // if (info!=null) + // { + // property.SetValue(outPutObject, info.GetValue(entity)); + // } + // } + // return outPutObject; + //} + + private static object MapToInstance(this Type reslutType, object sourceEntity, PropertyInfo[] sourcePro, PropertyInfo[] reslutPro, string[] sourceFilterField, string[] reslutFilterField, string mapType = null) + { + mapType = mapType ?? GetMapType(reslutType); + if (sourcePro == null) + { + sourcePro = sourceEntity.GetType().GetProperties(); + } + if (reslutPro == null) + { + reslutPro = reslutType.GetProperties(); ; + } + + object newObj = Activator.CreateInstance(reslutType); + + if (mapType == "Dictionary") + { + if (sourceFilterField != null && sourceFilterField.Length > 0) + { + sourcePro = sourcePro.Where(x => sourceFilterField.Contains(x.Name)).ToArray(); + } + foreach (var property in sourcePro) + { + (newObj as System.Collections.IDictionary).Add(property.Name, property.GetValue(sourceEntity)); + } + return newObj; + } + + if (reslutFilterField != null && reslutFilterField.Count() > 0) + { + reslutPro.Where(x => reslutFilterField.Contains(x.Name)); + } + + foreach (var property in reslutPro) + { + PropertyInfo info = sourcePro.Where(x => x.Name == property.Name).FirstOrDefault(); + if (!(info != null && info.PropertyType == property.PropertyType)) + continue; + property.SetValue(newObj, info.GetValue(sourceEntity)); + } + return newObj; + } + private static string GetMapType(Type type) + { + return typeof(Dictionary<,>) == type ? "Dictionary" : "entity"; + } + + /// + /// 将数据源映射到新的数据中,目前只支持List映射到List或TSource映射到TResult + /// 目前只支持Dictionary或实体类型 + /// + /// + /// + /// + /// 只映射返回对象的指定字段,若为null则默认为全部字段 + /// 只映射数据源对象的指定字段,若为null则默认为全部字段 + /// + public static TResult MapToObject(this TSource source, Expression> resultExpression, + Expression> sourceExpression = null + ) where TResult : class + { + if (source == null) + return null; + string[] sourceFilterField = sourceExpression == null ? typeof(TSource).GetProperties().Select(x => x.Name).ToArray() : sourceExpression.GetExpressionProperty(); + string[] reslutFilterField = resultExpression?.GetExpressionProperty(); + if (!(source is System.Collections.IList)) + return MapToInstance(typeof(TResult), source, null, null, sourceFilterField, reslutFilterField) as TResult; + + Type sourceType = null; + Type resultType = null; + System.Collections.IList sourceList = source as System.Collections.IList; + sourceType = sourceList[0].GetType(); + resultType = (typeof(TResult)).GenericTypeArguments[0]; + + System.Collections.IList reslutList = Activator.CreateInstance(typeof(TResult)) as System.Collections.IList; + PropertyInfo[] sourcePro = sourceType.GetProperties(); + PropertyInfo[] resultPro = resultType.GetProperties(); + + string mapType = GetMapType(resultType); + for (int i = 0; i < sourceList.Count; i++) + { + var reslutobj = MapToInstance(resultType, sourceList[i], sourcePro, resultPro, sourceFilterField, reslutFilterField, mapType); + reslutList.Add(reslutobj); + } + return reslutList as TResult; + } + + /// + /// 将一个实体的赋到另一个实体上,应用场景: + /// 两个实体,a a1= new a();b b1= new b(); a1.P=b1.P; a1.Name=b1.Name; + /// + /// + /// + /// + /// + /// 指定对需要的字段赋值,格式x=>new {x.Name,x.P},返回的结果只会对Name与P赋值 + public static void MapValueToEntity(this TSource source, TResult result, Expression> expression = null) where TResult : class + { + if (source == null) + return; + string[] fields = expression?.GetExpressionToArray(); + PropertyInfo[] reslutPro = fields == null ? result.GetType().GetProperties() : result.GetType().GetProperties().Where(x => fields.Contains(x.Name)).ToArray(); + PropertyInfo[] sourcePro = source.GetType().GetProperties(); + foreach (var property in reslutPro) + { + PropertyInfo info = sourcePro.Where(x => x.Name == property.Name).FirstOrDefault(); + if (info != null && info.PropertyType == property.PropertyType) + { + property.SetValue(result, info.GetValue(source)); + } + } + } + + /// + /// 设置默认字段的值"CreateID", "Creator", "CreateDate","ModifyID", "Modifier", "ModifyDate" + /// + /// + /// true=新增设置"CreateID", "Creator", "CreateDate"值 + /// false=编辑设置"ModifyID", "Modifier", "ModifyDate"值 + /// + public static SaveModel SetDefaultVal(this SaveModel saveDataModel, TableDefaultColumns defaultColumns, UserInfo userInfo = null) + { + SetDefaultVal(saveDataModel.MainData, defaultColumns, userInfo); + if (saveDataModel.DetailData != null && saveDataModel.DetailData.Count > 0) + { + foreach (var item in saveDataModel.DetailData) + { + if (item.Count == 0) continue; + SetDefaultVal(item, defaultColumns, userInfo); + } + } + return saveDataModel; + } + + public static TSource SetCreateDefaultVal(this TSource source, UserInfo userInfo = null) + { + return SetDefaultVal(source, AppSetting.CreateMember, userInfo); + } + public static TSource SetModifyDefaultVal(this TSource source, UserInfo userInfo = null) + { + return SetDefaultVal(source, AppSetting.ModifyMember, userInfo); + } + /// + /// + /// 设置默认字段的值如:"CreateID", "Creator", "CreateDate","ModifyID", "Modifier", "ModifyDate" + /// + /// + /// true=新增设置"CreateID", "Creator", "CreateDate"值 + /// false=编辑设置"ModifyID", "Modifier", "ModifyDate"值 + /// + private static TSource SetDefaultVal(this TSource source, TableDefaultColumns defaultColumns, UserInfo userInfo = null) + { + userInfo = userInfo ?? ManageUser.UserContext.Current.UserInfo; + foreach (PropertyInfo property in typeof(TSource).GetProperties()) + { + string filed = property.Name.ToLower(); + if (filed == defaultColumns.UserIdField?.ToLower()) + property.SetValue(source, userInfo.User_Id); + + if (filed == defaultColumns.UserNameField?.ToLower()) + property.SetValue(source, userInfo.UserTrueName); + + if (filed == defaultColumns.DateField?.ToLower()) + property.SetValue(source, DateTime.Now); + } + return source; + } + private static Dictionary SetDefaultVal(this Dictionary dic, TableDefaultColumns defaultColumns, UserInfo userInfo = null) + { + userInfo = userInfo ?? ManageUser.UserContext.Current.UserInfo; + + KeyValuePair valuePair = dic.Where(x => x.Key.ToLower() == defaultColumns.UserIdField?.ToLower()).FirstOrDefault(); + + if (valuePair.Key != null || defaultColumns.UserIdField != null) + { + dic[valuePair.Key ?? defaultColumns.UserIdField] = userInfo.User_Id; + } + + valuePair = dic.Where(x => x.Key.ToLower() == defaultColumns.UserNameField?.ToLower()).FirstOrDefault(); + if (valuePair.Key != null || defaultColumns.UserNameField != null) + { + dic[valuePair.Key ?? defaultColumns.UserNameField] = userInfo.UserTrueName; + } + + valuePair = dic.Where(x => x.Key.ToLower() == defaultColumns.DateField?.ToLower()).FirstOrDefault(); + if (valuePair.Key != null || defaultColumns.DateField != null) + { + dic[valuePair.Key ?? defaultColumns.DateField] = DateTime.Now; + } + + return dic; + } + public static Dictionary SetCreateDefaultVal(this Dictionary dic) + { + return SetDefaultVal(dic, AppSetting.CreateMember); + } + public static Dictionary SetModifyDefaultVal(this Dictionary dic) + { + return SetDefaultVal(dic, AppSetting.ModifyMember); + } + } + + public class ArrayEntity + { + public string column1 { get; set; } + } + + public enum FieldType + { + VarChar = 0, + NvarChar, + Int, + BigInt, + UniqueIdentifier + } + + public enum EntityToSqlTempName + { + TempInsert = 0 + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/GenericExtension.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/GenericExtension.cs new file mode 100644 index 0000000000000000000000000000000000000000..bd5744b4fbf36b699807cf7ab5a874046b9f8f76 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/GenericExtension.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; + +namespace VOL.Core.Extensions +{ + /// + /// 泛型扩展 + /// + public static class GenericExtension + { + public static bool Equal(this T x, T y) + { + return ((IComparable)(x)).CompareTo(y) == 0; + } + + #region ToDictionary + /// + /// 将实体指定的字段写入字典 + /// + /// + /// + /// + /// + + public static Dictionary ToDictionary(this T t, Expression> expression) where T : class + { + Dictionary dic = new Dictionary(); + string[] fields = expression.GetExpressionToArray(); + PropertyInfo[] properties = expression == null ? t.GetType().GetProperties() : t.GetType().GetProperties().Where(x => fields.Contains(x.Name)).ToArray(); + + foreach (var property in properties) + { + var value = property.GetValue(t, null); + dic.Add(property.Name, value != null ? value.ToString() : ""); + } + return dic; + } + + public static Dictionary ToDictionary(this TInterface t, Dictionary dic = null) where T : class, TInterface + { + if (dic == null) + dic = new Dictionary(); + var properties = typeof(T).GetProperties(); + foreach (var property in properties) + { + var value = property.GetValue(t, null); + if (value == null) continue; + dic.Add(property.Name, value != null ? value.ToString() : ""); + } + return dic; + } + + #endregion + + + public static DataTable ToDataTable(this IEnumerable source, Expression> columns = null, bool contianKey = true) + { + DataTable dtReturn = new DataTable(); + if (source == null) return dtReturn; + + PropertyInfo[] oProps = typeof(T).GetProperties() + .Where(x => x.PropertyType.Name != "List`1").ToArray(); + if (columns != null) + { + string[] columnArray = columns.GetExpressionToArray(); + oProps = oProps.Where(x => columnArray.Contains(x.Name)).ToArray(); + } + //移除自增主键 + PropertyInfo keyType = oProps.GetKeyProperty();// oProps.GetKeyProperty()?.PropertyType; + if (!contianKey && keyType != null && (keyType.PropertyType == typeof(int) || keyType.PropertyType == typeof(long))) + { + oProps = oProps.Where(x => x.Name != keyType.Name).ToArray(); + } + + foreach (var pi in oProps) + { + var colType = pi.PropertyType; + + if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>))) + { + colType = colType.GetGenericArguments()[0]; + } + + dtReturn.Columns.Add(new DataColumn(pi.Name, colType)); + } + foreach (var rec in source) + { + var dr = dtReturn.NewRow(); + foreach (var pi in oProps) + { + dr[pi.Name] = pi.GetValue(rec, null) == null + ? DBNull.Value + : pi.GetValue + (rec, null); + } + dtReturn.Rows.Add(dr); + } + return dtReturn; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/HtmlHelperViewExtensions.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/HtmlHelperViewExtensions.cs new file mode 100644 index 0000000000000000000000000000000000000000..868c40ea0b62398b56db9dd898022af36ef0fe9d --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/HtmlHelperViewExtensions.cs @@ -0,0 +1,103 @@ +using Microsoft.AspNetCore.Html; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Infrastructure; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Threading.Tasks; + +namespace VOL.Core.Extensions +{ + public static class HtmlHelperViewExtensions + { + public static IHtmlContent Action(this IHtmlHelper helper, string action, object parameters = null) + { + var controller = (string)helper.ViewContext.RouteData.Values["controller"]; + + return Action(helper, action, controller, parameters); + } + + public static IHtmlContent Action(this IHtmlHelper helper, string action, string controller, object parameters = null) + { + var area = (string)helper.ViewContext.RouteData.Values["area"]; + + return Action(helper, action, controller, area, parameters); + } + + public static IHtmlContent Action(this IHtmlHelper helper, string action, string controller, string area, object parameters = null) + { + if (action == null) + throw new ArgumentNullException("action"); + + if (controller == null) + throw new ArgumentNullException("controller"); + + + var task = RenderActionAsync(helper, action, controller, area, parameters); + + return task.Result; + } + + private static async Task RenderActionAsync(this IHtmlHelper helper, string action, string controller, string area, object parameters = null) + { + // fetching required services for invocation + var serviceProvider = helper.ViewContext.HttpContext.RequestServices; + var actionContextAccessor = helper.ViewContext.HttpContext.RequestServices.GetRequiredService(); + var httpContextAccessor = helper.ViewContext.HttpContext.RequestServices.GetRequiredService(); + var actionSelector = serviceProvider.GetRequiredService(); + + // creating new action invocation context + var routeData = new RouteData(); + foreach (var router in helper.ViewContext.RouteData.Routers) + { + routeData.PushState(router, null, null); + } + routeData.PushState(null, new RouteValueDictionary(new { controller = controller, action = action, area = area }), null); + routeData.PushState(null, new RouteValueDictionary(parameters ?? new { }), null); + + //get the actiondescriptor + RouteContext routeContext = new RouteContext(helper.ViewContext.HttpContext) { RouteData = routeData }; + var candidates = actionSelector.SelectCandidates(routeContext); + var actionDescriptor = actionSelector.SelectBestCandidate(routeContext, candidates); + + var originalActionContext = actionContextAccessor.ActionContext; + var originalhttpContext = httpContextAccessor.HttpContext; + try + { + var newHttpContext = serviceProvider.GetRequiredService().Create(helper.ViewContext.HttpContext.Features); + if (newHttpContext.Items.ContainsKey(typeof(IUrlHelper))) + { + newHttpContext.Items.Remove(typeof(IUrlHelper)); + } + newHttpContext.Response.Body = new MemoryStream(); + var actionContext = new ActionContext(newHttpContext, routeData, actionDescriptor); + actionContextAccessor.ActionContext = actionContext; + var invoker = serviceProvider.GetRequiredService().CreateInvoker(actionContext); + await invoker.InvokeAsync(); + newHttpContext.Response.Body.Position = 0; + using (var reader = new StreamReader(newHttpContext.Response.Body)) + { + return new HtmlString(reader.ReadToEnd()); + } + } + catch (Exception ex) + { + return new HtmlString(ex.Message); + } + finally + { + actionContextAccessor.ActionContext = originalActionContext; + httpContextAccessor.HttpContext = originalhttpContext; + if (helper.ViewContext.HttpContext.Items.ContainsKey(typeof(IUrlHelper))) + { + helper.ViewContext.HttpContext.Items.Remove(typeof(IUrlHelper)); + } + } + } + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/LambdaExtensions.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/LambdaExtensions.cs new file mode 100644 index 0000000000000000000000000000000000000000..f0ac2f494d26d3743fc183526dbd8fab326ee739 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/LambdaExtensions.cs @@ -0,0 +1,516 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using VOL.Core.Enums; + +namespace VOL.Core.Extensions +{ + public static class LambdaExtensions + { + /// + /// 分页查询 + /// + /// + /// + /// + /// + /// + public static IQueryable TakePage(this IQueryable queryable, int page, int size = 15) + { + return queryable.TakeOrderByPage(page, size); + } + /// + /// 分页查询 + /// + /// + /// + /// + /// + /// + /// + public static IQueryable TakeOrderByPage(this IQueryable queryable, int page, int size = 15, Expression>> orderBy = null) + { + if (page <= 0) + { + page = 1; + } + return queryable.GetIQueryableOrderBy(orderBy.GetExpressionToDic()) + .Skip((page - 1) * size) + .Take(size); + } + + /// + /// 创建lambda表达式:p=>true + /// + /// + /// + public static Expression> True() + { + return p => true; + } + + /// + /// 创建lambda表达式:p=>false + /// + /// + /// + public static Expression> False() + { + + return p => false; + } + + public static ParameterExpression GetExpressionParameter(this Type type) + { + + return Expression.Parameter(type, "p"); + } + /// + /// 创建lambda表达式:p=>p.propertyName + /// + /// + /// + /// + /// + public static Expression> GetExpression(this string propertyName) + { + return propertyName.GetExpression(typeof(T).GetExpressionParameter()); + } + /// + /// 创建委托有返回值的表达式:p=>p.propertyName + /// + /// + /// + /// + /// + public static Func GetFun(this string propertyName) + { + return propertyName.GetExpression(typeof(T).GetExpressionParameter()).Compile(); + } + + /// + /// 创建lambda表达式:p=>false + /// 在已知TKey字段类型时,如动态排序OrderBy(x=>x.ID)会用到此功能,返回的就是x=>x.ID + /// Expression> expression = x => x.CreateDate;指定了类型 + /// + /// + /// + public static Expression> GetExpression(this string propertyName, ParameterExpression parameter) + { + if (typeof(TKey).Name == "Object") + return Expression.Lambda>(Expression.Convert(Expression.Property(parameter, propertyName), typeof(object)), parameter); + return Expression.Lambda>(Expression.Property(parameter, propertyName), parameter); + } + /// + /// 创建lambda表达式:p=>false + /// object不能确认字段类型(datetime,int,string),如动态排序OrderBy(x=>x.ID)会用到此功能,返回的就是x=>x.ID + /// Expression> expression = x => x.CreateDate;任意类型的字段 + /// + /// + /// + public static Expression> GetExpression(this string propertyName) + { + return propertyName.GetExpression(typeof(T).GetExpressionParameter()); + } + + public static Expression> GetExpression(this string propertyName, ParameterExpression parameter) + { + return Expression.Lambda>(Expression.Convert(Expression.Property(parameter, propertyName), typeof(object)), parameter); + } + + + + /// + /// + /// + /// + /// 字段名 + /// 表达式的值 + /// 创建表达式的类型,如:p=>p.propertyName != propertyValue + /// p=>p.propertyName.Contains(propertyValue) + /// + public static Expression> CreateExpression(this string propertyName, object propertyValue, LinqExpressionType expressionType) + { + return propertyName.CreateExpression(propertyValue, null, expressionType); + } + + /// + /// + /// + /// + /// 字段名 + /// 表达式的值 + /// 创建表达式的类型,如:p=>p.propertyName != propertyValue + /// p=>p.propertyName.Contains(propertyValue) + /// + private static Expression> CreateExpression( + this string propertyName, + object propertyValue, + ParameterExpression parameter, + LinqExpressionType expressionType) + { + Type proType = typeof(T).GetProperty(propertyName).PropertyType; + //创建节点变量如p=>的节点p + // parameter ??= Expression.Parameter(typeof(T), "p");//创建参数p + parameter = parameter ?? Expression.Parameter(typeof(T), "p"); + + //创建节点的属性p=>p.name 属性name + MemberExpression memberProperty = Expression.PropertyOrField(parameter, propertyName); + if (expressionType == LinqExpressionType.In) + { + if (!(propertyValue is System.Collections.IList list) || list.Count == 0) throw new Exception("属性值类型不正确"); + + bool isStringValue = true; + List objList = new List(); + + if (proType.ToString() != "System.String") + { + isStringValue = false; + foreach (var value in list) + { + objList.Add(value.ToString().ChangeType(proType)); + } + list = objList; + } + + if (isStringValue) + { + //string 类型的字段,如果值带有'单引号,EF会默认变成''两个单引号 + MethodInfo method = typeof(System.Collections.IList).GetMethod("Contains"); + //创建集合常量并设置为常量的值 + ConstantExpression constantCollection = Expression.Constant(list); + //创建一个表示调用带参数的方法的:new string[]{"1","a"}.Contains("a"); + MethodCallExpression methodCall = Expression.Call(constantCollection, method, memberProperty); + return Expression.Lambda>(methodCall, parameter); + } + //非string字段,按上面方式处理报异常Null TypeMapping in Sql Tree + BinaryExpression body = null; + foreach (var value in list) + { + ConstantExpression constantExpression = Expression.Constant(value); + UnaryExpression unaryExpression = Expression.Convert(memberProperty, constantExpression.Type); + + body = body == null + ? Expression.Equal(unaryExpression, constantExpression) + : Expression.OrElse(body, Expression.Equal(unaryExpression, constantExpression)); + } + return Expression.Lambda>(body, parameter); + } + + // object value = propertyValue; + ConstantExpression constant = proType.ToString() == "System.String" + ? Expression.Constant(propertyValue) : Expression.Constant(propertyValue.ToString().ChangeType(proType)); + + UnaryExpression member = Expression.Convert(memberProperty, constant.Type); + Expression> expression; + switch (expressionType) + { + //p=>p.propertyName == propertyValue + case LinqExpressionType.Equal: + expression = Expression.Lambda>(Expression.Equal(member, constant), parameter); + break; + //p=>p.propertyName != propertyValue + case LinqExpressionType.NotEqual: + expression = Expression.Lambda>(Expression.NotEqual(member, constant), parameter); + break; + // p => p.propertyName > propertyValue + case LinqExpressionType.GreaterThan: + expression = Expression.Lambda>(Expression.GreaterThan(member, constant), parameter); + break; + // p => p.propertyName < propertyValue + case LinqExpressionType.LessThan: + expression = Expression.Lambda>(Expression.LessThan(member, constant), parameter); + break; + // p => p.propertyName >= propertyValue + case LinqExpressionType.ThanOrEqual: + expression = Expression.Lambda>(Expression.GreaterThanOrEqual(member, constant), parameter); + break; + // p => p.propertyName <= propertyValue + case LinqExpressionType.LessThanOrEqual: + expression = Expression.Lambda>(Expression.LessThanOrEqual(member, constant), parameter); + break; + // p => p.propertyName.Contains(propertyValue) + // p => !p.propertyName.Contains(propertyValue) + case LinqExpressionType.Contains: + case LinqExpressionType.NotContains: + MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); + constant = Expression.Constant(propertyValue, typeof(string)); + if (expressionType == LinqExpressionType.Contains) + { + expression = Expression.Lambda>(Expression.Call(member, method, constant), parameter); + } + else + { + expression = Expression.Lambda>(Expression.Not(Expression.Call(member, method, constant)), parameter); + } + break; + default: + // p => p.false + expression = False(); + break; + } + return expression; + } + + /// + /// 表达式转换成KeyValList(主要用于多字段排序,并且多个字段的排序规则不一样) + /// 如有多个字段进行排序,参数格式为 + /// Expression>> orderBy = x => new Dictionary() { + /// { x.ID, true }, + /// { x.DestWarehouseName, true } + /// }; + /// 返回的是new Dictionary(){{}}key为排序字段,bool为升降序 + /// + /// + /// + /// + public static IEnumerable> GetExpressionToPair(this Expression>> expression) + { + + foreach (var exp in ((ListInitExpression)expression.Body).Initializers) + { + yield return new KeyValuePair( + exp.Arguments[0] is MemberExpression ? + (exp.Arguments[0] as MemberExpression).Member.Name.ToString() + : ((exp.Arguments[0] as UnaryExpression).Operand as MemberExpression).Member.Name, + (QueryOrderBy)( + exp.Arguments[1] as ConstantExpression != null + ? (exp.Arguments[1] as ConstantExpression).Value + //2021.07.04增加自定排序按条件表达式 + : Expression.Lambda>(exp.Arguments[1] as Expression).Compile()() + )); + } + } + + + /// + /// 表达式转换成KeyValList(主要用于多字段排序,并且多个字段的排序规则不一样) + /// 如有多个字段进行排序,参数格式为 + /// Expression>> orderBy = x => new Dictionary() { + /// { x.ID, QueryOrderBy.Desc }, + /// { x.DestWarehouseName, QueryOrderBy.Asc } + /// }; + /// 返回的是new Dictionary(){{}}key为排序字段,QueryOrderBy为排序方式 + /// + /// + /// + /// + public static Dictionary GetExpressionToDic(this Expression>> expression) + { + //2020.09.14增加排序字段null值判断 + if (expression == null) + { + return new Dictionary(); + } + return expression.GetExpressionToPair().Reverse().ToList().ToDictionary(x => x.Key, x => x.Value); + } + /// + /// 解析多字段排序 + /// + /// + /// + /// string=排序的字段,bool=true降序/false升序 + /// + public static IQueryable GetIQueryableOrderBy(this IQueryable queryable, Dictionary orderBySelector) + { + string[] orderByKeys = orderBySelector.Select(x => x.Key).ToArray(); + if (orderByKeys == null || orderByKeys.Length == 0) return queryable; + + IOrderedQueryable queryableOrderBy = null; + // string orderByKey = orderByKeys[^1]; + string orderByKey = orderByKeys[orderByKeys.Length - 1]; + queryableOrderBy = orderBySelector[orderByKey] == QueryOrderBy.Desc + ? queryableOrderBy = queryable.OrderByDescending(orderByKey.GetExpression()) + : queryable.OrderBy(orderByKey.GetExpression()); + + for (int i = orderByKeys.Length - 2; i >= 0; i--) + { + queryableOrderBy = orderBySelector[orderByKeys[i]] == QueryOrderBy.Desc + ? queryableOrderBy.ThenByDescending(orderByKeys[i].GetExpression()) + : queryableOrderBy.ThenBy(orderByKeys[i].GetExpression()); + } + return queryableOrderBy; + } + + /// + /// 获取对象表达式指定属性的值 + /// 如获取:Out_Scheduling对象的ID或基他字段 + /// + /// + /// 格式 Expression>sch=x=>new {x.v1,x.v2} or x=>x.v1 解析里面的值返回为数组 + /// + public static string[] GetExpressionToArray(this Expression> expression) + { + string[] propertyNames = null; + if (expression.Body is MemberExpression) + { + propertyNames = new string[] { ((MemberExpression)expression.Body).Member.Name }; + } + else + { + propertyNames = expression.GetExpressionProperty().Distinct().ToArray(); + } + return propertyNames; + } + + /// + /// 与下面and生成方式有所不同,如果直接用表达式1.2进行合并产会提示数据源不同的异常,只能使用下面的的and合并 + /// 此种合并是在使用的同一个数据源(变量),生成的sql语句同样有性能问题(本身可以索引扫描的,生成的sql语句的case when变成索引查找) + /// + /// 通过字段动态生成where and /or表达 + /// 如:有多个where条件,当条件成立时where 1=1 and/or 2=2,依次往后拼接 + /// + /// + /// + /// ExpressionParameters + /// 1、Field生成的字段 + /// 2、ExpressionType 表达式类型大于、小于、于大=、小于=、contains + /// 3、Value表达式的值 + /// + /// + public static Expression> And(List listExpress) + { + return listExpress.Compose(Expression.And); + } + /// + /// 同上面and用法相同 + /// + /// + /// + /// + public static Expression> Or(this List listExpress) + { + return listExpress.Compose(Expression.Or); + } + private static Expression> Compose(this List listExpress, Func merge) + { + ParameterExpression parameter = Expression.Parameter(typeof(T), "p"); + Expression> expression = null; + foreach (ExpressionParameters exp in listExpress) + { + if (expression == null) + { + expression = exp.Field.GetExpression(parameter); + } + else + { + expression = expression.Compose(exp.Field.GetExpression(parameter), merge); + } + } + return expression; + } + /// + /// https://blogs.msdn.microsoft.com/meek/2008/05/02/linq-to-entities-combining-predicates/ + /// 表达式合并(合并生产的sql语句有性能问题) + /// 合并两个where条件,如:多个查询条件时,判断条件成立才where + /// + /// + /// + /// + /// + public static Expression> And(this Expression> first, Expression> second) + { + return first.Compose(second, Expression.And); + } + public static Expression> Or(this Expression> first, Expression> second) + { + return first.Compose(second, Expression.Or); + } + public static Expression Compose(this Expression first, Expression second, Func merge) + { + // build parameter map (from parameters of second to parameters of first) + var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f); + // replace parameters in the second lambda expression with parameters from the first + var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body); + // apply composition of lambda expression bodies to parameters from the first expression + return Expression.Lambda(merge(first.Body, secondBody), first.Parameters); + } + + public static IQueryable GetQueryableSelect(this IQueryable queryable) + { + Expression> expression = CreateMemberInitExpression(); + return queryable.Select(expression); + } + + /// + /// 动态创建表达式Expression> expression = CreateMemberInitExpression(); + ///结果为Expression> expression1 = x => new User() { Age = x.Age, Species = x.Species }; + ///参照文档https://docs.microsoft.com/zh-cn/dotnet/api/system.linq.expressions.memberinitexpression?redirectedfrom=MSDN&view=netframework-4.8 + /// + /// + /// + /// + public static Expression> CreateMemberInitExpression(Type resultType = null) + { + resultType = resultType ?? typeof(Result); + ParameterExpression left = Expression.Parameter(typeof(Source), "p"); + NewExpression newExpression = Expression.New(resultType); + PropertyInfo[] propertyInfos = resultType.GetProperties(); + List memberBindings = new List(); + foreach (PropertyInfo propertyInfo in propertyInfos) + { + MemberExpression member = Expression.Property(left, propertyInfo.Name); + MemberBinding speciesMemberBinding = Expression.Bind(resultType.GetMember(propertyInfo.Name)[0], member); + memberBindings.Add(speciesMemberBinding); + } + MemberInitExpression memberInitExpression = Expression.MemberInit(newExpression, memberBindings); + Expression> expression = Expression.Lambda>(memberInitExpression, new ParameterExpression[] { left }); + return expression; + } + public static Expression> CreateMemberInitExpression(Type resultType) + { + return CreateMemberInitExpression(resultType); + } + /// + /// 属性判断待完 + /// + /// + /// + public static IEnumerable GetGenericProperties(this Type type) + { + return type.GetProperties().GetGenericProperties(); + } + /// + /// 属性判断待完 + /// + /// + /// + public static IEnumerable GetGenericProperties(this IEnumerable properties) + { + return properties.Where(x => !x.PropertyType.IsGenericType && x.PropertyType.GetInterface("IList") == null || x.PropertyType.GetInterface("IEnumerable", false) == null); + } + } + + public class ExpressionParameters + { + public string Field { get; set; } + public LinqExpressionType ExpressionType { get; set; } + public object Value { get; set; } + // public + } + public class ParameterRebinder : ExpressionVisitor + { + + private readonly Dictionary map; + public ParameterRebinder(Dictionary map) + { + this.map = map ?? new Dictionary(); + } + + public static Expression ReplaceParameters(Dictionary map, Expression exp) + { + return new ParameterRebinder(map).Visit(exp); + } + protected override Expression VisitParameter(ParameterExpression p) + { + ParameterExpression replacement; + if (map.TryGetValue(p, out replacement)) + { + p = replacement; + } + return base.VisitParameter(p); + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/Middleware/ExceptionHandlerMiddleWare.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/Middleware/ExceptionHandlerMiddleWare.cs new file mode 100644 index 0000000000000000000000000000000000000000..f167f44a5b136a6dfc2db6b03c1dfff9f2e46f7f --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/Middleware/ExceptionHandlerMiddleWare.cs @@ -0,0 +1,90 @@ +//using VOL.Core.Enums; +//using VOL.Entity.DomainModels.ResponseEntity; +//using VOL.Entity.SystemsModels; +//using Microsoft.AspNetCore.Http; +//using Newtonsoft.Json; +//using System; +//using System.IO; +//using System.Net; +//using System.Text; +//using System.Threading.Tasks; +//using System.Xml.Serialization; + +//namespace VOL.Core.Extensions.Middleware +//{ +// public class ExceptionHandlerMiddleWare +// { +// private readonly RequestDelegate next; + +// public ExceptionHandlerMiddleWare(RequestDelegate next) +// { +// this.next = next; +// } + +// public async Task Invoke(HttpContext context) +// { +// try +// { +// await next(context); +// } +// catch (Exception ex) +// { +// await HandleExceptionAsync(context, ex); +// } +// } + +// private static async Task HandleExceptionAsync(HttpContext context, Exception exception) +// { +// if (exception == null) return; +// await WriteExceptionAsync(context, exception).ConfigureAwait(false); +// } + +// private static async Task WriteExceptionAsync(HttpContext context, Exception exception) +// { + +// Logger.WriteLog(LogEnum.Exception, null, exception.Message + exception.StackTrace, null); + +// var response = context.Response; + +// if (exception is UnauthorizedAccessException) +// response.StatusCode = (int)HttpStatusCode.Unauthorized; +// else if (exception is Exception) +// // response.StatusCode = (int)HttpStatusCode.BadRequest; +// response.StatusCode = (int)HttpStatusCode.InternalServerError; +// response.ContentType = context.Request.Headers["Accept"]; + +// //if (response.ContentType.ToLower() == "application/xml") +// response.ContentType = "application/json"; +// ResponseData responseData = new ResponseData(); +// responseData.SetResponseValue(ResponseType.ServerError); +// string reslutMsg = JsonConvert.SerializeObject(responseData); + +// await response.WriteAsync(reslutMsg, Encoding.UTF8).ConfigureAwait(false); +// } + +// /// +// /// 对象转为Xml +// /// +// /// +// /// +// private static string Object2XmlString(object o) +// { +// StringWriter sw = new StringWriter(); +// try +// { +// XmlSerializer serializer = new XmlSerializer(o.GetType()); +// serializer.Serialize(sw, o); +// } +// catch +// { +// //Handle Exception Code +// } +// finally +// { +// sw.Dispose(); +// } +// return sw.ToString(); +// } + +// } +//} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/Middleware/HttpContextMiddleware.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/Middleware/HttpContextMiddleware.cs new file mode 100644 index 0000000000000000000000000000000000000000..588d700b6c68d9bf08fbfc5dcc215e7619c855c1 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/Middleware/HttpContextMiddleware.cs @@ -0,0 +1,58 @@ +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace VOL.Core.Extensions +{ + public class HttpContextMiddleware + { + /// + /// 将流重新 + /// + public static Func contextMiddleware + { + get + { + return next => async context => + { + + var stream = context.Request.Body; + if (stream == Stream.Null || stream.CanSeek) + { + await next(context); + + return; + } + try + { + //将流拷贝一份出来,调用结束后再将流写回去 + using (var buffer = new MemoryStream()) + { + // Copy the request stream to the memory stream. + await stream.CopyToAsync(buffer); + + // Rewind the memory stream. + buffer.Position = 0L; + + // Replace the request stream by the memory stream. + context.Request.Body = buffer; + + // Invoke the rest of the pipeline. + await next(context); + } + } + + finally + { + // Restore the original stream. + context.Request.Body = stream; + } + + }; + + } + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/ObjectExtension.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/ObjectExtension.cs new file mode 100644 index 0000000000000000000000000000000000000000..661662511d8a815f23e1e26876be1bc2f6bd5817 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/ObjectExtension.cs @@ -0,0 +1,1222 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; +using System.Text; +using System.Text.RegularExpressions; +using System.Web; +using System.Xml; +using System.Xml.Linq; + +namespace VOL.Core.Extensions +{ + + public static class ObjectExtension + { + + public static bool DicKeyIsNullOrEmpty(this Dictionary dic, string key) + { + if (dic == null) + return true; + if (!dic.ContainsKey(key)) return true; + object value = dic[key]; + if (value == null || value.ToString() == "") + { + return true; + } + return false; + } + public static Dictionary ReaderToDictionary(this IDataReader Reader) + { + List> rowList = Reader.ReaderToDictionaryList(); + return rowList.Count() > 0 ? rowList[0] : null; + } + /// + /// IDataReader转换成DictionaryList + /// + /// + /// + public static List> ReaderToDictionaryList(this IDataReader Reader) + { + List> rowList = new List>(); + try + { + while (Reader.Read()) + { + Dictionary row = new Dictionary(StringComparer.OrdinalIgnoreCase); + for (var fieldCount = 0; fieldCount < Reader.FieldCount; fieldCount++) + { + row.Add(Reader.GetName(fieldCount), Reader[fieldCount]); + } + rowList.Add(row); + } + } + catch (Exception ex) { throw ex; } + finally + { + Reader.Close(); + Reader.Dispose(); + } + return rowList; + } + + public static T DicToEntity(this Dictionary dic) + { + return new List>() { dic }.DicToList().ToList()[0]; + } + public static List DicToList(this List> dicList) + { + return dicList.DicToIEnumerable().ToList(); + } + public static object DicToList(this List> dicList, Type type) + { + return typeof(ObjectExtension).GetMethod("DicToList") + .MakeGenericMethod(new Type[] { type }) + .Invoke(typeof(ObjectExtension), new object[] { dicList }); + } + + public static IEnumerable DicToIEnumerable(this List> dicList) + { + foreach (Dictionary dic in dicList) + { + T model = Activator.CreateInstance(); + foreach (PropertyInfo property in model.GetType() + .GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance)) + { + if (!dic.TryGetValue(property.Name, out object value)) continue; + property.SetValue(model, value?.ToString().ChangeType(property.PropertyType), null); + } + yield return model; + } + } + /// + /// IDataReader转换成List + /// + /// + /// + /// + public static List ReaderToList(this IDataReader Reader) + { + List objectField = new List(Reader.FieldCount); + for (int i = 0; i < Reader.FieldCount; i++) + { + objectField.Add(Reader.GetName(i).ToLower()); + } + List objectList = new List(); + try + { + while (Reader.Read()) + { + T model = Activator.CreateInstance(); + foreach (PropertyInfo property in model.GetType() + .GetProperties(BindingFlags.GetProperty + | BindingFlags.Public + | BindingFlags.Instance)) + { + if (!objectField.Contains(property.Name.ToLower())) { continue; } + if (Reader[property.Name].IsNullOrEmpty()) { continue; } + property.SetValue(model, Reader[property.Name].ToString().ChangeType(property.PropertyType), null); + } + objectList.Add(model); + } + } + catch (Exception ex) + { + + throw ex; + } + finally + { + Reader.Close(); + Reader.Dispose(); + } + return objectList; + } + + + public static object ChangeType(this object convertibleValue, Type type) + { + if (null == convertibleValue) return null; + + try + { + if (type == typeof(Guid) || type == typeof(Guid?)) + { + string value = convertibleValue.ToString(); + if (value == "") return null; + return Guid.Parse(value); + } + + if (!type.IsGenericType) return Convert.ChangeType(convertibleValue, type); + if (type.ToString() == "System.Nullable`1[System.Boolean]" || type.ToString() == "System.Boolean") + { + if (convertibleValue.ToString() == "0") + return false; + return true; + } + Type genericTypeDefinition = type.GetGenericTypeDefinition(); + if (genericTypeDefinition == typeof(Nullable<>)) + { + return Convert.ChangeType(convertibleValue, Nullable.GetUnderlyingType(type)); + } + } + catch + { + return null; + } + return null; + } + /// + /// 将集合转换为数据集。 + /// + /// 转换的元素类型。 + /// 集合。 + /// 是否生成泛型数据集。 + /// 数据集。 + public static DataSet ToDataSet(this IEnumerable list, bool generic = true) + { + return ListToDataSet(list, generic); + } + + /// + /// 将集合转换为数据集。 + /// + /// 集合。 + /// 是否生成泛型数据集。 + /// 数据集。 + public static DataSet ToDataSet(this IEnumerable list, bool generic = true) + { + return ListToDataSet(list, generic); + } + + /// + /// 将集合转换为数据集。 + /// + /// 转换的元素类型。 + /// 集合。 + /// 是否生成泛型数据集。 + /// 数据集。 + public static DataSet ToDataSet(this IEnumerable list, bool generic = true) + { + return ListToDataSet(list, typeof(T), generic); + } + + /// + /// 将实例转换为集合数据集。 + /// + /// 实例类型。 + /// 实例。 + /// 是否生成泛型数据集。 + /// 数据集。 + public static DataSet ToListSet(this T o, bool generic = true) + { + if (o is IEnumerable) + { + return ListToDataSet(o as IEnumerable, generic); + } + else + { + return ListToDataSet(new T[] { o }, generic); + } + } + + /// + /// 将可序列化实例转换为XmlDocument。 + /// + /// 实例类型。 + /// 实例。 + /// XmlDocument。 + public static XmlDocument ToXmlDocument(this T o) + { + XmlDocument xmlDocument = new XmlDocument + { + InnerXml = o.ToListSet().GetXml() + }; + return xmlDocument; + } + + /// + /// 将集合转换为数据集。 + /// + /// 集合。 + /// 转换的元素类型。 + /// 是否生成泛型数据集。 + /// 转换后的数据集。 + private static DataSet ListToDataSet(IEnumerable list, Type t, bool generic) + { + DataSet ds = new DataSet("Data"); + if (t == null) + { + if (list != null) + { + foreach (var i in list) + { + if (i == null) + { + continue; + } + t = i.GetType(); + break; + } + } + if (t == null) + { + return ds; + } + } + ds.Tables.Add(t.Name); + //如果集合中元素为DataSet扩展涉及到的基本类型时,进行特殊转换。 + if (t.IsValueType || t == typeof(string)) + { + ds.Tables[0].TableName = "Info"; + ds.Tables[0].Columns.Add(t.Name); + if (list != null) + { + foreach (var i in list) + { + DataRow addRow = ds.Tables[0].NewRow(); + addRow[t.Name] = i; + ds.Tables[0].Rows.Add(addRow); + } + } + return ds; + } + //处理模型的字段和属性。 + var fields = t.GetFields(); + var properties = t.GetProperties(); + foreach (var j in fields) + { + if (!ds.Tables[0].Columns.Contains(j.Name)) + { + if (generic) + { + ds.Tables[0].Columns.Add(j.Name, j.FieldType); + } + else + { + ds.Tables[0].Columns.Add(j.Name); + } + } + } + foreach (var j in properties) + { + if (!ds.Tables[0].Columns.Contains(j.Name)) + { + if (generic) + { + ds.Tables[0].Columns.Add(j.Name, j.PropertyType); + } + else + { + ds.Tables[0].Columns.Add(j.Name); + } + } + } + if (list == null) + { + return ds; + } + //读取list中元素的值。 + foreach (var i in list) + { + if (i == null) + { + continue; + } + DataRow addRow = ds.Tables[0].NewRow(); + foreach (var j in fields) + { + MemberExpression field = Expression.Field(Expression.Constant(i), j.Name); + LambdaExpression lambda = Expression.Lambda(field, new ParameterExpression[] { }); + Delegate func = lambda.Compile(); + object value = func.DynamicInvoke(); + addRow[j.Name] = value; + } + foreach (var j in properties) + { + MemberExpression property = Expression.Property(Expression.Constant(i), j); + LambdaExpression lambda = Expression.Lambda(property, new ParameterExpression[] { }); + Delegate func = lambda.Compile(); + object value = func.DynamicInvoke(); + addRow[j.Name] = value; + } + ds.Tables[0].Rows.Add(addRow); + } + return ds; + } + + /// + /// 将集合转换为数据集。 + /// + /// 转换的元素类型。 + /// 集合。 + /// 是否生成泛型数据集。 + /// 数据集。 + private static DataSet ListToDataSet(IEnumerable list, bool generic) + { + return ListToDataSet(list, typeof(T), generic); + } + + /// + /// 将集合转换为数据集。 + /// + /// 集合。 + /// 是否转换为字符串形式。 + /// 转换后的数据集。 + private static DataSet ListToDataSet(IEnumerable list, bool generic) + { + return ListToDataSet(list, null, generic); + } + + /// + /// 获取DataSet第一表,第一行,第一列的值。 + /// + /// DataSet数据集。 + /// 值。 + public static object GetData(this DataSet ds) + { + if ( + ds == null + || ds.Tables.Count == 0 + ) + { + return string.Empty; + } + else + { + return ds.Tables[0].GetData(); + } + } + + /// + /// 获取DataTable第一行,第一列的值。 + /// + /// DataTable数据集表。 + /// 值。 + public static object GetData(this DataTable dt) + { + if ( + dt.Columns.Count == 0 + || dt.Rows.Count == 0 + ) + { + return string.Empty; + } + else + { + return dt.Rows[0][0]; + } + } + + /// + /// 获取DataSet第一个匹配columnName的值。 + /// + /// 数据集。 + /// 列名。 + /// 值。 + public static object GetData(this DataSet ds, string columnName) + { + if ( + ds == null + || ds.Tables.Count == 0 + ) + { + return string.Empty; + } + foreach (DataTable dt in ds.Tables) + { + object o = dt.GetData(columnName); + if (!string.IsNullOrEmpty(o.ToString())) + { + return o; + } + } + return string.Empty; + } + + /// + /// 获取DataTable第一个匹配columnName的值。 + /// + /// 数据表。 + /// 列名。 + /// 值。 + public static object GetData(this DataTable dt, string columnName) + { + if (string.IsNullOrEmpty(columnName)) + { + return GetData(dt); + } + if ( + dt.Columns.Count == 0 + || dt.Columns.IndexOf(columnName) == -1 + || dt.Rows.Count == 0 + ) + { + return string.Empty; + } + return dt.Rows[0][columnName]; + } + + /// + /// 将object转换为string类型信息。 + /// + /// object。 + /// 默认值。 + /// string。 + public static string ToString(this object o, string t) + { + string info = string.Empty; + if (o == null) + { + info = t; + } + else + { + info = o.ToString(); + } + return info; + } + + /// + /// 将DateTime?转换为string类型信息。 + /// + /// DateTime?。 + /// 标准或自定义日期和时间格式的字符串。 + /// 默认值。 + /// string。 + public static string ToString(this DateTime? o, string format, string t) + { + string info = string.Empty; + if (o == null) + { + info = t; + } + else + { + info = o.Value.ToString(format); + } + return info; + } + + /// + /// 将TimeSpan?转换为string类型信息。 + /// + /// TimeSpan?。 + /// 标准或自定义时间格式的字符串。 + /// 默认值。 + /// string。 + public static string ToString(this TimeSpan? o, string format, string t) + { + string info = string.Empty; + if (o == null) + { + info = t; + } + else + { + info = o.Value.ToString(format); + } + return info; + } + + + + /// + /// 将object转换为byte类型信息。 + /// + /// object。 + /// 默认值。 + /// byte。 + public static byte ToByte(this object o, byte t = default(byte)) + { + if (!byte.TryParse(o.ToString(string.Empty), out byte info)) + { + info = t; + } + return info; + } + + public static byte[] ToBytes(this object obj) + { + if (obj == null) + return null; + var bf = new DataContractSerializer(obj.GetType()); + using (var ms = new MemoryStream()) + { + bf.WriteObject(ms, obj); + return ms.ToArray(); + } + } + + public static object ToObject(this byte[] source) + { + using (var memStream = new MemoryStream()) + { + var bf = new DataContractSerializer(typeof(object)); + memStream.Write(source, 0, source.Length); + memStream.Seek(0, SeekOrigin.Begin); + var obj = bf.ReadObject(memStream); + return obj; + } + } + + /// + /// 将object转换为char类型信息。 + /// + /// object。 + /// 默认值。 + /// char。 + public static char ToChar(this object o, char t = default(char)) + { + if (!char.TryParse(o.ToString(string.Empty), out char info)) + { + info = t; + } + return info; + } + + /// + /// 将object转换为int类型信息。 + /// + /// object。 + /// 默认值。 + /// int。 + public static int ToInt(this object o, int t = default(int)) + { + if (!int.TryParse(o.ToString(string.Empty), out int info)) + { + info = t; + } + return info; + } + + /// + /// 将object转换为double类型信息。 + /// + /// object。 + /// 默认值。 + /// double。 + public static double ToDouble(this object o, double t = default(double)) + { + double info; + if (!double.TryParse(o.ToString(string.Empty), out info)) + { + info = t; + } + return info; + } + + /// + /// 将object转换为decimal类型信息。 + /// + /// object。 + /// 默认值。 + /// decimal。 + public static decimal ToDecimal(this object o, decimal t = default(decimal)) + { + decimal info; + if (!decimal.TryParse(o.ToString(string.Empty), out info)) + { + info = t; + } + return info; + } + + /// + /// 将object转换为float类型信息。 + /// + /// object。 + /// 默认值。 + /// float。 + public static float ToFloat(this object o, float t = default(float)) + { + if (!float.TryParse(o.ToString(string.Empty), out float info)) + { + info = t; + } + return info; + } + + /// + /// 将object转换为long类型信息。 + /// + /// object。 + /// 默认值。 + /// long。 + public static long ToLong(this object o, long t = default(long)) + { + long info; + if (!long.TryParse(o.ToString(string.Empty), out info)) + { + info = t; + } + return info; + } + + /// + /// 将object转换为bool类型信息。 + /// + /// object。 + /// 默认值。 + /// bool。 + public static bool ToBool(this object o, bool t = default(bool)) + { + bool info; + if (!bool.TryParse(o.ToString(string.Empty), out info)) + { + info = t; + } + return info; + } + + /// + /// 将object转换为sbyte类型信息。 + /// + /// object。 + /// 默认值。 + /// sbyte。 + public static sbyte ToSbyte(this object o, sbyte t = default(sbyte)) + { + sbyte info; + if (!sbyte.TryParse(o.ToString(string.Empty), out info)) + { + info = t; + } + return info; + } + + /// + /// 将object转换为short类型信息。 + /// + /// object。 + /// 默认值。 + /// short。 + public static short ToShort(this object o, short t = default(short)) + { + short info; + if (!short.TryParse(o.ToString(string.Empty), out info)) + { + info = t; + } + return info; + } + + /// + /// 将object转换为ushort类型信息。 + /// + /// object。 + /// 默认值。 + /// ushort。 + public static ushort ToUShort(this object o, ushort t = default(ushort)) + { + ushort info; + if (!ushort.TryParse(o.ToString(string.Empty), out info)) + { + info = t; + } + return info; + } + + /// + /// 将object转换为ulong类型信息。 + /// + /// object。 + /// 默认值。 + /// ulong。 + public static ulong ToULong(this object o, ulong t = default(ulong)) + { + ulong info; + if (!ulong.TryParse(o.ToString(string.Empty), out info)) + { + info = t; + } + return info; + } + + /// + /// 将object转换为Enum[T]类型信息。 + /// + /// object。 + /// 默认值。 + /// Enum[T]。 + public static T ToEnum(this object o, T t = default(T)) + where T : struct + { + if (!System.Enum.TryParse(o.ToString(string.Empty), out T info)) + { + info = t; + } + return info; + } + + /// + /// 将object转换为DateTime类型信息。 + /// + /// object。 + /// 默认值。 + /// DateTime。 + public static DateTime ToDateTime(this object o, DateTime t = default(DateTime)) + { + if (t == default(DateTime)) + { + t = new DateTime(1753, 1, 1); + } + DateTime info; + if (!DateTime.TryParse(o.ToString(string.Empty), out info)) + { + info = t; + } + return info; + } + + /// + /// 将object转换为TimeSpan类型信息。 + /// + /// object。 + /// 默认值。 + /// TimeSpan。 + public static TimeSpan ToTimeSpan(this object o, TimeSpan t = default(TimeSpan)) + { + if (t == default(TimeSpan)) + { + t = new TimeSpan(0, 0, 0); + } + TimeSpan info; + if (!TimeSpan.TryParse(o.ToString(string.Empty), out info)) + { + info = t; + } + return info; + } + + /// + /// 将object转换为Guid类型信息。 + /// + /// object。 + /// 默认值。 + /// Guid。 + public static Guid ToGuid(this object o, Guid t = default(Guid)) + { + Guid info; + if (!Guid.TryParse(o.ToString(string.Empty), out info)) + { + info = t; + } + return info; + } + + private static Regex BoolRegex = new Regex("(?(true|false))", RegexOptions.IgnoreCase | RegexOptions.Singleline); + + /// + /// 从object中获取bool类型信息。 + /// + /// object。 + /// bool。 + public static bool GetBool(this string value) + { + bool.TryParse(value, out bool result); + return result; + } + + private static Regex IntRegex = new Regex("(?-?\\d+)", RegexOptions.IgnoreCase | RegexOptions.Singleline); + + + + private static Regex DecimalRegex = new Regex("(?-?\\d+(\\.\\d+)?)", RegexOptions.IgnoreCase | RegexOptions.Singleline); + + /// + /// 从object中获取decimal类型信息。 + /// + /// object。 + /// decimal。 + public static decimal? GetDecimal(this object o) + { + decimal info; + if (!decimal.TryParse(DecimalRegex.Match(o.ToString(string.Empty)).Groups["info"].Value, out info)) + { + return null; + } + return info; + } + + + + /// + /// 从object中获取正数信息。 + /// + /// object。 + /// decimal。 + public static decimal? GetPositiveNumber(this object o) + { + decimal info; + if (!decimal.TryParse(DecimalRegex.Match(o.ToString(string.Empty)).Groups["info"].Value, out info)) + { + return null; + } + return Math.Abs(info); + } + + private static Regex DateTimeRegex = new Regex("(?(((\\d+)[/年-](0?[13578]|1[02])[/月-](3[01]|[12]\\d|0?\\d)[日]?)|((\\d+)[/年-](0?[469]|11)[/月-](30|[12]\\d|0?\\d)[日]?)|((\\d+)[/年-]0?2[/月-](2[0-8]|1\\d|0?\\d)[日]?))(\\s((2[0-3]|[0-1]\\d)):[0-5]\\d:[0-5]\\d)?)", RegexOptions.IgnoreCase | RegexOptions.Singleline); + + /// + /// 从object中获取DateTime?类型信息。 + /// + /// object。 + /// DateTime?。 + public static DateTime? GetDateTime1(this object o) + { + DateTime info; + if (!DateTime.TryParse(DateTimeRegex.Match(o.ToString(string.Empty)).Groups["info"].Value.Replace("年", "-").Replace("月", "-").Replace("/", "-").Replace("日", ""), out info)) + { + return null; + } + return info; + } + + private static Regex TimeSpanRegex = new Regex("(?-?(\\d+\\.(([0-1]\\d)|(2[0-3])):[0-5]\\d:[0-5]\\d)|((([0-1]\\d)|(2[0-3])):[0-5]\\d:[0-5]\\d)|(\\d+))", RegexOptions.IgnoreCase | RegexOptions.Singleline); + + /// + /// 从object中获取TimeSpan?类型信息。 + /// + /// object。 + /// TimeSpan?。 + public static TimeSpan? GetTimeSpan(this object o) + { + TimeSpan info; + if (!TimeSpan.TryParse(TimeSpanRegex.Match(o.ToString(string.Empty)).Groups["info"].Value, out info)) + { + return null; + } + return info; + } + + private static Regex GuidRegex = new Regex("(?\\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\\}{0,1})", RegexOptions.IgnoreCase | RegexOptions.Singleline); + + /// + /// 从object中获取Guid?类型信息。 + /// + /// object。 + /// Guid?。 + public static Guid? GetGuid(this object o) + { + Guid info; + if (!Guid.TryParse(GuidRegex.Match(o.ToString(string.Empty)).Groups["info"].Value, out info)) + { + return null; + } + return info; + } + + /// + /// 将object转换为SqlServer中的DateTime?类型信息。 + /// + /// object。 + /// 默认值。 + /// DateTime?。 + public static DateTime? GetSqlDateTime(this object o, DateTime t = default(DateTime)) + { + DateTime info; + if (!DateTime.TryParse(o.ToString(string.Empty), out info)) + { + info = t; + } + if (info < new DateTime(1753, 1, 1) || info > new DateTime(9999, 12, 31)) + { + return null; + } + return info; + } + + /// + /// 读取XElement节点的文本内容。 + /// + /// XElement节点。 + /// 默认值。 + /// 文本内容。 + public static string Value(this XElement xElement, string t = default(string)) + { + if (xElement == null) + { + return t; + } + else + { + return xElement.Value; + } + } + + /// + /// 获取与指定键相关的值。 + /// + /// 键类型。 + /// 值类型。 + /// 表示键/值对象的泛型集合。 + /// 键。 + /// 默认值。 + /// 值。 + public static TValue GetValue(this IDictionary dictionary, TKey key, TValue t = default(TValue)) + { + TValue value = default(TValue); + if (dictionary == null || key == null) + { + return t; + } + if (!dictionary.TryGetValue(key, out value)) + { + value = t; + } + return value; + } + + /// + /// 获取与指定键相关或者第一个的值。 + /// + /// 键类型。 + /// 值类型。 + /// 表示键/值对象的泛型集合。 + /// 键。 + /// 默认值。 + /// 值。 + public static TValue GetFirstOrDefaultValue(this IDictionary dictionary, TKey key, TValue t = default(TValue)) + { + TValue value = default(TValue); + if (dictionary == null || key == null) + { + return t; + } + if (!dictionary.TryGetValue(key, out value)) + { + if (dictionary.Count() == 0) + { + value = t; + } + else + { + value = dictionary.FirstOrDefault().Value; + } + } + return value; + } + + /// + /// 获取具有指定 System.Xml.Linq.XName 的第一个(按文档顺序)子元素。 + /// + /// XContainer。 + /// 要匹配的 System.Xml.Linq.XName。 + /// 是否返回同名默认值。 + /// 与指定 System.Xml.Linq.XName 匹配的 System.Xml.Linq.XElement,或者为 null。 + public static XElement Element(this XContainer xContainer, XName xName, bool t) + { + XElement info; + if (xContainer == null) + { + info = null; + } + else + { + info = xContainer.Element(xName); + } + if (t && info == null) + { + info = new XElement(xName); + } + return info; + } + + /// + /// 按文档顺序返回此元素或文档的子元素集合。 + /// + /// XContainer。 + /// 是否返回非空默认值。 + /// System.Xml.Linq.XElement 的按文档顺序包含此System.Xml.Linq.XContainer 的子元素,或者非空默认值。 + public static IEnumerable Elements(this XContainer xContainer, bool t) + { + IEnumerable info; + if (xContainer == null) + { + info = null; + } + else + { + info = xContainer.Elements(); + } + if (t && info == null) + { + info = new List(); + } + return info; + } + + /// + /// 按文档顺序返回此元素或文档的经过筛选的子元素集合。集合中只包括具有匹配 System.Xml.Linq.XName 的元素。 + /// + /// XContainer。 + /// 要匹配的 System.Xml.Linq.XName。 + /// 是否返回非空默认值。 + /// System.Xml.Linq.XElement 的按文档顺序包含具有匹配System.Xml.Linq.XName 的 System.Xml.Linq.XContainer 的子级,或者非空默认值。 + public static IEnumerable Elements(this XContainer xContainer, XName xName, bool t) + { + IEnumerable info; + if (xContainer == null) + { + info = null; + } + else + { + info = xContainer.Elements(xName); + } + if (t && info == null) + { + info = new List(); + } + return info; + } + + /// + /// 删除html标签。 + /// + /// 输入的字符串。 + /// 没有html标签的字符串。 + public static string RemoveHTMLTags(this string html) + { + return Regex.Replace(Regex.Replace(Regex.Replace((html ?? string.Empty).Replace(" ", " ").Replace("\r\n", " ").Replace("\n", " ").Replace("\r", " ").Replace("\t", " "), "<\\/?[^>]+>", "\r\n"), "(\r\n)+", "\r\n"), "(\\s)+", " ").Trim(); + } + + /// + /// 字符串转换为文件名。 + /// + /// 字符串。 + /// 文件名。 + public static string ToFileName(this string s) + { + return Regex.Replace(s.ToString(string.Empty), @"[\\/:*?<>|]", "_").Replace("\t", " ").Replace("\r\n", " ").Replace("\"", " "); + } + + + /// + /// 获取默认非空字符串。 + /// + /// 首选默认非空字符串。 + /// 依次非空字符串可选项。 + /// 默认非空字符串。若无可选项则返回string.Empty。 + public static string DefaultStringIfEmpty(this string s, params string[] args) + { + if (string.IsNullOrEmpty(s)) + { + return string.Empty; + } + foreach (string i in args) + { + if (!string.IsNullOrEmpty(i) && !string.IsNullOrEmpty(i.Trim())) + { + return i; + } + } + + return (s ?? string.Empty); + } + + /// + /// 对 URL 字符串进行编码。 + /// + /// 要编码的文本。 + /// 匹配要编码的文本。 + /// 指定编码方案的 System.Text.Encoding 对象。 + /// 一个已编码的字符串。 + public static string ToUrlEncodeString(this string s, Regex regex = default(Regex), Encoding encoding = null) + { + if (encoding == null) + { + encoding = Encoding.UTF8; + } + if (regex == null) + { + return HttpUtility.UrlEncode(s, encoding); + } + List l = new List(); + foreach (char i in s) + { + string t = i.ToString(); + l.Add(regex.IsMatch(t) ? HttpUtility.UrlEncode(t, encoding) : t); + } + return string.Join(string.Empty, l); + } + + /// + /// 对 URL 字符串进行编码。 + /// + /// 要编码的文本。 + /// 匹配要编码的文本。 + /// 指定编码方案的 System.Text.Encoding 对象。 + /// 一个已编码的字符串。 + public static string ToUrlEncodeString(this string s, string regex, Encoding encoding = null) + { + return ToUrlEncodeString(s, new Regex(regex), encoding); + } + + /// + /// 将日期转换为UNIX时间戳字符串 + /// + /// + /// + public static string ToUnixTimeStamp(this DateTime date) + { + DateTime startTime = TimeZoneInfo.ConvertTimeToUtc(new DateTime(1970, 1, 1)); + string timeStamp = date.Subtract(startTime).Ticks.ToString(); + return timeStamp.Substring(0, timeStamp.Length - 7); + } + + private static readonly Regex MobileRegex = new Regex("^1[3-9][0-9]\\d{4,8}$"); + private static readonly Regex EmailRegex = new Regex("^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\\.[a-zA-Z0-9_-]{2,3}){1,2})$"); + + /// + /// 判断当前字符串是否是移动电话号码 + /// + /// + /// + public static bool IsMobile(this string mobile) + { + return MobileRegex.IsMatch(mobile); + } + + /// + /// 判断当前字符串是否为邮箱 + /// + /// + /// + public static bool IsEmail(this string email) + { + return EmailRegex.IsMatch(email); + } + + } + + + + /// + /// 标记。 + /// + public enum Flag + { + /// + /// 默认。 + /// + Default, + + /// + /// 真。 + /// + True, + + /// + /// 假。 + /// + False + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/RequestExtension.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/RequestExtension.cs new file mode 100644 index 0000000000000000000000000000000000000000..ea3541ceff31b43c4a771a5875fbd98d63d2ff29 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/RequestExtension.cs @@ -0,0 +1,148 @@ +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using VOL.Core.Enums; + +namespace VOL.Core.Extensions +{ + public static class HttpContextExtension + { + + public static T GetService(this HttpContext context) where T : class + { + return context.RequestServices.GetService(typeof(T)) as T; + } + public static string GetUserIp(this HttpContext context) + { + string realIP = null; + string forwarded = null; + string remoteIpAddress = context.Connection.RemoteIpAddress.ToString(); + if (context.Request.Headers.ContainsKey("X-Real-IP")) + { + realIP = context.Request.Headers["X-Real-IP"].ToString(); + if (realIP != remoteIpAddress) + { + remoteIpAddress = realIP; + } + } + if (context.Request.Headers.ContainsKey("X-Forwarded-For")) + { + forwarded = context.Request.Headers["X-Forwarded-For"].ToString(); + if (forwarded != remoteIpAddress) + { + remoteIpAddress = forwarded; + } + } + return remoteIpAddress; + } + + /// + /// 获取Request值 + /// + /// + /// + /// + public static string Request(this HttpContext context, string parameter) + { + try + { + if (context == null) + return null; + if (context.Request.Method == "POST") + return context.Request.Form[parameter].ToString(); + else + return context.Request.Query[parameter].ToString(); + } + catch (System.Exception ex) + { + Console.Write(ex.Message + ex.InnerException); + return context.RequestString(parameter); + } + } + + public static T Request(this HttpContext context, string parameter) where T : class + { + return context.RequestString(parameter)?.DeserializeObject(); + } + public static string RequestString(this HttpContext context, string parameter) + { + string requestParam = context.GetRequestParameters(); + if (string.IsNullOrEmpty(requestParam)) return null; + Dictionary keyValues = requestParam.DeserializeObject>(); + if (keyValues == null || keyValues.Count == 0) return null; + if (keyValues.TryGetValue(parameter, out object value)) + { + if (value == null) return null; + if (value.GetType() == typeof(string)) + { + return value?.ToString(); + } + return value.Serialize(); + } + return null; + } + /// + /// 是否为ajax请求 + /// + /// + /// + public static bool IsAjaxRequest(this HttpContext context) + { + return context.Request("X-Requested-With") == "XMLHttpRequest" + || (context.Request.Headers != null + && context.Request.Headers["X-Requested-With"] == "XMLHttpRequest"); + } + + public static UserAgent GetAgentType(this HttpContext context) + { + string agent = context.Request.Headers["User-Agent"].ToString().ToLower(); + + if (agent.Contains("ios") || agent.Contains("ipod") || agent.Contains("ipad")) + { + return UserAgent.IOS; + } + if (agent.Contains("windows")) + { + return UserAgent.Windows; + } + return UserAgent.Android; + + } + + /// + /// 获取请求的参数 + /// net core 2.0已增加回读方法 context.Request.EnableRewind(); + /// + /// + /// + /// + + public static string GetRequestParameters(this HttpContext context) + { + if (context.Request.Body == null || !context.Request.Body.CanRead || !context.Request.Body.CanSeek) + return null; + if (context.Request.Body.Length == 0) + return null; + if (context.Request.Body.Position > 0) + context.Request.Body.Position = 0; + + string prarameters = null; + var bodyStream = context.Request.Body; + + using (var buffer = new MemoryStream()) + { + bodyStream.CopyToAsync(buffer); + buffer.Position = 0L; + bodyStream.Position = 0L; + using (var reader = new StreamReader(buffer, Encoding.UTF8)) + { + buffer.Seek(0, SeekOrigin.Begin); + prarameters = reader.ReadToEnd(); + } + } + return prarameters; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/Response/ApiResponseExtension.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/Response/ApiResponseExtension.cs new file mode 100644 index 0000000000000000000000000000000000000000..dd7a7d2bda3a9c5026fa37472d65858357e7acb8 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/Response/ApiResponseExtension.cs @@ -0,0 +1,43 @@ +using VOL.Core.Enums; +using VOL.Core.Utilities; + +namespace VOL.Core.Extensions +{ + public static class ApiResponseExtension + { + + //public static ApiResponseData ApiResponseOK(this ApiResponseData responseData, string msg=null) + //{ + // return responseData.ApiSetResponse(ResponseType.OperSuccess, msg, ApiStatutsCode.Ok); + //} + + //public static ApiResponseData ApiSetResponse(this ApiResponseData responseData, ResponseType responseType, ApiStatutsCode? status = null) + //{ + // return responseData.ApiSetResponse(responseType, null, status); + //} + ///// + ///// + ///// + ///// + ///// 返回消息类型 + ///// 返回消息,若msg为null,则取responseType的描述信息 + ///// 返回状态,目前只有0、失败,1、成功,2、token过期 + //public static ApiResponseData ApiSetResponse(this ApiResponseData responseData, ResponseType responseType, string msg,ApiStatutsCode? status=null) + //{ + // if (status != null) + // { + // responseData.Status = (int)status; + // } + // if (!string.IsNullOrEmpty(msg)) + // { + // responseData.Message = msg; + // return responseData; + // } + // if (!string.IsNullOrEmpty(responseData.Message)) + // return responseData; + // responseData.Message = responseType.GetMsg(); + // return responseData; + //} + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/Response/ResponseExtension.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/Response/ResponseExtension.cs new file mode 100644 index 0000000000000000000000000000000000000000..85b152a1ab5001fc22c53ccfbd5096fb6d9711e7 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/Response/ResponseExtension.cs @@ -0,0 +1,44 @@ +//using VOL.Core.Enums; +//using VOL.Entity.DomainModels; +//using System; +//using System.Collections.Generic; +//using System.Text; +//using VOL.Core.Utilities; + +//namespace VOL.Core.Extensions +//{ +// public static class ResponseExtension +// { + +// public static WebResponseContent Set(this WebResponseContent responseData, ResponseType responseType) +// { +// bool? b = null; +// return Set(responseData, responseType, b); +// } +// public static WebResponseContent Set(this WebResponseContent responseData, ResponseType responseType, bool? status) +// { +// return Set(responseData, responseType, null, status); +// } +// public static WebResponseContent Set(this WebResponseContent responseData, ResponseType responseType, string msg) +// { +// bool? b = null; +// return Set(responseData, responseType, msg, b); +// } +// public static WebResponseContent Set(this WebResponseContent responseData, ResponseType responseType, string msg, bool? status) +// { +// if (status != null) +// { +// responseData.Status = (bool)status; +// } +// responseData.Code = ((int)responseType).ToString(); +// if (!string.IsNullOrEmpty(msg)) +// { +// responseData.Desc = msg; +// return responseData; +// } +// responseData.Desc = responseType.GetMsg(); +// return responseData; +// } + +// } +//} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/Response/ResponseMsg.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/Response/ResponseMsg.cs new file mode 100644 index 0000000000000000000000000000000000000000..934d995da7d2ea8a3b44c29073eed3bf2157507e --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/Response/ResponseMsg.cs @@ -0,0 +1,59 @@ +using VOL.Core.Enums; + +namespace VOL.Core.Extensions +{ + public static class ResponseMsg + { + public static string GetMsg(this ResponseType responseType) + { + string msg; + switch (responseType) + { + case ResponseType.LoginExpiration: + msg = "登陆已过期,请重新登陆"; break; + case ResponseType.TokenExpiration: + msg = "Token已过期,请重新登陆"; break; + case ResponseType.AccountLocked: + msg = "帐号已被锁定"; break; + case ResponseType.LoginSuccess: + msg = "登陆成功"; break; + case ResponseType.ParametersLack: + msg = "参数不完整"; break; + case ResponseType.NoPermissions: + msg = "没有权限操作"; break; + case ResponseType.NoRolePermissions: + msg = "角色没有权限操作"; break; + case ResponseType.ServerError: + msg = "服务器好像出了点问题....."; break; + case ResponseType.LoginError: + msg = "用户名或密码错误"; break; + case ResponseType.SaveSuccess: + msg = "保存成功"; break; + case ResponseType.NoKey: + msg = "没有主键不能编辑"; break; + case ResponseType.NoKeyDel: + msg = "没有主键不能删除"; break; + case ResponseType.KeyError: + msg = "主键不正确或没有传入主键"; break; + case ResponseType.EidtSuccess: + msg = "编辑成功"; break; + case ResponseType.DelSuccess: + msg = "删除成功"; break; + case ResponseType.RegisterSuccess: + msg = "注册成功"; break; + case ResponseType.AuditSuccess: + msg = "审核成功"; break; + case ResponseType.ModifyPwdSuccess: + msg = "密码修改成功"; break; + case ResponseType.OperSuccess: + msg = "操作成功"; break; + case ResponseType.PINError: + msg = "验证码不正确"; break; + + default: msg = responseType.ToString(); break; + } + return msg; + } + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/SecurityEncDecryptExtension.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/SecurityEncDecryptExtension.cs new file mode 100644 index 0000000000000000000000000000000000000000..cb207e71d5815bf3bd9566a153c765abaedc7ce0 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/SecurityEncDecryptExtension.cs @@ -0,0 +1,88 @@ +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; + +namespace VOL.Core.Extensions +{ + public static class SecurityEncDecryptExtensions + { + + private static byte[] Keys = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; + /// + /// DES加密字符串 + /// + /// 待加密的字符串 + /// 加密密钥,要求为16位 + /// 加密成功返回加密后的字符串,失败返回源串 + + public static string EncryptDES(this string encryptString, string encryptKey) + { + try + { + byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 16)); + byte[] rgbIV = Keys; + byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString); + + using (var DCSP = Aes.Create()) + { + using (MemoryStream mStream = new MemoryStream()) + { + using (CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write)) + { + cStream.Write(inputByteArray, 0, inputByteArray.Length); + cStream.FlushFinalBlock(); + return Convert.ToBase64String(mStream.ToArray()).Replace('+', '_').Replace('/', '~'); + } + } + } + } + catch (Exception ex) + { + throw new Exception("密码加密异常" + ex.Message); + } + + } + + /// + /// DES解密字符串 + /// + /// 待解密的字符串 + /// 解密密钥,要求为16位,和加密密钥相同 + /// 解密成功返回解密后的字符串,失败返源串 + + public static string DecryptDES(this string decryptString, string decryptKey) + { + byte[] rgbKey = Encoding.UTF8.GetBytes(decryptKey.Substring(0, 16)); + byte[] rgbIV = Keys; + byte[] inputByteArray = Convert.FromBase64String(decryptString.Replace('_', '+').Replace('~', '/')); + using (var DCSP = Aes.Create()) + { + using (MemoryStream mStream = new MemoryStream()) + { + using (CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write)) + { + byte[] inputByteArrays = new byte[inputByteArray.Length]; + cStream.Write(inputByteArray, 0, inputByteArray.Length); + cStream.FlushFinalBlock(); + return Encoding.UTF8.GetString(mStream.ToArray()); + } + } + } + + } + public static bool TryDecryptDES(this string decryptString, string decryptKey, out string result) + { + result = ""; + try + { + result = DecryptDES(decryptString, decryptKey); + return true; + } + catch + { + return false; + } + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/ServerExtension.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/ServerExtension.cs new file mode 100644 index 0000000000000000000000000000000000000000..3b56be4d4dea2d6afe9af128de788d3bfce16eb1 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/ServerExtension.cs @@ -0,0 +1,31 @@ +using VOL.Core.BaseProvider.ServerMapPath; +using System; +using System.Collections.Generic; +using System.Text; +using VOL.Core.Extensions.AutofacManager; + +namespace VOL.Core.Extensions +{ + public static class ServerExtension + { + /// + /// 返回的路径后面不带/,拼接时需要自己加上/ + /// + /// + /// + public static string MapPath(this string path) + { + return MapPath(path, false); + } + /// + /// + /// + /// + /// 获取wwwroot路径 + /// + public static string MapPath(this string path,bool rootPath) + { + return AutofacContainerModule.GetService().MapPath(path,rootPath); + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/ServiceProviderManagerExtension.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/ServiceProviderManagerExtension.cs new file mode 100644 index 0000000000000000000000000000000000000000..e97720c19414f8fbde3e74d85d8018c1f30412bd --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/ServiceProviderManagerExtension.cs @@ -0,0 +1,18 @@ +using VOL.Core.Extensions; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.Extensions +{ + public static class ServiceProviderManagerExtension + { + public static object GetService(this Type serviceType) + { + // HttpContext.Current.RequestServices.GetRequiredService(serviceType); + return Utilities.HttpContext.Current.RequestServices.GetService(serviceType); + } + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/StaticFileExtensions.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/StaticFileExtensions.cs new file mode 100644 index 0000000000000000000000000000000000000000..e358f079a7866633d7ada3d4fe76e31350767f7f --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/StaticFileExtensions.cs @@ -0,0 +1,50 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.FileProviders; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace VOL.Core.Extensions +{ + public static class StaticDefaultFileExtensions + { + public static IApplicationBuilder UseStaticDefaultFile(this IApplicationBuilder app, string path) + { + app.UseStaticFiles(new StaticFileOptions() + { + + FileProvider = new PhysicalFileProvider( + Path.Combine(path, "Content")), + RequestPath = new PathString("/Content") + //, + //OnPrepareResponse = x => { + // x.Context.Response.Headers.Append("Cache-Control", "public,max-age=600"); + //} + }) + .UseStaticFiles(new StaticFileOptions() + { + + FileProvider = new PhysicalFileProvider( + Path.Combine(path, "fonts")), + RequestPath = new PathString("/fonts") + }) + .UseStaticFiles(new StaticFileOptions() + { + + FileProvider = new PhysicalFileProvider( + Path.Combine(path, "Scripts")), + RequestPath = new PathString("/Scripts") + }) + .UseStaticFiles(new StaticFileOptions() + { + + FileProvider = new PhysicalFileProvider( + Path.Combine(path, "Html")), + RequestPath = new PathString("/Html") + }); + return app; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/StaticHttpContextExtensions.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/StaticHttpContextExtensions.cs new file mode 100644 index 0000000000000000000000000000000000000000..e45407f12a447dc095449c10a0154e84967134f3 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/StaticHttpContextExtensions.cs @@ -0,0 +1,25 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.Extensions +{ + public static class StaticHttpContextExtensions + { + //public static void AddHttpContextAccessor(this IServiceCollection services) + //{ + // services.AddSingleton(); + //} + + public static IApplicationBuilder UseStaticHttpContext(this IApplicationBuilder app) + { + var httpContextAccessor = app.ApplicationServices.GetRequiredService(); + Utilities.HttpContext.Configure(httpContextAccessor); + return app; + } + } + +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/StringExtension.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/StringExtension.cs new file mode 100644 index 0000000000000000000000000000000000000000..f5e3aa0d2bdaee5c15d915cb971949193b564cb4 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Extensions/StringExtension.cs @@ -0,0 +1,577 @@ +using System; +using System.Runtime.InteropServices; +using System.Text.RegularExpressions; +using VOL.Core.Const; +using VOL.Core.Enums; +using VOL.Core.ManageUser; + +namespace VOL.Core.Extensions +{ + public static class StringExtension + { + public static bool _windows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + public static string ReplacePath(this string path) + { + if (string.IsNullOrEmpty(path)) + return ""; + if (_windows) + return path.Replace("/", "\\"); + return path.Replace("\\", "/"); + + } + private static DateTime dateStart = new DateTime(1970, 1, 1, 8, 0, 0); + + private static long longTime = 621355968000000000; + + private static int samllTime = 10000000; + /// + /// 获取时间戳 + /// + /// + /// + public static long GetTimeStamp(this DateTime dateTime) + { + return (dateTime.ToUniversalTime().Ticks - longTime) / samllTime; + } + /// + /// 时间戳转换成日期 + /// + /// + /// + public static DateTime GetTimeSpmpToDate(this object timeStamp) + { + if (timeStamp == null) return dateStart; + DateTime dateTime = new DateTime(longTime + Convert.ToInt64(timeStamp) * samllTime, DateTimeKind.Utc).ToLocalTime(); + return dateTime; + } + public static string CreateHtmlParas(this string urlPath, int? userId = null) + { + if (string.IsNullOrEmpty(urlPath)) + return null; + userId = userId ?? UserContext.Current.UserInfo.User_Id; + return $"{urlPath}{(urlPath.IndexOf("?token") > 0 ? "&" : "?")}uid={userId}&rt_v={DateTime.Now.ToString("HHmmss")}"; + // return urlPath + ((urlPath.IndexOf("?token") > 0 ? "&" : "?") + "uid=" + userId); + } + + public static bool IsUrl(this string str) + { + if (string.IsNullOrEmpty(str)) + return false; + string Url = @"(http://)?([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?"; + return Regex.IsMatch(str, Url); + + } + /// + /// 判断是不是正确的手机号码 + /// + /// + /// + public static bool IsPhoneNo(this string input) + { + if (string.IsNullOrEmpty(input)) + return false; + if (input.Length != 11) + return false; + + if (new Regex(@"^1[3578][01379]\d{8}$").IsMatch(input) + || new Regex(@"^1[34578][01256]\d{8}").IsMatch(input) + || new Regex(@"^(1[012345678]\d{8}|1[345678][0123456789]\d{8})$").IsMatch(input) + ) + return true; + return false; + } + + public static string GetDBCondition(this string stringType) + { + string reslut = ""; + switch (stringType?.ToLower()) + { + case HtmlElementType.droplist: + case HtmlElementType.selectlist: + case HtmlElementType.textarea: + case HtmlElementType.checkbox: + reslut = HtmlElementType.Contains; + break; + case HtmlElementType.thanorequal: + reslut = HtmlElementType.ThanOrEqual; + break; + case HtmlElementType.lessorequal: + reslut = HtmlElementType.LessOrequal; + break; + case HtmlElementType.gt: + reslut = HtmlElementType.GT; + break; + case HtmlElementType.lt: + reslut = HtmlElementType.lt; + break; + case HtmlElementType.like: + reslut = HtmlElementType.like; + break; + default: + reslut = HtmlElementType.Equal; + break; + } + return reslut; + } + + public static LinqExpressionType GetLinqCondition(this string stringType) + { + LinqExpressionType linqExpression; + switch (stringType) + { + case HtmlElementType.Contains: + linqExpression = LinqExpressionType.In; + break; + case HtmlElementType.ThanOrEqual: + linqExpression = LinqExpressionType.ThanOrEqual; + break; + case HtmlElementType.LessOrequal: + linqExpression = LinqExpressionType.LessThanOrEqual; + break; + case HtmlElementType.GT: + linqExpression = LinqExpressionType.GreaterThan; + break; + case HtmlElementType.lt: + linqExpression = LinqExpressionType.LessThan; + break; + case HtmlElementType.like: + linqExpression = LinqExpressionType.Contains; + break; + default: + linqExpression = LinqExpressionType.Equal; + break; + } + return linqExpression; + } + + public static bool GetGuid(this string guid, out Guid outId) + { + Guid emptyId = Guid.Empty; + return Guid.TryParse(guid, out outId); + } + + public static bool IsGuid(this string guid) + { + Guid newId; + return guid.GetGuid(out newId); + } + + public static bool IsInt(this object obj) + { + if (obj == null) + return false; + bool reslut = Int32.TryParse(obj.ToString(), out int _number); + return reslut; + + } + public static bool IsDate(this object str) + { + return str.IsDate(out _); + } + public static bool IsDate(this object str, out DateTime dateTime) + { + dateTime = DateTime.Now; + if (str == null || str.ToString() == "") + { + return false; + } + return DateTime.TryParse(str.ToString(), out dateTime); + } + /// + /// 根据传入格式判断是否为小数 + /// + /// + /// 18,5 + /// + public static bool IsNumber(this string str, string formatString) + { + if (string.IsNullOrEmpty(str)) return false; + + return Regex.IsMatch(str, @"^[+-]?\d*[.]?\d*$"); + //int precision = 32; + //int scale = 5; + //try + //{ + // if (string.IsNullOrEmpty(formatString)) + // { + // precision = 10; + // scale = 2; + // } + // else + // { + // string[] numbers = formatString.Split(','); + // precision = Convert.ToInt32(numbers[0]); + // scale = numbers.Length == 0 ? 2 : Convert.ToInt32(numbers[1]); + // } + //} + //catch { }; + //return IsNumber(str, precision, scale); + } + /**/ + /// + /// 判断一个字符串是否为合法数字(指定整数位数和小数位数) + /// + /// 字符串 + /// 整数位数 + /// 小数位数 + /// + public static bool IsNumber(this string str, int precision, int scale) + { + if ((precision == 0) && (scale == 0)) + { + return false; + } + string pattern = @"(^\d{1," + precision + "}"; + if (scale > 0) + { + pattern += @"\.\d{0," + scale + "}$)|" + pattern; + } + pattern += "$)"; + return Regex.IsMatch(str, pattern); + } + + + public static bool IsNullOrEmpty(this object str) + { + if (str == null) + return true; + return str.ToString() == ""; + } + + + public static int GetInt(this object obj) + { + if (obj == null) + return 0; + int.TryParse(obj.ToString(), out int _number); + return _number; + + } + + /// + /// 获取 object 中的枚举值 + /// + /// + /// + /// + public static long GetLong(this object obj) + { + if (obj == null) + return 0; + + try + { + return Convert.ToInt64(Convert.ToDouble(obj)); + } + catch + { + return 0; + } + } + + /// + /// 获取 object 中的 float + /// + /// + /// + + public static float GetFloat(this object obj) + { + if (System.DBNull.Value.Equals(obj) || null == obj) + return 0; + + try + { + return float.Parse(obj.ToString()); + } + catch + { + return 0; + } + } + + public static double GetDouble(this object obj) + { + if (System.DBNull.Value.Equals(obj) || null == obj) + return 0; + + try + { + return Convert.ToDouble(obj); + } + catch + { + return 0; + } + } + /// + /// 获取 object 中的 decimal + /// + /// + /// + /// + public static decimal GetDecimal(this object obj) + { + if (System.DBNull.Value.Equals(obj) || null == obj) + return 0; + + try + { + return Convert.ToDecimal(obj); + } + catch + { + return 0; + } + } + + /// + /// 获取 object 中的 decimal + /// + /// + /// + /// + public static dynamic GetDynamic(this object obj) + { + if (System.DBNull.Value.Equals(obj) || null == obj) + return null; + + try + { + string str = obj.ToString(); + if (str.IsNumber(25, 15)) return Convert.ToDecimal(obj); + else return str; + } + catch + { + return string.Empty; + } + } + + public static DateTime? GetDateTime(this object obj) + { + if (System.DBNull.Value.Equals(obj) || null == obj) + return null; + bool result = DateTime.TryParse(obj.ToString(), out DateTime dateTime); + if (!result) + return null; + return dateTime; + } + + + + public static object ParseTo(this string str, string type) + { + switch (type) + { + case "System.Boolean": + return ToBoolean(str); + case "System.SByte": + return ToSByte(str); + case "System.Byte": + return ToByte(str); + case "System.UInt16": + return ToUInt16(str); + case "System.Int16": + return ToInt16(str); + case "System.uInt32": + return ToUInt32(str); + case "System.Int32": + return str.ToInt32(); + case "System.UInt64": + return ToUInt64(str); + case "System.Int64": + return ToInt64(str); + case "System.Single": + return ToSingle(str); + case "System.Double": + return ToDouble(str); + case "System.Decimal": + return ToDecimal(str); + case "System.DateTime": + return ToDateTime(str); + case "System.Guid": + return ToGuid(str); + } + throw new NotSupportedException(string.Format("The string of \"{0}\" can not be parsed to {1}", str, type)); + } + + public static sbyte? ToSByte(this string value) + { + sbyte value2; + if (sbyte.TryParse(value, out value2)) + { + return value2; + } + return null; + } + + public static byte? ToByte(this string value) + { + byte value2; + if (byte.TryParse(value, out value2)) + { + return value2; + } + return null; + } + + public static ushort? ToUInt16(this string value) + { + ushort value2; + if (ushort.TryParse(value, out value2)) + { + return value2; + } + return null; + } + + public static short? ToInt16(this string value) + { + if (short.TryParse(value, out short value2)) + { + return value2; + } + return null; + } + + public static uint? ToUInt32(this string value) + { + uint value2; + if (uint.TryParse(value, out value2)) + { + return value2; + } + return null; + } + + public static ulong? ToUInt64(this string value) + { + ulong value2; + if (ulong.TryParse(value, out value2)) + { + return value2; + } + return null; + } + + public static long? ToInt64(this string value) + { + long value2; + if (long.TryParse(value, out value2)) + { + return value2; + } + return null; + } + + public static float? ToSingle(this string value) + { + float value2; + if (float.TryParse(value, out value2)) + { + return value2; + } + return null; + } + + public static double? ToDouble(this string value) + { + double value2; + if (double.TryParse(value, out value2)) + { + return value2; + } + return null; + } + + public static decimal? ToDecimal(this string value) + { + decimal value2; + if (decimal.TryParse(value, out value2)) + { + return value2; + } + return null; + } + + public static bool? ToBoolean(this string value) + { + bool value2; + if (bool.TryParse(value, out value2)) + { + return value2; + } + return null; + } + + + + public static Guid? ToGuid(this string str) + { + Guid value; + if (Guid.TryParse(str, out value)) + { + return value; + } + return null; + } + + public static DateTime? ToDateTime(this string value) + { + DateTime value2; + if (DateTime.TryParse(value, out value2)) + { + return value2; + } + return null; + } + + public static int? ToInt32(this string input) + { + if (string.IsNullOrEmpty(input)) + { + return null; + } + int value; + if (int.TryParse(input, out value)) + { + return value; + } + return null; + } + + /// + /// 替换空格字符 + /// + /// + /// 替换为该字符 + /// 替换后的字符串 + public static string ReplaceWhitespace(this string input, string replacement = "") + { + return string.IsNullOrEmpty(input) ? null : Regex.Replace(input, "\\s", replacement, RegexOptions.Compiled); + } + + private static char[] randomConstant ={ + '0','1','2','3','4','5','6','7','8','9', + 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z', + 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z' + }; + /// + /// 生成指定长度的随机数 + /// + /// + /// + public static string GenerateRandomNumber(this int length) + { + System.Text.StringBuilder newRandom = new System.Text.StringBuilder(62); + Random rd = new Random(); + for (int i = 0; i < length; i++) + { + newRandom.Append(randomConstant[rd.Next(62)]); + } + return newRandom.ToString(); + } + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ActionExecuteFilter.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ActionExecuteFilter.cs new file mode 100644 index 0000000000000000000000000000000000000000..c8703acb2d4fa0b58dc9824b6f4421a1b3bcfa2f --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ActionExecuteFilter.cs @@ -0,0 +1,26 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using System; +using System.Linq; +using VOL.Core.Enums; +using VOL.Core.Extensions; +using VOL.Core.ObjectActionValidator; +using VOL.Core.Services; +using VOL.Core.Utilities; + +namespace VOL.Core.Filters +{ + public class ActionExecuteFilter : IActionFilter + { + + public void OnActionExecuting(ActionExecutingContext context) + { + //验证方法参数 + context.ActionParamsValidator(); + } + public void OnActionExecuted(ActionExecutedContext context) + { + + } + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ActionPermissionAttribute.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ActionPermissionAttribute.cs new file mode 100644 index 0000000000000000000000000000000000000000..d9f0fcce00080b8e39d2b492597fa4b3dccd9549 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ActionPermissionAttribute.cs @@ -0,0 +1,84 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Linq; +using VOL.Core.Enums; +using VOL.Core.Extensions; + +namespace VOL.Core.Filters +{ + public class ActionPermissionAttribute : TypeFilterAttribute + { + public ActionPermissionAttribute(bool isApi = false) + : base(typeof(ActionPermissionFilter)) + { + Arguments = new object[] { new ActionPermissionRequirement() { IsApi = isApi } }; + } + /// + /// 限定角色访问 + /// + /// + public ActionPermissionAttribute(int roleId, bool isApi = false) + : base(typeof(ActionPermissionFilter)) + { + Arguments = new object[] { new ActionPermissionRequirement() { RoleIds = new int[] { roleId }, IsApi = isApi } }; + } + public ActionPermissionAttribute(ActionRolePermission actionRolePermission, bool isApi = false) + : base(typeof(ActionPermissionFilter)) + { + Array array = Enum.GetValues(typeof(ActionRolePermission)); + List roles = new List(); + foreach (ActionRolePermission item in array) + { + if (actionRolePermission.HasFlag(item)) + { + roles.Add((int)item); + } + } + Arguments = new object[] { new ActionPermissionRequirement() { RoleIds = roles.ToArray(), IsApi = isApi } }; + } + /// + /// 限定角色访问 + /// + /// + public ActionPermissionAttribute(int[] roleIds, bool isApi = false) + : base(typeof(ActionPermissionFilter)) + { + Arguments = new object[] { new ActionPermissionRequirement() { RoleIds = roleIds, IsApi = isApi } }; + } + + public ActionPermissionAttribute(string tableName, ActionPermissionOptions tableAction, bool sysController = false, bool isApi = false) + : base(typeof(ActionPermissionFilter)) + { + this.SetActionPermissionRequirement(tableName, tableAction, sysController, isApi); + } + + public ActionPermissionAttribute(string tableName, string roleIds, ActionPermissionOptions tableAction, bool sysController = false, bool isApi = false) + : base(typeof(ActionPermissionFilter)) + { + this.SetActionPermissionRequirement(tableName, tableAction, (roleIds ?? "").Split(",").Select(x => x.GetInt()).ToArray(), sysController, isApi); + } + + public ActionPermissionAttribute(ActionPermissionOptions tableAction, bool isApi = false) + : base(typeof(ActionPermissionFilter)) + { + this.SetActionPermissionRequirement("", tableAction, true, isApi); + } + private void SetActionPermissionRequirement(string tableName, ActionPermissionOptions tableAction, + int[] roleId, bool sysController = false, bool isApi = false) + { + Arguments = new object[] { new ActionPermissionRequirement() { + SysController=sysController, + TableAction=tableAction.ToString(), + TableName=tableName, + IsApi = isApi, + RoleIds=roleId + } }; + } + + private void SetActionPermissionRequirement(string tableName, ActionPermissionOptions tableAction, bool sysController = false, bool isApi = false, int? roleId = null) + { + SetActionPermissionRequirement(tableName, tableAction, roleId == null ? null : new int[] { (int)roleId }, sysController, isApi); + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ActionPermissionFilter.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ActionPermissionFilter.cs new file mode 100644 index 0000000000000000000000000000000000000000..1fdb1b4acbbe032049bbd102ba836196d5ec9b44 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ActionPermissionFilter.cs @@ -0,0 +1,114 @@ +using Microsoft.AspNetCore.Mvc.Authorization; +using Microsoft.AspNetCore.Mvc.Filters; +using System.Linq; +using System.Threading.Tasks; +using VOL.Core.Configuration; +using VOL.Core.Enums; +using VOL.Core.ManageUser; +using VOL.Core.Services; +using VOL.Core.Utilities; +using VOL.Entity.AttributeManager; + +namespace VOL.Core.Filters +{ + /// + /// 1、控制器或controller设置了AllowAnonymousAttribute直接返回 + /// 2、TableName、TableAction 同时为null,SysController为false的,只判断是否登陆 + /// 3、TableName、TableAction 都不null根据表名与action判断是否有权限 + /// 4、SysController为true,通过httpcontext获取表名与action判断是否有权限 + /// 5、Roles对指定角色验证 + /// + public class ActionPermissionFilter : IAsyncActionFilter + { + private WebResponseContent ResponseContent { get; set; } + private ActionPermissionRequirement ActionPermission; + private UserContext _userContext { get; set; } + // private ResponseType responseType; + public ActionPermissionFilter(ActionPermissionRequirement actionPermissionRequirement, UserContext userContext) + { + this.ResponseContent = new WebResponseContent(); + this.ActionPermission = actionPermissionRequirement; + _userContext = userContext; + } + public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) + { + if (OnActionExecutionPermission(context).Status) + { + await next(); + return; + } + FilterResponse.SetActionResult(context, ResponseContent); + } + private WebResponseContent OnActionExecutionPermission(ActionExecutingContext context) + { + //!context.Filters.Any(item => item is IFixedTokenFilter))固定token的是否验证权限 + //if ((context.Filters.Any(item => item is IAllowAnonymousFilter) + // && !context.Filters.Any(item => item is IFixedTokenFilter)) + // || UserContext.Current.IsSuperAdmin + // ) + if (context.Filters.Any(item => item is IAllowAnonymousFilter) + || UserContext.Current.IsSuperAdmin) + return ResponseContent.OK(); + + //演示环境除了admin帐号,其他帐号都不能增删改等操作 + if (!_userContext.IsSuperAdmin && AppSetting.GlobalFilter.Enable + && AppSetting.GlobalFilter.Actions.Contains(((Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor)context.ActionDescriptor).ActionName)) + { + return ResponseContent.Error(AppSetting.GlobalFilter.Message); + } + + //如果没有指定表的权限,则默认为代码生成的控制器,优先获取PermissionTableAttribute指定的表,如果没有数据则使用当前控制器的名作为表名权限 + if (ActionPermission.SysController) + { + object[] permissionArray = ((Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor)context.ActionDescriptor)?.ControllerTypeInfo.GetCustomAttributes(typeof(PermissionTableAttribute), false); + if (permissionArray == null || permissionArray.Length == 0) + { + ActionPermission.TableName = ((Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor)context.ActionDescriptor).ControllerName; + } + else + { + ActionPermission.TableName = (permissionArray[0] as PermissionTableAttribute).Name; + } + if (string.IsNullOrEmpty(ActionPermission.TableName)) + { + //responseType = ResponseType.ParametersLack; + return ResponseContent.Error(ResponseType.ParametersLack); + } + } + + //如果没有给定权限,不需要判断 + if (string.IsNullOrEmpty(ActionPermission.TableName) + && string.IsNullOrEmpty(ActionPermission.TableAction) + && (ActionPermission.RoleIds == null || ActionPermission.RoleIds.Length == 0)) + { + return ResponseContent.OK(); + } + + //是否限制的角色ID称才能访问 + //权限判断角色ID, + if (ActionPermission.RoleIds != null && ActionPermission.RoleIds.Length > 0) + { + if (ActionPermission.RoleIds.Contains(_userContext.UserInfo.Role_Id)) return ResponseContent.OK(); + //如果角色ID没有权限。并且也没控制器权限 + if (string.IsNullOrEmpty(ActionPermission.TableAction)) + { + return ResponseContent.Error(ResponseType.NoRolePermissions); + } + } + //2020.05.05移除x.TableName.ToLower()转换,获取权限时已经转换成为小写 + var actionAuth = _userContext.GetPermissions(x => x.TableName == ActionPermission.TableName.ToLower())?.UserAuthArr; + + if (actionAuth == null + || actionAuth.Count() == 0 + || !actionAuth.Contains(ActionPermission.TableAction)) + { + Logger.Info(LoggerType.Authorzie, $"没有权限操作," + + $"用户ID{_userContext.UserId}:{_userContext.UserTrueName}," + + $"角色ID:{_userContext.RoleId}:{_userContext.UserInfo.RoleName}," + + $"操作权限{ActionPermission.TableName}:{ActionPermission.TableAction}"); + return ResponseContent.Error(ResponseType.NoPermissions); + } + return ResponseContent.OK(); + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ActionPermissionRequirement.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ActionPermissionRequirement.cs new file mode 100644 index 0000000000000000000000000000000000000000..42ec407e75690b68e32e0e9b462344f8795e7209 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ActionPermissionRequirement.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.Filters +{ + public class ActionPermissionRequirement + { + /// + /// 控制器要操作的表 + /// + public string TableName { get; set; } = string.Empty; + /// + /// 对表的操作/删除/查询等 + /// + public string TableAction { get; set; } = string.Empty; + /// + /// 是否为框架定义的控制器 + /// + public bool SysController { get; set; } + /// + /// 限制只能由某些角色Id访问 + /// + public int[] RoleIds { get; set; } + + public bool IsApi { get; set; } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ApiActionPermissionAttribute.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ApiActionPermissionAttribute.cs new file mode 100644 index 0000000000000000000000000000000000000000..78868e900e5f773e69244eb74c56fe544457c24b --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ApiActionPermissionAttribute.cs @@ -0,0 +1,55 @@ +using System; +using VOL.Core.Enums; + +namespace VOL.Core.Filters +{ + public class ApiActionPermissionAttribute : ActionPermissionAttribute + { + public ApiActionPermissionAttribute() + : base(true) + { + } + /// + /// 限定角色访问 + /// + /// + public ApiActionPermissionAttribute(int roleId) + : base(roleId, true) + { + } + /// + /// 限定角色访问 + /// + /// + public ApiActionPermissionAttribute(ActionRolePermission actionRolePermission) + : base(actionRolePermission, true) + { + + } + + public ApiActionPermissionAttribute(string tableName, ActionPermissionOptions tableAction, bool sysController = false) + : base(tableName, tableAction, sysController, true) + { + + } + public ApiActionPermissionAttribute(string tableName, string roleIds, ActionPermissionOptions tableAction, bool sysController = false) + : base(tableName, roleIds, tableAction, sysController, true) + { + } + public ApiActionPermissionAttribute(ActionPermissionOptions tableAction) + : base(tableAction, true) + { + + } + + } + + public enum ActionRolePermission + { + /// + /// 角色ID为1 + /// + SuperAdmin = 1, + Admin=2 + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ApiAuthorizeFilter.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ApiAuthorizeFilter.cs new file mode 100644 index 0000000000000000000000000000000000000000..d3d7a5fd9552e3af8d81ff035bd2cc4743939642 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ApiAuthorizeFilter.cs @@ -0,0 +1,85 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc.Authorization; +using Microsoft.AspNetCore.Mvc.Filters; +using System; +using System.IdentityModel.Tokens.Jwt; +using System.Linq; +using System.Net; +using System.Security.Claims; +using VOL.Core.Configuration; +using VOL.Core.Extensions; +using VOL.Core.ManageUser; +using static VOL.Core.Filters.ApiTaskAttribute; + +namespace VOL.Core.Filters +{ + public class ApiAuthorizeFilter : IAuthorizationFilter + { + + public ApiAuthorizeFilter() + { + + } + /// + /// 只判断token是否正确,不判断权限 + /// 如果需要判断权限的在Action上加上ApiActionPermission属性标识权限类别,ActionPermissionFilter作权限处理 + ///(string,string,string)1、请求参数,2、返回消息,3,异常消息,4状态 + /// + /// + public void OnAuthorization(AuthorizationFilterContext context) + { + // is Microsoft.AspNetCore.Authentication.AllowAnonymousAttribute + //if (context.Filters.Any(item => item is IAllowAnonymousFilter)) + if (context.ActionDescriptor.EndpointMetadata.Any(item => item is IAllowAnonymous)) + { + if (context.Filters + .Where(item => item is IApiTaskFilter) + .FirstOrDefault() is IApiTaskFilter apiTaskFilter) + { + apiTaskFilter.OnAuthorization(context); + return; + } + //如果使用了固定Token不过期,直接对token的合法性及token是否存在进行验证 + else if (context.Filters + .Where(item => item is IFixedTokenFilter) + .FirstOrDefault() is IFixedTokenFilter tokenFilter) + { + tokenFilter.OnAuthorization(context); + return; + } + //匿名并传入了token,需要将用户的ID缓存起来,保证UserHelper里能正确获取到用户信息 + if (!context.HttpContext.User.Identity.IsAuthenticated + && !string.IsNullOrEmpty(context.HttpContext.Request.Headers[AppSetting.TokenHeaderName])) + { + context.AddIdentity(); + } + return; + } + //限定一个帐号不能在多处登陆 UserContext.Current.Token != ((ClaimsIdentity)context.HttpContext.User.Identity)?.BootstrapContext?.ToString() + + // &&UserContext.Current.UserName!="admin666"为演示环境,实际使用时去掉此条件 + //if (!context.HttpContext.User.Identity.IsAuthenticated + // || ( + // UserContext.Current.Token != ((ClaimsIdentity)context.HttpContext.User.Identity) + // ?.BootstrapContext?.ToString() + // && UserContext.Current.UserName != "admin666" + // )) + //{ + // Console.Write($"IsAuthenticated:{context.HttpContext.User.Identity.IsAuthenticated}," + + // $"userToken{UserContext.Current.Token}" + + // $"BootstrapContext:{((ClaimsIdentity)context.HttpContext.User.Identity)?.BootstrapContext?.ToString()}"); + // context.Unauthorized("登陆已过期"); + // return; + //} + + DateTime expDate = context.HttpContext.User.Claims.Where(x => x.Type == JwtRegisteredClaimNames.Exp) + .Select(x => x.Value).FirstOrDefault().GetTimeSpmpToDate(); + //动态标识刷新token(2021.05.01) + if ((expDate - DateTime.Now).TotalMinutes < AppSetting.ExpMinutes/ 3 && context.HttpContext.Request.Path != replaceTokenPath) + { + context.HttpContext.Response.Headers.Add("vol_exp", "1"); + } + } + private static readonly string replaceTokenPath = "/api/User/replaceToken"; + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ApiTaskAttribute.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ApiTaskAttribute.cs new file mode 100644 index 0000000000000000000000000000000000000000..933f1ee663b7a3711c78b6e99f6ea88922681ee4 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ApiTaskAttribute.cs @@ -0,0 +1,26 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Primitives; +using System; +using System.Collections.Generic; +using System.Text; +using VOL.Core.Configuration; +using VOL.Core.Extensions; +using VOL.Core.Quartz; + +namespace VOL.Core.Filters +{ + public interface IApiTaskFilter : IFilterMetadata + { + AuthorizationFilterContext OnAuthorization(AuthorizationFilterContext context); + } + public class ApiTaskAttribute : Attribute, IApiTaskFilter, IAllowAnonymous + { + public AuthorizationFilterContext OnAuthorization(AuthorizationFilterContext context) + { + return QuartzAuthorization.Validation(context) ; + } + } + +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/FixedTokenAttribute.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/FixedTokenAttribute.cs new file mode 100644 index 0000000000000000000000000000000000000000..9df7752b13812256ae33cc489ef196d877804203 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/FixedTokenAttribute.cs @@ -0,0 +1,53 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc.Filters; +using System; +using System.Net; +using System.Security.Claims; +using VOL.Core.Configuration; +using VOL.Core.Extensions; +using VOL.Core.ManageUser; +using VOL.Core.Utilities; + +namespace VOL.Core.Filters +{ + public interface IFixedTokenFilter : IFilterMetadata + { + AuthorizationFilterContext OnAuthorization(AuthorizationFilterContext context); + } + public class FixedTokenAttribute : Attribute, IFixedTokenFilter, IAllowAnonymous + { + public AuthorizationFilterContext OnAuthorization(AuthorizationFilterContext context) + { + string fixedoken = ""; + //如果token已失效,直接获取header里的token + if (!context.HttpContext.User.Identity.IsAuthenticated) + { + fixedoken = context.HttpContext.Request.Headers[AppSetting.TokenHeaderName]; + fixedoken = fixedoken?.Replace("Bearer ", ""); + //判断是否传入了token + if (string.IsNullOrEmpty(fixedoken)) + { + return context.Unauthorized("没有传入token"); + } + //解析token + int userId = JwtHelper.GetUserId(fixedoken); + if (userId <= 0) + { + return context.Unauthorized("token不正确"); + } + context.AddIdentity(userId); + } + else + { + fixedoken = ((ClaimsIdentity)context.HttpContext.User.Identity) + ?.BootstrapContext?.ToString(); + } + //判断当前用户的token与缓存的token是否相同 + if (UserContext.Current.Token != fixedoken) + { + context.FilterResult(HttpStatusCode.Unauthorized, "token已失效"); + } + return context; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/JWTAuthorize.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/JWTAuthorize.cs new file mode 100644 index 0000000000000000000000000000000000000000..4274dce23ac82b67ad79cc396fc364243a92440e --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/JWTAuthorize.cs @@ -0,0 +1,15 @@ +using Microsoft.AspNetCore.Authorization; +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.Filters +{ + public class JWTAuthorizeAttribute : AuthorizeAttribute + { + public JWTAuthorizeAttribute() : base() + { + + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ServiceFunFilter.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ServiceFunFilter.cs new file mode 100644 index 0000000000000000000000000000000000000000..8c1142cf9671c172cad9c1e1f084dd4b62c5e114 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Filters/ServiceFunFilter.cs @@ -0,0 +1,244 @@ +using OfficeOpenXml; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using VOL.Core.Enums; +using VOL.Core.Utilities; +using VOL.Core.WorkFlow; +using VOL.Entity.DomainModels; + +namespace VOL.Core.Filters +{ + public abstract class ServiceFunFilter where T : class + { + + /// + /// 2020.08.15是否开启多租户功能 + /// 使用方法见文档或SellOrderService.cs + /// + protected bool IsMultiTenancy { get; set; } + + /// + /// 查询界面table 统计、求和、平均值等 + /// 实现方式 + ///SummaryExpress = (IQueryable queryable) => + // { + // return queryable.GroupBy(x => 1).Select(x => new + // { + // AvgPrice = x.Average(o => o.AvgPrice), + // Enable = x.Sum(o => o.Enable) + // }).FirstOrDefault(); + //}; + /// + // protected Func, object> SummaryExpress = null; + protected Func, object> SummaryExpress = null; + + /// + /// 明细table 统计、求和、平均值等 + /// + /// + /// + /// + protected abstract object GetDetailSummary(IQueryable queryeable); + + /// + /// 是否开启用户数据权限,true=用户只能操作自己(及下级角色)创建的数据,如:查询、删除、修改等操作 + /// 注意:需要在代码生成器界面选择【是】及生成Model才会生效) + /// + protected bool LimitCurrentUserPermission { get; set; } = false; + + ///默认导出最大表数量:0不限制 + protected int Limit { get; set; } = 0; + + /// + /// 默认上传文件大小限制3M + /// + protected int LimitUpFileSizee { get; set; } = 3; + + + /// + /// 2020.08.15添加自定义原生查询sql,这个对于不想写表达式关联或者复杂查询非常有用 + /// 例:QuerySql=$"select * from tb1 as a where a.name='xxxx' x.id in (select b.id from tb2 b)"; + /// select * 这里可以自定义,但select 必须返回表所有的列,不能少 + /// + protected string QuerySql = null; + + /// + /// 查询前,对现在有的查询字符串条件增加或删除 + /// + protected Action> QueryRelativeList { get; set; } + + //查询前,在现有的查询条件上通过表达式修改查询条件 + protected Func, IQueryable> QueryRelativeExpression { get; set; } + + + /// + /// 指定查询的列,格式:Expression> exp = x => new { x.字段1, x.字段2 }(暂时未启用) + /// + protected Expression> Columns { get; set; } + + /// + /// 设置查询排序参数及方式,参数格式为: + /// Expression>> orderBy = x => new Dictionary() + /// {{ x.ID, QueryOrderBy.Asc },{ x.DestWarehouseName, QueryOrderBy.Desc } }; + /// 返回的是new Dictionary(){{}}key为排序字段,QueryOrderBy为排序方式 + /// + protected Expression>> OrderByExpression; + + /// + /// 设置查询的表名(已弃用) + /// + protected string TableName { get; set; } + + /// + /// 页面查询或导出,从数据库查询出来的结果 + /// + protected Action> GetPageDataOnExecuted; + + /// + /// 调用新建处理前(SaveModel为传入的原生数据) + /// + protected Func AddOnExecute; + + /// + /// 调用新建保存数据库前处理(已将提交的原生数据转换成了对象) + /// Func T为主表数据,object为明细数据(如果需要使用明细对象,请用 object as List转换) + /// + protected Func AddOnExecuting; + + /// + /// 调用新建保存数据库后处理。 + /// **实现当前方法时,内部默认已经开启事务,如果实现的方法操作的是同一数据库,则不需要在AddOnExecuted中事务 + /// Func T为主表数据,object为明细数据(如果需要使用明细对象,请用 object as List转换) + /// 此处已开启了DbContext事务(重点),如果还有其他业务处事,直接在这里写EF代码,不需要再开启事务 + /// 如果执行的是手写sql请用repository.DbContext.Database.ExecuteSqlCommand()或 repository.DbContext.Set().FromSql执行具体sql语句 + /// + protected Func AddOnExecuted; + + /// + /// 进入审批流程方法之前 + /// + protected Func AddWorkFlowExecuting; + + /// + /// 写入审批流程数据之后 + /// list:审批的人id + /// + protected Action> AddWorkFlowExecuted; + + /// + /// 调用更新方法前处理(SaveModel为传入的原生数据) + /// + protected Func UpdateOnExecute; + + /// + /// 调用更新方法保存数据库前处理 + /// (已将提交的原生数据转换成了对象,将明细新增、修改、删除的数据分别用object1/2/3标识出来 ) + /// T=更新的主表对象 + /// object1=为新增明细的对象,使用时将object as List转换一下 + /// object2=为更新明细的对象 + /// List=为删除的细的对象Key + /// + protected Func, WebResponseContent> UpdateOnExecuting; + + /// + /// 调用更新方法保存数据库后处理 + /// **实现当前方法时,内部默认已经开启事务,如果实现的方法操作的是同一数据库,则不需要在UpdateOnExecuted中事务 + /// (已将提交的原生数据转换成了对象,将明细新增、修改、删除的数据分别用object1/2/3标识出来 ) + /// T=更新的主表对象 + /// object1=为新增明细的对象,使用时将object as List转换一下 + /// object2=为更新明细的对象 + /// List=为删除的细的对象Key + /// 此处已开启了DbContext事务(重点),如果还有其他业务处事,直接在这里写EF代码,不需要再开启事务 + /// 如果执行的是手写sql请用repository.DbContext.Database.ExecuteSqlCommand()或 repository.DbContext.Set().FromSql执行具体sql语句 + /// + protected Func, WebResponseContent> UpdateOnExecuted; + + /// + /// 删除前处理,object[]准备删除的主键 + /// + protected Func DelOnExecuting; + + /// + /// 删除后处理,object[]已删除的主键,此处已开启了DbContext事务(重点),如果还有其他业务处事,直接在这里写EF代码,不需要再开启事务 + /// 如果执行的是手写sql请用repository.DbContext.Database.ExecuteSqlCommand()或 repository.DbContext.Set().FromSql执行具体sql语句 + /// + protected Func DelOnExecuted; + + /// + /// 审核前处理 + /// + protected Func, WebResponseContent> AuditOnExecuting; + /// + /// 审核后处理 + /// + protected Func, WebResponseContent> AuditOnExecuted; + + + /// + /// 审批流程审核前 + /// T:当前审核的数据 + /// AuditStatus:审核状态 + /// bool:当前数据是否为最后一个人审核 + /// + protected Func AuditWorkFlowExecuting; + + /// + /// 审批流程审核后 + /// T:当前审核的数据 + /// AuditStatus:审核状态 + /// list:下一个节点的审批人id + /// bool:当前数据是否为最后一个人审核 + /// + protected Func, bool, WebResponseContent> AuditWorkFlowExecuted; + + /// + ///导出前处理,DataTable导出的表数据 + ///List导出的数据, List忽略不需要导出的字段 + ///此方法不建议使用,由下面ExportColumns委托替代2020.05.07 + /// + protected Func, List, WebResponseContent> ExportOnExecuting; + + /// + /// 2020.05.07 + /// 导出表数据(界面上导出操作),指定要导出的列,格式:Expression> exp = x => new { x.字段1, x.字段2 } + /// + protected Expression> ExportColumns { get; set; } + + + /// + /// 2020.05.07 + /// 导出下载模板,指定要导出的模板列,格式:Expression> exp = x => new { x.字段1, x.字段2 } + /// + protected Expression> DownLoadTemplateColumns { get; set; } + + /// + /// 导入保存后 + /// + protected Func, WebResponseContent> ImportOnExecuted; + + /// + /// 导入保存前 + /// + protected Func, WebResponseContent> ImportOnExecuting; + + /// + /// 2022.06.20增加原生excel读取方法(导入时可以自定义读取excel内容) + /// string=当前读取的excel单元格的值 + /// ExcelWorksheet=excel对象 + /// ExcelRange当前excel单元格对象 + /// int=当前读取的第几数 + /// int=当前读取的第几列 + /// string=返回的值 + /// + protected Func ImportOnReadCellValue; + + + /// + /// 自定义上传文件夹(2022.10.07) + /// + protected string UploadFolder = null; + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Infrastructure/DictionaryHandler.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Infrastructure/DictionaryHandler.cs new file mode 100644 index 0000000000000000000000000000000000000000..5be1013b45201e7f4c3435806c747da9a2545cc5 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Infrastructure/DictionaryHandler.cs @@ -0,0 +1,76 @@ +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.Text; +using VOL.Core.Const; +using VOL.Core.Enums; +using VOL.Core.ManageUser; +using VOL.Core.UserManager; + +namespace VOL.Core.Infrastructure +{ + public static class DictionaryHandler + { + /*2020.05.01增加根据用户信息加载字典数据源sql*/ + + /// + /// 获取自定义数据源sql + /// + /// + /// + /// + public static string GetCustomDBSql(string dicNo, string originalSql) + { + switch (dicNo) + { + case "roles": + originalSql = GetRolesSql(originalSql); + break; + //2020.05.24增加绑定table表时,获取所有的角色列表 + //注意,如果是2020.05.24之前获取的数据库脚本 + //请在菜单【下拉框绑定设置】添加一个字典编号【t_roles】,除了字典编号,其他内容随便填写 + case "t_roles": + originalSql = GetRolesSql(); + break; + default: + break; + } + return originalSql; + } + /// + /// 2020.05.24增加绑定table表时,获取所有的角色列表 + /// + /// + /// + /// + public static string GetRolesSql() + { + if (DBType.Name == DbCurrentType.PgSql.ToString()) + { + return "SELECT \"Role_Id\" as key,\"RoleName\" as value from Sys_Role"; + } + return $@"SELECT Role_Id as 'key',RoleName as 'value' FROM Sys_Role + WHERE Enable=1 "; + } + + /// + /// 获取解决的数据源,只能看到自己与下级所有角色 + /// + /// + /// + /// + public static string GetRolesSql(string originalSql) + { + if (UserContext.Current.IsSuperAdmin) + { + return originalSql; + } + int currnetRoleId = UserContext.Current.RoleId; + List roleIds = RoleContext.GetAllChildrenIds(currnetRoleId); + roleIds.Add(currnetRoleId); + string sql = $@"SELECT Role_Id as 'key',RoleName as 'value' FROM Sys_Role + WHERE Enable=1 and Role_Id in ({string.Join(',', roleIds)})"; + return sql; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Infrastructure/DictionaryManager.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Infrastructure/DictionaryManager.cs new file mode 100644 index 0000000000000000000000000000000000000000..cf4e994d4bce14975e7ae48ef497c83381f972c5 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Infrastructure/DictionaryManager.cs @@ -0,0 +1,114 @@ +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using VOL.Core.CacheManager; +using VOL.Core.DBManager; +using VOL.Core.Extensions.AutofacManager; +using VOL.Core.Services; +using VOL.Entity.DomainModels; + +namespace VOL.Core.Infrastructure +{ + public static class DictionaryManager + { + private static List _dictionaries { get; set; } + + private static object _dicObj = new object(); + private static string _dicVersionn = ""; + public const string Key = "inernalDic"; + + public static List Dictionaries + { + get + { + return GetAllDictionary(); + } + } + + public static Sys_Dictionary GetDictionary(string dicNo) + { + return GetDictionaries(new string[] { dicNo }).FirstOrDefault(); + } + /// + /// + /// + /// + /// 是否执行自定义sql + /// + public static IEnumerable GetDictionaries(IEnumerable dicNos, bool executeSql = true) + { + static List query(string sql) + { + try + { + return DBServerProvider.SqlDapper.QueryList(sql, null).Select(s => new Sys_DictionaryList() + { + DicName = s.Value, + DicValue = s.Key.ToString() + }).ToList(); + } + catch (Exception ex) + { + Logger.Error($"字典执行sql异常,sql:{sql},异常信息:{ex.Message + ex.StackTrace}"); + throw ex; + // Console.WriteLine(ex.Message); + // return null; + } + } + foreach (var item in Dictionaries.Where(x => dicNos.Contains(x.DicNo))) + { + if (executeSql) + { + // 2020.05.01增加根据用户信息加载字典数据源sql + string sql = DictionaryHandler.GetCustomDBSql(item.DicNo, item.DbSql); + if (!string.IsNullOrEmpty(item.DbSql)) + { + item.Sys_DictionaryList = query(sql); + } + } + yield return item; + } + } + /// + /// 每次变更字典配置的时候会重新拉取所有配置进行缓存(自行根据实际处理) + /// + /// + private static List GetAllDictionary() + { + ICacheService cacheService = AutofacContainerModule.GetService(); + //每次比较缓存是否更新过,如果更新则重新获取数据 + if (_dictionaries != null && _dicVersionn == cacheService.Get(Key)) + { + return _dictionaries; + } + + lock (_dicObj) + { + if (_dicVersionn != "" && _dictionaries != null && _dicVersionn == cacheService.Get(Key)) return _dictionaries; + _dictionaries = DBServerProvider.DbContext + .Set() + .Where(x => x.Enable == 1) + .Include(c => c.Sys_DictionaryList).ToList(); + + string cacheVersion = cacheService.Get(Key); + if (string.IsNullOrEmpty(cacheVersion)) + { + cacheVersion = DateTime.Now.ToString("yyyyMMddHHMMssfff"); + cacheService.Add(Key, cacheVersion); + } + else + { + _dicVersionn = cacheVersion; + } + } + return _dictionaries; + } + } + + public class SourceKeyVaule + { + public object Key { get; set; } + public string Value { get; set; } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/KafkaManager/IService/IKafkaConsumer.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/KafkaManager/IService/IKafkaConsumer.cs new file mode 100644 index 0000000000000000000000000000000000000000..f82f0edbf8ecd203510e14f85dcb4847c4b2e134 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/KafkaManager/IService/IKafkaConsumer.cs @@ -0,0 +1,41 @@ +//using Confluent.Kafka; +//using System; +//using System.Collections.Generic; +//using System.Text; + +//namespace VOL.Core.KafkaManager.IService +//{ +// public interface IKafkaConsumer : IDisposable +// { +// /// +// /// 订阅回调模式-消费(持续订阅) +// /// +// /// 回调函数,若配置为非自动提交(默认为否),则通过回调函数的返回值判断是否提交 +// /// 主题 +// void Consume(Func, bool> Func, string Topic); + +// /// +// /// 批量订阅回调模式-消费(持续订阅) +// /// +// /// 回调函数,若配置为非自动提交(默认为否),则通过回调函数的返回值判断是否提交 +// /// 主题集合 +// void ConsumeBatch(Func, bool> Func, List Topics); + +// /// +// /// 批量消费模式-单次消费(消费出当前Kafka缓存的所有数据,并持续监听 300ms,如无新数据生产,则返回(最多一次消费 100条) +// /// +// /// 主题 +// /// 持续监听时间,单位ms 默认值:300ms +// /// 最多单次消费行数 默认值:100行 +// /// 待消费数据 +// List> ConsumeOnce(string Topic, int TimeOut = 300, int MaxRow = 100); + +// /// +// /// 单笔消费模式-单行消费 +// /// +// /// 主题 +// /// 持续监听时间,单位ms 默认值:300ms +// /// 待消费数据 +// ConsumeResult ConsumeOneRow(string Topic, int TimeOut = 300); +// } +//} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/KafkaManager/IService/IKafkaProducer.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/KafkaManager/IService/IKafkaProducer.cs new file mode 100644 index 0000000000000000000000000000000000000000..b4e331ad08ff67ace405da06f860f6677e0c2795 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/KafkaManager/IService/IKafkaProducer.cs @@ -0,0 +1,28 @@ +//using System; +//using System.Collections.Generic; +//using System.Text; +//using System.Threading.Tasks; + +//namespace VOL.Core.KafkaManager.IService +//{ +// public interface IKafkaProducer +// { +// /// +// /// 生产 +// /// +// /// +// /// +// /// +// void Produce(TKey Key, TValue Value, string Topic); + +// /// +// /// 生产 异步 +// /// +// /// +// /// +// /// +// /// +// Task ProduceAsync(TKey Key, TValue Value, string Topic); + +// } +//} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/KafkaManager/KafkaConfig.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/KafkaManager/KafkaConfig.cs new file mode 100644 index 0000000000000000000000000000000000000000..524f66c1dc7f817a64b77c3a6ee8c6cad7d8fc79 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/KafkaManager/KafkaConfig.cs @@ -0,0 +1,48 @@ +////using Confluent.Kafka; +//using System; +//using System.Collections.Generic; +//using System.Text; +//using VOL.Core.Configuration; + +//namespace VOL.Core.KafkaManager +//{ +// /// +// /// 配置类 +// /// +// public class KafkaConfig +// { +// /// +// /// 构造配置类 +// /// +// protected KafkaConfig() +// { +// //ProducerConfig = new ProducerConfig() +// //{ +// // BootstrapServers = AppSetting.Kafka.ProducerSettings.BootstrapServers,// "192.168.20.241:9092", +// //}; + +// //ConsumerConfig = new ConsumerConfig() +// //{ +// // BootstrapServers = AppSetting.Kafka.ConsumerSettings.BootstrapServers, +// // GroupId = AppSetting.Kafka.ConsumerSettings.GroupId, +// // AutoOffsetReset = AutoOffsetReset.Earliest,//当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,从头开始消费 +// // EnableAutoCommit = false, +// // //Kafka配置安全认证 +// // //SecurityProtocol = SecurityProtocol.SaslPlaintext, +// // //SaslMechanism = SaslMechanism.Plain, +// // //SaslUsername = AppSetting.Kafka.ConsumerSettings.SaslUsername, +// // //SaslPassword = AppSetting.Kafka.ConsumerSettings.SaslPassword, +// //}; +// } + +// ///// +// ///// 消费者配置文件 +// ///// +// //public ConsumerConfig ConsumerConfig; + +// ///// +// ///// 生产者配置文件 +// ///// +// //public ProducerConfig ProducerConfig; +// } +//} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/KafkaManager/KafkaHelper.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/KafkaManager/KafkaHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..8436554c8ab3386f5f74bcc0fba143c795ebcd64 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/KafkaManager/KafkaHelper.cs @@ -0,0 +1,197 @@ +////using Confluent.Kafka; +//using Newtonsoft.Json; +//using System; +//using System.Collections.Generic; +//using System.Net; +//using System.Reflection; +//using System.Text; +//using System.Text.RegularExpressions; + +//namespace VOL.Core.KafkaManager +//{ +// /// +// /// 辅助类 +// /// +// public class KafkaHelper +// { +// /// +// /// 获取当前应用程式名称(仅控制台应用程序和Windows应用程序可用) +// /// +// /// +// public static string GetApplicationName() +// { +// try +// { +// return Assembly.GetEntryAssembly().GetName().Name; +// } +// catch +// { +// return "Kafka_Test"; +// } +// } + +// /// +// /// 获取服务器名称 +// /// +// /// +// public static string GetServerName() +// { +// return Dns.GetHostName(); +// } + +// /// +// /// 获取服务器IP +// /// +// /// +// public static string GetServerIp() +// { +// IPHostEntry ips = Dns.GetHostEntry(Dns.GetHostName()); +// foreach (var ip in ips.AddressList) +// { +// if (Regex.IsMatch(ip.ToString(), @"^10\.((25[0-5]|2[0-4]\d|1\d{2}|\d?\d)\.){2}(25[0-5]|2[0-4]\d|1\d{2}|\d?\d)$")) +// { +// return ip.ToString(); +// }; +// } +// return "127.0.0.1"; +// } + +// /// +// /// 将c# DateTime时间格式转换为Unix时间戳格式(毫秒级) +// /// +// /// long +// public static long GetTimeStamp() +// { +// DateTime time = DateTime.Now; +// long t = (time.Ticks - 621356256000000000) / 10000; +// return t; +// } +// } + +// #region 实现消息序列化和反序列化 +// public class KafkaConverter : ISerializer +// { +// /// +// /// 序列化数据成字节 +// /// +// /// +// /// +// /// +// public byte[] Serialize(T data, SerializationContext context) +// { +// var json = JsonConvert.SerializeObject(data); +// return Encoding.UTF8.GetBytes(json); +// } +// } + +// public class KafkaDConverter : IDeserializer +// { +// /// +// /// 反序列化字节数据成实体数据 +// /// +// /// +// /// +// /// +// /// +// public T Deserialize(ReadOnlySpan data, bool isNull, SerializationContext context) +// { +// if (isNull) return default(T); + +// var json = Encoding.UTF8.GetString(data.ToArray()); +// try +// { +// return JsonConvert.DeserializeObject(json); +// } +// catch +// { +// return default(T); +// } +// } +// } +// #endregion + +// #region 日志类 +// /// +// /// 默认日志类 可自行构造使用 +// /// +// public class KafkaLogModel +// { +// /// +// /// 构造默认日志类(设置默认值 ServerIp,ServerName,TimeStamp,ApplicationVersion) +// /// +// public KafkaLogModel() +// { +// ServerIp = KafkaHelper.GetServerIp(); +// ServerName = KafkaHelper.GetServerName(); +// TimeStamp = DateTime.Now; +// ApplicationName = KafkaHelper.GetApplicationName(); +// ApplicationVersion = "V1.0.0"; +// } + +// /// +// /// 程式名称(默认获取当前程式名称,Web应用 默认为 ISD_Kafka) +// /// +// public string ApplicationName { get; set; } + +// /// +// /// 程式版本(默认为V1.0.0) +// /// +// public string ApplicationVersion { get; set; } + +// /// +// /// 发生时间(默认为当前时间) +// /// +// public DateTime TimeStamp { get; set; } + +// /// +// /// 开始时间 +// /// +// public DateTime BeginDate { get; set; } + +// /// +// /// 结束时间 +// /// +// public DateTime EndDate { get; set; } + +// /// +// /// 服务器IP(默认抓取当前服务器IP) +// /// +// public string ServerIp { get; set; } + +// /// +// /// 服务器名称(默认抓取当前服务器名称) +// /// +// public string ServerName { get; set; } + +// /// +// /// 客户端IP +// /// +// public string ClientIp { get; set; } + +// /// +// /// 模块(页面路径) +// /// +// public string Module { get; set; } + +// /// +// /// 操作人 +// /// +// public string Operator { get; set; } + +// /// +// /// 操作类型 如:Query,Add,Update,Delete,Export等,可自定义 +// /// +// public string OperationType { get; set; } + +// /// +// /// 操作状态 如:http请求使用200,404,503等,其他操作 1:成功,0失败等 可自定义 +// /// +// public string Status { get; set; } + +// /// +// /// 其他信息 +// /// +// public string Message { get; set; } +// } +// #endregion +//} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/KafkaManager/Service/KafkaConsumer.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/KafkaManager/Service/KafkaConsumer.cs new file mode 100644 index 0000000000000000000000000000000000000000..3ff75df2346fdcfe86da729cfde35d7f6704f4df --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/KafkaManager/Service/KafkaConsumer.cs @@ -0,0 +1,255 @@ +//using Confluent.Kafka; +//using System; +//using System.Collections.Generic; +//using System.Text; +//using System.Threading.Tasks; +//using VOL.Core.Configuration; +//using VOL.Core.Enums; +//using VOL.Core.KafkaManager.IService; +//using VOL.Core.Services; + +//namespace VOL.Core.KafkaManager.Service +//{ +// /// +// /// 消费者 (Message.Key的数据类型为string、Message.Value的数据类型为string) +// /// 消费者实现三种消费方式:1.订阅回调模式 2.批量消费模式 3.单笔消费模式 +// /// +// /// Message.Key 的数据类型 +// /// Message.Value 的数据类型 +// public class KafkaConsumer : KafkaConfig, IKafkaConsumer +// { +// /// +// /// Kafka地址(包含端口号) +// /// +// public string Servers +// { +// get +// { +// return ConsumerConfig.BootstrapServers; +// } +// set +// { +// ConsumerConfig.BootstrapServers = value; +// } +// } + +// /// +// /// 消费者群组 +// /// +// public string GroupId +// { +// get +// { +// return ConsumerConfig.GroupId; +// } +// set +// { +// ConsumerConfig.GroupId = value; +// } +// } + +// /// +// /// 自动提交 默认为 false +// /// +// public bool EnableAutoCommit +// { +// get +// { +// return ConsumerConfig.EnableAutoCommit ?? false; +// } +// set +// { +// ConsumerConfig.EnableAutoCommit = value; +// } +// } + +// /// +// /// 订阅回调模式-消费(持续订阅) +// /// +// /// 回调函数,若配置为非自动提交(默认为否),则通过回调函数的返回值判断是否提交 +// /// 主题 +// public void Consume(Func, bool> Func, string Topic) +// { +// Task.Factory.StartNew(() => +// { +// var builder = new ConsumerBuilder(ConsumerConfig); +// //设置反序列化方式 +// builder.SetValueDeserializer(new KafkaDConverter()); +// builder.SetErrorHandler((_, e) => +// { +// Logger.Error(LoggerType.KafkaException, null, null, $"Error:{e.Reason}"); +// }).SetStatisticsHandler((_, json) => +// { +// Console.WriteLine($"-{DateTime.Now:yyyy-MM-dd HH:mm:ss} > 消息监听中.."); +// }).SetPartitionsAssignedHandler((c, partitions) => +// { +// string partitionsStr = string.Join(", ", partitions); +// Console.WriteLine($"-分配的kafka分区:{partitionsStr}"); +// }).SetPartitionsRevokedHandler((c, partitions) => +// { +// string partitionsStr = string.Join(", ", partitions); +// Console.WriteLine($"-回收了kafka的分区:{partitionsStr}"); +// }); +// using var consumer = builder.Build(); +// consumer.Subscribe(Topic); +// while (AppSetting.Kafka.IsConsumerSubscribe) //true +// { +// ConsumeResult result = null; +// try +// { +// result = consumer.Consume(); +// if (result.IsPartitionEOF) continue; +// if (Func(result)) +// { +// if (!(bool)ConsumerConfig.EnableAutoCommit) +// { +// //手动提交,如果上面的EnableAutoCommit=true表示自动提交,则无需调用Commit方法 +// consumer.Commit(result); +// } +// } +// } +// catch (ConsumeException ex) +// { +// Logger.Error(LoggerType.KafkaException, $"Topic:{Topic},{ex.Error.Reason}", null, ex.Message + ex.StackTrace); +// } +// catch (Exception ex) +// { +// Logger.Error(LoggerType.KafkaException, $"Topic:{result.Topic}", null, ex.Message + ex.StackTrace); +// } +// } +// }); +// } + +// /// +// /// 批量订阅回调模式-消费(持续订阅) +// /// +// /// 回调函数,若配置为非自动提交(默认为否),则通过回调函数的返回值判断是否提交 +// /// 主题 +// public void ConsumeBatch(Func, bool> Func, List Topics) +// { +// Task.Factory.StartNew(() => +// { +// var builder = new ConsumerBuilder(ConsumerConfig); +// //设置反序列化方式 +// builder.SetValueDeserializer(new KafkaDConverter()); +// builder.SetErrorHandler((_, e) => +// { +// Logger.Error(LoggerType.KafkaException, null, null, $"Error:{e.Reason}"); +// }).SetStatisticsHandler((_, json) => +// { +// Console.WriteLine($"-{DateTime.Now:yyyy-MM-dd HH:mm:ss} > 消息监听中.."); +// }).SetPartitionsAssignedHandler((c, partitions) => +// { +// string partitionsStr = string.Join(", ", partitions); +// Console.WriteLine($"-分配的kafka分区:{partitionsStr}"); +// }).SetPartitionsRevokedHandler((c, partitions) => +// { +// string partitionsStr = string.Join(", ", partitions); +// Console.WriteLine($"-回收了kafka的分区:{partitionsStr}"); +// }); +// using var consumer = builder.Build(); +// consumer.Subscribe(Topics); +// while (AppSetting.Kafka.IsConsumerSubscribe) //true +// { +// ConsumeResult result = null; +// try +// { +// result = consumer.Consume(); +// if (result.IsPartitionEOF) continue; +// if (Func(result)) +// { +// if (!(bool)ConsumerConfig.EnableAutoCommit) +// { +// //手动提交,如果上面的EnableAutoCommit=true表示自动提交,则无需调用Commit方法 +// consumer.Commit(result); +// } +// } +// } +// catch (ConsumeException ex) +// { +// Logger.Error(LoggerType.KafkaException, $"Topic:{Topics.ToArray()},{ex.Error.Reason}", null, ex.Message + ex.StackTrace); +// } +// catch (Exception ex) +// { +// Logger.Error(LoggerType.KafkaException, $"Topic:{result.Topic}", null, ex.Message + ex.StackTrace); +// } +// } +// }); +// } + +// /// +// /// 批量消费模式-单次消费(消费出当前Kafka缓存的所有数据,并持续监听 300ms,如无新数据生产,则返回(最多一次消费 100条) +// /// +// /// 主题 +// /// 持续监听时间,单位ms 默认值:300ms +// /// 最多单次消费行数 默认值:100行 +// /// 待消费数据 +// public List> ConsumeOnce(string Topic, int TimeOut = 300, int MaxRow = 100) +// { +// var builder = new ConsumerBuilder(ConsumerConfig); +// //设置反序列化方式 +// builder.SetValueDeserializer(new KafkaDConverter()); +// using var consumer = builder.Build(); +// consumer.Subscribe(Topic); +// List> Res = new List>(); +// while (true) +// { +// try +// { +// var result = consumer.Consume(TimeSpan.FromMilliseconds(TimeOut)); +// if (result == null) break; +// else +// { +// Res.Add(result); +// //手动提交,如果上面的EnableAutoCommit=true表示自动提交,则无需调用Commit方法 +// consumer.Commit(); +// } +// if (Res.Count > MaxRow) break; +// } +// catch (Exception ex) +// { +// Logger.Error(LoggerType.KafkaException, $"Topic:{Topic}", null, ex.Message + ex.StackTrace); +// return null; +// } +// } +// return Res; +// } + +// /// +// /// 单笔消费模式-单行消费 +// /// +// /// 主题 +// /// 持续监听时间,单位ms 默认值:300ms +// /// 待消费数据 +// public ConsumeResult ConsumeOneRow(string Topic, int TimeOut = 300) +// { +// var builder = new ConsumerBuilder(ConsumerConfig); +// //设置反序列化方式 +// builder.SetValueDeserializer(new KafkaDConverter()); +// using var consumer = builder.Build(); +// consumer.Subscribe(Topic); +// try +// { +// var result = consumer.Consume(TimeSpan.FromMilliseconds(TimeOut)); +// if (result != null) +// { +// //手动提交,如果上面的EnableAutoCommit=true表示自动提交,则无需调用Commit方法 +// consumer.Commit(); +// } +// return result; +// } +// catch (Exception ex) +// { +// Logger.Error(LoggerType.KafkaException, $"Topic:{Topic}", null, ex.Message + ex.StackTrace); +// return null; +// } +// } + +// public void Dispose() +// { +// //if (_cache != null) +// // _cache.Dispose(); +// GC.SuppressFinalize(this); +// } +// } +//} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/KafkaManager/Service/KafkaProducer.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/KafkaManager/Service/KafkaProducer.cs new file mode 100644 index 0000000000000000000000000000000000000000..59bf932a275644d4b0fb1620c61da50ac03ecd34 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/KafkaManager/Service/KafkaProducer.cs @@ -0,0 +1,99 @@ +//using Confluent.Kafka; +//using System; +//using System.Collections.Generic; +//using System.Text; +//using System.Threading.Tasks; +//using VOL.Core.Enums; +//using VOL.Core.KafkaManager.IService; +//using VOL.Core.Services; + +//namespace VOL.Core.KafkaManager.Service +//{ +// /// +// /// 生产者 控制器或Service里面构造函数注入即可调用 +// /// Message.Key的数据类型为string、Message.Value的数据类型为string +// /// +// /// Message.Key 的数据类型 +// /// Message.Value 的数据类型 +// public class KafkaProducer : KafkaConfig, IKafkaProducer +// { +// /// +// /// 构造生产者 +// /// +// public KafkaProducer() +// { + +// } + +// /// +// /// Kafka地址(包含端口号) +// /// +// public string Servers +// { +// get +// { +// return ProducerConfig.BootstrapServers; +// } +// set +// { +// ProducerConfig.BootstrapServers = value; +// } +// } + +// /// +// /// 生产 +// /// +// /// Message.Key 做消息指定分区投放有用的 +// /// Message.Value +// /// 主题 +// public void Produce(TKey Key, TValue Value, string Topic) +// { +// var producerBuilder = new ProducerBuilder(ProducerConfig); +// producerBuilder.SetValueSerializer(new KafkaConverter());//设置序列化方式 +// using var producer = producerBuilder.Build(); +// try +// { +// producer.Produce(Topic, new Message +// { +// Key = Key, +// Value = Value +// }, (result) => +// { +// if (result.Error.IsError) +// Logger.Error(LoggerType.KafkaException, $"Topic:{Topic},ServerIp:{KafkaHelper.GetServerIp()},ServerName:{ KafkaHelper.GetServerName()}", null, $"Delivery Error:{result.Error.Reason}"); +// });//Value = JsonConvert.SerializeObject(value) +// } +// catch (ProduceException ex) +// { +// Logger.Error(LoggerType.KafkaException, $"Topic:{Topic},Delivery failed: { ex.Error.Reason}", null, ex.Message + ex.StackTrace); +// } +// } + +// /// +// /// 生产异步 +// /// +// /// Message.Key +// /// Message.Value +// /// 主题 +// /// +// public async Task ProduceAsync(TKey Key, TValue Value, string Topic) +// { +// var producerBuilder = new ProducerBuilder(ProducerConfig); +// producerBuilder.SetValueSerializer(new KafkaConverter()); +// using var producer = producerBuilder.Build(); +// try +// { +// var dr = await producer.ProduceAsync(Topic, new Message +// { +// Key = Key, +// Value = Value +// }); +// //Console.WriteLine($"Delivered '{dr.Value}' to '{dr.TopicPartitionOffset}'"); +// } +// catch (ProduceException ex) +// { +// Logger.Error(LoggerType.KafkaException, $"Topic:{Topic},ServerIp:{KafkaHelper.GetServerIp()},ServerName:{ KafkaHelper.GetServerName()},Delivery failed: { ex.Error.Reason}", null, ex.Message + ex.StackTrace); +// } +// } +// } +//} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Middleware/ExceptionHandlerMiddleWare.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Middleware/ExceptionHandlerMiddleWare.cs new file mode 100644 index 0000000000000000000000000000000000000000..6ebb7216e4d5c86a35215c7541d34e30bd62c7ad --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Middleware/ExceptionHandlerMiddleWare.cs @@ -0,0 +1,52 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Hosting; +using System; +using System.IO; +using System.Text; +using System.Threading.Tasks; +using VOL.Core.Const; +using VOL.Core.EFDbContext; +using VOL.Core.Enums; +using VOL.Core.Extensions; +using VOL.Core.ManageUser; +using VOL.Core.Services; + +namespace VOL.Core.Middleware +{ + public class ExceptionHandlerMiddleWare + { + private readonly RequestDelegate next; + public ExceptionHandlerMiddleWare(RequestDelegate next) + { + this.next = next; + } + + public async Task Invoke(HttpContext context) + { + try + { + (context.RequestServices.GetService(typeof(ActionObserver)) as ActionObserver).RequestDate = DateTime.Now; + await next(context); + Logger.Info(LoggerType.System); + } + catch (Exception exception) + { + var env = context.RequestServices.GetService(typeof(IWebHostEnvironment)) as IWebHostEnvironment; + string message = exception.Message + exception.InnerException; + Logger.Error(LoggerType.Exception, message); + if (!env.IsDevelopment()) + { + message = "服务器处理异常"; + } + else + { + Console.WriteLine($"服务器处理出现异常:{message}"); + } + context.Response.StatusCode = 500; + context.Response.ContentType = ApplicationContentType.JSON; + await context.Response.WriteAsync(new { message, status = false }.Serialize(), Encoding.UTF8); + } + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Middleware/HttpRequestMiddleware.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Middleware/HttpRequestMiddleware.cs new file mode 100644 index 0000000000000000000000000000000000000000..ab372654172b582913ef6385445fed0406e31429 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Middleware/HttpRequestMiddleware.cs @@ -0,0 +1,56 @@ +using Microsoft.AspNetCore.Http; +using System; +using System.IO; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.Middleware +{ + public class HttpRequestMiddleware + { + public static Func Context + { + get + { + return next => async context => + { + //动态标识刷新token(2021.05.01) + context.Response.Headers.Add("Access-Control-Expose-Headers", "vol_exp"); + var stream = context.Request.Body; + if (stream == Stream.Null || stream.CanSeek) + { + await next(context); + + return; + } + try + { + using (var buffer = new MemoryStream()) + { + // Copy the request stream to the memory stream. + await stream.CopyToAsync(buffer); + + // Rewind the memory stream. + buffer.Position = 0L; + + // Replace the request stream by the memory stream. + context.Request.Body = buffer; + + // Invoke the rest of the pipeline. + await next(context); + } + } + + finally + { + // Restore the original stream. + context.Request.Body = stream; + } + + }; + + } + } + } + +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/ModelBinder/BaseBinderProvider.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/ModelBinder/BaseBinderProvider.cs new file mode 100644 index 0000000000000000000000000000000000000000..8478f26e547f7781ecdc9e110beddcd273c19049 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/ModelBinder/BaseBinderProvider.cs @@ -0,0 +1,58 @@ +using Microsoft.AspNetCore.Mvc.ModelBinding; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace VOL.Core.ModelBinder +{ + public class BaseBinderProvider : IModelBinderProvider + { + public List types = new List(); + + // public List binder=new BinderObject() + public BaseBinderProvider() + { + types.Add(typeof(Dictionary)); + InitType(); + } + + private void AddType(Type type) + { + if (!types.Any(x => x == type)) + { + types.Add(type); + } + } + private void InitType() + { + AddType(typeof(Dictionary)); + AddType(typeof(List>)); + AddType(typeof(List)); + AddType(typeof(List)); + AddType(typeof(VOL.Entity.DomainModels.Sys_TableInfo)); + } + /// + /// 增加一个委托用于调用 return new BaseModelBinder();时对参数进行行校验,待完.. + /// + /// + public BaseBinderProvider(List types) + { + this.types = types ?? throw new Exception("types初始化不能为null"); + InitType(); + } + public IModelBinder GetBinder(ModelBinderProviderContext context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (types.Any(x => x == context.Metadata.ModelType)) + { + return new BaseModelBinder();// new BinderTypeModelBinder(typeof(TableInfoEntityBinder)); + } + + return null; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/ModelBinder/BaseModelBinder.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/ModelBinder/BaseModelBinder.cs new file mode 100644 index 0000000000000000000000000000000000000000..614a3f2109fdd7bd46643c96afc5a2d34f2cbf82 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/ModelBinder/BaseModelBinder.cs @@ -0,0 +1,46 @@ +using Microsoft.AspNetCore.Mvc.ModelBinding; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using VOL.Entity.DomainModels; + +namespace VOL.Core.ModelBinder +{ + public class BaseModelBinder : IModelBinder + { + public BaseModelBinder() + { + } + + public Task BindModelAsync(ModelBindingContext bindingContext) + { + if (bindingContext == null) + { + throw new ArgumentNullException(nameof(bindingContext)); + } + + var modelName = bindingContext.ModelName; + + // Try to fetch the value of the argument by name + var valueProviderResult = + bindingContext.ValueProvider.GetValue(modelName); + + if (valueProviderResult == ValueProviderResult.None) + { + return Task.CompletedTask; + } + + bindingContext.ModelState.SetModelValue(modelName, + valueProviderResult); + + var value = valueProviderResult.FirstValue; + if (string.IsNullOrEmpty(value)) + { + return Task.CompletedTask; + } + var model = Newtonsoft.Json.JsonConvert.DeserializeObject(value, bindingContext.ModelType); + bindingContext.Result = ModelBindingResult.Success(model); + return Task.CompletedTask; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/ModelBinder/BinderObject.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/ModelBinder/BinderObject.cs new file mode 100644 index 0000000000000000000000000000000000000000..c939428781fd12b5eb1601283220d0646eea7b28 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/ModelBinder/BinderObject.cs @@ -0,0 +1,10 @@ +using System; + +namespace VOL.Core.ModelBinder +{ + public class BinderObject where T : class + { + public Type ModelType { get; set; } + public Action> Filter { get; set; } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/ObjectActionValidator/ExpressValidator/GeneralOptions.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/ObjectActionValidator/ExpressValidator/GeneralOptions.cs new file mode 100644 index 0000000000000000000000000000000000000000..8db4ffac4f6bbc627aed8a45761009893fa6c8c1 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/ObjectActionValidator/ExpressValidator/GeneralOptions.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.ObjectActionValidator +{ + /// + /// 普通参数配置 + /// + public class GeneralOptions + { + + /// + /// 自定义验证 + /// + /// + /// + public GeneralOptions(ValidatorGeneral generalName, string CNName, Func customValidator) + { + this.CNName = CNName; + this.CustomValidator = customValidator; + this.Name = generalName.ToString().ToLower(); + } + /// + /// + /// + /// 普通参数的名字,与方法参数名字必须一致(不分大小写),可以直接在ValidatorGeneral上添加 + public GeneralOptions(ValidatorGeneral generalName, string CNName) + { + this.Name = generalName.ToString().ToLower(); + this.CNName = CNName; + this.ParamType = ParamType.String; + } + public GeneralOptions(ValidatorGeneral generalName, string CNName, ParamType type) + { + this.Name = generalName.ToString().ToLower(); + this.CNName = CNName; + this.ParamType = ParamType.String; + } + public GeneralOptions(ValidatorGeneral generalName, string CNName, int? min, int? max) + { + this.Name = generalName.ToString().ToLower(); + this.CNName = CNName; + this.ParamType = ParamType.String; + this.Min = min; + this.Max = max; + } + + public GeneralOptions(ValidatorGeneral generalName, string CNName, ParamType type, int? min, int? max) + { + this.Name = generalName.ToString().ToLower(); + this.CNName = CNName; + this.ParamType = type; + this.Min = min; + this.Max = max; + } + + public Func CustomValidator; + /// + /// 方法上的参数名字 + /// + public string Name { get; set; } + /// + /// 中文名字,参数校验错误的提示文字 + /// + public string CNName { get; set; } + /// + /// 参数类型,目前只列出了这几种,不够自己再加 + /// + public ParamType ParamType { get; set; } + /// + /// 数字为最小值,字符串为最小长度 + /// + public int? Min { get; set; } + /// + /// 数字为最大值,字符串为最大长度 + /// + public int? Max { get; set; } + + } + public enum ParamType + { + Int, + //Long, + //Byte, + Bool, + String, + DateTime, + Decimal, + Guid + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/ObjectActionValidator/ExpressValidator/MethodsValidator.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/ObjectActionValidator/ExpressValidator/MethodsValidator.cs new file mode 100644 index 0000000000000000000000000000000000000000..765723c986f8d5894ac65e1664c2462cd09acb73 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/ObjectActionValidator/ExpressValidator/MethodsValidator.cs @@ -0,0 +1,366 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Primitives; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using VOL.Core.Extensions; +using VOL.Core.Filters; +using VOL.Core.Utilities; + + +namespace VOL.Core.ObjectActionValidator +{ + public static class MethodsValidator + { + /// + /// 方法上的model校验配置 + /// + public static Dictionary ValidatorCollection { get; } = new Dictionary(); + + public static void Add(this ValidatorModel validatorGroup, Expression> loginExpress = null) + { + if (!ValidatorCollection.TryAdd(validatorGroup.ToString().ToLower(), + loginExpress == null + ? typeof(T).GetGenericProperties().Select(x => x.Name).ToArray() + : loginExpress.GetExpressionToArray())) + { + throw new Exception($"键{validatorGroup.ToString()}的表达式已经注册过了"); + } + } + /// + /// 方法上的普通参数校验配置 + /// + public static Dictionary ValidatorGeneralCollection { get; } = new Dictionary(); + + /// + /// 默认校验的是string类型 + /// + /// 普通参数名 + /// 校验错误时显示的提示名字 + public static void Add(this ValidatorGeneral general, string CNName) + { + general.Add(CNName, ParamType.String, null, null); + } + public static void Add(this ValidatorGeneral general, string CNName, int? max) + { + general.Add(CNName, ParamType.String, null, max); + } + public static void Add(this ValidatorGeneral general, string CNName, ParamType type) + { + general.Add(CNName, type, null, null); + } + public static void Add(this ValidatorGeneral general, string CNName, ParamType type, int? max) + { + general.Add(CNName, type, null, max); + } + public static void Add(this ValidatorGeneral general, string CNName, int? min, int? max) + { + general.Add(CNName, ParamType.String, min, max); + } + /// + /// + /// + /// 普通参数名 + /// 校验错误时显示的提示名字 + /// 参数类型 + /// 最大小度(最小值) + /// 最大长度(最大值) + public static void Add(this ValidatorGeneral general, string CNName, ParamType type, int? min = null, int? max = null) + { + GeneralOptions options = new GeneralOptions(general, CNName, type, min, max); + if (!ValidatorGeneralCollection.TryAdd(general.ToString().ToLower(), options)) + { + throw new Exception($"键{general.ToString()}参数配置已经注入过了"); + } + } + /// + /// 自定义验证 + /// + /// + /// + public static void Add(this ValidatorGeneral general, string CNName, Func customValidator) + { + GeneralOptions options = new GeneralOptions(general, CNName, customValidator); + if (!ValidatorGeneralCollection.TryAdd(general.ToString().ToLower(), options)) + { + throw new Exception($"键{general.ToString()}参数配置已经注入过了"); + } + } + + + + /// + /// 获取方法上绑定的model校验字段 + /// + /// + /// + public static string[] GetModelParameters(this ValidatorModel validatorGroup) + { + return validatorGroup.ToString().GetModelParameters(); + } + /// + /// 获取方法上绑定的model校验字段 + /// + /// + /// + public static string[] GetModelParameters(this string validatorGroup) + { + if (!ValidatorCollection.TryGetValue(validatorGroup.ToLower(), out string[] values)) + { + Console.WriteLine($"未注册{validatorGroup}参数的表达式"); + throw new Exception($"未注册{validatorGroup}参数的表达式"); + } + return values; + } + /// + /// 获取方法上绑定校验字段的配置信息 + /// + /// + /// + public static IEnumerable GetGeneralOption(this ValidatorGeneral[] general) + { + return general.Select(x => x.ToString()).ToArray().GetGeneralOption(); + } + /// + /// 获取方法上绑定校验字段的配置信息 + /// + /// + /// + public static IEnumerable GetGeneralOption(this string[] generalName) + { + foreach (string item in generalName) + { + if (!ValidatorGeneralCollection.TryGetValue(item.ToLower(), out GeneralOptions options)) + { + throw new Exception($"未注册{generalName.ToString()}参数的配置"); + } + yield return options; + } + } + + public static void ActionParamsValidator(this ActionExecutingContext context) + { + //普通参数校验 + context.GeneralValidator(); + + //是否使用了model参数校验 + if (!context.ExistsActionModelValidator()) return; + //判断当前model校验是否通垸 + ObjectModelValidatorState objectModel = context.HttpContext.GetService(); + if (!objectModel.Status) + { + context.Result = new JsonResult(objectModel); + return; + } + + //判断是否提交了model参数 + if (!objectModel.HasModelContent) + { + context.Result = new JsonResult(new WebResponseContent().Error($"请提交参数")); + return; + } + } + + /// + /// 是否添加了ModelValidator实体校验 + /// + /// + /// + public static bool ExistsActionModelValidator(this ActionExecutingContext context) + { + return context.ActionDescriptor.EndpointMetadata.Any(item => item is ObjectModelValidatorFilter); + } + /// + /// 是否添加了ModelValidator实体校验 + /// + /// + /// + public static string[] GetModelValidatorParams(this ActionContext actionContext) + { + return (actionContext.ActionDescriptor + .EndpointMetadata + .Where(item => item is ObjectModelValidatorFilter) + .FirstOrDefault() as ObjectModelValidatorFilter)?.MethodsParameters; + } + /// + /// model校验 + /// + /// + /// + /// + /// + public static void ModelValidator(this ActionContext actionContext, string prefix, object model) + { + string[] parameters = actionContext.GetModelValidatorParams(); + //没有设置模型校验的直接返回 + if (parameters == null) return; + if (model == null) + { + actionContext.ErrorResult("没有获取到参数"); + return; + } + //model==list未判断 + PropertyInfo[] properties = model.GetType().GetProperties().Where(x => parameters.Contains(x.Name.ToLower())).ToArray(); + foreach (var item in properties) + { + if (!item.ValidationRquiredValueForDbType(item.GetValue(model), out string message)) + { + actionContext.ErrorResult(message); + return; + } + } + actionContext.OkModelResult(); + } + + /// + /// 普通参数校验 + /// + /// + public static void GeneralValidator(this ActionExecutingContext actionContext) + { + if (actionContext.ActionDescriptor + .EndpointMetadata + .Where(item => item is ObjectGeneralValidatorFilter) + .FirstOrDefault() is ObjectGeneralValidatorFilter objectGeneral) + { + foreach (GeneralOptions general in objectGeneral.MethodsParameters) + { + if (actionContext.Result != null) return; + if (!actionContext.HttpContext.Request.Query.TryGetValue(general.Name, out StringValues value)) + { + actionContext.ActionErrorResult($"请提交参数[{general.CNName}]"); + return; + } + if (string.IsNullOrEmpty(value)) + { + actionContext.ActionErrorResult($"参数[{general.CNName}]不能为空"); + return; + } + //自定义验证 + if (general.CustomValidator != null) + { + ObjectValidatorResult validatorResult = general.CustomValidator(value); + if (!validatorResult.Status) + { + actionContext.ActionErrorResult(validatorResult.Message); + return; + } + continue; + } + actionContext.ValidatorValue(general, value); + } + } + } + + public static void ValidatorNumber(Type type, object value) + { + value.ChangeType(type); + } + public static void ValidatorValue(this ActionExecutingContext actionContext, GeneralOptions options, object model) + { + if (model == null) + { + actionContext.ActionErrorResult($"请提交参数{options.CNName}"); + return; + } + if (options.Min == null && options.Max == null) return; + switch (options.ParamType) + { + //待完ParamType.Long,Byte类型 + case ParamType.Int: + //case ParamType.Long: + //case ParamType.Byte: + if (!int.TryParse(model.ToString(), out int _number)) + { + actionContext.ActionErrorResult($"[{options.CNName}]必须是整数"); + break; + } + if (options.Min != null && _number < options.Min) + { + actionContext.ActionErrorResult($"[{options.CNName}]不能小于[{options.Min}]"); + break; + } + if (options.Max != null && _number > options.Max) + { + actionContext.ActionErrorResult($"[{options.CNName}]不能大于[{options.Max}]"); + } + break; + case ParamType.String: + string value = model.ToString(); + if (options.Min != null && value.Length < options.Min) + { + actionContext.ActionErrorResult($"[{options.CNName}]至少[{options.Min}]个字符"); + } + if (options.Max != null && value.Length > options.Max) + { + actionContext.ActionErrorResult($"[{options.CNName}]最多[{options.Max}]个字符"); + } + break; + //待完日期大小 + case ParamType.DateTime: + if (!DateTime.TryParse(model.ToString(),out _)) + { + actionContext.ActionErrorResult($"[{options.CNName}]应该是日期格式"); + } + break; + //min,max应该是decimal类型,待完 + case ParamType.Decimal: + if (!decimal.TryParse(model.ToString(), out decimal _decimal)) + { + actionContext.ActionErrorResult($"[{options.CNName}]不是数字"); + break; + } + if (options.Min != null && _decimal < options.Min) + { + actionContext.ActionErrorResult($"[{options.CNName}]不能小于[{options.Min}]"); + break; + } + if (options.Max != null && _decimal > options.Max) + { + actionContext.ActionErrorResult($"[{options.CNName}]不能大于[{options.Max}]"); + } + break; + case ParamType.Guid: + if (!Guid.TryParse(model.ToString(), out _)) + { + actionContext.ActionErrorResult($"[{options.CNName}]不是Guid类型"); + } + break; + default: + break; + } + } + + public static void ActionErrorResult(this ActionExecutingContext actionContext, string message) + { + actionContext.Result = new JsonResult(new { Status = false, Message = message }); + } + + /// + ///参数验证没有通过的直接返回校验结果 + /// + /// + /// + public static void ErrorResult(this ActionContext actionContext, string message) + { + ObjectModelValidatorState objectModel = actionContext.HttpContext.GetService(); + if (!objectModel.Status) + { + return; + } + objectModel.Status = false; + objectModel.Message = message; + } + public static void OkModelResult(this ActionContext actionContext) + { + ObjectModelValidatorState objectModel = actionContext.HttpContext.GetService(); + objectModel.HasModelContent = true; + } + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/ObjectActionValidator/ExpressValidator/ObjectModelValidatorState.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/ObjectActionValidator/ExpressValidator/ObjectModelValidatorState.cs new file mode 100644 index 0000000000000000000000000000000000000000..b1e7db9ac673e540fb318b0b7f4b435cefb99194 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/ObjectActionValidator/ExpressValidator/ObjectModelValidatorState.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.ObjectActionValidator +{ + public class ObjectModelValidatorState + { + public ObjectModelValidatorState() + { + this.Status = true; + } + + public bool Status { get; set; } + public bool HasModelContent { get; set; } + public string Code { get; set; } + public string Message { get; set; } + } + public class ObjectValidatorResult + { + public ObjectValidatorResult() + { + + } + public ObjectValidatorResult(bool status) + { + this.Status = status; + } + public ObjectValidatorResult OK(string message) + { + this.Status = true; + this.Message = message; + return this; + } + public ObjectValidatorResult Error(string message) + { + this.Status = false; + this.Message = message; + return this; + } + public bool Status { get; set; } + public string Message { get; set; } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/ObjectActionValidator/Filters/ObjectGeneralValidatorFilter.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/ObjectActionValidator/Filters/ObjectGeneralValidatorFilter.cs new file mode 100644 index 0000000000000000000000000000000000000000..3e4bc99f7d4eba9763364b41548c8255b578d61d --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/ObjectActionValidator/Filters/ObjectGeneralValidatorFilter.cs @@ -0,0 +1,26 @@ +using Microsoft.AspNetCore.Mvc.Filters; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using VOL.Core.Infrastructure; +using VOL.Core.ObjectActionValidator; + +namespace VOL.Core.ObjectActionValidator +{ + //General + public class ObjectGeneralValidatorFilter :Attribute, IFilterMetadata + { + // + /// + /// 对方法参数进行校验 + /// + /// + public ObjectGeneralValidatorFilter([NotNull]params ValidatorGeneral[] validators) + { + MethodsParameters = validators.GetGeneralOption().ToArray(); + } + public GeneralOptions[] MethodsParameters { get; } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/ObjectActionValidator/Filters/ObjectModelValidatorFilter.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/ObjectActionValidator/Filters/ObjectModelValidatorFilter.cs new file mode 100644 index 0000000000000000000000000000000000000000..c8ac51e194b046bd217f586ffbb121dcffe4c95a --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/ObjectActionValidator/Filters/ObjectModelValidatorFilter.cs @@ -0,0 +1,17 @@ +using Microsoft.AspNetCore.Mvc.Filters; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; + +namespace VOL.Core.ObjectActionValidator +{ + public class ObjectModelValidatorFilter : Attribute + { + public ObjectModelValidatorFilter(ValidatorModel validatorGroup) + { + MethodsParameters = validatorGroup.GetModelParameters()?.Select(x => x.ToLower())?.ToArray(); + } + public string[] MethodsParameters { get; } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/ObjectActionValidator/NullObjectModelValidator.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/ObjectActionValidator/NullObjectModelValidator.cs new file mode 100644 index 0000000000000000000000000000000000000000..d12f9ec25fa47f688616c1e30f737fbd06e5afc1 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/ObjectActionValidator/NullObjectModelValidator.cs @@ -0,0 +1,29 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using VOL.Core.Extensions; +using VOL.Core.Filters; + +namespace VOL.Core.ObjectActionValidator +{ + public class NullObjectModelValidator : IObjectModelValidator + { + + public void Validate( + ActionContext actionContext, + ValidationStateDictionary validationState, + string prefix, + object model) + { + if (string.IsNullOrEmpty(prefix)) + { + actionContext.ModelValidator(prefix, model); + return; + } + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/ObjectActionValidator/ValidationContainer.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/ObjectActionValidator/ValidationContainer.cs new file mode 100644 index 0000000000000000000000000000000000000000..843740c0b470997b654213c639a6f3665caeecd5 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/ObjectActionValidator/ValidationContainer.cs @@ -0,0 +1,96 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Text; +using VOL.Core.Extensions; +using VOL.Entity.DomainModels; + +namespace VOL.Core.ObjectActionValidator +{ + /// + /// 对方法指定属性校验,此处配置完成就不用每处都写if esle判断值是合法 + /// 与自带模型校验相比,此处可以通过表达式校验指定字段,也不用担心model字段变化后还去手动修改配置的问题 + /// 目前只支持普通属性,不支持复杂类型 + /// + public static class ValidatorContainer + { + /// + /// model校验配置 + /// 方法参数名必须与枚举名称一致(不区分大小写),如:public void Test(LoginInfo login) + /// 表达式是model必须要验证的字段,如果不填,默认验证整个model + /// + /// + /// + public static IServiceCollection UseMethodsModelParameters(this IServiceCollection services) + { + //登陆方法校验参数,只验证密码与用户名 + ValidatorModel.Login.Add(x => new { x.Password, x.UserName,x.VerificationCode,x.UUID }); + + //只验证LoginInfo的密码字段必填 + ValidatorModel.LoginOnlyPassWord.Add(x => new { x.Password }); + + return services; + } + /// + /// 普通属性校验 + /// 方法上添加[ObjectGeneralValidatorFilter(ValidatorGeneral.xxx)]即可进行参数自动验证 + /// ValidatorGeneral为枚举(也是方法的参数名),自己需要校验的参数在枚举上添加 + /// ValidatorGeneral.xxx.Add() 配置自己的验证规则 + /// + /// + /// + public static IServiceCollection UseMethodsGeneralParameters(this IServiceCollection services) + { + //配置用户名最多30个字符 + ValidatorGeneral.UserName.Add("用户名", 30); + + //方法参数名为newPwd,直接在方法加上[ObjectGeneralValidatorFilter(ValidatorGeneral.NewPwd)]进行参数验证 + //如果newPwd为空会提示:新密码不能为空 + //6,50代表newPwd参数最少6个字符,最多50个符 + //其他需要验证的参数同样配置即可 + ValidatorGeneral.NewPwd.Add("新密码", 6, 50); + + //如果OldPwd为空会提示:旧密码不能为空 + ValidatorGeneral.OldPwd.Add("旧密码"); + + //校验手机号码格式 + ValidatorGeneral.PhoneNo.Add("手机号码", (object value) => + { + ObjectValidatorResult validatorResult = new ObjectValidatorResult(true); + if (!value.ToString().IsPhoneNo()) + { + validatorResult = validatorResult.Error("请输入正确的手机号码"); + } + return validatorResult; + }); + + //测试验证字符长度为6-10 + ValidatorGeneral.Local.Add("所在地",6,10); + + //测试验证数字范围 + ValidatorGeneral.Qty.Add("存货量",ParamType.Int, 200, 500); + + return services; + } + } + //方法参数是实体配置验证字段 + public enum ValidatorModel + { + Login, + LoginOnlyPassWord//只验证密码 + } + /// + /// 方法普通参数名配置(枚举的名字必须与参数名字一样,不区分大小写) + /// 通过在方法加上[ObjectGeneralValidatorFilter(ValidatorGeneral.UserName, ValidatorGeneral.PassWord)]指定要验证的参数 + /// + public enum ValidatorGeneral + { + UserName, + OldPwd, + NewPwd, + PhoneNo, + Local,//测试验证字符长度 + Qty//测试 验证值大小 + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Properties/launchSettings.json b/Pure_Vite_Net7/WebNet7/VOL.Core/Properties/launchSettings.json new file mode 100644 index 0000000000000000000000000000000000000000..17f5f464d1a46a5a1b88aada15b08f42896f8f8e --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:34189/", + "sslPort": 44383 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "VOL.Core": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:5001;http://localhost:5000" + } + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Quartz/HttpManager.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Quartz/HttpManager.cs new file mode 100644 index 0000000000000000000000000000000000000000..009aaa4f22ab57a346815d9c4a6006367fa8a59c --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Quartz/HttpManager.cs @@ -0,0 +1,54 @@ +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using System.Threading.Tasks; + +namespace VOL.Core.Quartz +{ + public static class HttpManager + { + + public static async Task SendAsync(this IHttpClientFactory httpClientFactory, + HttpMethod method, + string url, + string postData=null, + int timeOut=180, + Dictionary headers = null) + { + var client = httpClientFactory.CreateClient(); + var content = new StringContent(postData??""); + var request = new HttpRequestMessage(method, url) + { + Content = content + }; + headers ??= new Dictionary(); + headers.TryAdd(QuartzAuthorization.Key, QuartzAuthorization.AccessKey); + if (headers != null) + { + foreach (var header in headers) + { + request.Headers.Add(header.Key, header.Value); + } + } + try + { + client.Timeout = TimeSpan.FromSeconds(timeOut); + HttpResponseMessage httpResponseMessage = await client.SendAsync(request); + var result = await httpResponseMessage.Content + .ReadAsStringAsync(); + return result; + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + QuartzFileHelper.Error($"http请求异常,url:{url},{ex.Message+ex.StackTrace}"); + return ex.Message; + } + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Quartz/HttpResultfulJob.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Quartz/HttpResultfulJob.cs new file mode 100644 index 0000000000000000000000000000000000000000..28b7258f210c8a366eeefe91b83e92102e09931f --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Quartz/HttpResultfulJob.cs @@ -0,0 +1,134 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Quartz; +using Quartz.Impl; +using Quartz.Impl.Triggers; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using VOL.Core.Configuration; +using VOL.Core.EFDbContext; +using VOL.Core.Utilities; +using VOL.Entity.DomainModels; + +namespace VOL.Core.Quartz +{ + public class HttpResultfulJob : IJob + { + readonly IHttpClientFactory _httpClientFactory; + + readonly IServiceProvider _serviceProvider; + /// + /// 2020.05.31增加构造方法 + /// + /// + /// + public HttpResultfulJob(IServiceProvider serviceProvider, IHttpClientFactory httpClientFactory) + { + _httpClientFactory = httpClientFactory; + _serviceProvider = serviceProvider; + } + public async Task Execute(IJobExecutionContext context) + { + DateTime dateTime = DateTime.Now; + Sys_QuartzOptions taskOptions = context.GetTaskOptions(); + string httpMessage = ""; + AbstractTrigger trigger = (context as JobExecutionContextImpl).Trigger as AbstractTrigger; + if (taskOptions == null) + { + Console.WriteLine($"未获取到作业"); + return; + } + if (string.IsNullOrEmpty(taskOptions.ApiUrl) || taskOptions.ApiUrl == "/") + { + Console.WriteLine($"未配置作业:{taskOptions.TaskName}的url地址"); + QuartzFileHelper.Error($"未配置作业:{taskOptions.TaskName}的url地址"); + return; + } + string exceptionMsg = null; + + try + { + using (var dbContext = new VOLContext()) + { + var _taskOptions = dbContext.Set().AsTracking() + .Where(x => x.Id == taskOptions.Id).FirstOrDefault(); + + if (_taskOptions != null) + { + dbContext.Update(_taskOptions); + var entry = dbContext.Entry(_taskOptions); + entry.State = EntityState.Unchanged; + entry.Property("LastRunTime").IsModified = true; + _taskOptions.LastRunTime = DateTime.Now; + dbContext.SaveChanges(); + } + } + + Dictionary header = new Dictionary(); + if (!string.IsNullOrEmpty(taskOptions.AuthKey) + && !string.IsNullOrEmpty(taskOptions.AuthValue)) + { + header.Add(taskOptions.AuthKey.Trim(), taskOptions.AuthValue.Trim()); + } + + httpMessage = await _httpClientFactory.SendAsync( + taskOptions.Method?.ToLower() == "get" ? HttpMethod.Get : HttpMethod.Post, + taskOptions.ApiUrl, + taskOptions.PostData, + taskOptions.TimeOut ?? 180, + header); ; + } + catch (Exception ex) + { + exceptionMsg = ex.Message + ex.StackTrace; + } + finally + { + try + { + var log = new Sys_QuartzLog + { + LogId = Guid.NewGuid(), + TaskName = taskOptions.TaskName, + Id = taskOptions.Id, + CreateDate = dateTime, + ElapsedTime = Convert.ToInt32((DateTime.Now - dateTime).TotalSeconds), + ResponseContent = httpMessage, + ErrorMsg = exceptionMsg, + StratDate = dateTime, + Result = exceptionMsg == null ? 1 : 0, + EndDate = DateTime.Now + }; + using (var dbContext = new VOLContext()) + { + dbContext.Set().Add(log); + dbContext.SaveChanges(); + } + } + catch (Exception ex) + { + Console.WriteLine($"日志写入异常:{taskOptions.TaskName},{ex.Message}"); + QuartzFileHelper.Error($"日志写入异常:{typeof(HttpResultfulJob).Name},{taskOptions.TaskName},{ex.Message}"); + } + } + Console.WriteLine(trigger.FullName + " " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:sss") + " " + httpMessage); + return; + } + } + public class TaskOptions + { + public string TaskName { get; set; } + public string GroupName { get; set; } + public string Interval { get; set; } + public string ApiUrl { get; set; } + public string AuthKey { get; set; } + public string AuthValue { get; set; } + public string Describe { get; set; } + public string RequestType { get; set; } + public DateTime? LastRunTime { get; set; } + public int Status { get; set; } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Quartz/IOCJobFactory.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Quartz/IOCJobFactory.cs new file mode 100644 index 0000000000000000000000000000000000000000..ad328e790c3cd7b8a55f33bc480baede4030c799 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Quartz/IOCJobFactory.cs @@ -0,0 +1,28 @@ +using Quartz; +using Quartz.Spi; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace VOL.Core.Quartz +{ + public class IOCJobFactory: IJobFactory + { + private readonly IServiceProvider _serviceProvider; + public IOCJobFactory(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler) + { + return _serviceProvider.GetService(bundle.JobDetail.JobType) as IJob; + + } + + public void ReturnJob(IJob job) + { + (job as IDisposable)?.Dispose(); + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Quartz/JobAction.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Quartz/JobAction.cs new file mode 100644 index 0000000000000000000000000000000000000000..4e64657434d6191293ba90b56760218b50b5b807 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Quartz/JobAction.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.Quartz +{ + public enum JobAction + { + 新增 = 1, + 删除 = 2, + 修改 = 3, + 暂停 = 4, + 停止, + 开启, + 立即执行 + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Quartz/QuartzAuthorization.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Quartz/QuartzAuthorization.cs new file mode 100644 index 0000000000000000000000000000000000000000..0a8f77fcad58d76547cc0c369e217c4d75adf1e8 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Quartz/QuartzAuthorization.cs @@ -0,0 +1,69 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Primitives; +using System; +using System.Collections.Generic; +using System.Security.Cryptography; +using System.Text; +using VOL.Core.Configuration; +using VOL.Core.Extensions; + +namespace VOL.Core.Quartz +{ + public static class QuartzAuthorization + { + + private static string _quartzAccessKey; + + public static string Key = "QuartzAccessKey"; + public static string AccessKey + { + get + { + if (string.IsNullOrEmpty(_quartzAccessKey)) + { + _quartzAccessKey = GetAccessKey(); + } + return _quartzAccessKey; + } + } + public static string GetAccessKey() + { + if (string.IsNullOrEmpty(_quartzAccessKey)) + { + _quartzAccessKey = AppSetting.GetSettingString(Key); + } + if (string.IsNullOrEmpty(_quartzAccessKey)) + { + _quartzAccessKey = Guid.NewGuid().ToString(); + } + using (MD5 md5 = MD5.Create()) + { + string md5str = _quartzAccessKey; + byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(AppSetting.Secret.User)); + for (int i = 0; i < s.Length; i++) + { + string btos = s[i].ToString("X2"); + md5str += btos; + } + return md5str; + } + } + + public static AuthorizationFilterContext Validation(AuthorizationFilterContext context) + { + bool result = context.HttpContext.Request.Headers.TryGetValue(Key, out StringValues value); + if (!result || AccessKey != value) + { + context.Result = new ContentResult() + { + Content = new { message = "key不匹配", status = false, code = 401 }.Serialize(), + ContentType = "application/json", + StatusCode = 401 + }; + return context; + } + return context; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Quartz/QuartzFileHelper.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Quartz/QuartzFileHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..10948e763c86042e75704ab5b576edf39167787c --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Quartz/QuartzFileHelper.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Text; +using VOL.Core.Configuration; +using VOL.Core.Extensions; +using VOL.Core.Utilities; + +namespace VOL.Core.Quartz +{ + public static class QuartzFileHelper + { + public static void OK(string message) + { + Write(message, "log"); + } + + public static void Error(string message) + { + Write(message, "error"); + } + + private static void Write(string message,string folder) + { + try + { + string fileName = DateTime.Now.ToString("yyyy-MM-dd"); + string path = $"{AppSetting.CurrentPath}\\quartz\\{folder}\\".ReplacePath(); + FileHelper.WriteFile(path, $"{fileName}.txt", message, true); + } + catch (Exception ex) + { + Console.WriteLine($"文件写入异常{message},{ex.Message + ex.StackTrace}"); + } + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Quartz/QuartzNETExtension.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Quartz/QuartzNETExtension.cs new file mode 100644 index 0000000000000000000000000000000000000000..a029e189bf4ed22efbec40325b1f9a65b07158af --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Quartz/QuartzNETExtension.cs @@ -0,0 +1,349 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json; +using Quartz; +using Quartz.Impl; +using Quartz.Impl.Matchers; +using Quartz.Impl.Triggers; +using Quartz.Spi; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using VOL.Core.DBManager; +using VOL.Core.EFDbContext; +using VOL.Core.Extensions; +using VOL.Core.Utilities; +using VOL.Entity.DomainModels; + +namespace VOL.Core.Quartz +{ + public static class QuartzNETExtension + { + private static List _taskList = new List(); + + /// + /// 初始化作业 + /// + /// + /// + /// + public static IApplicationBuilder UseQuartz(this IApplicationBuilder applicationBuilder, IWebHostEnvironment env) + { + IServiceProvider services = applicationBuilder.ApplicationServices; + ISchedulerFactory _schedulerFactory = services.GetService(); + try + { + _taskList = services.GetService().Set().Where(x=>x.Status==0).ToList(); + for (int i = 0; i < 1; i++) + { + _taskList.Add(new Sys_QuartzOptions() + { + Id = Guid.NewGuid(), + GroupName = $"group{i}", + TaskName = $"task{i}", + CronExpression = "0 0 0 1 * ?", + Status = 0 + }); + } + _taskList.ForEach(options => + { + options.AddJob(_schedulerFactory, jobFactory: services.GetService()).GetAwaiter().GetResult(); + }); + } + catch (Exception ex) + { + Console.WriteLine($"作业启动异常:{ex.Message + ex.StackTrace}"); + } + return applicationBuilder; + } + + + private static async Task CheckTask(Sys_QuartzOptions taskOptions, ISchedulerFactory schedulerFactory) + { + string groupName = "group"; + string taskName = taskOptions.Id.ToString(); + IScheduler scheduler = await schedulerFactory.GetScheduler(); + List jobKeys =(await scheduler.GetJobKeys(GroupMatcher.GroupEquals(groupName))).ToList(); + if (jobKeys == null || jobKeys.Count() == 0) + { + return false; + } + JobKey jobKey = jobKeys.Where(s => scheduler.GetTriggersOfJob(s).Result + .Any(x => (x as CronTriggerImpl).Name == taskName)) + .FirstOrDefault(); + if (jobKey == null) + { + return false; + } + var triggers = await scheduler.GetTriggersOfJob(jobKey); + ITrigger trigger = triggers?.Where(x => (x as CronTriggerImpl).Name == taskName).FirstOrDefault(); + + if (trigger == null) + { + return false; + } + return true; + } + + /// + /// 添加作业 + /// + /// + /// + /// 是否初始化,否=需要重新生成配置文件,是=不重新生成配置文件 + /// + public static async Task AddJob(this Sys_QuartzOptions taskOptions, ISchedulerFactory schedulerFactory, IJobFactory jobFactory = null) + { + string msg = null; + try + { + if (await CheckTask(taskOptions,schedulerFactory)) + { + await schedulerFactory.TriggerAction(JobAction.开启, taskOptions); + return new { status = true }; + } + if (!_taskList.Exists(x => x.Id == taskOptions.Id)) + { + _taskList.Add(taskOptions); + } + else + { + _taskList = _taskList.Where(x => x.Id != taskOptions.Id).ToList(); + _taskList.Add(taskOptions); + } + taskOptions.GroupName = "group"; + (bool, string) validExpression = taskOptions.CronExpression.IsValidExpression(); + if (!validExpression.Item1) + { + msg = $"添加作业失败,作业:{taskOptions.TaskName},表达式不正确:{ taskOptions.CronExpression}"; + Console.WriteLine(msg); + QuartzFileHelper.Error(msg); + return new { status = false, msg = validExpression.Item2 }; + } + + IJobDetail job = JobBuilder.Create() + .WithIdentity(taskOptions.Id.ToString(), "group").Build(); + ITrigger trigger = TriggerBuilder.Create() + .WithIdentity(taskOptions.Id.ToString(), "group") + // .st() + .WithDescription(taskOptions.Describe) + .WithCronSchedule(taskOptions.CronExpression) + .Build(); + + IScheduler scheduler = await schedulerFactory.GetScheduler(); + + if (jobFactory == null) + { + jobFactory = HttpContext.Current.RequestServices.GetService(); + } + + if (jobFactory != null) + { + scheduler.JobFactory = jobFactory; + } + + await scheduler.ScheduleJob(job, trigger); + await scheduler.Start(); + msg = $"作业启动:{taskOptions.TaskName}"; + Console.WriteLine(msg); + QuartzFileHelper.Error(msg); + //if (taskOptions.Status == (int)TriggerState.Normal) + //{ + // await scheduler.Start(); + // msg = $"作业启动:{taskOptions.TaskName}"; + // Console.WriteLine(msg); + // QuartzFileHelper.Error(msg); + //} + //else + //{ + // await scheduler.PauseJob(job.Key); + //} + } + catch (Exception ex) + { + msg = $"作业启动异常:{taskOptions.TaskName},{ex.Message}"; + Console.WriteLine(msg); + QuartzFileHelper.Error(msg); + return new { status = false, msg = ex.Message }; + } + return new { status = true }; + } + + /// + /// 移除作业 + /// + /// + /// + /// + /// + public static Task Remove(this ISchedulerFactory schedulerFactory, Sys_QuartzOptions taskOptions) + { + return schedulerFactory.TriggerAction(JobAction.删除, taskOptions); + } + + /// + /// 更新作业 + /// + /// + /// + /// + public static Task Update(this ISchedulerFactory schedulerFactory, Sys_QuartzOptions taskOptions) + { + return schedulerFactory.TriggerAction(JobAction.修改, taskOptions); + } + + /// + /// 暂停作业 + /// + /// + /// + /// + public static Task Pause(this ISchedulerFactory schedulerFactory, Sys_QuartzOptions taskOptions) + { + return schedulerFactory.TriggerAction(JobAction.暂停, taskOptions); + } + + /// + /// 启动作业 + /// + /// + /// + /// + public static Task Start(this ISchedulerFactory schedulerFactory, Sys_QuartzOptions taskOptions) + { + return taskOptions.AddJob(schedulerFactory); + // return schedulerFactory.TriggerAction(JobAction.开启, taskOptions); + } + + /// + /// 立即执行一次作业 + /// + /// + /// + /// + public static Task Run(this ISchedulerFactory schedulerFactory, Sys_QuartzOptions taskOptions) + { + return schedulerFactory.TriggerAction(JobAction.立即执行, taskOptions); + } + + /// + /// 触发新增、删除、修改、暂停、启用、立即执行事件 + /// + /// + /// + /// + /// + /// + /// + public static async Task TriggerAction( + this ISchedulerFactory schedulerFactory, + JobAction action, + Sys_QuartzOptions taskOptions = null) + { + string errorMsg = ""; + try + { + string groupName = "group"; + string taskName = taskOptions.Id.ToString(); + IScheduler scheduler = await schedulerFactory.GetScheduler(); + List jobKeys = scheduler.GetJobKeys(GroupMatcher.GroupEquals(groupName)).Result.ToList(); + if (jobKeys == null || jobKeys.Count() == 0) + { + errorMsg = $"未找到分组[{groupName}]"; + return new { status = false, msg = errorMsg }; + } + JobKey jobKey = jobKeys.Where(s => scheduler.GetTriggersOfJob(s).Result + .Any(x => (x as CronTriggerImpl).Name == taskName)) + .FirstOrDefault(); + if (jobKey == null) + { + errorMsg = $"未找到触发器[{taskName}]"; + return new { status = false, msg = errorMsg }; + } + var triggers = await scheduler.GetTriggersOfJob(jobKey); + ITrigger trigger = triggers?.Where(x => (x as CronTriggerImpl).Name == taskName).FirstOrDefault(); + + if (trigger == null) + { + errorMsg = $"未找到触发器[{taskName}]"; + return new { status = false, msg = errorMsg }; + } + object result = null; + switch (action) + { + case JobAction.删除: + case JobAction.修改: + case JobAction.暂停: + await scheduler.PauseTrigger(trigger.Key); + await scheduler.UnscheduleJob(trigger.Key);// 移除触发器 + await scheduler.DeleteJob(trigger.JobKey); + if (action==JobAction.暂停) + { + taskOptions.Status = (int)JobAction.暂停; + } + break; + case JobAction.开启: + await scheduler.ResumeTrigger(trigger.Key); + await scheduler.TriggerJob(jobKey); + break; + } + return result ?? new { status = true, msg = $"作业{action.ToString()}成功" }; + } + catch (Exception ex) + { + errorMsg = ex.Message; + return new { status = false, msg = ex.Message }; + } + } + + /// + /// + /// + /// 通过作业上下文获取作业对应的配置参数 + /// + public static Sys_QuartzOptions GetTaskOptions(this IJobExecutionContext context) + { + AbstractTrigger trigger = (context as JobExecutionContextImpl).Trigger as AbstractTrigger; + Sys_QuartzOptions taskOptions = _taskList.Where(x => x.Id.ToString() == trigger.Name).FirstOrDefault(); + return taskOptions ?? _taskList.Where(x => x.Id.ToString() == trigger.JobName).FirstOrDefault(); + } + + /// + /// 作业是否存在 + /// + /// + /// 初始化的不需要判断 + /// + public static (bool, object) Exists(this Sys_QuartzOptions taskOptions, bool init) + { + if (!init && _taskList.Any(x => x.TaskName == taskOptions.TaskName && x.GroupName == taskOptions.GroupName)) + { + return (false, + new + { + status = false, + msg = $"作业:{taskOptions.TaskName},分组:{taskOptions.GroupName}已经存在" + }); + } + return (true, null); + } + + public static (bool, string) IsValidExpression(this string cronExpression) + { + try + { + CronTriggerImpl trigger = new CronTriggerImpl(); + trigger.CronExpressionString = cronExpression; + DateTimeOffset? date = trigger.ComputeFirstFireTimeUtc(null); + return (date != null, date == null ? $"请确认表达式{cronExpression}是否正确!" : ""); + } + catch (Exception e) + { + return (false, $"请确认表达式{cronExpression}是否正确!{e.Message}"); + } + } + } + +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Services/ActionExecutingLogger.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Services/ActionExecutingLogger.cs new file mode 100644 index 0000000000000000000000000000000000000000..1a17d4b091b00a899a35e8c0abf3efa97f540a8b --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Services/ActionExecutingLogger.cs @@ -0,0 +1,27 @@ +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.Services +{ + public class ActionObserver + { + //public ActionObserver(IHttpContextAccessor httpContextAccessor) + //{ + // this.RequestDate = DateTime.Now; + // this.HttpContext = httpContextAccessor.HttpContext; + //} + /// + /// 记录action执行的开始时间 + /// + public DateTime RequestDate { get; set; } + + /// + /// 当前请求是否已经写过日志,防止手动与系统自动重复写日志 + /// + public bool IsWrite { get; set; } + + public HttpContext HttpContext { get; } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Services/Logger.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Services/Logger.cs new file mode 100644 index 0000000000000000000000000000000000000000..03b5524a5805f96ff772489bcea6dd9451e8e169 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Services/Logger.cs @@ -0,0 +1,261 @@ +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using VOL.Core.Configuration; +using VOL.Core.DBManager; +using VOL.Core.Enums; +using VOL.Core.Extensions; +using VOL.Core.ManageUser; +using VOL.Entity.DomainModels; + +namespace VOL.Core.Services +{ + /// + /// 通过内置队列异步定时写日志 + /// + public static class Logger + { + public static ConcurrentQueue loggerQueueData = new ConcurrentQueue(); + private static DateTime lastClearFileDT = DateTime.Now.AddDays(-1); + private static string _loggerPath = AppSetting.DownLoadPath + "Logger\\Queue\\"; + static Logger() + { + Task.Run(() => { Start(); }); + } + + public static void Info(string message) + { + Info(LoggerType.Info, message); + } + public static void Info(LoggerType loggerType, string message = null) + { + Info(loggerType, message, null, null); + } + public static void Info(LoggerType loggerType, string requestParam, string resposeParam, string ex = null) + { + Add(loggerType, requestParam, resposeParam, ex, LoggerStatus.Info); + } + + public static void OK(string message) + { + OK(LoggerType.Success, message); + } + public static void OK(LoggerType loggerType, string message = null) + { + OK(loggerType, message, null, null); + } + public static void OK(LoggerType loggerType, string requestParam, string resposeParam, string ex = null) + { + Add(loggerType, requestParam, resposeParam, ex, LoggerStatus.Success); + } + public static void Error(string message) + { + Error(LoggerType.Error, message); + } + public static void Error(LoggerType loggerType, string message) + { + Error(loggerType, message, null, null); + } + public static void Error(LoggerType loggerType, string requestParam, string resposeParam, string ex = null) + { + Add(loggerType, requestParam, resposeParam, ex, LoggerStatus.Error); + } + + /// + /// + /// + /// 请求参数 + /// 响应参数 + /// 响应结果1、成功,2、异常,0、其他 + /// 用户数据 + private static void Add(LoggerType loggerType, string requestParameter, string responseParameter, string ex, LoggerStatus status) + { + Sys_Log log = null; + try + { + HttpContext context = Utilities.HttpContext.Current; + if (context.Request.Method == "OPTIONS") return; + ActionObserver cctionObserver = (context.RequestServices.GetService(typeof(ActionObserver)) as ActionObserver); + if (context == null) + { + WriteText($"未获取到httpcontext信息,type:{loggerType.ToString()},reqParam:{requestParameter},respParam:{responseParameter},ex:{ex},success:{status.ToString()}"); + return; + } + UserInfo userInfo = UserContext.Current.UserInfo; + log = new Sys_Log() + { + BeginDate = cctionObserver.RequestDate, + EndDate = DateTime.Now, + User_Id = userInfo.User_Id, + UserName = userInfo.UserTrueName, + Role_Id = userInfo.Role_Id, + LogType = loggerType.ToString(), + ExceptionInfo = ex, + RequestParameter = requestParameter, + ResponseParameter = responseParameter, + Success = (int)status + }; + SetServicesInfo(log, context); + } + catch (Exception exception) + { + log = log ?? new Sys_Log() + { + BeginDate = DateTime.Now, + EndDate = DateTime.Now, + LogType = loggerType.ToString(), + RequestParameter = requestParameter, + ResponseParameter = responseParameter, + Success = (int)status, + ExceptionInfo = ex + exception.Message + }; + } + loggerQueueData.Enqueue(log); + } + + private static void Start() + { + DataTable queueTable = CreateEmptyTable(); + while (true) + { + try + { + if (loggerQueueData.Count() > 0 && queueTable.Rows.Count < 500) + { + DequeueToTable(queueTable); continue; + } + //每5秒写一次数据 + Thread.Sleep(1000); + if (queueTable.Rows.Count == 0) { continue; } + + DBServerProvider.SqlDapper.BulkInsert(queueTable, "Sys_Log", SqlBulkCopyOptions.KeepIdentity, null, _loggerPath); + + queueTable.Clear(); + + if ((DateTime.Now - lastClearFileDT).TotalDays > 1) + { + Utilities.FileHelper.DeleteFolder(_loggerPath); + lastClearFileDT = DateTime.Now; + } + } + catch (Exception ex) + { + Console.WriteLine($"日志批量写入数据时出错:{ex.Message}"); + WriteText(ex.Message + ex.StackTrace + ex.Source); + queueTable.Clear(); + } + + } + + } + + private static void WriteText(string message) + { + try + { + Utilities.FileHelper.WriteFile(_loggerPath + "WriteError\\", $"{DateTime.Now.ToString("yyyyMMdd")}.txt", message + "\r\n"); + } + catch (Exception ex) + { + Console.WriteLine($"日志写入文件时出错:{ex.Message}"); + } + } + + private static void DequeueToTable(DataTable queueTable) + { + loggerQueueData.TryDequeue(out Sys_Log log); + DataRow row = queueTable.NewRow(); + if (log.BeginDate == null || log.BeginDate?.Year < 2010) + { + log.BeginDate = DateTime.Now; + } + if (log.EndDate == null) + { + log.EndDate = DateTime.Now; + } + // row["Id"] = log.Id; + row["LogType"] = log.LogType; + row["RequestParameter"] = log.RequestParameter?.Replace("\r\n", ""); + row["ResponseParameter"] = log.ResponseParameter?.Replace("\r\n", ""); + row["ExceptionInfo"] = log.ExceptionInfo; + row["Success"] = log.Success ?? -1; + row["BeginDate"] = log.BeginDate; + row["EndDate"] = log.EndDate; + row["ElapsedTime"] = ((DateTime)log.EndDate - (DateTime)log.BeginDate).TotalMilliseconds; + row["UserIP"] = log.UserIP; + row["ServiceIP"] = log.ServiceIP; + row["BrowserType"] = log.BrowserType; + row["Url"] = log.Url; + row["User_Id"] = log.User_Id ?? -1; + row["UserName"] = log.UserName; + row["Role_Id"] = log.Role_Id ?? -1; + queueTable.Rows.Add(row); + } + private static DataTable CreateEmptyTable() + { + DataTable queueTable = new DataTable(); + queueTable.Columns.Add("LogType", typeof(string)); + queueTable.Columns.Add("RequestParameter", typeof(string)); + queueTable.Columns.Add("ResponseParameter", typeof(string)); + queueTable.Columns.Add("ExceptionInfo", typeof(string)); + queueTable.Columns.Add("Success", Type.GetType("System.Int32")); + queueTable.Columns.Add("BeginDate", Type.GetType("System.DateTime")); + queueTable.Columns.Add("EndDate", Type.GetType("System.DateTime")); + queueTable.Columns.Add("ElapsedTime", Type.GetType("System.Int32")); + queueTable.Columns.Add("UserIP", typeof(string)); + queueTable.Columns.Add("ServiceIP", typeof(string)); + queueTable.Columns.Add("BrowserType", typeof(string)); + queueTable.Columns.Add("Url", typeof(string)); + queueTable.Columns.Add("User_Id", Type.GetType("System.Int32")); + queueTable.Columns.Add("UserName", typeof(string)); + queueTable.Columns.Add("Role_Id", Type.GetType("System.Int32")); + return queueTable; + } + + public static void SetServicesInfo(Sys_Log log, HttpContext context) + { + log.Url = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase + + context.Request.Path; + + log.UserIP = context.GetUserIp()?.Replace("::ffff:", ""); + log.ServiceIP = context.Connection.LocalIpAddress.MapToIPv4().ToString() + ":" + context.Connection.LocalPort; + + log.BrowserType = context.Request.Headers["User-Agent"]; + if (log.BrowserType!=null&&log.BrowserType.Length>190) + { + log.BrowserType = log.BrowserType.Substring(0, 190); + } + if (string.IsNullOrEmpty(log.RequestParameter)) + { + try + { + log.RequestParameter = context.GetRequestParameters(); + if (log.RequestParameter != null) + { + log.RequestParameter = HttpUtility.UrlDecode(log.RequestParameter, Encoding.UTF8); + } + } + catch (Exception ex) + { + log.ExceptionInfo += $"日志读取参数出错:{ex.Message}"; + Console.WriteLine($"日志读取参数出错:{ex.Message}"); + } + } + } + } + + public enum LoggerStatus + { + Success = 1, + Error = 2, + Info = 3 + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Tenancy/TenancyManager.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Tenancy/TenancyManager.cs new file mode 100644 index 0000000000000000000000000000000000000000..6d714cc84db64588b781a6ebaed5a547d54e851c --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Tenancy/TenancyManager.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Text; +using VOL.Core.ManageUser; + +namespace VOL.Core.Tenancy +{ + public static class TenancyManager where T : class + { + /// + /// 数据库表名 + /// + /// + /// + public static string GetSearchQueryable(string tableName) + { + string multiTenancyString = $"select * from {tableName}"; + //超级管理员不限制 + //if (UserContext.Current.IsSuperAdmin) + //{ + // return multiTenancyString; + //} + switch (tableName) + { + //例如:指定用户表指定查询条件 + //case "Sys_User": + // multiTenancyString += $" where UserId='{UserContext.Current.UserId}'"; + // break; + default: + //开启数租户数据隔离,用户只能看到自己的表数据(自己根据需要写条件做租户数据隔离) + multiTenancyString += $" where CreateID='{UserContext.Current.UserId}'"; + break; + } + return multiTenancyString; + } + + /// + /// + /// + /// 数据库表名 + /// 当前操作的所有id + /// 主键字段 + /// + public static string GetMultiTenancySql(string tableName, string ids, string tableKey) + { + //使用方法同上 + string multiTenancyString; + switch (tableName) + { + default: + multiTenancyString = $"select count(*) FROM {tableName} " + + $" where CreateID='{UserContext.Current.UserId}'" + + $" and { tableKey} in ({ids}) "; + break; + } + return multiTenancyString; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/UserManager/RoleContext.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/UserManager/RoleContext.cs new file mode 100644 index 0000000000000000000000000000000000000000..5176819bca33779c9235579ec4affd4434cd1397 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/UserManager/RoleContext.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using VOL.Core.CacheManager; +using VOL.Core.DBManager; +using VOL.Core.Extensions.AutofacManager; +using VOL.Core.ManageUser; +using VOL.Core.Services; +using VOL.Entity.DomainModels; + +namespace VOL.Core.UserManager +{ + public static class RoleContext + { + + private static object _RoleObj = new object(); + private static string _RoleVersionn = ""; + public const string Key = "inernalRole"; + + private static List _roles { get; set; } + public static List GetAllRoleId() + { + ICacheService cacheService = AutofacContainerModule.GetService(); + //每次比较缓存是否更新过,如果更新则重新获取数据 + if (_roles != null && _RoleVersionn == cacheService.Get(Key)) + { + return _roles; + } + lock (_RoleObj) + { + if (_RoleVersionn != "" && _roles != null && _RoleVersionn == cacheService.Get(Key)) return _roles; + _roles = DBServerProvider.DbContext + .Set() + .Where(x => x.Enable == 1) + .Select(s => new RoleNodes() { Id = s.Role_Id, ParentId = s.ParentId, RoleName = s.RoleName }) + .ToList(); + + string cacheVersion = cacheService.Get(Key); + if (string.IsNullOrEmpty(cacheVersion)) + { + cacheVersion = DateTime.Now.ToString("yyyyMMddHHMMssfff"); + cacheService.Add(Key, cacheVersion); + } + else + { + _RoleVersionn = cacheVersion; + } + } + return _roles; + } + + public static void Refresh() + { + AutofacContainerModule.GetService().Remove(Key); + } + /// + /// + /// 获取当前角色下的所有角色(不包括自己的角色) + /// + /// + /// + public static List GetAllChildren(int roleId) + { + if (roleId <= 0) return null; + var roles = GetAllRoleId(); + if (UserContext.IsRoleIdSuperAdmin(roleId)) return roles; + Dictionary completedRoles = new Dictionary(); + List rolesChildren = new List(); + var list= GetChildren(roles, rolesChildren, roleId, completedRoles); + //2021.07.11增加无限递归异常数据移除当前节点 + if (list.Any(x=>x.Id==roleId)) + { + return list.Where(x => x.Id != roleId).ToList(); + } + return list; + } + public static List GetAllChildrenIds(int roleId) + { + return GetAllChildren(roleId)?.Select(x => x.Id)?.ToList(); + } + /// + /// 递归获取所有子节点权限 + /// + /// + private static List GetChildren(List roles, List rolesChildren, int roleId, Dictionary completedRoles) + { + //2021.07.11修复不能获取三级以下角色的问题 + roles.ForEach(x => + { + if (x.ParentId == roleId) + { + if (completedRoles.TryGetValue(x.Id, out bool isWrite)) + { + if (!isWrite) + { + roles.Where(x => x.Id == roleId).FirstOrDefault().ParentId = 0; + Logger.Error($"获取子角色异常RoleContext,角色id:{x.Id}"); + Console.WriteLine($"获取子角色异常RoleContext,角色id:{x.Id}"); + completedRoles[x.Id] = true; + } + return; + } + if (!rolesChildren.Any(c => c.Id == x.Id)) + { + rolesChildren.Add(x); + } + completedRoles.Add(x.Id, false); + GetChildren(roles, rolesChildren, x.Id, completedRoles); + } + }); + return rolesChildren; + } + /// + /// 获取当前角色下的所有用户 + /// + /// + public static IQueryable GetCurrentAllChildUser() + { + var roles = GetAllChildrenIds(UserContext.Current.RoleId); + if (roles == null) + { + throw new Exception("未获取到当前角色"); + } + return DBServerProvider.DbContext + .Set() + .Where(u => roles.Contains(u.Role_Id)).Select(s => s.User_Id); + + } + } + public class RoleNodes + { + public int Id { get; set; } + public int ParentId { get; set; } + public string RoleName { get; set; } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/UserManager/UserContext.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/UserManager/UserContext.cs new file mode 100644 index 0000000000000000000000000000000000000000..1e896bfe24b7ac0334d71704e1356165583545aa --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/UserManager/UserContext.cs @@ -0,0 +1,372 @@ +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IdentityModel.Tokens.Jwt; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using VOL.Core.CacheManager; +using VOL.Core.DBManager; +using VOL.Core.Enums; +using VOL.Core.Extensions; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity; +using VOL.Entity.DomainModels; + +namespace VOL.Core.ManageUser +{ + public class UserContext + { + /// + /// 为了尽量减少redis或Memory读取,保证执行效率,将UserContext注入到DI, + /// 每个UserContext的属性至多读取一次redis或Memory缓存从而提高查询效率 + /// + public static UserContext Current + { + get + { + return Context.RequestServices.GetService(typeof(UserContext)) as UserContext; + } + } + + private static Microsoft.AspNetCore.Http.HttpContext Context + { + get + { + return Utilities.HttpContext.Current; + } + } + private static ICacheService CacheService + { + get { return GetService(); } + } + + private static T GetService() where T : class + { + return AutofacContainerModule.GetService(); + } + + public UserInfo UserInfo + { + get + { + if (_userInfo != null) + { + return _userInfo; + } + return GetUserInfo(UserId); + } + } + + private UserInfo _userInfo { get; set; } + + /// + /// 角色ID为1的默认为超级管理员 + /// + public bool IsSuperAdmin + { + get { return IsRoleIdSuperAdmin(this.RoleId); } + } + /// + /// 角色ID为1的默认为超级管理员 + /// + public static bool IsRoleIdSuperAdmin(int roleId) + { + return roleId == 1; + } + + public UserInfo GetUserInfo(int userId) + { + if (_userInfo != null) return _userInfo; + if (userId <= 0) + { + _userInfo = new UserInfo(); + return _userInfo; + } + string key = userId.GetUserIdKey(); + _userInfo = CacheService.Get(key); + if (_userInfo != null && _userInfo.User_Id > 0) return _userInfo; + + _userInfo = DBServerProvider.DbContext.Set() + .Where(x => x.User_Id == userId).Select(s => new UserInfo() + { + User_Id = userId, + Role_Id = s.Role_Id.GetInt(), + RoleName = s.RoleName, + //2022.08.15增加部门id + DeptId = s.Dept_Id??0, + Token = s.Token, + UserName = s.UserName, + UserTrueName = s.UserTrueName, + Enable = s.Enable + }).FirstOrDefault(); + + if (_userInfo != null && _userInfo.User_Id > 0) + { + CacheService.AddObject(key, _userInfo); + } + return _userInfo ?? new UserInfo(); + } + + /// + /// 获取角色权限时通过安全字典锁定的角色id + /// + private static ConcurrentDictionary objKeyValue = new ConcurrentDictionary(); + + /// + /// 角色权限的版本号 + /// + private static readonly Dictionary rolePermissionsVersion = new Dictionary(); + + /// + /// 每个角色ID对应的菜单权限(已做静态化处理) + /// 每次获取权限时用当前服务器的版本号与redis/memory缓存的版本比较,如果不同会重新刷新缓存 + /// + private static readonly Dictionary> rolePermissions = new Dictionary>(); + + + + /// + /// 获取用户所有的菜单权限 + /// + + public List Permissions + { + get + { + return GetPermissions(RoleId); + } + } + + /// + /// 菜单按钮变更时,同时刷新权限缓存2022.05.23 + /// + /// + public void RefreshWithMenuActionChange(int menuId) + { + foreach (var roleId in rolePermissions.Where(c => c.Value.Any(x => x.Menu_Id == menuId)).Select(s => s.Key)) + { + if (rolePermissionsVersion.ContainsKey(roleId)) + { + CacheService.Add(roleId.GetRoleIdKey(), DateTime.Now.ToString("yyyyMMddHHMMssfff")); + } + } + + } + + /// + /// 获取单个表的权限 + /// + /// + /// + public Permissions GetPermissions(string tableName) + { + return GetPermissions(RoleId).Where(x => x.TableName == tableName).FirstOrDefault(); + } + /// + /// 2022.03.26 + /// 菜单类型1:移动端,0:PC端 + /// + public static int MenuType + { + get + { + return Context.Request.Headers.ContainsKey("uapp") ? 1 : 0; + } + } + /// + /// 自定条件查询权限 + /// + /// + /// + public Permissions GetPermissions(Func func) + { + // 2022.03.26增移动端加菜单类型判断 + return GetPermissions(RoleId).Where(func).Where(x => x.MenuType == MenuType).FirstOrDefault(); + } + + private List ActionToArray(List permissions) + { + permissions.ForEach(x => + { + try + { + var menuAuthArr = x.MenuAuth.DeserializeObject>(); + x.UserAuthArr = string.IsNullOrEmpty(x.UserAuth) + ? new string[0] + : x.UserAuth.Split(",").Where(c => menuAuthArr.Any(m => m.Value == c)).ToArray(); + + } + catch { } + finally + { + if (x.UserAuthArr == null) + { + x.UserAuthArr = new string[0]; + } + } + }); + return permissions; + } + private List MenuActionToArray(List permissions) + { + permissions.ForEach(x => + { + try + { + x.UserAuthArr = string.IsNullOrEmpty(x.UserAuth) + ? new string[0] + : x.UserAuth.DeserializeObject>().Select(s => s.Value).ToArray(); + } + catch { } + finally + { + if (x.UserAuthArr == null) + { + x.UserAuthArr = new string[0]; + } + } + }); + return permissions; + } + public List GetPermissions(int roleId) + { + if (IsRoleIdSuperAdmin(roleId)) + { + //2020.12.27增加菜单界面上不显示,但可以分配权限 + var permissions = DBServerProvider.DbContext.Set() + .Where(x => x.Enable == 1 || x.Enable == 2) + .Select(a => new Permissions + { + Menu_Id = a.Menu_Id, + ParentId = a.ParentId, + //2020.05.06增加默认将表名转换成小写,权限验证时不再转换 + TableName = (a.TableName ?? "").ToLower(), + //MenuAuth = a.Auth, + UserAuth = a.Auth, + // 2022.03.26增移动端加菜单类型 + MenuType = a.MenuType ?? 0 + }).ToList(); + return MenuActionToArray(permissions); + } + ICacheService cacheService = CacheService; + string roleKey = roleId.GetRoleIdKey(); + + //角色有缓存,并且当前服务器的角色版本号与redis/memory缓存角色的版本号相同直接返回静态对象角色权限 + string currnetVeriosn = ""; + if (rolePermissionsVersion.TryGetValue(roleId, out currnetVeriosn) + && currnetVeriosn == cacheService.Get(roleKey)) + { + return rolePermissions.ContainsKey(roleId) ? rolePermissions[roleId] : new List(); + } + + //锁定每个角色,通过安全字典减少锁粒度,否则多个同时角色获取缓存会导致阻塞 + object objId = objKeyValue.GetOrAdd(roleId.ToString(), new object()); + //锁定每个角色 + lock (objId) + { + if (rolePermissionsVersion.TryGetValue(roleId, out currnetVeriosn) + && currnetVeriosn == cacheService.Get(roleKey)) + { + return rolePermissions.ContainsKey(roleId) ? rolePermissions[roleId] : new List(); + } + + //没有redis/memory缓存角色的版本号或与当前服务器的角色版本号不同时,刷新缓存 + var dbContext = DBServerProvider.DbContext; + List _permissions = (from a in dbContext.Set() + join b in dbContext.Set() + on a.Menu_Id equals b.Menu_Id + where b.Role_Id == roleId //&& a.ParentId > 0 + && b.AuthValue != "" + orderby a.ParentId + select new Permissions + { + Menu_Id = a.Menu_Id, + ParentId = a.ParentId, + //2020.05.06增加默认将表名转换成小写,权限验证时不再转换 + TableName = (a.TableName ?? "").ToLower(), + MenuAuth = a.Auth, + UserAuth = b.AuthValue ?? "", + // 2022.03.26增移动端加菜单类型 + MenuType = a.MenuType ?? 0 + }).ToList(); + ActionToArray(_permissions); + string _version = cacheService.Get(roleKey); + //生成一个唯一版本号标识 + if (_version == null) + { + _version = DateTime.Now.ToString("yyyyMMddHHMMssfff"); + //将版本号写入缓存 + cacheService.Add(roleKey, _version); + } + //刷新当前服务器角色的权限 + rolePermissions[roleId] = _permissions; + + //写入当前服务器的角色最新版本号 + rolePermissionsVersion[roleId] = _version; + return _permissions; + } + + } + + /// + /// 判断是否有权限 + /// + /// + /// + /// + /// + public bool ExistsPermissions(string tableName, string authName, int roleId = 0) + { + if (roleId <= 0) roleId = RoleId; + tableName = tableName.ToLower(); + return GetPermissions(roleId).Any(x => x.TableName == tableName && x.UserAuthArr.Contains(authName)); + } + + /// + /// 判断是否有权限 + /// + /// + /// + /// + /// + public bool ExistsPermissions(string tableName, ActionPermissionOptions actionPermission, int roleId = 0) + { + return ExistsPermissions(tableName, actionPermission.ToString(), roleId); + } + public int UserId + { + get + { + return (Context.User.FindFirstValue(JwtRegisteredClaimNames.Jti) + ?? Context.User.FindFirstValue(ClaimTypes.NameIdentifier)).GetInt(); + } + } + + public string UserName + { + get { return UserInfo.UserName; } + } + + public string UserTrueName + { + get { return UserInfo.UserTrueName; } + } + + public string Token + { + get { return UserInfo.Token; } + } + + public int RoleId + { + get { return UserInfo.Role_Id; } + } + + public void LogOut(int userId) + { + CacheService.Remove(userId.GetUserIdKey()); + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/ApiAuthorizeRequire.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/ApiAuthorizeRequire.cs new file mode 100644 index 0000000000000000000000000000000000000000..3653bdf43cd406391c51f22826c022988c91e247 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/ApiAuthorizeRequire.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.Utilities +{ + public class ApiAuthorizeRequire + { + public static void Require() + { + + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/DateTimeExtension.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/DateTimeExtension.cs new file mode 100644 index 0000000000000000000000000000000000000000..4d2b29c6f2e5dad4d4924b71ef555f63db45649e --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/DateTimeExtension.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Text; + +using System.IO; +using System.Collections; + +namespace VOL.Core.Utilities +{ + public static class DateTimeExtension + { + /// + /// 实现由C# 的时间到 Javascript 的时间的转换 + /// returns the number of milliseconds since Jan 1, 1970 (useful for converting C# dates to JS dates) + /// + /// + /// + public static double UnixTicks(this DateTime dt) + { + DateTime d1 = new DateTime(1970, 1, 1); + DateTime d2 = dt.AddHours(8).ToUniversalTime(); + TimeSpan ts = new TimeSpan(d2.Ticks - d1.Ticks); + return ts.TotalMilliseconds; + } + + /// + /// 将毫秒值转成 C# DateTime 类型 + /// + /// + /// + public static DateTime ConvertTime(this long time) + { + DateTime timeStamp = new DateTime(1970, 1, 1); //得到1970年的时间戳 + long t = (time + 8 * 60 * 60) * 10000000 + timeStamp.Ticks; + DateTime dt = new DateTime(t); + return dt; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/DateTimeHelper.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/DateTimeHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..1ea305e3f9ef64315c65f09563d5ca53e1e09a3e --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/DateTimeHelper.cs @@ -0,0 +1,45 @@ +using System.IO; + +using System.Text; +using System; + +namespace VOL.Core.Utilities +{ + public class DateTimeHelper + { + public static string FriendlyDate(DateTime? date) + { + if (!date.HasValue) return string.Empty; + + string strDate = date.Value.ToString("yyyy-MM-dd"); + string vDate = string.Empty; + if(DateTime.Now.ToString("yyyy-MM-dd")==strDate) + { + vDate = "今天"; + } + else if (DateTime.Now.AddDays(1).ToString("yyyy-MM-dd") == strDate) + { + vDate = "明天"; + } + else if (DateTime.Now.AddDays(2).ToString("yyyy-MM-dd") == strDate) + { + vDate = "后天"; + } + else if (DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd") == strDate) + { + vDate = "昨天"; + } + else if (DateTime.Now.AddDays(2).ToString("yyyy-MM-dd") == strDate) + { + vDate = "前天"; + } + else + { + vDate = strDate; + } + + return vDate; + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/DynamicPropertyBag .cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/DynamicPropertyBag .cs new file mode 100644 index 0000000000000000000000000000000000000000..90045ec4611db258538a9de9f587494285f6a117 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/DynamicPropertyBag .cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Dynamic; +using System.IO; + +namespace VOL.Core.Utilities +{ + /// + /// 动态属性Bag + /// + public class DynamicPropertyBag : DynamicObject + { + private Dictionary storage = new Dictionary(); + + public override bool TryGetMember(GetMemberBinder binder, out object result) + { + if (storage.ContainsKey(binder.Name)) + { + result = storage[binder.Name]; + return true; + } + result = null; + return false; + } + + public override bool TrySetMember(SetMemberBinder binder, object value) + { + string key = binder.Name; + if (storage.ContainsKey(key)) + storage[key] = value; + else + storage.Add(key, value); + return true; + } + + public override string ToString() + { + StringWriter message = new StringWriter(); + foreach (var item in storage) + message.WriteLine("{0}:\t{1}", item.Key, item.Value); + return message.ToString(); + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/EPPlusHelper.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/EPPlusHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..bd3c2191e3b5bef8e3a0f4dcd24731c655d26fd5 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/EPPlusHelper.cs @@ -0,0 +1,653 @@ +using OfficeOpenXml; +using OfficeOpenXml.Style; +using System; +using System.Collections.Generic; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using VOL.Core.DBManager; +using VOL.Core.Extensions; +using VOL.Core.Infrastructure; +using VOL.Entity.DomainModels; + +namespace VOL.Core.Utilities +{ + public class EPPlusHelper + { + /// + /// 导入模板(仅限框架导出模板使用)(202.05.07) + /// + /// + /// + /// 指定导出的列 + /// 忽略不导出的列(如果设置了exportColumns,ignoreColumns不会生效) + /// + + public static WebResponseContent ReadToDataTable(string path, + Expression> exportColumns = null, + List ignoreTemplate = null, + Func readValue = null) + { + WebResponseContent responseContent = new WebResponseContent(); + + FileInfo file = new FileInfo(path); + if (!file.Exists) return responseContent.Error("未找到上传的文件,请重新上传"); + + List entities = new List(); + using (ExcelPackage package = new ExcelPackage(file)) + { + if (package.Workbook.Worksheets.Count == 0 || + package.Workbook.Worksheets.FirstOrDefault().Dimension.End.Row <= 1) + return responseContent.Error("未导入数据"); + //2020.08.11修复获取表结构信息时,表为别名时查不到数据的问题 + //typeof(T).GetEntityTableName() + List cellOptions = GetExportColumnInfo(typeof(T).Name, false, false, columns: exportColumns?.GetExpressionToArray()); + //设置忽略的列 + if (exportColumns != null) + { + cellOptions = cellOptions + .Where(x => exportColumns.GetExpressionToArray().Select(s => s.ToLower()).Contains(x.ColumnName.ToLower())) + .ToList(); + } + else if (ignoreTemplate != null) + { + cellOptions = cellOptions + .Where(x => !ignoreTemplate.Select(s => s.ToLower()).Contains(x.ColumnName.ToLower())) + .ToList(); + } + + + ExcelWorksheet sheetFirst = package.Workbook.Worksheets.FirstOrDefault(); + + for (int j = sheetFirst.Dimension.Start.Column, k = sheetFirst.Dimension.End.Column; j <= k; j++) + { + string columnCNName = sheetFirst.Cells[1, j].Value?.ToString()?.Trim(); + if (!string.IsNullOrEmpty(columnCNName)) + { + CellOptions options = cellOptions.Where(x => x.ColumnCNName == columnCNName).FirstOrDefault(); + if (options == null) + { + return responseContent.Error("导入文件列[" + columnCNName + "]不是模板中的列"); + } + if (options.Index > 0) + { + return responseContent.Error("导入文件列[" + columnCNName + "]不能重复"); + } + options.Index = j; + } + } + if (cellOptions.Exists(x => x.Index == 0)) + { + return responseContent.Error("导入文件列必须与导入模板相同"); + } + + PropertyInfo[] propertyInfos = typeof(T).GetProperties() + .Where(x => cellOptions.Select(s => s.ColumnName).Contains(x.Name)) + .ToArray(); + ExcelWorksheet sheet = package.Workbook.Worksheets.FirstOrDefault(); + for (int m = sheet.Dimension.Start.Row + 1, n = sheet.Dimension.End.Row; m <= n; m++) + { + T entity = Activator.CreateInstance(); + for (int j = sheet.Dimension.Start.Column, k = sheet.Dimension.End.Column; j <= k; j++) + { + + string value = sheet.Cells[m, j].Value?.ToString(); + //2022.06.20增加原生excel读取方法 + if (readValue != null) + { + value = readValue(value, sheet, sheet.Cells[m, j], m, j); + } + + CellOptions options = cellOptions.Where(x => x.Index == j).FirstOrDefault(); + PropertyInfo property = propertyInfos.Where(x => x.Name == options.ColumnName).FirstOrDefault(); + //2021.06.04优化判断 + if (string.IsNullOrEmpty(value)) + { + if (options.Requierd) + { + return responseContent.Error($"第{m}行[{options.ColumnCNName}]验证未通过,不能为空。"); + } + continue; + } + + + //验证字典数据 + //2020.09.20增加判断数据源是否有值 + if (!string.IsNullOrEmpty(options.DropNo) && !string.IsNullOrEmpty(value)) + { + if (options.KeyValues == null) + { + return responseContent.Error($"[{options.ColumnCNName}]字段数字典编号[{options.DropNo}]缺失,请检查字典配置"); + } + string key = null; + //2022.11.21增加导入多选的支持 + if ((options.EditType == "selectList" || options.EditType == "checkbox") && !string.IsNullOrEmpty(value)) + { + var cellValues = value.Replace(",", ",").Split(",").Where(x => !string.IsNullOrEmpty(x)).ToArray(); + var keys = options.KeyValues.Where(x => cellValues.Contains(x.Value)) + .Select(s => s.Key).ToArray(); + if (cellValues.Length == keys.Length) + { + key = string.Join(",", keys); + } + } + else + { + key = options.KeyValues.Where(x => x.Value == value) + .Select(s => s.Key) + .FirstOrDefault(); + } + + if (key == null)//&& options.Requierd + { + //小于20个字典项,直接提示所有可选value + string values = options.KeyValues.Count < 20 ? (string.Join(',', options.KeyValues.Select(s => s.Value))) : options.ColumnCNName; + return responseContent.Error($"第{m}行[{options.ColumnCNName}]验证未通过,必须是字典数据中[{values}]的值。"); + } + //将值设置为数据字典的Key,如果导入为是/否字典项,存在表中应该对为1/0 + value = key; + } + else if (property.PropertyType == typeof(DateTime) || property.PropertyType == typeof(DateTime?)) + { + //2021.06.04增加日期格式处理 + if (value.Length == 5 && int.TryParse(value, out int days)) + { + property.SetValue(entity, new DateTime(1900, 1, 1).AddDays(days - 2)); + } + else + { + property.SetValue(entity, value.ChangeType(property.PropertyType)); + } + continue; + } + + //验证导入与实体数据类型是否相同 + (bool, string, object) result = property.ValidationProperty(value, options.Requierd); + + if (!result.Item1) + { + return responseContent.Error($"第{m}行[{options.ColumnCNName}]验证未通过,{result.Item2}"); + } + + property.SetValue(entity, value.ChangeType(property.PropertyType)); + } + entity.SetCreateDefaultVal(); + entities.Add(entity); + } + } + return responseContent.OK(null, entities); + } + + /// + /// + /// + /// + /// key为字段名, ValueTuple为字段中文名及列宽度 + /// List>item1列名,item2 字典value,item3字典name + /// 返回文件保存的路径 + public static string Export(DataTable table, List cellOptions, string savePath, string fileName) + { + if (!Directory.Exists(savePath)) Directory.CreateDirectory(savePath); + + //获取所有有值的数据源 + var dicNoKeys = cellOptions + .Where(x => !string.IsNullOrEmpty(x.DropNo) && x.KeyValues != null && x.KeyValues.Keys.Count > 0) + .Select(x => new { x.DropNo, x.ColumnName }).Distinct().ToList(); + + + + using (ExcelPackage package = new ExcelPackage()) + { + var worksheet = package.Workbook.Worksheets.Add("sheet1"); + for (int i = 0; i < table.Columns.Count; i++) + { + using (ExcelRange range = worksheet.Cells[1, i + 1]) + { + worksheet.Cells[1, i + 1].Style.Fill.PatternType = ExcelFillStyle.Solid; + worksheet.Cells[1, i + 1].Style.Fill.BackgroundColor.SetColor(Color.Gray); //背景色 + worksheet.Cells[1, i + 1].Style.Font.Color.SetColor(Color.White); + } + CellOptions options = cellOptions.Where(x => x.ColumnName == table.Columns[i].ColumnName).FirstOrDefault(); + if (options != null) + { + worksheet.Column(i + 1).Width = options.ColumnWidth / 6.00; + worksheet.Cells[1, i + 1].Value = options.ColumnCNName; + } + else + { + worksheet.Column(i + 1).Width = 15; + worksheet.Cells[1, i + 1].Value = table.Columns[i].ColumnName; + } + } + + for (int i = 0; i < table.Rows.Count; i++) + { + for (int j = 0; j < table.Columns.Count; j++) + { + string cellValue = (table.Rows[i][j] ?? "").ToString(); + if (dicNoKeys.Exists(x => x.ColumnName == table.Columns[j].ColumnName)) + { + cellOptions.Where(x => x.ColumnName == table.Columns[j].ColumnName) + .Select(s => s.KeyValues) + .FirstOrDefault() + .TryGetValue(cellValue, out string result); + cellValue = result ?? cellValue; + } + worksheet.Cells[i + 2, j + 1].Value = cellValue; + } + } + package.SaveAs(new FileInfo(savePath + fileName)); + } + return savePath + fileName; + } + + + /// + /// 下载导出模板(仅限框架导出模板使用)(202.05.07) + /// + /// + /// 指定导出的列 + /// 忽略不导出的列(如果设置了exportColumns,ignoreColumns不会生效) + /// 导出文件的绝对路径 + /// 导出的文件名+后缀,如:123.xlsx + /// + public static string ExportTemplate(List exportColumns, List ignoreColumns, string savePath, string fileName) + { + return Export(null, exportColumns, ignoreColumns, savePath, fileName, true); + } + + /// + /// 下载导出模板(仅限框架导出模板使用)(202.05.07) + /// + /// + /// 指定导出的列 + /// 忽略不导出的列(如果设置了exportColumns,ignoreColumns不会生效) + /// 导出文件的绝对路径 + /// 导出的文件名+后缀,如:123.xlsx + /// + public static string ExportTemplate(Expression> exportColumns, List ignoreColumns, string savePath, string fileName) + { + return Export(null, exportColumns?.GetExpressionToArray(), ignoreColumns, savePath, fileName, true); + } + + /// + /// 下载导出模板(仅限框架导出模板使用)(202.05.07) + /// + /// + /// 忽略不导出的列 + /// 导出文件的绝对路径 + /// 导出的文件名+后缀,如:123.xlsx + /// + public static string ExportTemplate(List ignoreColumns, string savePath, string fileName) + { + return Export(null, null, ignoreColumns, savePath, fileName, true); + } + + /// + /// 导出excel文件(导入功能里的导出模板也使用的此功能,list传的null,导出的文件只有模板的标题) + /// (202.05.07) + /// + /// + /// + /// 对应代码生成器的配置 + /// 忽略不导出的字段 + /// + /// + /// + /// + public static string Export(List list, Expression> ignore, string savePath, string fileName, bool template = false) + { + return Export(list, null, ignore?.GetExpressionProperty(), savePath, fileName, template); + } + + /// + /// 导出excel文件(导入功能里的导出模板也使用的此功能,list传的null,导出的文件只有模板的标题) + /// (202.05.07) + /// + /// + /// 导出的对象 + /// 指定导出的列 + /// 忽略不导出的列(如果设置了exportColumns,ignoreColumns不会生效) + /// 保存路径 + /// 保存的文件名 + /// 是否为下载模板 + /// + public static string Export(List list, IEnumerable exportColumns, IEnumerable ignoreColumns, string savePath, string fileName, bool template = false) + { + if (!Directory.Exists(savePath)) Directory.CreateDirectory(savePath); + + //获取代码生成器对应的配置信息 + // List cellOptions = GetExportColumnInfo(typeof(T).GetEntityTableName(), template); + //2020.06.02修复使用表别名时读取不到配置信息 + List cellOptions = GetExportColumnInfo(typeof(T).Name, template, columns: exportColumns?.ToArray()); + string fullPath = savePath + fileName; + //获取所有有值的数据源 + var dicNoKeys = cellOptions + .Where(x => !string.IsNullOrEmpty(x.DropNo) && x.KeyValues != null && x.KeyValues.Keys.Count > 0) + .Select(x => new { x.DropNo, x.ColumnName, x.SearchType, x.EditType }).Distinct().ToList(); + //2021.01.24修复多选类型,导出excel文件没有转换数据源的问题 + var selectList = dicNoKeys.Where(x => x.SearchType == "checkbox" || x.SearchType == "selectList" || x.EditType == "checkbox" || x.EditType == "selectList") + .Select(s => s.ColumnName).ToArray(); + + List propertyInfo = null; + + /*导出时,代码生成器中的表配置信息Sys_TableInfo/Sys_TableColumn必须与当前数据库相同,否则导出来可能没有数据*/ + + //2020.06.02优化读取导出列配置信息 + //导出指定的列 + //如果指定了导出的标题列,忽略的标题列不再起作用 + if (exportColumns != null && exportColumns.Count() > 0) + { + propertyInfo = new List(); + var properties = typeof(T).GetProperties(); + foreach (var name in exportColumns) + { + var property = properties.Where(x => x.Name.ToLower() == name.ToLower()).FirstOrDefault(); + if (property != null) + { + propertyInfo.Add(property); + } + } + //propertyInfo = + // typeof(T).GetProperties() + // .Where(x => exportColumns.Select(g => g.ToLower()).Contains(x.Name.ToLower())).ToList(); + //.Where(x => cellOptions.Select(s => s.ColumnName) //获取代码生成器配置的列 + //.Contains(x.Name)).ToList(); + } + else if (ignoreColumns != null && ignoreColumns.Count() > 0) + { + propertyInfo = typeof(T).GetProperties() + .Where(x => !ignoreColumns.Select(g => g.ToLower()).Contains(x.Name.ToLower())) + .Where(x => cellOptions.Select(s => s.ColumnName).Contains(x.Name)) //获取代码生成器配置的列 + .ToList(); + } + else + { + //默认导出代码生成器中配置【是否显示】=是的列 + propertyInfo = typeof(T).GetProperties() + .Where(x => cellOptions.Select(s => s.ColumnName).Contains(x.Name)) //获取代码生成器配置的列 + .ToList(); + /* + * 如果propertyInfo查出来的长度=0 + * 1、代码生成器中的配置信息是否同步到当前数据库 + * 2、代码生成器中的配置列名与model的字段是否大小写一致 + */ + } + string[] dateArr = null; + if (!template) + { + dateArr = propertyInfo.Where(x => x.PropertyType == typeof(DateTime) + || x.PropertyType == typeof(DateTime?)) + .Select(s => s.Name).ToArray(); + } + + using (ExcelPackage package = new ExcelPackage()) + { + var worksheet = package.Workbook.Worksheets.Add("sheet1"); + for (int i = 0; i < propertyInfo.Count; i++) + { + string columnName = propertyInfo[i].Name; + using (ExcelRange range = worksheet.Cells[1, i + 1]) + { + worksheet.Cells[1, i + 1].Style.Fill.PatternType = ExcelFillStyle.Solid; + //默认灰色背景,白色字体 + Color backgroundColor = Color.Gray; + //字体颜色 + Color fontColor = Color.White; + //下载模板并且是必填项,将表格设置为黄色 + if (template) + { + fontColor = Color.Black; + if (cellOptions.Exists(x => x.ColumnName == columnName && x.Requierd)) + { + backgroundColor = Color.Yellow; //黄色必填 + } + else + { + backgroundColor = Color.White; + } + } + worksheet.Cells[1, i + 1].Style.Fill.BackgroundColor.SetColor(backgroundColor); //背景色 + worksheet.Cells[1, i + 1].Style.Font.Color.SetColor(fontColor);//字体颜色 + } + CellOptions options = cellOptions.Where(x => x.ColumnName == columnName).FirstOrDefault(); + if (options != null) + { + worksheet.Column(i + 1).Width = options.ColumnWidth / 6.00; + worksheet.Cells[1, i + 1].Value = options.ColumnCNName; + } + else + { + worksheet.Column(i + 1).Width = 15; + worksheet.Cells[1, i + 1].Value = columnName; + } + } + //下载模板直接返回 + if (template) + { + package.SaveAs(new FileInfo(fullPath)); + return fullPath; + } + //2021.01.24修复多选类型,导出excel文件没有转换数据源的问题 + IEnumerable GetListValues(string cellValues, string propertyName) + { + var values = cellValues.Split(","); + for (int i = 0; i < values.Length; i++) + { + cellOptions.Where(x => x.ColumnName == propertyName) + .Select(s => s.KeyValues) + .FirstOrDefault() + .TryGetValue(values[i], out string result); + yield return result ?? values[i]; + } + + } + for (int i = 0; i < list.Count; i++) + { + for (int j = 0; j < propertyInfo.Count; j++) + { + object cellValue = null; + if (dateArr != null && dateArr.Contains(propertyInfo[j].Name)) + { + object value = propertyInfo[j].GetValue(list[i]); + cellValue = value == null ? "" : ((DateTime)value).ToString("yyyy-MM-dd HH:mm:sss").Replace(" 00:00:00", ""); + } + else + { + cellValue = propertyInfo[j].GetValue(list[i]); + } + if (cellValue != null && dicNoKeys.Exists(x => x.ColumnName == propertyInfo[j].Name)) + { + //2021.01.24修复多选类型,导出excel文件没有转换数据源的问题 + if (selectList.Contains(propertyInfo[j].Name)) + { + cellValue = string.Join(",", GetListValues(cellValue.ToString(), propertyInfo[j].Name)); + } + else + { + cellOptions.Where(x => x.ColumnName == propertyInfo[j].Name) + .Select(s => s.KeyValues) + .FirstOrDefault() + .TryGetValue(cellValue.ToString(), out string result); + cellValue = result ?? cellValue; + } + + } + worksheet.Cells[i + 2, j + 1].Value = cellValue; + } + } + + package.SaveAs(new FileInfo(fullPath)); + } + return fullPath; + } + + + /// + /// 获取导出的列的数据信息 + /// + /// + /// 是否为下载模板 + /// filterKeyValue是否过滤Key相同的数据 + /// + private static List GetExportColumnInfo(string tableName, bool temlate = false, bool filterKeyValue = true, string[] columns = null) + { + //&& x.IsDisplay == 1&&x.IsReadDataset==0只导出代码生器中设置为显示并且不是只读的列,可根据具体业务设置导出列 + // && x.IsReadDataset == 0 + //2020.06.02增加不区分大表名大小写: 原因mysql可能是表名是小写,但生成model的时候强制大写 + //x => x.TableName.ToLower() == tableName.ToLower() + var query = DBServerProvider.DbContext.Set().Where(x => x.TableName.ToLower() == tableName.ToLower()); + if (columns != null && columns.Length > 0) + { + query = query.Where(x => columns.Contains(x.ColumnName)); + } + else + { + query = query.Where(x => x.IsDisplay == 1); + } + List cellOptions = query.OrderByDescending(x => x.OrderNo).Select(c => new CellOptions() + { + ColumnName = c.ColumnName, + ColumnCNName = c.ColumnCnName, + DropNo = c.DropNo, + Requierd = c.IsNull > 0 ? false : true, + ColumnWidth = c.ColumnWidth ?? 90, + EditType = c.EditType, + SearchType = c.SearchType + + }).ToList(); + + + if (temlate) return cellOptions; + + var dicNos = cellOptions.Where(x => !string.IsNullOrEmpty(x.DropNo)).Select(c => c.DropNo); + + if (dicNos.Count() == 0) return cellOptions; + + var dictionaries = DictionaryManager.GetDictionaries(dicNos); + //获取绑定字典数据源下拉框的值 + foreach (string dicNo in dicNos.Distinct()) + { + Dictionary keyValues = new Dictionary(StringComparer.OrdinalIgnoreCase); + List dictionaryLists = dictionaries + .Where(x => x.DicNo == dicNo && x.Sys_DictionaryList != null) + .Select(s => s.Sys_DictionaryList).FirstOrDefault(); + if (dictionaryLists == null || dictionaryLists.Count == 0) continue; + foreach (var item in dictionaryLists) + { + ////filterKeyValue为true过滤keyvalue相不的项,key==value相同的则不处理 + if (filterKeyValue && item.DicName == item.DicValue) continue; + if (keyValues.ContainsKey(item.DicValue)) continue; + keyValues.Add(item.DicValue, item.DicName); + } + + foreach (CellOptions options in cellOptions.Where(x => x.DropNo == dicNo)) + { + options.KeyValues = keyValues; + } + } + return cellOptions; + } + + public static string ExportGeneralExcel( + List> rows, + string fileName, + string path = null, + Action onFillCell = null, + Action saveBefore = null) + { + return ExportGeneralExcel(rows.Select(item => item as IDictionary).ToList(), fileName, path, onFillCell, saveBefore); + } + + /// + /// 2021.01.10增加通过excel导出功能 + /// + /// + /// + /// + /// + /// + /// + public static string ExportGeneralExcel( + List> rows, + string fileName, + string path = null, + Action onFillCell = null, + Action saveBefore = null) + { + path = path ?? $"Download/ExcelExport/{ DateTime.Now.ToString("yyyyyMMdd")}/"; + string fullPath = path.MapPath(); + fileName = Guid.NewGuid() + "_" + fileName; + if (!Directory.Exists(fullPath)) Directory.CreateDirectory(fullPath); + + using (ExcelPackage package = new ExcelPackage()) + { + var worksheet = package.Workbook.Worksheets.Add("sheet1"); + int j = 0; + foreach (var item in rows[0]) + { + object cellValue = item.Key; + + int i = 0; + worksheet.Cells[1 + i, j + 1].Value = cellValue; + //worksheet.Column(j + 1).Width = 11; + worksheet.Row(i + 1).Height = 20;//设置行高 + var style = worksheet.Cells[i + 1, j + 1].Style; + style.Fill.PatternType = ExcelFillStyle.Solid; + style.HorizontalAlignment = ExcelHorizontalAlignment.Center;//水平居中 + style.VerticalAlignment = ExcelVerticalAlignment.Center;//垂直剧中 + style.Font.Bold = true;//字体为粗体 + //style + style.Fill.BackgroundColor.SetColor(Color.FromArgb(216, 216, 216));//背景色 + style.Border.BorderAround(ExcelBorderStyle.Thin, Color.FromArgb(191, 191, 191));//边框 + + onFillCell?.Invoke(worksheet, i, j, cellValue); + j++; + } + for (int i = 0; i < rows.Count; i++) + { + var row = rows[i]; + j = 0; + foreach (var item in row) + { + object cellValue = item.Value; + worksheet.Cells[i + 2, j + 1].Value = cellValue; + + onFillCell?.Invoke(worksheet, i + 1, j, cellValue); + j++; + } + worksheet.Cells[worksheet.Dimension.Address].AutoFitColumns(); + for (var col = 1; col <= worksheet.Dimension.End.Column; col++) + { + worksheet.Column(col).Width = worksheet.Column(col).Width + 2; + } + } + saveBefore?.Invoke(worksheet); + package.SaveAs(new FileInfo(fullPath + fileName)); + } + return path + fileName; + } + + + } + + public class CellOptions + { + public string ColumnName { get; set; }//导出表的列 + public string ColumnCNName { get; set; }//导出列的中文名 + public string DropNo { get; set; }//字典编号 + public int ColumnWidth { get; set; }//导出列的宽度,代码生成维护的宽度 + public bool Requierd { get; set; } //是否必填 + public int Index { get; set; }//列所在模板的序号(导入用) + //2021.01.24修复多选类型,导出excel文件没有转换数据源的问题 + public string EditType { get; set; } + public string SearchType { get; set; } + //对应字典项维护的Key,Value + public Dictionary KeyValues { get; set; } + //public string Value { get; set; } //对应字典项维护的Value + //public string Name { get; set; } //对应字典项显示的名称 + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/FileHelper.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/FileHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..5ac20c98052d544b66ae894800d4513c25dfffeb --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/FileHelper.cs @@ -0,0 +1,339 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using VOL.Core.Extensions; + +namespace VOL.Core.Utilities +{ + public class FileHelper + { + private static object _filePathObj = new object(); + + /// + /// 通过迭代器读取平面文件行内容(必须是带有\r\n换行的文件,百万行以上的内容读取效率存在问题,适用于100M左右文件,行100W内,超出的会有卡顿) + /// + /// 文件全路径 + /// 分页页数 + /// 分页大小 + /// 是否最后一行向前读取,默认从前向后读取 + /// + public static IEnumerable ReadPageLine(string fullPath, int page, int pageSize, bool seekEnd = false) + { + if (page <= 0) + { + page = 1; + } + fullPath = fullPath.ReplacePath(); + var lines = File.ReadLines(fullPath, Encoding.UTF8); + if (seekEnd) + { + int lineCount = lines.Count(); + int linPageCount = (int)Math.Ceiling(lineCount / (pageSize * 1.00)); + //超过总页数,不处理 + if (page > linPageCount) + { + page = 0; + pageSize = 0; + } + else if (page == linPageCount)//最后一页,取最后一页剩下所有的行 + { + pageSize = lineCount - (page - 1) * pageSize; + if (page == 1) + { + page = 0; + } + else + { + page = lines.Count() - page * pageSize; + } + } + else + { + page = lines.Count() - page * pageSize; + } + } + else + { + page = (page - 1) * pageSize; + } + lines = lines.Skip(page).Take(pageSize); + + var enumerator = lines.GetEnumerator(); + int count = 1; + while (enumerator.MoveNext() || count <= pageSize) + { + yield return enumerator.Current; + count++; + } + enumerator.Dispose(); + } + public static bool FileExists(string path) + { + return File.Exists(path.ReplacePath()); + } + + public static string GetCurrentDownLoadPath() + { + return ("Download\\").MapPath(); + } + + public static bool DirectoryExists(string path) + { + return Directory.Exists(path.ReplacePath()); + } + + + public static string Read_File(string fullpath, string filename, string suffix) + { + return ReadFile((fullpath + "\\" + filename + suffix).MapPath()); + } + public static string ReadFile(string fullName) + { + // Encoding code = Encoding.GetEncoding(); //Encoding.GetEncoding("gb2312"); + string temp = fullName.MapPath().ReplacePath(); + string str = ""; + if (!File.Exists(temp)) + { + return str; + } + StreamReader sr = null; + try + { + sr = new StreamReader(temp); + str = sr.ReadToEnd(); // 读取文件 + } + catch { } + sr?.Close(); + sr?.Dispose(); + return str; + } + + + + /// + /// 取后缀名 + /// + /// 文件名 + /// .gif|.html格式 + public static string GetPostfixStr(string filename) + { + int start = filename.LastIndexOf("."); + int length = filename.Length; + string postfix = filename.Substring(start, length - start); + return postfix; + } + + + /// + /// + /// + /// 路径 + /// 文件名 + /// 写入的内容 + /// 是否将内容添加到未尾,默认不添加 + public static void WriteFile(string path, string fileName, string content, bool appendToLast = false) + { + path = path.ReplacePath(); + fileName = fileName.ReplacePath(); + if (!Directory.Exists(path))//如果不存在就创建file文件夹 + Directory.CreateDirectory(path); + + using (FileStream stream = File.Open(path + fileName, FileMode.OpenOrCreate, FileAccess.Write)) + { + byte[] by = Encoding.Default.GetBytes(content); + if (appendToLast) + { + stream.Position = stream.Length; + } + else + { + stream.SetLength(0); + } + stream.Write(by, 0, by.Length); + } + } + + + + /// + /// 追加文件 + /// + /// 文件路径 + /// 内容 + public static void FileAdd(string Path, string strings) + { + StreamWriter sw = File.AppendText(Path.ReplacePath()); + sw.Write(strings); + sw.Flush(); + sw.Close(); + sw.Dispose(); + } + + + /// + /// 拷贝文件 + /// + /// 原始文件 + /// 新文件路径 + public static void FileCoppy(string OrignFile, string NewFile) + { + File.Copy(OrignFile.ReplacePath(), NewFile.ReplacePath(), true); + } + + + /// + /// 删除文件 + /// + /// 路径 + public static void FileDel(string Path) + { + File.Delete(Path.ReplacePath()); + } + + /// + /// 移动文件 + /// + /// 原始路径 + /// 新路径 + public static void FileMove(string OrignFile, string NewFile) + { + File.Move(OrignFile.ReplacePath(), NewFile.ReplacePath()); + } + + /// + /// 在当前目录下创建目录 + /// + /// 当前目录 + /// 新目录 + public static void FolderCreate(string OrignFolder, string NewFloder) + { + Directory.SetCurrentDirectory(OrignFolder.ReplacePath()); + Directory.CreateDirectory(NewFloder.ReplacePath()); + } + + /// + /// 创建文件夹 + /// + /// + public static void FolderCreate(string Path) + { + // 判断目标目录是否存在如果不存在则新建之 + if (!Directory.Exists(Path.ReplacePath())) + Directory.CreateDirectory(Path.ReplacePath()); + } + + + public static void FileCreate(string Path) + { + FileInfo CreateFile = new FileInfo(Path.ReplacePath()); //创建文件 + if (!CreateFile.Exists) + { + FileStream FS = CreateFile.Create(); + FS.Close(); + } + } + /// + /// 递归删除文件夹目录及文件 + /// + /// + /// + public static void DeleteFolder(string dir) + { + dir = dir.ReplacePath(); + if (Directory.Exists(dir)) //如果存在这个文件夹删除之 + { + foreach (string d in Directory.GetFileSystemEntries(dir)) + { + if (File.Exists(d)) + File.Delete(d); //直接删除其中的文件 + else + DeleteFolder(d); //递归删除子文件夹 + } + Directory.Delete(dir, true); //删除已空文件夹 + } + } + + + /// + /// 指定文件夹下面的所有内容copy到目标文件夹下面 + /// + /// 原始路径 + /// 目标文件夹 + public static void CopyDir(string srcPath, string aimPath) + { + try + { + aimPath = aimPath.ReplacePath(); + // 检查目标目录是否以目录分割字符结束如果不是则添加之 + if (aimPath[aimPath.Length - 1] != Path.DirectorySeparatorChar) + aimPath += Path.DirectorySeparatorChar; + // 判断目标目录是否存在如果不存在则新建之 + if (!Directory.Exists(aimPath)) + Directory.CreateDirectory(aimPath); + // 得到源目录的文件列表,该里面是包含文件以及目录路径的一个数组 + //如果你指向copy目标文件下面的文件而不包含目录请使用下面的方法 + //string[] fileList = Directory.GetFiles(srcPath); + string[] fileList = Directory.GetFileSystemEntries(srcPath.ReplacePath()); + //遍历所有的文件和目录 + foreach (string file in fileList) + { + //先当作目录处理如果存在这个目录就递归Copy该目录下面的文件 + + if (Directory.Exists(file)) + CopyDir(file, aimPath + Path.GetFileName(file)); + //否则直接Copy文件 + else + File.Copy(file, aimPath + Path.GetFileName(file), true); + } + } + catch (Exception ee) + { + throw new Exception(ee.ToString()); + } + } + + /// + /// 获取文件夹大小 + /// + /// 文件夹路径 + /// + public static long GetDirectoryLength(string dirPath) + { + dirPath = dirPath.ReplacePath(); + if (!Directory.Exists(dirPath)) + return 0; + long len = 0; + DirectoryInfo di = new DirectoryInfo(dirPath); + foreach (FileInfo fi in di.GetFiles()) + { + len += fi.Length; + } + DirectoryInfo[] dis = di.GetDirectories(); + if (dis.Length > 0) + { + for (int i = 0; i < dis.Length; i++) + { + len += GetDirectoryLength(dis[i].FullName); + } + } + return len; + } + + /// + /// 获取指定文件详细属性 + /// + /// 文件详细路径 + /// + public static string GetFileAttibe(string filePath) + { + string str = ""; + filePath = filePath.ReplacePath(); + System.IO.FileInfo objFI = new System.IO.FileInfo(filePath); + str += "详细路径:" + objFI.FullName + "
文件名称:" + objFI.Name + "
文件长度:" + objFI.Length.ToString() + "字节
创建时间" + objFI.CreationTime.ToString() + "
最后访问时间:" + objFI.LastAccessTime.ToString() + "
修改时间:" + objFI.LastWriteTime.ToString() + "
所在目录:" + objFI.DirectoryName + "
扩展名:" + objFI.Extension; + return str; + } + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/HttpContext.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/HttpContext.cs new file mode 100644 index 0000000000000000000000000000000000000000..13135e31ad04f490e5981bd8c261c9bee1859afa --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/HttpContext.cs @@ -0,0 +1,19 @@ +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.Utilities +{ + public static class HttpContext + { + private static IHttpContextAccessor _accessor; + + public static Microsoft.AspNetCore.Http.HttpContext Current => _accessor.HttpContext; + + internal static void Configure(IHttpContextAccessor accessor) + { + _accessor = accessor; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/HttpManager.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/HttpManager.cs new file mode 100644 index 0000000000000000000000000000000000000000..c54d5e3379baaae1fe791d0334882d85ca9c0c26 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/HttpManager.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Text; +using System.Threading.Tasks; + +namespace VOL.Core.Utilities +{ + public class HttpManager + { + public static Task HttpPostAsync(string url, string postData = null, string contentType = null, int timeOut = 30, Dictionary headers = null) + { + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); + request.Method = "POST"; + if (!string.IsNullOrEmpty(contentType)) + { + request.ContentType = contentType; + } + if (headers != null) + { + foreach (var header in headers) + request.Headers[header.Key] = header.Value; + } + + try + { + byte[] bytes = Encoding.UTF8.GetBytes(postData ?? ""); + using (Stream sendStream = request.GetRequestStream()) + { + sendStream.Write(bytes, 0, bytes.Length); + } + + using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) + { + Stream responseStream = response.GetResponseStream(); + StreamReader streamReader = new StreamReader(responseStream, Encoding.UTF8); + return streamReader.ReadToEndAsync(); + } + } + catch (Exception ex) + { + return Task.FromResult(ex.Message); + } + + } + public static Task HttpGetAsync(string url, Dictionary headers = null) + { + try + { + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); + if (headers != null) + { + foreach (var header in headers) + request.Headers[header.Key] = header.Value; + } + using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) + { + Stream responseStream = response.GetResponseStream(); + StreamReader streamReader = new StreamReader(responseStream, Encoding.UTF8); + return streamReader.ReadToEndAsync(); + } + } + catch (Exception ex) + { + return Task.FromResult(ex.Message); + } + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/JwtHelper.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/JwtHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..f3ece2d4733fe5e59e1da4b73bd980959b4de215 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/JwtHelper.cs @@ -0,0 +1,100 @@ +using Microsoft.IdentityModel.Tokens; +using System; +using System.Collections.Generic; +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; +using VOL.Core.Configuration; +using VOL.Core.Extensions; +using VOL.Entity.DomainModels; + +namespace VOL.Core.Utilities +{ + public class JwtHelper + { + + /// + /// 生成JWT + /// + /// + /// + public static string IssueJwt(UserInfo userInfo) + { + string exp = $"{new DateTimeOffset(DateTime.Now.AddMinutes(ManageUser.UserContext.MenuType == 1? 43200: AppSetting.ExpMinutes)).ToUnixTimeSeconds()}"; + var claims = new List + { + //new Claim(ClaimTypes.Name,userInfo.UserName ), + //new Claim(ClaimTypes.Role,userInfo.Role_Id ), + new Claim(JwtRegisteredClaimNames.Jti,userInfo.User_Id.ToString()), + new Claim(JwtRegisteredClaimNames.Iat, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"), + new Claim(JwtRegisteredClaimNames.Nbf,$"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}") , + //JWT过期时间 + //验证是否过期 从User读取过期 时间,再将时间戳转换成日期,如果时间在半个小时内即将过期,通知前台刷新JWT + //int val= HttpContext.User.Claims.Where(x => x.Type == JwtRegisteredClaimNames.Exp).FirstOrDefault().Value; + //new DateTime(621355968000000000 + (long)val* (long)10000000, DateTimeKind.Utc).ToLocalTime() + //默认设置jwt过期时间120分钟 + new Claim (JwtRegisteredClaimNames.Exp,exp), + new Claim(JwtRegisteredClaimNames.Iss,AppSetting.Secret.Issuer), + new Claim(JwtRegisteredClaimNames.Aud,AppSetting.Secret.Audience), + }; + + //秘钥16位 + var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(AppSetting.Secret.JWT)); + var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); + JwtSecurityToken securityToken = new JwtSecurityToken(issuer: AppSetting.Secret.Issuer, claims: claims, signingCredentials: creds); + string jwt = new JwtSecurityTokenHandler().WriteToken(securityToken); + return jwt; + } + + /// + /// 解析 + /// + /// + /// + public static UserInfo SerializeJwt(string jwtStr) + { + var jwtHandler = new JwtSecurityTokenHandler(); + JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(jwtStr); + UserInfo userInfo = new UserInfo + { + User_Id = Convert.ToInt32(jwtToken.Id), + Role_Id = (jwtToken.Payload[ClaimTypes.Role] ?? 0).GetInt(), + UserName = jwtToken.Payload[ClaimTypes.Name]?.ToString() + }; + return userInfo; + } + /// + /// 获取过期时间 + /// + /// + /// + public static DateTime GetExp(string jwtStr) + { + var jwtHandler = new JwtSecurityTokenHandler(); + JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(jwtStr); + + DateTime expDate = (jwtToken.Payload[JwtRegisteredClaimNames.Exp] ?? 0).GetInt().GetTimeSpmpToDate(); + return expDate; + } + public static bool IsExp(string jwtStr) + { + return GetExp(jwtStr) < DateTime.Now; + } + + public static int GetUserId(string jwtStr) + { + try + { + if (jwtStr.IsNullOrEmpty()) return 0; + jwtStr = jwtStr.Replace("Bearer ", ""); + return new JwtSecurityTokenHandler().ReadJwtToken(jwtStr).Id.GetInt(); + } + catch + { + return 0; + } + } + } + + +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/MailHelper.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/MailHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..accc91fa16747ab1739d3795615f4eb1db1a48d4 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/MailHelper.cs @@ -0,0 +1,64 @@ +using Microsoft.Extensions.Configuration; +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Mail; +using System.Text; +using VOL.Core.Configuration; +using VOL.Core.Extensions; + +namespace VOL.Core.Utilities +{ + public static class MailHelper + { + private static string address { get; set; } + private static string authPwd { get; set; } + private static string name { get; set; } + private static string host { get; set; } + private static int port; + private static bool enableSsl { get; set; } + static MailHelper() + { + IConfigurationSection section= AppSetting.GetSection("Mail"); + address = section["Address"]; + authPwd = section["AuthPwd"]; + name = section["Name"]; + host = section["Host"]; + port = section["Port"].GetInt(); + enableSsl = section["EnableSsl"].GetBool(); + } + + /// + /// 发送邮件 + /// + /// 标题 + /// 内容 + /// 收件人 + public static void Send(string title, string content, params string[] list) + { + Console.WriteLine(AppSetting.GetSection("ModifyMember")["DateUTCField"]); + MailMessage message = new MailMessage + { + From = new MailAddress(address, name)//发送人邮箱 + }; + foreach (var item in list) + { + message.To.Add(item);//收件人地址 + } + + message.Subject = title;//发送邮件的标题 + + message.Body = content;//发送邮件的内容 + //配置smtp服务地址 + SmtpClient client = new SmtpClient + { + Host = host, + Port = port,//端口587 + EnableSsl = enableSsl, + //发送人邮箱与授权密码 + Credentials = new NetworkCredential(address, authPwd) + }; + client.Send(message); + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/NPOIHelper.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/NPOIHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..33cbde4e37fa2e2826728df1c4661f9b88b775e9 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/NPOIHelper.cs @@ -0,0 +1,550 @@ +//using NPOI.HPSF; +//using NPOI.HSSF.UserModel; +//using NPOI.SS.UserModel; +//using System; +//using System.Collections.Generic; +//using System.Data; +//using System.IO; +//using System.Text; + +//namespace VOL.Core.Utilities +//{ +// public class NPOIHelper +// { +// /// +// /// DataTable 导出到 Excel 的 MemoryStream +// /// +// /// 源 DataTable +// /// 表头文本 空值未不要表头标题 +// /// +// public static MemoryStream ExportExcel(DataTable dtSource, string strHeaderText) +// { +// HSSFWorkbook workbook = new HSSFWorkbook(); +// ISheet sheet = workbook.CreateSheet(); +// #region 文件属性 +// DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation(); +// dsi.Company = "517best.com"; +// workbook.DocumentSummaryInformation = dsi; +// SummaryInformation si = PropertySetFactory.CreateSummaryInformation(); +// si.Author = "517best.com"; +// si.ApplicationName = "517best.com"; +// si.LastAuthor = "517best.com"; +// si.Comments = ""; +// si.Title = ""; +// si.Subject = ""; +// si.CreateDateTime = DateTime.Now; +// workbook.SummaryInformation = si; +// #endregion +// ICellStyle dateStyle = workbook.CreateCellStyle(); +// IDataFormat format = workbook.CreateDataFormat(); +// dateStyle.DataFormat = format.GetFormat("yyyy-mm-dd"); +// int[] arrColWidth = new int[dtSource.Columns.Count]; +// foreach (DataColumn item in dtSource.Columns) +// { +// arrColWidth[item.Ordinal] = Encoding.GetEncoding("gb2312").GetBytes(item.ColumnName.ToString()).Length; +// } +// for (int i = 0; i < dtSource.Rows.Count; i++) +// { +// for (int j = 0; j < dtSource.Columns.Count; j++) +// { +// int intTemp = Encoding.GetEncoding("gb2312").GetBytes(dtSource.Rows[i][j].ToString()).Length; +// if (intTemp > arrColWidth[j]) +// { +// arrColWidth[j] = intTemp; +// } +// } +// } +// int rowIndex = 0; +// int intTop = 0; +// foreach (DataRow row in dtSource.Rows) +// { +// #region 新建表、填充表头、填充列头,样式 +// if (rowIndex == 65535 || rowIndex == 0) +// { +// if (rowIndex != 0) +// { +// sheet = workbook.CreateSheet(); +// } +// intTop = 0; +// #region 表头及样式 +// { +// if (strHeaderText.Length > 0) +// { +// IRow headerRow = sheet.CreateRow(intTop); +// intTop += 1; +// headerRow.HeightInPoints = 25; +// headerRow.CreateCell(0).SetCellValue(strHeaderText); +// ICellStyle headStyle = workbook.CreateCellStyle(); +// headStyle.Alignment = HorizontalAlignment.Center; +// IFont font = workbook.CreateFont(); +// font.FontHeightInPoints = 20; +// font.Boldweight = 700; +// headStyle.SetFont(font); +// headerRow.GetCell(0).CellStyle = headStyle; +// sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(0, 0, 0, dtSource.Columns.Count - 1)); + +// } +// } +// #endregion +// #region 列头及样式 +// { +// IRow headerRow = sheet.CreateRow(intTop); +// intTop += 1; +// ICellStyle headStyle = workbook.CreateCellStyle(); +// headStyle.Alignment = HorizontalAlignment.Center; +// IFont font = workbook.CreateFont(); +// font.Boldweight = 700; +// headStyle.SetFont(font); +// foreach (DataColumn column in dtSource.Columns) +// { +// headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName); +// headerRow.GetCell(column.Ordinal).CellStyle = headStyle; +// //设置列宽 +// sheet.SetColumnWidth(column.Ordinal, (arrColWidth[column.Ordinal] + 1) * 256); +// } + + +// } +// #endregion +// rowIndex = intTop; +// } +// #endregion +// #region 填充内容 +// IRow dataRow = sheet.CreateRow(rowIndex); +// foreach (DataColumn column in dtSource.Columns) +// { +// ICell newCell = dataRow.CreateCell(column.Ordinal); +// string drValue = row[column].ToString(); +// switch (column.DataType.ToString()) +// { +// case "System.String"://字符串类型 +// newCell.SetCellValue(drValue); +// break; +// case "System.DateTime"://日期类型 +// DateTime dateV; +// DateTime.TryParse(drValue, out dateV); +// newCell.SetCellValue(dateV); +// newCell.CellStyle = dateStyle;//格式化显示 +// break; +// case "System.Boolean"://布尔型 +// bool boolV = false; +// bool.TryParse(drValue, out boolV); +// newCell.SetCellValue(boolV); +// break; +// case "System.Int16": +// case "System.Int32": +// case "System.Int64": +// case "System.Byte": +// int intV = 0; +// int.TryParse(drValue, out intV); +// newCell.SetCellValue(intV); +// break; +// case "System.Decimal": +// case "System.Double": +// double doubV = 0; +// double.TryParse(drValue, out doubV); +// newCell.SetCellValue(doubV); +// break; +// case "System.DBNull"://空值处理 +// newCell.SetCellValue(""); +// break; +// default: +// newCell.SetCellValue(""); +// break; +// } +// } +// #endregion +// rowIndex++; +// } +// using (MemoryStream ms = new MemoryStream()) +// { +// workbook.Write(ms); +// ms.Flush(); +// ms.Position = 0; +// return ms; +// } +// } +// /// +// /// DaataTable 导出到 Excel 文件 +// /// +// /// 源 DataaTable +// /// 表头文本 +// /// 保存位置(文件名及路径) +// public static void ExportExcel(DataTable dtSource, string strHeaderText, string strFileName) +// { +// using (MemoryStream ms = ExportExcel(dtSource, strHeaderText)) +// { +// using (FileStream fs = new FileStream(strFileName, FileMode.Create, FileAccess.Write)) +// { +// byte[] data = ms.ToArray(); +// fs.Write(data, 0, data.Length); +// fs.Flush(); +// } +// } +// } + +// /// +// /// 读取 excel +// /// 默认第一行为标头 +// /// +// /// excel 文档路径 +// /// +// public static DataTable ImportExcel(string strFileName) +// { +// DataTable dt = new DataTable(); +// HSSFWorkbook hssfworkbook; +// using (FileStream file = new FileStream(strFileName, FileMode.Open, FileAccess.Read)) +// { +// hssfworkbook = new HSSFWorkbook(file); +// } +// ISheet sheet = hssfworkbook.GetSheetAt(0); +// System.Collections.IEnumerator rows = sheet.GetRowEnumerator(); +// IRow headerRow = sheet.GetRow(0); +// int cellCount = headerRow.LastCellNum; +// for (int j = 0; j < cellCount; j++) +// { +// ICell cell = headerRow.GetCell(j); +// dt.Columns.Add(cell.ToString()); +// } +// for (int i = (sheet.FirstRowNum + 1); i <= sheet.LastRowNum; i++) +// { +// IRow row = sheet.GetRow(i); +// if (row.GetCell(row.FirstCellNum) != null && row.GetCell(row.FirstCellNum).ToString().Length > 0) +// { +// DataRow dataRow = dt.NewRow(); +// for (int j = row.FirstCellNum; j < cellCount; j++) +// { +// if (row.GetCell(j) != null) +// { + +// dataRow[j] = row.GetCell(j).ToString(); + +// } +// } +// dt.Rows.Add(dataRow); +// } +// } +// return dt; + +// } + + +// /// +// /// DataSet 导出到 Excel 的 MemoryStream +// /// +// /// 源 DataSet +// /// 表头文本 空值未不要表头标题(多个表对应多个表头以英文逗号(,)分开,个数应与表相同) +// /// +// public static MemoryStream ExportExcel(DataSet dsSource, string strHeaderText) +// { + +// HSSFWorkbook workbook = new HSSFWorkbook(); + +// #region 文件属性 +// DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation(); +// dsi.Company = "517best.com"; +// workbook.DocumentSummaryInformation = dsi; +// SummaryInformation si = PropertySetFactory.CreateSummaryInformation(); +// si.Author = "517best.com"; +// si.ApplicationName = "517best.com"; +// si.LastAuthor = "517best.com"; +// si.Comments = ""; +// si.Title = ""; +// si.Subject = ""; +// si.CreateDateTime = DateTime.Now; +// workbook.SummaryInformation = si; +// #endregion + +// #region 注释 + + +// //ICellStyle dateStyle = workbook.CreateCellStyle(); +// //IDataFormat format = workbook.CreateDataFormat(); +// //dateStyle.DataFormat = format.GetFormat("yyyy-mm-dd"); + +// //ISheet sheet = workbook.CreateSheet(); +// //int[] arrColWidth = new int[dtSource.Columns.Count]; +// //foreach (DataColumn item in dtSource.Columns) +// //{ +// // arrColWidth[item.Ordinal] = Encoding.GetEncoding("gb2312").GetBytes(item.ColumnName.ToString()).Length; +// //} +// //for (int i = 0; i < dtSource.Rows.Count; i++) +// //{ +// // for (int j = 0; j < dtSource.Columns.Count; j++) +// // { +// // int intTemp = Encoding.GetEncoding("gb2312").GetBytes(dtSource.Rows[i][j].ToString()).Length; +// // if (intTemp > arrColWidth[j]) +// // { +// // arrColWidth[j] = intTemp; +// // } +// // } +// //} +// //int rowIndex = 0; +// //int intTop = 0; +// //foreach (DataRow row in dtSource.Rows) +// //{ +// // #region 新建表、填充表头、填充列头,样式 +// // if (rowIndex == 65535 || rowIndex == 0) +// // { +// // if (rowIndex != 0) +// // { +// // sheet = workbook.CreateSheet(); +// // } +// // intTop = 0; +// // #region 表头及样式 +// // { +// // if (strHeaderText.Length > 0) +// // { +// // IRow headerRow = sheet.CreateRow(intTop); +// // intTop += 1; +// // headerRow.HeightInPoints = 25; +// // headerRow.CreateCell(0).SetCellValue(strHeaderText); +// // ICellStyle headStyle = workbook.CreateCellStyle(); +// // headStyle.Alignment = HorizontalAlignment.CENTER; +// // IFont font = workbook.CreateFont(); +// // font.FontHeightInPoints = 20; +// // font.Boldweight = 700; +// // headStyle.SetFont(font); +// // headerRow.GetCell(0).CellStyle = headStyle; +// // sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(0, 0, 0, dtSource.Columns.Count - 1)); + +// // } +// // } +// // #endregion +// // #region 列头及样式 +// // { +// // IRow headerRow = sheet.CreateRow(intTop); +// // intTop += 1; +// // ICellStyle headStyle = workbook.CreateCellStyle(); +// // headStyle.Alignment = HorizontalAlignment.CENTER; +// // IFont font = workbook.CreateFont(); +// // font.Boldweight = 700; +// // headStyle.SetFont(font); +// // foreach (DataColumn column in dtSource.Columns) +// // { +// // headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName); +// // headerRow.GetCell(column.Ordinal).CellStyle = headStyle; +// // //设置列宽 +// // sheet.SetColumnWidth(column.Ordinal, (arrColWidth[column.Ordinal] + 1) * 256); +// // } + + +// // } +// // #endregion +// // rowIndex = intTop; +// // } +// // #endregion +// // #region 填充内容 +// // IRow dataRow = sheet.CreateRow(rowIndex); +// // foreach (DataColumn column in dtSource.Columns) +// // { +// // ICell newCell = dataRow.CreateCell(column.Ordinal); +// // string drValue = row[column].ToString(); +// // switch (column.DataType.ToString()) +// // { +// // case "System.String"://字符串类型 +// // newCell.SetCellValue(drValue); +// // break; +// // case "System.DateTime"://日期类型 +// // DateTime dateV; +// // DateTime.TryParse(drValue, out dateV); +// // newCell.SetCellValue(dateV); +// // newCell.CellStyle = dateStyle;//格式化显示 +// // break; +// // case "System.Boolean"://布尔型 +// // bool boolV = false; +// // bool.TryParse(drValue, out boolV); +// // newCell.SetCellValue(boolV); +// // break; +// // case "System.Int16": +// // case "System.Int32": +// // case "System.Int64": +// // case "System.Byte": +// // int intV = 0; +// // int.TryParse(drValue, out intV); +// // newCell.SetCellValue(intV); +// // break; +// // case "System.Decimal": +// // case "System.Double": +// // double doubV = 0; +// // double.TryParse(drValue, out doubV); +// // newCell.SetCellValue(doubV); +// // break; +// // case "System.DBNull"://空值处理 +// // newCell.SetCellValue(""); +// // break; +// // default: +// // newCell.SetCellValue(""); +// // break; +// // } +// // } +// // #endregion +// // rowIndex++; +// //} +// #endregion + +// string[] strNewText = strHeaderText.Split(Convert.ToChar(",")); +// if (dsSource.Tables.Count == strNewText.Length) +// { +// for (int i = 0; i < dsSource.Tables.Count; i++) +// { +// ExportFromDSExcel(workbook, dsSource.Tables[i], strNewText[i]); +// } +// } + +// using (MemoryStream ms = new MemoryStream()) +// { +// workbook.Write(ms); +// ms.Flush(); +// ms.Position = 0; +// return ms; +// } +// } +// /// +// /// DataTable 导出到 Excel 的 MemoryStream +// /// +// /// 源 workbook +// /// 源 DataTable +// /// 表头文本 空值未不要表头标题(多个表对应多个表头以英文逗号(,)分开,个数应与表相同) +// /// +// public static void ExportFromDSExcel(HSSFWorkbook workbook, DataTable dtSource, string strHeaderText) +// { +// ICellStyle dateStyle = workbook.CreateCellStyle(); +// IDataFormat format = workbook.CreateDataFormat(); +// dateStyle.DataFormat = format.GetFormat("yyyy-MM-dd HH:mm:ss"); +// ISheet sheet = workbook.CreateSheet(strHeaderText); + +// int[] arrColWidth = new int[dtSource.Columns.Count]; +// foreach (DataColumn item in dtSource.Columns) +// { +// arrColWidth[item.Ordinal] = Encoding.GetEncoding("gb2312").GetBytes(item.ColumnName.ToString()).Length; +// } +// for (int i = 0; i < dtSource.Rows.Count; i++) +// { +// for (int j = 0; j < dtSource.Columns.Count; j++) +// { +// int intTemp = Encoding.GetEncoding("gb2312").GetBytes(dtSource.Rows[i][j].ToString()).Length; +// if (intTemp > arrColWidth[j]) +// { +// arrColWidth[j] = intTemp; +// } +// } +// } +// int rowIndex = 0; +// int intTop = 0; +// foreach (DataRow row in dtSource.Rows) +// { +// #region 新建表、填充表头、填充列头,样式 +// if (rowIndex == 65535 || rowIndex == 0) +// { +// if (rowIndex != 0) +// { +// sheet = workbook.CreateSheet(); +// } +// intTop = 0; +// #region 表头及样式 +// { +// if (strHeaderText.Length > 0) +// { +// IRow headerRow = sheet.CreateRow(intTop); +// intTop += 1; +// headerRow.HeightInPoints = 25; +// headerRow.CreateCell(0).SetCellValue(strHeaderText); +// ICellStyle headStyle = workbook.CreateCellStyle(); +// headStyle.Alignment = HorizontalAlignment.Center; +// IFont font = workbook.CreateFont(); +// font.FontHeightInPoints = 20; +// font.Boldweight = 700; +// headStyle.SetFont(font); +// headerRow.GetCell(0).CellStyle = headStyle; +// sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(0, 0, 0, dtSource.Columns.Count - 1)); + +// } +// } +// #endregion +// #region 列头及样式 +// { +// IRow headerRow = sheet.CreateRow(intTop); +// intTop += 1; +// ICellStyle headStyle = workbook.CreateCellStyle(); +// headStyle.Alignment = HorizontalAlignment.Center; +// IFont font = workbook.CreateFont(); +// font.Boldweight = 700; +// headStyle.SetFont(font); +// foreach (DataColumn column in dtSource.Columns) +// { +// headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName); +// headerRow.GetCell(column.Ordinal).CellStyle = headStyle; +// //设置列宽 +// // sheet.SetColumnWidth(column.Ordinal, (arrColWidth[column.Ordinal] + 1) * 256); // 设置设置列宽 太长会报错 修改2014 年9月22日 +// int dd = (arrColWidth[column.Ordinal] + 1) * 256; + +// if (dd > 200 * 256) +// { +// dd = 100 * 256; +// } + + +// sheet.SetColumnWidth(column.Ordinal, dd); +// } + + +// } +// #endregion +// rowIndex = intTop; +// } +// #endregion +// #region 填充内容 +// IRow dataRow = sheet.CreateRow(rowIndex); +// foreach (DataColumn column in dtSource.Columns) +// { +// ICell newCell = dataRow.CreateCell(column.Ordinal); +// string drValue = row[column].ToString(); +// switch (column.DataType.ToString()) +// { +// case "System.String"://字符串类型 +// newCell.SetCellValue(drValue); +// break; +// case "System.DateTime"://日期类型 +// if (drValue.Length > 0) +// { +// DateTime dateV; +// DateTime.TryParse(drValue, out dateV); +// newCell.SetCellValue(dateV); +// newCell.CellStyle = dateStyle;//格式化显示 +// } +// else { newCell.SetCellValue(drValue); } +// break; +// case "System.Boolean"://布尔型 +// bool boolV = false; +// bool.TryParse(drValue, out boolV); +// newCell.SetCellValue(boolV); +// break; +// case "System.Int16": +// case "System.Int32": +// case "System.Int64": +// case "System.Byte": +// int intV = 0; +// int.TryParse(drValue, out intV); +// newCell.SetCellValue(intV); +// break; +// case "System.Decimal": +// case "System.Double": +// double doubV = 0; +// double.TryParse(drValue, out doubV); +// newCell.SetCellValue(doubV); +// break; +// case "System.DBNull"://空值处理 +// newCell.SetCellValue(""); +// break; +// default: +// newCell.SetCellValue(""); +// break; +// } +// } +// #endregion +// rowIndex++; +// } +// } +// } +//} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/PDFHelper/IPDFService.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/PDFHelper/IPDFService.cs new file mode 100644 index 0000000000000000000000000000000000000000..006400fab06e663ee9b09ea16896278ee45616a7 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/PDFHelper/IPDFService.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.Utilities.PDFHelper +{ + /// + /// pdf接口 + /// + public interface IPDFService + { + /// + /// 创建PDF + /// + /// 传入html字符串 + /// + byte[] CreatePDF(string htmlContent); + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/PDFHelper/PDFService.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/PDFHelper/PDFService.cs new file mode 100644 index 0000000000000000000000000000000000000000..54bae2e41130634ce3c0c383d96745b7074c86b1 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/PDFHelper/PDFService.cs @@ -0,0 +1,62 @@ + +//using WkHtmlToPdfDotNet; +//using WkHtmlToPdfDotNet.Contracts; + +//namespace VOL.Core.Utilities.PDFHelper +//{ +// /// +// /// pdf实现 +// /// +// public class PDFService : IPDFService +// { +// private IConverter _converter; +// public PDFService(IConverter converter) +// { +// _converter = converter; +// } + +// /// +// /// 创建PDF +// /// +// /// 传入html字符串 +// /// +// public byte[] CreatePDF(string htmlContent) +// { +// var globalSettings = new GlobalSettings +// { +// ColorMode = ColorMode.Color, +// Orientation = Orientation.Portrait, +// PaperSize = PaperKind.A4, +// //Margins = new MarginSettings +// //{ +// // Top = 10, +// // Left = 0, +// // Right = 0, +// //}, +// DocumentTitle = "SuZong PDF Report", +// }; +// var objectSettings = new ObjectSettings +// { +// PagesCount = true, +// HtmlContent = htmlContent, +// //Page = "www.baidu.com", //USE THIS PROPERTY TO GENERATE PDF CONTENT FROM AN HTML PAGE 这里是用现有的网页生成PDF +// //WebSettings = { DefaultEncoding = "utf-8", UserStyleSheet = Path.Combine(Directory.GetCurrentDirectory(), "assets", "styles.css") }, +// WebSettings = { DefaultEncoding = "utf-8" }, +// //HeaderSettings = { FontName = "Arial", FontSize = 9, Right = "Page [page] of [toPage]", Line = true }, +// //FooterSettings = { FontName = "Arial", FontSize = 9, Line = true, Center = "Report Footer" } +// //允许本地文件访问 +// LoadSettings = new LoadSettings { BlockLocalFileAccess = false } +// }; +// var pdf = new HtmlToPdfDocument() +// { +// GlobalSettings = globalSettings, +// Objects = { objectSettings } +// }; + +// var file = _converter.Convert(pdf); +// //return File(file, "application/pdf"); +// return file; +// } + +// } +//} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/Response/ApiResponseContent.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/Response/ApiResponseContent.cs new file mode 100644 index 0000000000000000000000000000000000000000..909154764af16b8f2f97be39e7caa5bf3db048d1 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/Response/ApiResponseContent.cs @@ -0,0 +1,63 @@ +using Newtonsoft.Json; +using VOL.Core.Enums; +using VOL.Core.Extensions; + +namespace VOL.Core.Utilities +{ + public class ApiResponseContent + { + public ApiResponseContent() + { + } + public ApiResponseContent(int status) + { + this.Status = status; + } + [JsonProperty(PropertyName = "message")] + /// + /// 返回消息 + /// + public string Message { get; set; } + [JsonProperty(PropertyName = "status")] + /// + /// 返回状态 + /// + public int Status { get; set; } + [JsonProperty(PropertyName = "data")] + /// + /// 所有返回的业务数据 + /// + public object Data { get; set; } + + public ApiResponseContent OK(string msg = null) + { + return this.Set(ResponseType.OperSuccess, msg, ApiStatutsCode.Ok); + } + + public ApiResponseContent Set(ResponseType responseType, ApiStatutsCode? status = null) + { + return this.Set(responseType, null, status); + } + /// + /// + /// + /// + /// 返回消息类型 + /// 返回消息,若msg为null,则取responseType的描述信息 + /// 返回状态,目前只有0、失败,1、成功,2、token过期 + public ApiResponseContent Set(ResponseType responseType, string msg, ApiStatutsCode? status = null) + { + if (status != null) + this.Status = (int)status; + if (!string.IsNullOrEmpty(msg)) + { + this.Message = msg; + return this; + } + if (!string.IsNullOrEmpty(this.Message)) + return this; + this.Message = responseType.GetMsg(); + return this; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/Response/FilterResponse.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/Response/FilterResponse.cs new file mode 100644 index 0000000000000000000000000000000000000000..fca90f5d270871cca1fb7e7d6b151c7016f630e1 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/Response/FilterResponse.cs @@ -0,0 +1,56 @@ +using VOL.Core.Enums; +using VOL.Core.Extensions; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using Newtonsoft.Json; +using System.Net; +using System.Text; +using VOL.Core.Const; + +namespace VOL.Core.Utilities +{ + public static class FilterResponse + { + public static void GetContentResult(FilterContext context, IActionResult actionResult) + { + GetContentResult(context, actionResult, null); + } + + public static void SetActionResult(ActionExecutingContext context, WebResponseContent responseData) + { + context.Result = new ContentResult() + { + Content = new { status = false, message = responseData.Message }.Serialize(), + ContentType = ApplicationContentType.JSON, + StatusCode = (int)HttpStatusCode.Unauthorized + }; + } + + public static void GetContentResult(FilterContext context, IActionResult actionResult, WebResponseContent responseData) + { + responseData = responseData ?? new WebResponseContent(); + responseData.Set(ResponseType.ServerError); + + if (context.HttpContext.IsAjaxRequest()) + { + actionResult = new ContentResult() + { + Content = JsonConvert.SerializeObject(responseData), + ContentType = ApplicationContentType.JSON, + StatusCode = (int)HttpStatusCode.InternalServerError + }; + } + else + { + string desc = Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(responseData.Message)); + actionResult = new ContentResult() + { + Content = $@"{desc}", + ContentType = "text/html", + StatusCode = (int)HttpStatusCode.InternalServerError + }; + } + //writelog + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/Response/WebResponseContent.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/Response/WebResponseContent.cs new file mode 100644 index 0000000000000000000000000000000000000000..aeb704828931c7993397a0d55551f5c4fa954680 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/Response/WebResponseContent.cs @@ -0,0 +1,83 @@ +using VOL.Core.Enums; +using VOL.Core.Extensions; + +namespace VOL.Core.Utilities +{ + public class WebResponseContent + { + public WebResponseContent() + { + } + public WebResponseContent(bool status) + { + this.Status = status; + } + public bool Status { get; set; } + public string Code { get; set; } + public string Message { get; set; } + //public string Message { get; set; } + public object Data { get; set; } + + public WebResponseContent OK() + { + this.Status = true; + return this; + } + + public static WebResponseContent Instance + { + get { return new WebResponseContent(); } + } + public WebResponseContent OK(string message = null,object data=null) + { + this.Status = true; + this.Message = message; + this.Data = data; + return this; + } + public WebResponseContent OK(ResponseType responseType) + { + return Set(responseType, true); + } + public WebResponseContent Error(string message = null) + { + this.Status = false; + this.Message = message; + return this; + } + public WebResponseContent Error(ResponseType responseType) + { + return Set(responseType, false); + } + public WebResponseContent Set(ResponseType responseType) + { + bool? b = null; + return this.Set(responseType, b); + } + public WebResponseContent Set(ResponseType responseType, bool? status) + { + return this.Set(responseType, null, status); + } + public WebResponseContent Set(ResponseType responseType, string msg) + { + bool? b = null; + return this.Set(responseType, msg, b); + } + public WebResponseContent Set(ResponseType responseType, string msg, bool? status) + { + if (status != null) + { + this.Status = (bool)status; + } + this.Code = ((int)responseType).ToString(); + if (!string.IsNullOrEmpty(msg)) + { + Message = msg; + return this; + } + Message = responseType.GetMsg(); + return this; + } + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/SecurityEncDecrypt.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/SecurityEncDecrypt.cs new file mode 100644 index 0000000000000000000000000000000000000000..4750d426a8afc6b267e5d2dc86252233222d2147 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/SecurityEncDecrypt.cs @@ -0,0 +1,73 @@ +using Microsoft.Extensions.Logging; +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; +using VOL.Core.Services; + +namespace VOL.Core.Utilities +{ + public class SecurityEncDecrypt + { + #region + private static byte[] Keys = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; + /// + /// DES加密字符串 + /// + /// 待加密的字符串 + /// 加密密钥,要求为16位 + /// 加密成功返回加密后的字符串,失败返回源串 + + public static string EncryptDES(string encryptString, string encryptKey) + { + try + { + byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 16)); + byte[] rgbIV = Keys; + byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString); + var DCSP = Aes.Create(); + MemoryStream mStream = new MemoryStream(); + CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write); + cStream.Write(inputByteArray, 0, inputByteArray.Length); + cStream.FlushFinalBlock(); + return Convert.ToBase64String(mStream.ToArray()); + } + catch (Exception ex) + { + throw new Exception("数据库密码加密异常" + ex.Message); + } + + } + + /// + /// DES解密字符串 + /// + /// 待解密的字符串 + /// 解密密钥,要求为16位,和加密密钥相同 + /// 解密成功返回解密后的字符串,失败返源串 + + public static string DecryptDES(string decryptString, string decryptKey) + { + try + { + byte[] rgbKey = Encoding.UTF8.GetBytes(decryptKey.Substring(0, 16)); + byte[] rgbIV = Keys; + byte[] inputByteArray = Convert.FromBase64String(decryptString); + var DCSP = Aes.Create(); + MemoryStream mStream = new MemoryStream(); + CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write); + Byte[] inputByteArrays = new byte[inputByteArray.Length]; + cStream.Write(inputByteArray, 0, inputByteArray.Length); + cStream.FlushFinalBlock(); + return Encoding.UTF8.GetString(mStream.ToArray()); + } + catch (Exception ex) + { + Logger.Error("解密异常:str:" + decryptString + ",Key:" + decryptKey+"---"+ ex.Message); + return null; + } + + } + #endregion + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/VierificationCode.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/VierificationCode.cs new file mode 100644 index 0000000000000000000000000000000000000000..c297d3b6df4d28d5e5b47c121771c2b75a520a13 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/VierificationCode.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace VOL.Core.Utilities +{ + public static class VierificationCode + { + private static readonly string[] _chars = new string[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "P", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" }; + public static string RandomText() + { + string code = "";//产生的随机数 + int temp = -1; + Random rand = new Random(); + for (int i = 1; i < 5; i++) + { + if (temp != -1) + { + rand = new Random(i * temp * unchecked((int)DateTime.Now.Ticks)); + } + int t = rand.Next(61); + if (temp != -1 && temp == t) + { + return RandomText(); + } + temp = t; + code += _chars[t]; + } + return code; + } + public static string CreateBase64Imgage(string code) + { + return VierificationCodeServices.CreateBase64Image(code); + //Random random = new Random(); + ////验证码颜色集合 + //Color[] c = { Color.Black, Color.Red, Color.DarkBlue, Color.Green, Color.Orange, Color.Brown, Color.DarkCyan, Color.Purple }; + ////验证码字体集合 + //string[] fonts = { "Verdana", "Microsoft Sans Serif", "Comic Sans MS", "Arial", "宋体" }; + + //using var img = new Bitmap((int)code.Length * 18, 32); + //using var g = Graphics.FromImage(img); + //g.Clear(Color.White);//背景设为白色 + + ////在随机位置画背景点 + //for (int i = 0; i < 100; i++) + //{ + // int x = random.Next(img.Width); + // int y = random.Next(img.Height); + // g.DrawRectangle(new Pen(Color.LightGray, 0), x, y, 1, 1); + //} + ////验证码绘制在g中 + //for (int i = 0; i < code.Length; i++) + //{ + // int cindex = random.Next(7);//随机颜色索引值 + // int findex = random.Next(5);//随机字体索引值 + // Font f = new Font(fonts[findex], 15, FontStyle.Bold);//字体 + // Brush b = new SolidBrush(c[cindex]);//颜色 + // int ii = 4; + // if ((i + 1) % 2 == 0)//控制验证码不在同一高度 + // { + // ii = 2; + // } + // g.DrawString(code.Substring(i, 1), f, b, 3 + (i * 12), ii);//绘制一个验证字符 + //} + //using (MemoryStream stream = new MemoryStream()) + //{ + // img.Save(stream, ImageFormat.Jpeg); + // byte[] b = stream.ToArray(); + // return Convert.ToBase64String(stream.ToArray()); + //} + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/VierificationCodeServices.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/VierificationCodeServices.cs new file mode 100644 index 0000000000000000000000000000000000000000..3d23d2c4f42874d94b9969b43222c5105902ce57 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/VierificationCodeServices.cs @@ -0,0 +1,114 @@ +using SkiaSharp; +using System; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; + +namespace VOL.Core.Utilities +{ + public static class VierificationCodeServices + { //验证码字体集合 + private static readonly string[] fonts = null; + + static VierificationCodeServices() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + fonts = new string[] { "Verdana", "Microsoft Sans Serif", "Comic Sans MS", "Arial", "宋体" }; + } + else + { + fonts = new string[] { "Arial", "Arial", "宋体", "宋体" }; + } + } + + private static readonly SKColor[] colors = { SKColors.Black, SKColors.Green, SKColors.Brown }; + + /// + /// + /// + /// + /// + public static string CreateBase64Image(string code) + { + var random = new Random(); + var info = new SKImageInfo((int)code.Length * 18, 32); + using var bitmap = new SKBitmap(info); + using var canvas = new SKCanvas(bitmap); + + canvas.Clear(SKColors.White); + + using var pen = new SKPaint(); + pen.FakeBoldText = true; + pen.Style = SKPaintStyle.Fill; + pen.TextSize = 20;// 0.6f * info.Width * pen.TextSize / pen.MeasureText(code); + + //绘制随机字符 + for (int i = 0; i < code.Length; i++) + { + pen.Color = random.GetRandom(colors);//随机颜色索引值 + + pen.Typeface = SKTypeface.FromFamilyName(random.GetRandom(fonts), 700, 20, SKFontStyleSlant.Italic);//配置字体 + var point = new SKPoint() + { + X = i * 16, + Y = 22// info.Height - ((i + 1) % 2 == 0 ? 2 : 4), + + }; + canvas.DrawText(code.Substring(i, 1), point, pen);//绘制一个验证字符 + + } + + // 绘制噪点 + var points = Enumerable.Range(0, 100).Select( + _ => new SKPoint(random.Next(bitmap.Width), random.Next(bitmap.Height)) + ).ToArray(); + canvas.DrawPoints( + SKPointMode.Points, + points, + pen); + + //绘制贝塞尔线条 + for (int i = 0; i < 2; i++) + { + var p1 = new SKPoint(0, 0); + var p2 = new SKPoint(0, 0); + var p3 = new SKPoint(0, 0); + var p4 = new SKPoint(0, 0); + + var touchPoints = new SKPoint[] { p1, p2, p3, p4 }; + + using var bPen = new SKPaint(); + bPen.Color = random.GetRandom(colors); + bPen.Style = SKPaintStyle.Stroke; + + using var path = new SKPath(); + path.MoveTo(touchPoints[0]); + path.CubicTo(touchPoints[1], touchPoints[2], touchPoints[3]); + canvas.DrawPath(path, bPen); + } + return bitmap.ToBase64String(SKEncodedImageFormat.Png); + } + + public static T GetRandom(this Random random, T[] tArray) + { + if (random == null) random = new Random(); + return tArray[random.Next(tArray.Length)]; + } + + /// + /// SKBitmap转Base64String + /// + /// + /// + /// + public static string ToBase64String(this SKBitmap bitmap, SKEncodedImageFormat format) + { + using var memStream = new MemoryStream(); + using var wstream = new SKManagedWStream(memStream); + bitmap.Encode(wstream, format, 32); + memStream.TryGetBuffer(out ArraySegment buffer); + return $"{Convert.ToBase64String(buffer.Array, 0, (int)memStream.Length)}"; + } + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/XmlHelper.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/XmlHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..c143d31ec330c0f549e026347166fdfc1164d7d2 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/Utilities/XmlHelper.cs @@ -0,0 +1,717 @@ +using System; +using System.Linq; +using System.Xml.Linq; +using System.Xml; +using System.Data; +using System.Configuration; + +/// 这个是用VS2010写的,如果用VS2005,请去掉System.Linq和System.Xml.Linq的引用 +/// 可以将此文件直接编译成dll,今后程序只需要引用该dll后开头添加using XmlLibrary;即可。 +namespace Rattan.Basic.Utility +{ + /// + /// XMLHelper参数 + /// + public class XmlParameter + { + private string _name; + private string _innerText; + private string _namespaceOfPrefix; + private AttributeParameter[] _attributes; + + public XmlParameter() { } + public XmlParameter(string name, params AttributeParameter[] attParas) : this(name, null, null, attParas) { } + public XmlParameter(string name, string innerText, params AttributeParameter[] attParas) : this(name, innerText, null, attParas) { } + public XmlParameter(string name, string innerText, string namespaceOfPrefix, params AttributeParameter[] attParas) + { + this._name = name; + this._innerText = innerText; + this._namespaceOfPrefix = namespaceOfPrefix; + this._attributes = attParas; + } + /// + /// 节点名称 + /// + public string Name + { + get { return this._name; } + set { this._name = value; } + } + /// + /// 节点文本 + /// + public string InnerText + { + get { return this._innerText; } + set { this._innerText = value; } + } + /// + /// 节点前缀xmlns声明(命名空间URI) + /// + public string NamespaceOfPrefix + { + get { return this._namespaceOfPrefix; } + set { this._namespaceOfPrefix = value; } + } + /// + /// 节点属性集 + /// + public AttributeParameter[] Attributes + { + get { return this._attributes; } + set { this._attributes = value; } + } + } + + /// + /// 节点属性参数 + /// + public class AttributeParameter + { + private string _name; + private string _value; + + public AttributeParameter() { } + public AttributeParameter(string attributeName, string attributeValue) + { + this._name = attributeName; + this._value = attributeValue; + } + /// + /// 属性名称 + /// + public string Name + { + get { return this._name; } + set { this._name = value; } + } + /// + /// 属性值 + /// + public string Value + { + get { return this._value; } + set { this._value = value; } + } + } + + public class XMLHelper + { + private static string _xPath; + /// + /// xml文件路径 + /// + public static string XmlPath + { + get { return _xPath; } + set { _xPath = value; } + } + private static string _configName = "XmlPath"; + /// + /// 配置文件节点名称,请设置在AppSettings节点下 + /// + public static string ConfigName + { + get { return _configName; } + set { _configName = value; GetConfig(); } + } + /// + /// 从配置文件读取xml路径 + /// + static void GetConfig() + { + //if (string.IsNullOrEmpty(_xPath)) + //{ + // try + // { + // _xPath = ConfigurationManager.AppSettings[_configName]; + // } + // catch { } + //} + } + static XMLHelper() { GetConfig(); } + + #region private AppendChild + /// + /// 添加一个子节点 + /// + /// XmlDocument对象 + /// 父节点 + /// Xml参数 + private static void AppendChild(XmlDocument xDoc, XmlNode parentNode, params XmlParameter[] xlParameter) + { + foreach (XmlParameter xpar in xlParameter) + { + XmlNode newNode = xDoc.CreateNode(XmlNodeType.Element, xpar.Name, null); + string ns = string.IsNullOrEmpty(xpar.NamespaceOfPrefix) ? "" : newNode.GetNamespaceOfPrefix(xpar.NamespaceOfPrefix); + foreach (AttributeParameter attp in xpar.Attributes) + { + XmlNode attr = xDoc.CreateNode(XmlNodeType.Attribute, attp.Name, ns == "" ? null : ns); + attr.Value = attp.Value; + newNode.Attributes.SetNamedItem(attr); + } + newNode.InnerText = xpar.InnerText; + parentNode.AppendChild(newNode); + } + } + #endregion + + #region private AddEveryNode + private static void AddEveryNode(XmlDocument xDoc, XmlNode parentNode, params XmlParameter[] paras) + { + XmlNodeList nlst = xDoc.DocumentElement.ChildNodes; + foreach (XmlNode xns in nlst) + { + if (xns.Name == parentNode.Name) + { + AppendChild(xDoc, xns, paras); + } + else + { + foreach (XmlNode xn in xns) + { + if (xn.Name == parentNode.Name) + { + AppendChild(xDoc, xn, paras); + } + } + } + } + } + #endregion + + #region private GetXmlDom + /// + /// 获得一个XmlDocument对象 + /// + /// + private static XmlDocument GetXmlDom() + { + XmlDocument xdoc = new XmlDocument(); + xdoc.Load(_xPath); + return xdoc; + } + #endregion + + #region CreateXmlFile + /// + /// 创建一个XML文档,成功创建后操作路径将直接指向该文件 + /// + /// 文件物理路径名 + /// 根结点名称 + /// 元素节点名称 + /// XML参数 + public static void CreateXmlFile(string fileName, string rootNode, string elementName, params XmlParameter[] xmlParameter) + { + XmlDocument xDoc = new XmlDocument(); + XmlNode xn = xDoc.CreateXmlDeclaration("1.0", "UTF-8", null); + xDoc.AppendChild(xn); + XmlNode root = xDoc.CreateElement(rootNode); + xDoc.AppendChild(root); + XmlNode ln = xDoc.CreateNode(XmlNodeType.Element, elementName, null); + AppendChild(xDoc, ln, xmlParameter); + root.AppendChild(ln); + try + { + xDoc.Save(fileName); + _xPath = fileName; + } + catch + { + throw; + } + } + /// + /// 创建一个XML文档,成功创建后操作路径将直接指向该文件 + /// + /// 文件物理路径名 + /// xml字符串 + public static void CreateXmlFile(string fileName, string xmlString) + { + XmlDocument xDoc = new XmlDocument(); + try + { + xDoc.LoadXml(xmlString); + xDoc.Save(fileName); + _xPath = fileName; + } + catch { throw; } + } + #endregion + + #region AddNewNode + /// + /// 添加新节点 + /// + /// 新节点的父节点对象 + /// Xml参数对象 + public static void AddNewNode(XmlNode parentNode, params XmlParameter[] xmlParameter) + { + XmlDocument xDoc = GetXmlDom(); + if (parentNode.Name == xDoc.DocumentElement.Name) + { + XmlNode newNode = xDoc.CreateNode(XmlNodeType.Element, xDoc.DocumentElement.ChildNodes[0].Name, null); + AppendChild(xDoc, newNode, xmlParameter); + xDoc.DocumentElement.AppendChild(newNode); + } + else + { + AddEveryNode(xDoc, parentNode, xmlParameter); + } + xDoc.Save(_xPath); + } + /// + /// 添加新节点 + /// + /// XmlDocument对象 + /// 新节点的父节点名称 + /// XML参数对象 + public static void AddNewNode(string parentName, params XmlParameter[] xmlParameter) + { + XmlDocument xDoc = GetXmlDom(); + XmlNode parentNode = GetNode(xDoc, parentName); + if (parentNode == null) return; + if (parentNode.Name == xDoc.DocumentElement.Name) + { + XmlNode newNode = xDoc.CreateNode(XmlNodeType.Element, xDoc.DocumentElement.ChildNodes[0].Name, null); + AppendChild(xDoc, newNode, xmlParameter); + xDoc.DocumentElement.AppendChild(newNode); + } + else + { + AddEveryNode(xDoc, parentNode, xmlParameter); + } + xDoc.Save(_xPath); + } + #endregion + + #region AddAttribute + /// + /// 添加节点属性 + /// + /// 节点对象 + /// 该节点的命名空间URI + /// 新属性名称 + /// 属性值 + public static void AddAttribute(XmlNode node, string namespaceOfPrefix, string attributeName, string attributeValue) + { + XmlDocument xDoc = GetXmlDom(); + string ns = string.IsNullOrEmpty(namespaceOfPrefix) ? "" : node.GetNamespaceOfPrefix(namespaceOfPrefix); + XmlNode xn = xDoc.CreateNode(XmlNodeType.Attribute, attributeName, ns == "" ? null : ns); + xn.Value = attributeValue; + node.Attributes.SetNamedItem(xn); + xDoc.Save(_xPath); + } + /// + /// 添加节点属性 + /// + /// 节点对象 + /// 该节点的命名空间URI + /// 节点属性参数 + public static void AddAttribute(XmlNode node, string namespaceOfPrefix, params AttributeParameter[] attributeParameters) + { + XmlDocument xDoc = GetXmlDom(); + string ns = string.IsNullOrEmpty(namespaceOfPrefix) ? "" : node.GetNamespaceOfPrefix(namespaceOfPrefix); + foreach (AttributeParameter attp in attributeParameters) + { + XmlNode xn = xDoc.CreateNode(XmlNodeType.Attribute, attp.Name, ns == "" ? null : ns); + xn.Value = attp.Value; + node.Attributes.SetNamedItem(xn); + } + xDoc.Save(_xPath); + } + /// + /// 添加节点属性 + /// + /// 节点名称 + /// 该节点的命名空间URI + /// 新属性名称 + /// 属性值 + public static void AddAttribute(string nodeName, string namespaceOfPrefix, string attributeName, string attributeValue) + { + XmlDocument xDoc = GetXmlDom(); + XmlNodeList xlst = xDoc.DocumentElement.ChildNodes; + for (int i = 0; i < xlst.Count; i++) + { + XmlNode node = GetNode(xlst[i], nodeName); + if (node == null) break; + AddAttribute(node, namespaceOfPrefix, attributeName, attributeValue); + } + xDoc.Save(_xPath); + } + /// + /// 添加节点属性 + /// + /// 节点名称 + /// 该节点的命名空间URI + /// 节点属性参数 + public static void AddAttribute(string nodeName, string namespaceOfPrefix, params AttributeParameter[] attributeParameters) + { + XmlDocument xDoc = GetXmlDom(); + XmlNodeList xlst = xDoc.DocumentElement.ChildNodes; + for (int i = 0; i < xlst.Count; i++) + { + XmlNode node = GetNode(xlst[i], nodeName); + if (node == null) break; + AddAttribute(node, namespaceOfPrefix, attributeParameters); + } + xDoc.Save(_xPath); + } + #endregion + + #region GetNode + /// + /// 获取指定节点名称的节点对象 + /// + /// 节点名称 + /// + public static XmlNode GetNode(string nodeName) + { + XmlDocument xDoc = GetXmlDom(); + if (xDoc.DocumentElement.Name == nodeName) return (XmlNode)xDoc.DocumentElement; + XmlNodeList nlst = xDoc.DocumentElement.ChildNodes; + foreach (XmlNode xns in nlst) // 遍历所有子节点 + { + if (xns.Name == nodeName) return xns; + else + { + XmlNode xn = GetNode(xns, nodeName); + if (xn != null) return xn; /// V1.0.0.3添加节点判断 + } + } + return null; + } + /// + /// 获取指定节点名称的节点对象 + /// + /// 节点对象 + /// 节点名称 + /// + public static XmlNode GetNode(XmlNode node, string nodeName) + { + foreach (XmlNode xn in node) + { + if (xn.Name == nodeName) return xn; + else + { + XmlNode tmp = GetNode(xn, nodeName); + if (tmp != null) return tmp; + } + } + return null; + } + /// + /// 获取指定节点名称的节点对象 + /// + /// 节点索引 + /// 节点名称 + public static XmlNode GetNode(int index, string nodeName) + { + XmlDocument xDoc = GetXmlDom(); + XmlNodeList nlst = xDoc.DocumentElement.ChildNodes; + if (nlst.Count <= index) return null; + if (nlst[index].Name == nodeName) return (XmlNode)nlst[index]; + foreach (XmlNode xn in nlst[index]) + { + return GetNode(xn, nodeName); + } + return null; + } + /// + /// 获取指定节点名称的节点对象 + /// + /// 节点对象 + /// 节点名称 + /// 节点内容 + public static XmlNode GetNode(XmlNode node, string nodeName, string innerText) + { + foreach (XmlNode xn in node) + { + if (xn.Name == nodeName && xn.InnerText == innerText) return xn; + else + { + XmlNode tmp = GetNode(xn, nodeName, innerText); + if (tmp != null) return tmp; + } + } + return null; + } + /// + /// 获取指定节点名称的节点对象 + /// + /// 节点名称 + /// 节点内容 + public static XmlNode GetNode(string nodeName, string innerText) + { + XmlDocument xDoc = GetXmlDom(); + XmlNodeList nlst = xDoc.DocumentElement.ChildNodes; + foreach (XmlNode xns in nlst) // 遍历所有子节点 + { + if (xns.Name == nodeName && xns.InnerText == innerText) return xns; + XmlNode tmp = GetNode(xns, nodeName, innerText); + if (tmp != null) return tmp; + } + return null; + } + /// + /// 获取指定节点名称的节点对象 + /// + /// XML参数 + public static XmlNode GetNode(XmlParameter xmlParameter) + { + return GetNode(xmlParameter.Name, xmlParameter.InnerText); + } + /// + /// 获取指定节点名称的节点对象 + /// + /// 节点对象 + /// XML参数 + public static XmlNode GetNode(XmlNode node, XmlParameter xmlParameter) + { + return GetNode(node, xmlParameter.Name, node.InnerText); + } + #endregion + + #region UpdateNode + private static void UpdateNode(XmlNode node, XmlParameter xmlParameter) + { + node.InnerText = xmlParameter.InnerText; + for (int i = 0; i < xmlParameter.Attributes.Length; i++) + { + for (int j = 0; j < node.Attributes.Count; j++) + { + if (node.Attributes[j].Name == xmlParameter.Attributes[i].Name) + { + node.Attributes[j].Value = xmlParameter.Attributes[i].Value; + } + } + } + } + private static void UpdateNode(XmlNode node, string innerText, AttributeParameter[] attributeParameters) + { + node.InnerText = innerText; + for (int i = 0; i < attributeParameters.Length; i++) + { + for (int j = 0; j < node.Attributes.Count; j++) + { + if (node.Attributes[j].Name == attributeParameters[i].Name) + { + node.Attributes[j].Value = attributeParameters[i].Value; + } + } + } + } + /// + /// 修改节点的内容 + /// + /// 节点索引 + /// XML参数对象 + public static void UpdateNode(int index, XmlParameter xmlParameter) + { + XmlDocument xDoc = GetXmlDom(); + XmlNodeList nlst = xDoc.DocumentElement.ChildNodes; + if (nlst.Count <= index) return; + if (nlst[index].Name == xmlParameter.Name) + { + UpdateNode(nlst[index], xmlParameter); + } + else + { + foreach (XmlNode xn in nlst[index]) + { + XmlNode xnd = GetNode(xn, xmlParameter.Name); + if (xnd != null) + { + UpdateNode(xnd, xmlParameter); + } + } + } + xDoc.Save(_xPath); + } + /// + /// 修改节点的内容 + /// + /// 节点索引 + /// 节点名称 + /// 修改后的内容 + public static void UpdateNode(int index, string nodeName, string newInnerText) + { + XmlDocument xDoc = GetXmlDom(); + XmlNodeList nlst = xDoc.DocumentElement.ChildNodes; + if (nlst.Count <= index) return; + if (nlst[index].Name == nodeName) + { + nlst[index].InnerText = newInnerText; + } + else + { + foreach (XmlNode xn in nlst[index]) + { + XmlNode xnd = GetNode(xn, nodeName); + if (xnd != null) + { + xnd.InnerText = newInnerText; + } + } + } + xDoc.Save(_xPath); + } + /// + /// 修改节点的内容 + /// + /// XmlParameter对象 + /// 修改后的内容 + /// 需要修改的属性 + public static void UpdateNode(XmlParameter xmlParameter, string innerText, params AttributeParameter[] attributeParameters) + { + XmlDocument xDoc = GetXmlDom(); + XmlNodeList nlst = xDoc.DocumentElement.ChildNodes; + foreach (XmlNode xns in nlst) // 遍历所有子节点 + { + if (xns.Name == xmlParameter.Name && xns.InnerText == xmlParameter.InnerText) + { + UpdateNode(xns, innerText, attributeParameters); + break; + } + XmlNode tmp = GetNode(xns, xmlParameter); + if (tmp != null) + { + UpdateNode(tmp, innerText, attributeParameters); + break; + } + } + xDoc.Save(_xPath); + } + #endregion + + #region DeleteNode + /// + /// 删除节点 + /// + /// 节点索引 + public static void DeleteNode(int index) + { + XmlDocument xDoc = GetXmlDom(); + XmlNodeList nlst = xDoc.DocumentElement.ChildNodes; + nlst[index].ParentNode.RemoveChild(nlst[index]); + xDoc.Save(_xPath); + } + /// + /// 删除节点 + /// + /// 需要删除的节点对象 + public static void DeleteNode(params XmlNode[] nodeList) + { + XmlDocument xDoc = GetXmlDom(); + foreach (XmlNode xnl in nodeList) + { + foreach (XmlNode xn in xDoc.DocumentElement.ChildNodes) + { + if (xnl.Equals(xn)) + { + xn.ParentNode.RemoveChild(xn); + break; + } + } + } + xDoc.Save(_xPath); + } + /// + /// 删除节点 + /// + /// XmlDocument对象 + /// 节点名称 + /// 节点内容 + public static void DeleteNode(string nodeName, string nodeText) + { + XmlDocument xDoc = GetXmlDom(); + foreach (XmlNode xn in xDoc.DocumentElement.ChildNodes) + { + if (xn.Name == nodeName) + { + if (xn.InnerText == nodeText) + { + xn.ParentNode.RemoveChild(xn); + return; + } + } + else + { + XmlNode node = GetNode(xn, nodeName); + if (node != null && node.InnerText == nodeText) + { + node.ParentNode.ParentNode.RemoveChild(node.ParentNode); + return; + } + } + } + xDoc.Save(_xPath); + } + #endregion + + #region SetAttribute + /// + /// 修改属性值 + /// + /// 元素对象 + /// 属性参数 + private static void SetAttribute(XmlElement elem, params AttributeParameter[] attps) + { + foreach (AttributeParameter attp in attps) + { + elem.SetAttribute(attp.Name, attp.Value); + } + } + /// + /// 修改属性值 + /// + /// XML参数 + /// 属性参数 + public static void SetAttribute(XmlParameter xmlParameter, params AttributeParameter[] attributeParameters) + { + XmlDocument xDoc = GetXmlDom(); + XmlNodeList nlst = xDoc.DocumentElement.ChildNodes; + foreach (XmlNode xns in nlst) // 遍历所有子节点 + { + if (xns.Name == xmlParameter.Name && xns.InnerText == xmlParameter.InnerText) + { + SetAttribute((XmlElement)xns, attributeParameters); + break; + } + XmlNode tmp = GetNode(xns, xmlParameter); + if (tmp != null) + { + SetAttribute((XmlElement)tmp, attributeParameters); + break; + } + } + xDoc.Save(_xPath); + } + /// + /// 修改属性值 + /// + /// XML参数 + /// 新属性值 + public static void SetAttribute(XmlParameter xmlParameter, string attributeName, string attributeValue) + { + XmlDocument xDoc = GetXmlDom(); + XmlNodeList nlst = xDoc.DocumentElement.ChildNodes; + foreach (XmlNode xns in nlst) // 遍历所有子节点 + { + if (xns.Name == xmlParameter.Name && xns.InnerText == xmlParameter.InnerText) + { + ((XmlElement)xns).SetAttribute(attributeName, attributeValue); + break; + } + XmlNode tmp = GetNode(xns, xmlParameter); + if (tmp != null) + { + ((XmlElement)tmp).SetAttribute(attributeName, attributeValue); + break; + } + } + xDoc.Save(_xPath); + } + #endregion + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/VOL.Core.csproj b/Pure_Vite_Net7/WebNet7/VOL.Core/VOL.Core.csproj new file mode 100644 index 0000000000000000000000000000000000000000..6d20aa4d33d8de7eeb89d54633c0acd1b8a7ecf9 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/VOL.Core.csproj @@ -0,0 +1,66 @@ + + + + + + + + + + + net7.0 + + Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/WorkFlow/AuditStatus.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/WorkFlow/AuditStatus.cs new file mode 100644 index 0000000000000000000000000000000000000000..009b50b0e1f741dbf8822a11bae94ee3324573b5 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/WorkFlow/AuditStatus.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Core.WorkFlow +{ + public enum AuditStatus + { + 审核中 = 0, + 审核通过 = 1, + 审核未通过 = 2, + 驳回 = 3 + } + + public enum AuditType + { + 用户审批 = 1, + 角色审批 = 2, + 部门审批 = 3 + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/WorkFlow/WorkFlowContainer.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/WorkFlow/WorkFlowContainer.cs new file mode 100644 index 0000000000000000000000000000000000000000..71bb3b7922a4ae9d47dde39e3755793784697d1d --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/WorkFlow/WorkFlowContainer.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using VOL.Core.Extensions; + +namespace VOL.Core.WorkFlow +{ + public class WorkFlowContainer + { + private static WorkFlowContainer _instance; + private static Dictionary _container = new Dictionary(); + + public static WorkFlowContainer Instance + { + get + { + _instance = new WorkFlowContainer(); + return _instance; + } + } + + public WorkFlowContainer Use(string name = null) + { + _container[typeof(T).Name] = name ?? typeof(T).GetEntityTableCnName(); + return _instance; + } + + public static object GetDic() + { + return _container.Select(s => new { key = s.Key, value = s.Value }).ToList(); + } + + public static bool Exists() + { + return Exists(typeof(T).GetEntityTableName()); + } + + public static bool Exists(string table) + { + return _container.ContainsKey(table); + } + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Core/WorkFlow/WorkFlowManager.cs b/Pure_Vite_Net7/WebNet7/VOL.Core/WorkFlow/WorkFlowManager.cs new file mode 100644 index 0000000000000000000000000000000000000000..18e45804f3440cc3f86708929f73b3768fd04532 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Core/WorkFlow/WorkFlowManager.cs @@ -0,0 +1,308 @@ +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using VOL.Core.DBManager; +using VOL.Core.Extensions; +using VOL.Core.ManageUser; +using VOL.Core.Utilities; +using VOL.Entity.DomainModels; + +namespace VOL.Core.WorkFlow +{ + public static class WorkFlowManager + { + public static bool Exists() + { + return WorkFlowContainer.Exists(); + } + + public static bool Exists(T entity) + { + return WorkFlowContainer.Exists() && GetAuditStatusValue(typeof(T).GetKeyProperty().GetValue(entity).ToString()) != null; + } + public static bool Exists(string table) + { + return WorkFlowContainer.Exists(table); + } + + public static int GetAuditStatus(string value) + { + return GetAuditStatusValue(value) ?? 0; + } + + public static int? GetAuditStatusValue(string value) + { + return DBServerProvider.DbContext.Set() + .Where(x => x.WorkTable == typeof(T).GetEntityTableName() && x.WorkTableKey == value) + .Select(s => s.CurrentOrderId) + .FirstOrDefault(); + } + + private static void Rewrite(T entity, Sys_WorkFlow workFlow, bool changeTableStatus) where T : class + { + var autditProperty = typeof(T).GetProperties().Where(x => x.Name.ToLower() == "auditstatus").FirstOrDefault(); + if (autditProperty == null) + { + return; + } + + string value = typeof(T).GetKeyProperty().GetValue(entity).ToString(); + + var dbContext = DBServerProvider.DbContext; + + + var workTable = dbContext.Set().Where(x => x.WorkTableKey == value && x.WorkFlow_Id == workFlow.WorkFlow_Id) + .AsNoTracking() + .Include(x => x.Sys_WorkFlowTableStep).FirstOrDefault(); + if (workTable == null || workFlow.Sys_WorkFlowStep == null) + { + Console.WriteLine($"未查到流程数据,id:{ workFlow.WorkFlow_Id}"); + return; + } + workTable.CurrentOrderId = 1; + workTable.AuditStatus = (int)AuditStatus.审核中; + workTable.Sys_WorkFlowTableStep.ForEach(item => + { + item.Enable = 0; + }); + + if (changeTableStatus) + { + dbContext.Entry(entity).State = EntityState.Detached; + autditProperty.SetValue(entity, 0); + dbContext.Entry(entity).Property(autditProperty.Name).IsModified = true; + } + + var wlowTableStep = workFlow.Sys_WorkFlowStep.OrderBy(x => x.OrderId).Select(s => new Sys_WorkFlowTableStep() + { + Sys_WorkFlowTableStep_Id = Guid.NewGuid(), + WorkFlowTable_Id = workTable.WorkFlowTable_Id, + WorkFlow_Id = s.WorkFlow_Id, + StepId = s.StepId, + StepName = s.StepName, + AuditId = s.StepType == (int)AuditType.用户审批 ? s.StepValue : null, + StepType = s.StepType, + StepValue = s.StepValue, + OrderId = s.OrderId, + Enable = 1, + CreateDate = DateTime.Now, + }).ToList(); + dbContext.Entry(workTable).State = EntityState.Detached; + dbContext.Update(workTable); + dbContext.AddRange(wlowTableStep); + dbContext.SaveChanges(); + + } + /// + /// 写入流程 + /// + /// + /// + /// 是否重新生成流程 + /// 是否修改原表的审批状态 + public static void AddProcese(T entity, bool rewrite = false, bool changeTableStatus = true) where T : class + { + string workTable = typeof(T).GetEntityTableName(); + + Sys_WorkFlow workFlow = DBServerProvider.DbContext.Set() + .Where(x => x.WorkTable == workTable) + .Include(x => x.Sys_WorkFlowStep) + .FirstOrDefault(); + + if (workFlow == null || workFlow.Sys_WorkFlowStep.Count == 0) return; + //重新生成流程 + if (rewrite) + { + Rewrite(entity, workFlow, changeTableStatus); + return; + } + + var userInfo = UserContext.Current.UserInfo; + Guid workFlowTable_Id = Guid.NewGuid(); + Sys_WorkFlowTable workFlowTable = new Sys_WorkFlowTable() + { + WorkFlowTable_Id = workFlowTable_Id, + AuditStatus = (int)AuditStatus.审核中, + CurrentOrderId = 1, + Enable = 1, + WorkFlow_Id = workFlow.WorkFlow_Id, + WorkName = workFlow.WorkName, + WorkTable = workTable, + WorkTableKey = typeof(T).GetKeyProperty().GetValue(entity).ToString(), + WorkTableName = workFlow.WorkTableName, + CreateID = userInfo.User_Id, + CreateDate = DateTime.Now, + Creator = userInfo.UserTrueName, + Sys_WorkFlowTableStep = workFlow.Sys_WorkFlowStep.OrderBy(x => x.OrderId).Select(s => new Sys_WorkFlowTableStep() + { + Sys_WorkFlowTableStep_Id = Guid.NewGuid(), + WorkFlowTable_Id = workFlowTable_Id, + WorkFlow_Id = s.WorkFlow_Id, + StepId = s.StepId, + StepName = s.StepName, + AuditId = s.StepType == (int)AuditType.用户审批 ? s.StepValue : null, + StepType = s.StepType, + StepValue = s.StepValue, + OrderId = s.OrderId, + Enable = 1, + CreateDate = DateTime.Now, + }).ToList() + }; + DBServerProvider.DbContext.Set().Add(workFlowTable); + DBServerProvider.DbContext.SaveChanges(); + } + + + /// + /// 进入流程审核 + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static WebResponseContent Audit(T entity, AuditStatus status, string remark, + PropertyInfo autditProperty, + Func workFlowExecuting, + Func, bool, WebResponseContent> workFlowExecuted, + bool init = false, + Action> initInvoke = null + ) where T : class + { + WebResponseContent webResponse = new WebResponseContent(true); + if (init) + { + if (!WorkFlowContainer.Exists()) + { + return webResponse; + } + } + var dbContext = DBServerProvider.DbContext; + var query = dbContext.Set(); + + var keyProperty = typeof(T).GetKeyProperty(); + string key = keyProperty.GetValue(entity).ToString(); + string workTable = typeof(T).GetEntityTableName(); + + Sys_WorkFlowTable workFlow = dbContext.Set() + .Where(x => x.WorkTable == workTable && x.WorkTableKey == key) + .Include(x => x.Sys_WorkFlowTableStep) + .FirstOrDefault(); + + if (init) + { + if (workFlow.Sys_WorkFlowTableStep.Count == 0) + { + return webResponse; + } + var step = workFlow.Sys_WorkFlowTableStep.Where(x => x.OrderId == 1).Select(s => new { s.StepType, s.StepValue }).FirstOrDefault(); + if (step != null) + { + initInvoke?.Invoke(entity, GetAuditUserIds(step.StepType ?? 0, step.StepValue ?? 0)); + } + + return webResponse; + } + + workFlow.AuditStatus = (int)status; + if (workFlow == null || workFlow.Sys_WorkFlowTableStep.Count == 0) + { + autditProperty.SetValue(entity, (int)status); + query.Update(entity); + dbContext.SaveChanges(); + return webResponse; + } + + var currnetStep = workFlow.Sys_WorkFlowTableStep.Where(x => x.OrderId == workFlow.CurrentOrderId).FirstOrDefault(); + if (currnetStep == null) + { + autditProperty.SetValue(entity, (int)status); + query.Update(entity); + dbContext.SaveChanges(); + return webResponse; + } + + var nextStep = workFlow.Sys_WorkFlowTableStep.Where(x => x.OrderId == workFlow.CurrentOrderId + 1).FirstOrDefault(); + + //指向下一个人审批 + if (nextStep != null && status == AuditStatus.审核通过) + { + workFlow.CurrentOrderId = nextStep.OrderId; + //原表显示审核中状态 + autditProperty.SetValue(entity, (int)AuditStatus.审核中); + workFlow.AuditStatus = (int)AuditStatus.审核中; + } + else + { + autditProperty.SetValue(entity, (int)status); + } + bool isLast = nextStep == null; + + if (workFlowExecuting != null) + { + webResponse = workFlowExecuting.Invoke(entity, status, isLast); + if (!webResponse.Status) + { + return webResponse; + } + } + + query.Update(entity); + + var user = UserContext.Current.UserInfo; + currnetStep.AuditId = user.User_Id; + currnetStep.Auditor = user.UserTrueName; + currnetStep.AuditDate = DateTime.Now; + currnetStep.AuditStatus = (int)status; + currnetStep.Remark = remark; + + + //dbContext.Entry(workFlow).Property("CurrentOrderId").IsModified = true; + //dbContext.Entry(workFlow).Property("AuditStatus").IsModified = true; + + + dbContext.Set().Update(workFlow); + + dbContext.SaveChanges(); + dbContext.Entry(workFlow).State = EntityState.Detached; + if (workFlowExecuted != null) + { + webResponse = workFlowExecuted.Invoke(entity, status, GetAuditUserIds(nextStep?.StepType ?? 0, nextStep?.StepValue ?? 0), isLast); + } + return webResponse; + } + /// + /// 获取审批人的id + /// + /// + /// + private static List GetAuditUserIds(int stepType, int nextId = 0) + { + List userIds = new List(); + if (stepType == 0 || nextId == 0) + { + return userIds; + } + if (stepType == (int)AuditType.角色审批) + { + userIds = DBServerProvider.DbContext.Set().Where(s => s.Role_Id == stepType).Take(50).Select(s => s.User_Id).ToList(); + } + //else if (nextStep.StepType == (int)AuditType.部门审批) + //{ + // //部门审批待完 + // // users = DBServerProvider.DbContext.Set().Where(s => s.Role_Id == nextStep.StepValue).Take(50).Select(s => s.User_Id).ToList(); + //} + else + { + userIds.Add(nextId); + } + return userIds; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/AttributeManager/EntityAttribute.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/AttributeManager/EntityAttribute.cs new file mode 100644 index 0000000000000000000000000000000000000000..8afd6186ca513509c69afd243c7132779920c2f4 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/AttributeManager/EntityAttribute.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VOL.Entity +{ + public class EntityAttribute : Attribute + { + /// + /// 真实表名(数据库表名,若没有填写默认实体为表名) + /// + public string TableName { get; set; } + /// + /// 表中文名 + /// + public string TableCnName { get; set; } + /// + /// 子表 + /// + public Type[] DetailTable { get; set; } + /// + /// 子表中文名 + /// + public string DetailTableCnName { get; set; } + /// + /// 数据库 + /// + public string DBServer { get; set; } + + //是否开启用户数据权限,true=用户只能操作自己(及下级角色)创建的数据,如:查询、删除、修改等操作 + public bool CurrentUserPermission { get; set; } + + public Type ApiInput { get; set; } + public Type ApiOutput { get; set; } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/AttributeManager/PermissionTableAttribute.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/AttributeManager/PermissionTableAttribute.cs new file mode 100644 index 0000000000000000000000000000000000000000..c6c1409f684762158e062d1825b4bdae2a592e15 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/AttributeManager/PermissionTableAttribute.cs @@ -0,0 +1,12 @@ +using System; + +namespace VOL.Entity.AttributeManager +{ + public class PermissionTableAttribute : Attribute + { + /// + /// 需要控制权限的表名与Sys_Menu表的表名必须一致 + /// + public string Name { get; set; } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/ApiEntity/Input/ApiSys_UserInput.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/ApiEntity/Input/ApiSys_UserInput.cs new file mode 100644 index 0000000000000000000000000000000000000000..44aee15cd64fd3a6b9f306f920974da0ad083bdd --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/ApiEntity/Input/ApiSys_UserInput.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Entity; + +namespace VOL.Entity.DomainModels +{ + public class ApiSys_UserInput + { + /// + ///用户名 + /// + [Display(Name ="用户名")] + [MaxLength(200)] + [Column(TypeName="nvarchar(200)")] + [Editable(true)] + [Required(AllowEmptyStrings=false)] + public string UserName { get; set; } + + /// + ///密码 + /// + [Display(Name ="密码")] + [MaxLength(400)] + [Column(TypeName="nvarchar(400)")] + [Required(AllowEmptyStrings=false)] + public string UserPwd { get; set; } + + /// + ///手机号 + /// + [Display(Name ="手机号")] + [MaxLength(22)] + [Column(TypeName="nvarchar(22)")] + [Required(AllowEmptyStrings=false)] + public string PhoneNo { get; set; } + + + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/ApiEntity/OutPut/ApiSys_UserOutput.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/ApiEntity/OutPut/ApiSys_UserOutput.cs new file mode 100644 index 0000000000000000000000000000000000000000..2f633788c623c6f87d1a70434261fc1b3a6a1d0d --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/ApiEntity/OutPut/ApiSys_UserOutput.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Entity; + +namespace VOL.Entity.DomainModels +{ + public class ApiSys_UserOutput + { + /// + ///用户名 + /// + [Display(Name ="用户名")] + [MaxLength(200)] + [Column(TypeName="nvarchar(200)")] + [Editable(true)] + [Required(AllowEmptyStrings=false)] + public string UserName { get; set; } + + /// + ///部门 + /// + [Display(Name ="部门")] + [MaxLength(300)] + [Column(TypeName="nvarchar(300)")] + [Editable(true)] + public string DeptName { get; set; } + + /// + ///角色 + /// + [Display(Name ="角色")] + [Column(TypeName="int")] + [Editable(true)] + [Required(AllowEmptyStrings=false)] + public int Role_Id { get; set; } + + + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Core/LoadSingleDataModel.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Core/LoadSingleDataModel.cs new file mode 100644 index 0000000000000000000000000000000000000000..7d373ae48c730d295b7f7bba5459428a26863de2 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Core/LoadSingleDataModel.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VOL.Entity.DomainModels +{ + public class PageDataOptions + { + public int Page { get; set; } + public int Rows { get; set; } + public int Total { get; set; } + public string TableName { get; set; } + public string Sort { get; set; } + /// + /// 排序方式 + /// + public string Order { get; set; } + public string Wheres { get; set; } + public bool Export { get; set; } + public object Value { get; set; } + } + public class SearchParameters + { + public string Name { get; set; } + public string Value { get; set; } + public string DisplayType { get; set; } + } + +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Core/PageGridData.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Core/PageGridData.cs new file mode 100644 index 0000000000000000000000000000000000000000..4765eb83185775c210afea55c74ebf8ea8d65812 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Core/PageGridData.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VOL.Entity.DomainModels +{ + public class PageGridData + { + public int status { get; set; } + public string msg { get; set; } + public int total { get; set; } + public List rows { get; set; } + public object summary { get; set; } + /// + /// 可以在返回前,再返回一些额外的数据,比如返回其他表的信息,前台找到查询后的方法取出来 + /// + public object extra { get; set; } + } + +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Core/SaveDataModel.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Core/SaveDataModel.cs new file mode 100644 index 0000000000000000000000000000000000000000..ab7146631dfdd216e3f9b1f3239c58d84fdb664e --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Core/SaveDataModel.cs @@ -0,0 +1,18 @@ + +using System.Collections; +using System.Collections.Generic; + +namespace VOL.Entity.DomainModels +{ + public class SaveModel + { + public Dictionary MainData { get; set; } + public List> DetailData { get; set; } + public List DelKeys { get; set; } + + /// + /// 从前台传入的其他参数(自定义扩展可以使用) + /// + public object Extra { get; set; } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Core/Sys_TableColumn.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Core/Sys_TableColumn.cs new file mode 100644 index 0000000000000000000000000000000000000000..f2ce8ec99f5d4a9e54bc69edc1b44a447d292f47 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Core/Sys_TableColumn.cs @@ -0,0 +1,245 @@ +using VOL.Entity.SystemModels; +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + + +namespace VOL.Entity.DomainModels +{ + [Table("Sys_TableColumn")] + public class Sys_TableColumn : BaseEntity + { + /// + /// + /// + [Display(Name = "")] + [Column(TypeName = "int")] + [Editable(true)] + public int Table_Id { get; set; } + + /// + /// + /// + [Key] + [Display(Name = "")] + [Column(TypeName = "int")] + [Editable(true)] + public int ColumnId { get; set; } + + /// + /// + /// + [Display(Name = "")] + [Editable(true)] + public string ColumnName { get; set; } + + /// + /// + /// + [Display(Name = "")] + [Editable(true)] + public string ColumnCnName { get; set; } + + /// + /// + /// + [Display(Name = "")] + [Editable(true)] + public string ColumnType { get; set; } + + /// + /// + /// + [Display(Name = "")] + [Editable(true)] + public string TableName { get; set; } + + /// + /// + /// + [Display(Name = "")] + [Column(TypeName = "int")] + [Editable(true)] + public int? Maxlength { get; set; } + + /// + /// + /// + [Display(Name = "")] + [Column(TypeName = "int")] + [Editable(true)] + public int? IsNull { get; set; } + + /// + /// + /// + [Display(Name = "")] + [Column(TypeName = "int")] + [Editable(true)] + public int? IsDisplay { get; set; } + + /// + /// + /// + [Display(Name = "")] + [Column(TypeName = "int")] + [Editable(true)] + public int? IsKey { get; set; } + + /// + /// + /// + [Display(Name = "")] + [Editable(true)] + public string Columnformat { get; set; } + + /// + /// + /// + [Display(Name = "")] + [Editable(true)] + public string Script { get; set; } + + /// + /// + /// + [Display(Name = "")] + [Editable(true)] + public string DropNo { get; set; } + + [Editable(true)] + public int? IsImage { get; set; } + /// + /// + /// + [Display(Name = "")] + [Column(TypeName = "int")] + [Editable(true)] + public int? Sortable { get; set; } + + /// + /// + /// + [Display(Name = "")] + [Column(TypeName = "int")] + [Editable(true)] + public int? ColumnWidth { get; set; } + + /// + /// + /// + [Display(Name = "")] + [Editable(true)] + public int? SearchRowNo { get; set; } + [Editable(true)] + [Column(TypeName = "int")] + public int? SearchColNo { get; set; } + /// + /// + /// + [Display(Name = "")] + [Editable(true)] + public string SearchType { get; set; } + + /// + /// + /// + [Display(Name = "")] + [Editable(true)] + [Column(TypeName = "int")] + public int? EditRowNo { get; set; } + + [Editable(true)] + public int? EditColNo { get; set; } + /// + /// + /// + [Display(Name = "")] + [Editable(true)] + public string EditType { get; set; } + [Editable(true)] + [Column(TypeName = "int")] + public int? ColSize { get; set; } + + /// + /// + /// + [Display(Name = "")] + [Editable(true)] + [Column(TypeName = "int")] + public int? IsReadDataset { get; set; } + /// + /// + /// + [Display(Name = "")] + [Editable(true)] + [Column(TypeName = "int")] + public int? Enable { get; set; } + + [Editable(true)] + [Column(TypeName = "int")] + public int? ApiInPut { get; set; } + [Editable(true)] + [Column(TypeName = "int")] + public int? ApiIsNull { get; set; } + [Editable(true)] + [Column(TypeName = "int")] + public int? ApiOutPut { get; set; } + /// + /// + /// + [Display(Name = "")] + [Column(TypeName = "int")] + public int? CreateID { get; set; } + + /// + /// + /// + [Display(Name = "")] + public string Creator { get; set; } + + /// + /// + /// + [Display(Name = "")] + public DateTime? CreateDate { get; set; } + + /// + /// + /// + [Display(Name = "")] + [Column(TypeName = "int")] + public int? ModifyID { get; set; } + + /// + /// + /// + [Display(Name = "")] + public string Modifier { get; set; } + + /// + /// + /// + [Display(Name = "")] + public DateTime? ModifyDate { get; set; } + + /// + /// + /// + [Display(Name = "")] + [Column(TypeName = "int")] + [Editable(true)] + public int? OrderNo { get; set; } + + /// + /// + /// + [Display(Name = "")] + [Column(TypeName = "int")] + [Editable(true)] + public int? IsColumnData { get; set; } + + + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Core/Sys_TableInfo.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Core/Sys_TableInfo.cs new file mode 100644 index 0000000000000000000000000000000000000000..e988abd42a0fd36917571fe6e003497032d01341 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Core/Sys_TableInfo.cs @@ -0,0 +1,72 @@ +using VOL.Entity.SystemModels; +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Collections.Generic; + +namespace VOL.Entity.DomainModels +{ + [Table("Sys_TableInfo")] + [EntityAttribute(DetailTable = new Type[] { typeof(Sys_TableColumn) })] + public class Sys_TableInfo : BaseEntity + { + [Key] + [Column(TypeName = "int")] + public int Table_Id { get; set; } + [Editable(true)] + [Column(TypeName = "int")] + public int? ParentId { get; set; } + + [Editable(true)] + public string TableName { get; set; } + [Editable(true)] + public string TableTrueName { get; set; } + [Editable(true)] + public string ColumnCNName { get; set; } + + + public string Namespace { get; set; } + + [Editable(true)] + public string FolderName { get; set; } + + [Editable(true)] + public string DataTableType { get; set; } + + [Editable(true)] + public string EditorType { get; set; } + [Editable(true)] + [Column(TypeName = "int")] + public int? OrderNo { get; set; } + [Editable(true)] + public string UploadField { get; set; } + [Editable(true)] + public int? UploadMaxCount { get; set; } + [Editable(true)] + public string RichText { get; set; } + [Editable(true)] + public string ExpressField { get; set; } + [Editable(true)] + public string DBServer { get; set; } + [Editable(true)] + public string SortName { get; set; } + [Editable(true)] + public string DetailCnName { get; set; } + + + [Editable(true)] + public string DetailName { get; set; } + + [Editable(true)] + [Column(TypeName = "int")] + public int? Enable { get; set; } + + + [Editable(true)] + public string CnName { get; set; } + + [ForeignKey("Table_Id")] + public List TableColumns { get; set; } + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Quartz/Sys_QuartzLog.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Quartz/Sys_QuartzLog.cs new file mode 100644 index 0000000000000000000000000000000000000000..b04c387dada815940775298aefed5e6ceed8e6c1 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Quartz/Sys_QuartzLog.cs @@ -0,0 +1,145 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果数据库字段发生变化,请在代码生器重新生成此Model + */ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Entity.SystemModels; + +namespace VOL.Entity.DomainModels +{ + [Entity(TableCnName = "执行记录",TableName = "Sys_QuartzLog")] + public partial class Sys_QuartzLog:BaseEntity + { + /// + /// + /// + [Key] + [Display(Name ="LogId")] + [Column(TypeName="uniqueidentifier")] + [Editable(true)] + [Required(AllowEmptyStrings=false)] + public Guid LogId { get; set; } + + /// + ///任务id + /// + [Display(Name ="任务id")] + [Column(TypeName="uniqueidentifier")] + [Editable(true)] + public Guid? Id { get; set; } + + /// + ///任务名称 + /// + [Display(Name ="任务名称")] + [MaxLength(500)] + [Column(TypeName="nvarchar(500)")] + [Editable(true)] + public string TaskName { get; set; } + + /// + ///耗时(秒) + /// + [Display(Name ="耗时(秒)")] + [Column(TypeName="int")] + [Editable(true)] + public int? ElapsedTime { get; set; } + + /// + ///开始时间 + /// + [Display(Name ="开始时间")] + [Column(TypeName="datetime")] + [Editable(true)] + public DateTime? StratDate { get; set; } + + /// + ///结束时间 + /// + [Display(Name ="结束时间")] + [Column(TypeName="datetime")] + [Editable(true)] + public DateTime? EndDate { get; set; } + + /// + ///是否成功 + /// + [Display(Name ="是否成功")] + [Column(TypeName="int")] + [Editable(true)] + public int? Result { get; set; } + + /// + ///返回内容 + /// + [Display(Name ="返回内容")] + [Column(TypeName="nvarchar(max)")] + [Editable(true)] + public string ResponseContent { get; set; } + + /// + ///异常信息 + /// + [Display(Name ="异常信息")] + [Column(TypeName="nvarchar(max)")] + public string ErrorMsg { get; set; } + + /// + /// + /// + [Display(Name ="CreateID")] + [Column(TypeName="int")] + [Editable(true)] + public int? CreateID { get; set; } + + /// + /// + /// + [Display(Name ="Creator")] + [MaxLength(30)] + [Column(TypeName="nvarchar(30)")] + [Editable(true)] + public string Creator { get; set; } + + /// + /// + /// + [Display(Name ="CreateDate")] + [Column(TypeName="datetime")] + [Editable(true)] + public DateTime? CreateDate { get; set; } + + /// + /// + /// + [Display(Name ="ModifyID")] + [Column(TypeName="int")] + [Editable(true)] + public int? ModifyID { get; set; } + + /// + /// + /// + [Display(Name ="Modifier")] + [MaxLength(30)] + [Column(TypeName="nvarchar(30)")] + [Editable(true)] + public string Modifier { get; set; } + + /// + /// + /// + [Display(Name ="ModifyDate")] + [Column(TypeName="datetime")] + [Editable(true)] + public DateTime? ModifyDate { get; set; } + + + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Quartz/Sys_QuartzOptions.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Quartz/Sys_QuartzOptions.cs new file mode 100644 index 0000000000000000000000000000000000000000..e07c84dded892df892200dde8f9d96e67c6c6b7d --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Quartz/Sys_QuartzOptions.cs @@ -0,0 +1,183 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果数据库字段发生变化,请在代码生器重新生成此Model + */ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Entity.SystemModels; + +namespace VOL.Entity.DomainModels +{ + [Entity(TableCnName = "定时任务",TableName = "Sys_QuartzOptions")] + public partial class Sys_QuartzOptions:BaseEntity + { + /// + /// + /// + [Key] + [Display(Name ="Id")] + [Column(TypeName="uniqueidentifier")] + [Required(AllowEmptyStrings=false)] + public Guid Id { get; set; } + + /// + ///任务名称 + /// + [Display(Name ="任务名称")] + [MaxLength(500)] + [Column(TypeName="nvarchar(500)")] + [Editable(true)] + [Required(AllowEmptyStrings=false)] + public string TaskName { get; set; } + + /// + ///任务分组 + /// + [Display(Name ="任务分组")] + [MaxLength(500)] + [Column(TypeName="nvarchar(500)")] + [Editable(true)] + [Required(AllowEmptyStrings=false)] + public string GroupName { get; set; } + + /// + ///请求方式 + /// + [Display(Name ="请求方式")] + [MaxLength(50)] + [Column(TypeName="varchar(50)")] + [Editable(true)] + public string Method { get; set; } + + /// + ///超时时间(秒) + /// + [Display(Name ="超时时间(秒)")] + [Column(TypeName="int")] + [Editable(true)] + public int? TimeOut { get; set; } + + /// + ///Corn表达式 + /// + [Display(Name ="Corn表达式")] + [MaxLength(100)] + [Column(TypeName="varchar(100)")] + [Editable(true)] + [Required(AllowEmptyStrings=false)] + public string CronExpression { get; set; } + + /// + ///Url地址 + /// + [Display(Name ="Url地址")] + [MaxLength(2000)] + [Column(TypeName="nvarchar(2000)")] + [Editable(true)] + public string ApiUrl { get; set; } + + /// + ///post参数 + /// + [Display(Name ="post参数")] + [Column(TypeName="nvarchar(max)")] + [Editable(true)] + public string PostData { get; set; } + + /// + ///AuthKey + /// + [Display(Name ="AuthKey")] + [MaxLength(200)] + [Column(TypeName="nvarchar(200)")] + [Editable(true)] + public string AuthKey { get; set; } + + /// + ///AuthValue + /// + [Display(Name ="AuthValue")] + [MaxLength(200)] + [Column(TypeName="nvarchar(200)")] + [Editable(true)] + public string AuthValue { get; set; } + + /// + ///描述 + /// + [Display(Name ="描述")] + [MaxLength(2000)] + [Column(TypeName="nvarchar(2000)")] + [Editable(true)] + public string Describe { get; set; } + + /// + ///最后执行执行 + /// + [Display(Name ="最后执行执行")] + [Column(TypeName="datetime")] + [Editable(true)] + public DateTime? LastRunTime { get; set; } + + /// + ///运行状态 + /// + [Display(Name ="运行状态")] + [Column(TypeName="int")] + [Editable(true)] + public int? Status { get; set; } + + /// + /// + /// + [Display(Name ="CreateID")] + [Column(TypeName="int")] + public int? CreateID { get; set; } + + /// + ///创建人 + /// + [Display(Name ="创建人")] + [MaxLength(30)] + [Column(TypeName="nvarchar(30)")] + [Editable(true)] + public string Creator { get; set; } + + /// + ///创建时间 + /// + [Display(Name ="创建时间")] + [Column(TypeName="datetime")] + [Editable(true)] + public DateTime? CreateDate { get; set; } + + /// + /// + /// + [Display(Name ="ModifyID")] + [Column(TypeName="int")] + public int? ModifyID { get; set; } + + /// + /// + /// + [Display(Name ="Modifier")] + [MaxLength(30)] + [Column(TypeName="nvarchar(30)")] + public string Modifier { get; set; } + + /// + ///修改时间 + /// + [Display(Name ="修改时间")] + [Column(TypeName="datetime")] + public DateTime? ModifyDate { get; set; } + + + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Quartz/partial/Sys_QuartzLog.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Quartz/partial/Sys_QuartzLog.cs new file mode 100644 index 0000000000000000000000000000000000000000..b9d9863e6a1f6319a1858447d43257964140ebc7 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Quartz/partial/Sys_QuartzLog.cs @@ -0,0 +1,21 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果数据库字段发生变化,请在代码生器重新生成此Model + */ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Entity.SystemModels; + +namespace VOL.Entity.DomainModels +{ + + public partial class Sys_QuartzLog + { + //此处配置字段(字段配置见此model的另一个partial),如果表中没有此字段请加上 [NotMapped]属性,否则会异常 + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Quartz/partial/Sys_QuartzOptions.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Quartz/partial/Sys_QuartzOptions.cs new file mode 100644 index 0000000000000000000000000000000000000000..78cc7a58697e5ac4b40cc27578b96660a8f86f9c --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/Quartz/partial/Sys_QuartzOptions.cs @@ -0,0 +1,21 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果数据库字段发生变化,请在代码生器重新生成此Model + */ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Entity.SystemModels; + +namespace VOL.Entity.DomainModels +{ + + public partial class Sys_QuartzOptions + { + //此处配置字段(字段配置见此model的另一个partial),如果表中没有此字段请加上 [NotMapped]属性,否则会异常 + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/LoginInfo.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/LoginInfo.cs new file mode 100644 index 0000000000000000000000000000000000000000..12f58f63d1cb16d2c5c19dab91f9061c7a634675 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/LoginInfo.cs @@ -0,0 +1,28 @@ +using Newtonsoft.Json; +using System.ComponentModel.DataAnnotations; + +namespace VOL.Entity.DomainModels +{ + public class LoginInfo + { + + + [Display(Name = "用户名")] + [MaxLength(50)] + [Required(ErrorMessage = "用户名不能为空")] + public string UserName { get; set; } + [MaxLength(50)] + [Display(Name = "密码")] + [Required(ErrorMessage = "密码不能为空")] + public string Password { get; set; } + [MaxLength(6)] + [Display(Name = "验证码")] + [Required(ErrorMessage = "验证码不能为空")] + public string VerificationCode { get; set; } + [Required(ErrorMessage = "参数不完整")] + /// + /// 2020.06.12增加验证码 + /// + public string UUID { get; set; } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Permissions.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Permissions.cs new file mode 100644 index 0000000000000000000000000000000000000000..18a60f5b0ef70bcca68e0ccdd202b60ceb3506a7 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Permissions.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VOL.Entity.DomainModels +{ + public class Permissions + { + public int Menu_Id { get; set; } + public int ParentId { get; set; } + public string TableName { get; set; } + public string MenuAuth { get; set; } + public string UserAuth { get; set; } + /// + /// 当前用户权限,存储的是权限的值,如:Add,Search等 + /// + public string[] UserAuthArr { get; set; } + + /// + /// 2022.03.26 + /// 菜单类型1:移动端,0:PC端 + /// + public int MenuType { get; set; } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Sys_Dictionary.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Sys_Dictionary.cs new file mode 100644 index 0000000000000000000000000000000000000000..d2b5336fbc1a5a6c5cce6493d385d30e45820a25 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Sys_Dictionary.cs @@ -0,0 +1,160 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果数据库字段发生变化,请在代码生器重新生成此Model + */ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Entity.SystemModels; + +namespace VOL.Entity.DomainModels +{ + [Table("Sys_Dictionary")] + [Entity(TableCnName = "字典数据",DetailTable = new Type[] { typeof(Sys_DictionaryList)},DetailTableCnName = "字典明细")] + public class Sys_Dictionary:BaseEntity + { + /// + ///字典ID + /// + [Key] + [Display(Name ="字典ID")] + [Column(TypeName="int")] + [Required(AllowEmptyStrings=false)] + public int Dic_ID { get; set; } + + /// + ///字典编号 + /// + [Display(Name ="字典编号")] + [MaxLength(100)] + [Column(TypeName="nvarchar(100)")] + [Editable(true)] + [Required(AllowEmptyStrings=false)] + public string DicNo { get; set; } + + /// + ///字典名称 + /// + [Display(Name ="字典名称")] + [MaxLength(100)] + [Column(TypeName="nvarchar(100)")] + [Editable(true)] + [Required(AllowEmptyStrings=false)] + public string DicName { get; set; } + + /// + ///父级ID + /// + [Display(Name ="父级ID")] + [Column(TypeName="int")] + [Editable(true)] + [Required(AllowEmptyStrings=false)] + public int ParentId { get; set; } + + /// + ///配置项 + /// + [Display(Name ="配置项")] + [MaxLength(10000)] + [Column(TypeName="nvarchar(10000)")] + [Editable(true)] + public string Config { get; set; } + + /// + ///sql语句 + /// + [Display(Name ="sql语句")] + [MaxLength(10000)] + [Column(TypeName="nvarchar(10000)")] + [Editable(true)] + public string DbSql { get; set; } + + /// + ///DBServer + /// + [Display(Name ="DBServer")] + [MaxLength(10000)] + [Column(TypeName="nvarchar(10000)")] + public string DBServer { get; set; } + + /// + ///排序号 + /// + [Display(Name ="排序号")] + [Column(TypeName="int")] + [Editable(true)] + public int? OrderNo { get; set; } + + /// + ///备注 + /// + [Display(Name ="备注")] + [MaxLength(2000)] + [Column(TypeName="nvarchar(2000)")] + [Editable(true)] + public string Remark { get; set; } + + /// + ///是否启用 + /// + [Display(Name ="是否启用")] + [Column(TypeName="tinyint")] + [Editable(true)] + [Required(AllowEmptyStrings=false)] + public byte Enable { get; set; } + + /// + /// + /// + [Display(Name ="CreateID")] + [Column(TypeName="int")] + public int? CreateID { get; set; } + + /// + ///创建人 + /// + [Display(Name ="创建人")] + [MaxLength(30)] + [Column(TypeName="nvarchar(30)")] + public string Creator { get; set; } + + /// + ///创建时间 + /// + [Display(Name ="创建时间")] + [Column(TypeName="datetime")] + [Editable(true)] + public DateTime? CreateDate { get; set; } + + /// + /// + /// + [Display(Name ="ModifyID")] + [Column(TypeName="int")] + public int? ModifyID { get; set; } + + /// + ///修改人 + /// + [Display(Name ="修改人")] + [MaxLength(30)] + [Column(TypeName="nvarchar(30)")] + public string Modifier { get; set; } + + /// + ///修改时间 + /// + [Display(Name ="修改时间")] + [Column(TypeName="datetime")] + public DateTime? ModifyDate { get; set; } + + [Display(Name ="字典明细")] + [ForeignKey("Dic_ID")] + public List Sys_DictionaryList { get; set; } + + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Sys_DictionaryList.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Sys_DictionaryList.cs new file mode 100644 index 0000000000000000000000000000000000000000..edd10546f4e54692be7dc70e76612fd57c4de27c --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Sys_DictionaryList.cs @@ -0,0 +1,125 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果数据库字段发生变化,请在代码生器重新生成此Model + */ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Entity.SystemModels; + +namespace VOL.Entity.DomainModels +{ + [Entity(TableCnName = "字典明细")] + public class Sys_DictionaryList:BaseEntity + { + /// + /// + /// + [Key] + [Display(Name ="DicList_ID")] + [Column(TypeName="int")] + [Required(AllowEmptyStrings=false)] + public int DicList_ID { get; set; } + + /// + ///数据源ID + /// + [Display(Name ="数据源ID")] + [Column(TypeName="int")] + [Editable(true)] + public int? Dic_ID { get; set; } + + /// + ///数据源Value + /// + [Display(Name ="数据源Value")] + [MaxLength(100)] + [Column(TypeName="nvarchar(100)")] + [Editable(true)] + public string DicValue { get; set; } + + /// + ///数据源Text + /// + [Display(Name ="数据源Text")] + [MaxLength(100)] + [Column(TypeName="nvarchar(100)")] + [Editable(true)] + public string DicName { get; set; } + + /// + ///排序号 + /// + [Display(Name ="排序号")] + [Column(TypeName="int")] + [Editable(true)] + public int? OrderNo { get; set; } + + /// + ///备注 + /// + [Display(Name ="备注")] + [MaxLength(2000)] + [Column(TypeName="nvarchar(2000)")] + [Editable(true)] + public string Remark { get; set; } + + /// + ///是否可用 + /// + [Display(Name ="是否可用")] + [Column(TypeName="tinyint")] + [Editable(true)] + public byte? Enable { get; set; } + + /// + /// + /// + [Display(Name ="CreateID")] + [Column(TypeName="int")] + public int? CreateID { get; set; } + + /// + ///创建人 + /// + [Display(Name ="创建人")] + [MaxLength(30)] + [Column(TypeName="nvarchar(30)")] + public string Creator { get; set; } + + /// + ///创建时间 + /// + [Display(Name ="创建时间")] + [Column(TypeName="datetime")] + public DateTime? CreateDate { get; set; } + + /// + /// + /// + [Display(Name ="ModifyID")] + [Column(TypeName="int")] + public int? ModifyID { get; set; } + + /// + ///修改人 + /// + [Display(Name ="修改人")] + [MaxLength(30)] + [Column(TypeName="nvarchar(30)")] + public string Modifier { get; set; } + + /// + ///修改时间 + /// + [Display(Name ="修改时间")] + [Column(TypeName="datetime")] + public DateTime? ModifyDate { get; set; } + + + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Sys_Log.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Sys_Log.cs new file mode 100644 index 0000000000000000000000000000000000000000..f8ce34289e5571f0d45ade416d3ec828c2fce5d0 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Sys_Log.cs @@ -0,0 +1,148 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *Date:2018-07-01 + * 此代码由框架生成,请勿随意更改 + */ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Entity; +using VOL.Entity.SystemModels; + +namespace VOL.Entity.DomainModels +{ + [Table("Sys_Log")] + [EntityAttribute(TableCnName = "系统日志")] + public class Sys_Log:BaseEntity + { + /// + /// + /// + [Key] + [Display(Name ="Id")] + [Column(TypeName="int")] + [Required(AllowEmptyStrings=false)] + public int Id { get; set; } + + /// + ///开始时间 + /// + [Display(Name ="开始时间")] + [Column(TypeName="datetime")] + public DateTime? BeginDate { get; set; } + + /// + ///请求地址 + /// + [Display(Name ="请求地址")] + [MaxLength(30000)] + [Column(TypeName="varchar(30000)")] + public string Url { get; set; } + + /// + ///日志类型 + /// + [Display(Name ="日志类型")] + [MaxLength(50)] + [Column(TypeName="varchar(50)")] + public string LogType { get; set; } + + /// + ///响应状态 + /// + [Display(Name ="响应状态")] + [Column(TypeName="int")] + public int? Success { get; set; } + + /// + ///时长(毫秒) + /// + [Display(Name ="时长(毫秒)")] + [Column(TypeName="int")] + public int? ElapsedTime { get; set; } + + /// + ///请求参数 + /// + [Display(Name ="请求参数")] + [MaxLength(10000)] + [Column(TypeName="nvarchar(10000)")] + public string RequestParameter { get; set; } + + /// + ///响应参数 + /// + [Display(Name ="响应参数")] + [MaxLength(10000)] + [Column(TypeName="nvarchar(10000)")] + public string ResponseParameter { get; set; } + + /// + ///异常信息 + /// + [Display(Name ="异常信息")] + [MaxLength(10000)] + [Column(TypeName="nvarchar(10000)")] + public string ExceptionInfo { get; set; } + + /// + ///用户IP + /// + [Display(Name ="用户IP")] + [MaxLength(100)] + [Column(TypeName="varchar(100)")] + public string UserIP { get; set; } + + /// + ///服务器IP + /// + [Display(Name ="服务器IP")] + [MaxLength(100)] + [Column(TypeName="varchar(100)")] + public string ServiceIP { get; set; } + + /// + ///浏览器类型 + /// + [Display(Name ="浏览器类型")] + [MaxLength(200)] + [Column(TypeName="nvarchar(200)")] + public string BrowserType { get; set; } + + /// + ///用户ID + /// + [Display(Name ="用户ID")] + [Column(TypeName="int")] + public int? User_Id { get; set; } + + /// + ///用户名称 + /// + [Display(Name ="用户名称")] + [MaxLength(30000)] + [Column(TypeName="varchar(30000)")] + public string UserName { get; set; } + + /// + ///角色ID + /// + [Display(Name ="角色ID")] + [Column(TypeName="int")] + public int? Role_Id { get; set; } + + /// + ///结束时间 + /// + [Display(Name ="结束时间")] + [Column(TypeName="datetime")] + public DateTime? EndDate { get; set; } + + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Sys_Menu.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Sys_Menu.cs new file mode 100644 index 0000000000000000000000000000000000000000..202183a2732ac1101193948d2915f2c78777c977 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Sys_Menu.cs @@ -0,0 +1,167 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *Date:2018-07-01 + * 此代码由框架生成,请勿随意更改 + */ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Entity.SystemModels; + +namespace VOL.Entity.DomainModels +{ + [Table("Sys_Menu")] + [EntityAttribute(TableCnName = "菜单配置")] + public class Sys_Menu:BaseEntity + { + /// + ///ID + /// + [Key] + [Display(Name ="ID")] + [DisplayFormat(DataFormatString="10,0")] + [Column(TypeName="int")] + [Editable(true)] + [Required(AllowEmptyStrings=false)] + public int Menu_Id { get; set; } + + /// + ///父级ID + /// + [Display(Name ="父级ID")] + [DisplayFormat(DataFormatString="10,0")] + [Column(TypeName="int")] + [Editable(true)] + [Required(AllowEmptyStrings=false)] + public int ParentId { get; set; } + + + /// + ///菜单名称 + /// + [Display(Name ="菜单名称")] + [MaxLength(50)] + [Column(TypeName="nvarchar(50)")] + [Editable(true)] + [Required(AllowEmptyStrings=false)] + public string MenuName { get; set; } + + /// + /// + /// + [Display(Name = "TableName")] + [MaxLength(200)] + [Column(TypeName = "nvarchar(200)")] + [Editable(true)] + public string TableName { get; set; } + + /// + /// + /// + [Display(Name ="Url")] + [MaxLength(10000)] + [Column(TypeName="nvarchar(10000)")] + [Editable(true)] + public string Url { get; set; } + + /// + ///权限 + /// + [Display(Name ="权限")] + [MaxLength(10000)] + [Column(TypeName="nvarchar(10000)")] + [Editable(true)] + public string Auth { get; set; } + + + /// + /// + /// + [Display(Name ="Description")] + [MaxLength(200)] + [Column(TypeName="nvarchar(200)")] + [Editable(true)] + public string Description { get; set; } + + + /// + ///图标 + /// + [Display(Name ="图标")] + [MaxLength(50)] + [Column(TypeName="nvarchar(50)")] + [Editable(true)] + public string Icon { get; set; } + + /// + ///排序号 + /// + [Display(Name ="排序号")] + [DisplayFormat(DataFormatString="10,0")] + [Column(TypeName="int")] + [Editable(true)] + public int? OrderNo { get; set; } + + /// + ///创建人 + /// + [Display(Name ="创建人")] + [MaxLength(50)] + [Column(TypeName="nvarchar(50)")] + [Editable(true)] + public string Creator { get; set; } + + /// + ///创建时间 + /// + [Display(Name ="创建时间")] + [Column(TypeName="datetime")] + [Editable(true)] + public DateTime? CreateDate { get; set; } + + /// + /// + /// + [Display(Name ="Modifier")] + [MaxLength(50)] + [Column(TypeName="nvarchar(50)")] + [Editable(true)] + public string Modifier { get; set; } + + /// + /// + /// + [Display(Name ="ModifyDate")] + [Column(TypeName="datetime")] + [Editable(true)] + public DateTime? ModifyDate { get; set; } + + /// + ///是否启用 + /// + [Display(Name ="是否启用")] + [Column(TypeName="tinyint")] + [Editable(true)] + public byte? Enable { get; set; } + + + /// + /// 2022.03.26 + /// 菜单类型1:移动端,0:PC端 + /// + /// + [Display(Name = "是否启用")] + [Column(TypeName = "int")] + [Editable(true)] + public int? MenuType { get; set; } + + + + public List Actions { get; set; } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Sys_Role.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Sys_Role.cs new file mode 100644 index 0000000000000000000000000000000000000000..ce55aa8a435fc7f7c1405028a5065f5bad01b1d8 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Sys_Role.cs @@ -0,0 +1,127 @@ +using Newtonsoft.Json; +/* + *Author:jxx + *Contact:283591387@qq.com + *Date:2018-07-01 + * 此代码由框架生成,请勿随意更改 + */ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using VOL.Entity.SystemModels; + +namespace VOL.Entity.DomainModels +{ + [Table("Sys_Role")] + [EntityAttribute(TableCnName = "角色管理")] + public class Sys_Role : BaseEntity + { + /// + ///Id + /// + [Key] + [Display(Name = "Id")] + [Column(TypeName = "int")] + [Required(AllowEmptyStrings = false)] + public int Role_Id { get; set; } + + /// + ///父级ID + /// + [Display(Name = "父级ID")] + [Column(TypeName = "int")] + [Editable(true)] + [Required(AllowEmptyStrings = false)] + public int ParentId { get; set; } + + /// + ///角色名称 + /// + [Display(Name = "角色名称")] + [MaxLength(50)] + [Column(TypeName = "nvarchar(50)")] + [Editable(true)] + public string RoleName { get; set; } + + /// + ///部门ID + /// + [Display(Name = "部门ID")] + [Column(TypeName = "int")] + [Editable(true)] + public int? Dept_Id { get; set; } + + /// + ///部门名称 + /// + [Display(Name = "部门名称")] + [MaxLength(50)] + [Column(TypeName = "nvarchar(50)")] + [Editable(true)] + public string DeptName { get; set; } + + /// + ///排序 + /// + [Display(Name = "排序")] + [Column(TypeName = "int")] + [Editable(true)] + public int? OrderNo { get; set; } + + /// + ///创建人 + /// + [Display(Name = "创建人")] + [MaxLength(50)] + [Column(TypeName = "nvarchar(50)")] + [Editable(true)] + public string Creator { get; set; } + + /// + ///创建时间 + /// + [Display(Name = "创建时间")] + [Column(TypeName = "datetime")] + [Editable(true)] + public DateTime? CreateDate { get; set; } + + /// + ///修改人 + /// + [Display(Name = "修改人")] + [MaxLength(50)] + [Column(TypeName = "nvarchar(50)")] + [Editable(true)] + public string Modifier { get; set; } + + /// + ///修改时间 + /// + [Display(Name = "修改时间")] + [Column(TypeName = "datetime")] + [Editable(true)] + public DateTime? ModifyDate { get; set; } + + /// + /// + /// + [Display(Name = "DeleteBy")] + [MaxLength(50)] + [JsonIgnore] + [Column(TypeName = "nvarchar(50)")] + public string DeleteBy { get; set; } + + /// + ///是否启用 + /// + [Display(Name = "是否启用")] + [Column(TypeName = "tinyint")] + [Editable(true)] + public byte? Enable { get; set; } + [ForeignKey("Role_Id")] + public List RoleAuths { get; set; } + + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Sys_RoleAuth.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Sys_RoleAuth.cs new file mode 100644 index 0000000000000000000000000000000000000000..d0680c162ce52817a6d6b01139b9b0346de60c2d --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Sys_RoleAuth.cs @@ -0,0 +1,86 @@ +using VOL.Entity.SystemModels; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VOL.Entity.DomainModels +{ + [Table("Sys_RoleAuth")] + public class Sys_RoleAuth: BaseEntity + { + /// + /// + /// + [Key] + [Display(Name ="")] + [Required(AllowEmptyStrings=false)] + public int Auth_Id { get; set; } + + /// + /// + /// + [Display(Name ="")] + [Column(TypeName="int")] + public int? Role_Id { get; set; } + + /// + /// + /// + [Display(Name ="")] + [Column(TypeName="int")] + public int? User_Id { get; set; } + + /// + /// + /// + [Display(Name ="")] + [Column(TypeName="int")] + [Required(AllowEmptyStrings=false)] + public int Menu_Id { get; set; } + + /// + ///用户权限 + /// + [Display(Name ="用户权限")] + [MaxLength(1000)] + [Column(TypeName="nvarchar(1000)")] + [Required(AllowEmptyStrings=false)] + public string AuthValue { get; set; } + + /// + /// + /// + [Display(Name ="")] + [MaxLength(100)] + [Column(TypeName="nvarchar(1000)")] + public string Creator { get; set; } + + /// + /// + /// + [Display(Name ="")] + [Column(TypeName="datetime")] + public DateTime? CreateDate { get; set; } + + /// + /// + /// + [Display(Name ="")] + [MaxLength(100)] + [Column(TypeName="nvarchar(1000)")] + public string Modifier { get; set; } + + /// + /// + /// + [Display(Name ="")] + [Column(TypeName="datetime")] + public DateTime? ModifyDate { get; set; } + + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Sys_User.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Sys_User.cs new file mode 100644 index 0000000000000000000000000000000000000000..ddace5be003d7c9d2b8c779e70c948129400e1e7 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/Sys_User.cs @@ -0,0 +1,290 @@ +using Newtonsoft.Json; +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果数据库字段发生变化,请在代码生器重新生成此Model + */ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Entity.SystemModels; + +namespace VOL.Entity.DomainModels +{ + [Table("Sys_User")] + [Entity(ApiInput = typeof(ApiSys_UserInput),ApiOutput = typeof(ApiSys_UserOutput))] + public class Sys_User:BaseEntity + { + /// + ///用户名 + /// + [Display(Name ="用户名")] + [MaxLength(200)] + [Column(TypeName="nvarchar(200)")] + [Editable(true)] + [Required(AllowEmptyStrings=false)] + public string UserName { get; set; } + + /// + /// + /// + [Key] + [Display(Name ="User_Id")] + [Column(TypeName="int")] + [Required(AllowEmptyStrings=false)] + public int User_Id { get; set; } + + /// + ///性别 + /// + [Display(Name ="性别")] + [Column(TypeName="int")] + [Editable(true)] + public int? Gender { get; set; } + + /// + ///头像 + /// + [Display(Name ="头像")] + [MaxLength(400)] + [Column(TypeName="nvarchar(400)")] + [Editable(true)] + public string HeadImageUrl { get; set; } + + /// + /// + /// + [Display(Name ="Dept_Id")] + [Column(TypeName="int")] + public int? Dept_Id { get; set; } + + /// + ///部门 + /// + [Display(Name ="部门")] + [MaxLength(300)] + [Column(TypeName="nvarchar(300)")] + [Editable(true)] + public string DeptName { get; set; } + + /// + ///角色 + /// + [Display(Name ="角色")] + [Column(TypeName="int")] + [Editable(true)] + [Required(AllowEmptyStrings=false)] + public int Role_Id { get; set; } + + /// + /// + /// + [Display(Name ="RoleName")] + [MaxLength(300)] + [Column(TypeName="nvarchar(300)")] + [Editable(true)] + [Required(AllowEmptyStrings=false)] + public string RoleName { get; set; } + + /// + ///Token + /// + [Display(Name ="Token")] + [MaxLength(1000)] + [Column(TypeName="nvarchar(1000)")] + [Editable(true)] + public string Token { get; set; } + + /// + ///登陆设备类型 + /// + [Display(Name ="登陆设备类型")] + [Column(TypeName="int")] + [Editable(true)] + public int? AppType { get; set; } + + /// + ///用户真实姓名 + /// + [Display(Name ="用户真实姓名")] + [MaxLength(40)] + [Column(TypeName="nvarchar(40)")] + [Editable(true)] + [Required(AllowEmptyStrings=false)] + public string UserTrueName { get; set; } + + /// + ///密码 + /// + [Display(Name ="密码")] + [MaxLength(400)] + [JsonIgnore] + [Column(TypeName="nvarchar(400)")] + public string UserPwd { get; set; } + + /// + ///注册时间 + /// + [Display(Name ="注册时间")] + [Column(TypeName="datetime")] + [Editable(true)] + public DateTime? CreateDate { get; set; } + + /// + ///是否手机用户 + /// + [Display(Name ="是否手机用户")] + [Column(TypeName="int")] + [Editable(true)] + [Required(AllowEmptyStrings=false)] + public int IsRegregisterPhone { get; set; } + + /// + ///手机号 + /// + [Display(Name ="手机号")] + [MaxLength(22)] + [Column(TypeName="nvarchar(22)")] + public string PhoneNo { get; set; } + + /// + /// + /// + [Display(Name ="Tel")] + [MaxLength(40)] + [Column(TypeName="nvarchar(40)")] + public string Tel { get; set; } + + /// + /// + /// + [Display(Name ="CreateID")] + [Column(TypeName="int")] + public int? CreateID { get; set; } + + /// + ///创建人 + /// + [Display(Name ="创建人")] + [MaxLength(400)] + [Column(TypeName="nvarchar(400)")] + [Editable(true)] + public string Creator { get; set; } + + /// + ///是否可用 + /// + [Display(Name ="是否可用")] + [Column(TypeName="tinyint")] + [Editable(true)] + [Required(AllowEmptyStrings=false)] + public byte Enable { get; set; } + + /// + /// + /// + [Display(Name ="ModifyID")] + [Column(TypeName="int")] + public int? ModifyID { get; set; } + + /// + ///修改人 + /// + [Display(Name ="修改人")] + [MaxLength(400)] + [Column(TypeName="nvarchar(400)")] + public string Modifier { get; set; } + + /// + ///修改时间 + /// + [Display(Name ="修改时间")] + [Column(TypeName="datetime")] + public DateTime? ModifyDate { get; set; } + + /// + ///审核状态 + /// + [Display(Name ="审核状态")] + [Column(TypeName="int")] + public int? AuditStatus { get; set; } + + /// + ///审核人 + /// + [Display(Name ="审核人")] + [MaxLength(400)] + [Column(TypeName="nvarchar(400)")] + public string Auditor { get; set; } + + /// + ///审核时间 + /// + [Display(Name ="审核时间")] + [Column(TypeName="datetime")] + public DateTime? AuditDate { get; set; } + + /// + ///最后登陆时间 + /// + [Display(Name ="最后登陆时间")] + [Column(TypeName="datetime")] + public DateTime? LastLoginDate { get; set; } + + /// + ///最后密码修改时间 + /// + [Display(Name ="最后密码修改时间")] + [Column(TypeName="datetime")] + public DateTime? LastModifyPwdDate { get; set; } + + /// + ///地址 + /// + [Display(Name ="地址")] + [MaxLength(400)] + [Column(TypeName="nvarchar(400)")] + [Editable(true)] + public string Address { get; set; } + + /// + ///电话 + /// + [Display(Name ="电话")] + [MaxLength(200)] + [Column(TypeName="nvarchar(200)")] + [Editable(true)] + public string Mobile { get; set; } + + /// + ///Email + /// + [Display(Name ="Email")] + [MaxLength(200)] + [Column(TypeName="nvarchar(200)")] + [Editable(true)] + public string Email { get; set; } + + /// + ///备注 + /// + [Display(Name ="备注")] + [MaxLength(400)] + [Column(TypeName="nvarchar(400)")] + [Editable(true)] + public string Remark { get; set; } + + /// + ///排序号 + /// + [Display(Name ="排序号")] + [Column(TypeName="int")] + [Editable(true)] + public int? OrderNo { get; set; } + + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/TableColumnInfo.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/TableColumnInfo.cs new file mode 100644 index 0000000000000000000000000000000000000000..fa793b8a8b9c04f95c01d7040fd7a9c02a80821a --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/TableColumnInfo.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VOL.Entity.DomainModels.Sys +{ + public class TableColumnInfo + { + + public string Prec_Scale { get; set; } + public string ColumnType { get; set; } + public string ColumnName { get; set; } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/UserInfo.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/UserInfo.cs new file mode 100644 index 0000000000000000000000000000000000000000..3f1f1740017aa162fe9b1fbe9b45ba3e2e460fe5 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/System/UserInfo.cs @@ -0,0 +1,25 @@ +using VOL.Entity.SystemModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VOL.Entity.DomainModels +{ + public class UserInfo + { + public int User_Id { get; set; } + /// + /// 多个角色ID + /// + public int Role_Id { get; set; } + public string RoleName { get; set; } + public string UserName { get; set; } + public string UserTrueName { get; set; } + public int Enable { get; set; } + + public int DeptId { get; set; } + public string Token { get; set; } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/Sys_WorkFlow.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/Sys_WorkFlow.cs new file mode 100644 index 0000000000000000000000000000000000000000..e5befc26fa09e486d64266537813a546758c5eff --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/Sys_WorkFlow.cs @@ -0,0 +1,139 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果数据库字段发生变化,请在代码生器重新生成此Model + */ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Entity.SystemModels; + +namespace VOL.Entity.DomainModels +{ + [Entity(TableCnName = "审批流程配置",TableName = "Sys_WorkFlow",DetailTable = new Type[] { typeof(Sys_WorkFlowStep)},DetailTableCnName = "审批步骤")] + public partial class Sys_WorkFlow:BaseEntity + { + /// + /// + /// + [Key] + [Display(Name ="WorkFlow_Id")] + [Column(TypeName="uniqueidentifier")] + [Required(AllowEmptyStrings=false)] + public Guid WorkFlow_Id { get; set; } + + /// + ///流程名称 + /// + [Display(Name ="流程名称")] + [MaxLength(200)] + [Column(TypeName="nvarchar(200)")] + [Editable(true)] + [Required(AllowEmptyStrings=false)] + public string WorkName { get; set; } + + /// + ///表名 + /// + [Display(Name ="表名")] + [MaxLength(200)] + [Column(TypeName="nvarchar(200)")] + [Editable(true)] + [Required(AllowEmptyStrings=false)] + public string WorkTable { get; set; } + + /// + ///功能菜单 + /// + [Display(Name ="功能菜单")] + [MaxLength(200)] + [Column(TypeName="nvarchar(200)")] + [Editable(true)] + public string WorkTableName { get; set; } + + /// + ///是否启用 + /// + [Display(Name ="是否启用")] + [Column(TypeName="tinyint")] + [Editable(true)] + public byte? Enable { get; set; } + + /// + ///节点信息 + /// + [Display(Name ="节点信息")] + [Column(TypeName="nvarchar(max)")] + [Editable(true)] + public string NodeConfig { get; set; } + + /// + ///连接配置 + /// + [Display(Name ="连接配置")] + [Column(TypeName="nvarchar(max)")] + [Editable(true)] + public string LineConfig { get; set; } + + /// + ///备注 + /// + [Display(Name ="备注")] + [MaxLength(500)] + [Column(TypeName="nvarchar(500)")] + [Editable(true)] + public string Remark { get; set; } + + /// + /// + /// + [Display(Name ="CreateID")] + [Column(TypeName="int")] + public int? CreateID { get; set; } + + /// + ///创建人 + /// + [Display(Name ="创建人")] + [MaxLength(30)] + [Column(TypeName="nvarchar(30)")] + public string Creator { get; set; } + + /// + ///创建时间 + /// + [Display(Name ="创建时间")] + [Column(TypeName="datetime")] + public DateTime? CreateDate { get; set; } + + /// + /// + /// + [Display(Name ="ModifyID")] + [Column(TypeName="int")] + public int? ModifyID { get; set; } + + /// + ///修改人 + /// + [Display(Name ="修改人")] + [MaxLength(30)] + [Column(TypeName="nvarchar(30)")] + public string Modifier { get; set; } + + /// + ///修改时间 + /// + [Display(Name ="修改时间")] + [Column(TypeName="datetime")] + public DateTime? ModifyDate { get; set; } + + [Display(Name ="审批步骤")] + [ForeignKey("WorkFlow_Id")] + public List Sys_WorkFlowStep { get; set; } + + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/Sys_WorkFlowStep.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/Sys_WorkFlowStep.cs new file mode 100644 index 0000000000000000000000000000000000000000..4c34ca72a61a6a3c20cee46e2f7b23c595ee761d --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/Sys_WorkFlowStep.cs @@ -0,0 +1,141 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果数据库字段发生变化,请在代码生器重新生成此Model + */ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Entity.SystemModels; + +namespace VOL.Entity.DomainModels +{ + [Entity(TableCnName = "审批节点配置",TableName = "Sys_WorkFlowStep")] + public partial class Sys_WorkFlowStep:BaseEntity + { + /// + /// + /// + [Key] + [Display(Name ="WorkStepFlow_Id")] + [Column(TypeName="uniqueidentifier")] + [Required(AllowEmptyStrings=false)] + public Guid WorkStepFlow_Id { get; set; } + + /// + ///流程主表id + /// + [Display(Name ="流程主表id")] + [Column(TypeName="uniqueidentifier")] + [Editable(true)] + public Guid? WorkFlow_Id { get; set; } + + /// + ///流程节点Id + /// + [Display(Name ="流程节点Id")] + [MaxLength(100)] + [Column(TypeName="nvarchar(100)")] + [Editable(true)] + public string StepId { get; set; } + + /// + ///节点名称 + /// + [Display(Name ="节点名称")] + [MaxLength(200)] + [Column(TypeName="nvarchar(200)")] + [Editable(true)] + public string StepName { get; set; } + + /// + ///节点类型(1=按用户审批,2=按角色审批) + /// + [Display(Name ="节点类型(1=按用户审批,2=按角色审批)")] + [Column(TypeName="int")] + [Editable(true)] + public int? StepType { get; set; } + + /// + ///审批用户id或角色id + /// + [Display(Name ="审批用户id或角色id")] + [Column(TypeName="int")] + [Editable(true)] + public int? StepValue { get; set; } + + /// + ///备注 + /// + [Display(Name ="备注")] + [MaxLength(500)] + [Column(TypeName="nvarchar(500)")] + [Editable(true)] + public string Remark { get; set; } + + /// + ///审批顺序 + /// + [Display(Name ="审批顺序")] + [Column(TypeName="int")] + [Editable(true)] + public int? OrderId { get; set; } + + /// + ///创建时间 + /// + [Display(Name ="创建时间")] + [Column(TypeName="datetime")] + [Editable(true)] + public DateTime? CreateDate { get; set; } + + /// + /// + /// + [Display(Name ="CreateID")] + [Column(TypeName="int")] + public int? CreateID { get; set; } + + /// + ///创建人 + /// + [Display(Name ="创建人")] + [MaxLength(30)] + [Column(TypeName="nvarchar(30)")] + public string Creator { get; set; } + + /// + /// + /// + [Display(Name ="Enable")] + [Column(TypeName="tinyint")] + public byte? Enable { get; set; } + + /// + ///修改人 + /// + [Display(Name ="修改人")] + [MaxLength(30)] + [Column(TypeName="nvarchar(30)")] + public string Modifier { get; set; } + + /// + ///修改时间 + /// + [Display(Name ="修改时间")] + [Column(TypeName="datetime")] + public DateTime? ModifyDate { get; set; } + + /// + /// + /// + [Display(Name ="ModifyID")] + [Column(TypeName="int")] + public int? ModifyID { get; set; } + + + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/Sys_WorkFlowTable.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/Sys_WorkFlowTable.cs new file mode 100644 index 0000000000000000000000000000000000000000..76c3f120c91b5bc4cade4fe7e415bb9f9921dfa0 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/Sys_WorkFlowTable.cs @@ -0,0 +1,137 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果数据库字段发生变化,请在代码生器重新生成此Model + */ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Entity.SystemModels; + +namespace VOL.Entity.DomainModels +{ + [Entity(TableCnName = "审批流程",TableName = "Sys_WorkFlowTable",DetailTable = new Type[] { typeof(Sys_WorkFlowTableStep)},DetailTableCnName = "审批节点")] + public partial class Sys_WorkFlowTable:BaseEntity + { + /// + /// + /// + [Key] + [Display(Name ="WorkFlowTable_Id")] + [Column(TypeName="uniqueidentifier")] + [Required(AllowEmptyStrings=false)] + public Guid WorkFlowTable_Id { get; set; } + + /// + ///流程id + /// + [Display(Name ="流程id")] + [Column(TypeName="uniqueidentifier")] + public Guid? WorkFlow_Id { get; set; } + + /// + ///流程名称 + /// + [Display(Name ="流程名称")] + [MaxLength(200)] + [Column(TypeName="nvarchar(200)")] + public string WorkName { get; set; } + + /// + ///表主键id + /// + [Display(Name ="表主键id")] + [MaxLength(200)] + [Column(TypeName="nvarchar(200)")] + public string WorkTableKey { get; set; } + + /// + ///表名 + /// + [Display(Name ="表名")] + [MaxLength(200)] + [Column(TypeName="nvarchar(200)")] + public string WorkTable { get; set; } + + /// + ///业务名称 + /// + [Display(Name ="业务名称")] + [MaxLength(200)] + [Column(TypeName="nvarchar(200)")] + public string WorkTableName { get; set; } + + /// + ///当前审批节点 + /// + [Display(Name ="当前审批节点")] + [Column(TypeName="int")] + public int? CurrentOrderId { get; set; } + + /// + ///审批状态 + /// + [Display(Name ="审批状态")] + [Column(TypeName="int")] + public int? AuditStatus { get; set; } + + /// + ///创建人 + /// + [Display(Name ="创建人")] + [MaxLength(30)] + [Column(TypeName="nvarchar(30)")] + public string Creator { get; set; } + + /// + ///创建时间 + /// + [Display(Name ="创建时间")] + [Column(TypeName="datetime")] + public DateTime? CreateDate { get; set; } + + /// + /// + /// + [Display(Name ="CreateID")] + [Column(TypeName="int")] + public int? CreateID { get; set; } + + /// + /// + /// + [Display(Name ="Enable")] + [Column(TypeName="tinyint")] + public byte? Enable { get; set; } + + /// + /// + /// + [Display(Name ="Modifier")] + [MaxLength(30)] + [Column(TypeName="nvarchar(30)")] + public string Modifier { get; set; } + + /// + /// + /// + [Display(Name ="ModifyDate")] + [Column(TypeName="datetime")] + public DateTime? ModifyDate { get; set; } + + /// + /// + /// + [Display(Name ="ModifyID")] + [Column(TypeName="int")] + public int? ModifyID { get; set; } + + [Display(Name ="审批节点")] + [ForeignKey("WorkFlowTable_Id")] + public List Sys_WorkFlowTableStep { get; set; } + + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/Sys_WorkFlowTableStep.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/Sys_WorkFlowTableStep.cs new file mode 100644 index 0000000000000000000000000000000000000000..33d17d11c86479cbe8d65014194ff88afa063e25 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/Sys_WorkFlowTableStep.cs @@ -0,0 +1,170 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果数据库字段发生变化,请在代码生器重新生成此Model + */ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Entity.SystemModels; + +namespace VOL.Entity.DomainModels +{ + [Entity(TableCnName = "审批节点",TableName = "Sys_WorkFlowTableStep")] + public partial class Sys_WorkFlowTableStep:BaseEntity + { + /// + /// + /// + [Key] + [Display(Name ="Sys_WorkFlowTableStep_Id")] + [Column(TypeName="uniqueidentifier")] + [Required(AllowEmptyStrings=false)] + public Guid Sys_WorkFlowTableStep_Id { get; set; } + + /// + ///主表id + /// + [Display(Name ="主表id")] + [Column(TypeName="uniqueidentifier")] + [Required(AllowEmptyStrings=false)] + public Guid WorkFlowTable_Id { get; set; } + + /// + ///流程id + /// + [Display(Name ="流程id")] + [Column(TypeName="uniqueidentifier")] + public Guid? WorkFlow_Id { get; set; } + + /// + ///节点id + /// + [Display(Name ="节点id")] + [MaxLength(100)] + [Column(TypeName="nvarchar(100)")] + public string StepId { get; set; } + + /// + ///节名称 + /// + [Display(Name ="节名称")] + [MaxLength(200)] + [Column(TypeName="nvarchar(200)")] + public string StepName { get; set; } + + /// + ///审批类型 + /// + [Display(Name ="审批类型")] + [Column(TypeName="int")] + public int? StepType { get; set; } + + /// + ///节点类型(1=按用户审批,2=按角色审批) + /// + [Display(Name ="节点类型(1=按用户审批,2=按角色审批)")] + [Column(TypeName="int")] + public int? StepValue { get; set; } + + /// + ///审批顺序 + /// + [Display(Name ="审批顺序")] + [Column(TypeName="int")] + public int? OrderId { get; set; } + + /// + /// + /// + [Display(Name ="Remark")] + [MaxLength(500)] + [Column(TypeName="nvarchar(500)")] + public string Remark { get; set; } + + /// + /// + /// + [Display(Name ="CreateDate")] + [Column(TypeName="datetime")] + public DateTime? CreateDate { get; set; } + + /// + /// + /// + [Display(Name ="CreateID")] + [Column(TypeName="int")] + public int? CreateID { get; set; } + + /// + /// + /// + [Display(Name ="Creator")] + [MaxLength(30)] + [Column(TypeName="nvarchar(30)")] + public string Creator { get; set; } + + /// + /// + /// + [Display(Name ="Enable")] + [Column(TypeName="tinyint")] + public byte? Enable { get; set; } + + /// + /// + /// + [Display(Name ="Modifier")] + [MaxLength(30)] + [Column(TypeName="nvarchar(30)")] + public string Modifier { get; set; } + + /// + /// + /// + [Display(Name ="ModifyDate")] + [Column(TypeName="datetime")] + public DateTime? ModifyDate { get; set; } + + /// + /// + /// + [Display(Name ="ModifyID")] + [Column(TypeName="int")] + public int? ModifyID { get; set; } + + /// + ///审核人id + /// + [Display(Name ="审核人id")] + [Column(TypeName="int")] + public int? AuditId { get; set; } + + /// + ///审核人 + /// + [Display(Name ="审核人")] + [MaxLength(50)] + [Column(TypeName="nvarchar(50)")] + public string Auditor { get; set; } + + /// + ///审核状态 + /// + [Display(Name ="审核状态")] + [Column(TypeName="int")] + public int? AuditStatus { get; set; } + + /// + ///审核时间 + /// + [Display(Name ="审核时间")] + [Column(TypeName="datetime")] + public DateTime? AuditDate { get; set; } + + + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/partial/Sys_WorkFlow.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/partial/Sys_WorkFlow.cs new file mode 100644 index 0000000000000000000000000000000000000000..2291d3681041f120542dd46d1987b532b2e08bc4 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/partial/Sys_WorkFlow.cs @@ -0,0 +1,21 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果数据库字段发生变化,请在代码生器重新生成此Model + */ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Entity.SystemModels; + +namespace VOL.Entity.DomainModels +{ + + public partial class Sys_WorkFlow + { + //此处配置字段(字段配置见此model的另一个partial),如果表中没有此字段请加上 [NotMapped]属性,否则会异常 + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/partial/Sys_WorkFlowStep.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/partial/Sys_WorkFlowStep.cs new file mode 100644 index 0000000000000000000000000000000000000000..e4dfadecec8f095a3babb169451ea9dc98469258 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/partial/Sys_WorkFlowStep.cs @@ -0,0 +1,21 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果数据库字段发生变化,请在代码生器重新生成此Model + */ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Entity.SystemModels; + +namespace VOL.Entity.DomainModels +{ + + public partial class Sys_WorkFlowStep + { + //此处配置字段(字段配置见此model的另一个partial),如果表中没有此字段请加上 [NotMapped]属性,否则会异常 + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/partial/Sys_WorkFlowTable.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/partial/Sys_WorkFlowTable.cs new file mode 100644 index 0000000000000000000000000000000000000000..8b642f8f16f38c0cb323cb265204566c126147cb --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/partial/Sys_WorkFlowTable.cs @@ -0,0 +1,21 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果数据库字段发生变化,请在代码生器重新生成此Model + */ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Entity.SystemModels; + +namespace VOL.Entity.DomainModels +{ + + public partial class Sys_WorkFlowTable + { + //此处配置字段(字段配置见此model的另一个partial),如果表中没有此字段请加上 [NotMapped]属性,否则会异常 + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/partial/Sys_WorkFlowTableStep.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/partial/Sys_WorkFlowTableStep.cs new file mode 100644 index 0000000000000000000000000000000000000000..6426637c02c7cf89843811454fe9d735869b5f45 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/DomainModels/flow/partial/Sys_WorkFlowTableStep.cs @@ -0,0 +1,21 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果数据库字段发生变化,请在代码生器重新生成此Model + */ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Entity.SystemModels; + +namespace VOL.Entity.DomainModels +{ + + public partial class Sys_WorkFlowTableStep + { + //此处配置字段(字段配置见此model的另一个partial),如果表中没有此字段请加上 [NotMapped]属性,否则会异常 + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/IBaseInterface.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/IBaseInterface.cs new file mode 100644 index 0000000000000000000000000000000000000000..9154ce7ff85a0d3cfe8684f9f2753ec053ef937e --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/IBaseInterface.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Entity +{ + public interface IBaseInterface + { + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/MappingConfiguration/MappingManager.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/MappingConfiguration/MappingManager.cs new file mode 100644 index 0000000000000000000000000000000000000000..98f41ca666ab89b78886360e965d6033df56532a --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/MappingConfiguration/MappingManager.cs @@ -0,0 +1,129 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace VOL.Entity.MappingConfiguration +{ + + public interface IEntityMappingConfiguration + { + void Map(ModelBuilder b); + } + + public interface IEntityMappingConfiguration : IEntityMappingConfiguration where T : class + { + void Map(EntityTypeBuilder builder); + } + + public abstract class EntityMappingConfiguration : IEntityMappingConfiguration where T : class + { + public abstract void Map(EntityTypeBuilder b); + + public void Map(ModelBuilder b) + { + Map(b.Entity()); + } + } + + public static class ModelBuilderExtenions + { + private static IEnumerable GetMappingTypes(this Assembly assembly, Type mappingInterface) + { + return assembly.GetTypes().Where(x => !x.IsAbstract && x.GetInterfaces().Any(y => y.GetTypeInfo().IsGenericType && y.GetGenericTypeDefinition() == mappingInterface)); + } + + public static void AddEntityConfigurationsFromAssembly(this ModelBuilder modelBuilder, Assembly assembly) + { + var mappingTypes = assembly.GetMappingTypes(typeof(IEntityMappingConfiguration<>)); + foreach (var config in mappingTypes.Select(Activator.CreateInstance).Cast()) + { + config.Map(modelBuilder); + } + } + } +} + +//字符串默认长度 +//public class StringDefaultLengthConvention : IPropertyAddedConvention +//{ +// public InternalPropertyBuilder Apply(InternalPropertyBuilder propertyBuilder) +// { +// if (propertyBuilder.Metadata.ClrType == typeof(string)) +// propertyBuilder.HasMaxLength(32, ConfigurationSource.Convention); +// return propertyBuilder; +// } +//} +////attribute方式设置decimal精度 +//public class DecimalPrecisionAttributeConvention : PropertyAttributeConvention +//{ +// public override InternalPropertyBuilder Apply(InternalPropertyBuilder propertyBuilder, DecimalPrecisionAttribute attribute, MemberInfo clrMember) +// { +// if (propertyBuilder.Metadata.ClrType == typeof(decimal)) +// propertyBuilder.HasPrecision(attribute.Precision, attribute.Scale); +// return propertyBuilder; +// } + +// /// +// /// decimal类型设置精度 +// /// +// /// +// /// 精度 +// /// 小数位数 +// public static PropertyBuilder HasPrecision(this PropertyBuilder propertyBuilder, int precision = 18, int scale = 4) +// { +// //fluntapi方式设置精度 +// ((IInfrastructure)propertyBuilder).Instance.HasPrecision(precision, scale); + +// return propertyBuilder; +// } + +// public static InternalPropertyBuilder HasPrecision(this InternalPropertyBuilder propertyBuilder, int precision, int scale) +// { +// propertyBuilder.Relational(ConfigurationSource.Explicit).HasColumnType($"decimal({precision},{scale})"); + +// return propertyBuilder; +// } + +////servie,DI注入替换. +//services.AddSingleton(); +//services.AddSingleton(); + +////实现entity的自动发现和mapper设置 +//public class MyRelationalModelCustomizer : RelationalModelCustomizer +//{ +// public MyRelationalModelCustomizer(ModelCustomizerDependencies dependencies) +// : base(dependencies) { } + +// public override void Customize(ModelBuilder modelBuilder, DbContext dbContext) +// { +// base.Customize(modelBuilder, dbContext); +// var sp = (IInfrastructure)dbContext; +// var dbOptions = sp.Instance.GetServices(); +// foreach (var item in dbOptions) +// { +// if (item.ContextType == dbContext.GetType()) +// ConfigureDbContextEntityService.Configure(modelBuilder, item, dbContext); +// } +// } +//} + +//public class MyCoreConventionSetBuilder : CoreConventionSetBuilder +//{ +// public MyCoreConventionSetBuilder(CoreConventionSetBuilderDependencies dependencies) : base(dependencies) { } +// public override ConventionSet CreateConventionSet() +// { +// var conventionSet = base.CreateConventionSet(); +// //默认字符串长度,而不是nvarchar(max). +// //为什么要insert(0,obj),则是因为这个默认规则要最优先处理,如果后续有规则的话就直接覆盖了。 +// //propertyBuilder.HasMaxLength(32, ConfigurationSource.Convention); +// //理论上我指定了规则的级别为.Convention,应该和顺序就没有关系了。but,还没有完成测试,所以我也不知道 +// conventionSet.PropertyAddedConventions.Insert(0, new StringDefaultLengthConvention()); +// //decimal设置精度 +// conventionSet.PropertyAddedConventions.Add(new DecimalPrecisionAttributeConvention()); +// return conventionSet; +// } +//} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/MappingConfiguration/Quartz/Sys_QuartzLogMapConfig.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/MappingConfiguration/Quartz/Sys_QuartzLogMapConfig.cs new file mode 100644 index 0000000000000000000000000000000000000000..cb51f962c568a8e4839f3f5ee42dab424d85b935 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/MappingConfiguration/Quartz/Sys_QuartzLogMapConfig.cs @@ -0,0 +1,16 @@ +using VOL.Entity.MappingConfiguration; +using VOL.Entity.DomainModels; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace VOL.Entity.MappingConfiguration +{ + public class Sys_QuartzLogMapConfig : EntityMappingConfiguration + { + public override void Map(EntityTypeBuilder + builderTable) + { + //b.Property(x => x.StorageName).HasMaxLength(45); + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/MappingConfiguration/Quartz/Sys_QuartzOptionsMapConfig.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/MappingConfiguration/Quartz/Sys_QuartzOptionsMapConfig.cs new file mode 100644 index 0000000000000000000000000000000000000000..b4d80504ad369f7e8d9365379f05f921d5ef2528 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/MappingConfiguration/Quartz/Sys_QuartzOptionsMapConfig.cs @@ -0,0 +1,16 @@ +using VOL.Entity.MappingConfiguration; +using VOL.Entity.DomainModels; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace VOL.Entity.MappingConfiguration +{ + public class Sys_QuartzOptionsMapConfig : EntityMappingConfiguration + { + public override void Map(EntityTypeBuilder + builderTable) + { + //b.Property(x => x.StorageName).HasMaxLength(45); + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/MappingConfiguration/flow/Sys_WorkFlowMapConfig.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/MappingConfiguration/flow/Sys_WorkFlowMapConfig.cs new file mode 100644 index 0000000000000000000000000000000000000000..4c9c9f33a5d0ce9df7977c1760c6d833f03473d3 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/MappingConfiguration/flow/Sys_WorkFlowMapConfig.cs @@ -0,0 +1,16 @@ +using VOL.Entity.MappingConfiguration; +using VOL.Entity.DomainModels; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace VOL.Entity.MappingConfiguration +{ + public class Sys_WorkFlowMapConfig : EntityMappingConfiguration + { + public override void Map(EntityTypeBuilder + builderTable) + { + //b.Property(x => x.StorageName).HasMaxLength(45); + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/MappingConfiguration/flow/Sys_WorkFlowStepMapConfig.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/MappingConfiguration/flow/Sys_WorkFlowStepMapConfig.cs new file mode 100644 index 0000000000000000000000000000000000000000..0c30cdb49759510a5c4a9fbbcadd731496e9ee2c --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/MappingConfiguration/flow/Sys_WorkFlowStepMapConfig.cs @@ -0,0 +1,16 @@ +using VOL.Entity.MappingConfiguration; +using VOL.Entity.DomainModels; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace VOL.Entity.MappingConfiguration +{ + public class Sys_WorkFlowStepMapConfig : EntityMappingConfiguration + { + public override void Map(EntityTypeBuilder + builderTable) + { + //b.Property(x => x.StorageName).HasMaxLength(45); + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/MappingConfiguration/flow/Sys_WorkFlowTableMapConfig.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/MappingConfiguration/flow/Sys_WorkFlowTableMapConfig.cs new file mode 100644 index 0000000000000000000000000000000000000000..20e13bad0e8367efc9613b5e059aaae706cddffb --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/MappingConfiguration/flow/Sys_WorkFlowTableMapConfig.cs @@ -0,0 +1,16 @@ +using VOL.Entity.MappingConfiguration; +using VOL.Entity.DomainModels; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace VOL.Entity.MappingConfiguration +{ + public class Sys_WorkFlowTableMapConfig : EntityMappingConfiguration + { + public override void Map(EntityTypeBuilder + builderTable) + { + //b.Property(x => x.StorageName).HasMaxLength(45); + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/MappingConfiguration/flow/Sys_WorkFlowTableStepMapConfig.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/MappingConfiguration/flow/Sys_WorkFlowTableStepMapConfig.cs new file mode 100644 index 0000000000000000000000000000000000000000..e1c1efa7d18b83cd29b1e0d6bd93f5c41ecc78d0 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/MappingConfiguration/flow/Sys_WorkFlowTableStepMapConfig.cs @@ -0,0 +1,16 @@ +using VOL.Entity.MappingConfiguration; +using VOL.Entity.DomainModels; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace VOL.Entity.MappingConfiguration +{ + public class Sys_WorkFlowTableStepMapConfig : EntityMappingConfiguration + { + public override void Map(EntityTypeBuilder + builderTable) + { + //b.Property(x => x.StorageName).HasMaxLength(45); + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/SystemModels/BaseEntity.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/SystemModels/BaseEntity.cs new file mode 100644 index 0000000000000000000000000000000000000000..d69379eb9bcb263a8234d0824e999019e2ae337a --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/SystemModels/BaseEntity.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace VOL.Entity.SystemModels +{ + public class BaseEntity + { + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/SystemModels/Sys_MenuRole.cs b/Pure_Vite_Net7/WebNet7/VOL.Entity/SystemModels/Sys_MenuRole.cs new file mode 100644 index 0000000000000000000000000000000000000000..ba3d9d389c4cbd3d9e5f68933081fa26a0bd0d5e --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/SystemModels/Sys_MenuRole.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Text; + +namespace VOL.Entity +{ + public class Sys_Actions + { + [Key] + public int Action_Id { get; set; } + public int Menu_Id { get; set; } + public string Text { get; set; } + public string Value { get; set; } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.Entity/VOL.Entity.csproj b/Pure_Vite_Net7/WebNet7/VOL.Entity/VOL.Entity.csproj new file mode 100644 index 0000000000000000000000000000000000000000..1cd144d394d8dcf414627558c6dc0c5765cb2cbe --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.Entity/VOL.Entity.csproj @@ -0,0 +1,67 @@ + + + + + + + + + + + net7.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/Quartz/ISys_QuartzLogRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/Quartz/ISys_QuartzLogRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..632ac209e9d0d519670f5acd64f62f2d323514b6 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/Quartz/ISys_QuartzLogRepository.cs @@ -0,0 +1,18 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹ISys_QuartzLogRepository编写接口 + */ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; +using VOL.Core.Extensions.AutofacManager; +namespace VOL.System.IRepositories +{ + public partial interface ISys_QuartzLogRepository : IDependency,IRepository + { + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/Quartz/ISys_QuartzOptionsRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/Quartz/ISys_QuartzOptionsRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..574b9c1fb00e4a09b80dcd0098716aedd9015c8e --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/Quartz/ISys_QuartzOptionsRepository.cs @@ -0,0 +1,18 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹ISys_QuartzOptionsRepository编写接口 + */ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; +using VOL.Core.Extensions.AutofacManager; +namespace VOL.System.IRepositories +{ + public partial interface ISys_QuartzOptionsRepository : IDependency,IRepository + { + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/System/ISys_DictionaryListRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/System/ISys_DictionaryListRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..c792f2d180ba0631795d5f7acdba49716280ef3e --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/System/ISys_DictionaryListRepository.cs @@ -0,0 +1,21 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *Date:2018-07-01 + * 此代码由框架生成,请勿随意更改 + */ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; +using VOL.Core.Extensions.AutofacManager; +namespace VOL.System.IRepositories +{ + public partial interface ISys_DictionaryListRepository : IDependency,IRepository + { + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/System/ISys_DictionaryRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/System/ISys_DictionaryRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..8cb1e85ed7ba7c3252507aa500bed7e901e4997a --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/System/ISys_DictionaryRepository.cs @@ -0,0 +1,21 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *Date:2018-07-01 + * 此代码由框架生成,请勿随意更改 + */ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; +using VOL.Core.Extensions.AutofacManager; +namespace VOL.System.IRepositories +{ + public partial interface ISys_DictionaryRepository : IDependency,IRepository + { + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/System/ISys_LogRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/System/ISys_LogRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..912454a746f927617ba309207c36cfe0c393241d --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/System/ISys_LogRepository.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; +using VOL.Core.Extensions.AutofacManager; +namespace VOL.System.IRepositories +{ + public partial interface ISys_LogRepository : IDependency,IRepository + { + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/System/ISys_MenuRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/System/ISys_MenuRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..1c428ec5bb6dc460744b57f55bc178d465af0889 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/System/ISys_MenuRepository.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; +using VOL.Core.Extensions.AutofacManager; +namespace VOL.System.IRepositories +{ + public partial interface ISys_MenuRepository : IDependency,IRepository + { + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/System/ISys_RoleRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/System/ISys_RoleRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..59ad8464537a9693b56d7007f7baac3c5de060d7 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/System/ISys_RoleRepository.cs @@ -0,0 +1,18 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹ISys_RoleRepository编写接口 + */ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; +using VOL.Core.Extensions.AutofacManager; +namespace VOL.System.IRepositories +{ + public partial interface ISys_RoleRepository : IDependency,IRepository + { + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/System/ISys_UserRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/System/ISys_UserRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..3f17f123fab415d227dd1745aa5861b973e6f46d --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/System/ISys_UserRepository.cs @@ -0,0 +1,21 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *Date:2018-07-01 + * 此代码由框架生成,请勿随意更改 + */ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; +using VOL.Core.Extensions.AutofacManager; +namespace VOL.System.IRepositories +{ + public partial interface ISys_UserRepository : IDependency,IRepository + { + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/flow/ISys_WorkFlowRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/flow/ISys_WorkFlowRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..b9f1d668c187cb79119a4023161996b3104d99e0 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/flow/ISys_WorkFlowRepository.cs @@ -0,0 +1,18 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹ISys_WorkFlowRepository编写接口 + */ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; +using VOL.Core.Extensions.AutofacManager; +namespace VOL.System.IRepositories +{ + public partial interface ISys_WorkFlowRepository : IDependency,IRepository + { + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/flow/ISys_WorkFlowStepRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/flow/ISys_WorkFlowStepRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..0e55b79339c42027242930f007fab96040f9a73d --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/flow/ISys_WorkFlowStepRepository.cs @@ -0,0 +1,18 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹ISys_WorkFlowStepRepository编写接口 + */ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; +using VOL.Core.Extensions.AutofacManager; +namespace VOL.System.IRepositories +{ + public partial interface ISys_WorkFlowStepRepository : IDependency,IRepository + { + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/flow/ISys_WorkFlowTableRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/flow/ISys_WorkFlowTableRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..91f57cd31a7154eeb52f106c8588aa9f0579b591 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/flow/ISys_WorkFlowTableRepository.cs @@ -0,0 +1,18 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹ISys_WorkFlowTableRepository编写接口 + */ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; +using VOL.Core.Extensions.AutofacManager; +namespace VOL.System.IRepositories +{ + public partial interface ISys_WorkFlowTableRepository : IDependency,IRepository + { + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/flow/ISys_WorkFlowTableStepRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/flow/ISys_WorkFlowTableStepRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..ef7bd6f8e2e4f70e454d762650309a49012c8c11 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IRepositories/flow/ISys_WorkFlowTableStepRepository.cs @@ -0,0 +1,18 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹ISys_WorkFlowTableStepRepository编写接口 + */ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; +using VOL.Core.Extensions.AutofacManager; +namespace VOL.System.IRepositories +{ + public partial interface ISys_WorkFlowTableStepRepository : IDependency,IRepository + { + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IServices/Quartz/ISys_QuartzLogService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/Quartz/ISys_QuartzLogService.cs new file mode 100644 index 0000000000000000000000000000000000000000..01534bb8137070ce2111ff3c84710c976e25c1b5 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/Quartz/ISys_QuartzLogService.cs @@ -0,0 +1,12 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + */ +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; + +namespace VOL.System.IServices +{ + public partial interface ISys_QuartzLogService : IService + { + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IServices/Quartz/ISys_QuartzOptionsService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/Quartz/ISys_QuartzOptionsService.cs new file mode 100644 index 0000000000000000000000000000000000000000..a9cb0a91422bc78f070850b3a92aa82557eb395c --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/Quartz/ISys_QuartzOptionsService.cs @@ -0,0 +1,12 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + */ +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; + +namespace VOL.System.IServices +{ + public partial interface ISys_QuartzOptionsService : IService + { + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IServices/Quartz/Partial/ISys_QuartzLogService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/Quartz/Partial/ISys_QuartzLogService.cs new file mode 100644 index 0000000000000000000000000000000000000000..96c059e648e91a7d01371c672eea56024ca16c76 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/Quartz/Partial/ISys_QuartzLogService.cs @@ -0,0 +1,13 @@ +/* +*所有关于Sys_QuartzLog类的业务代码接口应在此处编写 +*/ +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; +using VOL.Core.Utilities; +using System.Linq.Expressions; +namespace VOL.System.IServices +{ + public partial interface ISys_QuartzLogService + { + } + } diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IServices/Quartz/Partial/ISys_QuartzOptionsService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/Quartz/Partial/ISys_QuartzOptionsService.cs new file mode 100644 index 0000000000000000000000000000000000000000..65f66bf2534c9c2c2204bd74fea2a4c527026334 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/Quartz/Partial/ISys_QuartzOptionsService.cs @@ -0,0 +1,37 @@ +/* +*所有关于Sys_QuartzOptions类的业务代码接口应在此处编写 +*/ +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; +using VOL.Core.Utilities; +using System.Linq.Expressions; +using System.Threading.Tasks; + +namespace VOL.System.IServices +{ + public partial interface ISys_QuartzOptionsService + { + + /// + /// 手动执行一次 + /// + /// + /// + Task Run(Sys_QuartzOptions taskOptions); + /// + /// 开启任务 + /// + /// + /// + /// + Task Start(Sys_QuartzOptions taskOptions); + /// + /// 暂停任务 + /// + /// + /// + /// + Task Pause(Sys_QuartzOptions taskOptions); + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/ISys_DictionaryListService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/ISys_DictionaryListService.cs new file mode 100644 index 0000000000000000000000000000000000000000..0a64f5eef403e5b3125b34f07f96be313e141bba --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/ISys_DictionaryListService.cs @@ -0,0 +1,16 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *Date:2018-07-01 + * 此代码由框架生成,请勿随意更改 + */ +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; + +namespace VOL.System.IServices +{ + public partial interface ISys_DictionaryListService : IService + { + } + } + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/ISys_DictionaryService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/ISys_DictionaryService.cs new file mode 100644 index 0000000000000000000000000000000000000000..3fe4d6b570bd4b45decdaf436d87c7344bfb2172 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/ISys_DictionaryService.cs @@ -0,0 +1,16 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *Date:2018-07-01 + * 此代码由框架生成,请勿随意更改 + */ +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; + +namespace VOL.System.IServices +{ + public partial interface ISys_DictionaryService : IService + { + } + } + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/ISys_LogService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/ISys_LogService.cs new file mode 100644 index 0000000000000000000000000000000000000000..073df2883c26cdef925689a2655c3d12c7416fc7 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/ISys_LogService.cs @@ -0,0 +1,10 @@ +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; + +namespace VOL.System.IServices +{ + public partial interface ISys_LogService : IService + { + } + } + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/ISys_MenuService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/ISys_MenuService.cs new file mode 100644 index 0000000000000000000000000000000000000000..309e3a6b6a0a333856b289084e4c7d0a697911bf --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/ISys_MenuService.cs @@ -0,0 +1,10 @@ +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; + +namespace VOL.System.IServices +{ + public partial interface ISys_MenuService : IService + { + } + } + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/ISys_RoleService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/ISys_RoleService.cs new file mode 100644 index 0000000000000000000000000000000000000000..8be51a62095c97c3fe35a67b5c43a82bbee3179f --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/ISys_RoleService.cs @@ -0,0 +1,16 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *Date:2018-07-01 + * 此代码由框架生成,请勿随意更改 + */ +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; + +namespace VOL.System.IServices +{ + public partial interface ISys_RoleService : IService + { + } + } + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/ISys_UserService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/ISys_UserService.cs new file mode 100644 index 0000000000000000000000000000000000000000..4b5572e029381c4f6461189840700d39c260f7e9 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/ISys_UserService.cs @@ -0,0 +1,16 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *Date:2018-07-01 + * 此代码由框架生成,请勿随意更改 + */ +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; + +namespace VOL.System.IServices +{ + public partial interface ISys_UserService : IService + { + } + } + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/Partial/ISys_DictionaryListService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/Partial/ISys_DictionaryListService.cs new file mode 100644 index 0000000000000000000000000000000000000000..a7aa5c28c9ceb70ab529bb5c05aa5ac470f15851 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/Partial/ISys_DictionaryListService.cs @@ -0,0 +1,10 @@ +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; + +namespace VOL.System.IServices +{ + public partial interface ISys_DictionaryListService + { + } + } + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/Partial/ISys_DictionaryService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/Partial/ISys_DictionaryService.cs new file mode 100644 index 0000000000000000000000000000000000000000..beabfd609680cfa0ff24e8b19990decf24c73c6d --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/Partial/ISys_DictionaryService.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; + +namespace VOL.System.IServices +{ + public partial interface ISys_DictionaryService + { + /// + /// 代码生成器获取所有字典项(超级管理权限) + /// + /// + Task> GetBuilderDictionary(); + object GetVueDictionary(string[] dicNos); + object GetTableDictionary(Dictionary keyData); + object GetSearchDictionary(string dicNo, string value); + + /// + /// 表单设置为远程查询,重置或第一次添加表单时,获取字典的key、value + /// + /// + /// + /// + Task GetRemoteDefaultKeyValue(string dicNo, string key); + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/Partial/ISys_MenuService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/Partial/ISys_MenuService.cs new file mode 100644 index 0000000000000000000000000000000000000000..db1ff588f889c9f15424e4f1ca3d5b8681147feb --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/Partial/ISys_MenuService.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using VOL.Core.Utilities; +using VOL.Entity.DomainModels; + +namespace VOL.System.IServices +{ + public partial interface ISys_MenuService + { + Task GetMenu(); + List GetCurrentMenuList(); + + List GetUserMenuList(int roleId); + + Task GetCurrentMenuActionList(); + + Task GetMenuActionList(int roleId); + Task Save(Sys_Menu menu); + + Task DelMenu(int menuId); + + + Task GetTreeItem(int menuId); + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/Partial/ISys_RoleService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/Partial/ISys_RoleService.cs new file mode 100644 index 0000000000000000000000000000000000000000..b140450b8b5bbc72aac811e795b0b389aeaaa170 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/Partial/ISys_RoleService.cs @@ -0,0 +1,49 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using VOL.Core.Utilities; +using VOL.Entity.DomainModels; +using VOL.System.Services; + +namespace VOL.System.IServices +{ + public partial interface ISys_RoleService + { + + Task GetUserTreePermission(int role_Id); + + Task GetCurrentUserTreePermission(); + + Task GetCurrentTreePermission(); + + Task SavePermission(List userPermissions, int roleId); + /// + /// 获取角色下所有的角色 + /// + /// + /// + Task> GetAllChildrenAsync(int roleId); + + /// + /// 获取角色下所有的角色 + /// + /// + /// + List GetAllChildren(int roleId); + + /// + /// 获取角色下所有的角色Id + /// + /// + /// + Task> GetAllChildrenRoleIdAsync(int roleId); + + List GetAllChildrenRoleId(int roleId); + /// + /// 获取当前角色下的所有角色包括自己的角色Id + /// + /// + List GetAllChildrenRoleIdAndSelf(); + + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/Partial/ISys_UserService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/Partial/ISys_UserService.cs new file mode 100644 index 0000000000000000000000000000000000000000..f0d97869066a475c2b57b82e22d3e4c2d3fcf73a --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/System/Partial/ISys_UserService.cs @@ -0,0 +1,17 @@ +using VOL.Core.BaseProvider; +using VOL.Core.Utilities; +using VOL.Entity.DomainModels; +using System.Threading.Tasks; + +namespace VOL.System.IServices +{ + public partial interface ISys_UserService + { + + Task Login(LoginInfo loginInfo, bool verificationCode = true); + Task ReplaceToken(); + Task ModifyPwd(string oldPwd, string newPwd); + Task GetCurrentUserInfo(); + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/ISys_WorkFlowService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/ISys_WorkFlowService.cs new file mode 100644 index 0000000000000000000000000000000000000000..490b99888bb7af9a361a04279340258ceb7b4f2e --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/ISys_WorkFlowService.cs @@ -0,0 +1,12 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + */ +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; + +namespace VOL.System.IServices +{ + public partial interface ISys_WorkFlowService : IService + { + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/ISys_WorkFlowStepService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/ISys_WorkFlowStepService.cs new file mode 100644 index 0000000000000000000000000000000000000000..e9c733c94b629257b651a26d4d0f8521c4897c29 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/ISys_WorkFlowStepService.cs @@ -0,0 +1,12 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + */ +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; + +namespace VOL.System.IServices +{ + public partial interface ISys_WorkFlowStepService : IService + { + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/ISys_WorkFlowTableService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/ISys_WorkFlowTableService.cs new file mode 100644 index 0000000000000000000000000000000000000000..8cea25f94fd5fd76b8a080417bb436db173ccbfa --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/ISys_WorkFlowTableService.cs @@ -0,0 +1,12 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + */ +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; + +namespace VOL.System.IServices +{ + public partial interface ISys_WorkFlowTableService : IService + { + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/ISys_WorkFlowTableStepService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/ISys_WorkFlowTableStepService.cs new file mode 100644 index 0000000000000000000000000000000000000000..12b4737aaf944ad56de573fa95f60d8584b162a9 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/ISys_WorkFlowTableStepService.cs @@ -0,0 +1,12 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + */ +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; + +namespace VOL.System.IServices +{ + public partial interface ISys_WorkFlowTableStepService : IService + { + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/Partial/ISys_WorkFlowService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/Partial/ISys_WorkFlowService.cs new file mode 100644 index 0000000000000000000000000000000000000000..f6564507296bd597a1fb33c0872b7357da1229ea --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/Partial/ISys_WorkFlowService.cs @@ -0,0 +1,13 @@ +/* +*所有关于Sys_WorkFlow类的业务代码接口应在此处编写 +*/ +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; +using VOL.Core.Utilities; +using System.Linq.Expressions; +namespace VOL.System.IServices +{ + public partial interface ISys_WorkFlowService + { + } + } diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/Partial/ISys_WorkFlowStepService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/Partial/ISys_WorkFlowStepService.cs new file mode 100644 index 0000000000000000000000000000000000000000..9ec17a3bc3adcbda098517fa0b3f5989ae19721a --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/Partial/ISys_WorkFlowStepService.cs @@ -0,0 +1,13 @@ +/* +*所有关于Sys_WorkFlowStep类的业务代码接口应在此处编写 +*/ +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; +using VOL.Core.Utilities; +using System.Linq.Expressions; +namespace VOL.System.IServices +{ + public partial interface ISys_WorkFlowStepService + { + } + } diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/Partial/ISys_WorkFlowTableService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/Partial/ISys_WorkFlowTableService.cs new file mode 100644 index 0000000000000000000000000000000000000000..c85bba7c7e0f14ce5134313a296aae65286bb660 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/Partial/ISys_WorkFlowTableService.cs @@ -0,0 +1,13 @@ +/* +*所有关于Sys_WorkFlowTable类的业务代码接口应在此处编写 +*/ +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; +using VOL.Core.Utilities; +using System.Linq.Expressions; +namespace VOL.System.IServices +{ + public partial interface ISys_WorkFlowTableService + { + } + } diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/Partial/ISys_WorkFlowTableStepService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/Partial/ISys_WorkFlowTableStepService.cs new file mode 100644 index 0000000000000000000000000000000000000000..001330188234937f9bbd12ba898bc4aa8b931182 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/IServices/flow/Partial/ISys_WorkFlowTableStepService.cs @@ -0,0 +1,13 @@ +/* +*所有关于Sys_WorkFlowTableStep类的业务代码接口应在此处编写 +*/ +using VOL.Core.BaseProvider; +using VOL.Entity.DomainModels; +using VOL.Core.Utilities; +using System.Linq.Expressions; +namespace VOL.System.IServices +{ + public partial interface ISys_WorkFlowTableStepService + { + } + } diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Properties/launchSettings.json b/Pure_Vite_Net7/WebNet7/VOL.System/Properties/launchSettings.json new file mode 100644 index 0000000000000000000000000000000000000000..c1b84ca0cbee3bd90e3441d5af0dfe9f0e1a7f17 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:34180/", + "sslPort": 44371 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "VOL.System": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:5001;http://localhost:5000" + } + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/Quartz/Sys_QuartzLogRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/Quartz/Sys_QuartzLogRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..34205a8baaae34388762d1f672df291000841368 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/Quartz/Sys_QuartzLogRepository.cs @@ -0,0 +1,24 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹Sys_QuartzLogRepository编写代码 + */ +using VOL.System.IRepositories; +using VOL.Core.BaseProvider; +using VOL.Core.EFDbContext; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.System.Repositories +{ + public partial class Sys_QuartzLogRepository : RepositoryBase , ISys_QuartzLogRepository + { + public Sys_QuartzLogRepository(VOLContext dbContext) + : base(dbContext) + { + + } + public static ISys_QuartzLogRepository Instance + { + get { return AutofacContainerModule.GetService(); } } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/Quartz/Sys_QuartzOptionsRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/Quartz/Sys_QuartzOptionsRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..3e5d6f7e5bb2bde77582747837e09fb4c4dc6dff --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/Quartz/Sys_QuartzOptionsRepository.cs @@ -0,0 +1,24 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹Sys_QuartzOptionsRepository编写代码 + */ +using VOL.System.IRepositories; +using VOL.Core.BaseProvider; +using VOL.Core.EFDbContext; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.System.Repositories +{ + public partial class Sys_QuartzOptionsRepository : RepositoryBase , ISys_QuartzOptionsRepository + { + public Sys_QuartzOptionsRepository(VOLContext dbContext) + : base(dbContext) + { + + } + public static ISys_QuartzOptionsRepository Instance + { + get { return AutofacContainerModule.GetService(); } } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/System/Partial/Sys_MenuRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/System/Partial/Sys_MenuRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..c91e4404407c34cfc97e3bcfb151627946c77cd1 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/System/Partial/Sys_MenuRepository.cs @@ -0,0 +1,14 @@ +using VOL.System.IRepositories; +using VOL.Core.BaseProvider; +using VOL.Core.Extensions.AutofacManager; +using VOL.Core.EFDbContext; +using VOL.Entity.DomainModels; + +namespace VOL.System.Repositories +{ + public partial class Sys_MenuRepository + { + public override VOLContext DbContext => base.DbContext; + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/System/Sys_DictionaryListRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/System/Sys_DictionaryListRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..ac9a6048dbb43955ca28a909f23b804f6cf5b578 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/System/Sys_DictionaryListRepository.cs @@ -0,0 +1,28 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *Date:2018-07-01 + * 此代码由框架生成,请勿随意更改 + */ +using VOL.System.IRepositories; +using VOL.Core.BaseProvider; +using VOL.Core.EFDbContext; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.System.Repositories +{ + public partial class Sys_DictionaryListRepository : RepositoryBase, ISys_DictionaryListRepository + { + public Sys_DictionaryListRepository(VOLContext dbContext) + : base(dbContext) + { + + } + public static ISys_DictionaryListRepository Instance + { + get { return AutofacContainerModule.GetService(); } + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/System/Sys_DictionaryRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/System/Sys_DictionaryRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..af10111a2c31b34e8e57c113eae06391ee48402f --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/System/Sys_DictionaryRepository.cs @@ -0,0 +1,28 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *Date:2018-07-01 + * 此代码由框架生成,请勿随意更改 + */ +using VOL.System.IRepositories; +using VOL.Core.BaseProvider; +using VOL.Core.EFDbContext; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.System.Repositories +{ + public partial class Sys_DictionaryRepository : RepositoryBase, ISys_DictionaryRepository + { + public Sys_DictionaryRepository(VOLContext dbContext) + : base(dbContext) + { + + } + public static ISys_DictionaryRepository Instance + { + get { return AutofacContainerModule.GetService(); } + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/System/Sys_LogRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/System/Sys_LogRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..af246b29e0ef602bc025c557741453903c13a311 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/System/Sys_LogRepository.cs @@ -0,0 +1,22 @@ +using VOL.System.IRepositories; +using VOL.Core.BaseProvider; +using VOL.Core.Extensions.AutofacManager; +using VOL.Core.EFDbContext; +using VOL.Entity.DomainModels; + +namespace VOL.System.Repositories +{ + public partial class Sys_LogRepository : RepositoryBase, ISys_LogRepository + { + public Sys_LogRepository(VOLContext dbContext) + : base(dbContext) + { + + } + public static ISys_LogRepository GetService + { + get { return AutofacContainerModule.GetService(); } + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/System/Sys_MenuRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/System/Sys_MenuRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..6149c44a3940f28ce733a4e0a990c8145f19e727 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/System/Sys_MenuRepository.cs @@ -0,0 +1,22 @@ +using VOL.System.IRepositories; +using VOL.Core.BaseProvider; +using VOL.Core.Extensions.AutofacManager; +using VOL.Core.EFDbContext; +using VOL.Entity.DomainModels; + +namespace VOL.System.Repositories +{ + public partial class Sys_MenuRepository : RepositoryBase, ISys_MenuRepository + { + public Sys_MenuRepository(VOLContext dbContext) + : base(dbContext) + { + + } + public static ISys_MenuRepository Instance + { + get { return AutofacContainerModule.GetService(); } + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/System/Sys_RoleRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/System/Sys_RoleRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..cf1e04431d93a57a7cc676a7b48d0bead14b9aad --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/System/Sys_RoleRepository.cs @@ -0,0 +1,28 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *Date:2018-07-01 + * 此代码由框架生成,请勿随意更改 + */ +using VOL.System.IRepositories; +using VOL.Core.BaseProvider; +using VOL.Core.EFDbContext; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.System.Repositories +{ + public partial class Sys_RoleRepository : RepositoryBase, ISys_RoleRepository + { + public Sys_RoleRepository(VOLContext dbContext) + : base(dbContext) + { + + } + public static ISys_RoleRepository Instance + { + get { return AutofacContainerModule.GetService(); } + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/System/Sys_UserRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/System/Sys_UserRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..d49c7e710febd4032b5db8bdb6c9578dcfb7b42c --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/System/Sys_UserRepository.cs @@ -0,0 +1,28 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *Date:2018-07-01 + * 此代码由框架生成,请勿随意更改 + */ +using VOL.System.IRepositories; +using VOL.Core.BaseProvider; +using VOL.Core.EFDbContext; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.System.Repositories +{ + public partial class Sys_UserRepository : RepositoryBase, ISys_UserRepository + { + public Sys_UserRepository(VOLContext dbContext) + : base(dbContext) + { + + } + public static ISys_UserRepository Instance + { + get { return AutofacContainerModule.GetService(); } + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/flow/Sys_WorkFlowRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/flow/Sys_WorkFlowRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..dff1ddd32c9504d1fa93eda41466cf0927748b7d --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/flow/Sys_WorkFlowRepository.cs @@ -0,0 +1,24 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹Sys_WorkFlowRepository编写代码 + */ +using VOL.System.IRepositories; +using VOL.Core.BaseProvider; +using VOL.Core.EFDbContext; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.System.Repositories +{ + public partial class Sys_WorkFlowRepository : RepositoryBase , ISys_WorkFlowRepository + { + public Sys_WorkFlowRepository(VOLContext dbContext) + : base(dbContext) + { + + } + public static ISys_WorkFlowRepository Instance + { + get { return AutofacContainerModule.GetService(); } } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/flow/Sys_WorkFlowStepRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/flow/Sys_WorkFlowStepRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..dcec968b8072b8643b9630f2fdba39463931a9aa --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/flow/Sys_WorkFlowStepRepository.cs @@ -0,0 +1,24 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹Sys_WorkFlowStepRepository编写代码 + */ +using VOL.System.IRepositories; +using VOL.Core.BaseProvider; +using VOL.Core.EFDbContext; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.System.Repositories +{ + public partial class Sys_WorkFlowStepRepository : RepositoryBase , ISys_WorkFlowStepRepository + { + public Sys_WorkFlowStepRepository(VOLContext dbContext) + : base(dbContext) + { + + } + public static ISys_WorkFlowStepRepository Instance + { + get { return AutofacContainerModule.GetService(); } } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/flow/Sys_WorkFlowTableRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/flow/Sys_WorkFlowTableRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..834a2b8d84a5b13c35b641e5db61c6d20746dbd8 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/flow/Sys_WorkFlowTableRepository.cs @@ -0,0 +1,24 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹Sys_WorkFlowTableRepository编写代码 + */ +using VOL.System.IRepositories; +using VOL.Core.BaseProvider; +using VOL.Core.EFDbContext; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.System.Repositories +{ + public partial class Sys_WorkFlowTableRepository : RepositoryBase , ISys_WorkFlowTableRepository + { + public Sys_WorkFlowTableRepository(VOLContext dbContext) + : base(dbContext) + { + + } + public static ISys_WorkFlowTableRepository Instance + { + get { return AutofacContainerModule.GetService(); } } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/flow/Sys_WorkFlowTableStepRepository.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/flow/Sys_WorkFlowTableStepRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..ca5319a716cdb2d16f1dace479237bb6aef6ff0a --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Repositories/flow/Sys_WorkFlowTableStepRepository.cs @@ -0,0 +1,24 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹Sys_WorkFlowTableStepRepository编写代码 + */ +using VOL.System.IRepositories; +using VOL.Core.BaseProvider; +using VOL.Core.EFDbContext; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.System.Repositories +{ + public partial class Sys_WorkFlowTableStepRepository : RepositoryBase , ISys_WorkFlowTableStepRepository + { + public Sys_WorkFlowTableStepRepository(VOLContext dbContext) + : base(dbContext) + { + + } + public static ISys_WorkFlowTableStepRepository Instance + { + get { return AutofacContainerModule.GetService(); } } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Services/Quartz/Partial/Sys_QuartzLogService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Services/Quartz/Partial/Sys_QuartzLogService.cs new file mode 100644 index 0000000000000000000000000000000000000000..ba2a72fbb57e309a02484ce7e872184a33153427 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Services/Quartz/Partial/Sys_QuartzLogService.cs @@ -0,0 +1,41 @@ +/* + *所有关于Sys_QuartzLog类的业务代码应在此处编写 +*可使用repository.调用常用方法,获取EF/Dapper等信息 +*如果需要事务请使用repository.DbContextBeginTransaction +*也可使用DBServerProvider.手动获取数据库相关信息 +*用户信息、权限、角色等使用UserContext.Current操作 +*Sys_QuartzLogService对增、删、改查、导入、导出、审核业务代码扩展参照ServiceFunFilter +*/ +using VOL.Core.BaseProvider; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; +using System.Linq; +using VOL.Core.Utilities; +using System.Linq.Expressions; +using VOL.Core.Extensions; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Http; +using VOL.System.IRepositories; + +namespace VOL.System.Services +{ + public partial class Sys_QuartzLogService + { + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly ISys_QuartzLogRepository _repository;//访问数据库 + + [ActivatorUtilitiesConstructor] + public Sys_QuartzLogService( + ISys_QuartzLogRepository dbRepository, + IHttpContextAccessor httpContextAccessor + ) + : base(dbRepository) + { + _httpContextAccessor = httpContextAccessor; + _repository = dbRepository; + //多租户会用到这init代码,其他情况可以不用 + //base.Init(dbRepository); + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Services/Quartz/Partial/Sys_QuartzOptionsService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Services/Quartz/Partial/Sys_QuartzOptionsService.cs new file mode 100644 index 0000000000000000000000000000000000000000..8a57b5a59c1109a72bb5c72dba35e72682342a46 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Services/Quartz/Partial/Sys_QuartzOptionsService.cs @@ -0,0 +1,123 @@ +/* + *所有关于Sys_QuartzOptions类的业务代码应在此处编写 +*可使用repository.调用常用方法,获取EF/Dapper等信息 +*如果需要事务请使用repository.DbContextBeginTransaction +*也可使用DBServerProvider.手动获取数据库相关信息 +*用户信息、权限、角色等使用UserContext.Current操作 +*Sys_QuartzOptionsService对增、删、改查、导入、导出、审核业务代码扩展参照ServiceFunFilter +*/ +using VOL.Core.BaseProvider; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; +using System.Linq; +using VOL.Core.Utilities; +using System.Linq.Expressions; +using VOL.Core.Extensions; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Http; +using VOL.System.IRepositories; +using VOL.Core.Quartz; +using Quartz; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace VOL.System.Services +{ + public partial class Sys_QuartzOptionsService + { + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly ISys_QuartzOptionsRepository _repository;//访问数据库 + private readonly ISchedulerFactory _schedulerFactory; + [ActivatorUtilitiesConstructor] + public Sys_QuartzOptionsService( + ISys_QuartzOptionsRepository dbRepository, + IHttpContextAccessor httpContextAccessor, + ISchedulerFactory schedulerFactory + ) + : base(dbRepository) + { + _httpContextAccessor = httpContextAccessor; + _repository = dbRepository; + _schedulerFactory = schedulerFactory; + //多租户会用到这init代码,其他情况可以不用 + //base.Init(dbRepository); + } + WebResponseContent webResponse = new WebResponseContent(); + public override WebResponseContent Add(SaveModel saveDataModel) + { + AddOnExecuting = (Sys_QuartzOptions options, object list) => + { + options.Status = (int)TriggerState.Paused; + return webResponse.OK(); + }; + AddOnExecuted = (Sys_QuartzOptions options, object list) => + { + return webResponse.OK(); + }; + return base.Add(saveDataModel); + } + + public override WebResponseContent Del(object[] keys, bool delList = true) + { + var ids = keys.Select(s => (Guid)(s.GetGuid())).ToArray(); + repository.FindAsIQueryable(x => ids.Contains(x.Id)).ToList().ForEach(options => + { + _schedulerFactory.Remove(options).GetAwaiter().GetResult(); + }); + + return base.Del(keys, delList); + } + + public override WebResponseContent Update(SaveModel saveModel) + { + UpdateOnExecuted = (Sys_QuartzOptions options, object addList, object updateList, List delKeys) => + { + _schedulerFactory.Update(options).GetAwaiter().GetResult(); + return webResponse.OK(); + }; + return base.Update(saveModel); + } + + /// + /// 手动执行一次 + /// + /// + /// + public async Task Run(Sys_QuartzOptions taskOptions) + { + return await _schedulerFactory.Run(taskOptions); + } + /// + /// 开启任务 + /// + /// + /// + /// + public async Task Start(Sys_QuartzOptions taskOptions) + { + var result = await _schedulerFactory.Start(taskOptions); + if (taskOptions.Status != (int)TriggerState.Normal) + { + taskOptions.Status = (int)TriggerState.Normal; + _repository.Update(taskOptions, x => new { x.Status }, true); + } + return result; + } + + /// + /// 暂停任务 + /// + /// + /// + /// + public async Task Pause(Sys_QuartzOptions taskOptions) + { + var result = await _schedulerFactory.Remove(taskOptions); + taskOptions.Status = (int)TriggerState.Paused; + _repository.Update(taskOptions, x => new { x.Status }, true); + return result; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Services/Quartz/Sys_QuartzLogService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Services/Quartz/Sys_QuartzLogService.cs new file mode 100644 index 0000000000000000000000000000000000000000..183a05f2bf0583514f3ab57cb8b1a0cf2d336469 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Services/Quartz/Sys_QuartzLogService.cs @@ -0,0 +1,27 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *代码由框架生成,此处任何更改都可能导致被代码生成器覆盖 + *所有业务编写全部应在Partial文件夹下Sys_QuartzLogService与ISys_QuartzLogService中编写 + */ +using VOL.System.IRepositories; +using VOL.System.IServices; +using VOL.Core.BaseProvider; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.System.Services +{ + public partial class Sys_QuartzLogService : ServiceBase + , ISys_QuartzLogService, IDependency + { + public Sys_QuartzLogService(ISys_QuartzLogRepository repository) + : base(repository) + { + Init(repository); + } + public static ISys_QuartzLogService Instance + { + get { return AutofacContainerModule.GetService(); } } + } + } diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Services/Quartz/Sys_QuartzOptionsService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Services/Quartz/Sys_QuartzOptionsService.cs new file mode 100644 index 0000000000000000000000000000000000000000..8c81e18025022df4d43aedda1b85cf9ff590a15e --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Services/Quartz/Sys_QuartzOptionsService.cs @@ -0,0 +1,27 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *代码由框架生成,此处任何更改都可能导致被代码生成器覆盖 + *所有业务编写全部应在Partial文件夹下Sys_QuartzOptionsService与ISys_QuartzOptionsService中编写 + */ +using VOL.System.IRepositories; +using VOL.System.IServices; +using VOL.Core.BaseProvider; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.System.Services +{ + public partial class Sys_QuartzOptionsService : ServiceBase + , ISys_QuartzOptionsService, IDependency + { + public Sys_QuartzOptionsService(ISys_QuartzOptionsRepository repository) + : base(repository) + { + Init(repository); + } + public static ISys_QuartzOptionsService Instance + { + get { return AutofacContainerModule.GetService(); } } + } + } diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Partial/Sys_DictionaryListService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Partial/Sys_DictionaryListService.cs new file mode 100644 index 0000000000000000000000000000000000000000..b7e689b8261392bba2159c752c2482f093e78d0a --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Partial/Sys_DictionaryListService.cs @@ -0,0 +1,27 @@ +using VOL.Core.BaseProvider; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; +using System.Linq; +using VOL.Core.Extensions; +using System.Collections.Generic; +using VOL.Core.Enums; + +namespace VOL.System.Services +{ + public partial class Sys_DictionaryListService + { + + public override PageGridData GetPageData(PageDataOptions pageData) + { + base.OrderByExpression = x => new Dictionary() { { + x.OrderNo,QueryOrderBy.Desc + }, + { + x.DicList_ID,QueryOrderBy.Asc + } + }; + return base.GetPageData(pageData); + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Partial/Sys_DictionaryService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Partial/Sys_DictionaryService.cs new file mode 100644 index 0000000000000000000000000000000000000000..8eb6e3ccb8525a76f68b7041a97c1a02e226c2c9 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Partial/Sys_DictionaryService.cs @@ -0,0 +1,286 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using VOL.Core.BaseProvider; +using VOL.Core.Const; +using VOL.Core.Enums; +using VOL.Core.Extensions; +using VOL.Core.Infrastructure; +using VOL.Core.Utilities; +using VOL.Entity.DomainModels; + +namespace VOL.System.Services +{ + public partial class Sys_DictionaryService + { + protected override void Init(IRepository repository) + { + } + /// + /// 代码生成器获取所有字典项编号(超级管理权限) + /// + /// + public async Task> GetBuilderDictionary() + { + return await repository.FindAsync(x => 1 == 1, s => s.DicNo); + } + + public List Dictionaries + { + get { return DictionaryManager.Dictionaries; } + } + + public object GetVueDictionary(string[] dicNos) + { + if (dicNos == null || dicNos.Count() == 0) return new string[] { }; + var dicConfig = DictionaryManager.GetDictionaries(dicNos, false).Select(s => new + { + dicNo = s.DicNo, + config = s.Config, + dbSql = s.DbSql, + list = s.Sys_DictionaryList.OrderByDescending(o => o.OrderNo) + .Select(list => new { key = list.DicValue, value = list.DicName }) + }).ToList(); + + object GetSourceData(string dicNo, string dbSql, object data) + { + // 2020.05.01增加根据用户信息加载字典数据源sql + dbSql = DictionaryHandler.GetCustomDBSql(dicNo, dbSql); + if (string.IsNullOrEmpty(dbSql)) + { + return data as object; + } + return repository.DapperContext.QueryList(dbSql, null); + } + return dicConfig.Select(item => new + { + item.dicNo, + item.config, + data = GetSourceData(item.dicNo, item.dbSql, item.list) + }).ToList(); + } + + + /// + /// 通过远程搜索 + /// + /// + /// + /// + public object GetSearchDictionary(string dicNo, string value) + { + if (string.IsNullOrEmpty(dicNo) || string.IsNullOrEmpty(value)) + { + return null; + } + // 2020.05.01增加根据用户信息加载字典数据源sql + string sql = Dictionaries.Where(x => x.DicNo == dicNo).FirstOrDefault()?.DbSql; + sql = DictionaryHandler.GetCustomDBSql(dicNo, sql); + if (string.IsNullOrEmpty(sql)) + { + return null; + } + sql = $"SELECT * FROM ({sql}) AS t WHERE value LIKE @value"; + return repository.DapperContext.QueryList(sql, new { value = "%" + value + "%" }); + } + + /// + /// 表单设置为远程查询,重置或第一次添加表单时,获取字典的key、value + /// + /// + /// + /// + public async Task GetRemoteDefaultKeyValue(string dicNo, string key) + { + return await Task.FromResult(1); + //if (string.IsNullOrEmpty(dicNo) || string.IsNullOrEmpty(key)) + //{ + // return null; + //} + //string sql = Dictionaries.Where(x => x.DicNo == dicNo).FirstOrDefault()?.DbSql; + //if (string.IsNullOrEmpty(sql)) + //{ + // return null; + //} + //sql = $"SELECT * FROM ({sql}) AS t WHERE t.key = @key"; + //return await Task.FromResult(repository.DapperContext.QueryFirst(sql, new { key })); + } + + + /// + /// table加载数据后刷新当前table数据的字典项(适用字典数据量比较大的情况) + /// + /// + /// + public object GetTableDictionary(Dictionary keyData) + { + // 2020.08.06增加pgsql获取数据源 + if (DBType.Name == DbCurrentType.PgSql.ToString()) + { + return GetPgSqlTableDictionary(keyData); + } + var dicInfo = Dictionaries.Where(x => keyData.ContainsKey(x.DicNo) && !string.IsNullOrEmpty(x.DbSql)) + .Select(x => new { x.DicNo, x.DbSql }) + .ToList(); + List list = new List(); + string keySql = DBType.Name == DbCurrentType.MySql.ToString() ? "t.key" : "t.[key]"; + dicInfo.ForEach(x => + { + if (keyData.TryGetValue(x.DicNo, out object[] data)) + { + // 2020.05.01增加根据用户信息加载字典数据源sql + string sql = DictionaryHandler.GetCustomDBSql(x.DicNo, x.DbSql); + sql = $"SELECT * FROM ({sql}) AS t WHERE " + + $"{keySql}" + + $" in @data"; + list.Add(new { key = x.DicNo, data = repository.DapperContext.QueryList(sql, new { data }) }); + } + }); + return list; + } + + /// + /// 2020.08.06增加pgsql获取数据源 + /// + /// + /// + public object GetPgSqlTableDictionary(Dictionary keyData) + { + var dicInfo = Dictionaries.Where(x => keyData.ContainsKey(x.DicNo) && !string.IsNullOrEmpty(x.DbSql)) + .Select(x => new { x.DicNo, x.DbSql }) + .ToList(); + List list = new List(); + + dicInfo.ForEach(x => + { + if (keyData.TryGetValue(x.DicNo, out object[] data)) + { + string sql = DictionaryHandler.GetCustomDBSql(x.DicNo, x.DbSql); + sql = $"SELECT * FROM ({sql}) AS t WHERE t.key=any(@data)"; + list.Add(new { key = x.DicNo, data = repository.DapperContext.QueryList(sql, new { data = data.Select(s => s.ToString()).ToList() }) }); + } + }); + return list; + } + + + public override PageGridData GetPageData(PageDataOptions pageData) + { + //增加查询条件 + base.QueryRelativeExpression = (IQueryable fun) => + { + return fun.Where(x => 1 == 1); + }; + return base.GetPageData(pageData); + } + public override WebResponseContent Update(SaveModel saveDataModel) + { + if (saveDataModel.MainData.DicKeyIsNullOrEmpty("DicNo") + || saveDataModel.MainData.DicKeyIsNullOrEmpty("Dic_ID")) + return base.Add(saveDataModel); + //判断修改的字典编号是否在其他ID存在 + string dicNo = saveDataModel.MainData["DicNo"].ToString().Trim(); + if (base.repository.Exists(x => x.DicNo == dicNo && x.Dic_ID != saveDataModel.MainData["Dic_ID"].GetInt())) + return new WebResponseContent().Error($"字典编号:{ dicNo}已存在。!"); + + base.UpdateOnExecuting = (Sys_Dictionary dictionary, object addList, object editList, List obj) => + { + List listObj = new List(); + listObj.AddRange(addList as List); + listObj.AddRange(editList as List); + + WebResponseContent _responseData = CheckKeyValue(listObj); + if (!_responseData.Status) return _responseData; + + dictionary.DbSql = SqlFilters(dictionary.DbSql); + return new WebResponseContent(true); + }; + return RemoveCache(base.Update(saveDataModel)); + + } + + + private WebResponseContent CheckKeyValue(List dictionaryLists) + { + WebResponseContent webResponse = new WebResponseContent(); + if (dictionaryLists == null || dictionaryLists.Count == 0) return webResponse.OK(); + + if (dictionaryLists.GroupBy(g => g.DicName).Any(x => x.Count() > 1)) + return webResponse.Error("【字典项名称】不能有重复的值"); + + if (dictionaryLists.GroupBy(g => g.DicValue).Any(x => x.Count() > 1)) + return webResponse.Error("【字典项Key】不能有重复的值"); + + return webResponse.OK(); + } + + private static string SqlFilters(string source) + { + if (string.IsNullOrEmpty(source)) return source; + + // source = source.Replace("'", "''"); + source = Regex.Replace(source, "-", "", RegexOptions.IgnoreCase); + //去除执行SQL语句的命令关键字 + source = Regex.Replace(source, "insert", "", RegexOptions.IgnoreCase); + // source = Regex.Replace(source, "sys.", "", RegexOptions.IgnoreCase); + source = Regex.Replace(source, "update", "", RegexOptions.IgnoreCase); + source = Regex.Replace(source, "delete", "", RegexOptions.IgnoreCase); + source = Regex.Replace(source, "drop", "", RegexOptions.IgnoreCase); + source = Regex.Replace(source, "truncate", "", RegexOptions.IgnoreCase); + source = Regex.Replace(source, "declare", "", RegexOptions.IgnoreCase); + source = Regex.Replace(source, "xp_cmdshell", "", RegexOptions.IgnoreCase); + source = Regex.Replace(source, "/add", "", RegexOptions.IgnoreCase); + source = Regex.Replace(source, "net user", "", RegexOptions.IgnoreCase); + //去除执行存储过程的命令关键字 + source = Regex.Replace(source, "exec", "", RegexOptions.IgnoreCase); + source = Regex.Replace(source, "execute", "", RegexOptions.IgnoreCase); + //去除系统存储过程或扩展存储过程关键字 + source = Regex.Replace(source, "xp_", "x p_", RegexOptions.IgnoreCase); + source = Regex.Replace(source, "sp_", "s p_", RegexOptions.IgnoreCase); + //防止16进制注入 + source = Regex.Replace(source, "0x", "0 x", RegexOptions.IgnoreCase); + + return source; + } + public override WebResponseContent Add(SaveModel saveDataModel) + { + if (saveDataModel.MainData.DicKeyIsNullOrEmpty("DicNo")) return base.Add(saveDataModel); + + string dicNo = saveDataModel.MainData["DicNo"].ToString(); + if (base.repository.Exists(x => x.DicNo == dicNo)) + return new WebResponseContent().Error("字典编号:" + dicNo + "已存在"); + + base.AddOnExecuting = (Sys_Dictionary dic, object obj) => + { + WebResponseContent _responseData = CheckKeyValue(obj as List); + if (!_responseData.Status) return _responseData; + + dic.DbSql = SqlFilters(dic.DbSql); + return new WebResponseContent(true); + }; + return RemoveCache(base.Add(saveDataModel)); + } + + public override WebResponseContent Del(object[] keys, bool delList = false) + { + //delKeys删除的key + base.DelOnExecuting = (object[] delKeys) => + { + return new WebResponseContent(true); + }; + //true将子表数据同时删除 + return RemoveCache(base.Del(keys, true)); + } + + private WebResponseContent RemoveCache(WebResponseContent webResponse) + { + if (webResponse.Status) + { + CacheContext.Remove(DictionaryManager.Key); + } + return webResponse; + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Partial/Sys_MenuService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Partial/Sys_MenuService.cs new file mode 100644 index 0000000000000000000000000000000000000000..c786d0e15b61315e894426efc34567609b6a6877 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Partial/Sys_MenuService.cs @@ -0,0 +1,304 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using VOL.Core.Extensions; +using VOL.Core.ManageUser; +using VOL.Core.Services; +using VOL.Core.Utilities; +using VOL.Entity; +using VOL.Entity.DomainModels; + +namespace VOL.System.Services +{ + public partial class Sys_MenuService + { + /// + /// 菜单静态化处理,每次获取菜单时先比较菜单是否发生变化,如果发生变化从数据库重新获取,否则直接获取_menus菜单 + /// + private static List _menus { get; set; } + + /// + /// 从数据库获取菜单时锁定的对象 + /// + private static object _menuObj = new object(); + + /// + /// 当前服务器的菜单版本 + /// + private static string _menuVersionn = ""; + + private const string _menuCacheKey = "inernalMenu"; + + /// + /// 编辑修改菜单时,获取所有菜单 + /// + /// + public async Task GetMenu() + { + // DBServerProvider.SqlDapper.q + return (await repository.FindAsync(x => 1 == 1, a => + new + { + id = a.Menu_Id, + parentId = a.ParentId, + name = a.MenuName, + a.MenuType, + a.OrderNo + })).OrderByDescending(a => a.OrderNo) + .ThenByDescending(q => q.parentId).ToList(); + + } + + private List GetAllMenu() + { + //每次比较缓存是否更新过,如果更新则重新获取数据 + string _cacheVersion = CacheContext.Get(_menuCacheKey); + if (_menuVersionn != "" && _menuVersionn == _cacheVersion) + { + return _menus ?? new List(); + } + lock (_menuObj) + { + if (_menuVersionn != "" && _menus != null && _menuVersionn == _cacheVersion) return _menus; + //2020.12.27增加菜单界面上不显示,但可以分配权限 + _menus = repository.FindAsIQueryable(x => x.Enable == 1 || x.Enable == 2) + .OrderByDescending(a => a.OrderNo) + .ThenByDescending(q => q.ParentId).ToList(); + + _menus.ForEach(x => + { + // 2022.03.26增移动端加菜单类型 + x.MenuType ??= 0; + if (!string.IsNullOrEmpty(x.Auth) && x.Auth.Length > 10) + { + try + { + x.Actions = x.Auth.DeserializeObject>(); + } + catch { } + } + if (x.Actions == null) x.Actions = new List(); + }); + + string cacheVersion = CacheContext.Get(_menuCacheKey); + if (string.IsNullOrEmpty(cacheVersion)) + { + cacheVersion = DateTime.Now.ToString("yyyyMMddHHMMssfff"); + CacheContext.Add(_menuCacheKey, cacheVersion); + } + else + { + _menuVersionn = cacheVersion; + } + } + return _menus; + } + + /// + /// 获取当前用户有权限查看的菜单 + /// + /// + public List GetCurrentMenuList() + { + int roleId = UserContext.Current.RoleId; + return GetUserMenuList(roleId); + } + + + public List GetUserMenuList(int roleId) + { + if (UserContext.IsRoleIdSuperAdmin(roleId)) + { + return GetAllMenu(); + } + List menuIds = UserContext.Current.GetPermissions(roleId).Select(x => x.Menu_Id).ToList(); + return GetAllMenu().Where(x => menuIds.Contains(x.Menu_Id)).ToList(); + } + + /// + /// 获取当前用户所有菜单与权限 + /// + /// + public async Task GetCurrentMenuActionList() + { + return await GetMenuActionList(UserContext.Current.RoleId); + } + + /// + /// 根据角色ID获取菜单与权限 + /// + /// + /// + public async Task GetMenuActionList(int roleId) + { + //2020.12.27增加菜单界面上不显示,但可以分配权限 + if (UserContext.IsRoleIdSuperAdmin(roleId)) + { + return await Task.Run(() => GetAllMenu() + .Where(c => c.MenuType == UserContext.MenuType) + .Select(x => + new + { + id = x.Menu_Id, + name = x.MenuName, + url = x.Url, + parentId = x.ParentId, + icon = x.Icon, + x.Enable, + x.TableName, // 2022.03.26增移动端加菜单类型 + permission = x.Actions.Select(s => s.Value).ToArray() + }).ToList()); + } + + var menu = from a in UserContext.Current.Permissions + join b in GetAllMenu().Where(c => c.MenuType == UserContext.MenuType) + on a.Menu_Id equals b.Menu_Id + orderby b.OrderNo descending + select new + { + id = a.Menu_Id, + name = b.MenuName, + url = b.Url, + parentId = b.ParentId, + icon = b.Icon, + b.Enable, + b.TableName, // 2022.03.26增移动端加菜单类型 + permission = a.UserAuthArr + }; + return menu.ToList(); + } + + /// + /// 新建或编辑菜单 + /// + /// + /// + public async Task Save(Sys_Menu menu) + { + WebResponseContent webResponse = new WebResponseContent(); + if (menu == null) return webResponse.Error("没有获取到提交的参数"); + if (menu.Menu_Id > 0 && menu.Menu_Id == menu.ParentId) return webResponse.Error("父级ID不能是当前菜单的ID"); + try + { + webResponse = menu.ValidationEntity(x => new { x.MenuName, x.TableName }); + if (!webResponse.Status) return webResponse; + if (menu.TableName != "/" && menu.TableName != ".") + { + // 2022.03.26增移动端加菜单类型判断 + Sys_Menu sysMenu = await repository.FindAsyncFirst(x => x.TableName == menu.TableName); + if (sysMenu != null) + { + sysMenu.MenuType ??= 0; + if (sysMenu.MenuType == menu.MenuType) + { + if ((menu.Menu_Id > 0 && sysMenu.Menu_Id != menu.Menu_Id) + || menu.Menu_Id <= 0) + { + return webResponse.Error($"视图/表名【{menu.TableName}】已被其他菜单使用"); + } + } + } + } + bool _changed = false; + if (menu.Menu_Id <= 0) + { + repository.Add(menu.SetCreateDefaultVal()); + } + else + { + //2020.05.07新增禁止选择上级角色为自己 + if (menu.Menu_Id == menu.ParentId) + { + return webResponse.Error($"父级id不能为自己"); + } + if (repository.Exists(x => x.ParentId == menu.Menu_Id && menu.ParentId == x.Menu_Id)) + { + return webResponse.Error($"不能选择此父级id,选择的父级id与当前菜单形成依赖关系"); + } + + _changed = repository.FindAsIQueryable(c => c.Menu_Id == menu.Menu_Id).Select(s => s.Auth).FirstOrDefault() != menu.Auth; + + repository.Update(menu.SetModifyDefaultVal(), p => new + { + p.ParentId, + p.MenuName, + p.Url, + p.Auth, + p.OrderNo, + p.Icon, + p.Enable, + p.MenuType,// 2022.03.26增移动端加菜单类型 + p.TableName, + p.ModifyDate, + p.Modifier + }); + } + await repository.SaveChangesAsync(); + + CacheContext.Add(_menuCacheKey, DateTime.Now.ToString("yyyyMMddHHMMssfff")); + if (_changed) + { + UserContext.Current.RefreshWithMenuActionChange(menu.Menu_Id); + } + _menus = null; + webResponse.OK("保存成功", menu); + } + catch (Exception ex) + { + webResponse.Error(ex.Message); + } + finally + { + Logger.Info($"表:{menu.TableName},菜单:{menu.MenuName},权限{menu.Auth},{(webResponse.Status ? "成功" : "失败")}{webResponse.Message}"); + } + return webResponse; + + } + + public async Task DelMenu(int menuId) + { + WebResponseContent webResponse = new WebResponseContent(); + + if (await repository.ExistsAsync(x => x.ParentId == menuId)) + { + return webResponse.Error("当前菜单存在子菜单,请先删除子菜单!"); + } + repository.Delete(new Sys_Menu() + { + Menu_Id = menuId + }, true); + CacheContext.Add(_menuCacheKey, DateTime.Now.ToString("yyyyMMddHHMMssfff")); + return webResponse.OK("删除成功"); + } + /// + /// 编辑菜单时,获取菜单信息 + /// + /// + /// + public async Task GetTreeItem(int menuId) + { + var sysMenu = (await base.repository.FindAsync(x => x.Menu_Id == menuId)) + .Select( + p => new + { + p.Menu_Id, + p.ParentId, + p.MenuName, + p.Url, + p.Auth, + p.OrderNo, + p.Icon, + p.Enable, + // 2022.03.26增移动端加菜单类型 + MenuType = p.MenuType ?? 0, + p.CreateDate, + p.Creator, + p.TableName, + p.ModifyDate + }).FirstOrDefault(); + return sysMenu; + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Partial/Sys_RoleService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Partial/Sys_RoleService.cs new file mode 100644 index 0000000000000000000000000000000000000000..0daa8e8779dbfa24dc518fdf9768c56a119d4389 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Partial/Sys_RoleService.cs @@ -0,0 +1,384 @@ +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading.Tasks; +using VOL.Core.Extensions; +using VOL.Core.ManageUser; +using VOL.Core.Services; +using VOL.Core.UserManager; +using VOL.Core.Utilities; +using VOL.Entity; +using VOL.Entity.DomainModels; + +namespace VOL.System.Services +{ + public partial class Sys_RoleService + { + private WebResponseContent _responseContent = new WebResponseContent(); + public override PageGridData GetPageData(PageDataOptions pageData) + { + //角色Id=1默认为超级管理员角色,界面上不显示此角色 + QueryRelativeExpression = (IQueryable queryable) => + { + if (UserContext.Current.IsSuperAdmin) + { + return queryable; + } + List roleIds = GetAllChildrenRoleIdAndSelf(); + return queryable.Where(x => roleIds.Contains(x.Role_Id)); + }; + return base.GetPageData(pageData); + } + /// + /// 编辑权限时,获取当前用户的所有菜单权限 + /// + /// + public async Task GetCurrentUserTreePermission() + { + return await GetUserTreePermission(UserContext.Current.RoleId); + } + + /// + /// 编辑权限时,获取指定角色的所有菜单权限 + /// + /// + /// + public async Task GetUserTreePermission(int roleId) + { + if (!UserContext.IsRoleIdSuperAdmin(roleId) && UserContext.Current.RoleId != roleId) + { + if (!(await GetAllChildrenAsync(UserContext.Current.RoleId)).Exists(x => x.Id == roleId)) + { + return _responseContent.Error("没有权限获取此角色的权限信息"); + } + } + //获取用户权限 + List permissions = UserContext.Current.GetPermissions(roleId); + //权限用户权限查询所有的菜单信息 + List menus = await Task.Run(() => Sys_MenuService.Instance.GetUserMenuList(roleId)); + //获取当前用户权限如:(Add,Search)对应的显示文本信息如:Add:添加,Search:查询 + var data = menus.Select(x => new + { + Id = x.Menu_Id, + Pid = x.ParentId, + Text = x.MenuName, + IsApp = x.MenuType == 1, + Actions = GetActions(x.Menu_Id, x.Actions, permissions, roleId) + }); + return _responseContent.OK(null, data); + } + + private List GetActions(int menuId, List menuActions, List permissions, int roleId) + { + if (UserContext.IsRoleIdSuperAdmin(roleId)) + { + return menuActions; + } + + return menuActions.Where(p => permissions + .Exists(w => menuId == w.Menu_Id + && w.UserAuthArr.Contains(p.Value))) + .ToList(); + } + + private List rolesChildren = new List(); + + /// + /// 编辑权限时获取当前用户下的所有角色与当前用户的菜单权限 + /// + /// + public async Task GetCurrentTreePermission() + { + _responseContent = await GetCurrentUserTreePermission(); + int roleId = UserContext.Current.RoleId; + return _responseContent.OK(null, new + { + tree = _responseContent.Data, + roles = await GetAllChildrenAsync(roleId) + }); + } + + private List roles = null; + + /// + /// 获取当前角色下的所有角色包括自己的角色Id + /// + /// + public List GetAllChildrenRoleIdAndSelf() + { + int roleId = UserContext.Current.RoleId; + List roleIds = GetAllChildren(roleId).Select(x => x.Id).ToList(); + roleIds.Add(roleId); + return roleIds; + } + + + /// + /// 获取当前角色下的所有角色 + /// + /// + /// + public List GetAllChildren(int roleId) + { + roles = GetAllRoleQueryable(roleId).ToList(); + return GetAllChildrenNodes(roleId); + } + + public async Task> GetAllChildrenAsync(int roleId) + { + roles = await GetAllRoleQueryable(roleId).ToListAsync(); + return GetAllChildrenNodes(roleId); + } + private IQueryable GetAllRoleQueryable(int roleId) + { + return repository + .FindAsIQueryable( + x => x.Enable == 1 && x.Role_Id > 1) + .Select( + s => new RoleNodes() + { + Id = s.Role_Id, + ParentId = s.ParentId, + RoleName = s.RoleName + }); + } + + public async Task> GetAllChildrenRoleIdAsync(int roleId) + { + return (await GetAllChildrenAsync(roleId)).Select(x => x.Id).ToList(); + } + + + public List GetAllChildrenRoleId(int roleId) + { + return GetAllChildren(roleId).Select(x => x.Id).ToList(); + } + + private List GetAllChildrenNodes(int roleId) + { + if (UserContext.IsRoleIdSuperAdmin(roleId)) return roles; + Dictionary completedRoles = new Dictionary(); + rolesChildren = GetChildren(roleId, completedRoles); + //2021.07.11增加无限递归异常数据移除当前节点 + if (rolesChildren.Any(x => x.Id == roleId)) + { + return rolesChildren.Where(x => x.Id != roleId).ToList(); + } + return rolesChildren; + } + /// + /// 递归获取所有子节点权限 + /// + /// + private List GetChildren(int roleId, Dictionary completedRoles) + { + roles.ForEach(x => + { + if (x.ParentId == roleId) + { + if (completedRoles.TryGetValue(x.Id, out bool isWrite)) + { + if (!isWrite) + { + roles.Where(x => x.Id == roleId).FirstOrDefault().ParentId = 0; + Logger.Error($"sys_roleservice获取子角色异常RoleContext,角色id:{x.Id}"); + Console.WriteLine($"sys_roleservice获取子角色异常RoleContext,角色id:{x.Id}"); + completedRoles[x.Id] = true; + } + return; + } + rolesChildren.Add(x); + + completedRoles[x.Id] = false; + + + if (x.Id != x.ParentId) + { + GetChildren(x.Id, completedRoles); + } + } + }); + return rolesChildren; + } + + /// + /// 保存角色权限 + /// + /// + /// + /// + public async Task SavePermission(List userPermissions, int roleId) + { + + string message = ""; + try + { + UserInfo user = UserContext.Current.UserInfo; + if (!(await GetAllChildrenAsync(user.Role_Id)).Exists(x => x.Id == roleId)) + return _responseContent.Error("没有权限修改此角色的权限信息"); + //当前用户的权限 + List permissions = UserContext.Current.Permissions; + + List originalMeunIds = new List(); + //被分配角色的权限 + List roleAuths = await repository.FindAsync(x => x.Role_Id == roleId); + List updateAuths = new List(); + foreach (UserPermissions x in userPermissions) + { + Permissions per = permissions.Where(p => p.Menu_Id == x.Id).FirstOrDefault(); + //不能分配超过当前用户的权限 + if (per == null) continue; + //per.UserAuthArr.Contains(a.Value)校验权限范围 + string[] arr = x.Actions == null || x.Actions.Count == 0 + ? new string[0] + : x.Actions.Where(a => per.UserAuthArr.Contains(a.Value)) + .Select(s => s.Value).ToArray(); + + //如果当前权限没有分配过,设置Auth_Id默认为0,表示新增的权限 + var auth = roleAuths.Where(r => r.Menu_Id == x.Id).Select(s => new { s.Auth_Id, s.AuthValue, s.Menu_Id }).FirstOrDefault(); + string newAuthValue = string.Join(",", arr); + //权限没有发生变化则不处理 + if (auth == null || auth.AuthValue != newAuthValue) + { + updateAuths.Add(new Sys_RoleAuth() + { + Role_Id = roleId, + Menu_Id = x.Id, + AuthValue = string.Join(",", arr), + Auth_Id = auth == null ? 0 : auth.Auth_Id, + ModifyDate = DateTime.Now, + Modifier = user.UserTrueName, + CreateDate = DateTime.Now, + Creator = user.UserTrueName + }); + } + else + { + originalMeunIds.Add(auth.Menu_Id); + } + + } + //更新权限 + repository.UpdateRange(updateAuths.Where(x => x.Auth_Id > 0), x => new + { + x.Menu_Id, + x.AuthValue, + x.Modifier, + x.ModifyDate + }); + //新增的权限 + repository.AddRange(updateAuths.Where(x => x.Auth_Id <= 0)); + + //获取权限取消的权限 + int[] authIds = roleAuths.Where(x => userPermissions.Select(u => u.Id) + .ToList().Contains(x.Menu_Id) || originalMeunIds.Contains(x.Menu_Id)) + .Select(s => s.Auth_Id) + .ToArray(); + List delAuths = roleAuths.Where(x => x.AuthValue != "" && !authIds.Contains(x.Auth_Id)).ToList(); + delAuths.ForEach(x => + { + x.AuthValue = ""; + }); + //将取消的权限设置为"" + repository.UpdateRange(delAuths, x => new + { + x.Menu_Id, + x.AuthValue, + x.Modifier, + x.ModifyDate + }); + + int addCount = updateAuths.Where(x => x.Auth_Id <= 0).Count(); + int updateCount = updateAuths.Where(x => x.Auth_Id > 0).Count(); + await repository.SaveChangesAsync(); + + string _version = DateTime.Now.ToString("yyyyMMddHHMMssfff"); + //标识缓存已更新 + base.CacheContext.Add(roleId.GetRoleIdKey(), _version); + + _responseContent.OK($"保存成功:新增加配菜单权限{addCount}条,更新菜单{updateCount}条,删除权限{delAuths.Count()}条"); + } + catch (Exception ex) + { + message = "异常信息:" + ex.Message + ex.StackTrace + ","; + } + finally + { + Logger.Info($"权限分配置:{message}{_responseContent.Message}"); + } + + return _responseContent; + } + + + public override WebResponseContent Add(SaveModel saveDataModel) + { + AddOnExecuting = (Sys_Role role, object obj) => + { + return ValidateRoleName(role, x => x.RoleName == role.RoleName); + }; + return RemoveCache(base.Add(saveDataModel)); + } + + public override WebResponseContent Del(object[] keys, bool delList = true) + { + return RemoveCache(base.Del(keys, delList)); + } + + private WebResponseContent ValidateRoleName(Sys_Role role, Expression> predicate) + { + if (repository.Exists(predicate)) + { + return _responseContent.Error($"角色名【{role.RoleName}】已存在,请设置其他角色名"); + } + return _responseContent.OK(); + } + + public override WebResponseContent Update(SaveModel saveModel) + { + UpdateOnExecuting = (Sys_Role role, object obj1, object obj2, List obj3) => + { + //2020.05.07新增禁止选择上级角色为自己 + if (role.Role_Id == role.ParentId) + { + return _responseContent.Error($"上级角色不能选择自己"); + } + if (role.Role_Id == UserContext.Current.RoleId) + { + return _responseContent.Error($"不能修改自己的角色"); + } + if (repository.Exists(x => x.Role_Id == role.ParentId && x.ParentId == role.Role_Id)) + { + return _responseContent.Error($"不能选择此上级角色,选择的上级角色与当前角色形成依赖关系"); + } + return ValidateRoleName(role, x => x.RoleName == role.RoleName && x.Role_Id != role.Role_Id); + }; + return RemoveCache(base.Update(saveModel)); + } + private WebResponseContent RemoveCache(WebResponseContent webResponse) + { + if (webResponse.Status) + { + RoleContext.Refresh(); + } + return webResponse; + } + } + + public class RoleNodes + { + public int Id { get; set; } + public int ParentId { get; set; } + public string RoleName { get; set; } + } + public class UserPermissions + { + public int Id { get; set; } + public int Pid { get; set; } + public string Text { get; set; } + public bool IsApp { get; set; } + public List Actions { get; set; } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Partial/Sys_UserService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Partial/Sys_UserService.cs new file mode 100644 index 0000000000000000000000000000000000000000..b9e8fb113f7dd61183603ec034a2c985789166ee --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Partial/Sys_UserService.cs @@ -0,0 +1,436 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using VOL.Core.Configuration; +using VOL.Core.Enums; +using VOL.Core.Extensions; +using VOL.Core.ManageUser; +using VOL.Core.Services; +using VOL.Core.Utilities; +using VOL.Entity.DomainModels; +using VOL.System.IRepositories; + +namespace VOL.System.Services +{ + public partial class Sys_UserService + { + private Microsoft.AspNetCore.Http.HttpContext _context; + private ISys_UserRepository _repository; + [ActivatorUtilitiesConstructor] + public Sys_UserService(IHttpContextAccessor httpContextAccessor, ISys_UserRepository repository) + : base(repository) + { + _context = httpContextAccessor.HttpContext; + _repository = repository; + } + WebResponseContent webResponse = new WebResponseContent(); + /// + /// WebApi登陆 + /// + /// + /// + /// + public async Task Login(LoginInfo loginInfo, bool verificationCode = true) + { + string msg = string.Empty; + // 2020.06.12增加验证码 + IMemoryCache memoryCache = _context.GetService(); + string cacheCode = (memoryCache.Get(loginInfo.UUID) ?? "").ToString(); + if (string.IsNullOrEmpty(cacheCode)) + { + return webResponse.Error("验证码已失效"); + } + if (cacheCode.ToLower() != loginInfo.VerificationCode.ToLower()) + { + memoryCache.Remove(loginInfo.UUID); + return webResponse.Error("验证码不正确"); + } + try + { + Sys_User user = await repository.FindAsIQueryable(x => x.UserName == loginInfo.UserName) + .FirstOrDefaultAsync(); + + if (user == null || loginInfo.Password.Trim().EncryptDES(AppSetting.Secret.User) != (user.UserPwd ?? "")) + return webResponse.Error(ResponseType.LoginError); + + string token = JwtHelper.IssueJwt(new UserInfo() + { + User_Id = user.User_Id, + UserName = user.UserName, + Role_Id = user.Role_Id + }); + user.Token = token; + webResponse.Data = new { token, userName = user.UserTrueName, img = user.HeadImageUrl }; + repository.Update(user, x => x.Token, true); + UserContext.Current.LogOut(user.User_Id); + + loginInfo.Password = string.Empty; + + return webResponse.OK(ResponseType.LoginSuccess); + } + catch (Exception ex) + { + msg = ex.Message + ex.StackTrace; + if (_context.GetService().IsDevelopment()) + { + throw new Exception(ex.Message + ex.StackTrace); + } + return webResponse.Error(ResponseType.ServerError); + } + finally + { + memoryCache.Remove(loginInfo.UUID); + Logger.Info(LoggerType.Login, loginInfo.Serialize(), webResponse.Message, msg); + } + } + + /// + ///当token将要过期时,提前置换一个新的token + /// + /// + public async Task ReplaceToken() + { + string error = ""; + UserInfo userInfo = null; + try + { + string requestToken = _context.Request.Headers[AppSetting.TokenHeaderName]; + requestToken = requestToken?.Replace("Bearer ", ""); + if (UserContext.Current.Token != requestToken) return webResponse.Error("Token已失效!"); + + if (JwtHelper.IsExp(requestToken)) return webResponse.Error("Token已过期!"); + + int userId = UserContext.Current.UserId; + userInfo = await + repository.FindFirstAsync(x => x.User_Id == userId, + s => new UserInfo() + { + User_Id = userId, + UserName = s.UserName, + UserTrueName = s.UserTrueName, + Role_Id = s.Role_Id, + RoleName = s.RoleName + }); + + if (userInfo == null) return webResponse.Error("未查到用户信息!"); + + string token = JwtHelper.IssueJwt(userInfo); + //移除当前缓存 + base.CacheContext.Remove(userId.GetUserIdKey()); + //只更新的token字段 + repository.Update(new Sys_User() { User_Id = userId, Token = token }, x => x.Token, true); + webResponse.OK(null, token); + } + catch (Exception ex) + { + error = ex.Message + ex.StackTrace + ex.Source; + webResponse.Error("token替换出错了.."); + } + finally + { + Logger.Info(LoggerType.ReplaceToeken, ($"用户Id:{userInfo?.User_Id},用户{userInfo?.UserTrueName}") + + (webResponse.Status ? "token替换成功" : "token替换失败"), null, error); + } + return webResponse; + } + + /// + /// 修改密码 + /// + /// + /// + public async Task ModifyPwd(string oldPwd, string newPwd) + { + oldPwd = oldPwd?.Trim(); + newPwd = newPwd?.Trim(); + string message = ""; + try + { + if (string.IsNullOrEmpty(oldPwd)) return webResponse.Error("旧密码不能为空"); + if (string.IsNullOrEmpty(newPwd)) return webResponse.Error("新密码不能为空"); + if (newPwd.Length < 6) return webResponse.Error("密码不能少于6位"); + + int userId = UserContext.Current.UserId; + string userCurrentPwd = await base.repository.FindFirstAsync(x => x.User_Id == userId, s => s.UserPwd); + + string _oldPwd = oldPwd.EncryptDES(AppSetting.Secret.User); + if (_oldPwd != userCurrentPwd) return webResponse.Error("旧密码不正确"); + + string _newPwd = newPwd.EncryptDES(AppSetting.Secret.User); + if (userCurrentPwd == _newPwd) return webResponse.Error("新密码不能与旧密码相同"); + + + repository.Update(new Sys_User + { + User_Id = userId, + UserPwd = _newPwd, + LastModifyPwdDate = DateTime.Now + }, x => new { x.UserPwd, x.LastModifyPwdDate }, true); + + webResponse.OK("密码修改成功"); + } + catch (Exception ex) + { + message = ex.Message; + webResponse.Error("服务器了点问题,请稍后再试"); + } + finally + { + if (message == "") + { + Logger.OK(LoggerType.ApiModifyPwd, "密码修改成功"); + } + else + { + Logger.Error(LoggerType.ApiModifyPwd, message); + } + } + return webResponse; + } + /// + /// 个人中心获取当前用户信息 + /// + /// + public async Task GetCurrentUserInfo() + { + var data = await base.repository + .FindAsIQueryable(x => x.User_Id == UserContext.Current.UserId) + .Select(s => new + { + s.UserName, + s.UserTrueName, + s.Address, + s.PhoneNo, + s.Email, + s.Remark, + s.Gender, + s.RoleName, + s.HeadImageUrl, + s.CreateDate + }) + .FirstOrDefaultAsync(); + return webResponse.OK(null, data); + } + + /// + /// 设置固定排序方式及显示用户过滤 + /// + /// + /// + public override PageGridData GetPageData(PageDataOptions pageData) + { + int roleId = -1; + //树形菜单传查询角色下所有用户 + if (pageData.Value != null) + { + roleId = pageData.Value.ToString().GetInt(); + } + QueryRelativeExpression = (IQueryable queryable) => + { + if (roleId <= 0) + { + if (UserContext.Current.IsSuperAdmin) return queryable; + roleId = UserContext.Current.RoleId; + } + + //查看用户时,只能看下自己角色下的所有用户 + List roleIds = Sys_RoleService + .Instance + .GetAllChildrenRoleId(roleId); + roleIds.Add(roleId); + //判断查询的角色是否越权 + if (roleId != UserContext.Current.RoleId && !roleIds.Contains(roleId)) + { + roleId = -999; + } + return queryable.Where(x => roleIds.Contains(x.Role_Id)); + }; + base.OrderByExpression = x => new Dictionary() { + { x.CreateDate, Core.Enums.QueryOrderBy.Desc }, + { x.User_Id,Core.Enums.QueryOrderBy.Desc} + }; + return base.GetPageData(pageData); + } + + /// + /// 新建用户,根据实际情况自行处理 + /// + /// + /// + public override WebResponseContent Add(SaveModel saveModel) + { + saveModel.MainData["RoleName"] = "无"; + base.AddOnExecute = (SaveModel userModel) => + { + int roleId = userModel?.MainData?["Role_Id"].GetInt() ?? 0; + if (roleId > 0 && !UserContext.Current.IsSuperAdmin) + { + string roleName = GetChildrenName(roleId); + if ((roleId == 1) || string.IsNullOrEmpty(roleName)) + return webResponse.Error("不能选择此角色"); + } + return webResponse.OK(); + }; + + + ///生成6位数随机密码 + string pwd = 6.GenerateRandomNumber(); + //在AddOnExecuting之前已经对提交的数据做过验证是否为空 + base.AddOnExecuting = (Sys_User user, object obj) => + { + user.UserName = user.UserName.Trim(); + if (repository.Exists(x => x.UserName == user.UserName)) + return webResponse.Error("用户名已经被注册"); + user.UserPwd = pwd.EncryptDES(AppSetting.Secret.User); + //设置默认头像 + return webResponse.OK(); + }; + + base.AddOnExecuted = (Sys_User user, object list) => + { + return webResponse.OK($"用户新建成功.帐号{user.UserName}密码{pwd}"); + }; + return base.Add(saveModel); ; + } + + /// + /// 删除用户拦截过滤 + /// 用户被删除后同时清空对应缓存 + /// + /// + /// + /// + public override WebResponseContent Del(object[] keys, bool delList = false) + { + base.DelOnExecuting = (object[] ids) => + { + if (!UserContext.Current.IsSuperAdmin) + { + int[] userIds = ids.Select(x => Convert.ToInt32(x)).ToArray(); + //校验只能删除当前角色下能看到的用户 + var xxx = repository.Find(x => userIds.Contains(x.User_Id)); + var delUserIds = repository.Find(x => userIds.Contains(x.User_Id), s => new { s.User_Id, s.Role_Id, s.UserTrueName }); + List roleIds = Sys_RoleService + .Instance + .GetAllChildrenRoleId(UserContext.Current.RoleId); + + string[] userNames = delUserIds.Where(x => !roleIds.Contains(x.Role_Id)) + .Select(s => s.UserTrueName) + .ToArray(); + if (userNames.Count() > 0) + { + return webResponse.Error($"没有权限删除用户:{string.Join(',', userNames)}"); + } + } + + return webResponse.OK(); + }; + base.DelOnExecuted = (object[] userIds) => + { + var objKeys = userIds.Select(x => x.GetInt().GetUserIdKey()); + base.CacheContext.RemoveAll(objKeys); + return new WebResponseContent() { Status = true }; + }; + return base.Del(keys, delList); + } + + private string GetChildrenName(int roleId) + { + //只能修改当前角色能看到的用户 + string roleName = Sys_RoleService + .Instance + .GetAllChildren(UserContext.Current.UserInfo.Role_Id).Where(x => x.Id == roleId) + .Select(s => s.RoleName).FirstOrDefault(); + return roleName; + } + + /// + /// 修改用户拦截过滤 + /// + /// + /// + /// + public override WebResponseContent Update(SaveModel saveModel) + { + UserInfo userInfo = UserContext.Current.UserInfo; + saveModel.MainData["RoleName"] = "无"; + //禁止修改用户名 + base.UpdateOnExecute = (SaveModel saveInfo) => + { + if (!UserContext.Current.IsSuperAdmin) + { + int roleId = saveModel.MainData["Role_Id"].GetInt(); + string roleName = GetChildrenName(roleId); + saveInfo.MainData.TryAdd("RoleName", roleName); + if (UserContext.IsRoleIdSuperAdmin(userInfo.Role_Id)) + { + return webResponse.OK(); + } + if (string.IsNullOrEmpty(roleName)) return webResponse.Error("不能选择此角色"); + } + + return webResponse.OK(); + }; + base.UpdateOnExecuting = (Sys_User user, object obj1, object obj2, List list) => + { + if (user.User_Id == userInfo.User_Id && user.Role_Id != userInfo.Role_Id) + return webResponse.Error("不能修改自己的角色"); + + var _user = repository.Find(x => x.User_Id == user.User_Id, + s => new { s.UserName, s.UserPwd }) + .FirstOrDefault(); + user.UserName = _user.UserName; + //Sys_User实体的UserPwd用户密码字段的属性不是编辑,此处不会修改密码。但防止代码生成器将密码字段的修改成了可编辑造成密码被修改 + user.UserPwd = _user.UserPwd; + return webResponse.OK(); + }; + //用户信息被修改后,将用户的缓存信息清除 + base.UpdateOnExecuted = (Sys_User user, object obj1, object obj2, List List) => + { + base.CacheContext.Remove(user.User_Id.GetUserIdKey()); + return new WebResponseContent(true); + }; + return base.Update(saveModel); + } + + /// + /// 导出处理 + /// + /// + /// + public override WebResponseContent Export(PageDataOptions pageData) + { + //限定只能导出当前角色能看到的所有用户 + QueryRelativeExpression = (IQueryable queryable) => + { + if (UserContext.Current.IsSuperAdmin) return queryable; + List roleIds = Sys_RoleService + .Instance + .GetAllChildrenRoleId(UserContext.Current.RoleId); + return queryable.Where(x => roleIds.Contains(x.Role_Id) || x.User_Id == UserContext.Current.UserId); + }; + + base.ExportOnExecuting = (List list, List ignoreColumn) => + { + if (!ignoreColumn.Contains("Role_Id")) + { + ignoreColumn.Add("Role_Id"); + } + if (!ignoreColumn.Contains("RoleName")) + { + ignoreColumn.Remove("RoleName"); + } + WebResponseContent responseData = new WebResponseContent(true); + return responseData; + }; + return base.Export(pageData); + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Sys_DictionaryListService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Sys_DictionaryListService.cs new file mode 100644 index 0000000000000000000000000000000000000000..76f440644eb33005e2d469efad98c1943feb486a --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Sys_DictionaryListService.cs @@ -0,0 +1,28 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *Date:2018-07-01 + * 此代码由框架生成,请勿随意更改 + */ +using VOL.System.IRepositories; +using VOL.System.IServices; +using VOL.Core.BaseProvider; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.System.Services +{ + public partial class Sys_DictionaryListService : ServiceBase, ISys_DictionaryListService, IDependency + { + public Sys_DictionaryListService(ISys_DictionaryListRepository repository) + : base(repository) + { + Init(repository); + } + public static ISys_DictionaryListService Instance + { + get { return AutofacContainerModule.GetService(); } + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Sys_DictionaryService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Sys_DictionaryService.cs new file mode 100644 index 0000000000000000000000000000000000000000..54c35c0e70125159dd07a6a4a8081a18aa1fb45b --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Sys_DictionaryService.cs @@ -0,0 +1,28 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *Date:2018-07-01 + * 此代码由框架生成,请勿随意更改 + */ +using VOL.System.IRepositories; +using VOL.System.IServices; +using VOL.Core.BaseProvider; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.System.Services +{ + public partial class Sys_DictionaryService : ServiceBase, ISys_DictionaryService, IDependency + { + public Sys_DictionaryService(ISys_DictionaryRepository repository) + : base(repository) + { + Init(repository); + } + public static ISys_DictionaryService Instance + { + get { return AutofacContainerModule.GetService(); } + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Sys_LogService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Sys_LogService.cs new file mode 100644 index 0000000000000000000000000000000000000000..e8a25c6f5ce9af51e1824b9bdf39cb4541e9fd1e --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Sys_LogService.cs @@ -0,0 +1,22 @@ +using VOL.System.IRepositories; +using VOL.System.IServices; +using VOL.Core.BaseProvider; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.System.Services +{ + public partial class Sys_LogService : ServiceBase, ISys_LogService, IDependency + { + public Sys_LogService(ISys_LogRepository repository) + : base(repository) + { + Init(repository); + } + public static ISys_LogService Instance + { + get { return AutofacContainerModule.GetService(); } + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Sys_MenuService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Sys_MenuService.cs new file mode 100644 index 0000000000000000000000000000000000000000..b5f2bfaba28fe1fc914c348640684a6ea0e6e582 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Sys_MenuService.cs @@ -0,0 +1,22 @@ +using VOL.System.IRepositories; +using VOL.System.IServices; +using VOL.Core.BaseProvider; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.System.Services +{ + public partial class Sys_MenuService : ServiceBase, ISys_MenuService, IDependency + { + public Sys_MenuService(ISys_MenuRepository repository) + : base(repository) + { + Init(repository); + } + public static ISys_MenuService Instance + { + get { return AutofacContainerModule.GetService(); } + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Sys_RoleService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Sys_RoleService.cs new file mode 100644 index 0000000000000000000000000000000000000000..1460b60d56f08fbdd5768f1bf752c0c462bbbb47 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Sys_RoleService.cs @@ -0,0 +1,28 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *Date:2018-07-01 + * 此代码由框架生成,请勿随意更改 + */ +using VOL.System.IRepositories; +using VOL.System.IServices; +using VOL.Core.BaseProvider; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.System.Services +{ + public partial class Sys_RoleService : ServiceBase, ISys_RoleService, IDependency + { + public Sys_RoleService(ISys_RoleRepository repository) + : base(repository) + { + Init(repository); + } + public static ISys_RoleService Instance + { + get { return AutofacContainerModule.GetService(); } + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Sys_UserService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Sys_UserService.cs new file mode 100644 index 0000000000000000000000000000000000000000..d99f24bba64cba7baefc288a372407742d69fa36 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Services/System/Sys_UserService.cs @@ -0,0 +1,28 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *Date:2018-07-01 + * 此代码由框架生成,请勿随意更改 + */ +using VOL.System.IRepositories; +using VOL.System.IServices; +using VOL.Core.BaseProvider; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.System.Services +{ + public partial class Sys_UserService : ServiceBase, ISys_UserService, IDependency + { + public Sys_UserService(ISys_UserRepository repository) + : base(repository) + { + Init(repository); + } + public static ISys_UserService Instance + { + get { return AutofacContainerModule.GetService(); } + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Partial/Sys_WorkFlowService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Partial/Sys_WorkFlowService.cs new file mode 100644 index 0000000000000000000000000000000000000000..fb93f86b23ffb17e66158bf235c90c2e74d16667 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Partial/Sys_WorkFlowService.cs @@ -0,0 +1,109 @@ +/* + *所有关于Sys_WorkFlow类的业务代码应在此处编写 +*可使用repository.调用常用方法,获取EF/Dapper等信息 +*如果需要事务请使用repository.DbContextBeginTransaction +*也可使用DBServerProvider.手动获取数据库相关信息 +*用户信息、权限、角色等使用UserContext.Current操作 +*Sys_WorkFlowService对增、删、改查、导入、导出、审核业务代码扩展参照ServiceFunFilter +*/ +using VOL.Core.BaseProvider; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; +using System.Linq; +using VOL.Core.Utilities; +using System.Linq.Expressions; +using VOL.Core.Extensions; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Http; +using VOL.System.IRepositories; +using System.Collections.Generic; + +namespace VOL.System.Services +{ + public partial class Sys_WorkFlowService + { + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly ISys_WorkFlowRepository _repository;//访问数据库 + private readonly ISys_WorkFlowStepRepository _stepRepository; + [ActivatorUtilitiesConstructor] + public Sys_WorkFlowService( + ISys_WorkFlowRepository dbRepository, + IHttpContextAccessor httpContextAccessor, + ISys_WorkFlowStepRepository stepRepository + ) + : base(dbRepository) + { + _httpContextAccessor = httpContextAccessor; + _repository = dbRepository; + _stepRepository = stepRepository; + //多租户会用到这init代码,其他情况可以不用 + //base.Init(dbRepository); + } + + WebResponseContent webResponse = new WebResponseContent(); + public override WebResponseContent Add(SaveModel saveDataModel) + { + saveDataModel.MainData["Enable"] = 1; + AddOnExecuting = (Sys_WorkFlow workFlow, object list) => + { + if (repository.Exists(x=>x.WorkTable==workFlow.WorkTable)) + { + return webResponse.Error("目前同一张表只能创建一个流程"); + } + List steps = list as List; + return webResponse.OK(); + }; + AddOnExecuted = (Sys_WorkFlow workFlow, object list) => + { + return webResponse.OK(); + }; + return base.Add(saveDataModel); + } + + public override WebResponseContent Update(SaveModel saveModel) + { + UpdateOnExecuting = (Sys_WorkFlow workFlow, object addList, object updateList, List delKeys) => + { + //新增的明细 + List add = addList as List; + var stepsClone = add.Serialize().DeserializeObject>(); + add.Clear(); + + var steps = _stepRepository.FindAsIQueryable(x => x.WorkFlow_Id == workFlow.WorkFlow_Id) + .Select(s => new { s.WorkStepFlow_Id, s.StepId }) + .ToList(); + //删除的节点 + var delIds = steps.Where(x => !stepsClone.Any(c => c.StepId == x.StepId)) + .Select(s => s.WorkStepFlow_Id).ToList(); + delKeys.AddRange(delKeys); + + //新增的节点 + var newSteps = stepsClone.Where(x => !steps.Any(c => c.StepId == x.StepId)) + .ToList(); + add.AddRange(newSteps); + + List update = updateList as List; + //修改的节点 + var updateSteps = stepsClone.Where(x => steps.Any(c => c.StepId == x.StepId)) + .ToList(); + update.AddRange(updateSteps); + updateSteps.ForEach(x => + { + x.WorkStepFlow_Id = steps.Where(c => c.StepId == x.StepId).Select(s => s.WorkStepFlow_Id).FirstOrDefault(); + foreach (var item in saveModel.DetailData) + { + if (item["StepId"].ToString()==x.StepId) + { + item["WorkFlow_Id"] = workFlow.WorkFlow_Id; + item["WorkStepFlow_Id"] = x.WorkStepFlow_Id; + } + } + }); + return webResponse.OK(); + }; + + return base.Update(saveModel); + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Partial/Sys_WorkFlowStepService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Partial/Sys_WorkFlowStepService.cs new file mode 100644 index 0000000000000000000000000000000000000000..3c27b753761617983ad37cfde882106d2c3217ff --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Partial/Sys_WorkFlowStepService.cs @@ -0,0 +1,43 @@ +/* + *所有关于Sys_WorkFlowStep类的业务代码应在此处编写 +*可使用repository.调用常用方法,获取EF/Dapper等信息 +*如果需要事务请使用repository.DbContextBeginTransaction +*也可使用DBServerProvider.手动获取数据库相关信息 +*用户信息、权限、角色等使用UserContext.Current操作 +*Sys_WorkFlowStepService对增、删、改查、导入、导出、审核业务代码扩展参照ServiceFunFilter +*/ +using VOL.Core.BaseProvider; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; +using System.Linq; +using VOL.Core.Utilities; +using System.Linq.Expressions; +using VOL.Core.Extensions; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Http; +using VOL.System.IRepositories; + +namespace VOL.System.Services +{ + public partial class Sys_WorkFlowStepService + { + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly ISys_WorkFlowStepRepository _repository;//访问数据库 + + [ActivatorUtilitiesConstructor] + public Sys_WorkFlowStepService( + ISys_WorkFlowStepRepository dbRepository, + IHttpContextAccessor httpContextAccessor + ) + : base(dbRepository) + { + _httpContextAccessor = httpContextAccessor; + _repository = dbRepository; + //多租户会用到这init代码,其他情况可以不用 + //base.Init(dbRepository); + } + + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Partial/Sys_WorkFlowTableService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Partial/Sys_WorkFlowTableService.cs new file mode 100644 index 0000000000000000000000000000000000000000..ac767af3c27949297160e1bb9f472cc064dc16be --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Partial/Sys_WorkFlowTableService.cs @@ -0,0 +1,63 @@ +/* + *所有关于Sys_WorkFlowTable类的业务代码应在此处编写 +*可使用repository.调用常用方法,获取EF/Dapper等信息 +*如果需要事务请使用repository.DbContextBeginTransaction +*也可使用DBServerProvider.手动获取数据库相关信息 +*用户信息、权限、角色等使用UserContext.Current操作 +*Sys_WorkFlowTableService对增、删、改查、导入、导出、审核业务代码扩展参照ServiceFunFilter +*/ +using VOL.Core.BaseProvider; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; +using System.Linq; +using VOL.Core.Utilities; +using System.Linq.Expressions; +using VOL.Core.Extensions; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Http; +using VOL.System.IRepositories; +using VOL.Core.ManageUser; +using VOL.Core.WorkFlow; + +namespace VOL.System.Services +{ + public partial class Sys_WorkFlowTableService + { + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly ISys_WorkFlowTableRepository _repository;//访问数据库 + private readonly ISys_WorkFlowTableStepRepository _stepRepository;//访问数据库 + [ActivatorUtilitiesConstructor] + public Sys_WorkFlowTableService( + ISys_WorkFlowTableRepository dbRepository, + IHttpContextAccessor httpContextAccessor, + ISys_WorkFlowTableStepRepository stepRepository + ) + : base(dbRepository) + { + _httpContextAccessor = httpContextAccessor; + _repository = dbRepository; + _stepRepository = stepRepository; + //多租户会用到这init代码,其他情况可以不用 + //base.Init(dbRepository); + } + + public override PageGridData GetPageData(PageDataOptions options) + { + if (!UserContext.Current.IsSuperAdmin) + { + var user = UserContext.Current.UserInfo; + //显示当前用户需要审批的数据 + var stepQuery = _stepRepository.FindAsIQueryable(x => (x.StepType == (int)AuditType.用户审批 && x.StepValue == user.User_Id) + || (x.StepType == (int)AuditType.角色审批 && x.StepValue == user.Role_Id) + || (x.StepType == (int)AuditType.部门审批 && x.StepValue == user.DeptId) + ); + QueryRelativeExpression = (IQueryable queryable) => + { + return queryable.Where(x => stepQuery.Any(c => x.WorkFlowTable_Id == c.WorkFlowTable_Id&&(x.CurrentOrderId == c.OrderId||c.AuditId==user.User_Id))); + }; + } + return base.GetPageData(options); + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Partial/Sys_WorkFlowTableStepService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Partial/Sys_WorkFlowTableStepService.cs new file mode 100644 index 0000000000000000000000000000000000000000..7159c4e0fd941eff0de13648e4a91587591680b3 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Partial/Sys_WorkFlowTableStepService.cs @@ -0,0 +1,41 @@ +/* + *所有关于Sys_WorkFlowTableStep类的业务代码应在此处编写 +*可使用repository.调用常用方法,获取EF/Dapper等信息 +*如果需要事务请使用repository.DbContextBeginTransaction +*也可使用DBServerProvider.手动获取数据库相关信息 +*用户信息、权限、角色等使用UserContext.Current操作 +*Sys_WorkFlowTableStepService对增、删、改查、导入、导出、审核业务代码扩展参照ServiceFunFilter +*/ +using VOL.Core.BaseProvider; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; +using System.Linq; +using VOL.Core.Utilities; +using System.Linq.Expressions; +using VOL.Core.Extensions; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Http; +using VOL.System.IRepositories; + +namespace VOL.System.Services +{ + public partial class Sys_WorkFlowTableStepService + { + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly ISys_WorkFlowTableStepRepository _repository;//访问数据库 + + [ActivatorUtilitiesConstructor] + public Sys_WorkFlowTableStepService( + ISys_WorkFlowTableStepRepository dbRepository, + IHttpContextAccessor httpContextAccessor + ) + : base(dbRepository) + { + _httpContextAccessor = httpContextAccessor; + _repository = dbRepository; + //多租户会用到这init代码,其他情况可以不用 + //base.Init(dbRepository); + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Sys_WorkFlowService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Sys_WorkFlowService.cs new file mode 100644 index 0000000000000000000000000000000000000000..6fa8582ceaf2a6b1c384bb6076d82c461d0447f2 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Sys_WorkFlowService.cs @@ -0,0 +1,27 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *代码由框架生成,此处任何更改都可能导致被代码生成器覆盖 + *所有业务编写全部应在Partial文件夹下Sys_WorkFlowService与ISys_WorkFlowService中编写 + */ +using VOL.System.IRepositories; +using VOL.System.IServices; +using VOL.Core.BaseProvider; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.System.Services +{ + public partial class Sys_WorkFlowService : ServiceBase + , ISys_WorkFlowService, IDependency + { + public Sys_WorkFlowService(ISys_WorkFlowRepository repository) + : base(repository) + { + Init(repository); + } + public static ISys_WorkFlowService Instance + { + get { return AutofacContainerModule.GetService(); } } + } + } diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Sys_WorkFlowStepService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Sys_WorkFlowStepService.cs new file mode 100644 index 0000000000000000000000000000000000000000..e69982973b86fc3af7ca2f5140d68bb5fe7aecc0 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Sys_WorkFlowStepService.cs @@ -0,0 +1,27 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *代码由框架生成,此处任何更改都可能导致被代码生成器覆盖 + *所有业务编写全部应在Partial文件夹下Sys_WorkFlowStepService与ISys_WorkFlowStepService中编写 + */ +using VOL.System.IRepositories; +using VOL.System.IServices; +using VOL.Core.BaseProvider; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.System.Services +{ + public partial class Sys_WorkFlowStepService : ServiceBase + , ISys_WorkFlowStepService, IDependency + { + public Sys_WorkFlowStepService(ISys_WorkFlowStepRepository repository) + : base(repository) + { + Init(repository); + } + public static ISys_WorkFlowStepService Instance + { + get { return AutofacContainerModule.GetService(); } } + } + } diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Sys_WorkFlowTableService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Sys_WorkFlowTableService.cs new file mode 100644 index 0000000000000000000000000000000000000000..ecd1ce903e9ac896f104527c1d1af71989079f0a --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Sys_WorkFlowTableService.cs @@ -0,0 +1,27 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *代码由框架生成,此处任何更改都可能导致被代码生成器覆盖 + *所有业务编写全部应在Partial文件夹下Sys_WorkFlowTableService与ISys_WorkFlowTableService中编写 + */ +using VOL.System.IRepositories; +using VOL.System.IServices; +using VOL.Core.BaseProvider; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.System.Services +{ + public partial class Sys_WorkFlowTableService : ServiceBase + , ISys_WorkFlowTableService, IDependency + { + public Sys_WorkFlowTableService(ISys_WorkFlowTableRepository repository) + : base(repository) + { + Init(repository); + } + public static ISys_WorkFlowTableService Instance + { + get { return AutofacContainerModule.GetService(); } } + } + } diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Sys_WorkFlowTableStepService.cs b/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Sys_WorkFlowTableStepService.cs new file mode 100644 index 0000000000000000000000000000000000000000..0eb3e32d824fc2bf86659de840df11f439cdad2a --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/Services/flow/Sys_WorkFlowTableStepService.cs @@ -0,0 +1,27 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *代码由框架生成,此处任何更改都可能导致被代码生成器覆盖 + *所有业务编写全部应在Partial文件夹下Sys_WorkFlowTableStepService与ISys_WorkFlowTableStepService中编写 + */ +using VOL.System.IRepositories; +using VOL.System.IServices; +using VOL.Core.BaseProvider; +using VOL.Core.Extensions.AutofacManager; +using VOL.Entity.DomainModels; + +namespace VOL.System.Services +{ + public partial class Sys_WorkFlowTableStepService : ServiceBase + , ISys_WorkFlowTableStepService, IDependency + { + public Sys_WorkFlowTableStepService(ISys_WorkFlowTableStepRepository repository) + : base(repository) + { + Init(repository); + } + public static ISys_WorkFlowTableStepService Instance + { + get { return AutofacContainerModule.GetService(); } } + } + } diff --git a/Pure_Vite_Net7/WebNet7/VOL.System/VOL.System.csproj b/Pure_Vite_Net7/WebNet7/VOL.System/VOL.System.csproj new file mode 100644 index 0000000000000000000000000000000000000000..b19ff6e69eb9635a72b77e9f6cad631fff99f07e --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.System/VOL.System.csproj @@ -0,0 +1,38 @@ + + + + + + + + + + + net7.0 + + Library + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/.config/dotnet-tools.json b/Pure_Vite_Net7/WebNet7/VOL.WebApi/.config/dotnet-tools.json new file mode 100644 index 0000000000000000000000000000000000000000..6b2cf2df65ab61160643f01cbbf7625b2354e9d9 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-ef": { + "version": "3.1.0", + "commands": [ + "dotnet-ef" + ] + } + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/ApiHomeController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/ApiHomeController.cs new file mode 100644 index 0000000000000000000000000000000000000000..dec07aaa26710baaace3e74a7ed6ef04c4fc211a --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/ApiHomeController.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using VOL.Core.EFDbContext; +using Microsoft.AspNetCore.Authorization; + +namespace VOL.WebApi.Controllers +{ + [AllowAnonymous] + [ApiExplorerSettings(IgnoreApi = true)] + public class ApiHomeController : Controller + { + public IActionResult Index() + { + + return new RedirectResult("/swagger/"); + } + + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/Builder/BuilderController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/Builder/BuilderController.cs new file mode 100644 index 0000000000000000000000000000000000000000..ecfa34cf71a9e95bca52089c81c9356fd1592f9c --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/Builder/BuilderController.cs @@ -0,0 +1,87 @@ +using VOL.Builder.IServices; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; +using VOL.Core.Filters; +using VOL.Entity.DomainModels; + +namespace VOL.WebApi.Controllers.Builder +{ + [JWTAuthorize] + [Route("/api/Builder")] + [ApiExplorerSettings(IgnoreApi = true,GroupName = "代码生成器_Builder")] + public class BuilderController : Controller + { + private ISys_TableInfoService Service; + public BuilderController(ISys_TableInfoService service) + { + Service = service; + } + [HttpPost] + [Route("GetTableTree")] + //[ApiActionPermission(ActionRolePermission.SuperAdmin)] + public async Task GetTableTree() + { + try + { + (string, string) builderInfo = await Service.GetTableTree(); + return Json(new { list = builderInfo.Item1, nameSpace = builderInfo.Item2 }); + } + catch (Exception ex) + { + + return Json(new { list = ex.Message + ex.StackTrace + ex.Source, nameSpace = ex.InnerException?.Message }); + } + } + + [Route("CreateVuePage")] + [ApiActionPermission(ActionRolePermission.SuperAdmin)] + [HttpPost] + public ActionResult CreateVuePage([FromBody] Sys_TableInfo sysTableInfo, string vuePath) + { + return Content(Service.CreateVuePage(sysTableInfo, vuePath)); + } + [Route("CreateModel")] + [ApiActionPermission(ActionRolePermission.SuperAdmin)] + [HttpPost] + public ActionResult CreateEntityModel([FromBody] Sys_TableInfo tableInfo) + { + return Content(Service.CreateEntityModel(tableInfo)); + } + [Route("Save")] + [ApiActionPermission(ActionRolePermission.SuperAdmin)] + [HttpPost] + public ActionResult SaveEidt([FromBody] Sys_TableInfo tableInfo) + { + return Json(Service.SaveEidt(tableInfo)); + } + [Route("CreateServices")] + [ApiActionPermission(ActionRolePermission.SuperAdmin)] + [HttpPost] + public ActionResult CreateServices(string tableName, string nameSpace, string foldername, bool? partial, bool? api) + { + return Content(Service.CreateServices(tableName, nameSpace, foldername, false, true)); + } + [Route("LoadTableInfo")] + [HttpPost] + public ActionResult LoadTable(int parentId, string tableName, string columnCNName, string nameSpace, string foldername, int table_Id, bool isTreeLoad) + { + return Json(Service.LoadTable(parentId, tableName, columnCNName, nameSpace, foldername, table_Id, isTreeLoad)); + + } + [Route("delTree")] + [ApiActionPermission(ActionRolePermission.SuperAdmin)] + [HttpPost] + public async Task DelTree(int table_Id) + { + return Json(await Service.DelTree(table_Id)); + } + [Route("syncTable")] + [ApiActionPermission(ActionRolePermission.SuperAdmin)] + [HttpPost] + public async Task SyncTable(string tableName) + { + return Json(await Service.SyncTable(tableName)); + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/Hubs/HomePageMessageHub.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/Hubs/HomePageMessageHub.cs new file mode 100644 index 0000000000000000000000000000000000000000..6b9da2ac501a9fecdefeb89cd6b2965533fcde0f --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/Hubs/HomePageMessageHub.cs @@ -0,0 +1,118 @@ +using Microsoft.AspNetCore.SignalR; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VOL.Core.CacheManager; +using VOL.Core.Extensions; +using VOL.Core.ManageUser; +using VOL.System.IServices; + +namespace VOL.WebApi.Controllers.Hubs +{ + /// + /// https://docs.microsoft.com/zh-cn/aspnet/core/signalr/introduction?view=aspnetcore-3.1 + /// https://docs.microsoft.com/zh-cn/aspnet/core/signalr/javascript-client?view=aspnetcore-6.0&tabs=visual-studio + /// + public class HomePageMessageHub : Hub + { + private readonly ICacheService _cacheService; + + + private static ConcurrentDictionary _connectionIds = new ConcurrentDictionary(); + + /// + /// 构造 注入 + /// + public HomePageMessageHub(ICacheService cacheService) + { + _cacheService = cacheService; + } + + /// + /// 建立连接时异步触发 + /// + /// + public override async Task OnConnectedAsync() + { + //Console.WriteLine($"建立连接{Context.ConnectionId}"); + _connectionIds[Context.ConnectionId] = Context.GetHttpContext().Request.Query["userName"].ToString(); + //添加到一个组下 + //await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users"); + //发送上线消息 + //await Clients.All.SendAsync("ReceiveHomePageMessage", 1, new { title = "系统消息", content = $"{Context.ConnectionId} 上线" }); + await base.OnConnectedAsync(); + } + + /// + /// 离开连接时异步触发 + /// + /// + /// + public override async Task OnDisconnectedAsync(Exception ex) + { + //Console.WriteLine($"断开连接{Context.ConnectionId}"); + //从组中删除 + // await Groups.RemoveFromGroupAsync(Context.ConnectionId, "SignalR Users"); + //可自行调用下线业务处理方法... + await UserOffline(); + //发送下线消息 + // await Clients.All.SendAsync("ReceiveHomePageMessage", 4, new { title = "系统消息", content = $"{Context.ConnectionId} 离线" }); + await base.OnDisconnectedAsync(ex); + } + + /// + /// 根据用户名获取所有的客户端 + /// + /// + /// + private IEnumerable GetCnnectionIds(string username) + { + foreach (var item in _connectionIds) + { + if (item.Value == username) + { + yield return item.Key; + } + } + } + + /// + /// 发送给指定的人 + /// + /// sys_user表的登陆帐号 + /// 发送的消息 + /// + public async Task SendHomeMessage(string username, string title, string message) + { + await Clients.Clients(GetCnnectionIds(username).ToArray()).SendAsync("ReceiveHomePageMessage", new + { + // username, + title, + message, + date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:sss") + }); + return true; + } + + /// + /// 断开连接 + /// + /// + public async Task UserOffline() + { + var cid = Context.ConnectionId;//也可以从缓存中获取ConnectionId + // await Clients.Client(cid).SendAsync("ReceiveHomePageMessage", 3, new { title = "系统消息", content = "离线成功" }); + //移除缓存 + if (_connectionIds.TryRemove(cid, out string value)) + { + } + await Task.CompletedTask; + return true; + } + + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/ObjectActionValidatorExampleController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/ObjectActionValidatorExampleController.cs new file mode 100644 index 0000000000000000000000000000000000000000..b82364bdb348fcedda5fe5fb49319cdc83ac6a57 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/ObjectActionValidatorExampleController.cs @@ -0,0 +1,111 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using VOL.Core.Filters; +using VOL.Core.ObjectActionValidator; +using VOL.Entity.DomainModels; + +namespace VOL.WebApi.Controllers +{ + /// + ///1、普通参数校验只需要标识属性:[ObjectGeneralValidatorFilter(ValidatorGeneral.xxx,ValidatorGeneral.xxx)], + ///需要在ValidatorGeneral枚举中添加枚举值(参数名),并在UseMethodsGeneralParameters方法中注入进去即可在任何地方重复使用 + /// + /// 2、model校验只需要标识属性[ObjectModelValidatorFilter(ValidatorModel.xxx)] + /// 需要在ValidatorModel枚举中添加枚举值(参数名), + /// 并在UseMethodsModelParameters方法中注入进去(注入时可以指定需要验证的字段)即可在任何地方重复使用 + /// --如果其他方法使用的是同一个model,但验证的字段不同,在ValidatorModel重新添加一个枚举值, + /// --并在UseMethodsModelParameters方法注入,添加新的指定字段即可 + /// + [JWTAuthorize, ApiController] + [Route("validatorExample")] + [ApiExplorerSettings(IgnoreApi = true)] + public class ObjectActionValidatorExampleController: Controller + { + public ObjectActionValidatorExampleController() + { + + } + + /// + /// 验证UserName与PhoneNo为必填 + /// + /// + /// + /// + [HttpPost, HttpGet, Route("test1")] + [ObjectGeneralValidatorFilter(ValidatorGeneral.UserName,ValidatorGeneral.PhoneNo)] + public IActionResult Test1(string userName,string phoneNo) + { + return Json("参数验证通过"); + } + + /// + /// 验证PhoneNo为必填 + /// + /// + /// + /// + [HttpPost, HttpGet, Route("test2")] + [ObjectGeneralValidatorFilter(ValidatorGeneral.PhoneNo)] + public IActionResult Test2(string userName, string phoneNo) + { + return Json("参数验证通过"); + } + + + /// + /// 验证字符长度与值大小 + /// + /// + /// + /// + [HttpPost, HttpGet, Route("test3")] + [ObjectGeneralValidatorFilter(ValidatorGeneral.Local, ValidatorGeneral.Qty)] + public IActionResult Test3(string local, string qty) + { + return Json("参数验证通过"); + } + + /// + /// Login配置的规则用户名与密码必填 + /// + /// + /// + [HttpPost, HttpGet, Route("Test4")] + [ObjectModelValidatorFilter(ValidatorModel.Login)] + public IActionResult Test4([FromBody]LoginInfo loginInfo) + { + return Json("参数验证通过"); + } + + /// + /// LoginOnlyPassWord配置的规则密码必填 + /// + /// + /// + [HttpPost, HttpGet, Route("Test5")] + [ObjectModelValidatorFilter(ValidatorModel.LoginOnlyPassWord)] + public IActionResult Test5([FromBody]LoginInfo loginInfo) + { + return Json("参数验证通过"); + } + + + /// + /// 同时验证实体LoginInfo与单个参数phoneNo + /// Login配置的规则用户名与密码必填,手机号必填 + /// + /// + /// + [HttpPost, HttpGet, Route("Test6")] + [ObjectModelValidatorFilter(ValidatorModel.Login)] + [ObjectGeneralValidatorFilter(ValidatorGeneral.PhoneNo)] + public IActionResult Test6([FromBody]LoginInfo loginInfo, string phoneNo) + { + return Json("参数验证通过"); + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_DictionaryController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_DictionaryController.cs new file mode 100644 index 0000000000000000000000000000000000000000..4e5609fc453de8310fcf2c060aa345032a6e50e4 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_DictionaryController.cs @@ -0,0 +1,63 @@ +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System.Threading.Tasks; +using VOL.Core.Controllers.Basic; +using VOL.Core.Extensions; +using VOL.Core.Filters; +using VOL.System.IServices; + +namespace VOL.System.Controllers +{ + public partial class Sys_DictionaryController + { + [HttpPost, Route("GetVueDictionary")] + [ApiActionPermission()] + public IActionResult GetVueDictionary([FromBody] string[] dicNos) + { + return Content(Service.GetVueDictionary(dicNos).Serialize()); + } + /// + /// table加载数据后刷新当前table数据的字典项(适用字典数据量比较大的情况) + /// + /// + /// + [HttpPost, Route("getTableDictionary")] + public IActionResult GetTableDictionary([FromBody] Dictionary keyData) + { + return Json(Service.GetTableDictionary(keyData)); + } + /// + /// 远程搜索 + /// + /// + /// + [HttpPost, Route("getSearchDictionary")] + public IActionResult GetSearchDictionary(string dicNo, string value) + { + return Json(Service.GetSearchDictionary(dicNo, value)); + } + + /// + /// 表单设置为远程查询,重置或第一次添加表单时,获取字典的key、value + /// + /// + /// + /// + [HttpPost, Route("getRemoteDefaultKeyValue")] + public async Task GetRemoteDefaultKeyValue(string dicNo, string key) + { + return Json(await Service.GetRemoteDefaultKeyValue(dicNo, key)); + } + /// + /// 代码生成器获取所有字典项(超级管理权限) + /// + /// + [HttpPost, Route("GetBuilderDictionary")] + // [ApiActionPermission(ActionRolePermission.SuperAdmin)] + public async Task GetBuilderDictionary() + { + return Json(await Service.GetBuilderDictionary()); + } + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_DictionaryListController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_DictionaryListController.cs new file mode 100644 index 0000000000000000000000000000000000000000..b94cc7d95d60ddb2398645d6a193c614681d0e50 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_DictionaryListController.cs @@ -0,0 +1,72 @@ +/* + *接口编写处... +*如果接口需要做Action的权限验证,请在Action上使用属性 +*如: [ApiActionPermission("Sys_DictionaryList",Enums.ActionPermissionOptions.Search)] + */ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Http; +using VOL.Entity.DomainModels; +using VOL.System.IServices; +using VOL.Core.Filters; + +namespace VOL.System.Controllers +{ + public partial class Sys_DictionaryListController + { + private readonly ISys_DictionaryListService _service;//访问业务代码 + private readonly IHttpContextAccessor _httpContextAccessor; + + [ActivatorUtilitiesConstructor] + public Sys_DictionaryListController( + ISys_DictionaryListService service, + IHttpContextAccessor httpContextAccessor + ) + : base(service) + { + _service = service; + _httpContextAccessor = httpContextAccessor; + } + /// + /// 导出明细 + /// (重写权限)将子表的权限指向主表权限 + /// + /// + /// + [ApiActionPermission("Sys_Dictionary", Core.Enums.ActionPermissionOptions.Export)] + [ApiExplorerSettings(IgnoreApi = false)] + [HttpPost, Route("Export")] + public override ActionResult Export([FromBody] PageDataOptions loadData) + { + return base.Export(loadData); + } + /// + /// 导入表数据Excel + /// (重写权限)将子表的权限指向主表权限 + /// + /// + /// + [HttpPost, Route("Import")] + [ApiActionPermission("Sys_Dictionary", Core.Enums.ActionPermissionOptions.Import)] + [ApiExplorerSettings(IgnoreApi = false)] + public override ActionResult Import(List fileInput) + { + return base.Import(fileInput); + } + /// + /// 下载导入Excel模板 + /// (重写权限)将子表的权限指向主表权限 + /// + /// + [HttpGet, Route("DownLoadTemplate")] + [ApiActionPermission("Sys_Dictionary", Core.Enums.ActionPermissionOptions.Import)] + [ApiExplorerSettings(IgnoreApi = false)] + public override ActionResult DownLoadTemplate() + { + return base.DownLoadTemplate(); + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_MenuController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_MenuController.cs new file mode 100644 index 0000000000000000000000000000000000000000..c1eb2dd9bc3ab639dd4e4c2384169b42a49e7231 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_MenuController.cs @@ -0,0 +1,58 @@ +using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; +using VOL.Core.Enums; +using VOL.Core.Filters; +using VOL.Entity.DomainModels; +using VOL.System.IServices; + +namespace VOL.System.Controllers +{ + public partial class Sys_MenuController + { + /// + /// + /// + /// + [HttpGet, HttpPost, Route("getTreeMenu")] + //2019.10.24屏蔽用户查询自己权限菜单 + // [ApiActionPermission("Sys_Menu", ActionPermissionOptions.Search)] + public async Task GetTreeMenu() + { + return Json(await _service.GetCurrentMenuActionList()); + } + [HttpPost, Route("getMenu")] + [ApiActionPermission("Sys_Menu", ActionPermissionOptions.Search)] + public async Task GetMenu() + { + return Json(await _service.GetMenu()); + } + + [HttpPost, Route("getTreeItem")] + [ApiActionPermission("Sys_Menu", "1", ActionPermissionOptions.Search)] + public async Task GetTreeItem(int menuId) + { + return Json(await _service.GetTreeItem(menuId)); + } + + //[ActionPermission("Sys_Menu", "1", ActionPermissionOptions.Add)] + //只有角色ID为1的才能进行保存操作 + [HttpPost, Route("save"), ApiActionPermission(ActionRolePermission.SuperAdmin)] + public async Task Save([FromBody] Sys_Menu menu) + { + return Json(await _service.Save(menu)); + } + + /// + /// 限制只能超级管理员才删除菜单 + /// + /// + /// + [ApiActionPermission(ActionRolePermission.SuperAdmin)] + [HttpPost, Route("delMenu")] + public async Task DelMenu(int menuId) + { + return Json(await Service.DelMenu(menuId)); + } + + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_QuartzLogController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_QuartzLogController.cs new file mode 100644 index 0000000000000000000000000000000000000000..4d4ebb1bc90966658bcdafd174856b49f9430361 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_QuartzLogController.cs @@ -0,0 +1,33 @@ +/* + *接口编写处... +*如果接口需要做Action的权限验证,请在Action上使用属性 +*如: [ApiActionPermission("Sys_QuartzLog",Enums.ActionPermissionOptions.Search)] + */ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Http; +using VOL.Entity.DomainModels; +using VOL.System.IServices; + +namespace VOL.System.Controllers +{ + public partial class Sys_QuartzLogController + { + private readonly ISys_QuartzLogService _service;//访问业务代码 + private readonly IHttpContextAccessor _httpContextAccessor; + + [ActivatorUtilitiesConstructor] + public Sys_QuartzLogController( + ISys_QuartzLogService service, + IHttpContextAccessor httpContextAccessor + ) + : base(service) + { + _service = service; + _httpContextAccessor = httpContextAccessor; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_QuartzOptionsController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_QuartzOptionsController.cs new file mode 100644 index 0000000000000000000000000000000000000000..23821f82f4c760e4d01440d439331b4a99d2d69e --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_QuartzOptionsController.cs @@ -0,0 +1,83 @@ +/* + *接口编写处... +*如果接口需要做Action的权限验证,请在Action上使用属性 +*如: [ApiActionPermission("Sys_QuartzOptions",Enums.ActionPermissionOptions.Search)] + */ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Http; +using VOL.Entity.DomainModels; +using VOL.System.IServices; +using VOL.Core.Filters; +using VOL.Core.Enums; + +namespace VOL.System.Controllers +{ + public partial class Sys_QuartzOptionsController + { + private readonly ISys_QuartzOptionsService _service;//访问业务代码 + private readonly IHttpContextAccessor _httpContextAccessor; + + [ActivatorUtilitiesConstructor] + public Sys_QuartzOptionsController( + ISys_QuartzOptionsService service, + IHttpContextAccessor httpContextAccessor + ) + : base(service) + { + _service = service; + _httpContextAccessor = httpContextAccessor; + } + + /// + /// api加上属性 [ApiTask] + /// + /// + [ApiTask] + [HttpGet, HttpPost, Route("test")] + public IActionResult Test() + { + return Content(DateTime.Now.ToString("yyyy-MM-dd HH:mm:sss")); + } + + /// + /// 手动执行一次 + /// + /// + /// + [Route("run"), HttpPost] + [ActionPermission(ActionPermissionOptions.Update)] + public async Task Run([FromBody] Sys_QuartzOptions taskOptions) + { + return await Service.Run(taskOptions); + } + /// + /// 开启任务 + /// + /// + /// + /// + [Route("start"), HttpPost] + [ActionPermission(ActionPermissionOptions.Update)] + public async Task Start([FromBody] Sys_QuartzOptions taskOptions) + { + return await Service.Start(taskOptions); + } + + /// + /// 暂停任务 + /// + /// + /// + /// + [Route("pause"), HttpPost] + [ActionPermission(ActionPermissionOptions.Update)] + public async Task Pause([FromBody] Sys_QuartzOptions taskOptions) + { + return await Service.Pause(taskOptions); + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_RoleController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_RoleController.cs new file mode 100644 index 0000000000000000000000000000000000000000..1800f3cd954c436cb8d0ed7c506ec50943bd0c45 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_RoleController.cs @@ -0,0 +1,74 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using VOL.Core.Controllers.Basic; +using VOL.Core.Enums; +using VOL.Core.Filters; +using VOL.Core.ManageUser; +using VOL.Core.UserManager; +using VOL.Core.Utilities; +using VOL.Entity.AttributeManager; +using VOL.Entity.DomainModels; +using VOL.System.IServices; +using VOL.System.Repositories; +using VOL.System.Services; + +namespace VOL.System.Controllers +{ + [Route("api/role")] + public partial class Sys_RoleController + { + [HttpPost, Route("getCurrentTreePermission")] + [ApiActionPermission(ActionPermissionOptions.Search)] + public async Task GetCurrentTreePermission() + { + return Json(await Service.GetCurrentTreePermission()); + } + + [HttpPost, Route("getUserTreePermission")] + [ApiActionPermission(ActionPermissionOptions.Search)] + public async Task GetUserTreePermission(int roleId) + { + return Json(await Service.GetUserTreePermission(roleId)); + } + + [HttpPost, Route("savePermission")] + [ApiActionPermission(ActionPermissionOptions.Update)] + public async Task SavePermission([FromBody] List userPermissions, int roleId) + { + return Json(await Service.SavePermission(userPermissions, roleId)); + } + + /// + /// 获取当前角色下的所有角色 + /// + /// + + [HttpPost, Route("getUserChildRoles")] + [ApiActionPermission(ActionPermissionOptions.Search)] + public IActionResult GetUserChildRoles() + { + int roleId = UserContext.Current.RoleId; + var data = RoleContext.GetAllChildren(UserContext.Current.RoleId); + + if (UserContext.Current.IsSuperAdmin) + { + return Json(WebResponseContent.Instance.OK(null, data)); + } + //不是超级管理,将自己的角色查出来,在树形菜单上作为根节点 + var self = Sys_RoleRepository.Instance.FindAsIQueryable(x => x.Role_Id == roleId) + .Select(s => new VOL.Core.UserManager.RoleNodes() + { + Id = s.Role_Id, + ParentId = 0,//将自己的角色作为root节点 + RoleName = s.RoleName + }).ToList(); + data.AddRange(self); + return Json(WebResponseContent.Instance.OK(null, data)); + } + } +} + + diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_UserController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_UserController.cs new file mode 100644 index 0000000000000000000000000000000000000000..2f4afd6c1e9096b5d121c540bb60b6b70bc8a8b3 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_UserController.cs @@ -0,0 +1,179 @@ + +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Concurrent; +using System.Linq; +using System.Linq.Expressions; +using System.Threading.Tasks; +using VOL.Core.CacheManager; +using VOL.Core.Configuration; +using VOL.Core.Controllers.Basic; +using VOL.Core.DBManager; +using VOL.Core.EFDbContext; +using VOL.Core.Enums; +using VOL.Core.Extensions; +using VOL.Core.Filters; +using VOL.Core.Infrastructure; +using VOL.Core.ManageUser; +using VOL.Core.ObjectActionValidator; +using VOL.Core.Services; +using VOL.Core.Utilities; +using VOL.Entity.AttributeManager; +using VOL.Entity.DomainModels; +using VOL.System.IRepositories; +using VOL.System.IServices; +using VOL.System.Repositories; + +namespace VOL.System.Controllers +{ + [Route("api/User")] + public partial class Sys_UserController + { + private ISys_UserRepository _userRepository; + private ICacheService _cache; + [ActivatorUtilitiesConstructor] + public Sys_UserController( + ISys_UserService userService, + ISys_UserRepository userRepository, + ICacheService cahce + ) + : base(userService) + { + _userRepository = userRepository; + _cache = cahce; + } + + [HttpPost, HttpGet, Route("login"), AllowAnonymous] + [ObjectModelValidatorFilter(ValidatorModel.Login)] + public async Task Login([FromBody] LoginInfo loginInfo) + { + return Json(await Service.Login(loginInfo)); + } + + private readonly ConcurrentDictionary _lockCurrent = new ConcurrentDictionary(); + [HttpPost, Route("replaceToken")] + public IActionResult ReplaceToken() + { + WebResponseContent responseContent = new WebResponseContent(); + string error = ""; + string key = $"rp:Token:{UserContext.Current.UserId}"; + UserInfo userInfo = null; + try + { + //如果5秒内替换过token,直接使用最新的token(防止一个页面多个并发请求同时替换token导致token错位) + if (_cache.Exists(key)) + { + return Json(responseContent.OK(null, _cache.Get(key))); + } + var _obj = _lockCurrent.GetOrAdd(UserContext.Current.UserId, new object() { }); + lock (_obj) + { + if (_cache.Exists(key)) + { + return Json(responseContent.OK(null, _cache.Get(key))); + } + string requestToken = HttpContext.Request.Headers[AppSetting.TokenHeaderName]; + requestToken = requestToken?.Replace("Bearer ", ""); + + if (JwtHelper.IsExp(requestToken)) return Json(responseContent.Error("Token已过期!")); + + int userId = UserContext.Current.UserId; + + userInfo = _userRepository.FindAsIQueryable(x => x.User_Id == userId).Select( + s => new UserInfo() + { + User_Id = userId, + UserName = s.UserName, + UserTrueName = s.UserTrueName, + Role_Id = s.Role_Id, + RoleName = s.RoleName + }).FirstOrDefault(); + + if (userInfo == null) return Json(responseContent.Error("未查到用户信息!")); + + string token = JwtHelper.IssueJwt(userInfo); + //移除当前缓存 + _cache.Remove(userId.GetUserIdKey()); + //只更新的token字段 + _userRepository.Update(new Sys_User() { User_Id = userId, Token = token }, x => x.Token, true); + //添加一个5秒缓存 + _cache.Add(key, token, 5); + responseContent.OK(null, token); + } + } + catch (Exception ex) + { + error = ex.Message + ex.StackTrace; + responseContent.Error("token替换异常"); + } + finally + { + _lockCurrent.TryRemove(UserContext.Current.UserId, out object val); + string _message = $"用户{userInfo?.User_Id}_{userInfo?.UserTrueName},({(responseContent.Status ? "token替换成功": "token替换失败")})"; + Logger.Info(LoggerType.ReplaceToeken, _message, null, error); + } + return Json(responseContent); + } + + + [HttpPost, Route("modifyPwd")] + [ApiActionPermission] + //通过ObjectGeneralValidatorFilter校验参数,不再需要if esle判断OldPwd与NewPwd参数 + [ObjectGeneralValidatorFilter(ValidatorGeneral.OldPwd, ValidatorGeneral.NewPwd)] + public async Task ModifyPwd(string oldPwd, string newPwd) + { + return Json(await Service.ModifyPwd(oldPwd, newPwd)); + } + + [HttpPost, Route("getCurrentUserInfo")] + public async Task GetCurrentUserInfo() + { + return Json(await Service.GetCurrentUserInfo()); + } + + //只能超级管理员才能修改密码 + //2020.08.01增加修改密码功能 + [HttpPost, Route("modifyUserPwd"), ApiActionPermission(ActionRolePermission.SuperAdmin)] + public IActionResult ModifyUserPwd(string password, string userName) + { + WebResponseContent webResponse = new WebResponseContent(); + if (string.IsNullOrEmpty(password) || string.IsNullOrEmpty(userName)) + { + return Json(webResponse.Error("参数不完整")); + } + if (password.Length < 6) return Json(webResponse.Error("密码长度不能少于6位")); + + ISys_UserRepository repository = Sys_UserRepository.Instance; + Sys_User user = repository.FindFirst(x => x.UserName == userName); + if (user == null) + { + return Json(webResponse.Error("用户不存在")); + } + user.UserPwd = password.EncryptDES(AppSetting.Secret.User); + repository.Update(user, x => new { x.UserPwd }, true); + //如果用户在线,强制下线 + UserContext.Current.LogOut(user.User_Id); + return Json(webResponse.OK("密码修改成功")); + } + + /// + /// 2020.06.15增加登陆验证码 + /// + /// + [HttpGet, Route("getVierificationCode"), AllowAnonymous] + public IActionResult GetVierificationCode() + { + string code = VierificationCode.RandomText(); + var data = new + { + img = VierificationCode.CreateBase64Imgage(code), + uuid = Guid.NewGuid() + }; + HttpContext.GetService().Set(data.uuid.ToString(), code, new TimeSpan(0, 5, 0)); + return Json(data); + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_WorkFlowController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_WorkFlowController.cs new file mode 100644 index 0000000000000000000000000000000000000000..8272d15b069c6da55010149157272020c2f795a8 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_WorkFlowController.cs @@ -0,0 +1,139 @@ +/* + *接口编写处... +*如果接口需要做Action的权限验证,请在Action上使用属性 +*如: [ApiActionPermission("Sys_WorkFlow",Enums.ActionPermissionOptions.Search)] + */ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Http; +using VOL.Entity.DomainModels; +using VOL.System.IServices; +using VOL.Core.WorkFlow; +using VOL.System.IRepositories; +using System.Linq; +using Microsoft.EntityFrameworkCore; +using VOL.Core.ManageUser; +using VOL.Core.Services; + +namespace VOL.System.Controllers +{ + public partial class Sys_WorkFlowController + { + private readonly ISys_WorkFlowService _service;//访问业务代码 + private readonly ISys_UserRepository _userRepository; + private readonly ISys_RoleRepository _roleRepository; + private readonly ISys_WorkFlowTableRepository _workFlowTableRepository; + private readonly IHttpContextAccessor _httpContextAccessor; + + [ActivatorUtilitiesConstructor] + public Sys_WorkFlowController( + ISys_WorkFlowService service, + ISys_UserRepository userRepository, + ISys_RoleRepository roleRepository, + ISys_WorkFlowTableRepository workFlowTableRepository, + IHttpContextAccessor httpContextAccessor + ) + : base(service) + { + _service = service; + _userRepository = userRepository; + _roleRepository = roleRepository; + _workFlowTableRepository = workFlowTableRepository; + _httpContextAccessor = httpContextAccessor; + } + /// + /// 获取工作流程表数据源 + /// + /// + [HttpGet, Route("getTableInfo")] + public IActionResult GetTableInfo() + { + return Json(WorkFlowContainer.GetDic()); + } + + /// + /// 获取流程节点数据源(用户与角色) + /// + /// + [HttpGet, Route("getNodeDic")] + public async Task GetNodeDic() + { + var data = new + { + users = await _userRepository.FindAsIQueryable(x => true).Select(s => new { key = s.User_Id, value = s.UserTrueName }).ToListAsync(), + roles = await _roleRepository.FindAsIQueryable(x => true).Select(s => new { key = s.Role_Id, value = s.RoleName }).ToListAsync(), + dept = new string[] { }//部门表,暂时没有 + }; + return Json(data); + } + /// + /// 获取单据的审批流程进度 + /// + /// + /// + /// + [HttpGet, Route("getSteps")] + public async Task GetSteps(string tableName, string id) + { + var flow = await _workFlowTableRepository.FindAsIQueryable(x => x.WorkTable == tableName && x.WorkTableKey == id) + .Include(x => x.Sys_WorkFlowTableStep) + .FirstOrDefaultAsync(); + + if (flow == null) + { + return Json(new { }); + } + + var user = UserContext.Current.UserInfo; + List stepValues = flow.Sys_WorkFlowTableStep.Select(s => s.StepValue ?? 0).ToList(); + + var auditUsers = flow.Sys_WorkFlowTableStep.Where(x => x.AuditId > 0).Select(s => s.AuditId).ToArray(); + var users = await _userRepository.FindAsIQueryable(x => auditUsers.Contains(x.User_Id)) + .Select(u => new { u.User_Id, u.UserTrueName }).ToListAsync(); + + var steps = flow.Sys_WorkFlowTableStep + .Select(c => new + { + c.AuditId, + Auditor = users.Where(us => us.User_Id == c.AuditId).Select(us => us.UserTrueName).FirstOrDefault(), + c.AuditDate, + c.AuditStatus, + c.Remark, + c.StepValue, + c.StepName, + c.OrderId, + c.Enable, + //判断是按角色审批 还是用户帐号审批 + isCurrentUser = (c.AuditStatus ?? 0) == (int)AuditStatus.审核中 && c.OrderId == flow.CurrentOrderId && GetAuditStepValue(c.StepType) == c.StepValue, + isCurrent = c.OrderId == flow.CurrentOrderId && c.AuditStatus != (int)AuditStatus.审核通过 + }).OrderBy(o => o.OrderId); + var data = new + { + step = flow.CurrentOrderId, + flow.AuditStatus, + list = steps.Where(x => (x.Enable == null || x.Enable > 0)).ToList(), + his = steps.Where(x => x.AuditId > 0 &&x.AuditStatus>0 && x.Enable == 0).ToList(), + }; + + return Json(data); + } + + private int GetAuditStepValue(int? stepType) + { + if (stepType == (int)AuditType.角色审批) + { + return UserContext.Current.RoleId; + } + if (stepType == (int)AuditType.部门审批) + { + return UserContext.Current.UserInfo.DeptId; + } + //按用户审批 + return UserContext.Current.UserId; + + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_WorkFlowStepController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_WorkFlowStepController.cs new file mode 100644 index 0000000000000000000000000000000000000000..6191e3e35d644cf5db7b9a8e1881ec257022f442 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_WorkFlowStepController.cs @@ -0,0 +1,33 @@ +/* + *接口编写处... +*如果接口需要做Action的权限验证,请在Action上使用属性 +*如: [ApiActionPermission("Sys_WorkFlowStep",Enums.ActionPermissionOptions.Search)] + */ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Http; +using VOL.Entity.DomainModels; +using VOL.System.IServices; + +namespace VOL.System.Controllers +{ + public partial class Sys_WorkFlowStepController + { + private readonly ISys_WorkFlowStepService _service;//访问业务代码 + private readonly IHttpContextAccessor _httpContextAccessor; + + [ActivatorUtilitiesConstructor] + public Sys_WorkFlowStepController( + ISys_WorkFlowStepService service, + IHttpContextAccessor httpContextAccessor + ) + : base(service) + { + _service = service; + _httpContextAccessor = httpContextAccessor; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_WorkFlowTableController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_WorkFlowTableController.cs new file mode 100644 index 0000000000000000000000000000000000000000..cb1772bd9993a25e3d70902e40205c3dc31ca572 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_WorkFlowTableController.cs @@ -0,0 +1,33 @@ +/* + *接口编写处... +*如果接口需要做Action的权限验证,请在Action上使用属性 +*如: [ApiActionPermission("Sys_WorkFlowTable",Enums.ActionPermissionOptions.Search)] + */ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Http; +using VOL.Entity.DomainModels; +using VOL.System.IServices; + +namespace VOL.System.Controllers +{ + public partial class Sys_WorkFlowTableController + { + private readonly ISys_WorkFlowTableService _service;//访问业务代码 + private readonly IHttpContextAccessor _httpContextAccessor; + + [ActivatorUtilitiesConstructor] + public Sys_WorkFlowTableController( + ISys_WorkFlowTableService service, + IHttpContextAccessor httpContextAccessor + ) + : base(service) + { + _service = service; + _httpContextAccessor = httpContextAccessor; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_WorkFlowTableStepController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_WorkFlowTableStepController.cs new file mode 100644 index 0000000000000000000000000000000000000000..9f9d6e1dfe22fa469106101b765ff25e4ca885cf --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Partial/Sys_WorkFlowTableStepController.cs @@ -0,0 +1,33 @@ +/* + *接口编写处... +*如果接口需要做Action的权限验证,请在Action上使用属性 +*如: [ApiActionPermission("Sys_WorkFlowTableStep",Enums.ActionPermissionOptions.Search)] + */ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Http; +using VOL.Entity.DomainModels; +using VOL.System.IServices; + +namespace VOL.System.Controllers +{ + public partial class Sys_WorkFlowTableStepController + { + private readonly ISys_WorkFlowTableStepService _service;//访问业务代码 + private readonly IHttpContextAccessor _httpContextAccessor; + + [ActivatorUtilitiesConstructor] + public Sys_WorkFlowTableStepController( + ISys_WorkFlowTableStepService service, + IHttpContextAccessor httpContextAccessor + ) + : base(service) + { + _service = service; + _httpContextAccessor = httpContextAccessor; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_DictionaryController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_DictionaryController.cs new file mode 100644 index 0000000000000000000000000000000000000000..407f252cd7215a603c89a8853ff6152659086db9 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_DictionaryController.cs @@ -0,0 +1,19 @@ +using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; +using VOL.Core.Controllers.Basic; +using VOL.Core.Extensions; +using VOL.Core.Filters; +using VOL.System.IServices; + +namespace VOL.System.Controllers +{ + [Route("api/Sys_Dictionary")] + [ApiExplorerSettings(GroupName = "字典管理_SysDictionary")] + public partial class Sys_DictionaryController : ApiBaseController + { + public Sys_DictionaryController(ISys_DictionaryService service) + : base("System", "System", "Sys_Dictionary", service) + { + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_DictionaryListController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_DictionaryListController.cs new file mode 100644 index 0000000000000000000000000000000000000000..9e01b48418db3d9cca3cfb8db4ca80cd3659e5b3 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_DictionaryListController.cs @@ -0,0 +1,22 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果要增加方法请在当前目录下Partial文件夹Sys_DictionaryListController编写 + */ +using Microsoft.AspNetCore.Mvc; +using VOL.Core.Controllers.Basic; +using VOL.Entity.AttributeManager; +using VOL.System.IServices; +namespace VOL.System.Controllers +{ + [Route("api/Sys_DictionaryList")] + [PermissionTable(Name = "Sys_DictionaryList")] + [ApiExplorerSettings(GroupName = "字典明细管理_SysDictionaryList")] + public partial class Sys_DictionaryListController : ApiBaseController + { + public Sys_DictionaryListController(ISys_DictionaryListService service) + : base(service) + { + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_LogController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_LogController.cs new file mode 100644 index 0000000000000000000000000000000000000000..f1c9173b31941ed608ad2bbcef4e9dcb15ad8e72 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_LogController.cs @@ -0,0 +1,21 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using VOL.Core.Controllers.Basic; +using VOL.Entity.DomainModels; +using VOL.System.IServices; + +namespace VOL.System.Controllers +{ + [Route("api/Sys_Log")] + [ApiExplorerSettings(GroupName = "日志管理_SysLog")] + public partial class Sys_LogController : ApiBaseController + { + public Sys_LogController(ISys_LogService service) + : base("System", "System", "Sys_Log", service) + { + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_MenuController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_MenuController.cs new file mode 100644 index 0000000000000000000000000000000000000000..99cb1c50b9da3fca8959756001b3811e22f35060 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_MenuController.cs @@ -0,0 +1,23 @@ +using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; +using VOL.Core.Controllers.Basic; +using VOL.Core.Enums; +using VOL.Core.Filters; +using VOL.Entity.DomainModels; +using VOL.System.IServices; + +namespace VOL.System.Controllers +{ + [Route("api/menu")] + [ApiController, JWTAuthorize()] + [ApiExplorerSettings(GroupName = "菜单管理_SysMenu")] + public partial class Sys_MenuController : ApiBaseController + { + private ISys_MenuService _service { get; set; } + public Sys_MenuController(ISys_MenuService service) : + base("System", "System", "Sys_Menu", service) + { + _service = service; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_QuartzLogController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_QuartzLogController.cs new file mode 100644 index 0000000000000000000000000000000000000000..b38ddbd24a25dbb1f6446144aa0c63c10c8f2155 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_QuartzLogController.cs @@ -0,0 +1,21 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果要增加方法请在当前目录下Partial文件夹Sys_QuartzLogController编写 + */ +using Microsoft.AspNetCore.Mvc; +using VOL.Core.Controllers.Basic; +using VOL.Entity.AttributeManager; +using VOL.System.IServices; +namespace VOL.System.Controllers +{ + [Route("api/Sys_QuartzLog")] + [PermissionTable(Name = "Sys_QuartzLog")] + public partial class Sys_QuartzLogController : ApiBaseController + { + public Sys_QuartzLogController(ISys_QuartzLogService service) + : base(service) + { + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_QuartzOptionsController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_QuartzOptionsController.cs new file mode 100644 index 0000000000000000000000000000000000000000..337307a1c5b2b4ea4916dd5aed4026d740d19d51 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_QuartzOptionsController.cs @@ -0,0 +1,21 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果要增加方法请在当前目录下Partial文件夹Sys_QuartzOptionsController编写 + */ +using Microsoft.AspNetCore.Mvc; +using VOL.Core.Controllers.Basic; +using VOL.Entity.AttributeManager; +using VOL.System.IServices; +namespace VOL.System.Controllers +{ + [Route("api/Sys_QuartzOptions")] + [PermissionTable(Name = "Sys_QuartzOptions")] + public partial class Sys_QuartzOptionsController : ApiBaseController + { + public Sys_QuartzOptionsController(ISys_QuartzOptionsService service) + : base(service) + { + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_RoleController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_RoleController.cs new file mode 100644 index 0000000000000000000000000000000000000000..95eec5414981bc06987354332edc0406760692d6 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_RoleController.cs @@ -0,0 +1,27 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System.Threading.Tasks; +using VOL.Core.Controllers.Basic; +using VOL.Core.Enums; +using VOL.Core.Filters; +using VOL.Entity.AttributeManager; +using VOL.Entity.DomainModels; +using VOL.System.IServices; + +namespace VOL.System.Controllers +{ + [Route("api/Sys_Role")] + [PermissionTable(Name = "Sys_Role")] + [ApiExplorerSettings(GroupName = "角色管理_SysRole")] + public partial class Sys_RoleController : ApiBaseController + { + public Sys_RoleController(ISys_RoleService service) + : base("System", "System", "Sys_Role", service) + { + + } + } +} + + diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_UserController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_UserController.cs new file mode 100644 index 0000000000000000000000000000000000000000..9230fb16d4fe5fb0c067c65cb04156da9d111fae --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_UserController.cs @@ -0,0 +1,24 @@ + +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Caching.Memory; +using System.Threading.Tasks; +using VOL.Core.Controllers.Basic; +using VOL.Entity.AttributeManager; +using VOL.Entity.DomainModels; +using VOL.System.IServices; + +namespace VOL.System.Controllers +{ + [Route("api/Sys_User")] + [PermissionTable(Name = "Sys_User")] + [ApiExplorerSettings(GroupName = "用户管理_SysUser")] + public partial class Sys_UserController : ApiBaseController + { + public Sys_UserController(ISys_UserService service) + : base("System", "System", "Sys_User", service) + { + //, IMemoryCache cache + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_WorkFlowController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_WorkFlowController.cs new file mode 100644 index 0000000000000000000000000000000000000000..b598be2c1147f6028cd082d340427db00f3f574f --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_WorkFlowController.cs @@ -0,0 +1,21 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果要增加方法请在当前目录下Partial文件夹Sys_WorkFlowController编写 + */ +using Microsoft.AspNetCore.Mvc; +using VOL.Core.Controllers.Basic; +using VOL.Entity.AttributeManager; +using VOL.System.IServices; +namespace VOL.System.Controllers +{ + [Route("api/Sys_WorkFlow")] + [PermissionTable(Name = "Sys_WorkFlow")] + public partial class Sys_WorkFlowController : ApiBaseController + { + public Sys_WorkFlowController(ISys_WorkFlowService service) + : base(service) + { + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_WorkFlowStepController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_WorkFlowStepController.cs new file mode 100644 index 0000000000000000000000000000000000000000..1b34e6b7238367bdd1c262c186ab6749152c060a --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_WorkFlowStepController.cs @@ -0,0 +1,21 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果要增加方法请在当前目录下Partial文件夹Sys_WorkFlowStepController编写 + */ +using Microsoft.AspNetCore.Mvc; +using VOL.Core.Controllers.Basic; +using VOL.Entity.AttributeManager; +using VOL.System.IServices; +namespace VOL.System.Controllers +{ + [Route("api/Sys_WorkFlowStep")] + [PermissionTable(Name = "Sys_WorkFlowStep")] + public partial class Sys_WorkFlowStepController : ApiBaseController + { + public Sys_WorkFlowStepController(ISys_WorkFlowStepService service) + : base(service) + { + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_WorkFlowTableController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_WorkFlowTableController.cs new file mode 100644 index 0000000000000000000000000000000000000000..057f5929e6ac3ce890ed186184596b3ddce697d0 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_WorkFlowTableController.cs @@ -0,0 +1,21 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果要增加方法请在当前目录下Partial文件夹Sys_WorkFlowTableController编写 + */ +using Microsoft.AspNetCore.Mvc; +using VOL.Core.Controllers.Basic; +using VOL.Entity.AttributeManager; +using VOL.System.IServices; +namespace VOL.System.Controllers +{ + [Route("api/Sys_WorkFlowTable")] + [PermissionTable(Name = "Sys_WorkFlowTable")] + public partial class Sys_WorkFlowTableController : ApiBaseController + { + public Sys_WorkFlowTableController(ISys_WorkFlowTableService service) + : base(service) + { + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_WorkFlowTableStepController.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_WorkFlowTableStepController.cs new file mode 100644 index 0000000000000000000000000000000000000000..ee468e906678dd6fbd85f4a1c4a4707b8193bf43 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Controllers/System/Sys_WorkFlowTableStepController.cs @@ -0,0 +1,21 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果要增加方法请在当前目录下Partial文件夹Sys_WorkFlowTableStepController编写 + */ +using Microsoft.AspNetCore.Mvc; +using VOL.Core.Controllers.Basic; +using VOL.Entity.AttributeManager; +using VOL.System.IServices; +namespace VOL.System.Controllers +{ + [Route("api/Sys_WorkFlowTableStep")] + [PermissionTable(Name = "Sys_WorkFlowTableStep")] + public partial class Sys_WorkFlowTableStepController : ApiBaseController + { + public Sys_WorkFlowTableStepController(ISys_WorkFlowTableStepService service) + : base(service) + { + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Program.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Program.cs new file mode 100644 index 0000000000000000000000000000000000000000..2d691dce668a72c71826646df3bd49dca9e95a72 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Program.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Autofac.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +namespace VOL.WebApi +{ + public class Program + { + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.ConfigureKestrel(serverOptions => + { + serverOptions.Limits.MaxRequestBodySize = 10485760; + // Set properties and call methods on options + }); + webBuilder.UseKestrel().UseUrls("http://*:9991"); + webBuilder.UseIIS(); + webBuilder.UseStartup(); + }).UseServiceProviderFactory(new AutofacServiceProviderFactory()); + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Properties/launchSettings.json b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Properties/launchSettings.json new file mode 100644 index 0000000000000000000000000000000000000000..bd82b4a041eed08d5965338a9936f8d48f0fb571 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:1309", + "sslPort": 44318 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "VOL.WebApi": { + "commandName": "Project", + "launchBrowser": false, + "applicationUrl": "https://localhost:5001;http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Startup.cs b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Startup.cs new file mode 100644 index 0000000000000000000000000000000000000000..d42204cc559273a0463182b36e487df62f861e21 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Startup.cs @@ -0,0 +1,304 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Autofac; +using IGeekFan.AspNetCore.Knife4jUI; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.FileProviders; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.IdentityModel.Tokens; +using Microsoft.OpenApi.Models; +using Newtonsoft.Json; +using Quartz; +using Quartz.Impl; +using Swashbuckle.AspNetCore.SwaggerGen; +using VOL.Core.Configuration; +using VOL.Core.Extensions; +using VOL.Core.Filters; +using VOL.Core.Middleware; +using VOL.Core.ObjectActionValidator; +using VOL.Core.Quartz; +using VOL.Core.WorkFlow; +using VOL.WebApi.Controllers.Hubs; + +namespace VOL.WebApi +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + private IServiceCollection Services { get; set; } + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + //ʼģ֤ + services.UseMethodsModelParameters().UseMethodsGeneralParameters(); + services.AddSingleton(new NullObjectModelValidator()); + Services = services; + // services.Replace( ServiceDescriptor.Transient()); + services.AddSession(); + services.AddMemoryCache(); + services.AddHttpContextAccessor(); + services.AddMvc(options => + { + options.Filters.Add(typeof(ApiAuthorizeFilter)); + options.Filters.Add(typeof(ActionExecuteFilter)); + // options.SuppressAsyncSuffixInActionNames = false; + }); + services.AddControllers() + .AddNewtonsoftJson(op => + { + op.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver(); + op.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss"; + }); + + Services.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + }) + .AddJwtBearer(options => + { + options.TokenValidationParameters = new TokenValidationParameters + { + SaveSigninToken = true,//token,̨֤tokenǷЧ(Ҫ) + ValidateIssuer = true,//Ƿ֤Issuer + ValidateAudience = true,//Ƿ֤Audience + ValidateLifetime = true,//Ƿ֤ʧЧʱ + ValidateIssuerSigningKey = true,//Ƿ֤SecurityKey + ValidAudience = AppSetting.Secret.Audience,//Audience + ValidIssuer = AppSetting.Secret.Issuer,//Issuerǰǩjwtһ + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(AppSetting.Secret.JWT)) + }; + options.Events = new JwtBearerEvents() + { + OnChallenge = context => + { + context.HandleResponse(); + context.Response.Clear(); + context.Response.ContentType = "application/json"; + context.Response.StatusCode = 401; + context.Response.WriteAsync(new { message = "Ȩδͨ", status = false, code = 401 }.Serialize()); + return Task.CompletedTask; + } + }; + }); + //appsettings.json + string corsUrls = Configuration["CorsUrls"]; + if (string.IsNullOrEmpty(corsUrls)) + { + throw new Exception("ÿǰUrl"); + } + services.AddCors(options => + { + options.AddDefaultPolicy( + builder => + { + builder.AllowAnyOrigin() + .SetPreflightMaxAge(TimeSpan.FromSeconds(2520)) + .AllowAnyHeader().AllowAnyMethod(); + }); + }); + services.AddSingleton(); + services.AddControllers(); + services.AddSwaggerGen(c => + { + //Ϊ2ݽӿĵ + c.SwaggerDoc("v1", new OpenApiInfo { Title = "VOL.CoręApi", Version = "v1", Description = "Ƕĵ" }); + c.SwaggerDoc("v2", new OpenApiInfo { Title = "VOL.CoreApi", Version = "v2", Description = "xxxӿĵ" }); //ʹ[ApiExplorerSettings(GroupName = "v2")] + //ע͹ + // var basePath = PlatformServices.Default.Application.ApplicationBasePath; + // var xmlPath = Path.Combine(basePath, "VOL.WebApi.xml"); + // c.IncludeXmlComments(xmlPath, true);//ʾxmlע + //ӹ ԶӶԿע + //c.DocumentFilter(); + + var security = new Dictionary> { { AppSetting.Secret.Issuer, new string[] { } } }; + c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme() + { + Description = "JWTȨtokenǰҪֶBearerһո,Bearer token", + Name = "Authorization", + In = ParameterLocation.Header, + Type = SecuritySchemeType.ApiKey, + BearerFormat = "JWT", + Scheme = "Bearer" + }); + + c.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference { + Type = ReferenceType.SecurityScheme, + Id = "Bearer" + } + }, + new string[] { } + } + }); + }) + .AddControllers() + .ConfigureApiBehaviorOptions(options => + { + options.SuppressConsumesConstraintForFormFileParameters = true; + options.SuppressInferBindingSourcesForParameters = true; + options.SuppressModelStateInvalidFilter = true; + options.SuppressMapClientErrors = true; + options.ClientErrorMapping[404].Link = + "https://*/404"; + }); + services.AddSignalR(); + + services.AddHttpClient(); + Services.AddTransient(); + Services.AddSingleton(); + Services.AddSingleton(); + } + public void ConfigureContainer(ContainerBuilder builder) + { + Services.AddModule(builder, Configuration); + //ʼ̱AuditStatusֶΣԲ ʾsellorder + // WorkFlowContainer.Instance.Use<1>().Use<2>(); + } + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + else + { + app.UseQuartz(env); + } + app.UseMiddleware(); + app.UseStaticFiles().UseStaticFiles(new StaticFileOptions + { + ServeUnknownFileTypes = true + }); + app.UseDefaultFiles(); + app.Use(HttpRequestMiddleware.Context); + + //2021.06.27ӴĬuploadļ + string _uploadPath = (env.ContentRootPath + "/Upload").ReplacePath(); + + if (!Directory.Exists(_uploadPath)) + { + Directory.CreateDirectory(_uploadPath); + } + + app.UseStaticFiles(new StaticFileOptions() + { + FileProvider = new PhysicalFileProvider( + Path.Combine(Directory.GetCurrentDirectory(), @"Upload")), + //÷Ŀ¼ʱļб + RequestPath = "/Upload", + OnPrepareResponse = (Microsoft.AspNetCore.StaticFiles.StaticFileResponseContext staticFile) => + { + //ڴ˴ȡϢȨ֤ + // staticFile.File + // staticFile.Context.Response.StatusCode; + } + }); + //HttpContext + app.UseStaticHttpContext(); + + app.UseSwagger(); + app.UseSwaggerUI(c => + { + //2ѡ ѡӦĵ + c.SwaggerEndpoint("/swagger/v1/swagger.json", "VOL.CoręApi"); + c.SwaggerEndpoint("/swagger/v2/swagger.json", "Api"); + c.RoutePrefix = ""; + }); + app.UseRouting(); + //UseCors,UseAuthenticationgλõ˳Ҫ + app.UseCors(); + app.UseAuthentication(); + app.UseAuthorization(); + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + //SignalR + if (AppSetting.UseSignalR) + { + string corsUrls = Configuration["CorsUrls"]; + endpoints.MapHub("/message").RequireCors(t => + t.WithOrigins(corsUrls.Split(',')). + AllowAnyMethod(). + AllowAnyHeader(). + AllowCredentials()); + } + + }); + } + + /// + /// ȡӦswaggerֵ + /// + private string GetSwaggerGroupName(Type controller) + { + var groupName = controller.Name.Replace("Controller", ""); + var apiSetting = controller.GetCustomAttribute(typeof(ApiExplorerSettingsAttribute)); + if (apiSetting != null) + { + groupName = ((ApiExplorerSettingsAttribute)apiSetting).GroupName; + + } + + return groupName; + } + + /// + /// ȡеĿ + /// + private List GetControllers() + { + Assembly asm = Assembly.GetExecutingAssembly(); + + var contradistinction = asm.GetTypes() + .Where(type => typeof(ControllerBase).IsAssignableFrom(type)) + .OrderBy(x => x.Name).ToList(); + return contradistinction; + } + } + + /// + /// SwaggerעͰ + /// + public class SwaggerDocTag : IDocumentFilter + { + /// + /// Ӹע + /// + /// + /// + public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) + { + //ӶӦĿ + swaggerDoc.Tags = new List + { + new OpenApiTag { Name = "Test", Description = "" }, + //new OpenApiTag { Name = "Ŀ֣Controller", Description = "" }, + }; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/AppHtml/news.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/AppHtml/news.html new file mode 100644 index 0000000000000000000000000000000000000000..eaa98e66e5825c276a55ce2bcdb1d5b4403ab8ff --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/AppHtml/news.html @@ -0,0 +1,88 @@ + + + + {title} + + + + + + + + + +
+

+ {title} +

+
+ 来源:vol-core + 发布时间:{date} + 浏览次数:0 +
+
+
+ {content} +
+ + + + \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/AppHtml/productDesc.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/AppHtml/productDesc.html new file mode 100644 index 0000000000000000000000000000000000000000..e49c163148169586728546cb82fcdd8efea3826f --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/AppHtml/productDesc.html @@ -0,0 +1,34 @@ + + + + + + + + 商品详情 + + + + + + + + + + + + +
+
+
+

商品详情

+
+
+
+ {#Content} +
+
+
+ + + diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Controller/Controller.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Controller/Controller.html new file mode 100644 index 0000000000000000000000000000000000000000..50e46b6f6b575976aefce1579e39f6e37c1632a9 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Controller/Controller.html @@ -0,0 +1,27 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *Date:2018-07-01 + * 此代码由框架生成,请勿随意更改 + */ +using System; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using {Namespace}.IServices; +using {StartName}.Core.Controllers.Basic; +using Microsoft.AspNetCore.Mvc; +using VOL.Entity.AttributeManager; + +namespace {Namespace}.Controllers +{ + [ApiExplorerSettings(IgnoreApi = true)] + [PermissionTable(Name = "{TableName}")] + public partial class {TableName}Controller : BaseController + { + public {TableName}Controller(I{TableName}Service service) + : base({BaseOptions}, service) + { + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Controller/ControllerApi.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Controller/ControllerApi.html new file mode 100644 index 0000000000000000000000000000000000000000..b4d9d55cff1ac33960c3ec2b721dc2b4cc7559ec --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Controller/ControllerApi.html @@ -0,0 +1,21 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果要增加方法请在当前目录下Partial文件夹{TableName}Controller编写 + */ +using Microsoft.AspNetCore.Mvc; +using VOL.Core.Controllers.Basic; +using VOL.Entity.AttributeManager; +using {Namespace}.IServices; +namespace {Namespace}.Controllers +{ + [Route("api/{TableName}")] + [PermissionTable(Name = "{TableName}")] + public partial class {TableName}Controller : ApiBaseController + { + public {TableName}Controller(I{TableName}Service service) + : base(service) + { + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Controller/ControllerApiPartial.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Controller/ControllerApiPartial.html new file mode 100644 index 0000000000000000000000000000000000000000..6977f3b82251307c9e226943f78e133a85a28e64 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Controller/ControllerApiPartial.html @@ -0,0 +1,33 @@ +/* + *接口编写处... +*如果接口需要做Action的权限验证,请在Action上使用属性 +*如: [ApiActionPermission("{TableName}",Enums.ActionPermissionOptions.Search)] + */ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Http; +using {StartName}.Entity.DomainModels; +using {Namespace}.IServices; + +namespace {Namespace}.Controllers +{ + public partial class {TableName}Controller + { + private readonly I{TableName}Service _service;//访问业务代码 + private readonly IHttpContextAccessor _httpContextAccessor; + + [ActivatorUtilitiesConstructor] + public {TableName}Controller( + I{TableName}Service service, + IHttpContextAccessor httpContextAccessor + ) + : base(service) + { + _service = service; + _httpContextAccessor = httpContextAccessor; + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Controller/ControllerPartial.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Controller/ControllerPartial.html new file mode 100644 index 0000000000000000000000000000000000000000..7b6bacdf94f91c970c1d293479823360f25d712b --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Controller/ControllerPartial.html @@ -0,0 +1,15 @@ +using {StartName}.Core.Extensions; +using {StartName}.Core.Filter; +using {StartName}.Core.Utility; +using {StartName}.Entity.DomainModels; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace {Namespace}.Controllers +{ + public partial class {TableName}Controller + { + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/DomianModel/ApiInputDomainModel.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/DomianModel/ApiInputDomainModel.html new file mode 100644 index 0000000000000000000000000000000000000000..8280810216c89b24a8ea88b80f7bab3bfe11b771 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/DomianModel/ApiInputDomainModel.html @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using {StartName}.Entity; + +namespace {Namespace}.DomainModels +{ + public class Api{TableName}Input + { + {AttributeList} + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/DomianModel/ApiOutputDomainModel.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/DomianModel/ApiOutputDomainModel.html new file mode 100644 index 0000000000000000000000000000000000000000..7cc77d00afd638acf7018ee3261066c67f13e652 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/DomianModel/ApiOutputDomainModel.html @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using {StartName}.Entity; + +namespace {Namespace}.DomainModels +{ + public class Api{TableName}Output + { + {AttributeList} + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/DomianModel/DomainModel.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/DomianModel/DomainModel.html new file mode 100644 index 0000000000000000000000000000000000000000..8e72871553fa6f8133e81d1e21d5902a49f9de16 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/DomianModel/DomainModel.html @@ -0,0 +1,21 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *如果数据库字段发生变化,请在代码生器重新生成此Model + */ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using {Namespace}.SystemModels; + +namespace {Namespace}.DomainModels +{ + {AttributeManager} + public partial class {TableName}:BaseEntity + { + {AttributeList} + } +} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/DomianModel/MappingConfiguration.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/DomianModel/MappingConfiguration.html new file mode 100644 index 0000000000000000000000000000000000000000..32eb1ce7caeea09a3514562c774824da40eb1e9d --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/DomianModel/MappingConfiguration.html @@ -0,0 +1,16 @@ +using {StartName}.Entity.MappingConfiguration; +using {StartName}.Entity.DomainModels; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace {Namespace}.MappingConfiguration +{ + public class {TableName}MapConfig : EntityMappingConfiguration<{TableName}> + { + public override void Map(EntityTypeBuilder<{TableName}> + builderTable) + { + //b.Property(x => x.StorageName).HasMaxLength(45); + } + } +} + diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/IRepositorys/BaseIRepositorie.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/IRepositorys/BaseIRepositorie.html new file mode 100644 index 0000000000000000000000000000000000000000..49bde31bffee083de679835f630e041679e31901 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/IRepositorys/BaseIRepositorie.html @@ -0,0 +1,18 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹I{TableName}Repository编写接口 + */ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using {StartName}.Core.BaseProvider; +using {StartName}.Entity.DomainModels; +using {StartName}.Core.Extensions.AutofacManager; +namespace {Namespace}.IRepositories +{ + public partial interface I{TableName}Repository : IDependency,IRepository<{TableName}> + { + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/IServices/IServiceBase.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/IServices/IServiceBase.html new file mode 100644 index 0000000000000000000000000000000000000000..5102b7b39bdd5586650ba9039ad29bdeedf99f25 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/IServices/IServiceBase.html @@ -0,0 +1,12 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + */ +using {StartName}.Core.BaseProvider; +using {StartName}.Entity.DomainModels; + +namespace {Namespace}.IServices +{ + public partial interface I{TableName}Service : IService<{TableName}> + { + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/IServices/IServiceBasePartial.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/IServices/IServiceBasePartial.html new file mode 100644 index 0000000000000000000000000000000000000000..90bcfd1bdbed7afe3be34782545dd4a6e05a15f5 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/IServices/IServiceBasePartial.html @@ -0,0 +1,13 @@ +/* +*所有关于{TableName}类的业务代码接口应在此处编写 +*/ +using {StartName}.Core.BaseProvider; +using {StartName}.Entity.DomainModels; +using VOL.Core.Utilities; +using System.Linq.Expressions; +namespace {Namespace}.IServices +{ + public partial interface I{TableName}Service + { + } + } diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/SearchPage.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/SearchPage.html new file mode 100644 index 0000000000000000000000000000000000000000..74e3e9280439be12685f7e8e53c05436f1e8ab25 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/SearchPage.html @@ -0,0 +1,47 @@ +@* + *Author:jxx + *Contact:283591387@qq.com + * 此代码由框架生成,请勿随意更改 + *@ +@{ + Layout = "~/Views/Shared/ManagerLayout.cshtml"; +} + + + + + + + + +
+ +
+
+
+
+
+
+ + + +{#uploader} +{#ueditor} + + + diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/Vue3SearchPage.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/Vue3SearchPage.html new file mode 100644 index 0000000000000000000000000000000000000000..178cb77db281b45783b16b1da9ad6b524ec21cd9 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/Vue3SearchPage.html @@ -0,0 +1,56 @@ + + + diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/VueExtension.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/VueExtension.html new file mode 100644 index 0000000000000000000000000000000000000000..7a41b7d6e2d74750de604292a3da06a6cd69585f --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/VueExtension.html @@ -0,0 +1,75 @@ +/***************************************************************************************** +** Author:jxx 2022 +** QQ:283591387 +**完整文档见:http://v2.volcore.xyz/document/api 【代码生成页面ViewGrid】 +**常用示例见:http://v2.volcore.xyz/document/vueDev +**后台操作见:http://v2.volcore.xyz/document/netCoreDev +*****************************************************************************************/ +//此js文件是用来自定义扩展业务代码,可以扩展一些自定义页面或者重新配置生成的代码 + +let extension = { + components: { + //查询界面扩展组件 + gridHeader: '', + gridBody: '', + gridFooter: '', + //新建、编辑弹出框扩展组件 + modelHeader: '', + modelBody: '', + modelFooter: '' + }, + tableAction: '', //指定某张表的权限(这里填写表名,默认不用填写) + buttons: { view: [], box: [], detail: [] }, //扩展的按钮 + methods: { + //下面这些方法可以保留也可以删除 + onInit() { //框架初始化配置前, + //示例:在按钮的最前面添加一个按钮 + // this.buttons.unshift({ //也可以用push或者splice方法来修改buttons数组 + // name: '按钮', //按钮名称 + // icon: 'el-icon-document', //按钮图标vue2版本见iview文档icon,vue3版本见element ui文档icon(注意不是element puls文档) + // type: 'primary', //按钮样式vue2版本见iview文档button,vue3版本见element ui文档button + // onClick: function () { + // this.$Message.success('点击了按钮'); + // } + // }); + + //示例:设置修改新建、编辑弹出框字段标签的长度 + // this.boxOptions.labelWidth = 150; + }, + onInited() { + //框架初始化配置后 + //如果要配置明细表,在此方法操作 + //this.detailOptions.columns.forEach(column=>{ }); + }, + searchBefore(param) { + //界面查询前,可以给param.wheres添加查询参数 + //返回false,则不会执行查询 + return true; + }, + searchAfter(result) { + //查询后,result返回的查询数据,可以在显示到表格前处理表格的值 + return true; + }, + addBefore(formData) { + //新建保存前formData为对象,包括明细表,可以给给表单设置值,自己输出看formData的值 + return true; + }, + updateBefore(formData) { + //编辑保存前formData为对象,包括明细表、删除行的Id + return true; + }, + rowClick({ row, column, event }) { + //查询界面点击行事件 + // this.$refs.table.$refs.table.toggleRowSelection(row); //单击行时选中当前行; + }, + modelOpenAfter(row) { + //点击编辑、新建按钮弹出框后,可以在此处写逻辑,如,从后台获取数据 + //(1)判断是编辑还是新建操作: this.currentAction=='Add'; + //(2)给弹出框设置默认值 + //(3)this.editFormFields.字段='xxx'; + //如果需要给下拉框设置默认值,请遍历this.editFormOptions找到字段配置对应data属性的key值 + //看不懂就把输出看:console.log(this.editFormOptions) + } + } +}; +export default extension; diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/VueSearchPage.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/VueSearchPage.html new file mode 100644 index 0000000000000000000000000000000000000000..bed17735c98f79dbb94e5de968bee283d44bd213 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/VueSearchPage.html @@ -0,0 +1,59 @@ + + + + diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/app/extension.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/app/extension.html new file mode 100644 index 0000000000000000000000000000000000000000..c867432a63683add5fe7828dcb998d9bdd37465f --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/app/extension.html @@ -0,0 +1,100 @@ +//************************************************ +// *Author:jxx +// *QQ:283591387 +// *自定义业务逻辑扩展 +//************************************************ +export default function() { + return { + methods: { + onInited() { //页面参数初始化 + //设置table超出换行显示 + //this.textInline = false; + + //设置列宽度 + //this.columns[1].width = 70; + + //设置table为水平显示或者list列表显示 + //this.direction = 'horizontal'//list + //如果为list列表显示,指定list的标题列 + //this.titleField="字段"; + + //设置自定义格式显示 + //this.columns.forEach(column=>{ + // if(column.field=='字段'){ + // //自定义格式化显示,在下面的formatter实现具体逻辑 + // //column.formatter=true; + + // //开启table单元格点击事件(仅设置this.direction = 'horizontal属性后生效) + // column.click=true; + + // //指定字段为date类型不显示时分秒 + // //column.type="date"; + // //设置列宽度 + // //column.width = 70; + // } + // }) + + //页面打开时禁用加载数据 + //this.load=false; + //页面打开时默认弹出查询框 + //this.searchModel = true; + }, + formatter(row, column,index) { //自定义格式化 + // if(column.field=='xx'){ + // return '' + row[column.field] + ''; + // } + //return row[column.field] + }, + rowClick(index, row, column) { //行点击事件(默认触发编辑) + return true; + }, + cellClick(index, row, column) { //单元格击事件(默认触发编辑) + //仅onInited中设置:this.direction = "horizontal", this.columns的字段设置为click=true后生效 + return true; + }, + rowButtons(index, row) { //列表显示的按钮 + //自定义按钮,仅onInited中设置:this.direction = "list"后生效 + // return [{ + // text: "测试", + // icon: "edit-pen", + // type: "primary", + // plain:true, + // shape:"circle", + // disabled: false + // },{ + // text: "删除", + // icon: "trash", + // type: "error", + // plain:true, + // shape:"circle", + // //shape:"",//square、circle + // disabled: false + // }]; + }, + rowButtonClick(btn,index, row){ //列表显示的按钮点击事件 + // if(btn.text=='删除'){ + // this.$toast('删除') + // } + }, + searchBefore(params){ //查询前 + return true; + }, + updateBefore(formData) { //更新保存前操作 + return true; + }, + addBefore(formData) {//新建保存前操作 + return true; + }, + searchFormOnChange(field,value){ //查询弹出框下拉框或日期选中事件 + //if(field=="字段"){ + // console.log(value) + //} + }, + editFormOnChange(field,value){ //新建编辑弹出框下拉框或日期选中事件 + //if(field=="字段"){ + // console.log(value) + //} + }, + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/app/options.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/app/options.html new file mode 100644 index 0000000000000000000000000000000000000000..7750fd2e5bb6b1a022d23aad99e0e97b403bc6b4 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/app/options.html @@ -0,0 +1,23 @@ +//************************************************ +// *Author:jxx +// *QQ:283591387 +// *代码由框架生成,任何更改都可能导致被代码生成器覆盖 +// *业务请在#TableName.js中编写 +//************************************************ +export default function() { + return { + editFormFields: #editFormFileds, + editFormOptions: #editFormOptions, + searchFormFields: #searchFormFileds, + searchFormOptions: #searchFormOptions, + columns: [#columns], + table: { + key: '#key', + footer: "Foots", + cnName: '#cnName', + name: '#TableName', + url: "#url", + sortName: "#SortName" + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/app/page.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/app/page.html new file mode 100644 index 0000000000000000000000000000000000000000..72c4e3edf4fa226fe8ab0ef538fbc4eba4fd7e70 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/app/page.html @@ -0,0 +1,41 @@ + + + + + diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/gridParameters.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/gridParameters.html new file mode 100644 index 0000000000000000000000000000000000000000..a88be7847ce185e1d37a1c343829c27d6ae83e98 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/gridParameters.html @@ -0,0 +1,24 @@ +{ + loadMsg: '数据正在加载。。。。', + //rownumbers: true, + pageSize: 30, + pageList: [10, 20, 30, 50, 80, 100, 200, 500, 1000], + height: 340, + key:'#key', + url: '#Url', + nameSpace:'', + queryParams: {TableName:'#TableName',sort:'#SortName',Foots:'#Foots',Wheres:'{}'}, + pagination: true, + striped:true, + fileLink:#fileLink, + richText:#richText, + hasSection:false, + cnName:'#cnName', + calculateHeight:{id:'#lay-search-panel'}, + calculateWidth:{id:'#lay-search-panel'{#Width}}, + frozenColumns: [[ + { field: 'ck', checkbox: true } + ]], + //showFooter: true, + columns: [[{#columns}]] + } \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/router.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/router.html new file mode 100644 index 0000000000000000000000000000000000000000..76d9994d710f094477f606284211256cc91b6824 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Page/router.html @@ -0,0 +1,5 @@ + ,{ + path: '/#TableName', + name: '#TableName', + component: () => import('@/views/#folder/#TableName.vue') + }] \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Repositorys/BaseRepository.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Repositorys/BaseRepository.html new file mode 100644 index 0000000000000000000000000000000000000000..38acef46ff9b4e034d48e1bb3fa1d8131a9060b1 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Repositorys/BaseRepository.html @@ -0,0 +1,24 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *Repository提供数据库操作,如果要增加数据库操作请在当前目录下Partial文件夹{TableName}Repository编写代码 + */ +using {Namespace}.IRepositories; +using {StartName}.Core.BaseProvider; +using {StartName}.Core.EFDbContext; +using {StartName}.Core.Extensions.AutofacManager; +using {StartName}.Entity.DomainModels; + +namespace {Namespace}.Repositories +{ + public partial class {TableName}Repository : RepositoryBase<{TableName}> , I{TableName}Repository + { + public {TableName}Repository(VOLContext dbContext) + : base(dbContext) + { + + } + public static I{TableName}Repository Instance + { + get { return AutofacContainerModule.GetService(); } } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Repositorys/BaseRepositoryPartial.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Repositorys/BaseRepositoryPartial.html new file mode 100644 index 0000000000000000000000000000000000000000..537813df05b359fe99f19e0920af7ee882a75337 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Repositorys/BaseRepositoryPartial.html @@ -0,0 +1,16 @@ +/* + *代码由框架生成,任何更改都可能导致被代码生成器覆盖 + *Repository提供数据库操作,如果要增加数据库操作请在此处编写代码 + */ +using {Namespace}.IRepositories; +using {StartName}.Core.BaseProvider; +using {StartName}.Core.Extensions.AutofacManager; +using {StartName}.Core.RepositoryEF; +using {StartName}.Entity.DomainModels; + +namespace {Namespace}.Repositories +{ + public partial class {TableName}Repository + { + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Services/ServiceBase.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Services/ServiceBase.html new file mode 100644 index 0000000000000000000000000000000000000000..bc57ad06a8fa0ac746b5ae358701ff5db303e05e --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Services/ServiceBase.html @@ -0,0 +1,27 @@ +/* + *Author:jxx + *Contact:283591387@qq.com + *代码由框架生成,此处任何更改都可能导致被代码生成器覆盖 + *所有业务编写全部应在Partial文件夹下{TableName}Service与I{TableName}Service中编写 + */ +using {Namespace}.IRepositories; +using {Namespace}.IServices; +using {StartName}.Core.BaseProvider; +using {StartName}.Core.Extensions.AutofacManager; +using {StartName}.Entity.DomainModels; + +namespace {Namespace}.Services +{ + public partial class {TableName}Service : ServiceBase<{TableName}, I{TableName}Repository> + , I{TableName}Service, IDependency + { + public {TableName}Service(I{TableName}Repository repository) + : base(repository) + { + Init(repository); + } + public static I{TableName}Service Instance + { + get { return AutofacContainerModule.GetService(); } } + } + } diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Services/ServiceBasePartial.html b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Services/ServiceBasePartial.html new file mode 100644 index 0000000000000000000000000000000000000000..c9170ac37e95c38ee042cdff02505699ab1fd08f --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Template/Services/ServiceBasePartial.html @@ -0,0 +1,41 @@ +/* + *所有关于{TableName}类的业务代码应在此处编写 +*可使用repository.调用常用方法,获取EF/Dapper等信息 +*如果需要事务请使用repository.DbContextBeginTransaction +*也可使用DBServerProvider.手动获取数据库相关信息 +*用户信息、权限、角色等使用UserContext.Current操作 +*{TableName}Service对增、删、改查、导入、导出、审核业务代码扩展参照ServiceFunFilter +*/ +using {StartName}.Core.BaseProvider; +using {StartName}.Core.Extensions.AutofacManager; +using {StartName}.Entity.DomainModels; +using System.Linq; +using VOL.Core.Utilities; +using System.Linq.Expressions; +using {StartName}.Core.Extensions; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Http; +using {Namespace}.IRepositories; + +namespace {Namespace}.Services +{ + public partial class {TableName}Service + { + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly I{TableName}Repository _repository;//访问数据库 + + [ActivatorUtilitiesConstructor] + public {TableName}Service( + I{TableName}Repository dbRepository, + IHttpContextAccessor httpContextAccessor + ) + : base(dbRepository) + { + _httpContextAccessor = httpContextAccessor; + _repository = dbRepository; + //多租户会用到这init代码,其他情况可以不用 + //base.Init(dbRepository); + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/Upload/1111.txt b/Pure_Vite_Net7/WebNet7/VOL.WebApi/Upload/1111.txt new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/VOL.WebApi.csproj b/Pure_Vite_Net7/WebNet7/VOL.WebApi/VOL.WebApi.csproj new file mode 100644 index 0000000000000000000000000000000000000000..42ee63bdfbefa23e4dfdb68867d76a7511477b64 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/VOL.WebApi.csproj @@ -0,0 +1,22 @@ + + + + net7.0 + + + + + + + + + + + + + + + + + + diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/appsettings.Development.json b/Pure_Vite_Net7/WebNet7/VOL.WebApi/appsettings.Development.json new file mode 100644 index 0000000000000000000000000000000000000000..8983e0fc1c5e2795ccfde0c771c6d66c88ef4a42 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/appsettings.json b/Pure_Vite_Net7/WebNet7/VOL.WebApi/appsettings.json new file mode 100644 index 0000000000000000000000000000000000000000..1c28523731094835fd7a968bd87b788919c9510b --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/appsettings.json @@ -0,0 +1,93 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*", + "VirtualPath": { + "StaticFile": "E:\\Web\\Static", //配置的虚拟目录文件所在路径 + "FolderName": "/Static" //访问时此路径时的别名 + }, + "AppUrls": { + }, + "Connection": { + "DBType": "MsSql", //MySql/MsSql/PgSql //数据库类型,如果使用的是sqlserver此处应设置为MsSql + //sqlserver连接字符串 + "DbConnectionString": "Data Source=192.168.98.128;Initial Catalog=netcoredev;Persist Security Info=True;User ID=vol;Password=1;Connect Timeout=500;TrustServerCertificate=true", + + //mysql连接字符串(升级EFCore3.1到时已将mysql连接字符串修改,2019-12-20) + //"DbConnectionString": " Data Source=127.0.0.1;Database=netcoredev1;AllowLoadLocalInfile=true;User ID=root;Password=jxx!@#123..errrewJXXX;allowPublicKeyRetrieval=true;pooling=true;CharSet=utf8;port=3306;sslmode=none;", + + //PgSql连接字符串 + // "DbConnectionString": "Host=132.232.2.109;Port=5432;User id=postgres;password=jxx_abcd;Database=netcoredev;", + "RedisConnectionString": "127.0.0.1,Password=123456,SyncTimeout=15000", //redis连接字符串(最好加密) + "UseRedis": "false", //是否使用redis,如果不使用,默认使用Memory内置缓存 + "UseSignalR": "true" //是否使用SignalR(2022.05.03),注意需要将端的地址配置到下面的CorsUrls属性中 + }, + "Secret": { //秘钥配置 + "JWT": "BB3647441FFA4B5DB4E64A29B53CE525", //JWT + "Audience": "vol.core", + "Issuer": "vol.core.owner", + "User": "C5ABA9E202D94C43A3CA66002BF77FAF", // + "DB": "3F8B7B38AD3D484A89ACA513CBD79F36", + "Redis": "E6D90DDBC70C4F4EA3C312B6FCB473C8" + }, + //================跨域请求 (CORS)配置(2019-12-20新增), + //================.netcore3.1必须配置此属性,多个url用豆号隔开,url为vue站点的地址,可以将发布后的地址也同时配置上 + "CorsUrls": "http://localhost:8081,http://localhost:8080,http://localhost:7080,http://localhost:9980,http://127.0.0.1:9980,http://localhost:9990,http://www.volcore.xyz", + "ExpMinutes": "120", //JWT有效期(分钟=默认120), + "CreateMember": { //对表插入数据时,需要记录创建人/创建时间/创建日期,配置UserIdField/UserNameField/DateField分别为对应数据库的创建人CreateID,创建人Creator,创建时间CreateDate字段(新建数据时,由框架默认完成给这几个字段赋值,字段区分大小写)或可手动调用T.SetCreateDefaultVal()完成设置创建人/创建时间/创建日期 + //如果表的主键是GUID,界面查询时默认会用到DateField对应的实体(数据库)字段进行排序 + "UserIdField": "CreateID", + "UserNameField": "Creator", + "DateField": "CreateDate" + }, + "ModifyMember": { //修改同上 + "UserIdField": "ModifyID", + "UserNameField": "Modifier", + "DateField": "ModifyDate" + }, //演示系统过滤Action,只有超级管理员才能操作,其他用户只有只读权限 + "GlobalFilter": { + "Message": "演示环境,当前帐号没有开启此功能权限", + "Enable": "false", //开启Action过滤 + "Actions": [ "Update", "Del", "Add", "SavePermission", "Save", "CreatePage", "CreateVuePage", "CreateEntityModel", "SaveEidt", "CreateServices", "Import", "Upload", "Audit", "ModifyPwd" ] + }, + "Kafka": { + //是否使用生产者 + "UseProducer": false, + "ProducerSettings": { + "BootstrapServers": "192.168.20.241:9092", //confluent cloud bootstrap servers + "SaslMechanism": "Plain", + "SecurityProtocol": "SaslSsl", + "SaslUsername": "", + "SaslPassword": "" + }, + //是否使用消费者 + "UseConsumer": false, + //是否持续监听消费者订阅 用于while循环订阅 + "IsConsumerSubscribe": true, + "ConsumerSettings": { + "BootstrapServers": "192.168.20.241:9092", //confluent cloud bootstrap servers + "GroupId": "amcl_group", //web-example-group + "SaslMechanism": "Plain", + "SecurityProtocol": "SaslSsl", + "SaslUsername": "", + "SaslPassword": "" + }, + "Topics": { + "TestTopic": "alarm_topic" + } + }, + "Mail": { + "Address": "code283591387@163.com", //发件的邮箱 + "Host": "smtp.163.com", + "Name": "VOL", //发送人名称 + "Port": 25, + "EnableSsl": false, + "AuthPwd": "授权密码" //授权密码(对应邮箱设置里面去开启) + }, + "QuartzAccessKey": "65EC9387355E4717899C552963CE59FF" //定时任务的值,请自行修改 +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/builder_run.bat b/Pure_Vite_Net7/WebNet7/VOL.WebApi/builder_run.bat new file mode 100644 index 0000000000000000000000000000000000000000..69b53d9228c245fd4ba9c266c2a63af9eeae01e3 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/builder_run.bat @@ -0,0 +1 @@ +dotnet run \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/dev_run.bat b/Pure_Vite_Net7/WebNet7/VOL.WebApi/dev_run.bat new file mode 100644 index 0000000000000000000000000000000000000000..af5df9d6c1dc0b3107b7d9a600361d718bdb6796 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/dev_run.bat @@ -0,0 +1 @@ +dotnet watch run \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/quartz/error/2022-09-07.txt b/Pure_Vite_Net7/WebNet7/VOL.WebApi/quartz/error/2022-09-07.txt new file mode 100644 index 0000000000000000000000000000000000000000..be7a5880fe83f8c76e47a11b3706e517dc655bdd --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/quartz/error/2022-09-07.txt @@ -0,0 +1 @@ +添加作业失败,作业:31321,表达式不正确:31作业启动:11作业启动:task0 \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/Upload/Tables/Sys_User/202006191517012253/1111s.jpg b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/Upload/Tables/Sys_User/202006191517012253/1111s.jpg new file mode 100644 index 0000000000000000000000000000000000000000..63f2d03a33ea41a0c66ef1fff3018c022d77d9fc Binary files /dev/null and b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/Upload/Tables/Sys_User/202006191517012253/1111s.jpg differ diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/css/site.css b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/css/site.css new file mode 100644 index 0000000000000000000000000000000000000000..e679a8ea7fb5aa818c3d3544896b178a2e149578 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/css/site.css @@ -0,0 +1,71 @@ +/* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification +for details on configuring this project to bundle and minify static web assets. */ + +a.navbar-brand { + white-space: normal; + text-align: center; + word-break: break-all; +} + +/* Provide sufficient contrast against white background */ +a { + color: #0366d6; +} + +.btn-primary { + color: #fff; + background-color: #1b6ec2; + border-color: #1861ac; +} + +.nav-pills .nav-link.active, .nav-pills .show > .nav-link { + color: #fff; + background-color: #1b6ec2; + border-color: #1861ac; +} + +/* Sticky footer styles +-------------------------------------------------- */ +html { + font-size: 14px; +} +@media (min-width: 768px) { + html { + font-size: 16px; + } +} + +.border-top { + border-top: 1px solid #e5e5e5; +} +.border-bottom { + border-bottom: 1px solid #e5e5e5; +} + +.box-shadow { + box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05); +} + +button.accept-policy { + font-size: 1rem; + line-height: inherit; +} + +/* Sticky footer styles +-------------------------------------------------- */ +html { + position: relative; + min-height: 100%; +} + +body { + /* Margin bottom by footer height */ + margin-bottom: 60px; +} +.footer { + position: absolute; + bottom: 0; + width: 100%; + white-space: nowrap; + line-height: 60px; /* Vertically center the text there */ +} diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/favicon.ico b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..a3a799985c43bc7309d701b2cad129023377dc71 Binary files /dev/null and b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/favicon.ico differ diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/js/site.js b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/js/site.js new file mode 100644 index 0000000000000000000000000000000000000000..ac49c18641810b586571be0cad32a36f6e7141b9 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/js/site.js @@ -0,0 +1,4 @@ +// Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification +// for details on configuring this project to bundle and minify static web assets. + +// Write your JavaScript code. diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/LICENSE b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..86f4b8ca04f8d10574f189b8f73bdf0d575675e3 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2011-2018 Twitter, Inc. +Copyright (c) 2011-2018 The Bootstrap Authors + +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. diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css new file mode 100644 index 0000000000000000000000000000000000000000..68b84f842afeffb95b30ec5fcbeeb23215644b08 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css @@ -0,0 +1,3719 @@ +/*! + * Bootstrap Grid v4.3.1 (https://getbootstrap.com/) + * Copyright 2011-2019 The Bootstrap Authors + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +html { + box-sizing: border-box; + -ms-overflow-style: scrollbar; +} + +*, +*::before, +*::after { + box-sizing: inherit; +} + +.container { + width: 100%; + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} + +@media (min-width: 576px) { + .container { + max-width: 540px; + } +} + +@media (min-width: 768px) { + .container { + max-width: 720px; + } +} + +@media (min-width: 992px) { + .container { + max-width: 960px; + } +} + +@media (min-width: 1200px) { + .container { + max-width: 1140px; + } +} + +.container-fluid { + width: 100%; + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} + +.row { + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-right: -15px; + margin-left: -15px; +} + +.no-gutters { + margin-right: 0; + margin-left: 0; +} + +.no-gutters > .col, +.no-gutters > [class*="col-"] { + padding-right: 0; + padding-left: 0; +} + +.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col, +.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm, +.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md, +.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg, +.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl, +.col-xl-auto { + position: relative; + width: 100%; + padding-right: 15px; + padding-left: 15px; +} + +.col { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; +} + +.col-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: 100%; +} + +.col-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; +} + +.col-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; +} + +.col-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; +} + +.col-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; +} + +.col-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; +} + +.col-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; +} + +.col-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; +} + +.col-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; +} + +.col-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; +} + +.col-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; +} + +.col-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; +} + +.col-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; +} + +.order-first { + -ms-flex-order: -1; + order: -1; +} + +.order-last { + -ms-flex-order: 13; + order: 13; +} + +.order-0 { + -ms-flex-order: 0; + order: 0; +} + +.order-1 { + -ms-flex-order: 1; + order: 1; +} + +.order-2 { + -ms-flex-order: 2; + order: 2; +} + +.order-3 { + -ms-flex-order: 3; + order: 3; +} + +.order-4 { + -ms-flex-order: 4; + order: 4; +} + +.order-5 { + -ms-flex-order: 5; + order: 5; +} + +.order-6 { + -ms-flex-order: 6; + order: 6; +} + +.order-7 { + -ms-flex-order: 7; + order: 7; +} + +.order-8 { + -ms-flex-order: 8; + order: 8; +} + +.order-9 { + -ms-flex-order: 9; + order: 9; +} + +.order-10 { + -ms-flex-order: 10; + order: 10; +} + +.order-11 { + -ms-flex-order: 11; + order: 11; +} + +.order-12 { + -ms-flex-order: 12; + order: 12; +} + +.offset-1 { + margin-left: 8.333333%; +} + +.offset-2 { + margin-left: 16.666667%; +} + +.offset-3 { + margin-left: 25%; +} + +.offset-4 { + margin-left: 33.333333%; +} + +.offset-5 { + margin-left: 41.666667%; +} + +.offset-6 { + margin-left: 50%; +} + +.offset-7 { + margin-left: 58.333333%; +} + +.offset-8 { + margin-left: 66.666667%; +} + +.offset-9 { + margin-left: 75%; +} + +.offset-10 { + margin-left: 83.333333%; +} + +.offset-11 { + margin-left: 91.666667%; +} + +@media (min-width: 576px) { + .col-sm { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; + } + .col-sm-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: 100%; + } + .col-sm-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; + } + .col-sm-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-sm-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-sm-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .col-sm-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; + } + .col-sm-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-sm-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; + } + .col-sm-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; + } + .col-sm-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-sm-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; + } + .col-sm-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; + } + .col-sm-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-sm-first { + -ms-flex-order: -1; + order: -1; + } + .order-sm-last { + -ms-flex-order: 13; + order: 13; + } + .order-sm-0 { + -ms-flex-order: 0; + order: 0; + } + .order-sm-1 { + -ms-flex-order: 1; + order: 1; + } + .order-sm-2 { + -ms-flex-order: 2; + order: 2; + } + .order-sm-3 { + -ms-flex-order: 3; + order: 3; + } + .order-sm-4 { + -ms-flex-order: 4; + order: 4; + } + .order-sm-5 { + -ms-flex-order: 5; + order: 5; + } + .order-sm-6 { + -ms-flex-order: 6; + order: 6; + } + .order-sm-7 { + -ms-flex-order: 7; + order: 7; + } + .order-sm-8 { + -ms-flex-order: 8; + order: 8; + } + .order-sm-9 { + -ms-flex-order: 9; + order: 9; + } + .order-sm-10 { + -ms-flex-order: 10; + order: 10; + } + .order-sm-11 { + -ms-flex-order: 11; + order: 11; + } + .order-sm-12 { + -ms-flex-order: 12; + order: 12; + } + .offset-sm-0 { + margin-left: 0; + } + .offset-sm-1 { + margin-left: 8.333333%; + } + .offset-sm-2 { + margin-left: 16.666667%; + } + .offset-sm-3 { + margin-left: 25%; + } + .offset-sm-4 { + margin-left: 33.333333%; + } + .offset-sm-5 { + margin-left: 41.666667%; + } + .offset-sm-6 { + margin-left: 50%; + } + .offset-sm-7 { + margin-left: 58.333333%; + } + .offset-sm-8 { + margin-left: 66.666667%; + } + .offset-sm-9 { + margin-left: 75%; + } + .offset-sm-10 { + margin-left: 83.333333%; + } + .offset-sm-11 { + margin-left: 91.666667%; + } +} + +@media (min-width: 768px) { + .col-md { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; + } + .col-md-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: 100%; + } + .col-md-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; + } + .col-md-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-md-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-md-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .col-md-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; + } + .col-md-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-md-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; + } + .col-md-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; + } + .col-md-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-md-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; + } + .col-md-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; + } + .col-md-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-md-first { + -ms-flex-order: -1; + order: -1; + } + .order-md-last { + -ms-flex-order: 13; + order: 13; + } + .order-md-0 { + -ms-flex-order: 0; + order: 0; + } + .order-md-1 { + -ms-flex-order: 1; + order: 1; + } + .order-md-2 { + -ms-flex-order: 2; + order: 2; + } + .order-md-3 { + -ms-flex-order: 3; + order: 3; + } + .order-md-4 { + -ms-flex-order: 4; + order: 4; + } + .order-md-5 { + -ms-flex-order: 5; + order: 5; + } + .order-md-6 { + -ms-flex-order: 6; + order: 6; + } + .order-md-7 { + -ms-flex-order: 7; + order: 7; + } + .order-md-8 { + -ms-flex-order: 8; + order: 8; + } + .order-md-9 { + -ms-flex-order: 9; + order: 9; + } + .order-md-10 { + -ms-flex-order: 10; + order: 10; + } + .order-md-11 { + -ms-flex-order: 11; + order: 11; + } + .order-md-12 { + -ms-flex-order: 12; + order: 12; + } + .offset-md-0 { + margin-left: 0; + } + .offset-md-1 { + margin-left: 8.333333%; + } + .offset-md-2 { + margin-left: 16.666667%; + } + .offset-md-3 { + margin-left: 25%; + } + .offset-md-4 { + margin-left: 33.333333%; + } + .offset-md-5 { + margin-left: 41.666667%; + } + .offset-md-6 { + margin-left: 50%; + } + .offset-md-7 { + margin-left: 58.333333%; + } + .offset-md-8 { + margin-left: 66.666667%; + } + .offset-md-9 { + margin-left: 75%; + } + .offset-md-10 { + margin-left: 83.333333%; + } + .offset-md-11 { + margin-left: 91.666667%; + } +} + +@media (min-width: 992px) { + .col-lg { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; + } + .col-lg-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: 100%; + } + .col-lg-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; + } + .col-lg-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-lg-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-lg-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .col-lg-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; + } + .col-lg-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-lg-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; + } + .col-lg-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; + } + .col-lg-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-lg-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; + } + .col-lg-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; + } + .col-lg-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-lg-first { + -ms-flex-order: -1; + order: -1; + } + .order-lg-last { + -ms-flex-order: 13; + order: 13; + } + .order-lg-0 { + -ms-flex-order: 0; + order: 0; + } + .order-lg-1 { + -ms-flex-order: 1; + order: 1; + } + .order-lg-2 { + -ms-flex-order: 2; + order: 2; + } + .order-lg-3 { + -ms-flex-order: 3; + order: 3; + } + .order-lg-4 { + -ms-flex-order: 4; + order: 4; + } + .order-lg-5 { + -ms-flex-order: 5; + order: 5; + } + .order-lg-6 { + -ms-flex-order: 6; + order: 6; + } + .order-lg-7 { + -ms-flex-order: 7; + order: 7; + } + .order-lg-8 { + -ms-flex-order: 8; + order: 8; + } + .order-lg-9 { + -ms-flex-order: 9; + order: 9; + } + .order-lg-10 { + -ms-flex-order: 10; + order: 10; + } + .order-lg-11 { + -ms-flex-order: 11; + order: 11; + } + .order-lg-12 { + -ms-flex-order: 12; + order: 12; + } + .offset-lg-0 { + margin-left: 0; + } + .offset-lg-1 { + margin-left: 8.333333%; + } + .offset-lg-2 { + margin-left: 16.666667%; + } + .offset-lg-3 { + margin-left: 25%; + } + .offset-lg-4 { + margin-left: 33.333333%; + } + .offset-lg-5 { + margin-left: 41.666667%; + } + .offset-lg-6 { + margin-left: 50%; + } + .offset-lg-7 { + margin-left: 58.333333%; + } + .offset-lg-8 { + margin-left: 66.666667%; + } + .offset-lg-9 { + margin-left: 75%; + } + .offset-lg-10 { + margin-left: 83.333333%; + } + .offset-lg-11 { + margin-left: 91.666667%; + } +} + +@media (min-width: 1200px) { + .col-xl { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; + } + .col-xl-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: 100%; + } + .col-xl-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; + } + .col-xl-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-xl-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-xl-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .col-xl-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; + } + .col-xl-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-xl-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; + } + .col-xl-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; + } + .col-xl-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-xl-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; + } + .col-xl-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; + } + .col-xl-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-xl-first { + -ms-flex-order: -1; + order: -1; + } + .order-xl-last { + -ms-flex-order: 13; + order: 13; + } + .order-xl-0 { + -ms-flex-order: 0; + order: 0; + } + .order-xl-1 { + -ms-flex-order: 1; + order: 1; + } + .order-xl-2 { + -ms-flex-order: 2; + order: 2; + } + .order-xl-3 { + -ms-flex-order: 3; + order: 3; + } + .order-xl-4 { + -ms-flex-order: 4; + order: 4; + } + .order-xl-5 { + -ms-flex-order: 5; + order: 5; + } + .order-xl-6 { + -ms-flex-order: 6; + order: 6; + } + .order-xl-7 { + -ms-flex-order: 7; + order: 7; + } + .order-xl-8 { + -ms-flex-order: 8; + order: 8; + } + .order-xl-9 { + -ms-flex-order: 9; + order: 9; + } + .order-xl-10 { + -ms-flex-order: 10; + order: 10; + } + .order-xl-11 { + -ms-flex-order: 11; + order: 11; + } + .order-xl-12 { + -ms-flex-order: 12; + order: 12; + } + .offset-xl-0 { + margin-left: 0; + } + .offset-xl-1 { + margin-left: 8.333333%; + } + .offset-xl-2 { + margin-left: 16.666667%; + } + .offset-xl-3 { + margin-left: 25%; + } + .offset-xl-4 { + margin-left: 33.333333%; + } + .offset-xl-5 { + margin-left: 41.666667%; + } + .offset-xl-6 { + margin-left: 50%; + } + .offset-xl-7 { + margin-left: 58.333333%; + } + .offset-xl-8 { + margin-left: 66.666667%; + } + .offset-xl-9 { + margin-left: 75%; + } + .offset-xl-10 { + margin-left: 83.333333%; + } + .offset-xl-11 { + margin-left: 91.666667%; + } +} + +.d-none { + display: none !important; +} + +.d-inline { + display: inline !important; +} + +.d-inline-block { + display: inline-block !important; +} + +.d-block { + display: block !important; +} + +.d-table { + display: table !important; +} + +.d-table-row { + display: table-row !important; +} + +.d-table-cell { + display: table-cell !important; +} + +.d-flex { + display: -ms-flexbox !important; + display: flex !important; +} + +.d-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; +} + +@media (min-width: 576px) { + .d-sm-none { + display: none !important; + } + .d-sm-inline { + display: inline !important; + } + .d-sm-inline-block { + display: inline-block !important; + } + .d-sm-block { + display: block !important; + } + .d-sm-table { + display: table !important; + } + .d-sm-table-row { + display: table-row !important; + } + .d-sm-table-cell { + display: table-cell !important; + } + .d-sm-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-sm-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media (min-width: 768px) { + .d-md-none { + display: none !important; + } + .d-md-inline { + display: inline !important; + } + .d-md-inline-block { + display: inline-block !important; + } + .d-md-block { + display: block !important; + } + .d-md-table { + display: table !important; + } + .d-md-table-row { + display: table-row !important; + } + .d-md-table-cell { + display: table-cell !important; + } + .d-md-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-md-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media (min-width: 992px) { + .d-lg-none { + display: none !important; + } + .d-lg-inline { + display: inline !important; + } + .d-lg-inline-block { + display: inline-block !important; + } + .d-lg-block { + display: block !important; + } + .d-lg-table { + display: table !important; + } + .d-lg-table-row { + display: table-row !important; + } + .d-lg-table-cell { + display: table-cell !important; + } + .d-lg-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-lg-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media (min-width: 1200px) { + .d-xl-none { + display: none !important; + } + .d-xl-inline { + display: inline !important; + } + .d-xl-inline-block { + display: inline-block !important; + } + .d-xl-block { + display: block !important; + } + .d-xl-table { + display: table !important; + } + .d-xl-table-row { + display: table-row !important; + } + .d-xl-table-cell { + display: table-cell !important; + } + .d-xl-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-xl-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media print { + .d-print-none { + display: none !important; + } + .d-print-inline { + display: inline !important; + } + .d-print-inline-block { + display: inline-block !important; + } + .d-print-block { + display: block !important; + } + .d-print-table { + display: table !important; + } + .d-print-table-row { + display: table-row !important; + } + .d-print-table-cell { + display: table-cell !important; + } + .d-print-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-print-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +.flex-row { + -ms-flex-direction: row !important; + flex-direction: row !important; +} + +.flex-column { + -ms-flex-direction: column !important; + flex-direction: column !important; +} + +.flex-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; +} + +.flex-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; +} + +.flex-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; +} + +.flex-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; +} + +.flex-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; +} + +.flex-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; +} + +.flex-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; +} + +.flex-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; +} + +.flex-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; +} + +.flex-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; +} + +.justify-content-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; +} + +.justify-content-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; +} + +.justify-content-center { + -ms-flex-pack: center !important; + justify-content: center !important; +} + +.justify-content-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; +} + +.justify-content-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; +} + +.align-items-start { + -ms-flex-align: start !important; + align-items: flex-start !important; +} + +.align-items-end { + -ms-flex-align: end !important; + align-items: flex-end !important; +} + +.align-items-center { + -ms-flex-align: center !important; + align-items: center !important; +} + +.align-items-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; +} + +.align-items-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; +} + +.align-content-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; +} + +.align-content-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; +} + +.align-content-center { + -ms-flex-line-pack: center !important; + align-content: center !important; +} + +.align-content-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; +} + +.align-content-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; +} + +.align-content-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; +} + +.align-self-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; +} + +.align-self-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; +} + +.align-self-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; +} + +.align-self-center { + -ms-flex-item-align: center !important; + align-self: center !important; +} + +.align-self-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; +} + +.align-self-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; +} + +@media (min-width: 576px) { + .flex-sm-row { + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-sm-column { + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-sm-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-sm-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-sm-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-sm-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-sm-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-sm-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-sm-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-sm-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; + } + .flex-sm-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; + } + .flex-sm-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; + } + .justify-content-sm-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-sm-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-sm-center { + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-sm-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-sm-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-sm-start { + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-sm-end { + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-sm-center { + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-sm-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-sm-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-sm-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-sm-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-sm-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-sm-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-sm-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-sm-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-sm-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-sm-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-sm-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-sm-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-sm-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-sm-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} + +@media (min-width: 768px) { + .flex-md-row { + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-md-column { + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-md-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-md-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-md-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-md-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-md-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-md-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-md-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-md-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; + } + .flex-md-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; + } + .flex-md-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; + } + .justify-content-md-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-md-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-md-center { + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-md-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-md-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-md-start { + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-md-end { + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-md-center { + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-md-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-md-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-md-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-md-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-md-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-md-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-md-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-md-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-md-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-md-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-md-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-md-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-md-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-md-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} + +@media (min-width: 992px) { + .flex-lg-row { + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-lg-column { + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-lg-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-lg-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-lg-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-lg-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-lg-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-lg-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-lg-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-lg-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; + } + .flex-lg-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; + } + .flex-lg-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; + } + .justify-content-lg-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-lg-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-lg-center { + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-lg-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-lg-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-lg-start { + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-lg-end { + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-lg-center { + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-lg-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-lg-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-lg-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-lg-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-lg-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-lg-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-lg-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-lg-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-lg-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-lg-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-lg-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-lg-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-lg-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-lg-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} + +@media (min-width: 1200px) { + .flex-xl-row { + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-xl-column { + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-xl-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-xl-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-xl-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-xl-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-xl-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-xl-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-xl-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-xl-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; + } + .flex-xl-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; + } + .flex-xl-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; + } + .justify-content-xl-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-xl-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-xl-center { + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-xl-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-xl-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-xl-start { + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-xl-end { + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-xl-center { + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-xl-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-xl-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-xl-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-xl-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-xl-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-xl-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-xl-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-xl-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-xl-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-xl-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-xl-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-xl-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-xl-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-xl-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} + +.m-0 { + margin: 0 !important; +} + +.mt-0, +.my-0 { + margin-top: 0 !important; +} + +.mr-0, +.mx-0 { + margin-right: 0 !important; +} + +.mb-0, +.my-0 { + margin-bottom: 0 !important; +} + +.ml-0, +.mx-0 { + margin-left: 0 !important; +} + +.m-1 { + margin: 0.25rem !important; +} + +.mt-1, +.my-1 { + margin-top: 0.25rem !important; +} + +.mr-1, +.mx-1 { + margin-right: 0.25rem !important; +} + +.mb-1, +.my-1 { + margin-bottom: 0.25rem !important; +} + +.ml-1, +.mx-1 { + margin-left: 0.25rem !important; +} + +.m-2 { + margin: 0.5rem !important; +} + +.mt-2, +.my-2 { + margin-top: 0.5rem !important; +} + +.mr-2, +.mx-2 { + margin-right: 0.5rem !important; +} + +.mb-2, +.my-2 { + margin-bottom: 0.5rem !important; +} + +.ml-2, +.mx-2 { + margin-left: 0.5rem !important; +} + +.m-3 { + margin: 1rem !important; +} + +.mt-3, +.my-3 { + margin-top: 1rem !important; +} + +.mr-3, +.mx-3 { + margin-right: 1rem !important; +} + +.mb-3, +.my-3 { + margin-bottom: 1rem !important; +} + +.ml-3, +.mx-3 { + margin-left: 1rem !important; +} + +.m-4 { + margin: 1.5rem !important; +} + +.mt-4, +.my-4 { + margin-top: 1.5rem !important; +} + +.mr-4, +.mx-4 { + margin-right: 1.5rem !important; +} + +.mb-4, +.my-4 { + margin-bottom: 1.5rem !important; +} + +.ml-4, +.mx-4 { + margin-left: 1.5rem !important; +} + +.m-5 { + margin: 3rem !important; +} + +.mt-5, +.my-5 { + margin-top: 3rem !important; +} + +.mr-5, +.mx-5 { + margin-right: 3rem !important; +} + +.mb-5, +.my-5 { + margin-bottom: 3rem !important; +} + +.ml-5, +.mx-5 { + margin-left: 3rem !important; +} + +.p-0 { + padding: 0 !important; +} + +.pt-0, +.py-0 { + padding-top: 0 !important; +} + +.pr-0, +.px-0 { + padding-right: 0 !important; +} + +.pb-0, +.py-0 { + padding-bottom: 0 !important; +} + +.pl-0, +.px-0 { + padding-left: 0 !important; +} + +.p-1 { + padding: 0.25rem !important; +} + +.pt-1, +.py-1 { + padding-top: 0.25rem !important; +} + +.pr-1, +.px-1 { + padding-right: 0.25rem !important; +} + +.pb-1, +.py-1 { + padding-bottom: 0.25rem !important; +} + +.pl-1, +.px-1 { + padding-left: 0.25rem !important; +} + +.p-2 { + padding: 0.5rem !important; +} + +.pt-2, +.py-2 { + padding-top: 0.5rem !important; +} + +.pr-2, +.px-2 { + padding-right: 0.5rem !important; +} + +.pb-2, +.py-2 { + padding-bottom: 0.5rem !important; +} + +.pl-2, +.px-2 { + padding-left: 0.5rem !important; +} + +.p-3 { + padding: 1rem !important; +} + +.pt-3, +.py-3 { + padding-top: 1rem !important; +} + +.pr-3, +.px-3 { + padding-right: 1rem !important; +} + +.pb-3, +.py-3 { + padding-bottom: 1rem !important; +} + +.pl-3, +.px-3 { + padding-left: 1rem !important; +} + +.p-4 { + padding: 1.5rem !important; +} + +.pt-4, +.py-4 { + padding-top: 1.5rem !important; +} + +.pr-4, +.px-4 { + padding-right: 1.5rem !important; +} + +.pb-4, +.py-4 { + padding-bottom: 1.5rem !important; +} + +.pl-4, +.px-4 { + padding-left: 1.5rem !important; +} + +.p-5 { + padding: 3rem !important; +} + +.pt-5, +.py-5 { + padding-top: 3rem !important; +} + +.pr-5, +.px-5 { + padding-right: 3rem !important; +} + +.pb-5, +.py-5 { + padding-bottom: 3rem !important; +} + +.pl-5, +.px-5 { + padding-left: 3rem !important; +} + +.m-n1 { + margin: -0.25rem !important; +} + +.mt-n1, +.my-n1 { + margin-top: -0.25rem !important; +} + +.mr-n1, +.mx-n1 { + margin-right: -0.25rem !important; +} + +.mb-n1, +.my-n1 { + margin-bottom: -0.25rem !important; +} + +.ml-n1, +.mx-n1 { + margin-left: -0.25rem !important; +} + +.m-n2 { + margin: -0.5rem !important; +} + +.mt-n2, +.my-n2 { + margin-top: -0.5rem !important; +} + +.mr-n2, +.mx-n2 { + margin-right: -0.5rem !important; +} + +.mb-n2, +.my-n2 { + margin-bottom: -0.5rem !important; +} + +.ml-n2, +.mx-n2 { + margin-left: -0.5rem !important; +} + +.m-n3 { + margin: -1rem !important; +} + +.mt-n3, +.my-n3 { + margin-top: -1rem !important; +} + +.mr-n3, +.mx-n3 { + margin-right: -1rem !important; +} + +.mb-n3, +.my-n3 { + margin-bottom: -1rem !important; +} + +.ml-n3, +.mx-n3 { + margin-left: -1rem !important; +} + +.m-n4 { + margin: -1.5rem !important; +} + +.mt-n4, +.my-n4 { + margin-top: -1.5rem !important; +} + +.mr-n4, +.mx-n4 { + margin-right: -1.5rem !important; +} + +.mb-n4, +.my-n4 { + margin-bottom: -1.5rem !important; +} + +.ml-n4, +.mx-n4 { + margin-left: -1.5rem !important; +} + +.m-n5 { + margin: -3rem !important; +} + +.mt-n5, +.my-n5 { + margin-top: -3rem !important; +} + +.mr-n5, +.mx-n5 { + margin-right: -3rem !important; +} + +.mb-n5, +.my-n5 { + margin-bottom: -3rem !important; +} + +.ml-n5, +.mx-n5 { + margin-left: -3rem !important; +} + +.m-auto { + margin: auto !important; +} + +.mt-auto, +.my-auto { + margin-top: auto !important; +} + +.mr-auto, +.mx-auto { + margin-right: auto !important; +} + +.mb-auto, +.my-auto { + margin-bottom: auto !important; +} + +.ml-auto, +.mx-auto { + margin-left: auto !important; +} + +@media (min-width: 576px) { + .m-sm-0 { + margin: 0 !important; + } + .mt-sm-0, + .my-sm-0 { + margin-top: 0 !important; + } + .mr-sm-0, + .mx-sm-0 { + margin-right: 0 !important; + } + .mb-sm-0, + .my-sm-0 { + margin-bottom: 0 !important; + } + .ml-sm-0, + .mx-sm-0 { + margin-left: 0 !important; + } + .m-sm-1 { + margin: 0.25rem !important; + } + .mt-sm-1, + .my-sm-1 { + margin-top: 0.25rem !important; + } + .mr-sm-1, + .mx-sm-1 { + margin-right: 0.25rem !important; + } + .mb-sm-1, + .my-sm-1 { + margin-bottom: 0.25rem !important; + } + .ml-sm-1, + .mx-sm-1 { + margin-left: 0.25rem !important; + } + .m-sm-2 { + margin: 0.5rem !important; + } + .mt-sm-2, + .my-sm-2 { + margin-top: 0.5rem !important; + } + .mr-sm-2, + .mx-sm-2 { + margin-right: 0.5rem !important; + } + .mb-sm-2, + .my-sm-2 { + margin-bottom: 0.5rem !important; + } + .ml-sm-2, + .mx-sm-2 { + margin-left: 0.5rem !important; + } + .m-sm-3 { + margin: 1rem !important; + } + .mt-sm-3, + .my-sm-3 { + margin-top: 1rem !important; + } + .mr-sm-3, + .mx-sm-3 { + margin-right: 1rem !important; + } + .mb-sm-3, + .my-sm-3 { + margin-bottom: 1rem !important; + } + .ml-sm-3, + .mx-sm-3 { + margin-left: 1rem !important; + } + .m-sm-4 { + margin: 1.5rem !important; + } + .mt-sm-4, + .my-sm-4 { + margin-top: 1.5rem !important; + } + .mr-sm-4, + .mx-sm-4 { + margin-right: 1.5rem !important; + } + .mb-sm-4, + .my-sm-4 { + margin-bottom: 1.5rem !important; + } + .ml-sm-4, + .mx-sm-4 { + margin-left: 1.5rem !important; + } + .m-sm-5 { + margin: 3rem !important; + } + .mt-sm-5, + .my-sm-5 { + margin-top: 3rem !important; + } + .mr-sm-5, + .mx-sm-5 { + margin-right: 3rem !important; + } + .mb-sm-5, + .my-sm-5 { + margin-bottom: 3rem !important; + } + .ml-sm-5, + .mx-sm-5 { + margin-left: 3rem !important; + } + .p-sm-0 { + padding: 0 !important; + } + .pt-sm-0, + .py-sm-0 { + padding-top: 0 !important; + } + .pr-sm-0, + .px-sm-0 { + padding-right: 0 !important; + } + .pb-sm-0, + .py-sm-0 { + padding-bottom: 0 !important; + } + .pl-sm-0, + .px-sm-0 { + padding-left: 0 !important; + } + .p-sm-1 { + padding: 0.25rem !important; + } + .pt-sm-1, + .py-sm-1 { + padding-top: 0.25rem !important; + } + .pr-sm-1, + .px-sm-1 { + padding-right: 0.25rem !important; + } + .pb-sm-1, + .py-sm-1 { + padding-bottom: 0.25rem !important; + } + .pl-sm-1, + .px-sm-1 { + padding-left: 0.25rem !important; + } + .p-sm-2 { + padding: 0.5rem !important; + } + .pt-sm-2, + .py-sm-2 { + padding-top: 0.5rem !important; + } + .pr-sm-2, + .px-sm-2 { + padding-right: 0.5rem !important; + } + .pb-sm-2, + .py-sm-2 { + padding-bottom: 0.5rem !important; + } + .pl-sm-2, + .px-sm-2 { + padding-left: 0.5rem !important; + } + .p-sm-3 { + padding: 1rem !important; + } + .pt-sm-3, + .py-sm-3 { + padding-top: 1rem !important; + } + .pr-sm-3, + .px-sm-3 { + padding-right: 1rem !important; + } + .pb-sm-3, + .py-sm-3 { + padding-bottom: 1rem !important; + } + .pl-sm-3, + .px-sm-3 { + padding-left: 1rem !important; + } + .p-sm-4 { + padding: 1.5rem !important; + } + .pt-sm-4, + .py-sm-4 { + padding-top: 1.5rem !important; + } + .pr-sm-4, + .px-sm-4 { + padding-right: 1.5rem !important; + } + .pb-sm-4, + .py-sm-4 { + padding-bottom: 1.5rem !important; + } + .pl-sm-4, + .px-sm-4 { + padding-left: 1.5rem !important; + } + .p-sm-5 { + padding: 3rem !important; + } + .pt-sm-5, + .py-sm-5 { + padding-top: 3rem !important; + } + .pr-sm-5, + .px-sm-5 { + padding-right: 3rem !important; + } + .pb-sm-5, + .py-sm-5 { + padding-bottom: 3rem !important; + } + .pl-sm-5, + .px-sm-5 { + padding-left: 3rem !important; + } + .m-sm-n1 { + margin: -0.25rem !important; + } + .mt-sm-n1, + .my-sm-n1 { + margin-top: -0.25rem !important; + } + .mr-sm-n1, + .mx-sm-n1 { + margin-right: -0.25rem !important; + } + .mb-sm-n1, + .my-sm-n1 { + margin-bottom: -0.25rem !important; + } + .ml-sm-n1, + .mx-sm-n1 { + margin-left: -0.25rem !important; + } + .m-sm-n2 { + margin: -0.5rem !important; + } + .mt-sm-n2, + .my-sm-n2 { + margin-top: -0.5rem !important; + } + .mr-sm-n2, + .mx-sm-n2 { + margin-right: -0.5rem !important; + } + .mb-sm-n2, + .my-sm-n2 { + margin-bottom: -0.5rem !important; + } + .ml-sm-n2, + .mx-sm-n2 { + margin-left: -0.5rem !important; + } + .m-sm-n3 { + margin: -1rem !important; + } + .mt-sm-n3, + .my-sm-n3 { + margin-top: -1rem !important; + } + .mr-sm-n3, + .mx-sm-n3 { + margin-right: -1rem !important; + } + .mb-sm-n3, + .my-sm-n3 { + margin-bottom: -1rem !important; + } + .ml-sm-n3, + .mx-sm-n3 { + margin-left: -1rem !important; + } + .m-sm-n4 { + margin: -1.5rem !important; + } + .mt-sm-n4, + .my-sm-n4 { + margin-top: -1.5rem !important; + } + .mr-sm-n4, + .mx-sm-n4 { + margin-right: -1.5rem !important; + } + .mb-sm-n4, + .my-sm-n4 { + margin-bottom: -1.5rem !important; + } + .ml-sm-n4, + .mx-sm-n4 { + margin-left: -1.5rem !important; + } + .m-sm-n5 { + margin: -3rem !important; + } + .mt-sm-n5, + .my-sm-n5 { + margin-top: -3rem !important; + } + .mr-sm-n5, + .mx-sm-n5 { + margin-right: -3rem !important; + } + .mb-sm-n5, + .my-sm-n5 { + margin-bottom: -3rem !important; + } + .ml-sm-n5, + .mx-sm-n5 { + margin-left: -3rem !important; + } + .m-sm-auto { + margin: auto !important; + } + .mt-sm-auto, + .my-sm-auto { + margin-top: auto !important; + } + .mr-sm-auto, + .mx-sm-auto { + margin-right: auto !important; + } + .mb-sm-auto, + .my-sm-auto { + margin-bottom: auto !important; + } + .ml-sm-auto, + .mx-sm-auto { + margin-left: auto !important; + } +} + +@media (min-width: 768px) { + .m-md-0 { + margin: 0 !important; + } + .mt-md-0, + .my-md-0 { + margin-top: 0 !important; + } + .mr-md-0, + .mx-md-0 { + margin-right: 0 !important; + } + .mb-md-0, + .my-md-0 { + margin-bottom: 0 !important; + } + .ml-md-0, + .mx-md-0 { + margin-left: 0 !important; + } + .m-md-1 { + margin: 0.25rem !important; + } + .mt-md-1, + .my-md-1 { + margin-top: 0.25rem !important; + } + .mr-md-1, + .mx-md-1 { + margin-right: 0.25rem !important; + } + .mb-md-1, + .my-md-1 { + margin-bottom: 0.25rem !important; + } + .ml-md-1, + .mx-md-1 { + margin-left: 0.25rem !important; + } + .m-md-2 { + margin: 0.5rem !important; + } + .mt-md-2, + .my-md-2 { + margin-top: 0.5rem !important; + } + .mr-md-2, + .mx-md-2 { + margin-right: 0.5rem !important; + } + .mb-md-2, + .my-md-2 { + margin-bottom: 0.5rem !important; + } + .ml-md-2, + .mx-md-2 { + margin-left: 0.5rem !important; + } + .m-md-3 { + margin: 1rem !important; + } + .mt-md-3, + .my-md-3 { + margin-top: 1rem !important; + } + .mr-md-3, + .mx-md-3 { + margin-right: 1rem !important; + } + .mb-md-3, + .my-md-3 { + margin-bottom: 1rem !important; + } + .ml-md-3, + .mx-md-3 { + margin-left: 1rem !important; + } + .m-md-4 { + margin: 1.5rem !important; + } + .mt-md-4, + .my-md-4 { + margin-top: 1.5rem !important; + } + .mr-md-4, + .mx-md-4 { + margin-right: 1.5rem !important; + } + .mb-md-4, + .my-md-4 { + margin-bottom: 1.5rem !important; + } + .ml-md-4, + .mx-md-4 { + margin-left: 1.5rem !important; + } + .m-md-5 { + margin: 3rem !important; + } + .mt-md-5, + .my-md-5 { + margin-top: 3rem !important; + } + .mr-md-5, + .mx-md-5 { + margin-right: 3rem !important; + } + .mb-md-5, + .my-md-5 { + margin-bottom: 3rem !important; + } + .ml-md-5, + .mx-md-5 { + margin-left: 3rem !important; + } + .p-md-0 { + padding: 0 !important; + } + .pt-md-0, + .py-md-0 { + padding-top: 0 !important; + } + .pr-md-0, + .px-md-0 { + padding-right: 0 !important; + } + .pb-md-0, + .py-md-0 { + padding-bottom: 0 !important; + } + .pl-md-0, + .px-md-0 { + padding-left: 0 !important; + } + .p-md-1 { + padding: 0.25rem !important; + } + .pt-md-1, + .py-md-1 { + padding-top: 0.25rem !important; + } + .pr-md-1, + .px-md-1 { + padding-right: 0.25rem !important; + } + .pb-md-1, + .py-md-1 { + padding-bottom: 0.25rem !important; + } + .pl-md-1, + .px-md-1 { + padding-left: 0.25rem !important; + } + .p-md-2 { + padding: 0.5rem !important; + } + .pt-md-2, + .py-md-2 { + padding-top: 0.5rem !important; + } + .pr-md-2, + .px-md-2 { + padding-right: 0.5rem !important; + } + .pb-md-2, + .py-md-2 { + padding-bottom: 0.5rem !important; + } + .pl-md-2, + .px-md-2 { + padding-left: 0.5rem !important; + } + .p-md-3 { + padding: 1rem !important; + } + .pt-md-3, + .py-md-3 { + padding-top: 1rem !important; + } + .pr-md-3, + .px-md-3 { + padding-right: 1rem !important; + } + .pb-md-3, + .py-md-3 { + padding-bottom: 1rem !important; + } + .pl-md-3, + .px-md-3 { + padding-left: 1rem !important; + } + .p-md-4 { + padding: 1.5rem !important; + } + .pt-md-4, + .py-md-4 { + padding-top: 1.5rem !important; + } + .pr-md-4, + .px-md-4 { + padding-right: 1.5rem !important; + } + .pb-md-4, + .py-md-4 { + padding-bottom: 1.5rem !important; + } + .pl-md-4, + .px-md-4 { + padding-left: 1.5rem !important; + } + .p-md-5 { + padding: 3rem !important; + } + .pt-md-5, + .py-md-5 { + padding-top: 3rem !important; + } + .pr-md-5, + .px-md-5 { + padding-right: 3rem !important; + } + .pb-md-5, + .py-md-5 { + padding-bottom: 3rem !important; + } + .pl-md-5, + .px-md-5 { + padding-left: 3rem !important; + } + .m-md-n1 { + margin: -0.25rem !important; + } + .mt-md-n1, + .my-md-n1 { + margin-top: -0.25rem !important; + } + .mr-md-n1, + .mx-md-n1 { + margin-right: -0.25rem !important; + } + .mb-md-n1, + .my-md-n1 { + margin-bottom: -0.25rem !important; + } + .ml-md-n1, + .mx-md-n1 { + margin-left: -0.25rem !important; + } + .m-md-n2 { + margin: -0.5rem !important; + } + .mt-md-n2, + .my-md-n2 { + margin-top: -0.5rem !important; + } + .mr-md-n2, + .mx-md-n2 { + margin-right: -0.5rem !important; + } + .mb-md-n2, + .my-md-n2 { + margin-bottom: -0.5rem !important; + } + .ml-md-n2, + .mx-md-n2 { + margin-left: -0.5rem !important; + } + .m-md-n3 { + margin: -1rem !important; + } + .mt-md-n3, + .my-md-n3 { + margin-top: -1rem !important; + } + .mr-md-n3, + .mx-md-n3 { + margin-right: -1rem !important; + } + .mb-md-n3, + .my-md-n3 { + margin-bottom: -1rem !important; + } + .ml-md-n3, + .mx-md-n3 { + margin-left: -1rem !important; + } + .m-md-n4 { + margin: -1.5rem !important; + } + .mt-md-n4, + .my-md-n4 { + margin-top: -1.5rem !important; + } + .mr-md-n4, + .mx-md-n4 { + margin-right: -1.5rem !important; + } + .mb-md-n4, + .my-md-n4 { + margin-bottom: -1.5rem !important; + } + .ml-md-n4, + .mx-md-n4 { + margin-left: -1.5rem !important; + } + .m-md-n5 { + margin: -3rem !important; + } + .mt-md-n5, + .my-md-n5 { + margin-top: -3rem !important; + } + .mr-md-n5, + .mx-md-n5 { + margin-right: -3rem !important; + } + .mb-md-n5, + .my-md-n5 { + margin-bottom: -3rem !important; + } + .ml-md-n5, + .mx-md-n5 { + margin-left: -3rem !important; + } + .m-md-auto { + margin: auto !important; + } + .mt-md-auto, + .my-md-auto { + margin-top: auto !important; + } + .mr-md-auto, + .mx-md-auto { + margin-right: auto !important; + } + .mb-md-auto, + .my-md-auto { + margin-bottom: auto !important; + } + .ml-md-auto, + .mx-md-auto { + margin-left: auto !important; + } +} + +@media (min-width: 992px) { + .m-lg-0 { + margin: 0 !important; + } + .mt-lg-0, + .my-lg-0 { + margin-top: 0 !important; + } + .mr-lg-0, + .mx-lg-0 { + margin-right: 0 !important; + } + .mb-lg-0, + .my-lg-0 { + margin-bottom: 0 !important; + } + .ml-lg-0, + .mx-lg-0 { + margin-left: 0 !important; + } + .m-lg-1 { + margin: 0.25rem !important; + } + .mt-lg-1, + .my-lg-1 { + margin-top: 0.25rem !important; + } + .mr-lg-1, + .mx-lg-1 { + margin-right: 0.25rem !important; + } + .mb-lg-1, + .my-lg-1 { + margin-bottom: 0.25rem !important; + } + .ml-lg-1, + .mx-lg-1 { + margin-left: 0.25rem !important; + } + .m-lg-2 { + margin: 0.5rem !important; + } + .mt-lg-2, + .my-lg-2 { + margin-top: 0.5rem !important; + } + .mr-lg-2, + .mx-lg-2 { + margin-right: 0.5rem !important; + } + .mb-lg-2, + .my-lg-2 { + margin-bottom: 0.5rem !important; + } + .ml-lg-2, + .mx-lg-2 { + margin-left: 0.5rem !important; + } + .m-lg-3 { + margin: 1rem !important; + } + .mt-lg-3, + .my-lg-3 { + margin-top: 1rem !important; + } + .mr-lg-3, + .mx-lg-3 { + margin-right: 1rem !important; + } + .mb-lg-3, + .my-lg-3 { + margin-bottom: 1rem !important; + } + .ml-lg-3, + .mx-lg-3 { + margin-left: 1rem !important; + } + .m-lg-4 { + margin: 1.5rem !important; + } + .mt-lg-4, + .my-lg-4 { + margin-top: 1.5rem !important; + } + .mr-lg-4, + .mx-lg-4 { + margin-right: 1.5rem !important; + } + .mb-lg-4, + .my-lg-4 { + margin-bottom: 1.5rem !important; + } + .ml-lg-4, + .mx-lg-4 { + margin-left: 1.5rem !important; + } + .m-lg-5 { + margin: 3rem !important; + } + .mt-lg-5, + .my-lg-5 { + margin-top: 3rem !important; + } + .mr-lg-5, + .mx-lg-5 { + margin-right: 3rem !important; + } + .mb-lg-5, + .my-lg-5 { + margin-bottom: 3rem !important; + } + .ml-lg-5, + .mx-lg-5 { + margin-left: 3rem !important; + } + .p-lg-0 { + padding: 0 !important; + } + .pt-lg-0, + .py-lg-0 { + padding-top: 0 !important; + } + .pr-lg-0, + .px-lg-0 { + padding-right: 0 !important; + } + .pb-lg-0, + .py-lg-0 { + padding-bottom: 0 !important; + } + .pl-lg-0, + .px-lg-0 { + padding-left: 0 !important; + } + .p-lg-1 { + padding: 0.25rem !important; + } + .pt-lg-1, + .py-lg-1 { + padding-top: 0.25rem !important; + } + .pr-lg-1, + .px-lg-1 { + padding-right: 0.25rem !important; + } + .pb-lg-1, + .py-lg-1 { + padding-bottom: 0.25rem !important; + } + .pl-lg-1, + .px-lg-1 { + padding-left: 0.25rem !important; + } + .p-lg-2 { + padding: 0.5rem !important; + } + .pt-lg-2, + .py-lg-2 { + padding-top: 0.5rem !important; + } + .pr-lg-2, + .px-lg-2 { + padding-right: 0.5rem !important; + } + .pb-lg-2, + .py-lg-2 { + padding-bottom: 0.5rem !important; + } + .pl-lg-2, + .px-lg-2 { + padding-left: 0.5rem !important; + } + .p-lg-3 { + padding: 1rem !important; + } + .pt-lg-3, + .py-lg-3 { + padding-top: 1rem !important; + } + .pr-lg-3, + .px-lg-3 { + padding-right: 1rem !important; + } + .pb-lg-3, + .py-lg-3 { + padding-bottom: 1rem !important; + } + .pl-lg-3, + .px-lg-3 { + padding-left: 1rem !important; + } + .p-lg-4 { + padding: 1.5rem !important; + } + .pt-lg-4, + .py-lg-4 { + padding-top: 1.5rem !important; + } + .pr-lg-4, + .px-lg-4 { + padding-right: 1.5rem !important; + } + .pb-lg-4, + .py-lg-4 { + padding-bottom: 1.5rem !important; + } + .pl-lg-4, + .px-lg-4 { + padding-left: 1.5rem !important; + } + .p-lg-5 { + padding: 3rem !important; + } + .pt-lg-5, + .py-lg-5 { + padding-top: 3rem !important; + } + .pr-lg-5, + .px-lg-5 { + padding-right: 3rem !important; + } + .pb-lg-5, + .py-lg-5 { + padding-bottom: 3rem !important; + } + .pl-lg-5, + .px-lg-5 { + padding-left: 3rem !important; + } + .m-lg-n1 { + margin: -0.25rem !important; + } + .mt-lg-n1, + .my-lg-n1 { + margin-top: -0.25rem !important; + } + .mr-lg-n1, + .mx-lg-n1 { + margin-right: -0.25rem !important; + } + .mb-lg-n1, + .my-lg-n1 { + margin-bottom: -0.25rem !important; + } + .ml-lg-n1, + .mx-lg-n1 { + margin-left: -0.25rem !important; + } + .m-lg-n2 { + margin: -0.5rem !important; + } + .mt-lg-n2, + .my-lg-n2 { + margin-top: -0.5rem !important; + } + .mr-lg-n2, + .mx-lg-n2 { + margin-right: -0.5rem !important; + } + .mb-lg-n2, + .my-lg-n2 { + margin-bottom: -0.5rem !important; + } + .ml-lg-n2, + .mx-lg-n2 { + margin-left: -0.5rem !important; + } + .m-lg-n3 { + margin: -1rem !important; + } + .mt-lg-n3, + .my-lg-n3 { + margin-top: -1rem !important; + } + .mr-lg-n3, + .mx-lg-n3 { + margin-right: -1rem !important; + } + .mb-lg-n3, + .my-lg-n3 { + margin-bottom: -1rem !important; + } + .ml-lg-n3, + .mx-lg-n3 { + margin-left: -1rem !important; + } + .m-lg-n4 { + margin: -1.5rem !important; + } + .mt-lg-n4, + .my-lg-n4 { + margin-top: -1.5rem !important; + } + .mr-lg-n4, + .mx-lg-n4 { + margin-right: -1.5rem !important; + } + .mb-lg-n4, + .my-lg-n4 { + margin-bottom: -1.5rem !important; + } + .ml-lg-n4, + .mx-lg-n4 { + margin-left: -1.5rem !important; + } + .m-lg-n5 { + margin: -3rem !important; + } + .mt-lg-n5, + .my-lg-n5 { + margin-top: -3rem !important; + } + .mr-lg-n5, + .mx-lg-n5 { + margin-right: -3rem !important; + } + .mb-lg-n5, + .my-lg-n5 { + margin-bottom: -3rem !important; + } + .ml-lg-n5, + .mx-lg-n5 { + margin-left: -3rem !important; + } + .m-lg-auto { + margin: auto !important; + } + .mt-lg-auto, + .my-lg-auto { + margin-top: auto !important; + } + .mr-lg-auto, + .mx-lg-auto { + margin-right: auto !important; + } + .mb-lg-auto, + .my-lg-auto { + margin-bottom: auto !important; + } + .ml-lg-auto, + .mx-lg-auto { + margin-left: auto !important; + } +} + +@media (min-width: 1200px) { + .m-xl-0 { + margin: 0 !important; + } + .mt-xl-0, + .my-xl-0 { + margin-top: 0 !important; + } + .mr-xl-0, + .mx-xl-0 { + margin-right: 0 !important; + } + .mb-xl-0, + .my-xl-0 { + margin-bottom: 0 !important; + } + .ml-xl-0, + .mx-xl-0 { + margin-left: 0 !important; + } + .m-xl-1 { + margin: 0.25rem !important; + } + .mt-xl-1, + .my-xl-1 { + margin-top: 0.25rem !important; + } + .mr-xl-1, + .mx-xl-1 { + margin-right: 0.25rem !important; + } + .mb-xl-1, + .my-xl-1 { + margin-bottom: 0.25rem !important; + } + .ml-xl-1, + .mx-xl-1 { + margin-left: 0.25rem !important; + } + .m-xl-2 { + margin: 0.5rem !important; + } + .mt-xl-2, + .my-xl-2 { + margin-top: 0.5rem !important; + } + .mr-xl-2, + .mx-xl-2 { + margin-right: 0.5rem !important; + } + .mb-xl-2, + .my-xl-2 { + margin-bottom: 0.5rem !important; + } + .ml-xl-2, + .mx-xl-2 { + margin-left: 0.5rem !important; + } + .m-xl-3 { + margin: 1rem !important; + } + .mt-xl-3, + .my-xl-3 { + margin-top: 1rem !important; + } + .mr-xl-3, + .mx-xl-3 { + margin-right: 1rem !important; + } + .mb-xl-3, + .my-xl-3 { + margin-bottom: 1rem !important; + } + .ml-xl-3, + .mx-xl-3 { + margin-left: 1rem !important; + } + .m-xl-4 { + margin: 1.5rem !important; + } + .mt-xl-4, + .my-xl-4 { + margin-top: 1.5rem !important; + } + .mr-xl-4, + .mx-xl-4 { + margin-right: 1.5rem !important; + } + .mb-xl-4, + .my-xl-4 { + margin-bottom: 1.5rem !important; + } + .ml-xl-4, + .mx-xl-4 { + margin-left: 1.5rem !important; + } + .m-xl-5 { + margin: 3rem !important; + } + .mt-xl-5, + .my-xl-5 { + margin-top: 3rem !important; + } + .mr-xl-5, + .mx-xl-5 { + margin-right: 3rem !important; + } + .mb-xl-5, + .my-xl-5 { + margin-bottom: 3rem !important; + } + .ml-xl-5, + .mx-xl-5 { + margin-left: 3rem !important; + } + .p-xl-0 { + padding: 0 !important; + } + .pt-xl-0, + .py-xl-0 { + padding-top: 0 !important; + } + .pr-xl-0, + .px-xl-0 { + padding-right: 0 !important; + } + .pb-xl-0, + .py-xl-0 { + padding-bottom: 0 !important; + } + .pl-xl-0, + .px-xl-0 { + padding-left: 0 !important; + } + .p-xl-1 { + padding: 0.25rem !important; + } + .pt-xl-1, + .py-xl-1 { + padding-top: 0.25rem !important; + } + .pr-xl-1, + .px-xl-1 { + padding-right: 0.25rem !important; + } + .pb-xl-1, + .py-xl-1 { + padding-bottom: 0.25rem !important; + } + .pl-xl-1, + .px-xl-1 { + padding-left: 0.25rem !important; + } + .p-xl-2 { + padding: 0.5rem !important; + } + .pt-xl-2, + .py-xl-2 { + padding-top: 0.5rem !important; + } + .pr-xl-2, + .px-xl-2 { + padding-right: 0.5rem !important; + } + .pb-xl-2, + .py-xl-2 { + padding-bottom: 0.5rem !important; + } + .pl-xl-2, + .px-xl-2 { + padding-left: 0.5rem !important; + } + .p-xl-3 { + padding: 1rem !important; + } + .pt-xl-3, + .py-xl-3 { + padding-top: 1rem !important; + } + .pr-xl-3, + .px-xl-3 { + padding-right: 1rem !important; + } + .pb-xl-3, + .py-xl-3 { + padding-bottom: 1rem !important; + } + .pl-xl-3, + .px-xl-3 { + padding-left: 1rem !important; + } + .p-xl-4 { + padding: 1.5rem !important; + } + .pt-xl-4, + .py-xl-4 { + padding-top: 1.5rem !important; + } + .pr-xl-4, + .px-xl-4 { + padding-right: 1.5rem !important; + } + .pb-xl-4, + .py-xl-4 { + padding-bottom: 1.5rem !important; + } + .pl-xl-4, + .px-xl-4 { + padding-left: 1.5rem !important; + } + .p-xl-5 { + padding: 3rem !important; + } + .pt-xl-5, + .py-xl-5 { + padding-top: 3rem !important; + } + .pr-xl-5, + .px-xl-5 { + padding-right: 3rem !important; + } + .pb-xl-5, + .py-xl-5 { + padding-bottom: 3rem !important; + } + .pl-xl-5, + .px-xl-5 { + padding-left: 3rem !important; + } + .m-xl-n1 { + margin: -0.25rem !important; + } + .mt-xl-n1, + .my-xl-n1 { + margin-top: -0.25rem !important; + } + .mr-xl-n1, + .mx-xl-n1 { + margin-right: -0.25rem !important; + } + .mb-xl-n1, + .my-xl-n1 { + margin-bottom: -0.25rem !important; + } + .ml-xl-n1, + .mx-xl-n1 { + margin-left: -0.25rem !important; + } + .m-xl-n2 { + margin: -0.5rem !important; + } + .mt-xl-n2, + .my-xl-n2 { + margin-top: -0.5rem !important; + } + .mr-xl-n2, + .mx-xl-n2 { + margin-right: -0.5rem !important; + } + .mb-xl-n2, + .my-xl-n2 { + margin-bottom: -0.5rem !important; + } + .ml-xl-n2, + .mx-xl-n2 { + margin-left: -0.5rem !important; + } + .m-xl-n3 { + margin: -1rem !important; + } + .mt-xl-n3, + .my-xl-n3 { + margin-top: -1rem !important; + } + .mr-xl-n3, + .mx-xl-n3 { + margin-right: -1rem !important; + } + .mb-xl-n3, + .my-xl-n3 { + margin-bottom: -1rem !important; + } + .ml-xl-n3, + .mx-xl-n3 { + margin-left: -1rem !important; + } + .m-xl-n4 { + margin: -1.5rem !important; + } + .mt-xl-n4, + .my-xl-n4 { + margin-top: -1.5rem !important; + } + .mr-xl-n4, + .mx-xl-n4 { + margin-right: -1.5rem !important; + } + .mb-xl-n4, + .my-xl-n4 { + margin-bottom: -1.5rem !important; + } + .ml-xl-n4, + .mx-xl-n4 { + margin-left: -1.5rem !important; + } + .m-xl-n5 { + margin: -3rem !important; + } + .mt-xl-n5, + .my-xl-n5 { + margin-top: -3rem !important; + } + .mr-xl-n5, + .mx-xl-n5 { + margin-right: -3rem !important; + } + .mb-xl-n5, + .my-xl-n5 { + margin-bottom: -3rem !important; + } + .ml-xl-n5, + .mx-xl-n5 { + margin-left: -3rem !important; + } + .m-xl-auto { + margin: auto !important; + } + .mt-xl-auto, + .my-xl-auto { + margin-top: auto !important; + } + .mr-xl-auto, + .mx-xl-auto { + margin-right: auto !important; + } + .mb-xl-auto, + .my-xl-auto { + margin-bottom: auto !important; + } + .ml-xl-auto, + .mx-xl-auto { + margin-left: auto !important; + } +} +/*# sourceMappingURL=bootstrap-grid.css.map */ \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map new file mode 100644 index 0000000000000000000000000000000000000000..db62f2f31126c5624e19f183c0e735f70b8ab76e --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../scss/bootstrap-grid.scss","bootstrap-grid.css","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/mixins/_breakpoints.scss","../../scss/_variables.scss","../../scss/mixins/_grid-framework.scss","../../scss/utilities/_display.scss","../../scss/utilities/_flex.scss","../../scss/utilities/_spacing.scss"],"names":[],"mappings":"AAAA;;;;;ECKE;ADEF;EACE,sBAAsB;EACtB,6BAA6B;ACA/B;;ADGA;;;EAGE,mBAAmB;ACArB;;ACVE;ECAA,WAAW;EACX,mBAA0B;EAC1B,kBAAyB;EACzB,kBAAkB;EAClB,iBAAiB;AFcnB;;AGqCI;EFvDF;ICYI,gBE8LK;EJnLT;AACF;;AG+BI;EFvDF;ICYI,gBE+LK;EJ9KT;AACF;;AGyBI;EFvDF;ICYI,gBEgMK;EJzKT;AACF;;AGmBI;EFvDF;ICYI,iBEiMM;EJpKV;AACF;;AC9BE;ECZA,WAAW;EACX,mBAA0B;EAC1B,kBAAyB;EACzB,kBAAkB;EAClB,iBAAiB;AF8CnB;;AC5BE;ECJA,oBAAa;EAAb,aAAa;EACb,mBAAe;EAAf,eAAe;EACf,mBAA0B;EAC1B,kBAAyB;AFoC3B;;AC7BE;EACE,eAAe;EACf,cAAc;ADgClB;;AClCE;;EAMI,gBAAgB;EAChB,eAAe;ADiCrB;;AKlEE;;;;;;EACE,kBAAkB;EAClB,WAAW;EACX,mBAA0B;EAC1B,kBAAyB;AL0E7B;;AKvDM;EACE,0BAAa;EAAb,aAAa;EACb,oBAAY;EAAZ,YAAY;EACZ,eAAe;AL0DvB;;AKxDM;EACE,kBAAc;EAAd,cAAc;EACd,WAAW;EACX,eAAe;AL2DvB;;AKvDQ;EHFN,uBAAsC;EAAtC,mBAAsC;EAItC,oBAAuC;AF0DzC;;AK5DQ;EHFN,wBAAsC;EAAtC,oBAAsC;EAItC,qBAAuC;AF+DzC;;AKjEQ;EHFN,iBAAsC;EAAtC,aAAsC;EAItC,cAAuC;AFoEzC;;AKtEQ;EHFN,wBAAsC;EAAtC,oBAAsC;EAItC,qBAAuC;AFyEzC;;AK3EQ;EHFN,wBAAsC;EAAtC,oBAAsC;EAItC,qBAAuC;AF8EzC;;AKhFQ;EHFN,iBAAsC;EAAtC,aAAsC;EAItC,cAAuC;AFmFzC;;AKrFQ;EHFN,wBAAsC;EAAtC,oBAAsC;EAItC,qBAAuC;AFwFzC;;AK1FQ;EHFN,wBAAsC;EAAtC,oBAAsC;EAItC,qBAAuC;AF6FzC;;AK/FQ;EHFN,iBAAsC;EAAtC,aAAsC;EAItC,cAAuC;AFkGzC;;AKpGQ;EHFN,wBAAsC;EAAtC,oBAAsC;EAItC,qBAAuC;AFuGzC;;AKzGQ;EHFN,wBAAsC;EAAtC,oBAAsC;EAItC,qBAAuC;AF4GzC;;AK9GQ;EHFN,kBAAsC;EAAtC,cAAsC;EAItC,eAAuC;AFiHzC;;AK9GM;EAAwB,kBAAS;EAAT,SAAS;ALkHvC;;AKhHM;EAAuB,kBD2KG;EC3KH,SD2KG;AJvDhC;;AKjHQ;EAAwB,iBADZ;EACY,QADZ;ALsHpB;;AKrHQ;EAAwB,iBADZ;EACY,QADZ;AL0HpB;;AKzHQ;EAAwB,iBADZ;EACY,QADZ;AL8HpB;;AK7HQ;EAAwB,iBADZ;EACY,QADZ;ALkIpB;;AKjIQ;EAAwB,iBADZ;EACY,QADZ;ALsIpB;;AKrIQ;EAAwB,iBADZ;EACY,QADZ;AL0IpB;;AKzIQ;EAAwB,iBADZ;EACY,QADZ;AL8IpB;;AK7IQ;EAAwB,iBADZ;EACY,QADZ;ALkJpB;;AKjJQ;EAAwB,iBADZ;EACY,QADZ;ALsJpB;;AKrJQ;EAAwB,iBADZ;EACY,QADZ;AL0JpB;;AKzJQ;EAAwB,kBADZ;EACY,SADZ;AL8JpB;;AK7JQ;EAAwB,kBADZ;EACY,SADZ;ALkKpB;;AKjKQ;EAAwB,kBADZ;EACY,SADZ;ALsKpB;;AK/JU;EHTR,sBAA8C;AF4KhD;;AKnKU;EHTR,uBAA8C;AFgLhD;;AKvKU;EHTR,gBAA8C;AFoLhD;;AK3KU;EHTR,uBAA8C;AFwLhD;;AK/KU;EHTR,uBAA8C;AF4LhD;;AKnLU;EHTR,gBAA8C;AFgMhD;;AKvLU;EHTR,uBAA8C;AFoMhD;;AK3LU;EHTR,uBAA8C;AFwMhD;;AK/LU;EHTR,gBAA8C;AF4MhD;;AKnMU;EHTR,uBAA8C;AFgNhD;;AKvMU;EHTR,uBAA8C;AFoNhD;;AGzMI;EE9BE;IACE,0BAAa;IAAb,aAAa;IACb,oBAAY;IAAZ,YAAY;IACZ,eAAe;EL2OrB;EKzOI;IACE,kBAAc;IAAd,cAAc;IACd,WAAW;IACX,eAAe;EL2OrB;EKvOM;IHFN,uBAAsC;IAAtC,mBAAsC;IAItC,oBAAuC;EFyOvC;EK3OM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EF6OvC;EK/OM;IHFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EFiPvC;EKnPM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFqPvC;EKvPM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFyPvC;EK3PM;IHFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EF6PvC;EK/PM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFiQvC;EKnQM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFqQvC;EKvQM;IHFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EFyQvC;EK3QM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EF6QvC;EK/QM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFiRvC;EKnRM;IHFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;EFqRvC;EKlRI;IAAwB,kBAAS;IAAT,SAAS;ELqRrC;EKnRI;IAAuB,kBD2KG;IC3KH,SD2KG;EJ2G9B;EKnRM;IAAwB,iBADZ;IACY,QADZ;ELuRlB;EKtRM;IAAwB,iBADZ;IACY,QADZ;EL0RlB;EKzRM;IAAwB,iBADZ;IACY,QADZ;EL6RlB;EK5RM;IAAwB,iBADZ;IACY,QADZ;ELgSlB;EK/RM;IAAwB,iBADZ;IACY,QADZ;ELmSlB;EKlSM;IAAwB,iBADZ;IACY,QADZ;ELsSlB;EKrSM;IAAwB,iBADZ;IACY,QADZ;ELySlB;EKxSM;IAAwB,iBADZ;IACY,QADZ;EL4SlB;EK3SM;IAAwB,iBADZ;IACY,QADZ;EL+SlB;EK9SM;IAAwB,iBADZ;IACY,QADZ;ELkTlB;EKjTM;IAAwB,kBADZ;IACY,SADZ;ELqTlB;EKpTM;IAAwB,kBADZ;IACY,SADZ;ELwTlB;EKvTM;IAAwB,kBADZ;IACY,SADZ;EL2TlB;EKpTQ;IHTR,cAA4B;EFgU5B;EKvTQ;IHTR,sBAA8C;EFmU9C;EK1TQ;IHTR,uBAA8C;EFsU9C;EK7TQ;IHTR,gBAA8C;EFyU9C;EKhUQ;IHTR,uBAA8C;EF4U9C;EKnUQ;IHTR,uBAA8C;EF+U9C;EKtUQ;IHTR,gBAA8C;EFkV9C;EKzUQ;IHTR,uBAA8C;EFqV9C;EK5UQ;IHTR,uBAA8C;EFwV9C;EK/UQ;IHTR,gBAA8C;EF2V9C;EKlVQ;IHTR,uBAA8C;EF8V9C;EKrVQ;IHTR,uBAA8C;EFiW9C;AACF;;AGvVI;EE9BE;IACE,0BAAa;IAAb,aAAa;IACb,oBAAY;IAAZ,YAAY;IACZ,eAAe;ELyXrB;EKvXI;IACE,kBAAc;IAAd,cAAc;IACd,WAAW;IACX,eAAe;ELyXrB;EKrXM;IHFN,uBAAsC;IAAtC,mBAAsC;IAItC,oBAAuC;EFuXvC;EKzXM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EF2XvC;EK7XM;IHFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EF+XvC;EKjYM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFmYvC;EKrYM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFuYvC;EKzYM;IHFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EF2YvC;EK7YM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EF+YvC;EKjZM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFmZvC;EKrZM;IHFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EFuZvC;EKzZM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EF2ZvC;EK7ZM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EF+ZvC;EKjaM;IHFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;EFmavC;EKhaI;IAAwB,kBAAS;IAAT,SAAS;ELmarC;EKjaI;IAAuB,kBD2KG;IC3KH,SD2KG;EJyP9B;EKjaM;IAAwB,iBADZ;IACY,QADZ;ELqalB;EKpaM;IAAwB,iBADZ;IACY,QADZ;ELwalB;EKvaM;IAAwB,iBADZ;IACY,QADZ;EL2alB;EK1aM;IAAwB,iBADZ;IACY,QADZ;EL8alB;EK7aM;IAAwB,iBADZ;IACY,QADZ;ELiblB;EKhbM;IAAwB,iBADZ;IACY,QADZ;ELoblB;EKnbM;IAAwB,iBADZ;IACY,QADZ;ELublB;EKtbM;IAAwB,iBADZ;IACY,QADZ;EL0blB;EKzbM;IAAwB,iBADZ;IACY,QADZ;EL6blB;EK5bM;IAAwB,iBADZ;IACY,QADZ;ELgclB;EK/bM;IAAwB,kBADZ;IACY,SADZ;ELmclB;EKlcM;IAAwB,kBADZ;IACY,SADZ;ELsclB;EKrcM;IAAwB,kBADZ;IACY,SADZ;ELyclB;EKlcQ;IHTR,cAA4B;EF8c5B;EKrcQ;IHTR,sBAA8C;EFid9C;EKxcQ;IHTR,uBAA8C;EFod9C;EK3cQ;IHTR,gBAA8C;EFud9C;EK9cQ;IHTR,uBAA8C;EF0d9C;EKjdQ;IHTR,uBAA8C;EF6d9C;EKpdQ;IHTR,gBAA8C;EFge9C;EKvdQ;IHTR,uBAA8C;EFme9C;EK1dQ;IHTR,uBAA8C;EFse9C;EK7dQ;IHTR,gBAA8C;EFye9C;EKheQ;IHTR,uBAA8C;EF4e9C;EKneQ;IHTR,uBAA8C;EF+e9C;AACF;;AGreI;EE9BE;IACE,0BAAa;IAAb,aAAa;IACb,oBAAY;IAAZ,YAAY;IACZ,eAAe;ELugBrB;EKrgBI;IACE,kBAAc;IAAd,cAAc;IACd,WAAW;IACX,eAAe;ELugBrB;EKngBM;IHFN,uBAAsC;IAAtC,mBAAsC;IAItC,oBAAuC;EFqgBvC;EKvgBM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFygBvC;EK3gBM;IHFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EF6gBvC;EK/gBM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFihBvC;EKnhBM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFqhBvC;EKvhBM;IHFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EFyhBvC;EK3hBM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EF6hBvC;EK/hBM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFiiBvC;EKniBM;IHFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EFqiBvC;EKviBM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFyiBvC;EK3iBM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EF6iBvC;EK/iBM;IHFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;EFijBvC;EK9iBI;IAAwB,kBAAS;IAAT,SAAS;ELijBrC;EK/iBI;IAAuB,kBD2KG;IC3KH,SD2KG;EJuY9B;EK/iBM;IAAwB,iBADZ;IACY,QADZ;ELmjBlB;EKljBM;IAAwB,iBADZ;IACY,QADZ;ELsjBlB;EKrjBM;IAAwB,iBADZ;IACY,QADZ;ELyjBlB;EKxjBM;IAAwB,iBADZ;IACY,QADZ;EL4jBlB;EK3jBM;IAAwB,iBADZ;IACY,QADZ;EL+jBlB;EK9jBM;IAAwB,iBADZ;IACY,QADZ;ELkkBlB;EKjkBM;IAAwB,iBADZ;IACY,QADZ;ELqkBlB;EKpkBM;IAAwB,iBADZ;IACY,QADZ;ELwkBlB;EKvkBM;IAAwB,iBADZ;IACY,QADZ;EL2kBlB;EK1kBM;IAAwB,iBADZ;IACY,QADZ;EL8kBlB;EK7kBM;IAAwB,kBADZ;IACY,SADZ;ELilBlB;EKhlBM;IAAwB,kBADZ;IACY,SADZ;ELolBlB;EKnlBM;IAAwB,kBADZ;IACY,SADZ;ELulBlB;EKhlBQ;IHTR,cAA4B;EF4lB5B;EKnlBQ;IHTR,sBAA8C;EF+lB9C;EKtlBQ;IHTR,uBAA8C;EFkmB9C;EKzlBQ;IHTR,gBAA8C;EFqmB9C;EK5lBQ;IHTR,uBAA8C;EFwmB9C;EK/lBQ;IHTR,uBAA8C;EF2mB9C;EKlmBQ;IHTR,gBAA8C;EF8mB9C;EKrmBQ;IHTR,uBAA8C;EFinB9C;EKxmBQ;IHTR,uBAA8C;EFonB9C;EK3mBQ;IHTR,gBAA8C;EFunB9C;EK9mBQ;IHTR,uBAA8C;EF0nB9C;EKjnBQ;IHTR,uBAA8C;EF6nB9C;AACF;;AGnnBI;EE9BE;IACE,0BAAa;IAAb,aAAa;IACb,oBAAY;IAAZ,YAAY;IACZ,eAAe;ELqpBrB;EKnpBI;IACE,kBAAc;IAAd,cAAc;IACd,WAAW;IACX,eAAe;ELqpBrB;EKjpBM;IHFN,uBAAsC;IAAtC,mBAAsC;IAItC,oBAAuC;EFmpBvC;EKrpBM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFupBvC;EKzpBM;IHFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EF2pBvC;EK7pBM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EF+pBvC;EKjqBM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFmqBvC;EKrqBM;IHFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EFuqBvC;EKzqBM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EF2qBvC;EK7qBM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EF+qBvC;EKjrBM;IHFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EFmrBvC;EKrrBM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFurBvC;EKzrBM;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EF2rBvC;EK7rBM;IHFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;EF+rBvC;EK5rBI;IAAwB,kBAAS;IAAT,SAAS;EL+rBrC;EK7rBI;IAAuB,kBD2KG;IC3KH,SD2KG;EJqhB9B;EK7rBM;IAAwB,iBADZ;IACY,QADZ;ELisBlB;EKhsBM;IAAwB,iBADZ;IACY,QADZ;ELosBlB;EKnsBM;IAAwB,iBADZ;IACY,QADZ;ELusBlB;EKtsBM;IAAwB,iBADZ;IACY,QADZ;EL0sBlB;EKzsBM;IAAwB,iBADZ;IACY,QADZ;EL6sBlB;EK5sBM;IAAwB,iBADZ;IACY,QADZ;ELgtBlB;EK/sBM;IAAwB,iBADZ;IACY,QADZ;ELmtBlB;EKltBM;IAAwB,iBADZ;IACY,QADZ;ELstBlB;EKrtBM;IAAwB,iBADZ;IACY,QADZ;ELytBlB;EKxtBM;IAAwB,iBADZ;IACY,QADZ;EL4tBlB;EK3tBM;IAAwB,kBADZ;IACY,SADZ;EL+tBlB;EK9tBM;IAAwB,kBADZ;IACY,SADZ;ELkuBlB;EKjuBM;IAAwB,kBADZ;IACY,SADZ;ELquBlB;EK9tBQ;IHTR,cAA4B;EF0uB5B;EKjuBQ;IHTR,sBAA8C;EF6uB9C;EKpuBQ;IHTR,uBAA8C;EFgvB9C;EKvuBQ;IHTR,gBAA8C;EFmvB9C;EK1uBQ;IHTR,uBAA8C;EFsvB9C;EK7uBQ;IHTR,uBAA8C;EFyvB9C;EKhvBQ;IHTR,gBAA8C;EF4vB9C;EKnvBQ;IHTR,uBAA8C;EF+vB9C;EKtvBQ;IHTR,uBAA8C;EFkwB9C;EKzvBQ;IHTR,gBAA8C;EFqwB9C;EK5vBQ;IHTR,uBAA8C;EFwwB9C;EK/vBQ;IHTR,uBAA8C;EF2wB9C;AACF;;AMlzBM;EAAwB,wBAA0B;ANszBxD;;AMtzBM;EAAwB,0BAA0B;AN0zBxD;;AM1zBM;EAAwB,gCAA0B;AN8zBxD;;AM9zBM;EAAwB,yBAA0B;ANk0BxD;;AMl0BM;EAAwB,yBAA0B;ANs0BxD;;AMt0BM;EAAwB,6BAA0B;AN00BxD;;AM10BM;EAAwB,8BAA0B;AN80BxD;;AM90BM;EAAwB,+BAA0B;EAA1B,wBAA0B;ANk1BxD;;AMl1BM;EAAwB,sCAA0B;EAA1B,+BAA0B;ANs1BxD;;AGryBI;EGjDE;IAAwB,wBAA0B;EN21BtD;EM31BI;IAAwB,0BAA0B;EN81BtD;EM91BI;IAAwB,gCAA0B;ENi2BtD;EMj2BI;IAAwB,yBAA0B;ENo2BtD;EMp2BI;IAAwB,yBAA0B;ENu2BtD;EMv2BI;IAAwB,6BAA0B;EN02BtD;EM12BI;IAAwB,8BAA0B;EN62BtD;EM72BI;IAAwB,+BAA0B;IAA1B,wBAA0B;ENg3BtD;EMh3BI;IAAwB,sCAA0B;IAA1B,+BAA0B;ENm3BtD;AACF;;AGn0BI;EGjDE;IAAwB,wBAA0B;ENy3BtD;EMz3BI;IAAwB,0BAA0B;EN43BtD;EM53BI;IAAwB,gCAA0B;EN+3BtD;EM/3BI;IAAwB,yBAA0B;ENk4BtD;EMl4BI;IAAwB,yBAA0B;ENq4BtD;EMr4BI;IAAwB,6BAA0B;ENw4BtD;EMx4BI;IAAwB,8BAA0B;EN24BtD;EM34BI;IAAwB,+BAA0B;IAA1B,wBAA0B;EN84BtD;EM94BI;IAAwB,sCAA0B;IAA1B,+BAA0B;ENi5BtD;AACF;;AGj2BI;EGjDE;IAAwB,wBAA0B;ENu5BtD;EMv5BI;IAAwB,0BAA0B;EN05BtD;EM15BI;IAAwB,gCAA0B;EN65BtD;EM75BI;IAAwB,yBAA0B;ENg6BtD;EMh6BI;IAAwB,yBAA0B;ENm6BtD;EMn6BI;IAAwB,6BAA0B;ENs6BtD;EMt6BI;IAAwB,8BAA0B;ENy6BtD;EMz6BI;IAAwB,+BAA0B;IAA1B,wBAA0B;EN46BtD;EM56BI;IAAwB,sCAA0B;IAA1B,+BAA0B;EN+6BtD;AACF;;AG/3BI;EGjDE;IAAwB,wBAA0B;ENq7BtD;EMr7BI;IAAwB,0BAA0B;ENw7BtD;EMx7BI;IAAwB,gCAA0B;EN27BtD;EM37BI;IAAwB,yBAA0B;EN87BtD;EM97BI;IAAwB,yBAA0B;ENi8BtD;EMj8BI;IAAwB,6BAA0B;ENo8BtD;EMp8BI;IAAwB,8BAA0B;ENu8BtD;EMv8BI;IAAwB,+BAA0B;IAA1B,wBAA0B;EN08BtD;EM18BI;IAAwB,sCAA0B;IAA1B,+BAA0B;EN68BtD;AACF;;AMp8BA;EAEI;IAAqB,wBAA0B;ENu8BjD;EMv8BE;IAAqB,0BAA0B;EN08BjD;EM18BE;IAAqB,gCAA0B;EN68BjD;EM78BE;IAAqB,yBAA0B;ENg9BjD;EMh9BE;IAAqB,yBAA0B;ENm9BjD;EMn9BE;IAAqB,6BAA0B;ENs9BjD;EMt9BE;IAAqB,8BAA0B;ENy9BjD;EMz9BE;IAAqB,+BAA0B;IAA1B,wBAA0B;EN49BjD;EM59BE;IAAqB,sCAA0B;IAA1B,+BAA0B;EN+9BjD;AACF;;AO7+BI;EAAgC,kCAA8B;EAA9B,8BAA8B;APi/BlE;;AOh/BI;EAAgC,qCAAiC;EAAjC,iCAAiC;APo/BrE;;AOn/BI;EAAgC,0CAAsC;EAAtC,sCAAsC;APu/B1E;;AOt/BI;EAAgC,6CAAyC;EAAzC,yCAAyC;AP0/B7E;;AOx/BI;EAA8B,8BAA0B;EAA1B,0BAA0B;AP4/B5D;;AO3/BI;EAA8B,gCAA4B;EAA5B,4BAA4B;AP+/B9D;;AO9/BI;EAA8B,sCAAkC;EAAlC,kCAAkC;APkgCpE;;AOjgCI;EAA8B,6BAAyB;EAAzB,yBAAyB;APqgC3D;;AOpgCI;EAA8B,+BAAuB;EAAvB,uBAAuB;APwgCzD;;AOvgCI;EAA8B,+BAAuB;EAAvB,uBAAuB;AP2gCzD;;AO1gCI;EAA8B,+BAAyB;EAAzB,yBAAyB;AP8gC3D;;AO7gCI;EAA8B,+BAAyB;EAAzB,yBAAyB;APihC3D;;AO/gCI;EAAoC,+BAAsC;EAAtC,sCAAsC;APmhC9E;;AOlhCI;EAAoC,6BAAoC;EAApC,oCAAoC;APshC5E;;AOrhCI;EAAoC,gCAAkC;EAAlC,kCAAkC;APyhC1E;;AOxhCI;EAAoC,iCAAyC;EAAzC,yCAAyC;AP4hCjF;;AO3hCI;EAAoC,oCAAwC;EAAxC,wCAAwC;AP+hChF;;AO7hCI;EAAiC,gCAAkC;EAAlC,kCAAkC;APiiCvE;;AOhiCI;EAAiC,8BAAgC;EAAhC,gCAAgC;APoiCrE;;AOniCI;EAAiC,iCAA8B;EAA9B,8BAA8B;APuiCnE;;AOtiCI;EAAiC,mCAAgC;EAAhC,gCAAgC;AP0iCrE;;AOziCI;EAAiC,kCAA+B;EAA/B,+BAA+B;AP6iCpE;;AO3iCI;EAAkC,oCAAoC;EAApC,oCAAoC;AP+iC1E;;AO9iCI;EAAkC,kCAAkC;EAAlC,kCAAkC;APkjCxE;;AOjjCI;EAAkC,qCAAgC;EAAhC,gCAAgC;APqjCtE;;AOpjCI;EAAkC,sCAAuC;EAAvC,uCAAuC;APwjC7E;;AOvjCI;EAAkC,yCAAsC;EAAtC,sCAAsC;AP2jC5E;;AO1jCI;EAAkC,sCAAiC;EAAjC,iCAAiC;AP8jCvE;;AO5jCI;EAAgC,oCAA2B;EAA3B,2BAA2B;APgkC/D;;AO/jCI;EAAgC,qCAAiC;EAAjC,iCAAiC;APmkCrE;;AOlkCI;EAAgC,mCAA+B;EAA/B,+BAA+B;APskCnE;;AOrkCI;EAAgC,sCAA6B;EAA7B,6BAA6B;APykCjE;;AOxkCI;EAAgC,wCAA+B;EAA/B,+BAA+B;AP4kCnE;;AO3kCI;EAAgC,uCAA8B;EAA9B,8BAA8B;AP+kClE;;AGnkCI;EIlDA;IAAgC,kCAA8B;IAA9B,8BAA8B;EP0nChE;EOznCE;IAAgC,qCAAiC;IAAjC,iCAAiC;EP4nCnE;EO3nCE;IAAgC,0CAAsC;IAAtC,sCAAsC;EP8nCxE;EO7nCE;IAAgC,6CAAyC;IAAzC,yCAAyC;EPgoC3E;EO9nCE;IAA8B,8BAA0B;IAA1B,0BAA0B;EPioC1D;EOhoCE;IAA8B,gCAA4B;IAA5B,4BAA4B;EPmoC5D;EOloCE;IAA8B,sCAAkC;IAAlC,kCAAkC;EPqoClE;EOpoCE;IAA8B,6BAAyB;IAAzB,yBAAyB;EPuoCzD;EOtoCE;IAA8B,+BAAuB;IAAvB,uBAAuB;EPyoCvD;EOxoCE;IAA8B,+BAAuB;IAAvB,uBAAuB;EP2oCvD;EO1oCE;IAA8B,+BAAyB;IAAzB,yBAAyB;EP6oCzD;EO5oCE;IAA8B,+BAAyB;IAAzB,yBAAyB;EP+oCzD;EO7oCE;IAAoC,+BAAsC;IAAtC,sCAAsC;EPgpC5E;EO/oCE;IAAoC,6BAAoC;IAApC,oCAAoC;EPkpC1E;EOjpCE;IAAoC,gCAAkC;IAAlC,kCAAkC;EPopCxE;EOnpCE;IAAoC,iCAAyC;IAAzC,yCAAyC;EPspC/E;EOrpCE;IAAoC,oCAAwC;IAAxC,wCAAwC;EPwpC9E;EOtpCE;IAAiC,gCAAkC;IAAlC,kCAAkC;EPypCrE;EOxpCE;IAAiC,8BAAgC;IAAhC,gCAAgC;EP2pCnE;EO1pCE;IAAiC,iCAA8B;IAA9B,8BAA8B;EP6pCjE;EO5pCE;IAAiC,mCAAgC;IAAhC,gCAAgC;EP+pCnE;EO9pCE;IAAiC,kCAA+B;IAA/B,+BAA+B;EPiqClE;EO/pCE;IAAkC,oCAAoC;IAApC,oCAAoC;EPkqCxE;EOjqCE;IAAkC,kCAAkC;IAAlC,kCAAkC;EPoqCtE;EOnqCE;IAAkC,qCAAgC;IAAhC,gCAAgC;EPsqCpE;EOrqCE;IAAkC,sCAAuC;IAAvC,uCAAuC;EPwqC3E;EOvqCE;IAAkC,yCAAsC;IAAtC,sCAAsC;EP0qC1E;EOzqCE;IAAkC,sCAAiC;IAAjC,iCAAiC;EP4qCrE;EO1qCE;IAAgC,oCAA2B;IAA3B,2BAA2B;EP6qC7D;EO5qCE;IAAgC,qCAAiC;IAAjC,iCAAiC;EP+qCnE;EO9qCE;IAAgC,mCAA+B;IAA/B,+BAA+B;EPirCjE;EOhrCE;IAAgC,sCAA6B;IAA7B,6BAA6B;EPmrC/D;EOlrCE;IAAgC,wCAA+B;IAA/B,+BAA+B;EPqrCjE;EOprCE;IAAgC,uCAA8B;IAA9B,8BAA8B;EPurChE;AACF;;AG5qCI;EIlDA;IAAgC,kCAA8B;IAA9B,8BAA8B;EPmuChE;EOluCE;IAAgC,qCAAiC;IAAjC,iCAAiC;EPquCnE;EOpuCE;IAAgC,0CAAsC;IAAtC,sCAAsC;EPuuCxE;EOtuCE;IAAgC,6CAAyC;IAAzC,yCAAyC;EPyuC3E;EOvuCE;IAA8B,8BAA0B;IAA1B,0BAA0B;EP0uC1D;EOzuCE;IAA8B,gCAA4B;IAA5B,4BAA4B;EP4uC5D;EO3uCE;IAA8B,sCAAkC;IAAlC,kCAAkC;EP8uClE;EO7uCE;IAA8B,6BAAyB;IAAzB,yBAAyB;EPgvCzD;EO/uCE;IAA8B,+BAAuB;IAAvB,uBAAuB;EPkvCvD;EOjvCE;IAA8B,+BAAuB;IAAvB,uBAAuB;EPovCvD;EOnvCE;IAA8B,+BAAyB;IAAzB,yBAAyB;EPsvCzD;EOrvCE;IAA8B,+BAAyB;IAAzB,yBAAyB;EPwvCzD;EOtvCE;IAAoC,+BAAsC;IAAtC,sCAAsC;EPyvC5E;EOxvCE;IAAoC,6BAAoC;IAApC,oCAAoC;EP2vC1E;EO1vCE;IAAoC,gCAAkC;IAAlC,kCAAkC;EP6vCxE;EO5vCE;IAAoC,iCAAyC;IAAzC,yCAAyC;EP+vC/E;EO9vCE;IAAoC,oCAAwC;IAAxC,wCAAwC;EPiwC9E;EO/vCE;IAAiC,gCAAkC;IAAlC,kCAAkC;EPkwCrE;EOjwCE;IAAiC,8BAAgC;IAAhC,gCAAgC;EPowCnE;EOnwCE;IAAiC,iCAA8B;IAA9B,8BAA8B;EPswCjE;EOrwCE;IAAiC,mCAAgC;IAAhC,gCAAgC;EPwwCnE;EOvwCE;IAAiC,kCAA+B;IAA/B,+BAA+B;EP0wClE;EOxwCE;IAAkC,oCAAoC;IAApC,oCAAoC;EP2wCxE;EO1wCE;IAAkC,kCAAkC;IAAlC,kCAAkC;EP6wCtE;EO5wCE;IAAkC,qCAAgC;IAAhC,gCAAgC;EP+wCpE;EO9wCE;IAAkC,sCAAuC;IAAvC,uCAAuC;EPixC3E;EOhxCE;IAAkC,yCAAsC;IAAtC,sCAAsC;EPmxC1E;EOlxCE;IAAkC,sCAAiC;IAAjC,iCAAiC;EPqxCrE;EOnxCE;IAAgC,oCAA2B;IAA3B,2BAA2B;EPsxC7D;EOrxCE;IAAgC,qCAAiC;IAAjC,iCAAiC;EPwxCnE;EOvxCE;IAAgC,mCAA+B;IAA/B,+BAA+B;EP0xCjE;EOzxCE;IAAgC,sCAA6B;IAA7B,6BAA6B;EP4xC/D;EO3xCE;IAAgC,wCAA+B;IAA/B,+BAA+B;EP8xCjE;EO7xCE;IAAgC,uCAA8B;IAA9B,8BAA8B;EPgyChE;AACF;;AGrxCI;EIlDA;IAAgC,kCAA8B;IAA9B,8BAA8B;EP40ChE;EO30CE;IAAgC,qCAAiC;IAAjC,iCAAiC;EP80CnE;EO70CE;IAAgC,0CAAsC;IAAtC,sCAAsC;EPg1CxE;EO/0CE;IAAgC,6CAAyC;IAAzC,yCAAyC;EPk1C3E;EOh1CE;IAA8B,8BAA0B;IAA1B,0BAA0B;EPm1C1D;EOl1CE;IAA8B,gCAA4B;IAA5B,4BAA4B;EPq1C5D;EOp1CE;IAA8B,sCAAkC;IAAlC,kCAAkC;EPu1ClE;EOt1CE;IAA8B,6BAAyB;IAAzB,yBAAyB;EPy1CzD;EOx1CE;IAA8B,+BAAuB;IAAvB,uBAAuB;EP21CvD;EO11CE;IAA8B,+BAAuB;IAAvB,uBAAuB;EP61CvD;EO51CE;IAA8B,+BAAyB;IAAzB,yBAAyB;EP+1CzD;EO91CE;IAA8B,+BAAyB;IAAzB,yBAAyB;EPi2CzD;EO/1CE;IAAoC,+BAAsC;IAAtC,sCAAsC;EPk2C5E;EOj2CE;IAAoC,6BAAoC;IAApC,oCAAoC;EPo2C1E;EOn2CE;IAAoC,gCAAkC;IAAlC,kCAAkC;EPs2CxE;EOr2CE;IAAoC,iCAAyC;IAAzC,yCAAyC;EPw2C/E;EOv2CE;IAAoC,oCAAwC;IAAxC,wCAAwC;EP02C9E;EOx2CE;IAAiC,gCAAkC;IAAlC,kCAAkC;EP22CrE;EO12CE;IAAiC,8BAAgC;IAAhC,gCAAgC;EP62CnE;EO52CE;IAAiC,iCAA8B;IAA9B,8BAA8B;EP+2CjE;EO92CE;IAAiC,mCAAgC;IAAhC,gCAAgC;EPi3CnE;EOh3CE;IAAiC,kCAA+B;IAA/B,+BAA+B;EPm3ClE;EOj3CE;IAAkC,oCAAoC;IAApC,oCAAoC;EPo3CxE;EOn3CE;IAAkC,kCAAkC;IAAlC,kCAAkC;EPs3CtE;EOr3CE;IAAkC,qCAAgC;IAAhC,gCAAgC;EPw3CpE;EOv3CE;IAAkC,sCAAuC;IAAvC,uCAAuC;EP03C3E;EOz3CE;IAAkC,yCAAsC;IAAtC,sCAAsC;EP43C1E;EO33CE;IAAkC,sCAAiC;IAAjC,iCAAiC;EP83CrE;EO53CE;IAAgC,oCAA2B;IAA3B,2BAA2B;EP+3C7D;EO93CE;IAAgC,qCAAiC;IAAjC,iCAAiC;EPi4CnE;EOh4CE;IAAgC,mCAA+B;IAA/B,+BAA+B;EPm4CjE;EOl4CE;IAAgC,sCAA6B;IAA7B,6BAA6B;EPq4C/D;EOp4CE;IAAgC,wCAA+B;IAA/B,+BAA+B;EPu4CjE;EOt4CE;IAAgC,uCAA8B;IAA9B,8BAA8B;EPy4ChE;AACF;;AG93CI;EIlDA;IAAgC,kCAA8B;IAA9B,8BAA8B;EPq7ChE;EOp7CE;IAAgC,qCAAiC;IAAjC,iCAAiC;EPu7CnE;EOt7CE;IAAgC,0CAAsC;IAAtC,sCAAsC;EPy7CxE;EOx7CE;IAAgC,6CAAyC;IAAzC,yCAAyC;EP27C3E;EOz7CE;IAA8B,8BAA0B;IAA1B,0BAA0B;EP47C1D;EO37CE;IAA8B,gCAA4B;IAA5B,4BAA4B;EP87C5D;EO77CE;IAA8B,sCAAkC;IAAlC,kCAAkC;EPg8ClE;EO/7CE;IAA8B,6BAAyB;IAAzB,yBAAyB;EPk8CzD;EOj8CE;IAA8B,+BAAuB;IAAvB,uBAAuB;EPo8CvD;EOn8CE;IAA8B,+BAAuB;IAAvB,uBAAuB;EPs8CvD;EOr8CE;IAA8B,+BAAyB;IAAzB,yBAAyB;EPw8CzD;EOv8CE;IAA8B,+BAAyB;IAAzB,yBAAyB;EP08CzD;EOx8CE;IAAoC,+BAAsC;IAAtC,sCAAsC;EP28C5E;EO18CE;IAAoC,6BAAoC;IAApC,oCAAoC;EP68C1E;EO58CE;IAAoC,gCAAkC;IAAlC,kCAAkC;EP+8CxE;EO98CE;IAAoC,iCAAyC;IAAzC,yCAAyC;EPi9C/E;EOh9CE;IAAoC,oCAAwC;IAAxC,wCAAwC;EPm9C9E;EOj9CE;IAAiC,gCAAkC;IAAlC,kCAAkC;EPo9CrE;EOn9CE;IAAiC,8BAAgC;IAAhC,gCAAgC;EPs9CnE;EOr9CE;IAAiC,iCAA8B;IAA9B,8BAA8B;EPw9CjE;EOv9CE;IAAiC,mCAAgC;IAAhC,gCAAgC;EP09CnE;EOz9CE;IAAiC,kCAA+B;IAA/B,+BAA+B;EP49ClE;EO19CE;IAAkC,oCAAoC;IAApC,oCAAoC;EP69CxE;EO59CE;IAAkC,kCAAkC;IAAlC,kCAAkC;EP+9CtE;EO99CE;IAAkC,qCAAgC;IAAhC,gCAAgC;EPi+CpE;EOh+CE;IAAkC,sCAAuC;IAAvC,uCAAuC;EPm+C3E;EOl+CE;IAAkC,yCAAsC;IAAtC,sCAAsC;EPq+C1E;EOp+CE;IAAkC,sCAAiC;IAAjC,iCAAiC;EPu+CrE;EOr+CE;IAAgC,oCAA2B;IAA3B,2BAA2B;EPw+C7D;EOv+CE;IAAgC,qCAAiC;IAAjC,iCAAiC;EP0+CnE;EOz+CE;IAAgC,mCAA+B;IAA/B,+BAA+B;EP4+CjE;EO3+CE;IAAgC,sCAA6B;IAA7B,6BAA6B;EP8+C/D;EO7+CE;IAAgC,wCAA+B;IAA/B,+BAA+B;EPg/CjE;EO/+CE;IAAgC,uCAA8B;IAA9B,8BAA8B;EPk/ChE;AACF;;AQzhDQ;EAAgC,oBAA4B;AR6hDpE;;AQ5hDQ;;EAEE,wBAAoC;AR+hD9C;;AQ7hDQ;;EAEE,0BAAwC;ARgiDlD;;AQ9hDQ;;EAEE,2BAA0C;ARiiDpD;;AQ/hDQ;;EAEE,yBAAsC;ARkiDhD;;AQjjDQ;EAAgC,0BAA4B;ARqjDpE;;AQpjDQ;;EAEE,8BAAoC;ARujD9C;;AQrjDQ;;EAEE,gCAAwC;ARwjDlD;;AQtjDQ;;EAEE,iCAA0C;ARyjDpD;;AQvjDQ;;EAEE,+BAAsC;AR0jDhD;;AQzkDQ;EAAgC,yBAA4B;AR6kDpE;;AQ5kDQ;;EAEE,6BAAoC;AR+kD9C;;AQ7kDQ;;EAEE,+BAAwC;ARglDlD;;AQ9kDQ;;EAEE,gCAA0C;ARilDpD;;AQ/kDQ;;EAEE,8BAAsC;ARklDhD;;AQjmDQ;EAAgC,uBAA4B;ARqmDpE;;AQpmDQ;;EAEE,2BAAoC;ARumD9C;;AQrmDQ;;EAEE,6BAAwC;ARwmDlD;;AQtmDQ;;EAEE,8BAA0C;ARymDpD;;AQvmDQ;;EAEE,4BAAsC;AR0mDhD;;AQznDQ;EAAgC,yBAA4B;AR6nDpE;;AQ5nDQ;;EAEE,6BAAoC;AR+nD9C;;AQ7nDQ;;EAEE,+BAAwC;ARgoDlD;;AQ9nDQ;;EAEE,gCAA0C;ARioDpD;;AQ/nDQ;;EAEE,8BAAsC;ARkoDhD;;AQjpDQ;EAAgC,uBAA4B;ARqpDpE;;AQppDQ;;EAEE,2BAAoC;ARupD9C;;AQrpDQ;;EAEE,6BAAwC;ARwpDlD;;AQtpDQ;;EAEE,8BAA0C;ARypDpD;;AQvpDQ;;EAEE,4BAAsC;AR0pDhD;;AQzqDQ;EAAgC,qBAA4B;AR6qDpE;;AQ5qDQ;;EAEE,yBAAoC;AR+qD9C;;AQ7qDQ;;EAEE,2BAAwC;ARgrDlD;;AQ9qDQ;;EAEE,4BAA0C;ARirDpD;;AQ/qDQ;;EAEE,0BAAsC;ARkrDhD;;AQjsDQ;EAAgC,2BAA4B;ARqsDpE;;AQpsDQ;;EAEE,+BAAoC;ARusD9C;;AQrsDQ;;EAEE,iCAAwC;ARwsDlD;;AQtsDQ;;EAEE,kCAA0C;ARysDpD;;AQvsDQ;;EAEE,gCAAsC;AR0sDhD;;AQztDQ;EAAgC,0BAA4B;AR6tDpE;;AQ5tDQ;;EAEE,8BAAoC;AR+tD9C;;AQ7tDQ;;EAEE,gCAAwC;ARguDlD;;AQ9tDQ;;EAEE,iCAA0C;ARiuDpD;;AQ/tDQ;;EAEE,+BAAsC;ARkuDhD;;AQjvDQ;EAAgC,wBAA4B;ARqvDpE;;AQpvDQ;;EAEE,4BAAoC;ARuvD9C;;AQrvDQ;;EAEE,8BAAwC;ARwvDlD;;AQtvDQ;;EAEE,+BAA0C;ARyvDpD;;AQvvDQ;;EAEE,6BAAsC;AR0vDhD;;AQzwDQ;EAAgC,0BAA4B;AR6wDpE;;AQ5wDQ;;EAEE,8BAAoC;AR+wD9C;;AQ7wDQ;;EAEE,gCAAwC;ARgxDlD;;AQ9wDQ;;EAEE,iCAA0C;ARixDpD;;AQ/wDQ;;EAEE,+BAAsC;ARkxDhD;;AQjyDQ;EAAgC,wBAA4B;ARqyDpE;;AQpyDQ;;EAEE,4BAAoC;ARuyD9C;;AQryDQ;;EAEE,8BAAwC;ARwyDlD;;AQtyDQ;;EAEE,+BAA0C;ARyyDpD;;AQvyDQ;;EAEE,6BAAsC;AR0yDhD;;AQlyDQ;EAAwB,2BAA2B;ARsyD3D;;AQryDQ;;EAEE,+BAA+B;ARwyDzC;;AQtyDQ;;EAEE,iCAAiC;ARyyD3C;;AQvyDQ;;EAEE,kCAAkC;AR0yD5C;;AQxyDQ;;EAEE,gCAAgC;AR2yD1C;;AQ1zDQ;EAAwB,0BAA2B;AR8zD3D;;AQ7zDQ;;EAEE,8BAA+B;ARg0DzC;;AQ9zDQ;;EAEE,gCAAiC;ARi0D3C;;AQ/zDQ;;EAEE,iCAAkC;ARk0D5C;;AQh0DQ;;EAEE,+BAAgC;ARm0D1C;;AQl1DQ;EAAwB,wBAA2B;ARs1D3D;;AQr1DQ;;EAEE,4BAA+B;ARw1DzC;;AQt1DQ;;EAEE,8BAAiC;ARy1D3C;;AQv1DQ;;EAEE,+BAAkC;AR01D5C;;AQx1DQ;;EAEE,6BAAgC;AR21D1C;;AQ12DQ;EAAwB,0BAA2B;AR82D3D;;AQ72DQ;;EAEE,8BAA+B;ARg3DzC;;AQ92DQ;;EAEE,gCAAiC;ARi3D3C;;AQ/2DQ;;EAEE,iCAAkC;ARk3D5C;;AQh3DQ;;EAEE,+BAAgC;ARm3D1C;;AQl4DQ;EAAwB,wBAA2B;ARs4D3D;;AQr4DQ;;EAEE,4BAA+B;ARw4DzC;;AQt4DQ;;EAEE,8BAAiC;ARy4D3C;;AQv4DQ;;EAEE,+BAAkC;AR04D5C;;AQx4DQ;;EAEE,6BAAgC;AR24D1C;;AQr4DI;EAAmB,uBAAuB;ARy4D9C;;AQx4DI;;EAEE,2BAA2B;AR24DjC;;AQz4DI;;EAEE,6BAA6B;AR44DnC;;AQ14DI;;EAEE,8BAA8B;AR64DpC;;AQ34DI;;EAEE,4BAA4B;AR84DlC;;AGv5DI;EKlDI;IAAgC,oBAA4B;ER88DlE;EQ78DM;;IAEE,wBAAoC;ER+8D5C;EQ78DM;;IAEE,0BAAwC;ER+8DhD;EQ78DM;;IAEE,2BAA0C;ER+8DlD;EQ78DM;;IAEE,yBAAsC;ER+8D9C;EQ99DM;IAAgC,0BAA4B;ERi+DlE;EQh+DM;;IAEE,8BAAoC;ERk+D5C;EQh+DM;;IAEE,gCAAwC;ERk+DhD;EQh+DM;;IAEE,iCAA0C;ERk+DlD;EQh+DM;;IAEE,+BAAsC;ERk+D9C;EQj/DM;IAAgC,yBAA4B;ERo/DlE;EQn/DM;;IAEE,6BAAoC;ERq/D5C;EQn/DM;;IAEE,+BAAwC;ERq/DhD;EQn/DM;;IAEE,gCAA0C;ERq/DlD;EQn/DM;;IAEE,8BAAsC;ERq/D9C;EQpgEM;IAAgC,uBAA4B;ERugElE;EQtgEM;;IAEE,2BAAoC;ERwgE5C;EQtgEM;;IAEE,6BAAwC;ERwgEhD;EQtgEM;;IAEE,8BAA0C;ERwgElD;EQtgEM;;IAEE,4BAAsC;ERwgE9C;EQvhEM;IAAgC,yBAA4B;ER0hElE;EQzhEM;;IAEE,6BAAoC;ER2hE5C;EQzhEM;;IAEE,+BAAwC;ER2hEhD;EQzhEM;;IAEE,gCAA0C;ER2hElD;EQzhEM;;IAEE,8BAAsC;ER2hE9C;EQ1iEM;IAAgC,uBAA4B;ER6iElE;EQ5iEM;;IAEE,2BAAoC;ER8iE5C;EQ5iEM;;IAEE,6BAAwC;ER8iEhD;EQ5iEM;;IAEE,8BAA0C;ER8iElD;EQ5iEM;;IAEE,4BAAsC;ER8iE9C;EQ7jEM;IAAgC,qBAA4B;ERgkElE;EQ/jEM;;IAEE,yBAAoC;ERikE5C;EQ/jEM;;IAEE,2BAAwC;ERikEhD;EQ/jEM;;IAEE,4BAA0C;ERikElD;EQ/jEM;;IAEE,0BAAsC;ERikE9C;EQhlEM;IAAgC,2BAA4B;ERmlElE;EQllEM;;IAEE,+BAAoC;ERolE5C;EQllEM;;IAEE,iCAAwC;ERolEhD;EQllEM;;IAEE,kCAA0C;ERolElD;EQllEM;;IAEE,gCAAsC;ERolE9C;EQnmEM;IAAgC,0BAA4B;ERsmElE;EQrmEM;;IAEE,8BAAoC;ERumE5C;EQrmEM;;IAEE,gCAAwC;ERumEhD;EQrmEM;;IAEE,iCAA0C;ERumElD;EQrmEM;;IAEE,+BAAsC;ERumE9C;EQtnEM;IAAgC,wBAA4B;ERynElE;EQxnEM;;IAEE,4BAAoC;ER0nE5C;EQxnEM;;IAEE,8BAAwC;ER0nEhD;EQxnEM;;IAEE,+BAA0C;ER0nElD;EQxnEM;;IAEE,6BAAsC;ER0nE9C;EQzoEM;IAAgC,0BAA4B;ER4oElE;EQ3oEM;;IAEE,8BAAoC;ER6oE5C;EQ3oEM;;IAEE,gCAAwC;ER6oEhD;EQ3oEM;;IAEE,iCAA0C;ER6oElD;EQ3oEM;;IAEE,+BAAsC;ER6oE9C;EQ5pEM;IAAgC,wBAA4B;ER+pElE;EQ9pEM;;IAEE,4BAAoC;ERgqE5C;EQ9pEM;;IAEE,8BAAwC;ERgqEhD;EQ9pEM;;IAEE,+BAA0C;ERgqElD;EQ9pEM;;IAEE,6BAAsC;ERgqE9C;EQxpEM;IAAwB,2BAA2B;ER2pEzD;EQ1pEM;;IAEE,+BAA+B;ER4pEvC;EQ1pEM;;IAEE,iCAAiC;ER4pEzC;EQ1pEM;;IAEE,kCAAkC;ER4pE1C;EQ1pEM;;IAEE,gCAAgC;ER4pExC;EQ3qEM;IAAwB,0BAA2B;ER8qEzD;EQ7qEM;;IAEE,8BAA+B;ER+qEvC;EQ7qEM;;IAEE,gCAAiC;ER+qEzC;EQ7qEM;;IAEE,iCAAkC;ER+qE1C;EQ7qEM;;IAEE,+BAAgC;ER+qExC;EQ9rEM;IAAwB,wBAA2B;ERisEzD;EQhsEM;;IAEE,4BAA+B;ERksEvC;EQhsEM;;IAEE,8BAAiC;ERksEzC;EQhsEM;;IAEE,+BAAkC;ERksE1C;EQhsEM;;IAEE,6BAAgC;ERksExC;EQjtEM;IAAwB,0BAA2B;ERotEzD;EQntEM;;IAEE,8BAA+B;ERqtEvC;EQntEM;;IAEE,gCAAiC;ERqtEzC;EQntEM;;IAEE,iCAAkC;ERqtE1C;EQntEM;;IAEE,+BAAgC;ERqtExC;EQpuEM;IAAwB,wBAA2B;ERuuEzD;EQtuEM;;IAEE,4BAA+B;ERwuEvC;EQtuEM;;IAEE,8BAAiC;ERwuEzC;EQtuEM;;IAEE,+BAAkC;ERwuE1C;EQtuEM;;IAEE,6BAAgC;ERwuExC;EQluEE;IAAmB,uBAAuB;ERquE5C;EQpuEE;;IAEE,2BAA2B;ERsuE/B;EQpuEE;;IAEE,6BAA6B;ERsuEjC;EQpuEE;;IAEE,8BAA8B;ERsuElC;EQpuEE;;IAEE,4BAA4B;ERsuEhC;AACF;;AGhvEI;EKlDI;IAAgC,oBAA4B;ERuyElE;EQtyEM;;IAEE,wBAAoC;ERwyE5C;EQtyEM;;IAEE,0BAAwC;ERwyEhD;EQtyEM;;IAEE,2BAA0C;ERwyElD;EQtyEM;;IAEE,yBAAsC;ERwyE9C;EQvzEM;IAAgC,0BAA4B;ER0zElE;EQzzEM;;IAEE,8BAAoC;ER2zE5C;EQzzEM;;IAEE,gCAAwC;ER2zEhD;EQzzEM;;IAEE,iCAA0C;ER2zElD;EQzzEM;;IAEE,+BAAsC;ER2zE9C;EQ10EM;IAAgC,yBAA4B;ER60ElE;EQ50EM;;IAEE,6BAAoC;ER80E5C;EQ50EM;;IAEE,+BAAwC;ER80EhD;EQ50EM;;IAEE,gCAA0C;ER80ElD;EQ50EM;;IAEE,8BAAsC;ER80E9C;EQ71EM;IAAgC,uBAA4B;ERg2ElE;EQ/1EM;;IAEE,2BAAoC;ERi2E5C;EQ/1EM;;IAEE,6BAAwC;ERi2EhD;EQ/1EM;;IAEE,8BAA0C;ERi2ElD;EQ/1EM;;IAEE,4BAAsC;ERi2E9C;EQh3EM;IAAgC,yBAA4B;ERm3ElE;EQl3EM;;IAEE,6BAAoC;ERo3E5C;EQl3EM;;IAEE,+BAAwC;ERo3EhD;EQl3EM;;IAEE,gCAA0C;ERo3ElD;EQl3EM;;IAEE,8BAAsC;ERo3E9C;EQn4EM;IAAgC,uBAA4B;ERs4ElE;EQr4EM;;IAEE,2BAAoC;ERu4E5C;EQr4EM;;IAEE,6BAAwC;ERu4EhD;EQr4EM;;IAEE,8BAA0C;ERu4ElD;EQr4EM;;IAEE,4BAAsC;ERu4E9C;EQt5EM;IAAgC,qBAA4B;ERy5ElE;EQx5EM;;IAEE,yBAAoC;ER05E5C;EQx5EM;;IAEE,2BAAwC;ER05EhD;EQx5EM;;IAEE,4BAA0C;ER05ElD;EQx5EM;;IAEE,0BAAsC;ER05E9C;EQz6EM;IAAgC,2BAA4B;ER46ElE;EQ36EM;;IAEE,+BAAoC;ER66E5C;EQ36EM;;IAEE,iCAAwC;ER66EhD;EQ36EM;;IAEE,kCAA0C;ER66ElD;EQ36EM;;IAEE,gCAAsC;ER66E9C;EQ57EM;IAAgC,0BAA4B;ER+7ElE;EQ97EM;;IAEE,8BAAoC;ERg8E5C;EQ97EM;;IAEE,gCAAwC;ERg8EhD;EQ97EM;;IAEE,iCAA0C;ERg8ElD;EQ97EM;;IAEE,+BAAsC;ERg8E9C;EQ/8EM;IAAgC,wBAA4B;ERk9ElE;EQj9EM;;IAEE,4BAAoC;ERm9E5C;EQj9EM;;IAEE,8BAAwC;ERm9EhD;EQj9EM;;IAEE,+BAA0C;ERm9ElD;EQj9EM;;IAEE,6BAAsC;ERm9E9C;EQl+EM;IAAgC,0BAA4B;ERq+ElE;EQp+EM;;IAEE,8BAAoC;ERs+E5C;EQp+EM;;IAEE,gCAAwC;ERs+EhD;EQp+EM;;IAEE,iCAA0C;ERs+ElD;EQp+EM;;IAEE,+BAAsC;ERs+E9C;EQr/EM;IAAgC,wBAA4B;ERw/ElE;EQv/EM;;IAEE,4BAAoC;ERy/E5C;EQv/EM;;IAEE,8BAAwC;ERy/EhD;EQv/EM;;IAEE,+BAA0C;ERy/ElD;EQv/EM;;IAEE,6BAAsC;ERy/E9C;EQj/EM;IAAwB,2BAA2B;ERo/EzD;EQn/EM;;IAEE,+BAA+B;ERq/EvC;EQn/EM;;IAEE,iCAAiC;ERq/EzC;EQn/EM;;IAEE,kCAAkC;ERq/E1C;EQn/EM;;IAEE,gCAAgC;ERq/ExC;EQpgFM;IAAwB,0BAA2B;ERugFzD;EQtgFM;;IAEE,8BAA+B;ERwgFvC;EQtgFM;;IAEE,gCAAiC;ERwgFzC;EQtgFM;;IAEE,iCAAkC;ERwgF1C;EQtgFM;;IAEE,+BAAgC;ERwgFxC;EQvhFM;IAAwB,wBAA2B;ER0hFzD;EQzhFM;;IAEE,4BAA+B;ER2hFvC;EQzhFM;;IAEE,8BAAiC;ER2hFzC;EQzhFM;;IAEE,+BAAkC;ER2hF1C;EQzhFM;;IAEE,6BAAgC;ER2hFxC;EQ1iFM;IAAwB,0BAA2B;ER6iFzD;EQ5iFM;;IAEE,8BAA+B;ER8iFvC;EQ5iFM;;IAEE,gCAAiC;ER8iFzC;EQ5iFM;;IAEE,iCAAkC;ER8iF1C;EQ5iFM;;IAEE,+BAAgC;ER8iFxC;EQ7jFM;IAAwB,wBAA2B;ERgkFzD;EQ/jFM;;IAEE,4BAA+B;ERikFvC;EQ/jFM;;IAEE,8BAAiC;ERikFzC;EQ/jFM;;IAEE,+BAAkC;ERikF1C;EQ/jFM;;IAEE,6BAAgC;ERikFxC;EQ3jFE;IAAmB,uBAAuB;ER8jF5C;EQ7jFE;;IAEE,2BAA2B;ER+jF/B;EQ7jFE;;IAEE,6BAA6B;ER+jFjC;EQ7jFE;;IAEE,8BAA8B;ER+jFlC;EQ7jFE;;IAEE,4BAA4B;ER+jFhC;AACF;;AGzkFI;EKlDI;IAAgC,oBAA4B;ERgoFlE;EQ/nFM;;IAEE,wBAAoC;ERioF5C;EQ/nFM;;IAEE,0BAAwC;ERioFhD;EQ/nFM;;IAEE,2BAA0C;ERioFlD;EQ/nFM;;IAEE,yBAAsC;ERioF9C;EQhpFM;IAAgC,0BAA4B;ERmpFlE;EQlpFM;;IAEE,8BAAoC;ERopF5C;EQlpFM;;IAEE,gCAAwC;ERopFhD;EQlpFM;;IAEE,iCAA0C;ERopFlD;EQlpFM;;IAEE,+BAAsC;ERopF9C;EQnqFM;IAAgC,yBAA4B;ERsqFlE;EQrqFM;;IAEE,6BAAoC;ERuqF5C;EQrqFM;;IAEE,+BAAwC;ERuqFhD;EQrqFM;;IAEE,gCAA0C;ERuqFlD;EQrqFM;;IAEE,8BAAsC;ERuqF9C;EQtrFM;IAAgC,uBAA4B;ERyrFlE;EQxrFM;;IAEE,2BAAoC;ER0rF5C;EQxrFM;;IAEE,6BAAwC;ER0rFhD;EQxrFM;;IAEE,8BAA0C;ER0rFlD;EQxrFM;;IAEE,4BAAsC;ER0rF9C;EQzsFM;IAAgC,yBAA4B;ER4sFlE;EQ3sFM;;IAEE,6BAAoC;ER6sF5C;EQ3sFM;;IAEE,+BAAwC;ER6sFhD;EQ3sFM;;IAEE,gCAA0C;ER6sFlD;EQ3sFM;;IAEE,8BAAsC;ER6sF9C;EQ5tFM;IAAgC,uBAA4B;ER+tFlE;EQ9tFM;;IAEE,2BAAoC;ERguF5C;EQ9tFM;;IAEE,6BAAwC;ERguFhD;EQ9tFM;;IAEE,8BAA0C;ERguFlD;EQ9tFM;;IAEE,4BAAsC;ERguF9C;EQ/uFM;IAAgC,qBAA4B;ERkvFlE;EQjvFM;;IAEE,yBAAoC;ERmvF5C;EQjvFM;;IAEE,2BAAwC;ERmvFhD;EQjvFM;;IAEE,4BAA0C;ERmvFlD;EQjvFM;;IAEE,0BAAsC;ERmvF9C;EQlwFM;IAAgC,2BAA4B;ERqwFlE;EQpwFM;;IAEE,+BAAoC;ERswF5C;EQpwFM;;IAEE,iCAAwC;ERswFhD;EQpwFM;;IAEE,kCAA0C;ERswFlD;EQpwFM;;IAEE,gCAAsC;ERswF9C;EQrxFM;IAAgC,0BAA4B;ERwxFlE;EQvxFM;;IAEE,8BAAoC;ERyxF5C;EQvxFM;;IAEE,gCAAwC;ERyxFhD;EQvxFM;;IAEE,iCAA0C;ERyxFlD;EQvxFM;;IAEE,+BAAsC;ERyxF9C;EQxyFM;IAAgC,wBAA4B;ER2yFlE;EQ1yFM;;IAEE,4BAAoC;ER4yF5C;EQ1yFM;;IAEE,8BAAwC;ER4yFhD;EQ1yFM;;IAEE,+BAA0C;ER4yFlD;EQ1yFM;;IAEE,6BAAsC;ER4yF9C;EQ3zFM;IAAgC,0BAA4B;ER8zFlE;EQ7zFM;;IAEE,8BAAoC;ER+zF5C;EQ7zFM;;IAEE,gCAAwC;ER+zFhD;EQ7zFM;;IAEE,iCAA0C;ER+zFlD;EQ7zFM;;IAEE,+BAAsC;ER+zF9C;EQ90FM;IAAgC,wBAA4B;ERi1FlE;EQh1FM;;IAEE,4BAAoC;ERk1F5C;EQh1FM;;IAEE,8BAAwC;ERk1FhD;EQh1FM;;IAEE,+BAA0C;ERk1FlD;EQh1FM;;IAEE,6BAAsC;ERk1F9C;EQ10FM;IAAwB,2BAA2B;ER60FzD;EQ50FM;;IAEE,+BAA+B;ER80FvC;EQ50FM;;IAEE,iCAAiC;ER80FzC;EQ50FM;;IAEE,kCAAkC;ER80F1C;EQ50FM;;IAEE,gCAAgC;ER80FxC;EQ71FM;IAAwB,0BAA2B;ERg2FzD;EQ/1FM;;IAEE,8BAA+B;ERi2FvC;EQ/1FM;;IAEE,gCAAiC;ERi2FzC;EQ/1FM;;IAEE,iCAAkC;ERi2F1C;EQ/1FM;;IAEE,+BAAgC;ERi2FxC;EQh3FM;IAAwB,wBAA2B;ERm3FzD;EQl3FM;;IAEE,4BAA+B;ERo3FvC;EQl3FM;;IAEE,8BAAiC;ERo3FzC;EQl3FM;;IAEE,+BAAkC;ERo3F1C;EQl3FM;;IAEE,6BAAgC;ERo3FxC;EQn4FM;IAAwB,0BAA2B;ERs4FzD;EQr4FM;;IAEE,8BAA+B;ERu4FvC;EQr4FM;;IAEE,gCAAiC;ERu4FzC;EQr4FM;;IAEE,iCAAkC;ERu4F1C;EQr4FM;;IAEE,+BAAgC;ERu4FxC;EQt5FM;IAAwB,wBAA2B;ERy5FzD;EQx5FM;;IAEE,4BAA+B;ER05FvC;EQx5FM;;IAEE,8BAAiC;ER05FzC;EQx5FM;;IAEE,+BAAkC;ER05F1C;EQx5FM;;IAEE,6BAAgC;ER05FxC;EQp5FE;IAAmB,uBAAuB;ERu5F5C;EQt5FE;;IAEE,2BAA2B;ERw5F/B;EQt5FE;;IAEE,6BAA6B;ERw5FjC;EQt5FE;;IAEE,8BAA8B;ERw5FlC;EQt5FE;;IAEE,4BAA4B;ERw5FhC;AACF;;AGl6FI;EKlDI;IAAgC,oBAA4B;ERy9FlE;EQx9FM;;IAEE,wBAAoC;ER09F5C;EQx9FM;;IAEE,0BAAwC;ER09FhD;EQx9FM;;IAEE,2BAA0C;ER09FlD;EQx9FM;;IAEE,yBAAsC;ER09F9C;EQz+FM;IAAgC,0BAA4B;ER4+FlE;EQ3+FM;;IAEE,8BAAoC;ER6+F5C;EQ3+FM;;IAEE,gCAAwC;ER6+FhD;EQ3+FM;;IAEE,iCAA0C;ER6+FlD;EQ3+FM;;IAEE,+BAAsC;ER6+F9C;EQ5/FM;IAAgC,yBAA4B;ER+/FlE;EQ9/FM;;IAEE,6BAAoC;ERggG5C;EQ9/FM;;IAEE,+BAAwC;ERggGhD;EQ9/FM;;IAEE,gCAA0C;ERggGlD;EQ9/FM;;IAEE,8BAAsC;ERggG9C;EQ/gGM;IAAgC,uBAA4B;ERkhGlE;EQjhGM;;IAEE,2BAAoC;ERmhG5C;EQjhGM;;IAEE,6BAAwC;ERmhGhD;EQjhGM;;IAEE,8BAA0C;ERmhGlD;EQjhGM;;IAEE,4BAAsC;ERmhG9C;EQliGM;IAAgC,yBAA4B;ERqiGlE;EQpiGM;;IAEE,6BAAoC;ERsiG5C;EQpiGM;;IAEE,+BAAwC;ERsiGhD;EQpiGM;;IAEE,gCAA0C;ERsiGlD;EQpiGM;;IAEE,8BAAsC;ERsiG9C;EQrjGM;IAAgC,uBAA4B;ERwjGlE;EQvjGM;;IAEE,2BAAoC;ERyjG5C;EQvjGM;;IAEE,6BAAwC;ERyjGhD;EQvjGM;;IAEE,8BAA0C;ERyjGlD;EQvjGM;;IAEE,4BAAsC;ERyjG9C;EQxkGM;IAAgC,qBAA4B;ER2kGlE;EQ1kGM;;IAEE,yBAAoC;ER4kG5C;EQ1kGM;;IAEE,2BAAwC;ER4kGhD;EQ1kGM;;IAEE,4BAA0C;ER4kGlD;EQ1kGM;;IAEE,0BAAsC;ER4kG9C;EQ3lGM;IAAgC,2BAA4B;ER8lGlE;EQ7lGM;;IAEE,+BAAoC;ER+lG5C;EQ7lGM;;IAEE,iCAAwC;ER+lGhD;EQ7lGM;;IAEE,kCAA0C;ER+lGlD;EQ7lGM;;IAEE,gCAAsC;ER+lG9C;EQ9mGM;IAAgC,0BAA4B;ERinGlE;EQhnGM;;IAEE,8BAAoC;ERknG5C;EQhnGM;;IAEE,gCAAwC;ERknGhD;EQhnGM;;IAEE,iCAA0C;ERknGlD;EQhnGM;;IAEE,+BAAsC;ERknG9C;EQjoGM;IAAgC,wBAA4B;ERooGlE;EQnoGM;;IAEE,4BAAoC;ERqoG5C;EQnoGM;;IAEE,8BAAwC;ERqoGhD;EQnoGM;;IAEE,+BAA0C;ERqoGlD;EQnoGM;;IAEE,6BAAsC;ERqoG9C;EQppGM;IAAgC,0BAA4B;ERupGlE;EQtpGM;;IAEE,8BAAoC;ERwpG5C;EQtpGM;;IAEE,gCAAwC;ERwpGhD;EQtpGM;;IAEE,iCAA0C;ERwpGlD;EQtpGM;;IAEE,+BAAsC;ERwpG9C;EQvqGM;IAAgC,wBAA4B;ER0qGlE;EQzqGM;;IAEE,4BAAoC;ER2qG5C;EQzqGM;;IAEE,8BAAwC;ER2qGhD;EQzqGM;;IAEE,+BAA0C;ER2qGlD;EQzqGM;;IAEE,6BAAsC;ER2qG9C;EQnqGM;IAAwB,2BAA2B;ERsqGzD;EQrqGM;;IAEE,+BAA+B;ERuqGvC;EQrqGM;;IAEE,iCAAiC;ERuqGzC;EQrqGM;;IAEE,kCAAkC;ERuqG1C;EQrqGM;;IAEE,gCAAgC;ERuqGxC;EQtrGM;IAAwB,0BAA2B;ERyrGzD;EQxrGM;;IAEE,8BAA+B;ER0rGvC;EQxrGM;;IAEE,gCAAiC;ER0rGzC;EQxrGM;;IAEE,iCAAkC;ER0rG1C;EQxrGM;;IAEE,+BAAgC;ER0rGxC;EQzsGM;IAAwB,wBAA2B;ER4sGzD;EQ3sGM;;IAEE,4BAA+B;ER6sGvC;EQ3sGM;;IAEE,8BAAiC;ER6sGzC;EQ3sGM;;IAEE,+BAAkC;ER6sG1C;EQ3sGM;;IAEE,6BAAgC;ER6sGxC;EQ5tGM;IAAwB,0BAA2B;ER+tGzD;EQ9tGM;;IAEE,8BAA+B;ERguGvC;EQ9tGM;;IAEE,gCAAiC;ERguGzC;EQ9tGM;;IAEE,iCAAkC;ERguG1C;EQ9tGM;;IAEE,+BAAgC;ERguGxC;EQ/uGM;IAAwB,wBAA2B;ERkvGzD;EQjvGM;;IAEE,4BAA+B;ERmvGvC;EQjvGM;;IAEE,8BAAiC;ERmvGzC;EQjvGM;;IAEE,+BAAkC;ERmvG1C;EQjvGM;;IAEE,6BAAgC;ERmvGxC;EQ7uGE;IAAmB,uBAAuB;ERgvG5C;EQ/uGE;;IAEE,2BAA2B;ERivG/B;EQ/uGE;;IAEE,6BAA6B;ERivGjC;EQ/uGE;;IAEE,8BAA8B;ERivGlC;EQ/uGE;;IAEE,4BAA4B;ERivGhC;AACF","file":"bootstrap-grid.css","sourcesContent":["/*!\n * Bootstrap Grid v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n@import \"functions\";\n@import \"variables\";\n\n@import \"mixins/breakpoints\";\n@import \"mixins/grid-framework\";\n@import \"mixins/grid\";\n\n@import \"grid\";\n@import \"utilities/display\";\n@import \"utilities/flex\";\n@import \"utilities/spacing\";\n","/*!\n * Bootstrap Grid v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n.container {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n@media (min-width: 576px) {\n .container {\n max-width: 540px;\n }\n}\n\n@media (min-width: 768px) {\n .container {\n max-width: 720px;\n }\n}\n\n@media (min-width: 992px) {\n .container {\n max-width: 960px;\n }\n}\n\n@media (min-width: 1200px) {\n .container {\n max-width: 1140px;\n }\n}\n\n.container-fluid {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n.row {\n display: flex;\n flex-wrap: wrap;\n margin-right: -15px;\n margin-left: -15px;\n}\n\n.no-gutters {\n margin-right: 0;\n margin-left: 0;\n}\n\n.no-gutters > .col,\n.no-gutters > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n}\n\n.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,\n.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,\n.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,\n.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,\n.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,\n.col-xl-auto {\n position: relative;\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n}\n\n.col {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n}\n\n.col-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n}\n\n.col-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n}\n\n.col-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n}\n\n.col-3 {\n flex: 0 0 25%;\n max-width: 25%;\n}\n\n.col-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n}\n\n.col-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n}\n\n.col-6 {\n flex: 0 0 50%;\n max-width: 50%;\n}\n\n.col-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n}\n\n.col-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n}\n\n.col-9 {\n flex: 0 0 75%;\n max-width: 75%;\n}\n\n.col-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n}\n\n.col-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n}\n\n.col-12 {\n flex: 0 0 100%;\n max-width: 100%;\n}\n\n.order-first {\n order: -1;\n}\n\n.order-last {\n order: 13;\n}\n\n.order-0 {\n order: 0;\n}\n\n.order-1 {\n order: 1;\n}\n\n.order-2 {\n order: 2;\n}\n\n.order-3 {\n order: 3;\n}\n\n.order-4 {\n order: 4;\n}\n\n.order-5 {\n order: 5;\n}\n\n.order-6 {\n order: 6;\n}\n\n.order-7 {\n order: 7;\n}\n\n.order-8 {\n order: 8;\n}\n\n.order-9 {\n order: 9;\n}\n\n.order-10 {\n order: 10;\n}\n\n.order-11 {\n order: 11;\n}\n\n.order-12 {\n order: 12;\n}\n\n.offset-1 {\n margin-left: 8.333333%;\n}\n\n.offset-2 {\n margin-left: 16.666667%;\n}\n\n.offset-3 {\n margin-left: 25%;\n}\n\n.offset-4 {\n margin-left: 33.333333%;\n}\n\n.offset-5 {\n margin-left: 41.666667%;\n}\n\n.offset-6 {\n margin-left: 50%;\n}\n\n.offset-7 {\n margin-left: 58.333333%;\n}\n\n.offset-8 {\n margin-left: 66.666667%;\n}\n\n.offset-9 {\n margin-left: 75%;\n}\n\n.offset-10 {\n margin-left: 83.333333%;\n}\n\n.offset-11 {\n margin-left: 91.666667%;\n}\n\n@media (min-width: 576px) {\n .col-sm {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-sm-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-sm-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-sm-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-sm-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-sm-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-sm-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-sm-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-sm-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-sm-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-sm-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-sm-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-sm-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-sm-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-sm-first {\n order: -1;\n }\n .order-sm-last {\n order: 13;\n }\n .order-sm-0 {\n order: 0;\n }\n .order-sm-1 {\n order: 1;\n }\n .order-sm-2 {\n order: 2;\n }\n .order-sm-3 {\n order: 3;\n }\n .order-sm-4 {\n order: 4;\n }\n .order-sm-5 {\n order: 5;\n }\n .order-sm-6 {\n order: 6;\n }\n .order-sm-7 {\n order: 7;\n }\n .order-sm-8 {\n order: 8;\n }\n .order-sm-9 {\n order: 9;\n }\n .order-sm-10 {\n order: 10;\n }\n .order-sm-11 {\n order: 11;\n }\n .order-sm-12 {\n order: 12;\n }\n .offset-sm-0 {\n margin-left: 0;\n }\n .offset-sm-1 {\n margin-left: 8.333333%;\n }\n .offset-sm-2 {\n margin-left: 16.666667%;\n }\n .offset-sm-3 {\n margin-left: 25%;\n }\n .offset-sm-4 {\n margin-left: 33.333333%;\n }\n .offset-sm-5 {\n margin-left: 41.666667%;\n }\n .offset-sm-6 {\n margin-left: 50%;\n }\n .offset-sm-7 {\n margin-left: 58.333333%;\n }\n .offset-sm-8 {\n margin-left: 66.666667%;\n }\n .offset-sm-9 {\n margin-left: 75%;\n }\n .offset-sm-10 {\n margin-left: 83.333333%;\n }\n .offset-sm-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 768px) {\n .col-md {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-md-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-md-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-md-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-md-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-md-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-md-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-md-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-md-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-md-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-md-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-md-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-md-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-md-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-md-first {\n order: -1;\n }\n .order-md-last {\n order: 13;\n }\n .order-md-0 {\n order: 0;\n }\n .order-md-1 {\n order: 1;\n }\n .order-md-2 {\n order: 2;\n }\n .order-md-3 {\n order: 3;\n }\n .order-md-4 {\n order: 4;\n }\n .order-md-5 {\n order: 5;\n }\n .order-md-6 {\n order: 6;\n }\n .order-md-7 {\n order: 7;\n }\n .order-md-8 {\n order: 8;\n }\n .order-md-9 {\n order: 9;\n }\n .order-md-10 {\n order: 10;\n }\n .order-md-11 {\n order: 11;\n }\n .order-md-12 {\n order: 12;\n }\n .offset-md-0 {\n margin-left: 0;\n }\n .offset-md-1 {\n margin-left: 8.333333%;\n }\n .offset-md-2 {\n margin-left: 16.666667%;\n }\n .offset-md-3 {\n margin-left: 25%;\n }\n .offset-md-4 {\n margin-left: 33.333333%;\n }\n .offset-md-5 {\n margin-left: 41.666667%;\n }\n .offset-md-6 {\n margin-left: 50%;\n }\n .offset-md-7 {\n margin-left: 58.333333%;\n }\n .offset-md-8 {\n margin-left: 66.666667%;\n }\n .offset-md-9 {\n margin-left: 75%;\n }\n .offset-md-10 {\n margin-left: 83.333333%;\n }\n .offset-md-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 992px) {\n .col-lg {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-lg-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-lg-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-lg-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-lg-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-lg-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-lg-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-lg-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-lg-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-lg-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-lg-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-lg-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-lg-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-lg-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-lg-first {\n order: -1;\n }\n .order-lg-last {\n order: 13;\n }\n .order-lg-0 {\n order: 0;\n }\n .order-lg-1 {\n order: 1;\n }\n .order-lg-2 {\n order: 2;\n }\n .order-lg-3 {\n order: 3;\n }\n .order-lg-4 {\n order: 4;\n }\n .order-lg-5 {\n order: 5;\n }\n .order-lg-6 {\n order: 6;\n }\n .order-lg-7 {\n order: 7;\n }\n .order-lg-8 {\n order: 8;\n }\n .order-lg-9 {\n order: 9;\n }\n .order-lg-10 {\n order: 10;\n }\n .order-lg-11 {\n order: 11;\n }\n .order-lg-12 {\n order: 12;\n }\n .offset-lg-0 {\n margin-left: 0;\n }\n .offset-lg-1 {\n margin-left: 8.333333%;\n }\n .offset-lg-2 {\n margin-left: 16.666667%;\n }\n .offset-lg-3 {\n margin-left: 25%;\n }\n .offset-lg-4 {\n margin-left: 33.333333%;\n }\n .offset-lg-5 {\n margin-left: 41.666667%;\n }\n .offset-lg-6 {\n margin-left: 50%;\n }\n .offset-lg-7 {\n margin-left: 58.333333%;\n }\n .offset-lg-8 {\n margin-left: 66.666667%;\n }\n .offset-lg-9 {\n margin-left: 75%;\n }\n .offset-lg-10 {\n margin-left: 83.333333%;\n }\n .offset-lg-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 1200px) {\n .col-xl {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-xl-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-xl-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-xl-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-xl-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-xl-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-xl-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-xl-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-xl-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-xl-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-xl-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-xl-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-xl-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-xl-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-xl-first {\n order: -1;\n }\n .order-xl-last {\n order: 13;\n }\n .order-xl-0 {\n order: 0;\n }\n .order-xl-1 {\n order: 1;\n }\n .order-xl-2 {\n order: 2;\n }\n .order-xl-3 {\n order: 3;\n }\n .order-xl-4 {\n order: 4;\n }\n .order-xl-5 {\n order: 5;\n }\n .order-xl-6 {\n order: 6;\n }\n .order-xl-7 {\n order: 7;\n }\n .order-xl-8 {\n order: 8;\n }\n .order-xl-9 {\n order: 9;\n }\n .order-xl-10 {\n order: 10;\n }\n .order-xl-11 {\n order: 11;\n }\n .order-xl-12 {\n order: 12;\n }\n .offset-xl-0 {\n margin-left: 0;\n }\n .offset-xl-1 {\n margin-left: 8.333333%;\n }\n .offset-xl-2 {\n margin-left: 16.666667%;\n }\n .offset-xl-3 {\n margin-left: 25%;\n }\n .offset-xl-4 {\n margin-left: 33.333333%;\n }\n .offset-xl-5 {\n margin-left: 41.666667%;\n }\n .offset-xl-6 {\n margin-left: 50%;\n }\n .offset-xl-7 {\n margin-left: 58.333333%;\n }\n .offset-xl-8 {\n margin-left: 66.666667%;\n }\n .offset-xl-9 {\n margin-left: 75%;\n }\n .offset-xl-10 {\n margin-left: 83.333333%;\n }\n .offset-xl-11 {\n margin-left: 91.666667%;\n }\n}\n\n.d-none {\n display: none !important;\n}\n\n.d-inline {\n display: inline !important;\n}\n\n.d-inline-block {\n display: inline-block !important;\n}\n\n.d-block {\n display: block !important;\n}\n\n.d-table {\n display: table !important;\n}\n\n.d-table-row {\n display: table-row !important;\n}\n\n.d-table-cell {\n display: table-cell !important;\n}\n\n.d-flex {\n display: flex !important;\n}\n\n.d-inline-flex {\n display: inline-flex !important;\n}\n\n@media (min-width: 576px) {\n .d-sm-none {\n display: none !important;\n }\n .d-sm-inline {\n display: inline !important;\n }\n .d-sm-inline-block {\n display: inline-block !important;\n }\n .d-sm-block {\n display: block !important;\n }\n .d-sm-table {\n display: table !important;\n }\n .d-sm-table-row {\n display: table-row !important;\n }\n .d-sm-table-cell {\n display: table-cell !important;\n }\n .d-sm-flex {\n display: flex !important;\n }\n .d-sm-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 768px) {\n .d-md-none {\n display: none !important;\n }\n .d-md-inline {\n display: inline !important;\n }\n .d-md-inline-block {\n display: inline-block !important;\n }\n .d-md-block {\n display: block !important;\n }\n .d-md-table {\n display: table !important;\n }\n .d-md-table-row {\n display: table-row !important;\n }\n .d-md-table-cell {\n display: table-cell !important;\n }\n .d-md-flex {\n display: flex !important;\n }\n .d-md-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 992px) {\n .d-lg-none {\n display: none !important;\n }\n .d-lg-inline {\n display: inline !important;\n }\n .d-lg-inline-block {\n display: inline-block !important;\n }\n .d-lg-block {\n display: block !important;\n }\n .d-lg-table {\n display: table !important;\n }\n .d-lg-table-row {\n display: table-row !important;\n }\n .d-lg-table-cell {\n display: table-cell !important;\n }\n .d-lg-flex {\n display: flex !important;\n }\n .d-lg-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 1200px) {\n .d-xl-none {\n display: none !important;\n }\n .d-xl-inline {\n display: inline !important;\n }\n .d-xl-inline-block {\n display: inline-block !important;\n }\n .d-xl-block {\n display: block !important;\n }\n .d-xl-table {\n display: table !important;\n }\n .d-xl-table-row {\n display: table-row !important;\n }\n .d-xl-table-cell {\n display: table-cell !important;\n }\n .d-xl-flex {\n display: flex !important;\n }\n .d-xl-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media print {\n .d-print-none {\n display: none !important;\n }\n .d-print-inline {\n display: inline !important;\n }\n .d-print-inline-block {\n display: inline-block !important;\n }\n .d-print-block {\n display: block !important;\n }\n .d-print-table {\n display: table !important;\n }\n .d-print-table-row {\n display: table-row !important;\n }\n .d-print-table-cell {\n display: table-cell !important;\n }\n .d-print-flex {\n display: flex !important;\n }\n .d-print-inline-flex {\n display: inline-flex !important;\n }\n}\n\n.flex-row {\n flex-direction: row !important;\n}\n\n.flex-column {\n flex-direction: column !important;\n}\n\n.flex-row-reverse {\n flex-direction: row-reverse !important;\n}\n\n.flex-column-reverse {\n flex-direction: column-reverse !important;\n}\n\n.flex-wrap {\n flex-wrap: wrap !important;\n}\n\n.flex-nowrap {\n flex-wrap: nowrap !important;\n}\n\n.flex-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n}\n\n.flex-fill {\n flex: 1 1 auto !important;\n}\n\n.flex-grow-0 {\n flex-grow: 0 !important;\n}\n\n.flex-grow-1 {\n flex-grow: 1 !important;\n}\n\n.flex-shrink-0 {\n flex-shrink: 0 !important;\n}\n\n.flex-shrink-1 {\n flex-shrink: 1 !important;\n}\n\n.justify-content-start {\n justify-content: flex-start !important;\n}\n\n.justify-content-end {\n justify-content: flex-end !important;\n}\n\n.justify-content-center {\n justify-content: center !important;\n}\n\n.justify-content-between {\n justify-content: space-between !important;\n}\n\n.justify-content-around {\n justify-content: space-around !important;\n}\n\n.align-items-start {\n align-items: flex-start !important;\n}\n\n.align-items-end {\n align-items: flex-end !important;\n}\n\n.align-items-center {\n align-items: center !important;\n}\n\n.align-items-baseline {\n align-items: baseline !important;\n}\n\n.align-items-stretch {\n align-items: stretch !important;\n}\n\n.align-content-start {\n align-content: flex-start !important;\n}\n\n.align-content-end {\n align-content: flex-end !important;\n}\n\n.align-content-center {\n align-content: center !important;\n}\n\n.align-content-between {\n align-content: space-between !important;\n}\n\n.align-content-around {\n align-content: space-around !important;\n}\n\n.align-content-stretch {\n align-content: stretch !important;\n}\n\n.align-self-auto {\n align-self: auto !important;\n}\n\n.align-self-start {\n align-self: flex-start !important;\n}\n\n.align-self-end {\n align-self: flex-end !important;\n}\n\n.align-self-center {\n align-self: center !important;\n}\n\n.align-self-baseline {\n align-self: baseline !important;\n}\n\n.align-self-stretch {\n align-self: stretch !important;\n}\n\n@media (min-width: 576px) {\n .flex-sm-row {\n flex-direction: row !important;\n }\n .flex-sm-column {\n flex-direction: column !important;\n }\n .flex-sm-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-sm-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-sm-wrap {\n flex-wrap: wrap !important;\n }\n .flex-sm-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-sm-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-sm-fill {\n flex: 1 1 auto !important;\n }\n .flex-sm-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-sm-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-sm-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-sm-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-sm-start {\n justify-content: flex-start !important;\n }\n .justify-content-sm-end {\n justify-content: flex-end !important;\n }\n .justify-content-sm-center {\n justify-content: center !important;\n }\n .justify-content-sm-between {\n justify-content: space-between !important;\n }\n .justify-content-sm-around {\n justify-content: space-around !important;\n }\n .align-items-sm-start {\n align-items: flex-start !important;\n }\n .align-items-sm-end {\n align-items: flex-end !important;\n }\n .align-items-sm-center {\n align-items: center !important;\n }\n .align-items-sm-baseline {\n align-items: baseline !important;\n }\n .align-items-sm-stretch {\n align-items: stretch !important;\n }\n .align-content-sm-start {\n align-content: flex-start !important;\n }\n .align-content-sm-end {\n align-content: flex-end !important;\n }\n .align-content-sm-center {\n align-content: center !important;\n }\n .align-content-sm-between {\n align-content: space-between !important;\n }\n .align-content-sm-around {\n align-content: space-around !important;\n }\n .align-content-sm-stretch {\n align-content: stretch !important;\n }\n .align-self-sm-auto {\n align-self: auto !important;\n }\n .align-self-sm-start {\n align-self: flex-start !important;\n }\n .align-self-sm-end {\n align-self: flex-end !important;\n }\n .align-self-sm-center {\n align-self: center !important;\n }\n .align-self-sm-baseline {\n align-self: baseline !important;\n }\n .align-self-sm-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 768px) {\n .flex-md-row {\n flex-direction: row !important;\n }\n .flex-md-column {\n flex-direction: column !important;\n }\n .flex-md-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-md-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-md-wrap {\n flex-wrap: wrap !important;\n }\n .flex-md-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-md-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-md-fill {\n flex: 1 1 auto !important;\n }\n .flex-md-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-md-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-md-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-md-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-md-start {\n justify-content: flex-start !important;\n }\n .justify-content-md-end {\n justify-content: flex-end !important;\n }\n .justify-content-md-center {\n justify-content: center !important;\n }\n .justify-content-md-between {\n justify-content: space-between !important;\n }\n .justify-content-md-around {\n justify-content: space-around !important;\n }\n .align-items-md-start {\n align-items: flex-start !important;\n }\n .align-items-md-end {\n align-items: flex-end !important;\n }\n .align-items-md-center {\n align-items: center !important;\n }\n .align-items-md-baseline {\n align-items: baseline !important;\n }\n .align-items-md-stretch {\n align-items: stretch !important;\n }\n .align-content-md-start {\n align-content: flex-start !important;\n }\n .align-content-md-end {\n align-content: flex-end !important;\n }\n .align-content-md-center {\n align-content: center !important;\n }\n .align-content-md-between {\n align-content: space-between !important;\n }\n .align-content-md-around {\n align-content: space-around !important;\n }\n .align-content-md-stretch {\n align-content: stretch !important;\n }\n .align-self-md-auto {\n align-self: auto !important;\n }\n .align-self-md-start {\n align-self: flex-start !important;\n }\n .align-self-md-end {\n align-self: flex-end !important;\n }\n .align-self-md-center {\n align-self: center !important;\n }\n .align-self-md-baseline {\n align-self: baseline !important;\n }\n .align-self-md-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 992px) {\n .flex-lg-row {\n flex-direction: row !important;\n }\n .flex-lg-column {\n flex-direction: column !important;\n }\n .flex-lg-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-lg-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-lg-wrap {\n flex-wrap: wrap !important;\n }\n .flex-lg-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-lg-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-lg-fill {\n flex: 1 1 auto !important;\n }\n .flex-lg-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-lg-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-lg-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-lg-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-lg-start {\n justify-content: flex-start !important;\n }\n .justify-content-lg-end {\n justify-content: flex-end !important;\n }\n .justify-content-lg-center {\n justify-content: center !important;\n }\n .justify-content-lg-between {\n justify-content: space-between !important;\n }\n .justify-content-lg-around {\n justify-content: space-around !important;\n }\n .align-items-lg-start {\n align-items: flex-start !important;\n }\n .align-items-lg-end {\n align-items: flex-end !important;\n }\n .align-items-lg-center {\n align-items: center !important;\n }\n .align-items-lg-baseline {\n align-items: baseline !important;\n }\n .align-items-lg-stretch {\n align-items: stretch !important;\n }\n .align-content-lg-start {\n align-content: flex-start !important;\n }\n .align-content-lg-end {\n align-content: flex-end !important;\n }\n .align-content-lg-center {\n align-content: center !important;\n }\n .align-content-lg-between {\n align-content: space-between !important;\n }\n .align-content-lg-around {\n align-content: space-around !important;\n }\n .align-content-lg-stretch {\n align-content: stretch !important;\n }\n .align-self-lg-auto {\n align-self: auto !important;\n }\n .align-self-lg-start {\n align-self: flex-start !important;\n }\n .align-self-lg-end {\n align-self: flex-end !important;\n }\n .align-self-lg-center {\n align-self: center !important;\n }\n .align-self-lg-baseline {\n align-self: baseline !important;\n }\n .align-self-lg-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 1200px) {\n .flex-xl-row {\n flex-direction: row !important;\n }\n .flex-xl-column {\n flex-direction: column !important;\n }\n .flex-xl-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-xl-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-xl-wrap {\n flex-wrap: wrap !important;\n }\n .flex-xl-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-xl-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-xl-fill {\n flex: 1 1 auto !important;\n }\n .flex-xl-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-xl-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-xl-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-xl-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-xl-start {\n justify-content: flex-start !important;\n }\n .justify-content-xl-end {\n justify-content: flex-end !important;\n }\n .justify-content-xl-center {\n justify-content: center !important;\n }\n .justify-content-xl-between {\n justify-content: space-between !important;\n }\n .justify-content-xl-around {\n justify-content: space-around !important;\n }\n .align-items-xl-start {\n align-items: flex-start !important;\n }\n .align-items-xl-end {\n align-items: flex-end !important;\n }\n .align-items-xl-center {\n align-items: center !important;\n }\n .align-items-xl-baseline {\n align-items: baseline !important;\n }\n .align-items-xl-stretch {\n align-items: stretch !important;\n }\n .align-content-xl-start {\n align-content: flex-start !important;\n }\n .align-content-xl-end {\n align-content: flex-end !important;\n }\n .align-content-xl-center {\n align-content: center !important;\n }\n .align-content-xl-between {\n align-content: space-between !important;\n }\n .align-content-xl-around {\n align-content: space-around !important;\n }\n .align-content-xl-stretch {\n align-content: stretch !important;\n }\n .align-self-xl-auto {\n align-self: auto !important;\n }\n .align-self-xl-start {\n align-self: flex-start !important;\n }\n .align-self-xl-end {\n align-self: flex-end !important;\n }\n .align-self-xl-center {\n align-self: center !important;\n }\n .align-self-xl-baseline {\n align-self: baseline !important;\n }\n .align-self-xl-stretch {\n align-self: stretch !important;\n }\n}\n\n.m-0 {\n margin: 0 !important;\n}\n\n.mt-0,\n.my-0 {\n margin-top: 0 !important;\n}\n\n.mr-0,\n.mx-0 {\n margin-right: 0 !important;\n}\n\n.mb-0,\n.my-0 {\n margin-bottom: 0 !important;\n}\n\n.ml-0,\n.mx-0 {\n margin-left: 0 !important;\n}\n\n.m-1 {\n margin: 0.25rem !important;\n}\n\n.mt-1,\n.my-1 {\n margin-top: 0.25rem !important;\n}\n\n.mr-1,\n.mx-1 {\n margin-right: 0.25rem !important;\n}\n\n.mb-1,\n.my-1 {\n margin-bottom: 0.25rem !important;\n}\n\n.ml-1,\n.mx-1 {\n margin-left: 0.25rem !important;\n}\n\n.m-2 {\n margin: 0.5rem !important;\n}\n\n.mt-2,\n.my-2 {\n margin-top: 0.5rem !important;\n}\n\n.mr-2,\n.mx-2 {\n margin-right: 0.5rem !important;\n}\n\n.mb-2,\n.my-2 {\n margin-bottom: 0.5rem !important;\n}\n\n.ml-2,\n.mx-2 {\n margin-left: 0.5rem !important;\n}\n\n.m-3 {\n margin: 1rem !important;\n}\n\n.mt-3,\n.my-3 {\n margin-top: 1rem !important;\n}\n\n.mr-3,\n.mx-3 {\n margin-right: 1rem !important;\n}\n\n.mb-3,\n.my-3 {\n margin-bottom: 1rem !important;\n}\n\n.ml-3,\n.mx-3 {\n margin-left: 1rem !important;\n}\n\n.m-4 {\n margin: 1.5rem !important;\n}\n\n.mt-4,\n.my-4 {\n margin-top: 1.5rem !important;\n}\n\n.mr-4,\n.mx-4 {\n margin-right: 1.5rem !important;\n}\n\n.mb-4,\n.my-4 {\n margin-bottom: 1.5rem !important;\n}\n\n.ml-4,\n.mx-4 {\n margin-left: 1.5rem !important;\n}\n\n.m-5 {\n margin: 3rem !important;\n}\n\n.mt-5,\n.my-5 {\n margin-top: 3rem !important;\n}\n\n.mr-5,\n.mx-5 {\n margin-right: 3rem !important;\n}\n\n.mb-5,\n.my-5 {\n margin-bottom: 3rem !important;\n}\n\n.ml-5,\n.mx-5 {\n margin-left: 3rem !important;\n}\n\n.p-0 {\n padding: 0 !important;\n}\n\n.pt-0,\n.py-0 {\n padding-top: 0 !important;\n}\n\n.pr-0,\n.px-0 {\n padding-right: 0 !important;\n}\n\n.pb-0,\n.py-0 {\n padding-bottom: 0 !important;\n}\n\n.pl-0,\n.px-0 {\n padding-left: 0 !important;\n}\n\n.p-1 {\n padding: 0.25rem !important;\n}\n\n.pt-1,\n.py-1 {\n padding-top: 0.25rem !important;\n}\n\n.pr-1,\n.px-1 {\n padding-right: 0.25rem !important;\n}\n\n.pb-1,\n.py-1 {\n padding-bottom: 0.25rem !important;\n}\n\n.pl-1,\n.px-1 {\n padding-left: 0.25rem !important;\n}\n\n.p-2 {\n padding: 0.5rem !important;\n}\n\n.pt-2,\n.py-2 {\n padding-top: 0.5rem !important;\n}\n\n.pr-2,\n.px-2 {\n padding-right: 0.5rem !important;\n}\n\n.pb-2,\n.py-2 {\n padding-bottom: 0.5rem !important;\n}\n\n.pl-2,\n.px-2 {\n padding-left: 0.5rem !important;\n}\n\n.p-3 {\n padding: 1rem !important;\n}\n\n.pt-3,\n.py-3 {\n padding-top: 1rem !important;\n}\n\n.pr-3,\n.px-3 {\n padding-right: 1rem !important;\n}\n\n.pb-3,\n.py-3 {\n padding-bottom: 1rem !important;\n}\n\n.pl-3,\n.px-3 {\n padding-left: 1rem !important;\n}\n\n.p-4 {\n padding: 1.5rem !important;\n}\n\n.pt-4,\n.py-4 {\n padding-top: 1.5rem !important;\n}\n\n.pr-4,\n.px-4 {\n padding-right: 1.5rem !important;\n}\n\n.pb-4,\n.py-4 {\n padding-bottom: 1.5rem !important;\n}\n\n.pl-4,\n.px-4 {\n padding-left: 1.5rem !important;\n}\n\n.p-5 {\n padding: 3rem !important;\n}\n\n.pt-5,\n.py-5 {\n padding-top: 3rem !important;\n}\n\n.pr-5,\n.px-5 {\n padding-right: 3rem !important;\n}\n\n.pb-5,\n.py-5 {\n padding-bottom: 3rem !important;\n}\n\n.pl-5,\n.px-5 {\n padding-left: 3rem !important;\n}\n\n.m-n1 {\n margin: -0.25rem !important;\n}\n\n.mt-n1,\n.my-n1 {\n margin-top: -0.25rem !important;\n}\n\n.mr-n1,\n.mx-n1 {\n margin-right: -0.25rem !important;\n}\n\n.mb-n1,\n.my-n1 {\n margin-bottom: -0.25rem !important;\n}\n\n.ml-n1,\n.mx-n1 {\n margin-left: -0.25rem !important;\n}\n\n.m-n2 {\n margin: -0.5rem !important;\n}\n\n.mt-n2,\n.my-n2 {\n margin-top: -0.5rem !important;\n}\n\n.mr-n2,\n.mx-n2 {\n margin-right: -0.5rem !important;\n}\n\n.mb-n2,\n.my-n2 {\n margin-bottom: -0.5rem !important;\n}\n\n.ml-n2,\n.mx-n2 {\n margin-left: -0.5rem !important;\n}\n\n.m-n3 {\n margin: -1rem !important;\n}\n\n.mt-n3,\n.my-n3 {\n margin-top: -1rem !important;\n}\n\n.mr-n3,\n.mx-n3 {\n margin-right: -1rem !important;\n}\n\n.mb-n3,\n.my-n3 {\n margin-bottom: -1rem !important;\n}\n\n.ml-n3,\n.mx-n3 {\n margin-left: -1rem !important;\n}\n\n.m-n4 {\n margin: -1.5rem !important;\n}\n\n.mt-n4,\n.my-n4 {\n margin-top: -1.5rem !important;\n}\n\n.mr-n4,\n.mx-n4 {\n margin-right: -1.5rem !important;\n}\n\n.mb-n4,\n.my-n4 {\n margin-bottom: -1.5rem !important;\n}\n\n.ml-n4,\n.mx-n4 {\n margin-left: -1.5rem !important;\n}\n\n.m-n5 {\n margin: -3rem !important;\n}\n\n.mt-n5,\n.my-n5 {\n margin-top: -3rem !important;\n}\n\n.mr-n5,\n.mx-n5 {\n margin-right: -3rem !important;\n}\n\n.mb-n5,\n.my-n5 {\n margin-bottom: -3rem !important;\n}\n\n.ml-n5,\n.mx-n5 {\n margin-left: -3rem !important;\n}\n\n.m-auto {\n margin: auto !important;\n}\n\n.mt-auto,\n.my-auto {\n margin-top: auto !important;\n}\n\n.mr-auto,\n.mx-auto {\n margin-right: auto !important;\n}\n\n.mb-auto,\n.my-auto {\n margin-bottom: auto !important;\n}\n\n.ml-auto,\n.mx-auto {\n margin-left: auto !important;\n}\n\n@media (min-width: 576px) {\n .m-sm-0 {\n margin: 0 !important;\n }\n .mt-sm-0,\n .my-sm-0 {\n margin-top: 0 !important;\n }\n .mr-sm-0,\n .mx-sm-0 {\n margin-right: 0 !important;\n }\n .mb-sm-0,\n .my-sm-0 {\n margin-bottom: 0 !important;\n }\n .ml-sm-0,\n .mx-sm-0 {\n margin-left: 0 !important;\n }\n .m-sm-1 {\n margin: 0.25rem !important;\n }\n .mt-sm-1,\n .my-sm-1 {\n margin-top: 0.25rem !important;\n }\n .mr-sm-1,\n .mx-sm-1 {\n margin-right: 0.25rem !important;\n }\n .mb-sm-1,\n .my-sm-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-sm-1,\n .mx-sm-1 {\n margin-left: 0.25rem !important;\n }\n .m-sm-2 {\n margin: 0.5rem !important;\n }\n .mt-sm-2,\n .my-sm-2 {\n margin-top: 0.5rem !important;\n }\n .mr-sm-2,\n .mx-sm-2 {\n margin-right: 0.5rem !important;\n }\n .mb-sm-2,\n .my-sm-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-sm-2,\n .mx-sm-2 {\n margin-left: 0.5rem !important;\n }\n .m-sm-3 {\n margin: 1rem !important;\n }\n .mt-sm-3,\n .my-sm-3 {\n margin-top: 1rem !important;\n }\n .mr-sm-3,\n .mx-sm-3 {\n margin-right: 1rem !important;\n }\n .mb-sm-3,\n .my-sm-3 {\n margin-bottom: 1rem !important;\n }\n .ml-sm-3,\n .mx-sm-3 {\n margin-left: 1rem !important;\n }\n .m-sm-4 {\n margin: 1.5rem !important;\n }\n .mt-sm-4,\n .my-sm-4 {\n margin-top: 1.5rem !important;\n }\n .mr-sm-4,\n .mx-sm-4 {\n margin-right: 1.5rem !important;\n }\n .mb-sm-4,\n .my-sm-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-sm-4,\n .mx-sm-4 {\n margin-left: 1.5rem !important;\n }\n .m-sm-5 {\n margin: 3rem !important;\n }\n .mt-sm-5,\n .my-sm-5 {\n margin-top: 3rem !important;\n }\n .mr-sm-5,\n .mx-sm-5 {\n margin-right: 3rem !important;\n }\n .mb-sm-5,\n .my-sm-5 {\n margin-bottom: 3rem !important;\n }\n .ml-sm-5,\n .mx-sm-5 {\n margin-left: 3rem !important;\n }\n .p-sm-0 {\n padding: 0 !important;\n }\n .pt-sm-0,\n .py-sm-0 {\n padding-top: 0 !important;\n }\n .pr-sm-0,\n .px-sm-0 {\n padding-right: 0 !important;\n }\n .pb-sm-0,\n .py-sm-0 {\n padding-bottom: 0 !important;\n }\n .pl-sm-0,\n .px-sm-0 {\n padding-left: 0 !important;\n }\n .p-sm-1 {\n padding: 0.25rem !important;\n }\n .pt-sm-1,\n .py-sm-1 {\n padding-top: 0.25rem !important;\n }\n .pr-sm-1,\n .px-sm-1 {\n padding-right: 0.25rem !important;\n }\n .pb-sm-1,\n .py-sm-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-sm-1,\n .px-sm-1 {\n padding-left: 0.25rem !important;\n }\n .p-sm-2 {\n padding: 0.5rem !important;\n }\n .pt-sm-2,\n .py-sm-2 {\n padding-top: 0.5rem !important;\n }\n .pr-sm-2,\n .px-sm-2 {\n padding-right: 0.5rem !important;\n }\n .pb-sm-2,\n .py-sm-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-sm-2,\n .px-sm-2 {\n padding-left: 0.5rem !important;\n }\n .p-sm-3 {\n padding: 1rem !important;\n }\n .pt-sm-3,\n .py-sm-3 {\n padding-top: 1rem !important;\n }\n .pr-sm-3,\n .px-sm-3 {\n padding-right: 1rem !important;\n }\n .pb-sm-3,\n .py-sm-3 {\n padding-bottom: 1rem !important;\n }\n .pl-sm-3,\n .px-sm-3 {\n padding-left: 1rem !important;\n }\n .p-sm-4 {\n padding: 1.5rem !important;\n }\n .pt-sm-4,\n .py-sm-4 {\n padding-top: 1.5rem !important;\n }\n .pr-sm-4,\n .px-sm-4 {\n padding-right: 1.5rem !important;\n }\n .pb-sm-4,\n .py-sm-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-sm-4,\n .px-sm-4 {\n padding-left: 1.5rem !important;\n }\n .p-sm-5 {\n padding: 3rem !important;\n }\n .pt-sm-5,\n .py-sm-5 {\n padding-top: 3rem !important;\n }\n .pr-sm-5,\n .px-sm-5 {\n padding-right: 3rem !important;\n }\n .pb-sm-5,\n .py-sm-5 {\n padding-bottom: 3rem !important;\n }\n .pl-sm-5,\n .px-sm-5 {\n padding-left: 3rem !important;\n }\n .m-sm-n1 {\n margin: -0.25rem !important;\n }\n .mt-sm-n1,\n .my-sm-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-sm-n1,\n .mx-sm-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-sm-n1,\n .my-sm-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-sm-n1,\n .mx-sm-n1 {\n margin-left: -0.25rem !important;\n }\n .m-sm-n2 {\n margin: -0.5rem !important;\n }\n .mt-sm-n2,\n .my-sm-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-sm-n2,\n .mx-sm-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-sm-n2,\n .my-sm-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-sm-n2,\n .mx-sm-n2 {\n margin-left: -0.5rem !important;\n }\n .m-sm-n3 {\n margin: -1rem !important;\n }\n .mt-sm-n3,\n .my-sm-n3 {\n margin-top: -1rem !important;\n }\n .mr-sm-n3,\n .mx-sm-n3 {\n margin-right: -1rem !important;\n }\n .mb-sm-n3,\n .my-sm-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-sm-n3,\n .mx-sm-n3 {\n margin-left: -1rem !important;\n }\n .m-sm-n4 {\n margin: -1.5rem !important;\n }\n .mt-sm-n4,\n .my-sm-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-sm-n4,\n .mx-sm-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-sm-n4,\n .my-sm-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-sm-n4,\n .mx-sm-n4 {\n margin-left: -1.5rem !important;\n }\n .m-sm-n5 {\n margin: -3rem !important;\n }\n .mt-sm-n5,\n .my-sm-n5 {\n margin-top: -3rem !important;\n }\n .mr-sm-n5,\n .mx-sm-n5 {\n margin-right: -3rem !important;\n }\n .mb-sm-n5,\n .my-sm-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-sm-n5,\n .mx-sm-n5 {\n margin-left: -3rem !important;\n }\n .m-sm-auto {\n margin: auto !important;\n }\n .mt-sm-auto,\n .my-sm-auto {\n margin-top: auto !important;\n }\n .mr-sm-auto,\n .mx-sm-auto {\n margin-right: auto !important;\n }\n .mb-sm-auto,\n .my-sm-auto {\n margin-bottom: auto !important;\n }\n .ml-sm-auto,\n .mx-sm-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 768px) {\n .m-md-0 {\n margin: 0 !important;\n }\n .mt-md-0,\n .my-md-0 {\n margin-top: 0 !important;\n }\n .mr-md-0,\n .mx-md-0 {\n margin-right: 0 !important;\n }\n .mb-md-0,\n .my-md-0 {\n margin-bottom: 0 !important;\n }\n .ml-md-0,\n .mx-md-0 {\n margin-left: 0 !important;\n }\n .m-md-1 {\n margin: 0.25rem !important;\n }\n .mt-md-1,\n .my-md-1 {\n margin-top: 0.25rem !important;\n }\n .mr-md-1,\n .mx-md-1 {\n margin-right: 0.25rem !important;\n }\n .mb-md-1,\n .my-md-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-md-1,\n .mx-md-1 {\n margin-left: 0.25rem !important;\n }\n .m-md-2 {\n margin: 0.5rem !important;\n }\n .mt-md-2,\n .my-md-2 {\n margin-top: 0.5rem !important;\n }\n .mr-md-2,\n .mx-md-2 {\n margin-right: 0.5rem !important;\n }\n .mb-md-2,\n .my-md-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-md-2,\n .mx-md-2 {\n margin-left: 0.5rem !important;\n }\n .m-md-3 {\n margin: 1rem !important;\n }\n .mt-md-3,\n .my-md-3 {\n margin-top: 1rem !important;\n }\n .mr-md-3,\n .mx-md-3 {\n margin-right: 1rem !important;\n }\n .mb-md-3,\n .my-md-3 {\n margin-bottom: 1rem !important;\n }\n .ml-md-3,\n .mx-md-3 {\n margin-left: 1rem !important;\n }\n .m-md-4 {\n margin: 1.5rem !important;\n }\n .mt-md-4,\n .my-md-4 {\n margin-top: 1.5rem !important;\n }\n .mr-md-4,\n .mx-md-4 {\n margin-right: 1.5rem !important;\n }\n .mb-md-4,\n .my-md-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-md-4,\n .mx-md-4 {\n margin-left: 1.5rem !important;\n }\n .m-md-5 {\n margin: 3rem !important;\n }\n .mt-md-5,\n .my-md-5 {\n margin-top: 3rem !important;\n }\n .mr-md-5,\n .mx-md-5 {\n margin-right: 3rem !important;\n }\n .mb-md-5,\n .my-md-5 {\n margin-bottom: 3rem !important;\n }\n .ml-md-5,\n .mx-md-5 {\n margin-left: 3rem !important;\n }\n .p-md-0 {\n padding: 0 !important;\n }\n .pt-md-0,\n .py-md-0 {\n padding-top: 0 !important;\n }\n .pr-md-0,\n .px-md-0 {\n padding-right: 0 !important;\n }\n .pb-md-0,\n .py-md-0 {\n padding-bottom: 0 !important;\n }\n .pl-md-0,\n .px-md-0 {\n padding-left: 0 !important;\n }\n .p-md-1 {\n padding: 0.25rem !important;\n }\n .pt-md-1,\n .py-md-1 {\n padding-top: 0.25rem !important;\n }\n .pr-md-1,\n .px-md-1 {\n padding-right: 0.25rem !important;\n }\n .pb-md-1,\n .py-md-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-md-1,\n .px-md-1 {\n padding-left: 0.25rem !important;\n }\n .p-md-2 {\n padding: 0.5rem !important;\n }\n .pt-md-2,\n .py-md-2 {\n padding-top: 0.5rem !important;\n }\n .pr-md-2,\n .px-md-2 {\n padding-right: 0.5rem !important;\n }\n .pb-md-2,\n .py-md-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-md-2,\n .px-md-2 {\n padding-left: 0.5rem !important;\n }\n .p-md-3 {\n padding: 1rem !important;\n }\n .pt-md-3,\n .py-md-3 {\n padding-top: 1rem !important;\n }\n .pr-md-3,\n .px-md-3 {\n padding-right: 1rem !important;\n }\n .pb-md-3,\n .py-md-3 {\n padding-bottom: 1rem !important;\n }\n .pl-md-3,\n .px-md-3 {\n padding-left: 1rem !important;\n }\n .p-md-4 {\n padding: 1.5rem !important;\n }\n .pt-md-4,\n .py-md-4 {\n padding-top: 1.5rem !important;\n }\n .pr-md-4,\n .px-md-4 {\n padding-right: 1.5rem !important;\n }\n .pb-md-4,\n .py-md-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-md-4,\n .px-md-4 {\n padding-left: 1.5rem !important;\n }\n .p-md-5 {\n padding: 3rem !important;\n }\n .pt-md-5,\n .py-md-5 {\n padding-top: 3rem !important;\n }\n .pr-md-5,\n .px-md-5 {\n padding-right: 3rem !important;\n }\n .pb-md-5,\n .py-md-5 {\n padding-bottom: 3rem !important;\n }\n .pl-md-5,\n .px-md-5 {\n padding-left: 3rem !important;\n }\n .m-md-n1 {\n margin: -0.25rem !important;\n }\n .mt-md-n1,\n .my-md-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-md-n1,\n .mx-md-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-md-n1,\n .my-md-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-md-n1,\n .mx-md-n1 {\n margin-left: -0.25rem !important;\n }\n .m-md-n2 {\n margin: -0.5rem !important;\n }\n .mt-md-n2,\n .my-md-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-md-n2,\n .mx-md-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-md-n2,\n .my-md-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-md-n2,\n .mx-md-n2 {\n margin-left: -0.5rem !important;\n }\n .m-md-n3 {\n margin: -1rem !important;\n }\n .mt-md-n3,\n .my-md-n3 {\n margin-top: -1rem !important;\n }\n .mr-md-n3,\n .mx-md-n3 {\n margin-right: -1rem !important;\n }\n .mb-md-n3,\n .my-md-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-md-n3,\n .mx-md-n3 {\n margin-left: -1rem !important;\n }\n .m-md-n4 {\n margin: -1.5rem !important;\n }\n .mt-md-n4,\n .my-md-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-md-n4,\n .mx-md-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-md-n4,\n .my-md-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-md-n4,\n .mx-md-n4 {\n margin-left: -1.5rem !important;\n }\n .m-md-n5 {\n margin: -3rem !important;\n }\n .mt-md-n5,\n .my-md-n5 {\n margin-top: -3rem !important;\n }\n .mr-md-n5,\n .mx-md-n5 {\n margin-right: -3rem !important;\n }\n .mb-md-n5,\n .my-md-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-md-n5,\n .mx-md-n5 {\n margin-left: -3rem !important;\n }\n .m-md-auto {\n margin: auto !important;\n }\n .mt-md-auto,\n .my-md-auto {\n margin-top: auto !important;\n }\n .mr-md-auto,\n .mx-md-auto {\n margin-right: auto !important;\n }\n .mb-md-auto,\n .my-md-auto {\n margin-bottom: auto !important;\n }\n .ml-md-auto,\n .mx-md-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 992px) {\n .m-lg-0 {\n margin: 0 !important;\n }\n .mt-lg-0,\n .my-lg-0 {\n margin-top: 0 !important;\n }\n .mr-lg-0,\n .mx-lg-0 {\n margin-right: 0 !important;\n }\n .mb-lg-0,\n .my-lg-0 {\n margin-bottom: 0 !important;\n }\n .ml-lg-0,\n .mx-lg-0 {\n margin-left: 0 !important;\n }\n .m-lg-1 {\n margin: 0.25rem !important;\n }\n .mt-lg-1,\n .my-lg-1 {\n margin-top: 0.25rem !important;\n }\n .mr-lg-1,\n .mx-lg-1 {\n margin-right: 0.25rem !important;\n }\n .mb-lg-1,\n .my-lg-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-lg-1,\n .mx-lg-1 {\n margin-left: 0.25rem !important;\n }\n .m-lg-2 {\n margin: 0.5rem !important;\n }\n .mt-lg-2,\n .my-lg-2 {\n margin-top: 0.5rem !important;\n }\n .mr-lg-2,\n .mx-lg-2 {\n margin-right: 0.5rem !important;\n }\n .mb-lg-2,\n .my-lg-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-lg-2,\n .mx-lg-2 {\n margin-left: 0.5rem !important;\n }\n .m-lg-3 {\n margin: 1rem !important;\n }\n .mt-lg-3,\n .my-lg-3 {\n margin-top: 1rem !important;\n }\n .mr-lg-3,\n .mx-lg-3 {\n margin-right: 1rem !important;\n }\n .mb-lg-3,\n .my-lg-3 {\n margin-bottom: 1rem !important;\n }\n .ml-lg-3,\n .mx-lg-3 {\n margin-left: 1rem !important;\n }\n .m-lg-4 {\n margin: 1.5rem !important;\n }\n .mt-lg-4,\n .my-lg-4 {\n margin-top: 1.5rem !important;\n }\n .mr-lg-4,\n .mx-lg-4 {\n margin-right: 1.5rem !important;\n }\n .mb-lg-4,\n .my-lg-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-lg-4,\n .mx-lg-4 {\n margin-left: 1.5rem !important;\n }\n .m-lg-5 {\n margin: 3rem !important;\n }\n .mt-lg-5,\n .my-lg-5 {\n margin-top: 3rem !important;\n }\n .mr-lg-5,\n .mx-lg-5 {\n margin-right: 3rem !important;\n }\n .mb-lg-5,\n .my-lg-5 {\n margin-bottom: 3rem !important;\n }\n .ml-lg-5,\n .mx-lg-5 {\n margin-left: 3rem !important;\n }\n .p-lg-0 {\n padding: 0 !important;\n }\n .pt-lg-0,\n .py-lg-0 {\n padding-top: 0 !important;\n }\n .pr-lg-0,\n .px-lg-0 {\n padding-right: 0 !important;\n }\n .pb-lg-0,\n .py-lg-0 {\n padding-bottom: 0 !important;\n }\n .pl-lg-0,\n .px-lg-0 {\n padding-left: 0 !important;\n }\n .p-lg-1 {\n padding: 0.25rem !important;\n }\n .pt-lg-1,\n .py-lg-1 {\n padding-top: 0.25rem !important;\n }\n .pr-lg-1,\n .px-lg-1 {\n padding-right: 0.25rem !important;\n }\n .pb-lg-1,\n .py-lg-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-lg-1,\n .px-lg-1 {\n padding-left: 0.25rem !important;\n }\n .p-lg-2 {\n padding: 0.5rem !important;\n }\n .pt-lg-2,\n .py-lg-2 {\n padding-top: 0.5rem !important;\n }\n .pr-lg-2,\n .px-lg-2 {\n padding-right: 0.5rem !important;\n }\n .pb-lg-2,\n .py-lg-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-lg-2,\n .px-lg-2 {\n padding-left: 0.5rem !important;\n }\n .p-lg-3 {\n padding: 1rem !important;\n }\n .pt-lg-3,\n .py-lg-3 {\n padding-top: 1rem !important;\n }\n .pr-lg-3,\n .px-lg-3 {\n padding-right: 1rem !important;\n }\n .pb-lg-3,\n .py-lg-3 {\n padding-bottom: 1rem !important;\n }\n .pl-lg-3,\n .px-lg-3 {\n padding-left: 1rem !important;\n }\n .p-lg-4 {\n padding: 1.5rem !important;\n }\n .pt-lg-4,\n .py-lg-4 {\n padding-top: 1.5rem !important;\n }\n .pr-lg-4,\n .px-lg-4 {\n padding-right: 1.5rem !important;\n }\n .pb-lg-4,\n .py-lg-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-lg-4,\n .px-lg-4 {\n padding-left: 1.5rem !important;\n }\n .p-lg-5 {\n padding: 3rem !important;\n }\n .pt-lg-5,\n .py-lg-5 {\n padding-top: 3rem !important;\n }\n .pr-lg-5,\n .px-lg-5 {\n padding-right: 3rem !important;\n }\n .pb-lg-5,\n .py-lg-5 {\n padding-bottom: 3rem !important;\n }\n .pl-lg-5,\n .px-lg-5 {\n padding-left: 3rem !important;\n }\n .m-lg-n1 {\n margin: -0.25rem !important;\n }\n .mt-lg-n1,\n .my-lg-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-lg-n1,\n .mx-lg-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-lg-n1,\n .my-lg-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-lg-n1,\n .mx-lg-n1 {\n margin-left: -0.25rem !important;\n }\n .m-lg-n2 {\n margin: -0.5rem !important;\n }\n .mt-lg-n2,\n .my-lg-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-lg-n2,\n .mx-lg-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-lg-n2,\n .my-lg-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-lg-n2,\n .mx-lg-n2 {\n margin-left: -0.5rem !important;\n }\n .m-lg-n3 {\n margin: -1rem !important;\n }\n .mt-lg-n3,\n .my-lg-n3 {\n margin-top: -1rem !important;\n }\n .mr-lg-n3,\n .mx-lg-n3 {\n margin-right: -1rem !important;\n }\n .mb-lg-n3,\n .my-lg-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-lg-n3,\n .mx-lg-n3 {\n margin-left: -1rem !important;\n }\n .m-lg-n4 {\n margin: -1.5rem !important;\n }\n .mt-lg-n4,\n .my-lg-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-lg-n4,\n .mx-lg-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-lg-n4,\n .my-lg-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-lg-n4,\n .mx-lg-n4 {\n margin-left: -1.5rem !important;\n }\n .m-lg-n5 {\n margin: -3rem !important;\n }\n .mt-lg-n5,\n .my-lg-n5 {\n margin-top: -3rem !important;\n }\n .mr-lg-n5,\n .mx-lg-n5 {\n margin-right: -3rem !important;\n }\n .mb-lg-n5,\n .my-lg-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-lg-n5,\n .mx-lg-n5 {\n margin-left: -3rem !important;\n }\n .m-lg-auto {\n margin: auto !important;\n }\n .mt-lg-auto,\n .my-lg-auto {\n margin-top: auto !important;\n }\n .mr-lg-auto,\n .mx-lg-auto {\n margin-right: auto !important;\n }\n .mb-lg-auto,\n .my-lg-auto {\n margin-bottom: auto !important;\n }\n .ml-lg-auto,\n .mx-lg-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 1200px) {\n .m-xl-0 {\n margin: 0 !important;\n }\n .mt-xl-0,\n .my-xl-0 {\n margin-top: 0 !important;\n }\n .mr-xl-0,\n .mx-xl-0 {\n margin-right: 0 !important;\n }\n .mb-xl-0,\n .my-xl-0 {\n margin-bottom: 0 !important;\n }\n .ml-xl-0,\n .mx-xl-0 {\n margin-left: 0 !important;\n }\n .m-xl-1 {\n margin: 0.25rem !important;\n }\n .mt-xl-1,\n .my-xl-1 {\n margin-top: 0.25rem !important;\n }\n .mr-xl-1,\n .mx-xl-1 {\n margin-right: 0.25rem !important;\n }\n .mb-xl-1,\n .my-xl-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-xl-1,\n .mx-xl-1 {\n margin-left: 0.25rem !important;\n }\n .m-xl-2 {\n margin: 0.5rem !important;\n }\n .mt-xl-2,\n .my-xl-2 {\n margin-top: 0.5rem !important;\n }\n .mr-xl-2,\n .mx-xl-2 {\n margin-right: 0.5rem !important;\n }\n .mb-xl-2,\n .my-xl-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-xl-2,\n .mx-xl-2 {\n margin-left: 0.5rem !important;\n }\n .m-xl-3 {\n margin: 1rem !important;\n }\n .mt-xl-3,\n .my-xl-3 {\n margin-top: 1rem !important;\n }\n .mr-xl-3,\n .mx-xl-3 {\n margin-right: 1rem !important;\n }\n .mb-xl-3,\n .my-xl-3 {\n margin-bottom: 1rem !important;\n }\n .ml-xl-3,\n .mx-xl-3 {\n margin-left: 1rem !important;\n }\n .m-xl-4 {\n margin: 1.5rem !important;\n }\n .mt-xl-4,\n .my-xl-4 {\n margin-top: 1.5rem !important;\n }\n .mr-xl-4,\n .mx-xl-4 {\n margin-right: 1.5rem !important;\n }\n .mb-xl-4,\n .my-xl-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-xl-4,\n .mx-xl-4 {\n margin-left: 1.5rem !important;\n }\n .m-xl-5 {\n margin: 3rem !important;\n }\n .mt-xl-5,\n .my-xl-5 {\n margin-top: 3rem !important;\n }\n .mr-xl-5,\n .mx-xl-5 {\n margin-right: 3rem !important;\n }\n .mb-xl-5,\n .my-xl-5 {\n margin-bottom: 3rem !important;\n }\n .ml-xl-5,\n .mx-xl-5 {\n margin-left: 3rem !important;\n }\n .p-xl-0 {\n padding: 0 !important;\n }\n .pt-xl-0,\n .py-xl-0 {\n padding-top: 0 !important;\n }\n .pr-xl-0,\n .px-xl-0 {\n padding-right: 0 !important;\n }\n .pb-xl-0,\n .py-xl-0 {\n padding-bottom: 0 !important;\n }\n .pl-xl-0,\n .px-xl-0 {\n padding-left: 0 !important;\n }\n .p-xl-1 {\n padding: 0.25rem !important;\n }\n .pt-xl-1,\n .py-xl-1 {\n padding-top: 0.25rem !important;\n }\n .pr-xl-1,\n .px-xl-1 {\n padding-right: 0.25rem !important;\n }\n .pb-xl-1,\n .py-xl-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-xl-1,\n .px-xl-1 {\n padding-left: 0.25rem !important;\n }\n .p-xl-2 {\n padding: 0.5rem !important;\n }\n .pt-xl-2,\n .py-xl-2 {\n padding-top: 0.5rem !important;\n }\n .pr-xl-2,\n .px-xl-2 {\n padding-right: 0.5rem !important;\n }\n .pb-xl-2,\n .py-xl-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-xl-2,\n .px-xl-2 {\n padding-left: 0.5rem !important;\n }\n .p-xl-3 {\n padding: 1rem !important;\n }\n .pt-xl-3,\n .py-xl-3 {\n padding-top: 1rem !important;\n }\n .pr-xl-3,\n .px-xl-3 {\n padding-right: 1rem !important;\n }\n .pb-xl-3,\n .py-xl-3 {\n padding-bottom: 1rem !important;\n }\n .pl-xl-3,\n .px-xl-3 {\n padding-left: 1rem !important;\n }\n .p-xl-4 {\n padding: 1.5rem !important;\n }\n .pt-xl-4,\n .py-xl-4 {\n padding-top: 1.5rem !important;\n }\n .pr-xl-4,\n .px-xl-4 {\n padding-right: 1.5rem !important;\n }\n .pb-xl-4,\n .py-xl-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-xl-4,\n .px-xl-4 {\n padding-left: 1.5rem !important;\n }\n .p-xl-5 {\n padding: 3rem !important;\n }\n .pt-xl-5,\n .py-xl-5 {\n padding-top: 3rem !important;\n }\n .pr-xl-5,\n .px-xl-5 {\n padding-right: 3rem !important;\n }\n .pb-xl-5,\n .py-xl-5 {\n padding-bottom: 3rem !important;\n }\n .pl-xl-5,\n .px-xl-5 {\n padding-left: 3rem !important;\n }\n .m-xl-n1 {\n margin: -0.25rem !important;\n }\n .mt-xl-n1,\n .my-xl-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-xl-n1,\n .mx-xl-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-xl-n1,\n .my-xl-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-xl-n1,\n .mx-xl-n1 {\n margin-left: -0.25rem !important;\n }\n .m-xl-n2 {\n margin: -0.5rem !important;\n }\n .mt-xl-n2,\n .my-xl-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-xl-n2,\n .mx-xl-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-xl-n2,\n .my-xl-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-xl-n2,\n .mx-xl-n2 {\n margin-left: -0.5rem !important;\n }\n .m-xl-n3 {\n margin: -1rem !important;\n }\n .mt-xl-n3,\n .my-xl-n3 {\n margin-top: -1rem !important;\n }\n .mr-xl-n3,\n .mx-xl-n3 {\n margin-right: -1rem !important;\n }\n .mb-xl-n3,\n .my-xl-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-xl-n3,\n .mx-xl-n3 {\n margin-left: -1rem !important;\n }\n .m-xl-n4 {\n margin: -1.5rem !important;\n }\n .mt-xl-n4,\n .my-xl-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-xl-n4,\n .mx-xl-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-xl-n4,\n .my-xl-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-xl-n4,\n .mx-xl-n4 {\n margin-left: -1.5rem !important;\n }\n .m-xl-n5 {\n margin: -3rem !important;\n }\n .mt-xl-n5,\n .my-xl-n5 {\n margin-top: -3rem !important;\n }\n .mr-xl-n5,\n .mx-xl-n5 {\n margin-right: -3rem !important;\n }\n .mb-xl-n5,\n .my-xl-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-xl-n5,\n .mx-xl-n5 {\n margin-left: -3rem !important;\n }\n .m-xl-auto {\n margin: auto !important;\n }\n .mt-xl-auto,\n .my-xl-auto {\n margin-top: auto !important;\n }\n .mr-xl-auto,\n .mx-xl-auto {\n margin-right: auto !important;\n }\n .mb-xl-auto,\n .my-xl-auto {\n margin-bottom: auto !important;\n }\n .ml-xl-auto,\n .mx-xl-auto {\n margin-left: auto !important;\n }\n}\n\n/*# sourceMappingURL=bootstrap-grid.css.map */","// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n@if $enable-grid-classes {\n .container {\n @include make-container();\n @include make-container-max-widths();\n }\n}\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but with 100% width for\n// fluid, full width layouts.\n\n@if $enable-grid-classes {\n .container-fluid {\n @include make-container();\n }\n}\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n@if $enable-grid-classes {\n .row {\n @include make-row();\n }\n\n // Remove the negative margin from default .row, then the horizontal padding\n // from all immediate children columns (to prevent runaway style inheritance).\n .no-gutters {\n margin-right: 0;\n margin-left: 0;\n\n > .col,\n > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n }\n }\n}\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n@if $enable-grid-classes {\n @include make-grid-columns();\n}\n","/// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n@mixin make-container($gutter: $grid-gutter-width) {\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n margin-right: auto;\n margin-left: auto;\n}\n\n\n// For each breakpoint, define the maximum width of the container in a media query\n@mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) {\n @each $breakpoint, $container-max-width in $max-widths {\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n max-width: $container-max-width;\n }\n }\n}\n\n@mixin make-row($gutter: $grid-gutter-width) {\n display: flex;\n flex-wrap: wrap;\n margin-right: -$gutter / 2;\n margin-left: -$gutter / 2;\n}\n\n@mixin make-col-ready($gutter: $grid-gutter-width) {\n position: relative;\n // Prevent columns from becoming too narrow when at smaller grid tiers by\n // always setting `width: 100%;`. This works because we use `flex` values\n // later on to override this initial width.\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n}\n\n@mixin make-col($size, $columns: $grid-columns) {\n flex: 0 0 percentage($size / $columns);\n // Add a `max-width` to ensure content within each column does not blow out\n // the width of the column. Applies to IE10+ and Firefox. Chrome and Safari\n // do not appear to require this.\n max-width: percentage($size / $columns);\n}\n\n@mixin make-col-offset($size, $columns: $grid-columns) {\n $num: $size / $columns;\n margin-left: if($num == 0, 0, percentage($num));\n}\n","// Breakpoint viewport sizes and media queries.\n//\n// Breakpoints are defined as a map of (name: minimum width), order from small to large:\n//\n// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)\n//\n// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.\n\n// Name of the next breakpoint, or null for the last breakpoint.\n//\n// >> breakpoint-next(sm)\n// md\n// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// md\n// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl))\n// md\n@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {\n $n: index($breakpoint-names, $name);\n @return if($n != null and $n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);\n}\n\n// Minimum breakpoint width. Null for the smallest (first) breakpoint.\n//\n// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 576px\n@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {\n $min: map-get($breakpoints, $name);\n @return if($min != 0, $min, null);\n}\n\n// Maximum breakpoint width. Null for the largest (last) breakpoint.\n// The maximum value is calculated as the minimum of the next one less 0.02px\n// to work around the limitations of `min-` and `max-` prefixes and viewports with fractional widths.\n// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max\n// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.\n// See https://bugs.webkit.org/show_bug.cgi?id=178261\n//\n// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 767.98px\n@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {\n $next: breakpoint-next($name, $breakpoints);\n @return if($next, breakpoint-min($next, $breakpoints) - .02, null);\n}\n\n// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front.\n// Useful for making responsive utilities.\n//\n// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"\" (Returns a blank string)\n// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"-sm\"\n@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {\n @return if(breakpoint-min($name, $breakpoints) == null, \"\", \"-#{$name}\");\n}\n\n// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.\n// Makes the @content apply to the given breakpoint and wider.\n@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n @if $min {\n @media (min-width: $min) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media of at most the maximum breakpoint width. No query for the largest breakpoint.\n// Makes the @content apply to the given breakpoint and narrower.\n@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {\n $max: breakpoint-max($name, $breakpoints);\n @if $max {\n @media (max-width: $max) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media that spans multiple breakpoint widths.\n// Makes the @content apply between the min and max breakpoints\n@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($lower, $breakpoints);\n $max: breakpoint-max($upper, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($lower, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($upper, $breakpoints) {\n @content;\n }\n }\n}\n\n// Media between the breakpoint's minimum and maximum widths.\n// No minimum for the smallest breakpoint, and no maximum for the largest one.\n// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.\n@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n $max: breakpoint-max($name, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($name, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($name, $breakpoints) {\n @content;\n }\n }\n}\n","// Variables\n//\n// Variables should follow the `$component-state-property-size` formula for\n// consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs.\n\n// Color system\n\n$white: #fff !default;\n$gray-100: #f8f9fa !default;\n$gray-200: #e9ecef !default;\n$gray-300: #dee2e6 !default;\n$gray-400: #ced4da !default;\n$gray-500: #adb5bd !default;\n$gray-600: #6c757d !default;\n$gray-700: #495057 !default;\n$gray-800: #343a40 !default;\n$gray-900: #212529 !default;\n$black: #000 !default;\n\n$grays: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$grays: map-merge(\n (\n \"100\": $gray-100,\n \"200\": $gray-200,\n \"300\": $gray-300,\n \"400\": $gray-400,\n \"500\": $gray-500,\n \"600\": $gray-600,\n \"700\": $gray-700,\n \"800\": $gray-800,\n \"900\": $gray-900\n ),\n $grays\n);\n\n$blue: #007bff !default;\n$indigo: #6610f2 !default;\n$purple: #6f42c1 !default;\n$pink: #e83e8c !default;\n$red: #dc3545 !default;\n$orange: #fd7e14 !default;\n$yellow: #ffc107 !default;\n$green: #28a745 !default;\n$teal: #20c997 !default;\n$cyan: #17a2b8 !default;\n\n$colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$colors: map-merge(\n (\n \"blue\": $blue,\n \"indigo\": $indigo,\n \"purple\": $purple,\n \"pink\": $pink,\n \"red\": $red,\n \"orange\": $orange,\n \"yellow\": $yellow,\n \"green\": $green,\n \"teal\": $teal,\n \"cyan\": $cyan,\n \"white\": $white,\n \"gray\": $gray-600,\n \"gray-dark\": $gray-800\n ),\n $colors\n);\n\n$primary: $blue !default;\n$secondary: $gray-600 !default;\n$success: $green !default;\n$info: $cyan !default;\n$warning: $yellow !default;\n$danger: $red !default;\n$light: $gray-100 !default;\n$dark: $gray-800 !default;\n\n$theme-colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$theme-colors: map-merge(\n (\n \"primary\": $primary,\n \"secondary\": $secondary,\n \"success\": $success,\n \"info\": $info,\n \"warning\": $warning,\n \"danger\": $danger,\n \"light\": $light,\n \"dark\": $dark\n ),\n $theme-colors\n);\n\n// Set a specific jump point for requesting color jumps\n$theme-color-interval: 8% !default;\n\n// The yiq lightness value that determines when the lightness of color changes from \"dark\" to \"light\". Acceptable values are between 0 and 255.\n$yiq-contrasted-threshold: 150 !default;\n\n// Customize the light and dark text colors for use in our YIQ color contrast function.\n$yiq-text-dark: $gray-900 !default;\n$yiq-text-light: $white !default;\n\n\n// Options\n//\n// Quickly modify global styling by enabling or disabling optional features.\n\n$enable-caret: true !default;\n$enable-rounded: true !default;\n$enable-shadows: false !default;\n$enable-gradients: false !default;\n$enable-transitions: true !default;\n$enable-prefers-reduced-motion-media-query: true !default;\n$enable-hover-media-query: false !default; // Deprecated, no longer affects any compiled CSS\n$enable-grid-classes: true !default;\n$enable-pointer-cursor-for-buttons: true !default;\n$enable-print-styles: true !default;\n$enable-responsive-font-sizes: false !default;\n$enable-validation-icons: true !default;\n$enable-deprecation-messages: true !default;\n\n\n// Spacing\n//\n// Control the default styling of most Bootstrap elements by modifying these\n// variables. Mostly focused on spacing.\n// You can add more entries to the $spacers map, should you need more variation.\n\n$spacer: 1rem !default;\n$spacers: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$spacers: map-merge(\n (\n 0: 0,\n 1: ($spacer * .25),\n 2: ($spacer * .5),\n 3: $spacer,\n 4: ($spacer * 1.5),\n 5: ($spacer * 3)\n ),\n $spacers\n);\n\n// This variable affects the `.h-*` and `.w-*` classes.\n$sizes: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$sizes: map-merge(\n (\n 25: 25%,\n 50: 50%,\n 75: 75%,\n 100: 100%,\n auto: auto\n ),\n $sizes\n);\n\n\n// Body\n//\n// Settings for the `` element.\n\n$body-bg: $white !default;\n$body-color: $gray-900 !default;\n\n\n// Links\n//\n// Style anchor elements.\n\n$link-color: theme-color(\"primary\") !default;\n$link-decoration: none !default;\n$link-hover-color: darken($link-color, 15%) !default;\n$link-hover-decoration: underline !default;\n// Darken percentage for links with `.text-*` class (e.g. `.text-success`)\n$emphasized-link-hover-darken-percentage: 15% !default;\n\n// Paragraphs\n//\n// Style p element.\n\n$paragraph-margin-bottom: 1rem !default;\n\n\n// Grid breakpoints\n//\n// Define the minimum dimensions at which your layout will change,\n// adapting to different screen sizes, for use in media queries.\n\n$grid-breakpoints: (\n xs: 0,\n sm: 576px,\n md: 768px,\n lg: 992px,\n xl: 1200px\n) !default;\n\n@include _assert-ascending($grid-breakpoints, \"$grid-breakpoints\");\n@include _assert-starts-at-zero($grid-breakpoints, \"$grid-breakpoints\");\n\n\n// Grid containers\n//\n// Define the maximum width of `.container` for different screen sizes.\n\n$container-max-widths: (\n sm: 540px,\n md: 720px,\n lg: 960px,\n xl: 1140px\n) !default;\n\n@include _assert-ascending($container-max-widths, \"$container-max-widths\");\n\n\n// Grid columns\n//\n// Set the number of columns and specify the width of the gutters.\n\n$grid-columns: 12 !default;\n$grid-gutter-width: 30px !default;\n\n\n// Components\n//\n// Define common padding and border radius sizes and more.\n\n$line-height-lg: 1.5 !default;\n$line-height-sm: 1.5 !default;\n\n$border-width: 1px !default;\n$border-color: $gray-300 !default;\n\n$border-radius: .25rem !default;\n$border-radius-lg: .3rem !default;\n$border-radius-sm: .2rem !default;\n\n$rounded-pill: 50rem !default;\n\n$box-shadow-sm: 0 .125rem .25rem rgba($black, .075) !default;\n$box-shadow: 0 .5rem 1rem rgba($black, .15) !default;\n$box-shadow-lg: 0 1rem 3rem rgba($black, .175) !default;\n\n$component-active-color: $white !default;\n$component-active-bg: theme-color(\"primary\") !default;\n\n$caret-width: .3em !default;\n$caret-vertical-align: $caret-width * .85 !default;\n$caret-spacing: $caret-width * .85 !default;\n\n$transition-base: all .2s ease-in-out !default;\n$transition-fade: opacity .15s linear !default;\n$transition-collapse: height .35s ease !default;\n\n$embed-responsive-aspect-ratios: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$embed-responsive-aspect-ratios: join(\n (\n (21 9),\n (16 9),\n (4 3),\n (1 1),\n ),\n $embed-responsive-aspect-ratios\n);\n\n// Typography\n//\n// Font, line-height, and color for body text, headings, and more.\n\n// stylelint-disable value-keyword-case\n$font-family-sans-serif: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\" !default;\n$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace !default;\n$font-family-base: $font-family-sans-serif !default;\n// stylelint-enable value-keyword-case\n\n$font-size-base: 1rem !default; // Assumes the browser default, typically `16px`\n$font-size-lg: $font-size-base * 1.25 !default;\n$font-size-sm: $font-size-base * .875 !default;\n\n$font-weight-lighter: lighter !default;\n$font-weight-light: 300 !default;\n$font-weight-normal: 400 !default;\n$font-weight-bold: 700 !default;\n$font-weight-bolder: bolder !default;\n\n$font-weight-base: $font-weight-normal !default;\n$line-height-base: 1.5 !default;\n\n$h1-font-size: $font-size-base * 2.5 !default;\n$h2-font-size: $font-size-base * 2 !default;\n$h3-font-size: $font-size-base * 1.75 !default;\n$h4-font-size: $font-size-base * 1.5 !default;\n$h5-font-size: $font-size-base * 1.25 !default;\n$h6-font-size: $font-size-base !default;\n\n$headings-margin-bottom: $spacer / 2 !default;\n$headings-font-family: null !default;\n$headings-font-weight: 500 !default;\n$headings-line-height: 1.2 !default;\n$headings-color: null !default;\n\n$display1-size: 6rem !default;\n$display2-size: 5.5rem !default;\n$display3-size: 4.5rem !default;\n$display4-size: 3.5rem !default;\n\n$display1-weight: 300 !default;\n$display2-weight: 300 !default;\n$display3-weight: 300 !default;\n$display4-weight: 300 !default;\n$display-line-height: $headings-line-height !default;\n\n$lead-font-size: $font-size-base * 1.25 !default;\n$lead-font-weight: 300 !default;\n\n$small-font-size: 80% !default;\n\n$text-muted: $gray-600 !default;\n\n$blockquote-small-color: $gray-600 !default;\n$blockquote-small-font-size: $small-font-size !default;\n$blockquote-font-size: $font-size-base * 1.25 !default;\n\n$hr-border-color: rgba($black, .1) !default;\n$hr-border-width: $border-width !default;\n\n$mark-padding: .2em !default;\n\n$dt-font-weight: $font-weight-bold !default;\n\n$kbd-box-shadow: inset 0 -.1rem 0 rgba($black, .25) !default;\n$nested-kbd-font-weight: $font-weight-bold !default;\n\n$list-inline-padding: .5rem !default;\n\n$mark-bg: #fcf8e3 !default;\n\n$hr-margin-y: $spacer !default;\n\n\n// Tables\n//\n// Customizes the `.table` component with basic values, each used across all table variations.\n\n$table-cell-padding: .75rem !default;\n$table-cell-padding-sm: .3rem !default;\n\n$table-color: $body-color !default;\n$table-bg: null !default;\n$table-accent-bg: rgba($black, .05) !default;\n$table-hover-color: $table-color !default;\n$table-hover-bg: rgba($black, .075) !default;\n$table-active-bg: $table-hover-bg !default;\n\n$table-border-width: $border-width !default;\n$table-border-color: $border-color !default;\n\n$table-head-bg: $gray-200 !default;\n$table-head-color: $gray-700 !default;\n\n$table-dark-color: $white !default;\n$table-dark-bg: $gray-800 !default;\n$table-dark-accent-bg: rgba($white, .05) !default;\n$table-dark-hover-color: $table-dark-color !default;\n$table-dark-hover-bg: rgba($white, .075) !default;\n$table-dark-border-color: lighten($table-dark-bg, 7.5%) !default;\n$table-dark-color: $white !default;\n\n$table-striped-order: odd !default;\n\n$table-caption-color: $text-muted !default;\n\n$table-bg-level: -9 !default;\n$table-border-level: -6 !default;\n\n\n// Buttons + Forms\n//\n// Shared variables that are reassigned to `$input-` and `$btn-` specific variables.\n\n$input-btn-padding-y: .375rem !default;\n$input-btn-padding-x: .75rem !default;\n$input-btn-font-family: null !default;\n$input-btn-font-size: $font-size-base !default;\n$input-btn-line-height: $line-height-base !default;\n\n$input-btn-focus-width: .2rem !default;\n$input-btn-focus-color: rgba($component-active-bg, .25) !default;\n$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color !default;\n\n$input-btn-padding-y-sm: .25rem !default;\n$input-btn-padding-x-sm: .5rem !default;\n$input-btn-font-size-sm: $font-size-sm !default;\n$input-btn-line-height-sm: $line-height-sm !default;\n\n$input-btn-padding-y-lg: .5rem !default;\n$input-btn-padding-x-lg: 1rem !default;\n$input-btn-font-size-lg: $font-size-lg !default;\n$input-btn-line-height-lg: $line-height-lg !default;\n\n$input-btn-border-width: $border-width !default;\n\n\n// Buttons\n//\n// For each of Bootstrap's buttons, define text, background, and border color.\n\n$btn-padding-y: $input-btn-padding-y !default;\n$btn-padding-x: $input-btn-padding-x !default;\n$btn-font-family: $input-btn-font-family !default;\n$btn-font-size: $input-btn-font-size !default;\n$btn-line-height: $input-btn-line-height !default;\n\n$btn-padding-y-sm: $input-btn-padding-y-sm !default;\n$btn-padding-x-sm: $input-btn-padding-x-sm !default;\n$btn-font-size-sm: $input-btn-font-size-sm !default;\n$btn-line-height-sm: $input-btn-line-height-sm !default;\n\n$btn-padding-y-lg: $input-btn-padding-y-lg !default;\n$btn-padding-x-lg: $input-btn-padding-x-lg !default;\n$btn-font-size-lg: $input-btn-font-size-lg !default;\n$btn-line-height-lg: $input-btn-line-height-lg !default;\n\n$btn-border-width: $input-btn-border-width !default;\n\n$btn-font-weight: $font-weight-normal !default;\n$btn-box-shadow: inset 0 1px 0 rgba($white, .15), 0 1px 1px rgba($black, .075) !default;\n$btn-focus-width: $input-btn-focus-width !default;\n$btn-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$btn-disabled-opacity: .65 !default;\n$btn-active-box-shadow: inset 0 3px 5px rgba($black, .125) !default;\n\n$btn-link-disabled-color: $gray-600 !default;\n\n$btn-block-spacing-y: .5rem !default;\n\n// Allows for customizing button radius independently from global border radius\n$btn-border-radius: $border-radius !default;\n$btn-border-radius-lg: $border-radius-lg !default;\n$btn-border-radius-sm: $border-radius-sm !default;\n\n$btn-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n\n// Forms\n\n$label-margin-bottom: .5rem !default;\n\n$input-padding-y: $input-btn-padding-y !default;\n$input-padding-x: $input-btn-padding-x !default;\n$input-font-family: $input-btn-font-family !default;\n$input-font-size: $input-btn-font-size !default;\n$input-font-weight: $font-weight-base !default;\n$input-line-height: $input-btn-line-height !default;\n\n$input-padding-y-sm: $input-btn-padding-y-sm !default;\n$input-padding-x-sm: $input-btn-padding-x-sm !default;\n$input-font-size-sm: $input-btn-font-size-sm !default;\n$input-line-height-sm: $input-btn-line-height-sm !default;\n\n$input-padding-y-lg: $input-btn-padding-y-lg !default;\n$input-padding-x-lg: $input-btn-padding-x-lg !default;\n$input-font-size-lg: $input-btn-font-size-lg !default;\n$input-line-height-lg: $input-btn-line-height-lg !default;\n\n$input-bg: $white !default;\n$input-disabled-bg: $gray-200 !default;\n\n$input-color: $gray-700 !default;\n$input-border-color: $gray-400 !default;\n$input-border-width: $input-btn-border-width !default;\n$input-box-shadow: inset 0 1px 1px rgba($black, .075) !default;\n\n$input-border-radius: $border-radius !default;\n$input-border-radius-lg: $border-radius-lg !default;\n$input-border-radius-sm: $border-radius-sm !default;\n\n$input-focus-bg: $input-bg !default;\n$input-focus-border-color: lighten($component-active-bg, 25%) !default;\n$input-focus-color: $input-color !default;\n$input-focus-width: $input-btn-focus-width !default;\n$input-focus-box-shadow: $input-btn-focus-box-shadow !default;\n\n$input-placeholder-color: $gray-600 !default;\n$input-plaintext-color: $body-color !default;\n\n$input-height-border: $input-border-width * 2 !default;\n\n$input-height-inner: calc(#{$input-line-height * 1em} + #{$input-padding-y * 2}) !default;\n$input-height-inner-half: calc(#{$input-line-height * .5em} + #{$input-padding-y}) !default;\n$input-height-inner-quarter: calc(#{$input-line-height * .25em} + #{$input-padding-y / 2}) !default;\n\n$input-height: calc(#{$input-line-height * 1em} + #{$input-padding-y * 2} + #{$input-height-border}) !default;\n$input-height-sm: calc(#{$input-line-height-sm * 1em} + #{$input-btn-padding-y-sm * 2} + #{$input-height-border}) !default;\n$input-height-lg: calc(#{$input-line-height-lg * 1em} + #{$input-btn-padding-y-lg * 2} + #{$input-height-border}) !default;\n\n$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$form-text-margin-top: .25rem !default;\n\n$form-check-input-gutter: 1.25rem !default;\n$form-check-input-margin-y: .3rem !default;\n$form-check-input-margin-x: .25rem !default;\n\n$form-check-inline-margin-x: .75rem !default;\n$form-check-inline-input-margin-x: .3125rem !default;\n\n$form-grid-gutter-width: 10px !default;\n$form-group-margin-bottom: 1rem !default;\n\n$input-group-addon-color: $input-color !default;\n$input-group-addon-bg: $gray-200 !default;\n$input-group-addon-border-color: $input-border-color !default;\n\n$custom-forms-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$custom-control-gutter: .5rem !default;\n$custom-control-spacer-x: 1rem !default;\n\n$custom-control-indicator-size: 1rem !default;\n$custom-control-indicator-bg: $input-bg !default;\n\n$custom-control-indicator-bg-size: 50% 50% !default;\n$custom-control-indicator-box-shadow: $input-box-shadow !default;\n$custom-control-indicator-border-color: $gray-500 !default;\n$custom-control-indicator-border-width: $input-border-width !default;\n\n$custom-control-indicator-disabled-bg: $input-disabled-bg !default;\n$custom-control-label-disabled-color: $gray-600 !default;\n\n$custom-control-indicator-checked-color: $component-active-color !default;\n$custom-control-indicator-checked-bg: $component-active-bg !default;\n$custom-control-indicator-checked-disabled-bg: rgba(theme-color(\"primary\"), .5) !default;\n$custom-control-indicator-checked-box-shadow: none !default;\n$custom-control-indicator-checked-border-color: $custom-control-indicator-checked-bg !default;\n\n$custom-control-indicator-focus-box-shadow: $input-focus-box-shadow !default;\n$custom-control-indicator-focus-border-color: $input-focus-border-color !default;\n\n$custom-control-indicator-active-color: $component-active-color !default;\n$custom-control-indicator-active-bg: lighten($component-active-bg, 35%) !default;\n$custom-control-indicator-active-box-shadow: none !default;\n$custom-control-indicator-active-border-color: $custom-control-indicator-active-bg !default;\n\n$custom-checkbox-indicator-border-radius: $border-radius !default;\n$custom-checkbox-indicator-icon-checked: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='#{$custom-control-indicator-checked-color}' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n\n$custom-checkbox-indicator-indeterminate-bg: $component-active-bg !default;\n$custom-checkbox-indicator-indeterminate-color: $custom-control-indicator-checked-color !default;\n$custom-checkbox-indicator-icon-indeterminate: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3e%3cpath stroke='#{$custom-checkbox-indicator-indeterminate-color}' d='M0 2h4'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$custom-checkbox-indicator-indeterminate-box-shadow: none !default;\n$custom-checkbox-indicator-indeterminate-border-color: $custom-checkbox-indicator-indeterminate-bg !default;\n\n$custom-radio-indicator-border-radius: 50% !default;\n$custom-radio-indicator-icon-checked: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='#{$custom-control-indicator-checked-color}'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n\n$custom-switch-width: $custom-control-indicator-size * 1.75 !default;\n$custom-switch-indicator-border-radius: $custom-control-indicator-size / 2 !default;\n$custom-switch-indicator-size: calc(#{$custom-control-indicator-size} - #{$custom-control-indicator-border-width * 4}) !default;\n\n$custom-select-padding-y: $input-padding-y !default;\n$custom-select-padding-x: $input-padding-x !default;\n$custom-select-font-family: $input-font-family !default;\n$custom-select-font-size: $input-font-size !default;\n$custom-select-height: $input-height !default;\n$custom-select-indicator-padding: 1rem !default; // Extra padding to account for the presence of the background-image based indicator\n$custom-select-font-weight: $input-font-weight !default;\n$custom-select-line-height: $input-line-height !default;\n$custom-select-color: $input-color !default;\n$custom-select-disabled-color: $gray-600 !default;\n$custom-select-bg: $input-bg !default;\n$custom-select-disabled-bg: $gray-200 !default;\n$custom-select-bg-size: 8px 10px !default; // In pixels because image dimensions\n$custom-select-indicator-color: $gray-800 !default;\n$custom-select-indicator: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='#{$custom-select-indicator-color}' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$custom-select-background: $custom-select-indicator no-repeat right $custom-select-padding-x center / $custom-select-bg-size !default; // Used so we can have multiple background elements (e.g., arrow and feedback icon)\n\n$custom-select-feedback-icon-padding-right: calc((1em + #{2 * $custom-select-padding-y}) * 3 / 4 + #{$custom-select-padding-x + $custom-select-indicator-padding}) !default;\n$custom-select-feedback-icon-position: center right ($custom-select-padding-x + $custom-select-indicator-padding) !default;\n$custom-select-feedback-icon-size: $input-height-inner-half $input-height-inner-half !default;\n\n$custom-select-border-width: $input-border-width !default;\n$custom-select-border-color: $input-border-color !default;\n$custom-select-border-radius: $border-radius !default;\n$custom-select-box-shadow: inset 0 1px 2px rgba($black, .075) !default;\n\n$custom-select-focus-border-color: $input-focus-border-color !default;\n$custom-select-focus-width: $input-focus-width !default;\n$custom-select-focus-box-shadow: 0 0 0 $custom-select-focus-width $input-btn-focus-color !default;\n\n$custom-select-padding-y-sm: $input-padding-y-sm !default;\n$custom-select-padding-x-sm: $input-padding-x-sm !default;\n$custom-select-font-size-sm: $input-font-size-sm !default;\n$custom-select-height-sm: $input-height-sm !default;\n\n$custom-select-padding-y-lg: $input-padding-y-lg !default;\n$custom-select-padding-x-lg: $input-padding-x-lg !default;\n$custom-select-font-size-lg: $input-font-size-lg !default;\n$custom-select-height-lg: $input-height-lg !default;\n\n$custom-range-track-width: 100% !default;\n$custom-range-track-height: .5rem !default;\n$custom-range-track-cursor: pointer !default;\n$custom-range-track-bg: $gray-300 !default;\n$custom-range-track-border-radius: 1rem !default;\n$custom-range-track-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;\n\n$custom-range-thumb-width: 1rem !default;\n$custom-range-thumb-height: $custom-range-thumb-width !default;\n$custom-range-thumb-bg: $component-active-bg !default;\n$custom-range-thumb-border: 0 !default;\n$custom-range-thumb-border-radius: 1rem !default;\n$custom-range-thumb-box-shadow: 0 .1rem .25rem rgba($black, .1) !default;\n$custom-range-thumb-focus-box-shadow: 0 0 0 1px $body-bg, $input-focus-box-shadow !default;\n$custom-range-thumb-focus-box-shadow-width: $input-focus-width !default; // For focus box shadow issue in IE/Edge\n$custom-range-thumb-active-bg: lighten($component-active-bg, 35%) !default;\n$custom-range-thumb-disabled-bg: $gray-500 !default;\n\n$custom-file-height: $input-height !default;\n$custom-file-height-inner: $input-height-inner !default;\n$custom-file-focus-border-color: $input-focus-border-color !default;\n$custom-file-focus-box-shadow: $input-focus-box-shadow !default;\n$custom-file-disabled-bg: $input-disabled-bg !default;\n\n$custom-file-padding-y: $input-padding-y !default;\n$custom-file-padding-x: $input-padding-x !default;\n$custom-file-line-height: $input-line-height !default;\n$custom-file-font-family: $input-font-family !default;\n$custom-file-font-weight: $input-font-weight !default;\n$custom-file-color: $input-color !default;\n$custom-file-bg: $input-bg !default;\n$custom-file-border-width: $input-border-width !default;\n$custom-file-border-color: $input-border-color !default;\n$custom-file-border-radius: $input-border-radius !default;\n$custom-file-box-shadow: $input-box-shadow !default;\n$custom-file-button-color: $custom-file-color !default;\n$custom-file-button-bg: $input-group-addon-bg !default;\n$custom-file-text: (\n en: \"Browse\"\n) !default;\n\n\n// Form validation\n\n$form-feedback-margin-top: $form-text-margin-top !default;\n$form-feedback-font-size: $small-font-size !default;\n$form-feedback-valid-color: theme-color(\"success\") !default;\n$form-feedback-invalid-color: theme-color(\"danger\") !default;\n\n$form-feedback-icon-valid-color: $form-feedback-valid-color !default;\n$form-feedback-icon-valid: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='#{$form-feedback-icon-valid-color}' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$form-feedback-icon-invalid-color: $form-feedback-invalid-color !default;\n$form-feedback-icon-invalid: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$form-feedback-icon-invalid-color}' viewBox='-2 -2 7 7'%3e%3cpath stroke='#{$form-feedback-icon-invalid-color}' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E\"), \"#\", \"%23\") !default;\n\n$form-validation-states: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$form-validation-states: map-merge(\n (\n \"valid\": (\n \"color\": $form-feedback-valid-color,\n \"icon\": $form-feedback-icon-valid\n ),\n \"invalid\": (\n \"color\": $form-feedback-invalid-color,\n \"icon\": $form-feedback-icon-invalid\n ),\n ),\n $form-validation-states\n);\n\n// Z-index master list\n//\n// Warning: Avoid customizing these values. They're used for a bird's eye view\n// of components dependent on the z-axis and are designed to all work together.\n\n$zindex-dropdown: 1000 !default;\n$zindex-sticky: 1020 !default;\n$zindex-fixed: 1030 !default;\n$zindex-modal-backdrop: 1040 !default;\n$zindex-modal: 1050 !default;\n$zindex-popover: 1060 !default;\n$zindex-tooltip: 1070 !default;\n\n\n// Navs\n\n$nav-link-padding-y: .5rem !default;\n$nav-link-padding-x: 1rem !default;\n$nav-link-disabled-color: $gray-600 !default;\n\n$nav-tabs-border-color: $gray-300 !default;\n$nav-tabs-border-width: $border-width !default;\n$nav-tabs-border-radius: $border-radius !default;\n$nav-tabs-link-hover-border-color: $gray-200 $gray-200 $nav-tabs-border-color !default;\n$nav-tabs-link-active-color: $gray-700 !default;\n$nav-tabs-link-active-bg: $body-bg !default;\n$nav-tabs-link-active-border-color: $gray-300 $gray-300 $nav-tabs-link-active-bg !default;\n\n$nav-pills-border-radius: $border-radius !default;\n$nav-pills-link-active-color: $component-active-color !default;\n$nav-pills-link-active-bg: $component-active-bg !default;\n\n$nav-divider-color: $gray-200 !default;\n$nav-divider-margin-y: $spacer / 2 !default;\n\n\n// Navbar\n\n$navbar-padding-y: $spacer / 2 !default;\n$navbar-padding-x: $spacer !default;\n\n$navbar-nav-link-padding-x: .5rem !default;\n\n$navbar-brand-font-size: $font-size-lg !default;\n// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link\n$nav-link-height: $font-size-base * $line-height-base + $nav-link-padding-y * 2 !default;\n$navbar-brand-height: $navbar-brand-font-size * $line-height-base !default;\n$navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) / 2 !default;\n\n$navbar-toggler-padding-y: .25rem !default;\n$navbar-toggler-padding-x: .75rem !default;\n$navbar-toggler-font-size: $font-size-lg !default;\n$navbar-toggler-border-radius: $btn-border-radius !default;\n\n$navbar-dark-color: rgba($white, .5) !default;\n$navbar-dark-hover-color: rgba($white, .75) !default;\n$navbar-dark-active-color: $white !default;\n$navbar-dark-disabled-color: rgba($white, .25) !default;\n$navbar-dark-toggler-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='#{$navbar-dark-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$navbar-dark-toggler-border-color: rgba($white, .1) !default;\n\n$navbar-light-color: rgba($black, .5) !default;\n$navbar-light-hover-color: rgba($black, .7) !default;\n$navbar-light-active-color: rgba($black, .9) !default;\n$navbar-light-disabled-color: rgba($black, .3) !default;\n$navbar-light-toggler-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='#{$navbar-light-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$navbar-light-toggler-border-color: rgba($black, .1) !default;\n\n$navbar-light-brand-color: $navbar-light-active-color !default;\n$navbar-light-brand-hover-color: $navbar-light-active-color !default;\n$navbar-dark-brand-color: $navbar-dark-active-color !default;\n$navbar-dark-brand-hover-color: $navbar-dark-active-color !default;\n\n\n// Dropdowns\n//\n// Dropdown menu container and contents.\n\n$dropdown-min-width: 10rem !default;\n$dropdown-padding-y: .5rem !default;\n$dropdown-spacer: .125rem !default;\n$dropdown-font-size: $font-size-base !default;\n$dropdown-color: $body-color !default;\n$dropdown-bg: $white !default;\n$dropdown-border-color: rgba($black, .15) !default;\n$dropdown-border-radius: $border-radius !default;\n$dropdown-border-width: $border-width !default;\n$dropdown-inner-border-radius: calc(#{$dropdown-border-radius} - #{$dropdown-border-width}) !default;\n$dropdown-divider-bg: $gray-200 !default;\n$dropdown-divider-margin-y: $nav-divider-margin-y !default;\n$dropdown-box-shadow: 0 .5rem 1rem rgba($black, .175) !default;\n\n$dropdown-link-color: $gray-900 !default;\n$dropdown-link-hover-color: darken($gray-900, 5%) !default;\n$dropdown-link-hover-bg: $gray-100 !default;\n\n$dropdown-link-active-color: $component-active-color !default;\n$dropdown-link-active-bg: $component-active-bg !default;\n\n$dropdown-link-disabled-color: $gray-600 !default;\n\n$dropdown-item-padding-y: .25rem !default;\n$dropdown-item-padding-x: 1.5rem !default;\n\n$dropdown-header-color: $gray-600 !default;\n\n\n// Pagination\n\n$pagination-padding-y: .5rem !default;\n$pagination-padding-x: .75rem !default;\n$pagination-padding-y-sm: .25rem !default;\n$pagination-padding-x-sm: .5rem !default;\n$pagination-padding-y-lg: .75rem !default;\n$pagination-padding-x-lg: 1.5rem !default;\n$pagination-line-height: 1.25 !default;\n\n$pagination-color: $link-color !default;\n$pagination-bg: $white !default;\n$pagination-border-width: $border-width !default;\n$pagination-border-color: $gray-300 !default;\n\n$pagination-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$pagination-focus-outline: 0 !default;\n\n$pagination-hover-color: $link-hover-color !default;\n$pagination-hover-bg: $gray-200 !default;\n$pagination-hover-border-color: $gray-300 !default;\n\n$pagination-active-color: $component-active-color !default;\n$pagination-active-bg: $component-active-bg !default;\n$pagination-active-border-color: $pagination-active-bg !default;\n\n$pagination-disabled-color: $gray-600 !default;\n$pagination-disabled-bg: $white !default;\n$pagination-disabled-border-color: $gray-300 !default;\n\n\n// Jumbotron\n\n$jumbotron-padding: 2rem !default;\n$jumbotron-color: null !default;\n$jumbotron-bg: $gray-200 !default;\n\n\n// Cards\n\n$card-spacer-y: .75rem !default;\n$card-spacer-x: 1.25rem !default;\n$card-border-width: $border-width !default;\n$card-border-radius: $border-radius !default;\n$card-border-color: rgba($black, .125) !default;\n$card-inner-border-radius: calc(#{$card-border-radius} - #{$card-border-width}) !default;\n$card-cap-bg: rgba($black, .03) !default;\n$card-cap-color: null !default;\n$card-color: null !default;\n$card-bg: $white !default;\n\n$card-img-overlay-padding: 1.25rem !default;\n\n$card-group-margin: $grid-gutter-width / 2 !default;\n$card-deck-margin: $card-group-margin !default;\n\n$card-columns-count: 3 !default;\n$card-columns-gap: 1.25rem !default;\n$card-columns-margin: $card-spacer-y !default;\n\n\n// Tooltips\n\n$tooltip-font-size: $font-size-sm !default;\n$tooltip-max-width: 200px !default;\n$tooltip-color: $white !default;\n$tooltip-bg: $black !default;\n$tooltip-border-radius: $border-radius !default;\n$tooltip-opacity: .9 !default;\n$tooltip-padding-y: .25rem !default;\n$tooltip-padding-x: .5rem !default;\n$tooltip-margin: 0 !default;\n\n$tooltip-arrow-width: .8rem !default;\n$tooltip-arrow-height: .4rem !default;\n$tooltip-arrow-color: $tooltip-bg !default;\n\n// Form tooltips must come after regular tooltips\n$form-feedback-tooltip-padding-y: $tooltip-padding-y !default;\n$form-feedback-tooltip-padding-x: $tooltip-padding-x !default;\n$form-feedback-tooltip-font-size: $tooltip-font-size !default;\n$form-feedback-tooltip-line-height: $line-height-base !default;\n$form-feedback-tooltip-opacity: $tooltip-opacity !default;\n$form-feedback-tooltip-border-radius: $tooltip-border-radius !default;\n\n\n// Popovers\n\n$popover-font-size: $font-size-sm !default;\n$popover-bg: $white !default;\n$popover-max-width: 276px !default;\n$popover-border-width: $border-width !default;\n$popover-border-color: rgba($black, .2) !default;\n$popover-border-radius: $border-radius-lg !default;\n$popover-box-shadow: 0 .25rem .5rem rgba($black, .2) !default;\n\n$popover-header-bg: darken($popover-bg, 3%) !default;\n$popover-header-color: $headings-color !default;\n$popover-header-padding-y: .5rem !default;\n$popover-header-padding-x: .75rem !default;\n\n$popover-body-color: $body-color !default;\n$popover-body-padding-y: $popover-header-padding-y !default;\n$popover-body-padding-x: $popover-header-padding-x !default;\n\n$popover-arrow-width: 1rem !default;\n$popover-arrow-height: .5rem !default;\n$popover-arrow-color: $popover-bg !default;\n\n$popover-arrow-outer-color: fade-in($popover-border-color, .05) !default;\n\n\n// Toasts\n\n$toast-max-width: 350px !default;\n$toast-padding-x: .75rem !default;\n$toast-padding-y: .25rem !default;\n$toast-font-size: .875rem !default;\n$toast-color: null !default;\n$toast-background-color: rgba($white, .85) !default;\n$toast-border-width: 1px !default;\n$toast-border-color: rgba(0, 0, 0, .1) !default;\n$toast-border-radius: .25rem !default;\n$toast-box-shadow: 0 .25rem .75rem rgba($black, .1) !default;\n\n$toast-header-color: $gray-600 !default;\n$toast-header-background-color: rgba($white, .85) !default;\n$toast-header-border-color: rgba(0, 0, 0, .05) !default;\n\n\n// Badges\n\n$badge-font-size: 75% !default;\n$badge-font-weight: $font-weight-bold !default;\n$badge-padding-y: .25em !default;\n$badge-padding-x: .4em !default;\n$badge-border-radius: $border-radius !default;\n\n$badge-transition: $btn-transition !default;\n$badge-focus-width: $input-btn-focus-width !default;\n\n$badge-pill-padding-x: .6em !default;\n// Use a higher than normal value to ensure completely rounded edges when\n// customizing padding or font-size on labels.\n$badge-pill-border-radius: 10rem !default;\n\n\n// Modals\n\n// Padding applied to the modal body\n$modal-inner-padding: 1rem !default;\n\n$modal-dialog-margin: .5rem !default;\n$modal-dialog-margin-y-sm-up: 1.75rem !default;\n\n$modal-title-line-height: $line-height-base !default;\n\n$modal-content-color: null !default;\n$modal-content-bg: $white !default;\n$modal-content-border-color: rgba($black, .2) !default;\n$modal-content-border-width: $border-width !default;\n$modal-content-border-radius: $border-radius-lg !default;\n$modal-content-box-shadow-xs: 0 .25rem .5rem rgba($black, .5) !default;\n$modal-content-box-shadow-sm-up: 0 .5rem 1rem rgba($black, .5) !default;\n\n$modal-backdrop-bg: $black !default;\n$modal-backdrop-opacity: .5 !default;\n$modal-header-border-color: $border-color !default;\n$modal-footer-border-color: $modal-header-border-color !default;\n$modal-header-border-width: $modal-content-border-width !default;\n$modal-footer-border-width: $modal-header-border-width !default;\n$modal-header-padding-y: 1rem !default;\n$modal-header-padding-x: 1rem !default;\n$modal-header-padding: $modal-header-padding-y $modal-header-padding-x !default; // Keep this for backwards compatibility\n\n$modal-xl: 1140px !default;\n$modal-lg: 800px !default;\n$modal-md: 500px !default;\n$modal-sm: 300px !default;\n\n$modal-fade-transform: translate(0, -50px) !default;\n$modal-show-transform: none !default;\n$modal-transition: transform .3s ease-out !default;\n\n\n// Alerts\n//\n// Define alert colors, border radius, and padding.\n\n$alert-padding-y: .75rem !default;\n$alert-padding-x: 1.25rem !default;\n$alert-margin-bottom: 1rem !default;\n$alert-border-radius: $border-radius !default;\n$alert-link-font-weight: $font-weight-bold !default;\n$alert-border-width: $border-width !default;\n\n$alert-bg-level: -10 !default;\n$alert-border-level: -9 !default;\n$alert-color-level: 6 !default;\n\n\n// Progress bars\n\n$progress-height: 1rem !default;\n$progress-font-size: $font-size-base * .75 !default;\n$progress-bg: $gray-200 !default;\n$progress-border-radius: $border-radius !default;\n$progress-box-shadow: inset 0 .1rem .1rem rgba($black, .1) !default;\n$progress-bar-color: $white !default;\n$progress-bar-bg: theme-color(\"primary\") !default;\n$progress-bar-animation-timing: 1s linear infinite !default;\n$progress-bar-transition: width .6s ease !default;\n\n\n// List group\n\n$list-group-color: null !default;\n$list-group-bg: $white !default;\n$list-group-border-color: rgba($black, .125) !default;\n$list-group-border-width: $border-width !default;\n$list-group-border-radius: $border-radius !default;\n\n$list-group-item-padding-y: .75rem !default;\n$list-group-item-padding-x: 1.25rem !default;\n\n$list-group-hover-bg: $gray-100 !default;\n$list-group-active-color: $component-active-color !default;\n$list-group-active-bg: $component-active-bg !default;\n$list-group-active-border-color: $list-group-active-bg !default;\n\n$list-group-disabled-color: $gray-600 !default;\n$list-group-disabled-bg: $list-group-bg !default;\n\n$list-group-action-color: $gray-700 !default;\n$list-group-action-hover-color: $list-group-action-color !default;\n\n$list-group-action-active-color: $body-color !default;\n$list-group-action-active-bg: $gray-200 !default;\n\n\n// Image thumbnails\n\n$thumbnail-padding: .25rem !default;\n$thumbnail-bg: $body-bg !default;\n$thumbnail-border-width: $border-width !default;\n$thumbnail-border-color: $gray-300 !default;\n$thumbnail-border-radius: $border-radius !default;\n$thumbnail-box-shadow: 0 1px 2px rgba($black, .075) !default;\n\n\n// Figures\n\n$figure-caption-font-size: 90% !default;\n$figure-caption-color: $gray-600 !default;\n\n\n// Breadcrumbs\n\n$breadcrumb-padding-y: .75rem !default;\n$breadcrumb-padding-x: 1rem !default;\n$breadcrumb-item-padding: .5rem !default;\n\n$breadcrumb-margin-bottom: 1rem !default;\n\n$breadcrumb-bg: $gray-200 !default;\n$breadcrumb-divider-color: $gray-600 !default;\n$breadcrumb-active-color: $gray-600 !default;\n$breadcrumb-divider: quote(\"/\") !default;\n\n$breadcrumb-border-radius: $border-radius !default;\n\n\n// Carousel\n\n$carousel-control-color: $white !default;\n$carousel-control-width: 15% !default;\n$carousel-control-opacity: .5 !default;\n$carousel-control-hover-opacity: .9 !default;\n$carousel-control-transition: opacity .15s ease !default;\n\n$carousel-indicator-width: 30px !default;\n$carousel-indicator-height: 3px !default;\n$carousel-indicator-hit-area-height: 10px !default;\n$carousel-indicator-spacer: 3px !default;\n$carousel-indicator-active-bg: $white !default;\n$carousel-indicator-transition: opacity .6s ease !default;\n\n$carousel-caption-width: 70% !default;\n$carousel-caption-color: $white !default;\n\n$carousel-control-icon-width: 20px !default;\n\n$carousel-control-prev-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$carousel-control-next-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n\n$carousel-transition-duration: .6s !default;\n$carousel-transition: transform $carousel-transition-duration ease-in-out !default; // Define transform transition first if using multiple transitions (e.g., `transform 2s ease, opacity .5s ease-out`)\n\n\n// Spinners\n\n$spinner-width: 2rem !default;\n$spinner-height: $spinner-width !default;\n$spinner-border-width: .25em !default;\n\n$spinner-width-sm: 1rem !default;\n$spinner-height-sm: $spinner-width-sm !default;\n$spinner-border-width-sm: .2em !default;\n\n\n// Close\n\n$close-font-size: $font-size-base * 1.5 !default;\n$close-font-weight: $font-weight-bold !default;\n$close-color: $black !default;\n$close-text-shadow: 0 1px 0 $white !default;\n\n\n// Code\n\n$code-font-size: 87.5% !default;\n$code-color: $pink !default;\n\n$kbd-padding-y: .2rem !default;\n$kbd-padding-x: .4rem !default;\n$kbd-font-size: $code-font-size !default;\n$kbd-color: $white !default;\n$kbd-bg: $gray-900 !default;\n\n$pre-color: $gray-900 !default;\n$pre-scrollable-max-height: 340px !default;\n\n\n// Utilities\n\n$displays: none, inline, inline-block, block, table, table-row, table-cell, flex, inline-flex !default;\n$overflows: auto, hidden !default;\n$positions: static, relative, absolute, fixed, sticky !default;\n\n\n// Printing\n\n$print-page-size: a3 !default;\n$print-body-min-width: map-get($grid-breakpoints, \"lg\") !default;\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `$grid-columns`.\n\n@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {\n // Common properties for all breakpoints\n %grid-column {\n position: relative;\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n }\n\n @each $breakpoint in map-keys($breakpoints) {\n $infix: breakpoint-infix($breakpoint, $breakpoints);\n\n // Allow columns to stretch full width below their breakpoints\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @extend %grid-column;\n }\n }\n .col#{$infix},\n .col#{$infix}-auto {\n @extend %grid-column;\n }\n\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n // Provide basic `.col-{bp}` classes for equal-width flexbox columns\n .col#{$infix} {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col#{$infix}-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%; // Reset earlier grid tiers\n }\n\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @include make-col($i, $columns);\n }\n }\n\n .order#{$infix}-first { order: -1; }\n\n .order#{$infix}-last { order: $columns + 1; }\n\n @for $i from 0 through $columns {\n .order#{$infix}-#{$i} { order: $i; }\n }\n\n // `$columns - 1` because offsetting by the width of an entire row isn't possible\n @for $i from 0 through ($columns - 1) {\n @if not ($infix == \"\" and $i == 0) { // Avoid emitting useless .offset-0\n .offset#{$infix}-#{$i} {\n @include make-col-offset($i, $columns);\n }\n }\n }\n }\n }\n}\n","// stylelint-disable declaration-no-important\n\n//\n// Utilities for common `display` values\n//\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n @each $value in $displays {\n .d#{$infix}-#{$value} { display: $value !important; }\n }\n }\n}\n\n\n//\n// Utilities for toggling `display` in print\n//\n\n@media print {\n @each $value in $displays {\n .d-print-#{$value} { display: $value !important; }\n }\n}\n","// stylelint-disable declaration-no-important\n\n// Flex variation\n//\n// Custom styles for additional flex alignment options.\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n .flex#{$infix}-row { flex-direction: row !important; }\n .flex#{$infix}-column { flex-direction: column !important; }\n .flex#{$infix}-row-reverse { flex-direction: row-reverse !important; }\n .flex#{$infix}-column-reverse { flex-direction: column-reverse !important; }\n\n .flex#{$infix}-wrap { flex-wrap: wrap !important; }\n .flex#{$infix}-nowrap { flex-wrap: nowrap !important; }\n .flex#{$infix}-wrap-reverse { flex-wrap: wrap-reverse !important; }\n .flex#{$infix}-fill { flex: 1 1 auto !important; }\n .flex#{$infix}-grow-0 { flex-grow: 0 !important; }\n .flex#{$infix}-grow-1 { flex-grow: 1 !important; }\n .flex#{$infix}-shrink-0 { flex-shrink: 0 !important; }\n .flex#{$infix}-shrink-1 { flex-shrink: 1 !important; }\n\n .justify-content#{$infix}-start { justify-content: flex-start !important; }\n .justify-content#{$infix}-end { justify-content: flex-end !important; }\n .justify-content#{$infix}-center { justify-content: center !important; }\n .justify-content#{$infix}-between { justify-content: space-between !important; }\n .justify-content#{$infix}-around { justify-content: space-around !important; }\n\n .align-items#{$infix}-start { align-items: flex-start !important; }\n .align-items#{$infix}-end { align-items: flex-end !important; }\n .align-items#{$infix}-center { align-items: center !important; }\n .align-items#{$infix}-baseline { align-items: baseline !important; }\n .align-items#{$infix}-stretch { align-items: stretch !important; }\n\n .align-content#{$infix}-start { align-content: flex-start !important; }\n .align-content#{$infix}-end { align-content: flex-end !important; }\n .align-content#{$infix}-center { align-content: center !important; }\n .align-content#{$infix}-between { align-content: space-between !important; }\n .align-content#{$infix}-around { align-content: space-around !important; }\n .align-content#{$infix}-stretch { align-content: stretch !important; }\n\n .align-self#{$infix}-auto { align-self: auto !important; }\n .align-self#{$infix}-start { align-self: flex-start !important; }\n .align-self#{$infix}-end { align-self: flex-end !important; }\n .align-self#{$infix}-center { align-self: center !important; }\n .align-self#{$infix}-baseline { align-self: baseline !important; }\n .align-self#{$infix}-stretch { align-self: stretch !important; }\n }\n}\n","// stylelint-disable declaration-no-important\n\n// Margin and Padding\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n @each $prop, $abbrev in (margin: m, padding: p) {\n @each $size, $length in $spacers {\n .#{$abbrev}#{$infix}-#{$size} { #{$prop}: $length !important; }\n .#{$abbrev}t#{$infix}-#{$size},\n .#{$abbrev}y#{$infix}-#{$size} {\n #{$prop}-top: $length !important;\n }\n .#{$abbrev}r#{$infix}-#{$size},\n .#{$abbrev}x#{$infix}-#{$size} {\n #{$prop}-right: $length !important;\n }\n .#{$abbrev}b#{$infix}-#{$size},\n .#{$abbrev}y#{$infix}-#{$size} {\n #{$prop}-bottom: $length !important;\n }\n .#{$abbrev}l#{$infix}-#{$size},\n .#{$abbrev}x#{$infix}-#{$size} {\n #{$prop}-left: $length !important;\n }\n }\n }\n\n // Negative margins (e.g., where `.mb-n1` is negative version of `.mb-1`)\n @each $size, $length in $spacers {\n @if $size != 0 {\n .m#{$infix}-n#{$size} { margin: -$length !important; }\n .mt#{$infix}-n#{$size},\n .my#{$infix}-n#{$size} {\n margin-top: -$length !important;\n }\n .mr#{$infix}-n#{$size},\n .mx#{$infix}-n#{$size} {\n margin-right: -$length !important;\n }\n .mb#{$infix}-n#{$size},\n .my#{$infix}-n#{$size} {\n margin-bottom: -$length !important;\n }\n .ml#{$infix}-n#{$size},\n .mx#{$infix}-n#{$size} {\n margin-left: -$length !important;\n }\n }\n }\n\n // Some special margin utils\n .m#{$infix}-auto { margin: auto !important; }\n .mt#{$infix}-auto,\n .my#{$infix}-auto {\n margin-top: auto !important;\n }\n .mr#{$infix}-auto,\n .mx#{$infix}-auto {\n margin-right: auto !important;\n }\n .mb#{$infix}-auto,\n .my#{$infix}-auto {\n margin-bottom: auto !important;\n }\n .ml#{$infix}-auto,\n .mx#{$infix}-auto {\n margin-left: auto !important;\n }\n }\n}\n"]} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css new file mode 100644 index 0000000000000000000000000000000000000000..e5e74f7f18ab0470419a8014c1b81a1288837886 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css @@ -0,0 +1,7 @@ +/*! + * Bootstrap Grid v4.3.1 (https://getbootstrap.com/) + * Copyright 2011-2019 The Bootstrap Authors + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */html{box-sizing:border-box;-ms-overflow-style:scrollbar}*,::after,::before{box-sizing:inherit}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.container-fluid{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-ms-flex-order:-1;order:-1}.order-last{-ms-flex-order:13;order:13}.order-0{-ms-flex-order:0;order:0}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;order:-1}.order-sm-last{-ms-flex-order:13;order:13}.order-sm-0{-ms-flex-order:0;order:0}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;order:-1}.order-md-last{-ms-flex-order:13;order:13}.order-md-0{-ms-flex-order:0;order:0}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;order:-1}.order-lg-last{-ms-flex-order:13;order:13}.order-lg-0{-ms-flex-order:0;order:0}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;order:-1}.order-xl-last{-ms-flex-order:13;order:13}.order-xl-0{-ms-flex-order:0;order:0}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}} +/*# sourceMappingURL=bootstrap-grid.min.css.map */ \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map new file mode 100644 index 0000000000000000000000000000000000000000..13e33dbc77653d72afa363ec6475569af8e2c0be --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../scss/bootstrap-grid.scss","dist/css/bootstrap-grid.css","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/mixins/_breakpoints.scss","../../scss/mixins/_grid-framework.scss","../../scss/utilities/_display.scss","../../scss/utilities/_flex.scss","../../scss/utilities/_spacing.scss"],"names":[],"mappings":"AAAA;;;;;AAOA,KACE,WAAA,WACA,mBAAA,UAGF,ECCA,QADA,SDGE,WAAA,QEVA,WCAA,MAAA,KACA,cAAA,KACA,aAAA,KACA,aAAA,KACA,YAAA,KCmDE,yBFvDF,WCYI,UAAA,OC2CF,yBFvDF,WCYI,UAAA,OC2CF,yBFvDF,WCYI,UAAA,OC2CF,0BFvDF,WCYI,UAAA,QDAJ,iBCZA,MAAA,KACA,cAAA,KACA,aAAA,KACA,aAAA,KACA,YAAA,KDkBA,KCJA,QAAA,YAAA,QAAA,KACA,cAAA,KAAA,UAAA,KACA,aAAA,MACA,YAAA,MDOA,YACE,aAAA,EACA,YAAA,EAFF,iBDuCF,0BCjCM,cAAA,EACA,aAAA,EGjCJ,KAAA,OAAA,QAAA,QAAA,QAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OJuEF,UAEqJ,QAAvI,UAAmG,WAAY,WAAY,WAAhH,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UACtG,aAFqJ,QAAvI,UAAmG,WAAY,WAAY,WAAhH,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UACtG,aAFkJ,QAAvI,UAAmG,WAAY,WAAY,WAAhH,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UACnG,aAEqJ,QAAvI,UAAmG,WAAY,WAAY,WAAhH,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UACtG,aI1EI,SAAA,SACA,MAAA,KACA,cAAA,KACA,aAAA,KAmBE,KACE,wBAAA,EAAA,WAAA,EACA,kBAAA,EAAA,UAAA,EACA,UAAA,KAEF,UACE,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,MAAA,KACA,UAAA,KAIA,OFFN,SAAA,EAAA,EAAA,UAAA,KAAA,EAAA,EAAA,UAIA,UAAA,UEFM,OFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,OFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,OFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,OFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,OFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,OFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,OFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,OFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,QFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,QFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,QFFN,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KAIA,UAAA,KEGI,aAAwB,eAAA,GAAA,MAAA,GAExB,YAAuB,eAAA,GAAA,MAAA,GAGrB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,UAAwB,eAAA,GAAA,MAAA,GAAxB,UAAwB,eAAA,GAAA,MAAA,GAAxB,UAAwB,eAAA,GAAA,MAAA,GAMtB,UFTR,YAAA,UESQ,UFTR,YAAA,WESQ,UFTR,YAAA,IESQ,UFTR,YAAA,WESQ,UFTR,YAAA,WESQ,UFTR,YAAA,IESQ,UFTR,YAAA,WESQ,UFTR,YAAA,WESQ,UFTR,YAAA,IESQ,WFTR,YAAA,WESQ,WFTR,YAAA,WCWE,yBC9BE,QACE,wBAAA,EAAA,WAAA,EACA,kBAAA,EAAA,UAAA,EACA,UAAA,KAEF,aACE,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,MAAA,KACA,UAAA,KAIA,UFFN,SAAA,EAAA,EAAA,UAAA,KAAA,EAAA,EAAA,UAIA,UAAA,UEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,WFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,WFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,WFFN,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KAIA,UAAA,KEGI,gBAAwB,eAAA,GAAA,MAAA,GAExB,eAAuB,eAAA,GAAA,MAAA,GAGrB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAMtB,aFTR,YAAA,EESQ,aFTR,YAAA,UESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,aFTR,YAAA,WESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,aFTR,YAAA,WESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,cFTR,YAAA,WESQ,cFTR,YAAA,YCWE,yBC9BE,QACE,wBAAA,EAAA,WAAA,EACA,kBAAA,EAAA,UAAA,EACA,UAAA,KAEF,aACE,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,MAAA,KACA,UAAA,KAIA,UFFN,SAAA,EAAA,EAAA,UAAA,KAAA,EAAA,EAAA,UAIA,UAAA,UEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,WFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,WFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,WFFN,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KAIA,UAAA,KEGI,gBAAwB,eAAA,GAAA,MAAA,GAExB,eAAuB,eAAA,GAAA,MAAA,GAGrB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAMtB,aFTR,YAAA,EESQ,aFTR,YAAA,UESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,aFTR,YAAA,WESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,aFTR,YAAA,WESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,cFTR,YAAA,WESQ,cFTR,YAAA,YCWE,yBC9BE,QACE,wBAAA,EAAA,WAAA,EACA,kBAAA,EAAA,UAAA,EACA,UAAA,KAEF,aACE,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,MAAA,KACA,UAAA,KAIA,UFFN,SAAA,EAAA,EAAA,UAAA,KAAA,EAAA,EAAA,UAIA,UAAA,UEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,WFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,WFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,WFFN,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KAIA,UAAA,KEGI,gBAAwB,eAAA,GAAA,MAAA,GAExB,eAAuB,eAAA,GAAA,MAAA,GAGrB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAMtB,aFTR,YAAA,EESQ,aFTR,YAAA,UESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,aFTR,YAAA,WESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,aFTR,YAAA,WESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,cFTR,YAAA,WESQ,cFTR,YAAA,YCWE,0BC9BE,QACE,wBAAA,EAAA,WAAA,EACA,kBAAA,EAAA,UAAA,EACA,UAAA,KAEF,aACE,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,MAAA,KACA,UAAA,KAIA,UFFN,SAAA,EAAA,EAAA,UAAA,KAAA,EAAA,EAAA,UAIA,UAAA,UEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,WFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,WFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,WFFN,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KAIA,UAAA,KEGI,gBAAwB,eAAA,GAAA,MAAA,GAExB,eAAuB,eAAA,GAAA,MAAA,GAGrB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAMtB,aFTR,YAAA,EESQ,aFTR,YAAA,UESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,aFTR,YAAA,WESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,aFTR,YAAA,WESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,cFTR,YAAA,WESQ,cFTR,YAAA,YGtCI,QAAwB,QAAA,eAAxB,UAAwB,QAAA,iBAAxB,gBAAwB,QAAA,uBAAxB,SAAwB,QAAA,gBAAxB,SAAwB,QAAA,gBAAxB,aAAwB,QAAA,oBAAxB,cAAwB,QAAA,qBAAxB,QAAwB,QAAA,sBAAA,QAAA,eAAxB,eAAwB,QAAA,6BAAA,QAAA,sBFiD1B,yBEjDE,WAAwB,QAAA,eAAxB,aAAwB,QAAA,iBAAxB,mBAAwB,QAAA,uBAAxB,YAAwB,QAAA,gBAAxB,YAAwB,QAAA,gBAAxB,gBAAwB,QAAA,oBAAxB,iBAAwB,QAAA,qBAAxB,WAAwB,QAAA,sBAAA,QAAA,eAAxB,kBAAwB,QAAA,6BAAA,QAAA,uBFiD1B,yBEjDE,WAAwB,QAAA,eAAxB,aAAwB,QAAA,iBAAxB,mBAAwB,QAAA,uBAAxB,YAAwB,QAAA,gBAAxB,YAAwB,QAAA,gBAAxB,gBAAwB,QAAA,oBAAxB,iBAAwB,QAAA,qBAAxB,WAAwB,QAAA,sBAAA,QAAA,eAAxB,kBAAwB,QAAA,6BAAA,QAAA,uBFiD1B,yBEjDE,WAAwB,QAAA,eAAxB,aAAwB,QAAA,iBAAxB,mBAAwB,QAAA,uBAAxB,YAAwB,QAAA,gBAAxB,YAAwB,QAAA,gBAAxB,gBAAwB,QAAA,oBAAxB,iBAAwB,QAAA,qBAAxB,WAAwB,QAAA,sBAAA,QAAA,eAAxB,kBAAwB,QAAA,6BAAA,QAAA,uBFiD1B,0BEjDE,WAAwB,QAAA,eAAxB,aAAwB,QAAA,iBAAxB,mBAAwB,QAAA,uBAAxB,YAAwB,QAAA,gBAAxB,YAAwB,QAAA,gBAAxB,gBAAwB,QAAA,oBAAxB,iBAAwB,QAAA,qBAAxB,WAAwB,QAAA,sBAAA,QAAA,eAAxB,kBAAwB,QAAA,6BAAA,QAAA,uBAU9B,aAEI,cAAqB,QAAA,eAArB,gBAAqB,QAAA,iBAArB,sBAAqB,QAAA,uBAArB,eAAqB,QAAA,gBAArB,eAAqB,QAAA,gBAArB,mBAAqB,QAAA,oBAArB,oBAAqB,QAAA,qBAArB,cAAqB,QAAA,sBAAA,QAAA,eAArB,qBAAqB,QAAA,6BAAA,QAAA,uBCbrB,UAAgC,mBAAA,cAAA,eAAA,cAChC,aAAgC,mBAAA,iBAAA,eAAA,iBAChC,kBAAgC,mBAAA,sBAAA,eAAA,sBAChC,qBAAgC,mBAAA,yBAAA,eAAA,yBAEhC,WAA8B,cAAA,eAAA,UAAA,eAC9B,aAA8B,cAAA,iBAAA,UAAA,iBAC9B,mBAA8B,cAAA,uBAAA,UAAA,uBAC9B,WAA8B,SAAA,EAAA,EAAA,eAAA,KAAA,EAAA,EAAA,eAC9B,aAA8B,kBAAA,YAAA,UAAA,YAC9B,aAA8B,kBAAA,YAAA,UAAA,YAC9B,eAA8B,kBAAA,YAAA,YAAA,YAC9B,eAA8B,kBAAA,YAAA,YAAA,YAE9B,uBAAoC,cAAA,gBAAA,gBAAA,qBACpC,qBAAoC,cAAA,cAAA,gBAAA,mBACpC,wBAAoC,cAAA,iBAAA,gBAAA,iBACpC,yBAAoC,cAAA,kBAAA,gBAAA,wBACpC,wBAAoC,cAAA,qBAAA,gBAAA,uBAEpC,mBAAiC,eAAA,gBAAA,YAAA,qBACjC,iBAAiC,eAAA,cAAA,YAAA,mBACjC,oBAAiC,eAAA,iBAAA,YAAA,iBACjC,sBAAiC,eAAA,mBAAA,YAAA,mBACjC,qBAAiC,eAAA,kBAAA,YAAA,kBAEjC,qBAAkC,mBAAA,gBAAA,cAAA,qBAClC,mBAAkC,mBAAA,cAAA,cAAA,mBAClC,sBAAkC,mBAAA,iBAAA,cAAA,iBAClC,uBAAkC,mBAAA,kBAAA,cAAA,wBAClC,sBAAkC,mBAAA,qBAAA,cAAA,uBAClC,uBAAkC,mBAAA,kBAAA,cAAA,kBAElC,iBAAgC,oBAAA,eAAA,WAAA,eAChC,kBAAgC,oBAAA,gBAAA,WAAA,qBAChC,gBAAgC,oBAAA,cAAA,WAAA,mBAChC,mBAAgC,oBAAA,iBAAA,WAAA,iBAChC,qBAAgC,oBAAA,mBAAA,WAAA,mBAChC,oBAAgC,oBAAA,kBAAA,WAAA,kBHYhC,yBGlDA,aAAgC,mBAAA,cAAA,eAAA,cAChC,gBAAgC,mBAAA,iBAAA,eAAA,iBAChC,qBAAgC,mBAAA,sBAAA,eAAA,sBAChC,wBAAgC,mBAAA,yBAAA,eAAA,yBAEhC,cAA8B,cAAA,eAAA,UAAA,eAC9B,gBAA8B,cAAA,iBAAA,UAAA,iBAC9B,sBAA8B,cAAA,uBAAA,UAAA,uBAC9B,cAA8B,SAAA,EAAA,EAAA,eAAA,KAAA,EAAA,EAAA,eAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAE9B,0BAAoC,cAAA,gBAAA,gBAAA,qBACpC,wBAAoC,cAAA,cAAA,gBAAA,mBACpC,2BAAoC,cAAA,iBAAA,gBAAA,iBACpC,4BAAoC,cAAA,kBAAA,gBAAA,wBACpC,2BAAoC,cAAA,qBAAA,gBAAA,uBAEpC,sBAAiC,eAAA,gBAAA,YAAA,qBACjC,oBAAiC,eAAA,cAAA,YAAA,mBACjC,uBAAiC,eAAA,iBAAA,YAAA,iBACjC,yBAAiC,eAAA,mBAAA,YAAA,mBACjC,wBAAiC,eAAA,kBAAA,YAAA,kBAEjC,wBAAkC,mBAAA,gBAAA,cAAA,qBAClC,sBAAkC,mBAAA,cAAA,cAAA,mBAClC,yBAAkC,mBAAA,iBAAA,cAAA,iBAClC,0BAAkC,mBAAA,kBAAA,cAAA,wBAClC,yBAAkC,mBAAA,qBAAA,cAAA,uBAClC,0BAAkC,mBAAA,kBAAA,cAAA,kBAElC,oBAAgC,oBAAA,eAAA,WAAA,eAChC,qBAAgC,oBAAA,gBAAA,WAAA,qBAChC,mBAAgC,oBAAA,cAAA,WAAA,mBAChC,sBAAgC,oBAAA,iBAAA,WAAA,iBAChC,wBAAgC,oBAAA,mBAAA,WAAA,mBAChC,uBAAgC,oBAAA,kBAAA,WAAA,mBHYhC,yBGlDA,aAAgC,mBAAA,cAAA,eAAA,cAChC,gBAAgC,mBAAA,iBAAA,eAAA,iBAChC,qBAAgC,mBAAA,sBAAA,eAAA,sBAChC,wBAAgC,mBAAA,yBAAA,eAAA,yBAEhC,cAA8B,cAAA,eAAA,UAAA,eAC9B,gBAA8B,cAAA,iBAAA,UAAA,iBAC9B,sBAA8B,cAAA,uBAAA,UAAA,uBAC9B,cAA8B,SAAA,EAAA,EAAA,eAAA,KAAA,EAAA,EAAA,eAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAE9B,0BAAoC,cAAA,gBAAA,gBAAA,qBACpC,wBAAoC,cAAA,cAAA,gBAAA,mBACpC,2BAAoC,cAAA,iBAAA,gBAAA,iBACpC,4BAAoC,cAAA,kBAAA,gBAAA,wBACpC,2BAAoC,cAAA,qBAAA,gBAAA,uBAEpC,sBAAiC,eAAA,gBAAA,YAAA,qBACjC,oBAAiC,eAAA,cAAA,YAAA,mBACjC,uBAAiC,eAAA,iBAAA,YAAA,iBACjC,yBAAiC,eAAA,mBAAA,YAAA,mBACjC,wBAAiC,eAAA,kBAAA,YAAA,kBAEjC,wBAAkC,mBAAA,gBAAA,cAAA,qBAClC,sBAAkC,mBAAA,cAAA,cAAA,mBAClC,yBAAkC,mBAAA,iBAAA,cAAA,iBAClC,0BAAkC,mBAAA,kBAAA,cAAA,wBAClC,yBAAkC,mBAAA,qBAAA,cAAA,uBAClC,0BAAkC,mBAAA,kBAAA,cAAA,kBAElC,oBAAgC,oBAAA,eAAA,WAAA,eAChC,qBAAgC,oBAAA,gBAAA,WAAA,qBAChC,mBAAgC,oBAAA,cAAA,WAAA,mBAChC,sBAAgC,oBAAA,iBAAA,WAAA,iBAChC,wBAAgC,oBAAA,mBAAA,WAAA,mBAChC,uBAAgC,oBAAA,kBAAA,WAAA,mBHYhC,yBGlDA,aAAgC,mBAAA,cAAA,eAAA,cAChC,gBAAgC,mBAAA,iBAAA,eAAA,iBAChC,qBAAgC,mBAAA,sBAAA,eAAA,sBAChC,wBAAgC,mBAAA,yBAAA,eAAA,yBAEhC,cAA8B,cAAA,eAAA,UAAA,eAC9B,gBAA8B,cAAA,iBAAA,UAAA,iBAC9B,sBAA8B,cAAA,uBAAA,UAAA,uBAC9B,cAA8B,SAAA,EAAA,EAAA,eAAA,KAAA,EAAA,EAAA,eAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAE9B,0BAAoC,cAAA,gBAAA,gBAAA,qBACpC,wBAAoC,cAAA,cAAA,gBAAA,mBACpC,2BAAoC,cAAA,iBAAA,gBAAA,iBACpC,4BAAoC,cAAA,kBAAA,gBAAA,wBACpC,2BAAoC,cAAA,qBAAA,gBAAA,uBAEpC,sBAAiC,eAAA,gBAAA,YAAA,qBACjC,oBAAiC,eAAA,cAAA,YAAA,mBACjC,uBAAiC,eAAA,iBAAA,YAAA,iBACjC,yBAAiC,eAAA,mBAAA,YAAA,mBACjC,wBAAiC,eAAA,kBAAA,YAAA,kBAEjC,wBAAkC,mBAAA,gBAAA,cAAA,qBAClC,sBAAkC,mBAAA,cAAA,cAAA,mBAClC,yBAAkC,mBAAA,iBAAA,cAAA,iBAClC,0BAAkC,mBAAA,kBAAA,cAAA,wBAClC,yBAAkC,mBAAA,qBAAA,cAAA,uBAClC,0BAAkC,mBAAA,kBAAA,cAAA,kBAElC,oBAAgC,oBAAA,eAAA,WAAA,eAChC,qBAAgC,oBAAA,gBAAA,WAAA,qBAChC,mBAAgC,oBAAA,cAAA,WAAA,mBAChC,sBAAgC,oBAAA,iBAAA,WAAA,iBAChC,wBAAgC,oBAAA,mBAAA,WAAA,mBAChC,uBAAgC,oBAAA,kBAAA,WAAA,mBHYhC,0BGlDA,aAAgC,mBAAA,cAAA,eAAA,cAChC,gBAAgC,mBAAA,iBAAA,eAAA,iBAChC,qBAAgC,mBAAA,sBAAA,eAAA,sBAChC,wBAAgC,mBAAA,yBAAA,eAAA,yBAEhC,cAA8B,cAAA,eAAA,UAAA,eAC9B,gBAA8B,cAAA,iBAAA,UAAA,iBAC9B,sBAA8B,cAAA,uBAAA,UAAA,uBAC9B,cAA8B,SAAA,EAAA,EAAA,eAAA,KAAA,EAAA,EAAA,eAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAE9B,0BAAoC,cAAA,gBAAA,gBAAA,qBACpC,wBAAoC,cAAA,cAAA,gBAAA,mBACpC,2BAAoC,cAAA,iBAAA,gBAAA,iBACpC,4BAAoC,cAAA,kBAAA,gBAAA,wBACpC,2BAAoC,cAAA,qBAAA,gBAAA,uBAEpC,sBAAiC,eAAA,gBAAA,YAAA,qBACjC,oBAAiC,eAAA,cAAA,YAAA,mBACjC,uBAAiC,eAAA,iBAAA,YAAA,iBACjC,yBAAiC,eAAA,mBAAA,YAAA,mBACjC,wBAAiC,eAAA,kBAAA,YAAA,kBAEjC,wBAAkC,mBAAA,gBAAA,cAAA,qBAClC,sBAAkC,mBAAA,cAAA,cAAA,mBAClC,yBAAkC,mBAAA,iBAAA,cAAA,iBAClC,0BAAkC,mBAAA,kBAAA,cAAA,wBAClC,yBAAkC,mBAAA,qBAAA,cAAA,uBAClC,0BAAkC,mBAAA,kBAAA,cAAA,kBAElC,oBAAgC,oBAAA,eAAA,WAAA,eAChC,qBAAgC,oBAAA,gBAAA,WAAA,qBAChC,mBAAgC,oBAAA,cAAA,WAAA,mBAChC,sBAAgC,oBAAA,iBAAA,WAAA,iBAChC,wBAAgC,oBAAA,mBAAA,WAAA,mBAChC,uBAAgC,oBAAA,kBAAA,WAAA,mBCtC5B,KAAgC,OAAA,YAChC,MP62DR,MO32DU,WAAA,YAEF,MP82DR,MO52DU,aAAA,YAEF,MP+2DR,MO72DU,cAAA,YAEF,MPg3DR,MO92DU,YAAA,YAfF,KAAgC,OAAA,iBAChC,MPq4DR,MOn4DU,WAAA,iBAEF,MPs4DR,MOp4DU,aAAA,iBAEF,MPu4DR,MOr4DU,cAAA,iBAEF,MPw4DR,MOt4DU,YAAA,iBAfF,KAAgC,OAAA,gBAChC,MP65DR,MO35DU,WAAA,gBAEF,MP85DR,MO55DU,aAAA,gBAEF,MP+5DR,MO75DU,cAAA,gBAEF,MPg6DR,MO95DU,YAAA,gBAfF,KAAgC,OAAA,eAChC,MPq7DR,MOn7DU,WAAA,eAEF,MPs7DR,MOp7DU,aAAA,eAEF,MPu7DR,MOr7DU,cAAA,eAEF,MPw7DR,MOt7DU,YAAA,eAfF,KAAgC,OAAA,iBAChC,MP68DR,MO38DU,WAAA,iBAEF,MP88DR,MO58DU,aAAA,iBAEF,MP+8DR,MO78DU,cAAA,iBAEF,MPg9DR,MO98DU,YAAA,iBAfF,KAAgC,OAAA,eAChC,MPq+DR,MOn+DU,WAAA,eAEF,MPs+DR,MOp+DU,aAAA,eAEF,MPu+DR,MOr+DU,cAAA,eAEF,MPw+DR,MOt+DU,YAAA,eAfF,KAAgC,QAAA,YAChC,MP6/DR,MO3/DU,YAAA,YAEF,MP8/DR,MO5/DU,cAAA,YAEF,MP+/DR,MO7/DU,eAAA,YAEF,MPggER,MO9/DU,aAAA,YAfF,KAAgC,QAAA,iBAChC,MPqhER,MOnhEU,YAAA,iBAEF,MPshER,MOphEU,cAAA,iBAEF,MPuhER,MOrhEU,eAAA,iBAEF,MPwhER,MOthEU,aAAA,iBAfF,KAAgC,QAAA,gBAChC,MP6iER,MO3iEU,YAAA,gBAEF,MP8iER,MO5iEU,cAAA,gBAEF,MP+iER,MO7iEU,eAAA,gBAEF,MPgjER,MO9iEU,aAAA,gBAfF,KAAgC,QAAA,eAChC,MPqkER,MOnkEU,YAAA,eAEF,MPskER,MOpkEU,cAAA,eAEF,MPukER,MOrkEU,eAAA,eAEF,MPwkER,MOtkEU,aAAA,eAfF,KAAgC,QAAA,iBAChC,MP6lER,MO3lEU,YAAA,iBAEF,MP8lER,MO5lEU,cAAA,iBAEF,MP+lER,MO7lEU,eAAA,iBAEF,MPgmER,MO9lEU,aAAA,iBAfF,KAAgC,QAAA,eAChC,MPqnER,MOnnEU,YAAA,eAEF,MPsnER,MOpnEU,cAAA,eAEF,MPunER,MOrnEU,eAAA,eAEF,MPwnER,MOtnEU,aAAA,eAQF,MAAwB,OAAA,kBACxB,OPsnER,OOpnEU,WAAA,kBAEF,OPunER,OOrnEU,aAAA,kBAEF,OPwnER,OOtnEU,cAAA,kBAEF,OPynER,OOvnEU,YAAA,kBAfF,MAAwB,OAAA,iBACxB,OP8oER,OO5oEU,WAAA,iBAEF,OP+oER,OO7oEU,aAAA,iBAEF,OPgpER,OO9oEU,cAAA,iBAEF,OPipER,OO/oEU,YAAA,iBAfF,MAAwB,OAAA,gBACxB,OPsqER,OOpqEU,WAAA,gBAEF,OPuqER,OOrqEU,aAAA,gBAEF,OPwqER,OOtqEU,cAAA,gBAEF,OPyqER,OOvqEU,YAAA,gBAfF,MAAwB,OAAA,kBACxB,OP8rER,OO5rEU,WAAA,kBAEF,OP+rER,OO7rEU,aAAA,kBAEF,OPgsER,OO9rEU,cAAA,kBAEF,OPisER,OO/rEU,YAAA,kBAfF,MAAwB,OAAA,gBACxB,OPstER,OOptEU,WAAA,gBAEF,OPutER,OOrtEU,aAAA,gBAEF,OPwtER,OOttEU,cAAA,gBAEF,OPytER,OOvtEU,YAAA,gBAMN,QAAmB,OAAA,eACnB,SPytEJ,SOvtEM,WAAA,eAEF,SP0tEJ,SOxtEM,aAAA,eAEF,SP2tEJ,SOztEM,cAAA,eAEF,SP4tEJ,SO1tEM,YAAA,eJTF,yBIlDI,QAAgC,OAAA,YAChC,SP6xEN,SO3xEQ,WAAA,YAEF,SP6xEN,SO3xEQ,aAAA,YAEF,SP6xEN,SO3xEQ,cAAA,YAEF,SP6xEN,SO3xEQ,YAAA,YAfF,QAAgC,OAAA,iBAChC,SPgzEN,SO9yEQ,WAAA,iBAEF,SPgzEN,SO9yEQ,aAAA,iBAEF,SPgzEN,SO9yEQ,cAAA,iBAEF,SPgzEN,SO9yEQ,YAAA,iBAfF,QAAgC,OAAA,gBAChC,SPm0EN,SOj0EQ,WAAA,gBAEF,SPm0EN,SOj0EQ,aAAA,gBAEF,SPm0EN,SOj0EQ,cAAA,gBAEF,SPm0EN,SOj0EQ,YAAA,gBAfF,QAAgC,OAAA,eAChC,SPs1EN,SOp1EQ,WAAA,eAEF,SPs1EN,SOp1EQ,aAAA,eAEF,SPs1EN,SOp1EQ,cAAA,eAEF,SPs1EN,SOp1EQ,YAAA,eAfF,QAAgC,OAAA,iBAChC,SPy2EN,SOv2EQ,WAAA,iBAEF,SPy2EN,SOv2EQ,aAAA,iBAEF,SPy2EN,SOv2EQ,cAAA,iBAEF,SPy2EN,SOv2EQ,YAAA,iBAfF,QAAgC,OAAA,eAChC,SP43EN,SO13EQ,WAAA,eAEF,SP43EN,SO13EQ,aAAA,eAEF,SP43EN,SO13EQ,cAAA,eAEF,SP43EN,SO13EQ,YAAA,eAfF,QAAgC,QAAA,YAChC,SP+4EN,SO74EQ,YAAA,YAEF,SP+4EN,SO74EQ,cAAA,YAEF,SP+4EN,SO74EQ,eAAA,YAEF,SP+4EN,SO74EQ,aAAA,YAfF,QAAgC,QAAA,iBAChC,SPk6EN,SOh6EQ,YAAA,iBAEF,SPk6EN,SOh6EQ,cAAA,iBAEF,SPk6EN,SOh6EQ,eAAA,iBAEF,SPk6EN,SOh6EQ,aAAA,iBAfF,QAAgC,QAAA,gBAChC,SPq7EN,SOn7EQ,YAAA,gBAEF,SPq7EN,SOn7EQ,cAAA,gBAEF,SPq7EN,SOn7EQ,eAAA,gBAEF,SPq7EN,SOn7EQ,aAAA,gBAfF,QAAgC,QAAA,eAChC,SPw8EN,SOt8EQ,YAAA,eAEF,SPw8EN,SOt8EQ,cAAA,eAEF,SPw8EN,SOt8EQ,eAAA,eAEF,SPw8EN,SOt8EQ,aAAA,eAfF,QAAgC,QAAA,iBAChC,SP29EN,SOz9EQ,YAAA,iBAEF,SP29EN,SOz9EQ,cAAA,iBAEF,SP29EN,SOz9EQ,eAAA,iBAEF,SP29EN,SOz9EQ,aAAA,iBAfF,QAAgC,QAAA,eAChC,SP8+EN,SO5+EQ,YAAA,eAEF,SP8+EN,SO5+EQ,cAAA,eAEF,SP8+EN,SO5+EQ,eAAA,eAEF,SP8+EN,SO5+EQ,aAAA,eAQF,SAAwB,OAAA,kBACxB,UP0+EN,UOx+EQ,WAAA,kBAEF,UP0+EN,UOx+EQ,aAAA,kBAEF,UP0+EN,UOx+EQ,cAAA,kBAEF,UP0+EN,UOx+EQ,YAAA,kBAfF,SAAwB,OAAA,iBACxB,UP6/EN,UO3/EQ,WAAA,iBAEF,UP6/EN,UO3/EQ,aAAA,iBAEF,UP6/EN,UO3/EQ,cAAA,iBAEF,UP6/EN,UO3/EQ,YAAA,iBAfF,SAAwB,OAAA,gBACxB,UPghFN,UO9gFQ,WAAA,gBAEF,UPghFN,UO9gFQ,aAAA,gBAEF,UPghFN,UO9gFQ,cAAA,gBAEF,UPghFN,UO9gFQ,YAAA,gBAfF,SAAwB,OAAA,kBACxB,UPmiFN,UOjiFQ,WAAA,kBAEF,UPmiFN,UOjiFQ,aAAA,kBAEF,UPmiFN,UOjiFQ,cAAA,kBAEF,UPmiFN,UOjiFQ,YAAA,kBAfF,SAAwB,OAAA,gBACxB,UPsjFN,UOpjFQ,WAAA,gBAEF,UPsjFN,UOpjFQ,aAAA,gBAEF,UPsjFN,UOpjFQ,cAAA,gBAEF,UPsjFN,UOpjFQ,YAAA,gBAMN,WAAmB,OAAA,eACnB,YPojFF,YOljFI,WAAA,eAEF,YPojFF,YOljFI,aAAA,eAEF,YPojFF,YOljFI,cAAA,eAEF,YPojFF,YOljFI,YAAA,gBJTF,yBIlDI,QAAgC,OAAA,YAChC,SPsnFN,SOpnFQ,WAAA,YAEF,SPsnFN,SOpnFQ,aAAA,YAEF,SPsnFN,SOpnFQ,cAAA,YAEF,SPsnFN,SOpnFQ,YAAA,YAfF,QAAgC,OAAA,iBAChC,SPyoFN,SOvoFQ,WAAA,iBAEF,SPyoFN,SOvoFQ,aAAA,iBAEF,SPyoFN,SOvoFQ,cAAA,iBAEF,SPyoFN,SOvoFQ,YAAA,iBAfF,QAAgC,OAAA,gBAChC,SP4pFN,SO1pFQ,WAAA,gBAEF,SP4pFN,SO1pFQ,aAAA,gBAEF,SP4pFN,SO1pFQ,cAAA,gBAEF,SP4pFN,SO1pFQ,YAAA,gBAfF,QAAgC,OAAA,eAChC,SP+qFN,SO7qFQ,WAAA,eAEF,SP+qFN,SO7qFQ,aAAA,eAEF,SP+qFN,SO7qFQ,cAAA,eAEF,SP+qFN,SO7qFQ,YAAA,eAfF,QAAgC,OAAA,iBAChC,SPksFN,SOhsFQ,WAAA,iBAEF,SPksFN,SOhsFQ,aAAA,iBAEF,SPksFN,SOhsFQ,cAAA,iBAEF,SPksFN,SOhsFQ,YAAA,iBAfF,QAAgC,OAAA,eAChC,SPqtFN,SOntFQ,WAAA,eAEF,SPqtFN,SOntFQ,aAAA,eAEF,SPqtFN,SOntFQ,cAAA,eAEF,SPqtFN,SOntFQ,YAAA,eAfF,QAAgC,QAAA,YAChC,SPwuFN,SOtuFQ,YAAA,YAEF,SPwuFN,SOtuFQ,cAAA,YAEF,SPwuFN,SOtuFQ,eAAA,YAEF,SPwuFN,SOtuFQ,aAAA,YAfF,QAAgC,QAAA,iBAChC,SP2vFN,SOzvFQ,YAAA,iBAEF,SP2vFN,SOzvFQ,cAAA,iBAEF,SP2vFN,SOzvFQ,eAAA,iBAEF,SP2vFN,SOzvFQ,aAAA,iBAfF,QAAgC,QAAA,gBAChC,SP8wFN,SO5wFQ,YAAA,gBAEF,SP8wFN,SO5wFQ,cAAA,gBAEF,SP8wFN,SO5wFQ,eAAA,gBAEF,SP8wFN,SO5wFQ,aAAA,gBAfF,QAAgC,QAAA,eAChC,SPiyFN,SO/xFQ,YAAA,eAEF,SPiyFN,SO/xFQ,cAAA,eAEF,SPiyFN,SO/xFQ,eAAA,eAEF,SPiyFN,SO/xFQ,aAAA,eAfF,QAAgC,QAAA,iBAChC,SPozFN,SOlzFQ,YAAA,iBAEF,SPozFN,SOlzFQ,cAAA,iBAEF,SPozFN,SOlzFQ,eAAA,iBAEF,SPozFN,SOlzFQ,aAAA,iBAfF,QAAgC,QAAA,eAChC,SPu0FN,SOr0FQ,YAAA,eAEF,SPu0FN,SOr0FQ,cAAA,eAEF,SPu0FN,SOr0FQ,eAAA,eAEF,SPu0FN,SOr0FQ,aAAA,eAQF,SAAwB,OAAA,kBACxB,UPm0FN,UOj0FQ,WAAA,kBAEF,UPm0FN,UOj0FQ,aAAA,kBAEF,UPm0FN,UOj0FQ,cAAA,kBAEF,UPm0FN,UOj0FQ,YAAA,kBAfF,SAAwB,OAAA,iBACxB,UPs1FN,UOp1FQ,WAAA,iBAEF,UPs1FN,UOp1FQ,aAAA,iBAEF,UPs1FN,UOp1FQ,cAAA,iBAEF,UPs1FN,UOp1FQ,YAAA,iBAfF,SAAwB,OAAA,gBACxB,UPy2FN,UOv2FQ,WAAA,gBAEF,UPy2FN,UOv2FQ,aAAA,gBAEF,UPy2FN,UOv2FQ,cAAA,gBAEF,UPy2FN,UOv2FQ,YAAA,gBAfF,SAAwB,OAAA,kBACxB,UP43FN,UO13FQ,WAAA,kBAEF,UP43FN,UO13FQ,aAAA,kBAEF,UP43FN,UO13FQ,cAAA,kBAEF,UP43FN,UO13FQ,YAAA,kBAfF,SAAwB,OAAA,gBACxB,UP+4FN,UO74FQ,WAAA,gBAEF,UP+4FN,UO74FQ,aAAA,gBAEF,UP+4FN,UO74FQ,cAAA,gBAEF,UP+4FN,UO74FQ,YAAA,gBAMN,WAAmB,OAAA,eACnB,YP64FF,YO34FI,WAAA,eAEF,YP64FF,YO34FI,aAAA,eAEF,YP64FF,YO34FI,cAAA,eAEF,YP64FF,YO34FI,YAAA,gBJTF,yBIlDI,QAAgC,OAAA,YAChC,SP+8FN,SO78FQ,WAAA,YAEF,SP+8FN,SO78FQ,aAAA,YAEF,SP+8FN,SO78FQ,cAAA,YAEF,SP+8FN,SO78FQ,YAAA,YAfF,QAAgC,OAAA,iBAChC,SPk+FN,SOh+FQ,WAAA,iBAEF,SPk+FN,SOh+FQ,aAAA,iBAEF,SPk+FN,SOh+FQ,cAAA,iBAEF,SPk+FN,SOh+FQ,YAAA,iBAfF,QAAgC,OAAA,gBAChC,SPq/FN,SOn/FQ,WAAA,gBAEF,SPq/FN,SOn/FQ,aAAA,gBAEF,SPq/FN,SOn/FQ,cAAA,gBAEF,SPq/FN,SOn/FQ,YAAA,gBAfF,QAAgC,OAAA,eAChC,SPwgGN,SOtgGQ,WAAA,eAEF,SPwgGN,SOtgGQ,aAAA,eAEF,SPwgGN,SOtgGQ,cAAA,eAEF,SPwgGN,SOtgGQ,YAAA,eAfF,QAAgC,OAAA,iBAChC,SP2hGN,SOzhGQ,WAAA,iBAEF,SP2hGN,SOzhGQ,aAAA,iBAEF,SP2hGN,SOzhGQ,cAAA,iBAEF,SP2hGN,SOzhGQ,YAAA,iBAfF,QAAgC,OAAA,eAChC,SP8iGN,SO5iGQ,WAAA,eAEF,SP8iGN,SO5iGQ,aAAA,eAEF,SP8iGN,SO5iGQ,cAAA,eAEF,SP8iGN,SO5iGQ,YAAA,eAfF,QAAgC,QAAA,YAChC,SPikGN,SO/jGQ,YAAA,YAEF,SPikGN,SO/jGQ,cAAA,YAEF,SPikGN,SO/jGQ,eAAA,YAEF,SPikGN,SO/jGQ,aAAA,YAfF,QAAgC,QAAA,iBAChC,SPolGN,SOllGQ,YAAA,iBAEF,SPolGN,SOllGQ,cAAA,iBAEF,SPolGN,SOllGQ,eAAA,iBAEF,SPolGN,SOllGQ,aAAA,iBAfF,QAAgC,QAAA,gBAChC,SPumGN,SOrmGQ,YAAA,gBAEF,SPumGN,SOrmGQ,cAAA,gBAEF,SPumGN,SOrmGQ,eAAA,gBAEF,SPumGN,SOrmGQ,aAAA,gBAfF,QAAgC,QAAA,eAChC,SP0nGN,SOxnGQ,YAAA,eAEF,SP0nGN,SOxnGQ,cAAA,eAEF,SP0nGN,SOxnGQ,eAAA,eAEF,SP0nGN,SOxnGQ,aAAA,eAfF,QAAgC,QAAA,iBAChC,SP6oGN,SO3oGQ,YAAA,iBAEF,SP6oGN,SO3oGQ,cAAA,iBAEF,SP6oGN,SO3oGQ,eAAA,iBAEF,SP6oGN,SO3oGQ,aAAA,iBAfF,QAAgC,QAAA,eAChC,SPgqGN,SO9pGQ,YAAA,eAEF,SPgqGN,SO9pGQ,cAAA,eAEF,SPgqGN,SO9pGQ,eAAA,eAEF,SPgqGN,SO9pGQ,aAAA,eAQF,SAAwB,OAAA,kBACxB,UP4pGN,UO1pGQ,WAAA,kBAEF,UP4pGN,UO1pGQ,aAAA,kBAEF,UP4pGN,UO1pGQ,cAAA,kBAEF,UP4pGN,UO1pGQ,YAAA,kBAfF,SAAwB,OAAA,iBACxB,UP+qGN,UO7qGQ,WAAA,iBAEF,UP+qGN,UO7qGQ,aAAA,iBAEF,UP+qGN,UO7qGQ,cAAA,iBAEF,UP+qGN,UO7qGQ,YAAA,iBAfF,SAAwB,OAAA,gBACxB,UPksGN,UOhsGQ,WAAA,gBAEF,UPksGN,UOhsGQ,aAAA,gBAEF,UPksGN,UOhsGQ,cAAA,gBAEF,UPksGN,UOhsGQ,YAAA,gBAfF,SAAwB,OAAA,kBACxB,UPqtGN,UOntGQ,WAAA,kBAEF,UPqtGN,UOntGQ,aAAA,kBAEF,UPqtGN,UOntGQ,cAAA,kBAEF,UPqtGN,UOntGQ,YAAA,kBAfF,SAAwB,OAAA,gBACxB,UPwuGN,UOtuGQ,WAAA,gBAEF,UPwuGN,UOtuGQ,aAAA,gBAEF,UPwuGN,UOtuGQ,cAAA,gBAEF,UPwuGN,UOtuGQ,YAAA,gBAMN,WAAmB,OAAA,eACnB,YPsuGF,YOpuGI,WAAA,eAEF,YPsuGF,YOpuGI,aAAA,eAEF,YPsuGF,YOpuGI,cAAA,eAEF,YPsuGF,YOpuGI,YAAA,gBJTF,0BIlDI,QAAgC,OAAA,YAChC,SPwyGN,SOtyGQ,WAAA,YAEF,SPwyGN,SOtyGQ,aAAA,YAEF,SPwyGN,SOtyGQ,cAAA,YAEF,SPwyGN,SOtyGQ,YAAA,YAfF,QAAgC,OAAA,iBAChC,SP2zGN,SOzzGQ,WAAA,iBAEF,SP2zGN,SOzzGQ,aAAA,iBAEF,SP2zGN,SOzzGQ,cAAA,iBAEF,SP2zGN,SOzzGQ,YAAA,iBAfF,QAAgC,OAAA,gBAChC,SP80GN,SO50GQ,WAAA,gBAEF,SP80GN,SO50GQ,aAAA,gBAEF,SP80GN,SO50GQ,cAAA,gBAEF,SP80GN,SO50GQ,YAAA,gBAfF,QAAgC,OAAA,eAChC,SPi2GN,SO/1GQ,WAAA,eAEF,SPi2GN,SO/1GQ,aAAA,eAEF,SPi2GN,SO/1GQ,cAAA,eAEF,SPi2GN,SO/1GQ,YAAA,eAfF,QAAgC,OAAA,iBAChC,SPo3GN,SOl3GQ,WAAA,iBAEF,SPo3GN,SOl3GQ,aAAA,iBAEF,SPo3GN,SOl3GQ,cAAA,iBAEF,SPo3GN,SOl3GQ,YAAA,iBAfF,QAAgC,OAAA,eAChC,SPu4GN,SOr4GQ,WAAA,eAEF,SPu4GN,SOr4GQ,aAAA,eAEF,SPu4GN,SOr4GQ,cAAA,eAEF,SPu4GN,SOr4GQ,YAAA,eAfF,QAAgC,QAAA,YAChC,SP05GN,SOx5GQ,YAAA,YAEF,SP05GN,SOx5GQ,cAAA,YAEF,SP05GN,SOx5GQ,eAAA,YAEF,SP05GN,SOx5GQ,aAAA,YAfF,QAAgC,QAAA,iBAChC,SP66GN,SO36GQ,YAAA,iBAEF,SP66GN,SO36GQ,cAAA,iBAEF,SP66GN,SO36GQ,eAAA,iBAEF,SP66GN,SO36GQ,aAAA,iBAfF,QAAgC,QAAA,gBAChC,SPg8GN,SO97GQ,YAAA,gBAEF,SPg8GN,SO97GQ,cAAA,gBAEF,SPg8GN,SO97GQ,eAAA,gBAEF,SPg8GN,SO97GQ,aAAA,gBAfF,QAAgC,QAAA,eAChC,SPm9GN,SOj9GQ,YAAA,eAEF,SPm9GN,SOj9GQ,cAAA,eAEF,SPm9GN,SOj9GQ,eAAA,eAEF,SPm9GN,SOj9GQ,aAAA,eAfF,QAAgC,QAAA,iBAChC,SPs+GN,SOp+GQ,YAAA,iBAEF,SPs+GN,SOp+GQ,cAAA,iBAEF,SPs+GN,SOp+GQ,eAAA,iBAEF,SPs+GN,SOp+GQ,aAAA,iBAfF,QAAgC,QAAA,eAChC,SPy/GN,SOv/GQ,YAAA,eAEF,SPy/GN,SOv/GQ,cAAA,eAEF,SPy/GN,SOv/GQ,eAAA,eAEF,SPy/GN,SOv/GQ,aAAA,eAQF,SAAwB,OAAA,kBACxB,UPq/GN,UOn/GQ,WAAA,kBAEF,UPq/GN,UOn/GQ,aAAA,kBAEF,UPq/GN,UOn/GQ,cAAA,kBAEF,UPq/GN,UOn/GQ,YAAA,kBAfF,SAAwB,OAAA,iBACxB,UPwgHN,UOtgHQ,WAAA,iBAEF,UPwgHN,UOtgHQ,aAAA,iBAEF,UPwgHN,UOtgHQ,cAAA,iBAEF,UPwgHN,UOtgHQ,YAAA,iBAfF,SAAwB,OAAA,gBACxB,UP2hHN,UOzhHQ,WAAA,gBAEF,UP2hHN,UOzhHQ,aAAA,gBAEF,UP2hHN,UOzhHQ,cAAA,gBAEF,UP2hHN,UOzhHQ,YAAA,gBAfF,SAAwB,OAAA,kBACxB,UP8iHN,UO5iHQ,WAAA,kBAEF,UP8iHN,UO5iHQ,aAAA,kBAEF,UP8iHN,UO5iHQ,cAAA,kBAEF,UP8iHN,UO5iHQ,YAAA,kBAfF,SAAwB,OAAA,gBACxB,UPikHN,UO/jHQ,WAAA,gBAEF,UPikHN,UO/jHQ,aAAA,gBAEF,UPikHN,UO/jHQ,cAAA,gBAEF,UPikHN,UO/jHQ,YAAA,gBAMN,WAAmB,OAAA,eACnB,YP+jHF,YO7jHI,WAAA,eAEF,YP+jHF,YO7jHI,aAAA,eAEF,YP+jHF,YO7jHI,cAAA,eAEF,YP+jHF,YO7jHI,YAAA","sourcesContent":["/*!\n * Bootstrap Grid v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n@import \"functions\";\n@import \"variables\";\n\n@import \"mixins/breakpoints\";\n@import \"mixins/grid-framework\";\n@import \"mixins/grid\";\n\n@import \"grid\";\n@import \"utilities/display\";\n@import \"utilities/flex\";\n@import \"utilities/spacing\";\n","/*!\n * Bootstrap Grid v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n.container {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n@media (min-width: 576px) {\n .container {\n max-width: 540px;\n }\n}\n\n@media (min-width: 768px) {\n .container {\n max-width: 720px;\n }\n}\n\n@media (min-width: 992px) {\n .container {\n max-width: 960px;\n }\n}\n\n@media (min-width: 1200px) {\n .container {\n max-width: 1140px;\n }\n}\n\n.container-fluid {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n.row {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-wrap: wrap;\n flex-wrap: wrap;\n margin-right: -15px;\n margin-left: -15px;\n}\n\n.no-gutters {\n margin-right: 0;\n margin-left: 0;\n}\n\n.no-gutters > .col,\n.no-gutters > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n}\n\n.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,\n.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,\n.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,\n.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,\n.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,\n.col-xl-auto {\n position: relative;\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n}\n\n.col {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n}\n\n.col-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n}\n\n.col-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n}\n\n.col-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n}\n\n.col-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n}\n\n.col-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n}\n\n.col-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n}\n\n.col-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n}\n\n.col-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n}\n\n.col-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n}\n\n.col-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n}\n\n.col-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n}\n\n.col-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n}\n\n.col-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n}\n\n.order-first {\n -ms-flex-order: -1;\n order: -1;\n}\n\n.order-last {\n -ms-flex-order: 13;\n order: 13;\n}\n\n.order-0 {\n -ms-flex-order: 0;\n order: 0;\n}\n\n.order-1 {\n -ms-flex-order: 1;\n order: 1;\n}\n\n.order-2 {\n -ms-flex-order: 2;\n order: 2;\n}\n\n.order-3 {\n -ms-flex-order: 3;\n order: 3;\n}\n\n.order-4 {\n -ms-flex-order: 4;\n order: 4;\n}\n\n.order-5 {\n -ms-flex-order: 5;\n order: 5;\n}\n\n.order-6 {\n -ms-flex-order: 6;\n order: 6;\n}\n\n.order-7 {\n -ms-flex-order: 7;\n order: 7;\n}\n\n.order-8 {\n -ms-flex-order: 8;\n order: 8;\n}\n\n.order-9 {\n -ms-flex-order: 9;\n order: 9;\n}\n\n.order-10 {\n -ms-flex-order: 10;\n order: 10;\n}\n\n.order-11 {\n -ms-flex-order: 11;\n order: 11;\n}\n\n.order-12 {\n -ms-flex-order: 12;\n order: 12;\n}\n\n.offset-1 {\n margin-left: 8.333333%;\n}\n\n.offset-2 {\n margin-left: 16.666667%;\n}\n\n.offset-3 {\n margin-left: 25%;\n}\n\n.offset-4 {\n margin-left: 33.333333%;\n}\n\n.offset-5 {\n margin-left: 41.666667%;\n}\n\n.offset-6 {\n margin-left: 50%;\n}\n\n.offset-7 {\n margin-left: 58.333333%;\n}\n\n.offset-8 {\n margin-left: 66.666667%;\n}\n\n.offset-9 {\n margin-left: 75%;\n}\n\n.offset-10 {\n margin-left: 83.333333%;\n}\n\n.offset-11 {\n margin-left: 91.666667%;\n}\n\n@media (min-width: 576px) {\n .col-sm {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-sm-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-sm-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-sm-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-sm-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-sm-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-sm-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-sm-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-sm-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-sm-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-sm-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-sm-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-sm-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-sm-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-sm-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-sm-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-sm-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-sm-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-sm-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-sm-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-sm-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-sm-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-sm-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-sm-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-sm-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-sm-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-sm-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-sm-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-sm-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-sm-0 {\n margin-left: 0;\n }\n .offset-sm-1 {\n margin-left: 8.333333%;\n }\n .offset-sm-2 {\n margin-left: 16.666667%;\n }\n .offset-sm-3 {\n margin-left: 25%;\n }\n .offset-sm-4 {\n margin-left: 33.333333%;\n }\n .offset-sm-5 {\n margin-left: 41.666667%;\n }\n .offset-sm-6 {\n margin-left: 50%;\n }\n .offset-sm-7 {\n margin-left: 58.333333%;\n }\n .offset-sm-8 {\n margin-left: 66.666667%;\n }\n .offset-sm-9 {\n margin-left: 75%;\n }\n .offset-sm-10 {\n margin-left: 83.333333%;\n }\n .offset-sm-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 768px) {\n .col-md {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-md-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-md-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-md-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-md-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-md-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-md-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-md-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-md-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-md-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-md-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-md-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-md-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-md-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-md-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-md-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-md-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-md-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-md-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-md-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-md-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-md-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-md-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-md-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-md-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-md-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-md-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-md-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-md-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-md-0 {\n margin-left: 0;\n }\n .offset-md-1 {\n margin-left: 8.333333%;\n }\n .offset-md-2 {\n margin-left: 16.666667%;\n }\n .offset-md-3 {\n margin-left: 25%;\n }\n .offset-md-4 {\n margin-left: 33.333333%;\n }\n .offset-md-5 {\n margin-left: 41.666667%;\n }\n .offset-md-6 {\n margin-left: 50%;\n }\n .offset-md-7 {\n margin-left: 58.333333%;\n }\n .offset-md-8 {\n margin-left: 66.666667%;\n }\n .offset-md-9 {\n margin-left: 75%;\n }\n .offset-md-10 {\n margin-left: 83.333333%;\n }\n .offset-md-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 992px) {\n .col-lg {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-lg-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-lg-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-lg-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-lg-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-lg-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-lg-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-lg-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-lg-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-lg-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-lg-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-lg-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-lg-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-lg-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-lg-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-lg-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-lg-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-lg-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-lg-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-lg-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-lg-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-lg-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-lg-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-lg-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-lg-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-lg-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-lg-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-lg-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-lg-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-lg-0 {\n margin-left: 0;\n }\n .offset-lg-1 {\n margin-left: 8.333333%;\n }\n .offset-lg-2 {\n margin-left: 16.666667%;\n }\n .offset-lg-3 {\n margin-left: 25%;\n }\n .offset-lg-4 {\n margin-left: 33.333333%;\n }\n .offset-lg-5 {\n margin-left: 41.666667%;\n }\n .offset-lg-6 {\n margin-left: 50%;\n }\n .offset-lg-7 {\n margin-left: 58.333333%;\n }\n .offset-lg-8 {\n margin-left: 66.666667%;\n }\n .offset-lg-9 {\n margin-left: 75%;\n }\n .offset-lg-10 {\n margin-left: 83.333333%;\n }\n .offset-lg-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 1200px) {\n .col-xl {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-xl-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-xl-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-xl-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-xl-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-xl-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-xl-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-xl-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-xl-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-xl-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-xl-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-xl-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-xl-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-xl-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-xl-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-xl-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-xl-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-xl-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-xl-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-xl-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-xl-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-xl-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-xl-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-xl-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-xl-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-xl-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-xl-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-xl-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-xl-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-xl-0 {\n margin-left: 0;\n }\n .offset-xl-1 {\n margin-left: 8.333333%;\n }\n .offset-xl-2 {\n margin-left: 16.666667%;\n }\n .offset-xl-3 {\n margin-left: 25%;\n }\n .offset-xl-4 {\n margin-left: 33.333333%;\n }\n .offset-xl-5 {\n margin-left: 41.666667%;\n }\n .offset-xl-6 {\n margin-left: 50%;\n }\n .offset-xl-7 {\n margin-left: 58.333333%;\n }\n .offset-xl-8 {\n margin-left: 66.666667%;\n }\n .offset-xl-9 {\n margin-left: 75%;\n }\n .offset-xl-10 {\n margin-left: 83.333333%;\n }\n .offset-xl-11 {\n margin-left: 91.666667%;\n }\n}\n\n.d-none {\n display: none !important;\n}\n\n.d-inline {\n display: inline !important;\n}\n\n.d-inline-block {\n display: inline-block !important;\n}\n\n.d-block {\n display: block !important;\n}\n\n.d-table {\n display: table !important;\n}\n\n.d-table-row {\n display: table-row !important;\n}\n\n.d-table-cell {\n display: table-cell !important;\n}\n\n.d-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n}\n\n.d-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n}\n\n@media (min-width: 576px) {\n .d-sm-none {\n display: none !important;\n }\n .d-sm-inline {\n display: inline !important;\n }\n .d-sm-inline-block {\n display: inline-block !important;\n }\n .d-sm-block {\n display: block !important;\n }\n .d-sm-table {\n display: table !important;\n }\n .d-sm-table-row {\n display: table-row !important;\n }\n .d-sm-table-cell {\n display: table-cell !important;\n }\n .d-sm-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-sm-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 768px) {\n .d-md-none {\n display: none !important;\n }\n .d-md-inline {\n display: inline !important;\n }\n .d-md-inline-block {\n display: inline-block !important;\n }\n .d-md-block {\n display: block !important;\n }\n .d-md-table {\n display: table !important;\n }\n .d-md-table-row {\n display: table-row !important;\n }\n .d-md-table-cell {\n display: table-cell !important;\n }\n .d-md-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-md-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 992px) {\n .d-lg-none {\n display: none !important;\n }\n .d-lg-inline {\n display: inline !important;\n }\n .d-lg-inline-block {\n display: inline-block !important;\n }\n .d-lg-block {\n display: block !important;\n }\n .d-lg-table {\n display: table !important;\n }\n .d-lg-table-row {\n display: table-row !important;\n }\n .d-lg-table-cell {\n display: table-cell !important;\n }\n .d-lg-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-lg-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 1200px) {\n .d-xl-none {\n display: none !important;\n }\n .d-xl-inline {\n display: inline !important;\n }\n .d-xl-inline-block {\n display: inline-block !important;\n }\n .d-xl-block {\n display: block !important;\n }\n .d-xl-table {\n display: table !important;\n }\n .d-xl-table-row {\n display: table-row !important;\n }\n .d-xl-table-cell {\n display: table-cell !important;\n }\n .d-xl-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-xl-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media print {\n .d-print-none {\n display: none !important;\n }\n .d-print-inline {\n display: inline !important;\n }\n .d-print-inline-block {\n display: inline-block !important;\n }\n .d-print-block {\n display: block !important;\n }\n .d-print-table {\n display: table !important;\n }\n .d-print-table-row {\n display: table-row !important;\n }\n .d-print-table-cell {\n display: table-cell !important;\n }\n .d-print-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-print-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n.flex-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n}\n\n.flex-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n}\n\n.flex-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n}\n\n.flex-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n}\n\n.flex-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n}\n\n.flex-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n}\n\n.flex-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n}\n\n.flex-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n}\n\n.flex-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n}\n\n.flex-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n}\n\n.flex-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n}\n\n.flex-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n}\n\n.justify-content-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n}\n\n.justify-content-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n}\n\n.justify-content-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n}\n\n.justify-content-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n}\n\n.justify-content-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n}\n\n.align-items-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n}\n\n.align-items-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n}\n\n.align-items-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n}\n\n.align-items-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n}\n\n.align-items-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n}\n\n.align-content-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n}\n\n.align-content-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n}\n\n.align-content-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n}\n\n.align-content-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n}\n\n.align-content-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n}\n\n.align-content-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n}\n\n.align-self-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n}\n\n.align-self-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n}\n\n.align-self-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n}\n\n.align-self-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n}\n\n.align-self-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n}\n\n.align-self-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n}\n\n@media (min-width: 576px) {\n .flex-sm-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-sm-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-sm-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-sm-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-sm-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-sm-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-sm-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-sm-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-sm-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-sm-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-sm-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-sm-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-sm-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-sm-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-sm-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-sm-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-sm-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-sm-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-sm-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-sm-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-sm-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-sm-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-sm-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-sm-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-sm-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-sm-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-sm-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-sm-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-sm-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-sm-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-sm-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-sm-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-sm-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-sm-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 768px) {\n .flex-md-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-md-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-md-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-md-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-md-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-md-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-md-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-md-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-md-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-md-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-md-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-md-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-md-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-md-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-md-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-md-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-md-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-md-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-md-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-md-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-md-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-md-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-md-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-md-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-md-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-md-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-md-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-md-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-md-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-md-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-md-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-md-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-md-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-md-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 992px) {\n .flex-lg-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-lg-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-lg-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-lg-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-lg-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-lg-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-lg-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-lg-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-lg-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-lg-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-lg-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-lg-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-lg-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-lg-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-lg-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-lg-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-lg-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-lg-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-lg-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-lg-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-lg-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-lg-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-lg-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-lg-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-lg-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-lg-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-lg-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-lg-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-lg-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-lg-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-lg-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-lg-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-lg-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-lg-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 1200px) {\n .flex-xl-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-xl-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-xl-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-xl-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-xl-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-xl-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-xl-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-xl-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-xl-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-xl-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-xl-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-xl-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-xl-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-xl-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-xl-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-xl-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-xl-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-xl-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-xl-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-xl-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-xl-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-xl-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-xl-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-xl-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-xl-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-xl-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-xl-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-xl-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-xl-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-xl-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-xl-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-xl-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-xl-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-xl-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n\n.m-0 {\n margin: 0 !important;\n}\n\n.mt-0,\n.my-0 {\n margin-top: 0 !important;\n}\n\n.mr-0,\n.mx-0 {\n margin-right: 0 !important;\n}\n\n.mb-0,\n.my-0 {\n margin-bottom: 0 !important;\n}\n\n.ml-0,\n.mx-0 {\n margin-left: 0 !important;\n}\n\n.m-1 {\n margin: 0.25rem !important;\n}\n\n.mt-1,\n.my-1 {\n margin-top: 0.25rem !important;\n}\n\n.mr-1,\n.mx-1 {\n margin-right: 0.25rem !important;\n}\n\n.mb-1,\n.my-1 {\n margin-bottom: 0.25rem !important;\n}\n\n.ml-1,\n.mx-1 {\n margin-left: 0.25rem !important;\n}\n\n.m-2 {\n margin: 0.5rem !important;\n}\n\n.mt-2,\n.my-2 {\n margin-top: 0.5rem !important;\n}\n\n.mr-2,\n.mx-2 {\n margin-right: 0.5rem !important;\n}\n\n.mb-2,\n.my-2 {\n margin-bottom: 0.5rem !important;\n}\n\n.ml-2,\n.mx-2 {\n margin-left: 0.5rem !important;\n}\n\n.m-3 {\n margin: 1rem !important;\n}\n\n.mt-3,\n.my-3 {\n margin-top: 1rem !important;\n}\n\n.mr-3,\n.mx-3 {\n margin-right: 1rem !important;\n}\n\n.mb-3,\n.my-3 {\n margin-bottom: 1rem !important;\n}\n\n.ml-3,\n.mx-3 {\n margin-left: 1rem !important;\n}\n\n.m-4 {\n margin: 1.5rem !important;\n}\n\n.mt-4,\n.my-4 {\n margin-top: 1.5rem !important;\n}\n\n.mr-4,\n.mx-4 {\n margin-right: 1.5rem !important;\n}\n\n.mb-4,\n.my-4 {\n margin-bottom: 1.5rem !important;\n}\n\n.ml-4,\n.mx-4 {\n margin-left: 1.5rem !important;\n}\n\n.m-5 {\n margin: 3rem !important;\n}\n\n.mt-5,\n.my-5 {\n margin-top: 3rem !important;\n}\n\n.mr-5,\n.mx-5 {\n margin-right: 3rem !important;\n}\n\n.mb-5,\n.my-5 {\n margin-bottom: 3rem !important;\n}\n\n.ml-5,\n.mx-5 {\n margin-left: 3rem !important;\n}\n\n.p-0 {\n padding: 0 !important;\n}\n\n.pt-0,\n.py-0 {\n padding-top: 0 !important;\n}\n\n.pr-0,\n.px-0 {\n padding-right: 0 !important;\n}\n\n.pb-0,\n.py-0 {\n padding-bottom: 0 !important;\n}\n\n.pl-0,\n.px-0 {\n padding-left: 0 !important;\n}\n\n.p-1 {\n padding: 0.25rem !important;\n}\n\n.pt-1,\n.py-1 {\n padding-top: 0.25rem !important;\n}\n\n.pr-1,\n.px-1 {\n padding-right: 0.25rem !important;\n}\n\n.pb-1,\n.py-1 {\n padding-bottom: 0.25rem !important;\n}\n\n.pl-1,\n.px-1 {\n padding-left: 0.25rem !important;\n}\n\n.p-2 {\n padding: 0.5rem !important;\n}\n\n.pt-2,\n.py-2 {\n padding-top: 0.5rem !important;\n}\n\n.pr-2,\n.px-2 {\n padding-right: 0.5rem !important;\n}\n\n.pb-2,\n.py-2 {\n padding-bottom: 0.5rem !important;\n}\n\n.pl-2,\n.px-2 {\n padding-left: 0.5rem !important;\n}\n\n.p-3 {\n padding: 1rem !important;\n}\n\n.pt-3,\n.py-3 {\n padding-top: 1rem !important;\n}\n\n.pr-3,\n.px-3 {\n padding-right: 1rem !important;\n}\n\n.pb-3,\n.py-3 {\n padding-bottom: 1rem !important;\n}\n\n.pl-3,\n.px-3 {\n padding-left: 1rem !important;\n}\n\n.p-4 {\n padding: 1.5rem !important;\n}\n\n.pt-4,\n.py-4 {\n padding-top: 1.5rem !important;\n}\n\n.pr-4,\n.px-4 {\n padding-right: 1.5rem !important;\n}\n\n.pb-4,\n.py-4 {\n padding-bottom: 1.5rem !important;\n}\n\n.pl-4,\n.px-4 {\n padding-left: 1.5rem !important;\n}\n\n.p-5 {\n padding: 3rem !important;\n}\n\n.pt-5,\n.py-5 {\n padding-top: 3rem !important;\n}\n\n.pr-5,\n.px-5 {\n padding-right: 3rem !important;\n}\n\n.pb-5,\n.py-5 {\n padding-bottom: 3rem !important;\n}\n\n.pl-5,\n.px-5 {\n padding-left: 3rem !important;\n}\n\n.m-n1 {\n margin: -0.25rem !important;\n}\n\n.mt-n1,\n.my-n1 {\n margin-top: -0.25rem !important;\n}\n\n.mr-n1,\n.mx-n1 {\n margin-right: -0.25rem !important;\n}\n\n.mb-n1,\n.my-n1 {\n margin-bottom: -0.25rem !important;\n}\n\n.ml-n1,\n.mx-n1 {\n margin-left: -0.25rem !important;\n}\n\n.m-n2 {\n margin: -0.5rem !important;\n}\n\n.mt-n2,\n.my-n2 {\n margin-top: -0.5rem !important;\n}\n\n.mr-n2,\n.mx-n2 {\n margin-right: -0.5rem !important;\n}\n\n.mb-n2,\n.my-n2 {\n margin-bottom: -0.5rem !important;\n}\n\n.ml-n2,\n.mx-n2 {\n margin-left: -0.5rem !important;\n}\n\n.m-n3 {\n margin: -1rem !important;\n}\n\n.mt-n3,\n.my-n3 {\n margin-top: -1rem !important;\n}\n\n.mr-n3,\n.mx-n3 {\n margin-right: -1rem !important;\n}\n\n.mb-n3,\n.my-n3 {\n margin-bottom: -1rem !important;\n}\n\n.ml-n3,\n.mx-n3 {\n margin-left: -1rem !important;\n}\n\n.m-n4 {\n margin: -1.5rem !important;\n}\n\n.mt-n4,\n.my-n4 {\n margin-top: -1.5rem !important;\n}\n\n.mr-n4,\n.mx-n4 {\n margin-right: -1.5rem !important;\n}\n\n.mb-n4,\n.my-n4 {\n margin-bottom: -1.5rem !important;\n}\n\n.ml-n4,\n.mx-n4 {\n margin-left: -1.5rem !important;\n}\n\n.m-n5 {\n margin: -3rem !important;\n}\n\n.mt-n5,\n.my-n5 {\n margin-top: -3rem !important;\n}\n\n.mr-n5,\n.mx-n5 {\n margin-right: -3rem !important;\n}\n\n.mb-n5,\n.my-n5 {\n margin-bottom: -3rem !important;\n}\n\n.ml-n5,\n.mx-n5 {\n margin-left: -3rem !important;\n}\n\n.m-auto {\n margin: auto !important;\n}\n\n.mt-auto,\n.my-auto {\n margin-top: auto !important;\n}\n\n.mr-auto,\n.mx-auto {\n margin-right: auto !important;\n}\n\n.mb-auto,\n.my-auto {\n margin-bottom: auto !important;\n}\n\n.ml-auto,\n.mx-auto {\n margin-left: auto !important;\n}\n\n@media (min-width: 576px) {\n .m-sm-0 {\n margin: 0 !important;\n }\n .mt-sm-0,\n .my-sm-0 {\n margin-top: 0 !important;\n }\n .mr-sm-0,\n .mx-sm-0 {\n margin-right: 0 !important;\n }\n .mb-sm-0,\n .my-sm-0 {\n margin-bottom: 0 !important;\n }\n .ml-sm-0,\n .mx-sm-0 {\n margin-left: 0 !important;\n }\n .m-sm-1 {\n margin: 0.25rem !important;\n }\n .mt-sm-1,\n .my-sm-1 {\n margin-top: 0.25rem !important;\n }\n .mr-sm-1,\n .mx-sm-1 {\n margin-right: 0.25rem !important;\n }\n .mb-sm-1,\n .my-sm-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-sm-1,\n .mx-sm-1 {\n margin-left: 0.25rem !important;\n }\n .m-sm-2 {\n margin: 0.5rem !important;\n }\n .mt-sm-2,\n .my-sm-2 {\n margin-top: 0.5rem !important;\n }\n .mr-sm-2,\n .mx-sm-2 {\n margin-right: 0.5rem !important;\n }\n .mb-sm-2,\n .my-sm-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-sm-2,\n .mx-sm-2 {\n margin-left: 0.5rem !important;\n }\n .m-sm-3 {\n margin: 1rem !important;\n }\n .mt-sm-3,\n .my-sm-3 {\n margin-top: 1rem !important;\n }\n .mr-sm-3,\n .mx-sm-3 {\n margin-right: 1rem !important;\n }\n .mb-sm-3,\n .my-sm-3 {\n margin-bottom: 1rem !important;\n }\n .ml-sm-3,\n .mx-sm-3 {\n margin-left: 1rem !important;\n }\n .m-sm-4 {\n margin: 1.5rem !important;\n }\n .mt-sm-4,\n .my-sm-4 {\n margin-top: 1.5rem !important;\n }\n .mr-sm-4,\n .mx-sm-4 {\n margin-right: 1.5rem !important;\n }\n .mb-sm-4,\n .my-sm-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-sm-4,\n .mx-sm-4 {\n margin-left: 1.5rem !important;\n }\n .m-sm-5 {\n margin: 3rem !important;\n }\n .mt-sm-5,\n .my-sm-5 {\n margin-top: 3rem !important;\n }\n .mr-sm-5,\n .mx-sm-5 {\n margin-right: 3rem !important;\n }\n .mb-sm-5,\n .my-sm-5 {\n margin-bottom: 3rem !important;\n }\n .ml-sm-5,\n .mx-sm-5 {\n margin-left: 3rem !important;\n }\n .p-sm-0 {\n padding: 0 !important;\n }\n .pt-sm-0,\n .py-sm-0 {\n padding-top: 0 !important;\n }\n .pr-sm-0,\n .px-sm-0 {\n padding-right: 0 !important;\n }\n .pb-sm-0,\n .py-sm-0 {\n padding-bottom: 0 !important;\n }\n .pl-sm-0,\n .px-sm-0 {\n padding-left: 0 !important;\n }\n .p-sm-1 {\n padding: 0.25rem !important;\n }\n .pt-sm-1,\n .py-sm-1 {\n padding-top: 0.25rem !important;\n }\n .pr-sm-1,\n .px-sm-1 {\n padding-right: 0.25rem !important;\n }\n .pb-sm-1,\n .py-sm-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-sm-1,\n .px-sm-1 {\n padding-left: 0.25rem !important;\n }\n .p-sm-2 {\n padding: 0.5rem !important;\n }\n .pt-sm-2,\n .py-sm-2 {\n padding-top: 0.5rem !important;\n }\n .pr-sm-2,\n .px-sm-2 {\n padding-right: 0.5rem !important;\n }\n .pb-sm-2,\n .py-sm-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-sm-2,\n .px-sm-2 {\n padding-left: 0.5rem !important;\n }\n .p-sm-3 {\n padding: 1rem !important;\n }\n .pt-sm-3,\n .py-sm-3 {\n padding-top: 1rem !important;\n }\n .pr-sm-3,\n .px-sm-3 {\n padding-right: 1rem !important;\n }\n .pb-sm-3,\n .py-sm-3 {\n padding-bottom: 1rem !important;\n }\n .pl-sm-3,\n .px-sm-3 {\n padding-left: 1rem !important;\n }\n .p-sm-4 {\n padding: 1.5rem !important;\n }\n .pt-sm-4,\n .py-sm-4 {\n padding-top: 1.5rem !important;\n }\n .pr-sm-4,\n .px-sm-4 {\n padding-right: 1.5rem !important;\n }\n .pb-sm-4,\n .py-sm-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-sm-4,\n .px-sm-4 {\n padding-left: 1.5rem !important;\n }\n .p-sm-5 {\n padding: 3rem !important;\n }\n .pt-sm-5,\n .py-sm-5 {\n padding-top: 3rem !important;\n }\n .pr-sm-5,\n .px-sm-5 {\n padding-right: 3rem !important;\n }\n .pb-sm-5,\n .py-sm-5 {\n padding-bottom: 3rem !important;\n }\n .pl-sm-5,\n .px-sm-5 {\n padding-left: 3rem !important;\n }\n .m-sm-n1 {\n margin: -0.25rem !important;\n }\n .mt-sm-n1,\n .my-sm-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-sm-n1,\n .mx-sm-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-sm-n1,\n .my-sm-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-sm-n1,\n .mx-sm-n1 {\n margin-left: -0.25rem !important;\n }\n .m-sm-n2 {\n margin: -0.5rem !important;\n }\n .mt-sm-n2,\n .my-sm-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-sm-n2,\n .mx-sm-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-sm-n2,\n .my-sm-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-sm-n2,\n .mx-sm-n2 {\n margin-left: -0.5rem !important;\n }\n .m-sm-n3 {\n margin: -1rem !important;\n }\n .mt-sm-n3,\n .my-sm-n3 {\n margin-top: -1rem !important;\n }\n .mr-sm-n3,\n .mx-sm-n3 {\n margin-right: -1rem !important;\n }\n .mb-sm-n3,\n .my-sm-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-sm-n3,\n .mx-sm-n3 {\n margin-left: -1rem !important;\n }\n .m-sm-n4 {\n margin: -1.5rem !important;\n }\n .mt-sm-n4,\n .my-sm-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-sm-n4,\n .mx-sm-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-sm-n4,\n .my-sm-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-sm-n4,\n .mx-sm-n4 {\n margin-left: -1.5rem !important;\n }\n .m-sm-n5 {\n margin: -3rem !important;\n }\n .mt-sm-n5,\n .my-sm-n5 {\n margin-top: -3rem !important;\n }\n .mr-sm-n5,\n .mx-sm-n5 {\n margin-right: -3rem !important;\n }\n .mb-sm-n5,\n .my-sm-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-sm-n5,\n .mx-sm-n5 {\n margin-left: -3rem !important;\n }\n .m-sm-auto {\n margin: auto !important;\n }\n .mt-sm-auto,\n .my-sm-auto {\n margin-top: auto !important;\n }\n .mr-sm-auto,\n .mx-sm-auto {\n margin-right: auto !important;\n }\n .mb-sm-auto,\n .my-sm-auto {\n margin-bottom: auto !important;\n }\n .ml-sm-auto,\n .mx-sm-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 768px) {\n .m-md-0 {\n margin: 0 !important;\n }\n .mt-md-0,\n .my-md-0 {\n margin-top: 0 !important;\n }\n .mr-md-0,\n .mx-md-0 {\n margin-right: 0 !important;\n }\n .mb-md-0,\n .my-md-0 {\n margin-bottom: 0 !important;\n }\n .ml-md-0,\n .mx-md-0 {\n margin-left: 0 !important;\n }\n .m-md-1 {\n margin: 0.25rem !important;\n }\n .mt-md-1,\n .my-md-1 {\n margin-top: 0.25rem !important;\n }\n .mr-md-1,\n .mx-md-1 {\n margin-right: 0.25rem !important;\n }\n .mb-md-1,\n .my-md-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-md-1,\n .mx-md-1 {\n margin-left: 0.25rem !important;\n }\n .m-md-2 {\n margin: 0.5rem !important;\n }\n .mt-md-2,\n .my-md-2 {\n margin-top: 0.5rem !important;\n }\n .mr-md-2,\n .mx-md-2 {\n margin-right: 0.5rem !important;\n }\n .mb-md-2,\n .my-md-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-md-2,\n .mx-md-2 {\n margin-left: 0.5rem !important;\n }\n .m-md-3 {\n margin: 1rem !important;\n }\n .mt-md-3,\n .my-md-3 {\n margin-top: 1rem !important;\n }\n .mr-md-3,\n .mx-md-3 {\n margin-right: 1rem !important;\n }\n .mb-md-3,\n .my-md-3 {\n margin-bottom: 1rem !important;\n }\n .ml-md-3,\n .mx-md-3 {\n margin-left: 1rem !important;\n }\n .m-md-4 {\n margin: 1.5rem !important;\n }\n .mt-md-4,\n .my-md-4 {\n margin-top: 1.5rem !important;\n }\n .mr-md-4,\n .mx-md-4 {\n margin-right: 1.5rem !important;\n }\n .mb-md-4,\n .my-md-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-md-4,\n .mx-md-4 {\n margin-left: 1.5rem !important;\n }\n .m-md-5 {\n margin: 3rem !important;\n }\n .mt-md-5,\n .my-md-5 {\n margin-top: 3rem !important;\n }\n .mr-md-5,\n .mx-md-5 {\n margin-right: 3rem !important;\n }\n .mb-md-5,\n .my-md-5 {\n margin-bottom: 3rem !important;\n }\n .ml-md-5,\n .mx-md-5 {\n margin-left: 3rem !important;\n }\n .p-md-0 {\n padding: 0 !important;\n }\n .pt-md-0,\n .py-md-0 {\n padding-top: 0 !important;\n }\n .pr-md-0,\n .px-md-0 {\n padding-right: 0 !important;\n }\n .pb-md-0,\n .py-md-0 {\n padding-bottom: 0 !important;\n }\n .pl-md-0,\n .px-md-0 {\n padding-left: 0 !important;\n }\n .p-md-1 {\n padding: 0.25rem !important;\n }\n .pt-md-1,\n .py-md-1 {\n padding-top: 0.25rem !important;\n }\n .pr-md-1,\n .px-md-1 {\n padding-right: 0.25rem !important;\n }\n .pb-md-1,\n .py-md-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-md-1,\n .px-md-1 {\n padding-left: 0.25rem !important;\n }\n .p-md-2 {\n padding: 0.5rem !important;\n }\n .pt-md-2,\n .py-md-2 {\n padding-top: 0.5rem !important;\n }\n .pr-md-2,\n .px-md-2 {\n padding-right: 0.5rem !important;\n }\n .pb-md-2,\n .py-md-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-md-2,\n .px-md-2 {\n padding-left: 0.5rem !important;\n }\n .p-md-3 {\n padding: 1rem !important;\n }\n .pt-md-3,\n .py-md-3 {\n padding-top: 1rem !important;\n }\n .pr-md-3,\n .px-md-3 {\n padding-right: 1rem !important;\n }\n .pb-md-3,\n .py-md-3 {\n padding-bottom: 1rem !important;\n }\n .pl-md-3,\n .px-md-3 {\n padding-left: 1rem !important;\n }\n .p-md-4 {\n padding: 1.5rem !important;\n }\n .pt-md-4,\n .py-md-4 {\n padding-top: 1.5rem !important;\n }\n .pr-md-4,\n .px-md-4 {\n padding-right: 1.5rem !important;\n }\n .pb-md-4,\n .py-md-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-md-4,\n .px-md-4 {\n padding-left: 1.5rem !important;\n }\n .p-md-5 {\n padding: 3rem !important;\n }\n .pt-md-5,\n .py-md-5 {\n padding-top: 3rem !important;\n }\n .pr-md-5,\n .px-md-5 {\n padding-right: 3rem !important;\n }\n .pb-md-5,\n .py-md-5 {\n padding-bottom: 3rem !important;\n }\n .pl-md-5,\n .px-md-5 {\n padding-left: 3rem !important;\n }\n .m-md-n1 {\n margin: -0.25rem !important;\n }\n .mt-md-n1,\n .my-md-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-md-n1,\n .mx-md-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-md-n1,\n .my-md-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-md-n1,\n .mx-md-n1 {\n margin-left: -0.25rem !important;\n }\n .m-md-n2 {\n margin: -0.5rem !important;\n }\n .mt-md-n2,\n .my-md-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-md-n2,\n .mx-md-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-md-n2,\n .my-md-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-md-n2,\n .mx-md-n2 {\n margin-left: -0.5rem !important;\n }\n .m-md-n3 {\n margin: -1rem !important;\n }\n .mt-md-n3,\n .my-md-n3 {\n margin-top: -1rem !important;\n }\n .mr-md-n3,\n .mx-md-n3 {\n margin-right: -1rem !important;\n }\n .mb-md-n3,\n .my-md-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-md-n3,\n .mx-md-n3 {\n margin-left: -1rem !important;\n }\n .m-md-n4 {\n margin: -1.5rem !important;\n }\n .mt-md-n4,\n .my-md-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-md-n4,\n .mx-md-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-md-n4,\n .my-md-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-md-n4,\n .mx-md-n4 {\n margin-left: -1.5rem !important;\n }\n .m-md-n5 {\n margin: -3rem !important;\n }\n .mt-md-n5,\n .my-md-n5 {\n margin-top: -3rem !important;\n }\n .mr-md-n5,\n .mx-md-n5 {\n margin-right: -3rem !important;\n }\n .mb-md-n5,\n .my-md-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-md-n5,\n .mx-md-n5 {\n margin-left: -3rem !important;\n }\n .m-md-auto {\n margin: auto !important;\n }\n .mt-md-auto,\n .my-md-auto {\n margin-top: auto !important;\n }\n .mr-md-auto,\n .mx-md-auto {\n margin-right: auto !important;\n }\n .mb-md-auto,\n .my-md-auto {\n margin-bottom: auto !important;\n }\n .ml-md-auto,\n .mx-md-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 992px) {\n .m-lg-0 {\n margin: 0 !important;\n }\n .mt-lg-0,\n .my-lg-0 {\n margin-top: 0 !important;\n }\n .mr-lg-0,\n .mx-lg-0 {\n margin-right: 0 !important;\n }\n .mb-lg-0,\n .my-lg-0 {\n margin-bottom: 0 !important;\n }\n .ml-lg-0,\n .mx-lg-0 {\n margin-left: 0 !important;\n }\n .m-lg-1 {\n margin: 0.25rem !important;\n }\n .mt-lg-1,\n .my-lg-1 {\n margin-top: 0.25rem !important;\n }\n .mr-lg-1,\n .mx-lg-1 {\n margin-right: 0.25rem !important;\n }\n .mb-lg-1,\n .my-lg-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-lg-1,\n .mx-lg-1 {\n margin-left: 0.25rem !important;\n }\n .m-lg-2 {\n margin: 0.5rem !important;\n }\n .mt-lg-2,\n .my-lg-2 {\n margin-top: 0.5rem !important;\n }\n .mr-lg-2,\n .mx-lg-2 {\n margin-right: 0.5rem !important;\n }\n .mb-lg-2,\n .my-lg-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-lg-2,\n .mx-lg-2 {\n margin-left: 0.5rem !important;\n }\n .m-lg-3 {\n margin: 1rem !important;\n }\n .mt-lg-3,\n .my-lg-3 {\n margin-top: 1rem !important;\n }\n .mr-lg-3,\n .mx-lg-3 {\n margin-right: 1rem !important;\n }\n .mb-lg-3,\n .my-lg-3 {\n margin-bottom: 1rem !important;\n }\n .ml-lg-3,\n .mx-lg-3 {\n margin-left: 1rem !important;\n }\n .m-lg-4 {\n margin: 1.5rem !important;\n }\n .mt-lg-4,\n .my-lg-4 {\n margin-top: 1.5rem !important;\n }\n .mr-lg-4,\n .mx-lg-4 {\n margin-right: 1.5rem !important;\n }\n .mb-lg-4,\n .my-lg-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-lg-4,\n .mx-lg-4 {\n margin-left: 1.5rem !important;\n }\n .m-lg-5 {\n margin: 3rem !important;\n }\n .mt-lg-5,\n .my-lg-5 {\n margin-top: 3rem !important;\n }\n .mr-lg-5,\n .mx-lg-5 {\n margin-right: 3rem !important;\n }\n .mb-lg-5,\n .my-lg-5 {\n margin-bottom: 3rem !important;\n }\n .ml-lg-5,\n .mx-lg-5 {\n margin-left: 3rem !important;\n }\n .p-lg-0 {\n padding: 0 !important;\n }\n .pt-lg-0,\n .py-lg-0 {\n padding-top: 0 !important;\n }\n .pr-lg-0,\n .px-lg-0 {\n padding-right: 0 !important;\n }\n .pb-lg-0,\n .py-lg-0 {\n padding-bottom: 0 !important;\n }\n .pl-lg-0,\n .px-lg-0 {\n padding-left: 0 !important;\n }\n .p-lg-1 {\n padding: 0.25rem !important;\n }\n .pt-lg-1,\n .py-lg-1 {\n padding-top: 0.25rem !important;\n }\n .pr-lg-1,\n .px-lg-1 {\n padding-right: 0.25rem !important;\n }\n .pb-lg-1,\n .py-lg-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-lg-1,\n .px-lg-1 {\n padding-left: 0.25rem !important;\n }\n .p-lg-2 {\n padding: 0.5rem !important;\n }\n .pt-lg-2,\n .py-lg-2 {\n padding-top: 0.5rem !important;\n }\n .pr-lg-2,\n .px-lg-2 {\n padding-right: 0.5rem !important;\n }\n .pb-lg-2,\n .py-lg-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-lg-2,\n .px-lg-2 {\n padding-left: 0.5rem !important;\n }\n .p-lg-3 {\n padding: 1rem !important;\n }\n .pt-lg-3,\n .py-lg-3 {\n padding-top: 1rem !important;\n }\n .pr-lg-3,\n .px-lg-3 {\n padding-right: 1rem !important;\n }\n .pb-lg-3,\n .py-lg-3 {\n padding-bottom: 1rem !important;\n }\n .pl-lg-3,\n .px-lg-3 {\n padding-left: 1rem !important;\n }\n .p-lg-4 {\n padding: 1.5rem !important;\n }\n .pt-lg-4,\n .py-lg-4 {\n padding-top: 1.5rem !important;\n }\n .pr-lg-4,\n .px-lg-4 {\n padding-right: 1.5rem !important;\n }\n .pb-lg-4,\n .py-lg-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-lg-4,\n .px-lg-4 {\n padding-left: 1.5rem !important;\n }\n .p-lg-5 {\n padding: 3rem !important;\n }\n .pt-lg-5,\n .py-lg-5 {\n padding-top: 3rem !important;\n }\n .pr-lg-5,\n .px-lg-5 {\n padding-right: 3rem !important;\n }\n .pb-lg-5,\n .py-lg-5 {\n padding-bottom: 3rem !important;\n }\n .pl-lg-5,\n .px-lg-5 {\n padding-left: 3rem !important;\n }\n .m-lg-n1 {\n margin: -0.25rem !important;\n }\n .mt-lg-n1,\n .my-lg-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-lg-n1,\n .mx-lg-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-lg-n1,\n .my-lg-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-lg-n1,\n .mx-lg-n1 {\n margin-left: -0.25rem !important;\n }\n .m-lg-n2 {\n margin: -0.5rem !important;\n }\n .mt-lg-n2,\n .my-lg-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-lg-n2,\n .mx-lg-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-lg-n2,\n .my-lg-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-lg-n2,\n .mx-lg-n2 {\n margin-left: -0.5rem !important;\n }\n .m-lg-n3 {\n margin: -1rem !important;\n }\n .mt-lg-n3,\n .my-lg-n3 {\n margin-top: -1rem !important;\n }\n .mr-lg-n3,\n .mx-lg-n3 {\n margin-right: -1rem !important;\n }\n .mb-lg-n3,\n .my-lg-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-lg-n3,\n .mx-lg-n3 {\n margin-left: -1rem !important;\n }\n .m-lg-n4 {\n margin: -1.5rem !important;\n }\n .mt-lg-n4,\n .my-lg-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-lg-n4,\n .mx-lg-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-lg-n4,\n .my-lg-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-lg-n4,\n .mx-lg-n4 {\n margin-left: -1.5rem !important;\n }\n .m-lg-n5 {\n margin: -3rem !important;\n }\n .mt-lg-n5,\n .my-lg-n5 {\n margin-top: -3rem !important;\n }\n .mr-lg-n5,\n .mx-lg-n5 {\n margin-right: -3rem !important;\n }\n .mb-lg-n5,\n .my-lg-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-lg-n5,\n .mx-lg-n5 {\n margin-left: -3rem !important;\n }\n .m-lg-auto {\n margin: auto !important;\n }\n .mt-lg-auto,\n .my-lg-auto {\n margin-top: auto !important;\n }\n .mr-lg-auto,\n .mx-lg-auto {\n margin-right: auto !important;\n }\n .mb-lg-auto,\n .my-lg-auto {\n margin-bottom: auto !important;\n }\n .ml-lg-auto,\n .mx-lg-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 1200px) {\n .m-xl-0 {\n margin: 0 !important;\n }\n .mt-xl-0,\n .my-xl-0 {\n margin-top: 0 !important;\n }\n .mr-xl-0,\n .mx-xl-0 {\n margin-right: 0 !important;\n }\n .mb-xl-0,\n .my-xl-0 {\n margin-bottom: 0 !important;\n }\n .ml-xl-0,\n .mx-xl-0 {\n margin-left: 0 !important;\n }\n .m-xl-1 {\n margin: 0.25rem !important;\n }\n .mt-xl-1,\n .my-xl-1 {\n margin-top: 0.25rem !important;\n }\n .mr-xl-1,\n .mx-xl-1 {\n margin-right: 0.25rem !important;\n }\n .mb-xl-1,\n .my-xl-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-xl-1,\n .mx-xl-1 {\n margin-left: 0.25rem !important;\n }\n .m-xl-2 {\n margin: 0.5rem !important;\n }\n .mt-xl-2,\n .my-xl-2 {\n margin-top: 0.5rem !important;\n }\n .mr-xl-2,\n .mx-xl-2 {\n margin-right: 0.5rem !important;\n }\n .mb-xl-2,\n .my-xl-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-xl-2,\n .mx-xl-2 {\n margin-left: 0.5rem !important;\n }\n .m-xl-3 {\n margin: 1rem !important;\n }\n .mt-xl-3,\n .my-xl-3 {\n margin-top: 1rem !important;\n }\n .mr-xl-3,\n .mx-xl-3 {\n margin-right: 1rem !important;\n }\n .mb-xl-3,\n .my-xl-3 {\n margin-bottom: 1rem !important;\n }\n .ml-xl-3,\n .mx-xl-3 {\n margin-left: 1rem !important;\n }\n .m-xl-4 {\n margin: 1.5rem !important;\n }\n .mt-xl-4,\n .my-xl-4 {\n margin-top: 1.5rem !important;\n }\n .mr-xl-4,\n .mx-xl-4 {\n margin-right: 1.5rem !important;\n }\n .mb-xl-4,\n .my-xl-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-xl-4,\n .mx-xl-4 {\n margin-left: 1.5rem !important;\n }\n .m-xl-5 {\n margin: 3rem !important;\n }\n .mt-xl-5,\n .my-xl-5 {\n margin-top: 3rem !important;\n }\n .mr-xl-5,\n .mx-xl-5 {\n margin-right: 3rem !important;\n }\n .mb-xl-5,\n .my-xl-5 {\n margin-bottom: 3rem !important;\n }\n .ml-xl-5,\n .mx-xl-5 {\n margin-left: 3rem !important;\n }\n .p-xl-0 {\n padding: 0 !important;\n }\n .pt-xl-0,\n .py-xl-0 {\n padding-top: 0 !important;\n }\n .pr-xl-0,\n .px-xl-0 {\n padding-right: 0 !important;\n }\n .pb-xl-0,\n .py-xl-0 {\n padding-bottom: 0 !important;\n }\n .pl-xl-0,\n .px-xl-0 {\n padding-left: 0 !important;\n }\n .p-xl-1 {\n padding: 0.25rem !important;\n }\n .pt-xl-1,\n .py-xl-1 {\n padding-top: 0.25rem !important;\n }\n .pr-xl-1,\n .px-xl-1 {\n padding-right: 0.25rem !important;\n }\n .pb-xl-1,\n .py-xl-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-xl-1,\n .px-xl-1 {\n padding-left: 0.25rem !important;\n }\n .p-xl-2 {\n padding: 0.5rem !important;\n }\n .pt-xl-2,\n .py-xl-2 {\n padding-top: 0.5rem !important;\n }\n .pr-xl-2,\n .px-xl-2 {\n padding-right: 0.5rem !important;\n }\n .pb-xl-2,\n .py-xl-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-xl-2,\n .px-xl-2 {\n padding-left: 0.5rem !important;\n }\n .p-xl-3 {\n padding: 1rem !important;\n }\n .pt-xl-3,\n .py-xl-3 {\n padding-top: 1rem !important;\n }\n .pr-xl-3,\n .px-xl-3 {\n padding-right: 1rem !important;\n }\n .pb-xl-3,\n .py-xl-3 {\n padding-bottom: 1rem !important;\n }\n .pl-xl-3,\n .px-xl-3 {\n padding-left: 1rem !important;\n }\n .p-xl-4 {\n padding: 1.5rem !important;\n }\n .pt-xl-4,\n .py-xl-4 {\n padding-top: 1.5rem !important;\n }\n .pr-xl-4,\n .px-xl-4 {\n padding-right: 1.5rem !important;\n }\n .pb-xl-4,\n .py-xl-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-xl-4,\n .px-xl-4 {\n padding-left: 1.5rem !important;\n }\n .p-xl-5 {\n padding: 3rem !important;\n }\n .pt-xl-5,\n .py-xl-5 {\n padding-top: 3rem !important;\n }\n .pr-xl-5,\n .px-xl-5 {\n padding-right: 3rem !important;\n }\n .pb-xl-5,\n .py-xl-5 {\n padding-bottom: 3rem !important;\n }\n .pl-xl-5,\n .px-xl-5 {\n padding-left: 3rem !important;\n }\n .m-xl-n1 {\n margin: -0.25rem !important;\n }\n .mt-xl-n1,\n .my-xl-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-xl-n1,\n .mx-xl-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-xl-n1,\n .my-xl-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-xl-n1,\n .mx-xl-n1 {\n margin-left: -0.25rem !important;\n }\n .m-xl-n2 {\n margin: -0.5rem !important;\n }\n .mt-xl-n2,\n .my-xl-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-xl-n2,\n .mx-xl-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-xl-n2,\n .my-xl-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-xl-n2,\n .mx-xl-n2 {\n margin-left: -0.5rem !important;\n }\n .m-xl-n3 {\n margin: -1rem !important;\n }\n .mt-xl-n3,\n .my-xl-n3 {\n margin-top: -1rem !important;\n }\n .mr-xl-n3,\n .mx-xl-n3 {\n margin-right: -1rem !important;\n }\n .mb-xl-n3,\n .my-xl-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-xl-n3,\n .mx-xl-n3 {\n margin-left: -1rem !important;\n }\n .m-xl-n4 {\n margin: -1.5rem !important;\n }\n .mt-xl-n4,\n .my-xl-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-xl-n4,\n .mx-xl-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-xl-n4,\n .my-xl-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-xl-n4,\n .mx-xl-n4 {\n margin-left: -1.5rem !important;\n }\n .m-xl-n5 {\n margin: -3rem !important;\n }\n .mt-xl-n5,\n .my-xl-n5 {\n margin-top: -3rem !important;\n }\n .mr-xl-n5,\n .mx-xl-n5 {\n margin-right: -3rem !important;\n }\n .mb-xl-n5,\n .my-xl-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-xl-n5,\n .mx-xl-n5 {\n margin-left: -3rem !important;\n }\n .m-xl-auto {\n margin: auto !important;\n }\n .mt-xl-auto,\n .my-xl-auto {\n margin-top: auto !important;\n }\n .mr-xl-auto,\n .mx-xl-auto {\n margin-right: auto !important;\n }\n .mb-xl-auto,\n .my-xl-auto {\n margin-bottom: auto !important;\n }\n .ml-xl-auto,\n .mx-xl-auto {\n margin-left: auto !important;\n }\n}\n/*# sourceMappingURL=bootstrap-grid.css.map */","// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n@if $enable-grid-classes {\n .container {\n @include make-container();\n @include make-container-max-widths();\n }\n}\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but with 100% width for\n// fluid, full width layouts.\n\n@if $enable-grid-classes {\n .container-fluid {\n @include make-container();\n }\n}\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n@if $enable-grid-classes {\n .row {\n @include make-row();\n }\n\n // Remove the negative margin from default .row, then the horizontal padding\n // from all immediate children columns (to prevent runaway style inheritance).\n .no-gutters {\n margin-right: 0;\n margin-left: 0;\n\n > .col,\n > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n }\n }\n}\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n@if $enable-grid-classes {\n @include make-grid-columns();\n}\n","/// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n@mixin make-container($gutter: $grid-gutter-width) {\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n margin-right: auto;\n margin-left: auto;\n}\n\n\n// For each breakpoint, define the maximum width of the container in a media query\n@mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) {\n @each $breakpoint, $container-max-width in $max-widths {\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n max-width: $container-max-width;\n }\n }\n}\n\n@mixin make-row($gutter: $grid-gutter-width) {\n display: flex;\n flex-wrap: wrap;\n margin-right: -$gutter / 2;\n margin-left: -$gutter / 2;\n}\n\n@mixin make-col-ready($gutter: $grid-gutter-width) {\n position: relative;\n // Prevent columns from becoming too narrow when at smaller grid tiers by\n // always setting `width: 100%;`. This works because we use `flex` values\n // later on to override this initial width.\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n}\n\n@mixin make-col($size, $columns: $grid-columns) {\n flex: 0 0 percentage($size / $columns);\n // Add a `max-width` to ensure content within each column does not blow out\n // the width of the column. Applies to IE10+ and Firefox. Chrome and Safari\n // do not appear to require this.\n max-width: percentage($size / $columns);\n}\n\n@mixin make-col-offset($size, $columns: $grid-columns) {\n $num: $size / $columns;\n margin-left: if($num == 0, 0, percentage($num));\n}\n","// Breakpoint viewport sizes and media queries.\n//\n// Breakpoints are defined as a map of (name: minimum width), order from small to large:\n//\n// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)\n//\n// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.\n\n// Name of the next breakpoint, or null for the last breakpoint.\n//\n// >> breakpoint-next(sm)\n// md\n// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// md\n// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl))\n// md\n@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {\n $n: index($breakpoint-names, $name);\n @return if($n != null and $n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);\n}\n\n// Minimum breakpoint width. Null for the smallest (first) breakpoint.\n//\n// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 576px\n@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {\n $min: map-get($breakpoints, $name);\n @return if($min != 0, $min, null);\n}\n\n// Maximum breakpoint width. Null for the largest (last) breakpoint.\n// The maximum value is calculated as the minimum of the next one less 0.02px\n// to work around the limitations of `min-` and `max-` prefixes and viewports with fractional widths.\n// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max\n// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.\n// See https://bugs.webkit.org/show_bug.cgi?id=178261\n//\n// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 767.98px\n@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {\n $next: breakpoint-next($name, $breakpoints);\n @return if($next, breakpoint-min($next, $breakpoints) - .02, null);\n}\n\n// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front.\n// Useful for making responsive utilities.\n//\n// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"\" (Returns a blank string)\n// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"-sm\"\n@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {\n @return if(breakpoint-min($name, $breakpoints) == null, \"\", \"-#{$name}\");\n}\n\n// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.\n// Makes the @content apply to the given breakpoint and wider.\n@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n @if $min {\n @media (min-width: $min) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media of at most the maximum breakpoint width. No query for the largest breakpoint.\n// Makes the @content apply to the given breakpoint and narrower.\n@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {\n $max: breakpoint-max($name, $breakpoints);\n @if $max {\n @media (max-width: $max) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media that spans multiple breakpoint widths.\n// Makes the @content apply between the min and max breakpoints\n@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($lower, $breakpoints);\n $max: breakpoint-max($upper, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($lower, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($upper, $breakpoints) {\n @content;\n }\n }\n}\n\n// Media between the breakpoint's minimum and maximum widths.\n// No minimum for the smallest breakpoint, and no maximum for the largest one.\n// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.\n@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n $max: breakpoint-max($name, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($name, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($name, $breakpoints) {\n @content;\n }\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `$grid-columns`.\n\n@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {\n // Common properties for all breakpoints\n %grid-column {\n position: relative;\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n }\n\n @each $breakpoint in map-keys($breakpoints) {\n $infix: breakpoint-infix($breakpoint, $breakpoints);\n\n // Allow columns to stretch full width below their breakpoints\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @extend %grid-column;\n }\n }\n .col#{$infix},\n .col#{$infix}-auto {\n @extend %grid-column;\n }\n\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n // Provide basic `.col-{bp}` classes for equal-width flexbox columns\n .col#{$infix} {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col#{$infix}-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%; // Reset earlier grid tiers\n }\n\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @include make-col($i, $columns);\n }\n }\n\n .order#{$infix}-first { order: -1; }\n\n .order#{$infix}-last { order: $columns + 1; }\n\n @for $i from 0 through $columns {\n .order#{$infix}-#{$i} { order: $i; }\n }\n\n // `$columns - 1` because offsetting by the width of an entire row isn't possible\n @for $i from 0 through ($columns - 1) {\n @if not ($infix == \"\" and $i == 0) { // Avoid emitting useless .offset-0\n .offset#{$infix}-#{$i} {\n @include make-col-offset($i, $columns);\n }\n }\n }\n }\n }\n}\n","// stylelint-disable declaration-no-important\n\n//\n// Utilities for common `display` values\n//\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n @each $value in $displays {\n .d#{$infix}-#{$value} { display: $value !important; }\n }\n }\n}\n\n\n//\n// Utilities for toggling `display` in print\n//\n\n@media print {\n @each $value in $displays {\n .d-print-#{$value} { display: $value !important; }\n }\n}\n","// stylelint-disable declaration-no-important\n\n// Flex variation\n//\n// Custom styles for additional flex alignment options.\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n .flex#{$infix}-row { flex-direction: row !important; }\n .flex#{$infix}-column { flex-direction: column !important; }\n .flex#{$infix}-row-reverse { flex-direction: row-reverse !important; }\n .flex#{$infix}-column-reverse { flex-direction: column-reverse !important; }\n\n .flex#{$infix}-wrap { flex-wrap: wrap !important; }\n .flex#{$infix}-nowrap { flex-wrap: nowrap !important; }\n .flex#{$infix}-wrap-reverse { flex-wrap: wrap-reverse !important; }\n .flex#{$infix}-fill { flex: 1 1 auto !important; }\n .flex#{$infix}-grow-0 { flex-grow: 0 !important; }\n .flex#{$infix}-grow-1 { flex-grow: 1 !important; }\n .flex#{$infix}-shrink-0 { flex-shrink: 0 !important; }\n .flex#{$infix}-shrink-1 { flex-shrink: 1 !important; }\n\n .justify-content#{$infix}-start { justify-content: flex-start !important; }\n .justify-content#{$infix}-end { justify-content: flex-end !important; }\n .justify-content#{$infix}-center { justify-content: center !important; }\n .justify-content#{$infix}-between { justify-content: space-between !important; }\n .justify-content#{$infix}-around { justify-content: space-around !important; }\n\n .align-items#{$infix}-start { align-items: flex-start !important; }\n .align-items#{$infix}-end { align-items: flex-end !important; }\n .align-items#{$infix}-center { align-items: center !important; }\n .align-items#{$infix}-baseline { align-items: baseline !important; }\n .align-items#{$infix}-stretch { align-items: stretch !important; }\n\n .align-content#{$infix}-start { align-content: flex-start !important; }\n .align-content#{$infix}-end { align-content: flex-end !important; }\n .align-content#{$infix}-center { align-content: center !important; }\n .align-content#{$infix}-between { align-content: space-between !important; }\n .align-content#{$infix}-around { align-content: space-around !important; }\n .align-content#{$infix}-stretch { align-content: stretch !important; }\n\n .align-self#{$infix}-auto { align-self: auto !important; }\n .align-self#{$infix}-start { align-self: flex-start !important; }\n .align-self#{$infix}-end { align-self: flex-end !important; }\n .align-self#{$infix}-center { align-self: center !important; }\n .align-self#{$infix}-baseline { align-self: baseline !important; }\n .align-self#{$infix}-stretch { align-self: stretch !important; }\n }\n}\n","// stylelint-disable declaration-no-important\n\n// Margin and Padding\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n @each $prop, $abbrev in (margin: m, padding: p) {\n @each $size, $length in $spacers {\n .#{$abbrev}#{$infix}-#{$size} { #{$prop}: $length !important; }\n .#{$abbrev}t#{$infix}-#{$size},\n .#{$abbrev}y#{$infix}-#{$size} {\n #{$prop}-top: $length !important;\n }\n .#{$abbrev}r#{$infix}-#{$size},\n .#{$abbrev}x#{$infix}-#{$size} {\n #{$prop}-right: $length !important;\n }\n .#{$abbrev}b#{$infix}-#{$size},\n .#{$abbrev}y#{$infix}-#{$size} {\n #{$prop}-bottom: $length !important;\n }\n .#{$abbrev}l#{$infix}-#{$size},\n .#{$abbrev}x#{$infix}-#{$size} {\n #{$prop}-left: $length !important;\n }\n }\n }\n\n // Negative margins (e.g., where `.mb-n1` is negative version of `.mb-1`)\n @each $size, $length in $spacers {\n @if $size != 0 {\n .m#{$infix}-n#{$size} { margin: -$length !important; }\n .mt#{$infix}-n#{$size},\n .my#{$infix}-n#{$size} {\n margin-top: -$length !important;\n }\n .mr#{$infix}-n#{$size},\n .mx#{$infix}-n#{$size} {\n margin-right: -$length !important;\n }\n .mb#{$infix}-n#{$size},\n .my#{$infix}-n#{$size} {\n margin-bottom: -$length !important;\n }\n .ml#{$infix}-n#{$size},\n .mx#{$infix}-n#{$size} {\n margin-left: -$length !important;\n }\n }\n }\n\n // Some special margin utils\n .m#{$infix}-auto { margin: auto !important; }\n .mt#{$infix}-auto,\n .my#{$infix}-auto {\n margin-top: auto !important;\n }\n .mr#{$infix}-auto,\n .mx#{$infix}-auto {\n margin-right: auto !important;\n }\n .mb#{$infix}-auto,\n .my#{$infix}-auto {\n margin-bottom: auto !important;\n }\n .ml#{$infix}-auto,\n .mx#{$infix}-auto {\n margin-left: auto !important;\n }\n }\n}\n"]} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css new file mode 100644 index 0000000000000000000000000000000000000000..09cf98693fe006384118657b551a3e81fba111f5 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css @@ -0,0 +1,331 @@ +/*! + * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/) + * Copyright 2011-2019 The Bootstrap Authors + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) + */ +*, +*::before, +*::after { + box-sizing: border-box; +} + +html { + font-family: sans-serif; + line-height: 1.15; + -webkit-text-size-adjust: 100%; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { + display: block; +} + +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + text-align: left; + background-color: #fff; +} + +[tabindex="-1"]:focus { + outline: 0 !important; +} + +hr { + box-sizing: content-box; + height: 0; + overflow: visible; +} + +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 0.5rem; +} + +p { + margin-top: 0; + margin-bottom: 1rem; +} + +abbr[title], +abbr[data-original-title] { + text-decoration: underline; + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; + cursor: help; + border-bottom: 0; + -webkit-text-decoration-skip-ink: none; + text-decoration-skip-ink: none; +} + +address { + margin-bottom: 1rem; + font-style: normal; + line-height: inherit; +} + +ol, +ul, +dl { + margin-top: 0; + margin-bottom: 1rem; +} + +ol ol, +ul ul, +ol ul, +ul ol { + margin-bottom: 0; +} + +dt { + font-weight: 700; +} + +dd { + margin-bottom: .5rem; + margin-left: 0; +} + +blockquote { + margin: 0 0 1rem; +} + +b, +strong { + font-weight: bolder; +} + +small { + font-size: 80%; +} + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} + +sub { + bottom: -.25em; +} + +sup { + top: -.5em; +} + +a { + color: #007bff; + text-decoration: none; + background-color: transparent; +} + +a:hover { + color: #0056b3; + text-decoration: underline; +} + +a:not([href]):not([tabindex]) { + color: inherit; + text-decoration: none; +} + +a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus { + color: inherit; + text-decoration: none; +} + +a:not([href]):not([tabindex]):focus { + outline: 0; +} + +pre, +code, +kbd, +samp { + font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + font-size: 1em; +} + +pre { + margin-top: 0; + margin-bottom: 1rem; + overflow: auto; +} + +figure { + margin: 0 0 1rem; +} + +img { + vertical-align: middle; + border-style: none; +} + +svg { + overflow: hidden; + vertical-align: middle; +} + +table { + border-collapse: collapse; +} + +caption { + padding-top: 0.75rem; + padding-bottom: 0.75rem; + color: #6c757d; + text-align: left; + caption-side: bottom; +} + +th { + text-align: inherit; +} + +label { + display: inline-block; + margin-bottom: 0.5rem; +} + +button { + border-radius: 0; +} + +button:focus { + outline: 1px dotted; + outline: 5px auto -webkit-focus-ring-color; +} + +input, +button, +select, +optgroup, +textarea { + margin: 0; + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +button, +input { + overflow: visible; +} + +button, +select { + text-transform: none; +} + +select { + word-wrap: normal; +} + +button, +[type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} + +button:not(:disabled), +[type="button"]:not(:disabled), +[type="reset"]:not(:disabled), +[type="submit"]:not(:disabled) { + cursor: pointer; +} + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + padding: 0; + border-style: none; +} + +input[type="radio"], +input[type="checkbox"] { + box-sizing: border-box; + padding: 0; +} + +input[type="date"], +input[type="time"], +input[type="datetime-local"], +input[type="month"] { + -webkit-appearance: listbox; +} + +textarea { + overflow: auto; + resize: vertical; +} + +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} + +legend { + display: block; + width: 100%; + max-width: 100%; + padding: 0; + margin-bottom: .5rem; + font-size: 1.5rem; + line-height: inherit; + color: inherit; + white-space: normal; +} + +progress { + vertical-align: baseline; +} + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +[type="search"] { + outline-offset: -2px; + -webkit-appearance: none; +} + +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +::-webkit-file-upload-button { + font: inherit; + -webkit-appearance: button; +} + +output { + display: inline-block; +} + +summary { + display: list-item; + cursor: pointer; +} + +template { + display: none; +} + +[hidden] { + display: none !important; +} +/*# sourceMappingURL=bootstrap-reboot.css.map */ \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map new file mode 100644 index 0000000000000000000000000000000000000000..d0b0f023ec463797cdd343fe0c9220caf2883031 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../scss/bootstrap-reboot.scss","bootstrap-reboot.css","../../scss/_reboot.scss","../../scss/_variables.scss","../../scss/vendor/_rfs.scss","../../scss/mixins/_hover.scss"],"names":[],"mappings":"AAAA;;;;;;ECME;ACYF;;;EAGE,sBAAsB;ADVxB;;ACaA;EACE,uBAAuB;EACvB,iBAAiB;EACjB,8BAA8B;EAC9B,6CCXa;AFCf;;ACgBA;EACE,cAAc;ADbhB;;ACuBA;EACE,SAAS;EACT,kMCiOiN;ECjJ7M,eAtCY;EFxChB,gBC0O+B;EDzO/B,gBC8O+B;ED7O/B,cCnCgB;EDoChB,gBAAgB;EAChB,sBC9Ca;AF0Bf;;AAEA;EC2BE,qBAAqB;ADzBvB;;ACkCA;EACE,uBAAuB;EACvB,SAAS;EACT,iBAAiB;AD/BnB;;AC4CA;EACE,aAAa;EACb,qBCgNuC;AFzPzC;;ACgDA;EACE,aAAa;EACb,mBCoF8B;AFjIhC;;ACwDA;;EAEE,0BAA0B;EAC1B,yCAAiC;EAAjC,iCAAiC;EACjC,YAAY;EACZ,gBAAgB;EAChB,sCAA8B;EAA9B,8BAA8B;ADrDhC;;ACwDA;EACE,mBAAmB;EACnB,kBAAkB;EAClB,oBAAoB;ADrDtB;;ACwDA;;;EAGE,aAAa;EACb,mBAAmB;ADrDrB;;ACwDA;;;;EAIE,gBAAgB;ADrDlB;;ACwDA;EACE,gBCiJ+B;AFtMjC;;ACwDA;EACE,oBAAoB;EACpB,cAAc;ADrDhB;;ACwDA;EACE,gBAAgB;ADrDlB;;ACwDA;;EAEE,mBCoIkC;AFzLpC;;ACwDA;EEpFI,cAAW;AHgCf;;AC6DA;;EAEE,kBAAkB;EE/FhB,cAAW;EFiGb,cAAc;EACd,wBAAwB;AD1D1B;;AC6DA;EAAM,cAAc;ADzDpB;;AC0DA;EAAM,UAAU;ADtDhB;;AC6DA;EACE,cClJe;EDmJf,qBCX4C;EDY5C,6BAA6B;AD1D/B;;AIlHE;EH+KE,cCd8D;EDe9D,0BCd+C;AF3CnD;;ACmEA;EACE,cAAc;EACd,qBAAqB;ADhEvB;;AIxHE;EH2LE,cAAc;EACd,qBAAqB;AD/DzB;;ACyDA;EAUI,UAAU;AD/Dd;;ACwEA;;;;EAIE,iGCoDgH;ECzM9G,cAAW;AHiFf;;ACwEA;EAEE,aAAa;EAEb,mBAAmB;EAEnB,cAAc;ADxEhB;;ACgFA;EAEE,gBAAgB;AD9ElB;;ACsFA;EACE,sBAAsB;EACtB,kBAAkB;ADnFpB;;ACsFA;EAGE,gBAAgB;EAChB,sBAAsB;ADrFxB;;AC6FA;EACE,yBAAyB;AD1F3B;;AC6FA;EACE,oBC2EkC;ED1ElC,uBC0EkC;EDzElC,cCpQgB;EDqQhB,gBAAgB;EAChB,oBAAoB;AD1FtB;;AC6FA;EAGE,mBAAmB;AD5FrB;;ACoGA;EAEE,qBAAqB;EACrB,qBC4J2C;AF9P7C;;ACwGA;EAEE,gBAAgB;ADtGlB;;AC6GA;EACE,mBAAmB;EACnB,0CAA0C;AD1G5C;;AC6GA;;;;;EAKE,SAAS;EACT,oBAAoB;EEtPlB,kBAAW;EFwPb,oBAAoB;AD1GtB;;AC6GA;;EAEE,iBAAiB;AD1GnB;;AC6GA;;EAEE,oBAAoB;AD1GtB;;ACgHA;EACE,iBAAiB;AD7GnB;;ACoHA;;;;EAIE,0BAA0B;ADjH5B;;ACsHE;;;;EAKI,eAAe;ADpHrB;;AC0HA;;;;EAIE,UAAU;EACV,kBAAkB;ADvHpB;;AC0HA;;EAEE,sBAAsB;EACtB,UAAU;ADvHZ;;AC2HA;;;;EASE,2BAA2B;AD7H7B;;ACgIA;EACE,cAAc;EAEd,gBAAgB;AD9HlB;;ACiIA;EAME,YAAY;EAEZ,UAAU;EACV,SAAS;EACT,SAAS;ADpIX;;ACyIA;EACE,cAAc;EACd,WAAW;EACX,eAAe;EACf,UAAU;EACV,oBAAoB;EElShB,iBAtCY;EF0UhB,oBAAoB;EACpB,cAAc;EACd,mBAAmB;ADtIrB;;ACyIA;EACE,wBAAwB;ADtI1B;;AAEA;;EC0IE,YAAY;ADvId;;AAEA;EC6IE,oBAAoB;EACpB,wBAAwB;AD3I1B;;AAEA;ECiJE,wBAAwB;AD/I1B;;ACuJA;EACE,aAAa;EACb,0BAA0B;ADpJ5B;;AC2JA;EACE,qBAAqB;ADxJvB;;AC2JA;EACE,kBAAkB;EAClB,eAAe;ADxJjB;;AC2JA;EACE,aAAa;ADxJf;;AAEA;EC4JE,wBAAwB;AD1J1B","file":"bootstrap-reboot.css","sourcesContent":["/*!\n * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n\n@import \"functions\";\n@import \"variables\";\n@import \"mixins\";\n@import \"reboot\";\n","/*!\n * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nhtml {\n font-family: sans-serif;\n line-height: 1.15;\n -webkit-text-size-adjust: 100%;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\nbody {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #212529;\n text-align: left;\n background-color: #fff;\n}\n\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\nhr {\n box-sizing: content-box;\n height: 0;\n overflow: visible;\n}\n\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n}\n\np {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-original-title] {\n text-decoration: underline;\n text-decoration: underline dotted;\n cursor: help;\n border-bottom: 0;\n text-decoration-skip-ink: none;\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: 700;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0;\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: bolder;\n}\n\nsmall {\n font-size: 80%;\n}\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -.25em;\n}\n\nsup {\n top: -.5em;\n}\n\na {\n color: #007bff;\n text-decoration: none;\n background-color: transparent;\n}\n\na:hover {\n color: #0056b3;\n text-decoration: underline;\n}\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):focus {\n outline: 0;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 1em;\n}\n\npre {\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n}\n\nfigure {\n margin: 0 0 1rem;\n}\n\nimg {\n vertical-align: middle;\n border-style: none;\n}\n\nsvg {\n overflow: hidden;\n vertical-align: middle;\n}\n\ntable {\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n color: #6c757d;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n text-align: inherit;\n}\n\nlabel {\n display: inline-block;\n margin-bottom: 0.5rem;\n}\n\nbutton {\n border-radius: 0;\n}\n\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible;\n}\n\nbutton,\nselect {\n text-transform: none;\n}\n\nselect {\n word-wrap: normal;\n}\n\nbutton,\n[type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\nbutton:not(:disabled),\n[type=\"button\"]:not(:disabled),\n[type=\"reset\"]:not(:disabled),\n[type=\"submit\"]:not(:disabled) {\n cursor: pointer;\n}\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box;\n padding: 0;\n}\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto;\n resize: vertical;\n}\n\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n max-width: 100%;\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit;\n white-space: normal;\n}\n\nprogress {\n vertical-align: baseline;\n}\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n outline-offset: -2px;\n -webkit-appearance: none;\n}\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n::-webkit-file-upload-button {\n font: inherit;\n -webkit-appearance: button;\n}\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item;\n cursor: pointer;\n}\n\ntemplate {\n display: none;\n}\n\n[hidden] {\n display: none !important;\n}\n\n/*# sourceMappingURL=bootstrap-reboot.css.map */","// stylelint-disable at-rule-no-vendor-prefix, declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix\n\n// Reboot\n//\n// Normalization of HTML elements, manually forked from Normalize.css to remove\n// styles targeting irrelevant browsers while applying new styles.\n//\n// Normalize is licensed MIT. https://github.com/necolas/normalize.css\n\n\n// Document\n//\n// 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.\n// 2. Change the default font family in all browsers.\n// 3. Correct the line height in all browsers.\n// 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS.\n// 5. Change the default tap highlight to be completely transparent in iOS.\n\n*,\n*::before,\n*::after {\n box-sizing: border-box; // 1\n}\n\nhtml {\n font-family: sans-serif; // 2\n line-height: 1.15; // 3\n -webkit-text-size-adjust: 100%; // 4\n -webkit-tap-highlight-color: rgba($black, 0); // 5\n}\n\n// Shim for \"new\" HTML5 structural elements to display correctly (IE10, older browsers)\n// TODO: remove in v5\n// stylelint-disable-next-line selector-list-comma-newline-after\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\n// Body\n//\n// 1. Remove the margin in all browsers.\n// 2. As a best practice, apply a default `background-color`.\n// 3. Set an explicit initial text-align value so that we can later use\n// the `inherit` value on things like `` elements.\n\nbody {\n margin: 0; // 1\n font-family: $font-family-base;\n @include font-size($font-size-base);\n font-weight: $font-weight-base;\n line-height: $line-height-base;\n color: $body-color;\n text-align: left; // 3\n background-color: $body-bg; // 2\n}\n\n// Suppress the focus outline on elements that cannot be accessed via keyboard.\n// This prevents an unwanted focus outline from appearing around elements that\n// might still respond to pointer events.\n//\n// Credit: https://github.com/suitcss/base\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\n\n// Content grouping\n//\n// 1. Add the correct box sizing in Firefox.\n// 2. Show the overflow in Edge and IE.\n\nhr {\n box-sizing: content-box; // 1\n height: 0; // 1\n overflow: visible; // 2\n}\n\n\n//\n// Typography\n//\n\n// Remove top margins from headings\n//\n// By default, `

`-`

` all receive top and bottom margins. We nuke the top\n// margin for easier control within type scales as it avoids margin collapsing.\n// stylelint-disable-next-line selector-list-comma-newline-after\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: $headings-margin-bottom;\n}\n\n// Reset margins on paragraphs\n//\n// Similarly, the top margin on `

`s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n// Abbreviations\n//\n// 1. Duplicate behavior to the data-* attribute for our tooltip plugin\n// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n// 3. Add explicit cursor to indicate changed behavior.\n// 4. Remove the bottom border in Firefox 39-.\n// 5. Prevent the text-decoration to be skipped.\n\nabbr[title],\nabbr[data-original-title] { // 1\n text-decoration: underline; // 2\n text-decoration: underline dotted; // 2\n cursor: help; // 3\n border-bottom: 0; // 4\n text-decoration-skip-ink: none; // 5\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // Undo browser default\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: $font-weight-bolder; // Add the correct font weight in Chrome, Edge, and Safari\n}\n\nsmall {\n @include font-size(80%); // Add the correct font size in all browsers\n}\n\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n//\n\nsub,\nsup {\n position: relative;\n @include font-size(75%);\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n//\n// Links\n//\n\na {\n color: $link-color;\n text-decoration: $link-decoration;\n background-color: transparent; // Remove the gray background on active links in IE 10.\n\n @include hover {\n color: $link-hover-color;\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href)\n// which have not been made explicitly keyboard-focusable (without tabindex).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n\n @include hover-focus {\n color: inherit;\n text-decoration: none;\n }\n\n &:focus {\n outline: 0;\n }\n}\n\n\n//\n// Code\n//\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-monospace;\n @include font-size(1em); // Correct the odd `em` font sizing in all browsers.\n}\n\npre {\n // Remove browser default top margin\n margin-top: 0;\n // Reset browser default of `1em` to use `rem`s\n margin-bottom: 1rem;\n // Don't allow content to break outside\n overflow: auto;\n}\n\n\n//\n// Figures\n//\n\nfigure {\n // Apply a consistent margin strategy (matches our type styles).\n margin: 0 0 1rem;\n}\n\n\n//\n// Images and content\n//\n\nimg {\n vertical-align: middle;\n border-style: none; // Remove the border on images inside links in IE 10-.\n}\n\nsvg {\n // Workaround for the SVG overflow bug in IE10/11 is still required.\n // See https://github.com/twbs/bootstrap/issues/26878\n overflow: hidden;\n vertical-align: middle;\n}\n\n\n//\n// Tables\n//\n\ntable {\n border-collapse: collapse; // Prevent double borders\n}\n\ncaption {\n padding-top: $table-cell-padding;\n padding-bottom: $table-cell-padding;\n color: $table-caption-color;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n // Matches default `` alignment by inheriting from the ``, or the\n // closest parent with a set `text-align`.\n text-align: inherit;\n}\n\n\n//\n// Forms\n//\n\nlabel {\n // Allow labels to use `margin` for spacing.\n display: inline-block;\n margin-bottom: $label-margin-bottom;\n}\n\n// Remove the default `border-radius` that macOS Chrome adds.\n//\n// Details at https://github.com/twbs/bootstrap/issues/24093\nbutton {\n // stylelint-disable-next-line property-blacklist\n border-radius: 0;\n}\n\n// Work around a Firefox/IE bug where the transparent `button` background\n// results in a loss of the default `button` focus styles.\n//\n// Credit: https://github.com/suitcss/base/\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0; // Remove the margin in Firefox and Safari\n font-family: inherit;\n @include font-size(inherit);\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible; // Show the overflow in Edge\n}\n\nbutton,\nselect {\n text-transform: none; // Remove the inheritance of text transform in Firefox\n}\n\n// Remove the inheritance of word-wrap in Safari.\n//\n// Details at https://github.com/twbs/bootstrap/issues/24990\nselect {\n word-wrap: normal;\n}\n\n\n// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`\n// controls in Android 4.\n// 2. Correct the inability to style clickable types in iOS and Safari.\nbutton,\n[type=\"button\"], // 1\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button; // 2\n}\n\n// Opinionated: add \"hand\" cursor to non-disabled button elements.\n@if $enable-pointer-cursor-for-buttons {\n button,\n [type=\"button\"],\n [type=\"reset\"],\n [type=\"submit\"] {\n &:not(:disabled) {\n cursor: pointer;\n }\n }\n}\n\n// Remove inner border and padding from Firefox, but don't restore the outline like Normalize.\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box; // 1. Add the correct box sizing in IE 10-\n padding: 0; // 2. Remove the padding in IE 10-\n}\n\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n // Remove the default appearance of temporal inputs to avoid a Mobile Safari\n // bug where setting a custom line-height prevents text from being vertically\n // centered within the input.\n // See https://bugs.webkit.org/show_bug.cgi?id=139848\n // and https://github.com/twbs/bootstrap/issues/11266\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto; // Remove the default vertical scrollbar in IE.\n // Textareas should really only resize vertically so they don't break their (horizontal) containers.\n resize: vertical;\n}\n\nfieldset {\n // Browsers set a default `min-width: min-content;` on fieldsets,\n // unlike e.g. `

`s, which have `min-width: 0;` by default.\n // So we reset that to ensure fieldsets behave more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359\n // and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements\n min-width: 0;\n // Reset the default outline behavior of fieldsets so they don't affect page layout.\n padding: 0;\n margin: 0;\n border: 0;\n}\n\n// 1. Correct the text wrapping in Edge and IE.\n// 2. Correct the color inheritance from `fieldset` elements in IE.\nlegend {\n display: block;\n width: 100%;\n max-width: 100%; // 1\n padding: 0;\n margin-bottom: .5rem;\n @include font-size(1.5rem);\n line-height: inherit;\n color: inherit; // 2\n white-space: normal; // 1\n}\n\nprogress {\n vertical-align: baseline; // Add the correct vertical alignment in Chrome, Firefox, and Opera.\n}\n\n// Correct the cursor style of increment and decrement buttons in Chrome.\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n // This overrides the extra rounded corners on search inputs in iOS so that our\n // `.form-control` class can properly style them. Note that this cannot simply\n // be added to `.form-control` as it's not specific enough. For details, see\n // https://github.com/twbs/bootstrap/issues/11586.\n outline-offset: -2px; // 2. Correct the outline style in Safari.\n -webkit-appearance: none;\n}\n\n//\n// Remove the inner padding in Chrome and Safari on macOS.\n//\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// 1. Correct the inability to style clickable types in iOS and Safari.\n// 2. Change font properties to `inherit` in Safari.\n//\n\n::-webkit-file-upload-button {\n font: inherit; // 2\n -webkit-appearance: button; // 1\n}\n\n//\n// Correct element displays\n//\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item; // Add the correct display in all browsers\n cursor: pointer;\n}\n\ntemplate {\n display: none; // Add the correct display in IE\n}\n\n// Always hide an element with the `hidden` HTML attribute (from PureCSS).\n// Needed for proper display in IE 10-.\n[hidden] {\n display: none !important;\n}\n","// Variables\n//\n// Variables should follow the `$component-state-property-size` formula for\n// consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs.\n\n// Color system\n\n$white: #fff !default;\n$gray-100: #f8f9fa !default;\n$gray-200: #e9ecef !default;\n$gray-300: #dee2e6 !default;\n$gray-400: #ced4da !default;\n$gray-500: #adb5bd !default;\n$gray-600: #6c757d !default;\n$gray-700: #495057 !default;\n$gray-800: #343a40 !default;\n$gray-900: #212529 !default;\n$black: #000 !default;\n\n$grays: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$grays: map-merge(\n (\n \"100\": $gray-100,\n \"200\": $gray-200,\n \"300\": $gray-300,\n \"400\": $gray-400,\n \"500\": $gray-500,\n \"600\": $gray-600,\n \"700\": $gray-700,\n \"800\": $gray-800,\n \"900\": $gray-900\n ),\n $grays\n);\n\n$blue: #007bff !default;\n$indigo: #6610f2 !default;\n$purple: #6f42c1 !default;\n$pink: #e83e8c !default;\n$red: #dc3545 !default;\n$orange: #fd7e14 !default;\n$yellow: #ffc107 !default;\n$green: #28a745 !default;\n$teal: #20c997 !default;\n$cyan: #17a2b8 !default;\n\n$colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$colors: map-merge(\n (\n \"blue\": $blue,\n \"indigo\": $indigo,\n \"purple\": $purple,\n \"pink\": $pink,\n \"red\": $red,\n \"orange\": $orange,\n \"yellow\": $yellow,\n \"green\": $green,\n \"teal\": $teal,\n \"cyan\": $cyan,\n \"white\": $white,\n \"gray\": $gray-600,\n \"gray-dark\": $gray-800\n ),\n $colors\n);\n\n$primary: $blue !default;\n$secondary: $gray-600 !default;\n$success: $green !default;\n$info: $cyan !default;\n$warning: $yellow !default;\n$danger: $red !default;\n$light: $gray-100 !default;\n$dark: $gray-800 !default;\n\n$theme-colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$theme-colors: map-merge(\n (\n \"primary\": $primary,\n \"secondary\": $secondary,\n \"success\": $success,\n \"info\": $info,\n \"warning\": $warning,\n \"danger\": $danger,\n \"light\": $light,\n \"dark\": $dark\n ),\n $theme-colors\n);\n\n// Set a specific jump point for requesting color jumps\n$theme-color-interval: 8% !default;\n\n// The yiq lightness value that determines when the lightness of color changes from \"dark\" to \"light\". Acceptable values are between 0 and 255.\n$yiq-contrasted-threshold: 150 !default;\n\n// Customize the light and dark text colors for use in our YIQ color contrast function.\n$yiq-text-dark: $gray-900 !default;\n$yiq-text-light: $white !default;\n\n\n// Options\n//\n// Quickly modify global styling by enabling or disabling optional features.\n\n$enable-caret: true !default;\n$enable-rounded: true !default;\n$enable-shadows: false !default;\n$enable-gradients: false !default;\n$enable-transitions: true !default;\n$enable-prefers-reduced-motion-media-query: true !default;\n$enable-hover-media-query: false !default; // Deprecated, no longer affects any compiled CSS\n$enable-grid-classes: true !default;\n$enable-pointer-cursor-for-buttons: true !default;\n$enable-print-styles: true !default;\n$enable-responsive-font-sizes: false !default;\n$enable-validation-icons: true !default;\n$enable-deprecation-messages: true !default;\n\n\n// Spacing\n//\n// Control the default styling of most Bootstrap elements by modifying these\n// variables. Mostly focused on spacing.\n// You can add more entries to the $spacers map, should you need more variation.\n\n$spacer: 1rem !default;\n$spacers: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$spacers: map-merge(\n (\n 0: 0,\n 1: ($spacer * .25),\n 2: ($spacer * .5),\n 3: $spacer,\n 4: ($spacer * 1.5),\n 5: ($spacer * 3)\n ),\n $spacers\n);\n\n// This variable affects the `.h-*` and `.w-*` classes.\n$sizes: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$sizes: map-merge(\n (\n 25: 25%,\n 50: 50%,\n 75: 75%,\n 100: 100%,\n auto: auto\n ),\n $sizes\n);\n\n\n// Body\n//\n// Settings for the `` element.\n\n$body-bg: $white !default;\n$body-color: $gray-900 !default;\n\n\n// Links\n//\n// Style anchor elements.\n\n$link-color: theme-color(\"primary\") !default;\n$link-decoration: none !default;\n$link-hover-color: darken($link-color, 15%) !default;\n$link-hover-decoration: underline !default;\n// Darken percentage for links with `.text-*` class (e.g. `.text-success`)\n$emphasized-link-hover-darken-percentage: 15% !default;\n\n// Paragraphs\n//\n// Style p element.\n\n$paragraph-margin-bottom: 1rem !default;\n\n\n// Grid breakpoints\n//\n// Define the minimum dimensions at which your layout will change,\n// adapting to different screen sizes, for use in media queries.\n\n$grid-breakpoints: (\n xs: 0,\n sm: 576px,\n md: 768px,\n lg: 992px,\n xl: 1200px\n) !default;\n\n@include _assert-ascending($grid-breakpoints, \"$grid-breakpoints\");\n@include _assert-starts-at-zero($grid-breakpoints, \"$grid-breakpoints\");\n\n\n// Grid containers\n//\n// Define the maximum width of `.container` for different screen sizes.\n\n$container-max-widths: (\n sm: 540px,\n md: 720px,\n lg: 960px,\n xl: 1140px\n) !default;\n\n@include _assert-ascending($container-max-widths, \"$container-max-widths\");\n\n\n// Grid columns\n//\n// Set the number of columns and specify the width of the gutters.\n\n$grid-columns: 12 !default;\n$grid-gutter-width: 30px !default;\n\n\n// Components\n//\n// Define common padding and border radius sizes and more.\n\n$line-height-lg: 1.5 !default;\n$line-height-sm: 1.5 !default;\n\n$border-width: 1px !default;\n$border-color: $gray-300 !default;\n\n$border-radius: .25rem !default;\n$border-radius-lg: .3rem !default;\n$border-radius-sm: .2rem !default;\n\n$rounded-pill: 50rem !default;\n\n$box-shadow-sm: 0 .125rem .25rem rgba($black, .075) !default;\n$box-shadow: 0 .5rem 1rem rgba($black, .15) !default;\n$box-shadow-lg: 0 1rem 3rem rgba($black, .175) !default;\n\n$component-active-color: $white !default;\n$component-active-bg: theme-color(\"primary\") !default;\n\n$caret-width: .3em !default;\n$caret-vertical-align: $caret-width * .85 !default;\n$caret-spacing: $caret-width * .85 !default;\n\n$transition-base: all .2s ease-in-out !default;\n$transition-fade: opacity .15s linear !default;\n$transition-collapse: height .35s ease !default;\n\n$embed-responsive-aspect-ratios: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$embed-responsive-aspect-ratios: join(\n (\n (21 9),\n (16 9),\n (4 3),\n (1 1),\n ),\n $embed-responsive-aspect-ratios\n);\n\n// Typography\n//\n// Font, line-height, and color for body text, headings, and more.\n\n// stylelint-disable value-keyword-case\n$font-family-sans-serif: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\" !default;\n$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace !default;\n$font-family-base: $font-family-sans-serif !default;\n// stylelint-enable value-keyword-case\n\n$font-size-base: 1rem !default; // Assumes the browser default, typically `16px`\n$font-size-lg: $font-size-base * 1.25 !default;\n$font-size-sm: $font-size-base * .875 !default;\n\n$font-weight-lighter: lighter !default;\n$font-weight-light: 300 !default;\n$font-weight-normal: 400 !default;\n$font-weight-bold: 700 !default;\n$font-weight-bolder: bolder !default;\n\n$font-weight-base: $font-weight-normal !default;\n$line-height-base: 1.5 !default;\n\n$h1-font-size: $font-size-base * 2.5 !default;\n$h2-font-size: $font-size-base * 2 !default;\n$h3-font-size: $font-size-base * 1.75 !default;\n$h4-font-size: $font-size-base * 1.5 !default;\n$h5-font-size: $font-size-base * 1.25 !default;\n$h6-font-size: $font-size-base !default;\n\n$headings-margin-bottom: $spacer / 2 !default;\n$headings-font-family: null !default;\n$headings-font-weight: 500 !default;\n$headings-line-height: 1.2 !default;\n$headings-color: null !default;\n\n$display1-size: 6rem !default;\n$display2-size: 5.5rem !default;\n$display3-size: 4.5rem !default;\n$display4-size: 3.5rem !default;\n\n$display1-weight: 300 !default;\n$display2-weight: 300 !default;\n$display3-weight: 300 !default;\n$display4-weight: 300 !default;\n$display-line-height: $headings-line-height !default;\n\n$lead-font-size: $font-size-base * 1.25 !default;\n$lead-font-weight: 300 !default;\n\n$small-font-size: 80% !default;\n\n$text-muted: $gray-600 !default;\n\n$blockquote-small-color: $gray-600 !default;\n$blockquote-small-font-size: $small-font-size !default;\n$blockquote-font-size: $font-size-base * 1.25 !default;\n\n$hr-border-color: rgba($black, .1) !default;\n$hr-border-width: $border-width !default;\n\n$mark-padding: .2em !default;\n\n$dt-font-weight: $font-weight-bold !default;\n\n$kbd-box-shadow: inset 0 -.1rem 0 rgba($black, .25) !default;\n$nested-kbd-font-weight: $font-weight-bold !default;\n\n$list-inline-padding: .5rem !default;\n\n$mark-bg: #fcf8e3 !default;\n\n$hr-margin-y: $spacer !default;\n\n\n// Tables\n//\n// Customizes the `.table` component with basic values, each used across all table variations.\n\n$table-cell-padding: .75rem !default;\n$table-cell-padding-sm: .3rem !default;\n\n$table-color: $body-color !default;\n$table-bg: null !default;\n$table-accent-bg: rgba($black, .05) !default;\n$table-hover-color: $table-color !default;\n$table-hover-bg: rgba($black, .075) !default;\n$table-active-bg: $table-hover-bg !default;\n\n$table-border-width: $border-width !default;\n$table-border-color: $border-color !default;\n\n$table-head-bg: $gray-200 !default;\n$table-head-color: $gray-700 !default;\n\n$table-dark-color: $white !default;\n$table-dark-bg: $gray-800 !default;\n$table-dark-accent-bg: rgba($white, .05) !default;\n$table-dark-hover-color: $table-dark-color !default;\n$table-dark-hover-bg: rgba($white, .075) !default;\n$table-dark-border-color: lighten($table-dark-bg, 7.5%) !default;\n$table-dark-color: $white !default;\n\n$table-striped-order: odd !default;\n\n$table-caption-color: $text-muted !default;\n\n$table-bg-level: -9 !default;\n$table-border-level: -6 !default;\n\n\n// Buttons + Forms\n//\n// Shared variables that are reassigned to `$input-` and `$btn-` specific variables.\n\n$input-btn-padding-y: .375rem !default;\n$input-btn-padding-x: .75rem !default;\n$input-btn-font-family: null !default;\n$input-btn-font-size: $font-size-base !default;\n$input-btn-line-height: $line-height-base !default;\n\n$input-btn-focus-width: .2rem !default;\n$input-btn-focus-color: rgba($component-active-bg, .25) !default;\n$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color !default;\n\n$input-btn-padding-y-sm: .25rem !default;\n$input-btn-padding-x-sm: .5rem !default;\n$input-btn-font-size-sm: $font-size-sm !default;\n$input-btn-line-height-sm: $line-height-sm !default;\n\n$input-btn-padding-y-lg: .5rem !default;\n$input-btn-padding-x-lg: 1rem !default;\n$input-btn-font-size-lg: $font-size-lg !default;\n$input-btn-line-height-lg: $line-height-lg !default;\n\n$input-btn-border-width: $border-width !default;\n\n\n// Buttons\n//\n// For each of Bootstrap's buttons, define text, background, and border color.\n\n$btn-padding-y: $input-btn-padding-y !default;\n$btn-padding-x: $input-btn-padding-x !default;\n$btn-font-family: $input-btn-font-family !default;\n$btn-font-size: $input-btn-font-size !default;\n$btn-line-height: $input-btn-line-height !default;\n\n$btn-padding-y-sm: $input-btn-padding-y-sm !default;\n$btn-padding-x-sm: $input-btn-padding-x-sm !default;\n$btn-font-size-sm: $input-btn-font-size-sm !default;\n$btn-line-height-sm: $input-btn-line-height-sm !default;\n\n$btn-padding-y-lg: $input-btn-padding-y-lg !default;\n$btn-padding-x-lg: $input-btn-padding-x-lg !default;\n$btn-font-size-lg: $input-btn-font-size-lg !default;\n$btn-line-height-lg: $input-btn-line-height-lg !default;\n\n$btn-border-width: $input-btn-border-width !default;\n\n$btn-font-weight: $font-weight-normal !default;\n$btn-box-shadow: inset 0 1px 0 rgba($white, .15), 0 1px 1px rgba($black, .075) !default;\n$btn-focus-width: $input-btn-focus-width !default;\n$btn-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$btn-disabled-opacity: .65 !default;\n$btn-active-box-shadow: inset 0 3px 5px rgba($black, .125) !default;\n\n$btn-link-disabled-color: $gray-600 !default;\n\n$btn-block-spacing-y: .5rem !default;\n\n// Allows for customizing button radius independently from global border radius\n$btn-border-radius: $border-radius !default;\n$btn-border-radius-lg: $border-radius-lg !default;\n$btn-border-radius-sm: $border-radius-sm !default;\n\n$btn-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n\n// Forms\n\n$label-margin-bottom: .5rem !default;\n\n$input-padding-y: $input-btn-padding-y !default;\n$input-padding-x: $input-btn-padding-x !default;\n$input-font-family: $input-btn-font-family !default;\n$input-font-size: $input-btn-font-size !default;\n$input-font-weight: $font-weight-base !default;\n$input-line-height: $input-btn-line-height !default;\n\n$input-padding-y-sm: $input-btn-padding-y-sm !default;\n$input-padding-x-sm: $input-btn-padding-x-sm !default;\n$input-font-size-sm: $input-btn-font-size-sm !default;\n$input-line-height-sm: $input-btn-line-height-sm !default;\n\n$input-padding-y-lg: $input-btn-padding-y-lg !default;\n$input-padding-x-lg: $input-btn-padding-x-lg !default;\n$input-font-size-lg: $input-btn-font-size-lg !default;\n$input-line-height-lg: $input-btn-line-height-lg !default;\n\n$input-bg: $white !default;\n$input-disabled-bg: $gray-200 !default;\n\n$input-color: $gray-700 !default;\n$input-border-color: $gray-400 !default;\n$input-border-width: $input-btn-border-width !default;\n$input-box-shadow: inset 0 1px 1px rgba($black, .075) !default;\n\n$input-border-radius: $border-radius !default;\n$input-border-radius-lg: $border-radius-lg !default;\n$input-border-radius-sm: $border-radius-sm !default;\n\n$input-focus-bg: $input-bg !default;\n$input-focus-border-color: lighten($component-active-bg, 25%) !default;\n$input-focus-color: $input-color !default;\n$input-focus-width: $input-btn-focus-width !default;\n$input-focus-box-shadow: $input-btn-focus-box-shadow !default;\n\n$input-placeholder-color: $gray-600 !default;\n$input-plaintext-color: $body-color !default;\n\n$input-height-border: $input-border-width * 2 !default;\n\n$input-height-inner: calc(#{$input-line-height * 1em} + #{$input-padding-y * 2}) !default;\n$input-height-inner-half: calc(#{$input-line-height * .5em} + #{$input-padding-y}) !default;\n$input-height-inner-quarter: calc(#{$input-line-height * .25em} + #{$input-padding-y / 2}) !default;\n\n$input-height: calc(#{$input-line-height * 1em} + #{$input-padding-y * 2} + #{$input-height-border}) !default;\n$input-height-sm: calc(#{$input-line-height-sm * 1em} + #{$input-btn-padding-y-sm * 2} + #{$input-height-border}) !default;\n$input-height-lg: calc(#{$input-line-height-lg * 1em} + #{$input-btn-padding-y-lg * 2} + #{$input-height-border}) !default;\n\n$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$form-text-margin-top: .25rem !default;\n\n$form-check-input-gutter: 1.25rem !default;\n$form-check-input-margin-y: .3rem !default;\n$form-check-input-margin-x: .25rem !default;\n\n$form-check-inline-margin-x: .75rem !default;\n$form-check-inline-input-margin-x: .3125rem !default;\n\n$form-grid-gutter-width: 10px !default;\n$form-group-margin-bottom: 1rem !default;\n\n$input-group-addon-color: $input-color !default;\n$input-group-addon-bg: $gray-200 !default;\n$input-group-addon-border-color: $input-border-color !default;\n\n$custom-forms-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$custom-control-gutter: .5rem !default;\n$custom-control-spacer-x: 1rem !default;\n\n$custom-control-indicator-size: 1rem !default;\n$custom-control-indicator-bg: $input-bg !default;\n\n$custom-control-indicator-bg-size: 50% 50% !default;\n$custom-control-indicator-box-shadow: $input-box-shadow !default;\n$custom-control-indicator-border-color: $gray-500 !default;\n$custom-control-indicator-border-width: $input-border-width !default;\n\n$custom-control-indicator-disabled-bg: $input-disabled-bg !default;\n$custom-control-label-disabled-color: $gray-600 !default;\n\n$custom-control-indicator-checked-color: $component-active-color !default;\n$custom-control-indicator-checked-bg: $component-active-bg !default;\n$custom-control-indicator-checked-disabled-bg: rgba(theme-color(\"primary\"), .5) !default;\n$custom-control-indicator-checked-box-shadow: none !default;\n$custom-control-indicator-checked-border-color: $custom-control-indicator-checked-bg !default;\n\n$custom-control-indicator-focus-box-shadow: $input-focus-box-shadow !default;\n$custom-control-indicator-focus-border-color: $input-focus-border-color !default;\n\n$custom-control-indicator-active-color: $component-active-color !default;\n$custom-control-indicator-active-bg: lighten($component-active-bg, 35%) !default;\n$custom-control-indicator-active-box-shadow: none !default;\n$custom-control-indicator-active-border-color: $custom-control-indicator-active-bg !default;\n\n$custom-checkbox-indicator-border-radius: $border-radius !default;\n$custom-checkbox-indicator-icon-checked: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='#{$custom-control-indicator-checked-color}' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n\n$custom-checkbox-indicator-indeterminate-bg: $component-active-bg !default;\n$custom-checkbox-indicator-indeterminate-color: $custom-control-indicator-checked-color !default;\n$custom-checkbox-indicator-icon-indeterminate: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3e%3cpath stroke='#{$custom-checkbox-indicator-indeterminate-color}' d='M0 2h4'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$custom-checkbox-indicator-indeterminate-box-shadow: none !default;\n$custom-checkbox-indicator-indeterminate-border-color: $custom-checkbox-indicator-indeterminate-bg !default;\n\n$custom-radio-indicator-border-radius: 50% !default;\n$custom-radio-indicator-icon-checked: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='#{$custom-control-indicator-checked-color}'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n\n$custom-switch-width: $custom-control-indicator-size * 1.75 !default;\n$custom-switch-indicator-border-radius: $custom-control-indicator-size / 2 !default;\n$custom-switch-indicator-size: calc(#{$custom-control-indicator-size} - #{$custom-control-indicator-border-width * 4}) !default;\n\n$custom-select-padding-y: $input-padding-y !default;\n$custom-select-padding-x: $input-padding-x !default;\n$custom-select-font-family: $input-font-family !default;\n$custom-select-font-size: $input-font-size !default;\n$custom-select-height: $input-height !default;\n$custom-select-indicator-padding: 1rem !default; // Extra padding to account for the presence of the background-image based indicator\n$custom-select-font-weight: $input-font-weight !default;\n$custom-select-line-height: $input-line-height !default;\n$custom-select-color: $input-color !default;\n$custom-select-disabled-color: $gray-600 !default;\n$custom-select-bg: $input-bg !default;\n$custom-select-disabled-bg: $gray-200 !default;\n$custom-select-bg-size: 8px 10px !default; // In pixels because image dimensions\n$custom-select-indicator-color: $gray-800 !default;\n$custom-select-indicator: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='#{$custom-select-indicator-color}' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$custom-select-background: $custom-select-indicator no-repeat right $custom-select-padding-x center / $custom-select-bg-size !default; // Used so we can have multiple background elements (e.g., arrow and feedback icon)\n\n$custom-select-feedback-icon-padding-right: calc((1em + #{2 * $custom-select-padding-y}) * 3 / 4 + #{$custom-select-padding-x + $custom-select-indicator-padding}) !default;\n$custom-select-feedback-icon-position: center right ($custom-select-padding-x + $custom-select-indicator-padding) !default;\n$custom-select-feedback-icon-size: $input-height-inner-half $input-height-inner-half !default;\n\n$custom-select-border-width: $input-border-width !default;\n$custom-select-border-color: $input-border-color !default;\n$custom-select-border-radius: $border-radius !default;\n$custom-select-box-shadow: inset 0 1px 2px rgba($black, .075) !default;\n\n$custom-select-focus-border-color: $input-focus-border-color !default;\n$custom-select-focus-width: $input-focus-width !default;\n$custom-select-focus-box-shadow: 0 0 0 $custom-select-focus-width $input-btn-focus-color !default;\n\n$custom-select-padding-y-sm: $input-padding-y-sm !default;\n$custom-select-padding-x-sm: $input-padding-x-sm !default;\n$custom-select-font-size-sm: $input-font-size-sm !default;\n$custom-select-height-sm: $input-height-sm !default;\n\n$custom-select-padding-y-lg: $input-padding-y-lg !default;\n$custom-select-padding-x-lg: $input-padding-x-lg !default;\n$custom-select-font-size-lg: $input-font-size-lg !default;\n$custom-select-height-lg: $input-height-lg !default;\n\n$custom-range-track-width: 100% !default;\n$custom-range-track-height: .5rem !default;\n$custom-range-track-cursor: pointer !default;\n$custom-range-track-bg: $gray-300 !default;\n$custom-range-track-border-radius: 1rem !default;\n$custom-range-track-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;\n\n$custom-range-thumb-width: 1rem !default;\n$custom-range-thumb-height: $custom-range-thumb-width !default;\n$custom-range-thumb-bg: $component-active-bg !default;\n$custom-range-thumb-border: 0 !default;\n$custom-range-thumb-border-radius: 1rem !default;\n$custom-range-thumb-box-shadow: 0 .1rem .25rem rgba($black, .1) !default;\n$custom-range-thumb-focus-box-shadow: 0 0 0 1px $body-bg, $input-focus-box-shadow !default;\n$custom-range-thumb-focus-box-shadow-width: $input-focus-width !default; // For focus box shadow issue in IE/Edge\n$custom-range-thumb-active-bg: lighten($component-active-bg, 35%) !default;\n$custom-range-thumb-disabled-bg: $gray-500 !default;\n\n$custom-file-height: $input-height !default;\n$custom-file-height-inner: $input-height-inner !default;\n$custom-file-focus-border-color: $input-focus-border-color !default;\n$custom-file-focus-box-shadow: $input-focus-box-shadow !default;\n$custom-file-disabled-bg: $input-disabled-bg !default;\n\n$custom-file-padding-y: $input-padding-y !default;\n$custom-file-padding-x: $input-padding-x !default;\n$custom-file-line-height: $input-line-height !default;\n$custom-file-font-family: $input-font-family !default;\n$custom-file-font-weight: $input-font-weight !default;\n$custom-file-color: $input-color !default;\n$custom-file-bg: $input-bg !default;\n$custom-file-border-width: $input-border-width !default;\n$custom-file-border-color: $input-border-color !default;\n$custom-file-border-radius: $input-border-radius !default;\n$custom-file-box-shadow: $input-box-shadow !default;\n$custom-file-button-color: $custom-file-color !default;\n$custom-file-button-bg: $input-group-addon-bg !default;\n$custom-file-text: (\n en: \"Browse\"\n) !default;\n\n\n// Form validation\n\n$form-feedback-margin-top: $form-text-margin-top !default;\n$form-feedback-font-size: $small-font-size !default;\n$form-feedback-valid-color: theme-color(\"success\") !default;\n$form-feedback-invalid-color: theme-color(\"danger\") !default;\n\n$form-feedback-icon-valid-color: $form-feedback-valid-color !default;\n$form-feedback-icon-valid: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='#{$form-feedback-icon-valid-color}' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$form-feedback-icon-invalid-color: $form-feedback-invalid-color !default;\n$form-feedback-icon-invalid: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$form-feedback-icon-invalid-color}' viewBox='-2 -2 7 7'%3e%3cpath stroke='#{$form-feedback-icon-invalid-color}' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E\"), \"#\", \"%23\") !default;\n\n$form-validation-states: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$form-validation-states: map-merge(\n (\n \"valid\": (\n \"color\": $form-feedback-valid-color,\n \"icon\": $form-feedback-icon-valid\n ),\n \"invalid\": (\n \"color\": $form-feedback-invalid-color,\n \"icon\": $form-feedback-icon-invalid\n ),\n ),\n $form-validation-states\n);\n\n// Z-index master list\n//\n// Warning: Avoid customizing these values. They're used for a bird's eye view\n// of components dependent on the z-axis and are designed to all work together.\n\n$zindex-dropdown: 1000 !default;\n$zindex-sticky: 1020 !default;\n$zindex-fixed: 1030 !default;\n$zindex-modal-backdrop: 1040 !default;\n$zindex-modal: 1050 !default;\n$zindex-popover: 1060 !default;\n$zindex-tooltip: 1070 !default;\n\n\n// Navs\n\n$nav-link-padding-y: .5rem !default;\n$nav-link-padding-x: 1rem !default;\n$nav-link-disabled-color: $gray-600 !default;\n\n$nav-tabs-border-color: $gray-300 !default;\n$nav-tabs-border-width: $border-width !default;\n$nav-tabs-border-radius: $border-radius !default;\n$nav-tabs-link-hover-border-color: $gray-200 $gray-200 $nav-tabs-border-color !default;\n$nav-tabs-link-active-color: $gray-700 !default;\n$nav-tabs-link-active-bg: $body-bg !default;\n$nav-tabs-link-active-border-color: $gray-300 $gray-300 $nav-tabs-link-active-bg !default;\n\n$nav-pills-border-radius: $border-radius !default;\n$nav-pills-link-active-color: $component-active-color !default;\n$nav-pills-link-active-bg: $component-active-bg !default;\n\n$nav-divider-color: $gray-200 !default;\n$nav-divider-margin-y: $spacer / 2 !default;\n\n\n// Navbar\n\n$navbar-padding-y: $spacer / 2 !default;\n$navbar-padding-x: $spacer !default;\n\n$navbar-nav-link-padding-x: .5rem !default;\n\n$navbar-brand-font-size: $font-size-lg !default;\n// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link\n$nav-link-height: $font-size-base * $line-height-base + $nav-link-padding-y * 2 !default;\n$navbar-brand-height: $navbar-brand-font-size * $line-height-base !default;\n$navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) / 2 !default;\n\n$navbar-toggler-padding-y: .25rem !default;\n$navbar-toggler-padding-x: .75rem !default;\n$navbar-toggler-font-size: $font-size-lg !default;\n$navbar-toggler-border-radius: $btn-border-radius !default;\n\n$navbar-dark-color: rgba($white, .5) !default;\n$navbar-dark-hover-color: rgba($white, .75) !default;\n$navbar-dark-active-color: $white !default;\n$navbar-dark-disabled-color: rgba($white, .25) !default;\n$navbar-dark-toggler-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='#{$navbar-dark-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$navbar-dark-toggler-border-color: rgba($white, .1) !default;\n\n$navbar-light-color: rgba($black, .5) !default;\n$navbar-light-hover-color: rgba($black, .7) !default;\n$navbar-light-active-color: rgba($black, .9) !default;\n$navbar-light-disabled-color: rgba($black, .3) !default;\n$navbar-light-toggler-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='#{$navbar-light-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$navbar-light-toggler-border-color: rgba($black, .1) !default;\n\n$navbar-light-brand-color: $navbar-light-active-color !default;\n$navbar-light-brand-hover-color: $navbar-light-active-color !default;\n$navbar-dark-brand-color: $navbar-dark-active-color !default;\n$navbar-dark-brand-hover-color: $navbar-dark-active-color !default;\n\n\n// Dropdowns\n//\n// Dropdown menu container and contents.\n\n$dropdown-min-width: 10rem !default;\n$dropdown-padding-y: .5rem !default;\n$dropdown-spacer: .125rem !default;\n$dropdown-font-size: $font-size-base !default;\n$dropdown-color: $body-color !default;\n$dropdown-bg: $white !default;\n$dropdown-border-color: rgba($black, .15) !default;\n$dropdown-border-radius: $border-radius !default;\n$dropdown-border-width: $border-width !default;\n$dropdown-inner-border-radius: calc(#{$dropdown-border-radius} - #{$dropdown-border-width}) !default;\n$dropdown-divider-bg: $gray-200 !default;\n$dropdown-divider-margin-y: $nav-divider-margin-y !default;\n$dropdown-box-shadow: 0 .5rem 1rem rgba($black, .175) !default;\n\n$dropdown-link-color: $gray-900 !default;\n$dropdown-link-hover-color: darken($gray-900, 5%) !default;\n$dropdown-link-hover-bg: $gray-100 !default;\n\n$dropdown-link-active-color: $component-active-color !default;\n$dropdown-link-active-bg: $component-active-bg !default;\n\n$dropdown-link-disabled-color: $gray-600 !default;\n\n$dropdown-item-padding-y: .25rem !default;\n$dropdown-item-padding-x: 1.5rem !default;\n\n$dropdown-header-color: $gray-600 !default;\n\n\n// Pagination\n\n$pagination-padding-y: .5rem !default;\n$pagination-padding-x: .75rem !default;\n$pagination-padding-y-sm: .25rem !default;\n$pagination-padding-x-sm: .5rem !default;\n$pagination-padding-y-lg: .75rem !default;\n$pagination-padding-x-lg: 1.5rem !default;\n$pagination-line-height: 1.25 !default;\n\n$pagination-color: $link-color !default;\n$pagination-bg: $white !default;\n$pagination-border-width: $border-width !default;\n$pagination-border-color: $gray-300 !default;\n\n$pagination-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$pagination-focus-outline: 0 !default;\n\n$pagination-hover-color: $link-hover-color !default;\n$pagination-hover-bg: $gray-200 !default;\n$pagination-hover-border-color: $gray-300 !default;\n\n$pagination-active-color: $component-active-color !default;\n$pagination-active-bg: $component-active-bg !default;\n$pagination-active-border-color: $pagination-active-bg !default;\n\n$pagination-disabled-color: $gray-600 !default;\n$pagination-disabled-bg: $white !default;\n$pagination-disabled-border-color: $gray-300 !default;\n\n\n// Jumbotron\n\n$jumbotron-padding: 2rem !default;\n$jumbotron-color: null !default;\n$jumbotron-bg: $gray-200 !default;\n\n\n// Cards\n\n$card-spacer-y: .75rem !default;\n$card-spacer-x: 1.25rem !default;\n$card-border-width: $border-width !default;\n$card-border-radius: $border-radius !default;\n$card-border-color: rgba($black, .125) !default;\n$card-inner-border-radius: calc(#{$card-border-radius} - #{$card-border-width}) !default;\n$card-cap-bg: rgba($black, .03) !default;\n$card-cap-color: null !default;\n$card-color: null !default;\n$card-bg: $white !default;\n\n$card-img-overlay-padding: 1.25rem !default;\n\n$card-group-margin: $grid-gutter-width / 2 !default;\n$card-deck-margin: $card-group-margin !default;\n\n$card-columns-count: 3 !default;\n$card-columns-gap: 1.25rem !default;\n$card-columns-margin: $card-spacer-y !default;\n\n\n// Tooltips\n\n$tooltip-font-size: $font-size-sm !default;\n$tooltip-max-width: 200px !default;\n$tooltip-color: $white !default;\n$tooltip-bg: $black !default;\n$tooltip-border-radius: $border-radius !default;\n$tooltip-opacity: .9 !default;\n$tooltip-padding-y: .25rem !default;\n$tooltip-padding-x: .5rem !default;\n$tooltip-margin: 0 !default;\n\n$tooltip-arrow-width: .8rem !default;\n$tooltip-arrow-height: .4rem !default;\n$tooltip-arrow-color: $tooltip-bg !default;\n\n// Form tooltips must come after regular tooltips\n$form-feedback-tooltip-padding-y: $tooltip-padding-y !default;\n$form-feedback-tooltip-padding-x: $tooltip-padding-x !default;\n$form-feedback-tooltip-font-size: $tooltip-font-size !default;\n$form-feedback-tooltip-line-height: $line-height-base !default;\n$form-feedback-tooltip-opacity: $tooltip-opacity !default;\n$form-feedback-tooltip-border-radius: $tooltip-border-radius !default;\n\n\n// Popovers\n\n$popover-font-size: $font-size-sm !default;\n$popover-bg: $white !default;\n$popover-max-width: 276px !default;\n$popover-border-width: $border-width !default;\n$popover-border-color: rgba($black, .2) !default;\n$popover-border-radius: $border-radius-lg !default;\n$popover-box-shadow: 0 .25rem .5rem rgba($black, .2) !default;\n\n$popover-header-bg: darken($popover-bg, 3%) !default;\n$popover-header-color: $headings-color !default;\n$popover-header-padding-y: .5rem !default;\n$popover-header-padding-x: .75rem !default;\n\n$popover-body-color: $body-color !default;\n$popover-body-padding-y: $popover-header-padding-y !default;\n$popover-body-padding-x: $popover-header-padding-x !default;\n\n$popover-arrow-width: 1rem !default;\n$popover-arrow-height: .5rem !default;\n$popover-arrow-color: $popover-bg !default;\n\n$popover-arrow-outer-color: fade-in($popover-border-color, .05) !default;\n\n\n// Toasts\n\n$toast-max-width: 350px !default;\n$toast-padding-x: .75rem !default;\n$toast-padding-y: .25rem !default;\n$toast-font-size: .875rem !default;\n$toast-color: null !default;\n$toast-background-color: rgba($white, .85) !default;\n$toast-border-width: 1px !default;\n$toast-border-color: rgba(0, 0, 0, .1) !default;\n$toast-border-radius: .25rem !default;\n$toast-box-shadow: 0 .25rem .75rem rgba($black, .1) !default;\n\n$toast-header-color: $gray-600 !default;\n$toast-header-background-color: rgba($white, .85) !default;\n$toast-header-border-color: rgba(0, 0, 0, .05) !default;\n\n\n// Badges\n\n$badge-font-size: 75% !default;\n$badge-font-weight: $font-weight-bold !default;\n$badge-padding-y: .25em !default;\n$badge-padding-x: .4em !default;\n$badge-border-radius: $border-radius !default;\n\n$badge-transition: $btn-transition !default;\n$badge-focus-width: $input-btn-focus-width !default;\n\n$badge-pill-padding-x: .6em !default;\n// Use a higher than normal value to ensure completely rounded edges when\n// customizing padding or font-size on labels.\n$badge-pill-border-radius: 10rem !default;\n\n\n// Modals\n\n// Padding applied to the modal body\n$modal-inner-padding: 1rem !default;\n\n$modal-dialog-margin: .5rem !default;\n$modal-dialog-margin-y-sm-up: 1.75rem !default;\n\n$modal-title-line-height: $line-height-base !default;\n\n$modal-content-color: null !default;\n$modal-content-bg: $white !default;\n$modal-content-border-color: rgba($black, .2) !default;\n$modal-content-border-width: $border-width !default;\n$modal-content-border-radius: $border-radius-lg !default;\n$modal-content-box-shadow-xs: 0 .25rem .5rem rgba($black, .5) !default;\n$modal-content-box-shadow-sm-up: 0 .5rem 1rem rgba($black, .5) !default;\n\n$modal-backdrop-bg: $black !default;\n$modal-backdrop-opacity: .5 !default;\n$modal-header-border-color: $border-color !default;\n$modal-footer-border-color: $modal-header-border-color !default;\n$modal-header-border-width: $modal-content-border-width !default;\n$modal-footer-border-width: $modal-header-border-width !default;\n$modal-header-padding-y: 1rem !default;\n$modal-header-padding-x: 1rem !default;\n$modal-header-padding: $modal-header-padding-y $modal-header-padding-x !default; // Keep this for backwards compatibility\n\n$modal-xl: 1140px !default;\n$modal-lg: 800px !default;\n$modal-md: 500px !default;\n$modal-sm: 300px !default;\n\n$modal-fade-transform: translate(0, -50px) !default;\n$modal-show-transform: none !default;\n$modal-transition: transform .3s ease-out !default;\n\n\n// Alerts\n//\n// Define alert colors, border radius, and padding.\n\n$alert-padding-y: .75rem !default;\n$alert-padding-x: 1.25rem !default;\n$alert-margin-bottom: 1rem !default;\n$alert-border-radius: $border-radius !default;\n$alert-link-font-weight: $font-weight-bold !default;\n$alert-border-width: $border-width !default;\n\n$alert-bg-level: -10 !default;\n$alert-border-level: -9 !default;\n$alert-color-level: 6 !default;\n\n\n// Progress bars\n\n$progress-height: 1rem !default;\n$progress-font-size: $font-size-base * .75 !default;\n$progress-bg: $gray-200 !default;\n$progress-border-radius: $border-radius !default;\n$progress-box-shadow: inset 0 .1rem .1rem rgba($black, .1) !default;\n$progress-bar-color: $white !default;\n$progress-bar-bg: theme-color(\"primary\") !default;\n$progress-bar-animation-timing: 1s linear infinite !default;\n$progress-bar-transition: width .6s ease !default;\n\n\n// List group\n\n$list-group-color: null !default;\n$list-group-bg: $white !default;\n$list-group-border-color: rgba($black, .125) !default;\n$list-group-border-width: $border-width !default;\n$list-group-border-radius: $border-radius !default;\n\n$list-group-item-padding-y: .75rem !default;\n$list-group-item-padding-x: 1.25rem !default;\n\n$list-group-hover-bg: $gray-100 !default;\n$list-group-active-color: $component-active-color !default;\n$list-group-active-bg: $component-active-bg !default;\n$list-group-active-border-color: $list-group-active-bg !default;\n\n$list-group-disabled-color: $gray-600 !default;\n$list-group-disabled-bg: $list-group-bg !default;\n\n$list-group-action-color: $gray-700 !default;\n$list-group-action-hover-color: $list-group-action-color !default;\n\n$list-group-action-active-color: $body-color !default;\n$list-group-action-active-bg: $gray-200 !default;\n\n\n// Image thumbnails\n\n$thumbnail-padding: .25rem !default;\n$thumbnail-bg: $body-bg !default;\n$thumbnail-border-width: $border-width !default;\n$thumbnail-border-color: $gray-300 !default;\n$thumbnail-border-radius: $border-radius !default;\n$thumbnail-box-shadow: 0 1px 2px rgba($black, .075) !default;\n\n\n// Figures\n\n$figure-caption-font-size: 90% !default;\n$figure-caption-color: $gray-600 !default;\n\n\n// Breadcrumbs\n\n$breadcrumb-padding-y: .75rem !default;\n$breadcrumb-padding-x: 1rem !default;\n$breadcrumb-item-padding: .5rem !default;\n\n$breadcrumb-margin-bottom: 1rem !default;\n\n$breadcrumb-bg: $gray-200 !default;\n$breadcrumb-divider-color: $gray-600 !default;\n$breadcrumb-active-color: $gray-600 !default;\n$breadcrumb-divider: quote(\"/\") !default;\n\n$breadcrumb-border-radius: $border-radius !default;\n\n\n// Carousel\n\n$carousel-control-color: $white !default;\n$carousel-control-width: 15% !default;\n$carousel-control-opacity: .5 !default;\n$carousel-control-hover-opacity: .9 !default;\n$carousel-control-transition: opacity .15s ease !default;\n\n$carousel-indicator-width: 30px !default;\n$carousel-indicator-height: 3px !default;\n$carousel-indicator-hit-area-height: 10px !default;\n$carousel-indicator-spacer: 3px !default;\n$carousel-indicator-active-bg: $white !default;\n$carousel-indicator-transition: opacity .6s ease !default;\n\n$carousel-caption-width: 70% !default;\n$carousel-caption-color: $white !default;\n\n$carousel-control-icon-width: 20px !default;\n\n$carousel-control-prev-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$carousel-control-next-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n\n$carousel-transition-duration: .6s !default;\n$carousel-transition: transform $carousel-transition-duration ease-in-out !default; // Define transform transition first if using multiple transitions (e.g., `transform 2s ease, opacity .5s ease-out`)\n\n\n// Spinners\n\n$spinner-width: 2rem !default;\n$spinner-height: $spinner-width !default;\n$spinner-border-width: .25em !default;\n\n$spinner-width-sm: 1rem !default;\n$spinner-height-sm: $spinner-width-sm !default;\n$spinner-border-width-sm: .2em !default;\n\n\n// Close\n\n$close-font-size: $font-size-base * 1.5 !default;\n$close-font-weight: $font-weight-bold !default;\n$close-color: $black !default;\n$close-text-shadow: 0 1px 0 $white !default;\n\n\n// Code\n\n$code-font-size: 87.5% !default;\n$code-color: $pink !default;\n\n$kbd-padding-y: .2rem !default;\n$kbd-padding-x: .4rem !default;\n$kbd-font-size: $code-font-size !default;\n$kbd-color: $white !default;\n$kbd-bg: $gray-900 !default;\n\n$pre-color: $gray-900 !default;\n$pre-scrollable-max-height: 340px !default;\n\n\n// Utilities\n\n$displays: none, inline, inline-block, block, table, table-row, table-cell, flex, inline-flex !default;\n$overflows: auto, hidden !default;\n$positions: static, relative, absolute, fixed, sticky !default;\n\n\n// Printing\n\n$print-page-size: a3 !default;\n$print-body-min-width: map-get($grid-breakpoints, \"lg\") !default;\n","// stylelint-disable property-blacklist, scss/dollar-variable-default\n\n// SCSS RFS mixin\n//\n// Automated font-resizing\n//\n// See https://github.com/twbs/rfs\n\n// Configuration\n\n// Base font size\n$rfs-base-font-size: 1.25rem !default;\n$rfs-font-size-unit: rem !default;\n\n// Breakpoint at where font-size starts decreasing if screen width is smaller\n$rfs-breakpoint: 1200px !default;\n$rfs-breakpoint-unit: px !default;\n\n// Resize font-size based on screen height and width\n$rfs-two-dimensional: false !default;\n\n// Factor of decrease\n$rfs-factor: 10 !default;\n\n@if type-of($rfs-factor) != \"number\" or $rfs-factor <= 1 {\n @error \"`#{$rfs-factor}` is not a valid $rfs-factor, it must be greater than 1.\";\n}\n\n// Generate enable or disable classes. Possibilities: false, \"enable\" or \"disable\"\n$rfs-class: false !default;\n\n// 1 rem = $rfs-rem-value px\n$rfs-rem-value: 16 !default;\n\n// Safari iframe resize bug: https://github.com/twbs/rfs/issues/14\n$rfs-safari-iframe-resize-bug-fix: false !default;\n\n// Disable RFS by setting $enable-responsive-font-sizes to false\n$enable-responsive-font-sizes: true !default;\n\n// Cache $rfs-base-font-size unit\n$rfs-base-font-size-unit: unit($rfs-base-font-size);\n\n// Remove px-unit from $rfs-base-font-size for calculations\n@if $rfs-base-font-size-unit == \"px\" {\n $rfs-base-font-size: $rfs-base-font-size / ($rfs-base-font-size * 0 + 1);\n}\n@else if $rfs-base-font-size-unit == \"rem\" {\n $rfs-base-font-size: $rfs-base-font-size / ($rfs-base-font-size * 0 + 1 / $rfs-rem-value);\n}\n\n// Cache $rfs-breakpoint unit to prevent multiple calls\n$rfs-breakpoint-unit-cache: unit($rfs-breakpoint);\n\n// Remove unit from $rfs-breakpoint for calculations\n@if $rfs-breakpoint-unit-cache == \"px\" {\n $rfs-breakpoint: $rfs-breakpoint / ($rfs-breakpoint * 0 + 1);\n}\n@else if $rfs-breakpoint-unit-cache == \"rem\" or $rfs-breakpoint-unit-cache == \"em\" {\n $rfs-breakpoint: $rfs-breakpoint / ($rfs-breakpoint * 0 + 1 / $rfs-rem-value);\n}\n\n// Responsive font-size mixin\n@mixin rfs($fs, $important: false) {\n // Cache $fs unit\n $fs-unit: if(type-of($fs) == \"number\", unit($fs), false);\n\n // Add !important suffix if needed\n $rfs-suffix: if($important, \" !important\", \"\");\n\n // If $fs isn't a number (like inherit) or $fs has a unit (not px or rem, like 1.5em) or $ is 0, just print the value\n @if not $fs-unit or $fs-unit != \"\" and $fs-unit != \"px\" and $fs-unit != \"rem\" or $fs == 0 {\n font-size: #{$fs}#{$rfs-suffix};\n }\n @else {\n // Variables for storing static and fluid rescaling\n $rfs-static: null;\n $rfs-fluid: null;\n\n // Remove px-unit from $fs for calculations\n @if $fs-unit == \"px\" {\n $fs: $fs / ($fs * 0 + 1);\n }\n @else if $fs-unit == \"rem\" {\n $fs: $fs / ($fs * 0 + 1 / $rfs-rem-value);\n }\n\n // Set default font-size\n @if $rfs-font-size-unit == rem {\n $rfs-static: #{$fs / $rfs-rem-value}rem#{$rfs-suffix};\n }\n @else if $rfs-font-size-unit == px {\n $rfs-static: #{$fs}px#{$rfs-suffix};\n }\n @else {\n @error \"`#{$rfs-font-size-unit}` is not a valid unit for $rfs-font-size-unit. Use `px` or `rem`.\";\n }\n\n // Only add media query if font-size is bigger as the minimum font-size\n // If $rfs-factor == 1, no rescaling will take place\n @if $fs > $rfs-base-font-size and $enable-responsive-font-sizes {\n $min-width: null;\n $variable-unit: null;\n\n // Calculate minimum font-size for given font-size\n $fs-min: $rfs-base-font-size + ($fs - $rfs-base-font-size) / $rfs-factor;\n\n // Calculate difference between given font-size and minimum font-size for given font-size\n $fs-diff: $fs - $fs-min;\n\n // Base font-size formatting\n // No need to check if the unit is valid, because we did that before\n $min-width: if($rfs-font-size-unit == rem, #{$fs-min / $rfs-rem-value}rem, #{$fs-min}px);\n\n // If two-dimensional, use smallest of screen width and height\n $variable-unit: if($rfs-two-dimensional, vmin, vw);\n\n // Calculate the variable width between 0 and $rfs-breakpoint\n $variable-width: #{$fs-diff * 100 / $rfs-breakpoint}#{$variable-unit};\n\n // Set the calculated font-size.\n $rfs-fluid: calc(#{$min-width} + #{$variable-width}) #{$rfs-suffix};\n }\n\n // Rendering\n @if $rfs-fluid == null {\n // Only render static font-size if no fluid font-size is available\n font-size: $rfs-static;\n }\n @else {\n $mq-value: null;\n\n // RFS breakpoint formatting\n @if $rfs-breakpoint-unit == em or $rfs-breakpoint-unit == rem {\n $mq-value: #{$rfs-breakpoint / $rfs-rem-value}#{$rfs-breakpoint-unit};\n }\n @else if $rfs-breakpoint-unit == px {\n $mq-value: #{$rfs-breakpoint}px;\n }\n @else {\n @error \"`#{$rfs-breakpoint-unit}` is not a valid unit for $rfs-breakpoint-unit. Use `px`, `em` or `rem`.\";\n }\n\n @if $rfs-class == \"disable\" {\n // Adding an extra class increases specificity,\n // which prevents the media query to override the font size\n &,\n .disable-responsive-font-size &,\n &.disable-responsive-font-size {\n font-size: $rfs-static;\n }\n }\n @else {\n font-size: $rfs-static;\n }\n\n @if $rfs-two-dimensional {\n @media (max-width: #{$mq-value}), (max-height: #{$mq-value}) {\n @if $rfs-class == \"enable\" {\n .enable-responsive-font-size &,\n &.enable-responsive-font-size {\n font-size: $rfs-fluid;\n }\n }\n @else {\n font-size: $rfs-fluid;\n }\n\n @if $rfs-safari-iframe-resize-bug-fix {\n // stylelint-disable-next-line length-zero-no-unit\n min-width: 0vw;\n }\n }\n }\n @else {\n @media (max-width: #{$mq-value}) {\n @if $rfs-class == \"enable\" {\n .enable-responsive-font-size &,\n &.enable-responsive-font-size {\n font-size: $rfs-fluid;\n }\n }\n @else {\n font-size: $rfs-fluid;\n }\n\n @if $rfs-safari-iframe-resize-bug-fix {\n // stylelint-disable-next-line length-zero-no-unit\n min-width: 0vw;\n }\n }\n }\n }\n }\n}\n\n// The font-size & responsive-font-size mixin uses RFS to rescale font sizes\n@mixin font-size($fs, $important: false) {\n @include rfs($fs, $important);\n}\n\n@mixin responsive-font-size($fs, $important: false) {\n @include rfs($fs, $important);\n}\n","// Hover mixin and `$enable-hover-media-query` are deprecated.\n//\n// Originally added during our alphas and maintained during betas, this mixin was\n// designed to prevent `:hover` stickiness on iOS-an issue where hover styles\n// would persist after initial touch.\n//\n// For backward compatibility, we've kept these mixins and updated them to\n// always return their regular pseudo-classes instead of a shimmed media query.\n//\n// Issue: https://github.com/twbs/bootstrap/issues/25195\n\n@mixin hover {\n &:hover { @content; }\n}\n\n@mixin hover-focus {\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin plain-hover-focus {\n &,\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin hover-focus-active {\n &:hover,\n &:focus,\n &:active {\n @content;\n }\n}\n"]} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css new file mode 100644 index 0000000000000000000000000000000000000000..c804b3b1029c935d7158ff165d601041b6337115 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css @@ -0,0 +1,8 @@ +/*! + * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/) + * Copyright 2011-2019 The Bootstrap Authors + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) + */*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important} +/*# sourceMappingURL=bootstrap-reboot.min.css.map */ \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map new file mode 100644 index 0000000000000000000000000000000000000000..73f4a1928ee1f9fc5cd56138b62d3be419edafce --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../scss/bootstrap-reboot.scss","../../scss/_reboot.scss","dist/css/bootstrap-reboot.css","../../scss/vendor/_rfs.scss","bootstrap-reboot.css","../../scss/mixins/_hover.scss"],"names":[],"mappings":"AAAA;;;;;;ACkBA,ECTA,QADA,SDaE,WAAA,WAGF,KACE,YAAA,WACA,YAAA,KACA,yBAAA,KACA,4BAAA,YAMF,QAAA,MAAA,WAAA,OAAA,OAAA,OAAA,OAAA,KAAA,IAAA,QACE,QAAA,MAUF,KACE,OAAA,EACA,YAAA,aAAA,CAAA,kBAAA,CAAA,UAAA,CAAA,MAAA,CAAA,gBAAA,CAAA,KAAA,CAAA,WAAA,CAAA,UAAA,CAAA,mBAAA,CAAA,gBAAA,CAAA,iBAAA,CAAA,mBEgFI,UAAA,KF9EJ,YAAA,IACA,YAAA,IACA,MAAA,QACA,WAAA,KACA,iBAAA,KGlBF,sBH2BE,QAAA,YASF,GACE,WAAA,YACA,OAAA,EACA,SAAA,QAaF,GAAA,GAAA,GAAA,GAAA,GAAA,GACE,WAAA,EACA,cAAA,MAOF,EACE,WAAA,EACA,cAAA,KC1CF,0BDqDA,YAEE,gBAAA,UACA,wBAAA,UAAA,OAAA,gBAAA,UAAA,OACA,OAAA,KACA,cAAA,EACA,iCAAA,KAAA,yBAAA,KAGF,QACE,cAAA,KACA,WAAA,OACA,YAAA,QC/CF,GDkDA,GCnDA,GDsDE,WAAA,EACA,cAAA,KAGF,MClDA,MACA,MAFA,MDuDE,cAAA,EAGF,GACE,YAAA,IAGF,GACE,cAAA,MACA,YAAA,EAGF,WACE,OAAA,EAAA,EAAA,KAGF,ECnDA,ODqDE,YAAA,OAGF,MEpFI,UAAA,IF6FJ,ICxDA,ID0DE,SAAA,SE/FE,UAAA,IFiGF,YAAA,EACA,eAAA,SAGF,IAAM,OAAA,OACN,IAAM,IAAA,MAON,EACE,MAAA,QACA,gBAAA,KACA,iBAAA,YI5KA,QJ+KE,MAAA,QACA,gBAAA,UAUJ,8BACE,MAAA,QACA,gBAAA,KIxLA,oCAAA,oCJ2LE,MAAA,QACA,gBAAA,KANJ,oCAUI,QAAA,EC1DJ,KACA,IDkEA,ICjEA,KDqEE,YAAA,cAAA,CAAA,KAAA,CAAA,MAAA,CAAA,QAAA,CAAA,iBAAA,CAAA,aAAA,CAAA,UErJE,UAAA,IFyJJ,IAEE,WAAA,EAEA,cAAA,KAEA,SAAA,KAQF,OAEE,OAAA,EAAA,EAAA,KAQF,IACE,eAAA,OACA,aAAA,KAGF,IAGE,SAAA,OACA,eAAA,OAQF,MACE,gBAAA,SAGF,QACE,YAAA,OACA,eAAA,OACA,MAAA,QACA,WAAA,KACA,aAAA,OAGF,GAGE,WAAA,QAQF,MAEE,QAAA,aACA,cAAA,MAMF,OAEE,cAAA,EAOF,aACE,QAAA,IAAA,OACA,QAAA,IAAA,KAAA,yBCrGF,ODwGA,MCtGA,SADA,OAEA,SD0GE,OAAA,EACA,YAAA,QEtPE,UAAA,QFwPF,YAAA,QAGF,OCxGA,MD0GE,SAAA,QAGF,OCxGA,OD0GE,eAAA,KAMF,OACE,UAAA,OCxGF,cACA,aACA,cD6GA,OAIE,mBAAA,OC5GF,6BACA,4BACA,6BD+GE,sBAKI,OAAA,QC/GN,gCACA,+BACA,gCDmHA,yBAIE,QAAA,EACA,aAAA,KClHF,qBDqHA,kBAEE,WAAA,WACA,QAAA,EAIF,iBCrHA,2BACA,kBAFA,iBD+HE,mBAAA,QAGF,SACE,SAAA,KAEA,OAAA,SAGF,SAME,UAAA,EAEA,QAAA,EACA,OAAA,EACA,OAAA,EAKF,OACE,QAAA,MACA,MAAA,KACA,UAAA,KACA,QAAA,EACA,cAAA,MElSI,UAAA,OFoSJ,YAAA,QACA,MAAA,QACA,YAAA,OAGF,SACE,eAAA,SGpIF,yCFGA,yCDuIE,OAAA,KGrIF,cH6IE,eAAA,KACA,mBAAA,KGzIF,yCHiJE,mBAAA,KAQF,6BACE,KAAA,QACA,mBAAA,OAOF,OACE,QAAA,aAGF,QACE,QAAA,UACA,OAAA,QAGF,SACE,QAAA,KGtJF,SH4JE,QAAA","sourcesContent":["/*!\n * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n\n@import \"functions\";\n@import \"variables\";\n@import \"mixins\";\n@import \"reboot\";\n","// stylelint-disable at-rule-no-vendor-prefix, declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix\n\n// Reboot\n//\n// Normalization of HTML elements, manually forked from Normalize.css to remove\n// styles targeting irrelevant browsers while applying new styles.\n//\n// Normalize is licensed MIT. https://github.com/necolas/normalize.css\n\n\n// Document\n//\n// 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.\n// 2. Change the default font family in all browsers.\n// 3. Correct the line height in all browsers.\n// 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS.\n// 5. Change the default tap highlight to be completely transparent in iOS.\n\n*,\n*::before,\n*::after {\n box-sizing: border-box; // 1\n}\n\nhtml {\n font-family: sans-serif; // 2\n line-height: 1.15; // 3\n -webkit-text-size-adjust: 100%; // 4\n -webkit-tap-highlight-color: rgba($black, 0); // 5\n}\n\n// Shim for \"new\" HTML5 structural elements to display correctly (IE10, older browsers)\n// TODO: remove in v5\n// stylelint-disable-next-line selector-list-comma-newline-after\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\n// Body\n//\n// 1. Remove the margin in all browsers.\n// 2. As a best practice, apply a default `background-color`.\n// 3. Set an explicit initial text-align value so that we can later use\n// the `inherit` value on things like `` elements.\n\nbody {\n margin: 0; // 1\n font-family: $font-family-base;\n @include font-size($font-size-base);\n font-weight: $font-weight-base;\n line-height: $line-height-base;\n color: $body-color;\n text-align: left; // 3\n background-color: $body-bg; // 2\n}\n\n// Suppress the focus outline on elements that cannot be accessed via keyboard.\n// This prevents an unwanted focus outline from appearing around elements that\n// might still respond to pointer events.\n//\n// Credit: https://github.com/suitcss/base\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\n\n// Content grouping\n//\n// 1. Add the correct box sizing in Firefox.\n// 2. Show the overflow in Edge and IE.\n\nhr {\n box-sizing: content-box; // 1\n height: 0; // 1\n overflow: visible; // 2\n}\n\n\n//\n// Typography\n//\n\n// Remove top margins from headings\n//\n// By default, `

`-`

` all receive top and bottom margins. We nuke the top\n// margin for easier control within type scales as it avoids margin collapsing.\n// stylelint-disable-next-line selector-list-comma-newline-after\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: $headings-margin-bottom;\n}\n\n// Reset margins on paragraphs\n//\n// Similarly, the top margin on `

`s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n// Abbreviations\n//\n// 1. Duplicate behavior to the data-* attribute for our tooltip plugin\n// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n// 3. Add explicit cursor to indicate changed behavior.\n// 4. Remove the bottom border in Firefox 39-.\n// 5. Prevent the text-decoration to be skipped.\n\nabbr[title],\nabbr[data-original-title] { // 1\n text-decoration: underline; // 2\n text-decoration: underline dotted; // 2\n cursor: help; // 3\n border-bottom: 0; // 4\n text-decoration-skip-ink: none; // 5\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // Undo browser default\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: $font-weight-bolder; // Add the correct font weight in Chrome, Edge, and Safari\n}\n\nsmall {\n @include font-size(80%); // Add the correct font size in all browsers\n}\n\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n//\n\nsub,\nsup {\n position: relative;\n @include font-size(75%);\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n//\n// Links\n//\n\na {\n color: $link-color;\n text-decoration: $link-decoration;\n background-color: transparent; // Remove the gray background on active links in IE 10.\n\n @include hover {\n color: $link-hover-color;\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href)\n// which have not been made explicitly keyboard-focusable (without tabindex).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n\n @include hover-focus {\n color: inherit;\n text-decoration: none;\n }\n\n &:focus {\n outline: 0;\n }\n}\n\n\n//\n// Code\n//\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-monospace;\n @include font-size(1em); // Correct the odd `em` font sizing in all browsers.\n}\n\npre {\n // Remove browser default top margin\n margin-top: 0;\n // Reset browser default of `1em` to use `rem`s\n margin-bottom: 1rem;\n // Don't allow content to break outside\n overflow: auto;\n}\n\n\n//\n// Figures\n//\n\nfigure {\n // Apply a consistent margin strategy (matches our type styles).\n margin: 0 0 1rem;\n}\n\n\n//\n// Images and content\n//\n\nimg {\n vertical-align: middle;\n border-style: none; // Remove the border on images inside links in IE 10-.\n}\n\nsvg {\n // Workaround for the SVG overflow bug in IE10/11 is still required.\n // See https://github.com/twbs/bootstrap/issues/26878\n overflow: hidden;\n vertical-align: middle;\n}\n\n\n//\n// Tables\n//\n\ntable {\n border-collapse: collapse; // Prevent double borders\n}\n\ncaption {\n padding-top: $table-cell-padding;\n padding-bottom: $table-cell-padding;\n color: $table-caption-color;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n // Matches default `` alignment by inheriting from the ``, or the\n // closest parent with a set `text-align`.\n text-align: inherit;\n}\n\n\n//\n// Forms\n//\n\nlabel {\n // Allow labels to use `margin` for spacing.\n display: inline-block;\n margin-bottom: $label-margin-bottom;\n}\n\n// Remove the default `border-radius` that macOS Chrome adds.\n//\n// Details at https://github.com/twbs/bootstrap/issues/24093\nbutton {\n // stylelint-disable-next-line property-blacklist\n border-radius: 0;\n}\n\n// Work around a Firefox/IE bug where the transparent `button` background\n// results in a loss of the default `button` focus styles.\n//\n// Credit: https://github.com/suitcss/base/\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0; // Remove the margin in Firefox and Safari\n font-family: inherit;\n @include font-size(inherit);\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible; // Show the overflow in Edge\n}\n\nbutton,\nselect {\n text-transform: none; // Remove the inheritance of text transform in Firefox\n}\n\n// Remove the inheritance of word-wrap in Safari.\n//\n// Details at https://github.com/twbs/bootstrap/issues/24990\nselect {\n word-wrap: normal;\n}\n\n\n// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`\n// controls in Android 4.\n// 2. Correct the inability to style clickable types in iOS and Safari.\nbutton,\n[type=\"button\"], // 1\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button; // 2\n}\n\n// Opinionated: add \"hand\" cursor to non-disabled button elements.\n@if $enable-pointer-cursor-for-buttons {\n button,\n [type=\"button\"],\n [type=\"reset\"],\n [type=\"submit\"] {\n &:not(:disabled) {\n cursor: pointer;\n }\n }\n}\n\n// Remove inner border and padding from Firefox, but don't restore the outline like Normalize.\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box; // 1. Add the correct box sizing in IE 10-\n padding: 0; // 2. Remove the padding in IE 10-\n}\n\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n // Remove the default appearance of temporal inputs to avoid a Mobile Safari\n // bug where setting a custom line-height prevents text from being vertically\n // centered within the input.\n // See https://bugs.webkit.org/show_bug.cgi?id=139848\n // and https://github.com/twbs/bootstrap/issues/11266\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto; // Remove the default vertical scrollbar in IE.\n // Textareas should really only resize vertically so they don't break their (horizontal) containers.\n resize: vertical;\n}\n\nfieldset {\n // Browsers set a default `min-width: min-content;` on fieldsets,\n // unlike e.g. `

`s, which have `min-width: 0;` by default.\n // So we reset that to ensure fieldsets behave more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359\n // and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements\n min-width: 0;\n // Reset the default outline behavior of fieldsets so they don't affect page layout.\n padding: 0;\n margin: 0;\n border: 0;\n}\n\n// 1. Correct the text wrapping in Edge and IE.\n// 2. Correct the color inheritance from `fieldset` elements in IE.\nlegend {\n display: block;\n width: 100%;\n max-width: 100%; // 1\n padding: 0;\n margin-bottom: .5rem;\n @include font-size(1.5rem);\n line-height: inherit;\n color: inherit; // 2\n white-space: normal; // 1\n}\n\nprogress {\n vertical-align: baseline; // Add the correct vertical alignment in Chrome, Firefox, and Opera.\n}\n\n// Correct the cursor style of increment and decrement buttons in Chrome.\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n // This overrides the extra rounded corners on search inputs in iOS so that our\n // `.form-control` class can properly style them. Note that this cannot simply\n // be added to `.form-control` as it's not specific enough. For details, see\n // https://github.com/twbs/bootstrap/issues/11586.\n outline-offset: -2px; // 2. Correct the outline style in Safari.\n -webkit-appearance: none;\n}\n\n//\n// Remove the inner padding in Chrome and Safari on macOS.\n//\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// 1. Correct the inability to style clickable types in iOS and Safari.\n// 2. Change font properties to `inherit` in Safari.\n//\n\n::-webkit-file-upload-button {\n font: inherit; // 2\n -webkit-appearance: button; // 1\n}\n\n//\n// Correct element displays\n//\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item; // Add the correct display in all browsers\n cursor: pointer;\n}\n\ntemplate {\n display: none; // Add the correct display in IE\n}\n\n// Always hide an element with the `hidden` HTML attribute (from PureCSS).\n// Needed for proper display in IE 10-.\n[hidden] {\n display: none !important;\n}\n","/*!\n * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nhtml {\n font-family: sans-serif;\n line-height: 1.15;\n -webkit-text-size-adjust: 100%;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\nbody {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #212529;\n text-align: left;\n background-color: #fff;\n}\n\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\nhr {\n box-sizing: content-box;\n height: 0;\n overflow: visible;\n}\n\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n}\n\np {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-original-title] {\n text-decoration: underline;\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n cursor: help;\n border-bottom: 0;\n -webkit-text-decoration-skip-ink: none;\n text-decoration-skip-ink: none;\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: 700;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0;\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: bolder;\n}\n\nsmall {\n font-size: 80%;\n}\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -.25em;\n}\n\nsup {\n top: -.5em;\n}\n\na {\n color: #007bff;\n text-decoration: none;\n background-color: transparent;\n}\n\na:hover {\n color: #0056b3;\n text-decoration: underline;\n}\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):focus {\n outline: 0;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 1em;\n}\n\npre {\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n}\n\nfigure {\n margin: 0 0 1rem;\n}\n\nimg {\n vertical-align: middle;\n border-style: none;\n}\n\nsvg {\n overflow: hidden;\n vertical-align: middle;\n}\n\ntable {\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n color: #6c757d;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n text-align: inherit;\n}\n\nlabel {\n display: inline-block;\n margin-bottom: 0.5rem;\n}\n\nbutton {\n border-radius: 0;\n}\n\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible;\n}\n\nbutton,\nselect {\n text-transform: none;\n}\n\nselect {\n word-wrap: normal;\n}\n\nbutton,\n[type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\nbutton:not(:disabled),\n[type=\"button\"]:not(:disabled),\n[type=\"reset\"]:not(:disabled),\n[type=\"submit\"]:not(:disabled) {\n cursor: pointer;\n}\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box;\n padding: 0;\n}\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto;\n resize: vertical;\n}\n\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n max-width: 100%;\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit;\n white-space: normal;\n}\n\nprogress {\n vertical-align: baseline;\n}\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n outline-offset: -2px;\n -webkit-appearance: none;\n}\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n::-webkit-file-upload-button {\n font: inherit;\n -webkit-appearance: button;\n}\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item;\n cursor: pointer;\n}\n\ntemplate {\n display: none;\n}\n\n[hidden] {\n display: none !important;\n}\n/*# sourceMappingURL=bootstrap-reboot.css.map */","// stylelint-disable property-blacklist, scss/dollar-variable-default\n\n// SCSS RFS mixin\n//\n// Automated font-resizing\n//\n// See https://github.com/twbs/rfs\n\n// Configuration\n\n// Base font size\n$rfs-base-font-size: 1.25rem !default;\n$rfs-font-size-unit: rem !default;\n\n// Breakpoint at where font-size starts decreasing if screen width is smaller\n$rfs-breakpoint: 1200px !default;\n$rfs-breakpoint-unit: px !default;\n\n// Resize font-size based on screen height and width\n$rfs-two-dimensional: false !default;\n\n// Factor of decrease\n$rfs-factor: 10 !default;\n\n@if type-of($rfs-factor) != \"number\" or $rfs-factor <= 1 {\n @error \"`#{$rfs-factor}` is not a valid $rfs-factor, it must be greater than 1.\";\n}\n\n// Generate enable or disable classes. Possibilities: false, \"enable\" or \"disable\"\n$rfs-class: false !default;\n\n// 1 rem = $rfs-rem-value px\n$rfs-rem-value: 16 !default;\n\n// Safari iframe resize bug: https://github.com/twbs/rfs/issues/14\n$rfs-safari-iframe-resize-bug-fix: false !default;\n\n// Disable RFS by setting $enable-responsive-font-sizes to false\n$enable-responsive-font-sizes: true !default;\n\n// Cache $rfs-base-font-size unit\n$rfs-base-font-size-unit: unit($rfs-base-font-size);\n\n// Remove px-unit from $rfs-base-font-size for calculations\n@if $rfs-base-font-size-unit == \"px\" {\n $rfs-base-font-size: $rfs-base-font-size / ($rfs-base-font-size * 0 + 1);\n}\n@else if $rfs-base-font-size-unit == \"rem\" {\n $rfs-base-font-size: $rfs-base-font-size / ($rfs-base-font-size * 0 + 1 / $rfs-rem-value);\n}\n\n// Cache $rfs-breakpoint unit to prevent multiple calls\n$rfs-breakpoint-unit-cache: unit($rfs-breakpoint);\n\n// Remove unit from $rfs-breakpoint for calculations\n@if $rfs-breakpoint-unit-cache == \"px\" {\n $rfs-breakpoint: $rfs-breakpoint / ($rfs-breakpoint * 0 + 1);\n}\n@else if $rfs-breakpoint-unit-cache == \"rem\" or $rfs-breakpoint-unit-cache == \"em\" {\n $rfs-breakpoint: $rfs-breakpoint / ($rfs-breakpoint * 0 + 1 / $rfs-rem-value);\n}\n\n// Responsive font-size mixin\n@mixin rfs($fs, $important: false) {\n // Cache $fs unit\n $fs-unit: if(type-of($fs) == \"number\", unit($fs), false);\n\n // Add !important suffix if needed\n $rfs-suffix: if($important, \" !important\", \"\");\n\n // If $fs isn't a number (like inherit) or $fs has a unit (not px or rem, like 1.5em) or $ is 0, just print the value\n @if not $fs-unit or $fs-unit != \"\" and $fs-unit != \"px\" and $fs-unit != \"rem\" or $fs == 0 {\n font-size: #{$fs}#{$rfs-suffix};\n }\n @else {\n // Variables for storing static and fluid rescaling\n $rfs-static: null;\n $rfs-fluid: null;\n\n // Remove px-unit from $fs for calculations\n @if $fs-unit == \"px\" {\n $fs: $fs / ($fs * 0 + 1);\n }\n @else if $fs-unit == \"rem\" {\n $fs: $fs / ($fs * 0 + 1 / $rfs-rem-value);\n }\n\n // Set default font-size\n @if $rfs-font-size-unit == rem {\n $rfs-static: #{$fs / $rfs-rem-value}rem#{$rfs-suffix};\n }\n @else if $rfs-font-size-unit == px {\n $rfs-static: #{$fs}px#{$rfs-suffix};\n }\n @else {\n @error \"`#{$rfs-font-size-unit}` is not a valid unit for $rfs-font-size-unit. Use `px` or `rem`.\";\n }\n\n // Only add media query if font-size is bigger as the minimum font-size\n // If $rfs-factor == 1, no rescaling will take place\n @if $fs > $rfs-base-font-size and $enable-responsive-font-sizes {\n $min-width: null;\n $variable-unit: null;\n\n // Calculate minimum font-size for given font-size\n $fs-min: $rfs-base-font-size + ($fs - $rfs-base-font-size) / $rfs-factor;\n\n // Calculate difference between given font-size and minimum font-size for given font-size\n $fs-diff: $fs - $fs-min;\n\n // Base font-size formatting\n // No need to check if the unit is valid, because we did that before\n $min-width: if($rfs-font-size-unit == rem, #{$fs-min / $rfs-rem-value}rem, #{$fs-min}px);\n\n // If two-dimensional, use smallest of screen width and height\n $variable-unit: if($rfs-two-dimensional, vmin, vw);\n\n // Calculate the variable width between 0 and $rfs-breakpoint\n $variable-width: #{$fs-diff * 100 / $rfs-breakpoint}#{$variable-unit};\n\n // Set the calculated font-size.\n $rfs-fluid: calc(#{$min-width} + #{$variable-width}) #{$rfs-suffix};\n }\n\n // Rendering\n @if $rfs-fluid == null {\n // Only render static font-size if no fluid font-size is available\n font-size: $rfs-static;\n }\n @else {\n $mq-value: null;\n\n // RFS breakpoint formatting\n @if $rfs-breakpoint-unit == em or $rfs-breakpoint-unit == rem {\n $mq-value: #{$rfs-breakpoint / $rfs-rem-value}#{$rfs-breakpoint-unit};\n }\n @else if $rfs-breakpoint-unit == px {\n $mq-value: #{$rfs-breakpoint}px;\n }\n @else {\n @error \"`#{$rfs-breakpoint-unit}` is not a valid unit for $rfs-breakpoint-unit. Use `px`, `em` or `rem`.\";\n }\n\n @if $rfs-class == \"disable\" {\n // Adding an extra class increases specificity,\n // which prevents the media query to override the font size\n &,\n .disable-responsive-font-size &,\n &.disable-responsive-font-size {\n font-size: $rfs-static;\n }\n }\n @else {\n font-size: $rfs-static;\n }\n\n @if $rfs-two-dimensional {\n @media (max-width: #{$mq-value}), (max-height: #{$mq-value}) {\n @if $rfs-class == \"enable\" {\n .enable-responsive-font-size &,\n &.enable-responsive-font-size {\n font-size: $rfs-fluid;\n }\n }\n @else {\n font-size: $rfs-fluid;\n }\n\n @if $rfs-safari-iframe-resize-bug-fix {\n // stylelint-disable-next-line length-zero-no-unit\n min-width: 0vw;\n }\n }\n }\n @else {\n @media (max-width: #{$mq-value}) {\n @if $rfs-class == \"enable\" {\n .enable-responsive-font-size &,\n &.enable-responsive-font-size {\n font-size: $rfs-fluid;\n }\n }\n @else {\n font-size: $rfs-fluid;\n }\n\n @if $rfs-safari-iframe-resize-bug-fix {\n // stylelint-disable-next-line length-zero-no-unit\n min-width: 0vw;\n }\n }\n }\n }\n }\n}\n\n// The font-size & responsive-font-size mixin uses RFS to rescale font sizes\n@mixin font-size($fs, $important: false) {\n @include rfs($fs, $important);\n}\n\n@mixin responsive-font-size($fs, $important: false) {\n @include rfs($fs, $important);\n}\n","/*!\n * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nhtml {\n font-family: sans-serif;\n line-height: 1.15;\n -webkit-text-size-adjust: 100%;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\nbody {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #212529;\n text-align: left;\n background-color: #fff;\n}\n\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\nhr {\n box-sizing: content-box;\n height: 0;\n overflow: visible;\n}\n\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n}\n\np {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-original-title] {\n text-decoration: underline;\n text-decoration: underline dotted;\n cursor: help;\n border-bottom: 0;\n text-decoration-skip-ink: none;\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: 700;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0;\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: bolder;\n}\n\nsmall {\n font-size: 80%;\n}\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -.25em;\n}\n\nsup {\n top: -.5em;\n}\n\na {\n color: #007bff;\n text-decoration: none;\n background-color: transparent;\n}\n\na:hover {\n color: #0056b3;\n text-decoration: underline;\n}\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):focus {\n outline: 0;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 1em;\n}\n\npre {\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n}\n\nfigure {\n margin: 0 0 1rem;\n}\n\nimg {\n vertical-align: middle;\n border-style: none;\n}\n\nsvg {\n overflow: hidden;\n vertical-align: middle;\n}\n\ntable {\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n color: #6c757d;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n text-align: inherit;\n}\n\nlabel {\n display: inline-block;\n margin-bottom: 0.5rem;\n}\n\nbutton {\n border-radius: 0;\n}\n\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible;\n}\n\nbutton,\nselect {\n text-transform: none;\n}\n\nselect {\n word-wrap: normal;\n}\n\nbutton,\n[type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\nbutton:not(:disabled),\n[type=\"button\"]:not(:disabled),\n[type=\"reset\"]:not(:disabled),\n[type=\"submit\"]:not(:disabled) {\n cursor: pointer;\n}\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box;\n padding: 0;\n}\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto;\n resize: vertical;\n}\n\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n max-width: 100%;\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit;\n white-space: normal;\n}\n\nprogress {\n vertical-align: baseline;\n}\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n outline-offset: -2px;\n -webkit-appearance: none;\n}\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n::-webkit-file-upload-button {\n font: inherit;\n -webkit-appearance: button;\n}\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item;\n cursor: pointer;\n}\n\ntemplate {\n display: none;\n}\n\n[hidden] {\n display: none !important;\n}\n\n/*# sourceMappingURL=bootstrap-reboot.css.map */","// Hover mixin and `$enable-hover-media-query` are deprecated.\n//\n// Originally added during our alphas and maintained during betas, this mixin was\n// designed to prevent `:hover` stickiness on iOS-an issue where hover styles\n// would persist after initial touch.\n//\n// For backward compatibility, we've kept these mixins and updated them to\n// always return their regular pseudo-classes instead of a shimmed media query.\n//\n// Issue: https://github.com/twbs/bootstrap/issues/25195\n\n@mixin hover {\n &:hover { @content; }\n}\n\n@mixin hover-focus {\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin plain-hover-focus {\n &,\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin hover-focus-active {\n &:hover,\n &:focus,\n &:active {\n @content;\n }\n}\n"]} \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap.css b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap.css new file mode 100644 index 0000000000000000000000000000000000000000..8f4758923aa884eb810ebd68c44c6ec6632c3adf --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap.css @@ -0,0 +1,10038 @@ +/*! + * Bootstrap v4.3.1 (https://getbootstrap.com/) + * Copyright 2011-2019 The Bootstrap Authors + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +:root { + --blue: #007bff; + --indigo: #6610f2; + --purple: #6f42c1; + --pink: #e83e8c; + --red: #dc3545; + --orange: #fd7e14; + --yellow: #ffc107; + --green: #28a745; + --teal: #20c997; + --cyan: #17a2b8; + --white: #fff; + --gray: #6c757d; + --gray-dark: #343a40; + --primary: #007bff; + --secondary: #6c757d; + --success: #28a745; + --info: #17a2b8; + --warning: #ffc107; + --danger: #dc3545; + --light: #f8f9fa; + --dark: #343a40; + --breakpoint-xs: 0; + --breakpoint-sm: 576px; + --breakpoint-md: 768px; + --breakpoint-lg: 992px; + --breakpoint-xl: 1200px; + --font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; +} + +*, +*::before, +*::after { + box-sizing: border-box; +} + +html { + font-family: sans-serif; + line-height: 1.15; + -webkit-text-size-adjust: 100%; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { + display: block; +} + +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + text-align: left; + background-color: #fff; +} + +[tabindex="-1"]:focus { + outline: 0 !important; +} + +hr { + box-sizing: content-box; + height: 0; + overflow: visible; +} + +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 0.5rem; +} + +p { + margin-top: 0; + margin-bottom: 1rem; +} + +abbr[title], +abbr[data-original-title] { + text-decoration: underline; + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; + cursor: help; + border-bottom: 0; + -webkit-text-decoration-skip-ink: none; + text-decoration-skip-ink: none; +} + +address { + margin-bottom: 1rem; + font-style: normal; + line-height: inherit; +} + +ol, +ul, +dl { + margin-top: 0; + margin-bottom: 1rem; +} + +ol ol, +ul ul, +ol ul, +ul ol { + margin-bottom: 0; +} + +dt { + font-weight: 700; +} + +dd { + margin-bottom: .5rem; + margin-left: 0; +} + +blockquote { + margin: 0 0 1rem; +} + +b, +strong { + font-weight: bolder; +} + +small { + font-size: 80%; +} + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} + +sub { + bottom: -.25em; +} + +sup { + top: -.5em; +} + +a { + color: #007bff; + text-decoration: none; + background-color: transparent; +} + +a:hover { + color: #0056b3; + text-decoration: underline; +} + +a:not([href]):not([tabindex]) { + color: inherit; + text-decoration: none; +} + +a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus { + color: inherit; + text-decoration: none; +} + +a:not([href]):not([tabindex]):focus { + outline: 0; +} + +pre, +code, +kbd, +samp { + font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + font-size: 1em; +} + +pre { + margin-top: 0; + margin-bottom: 1rem; + overflow: auto; +} + +figure { + margin: 0 0 1rem; +} + +img { + vertical-align: middle; + border-style: none; +} + +svg { + overflow: hidden; + vertical-align: middle; +} + +table { + border-collapse: collapse; +} + +caption { + padding-top: 0.75rem; + padding-bottom: 0.75rem; + color: #6c757d; + text-align: left; + caption-side: bottom; +} + +th { + text-align: inherit; +} + +label { + display: inline-block; + margin-bottom: 0.5rem; +} + +button { + border-radius: 0; +} + +button:focus { + outline: 1px dotted; + outline: 5px auto -webkit-focus-ring-color; +} + +input, +button, +select, +optgroup, +textarea { + margin: 0; + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +button, +input { + overflow: visible; +} + +button, +select { + text-transform: none; +} + +select { + word-wrap: normal; +} + +button, +[type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} + +button:not(:disabled), +[type="button"]:not(:disabled), +[type="reset"]:not(:disabled), +[type="submit"]:not(:disabled) { + cursor: pointer; +} + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + padding: 0; + border-style: none; +} + +input[type="radio"], +input[type="checkbox"] { + box-sizing: border-box; + padding: 0; +} + +input[type="date"], +input[type="time"], +input[type="datetime-local"], +input[type="month"] { + -webkit-appearance: listbox; +} + +textarea { + overflow: auto; + resize: vertical; +} + +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} + +legend { + display: block; + width: 100%; + max-width: 100%; + padding: 0; + margin-bottom: .5rem; + font-size: 1.5rem; + line-height: inherit; + color: inherit; + white-space: normal; +} + +progress { + vertical-align: baseline; +} + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +[type="search"] { + outline-offset: -2px; + -webkit-appearance: none; +} + +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +::-webkit-file-upload-button { + font: inherit; + -webkit-appearance: button; +} + +output { + display: inline-block; +} + +summary { + display: list-item; + cursor: pointer; +} + +template { + display: none; +} + +[hidden] { + display: none !important; +} + +h1, h2, h3, h4, h5, h6, +.h1, .h2, .h3, .h4, .h5, .h6 { + margin-bottom: 0.5rem; + font-weight: 500; + line-height: 1.2; +} + +h1, .h1 { + font-size: 2.5rem; +} + +h2, .h2 { + font-size: 2rem; +} + +h3, .h3 { + font-size: 1.75rem; +} + +h4, .h4 { + font-size: 1.5rem; +} + +h5, .h5 { + font-size: 1.25rem; +} + +h6, .h6 { + font-size: 1rem; +} + +.lead { + font-size: 1.25rem; + font-weight: 300; +} + +.display-1 { + font-size: 6rem; + font-weight: 300; + line-height: 1.2; +} + +.display-2 { + font-size: 5.5rem; + font-weight: 300; + line-height: 1.2; +} + +.display-3 { + font-size: 4.5rem; + font-weight: 300; + line-height: 1.2; +} + +.display-4 { + font-size: 3.5rem; + font-weight: 300; + line-height: 1.2; +} + +hr { + margin-top: 1rem; + margin-bottom: 1rem; + border: 0; + border-top: 1px solid rgba(0, 0, 0, 0.1); +} + +small, +.small { + font-size: 80%; + font-weight: 400; +} + +mark, +.mark { + padding: 0.2em; + background-color: #fcf8e3; +} + +.list-unstyled { + padding-left: 0; + list-style: none; +} + +.list-inline { + padding-left: 0; + list-style: none; +} + +.list-inline-item { + display: inline-block; +} + +.list-inline-item:not(:last-child) { + margin-right: 0.5rem; +} + +.initialism { + font-size: 90%; + text-transform: uppercase; +} + +.blockquote { + margin-bottom: 1rem; + font-size: 1.25rem; +} + +.blockquote-footer { + display: block; + font-size: 80%; + color: #6c757d; +} + +.blockquote-footer::before { + content: "\2014\00A0"; +} + +.img-fluid { + max-width: 100%; + height: auto; +} + +.img-thumbnail { + padding: 0.25rem; + background-color: #fff; + border: 1px solid #dee2e6; + border-radius: 0.25rem; + max-width: 100%; + height: auto; +} + +.figure { + display: inline-block; +} + +.figure-img { + margin-bottom: 0.5rem; + line-height: 1; +} + +.figure-caption { + font-size: 90%; + color: #6c757d; +} + +code { + font-size: 87.5%; + color: #e83e8c; + word-break: break-word; +} + +a > code { + color: inherit; +} + +kbd { + padding: 0.2rem 0.4rem; + font-size: 87.5%; + color: #fff; + background-color: #212529; + border-radius: 0.2rem; +} + +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: 700; +} + +pre { + display: block; + font-size: 87.5%; + color: #212529; +} + +pre code { + font-size: inherit; + color: inherit; + word-break: normal; +} + +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} + +.container { + width: 100%; + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} + +@media (min-width: 576px) { + .container { + max-width: 540px; + } +} + +@media (min-width: 768px) { + .container { + max-width: 720px; + } +} + +@media (min-width: 992px) { + .container { + max-width: 960px; + } +} + +@media (min-width: 1200px) { + .container { + max-width: 1140px; + } +} + +.container-fluid { + width: 100%; + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} + +.row { + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-right: -15px; + margin-left: -15px; +} + +.no-gutters { + margin-right: 0; + margin-left: 0; +} + +.no-gutters > .col, +.no-gutters > [class*="col-"] { + padding-right: 0; + padding-left: 0; +} + +.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col, +.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm, +.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md, +.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg, +.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl, +.col-xl-auto { + position: relative; + width: 100%; + padding-right: 15px; + padding-left: 15px; +} + +.col { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; +} + +.col-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: 100%; +} + +.col-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; +} + +.col-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; +} + +.col-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; +} + +.col-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; +} + +.col-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; +} + +.col-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; +} + +.col-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; +} + +.col-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; +} + +.col-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; +} + +.col-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; +} + +.col-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; +} + +.col-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; +} + +.order-first { + -ms-flex-order: -1; + order: -1; +} + +.order-last { + -ms-flex-order: 13; + order: 13; +} + +.order-0 { + -ms-flex-order: 0; + order: 0; +} + +.order-1 { + -ms-flex-order: 1; + order: 1; +} + +.order-2 { + -ms-flex-order: 2; + order: 2; +} + +.order-3 { + -ms-flex-order: 3; + order: 3; +} + +.order-4 { + -ms-flex-order: 4; + order: 4; +} + +.order-5 { + -ms-flex-order: 5; + order: 5; +} + +.order-6 { + -ms-flex-order: 6; + order: 6; +} + +.order-7 { + -ms-flex-order: 7; + order: 7; +} + +.order-8 { + -ms-flex-order: 8; + order: 8; +} + +.order-9 { + -ms-flex-order: 9; + order: 9; +} + +.order-10 { + -ms-flex-order: 10; + order: 10; +} + +.order-11 { + -ms-flex-order: 11; + order: 11; +} + +.order-12 { + -ms-flex-order: 12; + order: 12; +} + +.offset-1 { + margin-left: 8.333333%; +} + +.offset-2 { + margin-left: 16.666667%; +} + +.offset-3 { + margin-left: 25%; +} + +.offset-4 { + margin-left: 33.333333%; +} + +.offset-5 { + margin-left: 41.666667%; +} + +.offset-6 { + margin-left: 50%; +} + +.offset-7 { + margin-left: 58.333333%; +} + +.offset-8 { + margin-left: 66.666667%; +} + +.offset-9 { + margin-left: 75%; +} + +.offset-10 { + margin-left: 83.333333%; +} + +.offset-11 { + margin-left: 91.666667%; +} + +@media (min-width: 576px) { + .col-sm { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; + } + .col-sm-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: 100%; + } + .col-sm-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; + } + .col-sm-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-sm-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-sm-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .col-sm-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; + } + .col-sm-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-sm-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; + } + .col-sm-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; + } + .col-sm-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-sm-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; + } + .col-sm-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; + } + .col-sm-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-sm-first { + -ms-flex-order: -1; + order: -1; + } + .order-sm-last { + -ms-flex-order: 13; + order: 13; + } + .order-sm-0 { + -ms-flex-order: 0; + order: 0; + } + .order-sm-1 { + -ms-flex-order: 1; + order: 1; + } + .order-sm-2 { + -ms-flex-order: 2; + order: 2; + } + .order-sm-3 { + -ms-flex-order: 3; + order: 3; + } + .order-sm-4 { + -ms-flex-order: 4; + order: 4; + } + .order-sm-5 { + -ms-flex-order: 5; + order: 5; + } + .order-sm-6 { + -ms-flex-order: 6; + order: 6; + } + .order-sm-7 { + -ms-flex-order: 7; + order: 7; + } + .order-sm-8 { + -ms-flex-order: 8; + order: 8; + } + .order-sm-9 { + -ms-flex-order: 9; + order: 9; + } + .order-sm-10 { + -ms-flex-order: 10; + order: 10; + } + .order-sm-11 { + -ms-flex-order: 11; + order: 11; + } + .order-sm-12 { + -ms-flex-order: 12; + order: 12; + } + .offset-sm-0 { + margin-left: 0; + } + .offset-sm-1 { + margin-left: 8.333333%; + } + .offset-sm-2 { + margin-left: 16.666667%; + } + .offset-sm-3 { + margin-left: 25%; + } + .offset-sm-4 { + margin-left: 33.333333%; + } + .offset-sm-5 { + margin-left: 41.666667%; + } + .offset-sm-6 { + margin-left: 50%; + } + .offset-sm-7 { + margin-left: 58.333333%; + } + .offset-sm-8 { + margin-left: 66.666667%; + } + .offset-sm-9 { + margin-left: 75%; + } + .offset-sm-10 { + margin-left: 83.333333%; + } + .offset-sm-11 { + margin-left: 91.666667%; + } +} + +@media (min-width: 768px) { + .col-md { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; + } + .col-md-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: 100%; + } + .col-md-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; + } + .col-md-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-md-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-md-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .col-md-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; + } + .col-md-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-md-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; + } + .col-md-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; + } + .col-md-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-md-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; + } + .col-md-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; + } + .col-md-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-md-first { + -ms-flex-order: -1; + order: -1; + } + .order-md-last { + -ms-flex-order: 13; + order: 13; + } + .order-md-0 { + -ms-flex-order: 0; + order: 0; + } + .order-md-1 { + -ms-flex-order: 1; + order: 1; + } + .order-md-2 { + -ms-flex-order: 2; + order: 2; + } + .order-md-3 { + -ms-flex-order: 3; + order: 3; + } + .order-md-4 { + -ms-flex-order: 4; + order: 4; + } + .order-md-5 { + -ms-flex-order: 5; + order: 5; + } + .order-md-6 { + -ms-flex-order: 6; + order: 6; + } + .order-md-7 { + -ms-flex-order: 7; + order: 7; + } + .order-md-8 { + -ms-flex-order: 8; + order: 8; + } + .order-md-9 { + -ms-flex-order: 9; + order: 9; + } + .order-md-10 { + -ms-flex-order: 10; + order: 10; + } + .order-md-11 { + -ms-flex-order: 11; + order: 11; + } + .order-md-12 { + -ms-flex-order: 12; + order: 12; + } + .offset-md-0 { + margin-left: 0; + } + .offset-md-1 { + margin-left: 8.333333%; + } + .offset-md-2 { + margin-left: 16.666667%; + } + .offset-md-3 { + margin-left: 25%; + } + .offset-md-4 { + margin-left: 33.333333%; + } + .offset-md-5 { + margin-left: 41.666667%; + } + .offset-md-6 { + margin-left: 50%; + } + .offset-md-7 { + margin-left: 58.333333%; + } + .offset-md-8 { + margin-left: 66.666667%; + } + .offset-md-9 { + margin-left: 75%; + } + .offset-md-10 { + margin-left: 83.333333%; + } + .offset-md-11 { + margin-left: 91.666667%; + } +} + +@media (min-width: 992px) { + .col-lg { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; + } + .col-lg-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: 100%; + } + .col-lg-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; + } + .col-lg-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-lg-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-lg-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .col-lg-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; + } + .col-lg-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-lg-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; + } + .col-lg-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; + } + .col-lg-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-lg-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; + } + .col-lg-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; + } + .col-lg-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-lg-first { + -ms-flex-order: -1; + order: -1; + } + .order-lg-last { + -ms-flex-order: 13; + order: 13; + } + .order-lg-0 { + -ms-flex-order: 0; + order: 0; + } + .order-lg-1 { + -ms-flex-order: 1; + order: 1; + } + .order-lg-2 { + -ms-flex-order: 2; + order: 2; + } + .order-lg-3 { + -ms-flex-order: 3; + order: 3; + } + .order-lg-4 { + -ms-flex-order: 4; + order: 4; + } + .order-lg-5 { + -ms-flex-order: 5; + order: 5; + } + .order-lg-6 { + -ms-flex-order: 6; + order: 6; + } + .order-lg-7 { + -ms-flex-order: 7; + order: 7; + } + .order-lg-8 { + -ms-flex-order: 8; + order: 8; + } + .order-lg-9 { + -ms-flex-order: 9; + order: 9; + } + .order-lg-10 { + -ms-flex-order: 10; + order: 10; + } + .order-lg-11 { + -ms-flex-order: 11; + order: 11; + } + .order-lg-12 { + -ms-flex-order: 12; + order: 12; + } + .offset-lg-0 { + margin-left: 0; + } + .offset-lg-1 { + margin-left: 8.333333%; + } + .offset-lg-2 { + margin-left: 16.666667%; + } + .offset-lg-3 { + margin-left: 25%; + } + .offset-lg-4 { + margin-left: 33.333333%; + } + .offset-lg-5 { + margin-left: 41.666667%; + } + .offset-lg-6 { + margin-left: 50%; + } + .offset-lg-7 { + margin-left: 58.333333%; + } + .offset-lg-8 { + margin-left: 66.666667%; + } + .offset-lg-9 { + margin-left: 75%; + } + .offset-lg-10 { + margin-left: 83.333333%; + } + .offset-lg-11 { + margin-left: 91.666667%; + } +} + +@media (min-width: 1200px) { + .col-xl { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; + } + .col-xl-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: 100%; + } + .col-xl-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; + } + .col-xl-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-xl-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-xl-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .col-xl-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; + } + .col-xl-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-xl-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; + } + .col-xl-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; + } + .col-xl-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-xl-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; + } + .col-xl-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; + } + .col-xl-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-xl-first { + -ms-flex-order: -1; + order: -1; + } + .order-xl-last { + -ms-flex-order: 13; + order: 13; + } + .order-xl-0 { + -ms-flex-order: 0; + order: 0; + } + .order-xl-1 { + -ms-flex-order: 1; + order: 1; + } + .order-xl-2 { + -ms-flex-order: 2; + order: 2; + } + .order-xl-3 { + -ms-flex-order: 3; + order: 3; + } + .order-xl-4 { + -ms-flex-order: 4; + order: 4; + } + .order-xl-5 { + -ms-flex-order: 5; + order: 5; + } + .order-xl-6 { + -ms-flex-order: 6; + order: 6; + } + .order-xl-7 { + -ms-flex-order: 7; + order: 7; + } + .order-xl-8 { + -ms-flex-order: 8; + order: 8; + } + .order-xl-9 { + -ms-flex-order: 9; + order: 9; + } + .order-xl-10 { + -ms-flex-order: 10; + order: 10; + } + .order-xl-11 { + -ms-flex-order: 11; + order: 11; + } + .order-xl-12 { + -ms-flex-order: 12; + order: 12; + } + .offset-xl-0 { + margin-left: 0; + } + .offset-xl-1 { + margin-left: 8.333333%; + } + .offset-xl-2 { + margin-left: 16.666667%; + } + .offset-xl-3 { + margin-left: 25%; + } + .offset-xl-4 { + margin-left: 33.333333%; + } + .offset-xl-5 { + margin-left: 41.666667%; + } + .offset-xl-6 { + margin-left: 50%; + } + .offset-xl-7 { + margin-left: 58.333333%; + } + .offset-xl-8 { + margin-left: 66.666667%; + } + .offset-xl-9 { + margin-left: 75%; + } + .offset-xl-10 { + margin-left: 83.333333%; + } + .offset-xl-11 { + margin-left: 91.666667%; + } +} + +.table { + width: 100%; + margin-bottom: 1rem; + color: #212529; +} + +.table th, +.table td { + padding: 0.75rem; + vertical-align: top; + border-top: 1px solid #dee2e6; +} + +.table thead th { + vertical-align: bottom; + border-bottom: 2px solid #dee2e6; +} + +.table tbody + tbody { + border-top: 2px solid #dee2e6; +} + +.table-sm th, +.table-sm td { + padding: 0.3rem; +} + +.table-bordered { + border: 1px solid #dee2e6; +} + +.table-bordered th, +.table-bordered td { + border: 1px solid #dee2e6; +} + +.table-bordered thead th, +.table-bordered thead td { + border-bottom-width: 2px; +} + +.table-borderless th, +.table-borderless td, +.table-borderless thead th, +.table-borderless tbody + tbody { + border: 0; +} + +.table-striped tbody tr:nth-of-type(odd) { + background-color: rgba(0, 0, 0, 0.05); +} + +.table-hover tbody tr:hover { + color: #212529; + background-color: rgba(0, 0, 0, 0.075); +} + +.table-primary, +.table-primary > th, +.table-primary > td { + background-color: #b8daff; +} + +.table-primary th, +.table-primary td, +.table-primary thead th, +.table-primary tbody + tbody { + border-color: #7abaff; +} + +.table-hover .table-primary:hover { + background-color: #9fcdff; +} + +.table-hover .table-primary:hover > td, +.table-hover .table-primary:hover > th { + background-color: #9fcdff; +} + +.table-secondary, +.table-secondary > th, +.table-secondary > td { + background-color: #d6d8db; +} + +.table-secondary th, +.table-secondary td, +.table-secondary thead th, +.table-secondary tbody + tbody { + border-color: #b3b7bb; +} + +.table-hover .table-secondary:hover { + background-color: #c8cbcf; +} + +.table-hover .table-secondary:hover > td, +.table-hover .table-secondary:hover > th { + background-color: #c8cbcf; +} + +.table-success, +.table-success > th, +.table-success > td { + background-color: #c3e6cb; +} + +.table-success th, +.table-success td, +.table-success thead th, +.table-success tbody + tbody { + border-color: #8fd19e; +} + +.table-hover .table-success:hover { + background-color: #b1dfbb; +} + +.table-hover .table-success:hover > td, +.table-hover .table-success:hover > th { + background-color: #b1dfbb; +} + +.table-info, +.table-info > th, +.table-info > td { + background-color: #bee5eb; +} + +.table-info th, +.table-info td, +.table-info thead th, +.table-info tbody + tbody { + border-color: #86cfda; +} + +.table-hover .table-info:hover { + background-color: #abdde5; +} + +.table-hover .table-info:hover > td, +.table-hover .table-info:hover > th { + background-color: #abdde5; +} + +.table-warning, +.table-warning > th, +.table-warning > td { + background-color: #ffeeba; +} + +.table-warning th, +.table-warning td, +.table-warning thead th, +.table-warning tbody + tbody { + border-color: #ffdf7e; +} + +.table-hover .table-warning:hover { + background-color: #ffe8a1; +} + +.table-hover .table-warning:hover > td, +.table-hover .table-warning:hover > th { + background-color: #ffe8a1; +} + +.table-danger, +.table-danger > th, +.table-danger > td { + background-color: #f5c6cb; +} + +.table-danger th, +.table-danger td, +.table-danger thead th, +.table-danger tbody + tbody { + border-color: #ed969e; +} + +.table-hover .table-danger:hover { + background-color: #f1b0b7; +} + +.table-hover .table-danger:hover > td, +.table-hover .table-danger:hover > th { + background-color: #f1b0b7; +} + +.table-light, +.table-light > th, +.table-light > td { + background-color: #fdfdfe; +} + +.table-light th, +.table-light td, +.table-light thead th, +.table-light tbody + tbody { + border-color: #fbfcfc; +} + +.table-hover .table-light:hover { + background-color: #ececf6; +} + +.table-hover .table-light:hover > td, +.table-hover .table-light:hover > th { + background-color: #ececf6; +} + +.table-dark, +.table-dark > th, +.table-dark > td { + background-color: #c6c8ca; +} + +.table-dark th, +.table-dark td, +.table-dark thead th, +.table-dark tbody + tbody { + border-color: #95999c; +} + +.table-hover .table-dark:hover { + background-color: #b9bbbe; +} + +.table-hover .table-dark:hover > td, +.table-hover .table-dark:hover > th { + background-color: #b9bbbe; +} + +.table-active, +.table-active > th, +.table-active > td { + background-color: rgba(0, 0, 0, 0.075); +} + +.table-hover .table-active:hover { + background-color: rgba(0, 0, 0, 0.075); +} + +.table-hover .table-active:hover > td, +.table-hover .table-active:hover > th { + background-color: rgba(0, 0, 0, 0.075); +} + +.table .thead-dark th { + color: #fff; + background-color: #343a40; + border-color: #454d55; +} + +.table .thead-light th { + color: #495057; + background-color: #e9ecef; + border-color: #dee2e6; +} + +.table-dark { + color: #fff; + background-color: #343a40; +} + +.table-dark th, +.table-dark td, +.table-dark thead th { + border-color: #454d55; +} + +.table-dark.table-bordered { + border: 0; +} + +.table-dark.table-striped tbody tr:nth-of-type(odd) { + background-color: rgba(255, 255, 255, 0.05); +} + +.table-dark.table-hover tbody tr:hover { + color: #fff; + background-color: rgba(255, 255, 255, 0.075); +} + +@media (max-width: 575.98px) { + .table-responsive-sm { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } + .table-responsive-sm > .table-bordered { + border: 0; + } +} + +@media (max-width: 767.98px) { + .table-responsive-md { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } + .table-responsive-md > .table-bordered { + border: 0; + } +} + +@media (max-width: 991.98px) { + .table-responsive-lg { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } + .table-responsive-lg > .table-bordered { + border: 0; + } +} + +@media (max-width: 1199.98px) { + .table-responsive-xl { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } + .table-responsive-xl > .table-bordered { + border: 0; + } +} + +.table-responsive { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; +} + +.table-responsive > .table-bordered { + border: 0; +} + +.form-control { + display: block; + width: 100%; + height: calc(1.5em + 0.75rem + 2px); + padding: 0.375rem 0.75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #495057; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #ced4da; + border-radius: 0.25rem; + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +@media (prefers-reduced-motion: reduce) { + .form-control { + transition: none; + } +} + +.form-control::-ms-expand { + background-color: transparent; + border: 0; +} + +.form-control:focus { + color: #495057; + background-color: #fff; + border-color: #80bdff; + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} + +.form-control::-webkit-input-placeholder { + color: #6c757d; + opacity: 1; +} + +.form-control::-moz-placeholder { + color: #6c757d; + opacity: 1; +} + +.form-control:-ms-input-placeholder { + color: #6c757d; + opacity: 1; +} + +.form-control::-ms-input-placeholder { + color: #6c757d; + opacity: 1; +} + +.form-control::placeholder { + color: #6c757d; + opacity: 1; +} + +.form-control:disabled, .form-control[readonly] { + background-color: #e9ecef; + opacity: 1; +} + +select.form-control:focus::-ms-value { + color: #495057; + background-color: #fff; +} + +.form-control-file, +.form-control-range { + display: block; + width: 100%; +} + +.col-form-label { + padding-top: calc(0.375rem + 1px); + padding-bottom: calc(0.375rem + 1px); + margin-bottom: 0; + font-size: inherit; + line-height: 1.5; +} + +.col-form-label-lg { + padding-top: calc(0.5rem + 1px); + padding-bottom: calc(0.5rem + 1px); + font-size: 1.25rem; + line-height: 1.5; +} + +.col-form-label-sm { + padding-top: calc(0.25rem + 1px); + padding-bottom: calc(0.25rem + 1px); + font-size: 0.875rem; + line-height: 1.5; +} + +.form-control-plaintext { + display: block; + width: 100%; + padding-top: 0.375rem; + padding-bottom: 0.375rem; + margin-bottom: 0; + line-height: 1.5; + color: #212529; + background-color: transparent; + border: solid transparent; + border-width: 1px 0; +} + +.form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg { + padding-right: 0; + padding-left: 0; +} + +.form-control-sm { + height: calc(1.5em + 0.5rem + 2px); + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; + border-radius: 0.2rem; +} + +.form-control-lg { + height: calc(1.5em + 1rem + 2px); + padding: 0.5rem 1rem; + font-size: 1.25rem; + line-height: 1.5; + border-radius: 0.3rem; +} + +select.form-control[size], select.form-control[multiple] { + height: auto; +} + +textarea.form-control { + height: auto; +} + +.form-group { + margin-bottom: 1rem; +} + +.form-text { + display: block; + margin-top: 0.25rem; +} + +.form-row { + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-right: -5px; + margin-left: -5px; +} + +.form-row > .col, +.form-row > [class*="col-"] { + padding-right: 5px; + padding-left: 5px; +} + +.form-check { + position: relative; + display: block; + padding-left: 1.25rem; +} + +.form-check-input { + position: absolute; + margin-top: 0.3rem; + margin-left: -1.25rem; +} + +.form-check-input:disabled ~ .form-check-label { + color: #6c757d; +} + +.form-check-label { + margin-bottom: 0; +} + +.form-check-inline { + display: -ms-inline-flexbox; + display: inline-flex; + -ms-flex-align: center; + align-items: center; + padding-left: 0; + margin-right: 0.75rem; +} + +.form-check-inline .form-check-input { + position: static; + margin-top: 0; + margin-right: 0.3125rem; + margin-left: 0; +} + +.valid-feedback { + display: none; + width: 100%; + margin-top: 0.25rem; + font-size: 80%; + color: #28a745; +} + +.valid-tooltip { + position: absolute; + top: 100%; + z-index: 5; + display: none; + max-width: 100%; + padding: 0.25rem 0.5rem; + margin-top: .1rem; + font-size: 0.875rem; + line-height: 1.5; + color: #fff; + background-color: rgba(40, 167, 69, 0.9); + border-radius: 0.25rem; +} + +.was-validated .form-control:valid, .form-control.is-valid { + border-color: #28a745; + padding-right: calc(1.5em + 0.75rem); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: center right calc(0.375em + 0.1875rem); + background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} + +.was-validated .form-control:valid:focus, .form-control.is-valid:focus { + border-color: #28a745; + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); +} + +.was-validated .form-control:valid ~ .valid-feedback, +.was-validated .form-control:valid ~ .valid-tooltip, .form-control.is-valid ~ .valid-feedback, +.form-control.is-valid ~ .valid-tooltip { + display: block; +} + +.was-validated textarea.form-control:valid, textarea.form-control.is-valid { + padding-right: calc(1.5em + 0.75rem); + background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); +} + +.was-validated .custom-select:valid, .custom-select.is-valid { + border-color: #28a745; + padding-right: calc((1em + 0.75rem) * 3 / 4 + 1.75rem); + background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px, url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} + +.was-validated .custom-select:valid:focus, .custom-select.is-valid:focus { + border-color: #28a745; + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); +} + +.was-validated .custom-select:valid ~ .valid-feedback, +.was-validated .custom-select:valid ~ .valid-tooltip, .custom-select.is-valid ~ .valid-feedback, +.custom-select.is-valid ~ .valid-tooltip { + display: block; +} + +.was-validated .form-control-file:valid ~ .valid-feedback, +.was-validated .form-control-file:valid ~ .valid-tooltip, .form-control-file.is-valid ~ .valid-feedback, +.form-control-file.is-valid ~ .valid-tooltip { + display: block; +} + +.was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label { + color: #28a745; +} + +.was-validated .form-check-input:valid ~ .valid-feedback, +.was-validated .form-check-input:valid ~ .valid-tooltip, .form-check-input.is-valid ~ .valid-feedback, +.form-check-input.is-valid ~ .valid-tooltip { + display: block; +} + +.was-validated .custom-control-input:valid ~ .custom-control-label, .custom-control-input.is-valid ~ .custom-control-label { + color: #28a745; +} + +.was-validated .custom-control-input:valid ~ .custom-control-label::before, .custom-control-input.is-valid ~ .custom-control-label::before { + border-color: #28a745; +} + +.was-validated .custom-control-input:valid ~ .valid-feedback, +.was-validated .custom-control-input:valid ~ .valid-tooltip, .custom-control-input.is-valid ~ .valid-feedback, +.custom-control-input.is-valid ~ .valid-tooltip { + display: block; +} + +.was-validated .custom-control-input:valid:checked ~ .custom-control-label::before, .custom-control-input.is-valid:checked ~ .custom-control-label::before { + border-color: #34ce57; + background-color: #34ce57; +} + +.was-validated .custom-control-input:valid:focus ~ .custom-control-label::before, .custom-control-input.is-valid:focus ~ .custom-control-label::before { + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); +} + +.was-validated .custom-control-input:valid:focus:not(:checked) ~ .custom-control-label::before, .custom-control-input.is-valid:focus:not(:checked) ~ .custom-control-label::before { + border-color: #28a745; +} + +.was-validated .custom-file-input:valid ~ .custom-file-label, .custom-file-input.is-valid ~ .custom-file-label { + border-color: #28a745; +} + +.was-validated .custom-file-input:valid ~ .valid-feedback, +.was-validated .custom-file-input:valid ~ .valid-tooltip, .custom-file-input.is-valid ~ .valid-feedback, +.custom-file-input.is-valid ~ .valid-tooltip { + display: block; +} + +.was-validated .custom-file-input:valid:focus ~ .custom-file-label, .custom-file-input.is-valid:focus ~ .custom-file-label { + border-color: #28a745; + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); +} + +.invalid-feedback { + display: none; + width: 100%; + margin-top: 0.25rem; + font-size: 80%; + color: #dc3545; +} + +.invalid-tooltip { + position: absolute; + top: 100%; + z-index: 5; + display: none; + max-width: 100%; + padding: 0.25rem 0.5rem; + margin-top: .1rem; + font-size: 0.875rem; + line-height: 1.5; + color: #fff; + background-color: rgba(220, 53, 69, 0.9); + border-radius: 0.25rem; +} + +.was-validated .form-control:invalid, .form-control.is-invalid { + border-color: #dc3545; + padding-right: calc(1.5em + 0.75rem); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23dc3545' viewBox='-2 -2 7 7'%3e%3cpath stroke='%23dc3545' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E"); + background-repeat: no-repeat; + background-position: center right calc(0.375em + 0.1875rem); + background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} + +.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus { + border-color: #dc3545; + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); +} + +.was-validated .form-control:invalid ~ .invalid-feedback, +.was-validated .form-control:invalid ~ .invalid-tooltip, .form-control.is-invalid ~ .invalid-feedback, +.form-control.is-invalid ~ .invalid-tooltip { + display: block; +} + +.was-validated textarea.form-control:invalid, textarea.form-control.is-invalid { + padding-right: calc(1.5em + 0.75rem); + background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); +} + +.was-validated .custom-select:invalid, .custom-select.is-invalid { + border-color: #dc3545; + padding-right: calc((1em + 0.75rem) * 3 / 4 + 1.75rem); + background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px, url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23dc3545' viewBox='-2 -2 7 7'%3e%3cpath stroke='%23dc3545' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E") #fff no-repeat center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} + +.was-validated .custom-select:invalid:focus, .custom-select.is-invalid:focus { + border-color: #dc3545; + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); +} + +.was-validated .custom-select:invalid ~ .invalid-feedback, +.was-validated .custom-select:invalid ~ .invalid-tooltip, .custom-select.is-invalid ~ .invalid-feedback, +.custom-select.is-invalid ~ .invalid-tooltip { + display: block; +} + +.was-validated .form-control-file:invalid ~ .invalid-feedback, +.was-validated .form-control-file:invalid ~ .invalid-tooltip, .form-control-file.is-invalid ~ .invalid-feedback, +.form-control-file.is-invalid ~ .invalid-tooltip { + display: block; +} + +.was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label { + color: #dc3545; +} + +.was-validated .form-check-input:invalid ~ .invalid-feedback, +.was-validated .form-check-input:invalid ~ .invalid-tooltip, .form-check-input.is-invalid ~ .invalid-feedback, +.form-check-input.is-invalid ~ .invalid-tooltip { + display: block; +} + +.was-validated .custom-control-input:invalid ~ .custom-control-label, .custom-control-input.is-invalid ~ .custom-control-label { + color: #dc3545; +} + +.was-validated .custom-control-input:invalid ~ .custom-control-label::before, .custom-control-input.is-invalid ~ .custom-control-label::before { + border-color: #dc3545; +} + +.was-validated .custom-control-input:invalid ~ .invalid-feedback, +.was-validated .custom-control-input:invalid ~ .invalid-tooltip, .custom-control-input.is-invalid ~ .invalid-feedback, +.custom-control-input.is-invalid ~ .invalid-tooltip { + display: block; +} + +.was-validated .custom-control-input:invalid:checked ~ .custom-control-label::before, .custom-control-input.is-invalid:checked ~ .custom-control-label::before { + border-color: #e4606d; + background-color: #e4606d; +} + +.was-validated .custom-control-input:invalid:focus ~ .custom-control-label::before, .custom-control-input.is-invalid:focus ~ .custom-control-label::before { + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); +} + +.was-validated .custom-control-input:invalid:focus:not(:checked) ~ .custom-control-label::before, .custom-control-input.is-invalid:focus:not(:checked) ~ .custom-control-label::before { + border-color: #dc3545; +} + +.was-validated .custom-file-input:invalid ~ .custom-file-label, .custom-file-input.is-invalid ~ .custom-file-label { + border-color: #dc3545; +} + +.was-validated .custom-file-input:invalid ~ .invalid-feedback, +.was-validated .custom-file-input:invalid ~ .invalid-tooltip, .custom-file-input.is-invalid ~ .invalid-feedback, +.custom-file-input.is-invalid ~ .invalid-tooltip { + display: block; +} + +.was-validated .custom-file-input:invalid:focus ~ .custom-file-label, .custom-file-input.is-invalid:focus ~ .custom-file-label { + border-color: #dc3545; + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); +} + +.form-inline { + display: -ms-flexbox; + display: flex; + -ms-flex-flow: row wrap; + flex-flow: row wrap; + -ms-flex-align: center; + align-items: center; +} + +.form-inline .form-check { + width: 100%; +} + +@media (min-width: 576px) { + .form-inline label { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + margin-bottom: 0; + } + .form-inline .form-group { + display: -ms-flexbox; + display: flex; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + -ms-flex-flow: row wrap; + flex-flow: row wrap; + -ms-flex-align: center; + align-items: center; + margin-bottom: 0; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .form-control-plaintext { + display: inline-block; + } + .form-inline .input-group, + .form-inline .custom-select { + width: auto; + } + .form-inline .form-check { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + width: auto; + padding-left: 0; + } + .form-inline .form-check-input { + position: relative; + -ms-flex-negative: 0; + flex-shrink: 0; + margin-top: 0; + margin-right: 0.25rem; + margin-left: 0; + } + .form-inline .custom-control { + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + } + .form-inline .custom-control-label { + margin-bottom: 0; + } +} + +.btn { + display: inline-block; + font-weight: 400; + color: #212529; + text-align: center; + vertical-align: middle; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-color: transparent; + border: 1px solid transparent; + padding: 0.375rem 0.75rem; + font-size: 1rem; + line-height: 1.5; + border-radius: 0.25rem; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +@media (prefers-reduced-motion: reduce) { + .btn { + transition: none; + } +} + +.btn:hover { + color: #212529; + text-decoration: none; +} + +.btn:focus, .btn.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} + +.btn.disabled, .btn:disabled { + opacity: 0.65; +} + +a.btn.disabled, +fieldset:disabled a.btn { + pointer-events: none; +} + +.btn-primary { + color: #fff; + background-color: #007bff; + border-color: #007bff; +} + +.btn-primary:hover { + color: #fff; + background-color: #0069d9; + border-color: #0062cc; +} + +.btn-primary:focus, .btn-primary.focus { + box-shadow: 0 0 0 0.2rem rgba(38, 143, 255, 0.5); +} + +.btn-primary.disabled, .btn-primary:disabled { + color: #fff; + background-color: #007bff; + border-color: #007bff; +} + +.btn-primary:not(:disabled):not(.disabled):active, .btn-primary:not(:disabled):not(.disabled).active, +.show > .btn-primary.dropdown-toggle { + color: #fff; + background-color: #0062cc; + border-color: #005cbf; +} + +.btn-primary:not(:disabled):not(.disabled):active:focus, .btn-primary:not(:disabled):not(.disabled).active:focus, +.show > .btn-primary.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(38, 143, 255, 0.5); +} + +.btn-secondary { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} + +.btn-secondary:hover { + color: #fff; + background-color: #5a6268; + border-color: #545b62; +} + +.btn-secondary:focus, .btn-secondary.focus { + box-shadow: 0 0 0 0.2rem rgba(130, 138, 145, 0.5); +} + +.btn-secondary.disabled, .btn-secondary:disabled { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} + +.btn-secondary:not(:disabled):not(.disabled):active, .btn-secondary:not(:disabled):not(.disabled).active, +.show > .btn-secondary.dropdown-toggle { + color: #fff; + background-color: #545b62; + border-color: #4e555b; +} + +.btn-secondary:not(:disabled):not(.disabled):active:focus, .btn-secondary:not(:disabled):not(.disabled).active:focus, +.show > .btn-secondary.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(130, 138, 145, 0.5); +} + +.btn-success { + color: #fff; + background-color: #28a745; + border-color: #28a745; +} + +.btn-success:hover { + color: #fff; + background-color: #218838; + border-color: #1e7e34; +} + +.btn-success:focus, .btn-success.focus { + box-shadow: 0 0 0 0.2rem rgba(72, 180, 97, 0.5); +} + +.btn-success.disabled, .btn-success:disabled { + color: #fff; + background-color: #28a745; + border-color: #28a745; +} + +.btn-success:not(:disabled):not(.disabled):active, .btn-success:not(:disabled):not(.disabled).active, +.show > .btn-success.dropdown-toggle { + color: #fff; + background-color: #1e7e34; + border-color: #1c7430; +} + +.btn-success:not(:disabled):not(.disabled):active:focus, .btn-success:not(:disabled):not(.disabled).active:focus, +.show > .btn-success.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(72, 180, 97, 0.5); +} + +.btn-info { + color: #fff; + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-info:hover { + color: #fff; + background-color: #138496; + border-color: #117a8b; +} + +.btn-info:focus, .btn-info.focus { + box-shadow: 0 0 0 0.2rem rgba(58, 176, 195, 0.5); +} + +.btn-info.disabled, .btn-info:disabled { + color: #fff; + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-info:not(:disabled):not(.disabled):active, .btn-info:not(:disabled):not(.disabled).active, +.show > .btn-info.dropdown-toggle { + color: #fff; + background-color: #117a8b; + border-color: #10707f; +} + +.btn-info:not(:disabled):not(.disabled):active:focus, .btn-info:not(:disabled):not(.disabled).active:focus, +.show > .btn-info.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(58, 176, 195, 0.5); +} + +.btn-warning { + color: #212529; + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-warning:hover { + color: #212529; + background-color: #e0a800; + border-color: #d39e00; +} + +.btn-warning:focus, .btn-warning.focus { + box-shadow: 0 0 0 0.2rem rgba(222, 170, 12, 0.5); +} + +.btn-warning.disabled, .btn-warning:disabled { + color: #212529; + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-warning:not(:disabled):not(.disabled):active, .btn-warning:not(:disabled):not(.disabled).active, +.show > .btn-warning.dropdown-toggle { + color: #212529; + background-color: #d39e00; + border-color: #c69500; +} + +.btn-warning:not(:disabled):not(.disabled):active:focus, .btn-warning:not(:disabled):not(.disabled).active:focus, +.show > .btn-warning.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(222, 170, 12, 0.5); +} + +.btn-danger { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-danger:hover { + color: #fff; + background-color: #c82333; + border-color: #bd2130; +} + +.btn-danger:focus, .btn-danger.focus { + box-shadow: 0 0 0 0.2rem rgba(225, 83, 97, 0.5); +} + +.btn-danger.disabled, .btn-danger:disabled { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-danger:not(:disabled):not(.disabled):active, .btn-danger:not(:disabled):not(.disabled).active, +.show > .btn-danger.dropdown-toggle { + color: #fff; + background-color: #bd2130; + border-color: #b21f2d; +} + +.btn-danger:not(:disabled):not(.disabled):active:focus, .btn-danger:not(:disabled):not(.disabled).active:focus, +.show > .btn-danger.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(225, 83, 97, 0.5); +} + +.btn-light { + color: #212529; + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-light:hover { + color: #212529; + background-color: #e2e6ea; + border-color: #dae0e5; +} + +.btn-light:focus, .btn-light.focus { + box-shadow: 0 0 0 0.2rem rgba(216, 217, 219, 0.5); +} + +.btn-light.disabled, .btn-light:disabled { + color: #212529; + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-light:not(:disabled):not(.disabled):active, .btn-light:not(:disabled):not(.disabled).active, +.show > .btn-light.dropdown-toggle { + color: #212529; + background-color: #dae0e5; + border-color: #d3d9df; +} + +.btn-light:not(:disabled):not(.disabled):active:focus, .btn-light:not(:disabled):not(.disabled).active:focus, +.show > .btn-light.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(216, 217, 219, 0.5); +} + +.btn-dark { + color: #fff; + background-color: #343a40; + border-color: #343a40; +} + +.btn-dark:hover { + color: #fff; + background-color: #23272b; + border-color: #1d2124; +} + +.btn-dark:focus, .btn-dark.focus { + box-shadow: 0 0 0 0.2rem rgba(82, 88, 93, 0.5); +} + +.btn-dark.disabled, .btn-dark:disabled { + color: #fff; + background-color: #343a40; + border-color: #343a40; +} + +.btn-dark:not(:disabled):not(.disabled):active, .btn-dark:not(:disabled):not(.disabled).active, +.show > .btn-dark.dropdown-toggle { + color: #fff; + background-color: #1d2124; + border-color: #171a1d; +} + +.btn-dark:not(:disabled):not(.disabled):active:focus, .btn-dark:not(:disabled):not(.disabled).active:focus, +.show > .btn-dark.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(82, 88, 93, 0.5); +} + +.btn-outline-primary { + color: #007bff; + border-color: #007bff; +} + +.btn-outline-primary:hover { + color: #fff; + background-color: #007bff; + border-color: #007bff; +} + +.btn-outline-primary:focus, .btn-outline-primary.focus { + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); +} + +.btn-outline-primary.disabled, .btn-outline-primary:disabled { + color: #007bff; + background-color: transparent; +} + +.btn-outline-primary:not(:disabled):not(.disabled):active, .btn-outline-primary:not(:disabled):not(.disabled).active, +.show > .btn-outline-primary.dropdown-toggle { + color: #fff; + background-color: #007bff; + border-color: #007bff; +} + +.btn-outline-primary:not(:disabled):not(.disabled):active:focus, .btn-outline-primary:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-primary.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); +} + +.btn-outline-secondary { + color: #6c757d; + border-color: #6c757d; +} + +.btn-outline-secondary:hover { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} + +.btn-outline-secondary:focus, .btn-outline-secondary.focus { + box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5); +} + +.btn-outline-secondary.disabled, .btn-outline-secondary:disabled { + color: #6c757d; + background-color: transparent; +} + +.btn-outline-secondary:not(:disabled):not(.disabled):active, .btn-outline-secondary:not(:disabled):not(.disabled).active, +.show > .btn-outline-secondary.dropdown-toggle { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} + +.btn-outline-secondary:not(:disabled):not(.disabled):active:focus, .btn-outline-secondary:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-secondary.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5); +} + +.btn-outline-success { + color: #28a745; + border-color: #28a745; +} + +.btn-outline-success:hover { + color: #fff; + background-color: #28a745; + border-color: #28a745; +} + +.btn-outline-success:focus, .btn-outline-success.focus { + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + +.btn-outline-success.disabled, .btn-outline-success:disabled { + color: #28a745; + background-color: transparent; +} + +.btn-outline-success:not(:disabled):not(.disabled):active, .btn-outline-success:not(:disabled):not(.disabled).active, +.show > .btn-outline-success.dropdown-toggle { + color: #fff; + background-color: #28a745; + border-color: #28a745; +} + +.btn-outline-success:not(:disabled):not(.disabled):active:focus, .btn-outline-success:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-success.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + +.btn-outline-info { + color: #17a2b8; + border-color: #17a2b8; +} + +.btn-outline-info:hover { + color: #fff; + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-outline-info:focus, .btn-outline-info.focus { + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + +.btn-outline-info.disabled, .btn-outline-info:disabled { + color: #17a2b8; + background-color: transparent; +} + +.btn-outline-info:not(:disabled):not(.disabled):active, .btn-outline-info:not(:disabled):not(.disabled).active, +.show > .btn-outline-info.dropdown-toggle { + color: #fff; + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-outline-info:not(:disabled):not(.disabled):active:focus, .btn-outline-info:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-info.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + +.btn-outline-warning { + color: #ffc107; + border-color: #ffc107; +} + +.btn-outline-warning:hover { + color: #212529; + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-outline-warning:focus, .btn-outline-warning.focus { + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + +.btn-outline-warning.disabled, .btn-outline-warning:disabled { + color: #ffc107; + background-color: transparent; +} + +.btn-outline-warning:not(:disabled):not(.disabled):active, .btn-outline-warning:not(:disabled):not(.disabled).active, +.show > .btn-outline-warning.dropdown-toggle { + color: #212529; + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-outline-warning:not(:disabled):not(.disabled):active:focus, .btn-outline-warning:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-warning.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + +.btn-outline-danger { + color: #dc3545; + border-color: #dc3545; +} + +.btn-outline-danger:hover { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-outline-danger:focus, .btn-outline-danger.focus { + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + +.btn-outline-danger.disabled, .btn-outline-danger:disabled { + color: #dc3545; + background-color: transparent; +} + +.btn-outline-danger:not(:disabled):not(.disabled):active, .btn-outline-danger:not(:disabled):not(.disabled).active, +.show > .btn-outline-danger.dropdown-toggle { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-outline-danger:not(:disabled):not(.disabled):active:focus, .btn-outline-danger:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-danger.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + +.btn-outline-light { + color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-outline-light:hover { + color: #212529; + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-outline-light:focus, .btn-outline-light.focus { + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + +.btn-outline-light.disabled, .btn-outline-light:disabled { + color: #f8f9fa; + background-color: transparent; +} + +.btn-outline-light:not(:disabled):not(.disabled):active, .btn-outline-light:not(:disabled):not(.disabled).active, +.show > .btn-outline-light.dropdown-toggle { + color: #212529; + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-outline-light:not(:disabled):not(.disabled):active:focus, .btn-outline-light:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-light.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + +.btn-outline-dark { + color: #343a40; + border-color: #343a40; +} + +.btn-outline-dark:hover { + color: #fff; + background-color: #343a40; + border-color: #343a40; +} + +.btn-outline-dark:focus, .btn-outline-dark.focus { + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.btn-outline-dark.disabled, .btn-outline-dark:disabled { + color: #343a40; + background-color: transparent; +} + +.btn-outline-dark:not(:disabled):not(.disabled):active, .btn-outline-dark:not(:disabled):not(.disabled).active, +.show > .btn-outline-dark.dropdown-toggle { + color: #fff; + background-color: #343a40; + border-color: #343a40; +} + +.btn-outline-dark:not(:disabled):not(.disabled):active:focus, .btn-outline-dark:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-dark.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.btn-link { + font-weight: 400; + color: #007bff; + text-decoration: none; +} + +.btn-link:hover { + color: #0056b3; + text-decoration: underline; +} + +.btn-link:focus, .btn-link.focus { + text-decoration: underline; + box-shadow: none; +} + +.btn-link:disabled, .btn-link.disabled { + color: #6c757d; + pointer-events: none; +} + +.btn-lg, .btn-group-lg > .btn { + padding: 0.5rem 1rem; + font-size: 1.25rem; + line-height: 1.5; + border-radius: 0.3rem; +} + +.btn-sm, .btn-group-sm > .btn { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; + border-radius: 0.2rem; +} + +.btn-block { + display: block; + width: 100%; +} + +.btn-block + .btn-block { + margin-top: 0.5rem; +} + +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} + +.fade { + transition: opacity 0.15s linear; +} + +@media (prefers-reduced-motion: reduce) { + .fade { + transition: none; + } +} + +.fade:not(.show) { + opacity: 0; +} + +.collapse:not(.show) { + display: none; +} + +.collapsing { + position: relative; + height: 0; + overflow: hidden; + transition: height 0.35s ease; +} + +@media (prefers-reduced-motion: reduce) { + .collapsing { + transition: none; + } +} + +.dropup, +.dropright, +.dropdown, +.dropleft { + position: relative; +} + +.dropdown-toggle { + white-space: nowrap; +} + +.dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0.3em solid; + border-right: 0.3em solid transparent; + border-bottom: 0; + border-left: 0.3em solid transparent; +} + +.dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 10rem; + padding: 0.5rem 0; + margin: 0.125rem 0 0; + font-size: 1rem; + color: #212529; + text-align: left; + list-style: none; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 0.25rem; +} + +.dropdown-menu-left { + right: auto; + left: 0; +} + +.dropdown-menu-right { + right: 0; + left: auto; +} + +@media (min-width: 576px) { + .dropdown-menu-sm-left { + right: auto; + left: 0; + } + .dropdown-menu-sm-right { + right: 0; + left: auto; + } +} + +@media (min-width: 768px) { + .dropdown-menu-md-left { + right: auto; + left: 0; + } + .dropdown-menu-md-right { + right: 0; + left: auto; + } +} + +@media (min-width: 992px) { + .dropdown-menu-lg-left { + right: auto; + left: 0; + } + .dropdown-menu-lg-right { + right: 0; + left: auto; + } +} + +@media (min-width: 1200px) { + .dropdown-menu-xl-left { + right: auto; + left: 0; + } + .dropdown-menu-xl-right { + right: 0; + left: auto; + } +} + +.dropup .dropdown-menu { + top: auto; + bottom: 100%; + margin-top: 0; + margin-bottom: 0.125rem; +} + +.dropup .dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0; + border-right: 0.3em solid transparent; + border-bottom: 0.3em solid; + border-left: 0.3em solid transparent; +} + +.dropup .dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropright .dropdown-menu { + top: 0; + right: auto; + left: 100%; + margin-top: 0; + margin-left: 0.125rem; +} + +.dropright .dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0.3em solid transparent; + border-right: 0; + border-bottom: 0.3em solid transparent; + border-left: 0.3em solid; +} + +.dropright .dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropright .dropdown-toggle::after { + vertical-align: 0; +} + +.dropleft .dropdown-menu { + top: 0; + right: 100%; + left: auto; + margin-top: 0; + margin-right: 0.125rem; +} + +.dropleft .dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; +} + +.dropleft .dropdown-toggle::after { + display: none; +} + +.dropleft .dropdown-toggle::before { + display: inline-block; + margin-right: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0.3em solid transparent; + border-right: 0.3em solid; + border-bottom: 0.3em solid transparent; +} + +.dropleft .dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropleft .dropdown-toggle::before { + vertical-align: 0; +} + +.dropdown-menu[x-placement^="top"], .dropdown-menu[x-placement^="right"], .dropdown-menu[x-placement^="bottom"], .dropdown-menu[x-placement^="left"] { + right: auto; + bottom: auto; +} + +.dropdown-divider { + height: 0; + margin: 0.5rem 0; + overflow: hidden; + border-top: 1px solid #e9ecef; +} + +.dropdown-item { + display: block; + width: 100%; + padding: 0.25rem 1.5rem; + clear: both; + font-weight: 400; + color: #212529; + text-align: inherit; + white-space: nowrap; + background-color: transparent; + border: 0; +} + +.dropdown-item:hover, .dropdown-item:focus { + color: #16181b; + text-decoration: none; + background-color: #f8f9fa; +} + +.dropdown-item.active, .dropdown-item:active { + color: #fff; + text-decoration: none; + background-color: #007bff; +} + +.dropdown-item.disabled, .dropdown-item:disabled { + color: #6c757d; + pointer-events: none; + background-color: transparent; +} + +.dropdown-menu.show { + display: block; +} + +.dropdown-header { + display: block; + padding: 0.5rem 1.5rem; + margin-bottom: 0; + font-size: 0.875rem; + color: #6c757d; + white-space: nowrap; +} + +.dropdown-item-text { + display: block; + padding: 0.25rem 1.5rem; + color: #212529; +} + +.btn-group, +.btn-group-vertical { + position: relative; + display: -ms-inline-flexbox; + display: inline-flex; + vertical-align: middle; +} + +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + -ms-flex: 1 1 auto; + flex: 1 1 auto; +} + +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover { + z-index: 1; +} + +.btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active, +.btn-group-vertical > .btn:focus, +.btn-group-vertical > .btn:active, +.btn-group-vertical > .btn.active { + z-index: 1; +} + +.btn-toolbar { + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.btn-toolbar .input-group { + width: auto; +} + +.btn-group > .btn:not(:first-child), +.btn-group > .btn-group:not(:first-child) { + margin-left: -1px; +} + +.btn-group > .btn:not(:last-child):not(.dropdown-toggle), +.btn-group > .btn-group:not(:last-child) > .btn { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.btn-group > .btn:not(:first-child), +.btn-group > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.dropdown-toggle-split { + padding-right: 0.5625rem; + padding-left: 0.5625rem; +} + +.dropdown-toggle-split::after, +.dropup .dropdown-toggle-split::after, +.dropright .dropdown-toggle-split::after { + margin-left: 0; +} + +.dropleft .dropdown-toggle-split::before { + margin-right: 0; +} + +.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split { + padding-right: 0.375rem; + padding-left: 0.375rem; +} + +.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split { + padding-right: 0.75rem; + padding-left: 0.75rem; +} + +.btn-group-vertical { + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-align: start; + align-items: flex-start; + -ms-flex-pack: center; + justify-content: center; +} + +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group { + width: 100%; +} + +.btn-group-vertical > .btn:not(:first-child), +.btn-group-vertical > .btn-group:not(:first-child) { + margin-top: -1px; +} + +.btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle), +.btn-group-vertical > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.btn-group-vertical > .btn:not(:first-child), +.btn-group-vertical > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.btn-group-toggle > .btn, +.btn-group-toggle > .btn-group > .btn { + margin-bottom: 0; +} + +.btn-group-toggle > .btn input[type="radio"], +.btn-group-toggle > .btn input[type="checkbox"], +.btn-group-toggle > .btn-group > .btn input[type="radio"], +.btn-group-toggle > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} + +.input-group { + position: relative; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -ms-flex-align: stretch; + align-items: stretch; + width: 100%; +} + +.input-group > .form-control, +.input-group > .form-control-plaintext, +.input-group > .custom-select, +.input-group > .custom-file { + position: relative; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + width: 1%; + margin-bottom: 0; +} + +.input-group > .form-control + .form-control, +.input-group > .form-control + .custom-select, +.input-group > .form-control + .custom-file, +.input-group > .form-control-plaintext + .form-control, +.input-group > .form-control-plaintext + .custom-select, +.input-group > .form-control-plaintext + .custom-file, +.input-group > .custom-select + .form-control, +.input-group > .custom-select + .custom-select, +.input-group > .custom-select + .custom-file, +.input-group > .custom-file + .form-control, +.input-group > .custom-file + .custom-select, +.input-group > .custom-file + .custom-file { + margin-left: -1px; +} + +.input-group > .form-control:focus, +.input-group > .custom-select:focus, +.input-group > .custom-file .custom-file-input:focus ~ .custom-file-label { + z-index: 3; +} + +.input-group > .custom-file .custom-file-input:focus { + z-index: 4; +} + +.input-group > .form-control:not(:last-child), +.input-group > .custom-select:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.input-group > .form-control:not(:first-child), +.input-group > .custom-select:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.input-group > .custom-file { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; +} + +.input-group > .custom-file:not(:last-child) .custom-file-label, +.input-group > .custom-file:not(:last-child) .custom-file-label::after { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.input-group > .custom-file:not(:first-child) .custom-file-label { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.input-group-prepend, +.input-group-append { + display: -ms-flexbox; + display: flex; +} + +.input-group-prepend .btn, +.input-group-append .btn { + position: relative; + z-index: 2; +} + +.input-group-prepend .btn:focus, +.input-group-append .btn:focus { + z-index: 3; +} + +.input-group-prepend .btn + .btn, +.input-group-prepend .btn + .input-group-text, +.input-group-prepend .input-group-text + .input-group-text, +.input-group-prepend .input-group-text + .btn, +.input-group-append .btn + .btn, +.input-group-append .btn + .input-group-text, +.input-group-append .input-group-text + .input-group-text, +.input-group-append .input-group-text + .btn { + margin-left: -1px; +} + +.input-group-prepend { + margin-right: -1px; +} + +.input-group-append { + margin-left: -1px; +} + +.input-group-text { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + padding: 0.375rem 0.75rem; + margin-bottom: 0; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #495057; + text-align: center; + white-space: nowrap; + background-color: #e9ecef; + border: 1px solid #ced4da; + border-radius: 0.25rem; +} + +.input-group-text input[type="radio"], +.input-group-text input[type="checkbox"] { + margin-top: 0; +} + +.input-group-lg > .form-control:not(textarea), +.input-group-lg > .custom-select { + height: calc(1.5em + 1rem + 2px); +} + +.input-group-lg > .form-control, +.input-group-lg > .custom-select, +.input-group-lg > .input-group-prepend > .input-group-text, +.input-group-lg > .input-group-append > .input-group-text, +.input-group-lg > .input-group-prepend > .btn, +.input-group-lg > .input-group-append > .btn { + padding: 0.5rem 1rem; + font-size: 1.25rem; + line-height: 1.5; + border-radius: 0.3rem; +} + +.input-group-sm > .form-control:not(textarea), +.input-group-sm > .custom-select { + height: calc(1.5em + 0.5rem + 2px); +} + +.input-group-sm > .form-control, +.input-group-sm > .custom-select, +.input-group-sm > .input-group-prepend > .input-group-text, +.input-group-sm > .input-group-append > .input-group-text, +.input-group-sm > .input-group-prepend > .btn, +.input-group-sm > .input-group-append > .btn { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; + border-radius: 0.2rem; +} + +.input-group-lg > .custom-select, +.input-group-sm > .custom-select { + padding-right: 1.75rem; +} + +.input-group > .input-group-prepend > .btn, +.input-group > .input-group-prepend > .input-group-text, +.input-group > .input-group-append:not(:last-child) > .btn, +.input-group > .input-group-append:not(:last-child) > .input-group-text, +.input-group > .input-group-append:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group > .input-group-append:last-child > .input-group-text:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.input-group > .input-group-append > .btn, +.input-group > .input-group-append > .input-group-text, +.input-group > .input-group-prepend:not(:first-child) > .btn, +.input-group > .input-group-prepend:not(:first-child) > .input-group-text, +.input-group > .input-group-prepend:first-child > .btn:not(:first-child), +.input-group > .input-group-prepend:first-child > .input-group-text:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.custom-control { + position: relative; + display: block; + min-height: 1.5rem; + padding-left: 1.5rem; +} + +.custom-control-inline { + display: -ms-inline-flexbox; + display: inline-flex; + margin-right: 1rem; +} + +.custom-control-input { + position: absolute; + z-index: -1; + opacity: 0; +} + +.custom-control-input:checked ~ .custom-control-label::before { + color: #fff; + border-color: #007bff; + background-color: #007bff; +} + +.custom-control-input:focus ~ .custom-control-label::before { + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} + +.custom-control-input:focus:not(:checked) ~ .custom-control-label::before { + border-color: #80bdff; +} + +.custom-control-input:not(:disabled):active ~ .custom-control-label::before { + color: #fff; + background-color: #b3d7ff; + border-color: #b3d7ff; +} + +.custom-control-input:disabled ~ .custom-control-label { + color: #6c757d; +} + +.custom-control-input:disabled ~ .custom-control-label::before { + background-color: #e9ecef; +} + +.custom-control-label { + position: relative; + margin-bottom: 0; + vertical-align: top; +} + +.custom-control-label::before { + position: absolute; + top: 0.25rem; + left: -1.5rem; + display: block; + width: 1rem; + height: 1rem; + pointer-events: none; + content: ""; + background-color: #fff; + border: #adb5bd solid 1px; +} + +.custom-control-label::after { + position: absolute; + top: 0.25rem; + left: -1.5rem; + display: block; + width: 1rem; + height: 1rem; + content: ""; + background: no-repeat 50% / 50% 50%; +} + +.custom-checkbox .custom-control-label::before { + border-radius: 0.25rem; +} + +.custom-checkbox .custom-control-input:checked ~ .custom-control-label::after { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e"); +} + +.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before { + border-color: #007bff; + background-color: #007bff; +} + +.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::after { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e"); +} + +.custom-checkbox .custom-control-input:disabled:checked ~ .custom-control-label::before { + background-color: rgba(0, 123, 255, 0.5); +} + +.custom-checkbox .custom-control-input:disabled:indeterminate ~ .custom-control-label::before { + background-color: rgba(0, 123, 255, 0.5); +} + +.custom-radio .custom-control-label::before { + border-radius: 50%; +} + +.custom-radio .custom-control-input:checked ~ .custom-control-label::after { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e"); +} + +.custom-radio .custom-control-input:disabled:checked ~ .custom-control-label::before { + background-color: rgba(0, 123, 255, 0.5); +} + +.custom-switch { + padding-left: 2.25rem; +} + +.custom-switch .custom-control-label::before { + left: -2.25rem; + width: 1.75rem; + pointer-events: all; + border-radius: 0.5rem; +} + +.custom-switch .custom-control-label::after { + top: calc(0.25rem + 2px); + left: calc(-2.25rem + 2px); + width: calc(1rem - 4px); + height: calc(1rem - 4px); + background-color: #adb5bd; + border-radius: 0.5rem; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-transform 0.15s ease-in-out; + transition: transform 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: transform 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-transform 0.15s ease-in-out; +} + +@media (prefers-reduced-motion: reduce) { + .custom-switch .custom-control-label::after { + transition: none; + } +} + +.custom-switch .custom-control-input:checked ~ .custom-control-label::after { + background-color: #fff; + -webkit-transform: translateX(0.75rem); + transform: translateX(0.75rem); +} + +.custom-switch .custom-control-input:disabled:checked ~ .custom-control-label::before { + background-color: rgba(0, 123, 255, 0.5); +} + +.custom-select { + display: inline-block; + width: 100%; + height: calc(1.5em + 0.75rem + 2px); + padding: 0.375rem 1.75rem 0.375rem 0.75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #495057; + vertical-align: middle; + background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px; + background-color: #fff; + border: 1px solid #ced4da; + border-radius: 0.25rem; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +.custom-select:focus { + border-color: #80bdff; + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} + +.custom-select:focus::-ms-value { + color: #495057; + background-color: #fff; +} + +.custom-select[multiple], .custom-select[size]:not([size="1"]) { + height: auto; + padding-right: 0.75rem; + background-image: none; +} + +.custom-select:disabled { + color: #6c757d; + background-color: #e9ecef; +} + +.custom-select::-ms-expand { + display: none; +} + +.custom-select-sm { + height: calc(1.5em + 0.5rem + 2px); + padding-top: 0.25rem; + padding-bottom: 0.25rem; + padding-left: 0.5rem; + font-size: 0.875rem; +} + +.custom-select-lg { + height: calc(1.5em + 1rem + 2px); + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 1rem; + font-size: 1.25rem; +} + +.custom-file { + position: relative; + display: inline-block; + width: 100%; + height: calc(1.5em + 0.75rem + 2px); + margin-bottom: 0; +} + +.custom-file-input { + position: relative; + z-index: 2; + width: 100%; + height: calc(1.5em + 0.75rem + 2px); + margin: 0; + opacity: 0; +} + +.custom-file-input:focus ~ .custom-file-label { + border-color: #80bdff; + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} + +.custom-file-input:disabled ~ .custom-file-label { + background-color: #e9ecef; +} + +.custom-file-input:lang(en) ~ .custom-file-label::after { + content: "Browse"; +} + +.custom-file-input ~ .custom-file-label[data-browse]::after { + content: attr(data-browse); +} + +.custom-file-label { + position: absolute; + top: 0; + right: 0; + left: 0; + z-index: 1; + height: calc(1.5em + 0.75rem + 2px); + padding: 0.375rem 0.75rem; + font-weight: 400; + line-height: 1.5; + color: #495057; + background-color: #fff; + border: 1px solid #ced4da; + border-radius: 0.25rem; +} + +.custom-file-label::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + z-index: 3; + display: block; + height: calc(1.5em + 0.75rem); + padding: 0.375rem 0.75rem; + line-height: 1.5; + color: #495057; + content: "Browse"; + background-color: #e9ecef; + border-left: inherit; + border-radius: 0 0.25rem 0.25rem 0; +} + +.custom-range { + width: 100%; + height: calc(1rem + 0.4rem); + padding: 0; + background-color: transparent; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +.custom-range:focus { + outline: none; +} + +.custom-range:focus::-webkit-slider-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} + +.custom-range:focus::-moz-range-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} + +.custom-range:focus::-ms-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} + +.custom-range::-moz-focus-outer { + border: 0; +} + +.custom-range::-webkit-slider-thumb { + width: 1rem; + height: 1rem; + margin-top: -0.25rem; + background-color: #007bff; + border: 0; + border-radius: 1rem; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + -webkit-appearance: none; + appearance: none; +} + +@media (prefers-reduced-motion: reduce) { + .custom-range::-webkit-slider-thumb { + transition: none; + } +} + +.custom-range::-webkit-slider-thumb:active { + background-color: #b3d7ff; +} + +.custom-range::-webkit-slider-runnable-track { + width: 100%; + height: 0.5rem; + color: transparent; + cursor: pointer; + background-color: #dee2e6; + border-color: transparent; + border-radius: 1rem; +} + +.custom-range::-moz-range-thumb { + width: 1rem; + height: 1rem; + background-color: #007bff; + border: 0; + border-radius: 1rem; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + -moz-appearance: none; + appearance: none; +} + +@media (prefers-reduced-motion: reduce) { + .custom-range::-moz-range-thumb { + transition: none; + } +} + +.custom-range::-moz-range-thumb:active { + background-color: #b3d7ff; +} + +.custom-range::-moz-range-track { + width: 100%; + height: 0.5rem; + color: transparent; + cursor: pointer; + background-color: #dee2e6; + border-color: transparent; + border-radius: 1rem; +} + +.custom-range::-ms-thumb { + width: 1rem; + height: 1rem; + margin-top: 0; + margin-right: 0.2rem; + margin-left: 0.2rem; + background-color: #007bff; + border: 0; + border-radius: 1rem; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + appearance: none; +} + +@media (prefers-reduced-motion: reduce) { + .custom-range::-ms-thumb { + transition: none; + } +} + +.custom-range::-ms-thumb:active { + background-color: #b3d7ff; +} + +.custom-range::-ms-track { + width: 100%; + height: 0.5rem; + color: transparent; + cursor: pointer; + background-color: transparent; + border-color: transparent; + border-width: 0.5rem; +} + +.custom-range::-ms-fill-lower { + background-color: #dee2e6; + border-radius: 1rem; +} + +.custom-range::-ms-fill-upper { + margin-right: 15px; + background-color: #dee2e6; + border-radius: 1rem; +} + +.custom-range:disabled::-webkit-slider-thumb { + background-color: #adb5bd; +} + +.custom-range:disabled::-webkit-slider-runnable-track { + cursor: default; +} + +.custom-range:disabled::-moz-range-thumb { + background-color: #adb5bd; +} + +.custom-range:disabled::-moz-range-track { + cursor: default; +} + +.custom-range:disabled::-ms-thumb { + background-color: #adb5bd; +} + +.custom-control-label::before, +.custom-file-label, +.custom-select { + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +@media (prefers-reduced-motion: reduce) { + .custom-control-label::before, + .custom-file-label, + .custom-select { + transition: none; + } +} + +.nav { + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + padding-left: 0; + margin-bottom: 0; + list-style: none; +} + +.nav-link { + display: block; + padding: 0.5rem 1rem; +} + +.nav-link:hover, .nav-link:focus { + text-decoration: none; +} + +.nav-link.disabled { + color: #6c757d; + pointer-events: none; + cursor: default; +} + +.nav-tabs { + border-bottom: 1px solid #dee2e6; +} + +.nav-tabs .nav-item { + margin-bottom: -1px; +} + +.nav-tabs .nav-link { + border: 1px solid transparent; + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} + +.nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus { + border-color: #e9ecef #e9ecef #dee2e6; +} + +.nav-tabs .nav-link.disabled { + color: #6c757d; + background-color: transparent; + border-color: transparent; +} + +.nav-tabs .nav-link.active, +.nav-tabs .nav-item.show .nav-link { + color: #495057; + background-color: #fff; + border-color: #dee2e6 #dee2e6 #fff; +} + +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.nav-pills .nav-link { + border-radius: 0.25rem; +} + +.nav-pills .nav-link.active, +.nav-pills .show > .nav-link { + color: #fff; + background-color: #007bff; +} + +.nav-fill .nav-item { + -ms-flex: 1 1 auto; + flex: 1 1 auto; + text-align: center; +} + +.nav-justified .nav-item { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + text-align: center; +} + +.tab-content > .tab-pane { + display: none; +} + +.tab-content > .active { + display: block; +} + +.navbar { + position: relative; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; + padding: 0.5rem 1rem; +} + +.navbar > .container, +.navbar > .container-fluid { + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; +} + +.navbar-brand { + display: inline-block; + padding-top: 0.3125rem; + padding-bottom: 0.3125rem; + margin-right: 1rem; + font-size: 1.25rem; + line-height: inherit; + white-space: nowrap; +} + +.navbar-brand:hover, .navbar-brand:focus { + text-decoration: none; +} + +.navbar-nav { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + padding-left: 0; + margin-bottom: 0; + list-style: none; +} + +.navbar-nav .nav-link { + padding-right: 0; + padding-left: 0; +} + +.navbar-nav .dropdown-menu { + position: static; + float: none; +} + +.navbar-text { + display: inline-block; + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.navbar-collapse { + -ms-flex-preferred-size: 100%; + flex-basis: 100%; + -ms-flex-positive: 1; + flex-grow: 1; + -ms-flex-align: center; + align-items: center; +} + +.navbar-toggler { + padding: 0.25rem 0.75rem; + font-size: 1.25rem; + line-height: 1; + background-color: transparent; + border: 1px solid transparent; + border-radius: 0.25rem; +} + +.navbar-toggler:hover, .navbar-toggler:focus { + text-decoration: none; +} + +.navbar-toggler-icon { + display: inline-block; + width: 1.5em; + height: 1.5em; + vertical-align: middle; + content: ""; + background: no-repeat center center; + background-size: 100% 100%; +} + +@media (max-width: 575.98px) { + .navbar-expand-sm > .container, + .navbar-expand-sm > .container-fluid { + padding-right: 0; + padding-left: 0; + } +} + +@media (min-width: 576px) { + .navbar-expand-sm { + -ms-flex-flow: row nowrap; + flex-flow: row nowrap; + -ms-flex-pack: start; + justify-content: flex-start; + } + .navbar-expand-sm .navbar-nav { + -ms-flex-direction: row; + flex-direction: row; + } + .navbar-expand-sm .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-sm .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-sm > .container, + .navbar-expand-sm > .container-fluid { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + } + .navbar-expand-sm .navbar-collapse { + display: -ms-flexbox !important; + display: flex !important; + -ms-flex-preferred-size: auto; + flex-basis: auto; + } + .navbar-expand-sm .navbar-toggler { + display: none; + } +} + +@media (max-width: 767.98px) { + .navbar-expand-md > .container, + .navbar-expand-md > .container-fluid { + padding-right: 0; + padding-left: 0; + } +} + +@media (min-width: 768px) { + .navbar-expand-md { + -ms-flex-flow: row nowrap; + flex-flow: row nowrap; + -ms-flex-pack: start; + justify-content: flex-start; + } + .navbar-expand-md .navbar-nav { + -ms-flex-direction: row; + flex-direction: row; + } + .navbar-expand-md .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-md .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-md > .container, + .navbar-expand-md > .container-fluid { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + } + .navbar-expand-md .navbar-collapse { + display: -ms-flexbox !important; + display: flex !important; + -ms-flex-preferred-size: auto; + flex-basis: auto; + } + .navbar-expand-md .navbar-toggler { + display: none; + } +} + +@media (max-width: 991.98px) { + .navbar-expand-lg > .container, + .navbar-expand-lg > .container-fluid { + padding-right: 0; + padding-left: 0; + } +} + +@media (min-width: 992px) { + .navbar-expand-lg { + -ms-flex-flow: row nowrap; + flex-flow: row nowrap; + -ms-flex-pack: start; + justify-content: flex-start; + } + .navbar-expand-lg .navbar-nav { + -ms-flex-direction: row; + flex-direction: row; + } + .navbar-expand-lg .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-lg .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-lg > .container, + .navbar-expand-lg > .container-fluid { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + } + .navbar-expand-lg .navbar-collapse { + display: -ms-flexbox !important; + display: flex !important; + -ms-flex-preferred-size: auto; + flex-basis: auto; + } + .navbar-expand-lg .navbar-toggler { + display: none; + } +} + +@media (max-width: 1199.98px) { + .navbar-expand-xl > .container, + .navbar-expand-xl > .container-fluid { + padding-right: 0; + padding-left: 0; + } +} + +@media (min-width: 1200px) { + .navbar-expand-xl { + -ms-flex-flow: row nowrap; + flex-flow: row nowrap; + -ms-flex-pack: start; + justify-content: flex-start; + } + .navbar-expand-xl .navbar-nav { + -ms-flex-direction: row; + flex-direction: row; + } + .navbar-expand-xl .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-xl .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-xl > .container, + .navbar-expand-xl > .container-fluid { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + } + .navbar-expand-xl .navbar-collapse { + display: -ms-flexbox !important; + display: flex !important; + -ms-flex-preferred-size: auto; + flex-basis: auto; + } + .navbar-expand-xl .navbar-toggler { + display: none; + } +} + +.navbar-expand { + -ms-flex-flow: row nowrap; + flex-flow: row nowrap; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.navbar-expand > .container, +.navbar-expand > .container-fluid { + padding-right: 0; + padding-left: 0; +} + +.navbar-expand .navbar-nav { + -ms-flex-direction: row; + flex-direction: row; +} + +.navbar-expand .navbar-nav .dropdown-menu { + position: absolute; +} + +.navbar-expand .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; +} + +.navbar-expand > .container, +.navbar-expand > .container-fluid { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; +} + +.navbar-expand .navbar-collapse { + display: -ms-flexbox !important; + display: flex !important; + -ms-flex-preferred-size: auto; + flex-basis: auto; +} + +.navbar-expand .navbar-toggler { + display: none; +} + +.navbar-light .navbar-brand { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-brand:hover, .navbar-light .navbar-brand:focus { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-nav .nav-link { + color: rgba(0, 0, 0, 0.5); +} + +.navbar-light .navbar-nav .nav-link:hover, .navbar-light .navbar-nav .nav-link:focus { + color: rgba(0, 0, 0, 0.7); +} + +.navbar-light .navbar-nav .nav-link.disabled { + color: rgba(0, 0, 0, 0.3); +} + +.navbar-light .navbar-nav .show > .nav-link, +.navbar-light .navbar-nav .active > .nav-link, +.navbar-light .navbar-nav .nav-link.show, +.navbar-light .navbar-nav .nav-link.active { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-toggler { + color: rgba(0, 0, 0, 0.5); + border-color: rgba(0, 0, 0, 0.1); +} + +.navbar-light .navbar-toggler-icon { + background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); +} + +.navbar-light .navbar-text { + color: rgba(0, 0, 0, 0.5); +} + +.navbar-light .navbar-text a { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-text a:hover, .navbar-light .navbar-text a:focus { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-dark .navbar-brand { + color: #fff; +} + +.navbar-dark .navbar-brand:hover, .navbar-dark .navbar-brand:focus { + color: #fff; +} + +.navbar-dark .navbar-nav .nav-link { + color: rgba(255, 255, 255, 0.5); +} + +.navbar-dark .navbar-nav .nav-link:hover, .navbar-dark .navbar-nav .nav-link:focus { + color: rgba(255, 255, 255, 0.75); +} + +.navbar-dark .navbar-nav .nav-link.disabled { + color: rgba(255, 255, 255, 0.25); +} + +.navbar-dark .navbar-nav .show > .nav-link, +.navbar-dark .navbar-nav .active > .nav-link, +.navbar-dark .navbar-nav .nav-link.show, +.navbar-dark .navbar-nav .nav-link.active { + color: #fff; +} + +.navbar-dark .navbar-toggler { + color: rgba(255, 255, 255, 0.5); + border-color: rgba(255, 255, 255, 0.1); +} + +.navbar-dark .navbar-toggler-icon { + background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); +} + +.navbar-dark .navbar-text { + color: rgba(255, 255, 255, 0.5); +} + +.navbar-dark .navbar-text a { + color: #fff; +} + +.navbar-dark .navbar-text a:hover, .navbar-dark .navbar-text a:focus { + color: #fff; +} + +.card { + position: relative; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + min-width: 0; + word-wrap: break-word; + background-color: #fff; + background-clip: border-box; + border: 1px solid rgba(0, 0, 0, 0.125); + border-radius: 0.25rem; +} + +.card > hr { + margin-right: 0; + margin-left: 0; +} + +.card > .list-group:first-child .list-group-item:first-child { + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} + +.card > .list-group:last-child .list-group-item:last-child { + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} + +.card-body { + -ms-flex: 1 1 auto; + flex: 1 1 auto; + padding: 1.25rem; +} + +.card-title { + margin-bottom: 0.75rem; +} + +.card-subtitle { + margin-top: -0.375rem; + margin-bottom: 0; +} + +.card-text:last-child { + margin-bottom: 0; +} + +.card-link:hover { + text-decoration: none; +} + +.card-link + .card-link { + margin-left: 1.25rem; +} + +.card-header { + padding: 0.75rem 1.25rem; + margin-bottom: 0; + background-color: rgba(0, 0, 0, 0.03); + border-bottom: 1px solid rgba(0, 0, 0, 0.125); +} + +.card-header:first-child { + border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0; +} + +.card-header + .list-group .list-group-item:first-child { + border-top: 0; +} + +.card-footer { + padding: 0.75rem 1.25rem; + background-color: rgba(0, 0, 0, 0.03); + border-top: 1px solid rgba(0, 0, 0, 0.125); +} + +.card-footer:last-child { + border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px); +} + +.card-header-tabs { + margin-right: -0.625rem; + margin-bottom: -0.75rem; + margin-left: -0.625rem; + border-bottom: 0; +} + +.card-header-pills { + margin-right: -0.625rem; + margin-left: -0.625rem; +} + +.card-img-overlay { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + padding: 1.25rem; +} + +.card-img { + width: 100%; + border-radius: calc(0.25rem - 1px); +} + +.card-img-top { + width: 100%; + border-top-left-radius: calc(0.25rem - 1px); + border-top-right-radius: calc(0.25rem - 1px); +} + +.card-img-bottom { + width: 100%; + border-bottom-right-radius: calc(0.25rem - 1px); + border-bottom-left-radius: calc(0.25rem - 1px); +} + +.card-deck { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; +} + +.card-deck .card { + margin-bottom: 15px; +} + +@media (min-width: 576px) { + .card-deck { + -ms-flex-flow: row wrap; + flex-flow: row wrap; + margin-right: -15px; + margin-left: -15px; + } + .card-deck .card { + display: -ms-flexbox; + display: flex; + -ms-flex: 1 0 0%; + flex: 1 0 0%; + -ms-flex-direction: column; + flex-direction: column; + margin-right: 15px; + margin-bottom: 0; + margin-left: 15px; + } +} + +.card-group { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; +} + +.card-group > .card { + margin-bottom: 15px; +} + +@media (min-width: 576px) { + .card-group { + -ms-flex-flow: row wrap; + flex-flow: row wrap; + } + .card-group > .card { + -ms-flex: 1 0 0%; + flex: 1 0 0%; + margin-bottom: 0; + } + .card-group > .card + .card { + margin-left: 0; + border-left: 0; + } + .card-group > .card:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + .card-group > .card:not(:last-child) .card-img-top, + .card-group > .card:not(:last-child) .card-header { + border-top-right-radius: 0; + } + .card-group > .card:not(:last-child) .card-img-bottom, + .card-group > .card:not(:last-child) .card-footer { + border-bottom-right-radius: 0; + } + .card-group > .card:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + .card-group > .card:not(:first-child) .card-img-top, + .card-group > .card:not(:first-child) .card-header { + border-top-left-radius: 0; + } + .card-group > .card:not(:first-child) .card-img-bottom, + .card-group > .card:not(:first-child) .card-footer { + border-bottom-left-radius: 0; + } +} + +.card-columns .card { + margin-bottom: 0.75rem; +} + +@media (min-width: 576px) { + .card-columns { + -webkit-column-count: 3; + -moz-column-count: 3; + column-count: 3; + -webkit-column-gap: 1.25rem; + -moz-column-gap: 1.25rem; + column-gap: 1.25rem; + orphans: 1; + widows: 1; + } + .card-columns .card { + display: inline-block; + width: 100%; + } +} + +.accordion > .card { + overflow: hidden; +} + +.accordion > .card:not(:first-of-type) .card-header:first-child { + border-radius: 0; +} + +.accordion > .card:not(:first-of-type):not(:last-of-type) { + border-bottom: 0; + border-radius: 0; +} + +.accordion > .card:first-of-type { + border-bottom: 0; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.accordion > .card:last-of-type { + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.accordion > .card .card-header { + margin-bottom: -1px; +} + +.breadcrumb { + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + padding: 0.75rem 1rem; + margin-bottom: 1rem; + list-style: none; + background-color: #e9ecef; + border-radius: 0.25rem; +} + +.breadcrumb-item + .breadcrumb-item { + padding-left: 0.5rem; +} + +.breadcrumb-item + .breadcrumb-item::before { + display: inline-block; + padding-right: 0.5rem; + color: #6c757d; + content: "/"; +} + +.breadcrumb-item + .breadcrumb-item:hover::before { + text-decoration: underline; +} + +.breadcrumb-item + .breadcrumb-item:hover::before { + text-decoration: none; +} + +.breadcrumb-item.active { + color: #6c757d; +} + +.pagination { + display: -ms-flexbox; + display: flex; + padding-left: 0; + list-style: none; + border-radius: 0.25rem; +} + +.page-link { + position: relative; + display: block; + padding: 0.5rem 0.75rem; + margin-left: -1px; + line-height: 1.25; + color: #007bff; + background-color: #fff; + border: 1px solid #dee2e6; +} + +.page-link:hover { + z-index: 2; + color: #0056b3; + text-decoration: none; + background-color: #e9ecef; + border-color: #dee2e6; +} + +.page-link:focus { + z-index: 2; + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} + +.page-item:first-child .page-link { + margin-left: 0; + border-top-left-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} + +.page-item:last-child .page-link { + border-top-right-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; +} + +.page-item.active .page-link { + z-index: 1; + color: #fff; + background-color: #007bff; + border-color: #007bff; +} + +.page-item.disabled .page-link { + color: #6c757d; + pointer-events: none; + cursor: auto; + background-color: #fff; + border-color: #dee2e6; +} + +.pagination-lg .page-link { + padding: 0.75rem 1.5rem; + font-size: 1.25rem; + line-height: 1.5; +} + +.pagination-lg .page-item:first-child .page-link { + border-top-left-radius: 0.3rem; + border-bottom-left-radius: 0.3rem; +} + +.pagination-lg .page-item:last-child .page-link { + border-top-right-radius: 0.3rem; + border-bottom-right-radius: 0.3rem; +} + +.pagination-sm .page-link { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; +} + +.pagination-sm .page-item:first-child .page-link { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; +} + +.pagination-sm .page-item:last-child .page-link { + border-top-right-radius: 0.2rem; + border-bottom-right-radius: 0.2rem; +} + +.badge { + display: inline-block; + padding: 0.25em 0.4em; + font-size: 75%; + font-weight: 700; + line-height: 1; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: 0.25rem; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +@media (prefers-reduced-motion: reduce) { + .badge { + transition: none; + } +} + +a.badge:hover, a.badge:focus { + text-decoration: none; +} + +.badge:empty { + display: none; +} + +.btn .badge { + position: relative; + top: -1px; +} + +.badge-pill { + padding-right: 0.6em; + padding-left: 0.6em; + border-radius: 10rem; +} + +.badge-primary { + color: #fff; + background-color: #007bff; +} + +a.badge-primary:hover, a.badge-primary:focus { + color: #fff; + background-color: #0062cc; +} + +a.badge-primary:focus, a.badge-primary.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); +} + +.badge-secondary { + color: #fff; + background-color: #6c757d; +} + +a.badge-secondary:hover, a.badge-secondary:focus { + color: #fff; + background-color: #545b62; +} + +a.badge-secondary:focus, a.badge-secondary.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5); +} + +.badge-success { + color: #fff; + background-color: #28a745; +} + +a.badge-success:hover, a.badge-success:focus { + color: #fff; + background-color: #1e7e34; +} + +a.badge-success:focus, a.badge-success.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + +.badge-info { + color: #fff; + background-color: #17a2b8; +} + +a.badge-info:hover, a.badge-info:focus { + color: #fff; + background-color: #117a8b; +} + +a.badge-info:focus, a.badge-info.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + +.badge-warning { + color: #212529; + background-color: #ffc107; +} + +a.badge-warning:hover, a.badge-warning:focus { + color: #212529; + background-color: #d39e00; +} + +a.badge-warning:focus, a.badge-warning.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + +.badge-danger { + color: #fff; + background-color: #dc3545; +} + +a.badge-danger:hover, a.badge-danger:focus { + color: #fff; + background-color: #bd2130; +} + +a.badge-danger:focus, a.badge-danger.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + +.badge-light { + color: #212529; + background-color: #f8f9fa; +} + +a.badge-light:hover, a.badge-light:focus { + color: #212529; + background-color: #dae0e5; +} + +a.badge-light:focus, a.badge-light.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + +.badge-dark { + color: #fff; + background-color: #343a40; +} + +a.badge-dark:hover, a.badge-dark:focus { + color: #fff; + background-color: #1d2124; +} + +a.badge-dark:focus, a.badge-dark.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.jumbotron { + padding: 2rem 1rem; + margin-bottom: 2rem; + background-color: #e9ecef; + border-radius: 0.3rem; +} + +@media (min-width: 576px) { + .jumbotron { + padding: 4rem 2rem; + } +} + +.jumbotron-fluid { + padding-right: 0; + padding-left: 0; + border-radius: 0; +} + +.alert { + position: relative; + padding: 0.75rem 1.25rem; + margin-bottom: 1rem; + border: 1px solid transparent; + border-radius: 0.25rem; +} + +.alert-heading { + color: inherit; +} + +.alert-link { + font-weight: 700; +} + +.alert-dismissible { + padding-right: 4rem; +} + +.alert-dismissible .close { + position: absolute; + top: 0; + right: 0; + padding: 0.75rem 1.25rem; + color: inherit; +} + +.alert-primary { + color: #004085; + background-color: #cce5ff; + border-color: #b8daff; +} + +.alert-primary hr { + border-top-color: #9fcdff; +} + +.alert-primary .alert-link { + color: #002752; +} + +.alert-secondary { + color: #383d41; + background-color: #e2e3e5; + border-color: #d6d8db; +} + +.alert-secondary hr { + border-top-color: #c8cbcf; +} + +.alert-secondary .alert-link { + color: #202326; +} + +.alert-success { + color: #155724; + background-color: #d4edda; + border-color: #c3e6cb; +} + +.alert-success hr { + border-top-color: #b1dfbb; +} + +.alert-success .alert-link { + color: #0b2e13; +} + +.alert-info { + color: #0c5460; + background-color: #d1ecf1; + border-color: #bee5eb; +} + +.alert-info hr { + border-top-color: #abdde5; +} + +.alert-info .alert-link { + color: #062c33; +} + +.alert-warning { + color: #856404; + background-color: #fff3cd; + border-color: #ffeeba; +} + +.alert-warning hr { + border-top-color: #ffe8a1; +} + +.alert-warning .alert-link { + color: #533f03; +} + +.alert-danger { + color: #721c24; + background-color: #f8d7da; + border-color: #f5c6cb; +} + +.alert-danger hr { + border-top-color: #f1b0b7; +} + +.alert-danger .alert-link { + color: #491217; +} + +.alert-light { + color: #818182; + background-color: #fefefe; + border-color: #fdfdfe; +} + +.alert-light hr { + border-top-color: #ececf6; +} + +.alert-light .alert-link { + color: #686868; +} + +.alert-dark { + color: #1b1e21; + background-color: #d6d8d9; + border-color: #c6c8ca; +} + +.alert-dark hr { + border-top-color: #b9bbbe; +} + +.alert-dark .alert-link { + color: #040505; +} + +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 1rem 0; + } + to { + background-position: 0 0; + } +} + +@keyframes progress-bar-stripes { + from { + background-position: 1rem 0; + } + to { + background-position: 0 0; + } +} + +.progress { + display: -ms-flexbox; + display: flex; + height: 1rem; + overflow: hidden; + font-size: 0.75rem; + background-color: #e9ecef; + border-radius: 0.25rem; +} + +.progress-bar { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-pack: center; + justify-content: center; + color: #fff; + text-align: center; + white-space: nowrap; + background-color: #007bff; + transition: width 0.6s ease; +} + +@media (prefers-reduced-motion: reduce) { + .progress-bar { + transition: none; + } +} + +.progress-bar-striped { + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: 1rem 1rem; +} + +.progress-bar-animated { + -webkit-animation: progress-bar-stripes 1s linear infinite; + animation: progress-bar-stripes 1s linear infinite; +} + +@media (prefers-reduced-motion: reduce) { + .progress-bar-animated { + -webkit-animation: none; + animation: none; + } +} + +.media { + display: -ms-flexbox; + display: flex; + -ms-flex-align: start; + align-items: flex-start; +} + +.media-body { + -ms-flex: 1; + flex: 1; +} + +.list-group { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + padding-left: 0; + margin-bottom: 0; +} + +.list-group-item-action { + width: 100%; + color: #495057; + text-align: inherit; +} + +.list-group-item-action:hover, .list-group-item-action:focus { + z-index: 1; + color: #495057; + text-decoration: none; + background-color: #f8f9fa; +} + +.list-group-item-action:active { + color: #212529; + background-color: #e9ecef; +} + +.list-group-item { + position: relative; + display: block; + padding: 0.75rem 1.25rem; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid rgba(0, 0, 0, 0.125); +} + +.list-group-item:first-child { + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} + +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} + +.list-group-item.disabled, .list-group-item:disabled { + color: #6c757d; + pointer-events: none; + background-color: #fff; +} + +.list-group-item.active { + z-index: 2; + color: #fff; + background-color: #007bff; + border-color: #007bff; +} + +.list-group-horizontal { + -ms-flex-direction: row; + flex-direction: row; +} + +.list-group-horizontal .list-group-item { + margin-right: -1px; + margin-bottom: 0; +} + +.list-group-horizontal .list-group-item:first-child { + border-top-left-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; +} + +.list-group-horizontal .list-group-item:last-child { + margin-right: 0; + border-top-right-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0; +} + +@media (min-width: 576px) { + .list-group-horizontal-sm { + -ms-flex-direction: row; + flex-direction: row; + } + .list-group-horizontal-sm .list-group-item { + margin-right: -1px; + margin-bottom: 0; + } + .list-group-horizontal-sm .list-group-item:first-child { + border-top-left-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + .list-group-horizontal-sm .list-group-item:last-child { + margin-right: 0; + border-top-right-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } +} + +@media (min-width: 768px) { + .list-group-horizontal-md { + -ms-flex-direction: row; + flex-direction: row; + } + .list-group-horizontal-md .list-group-item { + margin-right: -1px; + margin-bottom: 0; + } + .list-group-horizontal-md .list-group-item:first-child { + border-top-left-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + .list-group-horizontal-md .list-group-item:last-child { + margin-right: 0; + border-top-right-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } +} + +@media (min-width: 992px) { + .list-group-horizontal-lg { + -ms-flex-direction: row; + flex-direction: row; + } + .list-group-horizontal-lg .list-group-item { + margin-right: -1px; + margin-bottom: 0; + } + .list-group-horizontal-lg .list-group-item:first-child { + border-top-left-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + .list-group-horizontal-lg .list-group-item:last-child { + margin-right: 0; + border-top-right-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } +} + +@media (min-width: 1200px) { + .list-group-horizontal-xl { + -ms-flex-direction: row; + flex-direction: row; + } + .list-group-horizontal-xl .list-group-item { + margin-right: -1px; + margin-bottom: 0; + } + .list-group-horizontal-xl .list-group-item:first-child { + border-top-left-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + .list-group-horizontal-xl .list-group-item:last-child { + margin-right: 0; + border-top-right-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } +} + +.list-group-flush .list-group-item { + border-right: 0; + border-left: 0; + border-radius: 0; +} + +.list-group-flush .list-group-item:last-child { + margin-bottom: -1px; +} + +.list-group-flush:first-child .list-group-item:first-child { + border-top: 0; +} + +.list-group-flush:last-child .list-group-item:last-child { + margin-bottom: 0; + border-bottom: 0; +} + +.list-group-item-primary { + color: #004085; + background-color: #b8daff; +} + +.list-group-item-primary.list-group-item-action:hover, .list-group-item-primary.list-group-item-action:focus { + color: #004085; + background-color: #9fcdff; +} + +.list-group-item-primary.list-group-item-action.active { + color: #fff; + background-color: #004085; + border-color: #004085; +} + +.list-group-item-secondary { + color: #383d41; + background-color: #d6d8db; +} + +.list-group-item-secondary.list-group-item-action:hover, .list-group-item-secondary.list-group-item-action:focus { + color: #383d41; + background-color: #c8cbcf; +} + +.list-group-item-secondary.list-group-item-action.active { + color: #fff; + background-color: #383d41; + border-color: #383d41; +} + +.list-group-item-success { + color: #155724; + background-color: #c3e6cb; +} + +.list-group-item-success.list-group-item-action:hover, .list-group-item-success.list-group-item-action:focus { + color: #155724; + background-color: #b1dfbb; +} + +.list-group-item-success.list-group-item-action.active { + color: #fff; + background-color: #155724; + border-color: #155724; +} + +.list-group-item-info { + color: #0c5460; + background-color: #bee5eb; +} + +.list-group-item-info.list-group-item-action:hover, .list-group-item-info.list-group-item-action:focus { + color: #0c5460; + background-color: #abdde5; +} + +.list-group-item-info.list-group-item-action.active { + color: #fff; + background-color: #0c5460; + border-color: #0c5460; +} + +.list-group-item-warning { + color: #856404; + background-color: #ffeeba; +} + +.list-group-item-warning.list-group-item-action:hover, .list-group-item-warning.list-group-item-action:focus { + color: #856404; + background-color: #ffe8a1; +} + +.list-group-item-warning.list-group-item-action.active { + color: #fff; + background-color: #856404; + border-color: #856404; +} + +.list-group-item-danger { + color: #721c24; + background-color: #f5c6cb; +} + +.list-group-item-danger.list-group-item-action:hover, .list-group-item-danger.list-group-item-action:focus { + color: #721c24; + background-color: #f1b0b7; +} + +.list-group-item-danger.list-group-item-action.active { + color: #fff; + background-color: #721c24; + border-color: #721c24; +} + +.list-group-item-light { + color: #818182; + background-color: #fdfdfe; +} + +.list-group-item-light.list-group-item-action:hover, .list-group-item-light.list-group-item-action:focus { + color: #818182; + background-color: #ececf6; +} + +.list-group-item-light.list-group-item-action.active { + color: #fff; + background-color: #818182; + border-color: #818182; +} + +.list-group-item-dark { + color: #1b1e21; + background-color: #c6c8ca; +} + +.list-group-item-dark.list-group-item-action:hover, .list-group-item-dark.list-group-item-action:focus { + color: #1b1e21; + background-color: #b9bbbe; +} + +.list-group-item-dark.list-group-item-action.active { + color: #fff; + background-color: #1b1e21; + border-color: #1b1e21; +} + +.close { + float: right; + font-size: 1.5rem; + font-weight: 700; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + opacity: .5; +} + +.close:hover { + color: #000; + text-decoration: none; +} + +.close:not(:disabled):not(.disabled):hover, .close:not(:disabled):not(.disabled):focus { + opacity: .75; +} + +button.close { + padding: 0; + background-color: transparent; + border: 0; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +a.close.disabled { + pointer-events: none; +} + +.toast { + max-width: 350px; + overflow: hidden; + font-size: 0.875rem; + background-color: rgba(255, 255, 255, 0.85); + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.1); + box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.1); + -webkit-backdrop-filter: blur(10px); + backdrop-filter: blur(10px); + opacity: 0; + border-radius: 0.25rem; +} + +.toast:not(:last-child) { + margin-bottom: 0.75rem; +} + +.toast.showing { + opacity: 1; +} + +.toast.show { + display: block; + opacity: 1; +} + +.toast.hide { + display: none; +} + +.toast-header { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + padding: 0.25rem 0.75rem; + color: #6c757d; + background-color: rgba(255, 255, 255, 0.85); + background-clip: padding-box; + border-bottom: 1px solid rgba(0, 0, 0, 0.05); +} + +.toast-body { + padding: 0.75rem; +} + +.modal-open { + overflow: hidden; +} + +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} + +.modal { + position: fixed; + top: 0; + left: 0; + z-index: 1050; + display: none; + width: 100%; + height: 100%; + overflow: hidden; + outline: 0; +} + +.modal-dialog { + position: relative; + width: auto; + margin: 0.5rem; + pointer-events: none; +} + +.modal.fade .modal-dialog { + transition: -webkit-transform 0.3s ease-out; + transition: transform 0.3s ease-out; + transition: transform 0.3s ease-out, -webkit-transform 0.3s ease-out; + -webkit-transform: translate(0, -50px); + transform: translate(0, -50px); +} + +@media (prefers-reduced-motion: reduce) { + .modal.fade .modal-dialog { + transition: none; + } +} + +.modal.show .modal-dialog { + -webkit-transform: none; + transform: none; +} + +.modal-dialog-scrollable { + display: -ms-flexbox; + display: flex; + max-height: calc(100% - 1rem); +} + +.modal-dialog-scrollable .modal-content { + max-height: calc(100vh - 1rem); + overflow: hidden; +} + +.modal-dialog-scrollable .modal-header, +.modal-dialog-scrollable .modal-footer { + -ms-flex-negative: 0; + flex-shrink: 0; +} + +.modal-dialog-scrollable .modal-body { + overflow-y: auto; +} + +.modal-dialog-centered { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + min-height: calc(100% - 1rem); +} + +.modal-dialog-centered::before { + display: block; + height: calc(100vh - 1rem); + content: ""; +} + +.modal-dialog-centered.modal-dialog-scrollable { + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-pack: center; + justify-content: center; + height: 100%; +} + +.modal-dialog-centered.modal-dialog-scrollable .modal-content { + max-height: none; +} + +.modal-dialog-centered.modal-dialog-scrollable::before { + content: none; +} + +.modal-content { + position: relative; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + width: 100%; + pointer-events: auto; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 0.3rem; + outline: 0; +} + +.modal-backdrop { + position: fixed; + top: 0; + left: 0; + z-index: 1040; + width: 100vw; + height: 100vh; + background-color: #000; +} + +.modal-backdrop.fade { + opacity: 0; +} + +.modal-backdrop.show { + opacity: 0.5; +} + +.modal-header { + display: -ms-flexbox; + display: flex; + -ms-flex-align: start; + align-items: flex-start; + -ms-flex-pack: justify; + justify-content: space-between; + padding: 1rem 1rem; + border-bottom: 1px solid #dee2e6; + border-top-left-radius: 0.3rem; + border-top-right-radius: 0.3rem; +} + +.modal-header .close { + padding: 1rem 1rem; + margin: -1rem -1rem -1rem auto; +} + +.modal-title { + margin-bottom: 0; + line-height: 1.5; +} + +.modal-body { + position: relative; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + padding: 1rem; +} + +.modal-footer { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: end; + justify-content: flex-end; + padding: 1rem; + border-top: 1px solid #dee2e6; + border-bottom-right-radius: 0.3rem; + border-bottom-left-radius: 0.3rem; +} + +.modal-footer > :not(:first-child) { + margin-left: .25rem; +} + +.modal-footer > :not(:last-child) { + margin-right: .25rem; +} + +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} + +@media (min-width: 576px) { + .modal-dialog { + max-width: 500px; + margin: 1.75rem auto; + } + .modal-dialog-scrollable { + max-height: calc(100% - 3.5rem); + } + .modal-dialog-scrollable .modal-content { + max-height: calc(100vh - 3.5rem); + } + .modal-dialog-centered { + min-height: calc(100% - 3.5rem); + } + .modal-dialog-centered::before { + height: calc(100vh - 3.5rem); + } + .modal-sm { + max-width: 300px; + } +} + +@media (min-width: 992px) { + .modal-lg, + .modal-xl { + max-width: 800px; + } +} + +@media (min-width: 1200px) { + .modal-xl { + max-width: 1140px; + } +} + +.tooltip { + position: absolute; + z-index: 1070; + display: block; + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-style: normal; + font-weight: 400; + line-height: 1.5; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + white-space: normal; + line-break: auto; + font-size: 0.875rem; + word-wrap: break-word; + opacity: 0; +} + +.tooltip.show { + opacity: 0.9; +} + +.tooltip .arrow { + position: absolute; + display: block; + width: 0.8rem; + height: 0.4rem; +} + +.tooltip .arrow::before { + position: absolute; + content: ""; + border-color: transparent; + border-style: solid; +} + +.bs-tooltip-top, .bs-tooltip-auto[x-placement^="top"] { + padding: 0.4rem 0; +} + +.bs-tooltip-top .arrow, .bs-tooltip-auto[x-placement^="top"] .arrow { + bottom: 0; +} + +.bs-tooltip-top .arrow::before, .bs-tooltip-auto[x-placement^="top"] .arrow::before { + top: 0; + border-width: 0.4rem 0.4rem 0; + border-top-color: #000; +} + +.bs-tooltip-right, .bs-tooltip-auto[x-placement^="right"] { + padding: 0 0.4rem; +} + +.bs-tooltip-right .arrow, .bs-tooltip-auto[x-placement^="right"] .arrow { + left: 0; + width: 0.4rem; + height: 0.8rem; +} + +.bs-tooltip-right .arrow::before, .bs-tooltip-auto[x-placement^="right"] .arrow::before { + right: 0; + border-width: 0.4rem 0.4rem 0.4rem 0; + border-right-color: #000; +} + +.bs-tooltip-bottom, .bs-tooltip-auto[x-placement^="bottom"] { + padding: 0.4rem 0; +} + +.bs-tooltip-bottom .arrow, .bs-tooltip-auto[x-placement^="bottom"] .arrow { + top: 0; +} + +.bs-tooltip-bottom .arrow::before, .bs-tooltip-auto[x-placement^="bottom"] .arrow::before { + bottom: 0; + border-width: 0 0.4rem 0.4rem; + border-bottom-color: #000; +} + +.bs-tooltip-left, .bs-tooltip-auto[x-placement^="left"] { + padding: 0 0.4rem; +} + +.bs-tooltip-left .arrow, .bs-tooltip-auto[x-placement^="left"] .arrow { + right: 0; + width: 0.4rem; + height: 0.8rem; +} + +.bs-tooltip-left .arrow::before, .bs-tooltip-auto[x-placement^="left"] .arrow::before { + left: 0; + border-width: 0.4rem 0 0.4rem 0.4rem; + border-left-color: #000; +} + +.tooltip-inner { + max-width: 200px; + padding: 0.25rem 0.5rem; + color: #fff; + text-align: center; + background-color: #000; + border-radius: 0.25rem; +} + +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: block; + max-width: 276px; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-style: normal; + font-weight: 400; + line-height: 1.5; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + white-space: normal; + line-break: auto; + font-size: 0.875rem; + word-wrap: break-word; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 0.3rem; +} + +.popover .arrow { + position: absolute; + display: block; + width: 1rem; + height: 0.5rem; + margin: 0 0.3rem; +} + +.popover .arrow::before, .popover .arrow::after { + position: absolute; + display: block; + content: ""; + border-color: transparent; + border-style: solid; +} + +.bs-popover-top, .bs-popover-auto[x-placement^="top"] { + margin-bottom: 0.5rem; +} + +.bs-popover-top > .arrow, .bs-popover-auto[x-placement^="top"] > .arrow { + bottom: calc((0.5rem + 1px) * -1); +} + +.bs-popover-top > .arrow::before, .bs-popover-auto[x-placement^="top"] > .arrow::before { + bottom: 0; + border-width: 0.5rem 0.5rem 0; + border-top-color: rgba(0, 0, 0, 0.25); +} + +.bs-popover-top > .arrow::after, .bs-popover-auto[x-placement^="top"] > .arrow::after { + bottom: 1px; + border-width: 0.5rem 0.5rem 0; + border-top-color: #fff; +} + +.bs-popover-right, .bs-popover-auto[x-placement^="right"] { + margin-left: 0.5rem; +} + +.bs-popover-right > .arrow, .bs-popover-auto[x-placement^="right"] > .arrow { + left: calc((0.5rem + 1px) * -1); + width: 0.5rem; + height: 1rem; + margin: 0.3rem 0; +} + +.bs-popover-right > .arrow::before, .bs-popover-auto[x-placement^="right"] > .arrow::before { + left: 0; + border-width: 0.5rem 0.5rem 0.5rem 0; + border-right-color: rgba(0, 0, 0, 0.25); +} + +.bs-popover-right > .arrow::after, .bs-popover-auto[x-placement^="right"] > .arrow::after { + left: 1px; + border-width: 0.5rem 0.5rem 0.5rem 0; + border-right-color: #fff; +} + +.bs-popover-bottom, .bs-popover-auto[x-placement^="bottom"] { + margin-top: 0.5rem; +} + +.bs-popover-bottom > .arrow, .bs-popover-auto[x-placement^="bottom"] > .arrow { + top: calc((0.5rem + 1px) * -1); +} + +.bs-popover-bottom > .arrow::before, .bs-popover-auto[x-placement^="bottom"] > .arrow::before { + top: 0; + border-width: 0 0.5rem 0.5rem 0.5rem; + border-bottom-color: rgba(0, 0, 0, 0.25); +} + +.bs-popover-bottom > .arrow::after, .bs-popover-auto[x-placement^="bottom"] > .arrow::after { + top: 1px; + border-width: 0 0.5rem 0.5rem 0.5rem; + border-bottom-color: #fff; +} + +.bs-popover-bottom .popover-header::before, .bs-popover-auto[x-placement^="bottom"] .popover-header::before { + position: absolute; + top: 0; + left: 50%; + display: block; + width: 1rem; + margin-left: -0.5rem; + content: ""; + border-bottom: 1px solid #f7f7f7; +} + +.bs-popover-left, .bs-popover-auto[x-placement^="left"] { + margin-right: 0.5rem; +} + +.bs-popover-left > .arrow, .bs-popover-auto[x-placement^="left"] > .arrow { + right: calc((0.5rem + 1px) * -1); + width: 0.5rem; + height: 1rem; + margin: 0.3rem 0; +} + +.bs-popover-left > .arrow::before, .bs-popover-auto[x-placement^="left"] > .arrow::before { + right: 0; + border-width: 0.5rem 0 0.5rem 0.5rem; + border-left-color: rgba(0, 0, 0, 0.25); +} + +.bs-popover-left > .arrow::after, .bs-popover-auto[x-placement^="left"] > .arrow::after { + right: 1px; + border-width: 0.5rem 0 0.5rem 0.5rem; + border-left-color: #fff; +} + +.popover-header { + padding: 0.5rem 0.75rem; + margin-bottom: 0; + font-size: 1rem; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-top-left-radius: calc(0.3rem - 1px); + border-top-right-radius: calc(0.3rem - 1px); +} + +.popover-header:empty { + display: none; +} + +.popover-body { + padding: 0.5rem 0.75rem; + color: #212529; +} + +.carousel { + position: relative; +} + +.carousel.pointer-event { + -ms-touch-action: pan-y; + touch-action: pan-y; +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} + +.carousel-inner::after { + display: block; + clear: both; + content: ""; +} + +.carousel-item { + position: relative; + display: none; + float: left; + width: 100%; + margin-right: -100%; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + transition: -webkit-transform 0.6s ease-in-out; + transition: transform 0.6s ease-in-out; + transition: transform 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out; +} + +@media (prefers-reduced-motion: reduce) { + .carousel-item { + transition: none; + } +} + +.carousel-item.active, +.carousel-item-next, +.carousel-item-prev { + display: block; +} + +.carousel-item-next:not(.carousel-item-left), +.active.carousel-item-right { + -webkit-transform: translateX(100%); + transform: translateX(100%); +} + +.carousel-item-prev:not(.carousel-item-right), +.active.carousel-item-left { + -webkit-transform: translateX(-100%); + transform: translateX(-100%); +} + +.carousel-fade .carousel-item { + opacity: 0; + transition-property: opacity; + -webkit-transform: none; + transform: none; +} + +.carousel-fade .carousel-item.active, +.carousel-fade .carousel-item-next.carousel-item-left, +.carousel-fade .carousel-item-prev.carousel-item-right { + z-index: 1; + opacity: 1; +} + +.carousel-fade .active.carousel-item-left, +.carousel-fade .active.carousel-item-right { + z-index: 0; + opacity: 0; + transition: 0s 0.6s opacity; +} + +@media (prefers-reduced-motion: reduce) { + .carousel-fade .active.carousel-item-left, + .carousel-fade .active.carousel-item-right { + transition: none; + } +} + +.carousel-control-prev, +.carousel-control-next { + position: absolute; + top: 0; + bottom: 0; + z-index: 1; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + width: 15%; + color: #fff; + text-align: center; + opacity: 0.5; + transition: opacity 0.15s ease; +} + +@media (prefers-reduced-motion: reduce) { + .carousel-control-prev, + .carousel-control-next { + transition: none; + } +} + +.carousel-control-prev:hover, .carousel-control-prev:focus, +.carousel-control-next:hover, +.carousel-control-next:focus { + color: #fff; + text-decoration: none; + outline: 0; + opacity: 0.9; +} + +.carousel-control-prev { + left: 0; +} + +.carousel-control-next { + right: 0; +} + +.carousel-control-prev-icon, +.carousel-control-next-icon { + display: inline-block; + width: 20px; + height: 20px; + background: no-repeat 50% / 100% 100%; +} + +.carousel-control-prev-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3e%3c/svg%3e"); +} + +.carousel-control-next-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3e%3c/svg%3e"); +} + +.carousel-indicators { + position: absolute; + right: 0; + bottom: 0; + left: 0; + z-index: 15; + display: -ms-flexbox; + display: flex; + -ms-flex-pack: center; + justify-content: center; + padding-left: 0; + margin-right: 15%; + margin-left: 15%; + list-style: none; +} + +.carousel-indicators li { + box-sizing: content-box; + -ms-flex: 0 1 auto; + flex: 0 1 auto; + width: 30px; + height: 3px; + margin-right: 3px; + margin-left: 3px; + text-indent: -999px; + cursor: pointer; + background-color: #fff; + background-clip: padding-box; + border-top: 10px solid transparent; + border-bottom: 10px solid transparent; + opacity: .5; + transition: opacity 0.6s ease; +} + +@media (prefers-reduced-motion: reduce) { + .carousel-indicators li { + transition: none; + } +} + +.carousel-indicators .active { + opacity: 1; +} + +.carousel-caption { + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; +} + +@-webkit-keyframes spinner-border { + to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@keyframes spinner-border { + to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +.spinner-border { + display: inline-block; + width: 2rem; + height: 2rem; + vertical-align: text-bottom; + border: 0.25em solid currentColor; + border-right-color: transparent; + border-radius: 50%; + -webkit-animation: spinner-border .75s linear infinite; + animation: spinner-border .75s linear infinite; +} + +.spinner-border-sm { + width: 1rem; + height: 1rem; + border-width: 0.2em; +} + +@-webkit-keyframes spinner-grow { + 0% { + -webkit-transform: scale(0); + transform: scale(0); + } + 50% { + opacity: 1; + } +} + +@keyframes spinner-grow { + 0% { + -webkit-transform: scale(0); + transform: scale(0); + } + 50% { + opacity: 1; + } +} + +.spinner-grow { + display: inline-block; + width: 2rem; + height: 2rem; + vertical-align: text-bottom; + background-color: currentColor; + border-radius: 50%; + opacity: 0; + -webkit-animation: spinner-grow .75s linear infinite; + animation: spinner-grow .75s linear infinite; +} + +.spinner-grow-sm { + width: 1rem; + height: 1rem; +} + +.align-baseline { + vertical-align: baseline !important; +} + +.align-top { + vertical-align: top !important; +} + +.align-middle { + vertical-align: middle !important; +} + +.align-bottom { + vertical-align: bottom !important; +} + +.align-text-bottom { + vertical-align: text-bottom !important; +} + +.align-text-top { + vertical-align: text-top !important; +} + +.bg-primary { + background-color: #007bff !important; +} + +a.bg-primary:hover, a.bg-primary:focus, +button.bg-primary:hover, +button.bg-primary:focus { + background-color: #0062cc !important; +} + +.bg-secondary { + background-color: #6c757d !important; +} + +a.bg-secondary:hover, a.bg-secondary:focus, +button.bg-secondary:hover, +button.bg-secondary:focus { + background-color: #545b62 !important; +} + +.bg-success { + background-color: #28a745 !important; +} + +a.bg-success:hover, a.bg-success:focus, +button.bg-success:hover, +button.bg-success:focus { + background-color: #1e7e34 !important; +} + +.bg-info { + background-color: #17a2b8 !important; +} + +a.bg-info:hover, a.bg-info:focus, +button.bg-info:hover, +button.bg-info:focus { + background-color: #117a8b !important; +} + +.bg-warning { + background-color: #ffc107 !important; +} + +a.bg-warning:hover, a.bg-warning:focus, +button.bg-warning:hover, +button.bg-warning:focus { + background-color: #d39e00 !important; +} + +.bg-danger { + background-color: #dc3545 !important; +} + +a.bg-danger:hover, a.bg-danger:focus, +button.bg-danger:hover, +button.bg-danger:focus { + background-color: #bd2130 !important; +} + +.bg-light { + background-color: #f8f9fa !important; +} + +a.bg-light:hover, a.bg-light:focus, +button.bg-light:hover, +button.bg-light:focus { + background-color: #dae0e5 !important; +} + +.bg-dark { + background-color: #343a40 !important; +} + +a.bg-dark:hover, a.bg-dark:focus, +button.bg-dark:hover, +button.bg-dark:focus { + background-color: #1d2124 !important; +} + +.bg-white { + background-color: #fff !important; +} + +.bg-transparent { + background-color: transparent !important; +} + +.border { + border: 1px solid #dee2e6 !important; +} + +.border-top { + border-top: 1px solid #dee2e6 !important; +} + +.border-right { + border-right: 1px solid #dee2e6 !important; +} + +.border-bottom { + border-bottom: 1px solid #dee2e6 !important; +} + +.border-left { + border-left: 1px solid #dee2e6 !important; +} + +.border-0 { + border: 0 !important; +} + +.border-top-0 { + border-top: 0 !important; +} + +.border-right-0 { + border-right: 0 !important; +} + +.border-bottom-0 { + border-bottom: 0 !important; +} + +.border-left-0 { + border-left: 0 !important; +} + +.border-primary { + border-color: #007bff !important; +} + +.border-secondary { + border-color: #6c757d !important; +} + +.border-success { + border-color: #28a745 !important; +} + +.border-info { + border-color: #17a2b8 !important; +} + +.border-warning { + border-color: #ffc107 !important; +} + +.border-danger { + border-color: #dc3545 !important; +} + +.border-light { + border-color: #f8f9fa !important; +} + +.border-dark { + border-color: #343a40 !important; +} + +.border-white { + border-color: #fff !important; +} + +.rounded-sm { + border-radius: 0.2rem !important; +} + +.rounded { + border-radius: 0.25rem !important; +} + +.rounded-top { + border-top-left-radius: 0.25rem !important; + border-top-right-radius: 0.25rem !important; +} + +.rounded-right { + border-top-right-radius: 0.25rem !important; + border-bottom-right-radius: 0.25rem !important; +} + +.rounded-bottom { + border-bottom-right-radius: 0.25rem !important; + border-bottom-left-radius: 0.25rem !important; +} + +.rounded-left { + border-top-left-radius: 0.25rem !important; + border-bottom-left-radius: 0.25rem !important; +} + +.rounded-lg { + border-radius: 0.3rem !important; +} + +.rounded-circle { + border-radius: 50% !important; +} + +.rounded-pill { + border-radius: 50rem !important; +} + +.rounded-0 { + border-radius: 0 !important; +} + +.clearfix::after { + display: block; + clear: both; + content: ""; +} + +.d-none { + display: none !important; +} + +.d-inline { + display: inline !important; +} + +.d-inline-block { + display: inline-block !important; +} + +.d-block { + display: block !important; +} + +.d-table { + display: table !important; +} + +.d-table-row { + display: table-row !important; +} + +.d-table-cell { + display: table-cell !important; +} + +.d-flex { + display: -ms-flexbox !important; + display: flex !important; +} + +.d-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; +} + +@media (min-width: 576px) { + .d-sm-none { + display: none !important; + } + .d-sm-inline { + display: inline !important; + } + .d-sm-inline-block { + display: inline-block !important; + } + .d-sm-block { + display: block !important; + } + .d-sm-table { + display: table !important; + } + .d-sm-table-row { + display: table-row !important; + } + .d-sm-table-cell { + display: table-cell !important; + } + .d-sm-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-sm-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media (min-width: 768px) { + .d-md-none { + display: none !important; + } + .d-md-inline { + display: inline !important; + } + .d-md-inline-block { + display: inline-block !important; + } + .d-md-block { + display: block !important; + } + .d-md-table { + display: table !important; + } + .d-md-table-row { + display: table-row !important; + } + .d-md-table-cell { + display: table-cell !important; + } + .d-md-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-md-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media (min-width: 992px) { + .d-lg-none { + display: none !important; + } + .d-lg-inline { + display: inline !important; + } + .d-lg-inline-block { + display: inline-block !important; + } + .d-lg-block { + display: block !important; + } + .d-lg-table { + display: table !important; + } + .d-lg-table-row { + display: table-row !important; + } + .d-lg-table-cell { + display: table-cell !important; + } + .d-lg-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-lg-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media (min-width: 1200px) { + .d-xl-none { + display: none !important; + } + .d-xl-inline { + display: inline !important; + } + .d-xl-inline-block { + display: inline-block !important; + } + .d-xl-block { + display: block !important; + } + .d-xl-table { + display: table !important; + } + .d-xl-table-row { + display: table-row !important; + } + .d-xl-table-cell { + display: table-cell !important; + } + .d-xl-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-xl-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media print { + .d-print-none { + display: none !important; + } + .d-print-inline { + display: inline !important; + } + .d-print-inline-block { + display: inline-block !important; + } + .d-print-block { + display: block !important; + } + .d-print-table { + display: table !important; + } + .d-print-table-row { + display: table-row !important; + } + .d-print-table-cell { + display: table-cell !important; + } + .d-print-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-print-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +.embed-responsive { + position: relative; + display: block; + width: 100%; + padding: 0; + overflow: hidden; +} + +.embed-responsive::before { + display: block; + content: ""; +} + +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object, +.embed-responsive video { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + border: 0; +} + +.embed-responsive-21by9::before { + padding-top: 42.857143%; +} + +.embed-responsive-16by9::before { + padding-top: 56.25%; +} + +.embed-responsive-4by3::before { + padding-top: 75%; +} + +.embed-responsive-1by1::before { + padding-top: 100%; +} + +.flex-row { + -ms-flex-direction: row !important; + flex-direction: row !important; +} + +.flex-column { + -ms-flex-direction: column !important; + flex-direction: column !important; +} + +.flex-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; +} + +.flex-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; +} + +.flex-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; +} + +.flex-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; +} + +.flex-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; +} + +.flex-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; +} + +.flex-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; +} + +.flex-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; +} + +.flex-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; +} + +.flex-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; +} + +.justify-content-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; +} + +.justify-content-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; +} + +.justify-content-center { + -ms-flex-pack: center !important; + justify-content: center !important; +} + +.justify-content-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; +} + +.justify-content-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; +} + +.align-items-start { + -ms-flex-align: start !important; + align-items: flex-start !important; +} + +.align-items-end { + -ms-flex-align: end !important; + align-items: flex-end !important; +} + +.align-items-center { + -ms-flex-align: center !important; + align-items: center !important; +} + +.align-items-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; +} + +.align-items-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; +} + +.align-content-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; +} + +.align-content-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; +} + +.align-content-center { + -ms-flex-line-pack: center !important; + align-content: center !important; +} + +.align-content-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; +} + +.align-content-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; +} + +.align-content-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; +} + +.align-self-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; +} + +.align-self-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; +} + +.align-self-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; +} + +.align-self-center { + -ms-flex-item-align: center !important; + align-self: center !important; +} + +.align-self-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; +} + +.align-self-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; +} + +@media (min-width: 576px) { + .flex-sm-row { + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-sm-column { + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-sm-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-sm-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-sm-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-sm-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-sm-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-sm-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-sm-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-sm-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; + } + .flex-sm-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; + } + .flex-sm-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; + } + .justify-content-sm-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-sm-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-sm-center { + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-sm-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-sm-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-sm-start { + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-sm-end { + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-sm-center { + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-sm-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-sm-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-sm-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-sm-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-sm-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-sm-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-sm-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-sm-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-sm-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-sm-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-sm-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-sm-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-sm-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-sm-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} + +@media (min-width: 768px) { + .flex-md-row { + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-md-column { + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-md-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-md-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-md-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-md-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-md-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-md-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-md-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-md-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; + } + .flex-md-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; + } + .flex-md-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; + } + .justify-content-md-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-md-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-md-center { + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-md-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-md-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-md-start { + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-md-end { + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-md-center { + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-md-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-md-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-md-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-md-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-md-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-md-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-md-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-md-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-md-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-md-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-md-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-md-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-md-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-md-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} + +@media (min-width: 992px) { + .flex-lg-row { + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-lg-column { + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-lg-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-lg-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-lg-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-lg-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-lg-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-lg-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-lg-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-lg-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; + } + .flex-lg-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; + } + .flex-lg-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; + } + .justify-content-lg-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-lg-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-lg-center { + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-lg-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-lg-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-lg-start { + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-lg-end { + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-lg-center { + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-lg-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-lg-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-lg-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-lg-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-lg-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-lg-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-lg-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-lg-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-lg-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-lg-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-lg-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-lg-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-lg-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-lg-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} + +@media (min-width: 1200px) { + .flex-xl-row { + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-xl-column { + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-xl-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-xl-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-xl-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-xl-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-xl-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-xl-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-xl-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-xl-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; + } + .flex-xl-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; + } + .flex-xl-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; + } + .justify-content-xl-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-xl-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-xl-center { + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-xl-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-xl-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-xl-start { + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-xl-end { + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-xl-center { + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-xl-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-xl-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-xl-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-xl-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-xl-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-xl-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-xl-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-xl-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-xl-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-xl-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-xl-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-xl-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-xl-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-xl-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} + +.float-left { + float: left !important; +} + +.float-right { + float: right !important; +} + +.float-none { + float: none !important; +} + +@media (min-width: 576px) { + .float-sm-left { + float: left !important; + } + .float-sm-right { + float: right !important; + } + .float-sm-none { + float: none !important; + } +} + +@media (min-width: 768px) { + .float-md-left { + float: left !important; + } + .float-md-right { + float: right !important; + } + .float-md-none { + float: none !important; + } +} + +@media (min-width: 992px) { + .float-lg-left { + float: left !important; + } + .float-lg-right { + float: right !important; + } + .float-lg-none { + float: none !important; + } +} + +@media (min-width: 1200px) { + .float-xl-left { + float: left !important; + } + .float-xl-right { + float: right !important; + } + .float-xl-none { + float: none !important; + } +} + +.overflow-auto { + overflow: auto !important; +} + +.overflow-hidden { + overflow: hidden !important; +} + +.position-static { + position: static !important; +} + +.position-relative { + position: relative !important; +} + +.position-absolute { + position: absolute !important; +} + +.position-fixed { + position: fixed !important; +} + +.position-sticky { + position: -webkit-sticky !important; + position: sticky !important; +} + +.fixed-top { + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 1030; +} + +.fixed-bottom { + position: fixed; + right: 0; + bottom: 0; + left: 0; + z-index: 1030; +} + +@supports ((position: -webkit-sticky) or (position: sticky)) { + .sticky-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +.sr-only-focusable:active, .sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + overflow: visible; + clip: auto; + white-space: normal; +} + +.shadow-sm { + box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; +} + +.shadow { + box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; +} + +.shadow-lg { + box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important; +} + +.shadow-none { + box-shadow: none !important; +} + +.w-25 { + width: 25% !important; +} + +.w-50 { + width: 50% !important; +} + +.w-75 { + width: 75% !important; +} + +.w-100 { + width: 100% !important; +} + +.w-auto { + width: auto !important; +} + +.h-25 { + height: 25% !important; +} + +.h-50 { + height: 50% !important; +} + +.h-75 { + height: 75% !important; +} + +.h-100 { + height: 100% !important; +} + +.h-auto { + height: auto !important; +} + +.mw-100 { + max-width: 100% !important; +} + +.mh-100 { + max-height: 100% !important; +} + +.min-vw-100 { + min-width: 100vw !important; +} + +.min-vh-100 { + min-height: 100vh !important; +} + +.vw-100 { + width: 100vw !important; +} + +.vh-100 { + height: 100vh !important; +} + +.stretched-link::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1; + pointer-events: auto; + content: ""; + background-color: rgba(0, 0, 0, 0); +} + +.m-0 { + margin: 0 !important; +} + +.mt-0, +.my-0 { + margin-top: 0 !important; +} + +.mr-0, +.mx-0 { + margin-right: 0 !important; +} + +.mb-0, +.my-0 { + margin-bottom: 0 !important; +} + +.ml-0, +.mx-0 { + margin-left: 0 !important; +} + +.m-1 { + margin: 0.25rem !important; +} + +.mt-1, +.my-1 { + margin-top: 0.25rem !important; +} + +.mr-1, +.mx-1 { + margin-right: 0.25rem !important; +} + +.mb-1, +.my-1 { + margin-bottom: 0.25rem !important; +} + +.ml-1, +.mx-1 { + margin-left: 0.25rem !important; +} + +.m-2 { + margin: 0.5rem !important; +} + +.mt-2, +.my-2 { + margin-top: 0.5rem !important; +} + +.mr-2, +.mx-2 { + margin-right: 0.5rem !important; +} + +.mb-2, +.my-2 { + margin-bottom: 0.5rem !important; +} + +.ml-2, +.mx-2 { + margin-left: 0.5rem !important; +} + +.m-3 { + margin: 1rem !important; +} + +.mt-3, +.my-3 { + margin-top: 1rem !important; +} + +.mr-3, +.mx-3 { + margin-right: 1rem !important; +} + +.mb-3, +.my-3 { + margin-bottom: 1rem !important; +} + +.ml-3, +.mx-3 { + margin-left: 1rem !important; +} + +.m-4 { + margin: 1.5rem !important; +} + +.mt-4, +.my-4 { + margin-top: 1.5rem !important; +} + +.mr-4, +.mx-4 { + margin-right: 1.5rem !important; +} + +.mb-4, +.my-4 { + margin-bottom: 1.5rem !important; +} + +.ml-4, +.mx-4 { + margin-left: 1.5rem !important; +} + +.m-5 { + margin: 3rem !important; +} + +.mt-5, +.my-5 { + margin-top: 3rem !important; +} + +.mr-5, +.mx-5 { + margin-right: 3rem !important; +} + +.mb-5, +.my-5 { + margin-bottom: 3rem !important; +} + +.ml-5, +.mx-5 { + margin-left: 3rem !important; +} + +.p-0 { + padding: 0 !important; +} + +.pt-0, +.py-0 { + padding-top: 0 !important; +} + +.pr-0, +.px-0 { + padding-right: 0 !important; +} + +.pb-0, +.py-0 { + padding-bottom: 0 !important; +} + +.pl-0, +.px-0 { + padding-left: 0 !important; +} + +.p-1 { + padding: 0.25rem !important; +} + +.pt-1, +.py-1 { + padding-top: 0.25rem !important; +} + +.pr-1, +.px-1 { + padding-right: 0.25rem !important; +} + +.pb-1, +.py-1 { + padding-bottom: 0.25rem !important; +} + +.pl-1, +.px-1 { + padding-left: 0.25rem !important; +} + +.p-2 { + padding: 0.5rem !important; +} + +.pt-2, +.py-2 { + padding-top: 0.5rem !important; +} + +.pr-2, +.px-2 { + padding-right: 0.5rem !important; +} + +.pb-2, +.py-2 { + padding-bottom: 0.5rem !important; +} + +.pl-2, +.px-2 { + padding-left: 0.5rem !important; +} + +.p-3 { + padding: 1rem !important; +} + +.pt-3, +.py-3 { + padding-top: 1rem !important; +} + +.pr-3, +.px-3 { + padding-right: 1rem !important; +} + +.pb-3, +.py-3 { + padding-bottom: 1rem !important; +} + +.pl-3, +.px-3 { + padding-left: 1rem !important; +} + +.p-4 { + padding: 1.5rem !important; +} + +.pt-4, +.py-4 { + padding-top: 1.5rem !important; +} + +.pr-4, +.px-4 { + padding-right: 1.5rem !important; +} + +.pb-4, +.py-4 { + padding-bottom: 1.5rem !important; +} + +.pl-4, +.px-4 { + padding-left: 1.5rem !important; +} + +.p-5 { + padding: 3rem !important; +} + +.pt-5, +.py-5 { + padding-top: 3rem !important; +} + +.pr-5, +.px-5 { + padding-right: 3rem !important; +} + +.pb-5, +.py-5 { + padding-bottom: 3rem !important; +} + +.pl-5, +.px-5 { + padding-left: 3rem !important; +} + +.m-n1 { + margin: -0.25rem !important; +} + +.mt-n1, +.my-n1 { + margin-top: -0.25rem !important; +} + +.mr-n1, +.mx-n1 { + margin-right: -0.25rem !important; +} + +.mb-n1, +.my-n1 { + margin-bottom: -0.25rem !important; +} + +.ml-n1, +.mx-n1 { + margin-left: -0.25rem !important; +} + +.m-n2 { + margin: -0.5rem !important; +} + +.mt-n2, +.my-n2 { + margin-top: -0.5rem !important; +} + +.mr-n2, +.mx-n2 { + margin-right: -0.5rem !important; +} + +.mb-n2, +.my-n2 { + margin-bottom: -0.5rem !important; +} + +.ml-n2, +.mx-n2 { + margin-left: -0.5rem !important; +} + +.m-n3 { + margin: -1rem !important; +} + +.mt-n3, +.my-n3 { + margin-top: -1rem !important; +} + +.mr-n3, +.mx-n3 { + margin-right: -1rem !important; +} + +.mb-n3, +.my-n3 { + margin-bottom: -1rem !important; +} + +.ml-n3, +.mx-n3 { + margin-left: -1rem !important; +} + +.m-n4 { + margin: -1.5rem !important; +} + +.mt-n4, +.my-n4 { + margin-top: -1.5rem !important; +} + +.mr-n4, +.mx-n4 { + margin-right: -1.5rem !important; +} + +.mb-n4, +.my-n4 { + margin-bottom: -1.5rem !important; +} + +.ml-n4, +.mx-n4 { + margin-left: -1.5rem !important; +} + +.m-n5 { + margin: -3rem !important; +} + +.mt-n5, +.my-n5 { + margin-top: -3rem !important; +} + +.mr-n5, +.mx-n5 { + margin-right: -3rem !important; +} + +.mb-n5, +.my-n5 { + margin-bottom: -3rem !important; +} + +.ml-n5, +.mx-n5 { + margin-left: -3rem !important; +} + +.m-auto { + margin: auto !important; +} + +.mt-auto, +.my-auto { + margin-top: auto !important; +} + +.mr-auto, +.mx-auto { + margin-right: auto !important; +} + +.mb-auto, +.my-auto { + margin-bottom: auto !important; +} + +.ml-auto, +.mx-auto { + margin-left: auto !important; +} + +@media (min-width: 576px) { + .m-sm-0 { + margin: 0 !important; + } + .mt-sm-0, + .my-sm-0 { + margin-top: 0 !important; + } + .mr-sm-0, + .mx-sm-0 { + margin-right: 0 !important; + } + .mb-sm-0, + .my-sm-0 { + margin-bottom: 0 !important; + } + .ml-sm-0, + .mx-sm-0 { + margin-left: 0 !important; + } + .m-sm-1 { + margin: 0.25rem !important; + } + .mt-sm-1, + .my-sm-1 { + margin-top: 0.25rem !important; + } + .mr-sm-1, + .mx-sm-1 { + margin-right: 0.25rem !important; + } + .mb-sm-1, + .my-sm-1 { + margin-bottom: 0.25rem !important; + } + .ml-sm-1, + .mx-sm-1 { + margin-left: 0.25rem !important; + } + .m-sm-2 { + margin: 0.5rem !important; + } + .mt-sm-2, + .my-sm-2 { + margin-top: 0.5rem !important; + } + .mr-sm-2, + .mx-sm-2 { + margin-right: 0.5rem !important; + } + .mb-sm-2, + .my-sm-2 { + margin-bottom: 0.5rem !important; + } + .ml-sm-2, + .mx-sm-2 { + margin-left: 0.5rem !important; + } + .m-sm-3 { + margin: 1rem !important; + } + .mt-sm-3, + .my-sm-3 { + margin-top: 1rem !important; + } + .mr-sm-3, + .mx-sm-3 { + margin-right: 1rem !important; + } + .mb-sm-3, + .my-sm-3 { + margin-bottom: 1rem !important; + } + .ml-sm-3, + .mx-sm-3 { + margin-left: 1rem !important; + } + .m-sm-4 { + margin: 1.5rem !important; + } + .mt-sm-4, + .my-sm-4 { + margin-top: 1.5rem !important; + } + .mr-sm-4, + .mx-sm-4 { + margin-right: 1.5rem !important; + } + .mb-sm-4, + .my-sm-4 { + margin-bottom: 1.5rem !important; + } + .ml-sm-4, + .mx-sm-4 { + margin-left: 1.5rem !important; + } + .m-sm-5 { + margin: 3rem !important; + } + .mt-sm-5, + .my-sm-5 { + margin-top: 3rem !important; + } + .mr-sm-5, + .mx-sm-5 { + margin-right: 3rem !important; + } + .mb-sm-5, + .my-sm-5 { + margin-bottom: 3rem !important; + } + .ml-sm-5, + .mx-sm-5 { + margin-left: 3rem !important; + } + .p-sm-0 { + padding: 0 !important; + } + .pt-sm-0, + .py-sm-0 { + padding-top: 0 !important; + } + .pr-sm-0, + .px-sm-0 { + padding-right: 0 !important; + } + .pb-sm-0, + .py-sm-0 { + padding-bottom: 0 !important; + } + .pl-sm-0, + .px-sm-0 { + padding-left: 0 !important; + } + .p-sm-1 { + padding: 0.25rem !important; + } + .pt-sm-1, + .py-sm-1 { + padding-top: 0.25rem !important; + } + .pr-sm-1, + .px-sm-1 { + padding-right: 0.25rem !important; + } + .pb-sm-1, + .py-sm-1 { + padding-bottom: 0.25rem !important; + } + .pl-sm-1, + .px-sm-1 { + padding-left: 0.25rem !important; + } + .p-sm-2 { + padding: 0.5rem !important; + } + .pt-sm-2, + .py-sm-2 { + padding-top: 0.5rem !important; + } + .pr-sm-2, + .px-sm-2 { + padding-right: 0.5rem !important; + } + .pb-sm-2, + .py-sm-2 { + padding-bottom: 0.5rem !important; + } + .pl-sm-2, + .px-sm-2 { + padding-left: 0.5rem !important; + } + .p-sm-3 { + padding: 1rem !important; + } + .pt-sm-3, + .py-sm-3 { + padding-top: 1rem !important; + } + .pr-sm-3, + .px-sm-3 { + padding-right: 1rem !important; + } + .pb-sm-3, + .py-sm-3 { + padding-bottom: 1rem !important; + } + .pl-sm-3, + .px-sm-3 { + padding-left: 1rem !important; + } + .p-sm-4 { + padding: 1.5rem !important; + } + .pt-sm-4, + .py-sm-4 { + padding-top: 1.5rem !important; + } + .pr-sm-4, + .px-sm-4 { + padding-right: 1.5rem !important; + } + .pb-sm-4, + .py-sm-4 { + padding-bottom: 1.5rem !important; + } + .pl-sm-4, + .px-sm-4 { + padding-left: 1.5rem !important; + } + .p-sm-5 { + padding: 3rem !important; + } + .pt-sm-5, + .py-sm-5 { + padding-top: 3rem !important; + } + .pr-sm-5, + .px-sm-5 { + padding-right: 3rem !important; + } + .pb-sm-5, + .py-sm-5 { + padding-bottom: 3rem !important; + } + .pl-sm-5, + .px-sm-5 { + padding-left: 3rem !important; + } + .m-sm-n1 { + margin: -0.25rem !important; + } + .mt-sm-n1, + .my-sm-n1 { + margin-top: -0.25rem !important; + } + .mr-sm-n1, + .mx-sm-n1 { + margin-right: -0.25rem !important; + } + .mb-sm-n1, + .my-sm-n1 { + margin-bottom: -0.25rem !important; + } + .ml-sm-n1, + .mx-sm-n1 { + margin-left: -0.25rem !important; + } + .m-sm-n2 { + margin: -0.5rem !important; + } + .mt-sm-n2, + .my-sm-n2 { + margin-top: -0.5rem !important; + } + .mr-sm-n2, + .mx-sm-n2 { + margin-right: -0.5rem !important; + } + .mb-sm-n2, + .my-sm-n2 { + margin-bottom: -0.5rem !important; + } + .ml-sm-n2, + .mx-sm-n2 { + margin-left: -0.5rem !important; + } + .m-sm-n3 { + margin: -1rem !important; + } + .mt-sm-n3, + .my-sm-n3 { + margin-top: -1rem !important; + } + .mr-sm-n3, + .mx-sm-n3 { + margin-right: -1rem !important; + } + .mb-sm-n3, + .my-sm-n3 { + margin-bottom: -1rem !important; + } + .ml-sm-n3, + .mx-sm-n3 { + margin-left: -1rem !important; + } + .m-sm-n4 { + margin: -1.5rem !important; + } + .mt-sm-n4, + .my-sm-n4 { + margin-top: -1.5rem !important; + } + .mr-sm-n4, + .mx-sm-n4 { + margin-right: -1.5rem !important; + } + .mb-sm-n4, + .my-sm-n4 { + margin-bottom: -1.5rem !important; + } + .ml-sm-n4, + .mx-sm-n4 { + margin-left: -1.5rem !important; + } + .m-sm-n5 { + margin: -3rem !important; + } + .mt-sm-n5, + .my-sm-n5 { + margin-top: -3rem !important; + } + .mr-sm-n5, + .mx-sm-n5 { + margin-right: -3rem !important; + } + .mb-sm-n5, + .my-sm-n5 { + margin-bottom: -3rem !important; + } + .ml-sm-n5, + .mx-sm-n5 { + margin-left: -3rem !important; + } + .m-sm-auto { + margin: auto !important; + } + .mt-sm-auto, + .my-sm-auto { + margin-top: auto !important; + } + .mr-sm-auto, + .mx-sm-auto { + margin-right: auto !important; + } + .mb-sm-auto, + .my-sm-auto { + margin-bottom: auto !important; + } + .ml-sm-auto, + .mx-sm-auto { + margin-left: auto !important; + } +} + +@media (min-width: 768px) { + .m-md-0 { + margin: 0 !important; + } + .mt-md-0, + .my-md-0 { + margin-top: 0 !important; + } + .mr-md-0, + .mx-md-0 { + margin-right: 0 !important; + } + .mb-md-0, + .my-md-0 { + margin-bottom: 0 !important; + } + .ml-md-0, + .mx-md-0 { + margin-left: 0 !important; + } + .m-md-1 { + margin: 0.25rem !important; + } + .mt-md-1, + .my-md-1 { + margin-top: 0.25rem !important; + } + .mr-md-1, + .mx-md-1 { + margin-right: 0.25rem !important; + } + .mb-md-1, + .my-md-1 { + margin-bottom: 0.25rem !important; + } + .ml-md-1, + .mx-md-1 { + margin-left: 0.25rem !important; + } + .m-md-2 { + margin: 0.5rem !important; + } + .mt-md-2, + .my-md-2 { + margin-top: 0.5rem !important; + } + .mr-md-2, + .mx-md-2 { + margin-right: 0.5rem !important; + } + .mb-md-2, + .my-md-2 { + margin-bottom: 0.5rem !important; + } + .ml-md-2, + .mx-md-2 { + margin-left: 0.5rem !important; + } + .m-md-3 { + margin: 1rem !important; + } + .mt-md-3, + .my-md-3 { + margin-top: 1rem !important; + } + .mr-md-3, + .mx-md-3 { + margin-right: 1rem !important; + } + .mb-md-3, + .my-md-3 { + margin-bottom: 1rem !important; + } + .ml-md-3, + .mx-md-3 { + margin-left: 1rem !important; + } + .m-md-4 { + margin: 1.5rem !important; + } + .mt-md-4, + .my-md-4 { + margin-top: 1.5rem !important; + } + .mr-md-4, + .mx-md-4 { + margin-right: 1.5rem !important; + } + .mb-md-4, + .my-md-4 { + margin-bottom: 1.5rem !important; + } + .ml-md-4, + .mx-md-4 { + margin-left: 1.5rem !important; + } + .m-md-5 { + margin: 3rem !important; + } + .mt-md-5, + .my-md-5 { + margin-top: 3rem !important; + } + .mr-md-5, + .mx-md-5 { + margin-right: 3rem !important; + } + .mb-md-5, + .my-md-5 { + margin-bottom: 3rem !important; + } + .ml-md-5, + .mx-md-5 { + margin-left: 3rem !important; + } + .p-md-0 { + padding: 0 !important; + } + .pt-md-0, + .py-md-0 { + padding-top: 0 !important; + } + .pr-md-0, + .px-md-0 { + padding-right: 0 !important; + } + .pb-md-0, + .py-md-0 { + padding-bottom: 0 !important; + } + .pl-md-0, + .px-md-0 { + padding-left: 0 !important; + } + .p-md-1 { + padding: 0.25rem !important; + } + .pt-md-1, + .py-md-1 { + padding-top: 0.25rem !important; + } + .pr-md-1, + .px-md-1 { + padding-right: 0.25rem !important; + } + .pb-md-1, + .py-md-1 { + padding-bottom: 0.25rem !important; + } + .pl-md-1, + .px-md-1 { + padding-left: 0.25rem !important; + } + .p-md-2 { + padding: 0.5rem !important; + } + .pt-md-2, + .py-md-2 { + padding-top: 0.5rem !important; + } + .pr-md-2, + .px-md-2 { + padding-right: 0.5rem !important; + } + .pb-md-2, + .py-md-2 { + padding-bottom: 0.5rem !important; + } + .pl-md-2, + .px-md-2 { + padding-left: 0.5rem !important; + } + .p-md-3 { + padding: 1rem !important; + } + .pt-md-3, + .py-md-3 { + padding-top: 1rem !important; + } + .pr-md-3, + .px-md-3 { + padding-right: 1rem !important; + } + .pb-md-3, + .py-md-3 { + padding-bottom: 1rem !important; + } + .pl-md-3, + .px-md-3 { + padding-left: 1rem !important; + } + .p-md-4 { + padding: 1.5rem !important; + } + .pt-md-4, + .py-md-4 { + padding-top: 1.5rem !important; + } + .pr-md-4, + .px-md-4 { + padding-right: 1.5rem !important; + } + .pb-md-4, + .py-md-4 { + padding-bottom: 1.5rem !important; + } + .pl-md-4, + .px-md-4 { + padding-left: 1.5rem !important; + } + .p-md-5 { + padding: 3rem !important; + } + .pt-md-5, + .py-md-5 { + padding-top: 3rem !important; + } + .pr-md-5, + .px-md-5 { + padding-right: 3rem !important; + } + .pb-md-5, + .py-md-5 { + padding-bottom: 3rem !important; + } + .pl-md-5, + .px-md-5 { + padding-left: 3rem !important; + } + .m-md-n1 { + margin: -0.25rem !important; + } + .mt-md-n1, + .my-md-n1 { + margin-top: -0.25rem !important; + } + .mr-md-n1, + .mx-md-n1 { + margin-right: -0.25rem !important; + } + .mb-md-n1, + .my-md-n1 { + margin-bottom: -0.25rem !important; + } + .ml-md-n1, + .mx-md-n1 { + margin-left: -0.25rem !important; + } + .m-md-n2 { + margin: -0.5rem !important; + } + .mt-md-n2, + .my-md-n2 { + margin-top: -0.5rem !important; + } + .mr-md-n2, + .mx-md-n2 { + margin-right: -0.5rem !important; + } + .mb-md-n2, + .my-md-n2 { + margin-bottom: -0.5rem !important; + } + .ml-md-n2, + .mx-md-n2 { + margin-left: -0.5rem !important; + } + .m-md-n3 { + margin: -1rem !important; + } + .mt-md-n3, + .my-md-n3 { + margin-top: -1rem !important; + } + .mr-md-n3, + .mx-md-n3 { + margin-right: -1rem !important; + } + .mb-md-n3, + .my-md-n3 { + margin-bottom: -1rem !important; + } + .ml-md-n3, + .mx-md-n3 { + margin-left: -1rem !important; + } + .m-md-n4 { + margin: -1.5rem !important; + } + .mt-md-n4, + .my-md-n4 { + margin-top: -1.5rem !important; + } + .mr-md-n4, + .mx-md-n4 { + margin-right: -1.5rem !important; + } + .mb-md-n4, + .my-md-n4 { + margin-bottom: -1.5rem !important; + } + .ml-md-n4, + .mx-md-n4 { + margin-left: -1.5rem !important; + } + .m-md-n5 { + margin: -3rem !important; + } + .mt-md-n5, + .my-md-n5 { + margin-top: -3rem !important; + } + .mr-md-n5, + .mx-md-n5 { + margin-right: -3rem !important; + } + .mb-md-n5, + .my-md-n5 { + margin-bottom: -3rem !important; + } + .ml-md-n5, + .mx-md-n5 { + margin-left: -3rem !important; + } + .m-md-auto { + margin: auto !important; + } + .mt-md-auto, + .my-md-auto { + margin-top: auto !important; + } + .mr-md-auto, + .mx-md-auto { + margin-right: auto !important; + } + .mb-md-auto, + .my-md-auto { + margin-bottom: auto !important; + } + .ml-md-auto, + .mx-md-auto { + margin-left: auto !important; + } +} + +@media (min-width: 992px) { + .m-lg-0 { + margin: 0 !important; + } + .mt-lg-0, + .my-lg-0 { + margin-top: 0 !important; + } + .mr-lg-0, + .mx-lg-0 { + margin-right: 0 !important; + } + .mb-lg-0, + .my-lg-0 { + margin-bottom: 0 !important; + } + .ml-lg-0, + .mx-lg-0 { + margin-left: 0 !important; + } + .m-lg-1 { + margin: 0.25rem !important; + } + .mt-lg-1, + .my-lg-1 { + margin-top: 0.25rem !important; + } + .mr-lg-1, + .mx-lg-1 { + margin-right: 0.25rem !important; + } + .mb-lg-1, + .my-lg-1 { + margin-bottom: 0.25rem !important; + } + .ml-lg-1, + .mx-lg-1 { + margin-left: 0.25rem !important; + } + .m-lg-2 { + margin: 0.5rem !important; + } + .mt-lg-2, + .my-lg-2 { + margin-top: 0.5rem !important; + } + .mr-lg-2, + .mx-lg-2 { + margin-right: 0.5rem !important; + } + .mb-lg-2, + .my-lg-2 { + margin-bottom: 0.5rem !important; + } + .ml-lg-2, + .mx-lg-2 { + margin-left: 0.5rem !important; + } + .m-lg-3 { + margin: 1rem !important; + } + .mt-lg-3, + .my-lg-3 { + margin-top: 1rem !important; + } + .mr-lg-3, + .mx-lg-3 { + margin-right: 1rem !important; + } + .mb-lg-3, + .my-lg-3 { + margin-bottom: 1rem !important; + } + .ml-lg-3, + .mx-lg-3 { + margin-left: 1rem !important; + } + .m-lg-4 { + margin: 1.5rem !important; + } + .mt-lg-4, + .my-lg-4 { + margin-top: 1.5rem !important; + } + .mr-lg-4, + .mx-lg-4 { + margin-right: 1.5rem !important; + } + .mb-lg-4, + .my-lg-4 { + margin-bottom: 1.5rem !important; + } + .ml-lg-4, + .mx-lg-4 { + margin-left: 1.5rem !important; + } + .m-lg-5 { + margin: 3rem !important; + } + .mt-lg-5, + .my-lg-5 { + margin-top: 3rem !important; + } + .mr-lg-5, + .mx-lg-5 { + margin-right: 3rem !important; + } + .mb-lg-5, + .my-lg-5 { + margin-bottom: 3rem !important; + } + .ml-lg-5, + .mx-lg-5 { + margin-left: 3rem !important; + } + .p-lg-0 { + padding: 0 !important; + } + .pt-lg-0, + .py-lg-0 { + padding-top: 0 !important; + } + .pr-lg-0, + .px-lg-0 { + padding-right: 0 !important; + } + .pb-lg-0, + .py-lg-0 { + padding-bottom: 0 !important; + } + .pl-lg-0, + .px-lg-0 { + padding-left: 0 !important; + } + .p-lg-1 { + padding: 0.25rem !important; + } + .pt-lg-1, + .py-lg-1 { + padding-top: 0.25rem !important; + } + .pr-lg-1, + .px-lg-1 { + padding-right: 0.25rem !important; + } + .pb-lg-1, + .py-lg-1 { + padding-bottom: 0.25rem !important; + } + .pl-lg-1, + .px-lg-1 { + padding-left: 0.25rem !important; + } + .p-lg-2 { + padding: 0.5rem !important; + } + .pt-lg-2, + .py-lg-2 { + padding-top: 0.5rem !important; + } + .pr-lg-2, + .px-lg-2 { + padding-right: 0.5rem !important; + } + .pb-lg-2, + .py-lg-2 { + padding-bottom: 0.5rem !important; + } + .pl-lg-2, + .px-lg-2 { + padding-left: 0.5rem !important; + } + .p-lg-3 { + padding: 1rem !important; + } + .pt-lg-3, + .py-lg-3 { + padding-top: 1rem !important; + } + .pr-lg-3, + .px-lg-3 { + padding-right: 1rem !important; + } + .pb-lg-3, + .py-lg-3 { + padding-bottom: 1rem !important; + } + .pl-lg-3, + .px-lg-3 { + padding-left: 1rem !important; + } + .p-lg-4 { + padding: 1.5rem !important; + } + .pt-lg-4, + .py-lg-4 { + padding-top: 1.5rem !important; + } + .pr-lg-4, + .px-lg-4 { + padding-right: 1.5rem !important; + } + .pb-lg-4, + .py-lg-4 { + padding-bottom: 1.5rem !important; + } + .pl-lg-4, + .px-lg-4 { + padding-left: 1.5rem !important; + } + .p-lg-5 { + padding: 3rem !important; + } + .pt-lg-5, + .py-lg-5 { + padding-top: 3rem !important; + } + .pr-lg-5, + .px-lg-5 { + padding-right: 3rem !important; + } + .pb-lg-5, + .py-lg-5 { + padding-bottom: 3rem !important; + } + .pl-lg-5, + .px-lg-5 { + padding-left: 3rem !important; + } + .m-lg-n1 { + margin: -0.25rem !important; + } + .mt-lg-n1, + .my-lg-n1 { + margin-top: -0.25rem !important; + } + .mr-lg-n1, + .mx-lg-n1 { + margin-right: -0.25rem !important; + } + .mb-lg-n1, + .my-lg-n1 { + margin-bottom: -0.25rem !important; + } + .ml-lg-n1, + .mx-lg-n1 { + margin-left: -0.25rem !important; + } + .m-lg-n2 { + margin: -0.5rem !important; + } + .mt-lg-n2, + .my-lg-n2 { + margin-top: -0.5rem !important; + } + .mr-lg-n2, + .mx-lg-n2 { + margin-right: -0.5rem !important; + } + .mb-lg-n2, + .my-lg-n2 { + margin-bottom: -0.5rem !important; + } + .ml-lg-n2, + .mx-lg-n2 { + margin-left: -0.5rem !important; + } + .m-lg-n3 { + margin: -1rem !important; + } + .mt-lg-n3, + .my-lg-n3 { + margin-top: -1rem !important; + } + .mr-lg-n3, + .mx-lg-n3 { + margin-right: -1rem !important; + } + .mb-lg-n3, + .my-lg-n3 { + margin-bottom: -1rem !important; + } + .ml-lg-n3, + .mx-lg-n3 { + margin-left: -1rem !important; + } + .m-lg-n4 { + margin: -1.5rem !important; + } + .mt-lg-n4, + .my-lg-n4 { + margin-top: -1.5rem !important; + } + .mr-lg-n4, + .mx-lg-n4 { + margin-right: -1.5rem !important; + } + .mb-lg-n4, + .my-lg-n4 { + margin-bottom: -1.5rem !important; + } + .ml-lg-n4, + .mx-lg-n4 { + margin-left: -1.5rem !important; + } + .m-lg-n5 { + margin: -3rem !important; + } + .mt-lg-n5, + .my-lg-n5 { + margin-top: -3rem !important; + } + .mr-lg-n5, + .mx-lg-n5 { + margin-right: -3rem !important; + } + .mb-lg-n5, + .my-lg-n5 { + margin-bottom: -3rem !important; + } + .ml-lg-n5, + .mx-lg-n5 { + margin-left: -3rem !important; + } + .m-lg-auto { + margin: auto !important; + } + .mt-lg-auto, + .my-lg-auto { + margin-top: auto !important; + } + .mr-lg-auto, + .mx-lg-auto { + margin-right: auto !important; + } + .mb-lg-auto, + .my-lg-auto { + margin-bottom: auto !important; + } + .ml-lg-auto, + .mx-lg-auto { + margin-left: auto !important; + } +} + +@media (min-width: 1200px) { + .m-xl-0 { + margin: 0 !important; + } + .mt-xl-0, + .my-xl-0 { + margin-top: 0 !important; + } + .mr-xl-0, + .mx-xl-0 { + margin-right: 0 !important; + } + .mb-xl-0, + .my-xl-0 { + margin-bottom: 0 !important; + } + .ml-xl-0, + .mx-xl-0 { + margin-left: 0 !important; + } + .m-xl-1 { + margin: 0.25rem !important; + } + .mt-xl-1, + .my-xl-1 { + margin-top: 0.25rem !important; + } + .mr-xl-1, + .mx-xl-1 { + margin-right: 0.25rem !important; + } + .mb-xl-1, + .my-xl-1 { + margin-bottom: 0.25rem !important; + } + .ml-xl-1, + .mx-xl-1 { + margin-left: 0.25rem !important; + } + .m-xl-2 { + margin: 0.5rem !important; + } + .mt-xl-2, + .my-xl-2 { + margin-top: 0.5rem !important; + } + .mr-xl-2, + .mx-xl-2 { + margin-right: 0.5rem !important; + } + .mb-xl-2, + .my-xl-2 { + margin-bottom: 0.5rem !important; + } + .ml-xl-2, + .mx-xl-2 { + margin-left: 0.5rem !important; + } + .m-xl-3 { + margin: 1rem !important; + } + .mt-xl-3, + .my-xl-3 { + margin-top: 1rem !important; + } + .mr-xl-3, + .mx-xl-3 { + margin-right: 1rem !important; + } + .mb-xl-3, + .my-xl-3 { + margin-bottom: 1rem !important; + } + .ml-xl-3, + .mx-xl-3 { + margin-left: 1rem !important; + } + .m-xl-4 { + margin: 1.5rem !important; + } + .mt-xl-4, + .my-xl-4 { + margin-top: 1.5rem !important; + } + .mr-xl-4, + .mx-xl-4 { + margin-right: 1.5rem !important; + } + .mb-xl-4, + .my-xl-4 { + margin-bottom: 1.5rem !important; + } + .ml-xl-4, + .mx-xl-4 { + margin-left: 1.5rem !important; + } + .m-xl-5 { + margin: 3rem !important; + } + .mt-xl-5, + .my-xl-5 { + margin-top: 3rem !important; + } + .mr-xl-5, + .mx-xl-5 { + margin-right: 3rem !important; + } + .mb-xl-5, + .my-xl-5 { + margin-bottom: 3rem !important; + } + .ml-xl-5, + .mx-xl-5 { + margin-left: 3rem !important; + } + .p-xl-0 { + padding: 0 !important; + } + .pt-xl-0, + .py-xl-0 { + padding-top: 0 !important; + } + .pr-xl-0, + .px-xl-0 { + padding-right: 0 !important; + } + .pb-xl-0, + .py-xl-0 { + padding-bottom: 0 !important; + } + .pl-xl-0, + .px-xl-0 { + padding-left: 0 !important; + } + .p-xl-1 { + padding: 0.25rem !important; + } + .pt-xl-1, + .py-xl-1 { + padding-top: 0.25rem !important; + } + .pr-xl-1, + .px-xl-1 { + padding-right: 0.25rem !important; + } + .pb-xl-1, + .py-xl-1 { + padding-bottom: 0.25rem !important; + } + .pl-xl-1, + .px-xl-1 { + padding-left: 0.25rem !important; + } + .p-xl-2 { + padding: 0.5rem !important; + } + .pt-xl-2, + .py-xl-2 { + padding-top: 0.5rem !important; + } + .pr-xl-2, + .px-xl-2 { + padding-right: 0.5rem !important; + } + .pb-xl-2, + .py-xl-2 { + padding-bottom: 0.5rem !important; + } + .pl-xl-2, + .px-xl-2 { + padding-left: 0.5rem !important; + } + .p-xl-3 { + padding: 1rem !important; + } + .pt-xl-3, + .py-xl-3 { + padding-top: 1rem !important; + } + .pr-xl-3, + .px-xl-3 { + padding-right: 1rem !important; + } + .pb-xl-3, + .py-xl-3 { + padding-bottom: 1rem !important; + } + .pl-xl-3, + .px-xl-3 { + padding-left: 1rem !important; + } + .p-xl-4 { + padding: 1.5rem !important; + } + .pt-xl-4, + .py-xl-4 { + padding-top: 1.5rem !important; + } + .pr-xl-4, + .px-xl-4 { + padding-right: 1.5rem !important; + } + .pb-xl-4, + .py-xl-4 { + padding-bottom: 1.5rem !important; + } + .pl-xl-4, + .px-xl-4 { + padding-left: 1.5rem !important; + } + .p-xl-5 { + padding: 3rem !important; + } + .pt-xl-5, + .py-xl-5 { + padding-top: 3rem !important; + } + .pr-xl-5, + .px-xl-5 { + padding-right: 3rem !important; + } + .pb-xl-5, + .py-xl-5 { + padding-bottom: 3rem !important; + } + .pl-xl-5, + .px-xl-5 { + padding-left: 3rem !important; + } + .m-xl-n1 { + margin: -0.25rem !important; + } + .mt-xl-n1, + .my-xl-n1 { + margin-top: -0.25rem !important; + } + .mr-xl-n1, + .mx-xl-n1 { + margin-right: -0.25rem !important; + } + .mb-xl-n1, + .my-xl-n1 { + margin-bottom: -0.25rem !important; + } + .ml-xl-n1, + .mx-xl-n1 { + margin-left: -0.25rem !important; + } + .m-xl-n2 { + margin: -0.5rem !important; + } + .mt-xl-n2, + .my-xl-n2 { + margin-top: -0.5rem !important; + } + .mr-xl-n2, + .mx-xl-n2 { + margin-right: -0.5rem !important; + } + .mb-xl-n2, + .my-xl-n2 { + margin-bottom: -0.5rem !important; + } + .ml-xl-n2, + .mx-xl-n2 { + margin-left: -0.5rem !important; + } + .m-xl-n3 { + margin: -1rem !important; + } + .mt-xl-n3, + .my-xl-n3 { + margin-top: -1rem !important; + } + .mr-xl-n3, + .mx-xl-n3 { + margin-right: -1rem !important; + } + .mb-xl-n3, + .my-xl-n3 { + margin-bottom: -1rem !important; + } + .ml-xl-n3, + .mx-xl-n3 { + margin-left: -1rem !important; + } + .m-xl-n4 { + margin: -1.5rem !important; + } + .mt-xl-n4, + .my-xl-n4 { + margin-top: -1.5rem !important; + } + .mr-xl-n4, + .mx-xl-n4 { + margin-right: -1.5rem !important; + } + .mb-xl-n4, + .my-xl-n4 { + margin-bottom: -1.5rem !important; + } + .ml-xl-n4, + .mx-xl-n4 { + margin-left: -1.5rem !important; + } + .m-xl-n5 { + margin: -3rem !important; + } + .mt-xl-n5, + .my-xl-n5 { + margin-top: -3rem !important; + } + .mr-xl-n5, + .mx-xl-n5 { + margin-right: -3rem !important; + } + .mb-xl-n5, + .my-xl-n5 { + margin-bottom: -3rem !important; + } + .ml-xl-n5, + .mx-xl-n5 { + margin-left: -3rem !important; + } + .m-xl-auto { + margin: auto !important; + } + .mt-xl-auto, + .my-xl-auto { + margin-top: auto !important; + } + .mr-xl-auto, + .mx-xl-auto { + margin-right: auto !important; + } + .mb-xl-auto, + .my-xl-auto { + margin-bottom: auto !important; + } + .ml-xl-auto, + .mx-xl-auto { + margin-left: auto !important; + } +} + +.text-monospace { + font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !important; +} + +.text-justify { + text-align: justify !important; +} + +.text-wrap { + white-space: normal !important; +} + +.text-nowrap { + white-space: nowrap !important; +} + +.text-truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.text-left { + text-align: left !important; +} + +.text-right { + text-align: right !important; +} + +.text-center { + text-align: center !important; +} + +@media (min-width: 576px) { + .text-sm-left { + text-align: left !important; + } + .text-sm-right { + text-align: right !important; + } + .text-sm-center { + text-align: center !important; + } +} + +@media (min-width: 768px) { + .text-md-left { + text-align: left !important; + } + .text-md-right { + text-align: right !important; + } + .text-md-center { + text-align: center !important; + } +} + +@media (min-width: 992px) { + .text-lg-left { + text-align: left !important; + } + .text-lg-right { + text-align: right !important; + } + .text-lg-center { + text-align: center !important; + } +} + +@media (min-width: 1200px) { + .text-xl-left { + text-align: left !important; + } + .text-xl-right { + text-align: right !important; + } + .text-xl-center { + text-align: center !important; + } +} + +.text-lowercase { + text-transform: lowercase !important; +} + +.text-uppercase { + text-transform: uppercase !important; +} + +.text-capitalize { + text-transform: capitalize !important; +} + +.font-weight-light { + font-weight: 300 !important; +} + +.font-weight-lighter { + font-weight: lighter !important; +} + +.font-weight-normal { + font-weight: 400 !important; +} + +.font-weight-bold { + font-weight: 700 !important; +} + +.font-weight-bolder { + font-weight: bolder !important; +} + +.font-italic { + font-style: italic !important; +} + +.text-white { + color: #fff !important; +} + +.text-primary { + color: #007bff !important; +} + +a.text-primary:hover, a.text-primary:focus { + color: #0056b3 !important; +} + +.text-secondary { + color: #6c757d !important; +} + +a.text-secondary:hover, a.text-secondary:focus { + color: #494f54 !important; +} + +.text-success { + color: #28a745 !important; +} + +a.text-success:hover, a.text-success:focus { + color: #19692c !important; +} + +.text-info { + color: #17a2b8 !important; +} + +a.text-info:hover, a.text-info:focus { + color: #0f6674 !important; +} + +.text-warning { + color: #ffc107 !important; +} + +a.text-warning:hover, a.text-warning:focus { + color: #ba8b00 !important; +} + +.text-danger { + color: #dc3545 !important; +} + +a.text-danger:hover, a.text-danger:focus { + color: #a71d2a !important; +} + +.text-light { + color: #f8f9fa !important; +} + +a.text-light:hover, a.text-light:focus { + color: #cbd3da !important; +} + +.text-dark { + color: #343a40 !important; +} + +a.text-dark:hover, a.text-dark:focus { + color: #121416 !important; +} + +.text-body { + color: #212529 !important; +} + +.text-muted { + color: #6c757d !important; +} + +.text-black-50 { + color: rgba(0, 0, 0, 0.5) !important; +} + +.text-white-50 { + color: rgba(255, 255, 255, 0.5) !important; +} + +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +.text-decoration-none { + text-decoration: none !important; +} + +.text-break { + word-break: break-word !important; + overflow-wrap: break-word !important; +} + +.text-reset { + color: inherit !important; +} + +.visible { + visibility: visible !important; +} + +.invisible { + visibility: hidden !important; +} + +@media print { + *, + *::before, + *::after { + text-shadow: none !important; + box-shadow: none !important; + } + a:not(.btn) { + text-decoration: underline; + } + abbr[title]::after { + content: " (" attr(title) ")"; + } + pre { + white-space: pre-wrap !important; + } + pre, + blockquote { + border: 1px solid #adb5bd; + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + @page { + size: a3; + } + body { + min-width: 992px !important; + } + .container { + min-width: 992px !important; + } + .navbar { + display: none; + } + .badge { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table td, + .table th { + background-color: #fff !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #dee2e6 !important; + } + .table-dark { + color: inherit; + } + .table-dark th, + .table-dark td, + .table-dark thead th, + .table-dark tbody + tbody { + border-color: #dee2e6; + } + .table .thead-dark th { + color: inherit; + border-color: #dee2e6; + } +} +/*# sourceMappingURL=bootstrap.css.map */ \ No newline at end of file diff --git a/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map new file mode 100644 index 0000000000000000000000000000000000000000..7eb158168fad673f9d7c4472e261a7fbd27a7d22 --- /dev/null +++ b/Pure_Vite_Net7/WebNet7/VOL.WebApi/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../scss/bootstrap.scss","bootstrap.css","../../scss/_root.scss","../../scss/_reboot.scss","../../scss/_variables.scss","../../scss/vendor/_rfs.scss","../../scss/mixins/_hover.scss","../../scss/_type.scss","../../scss/mixins/_lists.scss","../../scss/_images.scss","../../scss/mixins/_image.scss","../../scss/mixins/_border-radius.scss","../../scss/_code.scss","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/mixins/_breakpoints.scss","../../scss/mixins/_grid-framework.scss","../../scss/_tables.scss","../../scss/mixins/_table-row.scss","../../scss/_functions.scss","../../scss/_forms.scss","../../scss/mixins/_transition.scss","../../scss/mixins/_forms.scss","../../scss/mixins/_gradients.scss","../../scss/_buttons.scss","../../scss/mixins/_buttons.scss","../../scss/_transitions.scss","../../scss/_dropdown.scss","../../scss/mixins/_caret.scss","../../scss/mixins/_nav-divider.scss","../../scss/_button-group.scss","../../scss/_input-group.scss","../../scss/_custom-forms.scss","../../scss/_nav.scss","../../scss/_navbar.scss","../../scss/_card.scss","../../scss/_breadcrumb.scss","../../scss/_pagination.scss","../../scss/mixins/_pagination.scss","../../scss/_badge.scss","../../scss/mixins/_badge.scss","../../scss/_jumbotron.scss","../../scss/_alert.scss","../../scss/mixins/_alert.scss","../../scss/_progress.scss","../../scss/_media.scss","../../scss/_list-group.scss","../../scss/mixins/_list-group.scss","../../scss/_close.scss","../../scss/_toasts.scss","../../scss/_modal.scss","../../scss/_tooltip.scss","../../scss/mixins/_reset-text.scss","../../scss/_popover.scss","../../scss/_carousel.scss","../../scss/mixins/_clearfix.scss","../../scss/_spinners.scss","../../scss/utilities/_align.scss","../../scss/mixins/_background-variant.scss","../../scss/utilities/_background.scss","../../scss/utilities/_borders.scss","../../scss/utilities/_display.scss","../../scss/utilities/_embed.scss","../../scss/utilities/_flex.scss","../../scss/utilities/_float.scss","../../scss/utilities/_overflow.scss","../../scss/utilities/_position.scss","../../scss/utilities/_screenreaders.scss","../../scss/mixins/_screen-reader.scss","../../scss/utilities/_shadows.scss","../../scss/utilities/_sizing.scss","../../scss/utilities/_stretched-link.scss","../../scss/utilities/_spacing.scss","../../scss/utilities/_text.scss","../../scss/mixins/_text-truncate.scss","../../scss/mixins/_text-emphasis.scss","../../scss/mixins/_text-hide.scss","../../scss/utilities/_visibility.scss","../../scss/_print.scss"],"names":[],"mappings":"AAAA;;;;;ECKE;ACLF;EAGI,eAAc;EAAd,iBAAc;EAAd,iBAAc;EAAd,eAAc;EAAd,cAAc;EAAd,iBAAc;EAAd,iBAAc;EAAd,gBAAc;EAAd,eAAc;EAAd,eAAc;EAAd,aAAc;EAAd,eAAc;EAAd,oBAAc;EAId,kBAAc;EAAd,oBAAc;EAAd,kBAAc;EAAd,eAAc;EAAd,kBAAc;EAAd,iBAAc;EAAd,gBAAc;EAAd,eAAc;EAId,kBAAiC;EAAjC,sBAAiC;EAAjC,sBAAiC;EAAjC,sBAAiC;EAAjC,uBAAiC;EAKnC,+MAAyB;EACzB,6GAAwB;ADkB1B;;AEjBA;;;EAGE,sBAAsB;AFoBxB;;AEjBA;EACE,uBAAuB;EACvB,iBAAiB;EACjB,8BAA8B;EAC9B,6CCXa;AH+Bf;;AEdA;EACE,cAAc;AFiBhB;;AEPA;EACE,SAAS;EACT,kMCiOiN;ECjJ7M,eAtCY;EFxChB,gBC0O+B;EDzO/B,gBC8O+B;ED7O/B,cCnCgB;EDoChB,gBAAgB;EAChB,sBC9Ca;AHwDf;;AAEA;EEHE,qBAAqB;AFKvB;;AEIA;EACE,uBAAuB;EACvB,SAAS;EACT,iBAAiB;AFDnB;;AEcA;EACE,aAAa;EACb,qBCgNuC;AH3NzC;;AEkBA;EACE,aAAa;EACb,mBCoF8B;AHnGhC;;AE0BA;;EAEE,0BAA0B;EAC1B,yCAAiC;EAAjC,iCAAiC;EACjC,YAAY;EACZ,gBAAgB;EAChB,sCAA8B;EAA9B,8BAA8B;AFvBhC;;AE0BA;EACE,mBAAmB;EACnB,kBAAkB;EAClB,oBAAoB;AFvBtB;;AE0BA;;;EAGE,aAAa;EACb,mBAAmB;AFvBrB;;AE0BA;;;;EAIE,gBAAgB;AFvBlB;;AE0BA;EACE,gBCiJ+B;AHxKjC;;AE0BA;EACE,oBAAoB;EACpB,cAAc;AFvBhB;;AE0BA;EACE,gBAAgB;AFvBlB;;AE0BA;;EAEE,mBCoIkC;AH3JpC;;AE0BA;EEpFI,cAAW;AJ8Df;;AE+BA;;EAEE,kBAAkB;EE/FhB,cAAW;EFiGb,cAAc;EACd,wBAAwB;AF5B1B;;AE+BA;EAAM,cAAc;AF3BpB;;AE4BA;EAAM,UAAU;AFxBhB;;AE+BA;EACE,cClJe;EDmJf,qBCX4C;EDY5C,6BAA6B;AF5B/B;;AKhJE;EH+KE,cCd8D;EDe9D,0BCd+C;AHbnD;;AEqCA;EACE,cAAc;EACd,qBAAqB;AFlCvB;;AKtJE;EH2LE,cAAc;EACd,qBAAqB;AFjCzB;;AE2BA;EAUI,UAAU;AFjCd;;AE0CA;;;;EAIE,iGCoDgH;ECzM9G,cAAW;AJ+Gf;;AE0CA;EAEE,aAAa;EAEb,mBAAmB;EAEnB,cAAc;AF1ChB;;AEkDA;EAEE,gBAAgB;AFhDlB;;AEwDA;EACE,sBAAsB;EACtB,kBAAkB;AFrDpB;;AEwDA;EAGE,gBAAgB;EAChB,sBAAsB;AFvDxB;;AE+DA;EACE,yBAAyB;AF5D3B;;AE+DA;EACE,oBC2EkC;ED1ElC,uBC0EkC;EDzElC,cCpQgB;EDqQhB,gBAAgB;EAChB,oBAAoB;AF5DtB;;AE+DA;EAGE,mBAAmB;AF9DrB;;AEsEA;EAEE,qBAAqB;EACrB,qBC4J2C;AHhO7C;;AE0EA;EAEE,gBAAgB;AFxElB;;AE+EA;EACE,mBAAmB;EACnB,0CAA0C;AF5E5C;;AE+EA;;;;;EAKE,SAAS;EACT,oBAAoB;EEtPlB,kBAAW;EFwPb,oBAAoB;AF5EtB;;AE+EA;;EAEE,iBAAiB;AF5EnB;;AE+EA;;EAEE,oBAAoB;AF5EtB;;AEkFA;EACE,iBAAiB;AF/EnB;;AEsFA;;;;EAIE,0BAA0B;AFnF5B;;AEwFE;;;;EAKI,eAAe;AFtFrB;;AE4FA;;;;EAIE,UAAU;EACV,kBAAkB;AFzFpB;;AE4FA;;EAEE,sBAAsB;EACtB,UAAU;AFzFZ;;AE6FA;;;;EASE,2BAA2B;AF/F7B;;AEkGA;EACE,cAAc;EAEd,gBAAgB;AFhGlB;;AEmGA;EAME,YAAY;EAEZ,UAAU;EACV,SAAS;EACT,SAAS;AFtGX;;AE2GA;EACE,cAAc;EACd,WAAW;EACX,eAAe;EACf,UAAU;EACV,oBAAoB;EElShB,iBAtCY;EF0UhB,oBAAoB;EACpB,cAAc;EACd,mBAAmB;AFxGrB;;AE2GA;EACE,wBAAwB;AFxG1B;;AAEA;;EE4GE,YAAY;AFzGd;;AAEA;EE+GE,oBAAoB;EACpB,wBAAwB;AF7G1B;;AAEA;EEmHE,wBAAwB;AFjH1B;;AEyHA;EACE,aAAa;EACb,0BAA0B;AFtH5B;;AE6HA;EACE,qBAAqB;AF1HvB;;AE6HA;EACE,kBAAkB;EAClB,eAAe;AF1HjB;;AE6HA;EACE,aAAa;AF1Hf;;AAEA;EE8HE,wBAAwB;AF5H1B;;AM/VA;;EAEE,qBHiSuC;EG/RvC,gBHiS+B;EGhS/B,gBHiS+B;AHgEjC;;AM7VA;EFgHM,iBAtCY;AJuRlB;;AMhWA;EF+GM,eAtCY;AJ2RlB;;AMnWA;EF8GM,kBAtCY;AJ+RlB;;AMtWA;EF6GM,iBAtCY;AJmSlB;;AMzWA;EF4GM,kBAtCY;AJuSlB;;AM5WA;EF2GM,eAtCY;AJ2SlB;;AM9WA;EFyGM,kBAtCY;EEjEhB,gBHmS+B;AH8EjC;;AM7WA;EFmGM,eAtCY;EE3DhB,gBHsR+B;EGrR/B,gBH6Q+B;AHmGjC;;AM9WA;EF8FM,iBAtCY;EEtDhB,gBHkR+B;EGjR/B,gBHwQ+B;AHyGjC;;AM/WA;EFyFM,iBAtCY;EEjDhB,gBH8Q+B;EG7Q/B,gBHmQ+B;AH+GjC;;AMhXA;EFoFM,iBAtCY;EE5ChB,gBH0Q+B;EGzQ/B,gBH8P+B;AHqHjC;;AE1VA;EIhBE,gBH0EW;EGzEX,mBHyEW;EGxEX,SAAS;EACT,wCHzCa;AHuZf;;AMtWA;;EFMI,cAAW;EEHb,gBHsN+B;AHmJjC;;AMtWA;;EAEE,cH8PgC;EG7PhC,yBHsQmC;AHmGrC;;AMjWA;EC/EE,eAAe;EACf,gBAAgB;APoblB;;AMjWA;ECpFE,eAAe;EACf,gBAAgB;APyblB;;AMnWA;EACE,qBAAqB;ANsWvB;;AMvWA;EAII,oBHgP+B;AHuHnC;;AM7VA;EFjCI,cAAW;EEmCb,yBAAyB;ANgW3B;;AM5VA;EACE,mBHiBW;ECFP,kBAtCY;AJuXlB;;AM5VA;EACE,cAAc;EF7CZ,cAAW;EE+Cb,cH1GgB;AHyclB;;AMlWA;EAMI,qBAAqB;ANgWzB;;AQndA;ECIE,eAAe;EAGf,YAAY;ATidd;;AQldA;EACE,gBL++BwC;EK9+BxC,sBLRa;EKSb,yBLNgB;EOLd,sBPqOgC;EM/NlC,eAAe;EAGf,YAAY;AT0dd;;AQ5cA;EAEE,qBAAqB;AR8cvB;;AQ3cA;EACE,qBAA0B;EAC1B,cAAc;AR8chB;;AQ3cA;EJkCI,cAAW;EIhCb,cL3BgB;AHyelB;;AWrfA;EPuEI,gBAAW;EOrEb,cRoCe;EQnCf,sBAAsB;AXwfxB;;AWrfE;EACE,cAAc;AXwflB;;AWnfA;EACE,sBRikCuC;ECvgCrC,gBAAW;EOxDb,WRTa;EQUb,yBRDgB;EOXd,qBPuO+B;AH4RnC;;AW3fA;EASI,UAAU;EPkDV,eAAW;EOhDX,gBRoQ6B;AHkPjC;;AE7SA;ESlME,cAAc;EPyCZ,gBAAW;EOvCb,cRjBgB;AHogBlB;;AWtfA;EP0CI,kBAAW;EOlCX,cAAc;EACd,kBAAkB;AXmftB;;AW9eA;EACE,iBRwiCuC;EQviCvC,kBAAkB;AXifpB;;AY1hBE;ECAA,WAAW;EACX,mBAA0B;EAC1B,kBAAyB;EACzB,kBAAkB;EAClB,iBAAiB;Ab8hBnB;;Ac3eI;EFvDF;ICYI,gBV8LK;EH6VT;AACF;;AcjfI;EFvDF;ICYI,gBV+LK;EHkWT;AACF;;AcvfI;EFvDF;ICYI,gBVgMK;EHuWT;AACF;;Ac7fI;EFvDF;ICYI,iBViMM;EH4WV;AACF;;AY9iBE;ECZA,WAAW;EACX,mBAA0B;EAC1B,kBAAyB;EACzB,kBAAkB;EAClB,iBAAiB;Ab8jBnB;;AY5iBE;ECJA,oBAAa;EAAb,aAAa;EACb,mBAAe;EAAf,eAAe;EACf,mBAA0B;EAC1B,kBAAyB;AbojB3B;;AY7iBE;EACE,eAAe;EACf,cAAc;AZgjBlB;;AYljBE;;EAMI,gBAAgB;EAChB,eAAe;AZijBrB;;AellBE;;;;;;EACE,kBAAkB;EAClB,WAAW;EACX,mBAA0B;EAC1B,kBAAyB;Af0lB7B;;AevkBM;EACE,0BAAa;EAAb,aAAa;EACb,oBAAY;EAAZ,YAAY;EACZ,eAAe;Af0kBvB;;AexkBM;EACE,kBAAc;EAAd,cAAc;EACd,WAAW;EACX,eAAe;Af2kBvB;;AevkBQ;EFFN,uBAAsC;EAAtC,mBAAsC;EAItC,oBAAuC;Ab0kBzC;;Ae5kBQ;EFFN,wBAAsC;EAAtC,oBAAsC;EAItC,qBAAuC;Ab+kBzC;;AejlBQ;EFFN,iBAAsC;EAAtC,aAAsC;EAItC,cAAuC;AbolBzC;;AetlBQ;EFFN,wBAAsC;EAAtC,oBAAsC;EAItC,qBAAuC;AbylBzC;;Ae3lBQ;EFFN,wBAAsC;EAAtC,oBAAsC;EAItC,qBAAuC;Ab8lBzC;;AehmBQ;EFFN,iBAAsC;EAAtC,aAAsC;EAItC,cAAuC;AbmmBzC;;AermBQ;EFFN,wBAAsC;EAAtC,oBAAsC;EAItC,qBAAuC;AbwmBzC;;Ae1mBQ;EFFN,wBAAsC;EAAtC,oBAAsC;EAItC,qBAAuC;Ab6mBzC;;Ae/mBQ;EFFN,iBAAsC;EAAtC,aAAsC;EAItC,cAAuC;AbknBzC;;AepnBQ;EFFN,wBAAsC;EAAtC,oBAAsC;EAItC,qBAAuC;AbunBzC;;AeznBQ;EFFN,wBAAsC;EAAtC,oBAAsC;EAItC,qBAAuC;Ab4nBzC;;Ae9nBQ;EFFN,kBAAsC;EAAtC,cAAsC;EAItC,eAAuC;AbioBzC;;Ae9nBM;EAAwB,kBAAS;EAAT,SAAS;AfkoBvC;;AehoBM;EAAuB,kBZ2KG;EY3KH,SZ2KG;AHydhC;;AejoBQ;EAAwB,iBADZ;EACY,QADZ;AfsoBpB;;AeroBQ;EAAwB,iBADZ;EACY,QADZ;Af0oBpB;;AezoBQ;EAAwB,iBADZ;EACY,QADZ;Af8oBpB;;Ae7oBQ;EAAwB,iBADZ;EACY,QADZ;AfkpBpB;;AejpBQ;EAAwB,iBADZ;EACY,QADZ;AfspBpB;;AerpBQ;EAAwB,iBADZ;EACY,QADZ;Af0pBpB;;AezpBQ;EAAwB,iBADZ;EACY,QADZ;Af8pBpB;;Ae7pBQ;EAAwB,iBADZ;EACY,QADZ;AfkqBpB;;AejqBQ;EAAwB,iBADZ;EACY,QADZ;AfsqBpB;;AerqBQ;EAAwB,iBADZ;EACY,QADZ;Af0qBpB;;AezqBQ;EAAwB,kBADZ;EACY,SADZ;Af8qBpB;;Ae7qBQ;EAAwB,kBADZ;EACY,SADZ;AfkrBpB;;AejrBQ;EAAwB,kBADZ;EACY,SADZ;AfsrBpB;;Ae/qBU;EFTR,sBAA8C;Ab4rBhD;;AenrBU;EFTR,uBAA8C;AbgsBhD;;AevrBU;EFTR,gBAA8C;AbosBhD;;Ae3rBU;EFTR,uBAA8C;AbwsBhD;;Ae/rBU;EFTR,uBAA8C;Ab4sBhD;;AensBU;EFTR,gBAA8C;AbgtBhD;;AevsBU;EFTR,uBAA8C;AbotBhD;;Ae3sBU;EFTR,uBAA8C;AbwtBhD;;Ae/sBU;EFTR,gBAA8C;Ab4tBhD;;AentBU;EFTR,uBAA8C;AbguBhD;;AevtBU;EFTR,uBAA8C;AbouBhD;;AcztBI;EC9BE;IACE,0BAAa;IAAb,aAAa;IACb,oBAAY;IAAZ,YAAY;IACZ,eAAe;Ef2vBrB;EezvBI;IACE,kBAAc;IAAd,cAAc;IACd,WAAW;IACX,eAAe;Ef2vBrB;EevvBM;IFFN,uBAAsC;IAAtC,mBAAsC;IAItC,oBAAuC;EbyvBvC;Ee3vBM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;Eb6vBvC;Ee/vBM;IFFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EbiwBvC;EenwBM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EbqwBvC;EevwBM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EbywBvC;Ee3wBM;IFFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;Eb6wBvC;Ee/wBM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EbixBvC;EenxBM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EbqxBvC;EevxBM;IFFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EbyxBvC;Ee3xBM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;Eb6xBvC;Ee/xBM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EbiyBvC;EenyBM;IFFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;EbqyBvC;EelyBI;IAAwB,kBAAS;IAAT,SAAS;EfqyBrC;EenyBI;IAAuB,kBZ2KG;IY3KH,SZ2KG;EH2nB9B;EenyBM;IAAwB,iBADZ;IACY,QADZ;EfuyBlB;EetyBM;IAAwB,iBADZ;IACY,QADZ;Ef0yBlB;EezyBM;IAAwB,iBADZ;IACY,QADZ;Ef6yBlB;Ee5yBM;IAAwB,iBADZ;IACY,QADZ;EfgzBlB;Ee/yBM;IAAwB,iBADZ;IACY,QADZ;EfmzBlB;EelzBM;IAAwB,iBADZ;IACY,QADZ;EfszBlB;EerzBM;IAAwB,iBADZ;IACY,QADZ;EfyzBlB;EexzBM;IAAwB,iBADZ;IACY,QADZ;Ef4zBlB;Ee3zBM;IAAwB,iBADZ;IACY,QADZ;Ef+zBlB;Ee9zBM;IAAwB,iBADZ;IACY,QADZ;Efk0BlB;Eej0BM;IAAwB,kBADZ;IACY,SADZ;Efq0BlB;Eep0BM;IAAwB,kBADZ;IACY,SADZ;Efw0BlB;Eev0BM;IAAwB,kBADZ;IACY,SADZ;Ef20BlB;Eep0BQ;IFTR,cAA4B;Ebg1B5B;Eev0BQ;IFTR,sBAA8C;Ebm1B9C;Ee10BQ;IFTR,uBAA8C;Ebs1B9C;Ee70BQ;IFTR,gBAA8C;Eby1B9C;Eeh1BQ;IFTR,uBAA8C;Eb41B9C;Een1BQ;IFTR,uBAA8C;Eb+1B9C;Eet1BQ;IFTR,gBAA8C;Ebk2B9C;Eez1BQ;IFTR,uBAA8C;Ebq2B9C;Ee51BQ;IFTR,uBAA8C;Ebw2B9C;Ee/1BQ;IFTR,gBAA8C;Eb22B9C;Eel2BQ;IFTR,uBAA8C;Eb82B9C;Eer2BQ;IFTR,uBAA8C;Ebi3B9C;AACF;;Acv2BI;EC9BE;IACE,0BAAa;IAAb,aAAa;IACb,oBAAY;IAAZ,YAAY;IACZ,eAAe;Efy4BrB;Eev4BI;IACE,kBAAc;IAAd,cAAc;IACd,WAAW;IACX,eAAe;Efy4BrB;Eer4BM;IFFN,uBAAsC;IAAtC,mBAAsC;IAItC,oBAAuC;Ebu4BvC;Eez4BM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;Eb24BvC;Ee74BM;IFFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;Eb+4BvC;Eej5BM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;Ebm5BvC;Eer5BM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;Ebu5BvC;Eez5BM;IFFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;Eb25BvC;Ee75BM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;Eb+5BvC;Eej6BM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;Ebm6BvC;Eer6BM;IFFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;Ebu6BvC;Eez6BM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;Eb26BvC;Ee76BM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;Eb+6BvC;Eej7BM;IFFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;Ebm7BvC;Eeh7BI;IAAwB,kBAAS;IAAT,SAAS;Efm7BrC;Eej7BI;IAAuB,kBZ2KG;IY3KH,SZ2KG;EHywB9B;Eej7BM;IAAwB,iBADZ;IACY,QADZ;Efq7BlB;Eep7BM;IAAwB,iBADZ;IACY,QADZ;Efw7BlB;Eev7BM;IAAwB,iBADZ;IACY,QADZ;Ef27BlB;Ee17BM;IAAwB,iBADZ;IACY,QADZ;Ef87BlB;Ee77BM;IAAwB,iBADZ;IACY,QADZ;Efi8BlB;Eeh8BM;IAAwB,iBADZ;IACY,QADZ;Efo8BlB;Een8BM;IAAwB,iBADZ;IACY,QADZ;Efu8BlB;Eet8BM;IAAwB,iBADZ;IACY,QADZ;Ef08BlB;Eez8BM;IAAwB,iBADZ;IACY,QADZ;Ef68BlB;Ee58BM;IAAwB,iBADZ;IACY,QADZ;Efg9BlB;Ee/8BM;IAAwB,kBADZ;IACY,SADZ;Efm9BlB;Eel9BM;IAAwB,kBADZ;IACY,SADZ;Efs9BlB;Eer9BM;IAAwB,kBADZ;IACY,SADZ;Efy9BlB;Eel9BQ;IFTR,cAA4B;Eb89B5B;Eer9BQ;IFTR,sBAA8C;Ebi+B9C;Eex9BQ;IFTR,uBAA8C;Ebo+B9C;Ee39BQ;IFTR,gBAA8C;Ebu+B9C;Ee99BQ;IFTR,uBAA8C;Eb0+B9C;Eej+BQ;IFTR,uBAA8C;Eb6+B9C;Eep+BQ;IFTR,gBAA8C;Ebg/B9C;Eev+BQ;IFTR,uBAA8C;Ebm/B9C;Ee1+BQ;IFTR,uBAA8C;Ebs/B9C;Ee7+BQ;IFTR,gBAA8C;Eby/B9C;Eeh/BQ;IFTR,uBAA8C;Eb4/B9C;Een/BQ;IFTR,uBAA8C;Eb+/B9C;AACF;;Acr/BI;EC9BE;IACE,0BAAa;IAAb,aAAa;IACb,oBAAY;IAAZ,YAAY;IACZ,eAAe;EfuhCrB;EerhCI;IACE,kBAAc;IAAd,cAAc;IACd,WAAW;IACX,eAAe;EfuhCrB;EenhCM;IFFN,uBAAsC;IAAtC,mBAAsC;IAItC,oBAAuC;EbqhCvC;EevhCM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EbyhCvC;Ee3hCM;IFFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;Eb6hCvC;Ee/hCM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EbiiCvC;EeniCM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EbqiCvC;EeviCM;IFFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EbyiCvC;Ee3iCM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;Eb6iCvC;Ee/iCM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EbijCvC;EenjCM;IFFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EbqjCvC;EevjCM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EbyjCvC;Ee3jCM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;Eb6jCvC;Ee/jCM;IFFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;EbikCvC;Ee9jCI;IAAwB,kBAAS;IAAT,SAAS;EfikCrC;Ee/jCI;IAAuB,kBZ2KG;IY3KH,SZ2KG;EHu5B9B;Ee/jCM;IAAwB,iBADZ;IACY,QADZ;EfmkClB;EelkCM;IAAwB,iBADZ;IACY,QADZ;EfskClB;EerkCM;IAAwB,iBADZ;IACY,QADZ;EfykClB;EexkCM;IAAwB,iBADZ;IACY,QADZ;Ef4kClB;Ee3kCM;IAAwB,iBADZ;IACY,QADZ;Ef+kClB;Ee9kCM;IAAwB,iBADZ;IACY,QADZ;EfklClB;EejlCM;IAAwB,iBADZ;IACY,QADZ;EfqlClB;EeplCM;IAAwB,iBADZ;IACY,QADZ;EfwlClB;EevlCM;IAAwB,iBADZ;IACY,QADZ;Ef2lClB;Ee1lCM;IAAwB,iBADZ;IACY,QADZ;Ef8lClB;Ee7lCM;IAAwB,kBADZ;IACY,SADZ;EfimClB;EehmCM;IAAwB,kBADZ;IACY,SADZ;EfomClB;EenmCM;IAAwB,kBADZ;IACY,SADZ;EfumClB;EehmCQ;IFTR,cAA4B;Eb4mC5B;EenmCQ;IFTR,sBAA8C;Eb+mC9C;EetmCQ;IFTR,uBAA8C;EbknC9C;EezmCQ;IFTR,gBAA8C;EbqnC9C;Ee5mCQ;IFTR,uBAA8C;EbwnC9C;Ee/mCQ;IFTR,uBAA8C;Eb2nC9C;EelnCQ;IFTR,gBAA8C;Eb8nC9C;EernCQ;IFTR,uBAA8C;EbioC9C;EexnCQ;IFTR,uBAA8C;EbooC9C;Ee3nCQ;IFTR,gBAA8C;EbuoC9C;Ee9nCQ;IFTR,uBAA8C;Eb0oC9C;EejoCQ;IFTR,uBAA8C;Eb6oC9C;AACF;;AcnoCI;EC9BE;IACE,0BAAa;IAAb,aAAa;IACb,oBAAY;IAAZ,YAAY;IACZ,eAAe;EfqqCrB;EenqCI;IACE,kBAAc;IAAd,cAAc;IACd,WAAW;IACX,eAAe;EfqqCrB;EejqCM;IFFN,uBAAsC;IAAtC,mBAAsC;IAItC,oBAAuC;EbmqCvC;EerqCM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EbuqCvC;EezqCM;IFFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;Eb2qCvC;Ee7qCM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;Eb+qCvC;EejrCM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EbmrCvC;EerrCM;IFFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EburCvC;EezrCM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;Eb2rCvC;Ee7rCM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;Eb+rCvC;EejsCM;IFFN,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EbmsCvC;EersCM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EbusCvC;EezsCM;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;Eb2sCvC;Ee7sCM;IFFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;Eb+sCvC;Ee5sCI;IAAwB,kBAAS;IAAT,SAAS;Ef+sCrC;Ee7sCI;IAAuB,kBZ2KG;IY3KH,SZ2KG;EHqiC9B;Ee7sCM;IAAwB,iBADZ;IACY,QADZ;EfitClB;EehtCM;IAAwB,iBADZ;IACY,QADZ;EfotClB;EentCM;IAAwB,iBADZ;IACY,QADZ;EfutClB;EettCM;IAAwB,iBADZ;IACY,QADZ;Ef0tClB;EeztCM;IAAwB,iBADZ;IACY,QADZ;Ef6tClB;Ee5tCM;IAAwB,iBADZ;IACY,QADZ;EfguClB;Ee/tCM;IAAwB,iBADZ;IACY,QADZ;EfmuClB;EeluCM;IAAwB,iBADZ;IACY,QADZ;EfsuClB;EeruCM;IAAwB,iBADZ;IACY,QADZ;EfyuClB;EexuCM;IAAwB,iBADZ;IACY,QADZ;Ef4uClB;Ee3uCM;IAAwB,kBADZ;IACY,SADZ;Ef+uClB;Ee9uCM;IAAwB,kBADZ;IACY,SADZ;EfkvClB;EejvCM;IAAwB,kBADZ;IACY,SADZ;EfqvClB;Ee9uCQ;IFTR,cAA4B;Eb0vC5B;EejvCQ;IFTR,sBAA8C;Eb6vC9C;EepvCQ;IFTR,uBAA8C;EbgwC9C;EevvCQ;IFTR,gBAA8C;EbmwC9C;Ee1vCQ;IFTR,uBAA8C;EbswC9C;Ee7vCQ;IFTR,uBAA8C;EbywC9C;EehwCQ;IFTR,gBAA8C;Eb4wC9C;EenwCQ;IFTR,uBAA8C;Eb+wC9C;EetwCQ;IFTR,uBAA8C;EbkxC9C;EezwCQ;IFTR,gBAA8C;EbqxC9C;Ee5wCQ;IFTR,uBAA8C;EbwxC9C;Ee/wCQ;IFTR,uBAA8C;Eb2xC9C;AACF;;AgBz0CA;EACE,WAAW;EACX,mBb2HW;Ea1HX,cbSgB;AHm0ClB;;AgB/0CA;;EAQI,gBb8UgC;Ea7UhC,mBAAmB;EACnB,6BbJc;AHg1ClB;;AgBt1CA;EAcI,sBAAsB;EACtB,gCbTc;AHq1ClB;;AgB31CA;EAmBI,6Bbbc;AHy1ClB;;AgBn0CA;;EAGI,ebwT+B;AH6gCnC;;AgB5zCA;EACE,yBbnCgB;AHk2ClB;;AgBh0CA;;EAKI,yBbvCc;AHu2ClB;;AgBr0CA;;EAWM,wBAA4C;AhB+zClD;;AgB1zCA;;;;EAKI,SAAS;AhB4zCb;;AgBpzCA;EAEI,qCb1DW;AHg3Cf;;AKr3CE;EW2EI,cbvEY;EawEZ,sCbvES;AHq3Cf;;AiBj4CE;;;EAII,yBC2E4D;AlBwzClE;;AiBv4CE;;;;EAYM,qBCmE0D;AlB+zClE;;AKv4CE;EYiBM,yBAJsC;AjB83C9C;;AiB/3CE;;EASQ,yBARoC;AjBm4C9C;;AiBv5CE;;;EAII,yBC2E4D;AlB80ClE;;AiB75CE;;;;EAYM,qBCmE0D;AlBq1ClE;;AK75CE;EYiBM,yBAJsC;AjBo5C9C;;AiBr5CE;;EASQ,yBARoC;AjBy5C9C;;AiB76CE;;;EAII,yBC2E4D;AlBo2ClE;;AiBn7CE;;;;EAYM,qBCmE0D;AlB22ClE;;AKn7CE;EYiBM,yBAJsC;AjB06C9C;;AiB36CE;;EASQ,yBARoC;AjB+6C9C;;AiBn8CE;;;EAII,yBC2E4D;AlB03ClE;;AiBz8CE;;;;EAYM,qBCmE0D;AlBi4ClE;;AKz8CE;EYiBM,yBAJsC;AjBg8C9C;;AiBj8CE;;EASQ,yBARoC;AjBq8C9C;;AiBz9CE;;;EAII,yBC2E4D;AlBg5ClE;;AiB/9CE;;;;EAYM,qBCmE0D;AlBu5ClE;;AK/9CE;EYiBM,yBAJsC;AjBs9C9C;;AiBv9CE;;EASQ,yBARoC;AjB29C9C;;AiB/+CE;;;EAII,yBC2E4D;AlBs6ClE;;AiBr/CE;;;;EAYM,qBCmE0D;AlB66ClE;;AKr/CE;EYiBM,yBAJsC;AjB4+C9C;;AiB7+CE;;EASQ,yBARoC;AjBi/C9C;;AiBrgDE;;;EAII,yBC2E4D;AlB47ClE;;AiB3gDE;;;;EAYM,qBCmE0D;AlBm8ClE;;AK3gDE;EYiBM,yBAJsC;AjBkgD9C;;AiBngDE;;EASQ,yBARoC;AjBugD9C;;AiB3hDE;;;EAII,yBC2E4D;AlBk9ClE;;AiBjiDE;;;;EAYM,qBCmE0D;AlBy9ClE;;AKjiDE;EYiBM,yBAJsC;AjBwhD9C;;AiBzhDE;;EASQ,yBARoC;AjB6hD9C;;AiBjjDE;;;EAII,sCdQS;AH2iDf;;AKhjDE;EYiBM,sCAJsC;AjBuiD9C;;AiBxiDE;;EASQ,sCARoC;AjB4iD9C;;AgBt9CA;EAGM,Wb3GS;Ea4GT,yBbpGY;EaqGZ,qBb2PqD;AH4tC3D;;AgB59CA;EAWM,cb5GY;Ea6GZ,yBblHY;EamHZ,qBblHY;AHukDlB;;AgBh9CA;EACE,Wb3Ha;Ea4Hb,yBbpHgB;AHukDlB;;AgBr9CA;;;EAOI,qBbuOuD;AH6uC3D;;AgB39CA;EAWI,SAAS;AhBo9Cb;;AgB/9CA;EAgBM,2Cb1IS;AH6lDf;;AKxlDE;EW4IM,WbjJO;EakJP,4CblJO;AHkmDf;;AchiDI;EEiGA;IAEI,cAAc;IACd,WAAW;IACX,gBAAgB;IAChB,iCAAiC;EhBk8CvC;EgBv8CG;IASK,SAAS;EhBi8CjB;AACF;;Ac5iDI;EEiGA;IAEI,cAAc;IACd,WAAW;IACX,gBAAgB;IAChB,iCAAiC;EhB88CvC;EgBn9CG;IASK,SAAS;EhB68CjB;AACF;;AcxjDI;EEiGA;IAEI,cAAc;IACd,WAAW;IACX,gBAAgB;IAChB,iCAAiC;EhB09CvC;EgB/9CG;IASK,SAAS;EhBy9CjB;AACF;;AcpkDI;EEiGA;IAEI,cAAc;IACd,WAAW;IACX,gBAAgB;IAChB,iCAAiC;EhBs+CvC;EgB3+CG;IASK,SAAS;EhBq+CjB;AACF;;AgBp/CA;EAOQ,cAAc;EACd,WAAW;EACX,gBAAgB;EAChB,iCAAiC;AhBi/CzC;;AgB3/CA;EAcU,SAAS;AhBi/CnB;;AmB9pDA;EACE,cAAc;EACd,WAAW;EACX,mChBqe2H;EgBpe3H,yBhBqXkC;EChQ9B,eAtCY;Ee5EhB,gBhB8Q+B;EgB7Q/B,gBhBkR+B;EgBjR/B,chBDgB;EgBEhB,sBhBTa;EgBUb,4BAA4B;EAC5B,yBhBPgB;EONd,sBPqOgC;EiBpO9B,wEjB4e4F;AHksClG;;AoBzqDI;EDLJ;ICMM,gBAAgB;EpB6qDpB;AACF;;AmBprDA;EAsBI,6BAA6B;EAC7B,SAAS;AnBkqDb;;AqBlrDE;EACE,clBAc;EkBCd,sBlBRW;EkBSX,qBlBgdsE;EkB/ctE,UAAU;EAKR,gDlBcW;AHmqDjB;;AmBjsDA;EA+BI,chBxBc;EgB0Bd,UAAU;AnBqqDd;;AmBtsDA;EA+BI,chBxBc;EgB0Bd,UAAU;AnBqqDd;;AmBtsDA;EA+BI,chBxBc;EgB0Bd,UAAU;AnBqqDd;;AmBtsDA;EA+BI,chBxBc;EgB0Bd,UAAU;AnBqqDd;;AmBtsDA;EA+BI,chBxBc;EgB0Bd,UAAU;AnBqqDd;;AmBtsDA;EA2CI,yBhBxCc;EgB0Cd,UAAU;AnB8pDd;;AmB1pDA;EAOI,chBhDc;EgBiDd,sBhBxDW;AH+sDf;;AmBlpDA;;EAEE,cAAc;EACd,WAAW;AnBqpDb;;AmB3oDA;EACE,iCAA+D;EAC/D,oCAAkE;EAClE,gBAAgB;EfZd,kBAAW;Eecb,gBhB0M+B;AHo8CjC;;AmB3oDA;EACE,+BAAkE;EAClE,kCAAqE;EfoCjE,kBAtCY;EeIhB,gBhBuI+B;AHugDjC;;AmB3oDA;EACE,gCAAkE;EAClE,mCAAqE;Ef6BjE,mBAtCY;EeWhB,gBhBiI+B;AH6gDjC;;AmBroDA;EACE,cAAc;EACd,WAAW;EACX,qBhB8QmC;EgB7QnC,wBhB6QmC;EgB5QnC,gBAAgB;EAChB,gBhB6K+B;EgB5K/B,chBpGgB;EgBqGhB,6BAA6B;EAC7B,yBAAyB;EACzB,mBAAmC;AnBwoDrC;;AmBlpDA;EAcI,gBAAgB;EAChB,eAAe;AnBwoDnB;;AmB5nDA;EACE,kChBsWqI;EgBrWrI,uBhB+PiC;EC1Q7B,mBAtCY;EemDhB,gBhByF+B;EOhO7B,qBPuO+B;AHgiDnC;;AmB5nDA;EACE,gChB+VqI;EgB9VrI,oBhB4PgC;EC/Q5B,kBAtCY;Ee2DhB,gBhBgF+B;EO/N7B,qBPsO+B;AHyiDnC;;AmB3nDA;EAGI,YAAY;AnB4nDhB;;AmBxnDA;EACE,YAAY;AnB2nDd;;AmBnnDA;EACE,mBhBoV0C;AHkyC5C;;AmBnnDA;EACE,cAAc;EACd,mBhBqU4C;AHizC9C;;AmB9mDA;EACE,oBAAa;EAAb,aAAa;EACb,mBAAe;EAAf,eAAe;EACf,kBAA0C;EAC1C,iBAAyC;AnBinD3C;;AmBrnDA;;EAQI,kBAA0C;EAC1C,iBAAyC;AnBknD7C;;AmBzmDA;EACE,kBAAkB;EAClB,cAAc;EACd,qBhB0S6C;AHk0C/C;;AmBzmDA;EACE,kBAAkB;EAClB,kBhBsS2C;EgBrS3C,qBhBoS6C;AHw0C/C;;AmB/mDA;EAMI,chBxMc;AHqzDlB;;AmBzmDA;EACE,gBAAgB;AnB4mDlB;;AmBzmDA;EACE,2BAAoB;EAApB,oBAAoB;EACpB,sBAAmB;EAAnB,mBAAmB;EACnB,eAAe;EACf,qBhByR4C;AHm1C9C;;AmBhnDA;EAQI,gBAAgB;EAChB,aAAa;EACb,uBhBoR4C;EgBnR5C,cAAc;AnB4mDlB;;AqBvzDE;EACE,aAAa;EACb,WAAW;EACX,mBlBod0C;EC5a1C,cAAW;EiBtCX,clBSa;AHizDjB;;AqBvzDE;EACE,kBAAkB;EAClB,SAAS;EACT,UAAU;EACV,aAAa;EACb,eAAe;EACf,uBlBsyBqC;EkBryBrC,iBAAiB;EjBmFf,mBAtCY;EiB3Cd,gBlBkP6B;EkBjP7B,WlBxCW;EkByCX,wClBLa;EOtCb,sBPqOgC;AHioDpC;;AqBtzDI;EAEE,qBlBZW;EkBeT,oClBgb2F;EkB/a3F,4PHfmI;EGgBnI,4BAA4B;EAC5B,2DlB+a6F;EkB9a7F,gElB6awF;AHy4ChG;;AqB/zDI;EAaI,qBlBvBS;EkBwBT,gDlBxBS;AH80DjB;;AqBp0DI;;;EAmBI,cAAc;ArBuzDtB;;AqBhzDI;EAGI,oClBwZ2F;EkBvZ3F,kFlByZ6F;AHw5CrG;;AqB3yDI;EAEE,qBlBhDW;EkBmDT,sDlBqe0J;EkBpe1J,6gBAAkJ;ArB2yD1J;;AqBjzDI;EAUI,qBlBxDS;EkByDT,gDlBzDS;AHo2DjB;;AqBtzDI;;;EAgBI,cAAc;ArB4yDtB;;AqBryDI;;;EAII,cAAc;ArBuyDtB;;AqBjyDI;EAGI,clBlFS;AHo3DjB;;AqBryDI;;;EAQI,cAAc;ArBmyDtB;;AqB7xDI;EAGI,clBhGS;AH83DjB;;AqBjyDI;EAMM,qBlBnGO;AHk4DjB;;AqBryDI;;;EAYI,cAAc;ArB+xDtB;;AqB3yDI;EAiBM,qBAAkC;ECnJxC,yBDoJ+C;ArB8xDnD;;AqBhzDI;EAwBM,gDlBrHO;AHi5DjB;;AqBpzDI;EA4BM,qBlBzHO;AHq5DjB;;AqBpxDI;EAGI,qBlBpIS;AHy5DjB;;AqBxxDI;;;EAQI,cAAc;ArBsxDtB;;AqB9xDI;EAaM,qBlB9IO;EkB+IP,gDlB/IO;AHo6DjB;;AqBl7DE;EACE,aAAa;EACb,WAAW;EACX,mBlBod0C;EC5a1C,cAAW;EiBtCX,clBMa;AH+6DjB;;AqBl7DE;EACE,kBAAkB;EAClB,SAAS;EACT,UAAU;EACV,aAAa;EACb,eAAe;EACf,uBlBsyBqC;EkBryBrC,iBAAiB;EjBmFf,mBAtCY;EiB3Cd,gBlBkP6B;EkBjP7B,WlBxCW;EkByCX,wClBRa;EOnCb,sBPqOgC;AH4vDpC;;AqBj7DI;EAEE,qBlBfW;EkBkBT,oClBgb2F;EkB/a3F,sSHfmI;EGgBnI,4BAA4B;EAC5B,2DlB+a6F;EkB9a7F,gElB6awF;AHogDhG;;AqB17DI;EAaI,qBlB1BS;EkB2BT,gDlB3BS;AH48DjB;;AqB/7DI;;;EAmBI,cAAc;ArBk7DtB;;AqB36DI;EAGI,oClBwZ2F;EkBvZ3F,kFlByZ6F;AHmhDrG;;AqBt6DI;EAEE,qBlBnDW;EkBsDT,sDlBqe0J;EkBpe1J,ujBAAkJ;ArBs6D1J;;AqB56DI;EAUI,qBlB3DS;EkB4DT,gDlB5DS;AHk+DjB;;AqBj7DI;;;EAgBI,cAAc;ArBu6DtB;;AqBh6DI;;;EAII,cAAc;ArBk6DtB;;AqB55DI;EAGI,clBrFS;AHk/DjB;;AqBh6DI;;;EAQI,cAAc;ArB85DtB;;AqBx5DI;EAGI,clBnGS;AH4/DjB;;AqB55DI;EAMM,qBlBtGO;AHggEjB;;AqBh6DI;;;EAYI,cAAc;ArB05DtB;;AqBt6DI;EAiBM,qBAAkC;ECnJxC,yBDoJ+C;ArBy5DnD;;AqB36DI;EAwBM,gDlBxHO;AH+gEjB;;AqB/6DI;EA4BM,qBlB5HO;AHmhEjB;;AqB/4DI;EAGI,qBlBvIS;AHuhEjB;;AqBn5DI;;;EAQI,cAAc;ArBi5DtB;;AqBz5DI;EAaM,qBlBjJO;EkBkJP,gDlBlJO;AHkiEjB;;AmBz0DA;EACE,oBAAa;EAAb,aAAa;EACb,uBAAmB;EAAnB,mBAAmB;EACnB,sBAAmB;EAAnB,mBAAmB;AnB40DrB;;AmB/0DA;EASI,WAAW;AnB00Df;;AcxhEI;EKqMJ;IAeM,oBAAa;IAAb,aAAa;IACb,sBAAmB;IAAnB,mBAAmB;IACnB,qBAAuB;IAAvB,uBAAuB;IACvB,gBAAgB;EnBy0DpB;EmB31DF;IAuBM,oBAAa;IAAb,aAAa;IACb,kBAAc;IAAd,cAAc;IACd,uBAAmB;IAAnB,mBAAmB;IACnB,sBAAmB;IAAnB,mBAAmB;IACnB,gBAAgB;EnBu0DpB;EmBl2DF;IAgCM,qBAAqB;IACrB,WAAW;IACX,sBAAsB;EnBq0D1B;EmBv2DF;IAuCM,qBAAqB;EnBm0DzB;EmB12DF;;IA4CM,WAAW;EnBk0Df;EmB92DF;IAkDM,oBAAa;IAAb,aAAa;IACb,sBAAmB;IAAnB,mBAAmB;IACnB,qBAAuB;IAAvB,uBAAuB;IACvB,WAAW;IACX,eAAe;EnB+zDnB;EmBr3DF;IAyDM,kBAAkB;IAClB,oBAAc;IAAd,cAAc;IACd,aAAa;IACb,qBhB2LwC;IgB1LxC,cAAc;EnB+zDlB;EmB53DF;IAiEM,sBAAmB;IAAnB,mBAAmB;IACnB,qBAAuB;IAAvB,uBAAuB;EnB8zD3B;EmBh4DF;IAqEM,gBAAgB;EnB8zDpB;AACF;;AuB/nEA;EACE,qBAAqB;EAErB,gBpBkR+B;EoBjR/B,cpBMgB;EoBLhB,kBAAkB;EAClB,sBAAsB;EACtB,yBAAiB;EAAjB,sBAAiB;EAAjB,qBAAiB;EAAjB,iBAAiB;EACjB,6BAA6B;EAC7B,6BAA2C;ECsF3C,yBrB0RkC;EChQ9B,eAtCY;EoBchB,gBrByL+B;EO3R7B,sBPqOgC;EiBpO9B,qIjBqb6I;AH0tDnJ;;AoB1oEI;EGLJ;IHMM,gBAAgB;EpB8oEpB;AACF;;AK/oEE;EkBQE,cpBJc;EoBKd,qBAAqB;AvB2oEzB;;AuB1pEA;EAoBI,UAAU;EACV,gDpBSa;AHioEjB;;AuB/pEA;EA2BI,apB8Y6B;AH0vDjC;;AuBznEA;;EAEE,oBAAoB;AvB4nEtB;;AuBnnEE;ECrDA,WrBCa;EmBDX,yBnB8Ba;EqB5Bf,qBrB4Be;AHgpEjB;;AKxqEE;EmBAE,WrBLW;EmBDX,yBEDoF;EASpF,qBATyH;AxBqrE7H;;AwBzqEE;EAMI,gDAAiF;AxBuqEvF;;AwBlqEE;EAEE,WrBvBW;EqBwBX,yBrBKa;EqBJb,qBrBIa;AHgqEjB;;AwB7pEE;;EAGE,WrBnCW;EqBoCX,yBAtCuK;EA0CvK,qBA1C+M;AxBssEnN;;AwB1pEI;;EAKI,gDAAiF;AxB0pEzF;;AuBrpEE;ECrDA,WrBCa;EmBDX,yBnBOc;EqBLhB,qBrBKgB;AHysElB;;AK1sEE;EmBAE,WrBLW;EmBDX,yBEDoF;EASpF,qBATyH;AxButE7H;;AwB3sEE;EAMI,iDAAiF;AxBysEvF;;AwBpsEE;EAEE,WrBvBW;EqBwBX,yBrBlBc;EqBmBd,qBrBnBc;AHytElB;;AwB/rEE;;EAGE,WrBnCW;EqBoCX,yBAtCuK;EA0CvK,qBA1C+M;AxBwuEnN;;AwB5rEI;;EAKI,iDAAiF;AxB4rEzF;;AuBvrEE;ECrDA,WrBCa;EmBDX,yBnBqCa;EqBnCf,qBrBmCe;AH6sEjB;;AK5uEE;EmBAE,WrBLW;EmBDX,yBEDoF;EASpF,qBATyH;AxByvE7H;;AwB7uEE;EAMI,+CAAiF;AxB2uEvF;;AwBtuEE;EAEE,WrBvBW;EqBwBX,yBrBYa;EqBXb,qBrBWa;AH6tEjB;;AwBjuEE;;EAGE,WrBnCW;EqBoCX,yBAtCuK;EA0CvK,qBA1C+M;AxB0wEnN;;AwB9tEI;;EAKI,+CAAiF;AxB8tEzF;;AuBztEE;ECrDA,WrBCa;EmBDX,yBnBuCa;EqBrCf,qBrBqCe;AH6uEjB;;AK9wEE;EmBAE,WrBLW;EmBDX,yBEDoF;EASpF,qBATyH;AxB2xE7H;;AwB/wEE;EAMI,gDAAiF;AxB6wEvF;;AwBxwEE;EAEE,WrBvBW;EqBwBX,yBrBca;EqBbb,qBrBaa;AH6vEjB;;AwBnwEE;;EAGE,WrBnCW;EqBoCX,yBAtCuK;EA0CvK,qBA1C+M;AxB4yEnN;;AwBhwEI;;EAKI,gDAAiF;AxBgwEzF;;AuB3vEE;ECrDA,crBUgB;EmBVd,yBnBoCa;EqBlCf,qBrBkCe;AHkxEjB;;AKhzEE;EmBAE,crBIc;EmBVd,yBEDoF;EASpF,qBATyH;AxB6zE7H;;AwBjzEE;EAMI,gDAAiF;AxB+yEvF;;AwB1yEE;EAEE,crBdc;EqBed,yBrBWa;EqBVb,qBrBUa;AHkyEjB;;AwBryEE;;EAGE,crB1Bc;EqB2Bd,yBAtCuK;EA0CvK,qBA1C+M;AxB80EnN;;AwBlyEI;;EAKI,gDAAiF;AxBkyEzF;;AuB7xEE;ECrDA,WrBCa;EmBDX,yBnBkCa;EqBhCf,qBrBgCe;AHszEjB;;AKl1EE;EmBAE,WrBLW;EmBDX,yBEDoF;EASpF,qBATyH;AxB+1E7H;;AwBn1EE;EAMI,+CAAiF;AxBi1EvF;;AwB50EE;EAEE,WrBvBW;EqBwBX,yBrBSa;EqBRb,qBrBQa;AHs0EjB;;AwBv0EE;;EAGE,WrBnCW;EqBoCX,yBAtCuK;EA0CvK,qBA1C+M;AxBg3EnN;;AwBp0EI;;EAKI,+CAAiF;AxBo0EzF;;AuB/zEE;ECrDA,crBUgB;EmBVd,yBnBEc;EqBAhB,qBrBAgB;AHw3ElB;;AKp3EE;EmBAE,crBIc;EmBVd,yBEDoF;EASpF,qBATyH;AxBi4E7H;;AwBr3EE;EAMI,iDAAiF;AxBm3EvF;;AwB92EE;EAEE,crBdc;EqBed,yBrBvBc;EqBwBd,qBrBxBc;AHw4ElB;;AwBz2EE;;EAGE,crB1Bc;EqB2Bd,yBAtCuK;EA0CvK,qBA1C+M;AxBk5EnN;;AwBt2EI;;EAKI,iDAAiF;AxBs2EzF;;AuBj2EE;ECrDA,WrBCa;EmBDX,yBnBSc;EqBPhB,qBrBOgB;AHm5ElB;;AKt5EE;EmBAE,WrBLW;EmBDX,yBEDoF;EASpF,qBATyH;AxBm6E7H;;AwBv5EE;EAMI,8CAAiF;AxBq5EvF;;AwBh5EE;EAEE,WrBvBW;EqBwBX,yBrBhBc;EqBiBd,qBrBjBc;AHm6ElB;;AwB34EE;;EAGE,WrBnCW;EqBoCX,yBAtCuK;EA0CvK,qBA1C+M;AxBo7EnN;;AwBx4EI;;EAKI,8CAAiF;AxBw4EzF;;AuB73EE;ECJA,crBzBe;EqB0Bf,qBrB1Be;AH+5EjB;;AKv7EE;EmBqDE,WrB1DW;EqB2DX,yBrB9Ba;EqB+Bb,qBrB/Ba;AHq6EjB;;AwBn4EE;EAEE,+CrBpCa;AHy6EjB;;AwBl4EE;EAEE,crBzCa;EqB0Cb,6BAA6B;AxBo4EjC;;AwBj4EE;;EAGE,WrB7EW;EqB8EX,yBrBjDa;EqBkDb,qBrBlDa;AHq7EjB;;AwBj4EI;;EAKI,+CrBzDS;AH07EjB;;AuB75EE;ECJA,crBhDgB;EqBiDhB,qBrBjDgB;AHs9ElB;;AKv9EE;EmBqDE,WrB1DW;EqB2DX,yBrBrDc;EqBsDd,qBrBtDc;AH49ElB;;AwBn6EE;EAEE,iDrB3Dc;AHg+ElB;;AwBl6EE;EAEE,crBhEc;EqBiEd,6BAA6B;AxBo6EjC;;AwBj6EE;;EAGE,WrB7EW;EqB8EX,yBrBxEc;EqByEd,qBrBzEc;AH4+ElB;;AwBj6EI;;EAKI,iDrBhFU;AHi/ElB;;AuB77EE;ECJA,crBlBe;EqBmBf,qBrBnBe;AHw9EjB;;AKv/EE;EmBqDE,WrB1DW;EqB2DX,yBrBvBa;EqBwBb,qBrBxBa;AH89EjB;;AwBn8EE;EAEE,+CrB7Ba;AHk+EjB;;AwBl8EE;EAEE,crBlCa;EqBmCb,6BAA6B;AxBo8EjC;;AwBj8EE;;EAGE,WrB7EW;EqB8EX,yBrB1Ca;EqB2Cb,qBrB3Ca;AH8+EjB;;AwBj8EI;;EAKI,+CrBlDS;AHm/EjB;;AuB79EE;ECJA,crBhBe;EqBiBf,qBrBjBe;AHs/EjB;;AKvhFE;EmBqDE,WrB1DW;EqB2DX,yBrBrBa;EqBsBb,qBrBtBa;AH4/EjB;;AwBn+EE;EAEE,gDrB3Ba;AHggFjB;;AwBl+EE;EAEE,crBhCa;EqBiCb,6BAA6B;AxBo+EjC;;AwBj+EE;;EAGE,WrB7EW;EqB8EX,yBrBxCa;EqByCb,qBrBzCa;AH4gFjB;;AwBj+EI;;EAKI,gDrBhDS;AHihFjB;;AuB7/EE;ECJA,crBnBe;EqBoBf,qBrBpBe;AHyhFjB;;AKvjFE;EmBqDE,crBjDc;EqBkDd,yBrBxBa;EqByBb,qBrBzBa;AH+hFjB;;AwBngFE;EAEE,+CrB9Ba;AHmiFjB;;AwBlgFE;EAEE,crBnCa;EqBoCb,6BAA6B;AxBogFjC;;AwBjgFE;;EAGE,crBpEc;EqBqEd,yBrB3Ca;EqB4Cb,qBrB5Ca;AH+iFjB;;AwBjgFI;;EAKI,+CrBnDS;AHojFjB;;AuB7hFE;ECJA,crBrBe;EqBsBf,qBrBtBe;AH2jFjB;;AKvlFE;EmBqDE,WrB1DW;EqB2DX,yBrB1Ba;EqB2Bb,qBrB3Ba;AHikFjB;;AwBniFE;EAEE,+CrBhCa;AHqkFjB;;AwBliFE;EAEE,crBrCa;EqBsCb,6BAA6B;AxBoiFjC;;AwBjiFE;;EAGE,WrB7EW;EqB8EX,yBrB7Ca;EqB8Cb,qBrB9Ca;AHilFjB;;AwBjiFI;;EAKI,+CrBrDS;AHslFjB;;AuB7jFE;ECJA,crBrDgB;EqBsDhB,qBrBtDgB;AH2nFlB;;AKvnFE;EmBqDE,crBjDc;EqBkDd,yBrB1Dc;EqB2Dd,qBrB3Dc;AHioFlB;;AwBnkFE;EAEE,iDrBhEc;AHqoFlB;;AwBlkFE;EAEE,crBrEc;EqBsEd,6BAA6B;AxBokFjC;;AwBjkFE;;EAGE,crBpEc;EqBqEd,yBrB7Ec;EqB8Ed,qBrB9Ec;AHipFlB;;AwBjkFI;;EAKI,iDrBrFU;AHspFlB;;AuB7lFE;ECJA,crB9CgB;EqB+ChB,qBrB/CgB;AHopFlB;;AKvpFE;EmBqDE,WrB1DW;EqB2DX,yBrBnDc;EqBoDd,qBrBpDc;AH0pFlB;;AwBnmFE;EAEE,8CrBzDc;AH8pFlB;;AwBlmFE;EAEE,crB9Dc;EqB+Dd,6BAA6B;AxBomFjC;;AwBjmFE;;EAGE,WrB7EW;EqB8EX,yBrBtEc;EqBuEd,qBrBvEc;AH0qFlB;;AwBjmFI;;EAKI,8CrB9EU;AH+qFlB;;AuBlnFA;EACE,gBpB8M+B;EoB7M/B,cpB1Ce;EoB2Cf,qBpB6F4C;AHwhF9C;;AKxrFE;EkBsEE,cpB2F8D;EoB1F9D,0BpB2F+C;AH2hFnD;;AuB7nFA;EAYI,0BpBsF+C;EoBrF/C,gBAAgB;AvBqnFpB;;AuBloFA;EAkBI,cpBjFc;EoBkFd,oBAAoB;AvBonFxB;;AuBzmFA;ECLE,oBrBySgC;EC/Q5B,kBAtCY;EoBchB,gBrB6H+B;EO/N7B,qBPsO+B;AH++EnC;;AuB5mFA;ECTE,uBrBoSiC;EC1Q7B,mBAtCY;EoBchB,gBrB8H+B;EOhO7B,qBPuO+B;AHq/EnC;;AuB1mFA;EACE,cAAc;EACd,WAAW;AvB6mFb;;AuB/mFA;EAMI,kBpBuT+B;AHszEnC;;AuBxmFA;;;EAII,WAAW;AvB0mFf;;AyBhvFA;ELMM,gCjBsP2C;AHw/EjD;;AoBzuFI;EKXJ;ILYM,gBAAgB;EpB6uFpB;AACF;;AyB1vFA;EAII,UAAU;AzB0vFd;;AyBtvFA;EAEI,aAAa;AzBwvFjB;;AyBpvFA;EACE,kBAAkB;EAClB,SAAS;EACT,gBAAgB;ELXZ,6BjBuPwC;AH4gF9C;;AoB9vFI;EKGJ;ILFM,gBAAgB;EpBkwFpB;AACF;;A0B9wFA;;;;EAIE,kBAAkB;A1BixFpB;;A0B9wFA;EACE,mBAAmB;A1BixFrB;;A2B7vFI;EACE,qBAAqB;EACrB,oBxB0N0C;EwBzN1C,uBxBwN0C;EwBvN1C,WAAW;EAhCf,uBAA8B;EAC9B,qCAA4C;EAC5C,gBAAgB;EAChB,oCAA2C;A3BiyF7C;;A2B5uFI;EACE,cAAc;A3B+uFpB;;A0BzxFA;EACE,kBAAkB;EAClB,SAAS;EACT,OAAO;EACP,avBipBsC;EuBhpBtC,aAAa;EACb,WAAW;EACX,gBvButBuC;EuBttBvC,iBAA8B;EAC9B,oBAA4B;EtBsGxB,eAtCY;EsB9DhB,cvBXgB;EuBYhB,gBAAgB;EAChB,gBAAgB;EAChB,sBvBvBa;EuBwBb,4BAA4B;EAC5B,qCvBfa;EOZX,sBPqOgC;AHmlFpC;;A0BpxFI;EACE,WAAW;EACX,OAAO;A1BuxFb;;A0BpxFI;EACE,QAAQ;EACR,UAAU;A1BuxFhB;;Ac3wFI;EYnBA;IACE,WAAW;IACX,OAAO;E1BkyFX;E0B/xFE;IACE,QAAQ;IACR,UAAU;E1BiyFd;AACF;;ActxFI;EYnBA;IACE,WAAW;IACX,OAAO;E1B6yFX;E0B1yFE;IACE,QAAQ;IACR,UAAU;E1B4yFd;AACF;;AcjyFI;EYnBA;IACE,WAAW;IACX,OAAO;E1BwzFX;E0BrzFE;IACE,QAAQ;IACR,UAAU;E1BuzFd;AACF;;Ac5yFI;EYnBA;IACE,WAAW;IACX,OAAO;E1Bm0FX;E0Bh0FE;IACE,QAAQ;IACR,UAAU;E1Bk0Fd;AACF;;A0B5zFA;EAEI,SAAS;EACT,YAAY;EACZ,aAAa;EACb,uBvBorBuC;AH0oE3C;;A2B71FI;EACE,qBAAqB;EACrB,oBxB0N0C;EwBzN1C,uBxBwN0C;EwBvN1C,WAAW;EAzBf,aAAa;EACb,qCAA4C;EAC5C,0BAAiC;EACjC,oCAA2C;A3B03F7C;;A2B50FI;EACE,cAAc;A3B+0FpB;;A0Br0FA;EAEI,MAAM;EACN,WAAW;EACX,UAAU;EACV,aAAa;EACb,qBvBsqBuC;AHiqE3C;;A2Bp3FI;EACE,qBAAqB;EACrB,oBxB0N0C;EwBzN1C,uBxBwN0C;EwBvN1C,WAAW;EAlBf,mCAA0C;EAC1C,eAAe;EACf,sCAA6C;EAC7C,wBAA+B;A3B04FjC;;A2Bn2FI;EACE,cAAc;A3Bs2FpB;;A2Bn4FI;EDmDE,iBAAiB;A1Bo1FvB;;A0B/0FA;EAEI,MAAM;EACN,WAAW;EACX,UAAU;EACV,aAAa;EACb,sBvBqpBuC;AH4rE3C;;A2B/4FI;EACE,qBAAqB;EACrB,oBxB0N0C;EwBzN1C,uBxBwN0C;EwBvN1C,WAAW;A3Bk5FjB;;A2Bt5FI;EAgBI,aAAa;A3B04FrB;;A2Bv4FM;EACE,qBAAqB;EACrB,qBxBuMwC;EwBtMxC,uBxBqMwC;EwBpMxC,WAAW;EA9BjB,mCAA0C;EAC1C,yBAAgC;EAChC,sCAA6C;A3By6F/C;;A2Bx4FI;EACE,cAAc;A3B24FpB;;A2Br5FM;EDiDA,iBAAiB;A1Bw2FvB;;A0Bj2FA;EAKI,WAAW;EACX,YAAY;A1Bg2FhB;;A0B31FA;EE9GE,SAAS;EACT,gBAAmB;EACnB,gBAAgB;EAChB,6BzBCgB;AH48FlB;;A0B31FA;EACE,cAAc;EACd,WAAW;EACX,uBvByoBwC;EuBxoBxC,WAAW;EACX,gBvB4J+B;EuB3J/B,cvBhHgB;EuBiHhB,mBAAmB;EACnB,mBAAmB;EACnB,6BAA6B;EAC7B,SAAS;A1B81FX;;AKl9FE;EqBmIE,cvB0mBqD;EuBzmBrD,qBAAqB;EJ9IrB,yBnBEc;AHg+FlB;;A0B92FA;EAgCI,WvBnJW;EuBoJX,qBAAqB;EJrJrB,yBnB8Ba;AH08FjB;;A0Bp3FA;EAuCI,cvBpJc;EuBqJd,oBAAoB;EACpB,6BAA6B;A1Bi1FjC;;A0Bz0FA;EACE,cAAc;A1B40FhB;;A0Bx0FA;EACE,cAAc;EACd,sBvBolBwC;EuBnlBxC,gBAAgB;EtBpDZ,mBAtCY;EsB4FhB,cvBxKgB;EuByKhB,mBAAmB;A1B20FrB;;A0Bv0FA;EACE,cAAc;EACd,uBvB0kBwC;EuBzkBxC,cvB7KgB;AHu/FlB;;A6BpgGA;;EAEE,kBAAkB;EAClB,2BAAoB;EAApB,oBAAoB;EACpB,sBAAsB;A7BugGxB;;A6B3gGA;;EAOI,kBAAkB;EAClB,kBAAc;EAAd,cAAc;A7BygGlB;;AKxgGE;;EwBII,UAAU;A7BygGhB;;A6BthGA;;;;EAkBM,UAAU;A7B2gGhB;;A6BrgGA;EACE,oBAAa;EAAb,aAAa;EACb,mBAAe;EAAf,eAAe;EACf,oBAA2B;EAA3B,2BAA2B;A7BwgG7B;;A6B3gGA;EAMI,WAAW;A7BygGf;;A6BrgGA;;EAII,iB1B8L6B;AHw0FjC;;A6B1gGA;;EnBhBI,0BmB0B8B;EnBzB9B,6BmByB8B;A7BsgGlC;;A6BhhGA;;EnBFI,yBmBiB6B;EnBhB7B,4BmBgB6B;A7BugGjC;;A6Bv/FA;EACE,wBAAmC;EACnC,uBAAkC;A7B0/FpC;;A6B5/FA;;;EAOI,cAAc;A7B2/FlB;;A6Bx/FE;EACE,eAAe;A7B2/FnB;;A6Bv/FA;EACE,uBAAsC;EACtC,sBAAqC;A7B0/FvC;;A6Bv/FA;EACE,sBAAsC;EACtC,qBAAqC;A7B0/FvC;;A6Bt+FA;EACE,0BAAsB;EAAtB,sBAAsB;EACtB,qBAAuB;EAAvB,uBAAuB;EACvB,qBAAuB;EAAvB,uBAAuB;A7By+FzB;;A6B5+FA;;EAOI,WAAW;A7B0+Ff;;A6Bj/FA;;EAYI,gB1B6G6B;AH63FjC;;A6Bt/FA;;EnBlFI,6BmBoG+B;EnBnG/B,4BmBmG+B;A7B0+FnC;;A6B5/FA;;EnBhGI,yBmBuH4B;EnBtH5B,0BmBsH4B;A7B2+FhC;;A6B19FA;;EAGI,gBAAgB;A7B49FpB;;A6B/9FA;;;;EAOM,kBAAkB;EAClB,sBAAsB;EACtB,oBAAoB;A7B+9F1B;;A8BxnGA;EACE,kBAAkB;EAClB,oBAAa;EAAb,aAAa;EACb,mBAAe;EAAf,eAAe;EACf,uBAAoB;EAApB,oBAAoB;EACpB,WAAW;A9B2nGb;;A8BhoGA;;;;EAWI,kBAAkB;EAClB,kBAAc;EAAd,cAAc;EAGd,SAAS;EACT,gBAAgB;A9B0nGpB;;A8B1oGA;;;;;;;;;;;;EAqBM,iB3B4M2B;AHw7FjC;;A8BzpGA;;;EA6BI,UAAU;A9BkoGd;;A8B/pGA;EAkCI,UAAU;A9BioGd;;A8BnqGA;;EpBeI,0BoBwBmD;EpBvBnD,6BoBuBmD;A9BkoGvD;;A8BzqGA;;EpB6BI,yBoBWmD;EpBVnD,4BoBUmD;A9BuoGvD;;A8B/qGA;EA8CI,oBAAa;EAAb,aAAa;EACb,sBAAmB;EAAnB,mBAAmB;A9BqoGvB;;A8BprGA;;EpBeI,0BoBmC6E;EpBlC7E,6BoBkC6E;A9BwoGjF;;A8B1rGA;EpB6BI,yBoBsBsE;EpBrBtE,4BoBqBsE;A9B4oG1E;;A8BjoGA;;EAEE,oBAAa;EAAb,aAAa;A9BooGf;;A8BtoGA;;EAQI,kBAAkB;EAClB,UAAU;A9BmoGd;;A8B5oGA;;EAYM,UAAU;A9BqoGhB;;A8BjpGA;;;;;;;;EAoBI,iB3B+I6B;AHy/FjC;;A8BpoGA;EAAuB,kB3B2IU;AH6/FjC;;A8BvoGA;EAAsB,iB3B0IW;AHigGjC;;A8BnoGA;EACE,oBAAa;EAAb,aAAa;EACb,sBAAmB;EAAnB,mBAAmB;EACnB,yB3BuRkC;E2BtRlC,gBAAgB;E1BsBZ,eAtCY;E0BkBhB,gB3BgL+B;E2B/K/B,gB3BoL+B;E2BnL/B,c3B/FgB;E2BgGhB,kBAAkB;EAClB,mBAAmB;EACnB,yB3BvGgB;E2BwGhB,yB3BtGgB;EONd,sBPqOgC;AH8gGpC;;A8BnpGA;;EAkBI,aAAa;A9BsoGjB;;A8B5nGA;;EAEE,gC3B6WqI;AHkxFvI;;A8B5nGA;;;;;;EAME,oB3BkQgC;EC/Q5B,kBAtCY;E0BqDhB,gB3BsF+B;EO/N7B,qBPsO+B;AHmiGnC;;A8B5nGA;;EAEE,kC3B2VqI;AHoyFvI;;A8B5nGA;;;;;;EAME,uB3B4OiC;EC1Q7B,mBAtCY;E0BsEhB,gB3BsE+B;EOhO7B,qBPuO+B;AHmjGnC;;A8B5nGA;;EAEE,sBAA0E;A9B+nG5E;;A8BpnGA;;;;;;EpB3JI,0BoBiK4B;EpBhK5B,6BoBgK4B;A9BwnGhC;;A8BrnGA;;;;;;EpBtJI,yBoB4J2B;EpB3J3B,4BoB2J2B;A9BynG/B;;A+B/yGA;EACE,kBAAkB;EAClB,cAAc;EACd,kBAA+C;EAC/C,oBAAqE;A/BkzGvE;;A+B/yGA;EACE,2BAAoB;EAApB,oBAAoB;EACpB,kB5Bqf0C;AH6zF5C;;A+B/yGA;EACE,kBAAkB;EAClB,WAAW;EACX,UAAU;A/BkzGZ;;A+BrzGA;EAMI,W5BpBW;E4BqBX,qB5BQa;EmB9Bb,yBnB8Ba;AH4yGjB;;A+B3zGA;EAiBM,gD5BFW;AHgzGjB;;A+B/zGA;EAsBI,qB5BqbsE;AHw3F1E;;A+Bn0GA;EA0BI,W5BxCW;E4ByCX,yB5B8e8E;E4B7e9E,qB5B6e8E;AHg0FlF;;A+Bz0GA;EAkCM,c5B1CY;AHq1GlB;;A+B70GA;EAqCQ,yB5BjDU;AH61GlB;;A+BlyGA;EACE,kBAAkB;EAClB,gBAAgB;EAChB,mBAAmB;A/BqyGrB;;A+BxyGA;EAOI,kBAAkB;EAClB,YAA+E;EAC/E,aAA+D;EAC/D,cAAc;EACd,W5B0bwC;E4BzbxC,Y5BybwC;E4BxbxC,oBAAoB;EACpB,WAAW;EACX,sB5B5EW;E4B6EX,yB5BmJ6B;AHkpGjC;;A+BrzGA;EAsBI,kBAAkB;EAClB,YAA+E;EAC/E,aAA+D;EAC/D,cAAc;EACd,W5B2awC;E4B1axC,Y5B0awC;E4BzaxC,WAAW;EACX,mCAAgE;A/BmyGpE;;A+B1xGA;ErBrGI,sBPqOgC;AH8pGpC;;A+B9xGA;EAOM,6MbrEqI;AlBg2G3I;;A+BlyGA;EAaM,qB5BnFW;EmB9Bb,yBnB8Ba;AH62GjB;;A+BvyGA;EAkBM,0JbhFqI;AlBy2G3I;;A+B3yGA;EAwBM,wC5B9FW;AHq3GjB;;A+B/yGA;EA2BM,wC5BjGW;AHy3GjB;;A+B/wGA;EAGI,kB5B0Z+C;AHs3FnD;;A+BnxGA;EAQM,uJb1GqI;AlBy3G3I;;A+BvxGA;EAcM,wC5BxHW;AHq4GjB;;A+BnwGA;EACE,qBAA2D;A/BswG7D;;A+BvwGA;EAKM,cAAqD;EACrD,c5BkY+E;E4BjY/E,mBAAmB;EAEnB,qB5BgY4E;AHq4FlF;;A+B9wGA;EAaM,wBAA0I;EAC1I,0BAA+G;EAC/G,uB5B2XiI;E4B1XjI,wB5B0XiI;E4BzXjI,yB5B3KY;E4B6KZ,qB5BsX4E;EiBziB5E,iJjB8f+H;EiB9f/H,yIjB8f+H;EiB9f/H,8KjB8f+H;AH07FrI;;AoBn7GI;EW2JJ;IX1JM,gBAAgB;EpBu7GpB;AACF;;A+B9xGA;EA0BM,sB5BzLS;E4B0LT,sCAA4E;EAA5E,8BAA4E;A/BwwGlF;;A+BnyGA;EAiCM,wC5BnKW;AHy6GjB;;A+B1vGA;EACE,qBAAqB;EACrB,WAAW;EACX,mC5BwR2H;E4BvR3H,0C5BwKkC;EChQ9B,eAtCY;E2BiIhB,gB5BiE+B;E4BhE/B,gB5BqE+B;E4BpE/B,c5B9MgB;E4B+MhB,sBAAsB;EACtB,6M5BmWmI;E4BlWnI,sB5BxNa;E4ByNb,yB5BrNgB;EONd,sBPqOgC;E4BPlC,wBAAgB;EAAhB,qBAAgB;EAAhB,gBAAgB;A/B2vGlB;;A+B3wGA;EAmBI,qB5B0PsE;E4BzPtE,UAAU;EAIR,gD5BvMW;AHg8GjB;;A+BjxGA;EAiCM,c5BtOY;E4BuOZ,sB5B9OS;AHk+Gf;;A+BtxGA;EAwCI,YAAY;EACZ,sB5BmIgC;E4BlIhC,sBAAsB;A/BkvG1B;;A+B5xGA;EA8CI,c5BpPc;E4BqPd,yB5BzPc;AH2+GlB;;A+BjyGA;EAoDI,aAAa;A/BivGjB;;A+B7uGA;EACE,kC5BmOqI;E4BlOrI,oB5B2HkC;E4B1HlC,uB5B0HkC;E4BzHlC,oB5B0HiC;EC1Q7B,mBAtCY;AJu6GlB;;A+B7uGA;EACE,gC5B4NqI;E4B3NrI,mB5BwHiC;E4BvHjC,sB5BuHiC;E4BtHjC,kB5BuHgC;EC/Q5B,kBAtCY;AJ+6GlB;;A+BxuGA;EACE,kBAAkB;EAClB,qBAAqB;EACrB,WAAW;EACX,mC5B0M2H;E4BzM3H,gBAAgB;A/B2uGlB;;A+BxuGA;EACE,kBAAkB;EAClB,UAAU;EACV,WAAW;EACX,mC5BkM2H;E4BjM3H,SAAS;EACT,UAAU;A/B2uGZ;;A+BjvGA;EASI,qB5B+KsE;E4B9KtE,gD5B9Qa;AH0/GjB;;A+BtvGA;EAcI,yB5B7Sc;AHyhHlB;;A+B1vGA;EAmBM,iB5BqUQ;AHs6Fd;;A+B9vGA;EAwBI,0BAA0B;A/B0uG9B;;A+BtuGA;EACE,kBAAkB;EAClB,MAAM;EACN,QAAQ;EACR,OAAO;EACP,UAAU;EACV,mC5BoK2H;E4BnK3H,yB5BoDkC;E4BlDlC,gB5BlD+B;E4BmD/B,gB5B9C+B;E4B+C/B,c5BjUgB;E4BkUhB,sB5BzUa;E4B0Ub,yB5BtUgB;EONd,sBPqOgC;AHg1GpC;;A+BtvGA;EAkBI,kBAAkB;EAClB,MAAM;EACN,QAAQ;EACR,SAAS;EACT,UAAU;EACV,cAAc;EACd,6B5B8I+F;E4B7I/F,yB5BkCgC;E4BjChC,gB5B9D6B;E4B+D7B,c5BjVc;E4BkVd,iBAAiB;ET1VjB,yBnBGc;E4ByVd,oBAAoB;ErB7VpB,kCqB8VgF;A/BwuGpF;;A+B9tGA;EACE,WAAW;EACX,2BAA+F;EAC/F,UAAU;EACV,6BAA6B;EAC7B,wBAAgB;EAAhB,qBAAgB;EAAhB,gBAAgB;A/BiuGlB;;A+BtuGA;EAQI,aAAa;A/BkuGjB;;A+B1uGA;EAY8B,gE5BrVb;AHujHjB;;A+B9uGA;EAa8B,gE5BtVb;AH2jHjB;;A+BlvGA;EAc8B,gE5BvVb;AH+jHjB;;A+BtvGA;EAkBI,SAAS;A/BwuGb;;A+B1vGA;EAsBI,W5B8N6C;E4B7N7C,Y5B6N6C;E4B5N7C,oBAAyE;ET/XzE,yBnB8Ba;E4BmWb,S5B6N0C;EO/lB1C,mBPgmB6C;EiB/lB3C,4GjB8f+H;E4BzHjI,wBAAgB;EAAhB,gBAAgB;A/BuuGpB;;AoBvmHI;EWkWJ;IXjWM,gBAAgB;EpB2mHpB;AACF;;A+B3wGA;ETvWI,yBnBmmB2E;AHmhG/E;;A+B/wGA;EAsCI,W5BuMoC;E4BtMpC,c5BuMqC;E4BtMrC,kBAAkB;EAClB,e5BsMuC;E4BrMvC,yB5B7Yc;E4B8Yd,yBAAyB;ErBnZzB,mBPylBoC;AHwiGxC;;A+BzxGA;EAiDI,W5BmM6C;E4BlM7C,Y5BkM6C;EmB3lB7C,yBnB8Ba;E4B6Xb,S5BmM0C;EO/lB1C,mBPgmB6C;EiB/lB3C,4GjB8f+H;E4B/FjI,qBAAgB;EAAhB,gBAAgB;A/B2uGpB;;AoBroHI;EWkWJ;IXjWM,gBAAgB;EpByoHpB;AACF;;A+BzyGA;ETvWI,yBnBmmB2E;AHijG/E;;A+B7yGA;EAgEI,W5B6KoC;E4B5KpC,c5B6KqC;E4B5KrC,kBAAkB;EAClB,e5B4KuC;E4B3KvC,yB5Bvac;E4Bwad,yBAAyB;ErB7azB,mBPylBoC;AHskGxC;;A+BvzGA;EA2EI,W5ByK6C;E4BxK7C,Y5BwK6C;E4BvK7C,aAAa;EACb,oB5BvD+B;E4BwD/B,mB5BxD+B;EmB9X/B,yBnB8Ba;E4B0Zb,S5BsK0C;EO/lB1C,mBPgmB6C;EiB/lB3C,4GjB8f+H;E4BlEjI,gBAAgB;A/B+uGpB;;AoBtqHI;EWkWJ;IXjWM,gBAAgB;EpB0qHpB;AACF;;A+B10GA;ETvWI,yBnBmmB2E;AHklG/E;;A+B90GA;EA6FI,W5BgJoC;E4B/IpC,c5BgJqC;E4B/IrC,kBAAkB;EAClB,e5B+IuC;E4B9IvC,6BAA6B;EAC7B,yBAAyB;EACzB,oBAA4C;A/BqvGhD;;A+Bx1GA;EAwGI,yB5B3cc;EOLd,mBPylBoC;AH4mGxC;;A+B71GA;EA6GI,kBAAkB;EAClB,yB5Bjdc;EOLd,mBPylBoC;AHknGxC;;A+Bn2GA;EAoHM,yB5BrdY;AHwsHlB;;A+Bv2GA;EAwHM,eAAe;A/BmvGrB;;A+B32GA;EA4HM,yB5B7dY;AHgtHlB;;A+B/2GA;EAgIM,eAAe;A/BmvGrB;;A+Bn3GA;EAoIM,yB5BreY;AHwtHlB;;A+B9uGA;;;EXhfM,4GjB8f+H;AHsuGrI;;AoB/tHI;EW2eJ;;;IX1eM,gBAAgB;EpBquHpB;AACF;;AgC7uHA;EACE,oBAAa;EAAb,aAAa;EACb,mBAAe;EAAf,eAAe;EACf,eAAe;EACf,gBAAgB;EAChB,gBAAgB;AhCgvHlB;;AgC7uHA;EACE,cAAc;EACd,oB7BkqBsC;AH8kGxC;;AK/uHE;E2BEE,qBAAqB;AhCivHzB;;AgCtvHA;EAUI,c7BVc;E6BWd,oBAAoB;EACpB,eAAe;AhCgvHnB;;AgCxuHA;EACE,gC7BxBgB;AHmwHlB;;AgC5uHA;EAII,mB7BkM6B;AH0iHjC;;AgChvHA;EAQI,6BAAgD;EtB3BhD,+BP4NgC;EO3NhC,gCP2NgC;AH6iHpC;;AKvwHE;E2B6BI,qC7BnCY;AHixHlB;;AgC1vHA;EAgBM,c7BpCY;E6BqCZ,6BAA6B;EAC7B,yBAAyB;AhC8uH/B;;AgChwHA;;EAwBI,c7B3Cc;E6B4Cd,sB7BnDW;E6BoDX,kC7BpDW;AHiyHf;;AgCvwHA;EA+BI,gB7BuK6B;EOzN7B,yBsBoD4B;EtBnD5B,0BsBmD4B;AhC4uHhC;;AgCnuHA;EtBtEI,sBPqOgC;AHwkHpC;;AgCvuHA;;EAOI,W7B3EW;E6B4EX,yB7B/Ca;AHoxHjB;;AgC5tHA;EAEI,kBAAc;EAAd,cAAc;EACd,kBAAkB;AhC8tHtB;;AgC1tHA;EAEI,0BAAa;EAAb,aAAa;EACb,oBAAY;EAAZ,YAAY;EACZ,kBAAkB;AhC4tHtB;;AgCntHA;EAEI,aAAa;AhCqtHjB;;AgCvtHA;EAKI,cAAc;AhCstHlB;;AiC1zHA;EACE,kBAAkB;EAClB,oBAAa;EAAb,aAAa;EACb,mBAAe;EAAf,eAAe;EACf,sBAAmB;EAAnB,mBAAmB;EACnB,sBAA8B;EAA9B,8BAA8B;EAC9B,oB9B0GW;AHmtHb;;AiCn0HA;;EAYI,oBAAa;EAAb,aAAa;EACb,mBAAe;EAAf,eAAe;EACf,sBAAmB;EAAnB,mBAAmB;EACnB,sBAA8B;EAA9B,8BAA8B;AjC4zHlC;;AiCnzHA;EACE,qBAAqB;EACrB,sB9BoqB+E;E8BnqB/E,yB9BmqB+E;E8BlqB/E,kB9BoFW;ECFP,kBAtCY;E6B1ChB,oBAAoB;EACpB,mBAAmB;AjCszHrB;;AKt1HE;E4BmCE,qBAAqB;AjCuzHzB;;AiC9yHA;EACE,oBAAa;EAAb,aAAa;EACb,0BAAsB;EAAtB,sBAAsB;EACtB,eAAe;EACf,gBAAgB;EAChB,gBAAgB;AjCizHlB;;AiCtzHA;EAQI,gBAAgB;EAChB,eAAe;AjCkzHnB;;AiC3zHA;EAaI,gBAAgB;EAChB,WAAW;AjCkzHf;;AiCzyHA;EACE,qBAAqB;EACrB,mB9B2lBuC;E8B1lBvC,sB9B0lBuC;AHktGzC;;AiChyHA;EACE,6BAAgB;EAAhB,gBAAgB;EAChB,oBAAY;EAAZ,YAAY;EAGZ,sBAAmB;EAAnB,mBAAmB;AjCiyHrB;;AiC7xHA;EACE,wB9BsmBwC;ECnlBpC,kBAtCY;E6BqBhB,cAAc;EACd,6BAA6B;EAC7B,6BAAuC;EvB3GrC,sBPqOgC;AHuqHpC;;AKj4HE;E4BoGE,qBAAqB;AjCiyHzB;;AiC3xHA;EACE,qBAAqB;EACrB,YAAY;EACZ,aAAa;EACb,sBAAsB;EACtB,WAAW;EACX,mCAAmC;EACnC,0BAA0B;AjC8xH5B;;Act1HI;EmBkEC;;IAIK,gBAAgB;IAChB,eAAe;EjCsxHvB;AACF;;Ac32HI;EmB+EA;IAUI,yBAAqB;IAArB,qBAAqB;IACrB,oBAA2B;IAA3B,2BAA2B;EjCuxHjC;EiClyHG;IAcK,uBAAmB;IAAnB,mBAAmB;EjCuxH3B;EiCryHG;IAiBO,kBAAkB;EjCuxH5B;EiCxyHG;IAqBO,qB9ByiB6B;I8BxiB7B,oB9BwiB6B;EH8uGvC;EiC5yHG;;IA6BK,qBAAiB;IAAjB,iBAAiB;EjCmxHzB;EiChzHG;IAiCK,+BAAwB;IAAxB,wBAAwB;IAGxB,6BAAgB;IAAhB,gBAAgB;EjCgxHxB;EiCpzHG;IAwCK,aAAa;EjC+wHrB;AACF;;Ac13HI;EmBkEC;;IAIK,gBAAgB;IAChB,eAAe;EjC0zHvB;AACF;;Ac/4HI;EmB+EA;IAUI,yBAAqB;IAArB,qBAAqB;IACrB,oBAA2B;IAA3B,2BAA2B;EjC2zHjC;EiCt0HG;IAcK,uBAAmB;IAAnB,mBAAmB;EjC2zH3B;EiCz0HG;IAiBO,kBAAkB;EjC2zH5B;EiC50HG;IAqBO,qB9ByiB6B;I8BxiB7B,oB9BwiB6B;EHkxGvC;EiCh1HG;;IA6BK,qBAAiB;IAAjB,iBAAiB;EjCuzHzB;EiCp1HG;IAiCK,+BAAwB;IAAxB,wBAAwB;IAGxB,6BAAgB;IAAhB,gBAAgB;EjCozHxB;EiCx1HG;IAwCK,aAAa;EjCmzHrB;AACF;;Ac95HI;EmBkEC;;IAIK,gBAAgB;IAChB,eAAe;EjC81HvB;AACF;;Acn7HI;EmB+EA;IAUI,yBAAqB;IAArB,qBAAqB;IACrB,oBAA2B;IAA3B,2BAA2B;EjC+1HjC;EiC12HG;IAcK,uBAAmB;IAAnB,mBAAmB;EjC+1H3B;EiC72HG;IAiBO,kBAAkB;EjC+1H5B;EiCh3HG;IAqBO,qB9ByiB6B;I8BxiB7B,oB9BwiB6B;EHszGvC;EiCp3HG;;IA6BK,qBAAiB;IAAjB,iBAAiB;EjC21HzB;EiCx3HG;IAiCK,+BAAwB;IAAxB,wBAAwB;IAGxB,6BAAgB;IAAhB,gBAAgB;EjCw1HxB;EiC53HG;IAwCK,aAAa;EjCu1HrB;AACF;;Acl8HI;EmBkEC;;IAIK,gBAAgB;IAChB,eAAe;EjCk4HvB;AACF;;Acv9HI;EmB+EA;IAUI,yBAAqB;IAArB,qBAAqB;IACrB,oBAA2B;IAA3B,2BAA2B;EjCm4HjC;EiC94HG;IAcK,uBAAmB;IAAnB,mBAAmB;EjCm4H3B;EiCj5HG;IAiBO,kBAAkB;EjCm4H5B;EiCp5HG;IAqBO,qB9ByiB6B;I8BxiB7B,oB9BwiB6B;EH01GvC;EiCx5HG;;IA6BK,qBAAiB;IAAjB,iBAAiB;EjC+3HzB;EiC55HG;IAiCK,+BAAwB;IAAxB,wBAAwB;IAGxB,6BAAgB;IAAhB,gBAAgB;EjC43HxB;EiCh6HG;IAwCK,aAAa;EjC23HrB;AACF;;AiCz6HA;EAeQ,yBAAqB;EAArB,qBAAqB;EACrB,oBAA2B;EAA3B,2BAA2B;AjC85HnC;;AiC96HA;;EASU,gBAAgB;EAChB,eAAe;AjC06HzB;;AiCp7HA;EAmBU,uBAAmB;EAAnB,mBAAmB;AjCq6H7B;;AiCx7HA;EAsBY,kBAAkB;AjCs6H9B;;AiC57HA;EA0BY,qB9ByiB6B;E8BxiB7B,oB9BwiB6B;AH83GzC;;AiCj8HA;;EAkCU,qBAAiB;EAAjB,iBAAiB;AjCo6H3B;;AiCt8HA;EAsCU,+BAAwB;EAAxB,wBAAwB;EAGxB,6BAAgB;EAAhB,gBAAgB;AjCk6H1B;;AiC38HA;EA6CU,aAAa;AjCk6HvB;;AiCr5HA;EAEI,yB9BjLW;AHwkIf;;AKzkIE;E4BqLI,yB9BpLS;AH4kIf;;AiC75HA;EAWM,yB9B1LS;AHglIf;;AKjlIE;E4B8LM,yB9B7LO;AHolIf;;AiCr6HA;EAkBQ,yB9BjMO;AHwlIf;;AiCz6HA;;;;EA0BM,yB9BzMS;AH+lIf;;AiCh7HA;EA+BI,yB9B9MW;E8B+MX,gC9B/MW;AHomIf;;AiCr7HA;EAoCI,wP9B6fsR;AHw5G1R;;AiCz7HA;EAwCI,yB9BvNW;AH4mIf;;AiC77HA;EA0CM,yB9BzNS;AHgnIf;;AKjnIE;E4B6NM,yB9B5NO;AHonIf;;AiCj5HA;EAEI,W9B/OW;AHkoIf;;AKznIE;E4ByOI,W9BlPS;AHsoIf;;AiCz5HA;EAWM,+B9BxPS;AH0oIf;;AKjoIE;E4BkPM,gC9B3PO;AH8oIf;;AiCj6HA;EAkBQ,gC9B/PO;AHkpIf;;AiCr6HA;;;;EA0BM,W9BvQS;AHypIf;;AiC56HA;EA+BI,+B9B5QW;E8B6QX,sC9B7QW;AH8pIf;;AiCj7HA;EAoCI,8P9BkcqR;AH+8GzR;;AiCr7HA;EAwCI,+B9BrRW;AHsqIf;;AiCz7HA;EA0CM,W9BvRS;AH0qIf;;AKjqIE;E4BiRM,W9B1RO;AH8qIf;;AkCjrIA;EACE,kBAAkB;EAClB,oBAAa;EAAb,aAAa;EACb,0BAAsB;EAAtB,sBAAsB;EACtB,YAAY;EACZ,qBAAqB;EACrB,sB/BHa;E+BIb,2BAA2B;EAC3B,sC/BKa;EOZX,sBPqOgC;AHu9HpC;;AkC7rIA;EAYI,eAAe;EACf,cAAc;AlCqrIlB;;AkClsIA;ExBUI,+BP4NgC;EO3NhC,gCP2NgC;AHi+HpC;;AkCvsIA;ExBwBI,mCP8MgC;EO7MhC,kCP6MgC;AHs+HpC;;AkC/qIA;EAGE,kBAAc;EAAd,cAAc;EACd,gB/B+wByC;AHi6G3C;;AkC5qIA;EACE,sB/BywBwC;AHs6G1C;;AkC5qIA;EACE,qBAA+B;EAC/B,gBAAgB;AlC+qIlB;;AkC5qIA;EACE,gBAAgB;AlC+qIlB;;AKttIE;E6B4CE,qBAAqB;AlC8qIzB;;AkChrIA;EAMI,oB/BwvBuC;AHs7G3C;;AkCtqIA;EACE,wB/B+uByC;E+B9uBzC,gBAAgB;EAEhB,qC/BvDa;E+BwDb,6C/BxDa;AHguIf;;AkC7qIA;ExB/DI,0DwBuE8E;AlCyqIlF;;AkCjrIA;EAaM,aAAa;AlCwqInB;;AkCnqIA;EACE,wB/B6tByC;E+B5tBzC,qC/BvEa;E+BwEb,0C/BxEa;AH8uIf;;AkCzqIA;ExBjFI,0DPmzBoF;AH28GxF;;AkC9pIA;EACE,uBAAiC;EACjC,uB/B4sBwC;E+B3sBxC,sBAAgC;EAChC,gBAAgB;AlCiqIlB;;AkC9pIA;EACE,uBAAiC;EACjC,sBAAgC;AlCiqIlC;;AkC7pIA;EACE,kBAAkB;EAClB,MAAM;EACN,QAAQ;EACR,SAAS;EACT,OAAO;EACP,gB/BssByC;AH09G3C;;AkC7pIA;EACE,WAAW;ExBvHT,kCPmzBoF;AHq+GxF;;AkC5pIA;EACE,WAAW;ExBpHT,2CP0yBoF;EOzyBpF,4CPyyBoF;AH2+GxF;;AkC7pIA;EACE,WAAW;ExB3GT,+CP4xBoF;EO3xBpF,8CP2xBoF;AHi/GxF;;AkC3pIA;EACE,oBAAa;EAAb,aAAa;EACb,0BAAsB;EAAtB,sBAAsB;AlC8pIxB;;AkChqIA;EAKI,mB/B6qBsD;AHk/G1D;;ActvII;EoBkFJ;IASI,uBAAmB;IAAnB,mBAAmB;IACnB,mB/BwqBsD;I+BvqBtD,kB/BuqBsD;EHy/GxD;EkC3qIF;IAcM,oBAAa;IAAb,aAAa;IAEb,gBAAY;IAAZ,YAAY;IACZ,0BAAsB;IAAtB,sBAAsB;IACtB,kB/BgqBoD;I+B/pBpD,gBAAgB;IAChB,iB/B8pBoD;EHigHxD;AACF;;AkCtpIA;EACE,oBAAa;EAAb,aAAa;EACb,0BAAsB;EAAtB,sBAAsB;AlCypIxB;;AkC3pIA;EAOI,mB/B6oBsD;AH2gH1D;;Ac/wII;EoBgHJ;IAWI,uBAAmB;IAAnB,mBAAmB;ElCypIrB;EkCpqIF;IAgBM,gBAAY;IAAZ,YAAY;IACZ,gBAAgB;ElCupIpB;EkCxqIF;IAoBQ,cAAc;IACd,cAAc;ElCupIpB;EkC5qIF;IxBvJI,0BwBkLoC;IxBjLpC,6BwBiLoC;ElCqpItC;EkChrIF;;IAgCY,0BAA0B;ElCopIpC;EkCprIF;;IAqCY,6BAA6B;ElCmpIvC;EkCxrIF;IxBzII,yBwBmLmC;IxBlLnC,4BwBkLmC;ElCkpIrC;EkC5rIF;;IA+CY,yBAAyB;ElCipInC;EkChsIF;;IAoDY,4BAA4B;ElCgpItC;AACF;;AkCpoIA;EAEI,sB/BokBsC;AHkkH1C;;AczzII;EoBiLJ;IAMI,uB/BglBiC;I+BhlBjC,oB/BglBiC;I+BhlBjC,e/BglBiC;I+B/kBjC,2B/BglBuC;I+BhlBvC,wB/BglBuC;I+BhlBvC,mB/BglBuC;I+B/kBvC,UAAU;IACV,SAAS;ElCuoIX;EkChpIF;IAYM,qBAAqB;IACrB,WAAW;ElCuoIf;AACF;;AkC9nIA;EAEI,gBAAgB;AlCgoIpB;;AkCloIA;ExB/PI,gBwBqQ4B;AlCgoIhC;;AkCtoIA;EAUQ,gBAAgB;ExBzQpB,gBwB0Q4B;AlCgoIhC;;AkC3oIA;EAgBM,gBAAgB;ExBxPlB,6BwByPiC;ExBxPjC,4BwBwPiC;AlCgoIrC;;AkCjpIA;ExBtPI,yBwB2Q8B;ExB1Q9B,0BwB0Q8B;AlCioIlC;;AkCtpIA;EAyBM,mB/BtD2B;AHurIjC;;AmC95IA;EACE,oBAAa;EAAb,aAAa;EACb,mBAAe;EAAf,eAAe;EACf,qBhC2gCsC;EgC1gCtC,mBhC6gCsC;EgC5gCtC,gBAAgB;EAChB,yBhCGgB;EOJd,sBPqOgC;AH8rIpC;;AmC95IA;EAGI,oBhCkgCqC;AH65GzC;;AmCl6IA;EAMM,qBAAqB;EACrB,qBhC8/BmC;EgC7/BnC,chCLY;EgCMZ,YhCmgCuC;AH65G7C;;AmCz6IA;EAoBI,0BAA0B;AnCy5I9B;;AmC76IA;EAwBI,qBAAqB;AnCy5IzB;;AmCj7IA;EA4BI,chCzBc;AHk7IlB;;AoC/7IA;EACE,oBAAa;EAAb,aAAa;E7BGb,eAAe;EACf,gBAAgB;EGAd,sBPqOgC;AH4tIpC;;AoCh8IA;EACE,kBAAkB;EAClB,cAAc;EACd,uBjCqwBwC;EiCpwBxC,iBjC6N+B;EiC5N/B,iBjCwwBsC;EiCvwBtC,cjCwBe;EiCvBf,sBjCNa;EiCOb,yBjCJgB;AHu8IlB;;AoC38IA;EAWI,UAAU;EACV,cjC2J8D;EiC1J9D,qBAAqB;EACrB,yBjCXc;EiCYd,qBjCXc;AH+8IlB;;AoCn9IA;EAmBI,UAAU;EACV,UjCiwBiC;EiChwBjC,gDjCSa;AH27IjB;;AoCh8IA;EAGM,cAAc;E1BChB,+BPuMgC;EOtMhC,kCPsMgC;AH2vIpC;;AoCt8IA;E1BVI,gCPqNgC;EOpNhC,mCPoNgC;AHgwIpC;;AoC38IA;EAcI,UAAU;EACV,WjCvCW;EiCwCX,yBjCXa;EiCYb,qBjCZa;AH68IjB;;AoCl9IA;EAqBI,cjCvCc;EiCwCd,oBAAoB;EAEpB,YAAY;EACZ,sBjCjDW;EiCkDX,qBjC/Cc;AH++IlB;;AqCt/IE;EACE,uBlC8wBsC;ECnpBpC,kBAtCY;EiCnFd,gBlC8N6B;AH2xIjC;;AqCp/IM;E3BwBF,8BPwM+B;EOvM/B,iCPuM+B;AHyxInC;;AqCp/IM;E3BKF,+BPsN+B;EOrN/B,kCPqN+B;AH8xInC;;AqCtgJE;EACE,uBlC4wBqC;ECjpBnC,mBAtCY;EiCnFd,gBlC+N6B;AH0yIjC;;AqCpgJM;E3BwBF,8BPyM+B;EOxM/B,iCPwM+B;AHwyInC;;AqCpgJM;E3BKF,+BPuN+B;EOtN/B,kCPsN+B;AH6yInC;;AsCphJA;EACE,qBAAqB;EACrB,qBnC24BsC;EC10BpC,cAAW;EkC/Db,gBnCmR+B;EmClR/B,cAAc;EACd,kBAAkB;EAClB,mBAAmB;EACnB,wBAAwB;E5BRtB,sBPqOgC;EiBpO9B,qIjBqb6I;AH2mInJ;;AoB3hJI;EkBNJ;IlBOM,gBAAgB;EpB+hJpB;AACF;;AK5hJE;EiCGI,qBAAqB;AtC6hJ3B;;AsC3iJA;EAoBI,aAAa;AtC2hJjB;;AsCthJA;EACE,kBAAkB;EAClB,SAAS;AtCyhJX;;AsClhJA;EACE,oBnCg3BsC;EmC/2BtC,mBnC+2BsC;EOn5BpC,oBPs5BqC;AHoqHzC;;AsC7gJE;ECjDA,WpCMa;EoCLb,yBpCkCe;AHgiJjB;;AKpjJE;EkCVI,WpCCS;EoCAT,yBAAkC;AvCkkJxC;;AuCrkJU;EAQJ,UAAU;EACV,+CpCuBW;AH0iJjB;;AsC5hJE;ECjDA,WpCMa;EoCLb,yBpCWgB;AHskJlB;;AKnkJE;EkCVI,WpCCS;EoCAT,yBAAkC;AvCilJxC;;AuCplJU;EAQJ,UAAU;EACV,iDpCAY;AHglJlB;;AsC3iJE;ECjDA,WpCMa;EoCLb,yBpCyCe;AHujJjB;;AKllJE;EkCVI,WpCCS;EoCAT,yBAAkC;AvCgmJxC;;AuCnmJU;EAQJ,UAAU;EACV,+CpC8BW;AHikJjB;;AsC1jJE;ECjDA,WpCMa;EoCLb,yBpC2Ce;AHokJjB;;AKjmJE;EkCVI,WpCCS;EoCAT,yBAAkC;AvC+mJxC;;AuClnJU;EAQJ,UAAU;EACV,gDpCgCW;AH8kJjB;;AsCzkJE;ECjDA,cpCegB;EoCdhB,yBpCwCe;AHslJjB;;AKhnJE;EkCVI,cpCUY;EoCTZ,yBAAkC;AvC8nJxC;;AuCjoJU;EAQJ,UAAU;EACV,+CpC6BW;AHgmJjB;;AsCxlJE;ECjDA,WpCMa;EoCLb,yBpCsCe;AHumJjB;;AK/nJE;EkCVI,WpCCS;EoCAT,yBAAkC;AvC6oJxC;;AuChpJU;EAQJ,UAAU;EACV,+CpC2BW;AHinJjB;;AsCvmJE;ECjDA,cpCegB;EoCdhB,yBpCMgB;AHspJlB;;AK9oJE;EkCVI,cpCUY;EoCTZ,yBAAkC;AvC4pJxC;;AuC/pJU;EAQJ,UAAU;EACV,iDpCLY;AHgqJlB;;AsCtnJE;ECjDA,WpCMa;EoCLb,yBpCagB;AH8pJlB;;AK7pJE;EkCVI,WpCCS;EoCAT,yBAAkC;AvC2qJxC;;AuC9qJU;EAQJ,UAAU;EACV,8CpCEY;AHwqJlB;;AwCvrJA;EACE,kBAAoD;EACpD,mBrC0yBsC;EqCxyBtC,yBrCKgB;EOJd,qBPsO+B;AHm9InC;;AcloJI;E0B5DJ;IAQI,kBrCoyBoC;EHu5HtC;AACF;;AwCxrJA;EACE,gBAAgB;EAChB,eAAe;E9BTb,gB8BUsB;AxC2rJ1B;;AyCtsJA;EACE,kBAAkB;EAClB,wBtCm8ByC;EsCl8BzC,mBtCm8BsC;EsCl8BtC,6BAA6C;E/BH3C,sBPqOgC;AHw+IpC;;AyCrsJA;EAEE,cAAc;AzCusJhB;;AyCnsJA;EACE,gBtCwQ+B;AH87IjC;;AyC9rJA;EACE,mBAAsD;AzCisJxD;;AyClsJA;EAKI,kBAAkB;EAClB,MAAM;EACN,QAAQ;EACR,wBtCq6BuC;EsCp6BvC,cAAc;AzCisJlB;;AyCvrJE;EC9CA,cxBmFgE;EI9E9D,yBJ8E8D;EwBjFhE,qBxBiFgE;AlBwpJlE;;A0CvuJE;EACE,yBAAqC;A1C0uJzC;;A0CvuJE;EACE,cAA0B;A1C0uJ9B;;AyCrsJE;EC9CA,cxBmFgE;EI9E9D,yBJ8E8D;EwBjFhE,qBxBiFgE;AlBsqJlE;;A0CrvJE;EACE,yBAAqC;A1CwvJzC;;A0CrvJE;EACE,cAA0B;A1CwvJ9B;;AyCntJE;EC9CA,cxBmFgE;EI9E9D,yBJ8E8D;EwBjFhE,qBxBiFgE;AlBorJlE;;A0CnwJE;EACE,yBAAqC;A1CswJzC;;A0CnwJE;EACE,cAA0B;A1CswJ9B;;AyCjuJE;EC9CA,cxBmFgE;EI9E9D,yBJ8E8D;EwBjFhE,qBxBiFgE;AlBksJlE;;A0CjxJE;EACE,yBAAqC;A1CoxJzC;;A0CjxJE;EACE,cAA0B;A1CoxJ9B;;AyC/uJE;EC9CA,cxBmFgE;EI9E9D,yBJ8E8D;EwBjFhE,qBxBiFgE;AlBgtJlE;;A0C/xJE;EACE,yBAAqC;A1CkyJzC;;A0C/xJE;EACE,cAA0B;A1CkyJ9B;;AyC7vJE;EC9CA,cxBmFgE;EI9E9D,yBJ8E8D;EwBjFhE,qBxBiFgE;AlB8tJlE;;A0C7yJE;EACE,yBAAqC;A1CgzJzC;;A0C7yJE;EACE,cAA0B;A1CgzJ9B;;AyC3wJE;EC9CA,cxBmFgE;EI9E9D,yBJ8E8D;EwBjFhE,qBxBiFgE;AlB4uJlE;;A0C3zJE;EACE,yBAAqC;A1C8zJzC;;A0C3zJE;EACE,cAA0B;A1C8zJ9B;;AyCzxJE;EC9CA,cxBmFgE;EI9E9D,yBJ8E8D;EwBjFhE,qBxBiFgE;AlB0vJlE;;A0Cz0JE;EACE,yBAAqC;A1C40JzC;;A0Cz0JE;EACE,cAA0B;A1C40J9B;;A2Cp1JE;EACE;IAAO,2BAAuC;E3Cw1JhD;E2Cv1JE;IAAK,wBAAwB;E3C01J/B;AACF;;A2C71JE;EACE;IAAO,2BAAuC;E3Cw1JhD;E2Cv1JE;IAAK,wBAAwB;E3C01J/B;AACF;;A2Cv1JA;EACE,oBAAa;EAAb,aAAa;EACb,YxC48BsC;EwC38BtC,gBAAgB;EvCoHZ,kBAtCY;EuC5EhB,yBxCJgB;EOJd,sBPqOgC;AH8nJpC;;A2Ct1JA;EACE,oBAAa;EAAb,aAAa;EACb,0BAAsB;EAAtB,sBAAsB;EACtB,qBAAuB;EAAvB,uBAAuB;EACvB,WxCfa;EwCgBb,kBAAkB;EAClB,mBAAmB;EACnB,yBxCWe;EiB9BX,2BjBw9B4C;AHq5HlD;;AoBx2JI;EuBOJ;IvBNM,gBAAgB;EpB42JpB;AACF;;A2C51JA;ErBcE,qMAA6I;EqBZ7I,0BxCu7BsC;AHw6HxC;;A2C31JE;EACE,0DxCy7BkD;EwCz7BlD,kDxCy7BkD;AHq6HtD;;A2C51JI;EAHF;IAII,uBAAe;IAAf,eAAe;E3Cg2JnB;AACF;;A4Cx4JA;EACE,oBAAa;EAAb,aAAa;EACb,qBAAuB;EAAvB,uBAAuB;A5C24JzB;;A4Cx4JA;EACE,WAAO;EAAP,OAAO;A5C24JT;;A6C74JA;EACE,oBAAa;EAAb,aAAa;EACb,0BAAsB;EAAtB,sBAAsB;EAGtB,eAAe;EACf,gBAAgB;A7C84JlB;;A6Cr4JA;EACE,WAAW;EACX,c1CPgB;E0CQhB,mBAAmB;A7Cw4JrB;;AK94JE;EwCUE,UAAU;EACV,c1Cbc;E0Ccd,qBAAqB;EACrB,yB1CrBc;AH65JlB;;A6Cl5JA;EAcI,c1CjBc;E0CkBd,yB1CzBc;AHi6JlB;;A6C/3JA;EACE,kBAAkB;EAClB,cAAc;EACd,wB1C47ByC;E0C17BzC,mB1CuL+B;E0CrL/B,sB1C3Ca;E0C4Cb,sC1ClCa;AHk6Jf;;A6Cx4JA;EnC7BI,+BP4NgC;EO3NhC,gCP2NgC;AH8sJpC;;A6C74JA;EAeI,gBAAgB;EnC9BhB,mCP8MgC;EO7MhC,kCP6MgC;AHotJpC;;A6Cn5JA;EAqBI,c1CnDc;E0CoDd,oBAAoB;EACpB,sB1C3DW;AH67Jf;;A6Cz5JA;EA4BI,UAAU;EACV,W1CjEW;E0CkEX,yB1CrCa;E0CsCb,qB1CtCa;AHu6JjB;;A6Cp3JI;EACE,uBAAmB;EAAnB,mBAAmB;A7Cu3JzB;;A6Cx3JI;EAII,kB1C4IyB;E0C3IzB,gBAAgB;A7Cw3JxB;;A6C73JI;EnCpDA,+BPuMgC;EOtMhC,kCPsMgC;EO1LhC,0BmCgDwC;A7C03J5C;;A6Cn4JI;EAaM,eAAe;EnC/ErB,gCPqNgC;EOpNhC,mCPoNgC;EO9KhC,4BmC0C0C;A7C23J9C;;Acr6JI;E+B2BA;IACE,uBAAmB;IAAnB,mBAAmB;E7C84JvB;E6C/4JE;IAII,kB1C4IyB;I0C3IzB,gBAAgB;E7C84JtB;E6Cn5JE;InCpDA,+BPuMgC;IOtMhC,kCPsMgC;IO1LhC,0BmCgDwC;E7C+4J1C;E6Cx5JE;IAaM,eAAe;InC/ErB,gCPqNgC;IOpNhC,mCPoNgC;IO9KhC,4BmC0C0C;E7C+4J5C;AACF;;Ac17JI;E+B2BA;IACE,uBAAmB;IAAnB,mBAAmB;E7Cm6JvB;E6Cp6JE;IAII,kB1C4IyB;I0C3IzB,gBAAgB;E7Cm6JtB;E6Cx6JE;InCpDA,+BPuMgC;IOtMhC,kCPsMgC;IO1LhC,0BmCgDwC;E7Co6J1C;E6C76JE;IAaM,eAAe;InC/ErB,gCPqNgC;IOpNhC,mCPoNgC;IO9KhC,4BmC0C0C;E7Co6J5C;AACF;;Ac/8JI;E+B2BA;IACE,uBAAmB;IAAnB,mBAAmB;E7Cw7JvB;E6Cz7JE;IAII,kB1C4IyB;I0C3IzB,gBAAgB;E7Cw7JtB;E6C77JE;InCpDA,+BPuMgC;IOtMhC,kCPsMgC;IO1LhC,0BmCgDwC;E7Cy7J1C;E6Cl8JE;IAaM,eAAe;InC/ErB,gCPqNgC;IOpNhC,mCPoNgC;IO9KhC,4BmC0C0C;E7Cy7J5C;AACF;;Acp+JI;E+B2BA;IACE,uBAAmB;IAAnB,mBAAmB;E7C68JvB;E6C98JE;IAII,kB1C4IyB;I0C3IzB,gBAAgB;E7C68JtB;E6Cl9JE;InCpDA,+BPuMgC;IOtMhC,kCPsMgC;IO1LhC,0BmCgDwC;E7C88J1C;E6Cv9JE;IAaM,eAAe;InC/ErB,gCPqNgC;IOpNhC,mCPoNgC;IO9KhC,4BmC0C0C;E7C88J5C;AACF;;A6Cl8JA;EAEI,eAAe;EACf,cAAc;EnCjHd,gBmCkHwB;A7Co8J5B;;A6Cx8JA;EAOM,mB1C6G2B;AHw1JjC;;A6C58JA;EAaM,aAAa;A7Cm8JnB;;A6Ch9JA;EAmBM,gBAAgB;EAChB,gBAAgB;A7Ci8JtB;;A8CrkKE;EACE,c5BgF8D;E4B/E9D,yB5B+E8D;AlBy/JlE;;AK7jKE;EyCPM,c5B2E0D;E4B1E1D,yBAAyC;A9CwkKjD;;A8C/kKE;EAWM,W3CPO;E2CQP,yB5BqE0D;E4BpE1D,qB5BoE0D;AlBogKlE;;A8CrlKE;EACE,c5BgF8D;E4B/E9D,yB5B+E8D;AlBygKlE;;AK7kKE;EyCPM,c5B2E0D;E4B1E1D,yBAAyC;A9CwlKjD;;A8C/lKE;EAWM,W3CPO;E2CQP,yB5BqE0D;E4BpE1D,qB5BoE0D;AlBohKlE;;A8CrmKE;EACE,c5BgF8D;E4B/E9D,yB5B+E8D;AlByhKlE;;AK7lKE;EyCPM,c5B2E0D;E4B1E1D,yBAAyC;A9CwmKjD;;A8C/mKE;EAWM,W3CPO;E2CQP,yB5BqE0D;E4BpE1D,qB5BoE0D;AlBoiKlE;;A8CrnKE;EACE,c5BgF8D;E4B/E9D,yB5B+E8D;AlByiKlE;;AK7mKE;EyCPM,c5B2E0D;E4B1E1D,yBAAyC;A9CwnKjD;;A8C/nKE;EAWM,W3CPO;E2CQP,yB5BqE0D;E4BpE1D,qB5BoE0D;AlBojKlE;;A8CroKE;EACE,c5BgF8D;E4B/E9D,yB5B+E8D;AlByjKlE;;AK7nKE;EyCPM,c5B2E0D;E4B1E1D,yBAAyC;A9CwoKjD;;A8C/oKE;EAWM,W3CPO;E2CQP,yB5BqE0D;E4BpE1D,qB5BoE0D;AlBokKlE;;A8CrpKE;EACE,c5BgF8D;E4B/E9D,yB5B+E8D;AlBykKlE;;AK7oKE;EyCPM,c5B2E0D;E4B1E1D,yBAAyC;A9CwpKjD;;A8C/pKE;EAWM,W3CPO;E2CQP,yB5BqE0D;E4BpE1D,qB5BoE0D;AlBolKlE;;A8CrqKE;EACE,c5BgF8D;E4B/E9D,yB5B+E8D;AlBylKlE;;AK7pKE;EyCPM,c5B2E0D;E4B1E1D,yBAAyC;A9CwqKjD;;A8C/qKE;EAWM,W3CPO;E2CQP,yB5BqE0D;E4BpE1D,qB5BoE0D;AlBomKlE;;A8CrrKE;EACE,c5BgF8D;E4B/E9D,yB5B+E8D;AlBymKlE;;AK7qKE;EyCPM,c5B2E0D;E4B1E1D,yBAAyC;A9CwrKjD;;A8C/rKE;EAWM,W3CPO;E2CQP,yB5BqE0D;E4BpE1D,qB5BoE0D;AlBonKlE;;A+CxsKA;EACE,YAAY;E3C8HR,iBAtCY;E2CtFhB,gB5CyR+B;E4CxR/B,cAAc;EACd,W5CYa;E4CXb,yB5CCa;E4CAb,WAAW;A/C2sKb;;AKtsKE;E0CDE,W5CMW;E4CLX,qBAAqB;A/C2sKzB;;AKvsKE;E0CCI,YAAY;A/C0sKlB;;A+C/rKA;EACE,UAAU;EACV,6BAA6B;EAC7B,SAAS;EACT,wBAAgB;EAAhB,qBAAgB;EAAhB,gBAAgB;A/CksKlB;;A+C5rKA;EACE,oBAAoB;A/C+rKtB;;AgDtuKA;EACE,gB7C43BuC;E6C33BvC,gBAAgB;E5C6HZ,mBAtCY;E4CpFhB,2C7CEa;E6CDb,4BAA4B;EAC5B,oC7C63BmD;E6C53BnD,gD7CSa;E6CRb,mCAA2B;EAA3B,2BAA2B;EAC3B,UAAU;EtCLR,sBPg4BsC;AH82I1C;;AgDnvKA;EAcI,sB7Cg3BsC;AHy3I1C;;AgDvvKA;EAkBI,UAAU;AhDyuKd;;AgD3vKA;EAsBI,cAAc;EACd,UAAU;AhDyuKd;;AgDhwKA;EA2BI,aAAa;AhDyuKjB;;AgDruKA;EACE,oBAAa;EAAb,aAAa;EACb,sBAAmB;EAAnB,mBAAmB;EACnB,wB7C41BwC;E6C31BxC,c7CtBgB;E6CuBhB,2C7C7Ba;E6C8Bb,4BAA4B;EAC5B,4C7Co2BoD;AHo4ItD;;AgDruKA;EACE,gB7Co1BwC;AHo5I1C;;AiD5wKA;EAEE,gBAAgB;AjD8wKlB;;AiDhxKA;EAKI,kBAAkB;EAClB,gBAAgB;AjD+wKpB;;AiD1wKA;EACE,eAAe;EACf,MAAM;EACN,OAAO;EACP,a9CopBsC;E8CnpBtC,aAAa;EACb,WAAW;EACX,YAAY;EACZ,gBAAgB;EAGhB,UAAU;AjD2wKZ;;AiDpwKA;EACE,kBAAkB;EAClB,WAAW;EACX,c9C63BuC;E8C33BvC,oBAAoB;AjDswKtB;;AiDnwKE;E7BrCI,2CjB27BoD;EiB37BpD,mCjB27BoD;EiB37BpD,oEjB27BoD;E8Cp5BtD,sC9Ck5BmD;E8Cl5BnD,8B9Ck5BmD;AHo3IvD;;AoBxyKI;E6BgCF;I7B/BI,gBAAgB;EpB4yKpB;AACF;;AiD1wKE;EACE,uB9Cg5BoC;E8Ch5BpC,e9Cg5BoC;AH63IxC;;AiDzwKA;EACE,oBAAa;EAAb,aAAa;EACb,6BAAoD;AjD4wKtD;;AiD9wKA;EAKI,8BAAqD;EACrD,gBAAgB;AjD6wKpB;;AiDnxKA;;EAWI,oBAAc;EAAd,cAAc;AjD6wKlB;;AiDxxKA;EAeI,gBAAgB;AjD6wKpB;;AiDzwKA;EACE,oBAAa;EAAb,aAAa;EACb,sBAAmB;EAAnB,mBAAmB;EACnB,6BAAoD;AjD4wKtD;;AiD/wKA;EAOI,cAAc;EACd,0BAAiD;EACjD,WAAW;AjD4wKf;;AiDrxKA;EAcI,0BAAsB;EAAtB,sBAAsB;EACtB,qBAAuB;EAAvB,uBAAuB;EACvB,YAAY;AjD2wKhB;;AiD3xKA;EAmBM,gBAAgB;AjD4wKtB;;AiD/xKA;EAuBM,aAAa;AjD4wKnB;;AiDtwKA;EACE,kBAAkB;EAClB,oBAAa;EAAb,aAAa;EACb,0BAAsB;EAAtB,sBAAsB;EACtB,WAAW;EAGX,oBAAoB;EACpB,sB9CrGa;E8CsGb,4BAA4B;EAC5B,oC9C7Fa;EOZX,qBPsO+B;E8CzHjC,UAAU;AjDqwKZ;;AiDjwKA;EACE,eAAe;EACf,MAAM;EACN,OAAO;EACP,a9C8iBsC;E8C7iBtC,YAAY;EACZ,aAAa;EACb,sB9C5Ga;AHg3Kf;;AiD3wKA;EAUW,UAAU;AjDqwKrB;;AiD/wKA;EAWW,Y9CgzB2B;AHw9ItC;;AiDnwKA;EACE,oBAAa;EAAb,aAAa;EACb,qBAAuB;EAAvB,uBAAuB;EACvB,sBAA8B;EAA9B,8BAA8B;EAC9B,kB9C6yBsC;E8C5yBtC,gC9CjIgB;EOId,8BP6N+B;EO5N/B,+BP4N+B;AHwqKnC;;AiD7wKA;EASI,kB9CwyBoC;E8CtyBpC,8BAA6F;AjDuwKjG;;AiDlwKA;EACE,gBAAgB;EAChB,gB9CwI+B;AH6nKjC;;AiDhwKA;EACE,kBAAkB;EAGlB,kBAAc;EAAd,cAAc;EACd,a9C+vBsC;AHkgJxC;;AiD7vKA;EACE,oBAAa;EAAb,aAAa;EACb,sBAAmB;EAAnB,mBAAmB;EACnB,kBAAyB;EAAzB,yBAAyB;EACzB,a9CuvBsC;E8CtvBtC,6B9CjKgB;EOkBd,kCP+M+B;EO9M/B,iCP8M+B;AHksKnC;;AiDvwKA;EASyB,mBAAmB;AjDkwK5C;;AiD3wKA;EAUwB,oBAAoB;AjDqwK5C;;AiDjwKA;EACE,kBAAkB;EAClB,YAAY;EACZ,WAAW;EACX,YAAY;EACZ,gBAAgB;AjDowKlB;;Acj4KI;EmCzBJ;IA6JI,gB9C4vBqC;I8C3vBrC,oBAAyC;EjDkwK3C;EiD/4KF;IAiJI,+BAA4D;EjDiwK9D;EiDl5KF;IAoJM,gCAA6D;EjDiwKjE;EiDl4KF;IAsII,+BAA4D;EjD+vK9D;EiDr4KF;IAyIM,4BAAyD;EjD+vK7D;EiDvvKA;IAAY,gB9CquB2B;EHqhJvC;AACF;;Acv5KI;EmCgKF;;IAEE,gB9C6tBqC;EH8hJvC;AACF;;Ac95KI;EmCuKF;IAAY,iB9CutB4B;EHqiJxC;AACF;;AkD/9KA;EACE,kBAAkB;EAClB,a/CwqBsC;E+CvqBtC,cAAc;EACd,S/C60BmC;EgDj1BnC,kMhD+QiN;EgD7QjN,kBAAkB;EAClB,gBhDuR+B;EgDtR/B,gBhD2R+B;EgD1R/B,gBAAgB;EAChB,iBAAiB;EACjB,qBAAqB;EACrB,iBAAiB;EACjB,oBAAoB;EACpB,sBAAsB;EACtB,kBAAkB;EAClB,oBAAoB;EACpB,mBAAmB;EACnB,gBAAgB;E/CgHZ,mBAtCY;E8C9EhB,qBAAqB;EACrB,UAAU;AlD4+KZ;;AkDv/KA;EAaW,Y/Ci0B2B;AH6qJtC;;AkD3/KA;EAgBI,kBAAkB;EAClB,cAAc;EACd,a/Ci0BqC;E+Ch0BrC,c/Ci0BqC;AH8qJzC;;AkDlgLA;EAsBM,kBAAkB;EAClB,WAAW;EACX,yBAAyB;EACzB,mBAAmB;AlDg/KzB;;AkD3+KA;EACE,iBAAgC;AlD8+KlC;;AkD/+KA;EAII,SAAS;AlD++Kb;;AkDn/KA;EAOM,MAAM;EACN,6BAAgE;EAChE,sB/CvBS;AHugLf;;AkD3+KA;EACE,iB/CuyBuC;AHusJzC;;AkD/+KA;EAII,OAAO;EACP,a/CmyBqC;E+ClyBrC,c/CiyBqC;AH8sJzC;;AkDr/KA;EASM,QAAQ;EACR,oCAA2F;EAC3F,wB/CvCS;AHuhLf;;AkD3+KA;EACE,iBAAgC;AlD8+KlC;;AkD/+KA;EAII,MAAM;AlD++KV;;AkDn/KA;EAOM,SAAS;EACT,6B/CgxBmC;E+C/wBnC,yB/CrDS;AHqiLf;;AkD3+KA;EACE,iB/CywBuC;AHquJzC;;AkD/+KA;EAII,QAAQ;EACR,a/CqwBqC;E+CpwBrC,c/CmwBqC;AH4uJzC;;AkDr/KA;EASM,OAAO;EACP,oC/CgwBmC;E+C/vBnC,uB/CrES;AHqjLf;;AkD39KA;EACE,gB/C+tBuC;E+C9tBvC,uB/CouBuC;E+CnuBvC,W/CvGa;E+CwGb,kBAAkB;EAClB,sB/C/Fa;EOZX,sBPqOgC;AHq2KpC;;AoD/kLA;EACE,kBAAkB;EAClB,MAAM;EACN,OAAO;EACP,ajDsqBsC;EiDrqBtC,cAAc;EACd,gBjD+1BuC;EgDp2BvC,kMhD+QiN;EgD7QjN,kBAAkB;EAClB,gBhDuR+B;EgDtR/B,gBhD2R+B;EgD1R/B,gBAAgB;EAChB,iBAAiB;EACjB,qBAAqB;EACrB,iBAAiB;EACjB,oBAAoB;EACpB,sBAAsB;EACtB,kBAAkB;EAClB,oBAAoB;EACpB,mBAAmB;EACnB,gBAAgB;E/CgHZ,mBAtCY;EgD7EhB,qBAAqB;EACrB,sBjDNa;EiDOb,4BAA4B;EAC5B,oCjDEa;EOZX,qBPsO+B;AHi4KnC;;AoD5mLA;EAoBI,kBAAkB;EAClB,cAAc;EACd,WjD81BoC;EiD71BpC,cjD81BqC;EiD71BrC,gBjDmN+B;AHy4KnC;;AoDpnLA;EA4BM,kBAAkB;EAClB,cAAc;EACd,WAAW;EACX,yBAAyB;EACzB,mBAAmB;ApD4lLzB;;AoDvlLA;EACE,qBjD+0BuC;AH2wJzC;;AoD3lLA;EAII,iCAAwE;ApD2lL5E;;AoD/lLA;EAOM,SAAS;EACT,6BAAgE;EAChE,qCjD00BiE;AHkxJvE;;AoDrmLA;EAaM,WjDqL2B;EiDpL3B,6BAAgE;EAChE,sBjD7CS;AHyoLf;;AoDvlLA;EACE,mBjD2zBuC;AH+xJzC;;AoD3lLA;EAII,+BAAsE;EACtE,ajDuzBqC;EiDtzBrC,YjDqzBoC;EiDpzBpC,gBAA2B;ApD2lL/B;;AoDlmLA;EAUM,OAAO;EACP,oCAA2F;EAC3F,uCjDmzBiE;AHyyJvE;;AoDxmLA;EAgBM,SjD8J2B;EiD7J3B,oCAA2F;EAC3F,wBjDpES;AHgqLf;;AoDvlLA;EACE,kBjDoyBuC;AHszJzC;;AoD3lLA;EAII,8BAAqE;ApD2lLzE;;AoD/lLA;EAOM,MAAM;EACN,oCAA2F;EAC3F,wCjD+xBiE;AH6zJvE;;AoDrmLA;EAaM,QjD0I2B;EiDzI3B,oCAA2F;EAC3F,yBjDxFS;AHorLf;;AoD3mLA;EAqBI,kBAAkB;EAClB,MAAM;EACN,SAAS;EACT,cAAc;EACd,WjD2wBoC;EiD1wBpC,oBAAsC;EACtC,WAAW;EACX,gCjD+vBuD;AH21J3D;;AoDtlLA;EACE,oBjDowBuC;AHq1JzC;;AoD1lLA;EAII,gCAAuE;EACvE,ajDgwBqC;EiD/vBrC,YjD8vBoC;EiD7vBpC,gBAA2B;ApD0lL/B;;AoDjmLA;EAUM,QAAQ;EACR,oCjD0vBmC;EiDzvBnC,sCjD4vBiE;AH+1JvE;;AoDvmLA;EAgBM,UjDuG2B;EiDtG3B,oCjDovBmC;EiDnvBnC,uBjD3HS;AHstLf;;AoDrkLA;EACE,uBjDqtBwC;EiDptBxC,gBAAgB;EhD3BZ,eAtCY;EgDoEhB,yBjD8sByD;EiD7sBzD,gCAAyE;E1ChJvE,0C0CiJyE;E1ChJzE,2C0CgJyE;ApDwkL7E;;AoD/kLA;EAWI,aAAa;ApDwkLjB;;AoDpkLA;EACE,uBjDssBwC;EiDrsBxC,cjDzJgB;AHguLlB;;AqDnuLA;EACE,kBAAkB;ArDsuLpB;;AqDnuLA;EACE,uBAAmB;EAAnB,mBAAmB;ArDsuLrB;;AqDnuLA;EACE,kBAAkB;EAClB,WAAW;EACX,gBAAgB;ArDsuLlB;;AsD7vLE;EACE,cAAc;EACd,WAAW;EACX,WAAW;AtDgwLf;;AqDxuLA;EACE,kBAAkB;EAClB,aAAa;EACb,WAAW;EACX,WAAW;EACX,mBAAmB;EACnB,mCAA2B;EAA3B,2BAA2B;EjC5BvB,8CjB6iCkF;EiB7iClF,sCjB6iCkF;EiB7iClF,0EjB6iCkF;AH2tJxF;;AoBnwLI;EiCiBJ;IjChBM,gBAAgB;EpBuwLpB;AACF;;AqD9uLA;;;EAGE,cAAc;ArDivLhB;;AqD9uLA;;EAEE,mCAA2B;EAA3B,2BAA2B;ArDivL7B;;AqD9uLA;;EAEE,oCAA4B;EAA5B,4BAA4B;ArDivL9B;;AqDzuLA;EAEI,UAAU;EACV,4BAA4B;EAC5B,uBAAe;EAAf,eAAe;ArD2uLnB;;AqD/uLA;;;EAUI,UAAU;EACV,UAAU;ArD2uLd;;AqDtvLA;;EAgBI,UAAU;EACV,UAAU;EjCtER,2BiCuE0D;ArD2uLhE;;AoB7yLI;EiCgDJ;;IjC/CM,gBAAgB;EpBkzLpB;AACF;;AqDzuLA;;EAEE,kBAAkB;EAClB,MAAM;EACN,SAAS;EACT,UAAU;EAEV,oBAAa;EAAb,aAAa;EACb,sBAAmB;EAAnB,mBAAmB;EACnB,qBAAuB;EAAvB,uBAAuB;EACvB,UlD87BsC;EkD77BtC,WlD1Fa;EkD2Fb,kBAAkB;EAClB,YlD47BqC;EiBzhCjC,8BjB2hCgD;AH8yJtD;;AoBp0LI;EiC2EJ;;IjC1EM,gBAAgB;EpBy0LpB;AACF;;AKt0LE;;;EgDwFE,WlDjGW;EkDkGX,qBAAqB;EACrB,UAAU;EACV,YlDq7BmC;AH+zJvC;;AqDjvLA;EACE,OAAO;ArDovLT;;AqD/uLA;EACE,QAAQ;ArDkvLV;;AqD3uLA;;EAEE,qBAAqB;EACrB,WlD86BuC;EkD76BvC,YlD66BuC;EkD56BvC,qCAAqC;ArD8uLvC;;AqD5uLA;EACE,mMnCxFyI;AlBu0L3I;;AqD7uLA;EACE,mMnC3FyI;AlB20L3I;;AqDvuLA;EACE,kBAAkB;EAClB,QAAQ;EACR,SAAS;EACT,OAAO;EACP,WAAW;EACX,oBAAa;EAAb,aAAa;EACb,qBAAuB;EAAvB,uBAAuB;EACvB,eAAe;EAEf,iBlDo4BsC;EkDn4BtC,gBlDm4BsC;EkDl4BtC,gBAAgB;ArDyuLlB;;AqDrvLA;EAeI,uBAAuB;EACvB,kBAAc;EAAd,cAAc;EACd,WlDk4BqC;EkDj4BrC,WlDk4BoC;EkDj4BpC,iBlDm4BoC;EkDl4BpC,gBlDk4BoC;EkDj4BpC,mBAAmB;EACnB,eAAe;EACf,sBlDhKW;EkDiKX,4BAA4B;EAE5B,kCAAiE;EACjE,qCAAoE;EACpE,WAAW;EjCtKT,6BjBkiC+C;AH82JrD;;AoB34LI;EiCqIJ;IjCpIM,gBAAgB;EpB+4LpB;AACF;;AqD5wLA;EAiCI,UAAU;ArD+uLd;;AqDtuLA;EACE,kBAAkB;EAClB,UAA2C;EAC3C,YAAY;EACZ,SAA0C;EAC1C,WAAW;EACX,iBAAiB;EACjB,oBAAoB;EACpB,WlD3La;EkD4Lb,kBAAkB;ArDyuLpB;;AuDx6LA;EACE;IAAK,iCAAyB;IAAzB,yBAAyB;EvD46L9B;AACF;;AuD96LA;EACE;IAAK,iCAAyB;IAAzB,yBAAyB;EvD46L9B;AACF;;AuD16LA;EACE,qBAAqB;EACrB,WpD8iC0B;EoD7iC1B,YpD6iC0B;EoD5iC1B,2BAA2B;EAC3B,iCAAgD;EAChD,+BAA+B;EAE/B,kBAAkB;EAClB,sDAA8C;EAA9C,8CAA8C;AvD46LhD;;AuDz6LA;EACE,WpDuiC4B;EoDtiC5B,YpDsiC4B;EoDriC5B,mBpDuiC4B;AHq4J9B;;AuDr6LA;EACE;IACE,2BAAmB;IAAnB,mBAAmB;EvDw6LrB;EuDt6LA;IACE,UAAU;EvDw6LZ;AACF;;AuD96LA;EACE;IACE,2BAAmB;IAAnB,mBAAmB;EvDw6LrB;EuDt6LA;IACE,UAAU;EvDw6LZ;AACF;;AuDr6LA;EACE,qBAAqB;EACrB,WpD+gC0B;EoD9gC1B,YpD8gC0B;EoD7gC1B,2BAA2B;EAC3B,8BAA8B;EAE9B,kBAAkB;EAClB,UAAU;EACV,oDAA4C;EAA5C,4CAA4C;AvDu6L9C;;AuDp6LA;EACE,WpDwgC4B;EoDvgC5B,YpDugC4B;AHg6J9B;;AwD19LA;EAAqB,mCAAmC;AxD89LxD;;AwD79LA;EAAqB,8BAA8B;AxDi+LnD;;AwDh+LA;EAAqB,iCAAiC;AxDo+LtD;;AwDn+LA;EAAqB,iCAAiC;AxDu+LtD;;AwDt+LA;EAAqB,sCAAsC;AxD0+L3D;;AwDz+LA;EAAqB,mCAAmC;AxD6+LxD;;AyD/+LE;EACE,oCAAmC;AzDk/LvC;;AKx+LE;;;EoDLI,oCAAgD;AzDm/LtD;;AyDz/LE;EACE,oCAAmC;AzD4/LvC;;AKl/LE;;;EoDLI,oCAAgD;AzD6/LtD;;AyDngME;EACE,oCAAmC;AzDsgMvC;;AK5/LE;;;EoDLI,oCAAgD;AzDugMtD;;AyD7gME;EACE,oCAAmC;AzDghMvC;;AKtgME;;;EoDLI,oCAAgD;AzDihMtD;;AyDvhME;EACE,oCAAmC;AzD0hMvC;;AKhhME;;;EoDLI,oCAAgD;AzD2hMtD;;AyDjiME;EACE,oCAAmC;AzDoiMvC;;AK1hME;;;EoDLI,oCAAgD;AzDqiMtD;;AyD3iME;EACE,oCAAmC;AzD8iMvC;;AKpiME;;;EoDLI,oCAAgD;AzD+iMtD;;AyDrjME;EACE,oCAAmC;AzDwjMvC;;AK9iME;;;EoDLI,oCAAgD;AzDyjMtD;;A0DxjMA;EACE,iCAAmC;A1D2jMrC;;A0DxjMA;EACE,wCAAwC;A1D2jM1C;;A2DtkMA;EAAkB,oCAAoD;A3D0kMtE;;A2DzkMA;EAAkB,wCAAwD;A3D6kM1E;;A2D5kMA;EAAkB,0CAA0D;A3DglM5E;;A2D/kMA;EAAkB,2CAA2D;A3DmlM7E;;A2DllMA;EAAkB,yCAAyD;A3DslM3E;;A2DplMA;EAAmB,oBAAoB;A3DwlMvC;;A2DvlMA;EAAmB,wBAAwB;A3D2lM3C;;A2D1lMA;EAAmB,0BAA0B;A3D8lM7C;;A2D7lMA;EAAmB,2BAA2B;A3DimM9C;;A2DhmMA;EAAmB,yBAAyB;A3DomM5C;;A2DjmME;EACE,gCAA+B;A3DomMnC;;A2DrmME;EACE,gCAA+B;A3DwmMnC;;A2DzmME;EACE,gCAA+B;A3D4mMnC;;A2D7mME;EACE,gCAA+B;A3DgnMnC;;A2DjnME;EACE,gCAA+B;A3DonMnC;;A2DrnME;EACE,gCAA+B;A3DwnMnC;;A2DznME;EACE,gCAA+B;A3D4nMnC;;A2D7nME;EACE,gCAA+B;A3DgoMnC;;A2D5nMA;EACE,6BAA+B;A3D+nMjC;;A2DxnMA;EACE,gCAA2C;A3D2nM7C;;A2DxnMA;EACE,iCAAwC;A3D2nM1C;;A2DxnMA;EACE,0CAAiD;EACjD,2CAAkD;A3D2nMpD;;A2DxnMA;EACE,2CAAkD;EAClD,8CAAqD;A3D2nMvD;;A2DxnMA;EACE,8CAAqD;EACrD,6CAAoD;A3D2nMtD;;A2DxnMA;EACE,0CAAiD;EACjD,6CAAoD;A3D2nMtD;;A2DxnMA;EACE,gCAA2C;A3D2nM7C;;A2DxnMA;EACE,6BAA6B;A3D2nM/B;;A2DxnMA;EACE,+BAAuC;A3D2nMzC;;A2DxnMA;EACE,2BAA2B;A3D2nM7B;;AsDnsME;EACE,cAAc;EACd,WAAW;EACX,WAAW;AtDssMf;;A4D/rMM;EAAwB,wBAA0B;A5DmsMxD;;A4DnsMM;EAAwB,0BAA0B;A5DusMxD;;A4DvsMM;EAAwB,gCAA0B;A5D2sMxD;;A4D3sMM;EAAwB,yBAA0B;A5D+sMxD;;A4D/sMM;EAAwB,yBAA0B;A5DmtMxD;;A4DntMM;EAAwB,6BAA0B;A5DutMxD;;A4DvtMM;EAAwB,8BAA0B;A5D2tMxD;;A4D3tMM;EAAwB,+BAA0B;EAA1B,wBAA0B;A5D+tMxD;;A4D/tMM;EAAwB,sCAA0B;EAA1B,+BAA0B;A5DmuMxD;;AclrMI;E8CjDE;IAAwB,wBAA0B;E5DwuMtD;E4DxuMI;IAAwB,0BAA0B;E5D2uMtD;E4D3uMI;IAAwB,gCAA0B;E5D8uMtD;E4D9uMI;IAAwB,yBAA0B;E5DivMtD;E4DjvMI;IAAwB,yBAA0B;E5DovMtD;E4DpvMI;IAAwB,6BAA0B;E5DuvMtD;E4DvvMI;IAAwB,8BAA0B;E5D0vMtD;E4D1vMI;IAAwB,+BAA0B;IAA1B,wBAA0B;E5D6vMtD;E4D7vMI;IAAwB,sCAA0B;IAA1B,+BAA0B;E5DgwMtD;AACF;;AchtMI;E8CjDE;IAAwB,wBAA0B;E5DswMtD;E4DtwMI;IAAwB,0BAA0B;E5DywMtD;E4DzwMI;IAAwB,gCAA0B;E5D4wMtD;E4D5wMI;IAAwB,yBAA0B;E5D+wMtD;E4D/wMI;IAAwB,yBAA0B;E5DkxMtD;E4DlxMI;IAAwB,6BAA0B;E5DqxMtD;E4DrxMI;IAAwB,8BAA0B;E5DwxMtD;E4DxxMI;IAAwB,+BAA0B;IAA1B,wBAA0B;E5D2xMtD;E4D3xMI;IAAwB,sCAA0B;IAA1B,+BAA0B;E5D8xMtD;AACF;;Ac9uMI;E8CjDE;IAAwB,wBAA0B;E5DoyMtD;E4DpyMI;IAAwB,0BAA0B;E5DuyMtD;E4DvyMI;IAAwB,gCAA0B;E5D0yMtD;E4D1yMI;IAAwB,yBAA0B;E5D6yMtD;E4D7yMI;IAAwB,yBAA0B;E5DgzMtD;E4DhzMI;IAAwB,6BAA0B;E5DmzMtD;E4DnzMI;IAAwB,8BAA0B;E5DszMtD;E4DtzMI;IAAwB,+BAA0B;IAA1B,wBAA0B;E5DyzMtD;E4DzzMI;IAAwB,sCAA0B;IAA1B,+BAA0B;E5D4zMtD;AACF;;Ac5wMI;E8CjDE;IAAwB,wBAA0B;E5Dk0MtD;E4Dl0MI;IAAwB,0BAA0B;E5Dq0MtD;E4Dr0MI;IAAwB,gCAA0B;E5Dw0MtD;E4Dx0MI;IAAwB,yBAA0B;E5D20MtD;E4D30MI;IAAwB,yBAA0B;E5D80MtD;E4D90MI;IAAwB,6BAA0B;E5Di1MtD;E4Dj1MI;IAAwB,8BAA0B;E5Do1MtD;E4Dp1MI;IAAwB,+BAA0B;IAA1B,wBAA0B;E5Du1MtD;E4Dv1MI;IAAwB,sCAA0B;IAA1B,+BAA0B;E5D01MtD;AACF;;A4Dj1MA;EAEI;IAAqB,wBAA0B;E5Do1MjD;E4Dp1ME;IAAqB,0BAA0B;E5Du1MjD;E4Dv1ME;IAAqB,gCAA0B;E5D01MjD;E4D11ME;IAAqB,yBAA0B;E5D61MjD;E4D71ME;IAAqB,yBAA0B;E5Dg2MjD;E4Dh2ME;IAAqB,6BAA0B;E5Dm2MjD;E4Dn2ME;IAAqB,8BAA0B;E5Ds2MjD;E4Dt2ME;IAAqB,+BAA0B;IAA1B,wBAA0B;E5Dy2MjD;E4Dz2ME;IAAqB,sCAA0B;IAA1B,+BAA0B;E5D42MjD;AACF;;A6Dl4MA;EACE,kBAAkB;EAClB,cAAc;EACd,WAAW;EACX,UAAU;EACV,gBAAgB;A7Dq4MlB;;A6D14MA;EAQI,cAAc;EACd,WAAW;A7Ds4Mf;;A6D/4MA;;;;;EAiBI,kBAAkB;EAClB,MAAM;EACN,SAAS;EACT,OAAO;EACP,WAAW;EACX,YAAY;EACZ,SAAS;A7Ds4Mb;;A6D93ME;EAEI,uBAA4F;A7Dg4MlG;;A6Dl4ME;EAEI,mBAA4F;A7Do4MlG;;A6Dt4ME;EAEI,gBAA4F;A7Dw4MlG;;A6D14ME;EAEI,iBAA4F;A7D44MlG;;A8Dr6MI;EAAgC,kCAA8B;EAA9B,8BAA8B;A9Dy6MlE;;A8Dx6MI;EAAgC,qCAAiC;EAAjC,iCAAiC;A9D46MrE;;A8D36MI;EAAgC,0CAAsC;EAAtC,sCAAsC;A9D+6M1E;;A8D96MI;EAAgC,6CAAyC;EAAzC,yCAAyC;A9Dk7M7E;;A8Dh7MI;EAA8B,8BAA0B;EAA1B,0BAA0B;A9Do7M5D;;A8Dn7MI;EAA8B,gCAA4B;EAA5B,4BAA4B;A9Du7M9D;;A8Dt7MI;EAA8B,sCAAkC;EAAlC,kCAAkC;A9D07MpE;;A8Dz7MI;EAA8B,6BAAyB;EAAzB,yBAAyB;A9D67M3D;;A8D57MI;EAA8B,+BAAuB;EAAvB,uBAAuB;A9Dg8MzD;;A8D/7MI;EAA8B,+BAAuB;EAAvB,uBAAuB;A9Dm8MzD;;A8Dl8MI;EAA8B,+BAAyB;EAAzB,yBAAyB;A9Ds8M3D;;A8Dr8MI;EAA8B,+BAAyB;EAAzB,yBAAyB;A9Dy8M3D;;A8Dv8MI;EAAoC,+BAAsC;EAAtC,sCAAsC;A9D28M9E;;A8D18MI;EAAoC,6BAAoC;EAApC,oCAAoC;A9D88M5E;;A8D78MI;EAAoC,gCAAkC;EAAlC,kCAAkC;A9Di9M1E;;A8Dh9MI;EAAoC,iCAAyC;EAAzC,yCAAyC;A9Do9MjF;;A8Dn9MI;EAAoC,oCAAwC;EAAxC,wCAAwC;A9Du9MhF;;A8Dr9MI;EAAiC,gCAAkC;EAAlC,kCAAkC;A9Dy9MvE;;A8Dx9MI;EAAiC,8BAAgC;EAAhC,gCAAgC;A9D49MrE;;A8D39MI;EAAiC,iCAA8B;EAA9B,8BAA8B;A9D+9MnE;;A8D99MI;EAAiC,mCAAgC;EAAhC,gCAAgC;A9Dk+MrE;;A8Dj+MI;EAAiC,kCAA+B;EAA/B,+BAA+B;A9Dq+MpE;;A8Dn+MI;EAAkC,oCAAoC;EAApC,oCAAoC;A9Du+M1E;;A8Dt+MI;EAAkC,kCAAkC;EAAlC,kCAAkC;A9D0+MxE;;A8Dz+MI;EAAkC,qCAAgC;EAAhC,gCAAgC;A9D6+MtE;;A8D5+MI;EAAkC,sCAAuC;EAAvC,uCAAuC;A9Dg/M7E;;A8D/+MI;EAAkC,yCAAsC;EAAtC,sCAAsC;A9Dm/M5E;;A8Dl/MI;EAAkC,sCAAiC;EAAjC,iCAAiC;A9Ds/MvE;;A8Dp/MI;EAAgC,oCAA2B;EAA3B,2BAA2B;A9Dw/M/D;;A8Dv/MI;EAAgC,qCAAiC;EAAjC,iCAAiC;A9D2/MrE;;A8D1/MI;EAAgC,mCAA+B;EAA/B,+BAA+B;A9D8/MnE;;A8D7/MI;EAAgC,sCAA6B;EAA7B,6BAA6B;A9DigNjE;;A8DhgNI;EAAgC,wCAA+B;EAA/B,+BAA+B;A9DogNnE;;A8DngNI;EAAgC,uCAA8B;EAA9B,8BAA8B;A9DugNlE;;Ac3/MI;EgDlDA;IAAgC,kCAA8B;IAA9B,8BAA8B;E9DkjNhE;E8DjjNE;IAAgC,qCAAiC;IAAjC,iCAAiC;E9DojNnE;E8DnjNE;IAAgC,0CAAsC;IAAtC,sCAAsC;E9DsjNxE;E8DrjNE;IAAgC,6CAAyC;IAAzC,yCAAyC;E9DwjN3E;E8DtjNE;IAA8B,8BAA0B;IAA1B,0BAA0B;E9DyjN1D;E8DxjNE;IAA8B,gCAA4B;IAA5B,4BAA4B;E9D2jN5D;E8D1jNE;IAA8B,sCAAkC;IAAlC,kCAAkC;E9D6jNlE;E8D5jNE;IAA8B,6BAAyB;IAAzB,yBAAyB;E9D+jNzD;E8D9jNE;IAA8B,+BAAuB;IAAvB,uBAAuB;E9DikNvD;E8DhkNE;IAA8B,+BAAuB;IAAvB,uBAAuB;E9DmkNvD;E8DlkNE;IAA8B,+BAAyB;IAAzB,yBAAyB;E9DqkNzD;E8DpkNE;IAA8B,+BAAyB;IAAzB,yBAAyB;E9DukNzD;E8DrkNE;IAAoC,+BAAsC;IAAtC,sCAAsC;E9DwkN5E;E8DvkNE;IAAoC,6BAAoC;IAApC,oCAAoC;E9D0kN1E;E8DzkNE;IAAoC,gCAAkC;IAAlC,kCAAkC;E9D4kNxE;E8D3kNE;IAAoC,iCAAyC;IAAzC,yCAAyC;E9D8kN/E;E8D7kNE;IAAoC,oCAAwC;IAAxC,wCAAwC;E9DglN9E;E8D9kNE;IAAiC,gCAAkC;IAAlC,kCAAkC;E9DilNrE;E8DhlNE;IAAiC,8BAAgC;IAAhC,gCAAgC;E9DmlNnE;E8DllNE;IAAiC,iCAA8B;IAA9B,8BAA8B;E9DqlNjE;E8DplNE;IAAiC,mCAAgC;IAAhC,gCAAgC;E9DulNnE;E8DtlNE;IAAiC,kCAA+B;IAA/B,+BAA+B;E9DylNlE;E8DvlNE;IAAkC,oCAAoC;IAApC,oCAAoC;E9D0lNxE;E8DzlNE;IAAkC,kCAAkC;IAAlC,kCAAkC;E9D4lNtE;E8D3lNE;IAAkC,qCAAgC;IAAhC,gCAAgC;E9D8lNpE;E8D7lNE;IAAkC,sCAAuC;IAAvC,uCAAuC;E9DgmN3E;E8D/lNE;IAAkC,yCAAsC;IAAtC,sCAAsC;E9DkmN1E;E8DjmNE;IAAkC,sCAAiC;IAAjC,iCAAiC;E9DomNrE;E8DlmNE;IAAgC,oCAA2B;IAA3B,2BAA2B;E9DqmN7D;E8DpmNE;IAAgC,qCAAiC;IAAjC,iCAAiC;E9DumNnE;E8DtmNE;IAAgC,mCAA+B;IAA/B,+BAA+B;E9DymNjE;E8DxmNE;IAAgC,sCAA6B;IAA7B,6BAA6B;E9D2mN/D;E8D1mNE;IAAgC,wCAA+B;IAA/B,+BAA+B;E9D6mNjE;E8D5mNE;IAAgC,uCAA8B;IAA9B,8BAA8B;E9D+mNhE;AACF;;AcpmNI;EgDlDA;IAAgC,kCAA8B;IAA9B,8BAA8B;E9D2pNhE;E8D1pNE;IAAgC,qCAAiC;IAAjC,iCAAiC;E9D6pNnE;E8D5pNE;IAAgC,0CAAsC;IAAtC,sCAAsC;E9D+pNxE;E8D9pNE;IAAgC,6CAAyC;IAAzC,yCAAyC;E9DiqN3E;E8D/pNE;IAA8B,8BAA0B;IAA1B,0BAA0B;E9DkqN1D;E8DjqNE;IAA8B,gCAA4B;IAA5B,4BAA4B;E9DoqN5D;E8DnqNE;IAA8B,sCAAkC;IAAlC,kCAAkC;E9DsqNlE;E8DrqNE;IAA8B,6BAAyB;IAAzB,yBAAyB;E9DwqNzD;E8DvqNE;IAA8B,+BAAuB;IAAvB,uBAAuB;E9D0qNvD;E8DzqNE;IAA8B,+BAAuB;IAAvB,uBAAuB;E9D4qNvD;E8D3qNE;IAA8B,+BAAyB;IAAzB,yBAAyB;E9D8qNzD;E8D7qNE;IAA8B,+BAAyB;IAAzB,yBAAyB;E9DgrNzD;E8D9qNE;IAAoC,+BAAsC;IAAtC,sCAAsC;E9DirN5E;E8DhrNE;IAAoC,6BAAoC;IAApC,oCAAoC;E9DmrN1E;E8DlrNE;IAAoC,gCAAkC;IAAlC,kCAAkC;E9DqrNxE;E8DprNE;IAAoC,iCAAyC;IAAzC,yCAAyC;E9DurN/E;E8DtrNE;IAAoC,oCAAwC;IAAxC,wCAAwC;E9DyrN9E;E8DvrNE;IAAiC,gCAAkC;IAAlC,kCAAkC;E9D0rNrE;E8DzrNE;IAAiC,8BAAgC;IAAhC,gCAAgC;E9D4rNnE;E8D3rNE;IAAiC,iCAA8B;IAA9B,8BAA8B;E9D8rNjE;E8D7rNE;IAAiC,mCAAgC;IAAhC,gCAAgC;E9DgsNnE;E8D/rNE;IAAiC,kCAA+B;IAA/B,+BAA+B;E9DksNlE;E8DhsNE;IAAkC,oCAAoC;IAApC,oCAAoC;E9DmsNxE;E8DlsNE;IAAkC,kCAAkC;IAAlC,kCAAkC;E9DqsNtE;E8DpsNE;IAAkC,qCAAgC;IAAhC,gCAAgC;E9DusNpE;E8DtsNE;IAAkC,sCAAuC;IAAvC,uCAAuC;E9DysN3E;E8DxsNE;IAAkC,yCAAsC;IAAtC,sCAAsC;E9D2sN1E;E8D1sNE;IAAkC,sCAAiC;IAAjC,iCAAiC;E9D6sNrE;E8D3sNE;IAAgC,oCAA2B;IAA3B,2BAA2B;E9D8sN7D;E8D7sNE;IAAgC,qCAAiC;IAAjC,iCAAiC;E9DgtNnE;E8D/sNE;IAAgC,mCAA+B;IAA/B,+BAA+B;E9DktNjE;E8DjtNE;IAAgC,sCAA6B;IAA7B,6BAA6B;E9DotN/D;E8DntNE;IAAgC,wCAA+B;IAA/B,+BAA+B;E9DstNjE;E8DrtNE;IAAgC,uCAA8B;IAA9B,8BAA8B;E9DwtNhE;AACF;;Ac7sNI;EgDlDA;IAAgC,kCAA8B;IAA9B,8BAA8B;E9DowNhE;E8DnwNE;IAAgC,qCAAiC;IAAjC,iCAAiC;E9DswNnE;E8DrwNE;IAAgC,0CAAsC;IAAtC,sCAAsC;E9DwwNxE;E8DvwNE;IAAgC,6CAAyC;IAAzC,yCAAyC;E9D0wN3E;E8DxwNE;IAA8B,8BAA0B;IAA1B,0BAA0B;E9D2wN1D;E8D1wNE;IAA8B,gCAA4B;IAA5B,4BAA4B;E9D6wN5D;E8D5wNE;IAA8B,sCAAkC;IAAlC,kCAAkC;E9D+wNlE;E8D9wNE;IAA8B,6BAAyB;IAAzB,yBAAyB;E9DixNzD;E8DhxNE;IAA8B,+BAAuB;IAAvB,uBAAuB;E9DmxNvD;E8DlxNE;IAA8B,+BAAuB;IAAvB,uBAAuB;E9DqxNvD;E8DpxNE;IAA8B,+BAAyB;IAAzB,yBAAyB;E9DuxNzD;E8DtxNE;IAA8B,+BAAyB;IAAzB,yBAAyB;E9DyxNzD;E8DvxNE;IAAoC,+BAAsC;IAAtC,sCAAsC;E9D0xN5E;E8DzxNE;IAAoC,6BAAoC;IAApC,oCAAoC;E9D4xN1E;E8D3xNE;IAAoC,gCAAkC;IAAlC,kCAAkC;E9D8xNxE;E8D7xNE;IAAoC,iCAAyC;IAAzC,yCAAyC;E9DgyN/E;E8D/xNE;IAAoC,oCAAwC;IAAxC,wCAAwC;E9DkyN9E;E8DhyNE;IAAiC,gCAAkC;IAAlC,kCAAkC;E9DmyNrE;E8DlyNE;IAAiC,8BAAgC;IAAhC,gCAAgC;E9DqyNnE;E8DpyNE;IAAiC,iCAA8B;IAA9B,8BAA8B;E9DuyNjE;E8DtyNE;IAAiC,mCAAgC;IAAhC,gCAAgC;E9DyyNnE;E8DxyNE;IAAiC,kCAA+B;IAA/B,+BAA+B;E9D2yNlE;E8DzyNE;IAAkC,oCAAoC;IAApC,oCAAoC;E9D4yNxE;E8D3yNE;IAAkC,kCAAkC;IAAlC,kCAAkC;E9D8yNtE;E8D7yNE;IAAkC,qCAAgC;IAAhC,gCAAgC;E9DgzNpE;E8D/yNE;IAAkC,sCAAuC;IAAvC,uCAAuC;E9DkzN3E;E8DjzNE;IAAkC,yCAAsC;IAAtC,sCAAsC;E9DozN1E;E8DnzNE;IAAkC,sCAAiC;IAAjC,iCAAiC;E9DszNrE;E8DpzNE;IAAgC,oCAA2B;IAA3B,2BAA2B;E9DuzN7D;E8DtzNE;IAAgC,qCAAiC;IAAjC,iCAAiC;E9DyzNnE;E8DxzNE;IAAgC,mCAA+B;IAA/B,+BAA+B;E9D2zNjE;E8D1zNE;IAAgC,sCAA6B;IAA7B,6BAA6B;E9D6zN/D;E8D5zNE;IAAgC,wCAA+B;IAA/B,+BAA+B;E9D+zNjE;E8D9zNE;IAAgC,uCAA8B;IAA9B,8BAA8B;E9Di0NhE;AACF;;ActzNI;EgDlDA;IAAgC,kCAA8B;IAA9B,8BAA8B;E9D62NhE;E8D52NE;IAAgC,qCAAiC;IAAjC,iCAAiC;E9D+2NnE;E8D92NE;IAAgC,0CAAsC;IAAtC,sCAAsC;E9Di3NxE;E8Dh3NE;IAAgC,6CAAyC;IAAzC,yCAAyC;E9Dm3N3E;E8Dj3NE;IAA8B,8BAA0B;IAA1B,0BAA0B;E9Do3N1D;E8Dn3NE;IAA8B,gCAA4B;IAA5B,4BAA4B;E9Ds3N5D;E8Dr3NE;IAA8B,sCAAkC;IAAlC,kCAAkC;E9Dw3NlE;E8Dv3NE;IAA8B,6BAAyB;IAAzB,yBAAyB;E9D03NzD;E8Dz3NE;IAA8B,+BAAuB;IAAvB,uBAAuB;E9D43NvD;E8D33NE;IAA8B,+BAAuB;IAAvB,uBAAuB;E9D83NvD;E8D73NE;IAA8B,+BAAyB;IAAzB,yBAAyB;E9Dg4NzD;E8D/3NE;IAA8B,+BAAyB;IAAzB,yBAAyB;E9Dk4NzD;E8Dh4NE;IAAoC,+BAAsC;IAAtC,sCAAsC;E9Dm4N5E;E8Dl4NE;IAAoC,6BAAoC;IAApC,oCAAoC;E9Dq4N1E;E8Dp4NE;IAAoC,gCAAkC;IAAlC,kCAAkC;E9Du4NxE;E8Dt4NE;IAAoC,iCAAyC;IAAzC,yCAAyC;E9Dy4N/E;E8Dx4NE;IAAoC,oCAAwC;IAAxC,wCAAwC;E9D24N9E;E8Dz4NE;IAAiC,gCAAkC;IAAlC,kCAAkC;E9D44NrE;E8D34NE;IAAiC,8BAAgC;IAAhC,gCAAgC;E9D84NnE;E8D74NE;IAAiC,iCAA8B;IAA9B,8BAA8B;E9Dg5NjE;E8D/4NE;IAAiC,mCAAgC;IAAhC,gCAAgC;E9Dk5NnE;E8Dj5NE;IAAiC,kCAA+B;IAA/B,+BAA+B;E9Do5NlE;E8Dl5NE;IAAkC,oCAAoC;IAApC,oCAAoC;E9Dq5NxE;E8Dp5NE;IAAkC,kCAAkC;IAAlC,kCAAkC;E9Du5NtE;E8Dt5NE;IAAkC,qCAAgC;IAAhC,gCAAgC;E9Dy5NpE;E8Dx5NE;IAAkC,sCAAuC;IAAvC,uCAAuC;E9D25N3E;E8D15NE;IAAkC,yCAAsC;IAAtC,sCAAsC;E9D65N1E;E8D55NE;IAAkC,sCAAiC;IAAjC,iCAAiC;E9D+5NrE;E8D75NE;IAAgC,oCAA2B;IAA3B,2BAA2B;E9Dg6N7D;E8D/5NE;IAAgC,qCAAiC;IAAjC,iCAAiC;E9Dk6NnE;E8Dj6NE;IAAgC,mCAA+B;IAA/B,+BAA+B;E9Do6NjE;E8Dn6NE;IAAgC,sCAA6B;IAA7B,6BAA6B;E9Ds6N/D;E8Dr6NE;IAAgC,wCAA+B;IAA/B,+BAA+B;E9Dw6NjE;E8Dv6NE;IAAgC,uCAA8B;IAA9B,8BAA8B;E9D06NhE;AACF;;A+Dr9NI;EAAwB,sBAAsB;A/Dy9NlD;;A+Dx9NI;EAAwB,uBAAuB;A/D49NnD;;A+D39NI;EAAwB,sBAAsB;A/D+9NlD;;Ac36NI;EiDtDA;IAAwB,sBAAsB;E/Ds+NhD;E+Dr+NE;IAAwB,uBAAuB;E/Dw+NjD;E+Dv+NE;IAAwB,sBAAsB;E/D0+NhD;AACF;;Acv7NI;EiDtDA;IAAwB,sBAAsB;E/Dk/NhD;E+Dj/NE;IAAwB,uBAAuB;E/Do/NjD;E+Dn/NE;IAAwB,sBAAsB;E/Ds/NhD;AACF;;Acn8NI;EiDtDA;IAAwB,sBAAsB;E/D8/NhD;E+D7/NE;IAAwB,uBAAuB;E/DggOjD;E+D//NE;IAAwB,sBAAsB;E/DkgOhD;AACF;;Ac/8NI;EiDtDA;IAAwB,sBAAsB;E/D0gOhD;E+DzgOE;IAAwB,uBAAuB;E/D4gOjD;E+D3gOE;IAAwB,sBAAsB;E/D8gOhD;AACF;;AgEphOE;EAAsB,yBAA2B;AhEwhOnD;;AgExhOE;EAAsB,2BAA2B;AhE4hOnD;;AiE3hOE;EAAyB,2BAA8B;AjE+hOzD;;AiE/hOE;EAAyB,6BAA8B;AjEmiOzD;;AiEniOE;EAAyB,6BAA8B;AjEuiOzD;;AiEviOE;EAAyB,0BAA8B;AjE2iOzD;;AiE3iOE;EAAyB,mCAA8B;EAA9B,2BAA8B;AjE+iOzD;;AiE1iOA;EACE,eAAe;EACf,MAAM;EACN,QAAQ;EACR,OAAO;EACP,a9DypBsC;AHo5MxC;;AiE1iOA;EACE,eAAe;EACf,QAAQ;EACR,SAAS;EACT,OAAO;EACP,a9DipBsC;AH45MxC;;AiEziO8B;EAD9B;IAEI,wBAAgB;IAAhB,gBAAgB;IAChB,MAAM;IACN,a9DyoBoC;EHo6MtC;AACF;;AkEvkOA;ECEE,kBAAkB;EAClB,UAAU;EACV,WAAW;EACX,UAAU;EACV,gBAAgB;EAChB,sBAAsB;EACtB,mBAAmB;EACnB,SAAS;AnEykOX;;AmE/jOE;EAEE,gBAAgB;EAChB,WAAW;EACX,YAAY;EACZ,iBAAiB;EACjB,UAAU;EACV,mBAAmB;AnEikOvB;;AoE7lOA;EAAa,8DAAqC;ApEimOlD;;AoEhmOA;EAAU,wDAAkC;ApEomO5C;;AoEnmOA;EAAa,uDAAqC;ApEumOlD;;AoEtmOA;EAAe,2BAA2B;ApE0mO1C;;AqEzmOI;EAAuB,qBAA4B;ArE6mOvD;;AqE7mOI;EAAuB,qBAA4B;ArEinOvD;;AqEjnOI;EAAuB,qBAA4B;ArEqnOvD;;AqErnOI;EAAuB,sBAA4B;ArEynOvD;;AqEznOI;EAAuB,sBAA4B;ArE6nOvD;;AqE7nOI;EAAuB,sBAA4B;ArEioOvD;;AqEjoOI;EAAuB,sBAA4B;ArEqoOvD;;AqEroOI;EAAuB,sBAA4B;ArEyoOvD;;AqEzoOI;EAAuB,uBAA4B;ArE6oOvD;;AqE7oOI;EAAuB,uBAA4B;ArEipOvD;;AqE7oOA;EAAU,0BAA0B;ArEipOpC;;AqEhpOA;EAAU,2BAA2B;ArEopOrC;;AqEhpOA;EAAc,2BAA2B;ArEopOzC;;AqEnpOA;EAAc,4BAA4B;ArEupO1C;;AqErpOA;EAAU,uBAAuB;ArEypOjC;;AqExpOA;EAAU,wBAAwB;ArE4pOlC;;AsE3qOA;EAEI,kBAAkB;EAClB,MAAM;EACN,QAAQ;EACR,SAAS;EACT,OAAO;EACP,UAAU;EAEV,oBAAoB;EACpB,WAAW;EAEX,kCAAkC;AtE2qOtC;;AuEjrOQ;EAAgC,oBAA4B;AvEqrOpE;;AuEprOQ;;EAEE,wBAAoC;AvEurO9C;;AuErrOQ;;EAEE,0BAAwC;AvEwrOlD;;AuEtrOQ;;EAEE,2BAA0C;AvEyrOpD;;AuEvrOQ;;EAEE,yBAAsC;AvE0rOhD;;AuEzsOQ;EAAgC,0BAA4B;AvE6sOpE;;AuE5sOQ;;EAEE,8BAAoC;AvE+sO9C;;AuE7sOQ;;EAEE,gCAAwC;AvEgtOlD;;AuE9sOQ;;EAEE,iCAA0C;AvEitOpD;;AuE/sOQ;;EAEE,+BAAsC;AvEktOhD;;AuEjuOQ;EAAgC,yBAA4B;AvEquOpE;;AuEpuOQ;;EAEE,6BAAoC;AvEuuO9C;;AuEruOQ;;EAEE,+BAAwC;AvEwuOlD;;AuEtuOQ;;EAEE,gCAA0C;AvEyuOpD;;AuEvuOQ;;EAEE,8BAAsC;AvE0uOhD;;AuEzvOQ;EAAgC,uBAA4B;AvE6vOpE;;AuE5vOQ;;EAEE,2BAAoC;AvE+vO9C;;AuE7vOQ;;EAEE,6BAAwC;AvEgwOlD;;AuE9vOQ;;EAEE,8BAA0C;AvEiwOpD;;AuE/vOQ;;EAEE,4BAAsC;AvEkwOhD;;AuEjxOQ;EAAgC,yBAA4B;AvEqxOpE;;AuEpxOQ;;EAEE,6BAAoC;AvEuxO9C;;AuErxOQ;;EAEE,+BAAwC;AvEwxOlD;;AuEtxOQ;;EAEE,gCAA0C;AvEyxOpD;;AuEvxOQ;;EAEE,8BAAsC;AvE0xOhD;;AuEzyOQ;EAAgC,uBAA4B;AvE6yOpE;;AuE5yOQ;;EAEE,2BAAoC;AvE+yO9C;;AuE7yOQ;;EAEE,6BAAwC;AvEgzOlD;;AuE9yOQ;;EAEE,8BAA0C;AvEizOpD;;AuE/yOQ;;EAEE,4BAAsC;AvEkzOhD;;AuEj0OQ;EAAgC,qBAA4B;AvEq0OpE;;AuEp0OQ;;EAEE,yBAAoC;AvEu0O9C;;AuEr0OQ;;EAEE,2BAAwC;AvEw0OlD;;AuEt0OQ;;EAEE,4BAA0C;AvEy0OpD;;AuEv0OQ;;EAEE,0BAAsC;AvE00OhD;;AuEz1OQ;EAAgC,2BAA4B;AvE61OpE;;AuE51OQ;;EAEE,+BAAoC;AvE+1O9C;;AuE71OQ;;EAEE,iCAAwC;AvEg2OlD;;AuE91OQ;;EAEE,kCAA0C;AvEi2OpD;;AuE/1OQ;;EAEE,gCAAsC;AvEk2OhD;;AuEj3OQ;EAAgC,0BAA4B;AvEq3OpE;;AuEp3OQ;;EAEE,8BAAoC;AvEu3O9C;;AuEr3OQ;;EAEE,gCAAwC;AvEw3OlD;;AuEt3OQ;;EAEE,iCAA0C;AvEy3OpD;;AuEv3OQ;;EAEE,+BAAsC;AvE03OhD;;AuEz4OQ;EAAgC,wBAA4B;AvE64OpE;;AuE54OQ;;EAEE,4BAAoC;AvE+4O9C;;AuE74OQ;;EAEE,8BAAwC;AvEg5OlD;;AuE94OQ;;EAEE,+BAA0C;AvEi5OpD;;AuE/4OQ;;EAEE,6BAAsC;AvEk5OhD;;AuEj6OQ;EAAgC,0BAA4B;AvEq6OpE;;AuEp6OQ;;EAEE,8BAAoC;AvEu6O9C;;AuEr6OQ;;EAEE,gCAAwC;AvEw6OlD;;AuEt6OQ;;EAEE,iCAA0C;AvEy6OpD;;AuEv6OQ;;EAEE,+BAAsC;AvE06OhD;;AuEz7OQ;EAAgC,wBAA4B;AvE67OpE;;AuE57OQ;;EAEE,4BAAoC;AvE+7O9C;;AuE77OQ;;EAEE,8BAAwC;AvEg8OlD;;AuE97OQ;;EAEE,+BAA0C;AvEi8OpD;;AuE/7OQ;;EAEE,6BAAsC;AvEk8OhD;;AuE17OQ;EAAwB,2BAA2B;AvE87O3D;;AuE77OQ;;EAEE,+BAA+B;AvEg8OzC;;AuE97OQ;;EAEE,iCAAiC;AvEi8O3C;;AuE/7OQ;;EAEE,kCAAkC;AvEk8O5C;;AuEh8OQ;;EAEE,gCAAgC;AvEm8O1C;;AuEl9OQ;EAAwB,0BAA2B;AvEs9O3D;;AuEr9OQ;;EAEE,8BAA+B;AvEw9OzC;;AuEt9OQ;;EAEE,gCAAiC;AvEy9O3C;;AuEv9OQ;;EAEE,iCAAkC;AvE09O5C;;AuEx9OQ;;EAEE,+BAAgC;AvE29O1C;;AuE1+OQ;EAAwB,wBAA2B;AvE8+O3D;;AuE7+OQ;;EAEE,4BAA+B;AvEg/OzC;;AuE9+OQ;;EAEE,8BAAiC;AvEi/O3C;;AuE/+OQ;;EAEE,+BAAkC;AvEk/O5C;;AuEh/OQ;;EAEE,6BAAgC;AvEm/O1C;;AuElgPQ;EAAwB,0BAA2B;AvEsgP3D;;AuErgPQ;;EAEE,8BAA+B;AvEwgPzC;;AuEtgPQ;;EAEE,gCAAiC;AvEygP3C;;AuEvgPQ;;EAEE,iCAAkC;AvE0gP5C;;AuExgPQ;;EAEE,+BAAgC;AvE2gP1C;;AuE1hPQ;EAAwB,wBAA2B;AvE8hP3D;;AuE7hPQ;;EAEE,4BAA+B;AvEgiPzC;;AuE9hPQ;;EAEE,8BAAiC;AvEiiP3C;;AuE/hPQ;;EAEE,+BAAkC;AvEkiP5C;;AuEhiPQ;;EAEE,6BAAgC;AvEmiP1C;;AuE7hPI;EAAmB,uBAAuB;AvEiiP9C;;AuEhiPI;;EAEE,2BAA2B;AvEmiPjC;;AuEjiPI;;EAEE,6BAA6B;AvEoiPnC;;AuEliPI;;EAEE,8BAA8B;AvEqiPpC;;AuEniPI;;EAEE,4BAA4B;AvEsiPlC;;Ac/iPI;EyDlDI;IAAgC,oBAA4B;EvEsmPlE;EuErmPM;;IAEE,wBAAoC;EvEumP5C;EuErmPM;;IAEE,0BAAwC;EvEumPhD;EuErmPM;;IAEE,2BAA0C;EvEumPlD;EuErmPM;;IAEE,yBAAsC;EvEumP9C;EuEtnPM;IAAgC,0BAA4B;EvEynPlE;EuExnPM;;IAEE,8BAAoC;EvE0nP5C;EuExnPM;;IAEE,gCAAwC;EvE0nPhD;EuExnPM;;IAEE,iCAA0C;EvE0nPlD;EuExnPM;;IAEE,+BAAsC;EvE0nP9C;EuEzoPM;IAAgC,yBAA4B;EvE4oPlE;EuE3oPM;;IAEE,6BAAoC;EvE6oP5C;EuE3oPM;;IAEE,+BAAwC;EvE6oPhD;EuE3oPM;;IAEE,gCAA0C;EvE6oPlD;EuE3oPM;;IAEE,8BAAsC;EvE6oP9C;EuE5pPM;IAAgC,uBAA4B;EvE+pPlE;EuE9pPM;;IAEE,2BAAoC;EvEgqP5C;EuE9pPM;;IAEE,6BAAwC;EvEgqPhD;EuE9pPM;;IAEE,8BAA0C;EvEgqPlD;EuE9pPM;;IAEE,4BAAsC;EvEgqP9C;EuE/qPM;IAAgC,yBAA4B;EvEkrPlE;EuEjrPM;;IAEE,6BAAoC;EvEmrP5C;EuEjrPM;;IAEE,+BAAwC;EvEmrPhD;EuEjrPM;;IAEE,gCAA0C;EvEmrPlD;EuEjrPM;;IAEE,8BAAsC;EvEmrP9C;EuElsPM;IAAgC,uBAA4B;EvEqsPlE;EuEpsPM;;IAEE,2BAAoC;EvEssP5C;EuEpsPM;;IAEE,6BAAwC;EvEssPhD;EuEpsPM;;IAEE,8BAA0C;EvEssPlD;EuEpsPM;;IAEE,4BAAsC;EvEssP9C;EuErtPM;IAAgC,qBAA4B;EvEwtPlE;EuEvtPM;;IAEE,yBAAoC;EvEytP5C;EuEvtPM;;IAEE,2BAAwC;EvEytPhD;EuEvtPM;;IAEE,4BAA0C;EvEytPlD;EuEvtPM;;IAEE,0BAAsC;EvEytP9C;EuExuPM;IAAgC,2BAA4B;EvE2uPlE;EuE1uPM;;IAEE,+BAAoC;EvE4uP5C;EuE1uPM;;IAEE,iCAAwC;EvE4uPhD;EuE1uPM;;IAEE,kCAA0C;EvE4uPlD;EuE1uPM;;IAEE,gCAAsC;EvE4uP9C;EuE3vPM;IAAgC,0BAA4B;EvE8vPlE;EuE7vPM;;IAEE,8BAAoC;EvE+vP5C;EuE7vPM;;IAEE,gCAAwC;EvE+vPhD;EuE7vPM;;IAEE,iCAA0C;EvE+vPlD;EuE7vPM;;IAEE,+BAAsC;EvE+vP9C;EuE9wPM;IAAgC,wBAA4B;EvEixPlE;EuEhxPM;;IAEE,4BAAoC;EvEkxP5C;EuEhxPM;;IAEE,8BAAwC;EvEkxPhD;EuEhxPM;;IAEE,+BAA0C;EvEkxPlD;EuEhxPM;;IAEE,6BAAsC;EvEkxP9C;EuEjyPM;IAAgC,0BAA4B;EvEoyPlE;EuEnyPM;;IAEE,8BAAoC;EvEqyP5C;EuEnyPM;;IAEE,gCAAwC;EvEqyPhD;EuEnyPM;;IAEE,iCAA0C;EvEqyPlD;EuEnyPM;;IAEE,+BAAsC;EvEqyP9C;EuEpzPM;IAAgC,wBAA4B;EvEuzPlE;EuEtzPM;;IAEE,4BAAoC;EvEwzP5C;EuEtzPM;;IAEE,8BAAwC;EvEwzPhD;EuEtzPM;;IAEE,+BAA0C;EvEwzPlD;EuEtzPM;;IAEE,6BAAsC;EvEwzP9C;EuEhzPM;IAAwB,2BAA2B;EvEmzPzD;EuElzPM;;IAEE,+BAA+B;EvEozPvC;EuElzPM;;IAEE,iCAAiC;EvEozPzC;EuElzPM;;IAEE,kCAAkC;EvEozP1C;EuElzPM;;IAEE,gCAAgC;EvEozPxC;EuEn0PM;IAAwB,0BAA2B;EvEs0PzD;EuEr0PM;;IAEE,8BAA+B;EvEu0PvC;EuEr0PM;;IAEE,gCAAiC;EvEu0PzC;EuEr0PM;;IAEE,iCAAkC;EvEu0P1C;EuEr0PM;;IAEE,+BAAgC;EvEu0PxC;EuEt1PM;IAAwB,wBAA2B;EvEy1PzD;EuEx1PM;;IAEE,4BAA+B;EvE01PvC;EuEx1PM;;IAEE,8BAAiC;EvE01PzC;EuEx1PM;;IAEE,+BAAkC;EvE01P1C;EuEx1PM;;IAEE,6BAAgC;EvE01PxC;EuEz2PM;IAAwB,0BAA2B;EvE42PzD;EuE32PM;;IAEE,8BAA+B;EvE62PvC;EuE32PM;;IAEE,gCAAiC;EvE62PzC;EuE32PM;;IAEE,iCAAkC;EvE62P1C;EuE32PM;;IAEE,+BAAgC;EvE62PxC;EuE53PM;IAAwB,wBAA2B;EvE+3PzD;EuE93PM;;IAEE,4BAA+B;EvEg4PvC;EuE93PM;;IAEE,8BAAiC;EvEg4PzC;EuE93PM;;IAEE,+BAAkC;EvEg4P1C;EuE93PM;;IAEE,6BAAgC;EvEg4PxC;EuE13PE;IAAmB,uBAAuB;EvE63P5C;EuE53PE;;IAEE,2BAA2B;EvE83P/B;EuE53PE;;IAEE,6BAA6B;EvE83PjC;EuE53PE;;IAEE,8BAA8B;EvE83PlC;EuE53PE;;IAEE,4BAA4B;EvE83PhC;AACF;;Acx4PI;EyDlDI;IAAgC,oBAA4B;EvE+7PlE;EuE97PM;;IAEE,wBAAoC;EvEg8P5C;EuE97PM;;IAEE,0BAAwC;EvEg8PhD;EuE97PM;;IAEE,2BAA0C;EvEg8PlD;EuE97PM;;IAEE,yBAAsC;EvEg8P9C;EuE/8PM;IAAgC,0BAA4B;EvEk9PlE;EuEj9PM;;IAEE,8BAAoC;EvEm9P5C;EuEj9PM;;IAEE,gCAAwC;EvEm9PhD;EuEj9PM;;IAEE,iCAA0C;EvEm9PlD;EuEj9PM;;IAEE,+BAAsC;EvEm9P9C;EuEl+PM;IAAgC,yBAA4B;EvEq+PlE;EuEp+PM;;IAEE,6BAAoC;EvEs+P5C;EuEp+PM;;IAEE,+BAAwC;EvEs+PhD;EuEp+PM;;IAEE,gCAA0C;EvEs+PlD;EuEp+PM;;IAEE,8BAAsC;EvEs+P9C;EuEr/PM;IAAgC,uBAA4B;EvEw/PlE;EuEv/PM;;IAEE,2BAAoC;EvEy/P5C;EuEv/PM;;IAEE,6BAAwC;EvEy/PhD;EuEv/PM;;IAEE,8BAA0C;EvEy/PlD;EuEv/PM;;IAEE,4BAAsC;EvEy/P9C;EuExgQM;IAAgC,yBAA4B;EvE2gQlE;EuE1gQM;;IAEE,6BAAoC;EvE4gQ5C;EuE1gQM;;IAEE,+BAAwC;EvE4gQhD;EuE1gQM;;IAEE,gCAA0C;EvE4gQlD;EuE1gQM;;IAEE,8BAAsC;EvE4gQ9C;EuE3hQM;IAAgC,uBAA4B;EvE8hQlE;EuE7hQM;;IAEE,2BAAoC;EvE+hQ5C;EuE7hQM;;IAEE,6BAAwC;EvE+hQhD;EuE7hQM;;IAEE,8BAA0C;EvE+hQlD;EuE7hQM;;IAEE,4BAAsC;EvE+hQ9C;EuE9iQM;IAAgC,qBAA4B;EvEijQlE;EuEhjQM;;IAEE,yBAAoC;EvEkjQ5C;EuEhjQM;;IAEE,2BAAwC;EvEkjQhD;EuEhjQM;;IAEE,4BAA0C;EvEkjQlD;EuEhjQM;;IAEE,0BAAsC;EvEkjQ9C;EuEjkQM;IAAgC,2BAA4B;EvEokQlE;EuEnkQM;;IAEE,+BAAoC;EvEqkQ5C;EuEnkQM;;IAEE,iCAAwC;EvEqkQhD;EuEnkQM;;IAEE,kCAA0C;EvEqkQlD;EuEnkQM;;IAEE,gCAAsC;EvEqkQ9C;EuEplQM;IAAgC,0BAA4B;EvEulQlE;EuEtlQM;;IAEE,8BAAoC;EvEwlQ5C;EuEtlQM;;IAEE,gCAAwC;EvEwlQhD;EuEtlQM;;IAEE,iCAA0C;EvEwlQlD;EuEtlQM;;IAEE,+BAAsC;EvEwlQ9C;EuEvmQM;IAAgC,wBAA4B;EvE0mQlE;EuEzmQM;;IAEE,4BAAoC;EvE2mQ5C;EuEzmQM;;IAEE,8BAAwC;EvE2mQhD;EuEzmQM;;IAEE,+BAA0C;EvE2mQlD;EuEzmQM;;IAEE,6BAAsC;EvE2mQ9C;EuE1nQM;IAAgC,0BAA4B;EvE6nQlE;EuE5nQM;;IAEE,8BAAoC;EvE8nQ5C;EuE5nQM;;IAEE,gCAAwC;EvE8nQhD;EuE5nQM;;IAEE,iCAA0C;EvE8nQlD;EuE5nQM;;IAEE,+BAAsC;EvE8nQ9C;EuE7oQM;IAAgC,wBAA4B;EvEgpQlE;EuE/oQM;;IAEE,4BAAoC;EvEipQ5C;EuE/oQM;;IAEE,8BAAwC;EvEipQhD;EuE/oQM;;IAEE,+BAA0C;EvEipQlD;EuE/oQM;;IAEE,6BAAsC;EvEipQ9C;EuEzoQM;IAAwB,2BAA2B;EvE4oQzD;EuE3oQM;;IAEE,+BAA+B;EvE6oQvC;EuE3oQM;;IAEE,iCAAiC;EvE6oQzC;EuE3oQM;;IAEE,kCAAkC;EvE6oQ1C;EuE3oQM;;IAEE,gCAAgC;EvE6oQxC;EuE5pQM;IAAwB,0BAA2B;EvE+pQzD;EuE9pQM;;IAEE,8BAA+B;EvEgqQvC;EuE9pQM;;IAEE,gCAAiC;EvEgqQzC;EuE9pQM;;IAEE,iCAAkC;EvEgqQ1C;EuE9pQM;;IAEE,+BAAgC;EvEgqQxC;EuE/qQM;IAAwB,wBAA2B;EvEkrQzD;EuEjrQM;;IAEE,4BAA+B;EvEmrQvC;EuEjrQM;;IAEE,8BAAiC;EvEmrQzC;EuEjrQM;;IAEE,+BAAkC;EvEmrQ1C;EuEjrQM;;IAEE,6BAAgC;EvEmrQxC;EuElsQM;IAAwB,0BAA2B;EvEqsQzD;EuEpsQM;;IAEE,8BAA+B;EvEssQvC;EuEpsQM;;IAEE,gCAAiC;EvEssQzC;EuEpsQM;;IAEE,iCAAkC;EvEssQ1C;EuEpsQM;;IAEE,+BAAgC;EvEssQxC;EuErtQM;IAAwB,wBAA2B;EvEwtQzD;EuEvtQM;;IAEE,4BAA+B;EvEytQvC;EuEvtQM;;IAEE,8BAAiC;EvEytQzC;EuEvtQM;;IAEE,+BAAkC;EvEytQ1C;EuEvtQM;;IAEE,6BAAgC;EvEytQxC;EuEntQE;IAAmB,uBAAuB;EvEstQ5C;EuErtQE;;IAEE,2BAA2B;EvEutQ/B;EuErtQE;;IAEE,6BAA6B;EvEutQjC;EuErtQE;;IAEE,8BAA8B;EvEutQlC;EuErtQE;;IAEE,4BAA4B;EvEutQhC;AACF;;AcjuQI;EyDlDI;IAAgC,oBAA4B;EvEwxQlE;EuEvxQM;;IAEE,wBAAoC;EvEyxQ5C;EuEvxQM;;IAEE,0BAAwC;EvEyxQhD;EuEvxQM;;IAEE,2BAA0C;EvEyxQlD;EuEvxQM;;IAEE,yBAAsC;EvEyxQ9C;EuExyQM;IAAgC,0BAA4B;EvE2yQlE;EuE1yQM;;IAEE,8BAAoC;EvE4yQ5C;EuE1yQM;;IAEE,gCAAwC;EvE4yQhD;EuE1yQM;;IAEE,iCAA0C;EvE4yQlD;EuE1yQM;;IAEE,+BAAsC;EvE4yQ9C;EuE3zQM;IAAgC,yBAA4B;EvE8zQlE;EuE7zQM;;IAEE,6BAAoC;EvE+zQ5C;EuE7zQM;;IAEE,+BAAwC;EvE+zQhD;EuE7zQM;;IAEE,gCAA0C;EvE+zQlD;EuE7zQM;;IAEE,8BAAsC;EvE+zQ9C;EuE90QM;IAAgC,uBAA4B;EvEi1QlE;EuEh1QM;;IAEE,2BAAoC;EvEk1Q5C;EuEh1QM;;IAEE,6BAAwC;EvEk1QhD;EuEh1QM;;IAEE,8BAA0C;EvEk1QlD;EuEh1QM;;IAEE,4BAAsC;EvEk1Q9C;EuEj2QM;IAAgC,yBAA4B;EvEo2QlE;EuEn2QM;;IAEE,6BAAoC;EvEq2Q5C;EuEn2QM;;IAEE,+BAAwC;EvEq2QhD;EuEn2QM;;IAEE,gCAA0C;EvEq2QlD;EuEn2QM;;IAEE,8BAAsC;EvEq2Q9C;EuEp3QM;IAAgC,uBAA4B;EvEu3QlE;EuEt3QM;;IAEE,2BAAoC;EvEw3Q5C;EuEt3QM;;IAEE,6BAAwC;EvEw3QhD;EuEt3QM;;IAEE,8BAA0C;EvEw3QlD;EuEt3QM;;IAEE,4BAAsC;EvEw3Q9C;EuEv4QM;IAAgC,qBAA4B;EvE04QlE;EuEz4QM;;IAEE,yBAAoC;EvE24Q5C;EuEz4QM;;IAEE,2BAAwC;EvE24QhD;EuEz4QM;;IAEE,4BAA0C;EvE24QlD;EuEz4QM;;IAEE,0BAAsC;EvE24Q9C;EuE15QM;IAAgC,2BAA4B;EvE65QlE;EuE55QM;;IAEE,+BAAoC;EvE85Q5C;EuE55QM;;IAEE,iCAAwC;EvE85QhD;EuE55QM;;IAEE,kCAA0C;EvE85QlD;EuE55QM;;IAEE,gCAAsC;EvE85Q9C;EuE76QM;IAAgC,0BAA4B;EvEg7QlE;EuE/6QM;;IAEE,8BAAoC;EvEi7Q5C;EuE/6QM;;IAEE,gCAAwC;EvEi7QhD;EuE/6QM;;IAEE,iCAA0C;EvEi7QlD;EuE/6QM;;IAEE,+BAAsC;EvEi7Q9C;EuEh8QM;IAAgC,wBAA4B;EvEm8QlE;EuEl8QM;;IAEE,4BAAoC;EvEo8Q5C;EuEl8QM;;IAEE,8BAAwC;EvEo8QhD;EuEl8QM;;IAEE,+BAA0C;EvEo8QlD;EuEl8QM;;IAEE,6BAAsC;EvEo8Q9C;EuEn9QM;IAAgC,0BAA4B;EvEs9QlE;EuEr9QM;;IAEE,8BAAoC;EvEu9Q5C;EuEr9QM;;IAEE,gCAAwC;EvEu9QhD;EuEr9QM;;IAEE,iCAA0C;EvEu9QlD;EuEr9QM;;IAEE,+BAAsC;EvEu9Q9C;EuEt+QM;IAAgC,wBAA4B;EvEy+QlE;EuEx+QM;;IAEE,4BAAoC;EvE0+Q5C;EuEx+QM;;IAEE,8BAAwC;EvE0+QhD;EuEx+QM;;IAEE,+BAA0C;EvE0+QlD;EuEx+QM;;IAEE,6BAAsC;EvE0+Q9C;EuEl+QM;IAAwB,2BAA2B;EvEq+QzD;EuEp+QM;;IAEE,+BAA+B;EvEs+QvC;EuEp+QM;;IAEE,iCAAiC;EvEs+QzC;EuEp+QM;;IAEE,kCAAkC;EvEs+Q1C;EuEp+QM;;IAEE,gCAAgC;EvEs+QxC;EuEr/QM;IAAwB,0BAA2B;EvEw/QzD;EuEv/QM;;IAEE,8BAA+B;EvEy/QvC;EuEv/QM;;IAEE,gCAAiC;EvEy/QzC;EuEv/QM;;IAEE,iCAAkC;EvEy/Q1C;EuEv/QM;;IAEE,+BAAgC;EvEy/QxC;EuExgRM;IAAwB,wBAA2B;EvE2gRzD;EuE1gRM;;IAEE,4BAA+B;EvE4gRvC;EuE1gRM;;IAEE,8BAAiC;EvE4gRzC;EuE1gRM;;IAEE,+BAAkC;EvE4gR1C;EuE1gRM;;IAEE,6BAAgC;EvE4gRxC;EuE3hRM;IAAwB,0BAA2B;EvE8hRzD;EuE7hRM;;IAEE,8BAA+B;EvE+hRvC;EuE7hRM;;IAEE,gCAAiC;EvE+hRzC;EuE7hRM;;IAEE,iCAAkC;EvE+hR1C;EuE7hRM;;IAEE,+BAAgC;EvE+hRxC;EuE9iRM;IAAwB,wBAA2B;EvEijRzD;EuEhjRM;;IAEE,4BAA+B;EvEkjRvC;EuEhjRM;;IAEE,8BAAiC;EvEkjRzC;EuEhjRM;;IAEE,+BAAkC;EvEkjR1C;EuEhjRM;;IAEE,6BAAgC;EvEkjRxC;EuE5iRE;IAAmB,uBAAuB;EvE+iR5C;EuE9iRE;;IAEE,2BAA2B;EvEgjR/B;EuE9iRE;;IAEE,6BAA6B;EvEgjRjC;EuE9iRE;;IAEE,8BAA8B;EvEgjRlC;EuE9iRE;;IAEE,4BAA4B;EvEgjRhC;AACF;;Ac1jRI;EyDlDI;IAAgC,oBAA4B;EvEinRlE;EuEhnRM;;IAEE,wBAAoC;EvEknR5C;EuEhnRM;;IAEE,0BAAwC;EvEknRhD;EuEhnRM;;IAEE,2BAA0C;EvEknRlD;EuEhnRM;;IAEE,yBAAsC;EvEknR9C;EuEjoRM;IAAgC,0BAA4B;EvEooRlE;EuEnoRM;;IAEE,8BAAoC;EvEqoR5C;EuEnoRM;;IAEE,gCAAwC;EvEqoRhD;EuEnoRM;;IAEE,iCAA0C;EvEqoRlD;EuEnoRM;;IAEE,+BAAsC;EvEqoR9C;EuEppRM;IAAgC,yBAA4B;EvEupRlE;EuEtpRM;;IAEE,6BAAoC;EvEwpR5C;EuEtpRM;;IAEE,+BAAwC;EvEwpRhD;EuEtpRM;;IAEE,gCAA0C;EvEwpRlD;EuEtpRM;;IAEE,8BAAsC;EvEwpR9C;EuEvqRM;IAAgC,uBAA4B;EvE0qRlE;EuEzqRM;;IAEE,2BAAoC;EvE2qR5C;EuEzqRM;;IAEE,6BAAwC;EvE2qRhD;EuEzqRM;;IAEE,8BAA0C;EvE2qRlD;EuEzqRM;;IAEE,4BAAsC;EvE2qR9C;EuE1rRM;IAAgC,yBAA4B;EvE6rRlE;EuE5rRM;;IAEE,6BAAoC;EvE8rR5C;EuE5rRM;;IAEE,+BAAwC;EvE8rRhD;EuE5rRM;;IAEE,gCAA0C;EvE8rRlD;EuE5rRM;;IAEE,8BAAsC;EvE8rR9C;EuE7sRM;IAAgC,uBAA4B;EvEgtRlE;EuE/sRM;;IAEE,2BAAoC;EvEitR5C;EuE/sRM;;IAEE,6BAAwC;EvEitRhD;EuE/sRM;;IAEE,8BAA0C;EvEitRlD;EuE/sRM;;IAEE,4BAAsC;EvEitR9C;EuEhuRM;IAAgC,qBAA4B;EvEmuRlE;EuEluRM;;IAEE,yBAAoC;EvEouR5C;EuEluRM;;IAEE,2BAAwC;EvEouRhD;EuEluRM;;IAEE,4BAA0C;EvEouRlD;EuEluRM;;IAEE,0BAAsC;EvEouR9C;EuEnvRM;IAAgC,2BAA4B;EvEsvRlE;EuErvRM;;IAEE,+BAAoC;EvEuvR5C;EuErvRM;;IAEE,iCAAwC;EvEuvRhD;EuErvRM;;IAEE,kCAA0C;EvEuvRlD;EuErvRM;;IAEE,gCAAsC;EvEuvR9C;EuEtwRM;IAAgC,0BAA4B;EvEywRlE;EuExwRM;;IAEE,8BAAoC;EvE0wR5C;EuExwRM;;IAEE,gCAAwC;EvE0wRhD;EuExwRM;;IAEE,iCAA0C;EvE0wRlD;EuExwRM;;IAEE,+BAAsC;EvE0wR9C;EuEzxRM;IAAgC,wBAA4B;EvE4xRlE;EuE3xRM;;IAEE,4BAAoC;EvE6xR5C;EuE3xRM;;IAEE,8BAAwC;EvE6xRhD;EuE3xRM;;IAEE,+BAA0C;EvE6xRlD;EuE3xRM;;IAEE,6BAAsC;EvE6xR9C;EuE5yRM;IAAgC,0BAA4B;EvE+yRlE;EuE9yRM;;IAEE,8BAAoC;EvEgzR5C;EuE9yRM;;IAEE,gCAAwC;EvEgzRhD;EuE9yRM;;IAEE,iCAA0C;EvEgzRlD;EuE9yRM;;IAEE,+BAAsC;EvEgzR9C;EuE/zRM;IAAgC,wBAA4B;EvEk0RlE;EuEj0RM;;IAEE,4BAAoC;EvEm0R5C;EuEj0RM;;IAEE,8BAAwC;EvEm0RhD;EuEj0RM;;IAEE,+BAA0C;EvEm0RlD;EuEj0RM;;IAEE,6BAAsC;EvEm0R9C;EuE3zRM;IAAwB,2BAA2B;EvE8zRzD;EuE7zRM;;IAEE,+BAA+B;EvE+zRvC;EuE7zRM;;IAEE,iCAAiC;EvE+zRzC;EuE7zRM;;IAEE,kCAAkC;EvE+zR1C;EuE7zRM;;IAEE,gCAAgC;EvE+zRxC;EuE90RM;IAAwB,0BAA2B;EvEi1RzD;EuEh1RM;;IAEE,8BAA+B;EvEk1RvC;EuEh1RM;;IAEE,gCAAiC;EvEk1RzC;EuEh1RM;;IAEE,iCAAkC;EvEk1R1C;EuEh1RM;;IAEE,+BAAgC;EvEk1RxC;EuEj2RM;IAAwB,wBAA2B;EvEo2RzD;EuEn2RM;;IAEE,4BAA+B;EvEq2RvC;EuEn2RM;;IAEE,8BAAiC;EvEq2RzC;EuEn2RM;;IAEE,+BAAkC;EvEq2R1C;EuEn2RM;;IAEE,6BAAgC;EvEq2RxC;EuEp3RM;IAAwB,0BAA2B;EvEu3RzD;EuEt3RM;;IAEE,8BAA+B;EvEw3RvC;EuEt3RM;;IAEE,gCAAiC;EvEw3RzC;EuEt3RM;;IAEE,iCAAkC;EvEw3R1C;EuEt3RM;;IAEE,+BAAgC;EvEw3RxC;EuEv4RM;IAAwB,wBAA2B;EvE04RzD;EuEz4RM;;IAEE,4BAA+B;EvE24RvC;EuEz4RM;;IAEE,8BAAiC;EvE24RzC;EuEz4RM;;IAEE,+BAAkC;EvE24R1C;EuEz4RM;;IAEE,6BAAgC;EvE24RxC;EuEr4RE;IAAmB,uBAAuB;EvEw4R5C;EuEv4RE;;IAEE,2BAA2B;EvEy4R/B;EuEv4RE;;IAEE,6BAA6B;EvEy4RjC;EuEv4RE;;IAEE,8BAA8B;EvEy4RlC;EuEv4RE;;IAEE,4BAA4B;EvEy4RhC;AACF;;AwEz8RA;EAAkB,4GAA8C;AxE68RhE;;AwEz8RA;EAAiB,8BAA8B;AxE68R/C;;AwE58RA;EAAiB,8BAA8B;AxEg9R/C;;AwE/8RA;EAAiB,8BAA8B;AxEm9R/C;;AwEl9RA;ECTE,gBAAgB;EAChB,uBAAuB;EACvB,mBAAmB;AzE+9RrB;;AwEh9RI;EAAwB,2BAA2B;AxEo9RvD;;AwEn9RI;EAAwB,4BAA4B;AxEu9RxD;;AwEt9RI;EAAwB,6BAA6B;AxE09RzD;;Acr7RI;E0DvCA;IAAwB,2BAA2B;ExEi+RrD;EwEh+RE;IAAwB,4BAA4B;ExEm+RtD;EwEl+RE;IAAwB,6BAA6B;ExEq+RvD;AACF;;Acj8RI;E0DvCA;IAAwB,2BAA2B;ExE6+RrD;EwE5+RE;IAAwB,4BAA4B;ExE++RtD;EwE9+RE;IAAwB,6BAA6B;ExEi/RvD;AACF;;Ac78RI;E0DvCA;IAAwB,2BAA2B;ExEy/RrD;EwEx/RE;IAAwB,4BAA4B;ExE2/RtD;EwE1/RE;IAAwB,6BAA6B;ExE6/RvD;AACF;;Acz9RI;E0DvCA;IAAwB,2BAA2B;ExEqgSrD;EwEpgSE;IAAwB,4BAA4B;ExEugStD;EwEtgSE;IAAwB,6BAA6B;ExEygSvD;AACF;;AwEpgSA;EAAmB,oCAAoC;AxEwgSvD;;AwEvgSA;EAAmB,oCAAoC;AxE2gSvD;;AwE1gSA;EAAmB,qCAAqC;AxE8gSxD;;AwE1gSA;EAAuB,2BAA0C;AxE8gSjE;;AwE7gSA;EAAuB,+BAA4C;AxEihSnE;;AwEhhSA;EAAuB,2BAA2C;AxEohSlE;;AwEnhSA;EAAuB,2BAAyC;AxEuhShE;;AwEthSA;EAAuB,8BAA2C;AxE0hSlE;;AwEzhSA;EAAuB,6BAA6B;AxE6hSpD;;AwEzhSA;EAAc,sBAAwB;AxE6hStC;;A0EpkSE;EACE,yBAAwB;A1EukS5B;;AK7jSE;EqELM,yBAA0E;A1EskSlF;;A0E5kSE;EACE,yBAAwB;A1E+kS5B;;AKrkSE;EqELM,yBAA0E;A1E8kSlF;;A0EplSE;EACE,yBAAwB;A1EulS5B;;AK7kSE;EqELM,yBAA0E;A1EslSlF;;A0E5lSE;EACE,yBAAwB;A1E+lS5B;;AKrlSE;EqELM,yBAA0E;A1E8lSlF;;A0EpmSE;EACE,yBAAwB;A1EumS5B;;AK7lSE;EqELM,yBAA0E;A1EsmSlF;;A0E5mSE;EACE,yBAAwB;A1E+mS5B;;AKrmSE;EqELM,yBAA0E;A1E8mSlF;;A0EpnSE;EACE,yBAAwB;A1EunS5B;;AK7mSE;EqELM,yBAA0E;A1EsnSlF;;A0E5nSE;EACE,yBAAwB;A1E+nS5B;;AKrnSE;EqELM,yBAA0E;A1E8nSlF;;AwEvlSA;EAAa,yBAA6B;AxE2lS1C;;AwE1lSA;EAAc,yBAA6B;AxE8lS3C;;AwE5lSA;EAAiB,oCAAkC;AxEgmSnD;;AwE/lSA;EAAiB,0CAAkC;AxEmmSnD;;AwE/lSA;EGvDE,WAAW;EACX,kBAAkB;EAClB,iBAAiB;EACjB,6BAA6B;EAC7B,SAAS;A3E0pSX;;AwEnmSA;EAAwB,gCAAgC;AxEumSxD;;AwErmSA;EACE,iCAAiC;EACjC,oCAAoC;AxEwmStC;;AwEnmSA;EAAc,yBAAyB;AxEumSvC;;A4ExqSA;EACE,8BAA8B;A5E2qShC;;A4ExqSA;EACE,6BAA6B;A5E2qS/B;;A6E3qSE;E3EOF;;;I2EDM,4BAA4B;IAE5B,2BAA2B;E7E2qS/B;E6ExqSE;IAEI,0BAA0B;E7EyqShC;E6EhqSE;IACE,6BAA6B;E7EkqSjC;EEn+RF;I2EhLM,gCAAgC;E7EspSpC;E6EppSE;;IAEE,yB1EzCY;I0E0CZ,wBAAwB;E7EspS5B;E6E9oSE;IACE,2BAA2B;E7EgpS/B;E6E7oSE;;IAEE,wBAAwB;E7E+oS5B;E6E5oSE;;;IAGE,UAAU;IACV,SAAS;E7E8oSb;E6E3oSE;;IAEE,uBAAuB;E7E6oS3B;E6EroSE;IACE,Q1EwgCgC;EH+nQpC;EEnrSF;I2E+CM,2BAA2C;E7EuoS/C;EY9tSA;IiE0FI,2BAA2C;E7EuoS/C;EiCrtSF;I4CmFM,aAAa;E7EqoSjB;EsCpuSF;IuCkGM,sB1EtFS;EH2tSb;EgBxuSF;I6DuGM,oCAAoC;E7EooSxC;E6EroSE;;IAKI,iCAAmC;E7EooSzC;EgBvsSF;;I6D0EQ,oCAAsC;E7EioS5C;EgBtnSF;I6DNM,cAAc;E7E+nSlB;EiBrvSA;;;;I4D4HM,qB1EvHU;EHsvShB;EgBjpSF;I6DuBM,cAAc;IACd,qB1E7HY;EH0vShB;AACF","file":"bootstrap.css","sourcesContent":["/*!\n * Bootstrap v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n@import \"functions\";\n@import \"variables\";\n@import \"mixins\";\n@import \"root\";\n@import \"reboot\";\n@import \"type\";\n@import \"images\";\n@import \"code\";\n@import \"grid\";\n@import \"tables\";\n@import \"forms\";\n@import \"buttons\";\n@import \"transitions\";\n@import \"dropdown\";\n@import \"button-group\";\n@import \"input-group\";\n@import \"custom-forms\";\n@import \"nav\";\n@import \"navbar\";\n@import \"card\";\n@import \"breadcrumb\";\n@import \"pagination\";\n@import \"badge\";\n@import \"jumbotron\";\n@import \"alert\";\n@import \"progress\";\n@import \"media\";\n@import \"list-group\";\n@import \"close\";\n@import \"toasts\";\n@import \"modal\";\n@import \"tooltip\";\n@import \"popover\";\n@import \"carousel\";\n@import \"spinners\";\n@import \"utilities\";\n@import \"print\";\n","/*!\n * Bootstrap v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n:root {\n --blue: #007bff;\n --indigo: #6610f2;\n --purple: #6f42c1;\n --pink: #e83e8c;\n --red: #dc3545;\n --orange: #fd7e14;\n --yellow: #ffc107;\n --green: #28a745;\n --teal: #20c997;\n --cyan: #17a2b8;\n --white: #fff;\n --gray: #6c757d;\n --gray-dark: #343a40;\n --primary: #007bff;\n --secondary: #6c757d;\n --success: #28a745;\n --info: #17a2b8;\n --warning: #ffc107;\n --danger: #dc3545;\n --light: #f8f9fa;\n --dark: #343a40;\n --breakpoint-xs: 0;\n --breakpoint-sm: 576px;\n --breakpoint-md: 768px;\n --breakpoint-lg: 992px;\n --breakpoint-xl: 1200px;\n --font-family-sans-serif: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nhtml {\n font-family: sans-serif;\n line-height: 1.15;\n -webkit-text-size-adjust: 100%;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\nbody {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #212529;\n text-align: left;\n background-color: #fff;\n}\n\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\nhr {\n box-sizing: content-box;\n height: 0;\n overflow: visible;\n}\n\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n}\n\np {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-original-title] {\n text-decoration: underline;\n text-decoration: underline dotted;\n cursor: help;\n border-bottom: 0;\n text-decoration-skip-ink: none;\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: 700;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0;\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: bolder;\n}\n\nsmall {\n font-size: 80%;\n}\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -.25em;\n}\n\nsup {\n top: -.5em;\n}\n\na {\n color: #007bff;\n text-decoration: none;\n background-color: transparent;\n}\n\na:hover {\n color: #0056b3;\n text-decoration: underline;\n}\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):focus {\n outline: 0;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 1em;\n}\n\npre {\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n}\n\nfigure {\n margin: 0 0 1rem;\n}\n\nimg {\n vertical-align: middle;\n border-style: none;\n}\n\nsvg {\n overflow: hidden;\n vertical-align: middle;\n}\n\ntable {\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n color: #6c757d;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n text-align: inherit;\n}\n\nlabel {\n display: inline-block;\n margin-bottom: 0.5rem;\n}\n\nbutton {\n border-radius: 0;\n}\n\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible;\n}\n\nbutton,\nselect {\n text-transform: none;\n}\n\nselect {\n word-wrap: normal;\n}\n\nbutton,\n[type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\nbutton:not(:disabled),\n[type=\"button\"]:not(:disabled),\n[type=\"reset\"]:not(:disabled),\n[type=\"submit\"]:not(:disabled) {\n cursor: pointer;\n}\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box;\n padding: 0;\n}\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto;\n resize: vertical;\n}\n\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n max-width: 100%;\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit;\n white-space: normal;\n}\n\nprogress {\n vertical-align: baseline;\n}\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n outline-offset: -2px;\n -webkit-appearance: none;\n}\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n::-webkit-file-upload-button {\n font: inherit;\n -webkit-appearance: button;\n}\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item;\n cursor: pointer;\n}\n\ntemplate {\n display: none;\n}\n\n[hidden] {\n display: none !important;\n}\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n margin-bottom: 0.5rem;\n font-weight: 500;\n line-height: 1.2;\n}\n\nh1, .h1 {\n font-size: 2.5rem;\n}\n\nh2, .h2 {\n font-size: 2rem;\n}\n\nh3, .h3 {\n font-size: 1.75rem;\n}\n\nh4, .h4 {\n font-size: 1.5rem;\n}\n\nh5, .h5 {\n font-size: 1.25rem;\n}\n\nh6, .h6 {\n font-size: 1rem;\n}\n\n.lead {\n font-size: 1.25rem;\n font-weight: 300;\n}\n\n.display-1 {\n font-size: 6rem;\n font-weight: 300;\n line-height: 1.2;\n}\n\n.display-2 {\n font-size: 5.5rem;\n font-weight: 300;\n line-height: 1.2;\n}\n\n.display-3 {\n font-size: 4.5rem;\n font-weight: 300;\n line-height: 1.2;\n}\n\n.display-4 {\n font-size: 3.5rem;\n font-weight: 300;\n line-height: 1.2;\n}\n\nhr {\n margin-top: 1rem;\n margin-bottom: 1rem;\n border: 0;\n border-top: 1px solid rgba(0, 0, 0, 0.1);\n}\n\nsmall,\n.small {\n font-size: 80%;\n font-weight: 400;\n}\n\nmark,\n.mark {\n padding: 0.2em;\n background-color: #fcf8e3;\n}\n\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n.list-inline {\n padding-left: 0;\n list-style: none;\n}\n\n.list-inline-item {\n display: inline-block;\n}\n\n.list-inline-item:not(:last-child) {\n margin-right: 0.5rem;\n}\n\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\n\n.blockquote {\n margin-bottom: 1rem;\n font-size: 1.25rem;\n}\n\n.blockquote-footer {\n display: block;\n font-size: 80%;\n color: #6c757d;\n}\n\n.blockquote-footer::before {\n content: \"\\2014\\00A0\";\n}\n\n.img-fluid {\n max-width: 100%;\n height: auto;\n}\n\n.img-thumbnail {\n padding: 0.25rem;\n background-color: #fff;\n border: 1px solid #dee2e6;\n border-radius: 0.25rem;\n max-width: 100%;\n height: auto;\n}\n\n.figure {\n display: inline-block;\n}\n\n.figure-img {\n margin-bottom: 0.5rem;\n line-height: 1;\n}\n\n.figure-caption {\n font-size: 90%;\n color: #6c757d;\n}\n\ncode {\n font-size: 87.5%;\n color: #e83e8c;\n word-break: break-word;\n}\n\na > code {\n color: inherit;\n}\n\nkbd {\n padding: 0.2rem 0.4rem;\n font-size: 87.5%;\n color: #fff;\n background-color: #212529;\n border-radius: 0.2rem;\n}\n\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: 700;\n}\n\npre {\n display: block;\n font-size: 87.5%;\n color: #212529;\n}\n\npre code {\n font-size: inherit;\n color: inherit;\n word-break: normal;\n}\n\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n\n.container {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n@media (min-width: 576px) {\n .container {\n max-width: 540px;\n }\n}\n\n@media (min-width: 768px) {\n .container {\n max-width: 720px;\n }\n}\n\n@media (min-width: 992px) {\n .container {\n max-width: 960px;\n }\n}\n\n@media (min-width: 1200px) {\n .container {\n max-width: 1140px;\n }\n}\n\n.container-fluid {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n.row {\n display: flex;\n flex-wrap: wrap;\n margin-right: -15px;\n margin-left: -15px;\n}\n\n.no-gutters {\n margin-right: 0;\n margin-left: 0;\n}\n\n.no-gutters > .col,\n.no-gutters > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n}\n\n.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,\n.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,\n.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,\n.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,\n.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,\n.col-xl-auto {\n position: relative;\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n}\n\n.col {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n}\n\n.col-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n}\n\n.col-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n}\n\n.col-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n}\n\n.col-3 {\n flex: 0 0 25%;\n max-width: 25%;\n}\n\n.col-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n}\n\n.col-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n}\n\n.col-6 {\n flex: 0 0 50%;\n max-width: 50%;\n}\n\n.col-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n}\n\n.col-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n}\n\n.col-9 {\n flex: 0 0 75%;\n max-width: 75%;\n}\n\n.col-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n}\n\n.col-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n}\n\n.col-12 {\n flex: 0 0 100%;\n max-width: 100%;\n}\n\n.order-first {\n order: -1;\n}\n\n.order-last {\n order: 13;\n}\n\n.order-0 {\n order: 0;\n}\n\n.order-1 {\n order: 1;\n}\n\n.order-2 {\n order: 2;\n}\n\n.order-3 {\n order: 3;\n}\n\n.order-4 {\n order: 4;\n}\n\n.order-5 {\n order: 5;\n}\n\n.order-6 {\n order: 6;\n}\n\n.order-7 {\n order: 7;\n}\n\n.order-8 {\n order: 8;\n}\n\n.order-9 {\n order: 9;\n}\n\n.order-10 {\n order: 10;\n}\n\n.order-11 {\n order: 11;\n}\n\n.order-12 {\n order: 12;\n}\n\n.offset-1 {\n margin-left: 8.333333%;\n}\n\n.offset-2 {\n margin-left: 16.666667%;\n}\n\n.offset-3 {\n margin-left: 25%;\n}\n\n.offset-4 {\n margin-left: 33.333333%;\n}\n\n.offset-5 {\n margin-left: 41.666667%;\n}\n\n.offset-6 {\n margin-left: 50%;\n}\n\n.offset-7 {\n margin-left: 58.333333%;\n}\n\n.offset-8 {\n margin-left: 66.666667%;\n}\n\n.offset-9 {\n margin-left: 75%;\n}\n\n.offset-10 {\n margin-left: 83.333333%;\n}\n\n.offset-11 {\n margin-left: 91.666667%;\n}\n\n@media (min-width: 576px) {\n .col-sm {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-sm-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-sm-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-sm-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-sm-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-sm-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-sm-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-sm-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-sm-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-sm-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-sm-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-sm-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-sm-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-sm-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-sm-first {\n order: -1;\n }\n .order-sm-last {\n order: 13;\n }\n .order-sm-0 {\n order: 0;\n }\n .order-sm-1 {\n order: 1;\n }\n .order-sm-2 {\n order: 2;\n }\n .order-sm-3 {\n order: 3;\n }\n .order-sm-4 {\n order: 4;\n }\n .order-sm-5 {\n order: 5;\n }\n .order-sm-6 {\n order: 6;\n }\n .order-sm-7 {\n order: 7;\n }\n .order-sm-8 {\n order: 8;\n }\n .order-sm-9 {\n order: 9;\n }\n .order-sm-10 {\n order: 10;\n }\n .order-sm-11 {\n order: 11;\n }\n .order-sm-12 {\n order: 12;\n }\n .offset-sm-0 {\n margin-left: 0;\n }\n .offset-sm-1 {\n margin-left: 8.333333%;\n }\n .offset-sm-2 {\n margin-left: 16.666667%;\n }\n .offset-sm-3 {\n margin-left: 25%;\n }\n .offset-sm-4 {\n margin-left: 33.333333%;\n }\n .offset-sm-5 {\n margin-left: 41.666667%;\n }\n .offset-sm-6 {\n margin-left: 50%;\n }\n .offset-sm-7 {\n margin-left: 58.333333%;\n }\n .offset-sm-8 {\n margin-left: 66.666667%;\n }\n .offset-sm-9 {\n margin-left: 75%;\n }\n .offset-sm-10 {\n margin-left: 83.333333%;\n }\n .offset-sm-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 768px) {\n .col-md {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-md-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-md-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-md-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-md-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-md-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-md-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-md-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-md-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-md-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-md-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-md-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-md-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-md-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-md-first {\n order: -1;\n }\n .order-md-last {\n order: 13;\n }\n .order-md-0 {\n order: 0;\n }\n .order-md-1 {\n order: 1;\n }\n .order-md-2 {\n order: 2;\n }\n .order-md-3 {\n order: 3;\n }\n .order-md-4 {\n order: 4;\n }\n .order-md-5 {\n order: 5;\n }\n .order-md-6 {\n order: 6;\n }\n .order-md-7 {\n order: 7;\n }\n .order-md-8 {\n order: 8;\n }\n .order-md-9 {\n order: 9;\n }\n .order-md-10 {\n order: 10;\n }\n .order-md-11 {\n order: 11;\n }\n .order-md-12 {\n order: 12;\n }\n .offset-md-0 {\n margin-left: 0;\n }\n .offset-md-1 {\n margin-left: 8.333333%;\n }\n .offset-md-2 {\n margin-left: 16.666667%;\n }\n .offset-md-3 {\n margin-left: 25%;\n }\n .offset-md-4 {\n margin-left: 33.333333%;\n }\n .offset-md-5 {\n margin-left: 41.666667%;\n }\n .offset-md-6 {\n margin-left: 50%;\n }\n .offset-md-7 {\n margin-left: 58.333333%;\n }\n .offset-md-8 {\n margin-left: 66.666667%;\n }\n .offset-md-9 {\n margin-left: 75%;\n }\n .offset-md-10 {\n margin-left: 83.333333%;\n }\n .offset-md-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 992px) {\n .col-lg {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-lg-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-lg-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-lg-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-lg-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-lg-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-lg-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-lg-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-lg-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-lg-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-lg-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-lg-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-lg-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-lg-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-lg-first {\n order: -1;\n }\n .order-lg-last {\n order: 13;\n }\n .order-lg-0 {\n order: 0;\n }\n .order-lg-1 {\n order: 1;\n }\n .order-lg-2 {\n order: 2;\n }\n .order-lg-3 {\n order: 3;\n }\n .order-lg-4 {\n order: 4;\n }\n .order-lg-5 {\n order: 5;\n }\n .order-lg-6 {\n order: 6;\n }\n .order-lg-7 {\n order: 7;\n }\n .order-lg-8 {\n order: 8;\n }\n .order-lg-9 {\n order: 9;\n }\n .order-lg-10 {\n order: 10;\n }\n .order-lg-11 {\n order: 11;\n }\n .order-lg-12 {\n order: 12;\n }\n .offset-lg-0 {\n margin-left: 0;\n }\n .offset-lg-1 {\n margin-left: 8.333333%;\n }\n .offset-lg-2 {\n margin-left: 16.666667%;\n }\n .offset-lg-3 {\n margin-left: 25%;\n }\n .offset-lg-4 {\n margin-left: 33.333333%;\n }\n .offset-lg-5 {\n margin-left: 41.666667%;\n }\n .offset-lg-6 {\n margin-left: 50%;\n }\n .offset-lg-7 {\n margin-left: 58.333333%;\n }\n .offset-lg-8 {\n margin-left: 66.666667%;\n }\n .offset-lg-9 {\n margin-left: 75%;\n }\n .offset-lg-10 {\n margin-left: 83.333333%;\n }\n .offset-lg-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 1200px) {\n .col-xl {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-xl-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-xl-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-xl-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-xl-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-xl-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-xl-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-xl-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-xl-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-xl-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-xl-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-xl-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-xl-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-xl-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-xl-first {\n order: -1;\n }\n .order-xl-last {\n order: 13;\n }\n .order-xl-0 {\n order: 0;\n }\n .order-xl-1 {\n order: 1;\n }\n .order-xl-2 {\n order: 2;\n }\n .order-xl-3 {\n order: 3;\n }\n .order-xl-4 {\n order: 4;\n }\n .order-xl-5 {\n order: 5;\n }\n .order-xl-6 {\n order: 6;\n }\n .order-xl-7 {\n order: 7;\n }\n .order-xl-8 {\n order: 8;\n }\n .order-xl-9 {\n order: 9;\n }\n .order-xl-10 {\n order: 10;\n }\n .order-xl-11 {\n order: 11;\n }\n .order-xl-12 {\n order: 12;\n }\n .offset-xl-0 {\n margin-left: 0;\n }\n .offset-xl-1 {\n margin-left: 8.333333%;\n }\n .offset-xl-2 {\n margin-left: 16.666667%;\n }\n .offset-xl-3 {\n margin-left: 25%;\n }\n .offset-xl-4 {\n margin-left: 33.333333%;\n }\n .offset-xl-5 {\n margin-left: 41.666667%;\n }\n .offset-xl-6 {\n margin-left: 50%;\n }\n .offset-xl-7 {\n margin-left: 58.333333%;\n }\n .offset-xl-8 {\n margin-left: 66.666667%;\n }\n .offset-xl-9 {\n margin-left: 75%;\n }\n .offset-xl-10 {\n margin-left: 83.333333%;\n }\n .offset-xl-11 {\n margin-left: 91.666667%;\n }\n}\n\n.table {\n width: 100%;\n margin-bottom: 1rem;\n color: #212529;\n}\n\n.table th,\n.table td {\n padding: 0.75rem;\n vertical-align: top;\n border-top: 1px solid #dee2e6;\n}\n\n.table thead th {\n vertical-align: bottom;\n border-bottom: 2px solid #dee2e6;\n}\n\n.table tbody + tbody {\n border-top: 2px solid #dee2e6;\n}\n\n.table-sm th,\n.table-sm td {\n padding: 0.3rem;\n}\n\n.table-bordered {\n border: 1px solid #dee2e6;\n}\n\n.table-bordered th,\n.table-bordered td {\n border: 1px solid #dee2e6;\n}\n\n.table-bordered thead th,\n.table-bordered thead td {\n border-bottom-width: 2px;\n}\n\n.table-borderless th,\n.table-borderless td,\n.table-borderless thead th,\n.table-borderless tbody + tbody {\n border: 0;\n}\n\n.table-striped tbody tr:nth-of-type(odd) {\n background-color: rgba(0, 0, 0, 0.05);\n}\n\n.table-hover tbody tr:hover {\n color: #212529;\n background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table-primary,\n.table-primary > th,\n.table-primary > td {\n background-color: #b8daff;\n}\n\n.table-primary th,\n.table-primary td,\n.table-primary thead th,\n.table-primary tbody + tbody {\n border-color: #7abaff;\n}\n\n.table-hover .table-primary:hover {\n background-color: #9fcdff;\n}\n\n.table-hover .table-primary:hover > td,\n.table-hover .table-primary:hover > th {\n background-color: #9fcdff;\n}\n\n.table-secondary,\n.table-secondary > th,\n.table-secondary > td {\n background-color: #d6d8db;\n}\n\n.table-secondary th,\n.table-secondary td,\n.table-secondary thead th,\n.table-secondary tbody + tbody {\n border-color: #b3b7bb;\n}\n\n.table-hover .table-secondary:hover {\n background-color: #c8cbcf;\n}\n\n.table-hover .table-secondary:hover > td,\n.table-hover .table-secondary:hover > th {\n background-color: #c8cbcf;\n}\n\n.table-success,\n.table-success > th,\n.table-success > td {\n background-color: #c3e6cb;\n}\n\n.table-success th,\n.table-success td,\n.table-success thead th,\n.table-success tbody + tbody {\n border-color: #8fd19e;\n}\n\n.table-hover .table-success:hover {\n background-color: #b1dfbb;\n}\n\n.table-hover .table-success:hover > td,\n.table-hover .table-success:hover > th {\n background-color: #b1dfbb;\n}\n\n.table-info,\n.table-info > th,\n.table-info > td {\n background-color: #bee5eb;\n}\n\n.table-info th,\n.table-info td,\n.table-info thead th,\n.table-info tbody + tbody {\n border-color: #86cfda;\n}\n\n.table-hover .table-info:hover {\n background-color: #abdde5;\n}\n\n.table-hover .table-info:hover > td,\n.table-hover .table-info:hover > th {\n background-color: #abdde5;\n}\n\n.table-warning,\n.table-warning > th,\n.table-warning > td {\n background-color: #ffeeba;\n}\n\n.table-warning th,\n.table-warning td,\n.table-warning thead th,\n.table-warning tbody + tbody {\n border-color: #ffdf7e;\n}\n\n.table-hover .table-warning:hover {\n background-color: #ffe8a1;\n}\n\n.table-hover .table-warning:hover > td,\n.table-hover .table-warning:hover > th {\n background-color: #ffe8a1;\n}\n\n.table-danger,\n.table-danger > th,\n.table-danger > td {\n background-color: #f5c6cb;\n}\n\n.table-danger th,\n.table-danger td,\n.table-danger thead th,\n.table-danger tbody + tbody {\n border-color: #ed969e;\n}\n\n.table-hover .table-danger:hover {\n background-color: #f1b0b7;\n}\n\n.table-hover .table-danger:hover > td,\n.table-hover .table-danger:hover > th {\n background-color: #f1b0b7;\n}\n\n.table-light,\n.table-light > th,\n.table-light > td {\n background-color: #fdfdfe;\n}\n\n.table-light th,\n.table-light td,\n.table-light thead th,\n.table-light tbody + tbody {\n border-color: #fbfcfc;\n}\n\n.table-hover .table-light:hover {\n background-color: #ececf6;\n}\n\n.table-hover .table-light:hover > td,\n.table-hover .table-light:hover > th {\n background-color: #ececf6;\n}\n\n.table-dark,\n.table-dark > th,\n.table-dark > td {\n background-color: #c6c8ca;\n}\n\n.table-dark th,\n.table-dark td,\n.table-dark thead th,\n.table-dark tbody + tbody {\n border-color: #95999c;\n}\n\n.table-hover .table-dark:hover {\n background-color: #b9bbbe;\n}\n\n.table-hover .table-dark:hover > td,\n.table-hover .table-dark:hover > th {\n background-color: #b9bbbe;\n}\n\n.table-active,\n.table-active > th,\n.table-active > td {\n background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table-hover .table-active:hover {\n background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table-hover .table-active:hover > td,\n.table-hover .table-active:hover > th {\n background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table .thead-dark th {\n color: #fff;\n background-color: #343a40;\n border-color: #454d55;\n}\n\n.table .thead-light th {\n color: #495057;\n background-color: #e9ecef;\n border-color: #dee2e6;\n}\n\n.table-dark {\n color: #fff;\n background-color: #343a40;\n}\n\n.table-dark th,\n.table-dark td,\n.table-dark thead th {\n border-color: #454d55;\n}\n\n.table-dark.table-bordered {\n border: 0;\n}\n\n.table-dark.table-striped tbody tr:nth-of-type(odd) {\n background-color: rgba(255, 255, 255, 0.05);\n}\n\n.table-dark.table-hover tbody tr:hover {\n color: #fff;\n background-color: rgba(255, 255, 255, 0.075);\n}\n\n@media (max-width: 575.98px) {\n .table-responsive-sm {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n }\n .table-responsive-sm > .table-bordered {\n border: 0;\n }\n}\n\n@media (max-width: 767.98px) {\n .table-responsive-md {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n }\n .table-responsive-md > .table-bordered {\n border: 0;\n }\n}\n\n@media (max-width: 991.98px) {\n .table-responsive-lg {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n }\n .table-responsive-lg > .table-bordered {\n border: 0;\n }\n}\n\n@media (max-width: 1199.98px) {\n .table-responsive-xl {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n }\n .table-responsive-xl > .table-bordered {\n border: 0;\n }\n}\n\n.table-responsive {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n.table-responsive > .table-bordered {\n border: 0;\n}\n\n.form-control {\n display: block;\n width: 100%;\n height: calc(1.5em + 0.75rem + 2px);\n padding: 0.375rem 0.75rem;\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #495057;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #ced4da;\n border-radius: 0.25rem;\n transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .form-control {\n transition: none;\n }\n}\n\n.form-control::-ms-expand {\n background-color: transparent;\n border: 0;\n}\n\n.form-control:focus {\n color: #495057;\n background-color: #fff;\n border-color: #80bdff;\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.form-control::placeholder {\n color: #6c757d;\n opacity: 1;\n}\n\n.form-control:disabled, .form-control[readonly] {\n background-color: #e9ecef;\n opacity: 1;\n}\n\nselect.form-control:focus::-ms-value {\n color: #495057;\n background-color: #fff;\n}\n\n.form-control-file,\n.form-control-range {\n display: block;\n width: 100%;\n}\n\n.col-form-label {\n padding-top: calc(0.375rem + 1px);\n padding-bottom: calc(0.375rem + 1px);\n margin-bottom: 0;\n font-size: inherit;\n line-height: 1.5;\n}\n\n.col-form-label-lg {\n padding-top: calc(0.5rem + 1px);\n padding-bottom: calc(0.5rem + 1px);\n font-size: 1.25rem;\n line-height: 1.5;\n}\n\n.col-form-label-sm {\n padding-top: calc(0.25rem + 1px);\n padding-bottom: calc(0.25rem + 1px);\n font-size: 0.875rem;\n line-height: 1.5;\n}\n\n.form-control-plaintext {\n display: block;\n width: 100%;\n padding-top: 0.375rem;\n padding-bottom: 0.375rem;\n margin-bottom: 0;\n line-height: 1.5;\n color: #212529;\n background-color: transparent;\n border: solid transparent;\n border-width: 1px 0;\n}\n\n.form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg {\n padding-right: 0;\n padding-left: 0;\n}\n\n.form-control-sm {\n height: calc(1.5em + 0.5rem + 2px);\n padding: 0.25rem 0.5rem;\n font-size: 0.875rem;\n line-height: 1.5;\n border-radius: 0.2rem;\n}\n\n.form-control-lg {\n height: calc(1.5em + 1rem + 2px);\n padding: 0.5rem 1rem;\n font-size: 1.25rem;\n line-height: 1.5;\n border-radius: 0.3rem;\n}\n\nselect.form-control[size], select.form-control[multiple] {\n height: auto;\n}\n\ntextarea.form-control {\n height: auto;\n}\n\n.form-group {\n margin-bottom: 1rem;\n}\n\n.form-text {\n display: block;\n margin-top: 0.25rem;\n}\n\n.form-row {\n display: flex;\n flex-wrap: wrap;\n margin-right: -5px;\n margin-left: -5px;\n}\n\n.form-row > .col,\n.form-row > [class*=\"col-\"] {\n padding-right: 5px;\n padding-left: 5px;\n}\n\n.form-check {\n position: relative;\n display: block;\n padding-left: 1.25rem;\n}\n\n.form-check-input {\n position: absolute;\n margin-top: 0.3rem;\n margin-left: -1.25rem;\n}\n\n.form-check-input:disabled ~ .form-check-label {\n color: #6c757d;\n}\n\n.form-check-label {\n margin-bottom: 0;\n}\n\n.form-check-inline {\n display: inline-flex;\n align-items: center;\n padding-left: 0;\n margin-right: 0.75rem;\n}\n\n.form-check-inline .form-check-input {\n position: static;\n margin-top: 0;\n margin-right: 0.3125rem;\n margin-left: 0;\n}\n\n.valid-feedback {\n display: none;\n width: 100%;\n margin-top: 0.25rem;\n font-size: 80%;\n color: #28a745;\n}\n\n.valid-tooltip {\n position: absolute;\n top: 100%;\n z-index: 5;\n display: none;\n max-width: 100%;\n padding: 0.25rem 0.5rem;\n margin-top: .1rem;\n font-size: 0.875rem;\n line-height: 1.5;\n color: #fff;\n background-color: rgba(40, 167, 69, 0.9);\n border-radius: 0.25rem;\n}\n\n.was-validated .form-control:valid, .form-control.is-valid {\n border-color: #28a745;\n padding-right: calc(1.5em + 0.75rem);\n background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e\");\n background-repeat: no-repeat;\n background-position: center right calc(0.375em + 0.1875rem);\n background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);\n}\n\n.was-validated .form-control:valid:focus, .form-control.is-valid:focus {\n border-color: #28a745;\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);\n}\n\n.was-validated .form-control:valid ~ .valid-feedback,\n.was-validated .form-control:valid ~ .valid-tooltip, .form-control.is-valid ~ .valid-feedback,\n.form-control.is-valid ~ .valid-tooltip {\n display: block;\n}\n\n.was-validated textarea.form-control:valid, textarea.form-control.is-valid {\n padding-right: calc(1.5em + 0.75rem);\n background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem);\n}\n\n.was-validated .custom-select:valid, .custom-select.is-valid {\n border-color: #28a745;\n padding-right: calc((1em + 0.75rem) * 3 / 4 + 1.75rem);\n background: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e\") no-repeat right 0.75rem center/8px 10px, url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e\") #fff no-repeat center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);\n}\n\n.was-validated .custom-select:valid:focus, .custom-select.is-valid:focus {\n border-color: #28a745;\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);\n}\n\n.was-validated .custom-select:valid ~ .valid-feedback,\n.was-validated .custom-select:valid ~ .valid-tooltip, .custom-select.is-valid ~ .valid-feedback,\n.custom-select.is-valid ~ .valid-tooltip {\n display: block;\n}\n\n.was-validated .form-control-file:valid ~ .valid-feedback,\n.was-validated .form-control-file:valid ~ .valid-tooltip, .form-control-file.is-valid ~ .valid-feedback,\n.form-control-file.is-valid ~ .valid-tooltip {\n display: block;\n}\n\n.was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label {\n color: #28a745;\n}\n\n.was-validated .form-check-input:valid ~ .valid-feedback,\n.was-validated .form-check-input:valid ~ .valid-tooltip, .form-check-input.is-valid ~ .valid-feedback,\n.form-check-input.is-valid ~ .valid-tooltip {\n display: block;\n}\n\n.was-validated .custom-control-input:valid ~ .custom-control-label, .custom-control-input.is-valid ~ .custom-control-label {\n color: #28a745;\n}\n\n.was-validated .custom-control-input:valid ~ .custom-control-label::before, .custom-control-input.is-valid ~ .custom-control-label::before {\n border-color: #28a745;\n}\n\n.was-validated .custom-control-input:valid ~ .valid-feedback,\n.was-validated .custom-control-input:valid ~ .valid-tooltip, .custom-control-input.is-valid ~ .valid-feedback,\n.custom-control-input.is-valid ~ .valid-tooltip {\n display: block;\n}\n\n.was-validated .custom-control-input:valid:checked ~ .custom-control-label::before, .custom-control-input.is-valid:checked ~ .custom-control-label::before {\n border-color: #34ce57;\n background-color: #34ce57;\n}\n\n.was-validated .custom-control-input:valid:focus ~ .custom-control-label::before, .custom-control-input.is-valid:focus ~ .custom-control-label::before {\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);\n}\n\n.was-validated .custom-control-input:valid:focus:not(:checked) ~ .custom-control-label::before, .custom-control-input.is-valid:focus:not(:checked) ~ .custom-control-label::before {\n border-color: #28a745;\n}\n\n.was-validated .custom-file-input:valid ~ .custom-file-label, .custom-file-input.is-valid ~ .custom-file-label {\n border-color: #28a745;\n}\n\n.was-validated .custom-file-input:valid ~ .valid-feedback,\n.was-validated .custom-file-input:valid ~ .valid-tooltip, .custom-file-input.is-valid ~ .valid-feedback,\n.custom-file-input.is-valid ~ .valid-tooltip {\n display: block;\n}\n\n.was-validated .custom-file-input:valid:focus ~ .custom-file-label, .custom-file-input.is-valid:focus ~ .custom-file-label {\n border-color: #28a745;\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);\n}\n\n.invalid-feedback {\n display: none;\n width: 100%;\n margin-top: 0.25rem;\n font-size: 80%;\n color: #dc3545;\n}\n\n.invalid-tooltip {\n position: absolute;\n top: 100%;\n z-index: 5;\n display: none;\n max-width: 100%;\n padding: 0.25rem 0.5rem;\n margin-top: .1rem;\n font-size: 0.875rem;\n line-height: 1.5;\n color: #fff;\n background-color: rgba(220, 53, 69, 0.9);\n border-radius: 0.25rem;\n}\n\n.was-validated .form-control:invalid, .form-control.is-invalid {\n border-color: #dc3545;\n padding-right: calc(1.5em + 0.75rem);\n background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23dc3545' viewBox='-2 -2 7 7'%3e%3cpath stroke='%23dc3545' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E\");\n background-repeat: no-repeat;\n background-position: center right calc(0.375em + 0.1875rem);\n background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);\n}\n\n.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus {\n border-color: #dc3545;\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);\n}\n\n.was-validated .form-control:invalid ~ .invalid-feedback,\n.was-validated .form-control:invalid ~ .invalid-tooltip, .form-control.is-invalid ~ .invalid-feedback,\n.form-control.is-invalid ~ .invalid-tooltip {\n display: block;\n}\n\n.was-validated textarea.form-control:invalid, textarea.form-control.is-invalid {\n padding-right: calc(1.5em + 0.75rem);\n background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem);\n}\n\n.was-validated .custom-select:invalid, .custom-select.is-invalid {\n border-color: #dc3545;\n padding-right: calc((1em + 0.75rem) * 3 / 4 + 1.75rem);\n background: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e\") no-repeat right 0.75rem center/8px 10px, url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23dc3545' viewBox='-2 -2 7 7'%3e%3cpath stroke='%23dc3545' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E\") #fff no-repeat center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);\n}\n\n.was-validated .custom-select:invalid:focus, .custom-select.is-invalid:focus {\n border-color: #dc3545;\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);\n}\n\n.was-validated .custom-select:invalid ~ .invalid-feedback,\n.was-validated .custom-select:invalid ~ .invalid-tooltip, .custom-select.is-invalid ~ .invalid-feedback,\n.custom-select.is-invalid ~ .invalid-tooltip {\n display: block;\n}\n\n.was-validated .form-control-file:invalid ~ .invalid-feedback,\n.was-validated .form-control-file:invalid ~ .invalid-tooltip, .form-control-file.is-invalid ~ .invalid-feedback,\n.form-control-file.is-invalid ~ .invalid-tooltip {\n display: block;\n}\n\n.was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label {\n color: #dc3545;\n}\n\n.was-validated .form-check-input:invalid ~ .invalid-feedback,\n.was-validated .form-check-input:invalid ~ .invalid-tooltip, .form-check-input.is-invalid ~ .invalid-feedback,\n.form-check-input.is-invalid ~ .invalid-tooltip {\n display: block;\n}\n\n.was-validated .custom-control-input:invalid ~ .custom-control-label, .custom-control-input.is-invalid ~ .custom-control-label {\n color: #dc3545;\n}\n\n.was-validated .custom-control-input:invalid ~ .custom-control-label::before, .custom-control-input.is-invalid ~ .custom-control-label::before {\n border-color: #dc3545;\n}\n\n.was-validated .custom-control-input:invalid ~ .invalid-feedback,\n.was-validated .custom-control-input:invalid ~ .invalid-tooltip, .custom-control-input.is-invalid ~ .invalid-feedback,\n.custom-control-input.is-invalid ~ .invalid-tooltip {\n display: block;\n}\n\n.was-validated .custom-control-input:invalid:checked ~ .custom-control-label::before, .custom-control-input.is-invalid:checked ~ .custom-control-label::before {\n border-color: #e4606d;\n background-color: #e4606d;\n}\n\n.was-validated .custom-control-input:invalid:focus ~ .custom-control-label::before, .custom-control-input.is-invalid:focus ~ .custom-control-label::before {\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);\n}\n\n.was-validated .custom-control-input:invalid:focus:not(:checked) ~ .custom-control-label::before, .custom-control-input.is-invalid:focus:not(:checked) ~ .custom-control-label::before {\n border-color: #dc3545;\n}\n\n.was-validated .custom-file-input:invalid ~ .custom-file-label, .custom-file-input.is-invalid ~ .custom-file-label {\n border-color: #dc3545;\n}\n\n.was-validated .custom-file-input:invalid ~ .invalid-feedback,\n.was-validated .custom-file-input:invalid ~ .invalid-tooltip, .custom-file-input.is-invalid ~ .invalid-feedback,\n.custom-file-input.is-invalid ~ .invalid-tooltip {\n display: block;\n}\n\n.was-validated .custom-file-input:invalid:focus ~ .custom-file-label, .custom-file-input.is-invalid:focus ~ .custom-file-label {\n border-color: #dc3545;\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);\n}\n\n.form-inline {\n display: flex;\n flex-flow: row wrap;\n align-items: center;\n}\n\n.form-inline .form-check {\n width: 100%;\n}\n\n@media (min-width: 576px) {\n .form-inline label {\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 0;\n }\n .form-inline .form-group {\n display: flex;\n flex: 0 0 auto;\n flex-flow: row wrap;\n align-items: center;\n margin-bottom: 0;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-plaintext {\n display: inline-block;\n }\n .form-inline .input-group,\n .form-inline .custom-select {\n width: auto;\n }\n .form-inline .form-check {\n display: flex;\n align-items: center;\n justify-content: center;\n width: auto;\n padding-left: 0;\n }\n .form-inline .form-check-input {\n position: relative;\n flex-shrink: 0;\n margin-top: 0;\n margin-right: 0.25rem;\n margin-left: 0;\n }\n .form-inline .custom-control {\n align-items: center;\n justify-content: center;\n }\n .form-inline .custom-control-label {\n margin-bottom: 0;\n }\n}\n\n.btn {\n display: inline-block;\n font-weight: 400;\n color: #212529;\n text-align: center;\n vertical-align: middle;\n user-select: none;\n background-color: transparent;\n border: 1px solid transparent;\n padding: 0.375rem 0.75rem;\n font-size: 1rem;\n line-height: 1.5;\n border-radius: 0.25rem;\n transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .btn {\n transition: none;\n }\n}\n\n.btn:hover {\n color: #212529;\n text-decoration: none;\n}\n\n.btn:focus, .btn.focus {\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.btn.disabled, .btn:disabled {\n opacity: 0.65;\n}\n\na.btn.disabled,\nfieldset:disabled a.btn {\n pointer-events: none;\n}\n\n.btn-primary {\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.btn-primary:hover {\n color: #fff;\n background-color: #0069d9;\n border-color: #0062cc;\n}\n\n.btn-primary:focus, .btn-primary.focus {\n box-shadow: 0 0 0 0.2rem rgba(38, 143, 255, 0.5);\n}\n\n.btn-primary.disabled, .btn-primary:disabled {\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.btn-primary:not(:disabled):not(.disabled):active, .btn-primary:not(:disabled):not(.disabled).active,\n.show > .btn-primary.dropdown-toggle {\n color: #fff;\n background-color: #0062cc;\n border-color: #005cbf;\n}\n\n.btn-primary:not(:disabled):not(.disabled):active:focus, .btn-primary:not(:disabled):not(.disabled).active:focus,\n.show > .btn-primary.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(38, 143, 255, 0.5);\n}\n\n.btn-secondary {\n color: #fff;\n background-color: #6c757d;\n border-color: #6c757d;\n}\n\n.btn-secondary:hover {\n color: #fff;\n background-color: #5a6268;\n border-color: #545b62;\n}\n\n.btn-secondary:focus, .btn-secondary.focus {\n box-shadow: 0 0 0 0.2rem rgba(130, 138, 145, 0.5);\n}\n\n.btn-secondary.disabled, .btn-secondary:disabled {\n color: #fff;\n background-color: #6c757d;\n border-color: #6c757d;\n}\n\n.btn-secondary:not(:disabled):not(.disabled):active, .btn-secondary:not(:disabled):not(.disabled).active,\n.show > .btn-secondary.dropdown-toggle {\n color: #fff;\n background-color: #545b62;\n border-color: #4e555b;\n}\n\n.btn-secondary:not(:disabled):not(.disabled):active:focus, .btn-secondary:not(:disabled):not(.disabled).active:focus,\n.show > .btn-secondary.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(130, 138, 145, 0.5);\n}\n\n.btn-success {\n color: #fff;\n background-color: #28a745;\n border-color: #28a745;\n}\n\n.btn-success:hover {\n color: #fff;\n background-color: #218838;\n border-color: #1e7e34;\n}\n\n.btn-success:focus, .btn-success.focus {\n box-shadow: 0 0 0 0.2rem rgba(72, 180, 97, 0.5);\n}\n\n.btn-success.disabled, .btn-success:disabled {\n color: #fff;\n background-color: #28a745;\n border-color: #28a745;\n}\n\n.btn-success:not(:disabled):not(.disabled):active, .btn-success:not(:disabled):not(.disabled).active,\n.show > .btn-success.dropdown-toggle {\n color: #fff;\n background-color: #1e7e34;\n border-color: #1c7430;\n}\n\n.btn-success:not(:disabled):not(.disabled):active:focus, .btn-success:not(:disabled):not(.disabled).active:focus,\n.show > .btn-success.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(72, 180, 97, 0.5);\n}\n\n.btn-info {\n color: #fff;\n background-color: #17a2b8;\n border-color: #17a2b8;\n}\n\n.btn-info:hover {\n color: #fff;\n background-color: #138496;\n border-color: #117a8b;\n}\n\n.btn-info:focus, .btn-info.focus {\n box-shadow: 0 0 0 0.2rem rgba(58, 176, 195, 0.5);\n}\n\n.btn-info.disabled, .btn-info:disabled {\n color: #fff;\n background-color: #17a2b8;\n border-color: #17a2b8;\n}\n\n.btn-info:not(:disabled):not(.disabled):active, .btn-info:not(:disabled):not(.disabled).active,\n.show > .btn-info.dropdown-toggle {\n color: #fff;\n background-color: #117a8b;\n border-color: #10707f;\n}\n\n.btn-info:not(:disabled):not(.disabled):active:focus, .btn-info:not(:disabled):not(.disabled).active:focus,\n.show > .btn-info.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(58, 176, 195, 0.5);\n}\n\n.btn-warning {\n color: #212529;\n background-color: #ffc107;\n border-color: #ffc107;\n}\n\n.btn-warning:hover {\n color: #212529;\n background-color: #e0a800;\n border-color: #d39e00;\n}\n\n.btn-warning:focus, .btn-warning.focus {\n box-shadow: 0 0 0 0.2rem rgba(222, 170, 12, 0.5);\n}\n\n.btn-warning.disabled, .btn-warning:disabled {\n color: #212529;\n background-color: #ffc107;\n border-color: #ffc107;\n}\n\n.btn-warning:not(:disabled):not(.disabled):active, .btn-warning:not(:disabled):not(.disabled).active,\n.show > .btn-warning.dropdown-toggle {\n color: #212529;\n background-color: #d39e00;\n border-color: #c69500;\n}\n\n.btn-warning:not(:disabled):not(.disabled):active:focus, .btn-warning:not(:disabled):not(.disabled).active:focus,\n.show > .btn-warning.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(222, 170, 12, 0.5);\n}\n\n.btn-danger {\n color: #fff;\n background-color: #dc3545;\n border-color: #dc3545;\n}\n\n.btn-danger:hover {\n color: #fff;\n background-color: #c82333;\n border-color: #bd2130;\n}\n\n.btn-danger:focus, .btn-danger.focus {\n box-shadow: 0 0 0 0.2rem rgba(225, 83, 97, 0.5);\n}\n\n.btn-danger.disabled, .btn-danger:disabled {\n color: #fff;\n background-color: #dc3545;\n border-color: #dc3545;\n}\n\n.btn-danger:not(:disabled):not(.disabled):active, .btn-danger:not(:disabled):not(.disabled).active,\n.show > .btn-danger.dropdown-toggle {\n color: #fff;\n background-color: #bd2130;\n border-color: #b21f2d;\n}\n\n.btn-danger:not(:disabled):not(.disabled):active:focus, .btn-danger:not(:disabled):not(.disabled).active:focus,\n.show > .btn-danger.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(225, 83, 97, 0.5);\n}\n\n.btn-light {\n color: #212529;\n background-color: #f8f9fa;\n border-color: #f8f9fa;\n}\n\n.btn-light:hover {\n color: #212529;\n background-color: #e2e6ea;\n border-color: #dae0e5;\n}\n\n.btn-light:focus, .btn-light.focus {\n box-shadow: 0 0 0 0.2rem rgba(216, 217, 219, 0.5);\n}\n\n.btn-light.disabled, .btn-light:disabled {\n color: #212529;\n background-color: #f8f9fa;\n border-color: #f8f9fa;\n}\n\n.btn-light:not(:disabled):not(.disabled):active, .btn-light:not(:disabled):not(.disabled).active,\n.show > .btn-light.dropdown-toggle {\n color: #212529;\n background-color: #dae0e5;\n border-color: #d3d9df;\n}\n\n.btn-light:not(:disabled):not(.disabled):active:focus, .btn-light:not(:disabled):not(.disabled).active:focus,\n.show > .btn-light.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(216, 217, 219, 0.5);\n}\n\n.btn-dark {\n color: #fff;\n background-color: #343a40;\n border-color: #343a40;\n}\n\n.btn-dark:hover {\n color: #fff;\n background-color: #23272b;\n border-color: #1d2124;\n}\n\n.btn-dark:focus, .btn-dark.focus {\n box-shadow: 0 0 0 0.2rem rgba(82, 88, 93, 0.5);\n}\n\n.btn-dark.disabled, .btn-dark:disabled {\n color: #fff;\n background-color: #343a40;\n border-color: #343a40;\n}\n\n.btn-dark:not(:disabled):not(.disabled):active, .btn-dark:not(:disabled):not(.disabled).active,\n.show > .btn-dark.dropdown-toggle {\n color: #fff;\n background-color: #1d2124;\n border-color: #171a1d;\n}\n\n.btn-dark:not(:disabled):not(.disabled):active:focus, .btn-dark:not(:disabled):not(.disabled).active:focus,\n.show > .btn-dark.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(82, 88, 93, 0.5);\n}\n\n.btn-outline-primary {\n color: #007bff;\n border-color: #007bff;\n}\n\n.btn-outline-primary:hover {\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.btn-outline-primary:focus, .btn-outline-primary.focus {\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);\n}\n\n.btn-outline-primary.disabled, .btn-outline-primary:disabled {\n color: #007bff;\n background-color: transparent;\n}\n\n.btn-outline-primary:not(:disabled):not(.disabled):active, .btn-outline-primary:not(:disabled):not(.disabled).active,\n.show > .btn-outline-primary.dropdown-toggle {\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.btn-outline-primary:not(:disabled):not(.disabled):active:focus, .btn-outline-primary:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-primary.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);\n}\n\n.btn-outline-secondary {\n color: #6c757d;\n border-color: #6c757d;\n}\n\n.btn-outline-secondary:hover {\n color: #fff;\n background-color: #6c757d;\n border-color: #6c757d;\n}\n\n.btn-outline-secondary:focus, .btn-outline-secondary.focus {\n box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5);\n}\n\n.btn-outline-secondary.disabled, .btn-outline-secondary:disabled {\n color: #6c757d;\n background-color: transparent;\n}\n\n.btn-outline-secondary:not(:disabled):not(.disabled):active, .btn-outline-secondary:not(:disabled):not(.disabled).active,\n.show > .btn-outline-secondary.dropdown-toggle {\n color: #fff;\n background-color: #6c757d;\n border-color: #6c757d;\n}\n\n.btn-outline-secondary:not(:disabled):not(.disabled):active:focus, .btn-outline-secondary:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-secondary.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5);\n}\n\n.btn-outline-success {\n color: #28a745;\n border-color: #28a745;\n}\n\n.btn-outline-success:hover {\n color: #fff;\n background-color: #28a745;\n border-color: #28a745;\n}\n\n.btn-outline-success:focus, .btn-outline-success.focus {\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);\n}\n\n.btn-outline-success.disabled, .btn-outline-success:disabled {\n color: #28a745;\n background-color: transparent;\n}\n\n.btn-outline-success:not(:disabled):not(.disabled):active, .btn-outline-success:not(:disabled):not(.disabled).active,\n.show > .btn-outline-success.dropdown-toggle {\n color: #fff;\n background-color: #28a745;\n border-color: #28a745;\n}\n\n.btn-outline-success:not(:disabled):not(.disabled):active:focus, .btn-outline-success:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-success.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);\n}\n\n.btn-outline-info {\n color: #17a2b8;\n border-color: #17a2b8;\n}\n\n.btn-outline-info:hover {\n color: #fff;\n background-color: #17a2b8;\n border-color: #17a2b8;\n}\n\n.btn-outline-info:focus, .btn-outline-info.focus {\n box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);\n}\n\n.btn-outline-info.disabled, .btn-outline-info:disabled {\n color: #17a2b8;\n background-color: transparent;\n}\n\n.btn-outline-info:not(:disabled):not(.disabled):active, .btn-outline-info:not(:disabled):not(.disabled).active,\n.show > .btn-outline-info.dropdown-toggle {\n color: #fff;\n background-color: #17a2b8;\n border-color: #17a2b8;\n}\n\n.btn-outline-info:not(:disabled):not(.disabled):active:focus, .btn-outline-info:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-info.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);\n}\n\n.btn-outline-warning {\n color: #ffc107;\n border-color: #ffc107;\n}\n\n.btn-outline-warning:hover {\n color: #212529;\n background-color: #ffc107;\n border-color: #ffc107;\n}\n\n.btn-outline-warning:focus, .btn-outline-warning.focus {\n box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);\n}\n\n.btn-outline-warning.disabled, .btn-outline-warning:disabled {\n color: #ffc107;\n background-color: transparent;\n}\n\n.btn-outline-warning:not(:disabled):not(.disabled):active, .btn-outline-warning:not(:disabled):not(.disabled).active,\n.show > .btn-outline-warning.dropdown-toggle {\n color: #212529;\n background-color: #ffc107;\n border-color: #ffc107;\n}\n\n.btn-outline-warning:not(:disabled):not(.disabled):active:focus, .btn-outline-warning:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-warning.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);\n}\n\n.btn-outline-danger {\n color: #dc3545;\n border-color: #dc3545;\n}\n\n.btn-outline-danger:hover {\n color: #fff;\n background-color: #dc3545;\n border-color: #dc3545;\n}\n\n.btn-outline-danger:focus, .btn-outline-danger.focus {\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);\n}\n\n.btn-outline-danger.disabled, .btn-outline-danger:disabled {\n color: #dc3545;\n background-color: transparent;\n}\n\n.btn-outline-danger:not(:disabled):not(.disabled):active, .btn-outline-danger:not(:disabled):not(.disabled).active,\n.show > .btn-outline-danger.dropdown-toggle {\n color: #fff;\n background-color: #dc3545;\n border-color: #dc3545;\n}\n\n.btn-outline-danger:not(:disabled):not(.disabled):active:focus, .btn-outline-danger:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-danger.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);\n}\n\n.btn-outline-light {\n color: #f8f9fa;\n border-color: #f8f9fa;\n}\n\n.btn-outline-light:hover {\n color: #212529;\n background-color: #f8f9fa;\n border-color: #f8f9fa;\n}\n\n.btn-outline-light:focus, .btn-outline-light.focus {\n box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);\n}\n\n.btn-outline-light.disabled, .btn-outline-light:disabled {\n color: #f8f9fa;\n background-color: transparent;\n}\n\n.btn-outline-light:not(:disabled):not(.disabled):active, .btn-outline-light:not(:disabled):not(.disabled).active,\n.show > .btn-outline-light.dropdown-toggle {\n color: #212529;\n background-color: #f8f9fa;\n border-color: #f8f9fa;\n}\n\n.btn-outline-light:not(:disabled):not(.disabled):active:focus, .btn-outline-light:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-light.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);\n}\n\n.btn-outline-dark {\n color: #343a40;\n border-color: #343a40;\n}\n\n.btn-outline-dark:hover {\n color: #fff;\n background-color: #343a40;\n border-color: #343a40;\n}\n\n.btn-outline-dark:focus, .btn-outline-dark.focus {\n box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);\n}\n\n.btn-outline-dark.disabled, .btn-outline-dark:disabled {\n color: #343a40;\n background-color: transparent;\n}\n\n.btn-outline-dark:not(:disabled):not(.disabled):active, .btn-outline-dark:not(:disabled):not(.disabled).active,\n.show > .btn-outline-dark.dropdown-toggle {\n color: #fff;\n background-color: #343a40;\n border-color: #343a40;\n}\n\n.btn-outline-dark:not(:disabled):not(.disabled):active:focus, .btn-outline-dark:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-dark.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);\n}\n\n.btn-link {\n font-weight: 400;\n color: #007bff;\n text-decoration: none;\n}\n\n.btn-link:hover {\n color: #0056b3;\n text-decoration: underline;\n}\n\n.btn-link:focus, .btn-link.focus {\n text-decoration: underline;\n box-shadow: none;\n}\n\n.btn-link:disabled, .btn-link.disabled {\n color: #6c757d;\n pointer-events: none;\n}\n\n.btn-lg, .btn-group-lg > .btn {\n padding: 0.5rem 1rem;\n font-size: 1.25rem;\n line-height: 1.5;\n border-radius: 0.3rem;\n}\n\n.btn-sm, .btn-group-sm > .btn {\n padding: 0.25rem 0.5rem;\n font-size: 0.875rem;\n line-height: 1.5;\n border-radius: 0.2rem;\n}\n\n.btn-block {\n display: block;\n width: 100%;\n}\n\n.btn-block + .btn-block {\n margin-top: 0.5rem;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n\n.fade {\n transition: opacity 0.15s linear;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .fade {\n transition: none;\n }\n}\n\n.fade:not(.show) {\n opacity: 0;\n}\n\n.collapse:not(.show) {\n display: none;\n}\n\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n transition: height 0.35s ease;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .collapsing {\n transition: none;\n }\n}\n\n.dropup,\n.dropright,\n.dropdown,\n.dropleft {\n position: relative;\n}\n\n.dropdown-toggle {\n white-space: nowrap;\n}\n\n.dropdown-toggle::after {\n display: inline-block;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n border-top: 0.3em solid;\n border-right: 0.3em solid transparent;\n border-bottom: 0;\n border-left: 0.3em solid transparent;\n}\n\n.dropdown-toggle:empty::after {\n margin-left: 0;\n}\n\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 10rem;\n padding: 0.5rem 0;\n margin: 0.125rem 0 0;\n font-size: 1rem;\n color: #212529;\n text-align: left;\n list-style: none;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid rgba(0, 0, 0, 0.15);\n border-radius: 0.25rem;\n}\n\n.dropdown-menu-left {\n right: auto;\n left: 0;\n}\n\n.dropdown-menu-right {\n right: 0;\n left: auto;\n}\n\n@media (min-width: 576px) {\n .dropdown-menu-sm-left {\n right: auto;\n left: 0;\n }\n .dropdown-menu-sm-right {\n right: 0;\n left: auto;\n }\n}\n\n@media (min-width: 768px) {\n .dropdown-menu-md-left {\n right: auto;\n left: 0;\n }\n .dropdown-menu-md-right {\n right: 0;\n left: auto;\n }\n}\n\n@media (min-width: 992px) {\n .dropdown-menu-lg-left {\n right: auto;\n left: 0;\n }\n .dropdown-menu-lg-right {\n right: 0;\n left: auto;\n }\n}\n\n@media (min-width: 1200px) {\n .dropdown-menu-xl-left {\n right: auto;\n left: 0;\n }\n .dropdown-menu-xl-right {\n right: 0;\n left: auto;\n }\n}\n\n.dropup .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-top: 0;\n margin-bottom: 0.125rem;\n}\n\n.dropup .dropdown-toggle::after {\n display: inline-block;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n border-top: 0;\n border-right: 0.3em solid transparent;\n border-bottom: 0.3em solid;\n border-left: 0.3em solid transparent;\n}\n\n.dropup .dropdown-toggle:empty::after {\n margin-left: 0;\n}\n\n.dropright .dropdown-menu {\n top: 0;\n right: auto;\n left: 100%;\n margin-top: 0;\n margin-left: 0.125rem;\n}\n\n.dropright .dropdown-toggle::after {\n display: inline-block;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n border-top: 0.3em solid transparent;\n border-right: 0;\n border-bottom: 0.3em solid transparent;\n border-left: 0.3em solid;\n}\n\n.dropright .dropdown-toggle:empty::after {\n margin-left: 0;\n}\n\n.dropright .dropdown-toggle::after {\n vertical-align: 0;\n}\n\n.dropleft .dropdown-menu {\n top: 0;\n right: 100%;\n left: auto;\n margin-top: 0;\n margin-right: 0.125rem;\n}\n\n.dropleft .dropdown-toggle::after {\n display: inline-block;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n}\n\n.dropleft .dropdown-toggle::after {\n display: none;\n}\n\n.dropleft .dropdown-toggle::before {\n display: inline-block;\n margin-right: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n border-top: 0.3em solid transparent;\n border-right: 0.3em solid;\n border-bottom: 0.3em solid transparent;\n}\n\n.dropleft .dropdown-toggle:empty::after {\n margin-left: 0;\n}\n\n.dropleft .dropdown-toggle::before {\n vertical-align: 0;\n}\n\n.dropdown-menu[x-placement^=\"top\"], .dropdown-menu[x-placement^=\"right\"], .dropdown-menu[x-placement^=\"bottom\"], .dropdown-menu[x-placement^=\"left\"] {\n right: auto;\n bottom: auto;\n}\n\n.dropdown-divider {\n height: 0;\n margin: 0.5rem 0;\n overflow: hidden;\n border-top: 1px solid #e9ecef;\n}\n\n.dropdown-item {\n display: block;\n width: 100%;\n padding: 0.25rem 1.5rem;\n clear: both;\n font-weight: 400;\n color: #212529;\n text-align: inherit;\n white-space: nowrap;\n background-color: transparent;\n border: 0;\n}\n\n.dropdown-item:hover, .dropdown-item:focus {\n color: #16181b;\n text-decoration: none;\n background-color: #f8f9fa;\n}\n\n.dropdown-item.active, .dropdown-item:active {\n color: #fff;\n text-decoration: none;\n background-color: #007bff;\n}\n\n.dropdown-item.disabled, .dropdown-item:disabled {\n color: #6c757d;\n pointer-events: none;\n background-color: transparent;\n}\n\n.dropdown-menu.show {\n display: block;\n}\n\n.dropdown-header {\n display: block;\n padding: 0.5rem 1.5rem;\n margin-bottom: 0;\n font-size: 0.875rem;\n color: #6c757d;\n white-space: nowrap;\n}\n\n.dropdown-item-text {\n display: block;\n padding: 0.25rem 1.5rem;\n color: #212529;\n}\n\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-flex;\n vertical-align: middle;\n}\n\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n flex: 1 1 auto;\n}\n\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover {\n z-index: 1;\n}\n\n.btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active,\n.btn-group-vertical > .btn:focus,\n.btn-group-vertical > .btn:active,\n.btn-group-vertical > .btn.active {\n z-index: 1;\n}\n\n.btn-toolbar {\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-start;\n}\n\n.btn-toolbar .input-group {\n width: auto;\n}\n\n.btn-group > .btn:not(:first-child),\n.btn-group > .btn-group:not(:first-child) {\n margin-left: -1px;\n}\n\n.btn-group > .btn:not(:last-child):not(.dropdown-toggle),\n.btn-group > .btn-group:not(:last-child) > .btn {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n\n.btn-group > .btn:not(:first-child),\n.btn-group > .btn-group:not(:first-child) > .btn {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.dropdown-toggle-split {\n padding-right: 0.5625rem;\n padding-left: 0.5625rem;\n}\n\n.dropdown-toggle-split::after,\n.dropup .dropdown-toggle-split::after,\n.dropright .dropdown-toggle-split::after {\n margin-left: 0;\n}\n\n.dropleft .dropdown-toggle-split::before {\n margin-right: 0;\n}\n\n.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split {\n padding-right: 0.375rem;\n padding-left: 0.375rem;\n}\n\n.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split {\n padding-right: 0.75rem;\n padding-left: 0.75rem;\n}\n\n.btn-group-vertical {\n flex-direction: column;\n align-items: flex-start;\n justify-content: center;\n}\n\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group {\n width: 100%;\n}\n\n.btn-group-vertical > .btn:not(:first-child),\n.btn-group-vertical > .btn-group:not(:first-child) {\n margin-top: -1px;\n}\n\n.btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle),\n.btn-group-vertical > .btn-group:not(:last-child) > .btn {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.btn-group-vertical > .btn:not(:first-child),\n.btn-group-vertical > .btn-group:not(:first-child) > .btn {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n\n.btn-group-toggle > .btn,\n.btn-group-toggle > .btn-group > .btn {\n margin-bottom: 0;\n}\n\n.btn-group-toggle > .btn input[type=\"radio\"],\n.btn-group-toggle > .btn input[type=\"checkbox\"],\n.btn-group-toggle > .btn-group > .btn input[type=\"radio\"],\n.btn-group-toggle > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n\n.input-group {\n position: relative;\n display: flex;\n flex-wrap: wrap;\n align-items: stretch;\n width: 100%;\n}\n\n.input-group > .form-control,\n.input-group > .form-control-plaintext,\n.input-group > .custom-select,\n.input-group > .custom-file {\n position: relative;\n flex: 1 1 auto;\n width: 1%;\n margin-bottom: 0;\n}\n\n.input-group > .form-control + .form-control,\n.input-group > .form-control + .custom-select,\n.input-group > .form-control + .custom-file,\n.input-group > .form-control-plaintext + .form-control,\n.input-group > .form-control-plaintext + .custom-select,\n.input-group > .form-control-plaintext + .custom-file,\n.input-group > .custom-select + .form-control,\n.input-group > .custom-select + .custom-select,\n.input-group > .custom-select + .custom-file,\n.input-group > .custom-file + .form-control,\n.input-group > .custom-file + .custom-select,\n.input-group > .custom-file + .custom-file {\n margin-left: -1px;\n}\n\n.input-group > .form-control:focus,\n.input-group > .custom-select:focus,\n.input-group > .custom-file .custom-file-input:focus ~ .custom-file-label {\n z-index: 3;\n}\n\n.input-group > .custom-file .custom-file-input:focus {\n z-index: 4;\n}\n\n.input-group > .form-control:not(:last-child),\n.input-group > .custom-select:not(:last-child) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n\n.input-group > .form-control:not(:first-child),\n.input-group > .custom-select:not(:first-child) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.input-group > .custom-file {\n display: flex;\n align-items: center;\n}\n\n.input-group > .custom-file:not(:last-child) .custom-file-label,\n.input-group > .custom-file:not(:last-child) .custom-file-label::after {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n\n.input-group > .custom-file:not(:first-child) .custom-file-label {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.input-group-prepend,\n.input-group-append {\n display: flex;\n}\n\n.input-group-prepend .btn,\n.input-group-append .btn {\n position: relative;\n z-index: 2;\n}\n\n.input-group-prepend .btn:focus,\n.input-group-append .btn:focus {\n z-index: 3;\n}\n\n.input-group-prepend .btn + .btn,\n.input-group-prepend .btn + .input-group-text,\n.input-group-prepend .input-group-text + .input-group-text,\n.input-group-prepend .input-group-text + .btn,\n.input-group-append .btn + .btn,\n.input-group-append .btn + .input-group-text,\n.input-group-append .input-group-text + .input-group-text,\n.input-group-append .input-group-text + .btn {\n margin-left: -1px;\n}\n\n.input-group-prepend {\n margin-right: -1px;\n}\n\n.input-group-append {\n margin-left: -1px;\n}\n\n.input-group-text {\n display: flex;\n align-items: center;\n padding: 0.375rem 0.75rem;\n margin-bottom: 0;\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #495057;\n text-align: center;\n white-space: nowrap;\n background-color: #e9ecef;\n border: 1px solid #ced4da;\n border-radius: 0.25rem;\n}\n\n.input-group-text input[type=\"radio\"],\n.input-group-text input[type=\"checkbox\"] {\n margin-top: 0;\n}\n\n.input-group-lg > .form-control:not(textarea),\n.input-group-lg > .custom-select {\n height: calc(1.5em + 1rem + 2px);\n}\n\n.input-group-lg > .form-control,\n.input-group-lg > .custom-select,\n.input-group-lg > .input-group-prepend > .input-group-text,\n.input-group-lg > .input-group-append > .input-group-text,\n.input-group-lg > .input-group-prepend > .btn,\n.input-group-lg > .input-group-append > .btn {\n padding: 0.5rem 1rem;\n font-size: 1.25rem;\n line-height: 1.5;\n border-radius: 0.3rem;\n}\n\n.input-group-sm > .form-control:not(textarea),\n.input-group-sm > .custom-select {\n height: calc(1.5em + 0.5rem + 2px);\n}\n\n.input-group-sm > .form-control,\n.input-group-sm > .custom-select,\n.input-group-sm > .input-group-prepend > .input-group-text,\n.input-group-sm > .input-group-append > .input-group-text,\n.input-group-sm > .input-group-prepend > .btn,\n.input-group-sm > .input-group-append > .btn {\n padding: 0.25rem 0.5rem;\n font-size: 0.875rem;\n line-height: 1.5;\n border-radius: 0.2rem;\n}\n\n.input-group-lg > .custom-select,\n.input-group-sm > .custom-select {\n padding-right: 1.75rem;\n}\n\n.input-group > .input-group-prepend > .btn,\n.input-group > .input-group-prepend > .input-group-text,\n.input-group > .input-group-append:not(:last-child) > .btn,\n.input-group > .input-group-append:not(:last-child) > .input-group-text,\n.input-group > .input-group-append:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group > .input-group-append:last-child > .input-group-text:not(:last-child) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n\n.input-group > .input-group-append > .btn,\n.input-group > .input-group-append > .input-group-text,\n.input-group > .input-group-prepend:not(:first-child) > .btn,\n.input-group > .input-group-prepend:not(:first-child) > .input-group-text,\n.input-group > .input-group-prepend:first-child > .btn:not(:first-child),\n.input-group > .input-group-prepend:first-child > .input-group-text:not(:first-child) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.custom-control {\n position: relative;\n display: block;\n min-height: 1.5rem;\n padding-left: 1.5rem;\n}\n\n.custom-control-inline {\n display: inline-flex;\n margin-right: 1rem;\n}\n\n.custom-control-input {\n position: absolute;\n z-index: -1;\n opacity: 0;\n}\n\n.custom-control-input:checked ~ .custom-control-label::before {\n color: #fff;\n border-color: #007bff;\n background-color: #007bff;\n}\n\n.custom-control-input:focus ~ .custom-control-label::before {\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-control-input:focus:not(:checked) ~ .custom-control-label::before {\n border-color: #80bdff;\n}\n\n.custom-control-input:not(:disabled):active ~ .custom-control-label::before {\n color: #fff;\n background-color: #b3d7ff;\n border-color: #b3d7ff;\n}\n\n.custom-control-input:disabled ~ .custom-control-label {\n color: #6c757d;\n}\n\n.custom-control-input:disabled ~ .custom-control-label::before {\n background-color: #e9ecef;\n}\n\n.custom-control-label {\n position: relative;\n margin-bottom: 0;\n vertical-align: top;\n}\n\n.custom-control-label::before {\n position: absolute;\n top: 0.25rem;\n left: -1.5rem;\n display: block;\n width: 1rem;\n height: 1rem;\n pointer-events: none;\n content: \"\";\n background-color: #fff;\n border: #adb5bd solid 1px;\n}\n\n.custom-control-label::after {\n position: absolute;\n top: 0.25rem;\n left: -1.5rem;\n display: block;\n width: 1rem;\n height: 1rem;\n content: \"\";\n background: no-repeat 50% / 50% 50%;\n}\n\n.custom-checkbox .custom-control-label::before {\n border-radius: 0.25rem;\n}\n\n.custom-checkbox .custom-control-input:checked ~ .custom-control-label::after {\n background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e\");\n}\n\n.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before {\n border-color: #007bff;\n background-color: #007bff;\n}\n\n.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::after {\n background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e\");\n}\n\n.custom-checkbox .custom-control-input:disabled:checked ~ .custom-control-label::before {\n background-color: rgba(0, 123, 255, 0.5);\n}\n\n.custom-checkbox .custom-control-input:disabled:indeterminate ~ .custom-control-label::before {\n background-color: rgba(0, 123, 255, 0.5);\n}\n\n.custom-radio .custom-control-label::before {\n border-radius: 50%;\n}\n\n.custom-radio .custom-control-input:checked ~ .custom-control-label::after {\n background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e\");\n}\n\n.custom-radio .custom-control-input:disabled:checked ~ .custom-control-label::before {\n background-color: rgba(0, 123, 255, 0.5);\n}\n\n.custom-switch {\n padding-left: 2.25rem;\n}\n\n.custom-switch .custom-control-label::before {\n left: -2.25rem;\n width: 1.75rem;\n pointer-events: all;\n border-radius: 0.5rem;\n}\n\n.custom-switch .custom-control-label::after {\n top: calc(0.25rem + 2px);\n left: calc(-2.25rem + 2px);\n width: calc(1rem - 4px);\n height: calc(1rem - 4px);\n background-color: #adb5bd;\n border-radius: 0.5rem;\n transition: transform 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .custom-switch .custom-control-label::after {\n transition: none;\n }\n}\n\n.custom-switch .custom-control-input:checked ~ .custom-control-label::after {\n background-color: #fff;\n transform: translateX(0.75rem);\n}\n\n.custom-switch .custom-control-input:disabled:checked ~ .custom-control-label::before {\n background-color: rgba(0, 123, 255, 0.5);\n}\n\n.custom-select {\n display: inline-block;\n width: 100%;\n height: calc(1.5em + 0.75rem + 2px);\n padding: 0.375rem 1.75rem 0.375rem 0.75rem;\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #495057;\n vertical-align: middle;\n background: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e\") no-repeat right 0.75rem center/8px 10px;\n background-color: #fff;\n border: 1px solid #ced4da;\n border-radius: 0.25rem;\n appearance: none;\n}\n\n.custom-select:focus {\n border-color: #80bdff;\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-select:focus::-ms-value {\n color: #495057;\n background-color: #fff;\n}\n\n.custom-select[multiple], .custom-select[size]:not([size=\"1\"]) {\n height: auto;\n padding-right: 0.75rem;\n background-image: none;\n}\n\n.custom-select:disabled {\n color: #6c757d;\n background-color: #e9ecef;\n}\n\n.custom-select::-ms-expand {\n display: none;\n}\n\n.custom-select-sm {\n height: calc(1.5em + 0.5rem + 2px);\n padding-top: 0.25rem;\n padding-bottom: 0.25rem;\n padding-left: 0.5rem;\n font-size: 0.875rem;\n}\n\n.custom-select-lg {\n height: calc(1.5em + 1rem + 2px);\n padding-top: 0.5rem;\n padding-bottom: 0.5rem;\n padding-left: 1rem;\n font-size: 1.25rem;\n}\n\n.custom-file {\n position: relative;\n display: inline-block;\n width: 100%;\n height: calc(1.5em + 0.75rem + 2px);\n margin-bottom: 0;\n}\n\n.custom-file-input {\n position: relative;\n z-index: 2;\n width: 100%;\n height: calc(1.5em + 0.75rem + 2px);\n margin: 0;\n opacity: 0;\n}\n\n.custom-file-input:focus ~ .custom-file-label {\n border-color: #80bdff;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-file-input:disabled ~ .custom-file-label {\n background-color: #e9ecef;\n}\n\n.custom-file-input:lang(en) ~ .custom-file-label::after {\n content: \"Browse\";\n}\n\n.custom-file-input ~ .custom-file-label[data-browse]::after {\n content: attr(data-browse);\n}\n\n.custom-file-label {\n position: absolute;\n top: 0;\n right: 0;\n left: 0;\n z-index: 1;\n height: calc(1.5em + 0.75rem + 2px);\n padding: 0.375rem 0.75rem;\n font-weight: 400;\n line-height: 1.5;\n color: #495057;\n background-color: #fff;\n border: 1px solid #ced4da;\n border-radius: 0.25rem;\n}\n\n.custom-file-label::after {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n z-index: 3;\n display: block;\n height: calc(1.5em + 0.75rem);\n padding: 0.375rem 0.75rem;\n line-height: 1.5;\n color: #495057;\n content: \"Browse\";\n background-color: #e9ecef;\n border-left: inherit;\n border-radius: 0 0.25rem 0.25rem 0;\n}\n\n.custom-range {\n width: 100%;\n height: calc(1rem + 0.4rem);\n padding: 0;\n background-color: transparent;\n appearance: none;\n}\n\n.custom-range:focus {\n outline: none;\n}\n\n.custom-range:focus::-webkit-slider-thumb {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-range:focus::-moz-range-thumb {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-range:focus::-ms-thumb {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-range::-moz-focus-outer {\n border: 0;\n}\n\n.custom-range::-webkit-slider-thumb {\n width: 1rem;\n height: 1rem;\n margin-top: -0.25rem;\n background-color: #007bff;\n border: 0;\n border-radius: 1rem;\n transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n appearance: none;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .custom-range::-webkit-slider-thumb {\n transition: none;\n }\n}\n\n.custom-range::-webkit-slider-thumb:active {\n background-color: #b3d7ff;\n}\n\n.custom-range::-webkit-slider-runnable-track {\n width: 100%;\n height: 0.5rem;\n color: transparent;\n cursor: pointer;\n background-color: #dee2e6;\n border-color: transparent;\n border-radius: 1rem;\n}\n\n.custom-range::-moz-range-thumb {\n width: 1rem;\n height: 1rem;\n background-color: #007bff;\n border: 0;\n border-radius: 1rem;\n transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n appearance: none;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .custom-range::-moz-range-thumb {\n transition: none;\n }\n}\n\n.custom-range::-moz-range-thumb:active {\n background-color: #b3d7ff;\n}\n\n.custom-range::-moz-range-track {\n width: 100%;\n height: 0.5rem;\n color: transparent;\n cursor: pointer;\n background-color: #dee2e6;\n border-color: transparent;\n border-radius: 1rem;\n}\n\n.custom-range::-ms-thumb {\n width: 1rem;\n height: 1rem;\n margin-top: 0;\n margin-right: 0.2rem;\n margin-left: 0.2rem;\n background-color: #007bff;\n border: 0;\n border-radius: 1rem;\n transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n appearance: none;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .custom-range::-ms-thumb {\n transition: none;\n }\n}\n\n.custom-range::-ms-thumb:active {\n background-color: #b3d7ff;\n}\n\n.custom-range::-ms-track {\n width: 100%;\n height: 0.5rem;\n color: transparent;\n cursor: pointer;\n background-color: transparent;\n border-color: transparent;\n border-width: 0.5rem;\n}\n\n.custom-range::-ms-fill-lower {\n background-color: #dee2e6;\n border-radius: 1rem;\n}\n\n.custom-range::-ms-fill-upper {\n margin-right: 15px;\n background-color: #dee2e6;\n border-radius: 1rem;\n}\n\n.custom-range:disabled::-webkit-slider-thumb {\n background-color: #adb5bd;\n}\n\n.custom-range:disabled::-webkit-slider-runnable-track {\n cursor: default;\n}\n\n.custom-range:disabled::-moz-range-thumb {\n background-color: #adb5bd;\n}\n\n.custom-range:disabled::-moz-range-track {\n cursor: default;\n}\n\n.custom-range:disabled::-ms-thumb {\n background-color: #adb5bd;\n}\n\n.custom-control-label::before,\n.custom-file-label,\n.custom-select {\n transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .custom-control-label::before,\n .custom-file-label,\n .custom-select {\n transition: none;\n }\n}\n\n.nav {\n display: flex;\n flex-wrap: wrap;\n padding-left: 0;\n margin-bottom: 0;\n list-style: none;\n}\n\n.nav-link {\n display: block;\n padding: 0.5rem 1rem;\n}\n\n.nav-link:hover, .nav-link:focus {\n text-decoration: none;\n}\n\n.nav-link.disabled {\n color: #6c757d;\n pointer-events: none;\n cursor: default;\n}\n\n.nav-tabs {\n border-bottom: 1px solid #dee2e6;\n}\n\n.nav-tabs .nav-item {\n margin-bottom: -1px;\n}\n\n.nav-tabs .nav-link {\n border: 1px solid transparent;\n border-top-left-radius: 0.25rem;\n border-top-right-radius: 0.25rem;\n}\n\n.nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus {\n border-color: #e9ecef #e9ecef #dee2e6;\n}\n\n.nav-tabs .nav-link.disabled {\n color: #6c757d;\n background-color: transparent;\n border-color: transparent;\n}\n\n.nav-tabs .nav-link.active,\n.nav-tabs .nav-item.show .nav-link {\n color: #495057;\n background-color: #fff;\n border-color: #dee2e6 #dee2e6 #fff;\n}\n\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n\n.nav-pills .nav-link {\n border-radius: 0.25rem;\n}\n\n.nav-pills .nav-link.active,\n.nav-pills .show > .nav-link {\n color: #fff;\n background-color: #007bff;\n}\n\n.nav-fill .nav-item {\n flex: 1 1 auto;\n text-align: center;\n}\n\n.nav-justified .nav-item {\n flex-basis: 0;\n flex-grow: 1;\n text-align: center;\n}\n\n.tab-content > .tab-pane {\n display: none;\n}\n\n.tab-content > .active {\n display: block;\n}\n\n.navbar {\n position: relative;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n padding: 0.5rem 1rem;\n}\n\n.navbar > .container,\n.navbar > .container-fluid {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n}\n\n.navbar-brand {\n display: inline-block;\n padding-top: 0.3125rem;\n padding-bottom: 0.3125rem;\n margin-right: 1rem;\n font-size: 1.25rem;\n line-height: inherit;\n white-space: nowrap;\n}\n\n.navbar-brand:hover, .navbar-brand:focus {\n text-decoration: none;\n}\n\n.navbar-nav {\n display: flex;\n flex-direction: column;\n padding-left: 0;\n margin-bottom: 0;\n list-style: none;\n}\n\n.navbar-nav .nav-link {\n padding-right: 0;\n padding-left: 0;\n}\n\n.navbar-nav .dropdown-menu {\n position: static;\n float: none;\n}\n\n.navbar-text {\n display: inline-block;\n padding-top: 0.5rem;\n padding-bottom: 0.5rem;\n}\n\n.navbar-collapse {\n flex-basis: 100%;\n flex-grow: 1;\n align-items: center;\n}\n\n.navbar-toggler {\n padding: 0.25rem 0.75rem;\n font-size: 1.25rem;\n line-height: 1;\n background-color: transparent;\n border: 1px solid transparent;\n border-radius: 0.25rem;\n}\n\n.navbar-toggler:hover, .navbar-toggler:focus {\n text-decoration: none;\n}\n\n.navbar-toggler-icon {\n display: inline-block;\n width: 1.5em;\n height: 1.5em;\n vertical-align: middle;\n content: \"\";\n background: no-repeat center center;\n background-size: 100% 100%;\n}\n\n@media (max-width: 575.98px) {\n .navbar-expand-sm > .container,\n .navbar-expand-sm > .container-fluid {\n padding-right: 0;\n padding-left: 0;\n }\n}\n\n@media (min-width: 576px) {\n .navbar-expand-sm {\n flex-flow: row nowrap;\n justify-content: flex-start;\n }\n .navbar-expand-sm .navbar-nav {\n flex-direction: row;\n }\n .navbar-expand-sm .navbar-nav .dropdown-menu {\n position: absolute;\n }\n .navbar-expand-sm .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem;\n }\n .navbar-expand-sm > .container,\n .navbar-expand-sm > .container-fluid {\n flex-wrap: nowrap;\n }\n .navbar-expand-sm .navbar-collapse {\n display: flex !important;\n flex-basis: auto;\n }\n .navbar-expand-sm .navbar-toggler {\n display: none;\n }\n}\n\n@media (max-width: 767.98px) {\n .navbar-expand-md > .container,\n .navbar-expand-md > .container-fluid {\n padding-right: 0;\n padding-left: 0;\n }\n}\n\n@media (min-width: 768px) {\n .navbar-expand-md {\n flex-flow: row nowrap;\n justify-content: flex-start;\n }\n .navbar-expand-md .navbar-nav {\n flex-direction: row;\n }\n .navbar-expand-md .navbar-nav .dropdown-menu {\n position: absolute;\n }\n .navbar-expand-md .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem;\n }\n .navbar-expand-md > .container,\n .navbar-expand-md > .container-fluid {\n flex-wrap: nowrap;\n }\n .navbar-expand-md .navbar-collapse {\n display: flex !important;\n flex-basis: auto;\n }\n .navbar-expand-md .navbar-toggler {\n display: none;\n }\n}\n\n@media (max-width: 991.98px) {\n .navbar-expand-lg > .container,\n .navbar-expand-lg > .container-fluid {\n padding-right: 0;\n padding-left: 0;\n }\n}\n\n@media (min-width: 992px) {\n .navbar-expand-lg {\n flex-flow: row nowrap;\n justify-content: flex-start;\n }\n .navbar-expand-lg .navbar-nav {\n flex-direction: row;\n }\n .navbar-expand-lg .navbar-nav .dropdown-menu {\n position: absolute;\n }\n .navbar-expand-lg .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem;\n }\n .navbar-expand-lg > .container,\n .navbar-expand-lg > .container-fluid {\n flex-wrap: nowrap;\n }\n .navbar-expand-lg .navbar-collapse {\n display: flex !important;\n flex-basis: auto;\n }\n .navbar-expand-lg .navbar-toggler {\n display: none;\n }\n}\n\n@media (max-width: 1199.98px) {\n .navbar-expand-xl > .container,\n .navbar-expand-xl > .container-fluid {\n padding-right: 0;\n padding-left: 0;\n }\n}\n\n@media (min-width: 1200px) {\n .navbar-expand-xl {\n flex-flow: row nowrap;\n justify-content: flex-start;\n }\n .navbar-expand-xl .navbar-nav {\n flex-direction: row;\n }\n .navbar-expand-xl .navbar-nav .dropdown-menu {\n position: absolute;\n }\n .navbar-expand-xl .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem;\n }\n .navbar-expand-xl > .container,\n .navbar-expand-xl > .container-fluid {\n flex-wrap: nowrap;\n }\n .navbar-expand-xl .navbar-collapse {\n display: flex !important;\n flex-basis: auto;\n }\n .navbar-expand-xl .navbar-toggler {\n display: none;\n }\n}\n\n.navbar-expand {\n flex-flow: row nowrap;\n justify-content: flex-start;\n}\n\n.navbar-expand > .container,\n.navbar-expand > .container-fluid {\n padding-right: 0;\n padding-left: 0;\n}\n\n.navbar-expand .navbar-nav {\n flex-direction: row;\n}\n\n.navbar-expand .navbar-nav .dropdown-menu {\n position: absolute;\n}\n\n.navbar-expand .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem;\n}\n\n.navbar-expand > .container,\n.navbar-expand > .container-fluid {\n flex-wrap: nowrap;\n}\n\n.navbar-expand .navbar-collapse {\n display: flex !important;\n flex-basis: auto;\n}\n\n.navbar-expand .navbar-toggler {\n display: none;\n}\n\n.navbar-light .navbar-brand {\n color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-brand:hover, .navbar-light .navbar-brand:focus {\n color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-nav .nav-link {\n color: rgba(0, 0, 0, 0.5);\n}\n\n.navbar-light .navbar-nav .nav-link:hover, .navbar-light .navbar-nav .nav-link:focus {\n color: rgba(0, 0, 0, 0.7);\n}\n\n.navbar-light .navbar-nav .nav-link.disabled {\n color: rgba(0, 0, 0, 0.3);\n}\n\n.navbar-light .navbar-nav .show > .nav-link,\n.navbar-light .navbar-nav .active > .nav-link,\n.navbar-light .navbar-nav .nav-link.show,\n.navbar-light .navbar-nav .nav-link.active {\n color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-toggler {\n color: rgba(0, 0, 0, 0.5);\n border-color: rgba(0, 0, 0, 0.1);\n}\n\n.navbar-light .navbar-toggler-icon {\n background-image: url(\"data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e\");\n}\n\n.navbar-light .navbar-text {\n color: rgba(0, 0, 0, 0.5);\n}\n\n.navbar-light .navbar-text a {\n color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-text a:hover, .navbar-light .navbar-text a:focus {\n color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-dark .navbar-brand {\n color: #fff;\n}\n\n.navbar-dark .navbar-brand:hover, .navbar-dark .navbar-brand:focus {\n color: #fff;\n}\n\n.navbar-dark .navbar-nav .nav-link {\n color: rgba(255, 255, 255, 0.5);\n}\n\n.navbar-dark .navbar-nav .nav-link:hover, .navbar-dark .navbar-nav .nav-link:focus {\n color: rgba(255, 255, 255, 0.75);\n}\n\n.navbar-dark .navbar-nav .nav-link.disabled {\n color: rgba(255, 255, 255, 0.25);\n}\n\n.navbar-dark .navbar-nav .show > .nav-link,\n.navbar-dark .navbar-nav .active > .nav-link,\n.navbar-dark .navbar-nav .nav-link.show,\n.navbar-dark .navbar-nav .nav-link.active {\n color: #fff;\n}\n\n.navbar-dark .navbar-toggler {\n color: rgba(255, 255, 255, 0.5);\n border-color: rgba(255, 255, 255, 0.1);\n}\n\n.navbar-dark .navbar-toggler-icon {\n background-image: url(\"data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e\");\n}\n\n.navbar-dark .navbar-text {\n color: rgba(255, 255, 255, 0.5);\n}\n\n.navbar-dark .navbar-text a {\n color: #fff;\n}\n\n.navbar-dark .navbar-text a:hover, .navbar-dark .navbar-text a:focus {\n color: #fff;\n}\n\n.card {\n position: relative;\n display: flex;\n flex-direction: column;\n min-width: 0;\n word-wrap: break-word;\n background-color: #fff;\n background-clip: border-box;\n border: 1px solid rgba(0, 0, 0, 0.125);\n border-radius: 0.25rem;\n}\n\n.card > hr {\n margin-right: 0;\n margin-left: 0;\n}\n\n.card > .list-group:first-child .list-group-item:first-child {\n border-top-left-radius: 0.25rem;\n border-top-right-radius: 0.25rem;\n}\n\n.card > .list-group:last-child .list-group-item:last-child {\n border-bottom-right-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n}\n\n.card-body {\n flex: 1 1 auto;\n padding: 1.25rem;\n}\n\n.card-title {\n margin-bottom: 0.75rem;\n}\n\n.card-subtitle {\n margin-top: -0.375rem;\n margin-bottom: 0;\n}\n\n.card-text:last-child {\n margin-bottom: 0;\n}\n\n.card-link:hover {\n text-decoration: none;\n}\n\n.card-link + .card-link {\n margin-left: 1.25rem;\n}\n\n.card-header {\n padding: 0.75rem 1.25rem;\n margin-bottom: 0;\n background-color: rgba(0, 0, 0, 0.03);\n border-bottom: 1px solid rgba(0, 0, 0, 0.125);\n}\n\n.card-header:first-child {\n border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0;\n}\n\n.card-header + .list-group .list-group-item:first-child {\n border-top: 0;\n}\n\n.card-footer {\n padding: 0.75rem 1.25rem;\n background-color: rgba(0, 0, 0, 0.03);\n border-top: 1px solid rgba(0, 0, 0, 0.125);\n}\n\n.card-footer:last-child {\n border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px);\n}\n\n.card-header-tabs {\n margin-right: -0.625rem;\n margin-bottom: -0.75rem;\n margin-left: -0.625rem;\n border-bottom: 0;\n}\n\n.card-header-pills {\n margin-right: -0.625rem;\n margin-left: -0.625rem;\n}\n\n.card-img-overlay {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n padding: 1.25rem;\n}\n\n.card-img {\n width: 100%;\n border-radius: calc(0.25rem - 1px);\n}\n\n.card-img-top {\n width: 100%;\n border-top-left-radius: calc(0.25rem - 1px);\n border-top-right-radius: calc(0.25rem - 1px);\n}\n\n.card-img-bottom {\n width: 100%;\n border-bottom-right-radius: calc(0.25rem - 1px);\n border-bottom-left-radius: calc(0.25rem - 1px);\n}\n\n.card-deck {\n display: flex;\n flex-direction: column;\n}\n\n.card-deck .card {\n margin-bottom: 15px;\n}\n\n@media (min-width: 576px) {\n .card-deck {\n flex-flow: row wrap;\n margin-right: -15px;\n margin-left: -15px;\n }\n .card-deck .card {\n display: flex;\n flex: 1 0 0%;\n flex-direction: column;\n margin-right: 15px;\n margin-bottom: 0;\n margin-left: 15px;\n }\n}\n\n.card-group {\n display: flex;\n flex-direction: column;\n}\n\n.card-group > .card {\n margin-bottom: 15px;\n}\n\n@media (min-width: 576px) {\n .card-group {\n flex-flow: row wrap;\n }\n .card-group > .card {\n flex: 1 0 0%;\n margin-bottom: 0;\n }\n .card-group > .card + .card {\n margin-left: 0;\n border-left: 0;\n }\n .card-group > .card:not(:last-child) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n }\n .card-group > .card:not(:last-child) .card-img-top,\n .card-group > .card:not(:last-child) .card-header {\n border-top-right-radius: 0;\n }\n .card-group > .card:not(:last-child) .card-img-bottom,\n .card-group > .card:not(:last-child) .card-footer {\n border-bottom-right-radius: 0;\n }\n .card-group > .card:not(:first-child) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n }\n .card-group > .card:not(:first-child) .card-img-top,\n .card-group > .card:not(:first-child) .card-header {\n border-top-left-radius: 0;\n }\n .card-group > .card:not(:first-child) .card-img-bottom,\n .card-group > .card:not(:first-child) .card-footer {\n border-bottom-left-radius: 0;\n }\n}\n\n.card-columns .card {\n margin-bottom: 0.75rem;\n}\n\n@media (min-width: 576px) {\n .card-columns {\n column-count: 3;\n column-gap: 1.25rem;\n orphans: 1;\n widows: 1;\n }\n .card-columns .card {\n display: inline-block;\n width: 100%;\n }\n}\n\n.accordion > .card {\n overflow: hidden;\n}\n\n.accordion > .card:not(:first-of-type) .card-header:first-child {\n border-radius: 0;\n}\n\n.accordion > .card:not(:first-of-type):not(:last-of-type) {\n border-bottom: 0;\n border-radius: 0;\n}\n\n.accordion > .card:first-of-type {\n border-bottom: 0;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.accordion > .card:last-of-type {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n\n.accordion > .card .card-header {\n margin-bottom: -1px;\n}\n\n.breadcrumb {\n display: flex;\n flex-wrap: wrap;\n padding: 0.75rem 1rem;\n margin-bottom: 1rem;\n list-style: none;\n background-color: #e9ecef;\n border-radius: 0.25rem;\n}\n\n.breadcrumb-item + .breadcrumb-item {\n padding-left: 0.5rem;\n}\n\n.breadcrumb-item + .breadcrumb-item::before {\n display: inline-block;\n padding-right: 0.5rem;\n color: #6c757d;\n content: \"/\";\n}\n\n.breadcrumb-item + .breadcrumb-item:hover::before {\n text-decoration: underline;\n}\n\n.breadcrumb-item + .breadcrumb-item:hover::before {\n text-decoration: none;\n}\n\n.breadcrumb-item.active {\n color: #6c757d;\n}\n\n.pagination {\n display: flex;\n padding-left: 0;\n list-style: none;\n border-radius: 0.25rem;\n}\n\n.page-link {\n position: relative;\n display: block;\n padding: 0.5rem 0.75rem;\n margin-left: -1px;\n line-height: 1.25;\n color: #007bff;\n background-color: #fff;\n border: 1px solid #dee2e6;\n}\n\n.page-link:hover {\n z-index: 2;\n color: #0056b3;\n text-decoration: none;\n background-color: #e9ecef;\n border-color: #dee2e6;\n}\n\n.page-link:focus {\n z-index: 2;\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.page-item:first-child .page-link {\n margin-left: 0;\n border-top-left-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n}\n\n.page-item:last-child .page-link {\n border-top-right-radius: 0.25rem;\n border-bottom-right-radius: 0.25rem;\n}\n\n.page-item.active .page-link {\n z-index: 1;\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.page-item.disabled .page-link {\n color: #6c757d;\n pointer-events: none;\n cursor: auto;\n background-color: #fff;\n border-color: #dee2e6;\n}\n\n.pagination-lg .page-link {\n padding: 0.75rem 1.5rem;\n font-size: 1.25rem;\n line-height: 1.5;\n}\n\n.pagination-lg .page-item:first-child .page-link {\n border-top-left-radius: 0.3rem;\n border-bottom-left-radius: 0.3rem;\n}\n\n.pagination-lg .page-item:last-child .page-link {\n border-top-right-radius: 0.3rem;\n border-bottom-right-radius: 0.3rem;\n}\n\n.pagination-sm .page-link {\n padding: 0.25rem 0.5rem;\n font-size: 0.875rem;\n line-height: 1.5;\n}\n\n.pagination-sm .page-item:first-child .page-link {\n border-top-left-radius: 0.2rem;\n border-bottom-left-radius: 0.2rem;\n}\n\n.pagination-sm .page-item:last-child .page-link {\n border-top-right-radius: 0.2rem;\n border-bottom-right-radius: 0.2rem;\n}\n\n.badge {\n display: inline-block;\n padding: 0.25em 0.4em;\n font-size: 75%;\n font-weight: 700;\n line-height: 1;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: 0.25rem;\n transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .badge {\n transition: none;\n }\n}\n\na.badge:hover, a.badge:focus {\n text-decoration: none;\n}\n\n.badge:empty {\n display: none;\n}\n\n.btn .badge {\n position: relative;\n top: -1px;\n}\n\n.badge-pill {\n padding-right: 0.6em;\n padding-left: 0.6em;\n border-radius: 10rem;\n}\n\n.badge-primary {\n color: #fff;\n background-color: #007bff;\n}\n\na.badge-primary:hover, a.badge-primary:focus {\n color: #fff;\n background-color: #0062cc;\n}\n\na.badge-primary:focus, a.badge-primary.focus {\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);\n}\n\n.badge-secondary {\n color: #fff;\n background-color: #6c757d;\n}\n\na.badge-secondary:hover, a.badge-secondary:focus {\n color: #fff;\n background-color: #545b62;\n}\n\na.badge-secondary:focus, a.badge-secondary.focus {\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5);\n}\n\n.badge-success {\n color: #fff;\n background-color: #28a745;\n}\n\na.badge-success:hover, a.badge-success:focus {\n color: #fff;\n background-color: #1e7e34;\n}\n\na.badge-success:focus, a.badge-success.focus {\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);\n}\n\n.badge-info {\n color: #fff;\n background-color: #17a2b8;\n}\n\na.badge-info:hover, a.badge-info:focus {\n color: #fff;\n background-color: #117a8b;\n}\n\na.badge-info:focus, a.badge-info.focus {\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);\n}\n\n.badge-warning {\n color: #212529;\n background-color: #ffc107;\n}\n\na.badge-warning:hover, a.badge-warning:focus {\n color: #212529;\n background-color: #d39e00;\n}\n\na.badge-warning:focus, a.badge-warning.focus {\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);\n}\n\n.badge-danger {\n color: #fff;\n background-color: #dc3545;\n}\n\na.badge-danger:hover, a.badge-danger:focus {\n color: #fff;\n background-color: #bd2130;\n}\n\na.badge-danger:focus, a.badge-danger.focus {\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);\n}\n\n.badge-light {\n color: #212529;\n background-color: #f8f9fa;\n}\n\na.badge-light:hover, a.badge-light:focus {\n color: #212529;\n background-color: #dae0e5;\n}\n\na.badge-light:focus, a.badge-light.focus {\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);\n}\n\n.badge-dark {\n color: #fff;\n background-color: #343a40;\n}\n\na.badge-dark:hover, a.badge-dark:focus {\n color: #fff;\n background-color: #1d2124;\n}\n\na.badge-dark:focus, a.badge-dark.focus {\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);\n}\n\n.jumbotron {\n padding: 2rem 1rem;\n margin-bottom: 2rem;\n background-color: #e9ecef;\n border-radius: 0.3rem;\n}\n\n@media (min-width: 576px) {\n .jumbotron {\n padding: 4rem 2rem;\n }\n}\n\n.jumbotron-fluid {\n padding-right: 0;\n padding-left: 0;\n border-radius: 0;\n}\n\n.alert {\n position: relative;\n padding: 0.75rem 1.25rem;\n margin-bottom: 1rem;\n border: 1px solid transparent;\n border-radius: 0.25rem;\n}\n\n.alert-heading {\n color: inherit;\n}\n\n.alert-link {\n font-weight: 700;\n}\n\n.alert-dismissible {\n padding-right: 4rem;\n}\n\n.alert-dismissible .close {\n position: absolute;\n top: 0;\n right: 0;\n padding: 0.75rem 1.25rem;\n color: inherit;\n}\n\n.alert-primary {\n color: #004085;\n background-color: #cce5ff;\n border-color: #b8daff;\n}\n\n.alert-primary hr {\n border-top-color: #9fcdff;\n}\n\n.alert-primary .alert-link {\n color: #002752;\n}\n\n.alert-secondary {\n color: #383d41;\n background-color: #e2e3e5;\n border-color: #d6d8db;\n}\n\n.alert-secondary hr {\n border-top-color: #c8cbcf;\n}\n\n.alert-secondary .alert-link {\n color: #202326;\n}\n\n.alert-success {\n color: #155724;\n background-color: #d4edda;\n border-color: #c3e6cb;\n}\n\n.alert-success hr {\n border-top-color: #b1dfbb;\n}\n\n.alert-success .alert-link {\n color: #0b2e13;\n}\n\n.alert-info {\n color: #0c5460;\n background-color: #d1ecf1;\n border-color: #bee5eb;\n}\n\n.alert-info hr {\n border-top-color: #abdde5;\n}\n\n.alert-info .alert-link {\n color: #062c33;\n}\n\n.alert-warning {\n color: #856404;\n background-color: #fff3cd;\n border-color: #ffeeba;\n}\n\n.alert-warning hr {\n border-top-color: #ffe8a1;\n}\n\n.alert-warning .alert-link {\n color: #533f03;\n}\n\n.alert-danger {\n color: #721c24;\n background-color: #f8d7da;\n border-color: #f5c6cb;\n}\n\n.alert-danger hr {\n border-top-color: #f1b0b7;\n}\n\n.alert-danger .alert-link {\n color: #491217;\n}\n\n.alert-light {\n color: #818182;\n background-color: #fefefe;\n border-color: #fdfdfe;\n}\n\n.alert-light hr {\n border-top-color: #ececf6;\n}\n\n.alert-light .alert-link {\n color: #686868;\n}\n\n.alert-dark {\n color: #1b1e21;\n background-color: #d6d8d9;\n border-color: #c6c8ca;\n}\n\n.alert-dark hr {\n border-top-color: #b9bbbe;\n}\n\n.alert-dark .alert-link {\n color: #040505;\n}\n\n@keyframes progress-bar-stripes {\n from {\n background-position: 1rem 0;\n }\n to {\n background-position: 0 0;\n }\n}\n\n.progress {\n display: flex;\n height: 1rem;\n overflow: hidden;\n font-size: 0.75rem;\n background-color: #e9ecef;\n border-radius: 0.25rem;\n}\n\n.progress-bar {\n display: flex;\n flex-direction: column;\n justify-content: center;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n background-color: #007bff;\n transition: width 0.6s ease;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .progress-bar {\n transition: none;\n }\n}\n\n.progress-bar-striped {\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-size: 1rem 1rem;\n}\n\n.progress-bar-animated {\n animation: progress-bar-stripes 1s linear infinite;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .progress-bar-animated {\n animation: none;\n }\n}\n\n.media {\n display: flex;\n align-items: flex-start;\n}\n\n.media-body {\n flex: 1;\n}\n\n.list-group {\n display: flex;\n flex-direction: column;\n padding-left: 0;\n margin-bottom: 0;\n}\n\n.list-group-item-action {\n width: 100%;\n color: #495057;\n text-align: inherit;\n}\n\n.list-group-item-action:hover, .list-group-item-action:focus {\n z-index: 1;\n color: #495057;\n text-decoration: none;\n background-color: #f8f9fa;\n}\n\n.list-group-item-action:active {\n color: #212529;\n background-color: #e9ecef;\n}\n\n.list-group-item {\n position: relative;\n display: block;\n padding: 0.75rem 1.25rem;\n margin-bottom: -1px;\n background-color: #fff;\n border: 1px solid rgba(0, 0, 0, 0.125);\n}\n\n.list-group-item:first-child {\n border-top-left-radius: 0.25rem;\n border-top-right-radius: 0.25rem;\n}\n\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n}\n\n.list-group-item.disabled, .list-group-item:disabled {\n color: #6c757d;\n pointer-events: none;\n background-color: #fff;\n}\n\n.list-group-item.active {\n z-index: 2;\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.list-group-horizontal {\n flex-direction: row;\n}\n\n.list-group-horizontal .list-group-item {\n margin-right: -1px;\n margin-bottom: 0;\n}\n\n.list-group-horizontal .list-group-item:first-child {\n border-top-left-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n border-top-right-radius: 0;\n}\n\n.list-group-horizontal .list-group-item:last-child {\n margin-right: 0;\n border-top-right-radius: 0.25rem;\n border-bottom-right-radius: 0.25rem;\n border-bottom-left-radius: 0;\n}\n\n@media (min-width: 576px) {\n .list-group-horizontal-sm {\n flex-direction: row;\n }\n .list-group-horizontal-sm .list-group-item {\n margin-right: -1px;\n margin-bottom: 0;\n }\n .list-group-horizontal-sm .list-group-item:first-child {\n border-top-left-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n border-top-right-radius: 0;\n }\n .list-group-horizontal-sm .list-group-item:last-child {\n margin-right: 0;\n border-top-right-radius: 0.25rem;\n border-bottom-right-radius: 0.25rem;\n border-bottom-left-radius: 0;\n }\n}\n\n@media (min-width: 768px) {\n .list-group-horizontal-md {\n flex-direction: row;\n }\n .list-group-horizontal-md .list-group-item {\n margin-right: -1px;\n margin-bottom: 0;\n }\n .list-group-horizontal-md .list-group-item:first-child {\n border-top-left-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n border-top-right-radius: 0;\n }\n .list-group-horizontal-md .list-group-item:last-child {\n margin-right: 0;\n border-top-right-radius: 0.25rem;\n border-bottom-right-radius: 0.25rem;\n border-bottom-left-radius: 0;\n }\n}\n\n@media (min-width: 992px) {\n .list-group-horizontal-lg {\n flex-direction: row;\n }\n .list-group-horizontal-lg .list-group-item {\n margin-right: -1px;\n margin-bottom: 0;\n }\n .list-group-horizontal-lg .list-group-item:first-child {\n border-top-left-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n border-top-right-radius: 0;\n }\n .list-group-horizontal-lg .list-group-item:last-child {\n margin-right: 0;\n border-top-right-radius: 0.25rem;\n border-bottom-right-radius: 0.25rem;\n border-bottom-left-radius: 0;\n }\n}\n\n@media (min-width: 1200px) {\n .list-group-horizontal-xl {\n flex-direction: row;\n }\n .list-group-horizontal-xl .list-group-item {\n margin-right: -1px;\n margin-bottom: 0;\n }\n .list-group-horizontal-xl .list-group-item:first-child {\n border-top-left-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n border-top-right-radius: 0;\n }\n .list-group-horizontal-xl .list-group-item:last-child {\n margin-right: 0;\n border-top-right-radius: 0.25rem;\n border-bottom-right-radius: 0.25rem;\n border-bottom-left-radius: 0;\n }\n}\n\n.list-group-flush .list-group-item {\n border-right: 0;\n border-left: 0;\n border-radius: 0;\n}\n\n.list-group-flush .list-group-item:last-child {\n margin-bottom: -1px;\n}\n\n.list-group-flush:first-child .list-group-item:first-child {\n border-top: 0;\n}\n\n.list-group-flush:last-child .list-group-item:last-child {\n margin-bottom: 0;\n border-bottom: 0;\n}\n\n.list-group-item-primary {\n color: #004085;\n background-color: #b8daff;\n}\n\n.list-group-item-primary.list-group-item-action:hover, .list-group-item-primary.list-group-item-action:focus {\n color: #004085;\n background-color: #9fcdff;\n}\n\n.list-group-item-primary.list-group-item-action.active {\n color: #fff;\n background-color: #004085;\n border-color: #004085;\n}\n\n.list-group-item-secondary {\n color: #383d41;\n background-color: #d6d8db;\n}\n\n.list-group-item-secondary.list-group-item-action:hover, .list-group-item-secondary.list-group-item-action:focus {\n color: #383d41;\n background-color: #c8cbcf;\n}\n\n.list-group-item-secondary.list-group-item-action.active {\n color: #fff;\n background-color: #383d41;\n border-color: #383d41;\n}\n\n.list-group-item-success {\n color: #155724;\n background-color: #c3e6cb;\n}\n\n.list-group-item-success.list-group-item-action:hover, .list-group-item-success.list-group-item-action:focus {\n color: #155724;\n background-color: #b1dfbb;\n}\n\n.list-group-item-success.list-group-item-action.active {\n color: #fff;\n background-color: #155724;\n border-color: #155724;\n}\n\n.list-group-item-info {\n color: #0c5460;\n background-color: #bee5eb;\n}\n\n.list-group-item-info.list-group-item-action:hover, .list-group-item-info.list-group-item-action:focus {\n color: #0c5460;\n background-color: #abdde5;\n}\n\n.list-group-item-info.list-group-item-action.active {\n color: #fff;\n background-color: #0c5460;\n border-color: #0c5460;\n}\n\n.list-group-item-warning {\n color: #856404;\n background-color: #ffeeba;\n}\n\n.list-group-item-warning.list-group-item-action:hover, .list-group-item-warning.list-group-item-action:focus {\n color: #856404;\n background-color: #ffe8a1;\n}\n\n.list-group-item-warning.list-group-item-action.active {\n color: #fff;\n background-color: #856404;\n border-color: #856404;\n}\n\n.list-group-item-danger {\n color: #721c24;\n background-color: #f5c6cb;\n}\n\n.list-group-item-danger.list-group-item-action:hover, .list-group-item-danger.list-group-item-action:focus {\n color: #721c24;\n background-color: #f1b0b7;\n}\n\n.list-group-item-danger.list-group-item-action.active {\n color: #fff;\n background-color: #721c24;\n border-color: #721c24;\n}\n\n.list-group-item-light {\n color: #818182;\n background-color: #fdfdfe;\n}\n\n.list-group-item-light.list-group-item-action:hover, .list-group-item-light.list-group-item-action:focus {\n color: #818182;\n background-color: #ececf6;\n}\n\n.list-group-item-light.list-group-item-action.active {\n color: #fff;\n background-color: #818182;\n border-color: #818182;\n}\n\n.list-group-item-dark {\n color: #1b1e21;\n background-color: #c6c8ca;\n}\n\n.list-group-item-dark.list-group-item-action:hover, .list-group-item-dark.list-group-item-action:focus {\n color: #1b1e21;\n background-color: #b9bbbe;\n}\n\n.list-group-item-dark.list-group-item-action.active {\n color: #fff;\n background-color: #1b1e21;\n border-color: #1b1e21;\n}\n\n.close {\n float: right;\n font-size: 1.5rem;\n font-weight: 700;\n line-height: 1;\n color: #000;\n text-shadow: 0 1px 0 #fff;\n opacity: .5;\n}\n\n.close:hover {\n color: #000;\n text-decoration: none;\n}\n\n.close:not(:disabled):not(.disabled):hover, .close:not(:disabled):not(.disabled):focus {\n opacity: .75;\n}\n\nbutton.close {\n padding: 0;\n background-color: transparent;\n border: 0;\n appearance: none;\n}\n\na.close.disabled {\n pointer-events: none;\n}\n\n.toast {\n max-width: 350px;\n overflow: hidden;\n font-size: 0.875rem;\n background-color: rgba(255, 255, 255, 0.85);\n background-clip: padding-box;\n border: 1px solid rgba(0, 0, 0, 0.1);\n box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.1);\n backdrop-filter: blur(10px);\n opacity: 0;\n border-radius: 0.25rem;\n}\n\n.toast:not(:last-child) {\n margin-bottom: 0.75rem;\n}\n\n.toast.showing {\n opacity: 1;\n}\n\n.toast.show {\n display: block;\n opacity: 1;\n}\n\n.toast.hide {\n display: none;\n}\n\n.toast-header {\n display: flex;\n align-items: center;\n padding: 0.25rem 0.75rem;\n color: #6c757d;\n background-color: rgba(255, 255, 255, 0.85);\n background-clip: padding-box;\n border-bottom: 1px solid rgba(0, 0, 0, 0.05);\n}\n\n.toast-body {\n padding: 0.75rem;\n}\n\n.modal-open {\n overflow: hidden;\n}\n\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n\n.modal {\n position: fixed;\n top: 0;\n left: 0;\n z-index: 1050;\n display: none;\n width: 100%;\n height: 100%;\n overflow: hidden;\n outline: 0;\n}\n\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 0.5rem;\n pointer-events: none;\n}\n\n.modal.fade .modal-dialog {\n transition: transform 0.3s ease-out;\n transform: translate(0, -50px);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .modal.fade .modal-dialog {\n transition: none;\n }\n}\n\n.modal.show .modal-dialog {\n transform: none;\n}\n\n.modal-dialog-scrollable {\n display: flex;\n max-height: calc(100% - 1rem);\n}\n\n.modal-dialog-scrollable .modal-content {\n max-height: calc(100vh - 1rem);\n overflow: hidden;\n}\n\n.modal-dialog-scrollable .modal-header,\n.modal-dialog-scrollable .modal-footer {\n flex-shrink: 0;\n}\n\n.modal-dialog-scrollable .modal-body {\n overflow-y: auto;\n}\n\n.modal-dialog-centered {\n display: flex;\n align-items: center;\n min-height: calc(100% - 1rem);\n}\n\n.modal-dialog-centered::before {\n display: block;\n height: calc(100vh - 1rem);\n content: \"\";\n}\n\n.modal-dialog-centered.modal-dialog-scrollable {\n flex-direction: column;\n justify-content: center;\n height: 100%;\n}\n\n.modal-dialog-centered.modal-dialog-scrollable .modal-content {\n max-height: none;\n}\n\n.modal-dialog-centered.modal-dialog-scrollable::before {\n content: none;\n}\n\n.modal-content {\n position: relative;\n display: flex;\n flex-direction: column;\n width: 100%;\n pointer-events: auto;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 0.3rem;\n outline: 0;\n}\n\n.modal-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n z-index: 1040;\n width: 100vw;\n height: 100vh;\n background-color: #000;\n}\n\n.modal-backdrop.fade {\n opacity: 0;\n}\n\n.modal-backdrop.show {\n opacity: 0.5;\n}\n\n.modal-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n padding: 1rem 1rem;\n border-bottom: 1px solid #dee2e6;\n border-top-left-radius: 0.3rem;\n border-top-right-radius: 0.3rem;\n}\n\n.modal-header .close {\n padding: 1rem 1rem;\n margin: -1rem -1rem -1rem auto;\n}\n\n.modal-title {\n margin-bottom: 0;\n line-height: 1.5;\n}\n\n.modal-body {\n position: relative;\n flex: 1 1 auto;\n padding: 1rem;\n}\n\n.modal-footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n padding: 1rem;\n border-top: 1px solid #dee2e6;\n border-bottom-right-radius: 0.3rem;\n border-bottom-left-radius: 0.3rem;\n}\n\n.modal-footer > :not(:first-child) {\n margin-left: .25rem;\n}\n\n.modal-footer > :not(:last-child) {\n margin-right: .25rem;\n}\n\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n\n@media (min-width: 576px) {\n .modal-dialog {\n max-width: 500px;\n margin: 1.75rem auto;\n }\n .modal-dialog-scrollable {\n max-height: calc(100% - 3.5rem);\n }\n .modal-dialog-scrollable .modal-content {\n max-height: calc(100vh - 3.5rem);\n }\n .modal-dialog-centered {\n min-height: calc(100% - 3.5rem);\n }\n .modal-dialog-centered::before {\n height: calc(100vh - 3.5rem);\n }\n .modal-sm {\n max-width: 300px;\n }\n}\n\n@media (min-width: 992px) {\n .modal-lg,\n .modal-xl {\n max-width: 800px;\n }\n}\n\n@media (min-width: 1200px) {\n .modal-xl {\n max-width: 1140px;\n }\n}\n\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-style: normal;\n font-weight: 400;\n line-height: 1.5;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n white-space: normal;\n line-break: auto;\n font-size: 0.875rem;\n word-wrap: break-word;\n opacity: 0;\n}\n\n.tooltip.show {\n opacity: 0.9;\n}\n\n.tooltip .arrow {\n position: absolute;\n display: block;\n width: 0.8rem;\n height: 0.4rem;\n}\n\n.tooltip .arrow::before {\n position: absolute;\n content: \"\";\n border-color: transparent;\n border-style: solid;\n}\n\n.bs-tooltip-top, .bs-tooltip-auto[x-placement^=\"top\"] {\n padding: 0.4rem 0;\n}\n\n.bs-tooltip-top .arrow, .bs-tooltip-auto[x-placement^=\"top\"] .arrow {\n bottom: 0;\n}\n\n.bs-tooltip-top .arrow::before, .bs-tooltip-auto[x-placement^=\"top\"] .arrow::before {\n top: 0;\n border-width: 0.4rem 0.4rem 0;\n border-top-color: #000;\n}\n\n.bs-tooltip-right, .bs-tooltip-auto[x-placement^=\"right\"] {\n padding: 0 0.4rem;\n}\n\n.bs-tooltip-right .arrow, .bs-tooltip-auto[x-placement^=\"right\"] .arrow {\n left: 0;\n width: 0.4rem;\n height: 0.8rem;\n}\n\n.bs-tooltip-right .arrow::before, .bs-tooltip-auto[x-placement^=\"right\"] .arrow::before {\n right: 0;\n border-width: 0.4rem 0.4rem 0.4rem 0;\n border-right-color: #000;\n}\n\n.bs-tooltip-bottom, .bs-tooltip-auto[x-placement^=\"bottom\"] {\n padding: 0.4rem 0;\n}\n\n.bs-tooltip-bottom .arrow, .bs-tooltip-auto[x-placement^=\"bottom\"] .arrow {\n top: 0;\n}\n\n.bs-tooltip-bottom .arrow::before, .bs-tooltip-auto[x-placement^=\"bottom\"] .arrow::before {\n bottom: 0;\n border-width: 0 0.4rem 0.4rem;\n border-bottom-color: #000;\n}\n\n.bs-tooltip-left, .bs-tooltip-auto[x-placement^=\"left\"] {\n padding: 0 0.4rem;\n}\n\n.bs-tooltip-left .arrow, .bs-tooltip-auto[x-placement^=\"left\"] .arrow {\n right: 0;\n width: 0.4rem;\n height: 0.8rem;\n}\n\n.bs-tooltip-left .arrow::before, .bs-tooltip-auto[x-placement^=\"left\"] .arrow::before {\n left: 0;\n border-width: 0.4rem 0 0.4rem 0.4rem;\n border-left-color: #000;\n}\n\n.tooltip-inner {\n max-width: 200px;\n padding: 0.25rem 0.5rem;\n color: #fff;\n text-align: center;\n background-color: #000;\n border-radius: 0.25rem;\n}\n\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: block;\n max-width: 276px;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-style: normal;\n font-weight: 400;\n line-height: 1.5;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n white-space: normal;\n line-break: auto;\n font-size: 0.875rem;\n word-wrap: break-word;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 0.3rem;\n}\n\n.popover .arrow {\n position: absolute;\n display: block;\n width: 1rem;\n height: 0.5rem;\n margin: 0 0.3rem;\n}\n\n.popover .arrow::before, .popover .arrow::after {\n position: absolute;\n display: block;\n content: \"\";\n border-color: transparent;\n border-style: solid;\n}\n\n.bs-popover-top, .bs-popover-auto[x-placement^=\"top\"] {\n margin-bottom: 0.5rem;\n}\n\n.bs-popover-top > .arrow, .bs-popover-auto[x-placement^=\"top\"] > .arrow {\n bottom: calc((0.5rem + 1px) * -1);\n}\n\n.bs-popover-top > .arrow::before, .bs-popover-auto[x-placement^=\"top\"] > .arrow::before {\n bottom: 0;\n border-width: 0.5rem 0.5rem 0;\n border-top-color: rgba(0, 0, 0, 0.25);\n}\n\n.bs-popover-top > .arrow::after, .bs-popover-auto[x-placement^=\"top\"] > .arrow::after {\n bottom: 1px;\n border-width: 0.5rem 0.5rem 0;\n border-top-color: #fff;\n}\n\n.bs-popover-right, .bs-popover-auto[x-placement^=\"right\"] {\n margin-left: 0.5rem;\n}\n\n.bs-popover-right > .arrow, .bs-popover-auto[x-placement^=\"right\"] > .arrow {\n left: calc((0.5rem + 1px) * -1);\n width: 0.5rem;\n height: 1rem;\n margin: 0.3rem 0;\n}\n\n.bs-popover-right > .arrow::before, .bs-popover-auto[x-placement^=\"right\"] > .arrow::before {\n left: 0;\n border-width: 0.5rem 0.5rem 0.5rem 0;\n border-right-color: rgba(0, 0, 0, 0.25);\n}\n\n.bs-popover-right > .arrow::after, .bs-popover-auto[x-placement^=\"right\"] > .arrow::after {\n left: 1px;\n border-width: 0.5rem 0.5rem 0.5rem 0;\n border-right-color: #fff;\n}\n\n.bs-popover-bottom, .bs-popover-auto[x-placement^=\"bottom\"] {\n margin-top: 0.5rem;\n}\n\n.bs-popover-bottom > .arrow, .bs-popover-auto[x-placement^=\"bottom\"] > .arrow {\n top: calc((0.5rem + 1px) * -1);\n}\n\n.bs-popover-bottom > .arrow::before, .bs-popover-auto[x-placement^=\"bottom\"] > .arrow::before {\n top: 0;\n border-width: 0 0.5rem 0.5rem 0.5rem;\n border-bottom-color: rgba(0, 0, 0, 0.25);\n}\n\n.bs-popover-bottom > .arrow::after, .bs-popover-auto[x-placement^=\"bottom\"] > .arrow::after {\n top: 1px;\n border-width: 0 0.5rem 0.5rem 0.5rem;\n border-bottom-color: #fff;\n}\n\n.bs-popover-bottom .popover-header::before, .bs-popover-auto[x-placement^=\"bottom\"] .popover-header::before {\n position: absolute;\n top: 0;\n left: 50%;\n display: block;\n width: 1rem;\n margin-left: -0.5rem;\n content: \"\";\n border-bottom: 1px solid #f7f7f7;\n}\n\n.bs-popover-left, .bs-popover-auto[x-placement^=\"left\"] {\n margin-right: 0.5rem;\n}\n\n.bs-popover-left > .arrow, .bs-popover-auto[x-placement^=\"left\"] > .arrow {\n right: calc((0.5rem + 1px) * -1);\n width: 0.5rem;\n height: 1rem;\n margin: 0.3rem 0;\n}\n\n.bs-popover-left > .arrow::before, .bs-popover-auto[x-placement^=\"left\"] > .arrow::before {\n right: 0;\n border-width: 0.5rem 0 0.5rem 0.5rem;\n border-left-color: rgba(0, 0, 0, 0.25);\n}\n\n.bs-popover-left > .arrow::after, .bs-popover-auto[x-placement^=\"left\"] > .arrow::after {\n right: 1px;\n border-width: 0.5rem 0 0.5rem 0.5rem;\n border-left-color: #fff;\n}\n\n.popover-header {\n padding: 0.5rem 0.75rem;\n margin-bottom: 0;\n font-size: 1rem;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-top-left-radius: calc(0.3rem - 1px);\n border-top-right-radius: calc(0.3rem - 1px);\n}\n\n.popover-header:empty {\n display: none;\n}\n\n.popover-body {\n padding: 0.5rem 0.75rem;\n color: #212529;\n}\n\n.carousel {\n position: relative;\n}\n\n.carousel.pointer-event {\n touch-action: pan-y;\n}\n\n.carousel-inner {\n position: relative;\n width: 100%;\n overflow: hidden;\n}\n\n.carousel-inner::after {\n display: block;\n clear: both;\n content: \"\";\n}\n\n.carousel-item {\n position: relative;\n display: none;\n float: left;\n width: 100%;\n margin-right: -100%;\n backface-visibility: hidden;\n transition: transform 0.6s ease-in-out;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .carousel-item {\n transition: none;\n }\n}\n\n.carousel-item.active,\n.carousel-item-next,\n.carousel-item-prev {\n display: block;\n}\n\n.carousel-item-next:not(.carousel-item-left),\n.active.carousel-item-right {\n transform: translateX(100%);\n}\n\n.carousel-item-prev:not(.carousel-item-right),\n.active.carousel-item-left {\n transform: translateX(-100%);\n}\n\n.carousel-fade .carousel-item {\n opacity: 0;\n transition-property: opacity;\n transform: none;\n}\n\n.carousel-fade .carousel-item.active,\n.carousel-fade .carousel-item-next.carousel-item-left,\n.carousel-fade .carousel-item-prev.carousel-item-right {\n z-index: 1;\n opacity: 1;\n}\n\n.carousel-fade .active.carousel-item-left,\n.carousel-fade .active.carousel-item-right {\n z-index: 0;\n opacity: 0;\n transition: 0s 0.6s opacity;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .carousel-fade .active.carousel-item-left,\n .carousel-fade .active.carousel-item-right {\n transition: none;\n }\n}\n\n.carousel-control-prev,\n.carousel-control-next {\n position: absolute;\n top: 0;\n bottom: 0;\n z-index: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 15%;\n color: #fff;\n text-align: center;\n opacity: 0.5;\n transition: opacity 0.15s ease;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .carousel-control-prev,\n .carousel-control-next {\n transition: none;\n }\n}\n\n.carousel-control-prev:hover, .carousel-control-prev:focus,\n.carousel-control-next:hover,\n.carousel-control-next:focus {\n color: #fff;\n text-decoration: none;\n outline: 0;\n opacity: 0.9;\n}\n\n.carousel-control-prev {\n left: 0;\n}\n\n.carousel-control-next {\n right: 0;\n}\n\n.carousel-control-prev-icon,\n.carousel-control-next-icon {\n display: inline-block;\n width: 20px;\n height: 20px;\n background: no-repeat 50% / 100% 100%;\n}\n\n.carousel-control-prev-icon {\n background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3e%3c/svg%3e\");\n}\n\n.carousel-control-next-icon {\n background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3e%3c/svg%3e\");\n}\n\n.carousel-indicators {\n position: absolute;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 15;\n display: flex;\n justify-content: center;\n padding-left: 0;\n margin-right: 15%;\n margin-left: 15%;\n list-style: none;\n}\n\n.carousel-indicators li {\n box-sizing: content-box;\n flex: 0 1 auto;\n width: 30px;\n height: 3px;\n margin-right: 3px;\n margin-left: 3px;\n text-indent: -999px;\n cursor: pointer;\n background-color: #fff;\n background-clip: padding-box;\n border-top: 10px solid transparent;\n border-bottom: 10px solid transparent;\n opacity: .5;\n transition: opacity 0.6s ease;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .carousel-indicators li {\n transition: none;\n }\n}\n\n.carousel-indicators .active {\n opacity: 1;\n}\n\n.carousel-caption {\n position: absolute;\n right: 15%;\n bottom: 20px;\n left: 15%;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #fff;\n text-align: center;\n}\n\n@keyframes spinner-border {\n to {\n transform: rotate(360deg);\n }\n}\n\n.spinner-border {\n display: inline-block;\n width: 2rem;\n height: 2rem;\n vertical-align: text-bottom;\n border: 0.25em solid currentColor;\n border-right-color: transparent;\n border-radius: 50%;\n animation: spinner-border .75s linear infinite;\n}\n\n.spinner-border-sm {\n width: 1rem;\n height: 1rem;\n border-width: 0.2em;\n}\n\n@keyframes spinner-grow {\n 0% {\n transform: scale(0);\n }\n 50% {\n opacity: 1;\n }\n}\n\n.spinner-grow {\n display: inline-block;\n width: 2rem;\n height: 2rem;\n vertical-align: text-bottom;\n background-color: currentColor;\n border-radius: 50%;\n opacity: 0;\n animation: spinner-grow .75s linear infinite;\n}\n\n.spinner-grow-sm {\n width: 1rem;\n height: 1rem;\n}\n\n.align-baseline {\n vertical-align: baseline !important;\n}\n\n.align-top {\n vertical-align: top !important;\n}\n\n.align-middle {\n vertical-align: middle !important;\n}\n\n.align-bottom {\n vertical-align: bottom !important;\n}\n\n.align-text-bottom {\n vertical-align: text-bottom !important;\n}\n\n.align-text-top {\n vertical-align: text-top !important;\n}\n\n.bg-primary {\n background-color: #007bff !important;\n}\n\na.bg-primary:hover, a.bg-primary:focus,\nbutton.bg-primary:hover,\nbutton.bg-primary:focus {\n background-color: #0062cc !important;\n}\n\n.bg-secondary {\n background-color: #6c757d !important;\n}\n\na.bg-secondary:hover, a.bg-secondary:focus,\nbutton.bg-secondary:hover,\nbutton.bg-secondary:focus {\n background-color: #545b62 !important;\n}\n\n.bg-success {\n background-color: #28a745 !important;\n}\n\na.bg-success:hover, a.bg-success:focus,\nbutton.bg-success:hover,\nbutton.bg-success:focus {\n background-color: #1e7e34 !important;\n}\n\n.bg-info {\n background-color: #17a2b8 !important;\n}\n\na.bg-info:hover, a.bg-info:focus,\nbutton.bg-info:hover,\nbutton.bg-info:focus {\n background-color: #117a8b !important;\n}\n\n.bg-warning {\n background-color: #ffc107 !important;\n}\n\na.bg-warning:hover, a.bg-warning:focus,\nbutton.bg-warning:hover,\nbutton.bg-warning:focus {\n background-color: #d39e00 !important;\n}\n\n.bg-danger {\n background-color: #dc3545 !important;\n}\n\na.bg-danger:hover, a.bg-danger:focus,\nbutton.bg-danger:hover,\nbutton.bg-danger:focus {\n background-color: #bd2130 !important;\n}\n\n.bg-light {\n background-color: #f8f9fa !important;\n}\n\na.bg-light:hover, a.bg-light:focus,\nbutton.bg-light:hover,\nbutton.bg-light:focus {\n background-color: #dae0e5 !important;\n}\n\n.bg-dark {\n background-color: #343a40 !important;\n}\n\na.bg-dark:hover, a.bg-dark:focus,\nbutton.bg-dark:hover,\nbutton.bg-dark:focus {\n background-color: #1d2124 !important;\n}\n\n.bg-white {\n background-color: #fff !important;\n}\n\n.bg-transparent {\n background-color: transparent !important;\n}\n\n.border {\n border: 1px solid #dee2e6 !important;\n}\n\n.border-top {\n border-top: 1px solid #dee2e6 !important;\n}\n\n.border-right {\n border-right: 1px solid #dee2e6 !important;\n}\n\n.border-bottom {\n border-bottom: 1px solid #dee2e6 !important;\n}\n\n.border-left {\n border-left: 1px solid #dee2e6 !important;\n}\n\n.border-0 {\n border: 0 !important;\n}\n\n.border-top-0 {\n border-top: 0 !important;\n}\n\n.border-right-0 {\n border-right: 0 !important;\n}\n\n.border-bottom-0 {\n border-bottom: 0 !important;\n}\n\n.border-left-0 {\n border-left: 0 !important;\n}\n\n.border-primary {\n border-color: #007bff !important;\n}\n\n.border-secondary {\n border-color: #6c757d !important;\n}\n\n.border-success {\n border-color: #28a745 !important;\n}\n\n.border-info {\n border-color: #17a2b8 !important;\n}\n\n.border-warning {\n border-color: #ffc107 !important;\n}\n\n.border-danger {\n border-color: #dc3545 !important;\n}\n\n.border-light {\n border-color: #f8f9fa !important;\n}\n\n.border-dark {\n border-color: #343a40 !important;\n}\n\n.border-white {\n border-color: #fff !important;\n}\n\n.rounded-sm {\n border-radius: 0.2rem !important;\n}\n\n.rounded {\n border-radius: 0.25rem !important;\n}\n\n.rounded-top {\n border-top-left-radius: 0.25rem !important;\n border-top-right-radius: 0.25rem !important;\n}\n\n.rounded-right {\n border-top-right-radius: 0.25rem !important;\n border-bottom-right-radius: 0.25rem !important;\n}\n\n.rounded-bottom {\n border-bottom-right-radius: 0.25rem !important;\n border-bottom-left-radius: 0.25rem !important;\n}\n\n.rounded-left {\n border-top-left-radius: 0.25rem !important;\n border-bottom-left-radius: 0.25rem !important;\n}\n\n.rounded-lg {\n border-radius: 0.3rem !important;\n}\n\n.rounded-circle {\n border-radius: 50% !important;\n}\n\n.rounded-pill {\n border-radius: 50rem !important;\n}\n\n.rounded-0 {\n border-radius: 0 !important;\n}\n\n.clearfix::after {\n display: block;\n clear: both;\n content: \"\";\n}\n\n.d-none {\n display: none !important;\n}\n\n.d-inline {\n display: inline !important;\n}\n\n.d-inline-block {\n display: inline-block !important;\n}\n\n.d-block {\n display: block !important;\n}\n\n.d-table {\n display: table !important;\n}\n\n.d-table-row {\n display: table-row !important;\n}\n\n.d-table-cell {\n display: table-cell !important;\n}\n\n.d-flex {\n display: flex !important;\n}\n\n.d-inline-flex {\n display: inline-flex !important;\n}\n\n@media (min-width: 576px) {\n .d-sm-none {\n display: none !important;\n }\n .d-sm-inline {\n display: inline !important;\n }\n .d-sm-inline-block {\n display: inline-block !important;\n }\n .d-sm-block {\n display: block !important;\n }\n .d-sm-table {\n display: table !important;\n }\n .d-sm-table-row {\n display: table-row !important;\n }\n .d-sm-table-cell {\n display: table-cell !important;\n }\n .d-sm-flex {\n display: flex !important;\n }\n .d-sm-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 768px) {\n .d-md-none {\n display: none !important;\n }\n .d-md-inline {\n display: inline !important;\n }\n .d-md-inline-block {\n display: inline-block !important;\n }\n .d-md-block {\n display: block !important;\n }\n .d-md-table {\n display: table !important;\n }\n .d-md-table-row {\n display: table-row !important;\n }\n .d-md-table-cell {\n display: table-cell !important;\n }\n .d-md-flex {\n display: flex !important;\n }\n .d-md-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 992px) {\n .d-lg-none {\n display: none !important;\n }\n .d-lg-inline {\n display: inline !important;\n }\n .d-lg-inline-block {\n display: inline-block !important;\n }\n .d-lg-block {\n display: block !important;\n }\n .d-lg-table {\n display: table !important;\n }\n .d-lg-table-row {\n display: table-row !important;\n }\n .d-lg-table-cell {\n display: table-cell !important;\n }\n .d-lg-flex {\n display: flex !important;\n }\n .d-lg-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 1200px) {\n .d-xl-none {\n display: none !important;\n }\n .d-xl-inline {\n display: inline !important;\n }\n .d-xl-inline-block {\n display: inline-block !important;\n }\n .d-xl-block {\n display: block !important;\n }\n .d-xl-table {\n display: table !important;\n }\n .d-xl-table-row {\n display: table-row !important;\n }\n .d-xl-table-cell {\n display: table-cell !important;\n }\n .d-xl-flex {\n display: flex !important;\n }\n .d-xl-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media print {\n .d-print-none {\n display: none !important;\n }\n .d-print-inline {\n display: inline !important;\n }\n .d-print-inline-block {\n display: inline-block !important;\n }\n .d-print-block {\n display: block !important;\n }\n .d-print-table {\n display: table !important;\n }\n .d-print-table-row {\n display: table-row !important;\n }\n .d-print-table-cell {\n display: table-cell !important;\n }\n .d-print-flex {\n display: flex !important;\n }\n .d-print-inline-flex {\n display: inline-flex !important;\n }\n}\n\n.embed-responsive {\n position: relative;\n display: block;\n width: 100%;\n padding: 0;\n overflow: hidden;\n}\n\n.embed-responsive::before {\n display: block;\n content: \"\";\n}\n\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 100%;\n height: 100%;\n border: 0;\n}\n\n.embed-responsive-21by9::before {\n padding-top: 42.857143%;\n}\n\n.embed-responsive-16by9::before {\n padding-top: 56.25%;\n}\n\n.embed-responsive-4by3::before {\n padding-top: 75%;\n}\n\n.embed-responsive-1by1::before {\n padding-top: 100%;\n}\n\n.flex-row {\n flex-direction: row !important;\n}\n\n.flex-column {\n flex-direction: column !important;\n}\n\n.flex-row-reverse {\n flex-direction: row-reverse !important;\n}\n\n.flex-column-reverse {\n flex-direction: column-reverse !important;\n}\n\n.flex-wrap {\n flex-wrap: wrap !important;\n}\n\n.flex-nowrap {\n flex-wrap: nowrap !important;\n}\n\n.flex-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n}\n\n.flex-fill {\n flex: 1 1 auto !important;\n}\n\n.flex-grow-0 {\n flex-grow: 0 !important;\n}\n\n.flex-grow-1 {\n flex-grow: 1 !important;\n}\n\n.flex-shrink-0 {\n flex-shrink: 0 !important;\n}\n\n.flex-shrink-1 {\n flex-shrink: 1 !important;\n}\n\n.justify-content-start {\n justify-content: flex-start !important;\n}\n\n.justify-content-end {\n justify-content: flex-end !important;\n}\n\n.justify-content-center {\n justify-content: center !important;\n}\n\n.justify-content-between {\n justify-content: space-between !important;\n}\n\n.justify-content-around {\n justify-content: space-around !important;\n}\n\n.align-items-start {\n align-items: flex-start !important;\n}\n\n.align-items-end {\n align-items: flex-end !important;\n}\n\n.align-items-center {\n align-items: center !important;\n}\n\n.align-items-baseline {\n align-items: baseline !important;\n}\n\n.align-items-stretch {\n align-items: stretch !important;\n}\n\n.align-content-start {\n align-content: flex-start !important;\n}\n\n.align-content-end {\n align-content: flex-end !important;\n}\n\n.align-content-center {\n align-content: center !important;\n}\n\n.align-content-between {\n align-content: space-between !important;\n}\n\n.align-content-around {\n align-content: space-around !important;\n}\n\n.align-content-stretch {\n align-content: stretch !important;\n}\n\n.align-self-auto {\n align-self: auto !important;\n}\n\n.align-self-start {\n align-self: flex-start !important;\n}\n\n.align-self-end {\n align-self: flex-end !important;\n}\n\n.align-self-center {\n align-self: center !important;\n}\n\n.align-self-baseline {\n align-self: baseline !important;\n}\n\n.align-self-stretch {\n align-self: stretch !important;\n}\n\n@media (min-width: 576px) {\n .flex-sm-row {\n flex-direction: row !important;\n }\n .flex-sm-column {\n flex-direction: column !important;\n }\n .flex-sm-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-sm-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-sm-wrap {\n flex-wrap: wrap !important;\n }\n .flex-sm-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-sm-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-sm-fill {\n flex: 1 1 auto !important;\n }\n .flex-sm-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-sm-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-sm-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-sm-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-sm-start {\n justify-content: flex-start !important;\n }\n .justify-content-sm-end {\n justify-content: flex-end !important;\n }\n .justify-content-sm-center {\n justify-content: center !important;\n }\n .justify-content-sm-between {\n justify-content: space-between !important;\n }\n .justify-content-sm-around {\n justify-content: space-around !important;\n }\n .align-items-sm-start {\n align-items: flex-start !important;\n }\n .align-items-sm-end {\n align-items: flex-end !important;\n }\n .align-items-sm-center {\n align-items: center !important;\n }\n .align-items-sm-baseline {\n align-items: baseline !important;\n }\n .align-items-sm-stretch {\n align-items: stretch !important;\n }\n .align-content-sm-start {\n align-content: flex-start !important;\n }\n .align-content-sm-end {\n align-content: flex-end !important;\n }\n .align-content-sm-center {\n align-content: center !important;\n }\n .align-content-sm-between {\n align-content: space-between !important;\n }\n .align-content-sm-around {\n align-content: space-around !important;\n }\n .align-content-sm-stretch {\n align-content: stretch !important;\n }\n .align-self-sm-auto {\n align-self: auto !important;\n }\n .align-self-sm-start {\n align-self: flex-start !important;\n }\n .align-self-sm-end {\n align-self: flex-end !important;\n }\n .align-self-sm-center {\n align-self: center !important;\n }\n .align-self-sm-baseline {\n align-self: baseline !important;\n }\n .align-self-sm-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 768px) {\n .flex-md-row {\n flex-direction: row !important;\n }\n .flex-md-column {\n flex-direction: column !important;\n }\n .flex-md-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-md-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-md-wrap {\n flex-wrap: wrap !important;\n }\n .flex-md-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-md-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-md-fill {\n flex: 1 1 auto !important;\n }\n .flex-md-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-md-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-md-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-md-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-md-start {\n justify-content: flex-start !important;\n }\n .justify-content-md-end {\n justify-content: flex-end !important;\n }\n .justify-content-md-center {\n justify-content: center !important;\n }\n .justify-content-md-between {\n justify-content: space-between !important;\n }\n .justify-content-md-around {\n justify-content: space-around !important;\n }\n .align-items-md-start {\n align-items: flex-start !important;\n }\n .align-items-md-end {\n align-items: flex-end !important;\n }\n .align-items-md-center {\n align-items: center !important;\n }\n .align-items-md-baseline {\n align-items: baseline !important;\n }\n .align-items-md-stretch {\n align-items: stretch !important;\n }\n .align-content-md-start {\n align-content: flex-start !important;\n }\n .align-content-md-end {\n align-content: flex-end !important;\n }\n .align-content-md-center {\n align-content: center !important;\n }\n .align-content-md-between {\n align-content: space-between !important;\n }\n .align-content-md-around {\n align-content: space-around !important;\n }\n .align-content-md-stretch {\n align-content: stretch !important;\n }\n .align-self-md-auto {\n align-self: auto !important;\n }\n .align-self-md-start {\n align-self: flex-start !important;\n }\n .align-self-md-end {\n align-self: flex-end !important;\n }\n .align-self-md-center {\n align-self: center !important;\n }\n .align-self-md-baseline {\n align-self: baseline !important;\n }\n .align-self-md-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 992px) {\n .flex-lg-row {\n flex-direction: row !important;\n }\n .flex-lg-column {\n flex-direction: column !important;\n }\n .flex-lg-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-lg-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-lg-wrap {\n flex-wrap: wrap !important;\n }\n .flex-lg-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-lg-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-lg-fill {\n flex: 1 1 auto !important;\n }\n .flex-lg-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-lg-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-lg-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-lg-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-lg-start {\n justify-content: flex-start !important;\n }\n .justify-content-lg-end {\n justify-content: flex-end !important;\n }\n .justify-content-lg-center {\n justify-content: center !important;\n }\n .justify-content-lg-between {\n justify-content: space-between !important;\n }\n .justify-content-lg-around {\n justify-content: space-around !important;\n }\n .align-items-lg-start {\n align-items: flex-start !important;\n }\n .align-items-lg-end {\n align-items: flex-end !important;\n }\n .align-items-lg-center {\n align-items: center !important;\n }\n .align-items-lg-baseline {\n align-items: baseline !important;\n }\n .align-items-lg-stretch {\n align-items: stretch !important;\n }\n .align-content-lg-start {\n align-content: flex-start !important;\n }\n .align-content-lg-end {\n align-content: flex-end !important;\n }\n .align-content-lg-center {\n align-content: center !important;\n }\n .align-content-lg-between {\n align-content: space-between !important;\n }\n .align-content-lg-around {\n align-content: space-around !important;\n }\n .align-content-lg-stretch {\n align-content: stretch !important;\n }\n .align-self-lg-auto {\n align-self: auto !important;\n }\n .align-self-lg-start {\n align-self: flex-start !important;\n }\n .align-self-lg-end {\n align-self: flex-end !important;\n }\n .align-self-lg-center {\n align-self: center !important;\n }\n .align-self-lg-baseline {\n align-self: baseline !important;\n }\n .align-self-lg-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 1200px) {\n .flex-xl-row {\n flex-direction: row !important;\n }\n .flex-xl-column {\n flex-direction: column !important;\n }\n .flex-xl-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-xl-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-xl-wrap {\n flex-wrap: wrap !important;\n }\n .flex-xl-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-xl-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-xl-fill {\n flex: 1 1 auto !important;\n }\n .flex-xl-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-xl-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-xl-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-xl-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-xl-start {\n justify-content: flex-start !important;\n }\n .justify-content-xl-end {\n justify-content: flex-end !important;\n }\n .justify-content-xl-center {\n justify-content: center !important;\n }\n .justify-content-xl-between {\n justify-content: space-between !important;\n }\n .justify-content-xl-around {\n justify-content: space-around !important;\n }\n .align-items-xl-start {\n align-items: flex-start !important;\n }\n .align-items-xl-end {\n align-items: flex-end !important;\n }\n .align-items-xl-center {\n align-items: center !important;\n }\n .align-items-xl-baseline {\n align-items: baseline !important;\n }\n .align-items-xl-stretch {\n align-items: stretch !important;\n }\n .align-content-xl-start {\n align-content: flex-start !important;\n }\n .align-content-xl-end {\n align-content: flex-end !important;\n }\n .align-content-xl-center {\n align-content: center !important;\n }\n .align-content-xl-between {\n align-content: space-between !important;\n }\n .align-content-xl-around {\n align-content: space-around !important;\n }\n .align-content-xl-stretch {\n align-content: stretch !important;\n }\n .align-self-xl-auto {\n align-self: auto !important;\n }\n .align-self-xl-start {\n align-self: flex-start !important;\n }\n .align-self-xl-end {\n align-self: flex-end !important;\n }\n .align-self-xl-center {\n align-self: center !important;\n }\n .align-self-xl-baseline {\n align-self: baseline !important;\n }\n .align-self-xl-stretch {\n align-self: stretch !important;\n }\n}\n\n.float-left {\n float: left !important;\n}\n\n.float-right {\n float: right !important;\n}\n\n.float-none {\n float: none !important;\n}\n\n@media (min-width: 576px) {\n .float-sm-left {\n float: left !important;\n }\n .float-sm-right {\n float: right !important;\n }\n .float-sm-none {\n float: none !important;\n }\n}\n\n@media (min-width: 768px) {\n .float-md-left {\n float: left !important;\n }\n .float-md-right {\n float: right !important;\n }\n .float-md-none {\n float: none !important;\n }\n}\n\n@media (min-width: 992px) {\n .float-lg-left {\n float: left !important;\n }\n .float-lg-right {\n float: right !important;\n }\n .float-lg-none {\n float: none !important;\n }\n}\n\n@media (min-width: 1200px) {\n .float-xl-left {\n float: left !important;\n }\n .float-xl-right {\n float: right !important;\n }\n .float-xl-none {\n float: none !important;\n }\n}\n\n.overflow-auto {\n overflow: auto !important;\n}\n\n.overflow-hidden {\n overflow: hidden !important;\n}\n\n.position-static {\n position: static !important;\n}\n\n.position-relative {\n position: relative !important;\n}\n\n.position-absolute {\n position: absolute !important;\n}\n\n.position-fixed {\n position: fixed !important;\n}\n\n.position-sticky {\n position: sticky !important;\n}\n\n.fixed-top {\n position: fixed;\n top: 0;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n\n.fixed-bottom {\n position: fixed;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1030;\n}\n\n@supports (position: sticky) {\n .sticky-top {\n position: sticky;\n top: 0;\n z-index: 1020;\n }\n}\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n.sr-only-focusable:active, .sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n overflow: visible;\n clip: auto;\n white-space: normal;\n}\n\n.shadow-sm {\n box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important;\n}\n\n.shadow {\n box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important;\n}\n\n.shadow-lg {\n box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important;\n}\n\n.shadow-none {\n box-shadow: none !important;\n}\n\n.w-25 {\n width: 25% !important;\n}\n\n.w-50 {\n width: 50% !important;\n}\n\n.w-75 {\n width: 75% !important;\n}\n\n.w-100 {\n width: 100% !important;\n}\n\n.w-auto {\n width: auto !important;\n}\n\n.h-25 {\n height: 25% !important;\n}\n\n.h-50 {\n height: 50% !important;\n}\n\n.h-75 {\n height: 75% !important;\n}\n\n.h-100 {\n height: 100% !important;\n}\n\n.h-auto {\n height: auto !important;\n}\n\n.mw-100 {\n max-width: 100% !important;\n}\n\n.mh-100 {\n max-height: 100% !important;\n}\n\n.min-vw-100 {\n min-width: 100vw !important;\n}\n\n.min-vh-100 {\n min-height: 100vh !important;\n}\n\n.vw-100 {\n width: 100vw !important;\n}\n\n.vh-100 {\n height: 100vh !important;\n}\n\n.stretched-link::after {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1;\n pointer-events: auto;\n content: \"\";\n background-color: rgba(0, 0, 0, 0);\n}\n\n.m-0 {\n margin: 0 !important;\n}\n\n.mt-0,\n.my-0 {\n margin-top: 0 !important;\n}\n\n.mr-0,\n.mx-0 {\n margin-right: 0 !important;\n}\n\n.mb-0,\n.my-0 {\n margin-bottom: 0 !important;\n}\n\n.ml-0,\n.mx-0 {\n margin-left: 0 !important;\n}\n\n.m-1 {\n margin: 0.25rem !important;\n}\n\n.mt-1,\n.my-1 {\n margin-top: 0.25rem !important;\n}\n\n.mr-1,\n.mx-1 {\n margin-right: 0.25rem !important;\n}\n\n.mb-1,\n.my-1 {\n margin-bottom: 0.25rem !important;\n}\n\n.ml-1,\n.mx-1 {\n margin-left: 0.25rem !important;\n}\n\n.m-2 {\n margin: 0.5rem !important;\n}\n\n.mt-2,\n.my-2 {\n margin-top: 0.5rem !important;\n}\n\n.mr-2,\n.mx-2 {\n margin-right: 0.5rem !important;\n}\n\n.mb-2,\n.my-2 {\n margin-bottom: 0.5rem !important;\n}\n\n.ml-2,\n.mx-2 {\n margin-left: 0.5rem !important;\n}\n\n.m-3 {\n margin: 1rem !important;\n}\n\n.mt-3,\n.my-3 {\n margin-top: 1rem !important;\n}\n\n.mr-3,\n.mx-3 {\n margin-right: 1rem !important;\n}\n\n.mb-3,\n.my-3 {\n margin-bottom: 1rem !important;\n}\n\n.ml-3,\n.mx-3 {\n margin-left: 1rem !important;\n}\n\n.m-4 {\n margin: 1.5rem !important;\n}\n\n.mt-4,\n.my-4 {\n margin-top: 1.5rem !important;\n}\n\n.mr-4,\n.mx-4 {\n margin-right: 1.5rem !important;\n}\n\n.mb-4,\n.my-4 {\n margin-bottom: 1.5rem !important;\n}\n\n.ml-4,\n.mx-4 {\n margin-left: 1.5rem !important;\n}\n\n.m-5 {\n margin: 3rem !important;\n}\n\n.mt-5,\n.my-5 {\n margin-top: 3rem !important;\n}\n\n.mr-5,\n.mx-5 {\n margin-right: 3rem !important;\n}\n\n.mb-5,\n.my-5 {\n margin-bottom: 3rem !important;\n}\n\n.ml-5,\n.mx-5 {\n margin-left: 3rem !important;\n}\n\n.p-0 {\n padding: 0 !important;\n}\n\n.pt-0,\n.py-0 {\n padding-top: 0 !important;\n}\n\n.pr-0,\n.px-0 {\n padding-right: 0 !important;\n}\n\n.pb-0,\n.py-0 {\n padding-bottom: 0 !important;\n}\n\n.pl-0,\n.px-0 {\n padding-left: 0 !important;\n}\n\n.p-1 {\n padding: 0.25rem !important;\n}\n\n.pt-1,\n.py-1 {\n padding-top: 0.25rem !important;\n}\n\n.pr-1,\n.px-1 {\n padding-right: 0.25rem !important;\n}\n\n.pb-1,\n.py-1 {\n padding-bottom: 0.25rem !important;\n}\n\n.pl-1,\n.px-1 {\n padding-left: 0.25rem !important;\n}\n\n.p-2 {\n padding: 0.5rem !important;\n}\n\n.pt-2,\n.py-2 {\n padding-top: 0.5rem !important;\n}\n\n.pr-2,\n.px-2 {\n padding-right: 0.5rem !important;\n}\n\n.pb-2,\n.py-2 {\n padding-bottom: 0.5rem !important;\n}\n\n.pl-2,\n.px-2 {\n padding-left: 0.5rem !important;\n}\n\n.p-3 {\n padding: 1rem !important;\n}\n\n.pt-3,\n.py-3 {\n padding-top: 1rem !important;\n}\n\n.pr-3,\n.px-3 {\n padding-right: 1rem !important;\n}\n\n.pb-3,\n.py-3 {\n padding-bottom: 1rem !important;\n}\n\n.pl-3,\n.px-3 {\n padding-left: 1rem !important;\n}\n\n.p-4 {\n padding: 1.5rem !important;\n}\n\n.pt-4,\n.py-4 {\n padding-top: 1.5rem !important;\n}\n\n.pr-4,\n.px-4 {\n padding-right: 1.5rem !important;\n}\n\n.pb-4,\n.py-4 {\n padding-bottom: 1.5rem !important;\n}\n\n.pl-4,\n.px-4 {\n padding-left: 1.5rem !important;\n}\n\n.p-5 {\n padding: 3rem !important;\n}\n\n.pt-5,\n.py-5 {\n padding-top: 3rem !important;\n}\n\n.pr-5,\n.px-5 {\n padding-right: 3rem !important;\n}\n\n.pb-5,\n.py-5 {\n padding-bottom: 3rem !important;\n}\n\n.pl-5,\n.px-5 {\n padding-left: 3rem !important;\n}\n\n.m-n1 {\n margin: -0.25rem !important;\n}\n\n.mt-n1,\n.my-n1 {\n margin-top: -0.25rem !important;\n}\n\n.mr-n1,\n.mx-n1 {\n margin-right: -0.25rem !important;\n}\n\n.mb-n1,\n.my-n1 {\n margin-bottom: -0.25rem !important;\n}\n\n.ml-n1,\n.mx-n1 {\n margin-left: -0.25rem !important;\n}\n\n.m-n2 {\n margin: -0.5rem !important;\n}\n\n.mt-n2,\n.my-n2 {\n margin-top: -0.5rem !important;\n}\n\n.mr-n2,\n.mx-n2 {\n margin-right: -0.5rem !important;\n}\n\n.mb-n2,\n.my-n2 {\n margin-bottom: -0.5rem !important;\n}\n\n.ml-n2,\n.mx-n2 {\n margin-left: -0.5rem !important;\n}\n\n.m-n3 {\n margin: -1rem !important;\n}\n\n.mt-n3,\n.my-n3 {\n margin-top: -1rem !important;\n}\n\n.mr-n3,\n.mx-n3 {\n margin-right: -1rem !important;\n}\n\n.mb-n3,\n.my-n3 {\n margin-bottom: -1rem !important;\n}\n\n.ml-n3,\n.mx-n3 {\n margin-left: -1rem !important;\n}\n\n.m-n4 {\n margin: -1.5rem !important;\n}\n\n.mt-n4,\n.my-n4 {\n margin-top: -1.5rem !important;\n}\n\n.mr-n4,\n.mx-n4 {\n margin-right: -1.5rem !important;\n}\n\n.mb-n4,\n.my-n4 {\n margin-bottom: -1.5rem !important;\n}\n\n.ml-n4,\n.mx-n4 {\n margin-left: -1.5rem !important;\n}\n\n.m-n5 {\n margin: -3rem !important;\n}\n\n.mt-n5,\n.my-n5 {\n margin-top: -3rem !important;\n}\n\n.mr-n5,\n.mx-n5 {\n margin-right: -3rem !important;\n}\n\n.mb-n5,\n.my-n5 {\n margin-bottom: -3rem !important;\n}\n\n.ml-n5,\n.mx-n5 {\n margin-left: -3rem !important;\n}\n\n.m-auto {\n margin: auto !important;\n}\n\n.mt-auto,\n.my-auto {\n margin-top: auto !important;\n}\n\n.mr-auto,\n.mx-auto {\n margin-right: auto !important;\n}\n\n.mb-auto,\n.my-auto {\n margin-bottom: auto !important;\n}\n\n.ml-auto,\n.mx-auto {\n margin-left: auto !important;\n}\n\n@media (min-width: 576px) {\n .m-sm-0 {\n margin: 0 !important;\n }\n .mt-sm-0,\n .my-sm-0 {\n margin-top: 0 !important;\n }\n .mr-sm-0,\n .mx-sm-0 {\n margin-right: 0 !important;\n }\n .mb-sm-0,\n .my-sm-0 {\n margin-bottom: 0 !important;\n }\n .ml-sm-0,\n .mx-sm-0 {\n margin-left: 0 !important;\n }\n .m-sm-1 {\n margin: 0.25rem !important;\n }\n .mt-sm-1,\n .my-sm-1 {\n margin-top: 0.25rem !important;\n }\n .mr-sm-1,\n .mx-sm-1 {\n margin-right: 0.25rem !important;\n }\n .mb-sm-1,\n .my-sm-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-sm-1,\n .mx-sm-1 {\n margin-left: 0.25rem !important;\n }\n .m-sm-2 {\n margin: 0.5rem !important;\n }\n .mt-sm-2,\n .my-sm-2 {\n margin-top: 0.5rem !important;\n }\n .mr-sm-2,\n .mx-sm-2 {\n margin-right: 0.5rem !important;\n }\n .mb-sm-2,\n .my-sm-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-sm-2,\n .mx-sm-2 {\n margin-left: 0.5rem !important;\n }\n .m-sm-3 {\n margin: 1rem !important;\n }\n .mt-sm-3,\n .my-sm-3 {\n margin-top: 1rem !important;\n }\n .mr-sm-3,\n .mx-sm-3 {\n margin-right: 1rem !important;\n }\n .mb-sm-3,\n .my-sm-3 {\n margin-bottom: 1rem !important;\n }\n .ml-sm-3,\n .mx-sm-3 {\n margin-left: 1rem !important;\n }\n .m-sm-4 {\n margin: 1.5rem !important;\n }\n .mt-sm-4,\n .my-sm-4 {\n margin-top: 1.5rem !important;\n }\n .mr-sm-4,\n .mx-sm-4 {\n margin-right: 1.5rem !important;\n }\n .mb-sm-4,\n .my-sm-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-sm-4,\n .mx-sm-4 {\n margin-left: 1.5rem !important;\n }\n .m-sm-5 {\n margin: 3rem !important;\n }\n .mt-sm-5,\n .my-sm-5 {\n margin-top: 3rem !important;\n }\n .mr-sm-5,\n .mx-sm-5 {\n margin-right: 3rem !important;\n }\n .mb-sm-5,\n .my-sm-5 {\n margin-bottom: 3rem !important;\n }\n .ml-sm-5,\n .mx-sm-5 {\n margin-left: 3rem !important;\n }\n .p-sm-0 {\n padding: 0 !important;\n }\n .pt-sm-0,\n .py-sm-0 {\n padding-top: 0 !important;\n }\n .pr-sm-0,\n .px-sm-0 {\n padding-right: 0 !important;\n }\n .pb-sm-0,\n .py-sm-0 {\n padding-bottom: 0 !important;\n }\n .pl-sm-0,\n .px-sm-0 {\n padding-left: 0 !important;\n }\n .p-sm-1 {\n padding: 0.25rem !important;\n }\n .pt-sm-1,\n .py-sm-1 {\n padding-top: 0.25rem !important;\n }\n .pr-sm-1,\n .px-sm-1 {\n padding-right: 0.25rem !important;\n }\n .pb-sm-1,\n .py-sm-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-sm-1,\n .px-sm-1 {\n padding-left: 0.25rem !important;\n }\n .p-sm-2 {\n padding: 0.5rem !important;\n }\n .pt-sm-2,\n .py-sm-2 {\n padding-top: 0.5rem !important;\n }\n .pr-sm-2,\n .px-sm-2 {\n padding-right: 0.5rem !important;\n }\n .pb-sm-2,\n .py-sm-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-sm-2,\n .px-sm-2 {\n padding-left: 0.5rem !important;\n }\n .p-sm-3 {\n padding: 1rem !important;\n }\n .pt-sm-3,\n .py-sm-3 {\n padding-top: 1rem !important;\n }\n .pr-sm-3,\n .px-sm-3 {\n padding-right: 1rem !important;\n }\n .pb-sm-3,\n .py-sm-3 {\n padding-bottom: 1rem !important;\n }\n .pl-sm-3,\n .px-sm-3 {\n padding-left: 1rem !important;\n }\n .p-sm-4 {\n padding: 1.5rem !important;\n }\n .pt-sm-4,\n .py-sm-4 {\n padding-top: 1.5rem !important;\n }\n .pr-sm-4,\n .px-sm-4 {\n padding-right: 1.5rem !important;\n }\n .pb-sm-4,\n .py-sm-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-sm-4,\n .px-sm-4 {\n padding-left: 1.5rem !important;\n }\n .p-sm-5 {\n padding: 3rem !important;\n }\n .pt-sm-5,\n .py-sm-5 {\n padding-top: 3rem !important;\n }\n .pr-sm-5,\n .px-sm-5 {\n padding-right: 3rem !important;\n }\n .pb-sm-5,\n .py-sm-5 {\n padding-bottom: 3rem !important;\n }\n .pl-sm-5,\n .px-sm-5 {\n padding-left: 3rem !important;\n }\n .m-sm-n1 {\n margin: -0.25rem !important;\n }\n .mt-sm-n1,\n .my-sm-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-sm-n1,\n .mx-sm-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-sm-n1,\n .my-sm-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-sm-n1,\n .mx-sm-n1 {\n margin-left: -0.25rem !important;\n }\n .m-sm-n2 {\n margin: -0.5rem !important;\n }\n .mt-sm-n2,\n .my-sm-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-sm-n2,\n .mx-sm-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-sm-n2,\n .my-sm-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-sm-n2,\n .mx-sm-n2 {\n margin-left: -0.5rem !important;\n }\n .m-sm-n3 {\n margin: -1rem !important;\n }\n .mt-sm-n3,\n .my-sm-n3 {\n margin-top: -1rem !important;\n }\n .mr-sm-n3,\n .mx-sm-n3 {\n margin-right: -1rem !important;\n }\n .mb-sm-n3,\n .my-sm-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-sm-n3,\n .mx-sm-n3 {\n margin-left: -1rem !important;\n }\n .m-sm-n4 {\n margin: -1.5rem !important;\n }\n .mt-sm-n4,\n .my-sm-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-sm-n4,\n .mx-sm-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-sm-n4,\n .my-sm-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-sm-n4,\n .mx-sm-n4 {\n margin-left: -1.5rem !important;\n }\n .m-sm-n5 {\n margin: -3rem !important;\n }\n .mt-sm-n5,\n .my-sm-n5 {\n margin-top: -3rem !important;\n }\n .mr-sm-n5,\n .mx-sm-n5 {\n margin-right: -3rem !important;\n }\n .mb-sm-n5,\n .my-sm-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-sm-n5,\n .mx-sm-n5 {\n margin-left: -3rem !important;\n }\n .m-sm-auto {\n margin: auto !important;\n }\n .mt-sm-auto,\n .my-sm-auto {\n margin-top: auto !important;\n }\n .mr-sm-auto,\n .mx-sm-auto {\n margin-right: auto !important;\n }\n .mb-sm-auto,\n .my-sm-auto {\n margin-bottom: auto !important;\n }\n .ml-sm-auto,\n .mx-sm-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 768px) {\n .m-md-0 {\n margin: 0 !important;\n }\n .mt-md-0,\n .my-md-0 {\n margin-top: 0 !important;\n }\n .mr-md-0,\n .mx-md-0 {\n margin-right: 0 !important;\n }\n .mb-md-0,\n .my-md-0 {\n margin-bottom: 0 !important;\n }\n .ml-md-0,\n .mx-md-0 {\n margin-left: 0 !important;\n }\n .m-md-1 {\n margin: 0.25rem !important;\n }\n .mt-md-1,\n .my-md-1 {\n margin-top: 0.25rem !important;\n }\n .mr-md-1,\n .mx-md-1 {\n margin-right: 0.25rem !important;\n }\n .mb-md-1,\n .my-md-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-md-1,\n .mx-md-1 {\n margin-left: 0.25rem !important;\n }\n .m-md-2 {\n margin: 0.5rem !important;\n }\n .mt-md-2,\n .my-md-2 {\n margin-top: 0.5rem !important;\n }\n .mr-md-2,\n .mx-md-2 {\n margin-right: 0.5rem !important;\n }\n .mb-md-2,\n .my-md-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-md-2,\n .mx-md-2 {\n margin-left: 0.5rem !important;\n }\n .m-md-3 {\n margin: 1rem !important;\n }\n .mt-md-3,\n .my-md-3 {\n margin-top: 1rem !important;\n }\n .mr-md-3,\n .mx-md-3 {\n margin-right: 1rem !important;\n }\n .mb-md-3,\n .my-md-3 {\n margin-bottom: 1rem !important;\n }\n .ml-md-3,\n .mx-md-3 {\n margin-left: 1rem !important;\n }\n .m-md-4 {\n margin: 1.5rem !important;\n }\n .mt-md-4,\n .my-md-4 {\n margin-top: 1.5rem !important;\n }\n .mr-md-4,\n .mx-md-4 {\n margin-right: 1.5rem !important;\n }\n .mb-md-4,\n .my-md-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-md-4,\n .mx-md-4 {\n margin-left: 1.5rem !important;\n }\n .m-md-5 {\n margin: 3rem !important;\n }\n .mt-md-5,\n .my-md-5 {\n margin-top: 3rem !important;\n }\n .mr-md-5,\n .mx-md-5 {\n margin-right: 3rem !important;\n }\n .mb-md-5,\n .my-md-5 {\n margin-bottom: 3rem !important;\n }\n .ml-md-5,\n .mx-md-5 {\n margin-left: 3rem !important;\n }\n .p-md-0 {\n padding: 0 !important;\n }\n .pt-md-0,\n .py-md-0 {\n padding-top: 0 !important;\n }\n .pr-md-0,\n .px-md-0 {\n padding-right: 0 !important;\n }\n .pb-md-0,\n .py-md-0 {\n padding-bottom: 0 !important;\n }\n .pl-md-0,\n .px-md-0 {\n padding-left: 0 !important;\n }\n .p-md-1 {\n padding: 0.25rem !important;\n }\n .pt-md-1,\n .py-md-1 {\n padding-top: 0.25rem !important;\n }\n .pr-md-1,\n .px-md-1 {\n padding-right: 0.25rem !important;\n }\n .pb-md-1,\n .py-md-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-md-1,\n .px-md-1 {\n padding-left: 0.25rem !important;\n }\n .p-md-2 {\n padding: 0.5rem !important;\n }\n .pt-md-2,\n .py-md-2 {\n padding-top: 0.5rem !important;\n }\n .pr-md-2,\n .px-md-2 {\n padding-right: 0.5rem !important;\n }\n .pb-md-2,\n .py-md-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-md-2,\n .px-md-2 {\n padding-left: 0.5rem !important;\n }\n .p-md-3 {\n padding: 1rem !important;\n }\n .pt-md-3,\n .py-md-3 {\n padding-top: 1rem !important;\n }\n .pr-md-3,\n .px-md-3 {\n padding-right: 1rem !important;\n }\n .pb-md-3,\n .py-md-3 {\n padding-bottom: 1rem !important;\n }\n .pl-md-3,\n .px-md-3 {\n padding-left: 1rem !important;\n }\n .p-md-4 {\n padding: 1.5rem !important;\n }\n .pt-md-4,\n .py-md-4 {\n padding-top: 1.5rem !important;\n }\n .pr-md-4,\n .px-md-4 {\n padding-right: 1.5rem !important;\n }\n .pb-md-4,\n .py-md-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-md-4,\n .px-md-4 {\n padding-left: 1.5rem !important;\n }\n .p-md-5 {\n padding: 3rem !important;\n }\n .pt-md-5,\n .py-md-5 {\n padding-top: 3rem !important;\n }\n .pr-md-5,\n .px-md-5 {\n padding-right: 3rem !important;\n }\n .pb-md-5,\n .py-md-5 {\n padding-bottom: 3rem !important;\n }\n .pl-md-5,\n .px-md-5 {\n padding-left: 3rem !important;\n }\n .m-md-n1 {\n margin: -0.25rem !important;\n }\n .mt-md-n1,\n .my-md-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-md-n1,\n .mx-md-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-md-n1,\n .my-md-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-md-n1,\n .mx-md-n1 {\n margin-left: -0.25rem !important;\n }\n .m-md-n2 {\n margin: -0.5rem !important;\n }\n .mt-md-n2,\n .my-md-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-md-n2,\n .mx-md-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-md-n2,\n .my-md-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-md-n2,\n .mx-md-n2 {\n margin-left: -0.5rem !important;\n }\n .m-md-n3 {\n margin: -1rem !important;\n }\n .mt-md-n3,\n .my-md-n3 {\n margin-top: -1rem !important;\n }\n .mr-md-n3,\n .mx-md-n3 {\n margin-right: -1rem !important;\n }\n .mb-md-n3,\n .my-md-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-md-n3,\n .mx-md-n3 {\n margin-left: -1rem !important;\n }\n .m-md-n4 {\n margin: -1.5rem !important;\n }\n .mt-md-n4,\n .my-md-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-md-n4,\n .mx-md-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-md-n4,\n .my-md-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-md-n4,\n .mx-md-n4 {\n margin-left: -1.5rem !important;\n }\n .m-md-n5 {\n margin: -3rem !important;\n }\n .mt-md-n5,\n .my-md-n5 {\n margin-top: -3rem !important;\n }\n .mr-md-n5,\n .mx-md-n5 {\n margin-right: -3rem !important;\n }\n .mb-md-n5,\n .my-md-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-md-n5,\n .mx-md-n5 {\n margin-left: -3rem !important;\n }\n .m-md-auto {\n margin: auto !important;\n }\n .mt-md-auto,\n .my-md-auto {\n margin-top: auto !important;\n }\n .mr-md-auto,\n .mx-md-auto {\n margin-right: auto !important;\n }\n .mb-md-auto,\n .my-md-auto {\n margin-bottom: auto !important;\n }\n .ml-md-auto,\n .mx-md-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 992px) {\n .m-lg-0 {\n margin: 0 !important;\n }\n .mt-lg-0,\n .my-lg-0 {\n margin-top: 0 !important;\n }\n .mr-lg-0,\n .mx-lg-0 {\n margin-right: 0 !important;\n }\n .mb-lg-0,\n .my-lg-0 {\n margin-bottom: 0 !important;\n }\n .ml-lg-0,\n .mx-lg-0 {\n margin-left: 0 !important;\n }\n .m-lg-1 {\n margin: 0.25rem !important;\n }\n .mt-lg-1,\n .my-lg-1 {\n margin-top: 0.25rem !important;\n }\n .mr-lg-1,\n .mx-lg-1 {\n margin-right: 0.25rem !important;\n }\n .mb-lg-1,\n .my-lg-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-lg-1,\n .mx-lg-1 {\n margin-left: 0.25rem !important;\n }\n .m-lg-2 {\n margin: 0.5rem !important;\n }\n .mt-lg-2,\n .my-lg-2 {\n margin-top: 0.5rem !important;\n }\n .mr-lg-2,\n .mx-lg-2 {\n margin-right: 0.5rem !important;\n }\n .mb-lg-2,\n .my-lg-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-lg-2,\n .mx-lg-2 {\n margin-left: 0.5rem !important;\n }\n .m-lg-3 {\n margin: 1rem !important;\n }\n .mt-lg-3,\n .my-lg-3 {\n margin-top: 1rem !important;\n }\n .mr-lg-3,\n .mx-lg-3 {\n margin-right: 1rem !important;\n }\n .mb-lg-3,\n .my-lg-3 {\n margin-bottom: 1rem !important;\n }\n .ml-lg-3,\n .mx-lg-3 {\n margin-left: 1rem !important;\n }\n .m-lg-4 {\n margin: 1.5rem !important;\n }\n .mt-lg-4,\n .my-lg-4 {\n margin-top: 1.5rem !important;\n }\n .mr-lg-4,\n .mx-lg-4 {\n margin-right: 1.5rem !important;\n }\n .mb-lg-4,\n .my-lg-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-lg-4,\n .mx-lg-4 {\n margin-left: 1.5rem !important;\n }\n .m-lg-5 {\n margin: 3rem !important;\n }\n .mt-lg-5,\n .my-lg-5 {\n margin-top: 3rem !important;\n }\n .mr-lg-5,\n .mx-lg-5 {\n margin-right: 3rem !important;\n }\n .mb-lg-5,\n .my-lg-5 {\n margin-bottom: 3rem !important;\n }\n .ml-lg-5,\n .mx-lg-5 {\n margin-left: 3rem !important;\n }\n .p-lg-0 {\n padding: 0 !important;\n }\n .pt-lg-0,\n .py-lg-0 {\n padding-top: 0 !important;\n }\n .pr-lg-0,\n .px-lg-0 {\n padding-right: 0 !important;\n }\n .pb-lg-0,\n .py-lg-0 {\n padding-bottom: 0 !important;\n }\n .pl-lg-0,\n .px-lg-0 {\n padding-left: 0 !important;\n }\n .p-lg-1 {\n padding: 0.25rem !important;\n }\n .pt-lg-1,\n .py-lg-1 {\n padding-top: 0.25rem !important;\n }\n .pr-lg-1,\n .px-lg-1 {\n padding-right: 0.25rem !important;\n }\n .pb-lg-1,\n .py-lg-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-lg-1,\n .px-lg-1 {\n padding-left: 0.25rem !important;\n }\n .p-lg-2 {\n padding: 0.5rem !important;\n }\n .pt-lg-2,\n .py-lg-2 {\n padding-top: 0.5rem !important;\n }\n .pr-lg-2,\n .px-lg-2 {\n padding-right: 0.5rem !important;\n }\n .pb-lg-2,\n .py-lg-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-lg-2,\n .px-lg-2 {\n padding-left: 0.5rem !important;\n }\n .p-lg-3 {\n padding: 1rem !important;\n }\n .pt-lg-3,\n .py-lg-3 {\n padding-top: 1rem !important;\n }\n .pr-lg-3,\n .px-lg-3 {\n padding-right: 1rem !important;\n }\n .pb-lg-3,\n .py-lg-3 {\n padding-bottom: 1rem !important;\n }\n .pl-lg-3,\n .px-lg-3 {\n padding-left: 1rem !important;\n }\n .p-lg-4 {\n padding: 1.5rem !important;\n }\n .pt-lg-4,\n .py-lg-4 {\n padding-top: 1.5rem !important;\n }\n .pr-lg-4,\n .px-lg-4 {\n padding-right: 1.5rem !important;\n }\n .pb-lg-4,\n .py-lg-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-lg-4,\n .px-lg-4 {\n padding-left: 1.5rem !important;\n }\n .p-lg-5 {\n padding: 3rem !important;\n }\n .pt-lg-5,\n .py-lg-5 {\n padding-top: 3rem !important;\n }\n .pr-lg-5,\n .px-lg-5 {\n padding-right: 3rem !important;\n }\n .pb-lg-5,\n .py-lg-5 {\n padding-bottom: 3rem !important;\n }\n .pl-lg-5,\n .px-lg-5 {\n padding-left: 3rem !important;\n }\n .m-lg-n1 {\n margin: -0.25rem !important;\n }\n .mt-lg-n1,\n .my-lg-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-lg-n1,\n .mx-lg-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-lg-n1,\n .my-lg-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-lg-n1,\n .mx-lg-n1 {\n margin-left: -0.25rem !important;\n }\n .m-lg-n2 {\n margin: -0.5rem !important;\n }\n .mt-lg-n2,\n .my-lg-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-lg-n2,\n .mx-lg-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-lg-n2,\n .my-lg-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-lg-n2,\n .mx-lg-n2 {\n margin-left: -0.5rem !important;\n }\n .m-lg-n3 {\n margin: -1rem !important;\n }\n .mt-lg-n3,\n .my-lg-n3 {\n margin-top: -1rem !important;\n }\n .mr-lg-n3,\n .mx-lg-n3 {\n margin-right: -1rem !important;\n }\n .mb-lg-n3,\n .my-lg-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-lg-n3,\n .mx-lg-n3 {\n margin-left: -1rem !important;\n }\n .m-lg-n4 {\n margin: -1.5rem !important;\n }\n .mt-lg-n4,\n .my-lg-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-lg-n4,\n .mx-lg-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-lg-n4,\n .my-lg-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-lg-n4,\n .mx-lg-n4 {\n margin-left: -1.5rem !important;\n }\n .m-lg-n5 {\n margin: -3rem !important;\n }\n .mt-lg-n5,\n .my-lg-n5 {\n margin-top: -3rem !important;\n }\n .mr-lg-n5,\n .mx-lg-n5 {\n margin-right: -3rem !important;\n }\n .mb-lg-n5,\n .my-lg-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-lg-n5,\n .mx-lg-n5 {\n margin-left: -3rem !important;\n }\n .m-lg-auto {\n margin: auto !important;\n }\n .mt-lg-auto,\n .my-lg-auto {\n margin-top: auto !important;\n }\n .mr-lg-auto,\n .mx-lg-auto {\n margin-right: auto !important;\n }\n .mb-lg-auto,\n .my-lg-auto {\n margin-bottom: auto !important;\n }\n .ml-lg-auto,\n .mx-lg-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 1200px) {\n .m-xl-0 {\n margin: 0 !important;\n }\n .mt-xl-0,\n .my-xl-0 {\n margin-top: 0 !important;\n }\n .mr-xl-0,\n .mx-xl-0 {\n margin-right: 0 !important;\n }\n .mb-xl-0,\n .my-xl-0 {\n margin-bottom: 0 !important;\n }\n .ml-xl-0,\n .mx-xl-0 {\n margin-left: 0 !important;\n }\n .m-xl-1 {\n margin: 0.25rem !important;\n }\n .mt-xl-1,\n .my-xl-1 {\n margin-top: 0.25rem !important;\n }\n .mr-xl-1,\n .mx-xl-1 {\n margin-right: 0.25rem !important;\n }\n .mb-xl-1,\n .my-xl-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-xl-1,\n .mx-xl-1 {\n margin-left: 0.25rem !important;\n }\n .m-xl-2 {\n margin: 0.5rem !important;\n }\n .mt-xl-2,\n .my-xl-2 {\n margin-top: 0.5rem !important;\n }\n .mr-xl-2,\n .mx-xl-2 {\n margin-right: 0.5rem !important;\n }\n .mb-xl-2,\n .my-xl-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-xl-2,\n .mx-xl-2 {\n margin-left: 0.5rem !important;\n }\n .m-xl-3 {\n margin: 1rem !important;\n }\n .mt-xl-3,\n .my-xl-3 {\n margin-top: 1rem !important;\n }\n .mr-xl-3,\n .mx-xl-3 {\n margin-right: 1rem !important;\n }\n .mb-xl-3,\n .my-xl-3 {\n margin-bottom: 1rem !important;\n }\n .ml-xl-3,\n .mx-xl-3 {\n margin-left: 1rem !important;\n }\n .m-xl-4 {\n margin: 1.5rem !important;\n }\n .mt-xl-4,\n .my-xl-4 {\n margin-top: 1.5rem !important;\n }\n .mr-xl-4,\n .mx-xl-4 {\n margin-right: 1.5rem !important;\n }\n .mb-xl-4,\n .my-xl-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-xl-4,\n .mx-xl-4 {\n margin-left: 1.5rem !important;\n }\n .m-xl-5 {\n margin: 3rem !important;\n }\n .mt-xl-5,\n .my-xl-5 {\n margin-top: 3rem !important;\n }\n .mr-xl-5,\n .mx-xl-5 {\n margin-right: 3rem !important;\n }\n .mb-xl-5,\n .my-xl-5 {\n margin-bottom: 3rem !important;\n }\n .ml-xl-5,\n .mx-xl-5 {\n margin-left: 3rem !important;\n }\n .p-xl-0 {\n padding: 0 !important;\n }\n .pt-xl-0,\n .py-xl-0 {\n padding-top: 0 !important;\n }\n .pr-xl-0,\n .px-xl-0 {\n padding-right: 0 !important;\n }\n .pb-xl-0,\n .py-xl-0 {\n padding-bottom: 0 !important;\n }\n .pl-xl-0,\n .px-xl-0 {\n padding-left: 0 !important;\n }\n .p-xl-1 {\n padding: 0.25rem !important;\n }\n .pt-xl-1,\n .py-xl-1 {\n padding-top: 0.25rem !important;\n }\n .pr-xl-1,\n .px-xl-1 {\n padding-right: 0.25rem !important;\n }\n .pb-xl-1,\n .py-xl-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-xl-1,\n .px-xl-1 {\n padding-left: 0.25rem !important;\n }\n .p-xl-2 {\n padding: 0.5rem !important;\n }\n .pt-xl-2,\n .py-xl-2 {\n padding-top: 0.5rem !important;\n }\n .pr-xl-2,\n .px-xl-2 {\n padding-right: 0.5rem !important;\n }\n .pb-xl-2,\n .py-xl-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-xl-2,\n .px-xl-2 {\n padding-left: 0.5rem !important;\n }\n .p-xl-3 {\n padding: 1rem !important;\n }\n .pt-xl-3,\n .py-xl-3 {\n padding-top: 1rem !important;\n }\n .pr-xl-3,\n .px-xl-3 {\n padding-right: 1rem !important;\n }\n .pb-xl-3,\n .py-xl-3 {\n padding-bottom: 1rem !important;\n }\n .pl-xl-3,\n .px-xl-3 {\n padding-left: 1rem !important;\n }\n .p-xl-4 {\n padding: 1.5rem !important;\n }\n .pt-xl-4,\n .py-xl-4 {\n padding-top: 1.5rem !important;\n }\n .pr-xl-4,\n .px-xl-4 {\n padding-right: 1.5rem !important;\n }\n .pb-xl-4,\n .py-xl-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-xl-4,\n .px-xl-4 {\n padding-left: 1.5rem !important;\n }\n .p-xl-5 {\n padding: 3rem !important;\n }\n .pt-xl-5,\n .py-xl-5 {\n padding-top: 3rem !important;\n }\n .pr-xl-5,\n .px-xl-5 {\n padding-right: 3rem !important;\n }\n .pb-xl-5,\n .py-xl-5 {\n padding-bottom: 3rem !important;\n }\n .pl-xl-5,\n .px-xl-5 {\n padding-left: 3rem !important;\n }\n .m-xl-n1 {\n margin: -0.25rem !important;\n }\n .mt-xl-n1,\n .my-xl-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-xl-n1,\n .mx-xl-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-xl-n1,\n .my-xl-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-xl-n1,\n .mx-xl-n1 {\n margin-left: -0.25rem !important;\n }\n .m-xl-n2 {\n margin: -0.5rem !important;\n }\n .mt-xl-n2,\n .my-xl-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-xl-n2,\n .mx-xl-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-xl-n2,\n .my-xl-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-xl-n2,\n .mx-xl-n2 {\n margin-left: -0.5rem !important;\n }\n .m-xl-n3 {\n margin: -1rem !important;\n }\n .mt-xl-n3,\n .my-xl-n3 {\n margin-top: -1rem !important;\n }\n .mr-xl-n3,\n .mx-xl-n3 {\n margin-right: -1rem !important;\n }\n .mb-xl-n3,\n .my-xl-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-xl-n3,\n .mx-xl-n3 {\n margin-left: -1rem !important;\n }\n .m-xl-n4 {\n margin: -1.5rem !important;\n }\n .mt-xl-n4,\n .my-xl-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-xl-n4,\n .mx-xl-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-xl-n4,\n .my-xl-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-xl-n4,\n .mx-xl-n4 {\n margin-left: -1.5rem !important;\n }\n .m-xl-n5 {\n margin: -3rem !important;\n }\n .mt-xl-n5,\n .my-xl-n5 {\n margin-top: -3rem !important;\n }\n .mr-xl-n5,\n .mx-xl-n5 {\n margin-right: -3rem !important;\n }\n .mb-xl-n5,\n .my-xl-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-xl-n5,\n .mx-xl-n5 {\n margin-left: -3rem !important;\n }\n .m-xl-auto {\n margin: auto !important;\n }\n .mt-xl-auto,\n .my-xl-auto {\n margin-top: auto !important;\n }\n .mr-xl-auto,\n .mx-xl-auto {\n margin-right: auto !important;\n }\n .mb-xl-auto,\n .my-xl-auto {\n margin-bottom: auto !important;\n }\n .ml-xl-auto,\n .mx-xl-auto {\n margin-left: auto !important;\n }\n}\n\n.text-monospace {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace !important;\n}\n\n.text-justify {\n text-align: justify !important;\n}\n\n.text-wrap {\n white-space: normal !important;\n}\n\n.text-nowrap {\n white-space: nowrap !important;\n}\n\n.text-truncate {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.text-left {\n text-align: left !important;\n}\n\n.text-right {\n text-align: right !important;\n}\n\n.text-center {\n text-align: center !important;\n}\n\n@media (min-width: 576px) {\n .text-sm-left {\n text-align: left !important;\n }\n .text-sm-right {\n text-align: right !important;\n }\n .text-sm-center {\n text-align: center !important;\n }\n}\n\n@media (min-width: 768px) {\n .text-md-left {\n text-align: left !important;\n }\n .text-md-right {\n text-align: right !important;\n }\n .text-md-center {\n text-align: center !important;\n }\n}\n\n@media (min-width: 992px) {\n .text-lg-left {\n text-align: left !important;\n }\n .text-lg-right {\n text-align: right !important;\n }\n .text-lg-center {\n text-align: center !important;\n }\n}\n\n@media (min-width: 1200px) {\n .text-xl-left {\n text-align: left !important;\n }\n .text-xl-right {\n text-align: right !important;\n }\n .text-xl-center {\n text-align: center !important;\n }\n}\n\n.text-lowercase {\n text-transform: lowercase !important;\n}\n\n.text-uppercase {\n text-transform: uppercase !important;\n}\n\n.text-capitalize {\n text-transform: capitalize !important;\n}\n\n.font-weight-light {\n font-weight: 300 !important;\n}\n\n.font-weight-lighter {\n font-weight: lighter !important;\n}\n\n.font-weight-normal {\n font-weight: 400 !important;\n}\n\n.font-weight-bold {\n font-weight: 700 !important;\n}\n\n.font-weight-bolder {\n font-weight: bolder !important;\n}\n\n.font-italic {\n font-style: italic !important;\n}\n\n.text-white {\n color: #fff !important;\n}\n\n.text-primary {\n color: #007bff !important;\n}\n\na.text-primary:hover, a.text-primary:focus {\n color: #0056b3 !important;\n}\n\n.text-secondary {\n color: #6c757d !important;\n}\n\na.text-secondary:hover, a.text-secondary:focus {\n color: #494f54 !important;\n}\n\n.text-success {\n color: #28a745 !important;\n}\n\na.text-success:hover, a.text-success:focus {\n color: #19692c !important;\n}\n\n.text-info {\n color: #17a2b8 !important;\n}\n\na.text-info:hover, a.text-info:focus {\n color: #0f6674 !important;\n}\n\n.text-warning {\n color: #ffc107 !important;\n}\n\na.text-warning:hover, a.text-warning:focus {\n color: #ba8b00 !important;\n}\n\n.text-danger {\n color: #dc3545 !important;\n}\n\na.text-danger:hover, a.text-danger:focus {\n color: #a71d2a !important;\n}\n\n.text-light {\n color: #f8f9fa !important;\n}\n\na.text-light:hover, a.text-light:focus {\n color: #cbd3da !important;\n}\n\n.text-dark {\n color: #343a40 !important;\n}\n\na.text-dark:hover, a.text-dark:focus {\n color: #121416 !important;\n}\n\n.text-body {\n color: #212529 !important;\n}\n\n.text-muted {\n color: #6c757d !important;\n}\n\n.text-black-50 {\n color: rgba(0, 0, 0, 0.5) !important;\n}\n\n.text-white-50 {\n color: rgba(255, 255, 255, 0.5) !important;\n}\n\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n\n.text-decoration-none {\n text-decoration: none !important;\n}\n\n.text-break {\n word-break: break-word !important;\n overflow-wrap: break-word !important;\n}\n\n.text-reset {\n color: inherit !important;\n}\n\n.visible {\n visibility: visible !important;\n}\n\n.invisible {\n visibility: hidden !important;\n}\n\n@media print {\n *,\n *::before,\n *::after {\n text-shadow: none !important;\n box-shadow: none !important;\n }\n a:not(.btn) {\n text-decoration: underline;\n }\n abbr[title]::after {\n content: \" (\" attr(title) \")\";\n }\n pre {\n white-space: pre-wrap !important;\n }\n pre,\n blockquote {\n border: 1px solid #adb5bd;\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n @page {\n size: a3;\n }\n body {\n min-width: 992px !important;\n }\n .container {\n min-width: 992px !important;\n }\n .navbar {\n display: none;\n }\n .badge {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #dee2e6 !important;\n }\n .table-dark {\n color: inherit;\n }\n .table-dark th,\n .table-dark td,\n .table-dark thead th,\n .table-dark tbody + tbody {\n border-color: #dee2e6;\n }\n .table .thead-dark th {\n color: inherit;\n border-color: #dee2e6;\n }\n}\n\n/*# sourceMappingURL=bootstrap.css.map */",":root {\n // Custom variable values only support SassScript inside `#{}`.\n @each $color, $value in $colors {\n --#{$color}: #{$value};\n }\n\n @each $color, $value in $theme-colors {\n --#{$color}: #{$value};\n }\n\n @each $bp, $value in $grid-breakpoints {\n --breakpoint-#{$bp}: #{$value};\n }\n\n // Use `inspect` for lists so that quoted items keep the quotes.\n // See https://github.com/sass/sass/issues/2383#issuecomment-336349172\n --font-family-sans-serif: #{inspect($font-family-sans-serif)};\n --font-family-monospace: #{inspect($font-family-monospace)};\n}\n","// stylelint-disable at-rule-no-vendor-prefix, declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix\n\n// Reboot\n//\n// Normalization of HTML elements, manually forked from Normalize.css to remove\n// styles targeting irrelevant browsers while applying new styles.\n//\n// Normalize is licensed MIT. https://github.com/necolas/normalize.css\n\n\n// Document\n//\n// 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.\n// 2. Change the default font family in all browsers.\n// 3. Correct the line height in all browsers.\n// 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS.\n// 5. Change the default tap highlight to be completely transparent in iOS.\n\n*,\n*::before,\n*::after {\n box-sizing: border-box; // 1\n}\n\nhtml {\n font-family: sans-serif; // 2\n line-height: 1.15; // 3\n -webkit-text-size-adjust: 100%; // 4\n -webkit-tap-highlight-color: rgba($black, 0); // 5\n}\n\n// Shim for \"new\" HTML5 structural elements to display correctly (IE10, older browsers)\n// TODO: remove in v5\n// stylelint-disable-next-line selector-list-comma-newline-after\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\n// Body\n//\n// 1. Remove the margin in all browsers.\n// 2. As a best practice, apply a default `background-color`.\n// 3. Set an explicit initial text-align value so that we can later use\n// the `inherit` value on things like `` elements.\n\nbody {\n margin: 0; // 1\n font-family: $font-family-base;\n @include font-size($font-size-base);\n font-weight: $font-weight-base;\n line-height: $line-height-base;\n color: $body-color;\n text-align: left; // 3\n background-color: $body-bg; // 2\n}\n\n// Suppress the focus outline on elements that cannot be accessed via keyboard.\n// This prevents an unwanted focus outline from appearing around elements that\n// might still respond to pointer events.\n//\n// Credit: https://github.com/suitcss/base\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\n\n// Content grouping\n//\n// 1. Add the correct box sizing in Firefox.\n// 2. Show the overflow in Edge and IE.\n\nhr {\n box-sizing: content-box; // 1\n height: 0; // 1\n overflow: visible; // 2\n}\n\n\n//\n// Typography\n//\n\n// Remove top margins from headings\n//\n// By default, `

`-`

` all receive top and bottom margins. We nuke the top\n// margin for easier control within type scales as it avoids margin collapsing.\n// stylelint-disable-next-line selector-list-comma-newline-after\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: $headings-margin-bottom;\n}\n\n// Reset margins on paragraphs\n//\n// Similarly, the top margin on `

`s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n// Abbreviations\n//\n// 1. Duplicate behavior to the data-* attribute for our tooltip plugin\n// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n// 3. Add explicit cursor to indicate changed behavior.\n// 4. Remove the bottom border in Firefox 39-.\n// 5. Prevent the text-decoration to be skipped.\n\nabbr[title],\nabbr[data-original-title] { // 1\n text-decoration: underline; // 2\n text-decoration: underline dotted; // 2\n cursor: help; // 3\n border-bottom: 0; // 4\n text-decoration-skip-ink: none; // 5\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // Undo browser default\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: $font-weight-bolder; // Add the correct font weight in Chrome, Edge, and Safari\n}\n\nsmall {\n @include font-size(80%); // Add the correct font size in all browsers\n}\n\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n//\n\nsub,\nsup {\n position: relative;\n @include font-size(75%);\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n//\n// Links\n//\n\na {\n color: $link-color;\n text-decoration: $link-decoration;\n background-color: transparent; // Remove the gray background on active links in IE 10.\n\n @include hover {\n color: $link-hover-color;\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href)\n// which have not been made explicitly keyboard-focusable (without tabindex).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n\n @include hover-focus {\n color: inherit;\n text-decoration: none;\n }\n\n &:focus {\n outline: 0;\n }\n}\n\n\n//\n// Code\n//\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-monospace;\n @include font-size(1em); // Correct the odd `em` font sizing in all browsers.\n}\n\npre {\n // Remove browser default top margin\n margin-top: 0;\n // Reset browser default of `1em` to use `rem`s\n margin-bottom: 1rem;\n // Don't allow content to break outside\n overflow: auto;\n}\n\n\n//\n// Figures\n//\n\nfigure {\n // Apply a consistent margin strategy (matches our type styles).\n margin: 0 0 1rem;\n}\n\n\n//\n// Images and content\n//\n\nimg {\n vertical-align: middle;\n border-style: none; // Remove the border on images inside links in IE 10-.\n}\n\nsvg {\n // Workaround for the SVG overflow bug in IE10/11 is still required.\n // See https://github.com/twbs/bootstrap/issues/26878\n overflow: hidden;\n vertical-align: middle;\n}\n\n\n//\n// Tables\n//\n\ntable {\n border-collapse: collapse; // Prevent double borders\n}\n\ncaption {\n padding-top: $table-cell-padding;\n padding-bottom: $table-cell-padding;\n color: $table-caption-color;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n // Matches default `` alignment by inheriting from the ``, or the\n // closest parent with a set `text-align`.\n text-align: inherit;\n}\n\n\n//\n// Forms\n//\n\nlabel {\n // Allow labels to use `margin` for spacing.\n display: inline-block;\n margin-bottom: $label-margin-bottom;\n}\n\n// Remove the default `border-radius` that macOS Chrome adds.\n//\n// Details at https://github.com/twbs/bootstrap/issues/24093\nbutton {\n // stylelint-disable-next-line property-blacklist\n border-radius: 0;\n}\n\n// Work around a Firefox/IE bug where the transparent `button` background\n// results in a loss of the default `button` focus styles.\n//\n// Credit: https://github.com/suitcss/base/\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0; // Remove the margin in Firefox and Safari\n font-family: inherit;\n @include font-size(inherit);\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible; // Show the overflow in Edge\n}\n\nbutton,\nselect {\n text-transform: none; // Remove the inheritance of text transform in Firefox\n}\n\n// Remove the inheritance of word-wrap in Safari.\n//\n// Details at https://github.com/twbs/bootstrap/issues/24990\nselect {\n word-wrap: normal;\n}\n\n\n// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`\n// controls in Android 4.\n// 2. Correct the inability to style clickable types in iOS and Safari.\nbutton,\n[type=\"button\"], // 1\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button; // 2\n}\n\n// Opinionated: add \"hand\" cursor to non-disabled button elements.\n@if $enable-pointer-cursor-for-buttons {\n button,\n [type=\"button\"],\n [type=\"reset\"],\n [type=\"submit\"] {\n &:not(:disabled) {\n cursor: pointer;\n }\n }\n}\n\n// Remove inner border and padding from Firefox, but don't restore the outline like Normalize.\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box; // 1. Add the correct box sizing in IE 10-\n padding: 0; // 2. Remove the padding in IE 10-\n}\n\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n // Remove the default appearance of temporal inputs to avoid a Mobile Safari\n // bug where setting a custom line-height prevents text from being vertically\n // centered within the input.\n // See https://bugs.webkit.org/show_bug.cgi?id=139848\n // and https://github.com/twbs/bootstrap/issues/11266\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto; // Remove the default vertical scrollbar in IE.\n // Textareas should really only resize vertically so they don't break their (horizontal) containers.\n resize: vertical;\n}\n\nfieldset {\n // Browsers set a default `min-width: min-content;` on fieldsets,\n // unlike e.g. `

`s, which have `min-width: 0;` by default.\n // So we reset that to ensure fieldsets behave more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359\n // and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements\n min-width: 0;\n // Reset the default outline behavior of fieldsets so they don't affect page layout.\n padding: 0;\n margin: 0;\n border: 0;\n}\n\n// 1. Correct the text wrapping in Edge and IE.\n// 2. Correct the color inheritance from `fieldset` elements in IE.\nlegend {\n display: block;\n width: 100%;\n max-width: 100%; // 1\n padding: 0;\n margin-bottom: .5rem;\n @include font-size(1.5rem);\n line-height: inherit;\n color: inherit; // 2\n white-space: normal; // 1\n}\n\nprogress {\n vertical-align: baseline; // Add the correct vertical alignment in Chrome, Firefox, and Opera.\n}\n\n// Correct the cursor style of increment and decrement buttons in Chrome.\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n // This overrides the extra rounded corners on search inputs in iOS so that our\n // `.form-control` class can properly style them. Note that this cannot simply\n // be added to `.form-control` as it's not specific enough. For details, see\n // https://github.com/twbs/bootstrap/issues/11586.\n outline-offset: -2px; // 2. Correct the outline style in Safari.\n -webkit-appearance: none;\n}\n\n//\n// Remove the inner padding in Chrome and Safari on macOS.\n//\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// 1. Correct the inability to style clickable types in iOS and Safari.\n// 2. Change font properties to `inherit` in Safari.\n//\n\n::-webkit-file-upload-button {\n font: inherit; // 2\n -webkit-appearance: button; // 1\n}\n\n//\n// Correct element displays\n//\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item; // Add the correct display in all browsers\n cursor: pointer;\n}\n\ntemplate {\n display: none; // Add the correct display in IE\n}\n\n// Always hide an element with the `hidden` HTML attribute (from PureCSS).\n// Needed for proper display in IE 10-.\n[hidden] {\n display: none !important;\n}\n","// Variables\n//\n// Variables should follow the `$component-state-property-size` formula for\n// consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs.\n\n// Color system\n\n$white: #fff !default;\n$gray-100: #f8f9fa !default;\n$gray-200: #e9ecef !default;\n$gray-300: #dee2e6 !default;\n$gray-400: #ced4da !default;\n$gray-500: #adb5bd !default;\n$gray-600: #6c757d !default;\n$gray-700: #495057 !default;\n$gray-800: #343a40 !default;\n$gray-900: #212529 !default;\n$black: #000 !default;\n\n$grays: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$grays: map-merge(\n (\n \"100\": $gray-100,\n \"200\": $gray-200,\n \"300\": $gray-300,\n \"400\": $gray-400,\n \"500\": $gray-500,\n \"600\": $gray-600,\n \"700\": $gray-700,\n \"800\": $gray-800,\n \"900\": $gray-900\n ),\n $grays\n);\n\n$blue: #007bff !default;\n$indigo: #6610f2 !default;\n$purple: #6f42c1 !default;\n$pink: #e83e8c !default;\n$red: #dc3545 !default;\n$orange: #fd7e14 !default;\n$yellow: #ffc107 !default;\n$green: #28a745 !default;\n$teal: #20c997 !default;\n$cyan: #17a2b8 !default;\n\n$colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$colors: map-merge(\n (\n \"blue\": $blue,\n \"indigo\": $indigo,\n \"purple\": $purple,\n \"pink\": $pink,\n \"red\": $red,\n \"orange\": $orange,\n \"yellow\": $yellow,\n \"green\": $green,\n \"teal\": $teal,\n \"cyan\": $cyan,\n \"white\": $white,\n \"gray\": $gray-600,\n \"gray-dark\": $gray-800\n ),\n $colors\n);\n\n$primary: $blue !default;\n$secondary: $gray-600 !default;\n$success: $green !default;\n$info: $cyan !default;\n$warning: $yellow !default;\n$danger: $red !default;\n$light: $gray-100 !default;\n$dark: $gray-800 !default;\n\n$theme-colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$theme-colors: map-merge(\n (\n \"primary\": $primary,\n \"secondary\": $secondary,\n \"success\": $success,\n \"info\": $info,\n \"warning\": $warning,\n \"danger\": $danger,\n \"light\": $light,\n \"dark\": $dark\n ),\n $theme-colors\n);\n\n// Set a specific jump point for requesting color jumps\n$theme-color-interval: 8% !default;\n\n// The yiq lightness value that determines when the lightness of color changes from \"dark\" to \"light\". Acceptable values are between 0 and 255.\n$yiq-contrasted-threshold: 150 !default;\n\n// Customize the light and dark text colors for use in our YIQ color contrast function.\n$yiq-text-dark: $gray-900 !default;\n$yiq-text-light: $white !default;\n\n\n// Options\n//\n// Quickly modify global styling by enabling or disabling optional features.\n\n$enable-caret: true !default;\n$enable-rounded: true !default;\n$enable-shadows: false !default;\n$enable-gradients: false !default;\n$enable-transitions: true !default;\n$enable-prefers-reduced-motion-media-query: true !default;\n$enable-hover-media-query: false !default; // Deprecated, no longer affects any compiled CSS\n$enable-grid-classes: true !default;\n$enable-pointer-cursor-for-buttons: true !default;\n$enable-print-styles: true !default;\n$enable-responsive-font-sizes: false !default;\n$enable-validation-icons: true !default;\n$enable-deprecation-messages: true !default;\n\n\n// Spacing\n//\n// Control the default styling of most Bootstrap elements by modifying these\n// variables. Mostly focused on spacing.\n// You can add more entries to the $spacers map, should you need more variation.\n\n$spacer: 1rem !default;\n$spacers: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$spacers: map-merge(\n (\n 0: 0,\n 1: ($spacer * .25),\n 2: ($spacer * .5),\n 3: $spacer,\n 4: ($spacer * 1.5),\n 5: ($spacer * 3)\n ),\n $spacers\n);\n\n// This variable affects the `.h-*` and `.w-*` classes.\n$sizes: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$sizes: map-merge(\n (\n 25: 25%,\n 50: 50%,\n 75: 75%,\n 100: 100%,\n auto: auto\n ),\n $sizes\n);\n\n\n// Body\n//\n// Settings for the `` element.\n\n$body-bg: $white !default;\n$body-color: $gray-900 !default;\n\n\n// Links\n//\n// Style anchor elements.\n\n$link-color: theme-color(\"primary\") !default;\n$link-decoration: none !default;\n$link-hover-color: darken($link-color, 15%) !default;\n$link-hover-decoration: underline !default;\n// Darken percentage for links with `.text-*` class (e.g. `.text-success`)\n$emphasized-link-hover-darken-percentage: 15% !default;\n\n// Paragraphs\n//\n// Style p element.\n\n$paragraph-margin-bottom: 1rem !default;\n\n\n// Grid breakpoints\n//\n// Define the minimum dimensions at which your layout will change,\n// adapting to different screen sizes, for use in media queries.\n\n$grid-breakpoints: (\n xs: 0,\n sm: 576px,\n md: 768px,\n lg: 992px,\n xl: 1200px\n) !default;\n\n@include _assert-ascending($grid-breakpoints, \"$grid-breakpoints\");\n@include _assert-starts-at-zero($grid-breakpoints, \"$grid-breakpoints\");\n\n\n// Grid containers\n//\n// Define the maximum width of `.container` for different screen sizes.\n\n$container-max-widths: (\n sm: 540px,\n md: 720px,\n lg: 960px,\n xl: 1140px\n) !default;\n\n@include _assert-ascending($container-max-widths, \"$container-max-widths\");\n\n\n// Grid columns\n//\n// Set the number of columns and specify the width of the gutters.\n\n$grid-columns: 12 !default;\n$grid-gutter-width: 30px !default;\n\n\n// Components\n//\n// Define common padding and border radius sizes and more.\n\n$line-height-lg: 1.5 !default;\n$line-height-sm: 1.5 !default;\n\n$border-width: 1px !default;\n$border-color: $gray-300 !default;\n\n$border-radius: .25rem !default;\n$border-radius-lg: .3rem !default;\n$border-radius-sm: .2rem !default;\n\n$rounded-pill: 50rem !default;\n\n$box-shadow-sm: 0 .125rem .25rem rgba($black, .075) !default;\n$box-shadow: 0 .5rem 1rem rgba($black, .15) !default;\n$box-shadow-lg: 0 1rem 3rem rgba($black, .175) !default;\n\n$component-active-color: $white !default;\n$component-active-bg: theme-color(\"primary\") !default;\n\n$caret-width: .3em !default;\n$caret-vertical-align: $caret-width * .85 !default;\n$caret-spacing: $caret-width * .85 !default;\n\n$transition-base: all .2s ease-in-out !default;\n$transition-fade: opacity .15s linear !default;\n$transition-collapse: height .35s ease !default;\n\n$embed-responsive-aspect-ratios: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$embed-responsive-aspect-ratios: join(\n (\n (21 9),\n (16 9),\n (4 3),\n (1 1),\n ),\n $embed-responsive-aspect-ratios\n);\n\n// Typography\n//\n// Font, line-height, and color for body text, headings, and more.\n\n// stylelint-disable value-keyword-case\n$font-family-sans-serif: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\" !default;\n$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace !default;\n$font-family-base: $font-family-sans-serif !default;\n// stylelint-enable value-keyword-case\n\n$font-size-base: 1rem !default; // Assumes the browser default, typically `16px`\n$font-size-lg: $font-size-base * 1.25 !default;\n$font-size-sm: $font-size-base * .875 !default;\n\n$font-weight-lighter: lighter !default;\n$font-weight-light: 300 !default;\n$font-weight-normal: 400 !default;\n$font-weight-bold: 700 !default;\n$font-weight-bolder: bolder !default;\n\n$font-weight-base: $font-weight-normal !default;\n$line-height-base: 1.5 !default;\n\n$h1-font-size: $font-size-base * 2.5 !default;\n$h2-font-size: $font-size-base * 2 !default;\n$h3-font-size: $font-size-base * 1.75 !default;\n$h4-font-size: $font-size-base * 1.5 !default;\n$h5-font-size: $font-size-base * 1.25 !default;\n$h6-font-size: $font-size-base !default;\n\n$headings-margin-bottom: $spacer / 2 !default;\n$headings-font-family: null !default;\n$headings-font-weight: 500 !default;\n$headings-line-height: 1.2 !default;\n$headings-color: null !default;\n\n$display1-size: 6rem !default;\n$display2-size: 5.5rem !default;\n$display3-size: 4.5rem !default;\n$display4-size: 3.5rem !default;\n\n$display1-weight: 300 !default;\n$display2-weight: 300 !default;\n$display3-weight: 300 !default;\n$display4-weight: 300 !default;\n$display-line-height: $headings-line-height !default;\n\n$lead-font-size: $font-size-base * 1.25 !default;\n$lead-font-weight: 300 !default;\n\n$small-font-size: 80% !default;\n\n$text-muted: $gray-600 !default;\n\n$blockquote-small-color: $gray-600 !default;\n$blockquote-small-font-size: $small-font-size !default;\n$blockquote-font-size: $font-size-base * 1.25 !default;\n\n$hr-border-color: rgba($black, .1) !default;\n$hr-border-width: $border-width !default;\n\n$mark-padding: .2em !default;\n\n$dt-font-weight: $font-weight-bold !default;\n\n$kbd-box-shadow: inset 0 -.1rem 0 rgba($black, .25) !default;\n$nested-kbd-font-weight: $font-weight-bold !default;\n\n$list-inline-padding: .5rem !default;\n\n$mark-bg: #fcf8e3 !default;\n\n$hr-margin-y: $spacer !default;\n\n\n// Tables\n//\n// Customizes the `.table` component with basic values, each used across all table variations.\n\n$table-cell-padding: .75rem !default;\n$table-cell-padding-sm: .3rem !default;\n\n$table-color: $body-color !default;\n$table-bg: null !default;\n$table-accent-bg: rgba($black, .05) !default;\n$table-hover-color: $table-color !default;\n$table-hover-bg: rgba($black, .075) !default;\n$table-active-bg: $table-hover-bg !default;\n\n$table-border-width: $border-width !default;\n$table-border-color: $border-color !default;\n\n$table-head-bg: $gray-200 !default;\n$table-head-color: $gray-700 !default;\n\n$table-dark-color: $white !default;\n$table-dark-bg: $gray-800 !default;\n$table-dark-accent-bg: rgba($white, .05) !default;\n$table-dark-hover-color: $table-dark-color !default;\n$table-dark-hover-bg: rgba($white, .075) !default;\n$table-dark-border-color: lighten($table-dark-bg, 7.5%) !default;\n$table-dark-color: $white !default;\n\n$table-striped-order: odd !default;\n\n$table-caption-color: $text-muted !default;\n\n$table-bg-level: -9 !default;\n$table-border-level: -6 !default;\n\n\n// Buttons + Forms\n//\n// Shared variables that are reassigned to `$input-` and `$btn-` specific variables.\n\n$input-btn-padding-y: .375rem !default;\n$input-btn-padding-x: .75rem !default;\n$input-btn-font-family: null !default;\n$input-btn-font-size: $font-size-base !default;\n$input-btn-line-height: $line-height-base !default;\n\n$input-btn-focus-width: .2rem !default;\n$input-btn-focus-color: rgba($component-active-bg, .25) !default;\n$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color !default;\n\n$input-btn-padding-y-sm: .25rem !default;\n$input-btn-padding-x-sm: .5rem !default;\n$input-btn-font-size-sm: $font-size-sm !default;\n$input-btn-line-height-sm: $line-height-sm !default;\n\n$input-btn-padding-y-lg: .5rem !default;\n$input-btn-padding-x-lg: 1rem !default;\n$input-btn-font-size-lg: $font-size-lg !default;\n$input-btn-line-height-lg: $line-height-lg !default;\n\n$input-btn-border-width: $border-width !default;\n\n\n// Buttons\n//\n// For each of Bootstrap's buttons, define text, background, and border color.\n\n$btn-padding-y: $input-btn-padding-y !default;\n$btn-padding-x: $input-btn-padding-x !default;\n$btn-font-family: $input-btn-font-family !default;\n$btn-font-size: $input-btn-font-size !default;\n$btn-line-height: $input-btn-line-height !default;\n\n$btn-padding-y-sm: $input-btn-padding-y-sm !default;\n$btn-padding-x-sm: $input-btn-padding-x-sm !default;\n$btn-font-size-sm: $input-btn-font-size-sm !default;\n$btn-line-height-sm: $input-btn-line-height-sm !default;\n\n$btn-padding-y-lg: $input-btn-padding-y-lg !default;\n$btn-padding-x-lg: $input-btn-padding-x-lg !default;\n$btn-font-size-lg: $input-btn-font-size-lg !default;\n$btn-line-height-lg: $input-btn-line-height-lg !default;\n\n$btn-border-width: $input-btn-border-width !default;\n\n$btn-font-weight: $font-weight-normal !default;\n$btn-box-shadow: inset 0 1px 0 rgba($white, .15), 0 1px 1px rgba($black, .075) !default;\n$btn-focus-width: $input-btn-focus-width !default;\n$btn-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$btn-disabled-opacity: .65 !default;\n$btn-active-box-shadow: inset 0 3px 5px rgba($black, .125) !default;\n\n$btn-link-disabled-color: $gray-600 !default;\n\n$btn-block-spacing-y: .5rem !default;\n\n// Allows for customizing button radius independently from global border radius\n$btn-border-radius: $border-radius !default;\n$btn-border-radius-lg: $border-radius-lg !default;\n$btn-border-radius-sm: $border-radius-sm !default;\n\n$btn-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n\n// Forms\n\n$label-margin-bottom: .5rem !default;\n\n$input-padding-y: $input-btn-padding-y !default;\n$input-padding-x: $input-btn-padding-x !default;\n$input-font-family: $input-btn-font-family !default;\n$input-font-size: $input-btn-font-size !default;\n$input-font-weight: $font-weight-base !default;\n$input-line-height: $input-btn-line-height !default;\n\n$input-padding-y-sm: $input-btn-padding-y-sm !default;\n$input-padding-x-sm: $input-btn-padding-x-sm !default;\n$input-font-size-sm: $input-btn-font-size-sm !default;\n$input-line-height-sm: $input-btn-line-height-sm !default;\n\n$input-padding-y-lg: $input-btn-padding-y-lg !default;\n$input-padding-x-lg: $input-btn-padding-x-lg !default;\n$input-font-size-lg: $input-btn-font-size-lg !default;\n$input-line-height-lg: $input-btn-line-height-lg !default;\n\n$input-bg: $white !default;\n$input-disabled-bg: $gray-200 !default;\n\n$input-color: $gray-700 !default;\n$input-border-color: $gray-400 !default;\n$input-border-width: $input-btn-border-width !default;\n$input-box-shadow: inset 0 1px 1px rgba($black, .075) !default;\n\n$input-border-radius: $border-radius !default;\n$input-border-radius-lg: $border-radius-lg !default;\n$input-border-radius-sm: $border-radius-sm !default;\n\n$input-focus-bg: $input-bg !default;\n$input-focus-border-color: lighten($component-active-bg, 25%) !default;\n$input-focus-color: $input-color !default;\n$input-focus-width: $input-btn-focus-width !default;\n$input-focus-box-shadow: $input-btn-focus-box-shadow !default;\n\n$input-placeholder-color: $gray-600 !default;\n$input-plaintext-color: $body-color !default;\n\n$input-height-border: $input-border-width * 2 !default;\n\n$input-height-inner: calc(#{$input-line-height * 1em} + #{$input-padding-y * 2}) !default;\n$input-height-inner-half: calc(#{$input-line-height * .5em} + #{$input-padding-y}) !default;\n$input-height-inner-quarter: calc(#{$input-line-height * .25em} + #{$input-padding-y / 2}) !default;\n\n$input-height: calc(#{$input-line-height * 1em} + #{$input-padding-y * 2} + #{$input-height-border}) !default;\n$input-height-sm: calc(#{$input-line-height-sm * 1em} + #{$input-btn-padding-y-sm * 2} + #{$input-height-border}) !default;\n$input-height-lg: calc(#{$input-line-height-lg * 1em} + #{$input-btn-padding-y-lg * 2} + #{$input-height-border}) !default;\n\n$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$form-text-margin-top: .25rem !default;\n\n$form-check-input-gutter: 1.25rem !default;\n$form-check-input-margin-y: .3rem !default;\n$form-check-input-margin-x: .25rem !default;\n\n$form-check-inline-margin-x: .75rem !default;\n$form-check-inline-input-margin-x: .3125rem !default;\n\n$form-grid-gutter-width: 10px !default;\n$form-group-margin-bottom: 1rem !default;\n\n$input-group-addon-color: $input-color !default;\n$input-group-addon-bg: $gray-200 !default;\n$input-group-addon-border-color: $input-border-color !default;\n\n$custom-forms-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$custom-control-gutter: .5rem !default;\n$custom-control-spacer-x: 1rem !default;\n\n$custom-control-indicator-size: 1rem !default;\n$custom-control-indicator-bg: $input-bg !default;\n\n$custom-control-indicator-bg-size: 50% 50% !default;\n$custom-control-indicator-box-shadow: $input-box-shadow !default;\n$custom-control-indicator-border-color: $gray-500 !default;\n$custom-control-indicator-border-width: $input-border-width !default;\n\n$custom-control-indicator-disabled-bg: $input-disabled-bg !default;\n$custom-control-label-disabled-color: $gray-600 !default;\n\n$custom-control-indicator-checked-color: $component-active-color !default;\n$custom-control-indicator-checked-bg: $component-active-bg !default;\n$custom-control-indicator-checked-disabled-bg: rgba(theme-color(\"primary\"), .5) !default;\n$custom-control-indicator-checked-box-shadow: none !default;\n$custom-control-indicator-checked-border-color: $custom-control-indicator-checked-bg !default;\n\n$custom-control-indicator-focus-box-shadow: $input-focus-box-shadow !default;\n$custom-control-indicator-focus-border-color: $input-focus-border-color !default;\n\n$custom-control-indicator-active-color: $component-active-color !default;\n$custom-control-indicator-active-bg: lighten($component-active-bg, 35%) !default;\n$custom-control-indicator-active-box-shadow: none !default;\n$custom-control-indicator-active-border-color: $custom-control-indicator-active-bg !default;\n\n$custom-checkbox-indicator-border-radius: $border-radius !default;\n$custom-checkbox-indicator-icon-checked: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='#{$custom-control-indicator-checked-color}' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n\n$custom-checkbox-indicator-indeterminate-bg: $component-active-bg !default;\n$custom-checkbox-indicator-indeterminate-color: $custom-control-indicator-checked-color !default;\n$custom-checkbox-indicator-icon-indeterminate: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3e%3cpath stroke='#{$custom-checkbox-indicator-indeterminate-color}' d='M0 2h4'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$custom-checkbox-indicator-indeterminate-box-shadow: none !default;\n$custom-checkbox-indicator-indeterminate-border-color: $custom-checkbox-indicator-indeterminate-bg !default;\n\n$custom-radio-indicator-border-radius: 50% !default;\n$custom-radio-indicator-icon-checked: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='#{$custom-control-indicator-checked-color}'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n\n$custom-switch-width: $custom-control-indicator-size * 1.75 !default;\n$custom-switch-indicator-border-radius: $custom-control-indicator-size / 2 !default;\n$custom-switch-indicator-size: calc(#{$custom-control-indicator-size} - #{$custom-control-indicator-border-width * 4}) !default;\n\n$custom-select-padding-y: $input-padding-y !default;\n$custom-select-padding-x: $input-padding-x !default;\n$custom-select-font-family: $input-font-family !default;\n$custom-select-font-size: $input-font-size !default;\n$custom-select-height: $input-height !default;\n$custom-select-indicator-padding: 1rem !default; // Extra padding to account for the presence of the background-image based indicator\n$custom-select-font-weight: $input-font-weight !default;\n$custom-select-line-height: $input-line-height !default;\n$custom-select-color: $input-color !default;\n$custom-select-disabled-color: $gray-600 !default;\n$custom-select-bg: $input-bg !default;\n$custom-select-disabled-bg: $gray-200 !default;\n$custom-select-bg-size: 8px 10px !default; // In pixels because image dimensions\n$custom-select-indicator-color: $gray-800 !default;\n$custom-select-indicator: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='#{$custom-select-indicator-color}' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$custom-select-background: $custom-select-indicator no-repeat right $custom-select-padding-x center / $custom-select-bg-size !default; // Used so we can have multiple background elements (e.g., arrow and feedback icon)\n\n$custom-select-feedback-icon-padding-right: calc((1em + #{2 * $custom-select-padding-y}) * 3 / 4 + #{$custom-select-padding-x + $custom-select-indicator-padding}) !default;\n$custom-select-feedback-icon-position: center right ($custom-select-padding-x + $custom-select-indicator-padding) !default;\n$custom-select-feedback-icon-size: $input-height-inner-half $input-height-inner-half !default;\n\n$custom-select-border-width: $input-border-width !default;\n$custom-select-border-color: $input-border-color !default;\n$custom-select-border-radius: $border-radius !default;\n$custom-select-box-shadow: inset 0 1px 2px rgba($black, .075) !default;\n\n$custom-select-focus-border-color: $input-focus-border-color !default;\n$custom-select-focus-width: $input-focus-width !default;\n$custom-select-focus-box-shadow: 0 0 0 $custom-select-focus-width $input-btn-focus-color !default;\n\n$custom-select-padding-y-sm: $input-padding-y-sm !default;\n$custom-select-padding-x-sm: $input-padding-x-sm !default;\n$custom-select-font-size-sm: $input-font-size-sm !default;\n$custom-select-height-sm: $input-height-sm !default;\n\n$custom-select-padding-y-lg: $input-padding-y-lg !default;\n$custom-select-padding-x-lg: $input-padding-x-lg !default;\n$custom-select-font-size-lg: $input-font-size-lg !default;\n$custom-select-height-lg: $input-height-lg !default;\n\n$custom-range-track-width: 100% !default;\n$custom-range-track-height: .5rem !default;\n$custom-range-track-cursor: pointer !default;\n$custom-range-track-bg: $gray-300 !default;\n$custom-range-track-border-radius: 1rem !default;\n$custom-range-track-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;\n\n$custom-range-thumb-width: 1rem !default;\n$custom-range-thumb-height: $custom-range-thumb-width !default;\n$custom-range-thumb-bg: $component-active-bg !default;\n$custom-range-thumb-border: 0 !default;\n$custom-range-thumb-border-radius: 1rem !default;\n$custom-range-thumb-box-shadow: 0 .1rem .25rem rgba($black, .1) !default;\n$custom-range-thumb-focus-box-shadow: 0 0 0 1px $body-bg, $input-focus-box-shadow !default;\n$custom-range-thumb-focus-box-shadow-width: $input-focus-width !default; // For focus box shadow issue in IE/Edge\n$custom-range-thumb-active-bg: lighten($component-active-bg, 35%) !default;\n$custom-range-thumb-disabled-bg: $gray-500 !default;\n\n$custom-file-height: $input-height !default;\n$custom-file-height-inner: $input-height-inner !default;\n$custom-file-focus-border-color: $input-focus-border-color !default;\n$custom-file-focus-box-shadow: $input-focus-box-shadow !default;\n$custom-file-disabled-bg: $input-disabled-bg !default;\n\n$custom-file-padding-y: $input-padding-y !default;\n$custom-file-padding-x: $input-padding-x !default;\n$custom-file-line-height: $input-line-height !default;\n$custom-file-font-family: $input-font-family !default;\n$custom-file-font-weight: $input-font-weight !default;\n$custom-file-color: $input-color !default;\n$custom-file-bg: $input-bg !default;\n$custom-file-border-width: $input-border-width !default;\n$custom-file-border-color: $input-border-color !default;\n$custom-file-border-radius: $input-border-radius !default;\n$custom-file-box-shadow: $input-box-shadow !default;\n$custom-file-button-color: $custom-file-color !default;\n$custom-file-button-bg: $input-group-addon-bg !default;\n$custom-file-text: (\n en: \"Browse\"\n) !default;\n\n\n// Form validation\n\n$form-feedback-margin-top: $form-text-margin-top !default;\n$form-feedback-font-size: $small-font-size !default;\n$form-feedback-valid-color: theme-color(\"success\") !default;\n$form-feedback-invalid-color: theme-color(\"danger\") !default;\n\n$form-feedback-icon-valid-color: $form-feedback-valid-color !default;\n$form-feedback-icon-valid: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='#{$form-feedback-icon-valid-color}' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$form-feedback-icon-invalid-color: $form-feedback-invalid-color !default;\n$form-feedback-icon-invalid: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$form-feedback-icon-invalid-color}' viewBox='-2 -2 7 7'%3e%3cpath stroke='#{$form-feedback-icon-invalid-color}' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E\"), \"#\", \"%23\") !default;\n\n$form-validation-states: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$form-validation-states: map-merge(\n (\n \"valid\": (\n \"color\": $form-feedback-valid-color,\n \"icon\": $form-feedback-icon-valid\n ),\n \"invalid\": (\n \"color\": $form-feedback-invalid-color,\n \"icon\": $form-feedback-icon-invalid\n ),\n ),\n $form-validation-states\n);\n\n// Z-index master list\n//\n// Warning: Avoid customizing these values. They're used for a bird's eye view\n// of components dependent on the z-axis and are designed to all work together.\n\n$zindex-dropdown: 1000 !default;\n$zindex-sticky: 1020 !default;\n$zindex-fixed: 1030 !default;\n$zindex-modal-backdrop: 1040 !default;\n$zindex-modal: 1050 !default;\n$zindex-popover: 1060 !default;\n$zindex-tooltip: 1070 !default;\n\n\n// Navs\n\n$nav-link-padding-y: .5rem !default;\n$nav-link-padding-x: 1rem !default;\n$nav-link-disabled-color: $gray-600 !default;\n\n$nav-tabs-border-color: $gray-300 !default;\n$nav-tabs-border-width: $border-width !default;\n$nav-tabs-border-radius: $border-radius !default;\n$nav-tabs-link-hover-border-color: $gray-200 $gray-200 $nav-tabs-border-color !default;\n$nav-tabs-link-active-color: $gray-700 !default;\n$nav-tabs-link-active-bg: $body-bg !default;\n$nav-tabs-link-active-border-color: $gray-300 $gray-300 $nav-tabs-link-active-bg !default;\n\n$nav-pills-border-radius: $border-radius !default;\n$nav-pills-link-active-color: $component-active-color !default;\n$nav-pills-link-active-bg: $component-active-bg !default;\n\n$nav-divider-color: $gray-200 !default;\n$nav-divider-margin-y: $spacer / 2 !default;\n\n\n// Navbar\n\n$navbar-padding-y: $spacer / 2 !default;\n$navbar-padding-x: $spacer !default;\n\n$navbar-nav-link-padding-x: .5rem !default;\n\n$navbar-brand-font-size: $font-size-lg !default;\n// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link\n$nav-link-height: $font-size-base * $line-height-base + $nav-link-padding-y * 2 !default;\n$navbar-brand-height: $navbar-brand-font-size * $line-height-base !default;\n$navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) / 2 !default;\n\n$navbar-toggler-padding-y: .25rem !default;\n$navbar-toggler-padding-x: .75rem !default;\n$navbar-toggler-font-size: $font-size-lg !default;\n$navbar-toggler-border-radius: $btn-border-radius !default;\n\n$navbar-dark-color: rgba($white, .5) !default;\n$navbar-dark-hover-color: rgba($white, .75) !default;\n$navbar-dark-active-color: $white !default;\n$navbar-dark-disabled-color: rgba($white, .25) !default;\n$navbar-dark-toggler-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='#{$navbar-dark-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$navbar-dark-toggler-border-color: rgba($white, .1) !default;\n\n$navbar-light-color: rgba($black, .5) !default;\n$navbar-light-hover-color: rgba($black, .7) !default;\n$navbar-light-active-color: rgba($black, .9) !default;\n$navbar-light-disabled-color: rgba($black, .3) !default;\n$navbar-light-toggler-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='#{$navbar-light-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$navbar-light-toggler-border-color: rgba($black, .1) !default;\n\n$navbar-light-brand-color: $navbar-light-active-color !default;\n$navbar-light-brand-hover-color: $navbar-light-active-color !default;\n$navbar-dark-brand-color: $navbar-dark-active-color !default;\n$navbar-dark-brand-hover-color: $navbar-dark-active-color !default;\n\n\n// Dropdowns\n//\n// Dropdown menu container and contents.\n\n$dropdown-min-width: 10rem !default;\n$dropdown-padding-y: .5rem !default;\n$dropdown-spacer: .125rem !default;\n$dropdown-font-size: $font-size-base !default;\n$dropdown-color: $body-color !default;\n$dropdown-bg: $white !default;\n$dropdown-border-color: rgba($black, .15) !default;\n$dropdown-border-radius: $border-radius !default;\n$dropdown-border-width: $border-width !default;\n$dropdown-inner-border-radius: calc(#{$dropdown-border-radius} - #{$dropdown-border-width}) !default;\n$dropdown-divider-bg: $gray-200 !default;\n$dropdown-divider-margin-y: $nav-divider-margin-y !default;\n$dropdown-box-shadow: 0 .5rem 1rem rgba($black, .175) !default;\n\n$dropdown-link-color: $gray-900 !default;\n$dropdown-link-hover-color: darken($gray-900, 5%) !default;\n$dropdown-link-hover-bg: $gray-100 !default;\n\n$dropdown-link-active-color: $component-active-color !default;\n$dropdown-link-active-bg: $component-active-bg !default;\n\n$dropdown-link-disabled-color: $gray-600 !default;\n\n$dropdown-item-padding-y: .25rem !default;\n$dropdown-item-padding-x: 1.5rem !default;\n\n$dropdown-header-color: $gray-600 !default;\n\n\n// Pagination\n\n$pagination-padding-y: .5rem !default;\n$pagination-padding-x: .75rem !default;\n$pagination-padding-y-sm: .25rem !default;\n$pagination-padding-x-sm: .5rem !default;\n$pagination-padding-y-lg: .75rem !default;\n$pagination-padding-x-lg: 1.5rem !default;\n$pagination-line-height: 1.25 !default;\n\n$pagination-color: $link-color !default;\n$pagination-bg: $white !default;\n$pagination-border-width: $border-width !default;\n$pagination-border-color: $gray-300 !default;\n\n$pagination-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$pagination-focus-outline: 0 !default;\n\n$pagination-hover-color: $link-hover-color !default;\n$pagination-hover-bg: $gray-200 !default;\n$pagination-hover-border-color: $gray-300 !default;\n\n$pagination-active-color: $component-active-color !default;\n$pagination-active-bg: $component-active-bg !default;\n$pagination-active-border-color: $pagination-active-bg !default;\n\n$pagination-disabled-color: $gray-600 !default;\n$pagination-disabled-bg: $white !default;\n$pagination-disabled-border-color: $gray-300 !default;\n\n\n// Jumbotron\n\n$jumbotron-padding: 2rem !default;\n$jumbotron-color: null !default;\n$jumbotron-bg: $gray-200 !default;\n\n\n// Cards\n\n$card-spacer-y: .75rem !default;\n$card-spacer-x: 1.25rem !default;\n$card-border-width: $border-width !default;\n$card-border-radius: $border-radius !default;\n$card-border-color: rgba($black, .125) !default;\n$card-inner-border-radius: calc(#{$card-border-radius} - #{$card-border-width}) !default;\n$card-cap-bg: rgba($black, .03) !default;\n$card-cap-color: null !default;\n$card-color: null !default;\n$card-bg: $white !default;\n\n$card-img-overlay-padding: 1.25rem !default;\n\n$card-group-margin: $grid-gutter-width / 2 !default;\n$card-deck-margin: $card-group-margin !default;\n\n$card-columns-count: 3 !default;\n$card-columns-gap: 1.25rem !default;\n$card-columns-margin: $card-spacer-y !default;\n\n\n// Tooltips\n\n$tooltip-font-size: $font-size-sm !default;\n$tooltip-max-width: 200px !default;\n$tooltip-color: $white !default;\n$tooltip-bg: $black !default;\n$tooltip-border-radius: $border-radius !default;\n$tooltip-opacity: .9 !default;\n$tooltip-padding-y: .25rem !default;\n$tooltip-padding-x: .5rem !default;\n$tooltip-margin: 0 !default;\n\n$tooltip-arrow-width: .8rem !default;\n$tooltip-arrow-height: .4rem !default;\n$tooltip-arrow-color: $tooltip-bg !default;\n\n// Form tooltips must come after regular tooltips\n$form-feedback-tooltip-padding-y: $tooltip-padding-y !default;\n$form-feedback-tooltip-padding-x: $tooltip-padding-x !default;\n$form-feedback-tooltip-font-size: $tooltip-font-size !default;\n$form-feedback-tooltip-line-height: $line-height-base !default;\n$form-feedback-tooltip-opacity: $tooltip-opacity !default;\n$form-feedback-tooltip-border-radius: $tooltip-border-radius !default;\n\n\n// Popovers\n\n$popover-font-size: $font-size-sm !default;\n$popover-bg: $white !default;\n$popover-max-width: 276px !default;\n$popover-border-width: $border-width !default;\n$popover-border-color: rgba($black, .2) !default;\n$popover-border-radius: $border-radius-lg !default;\n$popover-box-shadow: 0 .25rem .5rem rgba($black, .2) !default;\n\n$popover-header-bg: darken($popover-bg, 3%) !default;\n$popover-header-color: $headings-color !default;\n$popover-header-padding-y: .5rem !default;\n$popover-header-padding-x: .75rem !default;\n\n$popover-body-color: $body-color !default;\n$popover-body-padding-y: $popover-header-padding-y !default;\n$popover-body-padding-x: $popover-header-padding-x !default;\n\n$popover-arrow-width: 1rem !default;\n$popover-arrow-height: .5rem !default;\n$popover-arrow-color: $popover-bg !default;\n\n$popover-arrow-outer-color: fade-in($popover-border-color, .05) !default;\n\n\n// Toasts\n\n$toast-max-width: 350px !default;\n$toast-padding-x: .75rem !default;\n$toast-padding-y: .25rem !default;\n$toast-font-size: .875rem !default;\n$toast-color: null !default;\n$toast-background-color: rgba($white, .85) !default;\n$toast-border-width: 1px !default;\n$toast-border-color: rgba(0, 0, 0, .1) !default;\n$toast-border-radius: .25rem !default;\n$toast-box-shadow: 0 .25rem .75rem rgba($black, .1) !default;\n\n$toast-header-color: $gray-600 !default;\n$toast-header-background-color: rgba($white, .85) !default;\n$toast-header-border-color: rgba(0, 0, 0, .05) !default;\n\n\n// Badges\n\n$badge-font-size: 75% !default;\n$badge-font-weight: $font-weight-bold !default;\n$badge-padding-y: .25em !default;\n$badge-padding-x: .4em !default;\n$badge-border-radius: $border-radius !default;\n\n$badge-transition: $btn-transition !default;\n$badge-focus-width: $input-btn-focus-width !default;\n\n$badge-pill-padding-x: .6em !default;\n// Use a higher than normal value to ensure completely rounded edges when\n// customizing padding or font-size on labels.\n$badge-pill-border-radius: 10rem !default;\n\n\n// Modals\n\n// Padding applied to the modal body\n$modal-inner-padding: 1rem !default;\n\n$modal-dialog-margin: .5rem !default;\n$modal-dialog-margin-y-sm-up: 1.75rem !default;\n\n$modal-title-line-height: $line-height-base !default;\n\n$modal-content-color: null !default;\n$modal-content-bg: $white !default;\n$modal-content-border-color: rgba($black, .2) !default;\n$modal-content-border-width: $border-width !default;\n$modal-content-border-radius: $border-radius-lg !default;\n$modal-content-box-shadow-xs: 0 .25rem .5rem rgba($black, .5) !default;\n$modal-content-box-shadow-sm-up: 0 .5rem 1rem rgba($black, .5) !default;\n\n$modal-backdrop-bg: $black !default;\n$modal-backdrop-opacity: .5 !default;\n$modal-header-border-color: $border-color !default;\n$modal-footer-border-color: $modal-header-border-color !default;\n$modal-header-border-width: $modal-content-border-width !default;\n$modal-footer-border-width: $modal-header-border-width !default;\n$modal-header-padding-y: 1rem !default;\n$modal-header-padding-x: 1rem !default;\n$modal-header-padding: $modal-header-padding-y $modal-header-padding-x !default; // Keep this for backwards compatibility\n\n$modal-xl: 1140px !default;\n$modal-lg: 800px !default;\n$modal-md: 500px !default;\n$modal-sm: 300px !default;\n\n$modal-fade-transform: translate(0, -50px) !default;\n$modal-show-transform: none !default;\n$modal-transition: transform .3s ease-out !default;\n\n\n// Alerts\n//\n// Define alert colors, border radius, and padding.\n\n$alert-padding-y: .75rem !default;\n$alert-padding-x: 1.25rem !default;\n$alert-margin-bottom: 1rem !default;\n$alert-border-radius: $border-radius !default;\n$alert-link-font-weight: $font-weight-bold !default;\n$alert-border-width: $border-width !default;\n\n$alert-bg-level: -10 !default;\n$alert-border-level: -9 !default;\n$alert-color-level: 6 !default;\n\n\n// Progress bars\n\n$progress-height: 1rem !default;\n$progress-font-size: $font-size-base * .75 !default;\n$progress-bg: $gray-200 !default;\n$progress-border-radius: $border-radius !default;\n$progress-box-shadow: inset 0 .1rem .1rem rgba($black, .1) !default;\n$progress-bar-color: $white !default;\n$progress-bar-bg: theme-color(\"primary\") !default;\n$progress-bar-animation-timing: 1s linear infinite !default;\n$progress-bar-transition: width .6s ease !default;\n\n\n// List group\n\n$list-group-color: null !default;\n$list-group-bg: $white !default;\n$list-group-border-color: rgba($black, .125) !default;\n$list-group-border-width: $border-width !default;\n$list-group-border-radius: $border-radius !default;\n\n$list-group-item-padding-y: .75rem !default;\n$list-group-item-padding-x: 1.25rem !default;\n\n$list-group-hover-bg: $gray-100 !default;\n$list-group-active-color: $component-active-color !default;\n$list-group-active-bg: $component-active-bg !default;\n$list-group-active-border-color: $list-group-active-bg !default;\n\n$list-group-disabled-color: $gray-600 !default;\n$list-group-disabled-bg: $list-group-bg !default;\n\n$list-group-action-color: $gray-700 !default;\n$list-group-action-hover-color: $list-group-action-color !default;\n\n$list-group-action-active-color: $body-color !default;\n$list-group-action-active-bg: $gray-200 !default;\n\n\n// Image thumbnails\n\n$thumbnail-padding: .25rem !default;\n$thumbnail-bg: $body-bg !default;\n$thumbnail-border-width: $border-width !default;\n$thumbnail-border-color: $gray-300 !default;\n$thumbnail-border-radius: $border-radius !default;\n$thumbnail-box-shadow: 0 1px 2px rgba($black, .075) !default;\n\n\n// Figures\n\n$figure-caption-font-size: 90% !default;\n$figure-caption-color: $gray-600 !default;\n\n\n// Breadcrumbs\n\n$breadcrumb-padding-y: .75rem !default;\n$breadcrumb-padding-x: 1rem !default;\n$breadcrumb-item-padding: .5rem !default;\n\n$breadcrumb-margin-bottom: 1rem !default;\n\n$breadcrumb-bg: $gray-200 !default;\n$breadcrumb-divider-color: $gray-600 !default;\n$breadcrumb-active-color: $gray-600 !default;\n$breadcrumb-divider: quote(\"/\") !default;\n\n$breadcrumb-border-radius: $border-radius !default;\n\n\n// Carousel\n\n$carousel-control-color: $white !default;\n$carousel-control-width: 15% !default;\n$carousel-control-opacity: .5 !default;\n$carousel-control-hover-opacity: .9 !default;\n$carousel-control-transition: opacity .15s ease !default;\n\n$carousel-indicator-width: 30px !default;\n$carousel-indicator-height: 3px !default;\n$carousel-indicator-hit-area-height: 10px !default;\n$carousel-indicator-spacer: 3px !default;\n$carousel-indicator-active-bg: $white !default;\n$carousel-indicator-transition: opacity .6s ease !default;\n\n$carousel-caption-width: 70% !default;\n$carousel-caption-color: $white !default;\n\n$carousel-control-icon-width: 20px !default;\n\n$carousel-control-prev-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$carousel-control-next-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n\n$carousel-transition-duration: .6s !default;\n$carousel-transition: transform $carousel-transition-duration ease-in-out !default; // Define transform transition first if using multiple transitions (e.g., `transform 2s ease, opacity .5s ease-out`)\n\n\n// Spinners\n\n$spinner-width: 2rem !default;\n$spinner-height: $spinner-width !default;\n$spinner-border-width: .25em !default;\n\n$spinner-width-sm: 1rem !default;\n$spinner-height-sm: $spinner-width-sm !default;\n$spinner-border-width-sm: .2em !default;\n\n\n// Close\n\n$close-font-size: $font-size-base * 1.5 !default;\n$close-font-weight: $font-weight-bold !default;\n$close-color: $black !default;\n$close-text-shadow: 0 1px 0 $white !default;\n\n\n// Code\n\n$code-font-size: 87.5% !default;\n$code-color: $pink !default;\n\n$kbd-padding-y: .2rem !default;\n$kbd-padding-x: .4rem !default;\n$kbd-font-size: $code-font-size !default;\n$kbd-color: $white !default;\n$kbd-bg: $gray-900 !default;\n\n$pre-color: $gray-900 !default;\n$pre-scrollable-max-height: 340px !default;\n\n\n// Utilities\n\n$displays: none, inline, inline-block, block, table, table-row, table-cell, flex, inline-flex !default;\n$overflows: auto, hidden !default;\n$positions: static, relative, absolute, fixed, sticky !default;\n\n\n// Printing\n\n$print-page-size: a3 !default;\n$print-body-min-width: map-get($grid-breakpoints, \"lg\") !default;\n","// stylelint-disable property-blacklist, scss/dollar-variable-default\n\n// SCSS RFS mixin\n//\n// Automated font-resizing\n//\n// See https://github.com/twbs/rfs\n\n// Configuration\n\n// Base font size\n$rfs-base-font-size: 1.25rem !default;\n$rfs-font-size-unit: rem !default;\n\n// Breakpoint at where font-size starts decreasing if screen width is smaller\n$rfs-breakpoint: 1200px !default;\n$rfs-breakpoint-unit: px !default;\n\n// Resize font-size based on screen height and width\n$rfs-two-dimensional: false !default;\n\n// Factor of decrease\n$rfs-factor: 10 !default;\n\n@if type-of($rfs-factor) != \"number\" or $rfs-factor <= 1 {\n @error \"`#{$rfs-factor}` is not a valid $rfs-factor, it must be greater than 1.\";\n}\n\n// Generate enable or disable classes. Possibilities: false, \"enable\" or \"disable\"\n$rfs-class: false !default;\n\n// 1 rem = $rfs-rem-value px\n$rfs-rem-value: 16 !default;\n\n// Safari iframe resize bug: https://github.com/twbs/rfs/issues/14\n$rfs-safari-iframe-resize-bug-fix: false !default;\n\n// Disable RFS by setting $enable-responsive-font-sizes to false\n$enable-responsive-font-sizes: true !default;\n\n// Cache $rfs-base-font-size unit\n$rfs-base-font-size-unit: unit($rfs-base-font-size);\n\n// Remove px-unit from $rfs-base-font-size for calculations\n@if $rfs-base-font-size-unit == \"px\" {\n $rfs-base-font-size: $rfs-base-font-size / ($rfs-base-font-size * 0 + 1);\n}\n@else if $rfs-base-font-size-unit == \"rem\" {\n $rfs-base-font-size: $rfs-base-font-size / ($rfs-base-font-size * 0 + 1 / $rfs-rem-value);\n}\n\n// Cache $rfs-breakpoint unit to prevent multiple calls\n$rfs-breakpoint-unit-cache: unit($rfs-breakpoint);\n\n// Remove unit from $rfs-breakpoint for calculations\n@if $rfs-breakpoint-unit-cache == \"px\" {\n $rfs-breakpoint: $rfs-breakpoint / ($rfs-breakpoint * 0 + 1);\n}\n@else if $rfs-breakpoint-unit-cache == \"rem\" or $rfs-breakpoint-unit-cache == \"em\" {\n $rfs-breakpoint: $rfs-breakpoint / ($rfs-breakpoint * 0 + 1 / $rfs-rem-value);\n}\n\n// Responsive font-size mixin\n@mixin rfs($fs, $important: false) {\n // Cache $fs unit\n $fs-unit: if(type-of($fs) == \"number\", unit($fs), false);\n\n // Add !important suffix if needed\n $rfs-suffix: if($important, \" !important\", \"\");\n\n // If $fs isn't a number (like inherit) or $fs has a unit (not px or rem, like 1.5em) or $ is 0, just print the value\n @if not $fs-unit or $fs-unit != \"\" and $fs-unit != \"px\" and $fs-unit != \"rem\" or $fs == 0 {\n font-size: #{$fs}#{$rfs-suffix};\n }\n @else {\n // Variables for storing static and fluid rescaling\n $rfs-static: null;\n $rfs-fluid: null;\n\n // Remove px-unit from $fs for calculations\n @if $fs-unit == \"px\" {\n $fs: $fs / ($fs * 0 + 1);\n }\n @else if $fs-unit == \"rem\" {\n $fs: $fs / ($fs * 0 + 1 / $rfs-rem-value);\n }\n\n // Set default font-size\n @if $rfs-font-size-unit == rem {\n $rfs-static: #{$fs / $rfs-rem-value}rem#{$rfs-suffix};\n }\n @else if $rfs-font-size-unit == px {\n $rfs-static: #{$fs}px#{$rfs-suffix};\n }\n @else {\n @error \"`#{$rfs-font-size-unit}` is not a valid unit for $rfs-font-size-unit. Use `px` or `rem`.\";\n }\n\n // Only add media query if font-size is bigger as the minimum font-size\n // If $rfs-factor == 1, no rescaling will take place\n @if $fs > $rfs-base-font-size and $enable-responsive-font-sizes {\n $min-width: null;\n $variable-unit: null;\n\n // Calculate minimum font-size for given font-size\n $fs-min: $rfs-base-font-size + ($fs - $rfs-base-font-size) / $rfs-factor;\n\n // Calculate difference between given font-size and minimum font-size for given font-size\n $fs-diff: $fs - $fs-min;\n\n // Base font-size formatting\n // No need to check if the unit is valid, because we did that before\n $min-width: if($rfs-font-size-unit == rem, #{$fs-min / $rfs-rem-value}rem, #{$fs-min}px);\n\n // If two-dimensional, use smallest of screen width and height\n $variable-unit: if($rfs-two-dimensional, vmin, vw);\n\n // Calculate the variable width between 0 and $rfs-breakpoint\n $variable-width: #{$fs-diff * 100 / $rfs-breakpoint}#{$variable-unit};\n\n // Set the calculated font-size.\n $rfs-fluid: calc(#{$min-width} + #{$variable-width}) #{$rfs-suffix};\n }\n\n // Rendering\n @if $rfs-fluid == null {\n // Only render static font-size if no fluid font-size is available\n font-size: $rfs-static;\n }\n @else {\n $mq-value: null;\n\n // RFS breakpoint formatting\n @if $rfs-breakpoint-unit == em or $rfs-breakpoint-unit == rem {\n $mq-value: #{$rfs-breakpoint / $rfs-rem-value}#{$rfs-breakpoint-unit};\n }\n @else if $rfs-breakpoint-unit == px {\n $mq-value: #{$rfs-breakpoint}px;\n }\n @else {\n @error \"`#{$rfs-breakpoint-unit}` is not a valid unit for $rfs-breakpoint-unit. Use `px`, `em` or `rem`.\";\n }\n\n @if $rfs-class == \"disable\" {\n // Adding an extra class increases specificity,\n // which prevents the media query to override the font size\n &,\n .disable-responsive-font-size &,\n &.disable-responsive-font-size {\n font-size: $rfs-static;\n }\n }\n @else {\n font-size: $rfs-static;\n }\n\n @if $rfs-two-dimensional {\n @media (max-width: #{$mq-value}), (max-height: #{$mq-value}) {\n @if $rfs-class == \"enable\" {\n .enable-responsive-font-size &,\n &.enable-responsive-font-size {\n font-size: $rfs-fluid;\n }\n }\n @else {\n font-size: $rfs-fluid;\n }\n\n @if $rfs-safari-iframe-resize-bug-fix {\n // stylelint-disable-next-line length-zero-no-unit\n min-width: 0vw;\n }\n }\n }\n @else {\n @media (max-width: #{$mq-value}) {\n @if $rfs-class == \"enable\" {\n .enable-responsive-font-size &,\n &.enable-responsive-font-size {\n font-size: $rfs-fluid;\n }\n }\n @else {\n font-size: $rfs-fluid;\n }\n\n @if $rfs-safari-iframe-resize-bug-fix {\n // stylelint-disable-next-line length-zero-no-unit\n min-width: 0vw;\n }\n }\n }\n }\n }\n}\n\n// The font-size & responsive-font-size mixin uses RFS to rescale font sizes\n@mixin font-size($fs, $important: false) {\n @include rfs($fs, $important);\n}\n\n@mixin responsive-font-size($fs, $important: false) {\n @include rfs($fs, $important);\n}\n","// Hover mixin and `$enable-hover-media-query` are deprecated.\n//\n// Originally added during our alphas and maintained during betas, this mixin was\n// designed to prevent `:hover` stickiness on iOS-an issue where hover styles\n// would persist after initial touch.\n//\n// For backward compatibility, we've kept these mixins and updated them to\n// always return their regular pseudo-classes instead of a shimmed media query.\n//\n// Issue: https://github.com/twbs/bootstrap/issues/25195\n\n@mixin hover {\n &:hover { @content; }\n}\n\n@mixin hover-focus {\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin plain-hover-focus {\n &,\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin hover-focus-active {\n &:hover,\n &:focus,\n &:active {\n @content;\n }\n}\n","// stylelint-disable declaration-no-important, selector-list-comma-newline-after\n\n//\n// Headings\n//\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n margin-bottom: $headings-margin-bottom;\n font-family: $headings-font-family;\n font-weight: $headings-font-weight;\n line-height: $headings-line-height;\n color: $headings-color;\n}\n\nh1, .h1 { @include font-size($h1-font-size); }\nh2, .h2 { @include font-size($h2-font-size); }\nh3, .h3 { @include font-size($h3-font-size); }\nh4, .h4 { @include font-size($h4-font-size); }\nh5, .h5 { @include font-size($h5-font-size); }\nh6, .h6 { @include font-size($h6-font-size); }\n\n.lead {\n @include font-size($lead-font-size);\n font-weight: $lead-font-weight;\n}\n\n// Type display classes\n.display-1 {\n @include font-size($display1-size);\n font-weight: $display1-weight;\n line-height: $display-line-height;\n}\n.display-2 {\n @include font-size($display2-size);\n font-weight: $display2-weight;\n line-height: $display-line-height;\n}\n.display-3 {\n @include font-size($display3-size);\n font-weight: $display3-weight;\n line-height: $display-line-height;\n}\n.display-4 {\n @include font-size($display4-size);\n font-weight: $display4-weight;\n line-height: $display-line-height;\n}\n\n\n//\n// Horizontal rules\n//\n\nhr {\n margin-top: $hr-margin-y;\n margin-bottom: $hr-margin-y;\n border: 0;\n border-top: $hr-border-width solid $hr-border-color;\n}\n\n\n//\n// Emphasis\n//\n\nsmall,\n.small {\n @include font-size($small-font-size);\n font-weight: $font-weight-normal;\n}\n\nmark,\n.mark {\n padding: $mark-padding;\n background-color: $mark-bg;\n}\n\n\n//\n// Lists\n//\n\n.list-unstyled {\n @include list-unstyled;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n @include list-unstyled;\n}\n.list-inline-item {\n display: inline-block;\n\n &:not(:last-child) {\n margin-right: $list-inline-padding;\n }\n}\n\n\n//\n// Misc\n//\n\n// Builds on `abbr`\n.initialism {\n @include font-size(90%);\n text-transform: uppercase;\n}\n\n// Blockquotes\n.blockquote {\n margin-bottom: $spacer;\n @include font-size($blockquote-font-size);\n}\n\n.blockquote-footer {\n display: block;\n @include font-size($blockquote-small-font-size);\n color: $blockquote-small-color;\n\n &::before {\n content: \"\\2014\\00A0\"; // em dash, nbsp\n }\n}\n","// Lists\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n@mixin list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n","// Responsive images (ensure images don't scale beyond their parents)\n//\n// This is purposefully opt-in via an explicit class rather than being the default for all ``s.\n// We previously tried the \"images are responsive by default\" approach in Bootstrap v2,\n// and abandoned it in Bootstrap v3 because it breaks lots of third-party widgets (including Google Maps)\n// which weren't expecting the images within themselves to be involuntarily resized.\n// See also https://github.com/twbs/bootstrap/issues/18178\n.img-fluid {\n @include img-fluid;\n}\n\n\n// Image thumbnails\n.img-thumbnail {\n padding: $thumbnail-padding;\n background-color: $thumbnail-bg;\n border: $thumbnail-border-width solid $thumbnail-border-color;\n @include border-radius($thumbnail-border-radius);\n @include box-shadow($thumbnail-box-shadow);\n\n // Keep them at most 100% wide\n @include img-fluid;\n}\n\n//\n// Figures\n//\n\n.figure {\n // Ensures the caption's text aligns with the image.\n display: inline-block;\n}\n\n.figure-img {\n margin-bottom: $spacer / 2;\n line-height: 1;\n}\n\n.figure-caption {\n @include font-size($figure-caption-font-size);\n color: $figure-caption-color;\n}\n","// Image Mixins\n// - Responsive image\n// - Retina image\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n\n@mixin img-fluid {\n // Part 1: Set a maximum relative to the parent\n max-width: 100%;\n // Part 2: Override the height to auto, otherwise images will be stretched\n // when setting a width and height attribute on the img element.\n height: auto;\n}\n\n\n// Retina image\n//\n// Short retina mixin for setting background-image and -size.\n\n@mixin img-retina($file-1x, $file-2x, $width-1x, $height-1x) {\n background-image: url($file-1x);\n\n // Autoprefixer takes care of adding -webkit-min-device-pixel-ratio and -o-min-device-pixel-ratio,\n // but doesn't convert dppx=>dpi.\n // There's no such thing as unprefixed min-device-pixel-ratio since it's nonstandard.\n // Compatibility info: https://caniuse.com/#feat=css-media-resolution\n @media only screen and (min-resolution: 192dpi), // IE9-11 don't support dppx\n only screen and (min-resolution: 2dppx) { // Standardized\n background-image: url($file-2x);\n background-size: $width-1x $height-1x;\n }\n @include deprecate(\"`img-retina()`\", \"v4.3.0\", \"v5\");\n}\n","// stylelint-disable property-blacklist\n// Single side border-radius\n\n@mixin border-radius($radius: $border-radius, $fallback-border-radius: false) {\n @if $enable-rounded {\n border-radius: $radius;\n }\n @else if $fallback-border-radius != false {\n border-radius: $fallback-border-radius;\n }\n}\n\n@mixin border-top-radius($radius) {\n @if $enable-rounded {\n border-top-left-radius: $radius;\n border-top-right-radius: $radius;\n }\n}\n\n@mixin border-right-radius($radius) {\n @if $enable-rounded {\n border-top-right-radius: $radius;\n border-bottom-right-radius: $radius;\n }\n}\n\n@mixin border-bottom-radius($radius) {\n @if $enable-rounded {\n border-bottom-right-radius: $radius;\n border-bottom-left-radius: $radius;\n }\n}\n\n@mixin border-left-radius($radius) {\n @if $enable-rounded {\n border-top-left-radius: $radius;\n border-bottom-left-radius: $radius;\n }\n}\n\n@mixin border-top-left-radius($radius) {\n @if $enable-rounded {\n border-top-left-radius: $radius;\n }\n}\n\n@mixin border-top-right-radius($radius) {\n @if $enable-rounded {\n border-top-right-radius: $radius;\n }\n}\n\n@mixin border-bottom-right-radius($radius) {\n @if $enable-rounded {\n border-bottom-right-radius: $radius;\n }\n}\n\n@mixin border-bottom-left-radius($radius) {\n @if $enable-rounded {\n border-bottom-left-radius: $radius;\n }\n}\n","// Inline code\ncode {\n @include font-size($code-font-size);\n color: $code-color;\n word-break: break-word;\n\n // Streamline the style when inside anchors to avoid broken underline and more\n a > & {\n color: inherit;\n }\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: $kbd-padding-y $kbd-padding-x;\n @include font-size($kbd-font-size);\n color: $kbd-color;\n background-color: $kbd-bg;\n @include border-radius($border-radius-sm);\n @include box-shadow($kbd-box-shadow);\n\n kbd {\n padding: 0;\n @include font-size(100%);\n font-weight: $nested-kbd-font-weight;\n @include box-shadow(none);\n }\n}\n\n// Blocks of code\npre {\n display: block;\n @include font-size($code-font-size);\n color: $pre-color;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n @include font-size(inherit);\n color: inherit;\n word-break: normal;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: $pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n@if $enable-grid-classes {\n .container {\n @include make-container();\n @include make-container-max-widths();\n }\n}\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but with 100% width for\n// fluid, full width layouts.\n\n@if $enable-grid-classes {\n .container-fluid {\n @include make-container();\n }\n}\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n@if $enable-grid-classes {\n .row {\n @include make-row();\n }\n\n // Remove the negative margin from default .row, then the horizontal padding\n // from all immediate children columns (to prevent runaway style inheritance).\n .no-gutters {\n margin-right: 0;\n margin-left: 0;\n\n > .col,\n > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n }\n }\n}\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n@if $enable-grid-classes {\n @include make-grid-columns();\n}\n","/// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n@mixin make-container($gutter: $grid-gutter-width) {\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n margin-right: auto;\n margin-left: auto;\n}\n\n\n// For each breakpoint, define the maximum width of the container in a media query\n@mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) {\n @each $breakpoint, $container-max-width in $max-widths {\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n max-width: $container-max-width;\n }\n }\n}\n\n@mixin make-row($gutter: $grid-gutter-width) {\n display: flex;\n flex-wrap: wrap;\n margin-right: -$gutter / 2;\n margin-left: -$gutter / 2;\n}\n\n@mixin make-col-ready($gutter: $grid-gutter-width) {\n position: relative;\n // Prevent columns from becoming too narrow when at smaller grid tiers by\n // always setting `width: 100%;`. This works because we use `flex` values\n // later on to override this initial width.\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n}\n\n@mixin make-col($size, $columns: $grid-columns) {\n flex: 0 0 percentage($size / $columns);\n // Add a `max-width` to ensure content within each column does not blow out\n // the width of the column. Applies to IE10+ and Firefox. Chrome and Safari\n // do not appear to require this.\n max-width: percentage($size / $columns);\n}\n\n@mixin make-col-offset($size, $columns: $grid-columns) {\n $num: $size / $columns;\n margin-left: if($num == 0, 0, percentage($num));\n}\n","// Breakpoint viewport sizes and media queries.\n//\n// Breakpoints are defined as a map of (name: minimum width), order from small to large:\n//\n// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)\n//\n// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.\n\n// Name of the next breakpoint, or null for the last breakpoint.\n//\n// >> breakpoint-next(sm)\n// md\n// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// md\n// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl))\n// md\n@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {\n $n: index($breakpoint-names, $name);\n @return if($n != null and $n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);\n}\n\n// Minimum breakpoint width. Null for the smallest (first) breakpoint.\n//\n// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 576px\n@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {\n $min: map-get($breakpoints, $name);\n @return if($min != 0, $min, null);\n}\n\n// Maximum breakpoint width. Null for the largest (last) breakpoint.\n// The maximum value is calculated as the minimum of the next one less 0.02px\n// to work around the limitations of `min-` and `max-` prefixes and viewports with fractional widths.\n// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max\n// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.\n// See https://bugs.webkit.org/show_bug.cgi?id=178261\n//\n// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 767.98px\n@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {\n $next: breakpoint-next($name, $breakpoints);\n @return if($next, breakpoint-min($next, $breakpoints) - .02, null);\n}\n\n// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front.\n// Useful for making responsive utilities.\n//\n// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"\" (Returns a blank string)\n// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"-sm\"\n@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {\n @return if(breakpoint-min($name, $breakpoints) == null, \"\", \"-#{$name}\");\n}\n\n// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.\n// Makes the @content apply to the given breakpoint and wider.\n@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n @if $min {\n @media (min-width: $min) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media of at most the maximum breakpoint width. No query for the largest breakpoint.\n// Makes the @content apply to the given breakpoint and narrower.\n@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {\n $max: breakpoint-max($name, $breakpoints);\n @if $max {\n @media (max-width: $max) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media that spans multiple breakpoint widths.\n// Makes the @content apply between the min and max breakpoints\n@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($lower, $breakpoints);\n $max: breakpoint-max($upper, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($lower, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($upper, $breakpoints) {\n @content;\n }\n }\n}\n\n// Media between the breakpoint's minimum and maximum widths.\n// No minimum for the smallest breakpoint, and no maximum for the largest one.\n// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.\n@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n $max: breakpoint-max($name, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($name, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($name, $breakpoints) {\n @content;\n }\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `$grid-columns`.\n\n@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {\n // Common properties for all breakpoints\n %grid-column {\n position: relative;\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n }\n\n @each $breakpoint in map-keys($breakpoints) {\n $infix: breakpoint-infix($breakpoint, $breakpoints);\n\n // Allow columns to stretch full width below their breakpoints\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @extend %grid-column;\n }\n }\n .col#{$infix},\n .col#{$infix}-auto {\n @extend %grid-column;\n }\n\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n // Provide basic `.col-{bp}` classes for equal-width flexbox columns\n .col#{$infix} {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col#{$infix}-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%; // Reset earlier grid tiers\n }\n\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @include make-col($i, $columns);\n }\n }\n\n .order#{$infix}-first { order: -1; }\n\n .order#{$infix}-last { order: $columns + 1; }\n\n @for $i from 0 through $columns {\n .order#{$infix}-#{$i} { order: $i; }\n }\n\n // `$columns - 1` because offsetting by the width of an entire row isn't possible\n @for $i from 0 through ($columns - 1) {\n @if not ($infix == \"\" and $i == 0) { // Avoid emitting useless .offset-0\n .offset#{$infix}-#{$i} {\n @include make-col-offset($i, $columns);\n }\n }\n }\n }\n }\n}\n","//\n// Basic Bootstrap table\n//\n\n.table {\n width: 100%;\n margin-bottom: $spacer;\n color: $table-color;\n background-color: $table-bg; // Reset for nesting within parents with `background-color`.\n\n th,\n td {\n padding: $table-cell-padding;\n vertical-align: top;\n border-top: $table-border-width solid $table-border-color;\n }\n\n thead th {\n vertical-align: bottom;\n border-bottom: (2 * $table-border-width) solid $table-border-color;\n }\n\n tbody + tbody {\n border-top: (2 * $table-border-width) solid $table-border-color;\n }\n}\n\n\n//\n// Condensed table w/ half padding\n//\n\n.table-sm {\n th,\n td {\n padding: $table-cell-padding-sm;\n }\n}\n\n\n// Border versions\n//\n// Add or remove borders all around the table and between all the columns.\n\n.table-bordered {\n border: $table-border-width solid $table-border-color;\n\n th,\n td {\n border: $table-border-width solid $table-border-color;\n }\n\n thead {\n th,\n td {\n border-bottom-width: 2 * $table-border-width;\n }\n }\n}\n\n.table-borderless {\n th,\n td,\n thead th,\n tbody + tbody {\n border: 0;\n }\n}\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n tbody tr:nth-of-type(#{$table-striped-order}) {\n background-color: $table-accent-bg;\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n tbody tr {\n @include hover {\n color: $table-hover-color;\n background-color: $table-hover-bg;\n }\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n@each $color, $value in $theme-colors {\n @include table-row-variant($color, theme-color-level($color, $table-bg-level), theme-color-level($color, $table-border-level));\n}\n\n@include table-row-variant(active, $table-active-bg);\n\n\n// Dark styles\n//\n// Same table markup, but inverted color scheme: dark background and light text.\n\n// stylelint-disable-next-line no-duplicate-selectors\n.table {\n .thead-dark {\n th {\n color: $table-dark-color;\n background-color: $table-dark-bg;\n border-color: $table-dark-border-color;\n }\n }\n\n .thead-light {\n th {\n color: $table-head-color;\n background-color: $table-head-bg;\n border-color: $table-border-color;\n }\n }\n}\n\n.table-dark {\n color: $table-dark-color;\n background-color: $table-dark-bg;\n\n th,\n td,\n thead th {\n border-color: $table-dark-border-color;\n }\n\n &.table-bordered {\n border: 0;\n }\n\n &.table-striped {\n tbody tr:nth-of-type(odd) {\n background-color: $table-dark-accent-bg;\n }\n }\n\n &.table-hover {\n tbody tr {\n @include hover {\n color: $table-dark-hover-color;\n background-color: $table-dark-hover-bg;\n }\n }\n }\n}\n\n\n// Responsive tables\n//\n// Generate series of `.table-responsive-*` classes for configuring the screen\n// size of where your table will overflow.\n\n.table-responsive {\n @each $breakpoint in map-keys($grid-breakpoints) {\n $next: breakpoint-next($breakpoint, $grid-breakpoints);\n $infix: breakpoint-infix($next, $grid-breakpoints);\n\n &#{$infix} {\n @include media-breakpoint-down($breakpoint) {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n\n // Prevent double border on horizontal scroll due to use of `display: block;`\n > .table-bordered {\n border: 0;\n }\n }\n }\n }\n}\n","// Tables\n\n@mixin table-row-variant($state, $background, $border: null) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table-#{$state} {\n &,\n > th,\n > td {\n background-color: $background;\n }\n\n @if $border != null {\n th,\n td,\n thead th,\n tbody + tbody {\n border-color: $border;\n }\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover {\n $hover-background: darken($background, 5%);\n\n .table-#{$state} {\n @include hover {\n background-color: $hover-background;\n\n > td,\n > th {\n background-color: $hover-background;\n }\n }\n }\n }\n}\n","// Bootstrap functions\n//\n// Utility mixins and functions for evaluating source code across our variables, maps, and mixins.\n\n// Ascending\n// Used to evaluate Sass maps like our grid breakpoints.\n@mixin _assert-ascending($map, $map-name) {\n $prev-key: null;\n $prev-num: null;\n @each $key, $num in $map {\n @if $prev-num == null or unit($num) == \"%\" {\n // Do nothing\n } @else if not comparable($prev-num, $num) {\n @warn \"Potentially invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} whose unit makes it incomparable to #{$prev-num}, the value of the previous key '#{$prev-key}' !\";\n } @else if $prev-num >= $num {\n @warn \"Invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} which isn't greater than #{$prev-num}, the value of the previous key '#{$prev-key}' !\";\n }\n $prev-key: $key;\n $prev-num: $num;\n }\n}\n\n// Starts at zero\n// Used to ensure the min-width of the lowest breakpoint starts at 0.\n@mixin _assert-starts-at-zero($map, $map-name: \"$grid-breakpoints\") {\n $values: map-values($map);\n $first-value: nth($values, 1);\n @if $first-value != 0 {\n @warn \"First breakpoint in #{$map-name} must start at 0, but starts at #{$first-value}.\";\n }\n}\n\n// Replace `$search` with `$replace` in `$string`\n// Used on our SVG icon backgrounds for custom forms.\n//\n// @author Hugo Giraudel\n// @param {String} $string - Initial string\n// @param {String} $search - Substring to replace\n// @param {String} $replace ('') - New value\n// @return {String} - Updated string\n@function str-replace($string, $search, $replace: \"\") {\n $index: str-index($string, $search);\n\n @if $index {\n @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);\n }\n\n @return $string;\n}\n\n// Color contrast\n@function color-yiq($color, $dark: $yiq-text-dark, $light: $yiq-text-light) {\n $r: red($color);\n $g: green($color);\n $b: blue($color);\n\n $yiq: (($r * 299) + ($g * 587) + ($b * 114)) / 1000;\n\n @if ($yiq >= $yiq-contrasted-threshold) {\n @return $dark;\n } @else {\n @return $light;\n }\n}\n\n// Retrieve color Sass maps\n@function color($key: \"blue\") {\n @return map-get($colors, $key);\n}\n\n@function theme-color($key: \"primary\") {\n @return map-get($theme-colors, $key);\n}\n\n@function gray($key: \"100\") {\n @return map-get($grays, $key);\n}\n\n// Request a theme color level\n@function theme-color-level($color-name: \"primary\", $level: 0) {\n $color: theme-color($color-name);\n $color-base: if($level > 0, $black, $white);\n $level: abs($level);\n\n @return mix($color-base, $color, $level * $theme-color-interval);\n}\n","// stylelint-disable selector-no-qualifying-type\n\n//\n// Textual form controls\n//\n\n.form-control {\n display: block;\n width: 100%;\n height: $input-height;\n padding: $input-padding-y $input-padding-x;\n font-family: $input-font-family;\n @include font-size($input-font-size);\n font-weight: $input-font-weight;\n line-height: $input-line-height;\n color: $input-color;\n background-color: $input-bg;\n background-clip: padding-box;\n border: $input-border-width solid $input-border-color;\n\n // Note: This has no effect on `s in CSS.\n @include border-radius($input-border-radius, 0);\n\n @include box-shadow($input-box-shadow);\n @include transition($input-transition);\n\n // Unstyle the caret on ` receives focus\n // in IE and (under certain conditions) Edge, as it looks bad and cannot be made to\n // match the appearance of the native widget.\n // See https://github.com/twbs/bootstrap/issues/19398.\n color: $input-color;\n background-color: $input-bg;\n }\n}\n\n// Make file inputs better match text inputs by forcing them to new lines.\n.form-control-file,\n.form-control-range {\n display: block;\n width: 100%;\n}\n\n\n//\n// Labels\n//\n\n// For use with horizontal and inline forms, when you need the label (or legend)\n// text to align with the form controls.\n.col-form-label {\n padding-top: calc(#{$input-padding-y} + #{$input-border-width});\n padding-bottom: calc(#{$input-padding-y} + #{$input-border-width});\n margin-bottom: 0; // Override the `
',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",sanitize:!0,sanitizeFn:null,whiteList:Ee},je="show",He="out",Re={HIDE:"hide"+De,HIDDEN:"hidden"+De,SHOW:"show"+De,SHOWN:"shown"+De,INSERTED:"inserted"+De,CLICK:"click"+De,FOCUSIN:"focusin"+De,FOCUSOUT:"focusout"+De,MOUSEENTER:"mouseenter"+De,MOUSELEAVE:"mouseleave"+De},xe="fade",Fe="show",Ue=".tooltip-inner",We=".arrow",qe="hover",Me="focus",Ke="click",Qe="manual",Be=function(){function i(t,e){if("undefined"==typeof u)throw new TypeError("Bootstrap's tooltips require Popper.js (https://popper.js.org/)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var t=i.prototype;return t.enable=function(){this._isEnabled=!0},t.disable=function(){this._isEnabled=!1},t.toggleEnabled=function(){this._isEnabled=!this._isEnabled},t.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=g(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(g(this.getTipElement()).hasClass(Fe))return void this._leave(null,this);this._enter(null,this)}},t.dispose=function(){clearTimeout(this._timeout),g.removeData(this.element,this.constructor.DATA_KEY),g(this.element).off(this.constructor.EVENT_KEY),g(this.element).closest(".modal").off("hide.bs.modal"),this.tip&&g(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,(this._activeTrigger=null)!==this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},t.show=function(){var e=this;if("none"===g(this.element).css("display"))throw new Error("Please use show on visible elements");var t=g.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){g(this.element).trigger(t);var n=_.findShadowRoot(this.element),i=g.contains(null!==n?n:this.element.ownerDocument.documentElement,this.element);if(t.isDefaultPrevented()||!i)return;var o=this.getTipElement(),r=_.getUID(this.constructor.NAME);o.setAttribute("id",r),this.element.setAttribute("aria-describedby",r),this.setContent(),this.config.animation&&g(o).addClass(xe);var s="function"==typeof this.config.placement?this.config.placement.call(this,o,this.element):this.config.placement,a=this._getAttachment(s);this.addAttachmentClass(a);var l=this._getContainer();g(o).data(this.constructor.DATA_KEY,this),g.contains(this.element.ownerDocument.documentElement,this.tip)||g(o).appendTo(l),g(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new u(this.element,o,{placement:a,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:We},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}}),g(o).addClass(Fe),"ontouchstart"in document.documentElement&&g(document.body).children().on("mouseover",null,g.noop);var c=function(){e.config.animation&&e._fixTransition();var t=e._hoverState;e._hoverState=null,g(e.element).trigger(e.constructor.Event.SHOWN),t===He&&e._leave(null,e)};if(g(this.tip).hasClass(xe)){var h=_.getTransitionDurationFromElement(this.tip);g(this.tip).one(_.TRANSITION_END,c).emulateTransitionEnd(h)}else c()}},t.hide=function(t){var e=this,n=this.getTipElement(),i=g.Event(this.constructor.Event.HIDE),o=function(){e._hoverState!==je&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),g(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(g(this.element).trigger(i),!i.isDefaultPrevented()){if(g(n).removeClass(Fe),"ontouchstart"in document.documentElement&&g(document.body).children().off("mouseover",null,g.noop),this._activeTrigger[Ke]=!1,this._activeTrigger[Me]=!1,this._activeTrigger[qe]=!1,g(this.tip).hasClass(xe)){var r=_.getTransitionDurationFromElement(n);g(n).one(_.TRANSITION_END,o).emulateTransitionEnd(r)}else o();this._hoverState=""}},t.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},t.isWithContent=function(){return Boolean(this.getTitle())},t.addAttachmentClass=function(t){g(this.getTipElement()).addClass(Ae+"-"+t)},t.getTipElement=function(){return this.tip=this.tip||g(this.config.template)[0],this.tip},t.setContent=function(){var t=this.getTipElement();this.setElementContent(g(t.querySelectorAll(Ue)),this.getTitle()),g(t).removeClass(xe+" "+Fe)},t.setElementContent=function(t,e){"object"!=typeof e||!e.nodeType&&!e.jquery?this.config.html?(this.config.sanitize&&(e=Se(e,this.config.whiteList,this.config.sanitizeFn)),t.html(e)):t.text(e):this.config.html?g(e).parent().is(t)||t.empty().append(e):t.text(g(e).text())},t.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},t._getOffset=function(){var e=this,t={};return"function"==typeof this.config.offset?t.fn=function(t){return t.offsets=l({},t.offsets,e.config.offset(t.offsets,e.element)||{}),t}:t.offset=this.config.offset,t},t._getContainer=function(){return!1===this.config.container?document.body:_.isElement(this.config.container)?g(this.config.container):g(document).find(this.config.container)},t._getAttachment=function(t){return Pe[t.toUpperCase()]},t._setListeners=function(){var i=this;this.config.trigger.split(" ").forEach(function(t){if("click"===t)g(i.element).on(i.constructor.Event.CLICK,i.config.selector,function(t){return i.toggle(t)});else if(t!==Qe){var e=t===qe?i.constructor.Event.MOUSEENTER:i.constructor.Event.FOCUSIN,n=t===qe?i.constructor.Event.MOUSELEAVE:i.constructor.Event.FOCUSOUT;g(i.element).on(e,i.config.selector,function(t){return i._enter(t)}).on(n,i.config.selector,function(t){return i._leave(t)})}}),g(this.element).closest(".modal").on("hide.bs.modal",function(){i.element&&i.hide()}),this.config.selector?this.config=l({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},t._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},t._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||g(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?Me:qe]=!0),g(e.getTipElement()).hasClass(Fe)||e._hoverState===je?e._hoverState=je:(clearTimeout(e._timeout),e._hoverState=je,e.config.delay&&e.config.delay.show?e._timeout=setTimeout(function(){e._hoverState===je&&e.show()},e.config.delay.show):e.show())},t._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||g(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?Me:qe]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=He,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout(function(){e._hoverState===He&&e.hide()},e.config.delay.hide):e.hide())},t._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},t._getConfig=function(t){var e=g(this.element).data();return Object.keys(e).forEach(function(t){-1!==Oe.indexOf(t)&&delete e[t]}),"number"==typeof(t=l({},this.constructor.Default,e,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),_.typeCheckConfig(be,t,this.constructor.DefaultType),t.sanitize&&(t.template=Se(t.template,t.whiteList,t.sanitizeFn)),t},t._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},t._cleanTipClass=function(){var t=g(this.getTipElement()),e=t.attr("class").match(Ne);null!==e&&e.length&&t.removeClass(e.join(""))},t._handlePopperPlacementChange=function(t){var e=t.instance;this.tip=e.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},t._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(g(t).removeClass(xe),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},i._jQueryInterface=function(n){return this.each(function(){var t=g(this).data(Ie),e="object"==typeof n&&n;if((t||!/dispose|hide/.test(n))&&(t||(t=new i(this,e),g(this).data(Ie,t)),"string"==typeof n)){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return Le}},{key:"NAME",get:function(){return be}},{key:"DATA_KEY",get:function(){return Ie}},{key:"Event",get:function(){return Re}},{key:"EVENT_KEY",get:function(){return De}},{key:"DefaultType",get:function(){return ke}}]),i}();g.fn[be]=Be._jQueryInterface,g.fn[be].Constructor=Be,g.fn[be].noConflict=function(){return g.fn[be]=we,Be._jQueryInterface};var Ve="popover",Ye="bs.popover",ze="."+Ye,Xe=g.fn[Ve],$e="bs-popover",Ge=new RegExp("(^|\\s)"+$e+"\\S+","g"),Je=l({},Be.Default,{placement:"right",trigger:"click",content:"",template:''}),Ze=l({},Be.DefaultType,{content:"(string|element|function)"}),tn="fade",en="show",nn=".popover-header",on=".popover-body",rn={HIDE:"hide"+ze,HIDDEN:"hidden"+ze,SHOW:"show"+ze,SHOWN:"shown"+ze,INSERTED:"inserted"+ze,CLICK:"click"+ze,FOCUSIN:"focusin"+ze,FOCUSOUT:"focusout"+ze,MOUSEENTER:"mouseenter"+ze,MOUSELEAVE:"mouseleave"+ze},sn=function(t){var e,n;function i(){return t.apply(this,arguments)||this}n=t,(e=i).prototype=Object.create(n.prototype),(e.prototype.constructor=e).__proto__=n;var o=i.prototype;return o.isWithContent=function(){return this.getTitle()||this._getContent()},o.addAttachmentClass=function(t){g(this.getTipElement()).addClass($e+"-"+t)},o.getTipElement=function(){return this.tip=this.tip||g(this.config.template)[0],this.tip},o.setContent=function(){var t=g(this.getTipElement());this.setElementContent(t.find(nn),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(on),e),t.removeClass(tn+" "+en)},o._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},o._cleanTipClass=function(){var t=g(this.getTipElement()),e=t.attr("class").match(Ge);null!==e&&0=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t {\n called = true\n })\n\n setTimeout(() => {\n if (!called) {\n Util.triggerTransitionEnd(this)\n }\n }, duration)\n\n return this\n}\n\nfunction setTransitionEndSupport() {\n $.fn.emulateTransitionEnd = transitionEndEmulator\n $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent()\n}\n\n/**\n * --------------------------------------------------------------------------\n * Public Util Api\n * --------------------------------------------------------------------------\n */\n\nconst Util = {\n\n TRANSITION_END: 'bsTransitionEnd',\n\n getUID(prefix) {\n do {\n // eslint-disable-next-line no-bitwise\n prefix += ~~(Math.random() * MAX_UID) // \"~~\" acts like a faster Math.floor() here\n } while (document.getElementById(prefix))\n return prefix\n },\n\n getSelectorFromElement(element) {\n let selector = element.getAttribute('data-target')\n\n if (!selector || selector === '#') {\n const hrefAttr = element.getAttribute('href')\n selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : ''\n }\n\n try {\n return document.querySelector(selector) ? selector : null\n } catch (err) {\n return null\n }\n },\n\n getTransitionDurationFromElement(element) {\n if (!element) {\n return 0\n }\n\n // Get transition-duration of the element\n let transitionDuration = $(element).css('transition-duration')\n let transitionDelay = $(element).css('transition-delay')\n\n const floatTransitionDuration = parseFloat(transitionDuration)\n const floatTransitionDelay = parseFloat(transitionDelay)\n\n // Return 0 if element or transition duration is not found\n if (!floatTransitionDuration && !floatTransitionDelay) {\n return 0\n }\n\n // If multiple durations are defined, take the first\n transitionDuration = transitionDuration.split(',')[0]\n transitionDelay = transitionDelay.split(',')[0]\n\n return (parseFloat(transitionDuration) + parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER\n },\n\n reflow(element) {\n return element.offsetHeight\n },\n\n triggerTransitionEnd(element) {\n $(element).trigger(TRANSITION_END)\n },\n\n // TODO: Remove in v5\n supportsTransitionEnd() {\n return Boolean(TRANSITION_END)\n },\n\n isElement(obj) {\n return (obj[0] || obj).nodeType\n },\n\n typeCheckConfig(componentName, config, configTypes) {\n for (const property in configTypes) {\n if (Object.prototype.hasOwnProperty.call(configTypes, property)) {\n const expectedTypes = configTypes[property]\n const value = config[property]\n const valueType = value && Util.isElement(value)\n ? 'element' : toType(value)\n\n if (!new RegExp(expectedTypes).test(valueType)) {\n throw new Error(\n `${componentName.toUpperCase()}: ` +\n `Option \"${property}\" provided type \"${valueType}\" ` +\n `but expected type \"${expectedTypes}\".`)\n }\n }\n }\n },\n\n findShadowRoot(element) {\n if (!document.documentElement.attachShadow) {\n return null\n }\n\n // Can find the shadow root otherwise it'll return the document\n if (typeof element.getRootNode === 'function') {\n const root = element.getRootNode()\n return root instanceof ShadowRoot ? root : null\n }\n\n if (element instanceof ShadowRoot) {\n return element\n }\n\n // when we don't find a shadow root\n if (!element.parentNode) {\n return null\n }\n\n return Util.findShadowRoot(element.parentNode)\n }\n}\n\nsetTransitionEndSupport()\n\nexport default Util\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.3.1): alert.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport $ from 'jquery'\nimport Util from './util'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'alert'\nconst VERSION = '4.3.1'\nconst DATA_KEY = 'bs.alert'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\nconst JQUERY_NO_CONFLICT = $.fn[NAME]\n\nconst Selector = {\n DISMISS : '[data-dismiss=\"alert\"]'\n}\n\nconst Event = {\n CLOSE : `close${EVENT_KEY}`,\n CLOSED : `closed${EVENT_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n}\n\nconst ClassName = {\n ALERT : 'alert',\n FADE : 'fade',\n SHOW : 'show'\n}\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\nclass Alert {\n constructor(element) {\n this._element = element\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n // Public\n\n close(element) {\n let rootElement = this._element\n if (element) {\n rootElement = this._getRootElement(element)\n }\n\n const customEvent = this._triggerCloseEvent(rootElement)\n\n if (customEvent.isDefaultPrevented()) {\n return\n }\n\n this._removeElement(rootElement)\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n this._element = null\n }\n\n // Private\n\n _getRootElement(element) {\n const selector = Util.getSelectorFromElement(element)\n let parent = false\n\n if (selector) {\n parent = document.querySelector(selector)\n }\n\n if (!parent) {\n parent = $(element).closest(`.${ClassName.ALERT}`)[0]\n }\n\n return parent\n }\n\n _triggerCloseEvent(element) {\n const closeEvent = $.Event(Event.CLOSE)\n\n $(element).trigger(closeEvent)\n return closeEvent\n }\n\n _removeElement(element) {\n $(element).removeClass(ClassName.SHOW)\n\n if (!$(element).hasClass(ClassName.FADE)) {\n this._destroyElement(element)\n return\n }\n\n const transitionDuration = Util.getTransitionDurationFromElement(element)\n\n $(element)\n .one(Util.TRANSITION_END, (event) => this._destroyElement(element, event))\n .emulateTransitionEnd(transitionDuration)\n }\n\n _destroyElement(element) {\n $(element)\n .detach()\n .trigger(Event.CLOSED)\n .remove()\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n const $element = $(this)\n let data = $element.data(DATA_KEY)\n\n if (!data) {\n data = new Alert(this)\n $element.data(DATA_KEY, data)\n }\n\n if (config === 'close') {\n data[config](this)\n }\n })\n }\n\n static _handleDismiss(alertInstance) {\n return function (event) {\n if (event) {\n event.preventDefault()\n }\n\n alertInstance.close(this)\n }\n }\n}\n\n/**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n$(document).on(\n Event.CLICK_DATA_API,\n Selector.DISMISS,\n Alert._handleDismiss(new Alert())\n)\n\n/**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n$.fn[NAME] = Alert._jQueryInterface\n$.fn[NAME].Constructor = Alert\n$.fn[NAME].noConflict = () => {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Alert._jQueryInterface\n}\n\nexport default Alert\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.3.1): button.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport $ from 'jquery'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'button'\nconst VERSION = '4.3.1'\nconst DATA_KEY = 'bs.button'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\nconst JQUERY_NO_CONFLICT = $.fn[NAME]\n\nconst ClassName = {\n ACTIVE : 'active',\n BUTTON : 'btn',\n FOCUS : 'focus'\n}\n\nconst Selector = {\n DATA_TOGGLE_CARROT : '[data-toggle^=\"button\"]',\n DATA_TOGGLE : '[data-toggle=\"buttons\"]',\n INPUT : 'input:not([type=\"hidden\"])',\n ACTIVE : '.active',\n BUTTON : '.btn'\n}\n\nconst Event = {\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`,\n FOCUS_BLUR_DATA_API : `focus${EVENT_KEY}${DATA_API_KEY} ` +\n `blur${EVENT_KEY}${DATA_API_KEY}`\n}\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\nclass Button {\n constructor(element) {\n this._element = element\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n // Public\n\n toggle() {\n let triggerChangeEvent = true\n let addAriaPressed = true\n const rootElement = $(this._element).closest(\n Selector.DATA_TOGGLE\n )[0]\n\n if (rootElement) {\n const input = this._element.querySelector(Selector.INPUT)\n\n if (input) {\n if (input.type === 'radio') {\n if (input.checked &&\n this._element.classList.contains(ClassName.ACTIVE)) {\n triggerChangeEvent = false\n } else {\n const activeElement = rootElement.querySelector(Selector.ACTIVE)\n\n if (activeElement) {\n $(activeElement).removeClass(ClassName.ACTIVE)\n }\n }\n }\n\n if (triggerChangeEvent) {\n if (input.hasAttribute('disabled') ||\n rootElement.hasAttribute('disabled') ||\n input.classList.contains('disabled') ||\n rootElement.classList.contains('disabled')) {\n return\n }\n input.checked = !this._element.classList.contains(ClassName.ACTIVE)\n $(input).trigger('change')\n }\n\n input.focus()\n addAriaPressed = false\n }\n }\n\n if (addAriaPressed) {\n this._element.setAttribute('aria-pressed',\n !this._element.classList.contains(ClassName.ACTIVE))\n }\n\n if (triggerChangeEvent) {\n $(this._element).toggleClass(ClassName.ACTIVE)\n }\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n this._element = null\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n\n if (!data) {\n data = new Button(this)\n $(this).data(DATA_KEY, data)\n }\n\n if (config === 'toggle') {\n data[config]()\n }\n })\n }\n}\n\n/**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n$(document)\n .on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, (event) => {\n event.preventDefault()\n\n let button = event.target\n\n if (!$(button).hasClass(ClassName.BUTTON)) {\n button = $(button).closest(Selector.BUTTON)\n }\n\n Button._jQueryInterface.call($(button), 'toggle')\n })\n .on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, (event) => {\n const button = $(event.target).closest(Selector.BUTTON)[0]\n $(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type))\n })\n\n/**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n$.fn[NAME] = Button._jQueryInterface\n$.fn[NAME].Constructor = Button\n$.fn[NAME].noConflict = () => {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Button._jQueryInterface\n}\n\nexport default Button\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.3.1): carousel.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport $ from 'jquery'\nimport Util from './util'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'carousel'\nconst VERSION = '4.3.1'\nconst DATA_KEY = 'bs.carousel'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\nconst JQUERY_NO_CONFLICT = $.fn[NAME]\nconst ARROW_LEFT_KEYCODE = 37 // KeyboardEvent.which value for left arrow key\nconst ARROW_RIGHT_KEYCODE = 39 // KeyboardEvent.which value for right arrow key\nconst TOUCHEVENT_COMPAT_WAIT = 500 // Time for mouse compat events to fire after touch\nconst SWIPE_THRESHOLD = 40\n\nconst Default = {\n interval : 5000,\n keyboard : true,\n slide : false,\n pause : 'hover',\n wrap : true,\n touch : true\n}\n\nconst DefaultType = {\n interval : '(number|boolean)',\n keyboard : 'boolean',\n slide : '(boolean|string)',\n pause : '(string|boolean)',\n wrap : 'boolean',\n touch : 'boolean'\n}\n\nconst Direction = {\n NEXT : 'next',\n PREV : 'prev',\n LEFT : 'left',\n RIGHT : 'right'\n}\n\nconst Event = {\n SLIDE : `slide${EVENT_KEY}`,\n SLID : `slid${EVENT_KEY}`,\n KEYDOWN : `keydown${EVENT_KEY}`,\n MOUSEENTER : `mouseenter${EVENT_KEY}`,\n MOUSELEAVE : `mouseleave${EVENT_KEY}`,\n TOUCHSTART : `touchstart${EVENT_KEY}`,\n TOUCHMOVE : `touchmove${EVENT_KEY}`,\n TOUCHEND : `touchend${EVENT_KEY}`,\n POINTERDOWN : `pointerdown${EVENT_KEY}`,\n POINTERUP : `pointerup${EVENT_KEY}`,\n DRAG_START : `dragstart${EVENT_KEY}`,\n LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n}\n\nconst ClassName = {\n CAROUSEL : 'carousel',\n ACTIVE : 'active',\n SLIDE : 'slide',\n RIGHT : 'carousel-item-right',\n LEFT : 'carousel-item-left',\n NEXT : 'carousel-item-next',\n PREV : 'carousel-item-prev',\n ITEM : 'carousel-item',\n POINTER_EVENT : 'pointer-event'\n}\n\nconst Selector = {\n ACTIVE : '.active',\n ACTIVE_ITEM : '.active.carousel-item',\n ITEM : '.carousel-item',\n ITEM_IMG : '.carousel-item img',\n NEXT_PREV : '.carousel-item-next, .carousel-item-prev',\n INDICATORS : '.carousel-indicators',\n DATA_SLIDE : '[data-slide], [data-slide-to]',\n DATA_RIDE : '[data-ride=\"carousel\"]'\n}\n\nconst PointerType = {\n TOUCH : 'touch',\n PEN : 'pen'\n}\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\nclass Carousel {\n constructor(element, config) {\n this._items = null\n this._interval = null\n this._activeElement = null\n this._isPaused = false\n this._isSliding = false\n this.touchTimeout = null\n this.touchStartX = 0\n this.touchDeltaX = 0\n\n this._config = this._getConfig(config)\n this._element = element\n this._indicatorsElement = this._element.querySelector(Selector.INDICATORS)\n this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0\n this._pointerEvent = Boolean(window.PointerEvent || window.MSPointerEvent)\n\n this._addEventListeners()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n next() {\n if (!this._isSliding) {\n this._slide(Direction.NEXT)\n }\n }\n\n nextWhenVisible() {\n // Don't call next when the page isn't visible\n // or the carousel or its parent isn't visible\n if (!document.hidden &&\n ($(this._element).is(':visible') && $(this._element).css('visibility') !== 'hidden')) {\n this.next()\n }\n }\n\n prev() {\n if (!this._isSliding) {\n this._slide(Direction.PREV)\n }\n }\n\n pause(event) {\n if (!event) {\n this._isPaused = true\n }\n\n if (this._element.querySelector(Selector.NEXT_PREV)) {\n Util.triggerTransitionEnd(this._element)\n this.cycle(true)\n }\n\n clearInterval(this._interval)\n this._interval = null\n }\n\n cycle(event) {\n if (!event) {\n this._isPaused = false\n }\n\n if (this._interval) {\n clearInterval(this._interval)\n this._interval = null\n }\n\n if (this._config.interval && !this._isPaused) {\n this._interval = setInterval(\n (document.visibilityState ? this.nextWhenVisible : this.next).bind(this),\n this._config.interval\n )\n }\n }\n\n to(index) {\n this._activeElement = this._element.querySelector(Selector.ACTIVE_ITEM)\n\n const activeIndex = this._getItemIndex(this._activeElement)\n\n if (index > this._items.length - 1 || index < 0) {\n return\n }\n\n if (this._isSliding) {\n $(this._element).one(Event.SLID, () => this.to(index))\n return\n }\n\n if (activeIndex === index) {\n this.pause()\n this.cycle()\n return\n }\n\n const direction = index > activeIndex\n ? Direction.NEXT\n : Direction.PREV\n\n this._slide(direction, this._items[index])\n }\n\n dispose() {\n $(this._element).off(EVENT_KEY)\n $.removeData(this._element, DATA_KEY)\n\n this._items = null\n this._config = null\n this._element = null\n this._interval = null\n this._isPaused = null\n this._isSliding = null\n this._activeElement = null\n this._indicatorsElement = null\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...config\n }\n Util.typeCheckConfig(NAME, config, DefaultType)\n return config\n }\n\n _handleSwipe() {\n const absDeltax = Math.abs(this.touchDeltaX)\n\n if (absDeltax <= SWIPE_THRESHOLD) {\n return\n }\n\n const direction = absDeltax / this.touchDeltaX\n\n // swipe left\n if (direction > 0) {\n this.prev()\n }\n\n // swipe right\n if (direction < 0) {\n this.next()\n }\n }\n\n _addEventListeners() {\n if (this._config.keyboard) {\n $(this._element)\n .on(Event.KEYDOWN, (event) => this._keydown(event))\n }\n\n if (this._config.pause === 'hover') {\n $(this._element)\n .on(Event.MOUSEENTER, (event) => this.pause(event))\n .on(Event.MOUSELEAVE, (event) => this.cycle(event))\n }\n\n if (this._config.touch) {\n this._addTouchEventListeners()\n }\n }\n\n _addTouchEventListeners() {\n if (!this._touchSupported) {\n return\n }\n\n const start = (event) => {\n if (this._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) {\n this.touchStartX = event.originalEvent.clientX\n } else if (!this._pointerEvent) {\n this.touchStartX = event.originalEvent.touches[0].clientX\n }\n }\n\n const move = (event) => {\n // ensure swiping with one touch and not pinching\n if (event.originalEvent.touches && event.originalEvent.touches.length > 1) {\n this.touchDeltaX = 0\n } else {\n this.touchDeltaX = event.originalEvent.touches[0].clientX - this.touchStartX\n }\n }\n\n const end = (event) => {\n if (this._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) {\n this.touchDeltaX = event.originalEvent.clientX - this.touchStartX\n }\n\n this._handleSwipe()\n if (this._config.pause === 'hover') {\n // If it's a touch-enabled device, mouseenter/leave are fired as\n // part of the mouse compatibility events on first tap - the carousel\n // would stop cycling until user tapped out of it;\n // here, we listen for touchend, explicitly pause the carousel\n // (as if it's the second time we tap on it, mouseenter compat event\n // is NOT fired) and after a timeout (to allow for mouse compatibility\n // events to fire) we explicitly restart cycling\n\n this.pause()\n if (this.touchTimeout) {\n clearTimeout(this.touchTimeout)\n }\n this.touchTimeout = setTimeout((event) => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval)\n }\n }\n\n $(this._element.querySelectorAll(Selector.ITEM_IMG)).on(Event.DRAG_START, (e) => e.preventDefault())\n if (this._pointerEvent) {\n $(this._element).on(Event.POINTERDOWN, (event) => start(event))\n $(this._element).on(Event.POINTERUP, (event) => end(event))\n\n this._element.classList.add(ClassName.POINTER_EVENT)\n } else {\n $(this._element).on(Event.TOUCHSTART, (event) => start(event))\n $(this._element).on(Event.TOUCHMOVE, (event) => move(event))\n $(this._element).on(Event.TOUCHEND, (event) => end(event))\n }\n }\n\n _keydown(event) {\n if (/input|textarea/i.test(event.target.tagName)) {\n return\n }\n\n switch (event.which) {\n case ARROW_LEFT_KEYCODE:\n event.preventDefault()\n this.prev()\n break\n case ARROW_RIGHT_KEYCODE:\n event.preventDefault()\n this.next()\n break\n default:\n }\n }\n\n _getItemIndex(element) {\n this._items = element && element.parentNode\n ? [].slice.call(element.parentNode.querySelectorAll(Selector.ITEM))\n : []\n return this._items.indexOf(element)\n }\n\n _getItemByDirection(direction, activeElement) {\n const isNextDirection = direction === Direction.NEXT\n const isPrevDirection = direction === Direction.PREV\n const activeIndex = this._getItemIndex(activeElement)\n const lastItemIndex = this._items.length - 1\n const isGoingToWrap = isPrevDirection && activeIndex === 0 ||\n isNextDirection && activeIndex === lastItemIndex\n\n if (isGoingToWrap && !this._config.wrap) {\n return activeElement\n }\n\n const delta = direction === Direction.PREV ? -1 : 1\n const itemIndex = (activeIndex + delta) % this._items.length\n\n return itemIndex === -1\n ? this._items[this._items.length - 1] : this._items[itemIndex]\n }\n\n _triggerSlideEvent(relatedTarget, eventDirectionName) {\n const targetIndex = this._getItemIndex(relatedTarget)\n const fromIndex = this._getItemIndex(this._element.querySelector(Selector.ACTIVE_ITEM))\n const slideEvent = $.Event(Event.SLIDE, {\n relatedTarget,\n direction: eventDirectionName,\n from: fromIndex,\n to: targetIndex\n })\n\n $(this._element).trigger(slideEvent)\n\n return slideEvent\n }\n\n _setActiveIndicatorElement(element) {\n if (this._indicatorsElement) {\n const indicators = [].slice.call(this._indicatorsElement.querySelectorAll(Selector.ACTIVE))\n $(indicators)\n .removeClass(ClassName.ACTIVE)\n\n const nextIndicator = this._indicatorsElement.children[\n this._getItemIndex(element)\n ]\n\n if (nextIndicator) {\n $(nextIndicator).addClass(ClassName.ACTIVE)\n }\n }\n }\n\n _slide(direction, element) {\n const activeElement = this._element.querySelector(Selector.ACTIVE_ITEM)\n const activeElementIndex = this._getItemIndex(activeElement)\n const nextElement = element || activeElement &&\n this._getItemByDirection(direction, activeElement)\n const nextElementIndex = this._getItemIndex(nextElement)\n const isCycling = Boolean(this._interval)\n\n let directionalClassName\n let orderClassName\n let eventDirectionName\n\n if (direction === Direction.NEXT) {\n directionalClassName = ClassName.LEFT\n orderClassName = ClassName.NEXT\n eventDirectionName = Direction.LEFT\n } else {\n directionalClassName = ClassName.RIGHT\n orderClassName = ClassName.PREV\n eventDirectionName = Direction.RIGHT\n }\n\n if (nextElement && $(nextElement).hasClass(ClassName.ACTIVE)) {\n this._isSliding = false\n return\n }\n\n const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName)\n if (slideEvent.isDefaultPrevented()) {\n return\n }\n\n if (!activeElement || !nextElement) {\n // Some weirdness is happening, so we bail\n return\n }\n\n this._isSliding = true\n\n if (isCycling) {\n this.pause()\n }\n\n this._setActiveIndicatorElement(nextElement)\n\n const slidEvent = $.Event(Event.SLID, {\n relatedTarget: nextElement,\n direction: eventDirectionName,\n from: activeElementIndex,\n to: nextElementIndex\n })\n\n if ($(this._element).hasClass(ClassName.SLIDE)) {\n $(nextElement).addClass(orderClassName)\n\n Util.reflow(nextElement)\n\n $(activeElement).addClass(directionalClassName)\n $(nextElement).addClass(directionalClassName)\n\n const nextElementInterval = parseInt(nextElement.getAttribute('data-interval'), 10)\n if (nextElementInterval) {\n this._config.defaultInterval = this._config.defaultInterval || this._config.interval\n this._config.interval = nextElementInterval\n } else {\n this._config.interval = this._config.defaultInterval || this._config.interval\n }\n\n const transitionDuration = Util.getTransitionDurationFromElement(activeElement)\n\n $(activeElement)\n .one(Util.TRANSITION_END, () => {\n $(nextElement)\n .removeClass(`${directionalClassName} ${orderClassName}`)\n .addClass(ClassName.ACTIVE)\n\n $(activeElement).removeClass(`${ClassName.ACTIVE} ${orderClassName} ${directionalClassName}`)\n\n this._isSliding = false\n\n setTimeout(() => $(this._element).trigger(slidEvent), 0)\n })\n .emulateTransitionEnd(transitionDuration)\n } else {\n $(activeElement).removeClass(ClassName.ACTIVE)\n $(nextElement).addClass(ClassName.ACTIVE)\n\n this._isSliding = false\n $(this._element).trigger(slidEvent)\n }\n\n if (isCycling) {\n this.cycle()\n }\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n let _config = {\n ...Default,\n ...$(this).data()\n }\n\n if (typeof config === 'object') {\n _config = {\n ..._config,\n ...config\n }\n }\n\n const action = typeof config === 'string' ? config : _config.slide\n\n if (!data) {\n data = new Carousel(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'number') {\n data.to(config)\n } else if (typeof action === 'string') {\n if (typeof data[action] === 'undefined') {\n throw new TypeError(`No method named \"${action}\"`)\n }\n data[action]()\n } else if (_config.interval && _config.ride) {\n data.pause()\n data.cycle()\n }\n })\n }\n\n static _dataApiClickHandler(event) {\n const selector = Util.getSelectorFromElement(this)\n\n if (!selector) {\n return\n }\n\n const target = $(selector)[0]\n\n if (!target || !$(target).hasClass(ClassName.CAROUSEL)) {\n return\n }\n\n const config = {\n ...$(target).data(),\n ...$(this).data()\n }\n const slideIndex = this.getAttribute('data-slide-to')\n\n if (slideIndex) {\n config.interval = false\n }\n\n Carousel._jQueryInterface.call($(target), config)\n\n if (slideIndex) {\n $(target).data(DATA_KEY).to(slideIndex)\n }\n\n event.preventDefault()\n }\n}\n\n/**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n$(document)\n .on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler)\n\n$(window).on(Event.LOAD_DATA_API, () => {\n const carousels = [].slice.call(document.querySelectorAll(Selector.DATA_RIDE))\n for (let i = 0, len = carousels.length; i < len; i++) {\n const $carousel = $(carousels[i])\n Carousel._jQueryInterface.call($carousel, $carousel.data())\n }\n})\n\n/**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n$.fn[NAME] = Carousel._jQueryInterface\n$.fn[NAME].Constructor = Carousel\n$.fn[NAME].noConflict = () => {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Carousel._jQueryInterface\n}\n\nexport default Carousel\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.3.1): collapse.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport $ from 'jquery'\nimport Util from './util'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'collapse'\nconst VERSION = '4.3.1'\nconst DATA_KEY = 'bs.collapse'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\nconst JQUERY_NO_CONFLICT = $.fn[NAME]\n\nconst Default = {\n toggle : true,\n parent : ''\n}\n\nconst DefaultType = {\n toggle : 'boolean',\n parent : '(string|element)'\n}\n\nconst Event = {\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n}\n\nconst ClassName = {\n SHOW : 'show',\n COLLAPSE : 'collapse',\n COLLAPSING : 'collapsing',\n COLLAPSED : 'collapsed'\n}\n\nconst Dimension = {\n WIDTH : 'width',\n HEIGHT : 'height'\n}\n\nconst Selector = {\n ACTIVES : '.show, .collapsing',\n DATA_TOGGLE : '[data-toggle=\"collapse\"]'\n}\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\nclass Collapse {\n constructor(element, config) {\n this._isTransitioning = false\n this._element = element\n this._config = this._getConfig(config)\n this._triggerArray = [].slice.call(document.querySelectorAll(\n `[data-toggle=\"collapse\"][href=\"#${element.id}\"],` +\n `[data-toggle=\"collapse\"][data-target=\"#${element.id}\"]`\n ))\n\n const toggleList = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE))\n for (let i = 0, len = toggleList.length; i < len; i++) {\n const elem = toggleList[i]\n const selector = Util.getSelectorFromElement(elem)\n const filterElement = [].slice.call(document.querySelectorAll(selector))\n .filter((foundElem) => foundElem === element)\n\n if (selector !== null && filterElement.length > 0) {\n this._selector = selector\n this._triggerArray.push(elem)\n }\n }\n\n this._parent = this._config.parent ? this._getParent() : null\n\n if (!this._config.parent) {\n this._addAriaAndCollapsedClass(this._element, this._triggerArray)\n }\n\n if (this._config.toggle) {\n this.toggle()\n }\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n toggle() {\n if ($(this._element).hasClass(ClassName.SHOW)) {\n this.hide()\n } else {\n this.show()\n }\n }\n\n show() {\n if (this._isTransitioning ||\n $(this._element).hasClass(ClassName.SHOW)) {\n return\n }\n\n let actives\n let activesData\n\n if (this._parent) {\n actives = [].slice.call(this._parent.querySelectorAll(Selector.ACTIVES))\n .filter((elem) => {\n if (typeof this._config.parent === 'string') {\n return elem.getAttribute('data-parent') === this._config.parent\n }\n\n return elem.classList.contains(ClassName.COLLAPSE)\n })\n\n if (actives.length === 0) {\n actives = null\n }\n }\n\n if (actives) {\n activesData = $(actives).not(this._selector).data(DATA_KEY)\n if (activesData && activesData._isTransitioning) {\n return\n }\n }\n\n const startEvent = $.Event(Event.SHOW)\n $(this._element).trigger(startEvent)\n if (startEvent.isDefaultPrevented()) {\n return\n }\n\n if (actives) {\n Collapse._jQueryInterface.call($(actives).not(this._selector), 'hide')\n if (!activesData) {\n $(actives).data(DATA_KEY, null)\n }\n }\n\n const dimension = this._getDimension()\n\n $(this._element)\n .removeClass(ClassName.COLLAPSE)\n .addClass(ClassName.COLLAPSING)\n\n this._element.style[dimension] = 0\n\n if (this._triggerArray.length) {\n $(this._triggerArray)\n .removeClass(ClassName.COLLAPSED)\n .attr('aria-expanded', true)\n }\n\n this.setTransitioning(true)\n\n const complete = () => {\n $(this._element)\n .removeClass(ClassName.COLLAPSING)\n .addClass(ClassName.COLLAPSE)\n .addClass(ClassName.SHOW)\n\n this._element.style[dimension] = ''\n\n this.setTransitioning(false)\n\n $(this._element).trigger(Event.SHOWN)\n }\n\n const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1)\n const scrollSize = `scroll${capitalizedDimension}`\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._element)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n\n this._element.style[dimension] = `${this._element[scrollSize]}px`\n }\n\n hide() {\n if (this._isTransitioning ||\n !$(this._element).hasClass(ClassName.SHOW)) {\n return\n }\n\n const startEvent = $.Event(Event.HIDE)\n $(this._element).trigger(startEvent)\n if (startEvent.isDefaultPrevented()) {\n return\n }\n\n const dimension = this._getDimension()\n\n this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`\n\n Util.reflow(this._element)\n\n $(this._element)\n .addClass(ClassName.COLLAPSING)\n .removeClass(ClassName.COLLAPSE)\n .removeClass(ClassName.SHOW)\n\n const triggerArrayLength = this._triggerArray.length\n if (triggerArrayLength > 0) {\n for (let i = 0; i < triggerArrayLength; i++) {\n const trigger = this._triggerArray[i]\n const selector = Util.getSelectorFromElement(trigger)\n\n if (selector !== null) {\n const $elem = $([].slice.call(document.querySelectorAll(selector)))\n if (!$elem.hasClass(ClassName.SHOW)) {\n $(trigger).addClass(ClassName.COLLAPSED)\n .attr('aria-expanded', false)\n }\n }\n }\n }\n\n this.setTransitioning(true)\n\n const complete = () => {\n this.setTransitioning(false)\n $(this._element)\n .removeClass(ClassName.COLLAPSING)\n .addClass(ClassName.COLLAPSE)\n .trigger(Event.HIDDEN)\n }\n\n this._element.style[dimension] = ''\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._element)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n }\n\n setTransitioning(isTransitioning) {\n this._isTransitioning = isTransitioning\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n\n this._config = null\n this._parent = null\n this._element = null\n this._triggerArray = null\n this._isTransitioning = null\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...config\n }\n config.toggle = Boolean(config.toggle) // Coerce string values\n Util.typeCheckConfig(NAME, config, DefaultType)\n return config\n }\n\n _getDimension() {\n const hasWidth = $(this._element).hasClass(Dimension.WIDTH)\n return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT\n }\n\n _getParent() {\n let parent\n\n if (Util.isElement(this._config.parent)) {\n parent = this._config.parent\n\n // It's a jQuery object\n if (typeof this._config.parent.jquery !== 'undefined') {\n parent = this._config.parent[0]\n }\n } else {\n parent = document.querySelector(this._config.parent)\n }\n\n const selector =\n `[data-toggle=\"collapse\"][data-parent=\"${this._config.parent}\"]`\n\n const children = [].slice.call(parent.querySelectorAll(selector))\n $(children).each((i, element) => {\n this._addAriaAndCollapsedClass(\n Collapse._getTargetFromElement(element),\n [element]\n )\n })\n\n return parent\n }\n\n _addAriaAndCollapsedClass(element, triggerArray) {\n const isOpen = $(element).hasClass(ClassName.SHOW)\n\n if (triggerArray.length) {\n $(triggerArray)\n .toggleClass(ClassName.COLLAPSED, !isOpen)\n .attr('aria-expanded', isOpen)\n }\n }\n\n // Static\n\n static _getTargetFromElement(element) {\n const selector = Util.getSelectorFromElement(element)\n return selector ? document.querySelector(selector) : null\n }\n\n static _jQueryInterface(config) {\n return this.each(function () {\n const $this = $(this)\n let data = $this.data(DATA_KEY)\n const _config = {\n ...Default,\n ...$this.data(),\n ...typeof config === 'object' && config ? config : {}\n }\n\n if (!data && _config.toggle && /show|hide/.test(config)) {\n _config.toggle = false\n }\n\n if (!data) {\n data = new Collapse(this, _config)\n $this.data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config]()\n }\n })\n }\n}\n\n/**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n$(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n // preventDefault only for elements (which change the URL) not inside the collapsible element\n if (event.currentTarget.tagName === 'A') {\n event.preventDefault()\n }\n\n const $trigger = $(this)\n const selector = Util.getSelectorFromElement(this)\n const selectors = [].slice.call(document.querySelectorAll(selector))\n\n $(selectors).each(function () {\n const $target = $(this)\n const data = $target.data(DATA_KEY)\n const config = data ? 'toggle' : $trigger.data()\n Collapse._jQueryInterface.call($target, config)\n })\n})\n\n/**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n$.fn[NAME] = Collapse._jQueryInterface\n$.fn[NAME].Constructor = Collapse\n$.fn[NAME].noConflict = () => {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Collapse._jQueryInterface\n}\n\nexport default Collapse\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.3.1): dropdown.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport $ from 'jquery'\nimport Popper from 'popper.js'\nimport Util from './util'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'dropdown'\nconst VERSION = '4.3.1'\nconst DATA_KEY = 'bs.dropdown'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\nconst JQUERY_NO_CONFLICT = $.fn[NAME]\nconst ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key\nconst SPACE_KEYCODE = 32 // KeyboardEvent.which value for space key\nconst TAB_KEYCODE = 9 // KeyboardEvent.which value for tab key\nconst ARROW_UP_KEYCODE = 38 // KeyboardEvent.which value for up arrow key\nconst ARROW_DOWN_KEYCODE = 40 // KeyboardEvent.which value for down arrow key\nconst RIGHT_MOUSE_BUTTON_WHICH = 3 // MouseEvent.which value for the right button (assuming a right-handed mouse)\nconst REGEXP_KEYDOWN = new RegExp(`${ARROW_UP_KEYCODE}|${ARROW_DOWN_KEYCODE}|${ESCAPE_KEYCODE}`)\n\nconst Event = {\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n CLICK : `click${EVENT_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`,\n KEYDOWN_DATA_API : `keydown${EVENT_KEY}${DATA_API_KEY}`,\n KEYUP_DATA_API : `keyup${EVENT_KEY}${DATA_API_KEY}`\n}\n\nconst ClassName = {\n DISABLED : 'disabled',\n SHOW : 'show',\n DROPUP : 'dropup',\n DROPRIGHT : 'dropright',\n DROPLEFT : 'dropleft',\n MENURIGHT : 'dropdown-menu-right',\n MENULEFT : 'dropdown-menu-left',\n POSITION_STATIC : 'position-static'\n}\n\nconst Selector = {\n DATA_TOGGLE : '[data-toggle=\"dropdown\"]',\n FORM_CHILD : '.dropdown form',\n MENU : '.dropdown-menu',\n NAVBAR_NAV : '.navbar-nav',\n VISIBLE_ITEMS : '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)'\n}\n\nconst AttachmentMap = {\n TOP : 'top-start',\n TOPEND : 'top-end',\n BOTTOM : 'bottom-start',\n BOTTOMEND : 'bottom-end',\n RIGHT : 'right-start',\n RIGHTEND : 'right-end',\n LEFT : 'left-start',\n LEFTEND : 'left-end'\n}\n\nconst Default = {\n offset : 0,\n flip : true,\n boundary : 'scrollParent',\n reference : 'toggle',\n display : 'dynamic'\n}\n\nconst DefaultType = {\n offset : '(number|string|function)',\n flip : 'boolean',\n boundary : '(string|element)',\n reference : '(string|element)',\n display : 'string'\n}\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\nclass Dropdown {\n constructor(element, config) {\n this._element = element\n this._popper = null\n this._config = this._getConfig(config)\n this._menu = this._getMenuElement()\n this._inNavbar = this._detectNavbar()\n\n this._addEventListeners()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n // Public\n\n toggle() {\n if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED)) {\n return\n }\n\n const parent = Dropdown._getParentFromElement(this._element)\n const isActive = $(this._menu).hasClass(ClassName.SHOW)\n\n Dropdown._clearMenus()\n\n if (isActive) {\n return\n }\n\n const relatedTarget = {\n relatedTarget: this._element\n }\n const showEvent = $.Event(Event.SHOW, relatedTarget)\n\n $(parent).trigger(showEvent)\n\n if (showEvent.isDefaultPrevented()) {\n return\n }\n\n // Disable totally Popper.js for Dropdown in Navbar\n if (!this._inNavbar) {\n /**\n * Check for Popper dependency\n * Popper - https://popper.js.org\n */\n if (typeof Popper === 'undefined') {\n throw new TypeError('Bootstrap\\'s dropdowns require Popper.js (https://popper.js.org/)')\n }\n\n let referenceElement = this._element\n\n if (this._config.reference === 'parent') {\n referenceElement = parent\n } else if (Util.isElement(this._config.reference)) {\n referenceElement = this._config.reference\n\n // Check if it's jQuery element\n if (typeof this._config.reference.jquery !== 'undefined') {\n referenceElement = this._config.reference[0]\n }\n }\n\n // If boundary is not `scrollParent`, then set position to `static`\n // to allow the menu to \"escape\" the scroll parent's boundaries\n // https://github.com/twbs/bootstrap/issues/24251\n if (this._config.boundary !== 'scrollParent') {\n $(parent).addClass(ClassName.POSITION_STATIC)\n }\n this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig())\n }\n\n // If this is a touch-enabled device we add extra\n // empty mouseover listeners to the body's immediate children;\n // only needed because of broken event delegation on iOS\n // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n if ('ontouchstart' in document.documentElement &&\n $(parent).closest(Selector.NAVBAR_NAV).length === 0) {\n $(document.body).children().on('mouseover', null, $.noop)\n }\n\n this._element.focus()\n this._element.setAttribute('aria-expanded', true)\n\n $(this._menu).toggleClass(ClassName.SHOW)\n $(parent)\n .toggleClass(ClassName.SHOW)\n .trigger($.Event(Event.SHOWN, relatedTarget))\n }\n\n show() {\n if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED) || $(this._menu).hasClass(ClassName.SHOW)) {\n return\n }\n\n const relatedTarget = {\n relatedTarget: this._element\n }\n const showEvent = $.Event(Event.SHOW, relatedTarget)\n const parent = Dropdown._getParentFromElement(this._element)\n\n $(parent).trigger(showEvent)\n\n if (showEvent.isDefaultPrevented()) {\n return\n }\n\n $(this._menu).toggleClass(ClassName.SHOW)\n $(parent)\n .toggleClass(ClassName.SHOW)\n .trigger($.Event(Event.SHOWN, relatedTarget))\n }\n\n hide() {\n if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED) || !$(this._menu).hasClass(ClassName.SHOW)) {\n return\n }\n\n const relatedTarget = {\n relatedTarget: this._element\n }\n const hideEvent = $.Event(Event.HIDE, relatedTarget)\n const parent = Dropdown._getParentFromElement(this._element)\n\n $(parent).trigger(hideEvent)\n\n if (hideEvent.isDefaultPrevented()) {\n return\n }\n\n $(this._menu).toggleClass(ClassName.SHOW)\n $(parent)\n .toggleClass(ClassName.SHOW)\n .trigger($.Event(Event.HIDDEN, relatedTarget))\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n $(this._element).off(EVENT_KEY)\n this._element = null\n this._menu = null\n if (this._popper !== null) {\n this._popper.destroy()\n this._popper = null\n }\n }\n\n update() {\n this._inNavbar = this._detectNavbar()\n if (this._popper !== null) {\n this._popper.scheduleUpdate()\n }\n }\n\n // Private\n\n _addEventListeners() {\n $(this._element).on(Event.CLICK, (event) => {\n event.preventDefault()\n event.stopPropagation()\n this.toggle()\n })\n }\n\n _getConfig(config) {\n config = {\n ...this.constructor.Default,\n ...$(this._element).data(),\n ...config\n }\n\n Util.typeCheckConfig(\n NAME,\n config,\n this.constructor.DefaultType\n )\n\n return config\n }\n\n _getMenuElement() {\n if (!this._menu) {\n const parent = Dropdown._getParentFromElement(this._element)\n\n if (parent) {\n this._menu = parent.querySelector(Selector.MENU)\n }\n }\n return this._menu\n }\n\n _getPlacement() {\n const $parentDropdown = $(this._element.parentNode)\n let placement = AttachmentMap.BOTTOM\n\n // Handle dropup\n if ($parentDropdown.hasClass(ClassName.DROPUP)) {\n placement = AttachmentMap.TOP\n if ($(this._menu).hasClass(ClassName.MENURIGHT)) {\n placement = AttachmentMap.TOPEND\n }\n } else if ($parentDropdown.hasClass(ClassName.DROPRIGHT)) {\n placement = AttachmentMap.RIGHT\n } else if ($parentDropdown.hasClass(ClassName.DROPLEFT)) {\n placement = AttachmentMap.LEFT\n } else if ($(this._menu).hasClass(ClassName.MENURIGHT)) {\n placement = AttachmentMap.BOTTOMEND\n }\n return placement\n }\n\n _detectNavbar() {\n return $(this._element).closest('.navbar').length > 0\n }\n\n _getOffset() {\n const offset = {}\n\n if (typeof this._config.offset === 'function') {\n offset.fn = (data) => {\n data.offsets = {\n ...data.offsets,\n ...this._config.offset(data.offsets, this._element) || {}\n }\n\n return data\n }\n } else {\n offset.offset = this._config.offset\n }\n\n return offset\n }\n\n _getPopperConfig() {\n const popperConfig = {\n placement: this._getPlacement(),\n modifiers: {\n offset: this._getOffset(),\n flip: {\n enabled: this._config.flip\n },\n preventOverflow: {\n boundariesElement: this._config.boundary\n }\n }\n }\n\n // Disable Popper.js if we have a static display\n if (this._config.display === 'static') {\n popperConfig.modifiers.applyStyle = {\n enabled: false\n }\n }\n\n return popperConfig\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = typeof config === 'object' ? config : null\n\n if (!data) {\n data = new Dropdown(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config]()\n }\n })\n }\n\n static _clearMenus(event) {\n if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH ||\n event.type === 'keyup' && event.which !== TAB_KEYCODE)) {\n return\n }\n\n const toggles = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE))\n\n for (let i = 0, len = toggles.length; i < len; i++) {\n const parent = Dropdown._getParentFromElement(toggles[i])\n const context = $(toggles[i]).data(DATA_KEY)\n const relatedTarget = {\n relatedTarget: toggles[i]\n }\n\n if (event && event.type === 'click') {\n relatedTarget.clickEvent = event\n }\n\n if (!context) {\n continue\n }\n\n const dropdownMenu = context._menu\n if (!$(parent).hasClass(ClassName.SHOW)) {\n continue\n }\n\n if (event && (event.type === 'click' &&\n /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) &&\n $.contains(parent, event.target)) {\n continue\n }\n\n const hideEvent = $.Event(Event.HIDE, relatedTarget)\n $(parent).trigger(hideEvent)\n if (hideEvent.isDefaultPrevented()) {\n continue\n }\n\n // If this is a touch-enabled device we remove the extra\n // empty mouseover listeners we added for iOS support\n if ('ontouchstart' in document.documentElement) {\n $(document.body).children().off('mouseover', null, $.noop)\n }\n\n toggles[i].setAttribute('aria-expanded', 'false')\n\n $(dropdownMenu).removeClass(ClassName.SHOW)\n $(parent)\n .removeClass(ClassName.SHOW)\n .trigger($.Event(Event.HIDDEN, relatedTarget))\n }\n }\n\n static _getParentFromElement(element) {\n let parent\n const selector = Util.getSelectorFromElement(element)\n\n if (selector) {\n parent = document.querySelector(selector)\n }\n\n return parent || element.parentNode\n }\n\n // eslint-disable-next-line complexity\n static _dataApiKeydownHandler(event) {\n // If not input/textarea:\n // - And not a key in REGEXP_KEYDOWN => not a dropdown command\n // If input/textarea:\n // - If space key => not a dropdown command\n // - If key is other than escape\n // - If key is not up or down => not a dropdown command\n // - If trigger inside the menu => not a dropdown command\n if (/input|textarea/i.test(event.target.tagName)\n ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE &&\n (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE ||\n $(event.target).closest(Selector.MENU).length) : !REGEXP_KEYDOWN.test(event.which)) {\n return\n }\n\n event.preventDefault()\n event.stopPropagation()\n\n if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {\n return\n }\n\n const parent = Dropdown._getParentFromElement(this)\n const isActive = $(parent).hasClass(ClassName.SHOW)\n\n if (!isActive || isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) {\n if (event.which === ESCAPE_KEYCODE) {\n const toggle = parent.querySelector(Selector.DATA_TOGGLE)\n $(toggle).trigger('focus')\n }\n\n $(this).trigger('click')\n return\n }\n\n const items = [].slice.call(parent.querySelectorAll(Selector.VISIBLE_ITEMS))\n\n if (items.length === 0) {\n return\n }\n\n let index = items.indexOf(event.target)\n\n if (event.which === ARROW_UP_KEYCODE && index > 0) { // Up\n index--\n }\n\n if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) { // Down\n index++\n }\n\n if (index < 0) {\n index = 0\n }\n\n items[index].focus()\n }\n}\n\n/**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n$(document)\n .on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler)\n .on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler)\n .on(`${Event.CLICK_DATA_API} ${Event.KEYUP_DATA_API}`, Dropdown._clearMenus)\n .on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n event.preventDefault()\n event.stopPropagation()\n Dropdown._jQueryInterface.call($(this), 'toggle')\n })\n .on(Event.CLICK_DATA_API, Selector.FORM_CHILD, (e) => {\n e.stopPropagation()\n })\n\n/**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n$.fn[NAME] = Dropdown._jQueryInterface\n$.fn[NAME].Constructor = Dropdown\n$.fn[NAME].noConflict = () => {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Dropdown._jQueryInterface\n}\n\n\nexport default Dropdown\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.3.1): modal.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport $ from 'jquery'\nimport Util from './util'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'modal'\nconst VERSION = '4.3.1'\nconst DATA_KEY = 'bs.modal'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\nconst JQUERY_NO_CONFLICT = $.fn[NAME]\nconst ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key\n\nconst Default = {\n backdrop : true,\n keyboard : true,\n focus : true,\n show : true\n}\n\nconst DefaultType = {\n backdrop : '(boolean|string)',\n keyboard : 'boolean',\n focus : 'boolean',\n show : 'boolean'\n}\n\nconst Event = {\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n FOCUSIN : `focusin${EVENT_KEY}`,\n RESIZE : `resize${EVENT_KEY}`,\n CLICK_DISMISS : `click.dismiss${EVENT_KEY}`,\n KEYDOWN_DISMISS : `keydown.dismiss${EVENT_KEY}`,\n MOUSEUP_DISMISS : `mouseup.dismiss${EVENT_KEY}`,\n MOUSEDOWN_DISMISS : `mousedown.dismiss${EVENT_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n}\n\nconst ClassName = {\n SCROLLABLE : 'modal-dialog-scrollable',\n SCROLLBAR_MEASURER : 'modal-scrollbar-measure',\n BACKDROP : 'modal-backdrop',\n OPEN : 'modal-open',\n FADE : 'fade',\n SHOW : 'show'\n}\n\nconst Selector = {\n DIALOG : '.modal-dialog',\n MODAL_BODY : '.modal-body',\n DATA_TOGGLE : '[data-toggle=\"modal\"]',\n DATA_DISMISS : '[data-dismiss=\"modal\"]',\n FIXED_CONTENT : '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top',\n STICKY_CONTENT : '.sticky-top'\n}\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\nclass Modal {\n constructor(element, config) {\n this._config = this._getConfig(config)\n this._element = element\n this._dialog = element.querySelector(Selector.DIALOG)\n this._backdrop = null\n this._isShown = false\n this._isBodyOverflowing = false\n this._ignoreBackdropClick = false\n this._isTransitioning = false\n this._scrollbarWidth = 0\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n toggle(relatedTarget) {\n return this._isShown ? this.hide() : this.show(relatedTarget)\n }\n\n show(relatedTarget) {\n if (this._isShown || this._isTransitioning) {\n return\n }\n\n if ($(this._element).hasClass(ClassName.FADE)) {\n this._isTransitioning = true\n }\n\n const showEvent = $.Event(Event.SHOW, {\n relatedTarget\n })\n\n $(this._element).trigger(showEvent)\n\n if (this._isShown || showEvent.isDefaultPrevented()) {\n return\n }\n\n this._isShown = true\n\n this._checkScrollbar()\n this._setScrollbar()\n\n this._adjustDialog()\n\n this._setEscapeEvent()\n this._setResizeEvent()\n\n $(this._element).on(\n Event.CLICK_DISMISS,\n Selector.DATA_DISMISS,\n (event) => this.hide(event)\n )\n\n $(this._dialog).on(Event.MOUSEDOWN_DISMISS, () => {\n $(this._element).one(Event.MOUSEUP_DISMISS, (event) => {\n if ($(event.target).is(this._element)) {\n this._ignoreBackdropClick = true\n }\n })\n })\n\n this._showBackdrop(() => this._showElement(relatedTarget))\n }\n\n hide(event) {\n if (event) {\n event.preventDefault()\n }\n\n if (!this._isShown || this._isTransitioning) {\n return\n }\n\n const hideEvent = $.Event(Event.HIDE)\n\n $(this._element).trigger(hideEvent)\n\n if (!this._isShown || hideEvent.isDefaultPrevented()) {\n return\n }\n\n this._isShown = false\n const transition = $(this._element).hasClass(ClassName.FADE)\n\n if (transition) {\n this._isTransitioning = true\n }\n\n this._setEscapeEvent()\n this._setResizeEvent()\n\n $(document).off(Event.FOCUSIN)\n\n $(this._element).removeClass(ClassName.SHOW)\n\n $(this._element).off(Event.CLICK_DISMISS)\n $(this._dialog).off(Event.MOUSEDOWN_DISMISS)\n\n\n if (transition) {\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._element)\n .one(Util.TRANSITION_END, (event) => this._hideModal(event))\n .emulateTransitionEnd(transitionDuration)\n } else {\n this._hideModal()\n }\n }\n\n dispose() {\n [window, this._element, this._dialog]\n .forEach((htmlElement) => $(htmlElement).off(EVENT_KEY))\n\n /**\n * `document` has 2 events `Event.FOCUSIN` and `Event.CLICK_DATA_API`\n * Do not move `document` in `htmlElements` array\n * It will remove `Event.CLICK_DATA_API` event that should remain\n */\n $(document).off(Event.FOCUSIN)\n\n $.removeData(this._element, DATA_KEY)\n\n this._config = null\n this._element = null\n this._dialog = null\n this._backdrop = null\n this._isShown = null\n this._isBodyOverflowing = null\n this._ignoreBackdropClick = null\n this._isTransitioning = null\n this._scrollbarWidth = null\n }\n\n handleUpdate() {\n this._adjustDialog()\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...config\n }\n Util.typeCheckConfig(NAME, config, DefaultType)\n return config\n }\n\n _showElement(relatedTarget) {\n const transition = $(this._element).hasClass(ClassName.FADE)\n\n if (!this._element.parentNode ||\n this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {\n // Don't move modal's DOM position\n document.body.appendChild(this._element)\n }\n\n this._element.style.display = 'block'\n this._element.removeAttribute('aria-hidden')\n this._element.setAttribute('aria-modal', true)\n\n if ($(this._dialog).hasClass(ClassName.SCROLLABLE)) {\n this._dialog.querySelector(Selector.MODAL_BODY).scrollTop = 0\n } else {\n this._element.scrollTop = 0\n }\n\n if (transition) {\n Util.reflow(this._element)\n }\n\n $(this._element).addClass(ClassName.SHOW)\n\n if (this._config.focus) {\n this._enforceFocus()\n }\n\n const shownEvent = $.Event(Event.SHOWN, {\n relatedTarget\n })\n\n const transitionComplete = () => {\n if (this._config.focus) {\n this._element.focus()\n }\n this._isTransitioning = false\n $(this._element).trigger(shownEvent)\n }\n\n if (transition) {\n const transitionDuration = Util.getTransitionDurationFromElement(this._dialog)\n\n $(this._dialog)\n .one(Util.TRANSITION_END, transitionComplete)\n .emulateTransitionEnd(transitionDuration)\n } else {\n transitionComplete()\n }\n }\n\n _enforceFocus() {\n $(document)\n .off(Event.FOCUSIN) // Guard against infinite focus loop\n .on(Event.FOCUSIN, (event) => {\n if (document !== event.target &&\n this._element !== event.target &&\n $(this._element).has(event.target).length === 0) {\n this._element.focus()\n }\n })\n }\n\n _setEscapeEvent() {\n if (this._isShown && this._config.keyboard) {\n $(this._element).on(Event.KEYDOWN_DISMISS, (event) => {\n if (event.which === ESCAPE_KEYCODE) {\n event.preventDefault()\n this.hide()\n }\n })\n } else if (!this._isShown) {\n $(this._element).off(Event.KEYDOWN_DISMISS)\n }\n }\n\n _setResizeEvent() {\n if (this._isShown) {\n $(window).on(Event.RESIZE, (event) => this.handleUpdate(event))\n } else {\n $(window).off(Event.RESIZE)\n }\n }\n\n _hideModal() {\n this._element.style.display = 'none'\n this._element.setAttribute('aria-hidden', true)\n this._element.removeAttribute('aria-modal')\n this._isTransitioning = false\n this._showBackdrop(() => {\n $(document.body).removeClass(ClassName.OPEN)\n this._resetAdjustments()\n this._resetScrollbar()\n $(this._element).trigger(Event.HIDDEN)\n })\n }\n\n _removeBackdrop() {\n if (this._backdrop) {\n $(this._backdrop).remove()\n this._backdrop = null\n }\n }\n\n _showBackdrop(callback) {\n const animate = $(this._element).hasClass(ClassName.FADE)\n ? ClassName.FADE : ''\n\n if (this._isShown && this._config.backdrop) {\n this._backdrop = document.createElement('div')\n this._backdrop.className = ClassName.BACKDROP\n\n if (animate) {\n this._backdrop.classList.add(animate)\n }\n\n $(this._backdrop).appendTo(document.body)\n\n $(this._element).on(Event.CLICK_DISMISS, (event) => {\n if (this._ignoreBackdropClick) {\n this._ignoreBackdropClick = false\n return\n }\n if (event.target !== event.currentTarget) {\n return\n }\n if (this._config.backdrop === 'static') {\n this._element.focus()\n } else {\n this.hide()\n }\n })\n\n if (animate) {\n Util.reflow(this._backdrop)\n }\n\n $(this._backdrop).addClass(ClassName.SHOW)\n\n if (!callback) {\n return\n }\n\n if (!animate) {\n callback()\n return\n }\n\n const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop)\n\n $(this._backdrop)\n .one(Util.TRANSITION_END, callback)\n .emulateTransitionEnd(backdropTransitionDuration)\n } else if (!this._isShown && this._backdrop) {\n $(this._backdrop).removeClass(ClassName.SHOW)\n\n const callbackRemove = () => {\n this._removeBackdrop()\n if (callback) {\n callback()\n }\n }\n\n if ($(this._element).hasClass(ClassName.FADE)) {\n const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop)\n\n $(this._backdrop)\n .one(Util.TRANSITION_END, callbackRemove)\n .emulateTransitionEnd(backdropTransitionDuration)\n } else {\n callbackRemove()\n }\n } else if (callback) {\n callback()\n }\n }\n\n // ----------------------------------------------------------------------\n // the following methods are used to handle overflowing modals\n // todo (fat): these should probably be refactored out of modal.js\n // ----------------------------------------------------------------------\n\n _adjustDialog() {\n const isModalOverflowing =\n this._element.scrollHeight > document.documentElement.clientHeight\n\n if (!this._isBodyOverflowing && isModalOverflowing) {\n this._element.style.paddingLeft = `${this._scrollbarWidth}px`\n }\n\n if (this._isBodyOverflowing && !isModalOverflowing) {\n this._element.style.paddingRight = `${this._scrollbarWidth}px`\n }\n }\n\n _resetAdjustments() {\n this._element.style.paddingLeft = ''\n this._element.style.paddingRight = ''\n }\n\n _checkScrollbar() {\n const rect = document.body.getBoundingClientRect()\n this._isBodyOverflowing = rect.left + rect.right < window.innerWidth\n this._scrollbarWidth = this._getScrollbarWidth()\n }\n\n _setScrollbar() {\n if (this._isBodyOverflowing) {\n // Note: DOMNode.style.paddingRight returns the actual value or '' if not set\n // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set\n const fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT))\n const stickyContent = [].slice.call(document.querySelectorAll(Selector.STICKY_CONTENT))\n\n // Adjust fixed content padding\n $(fixedContent).each((index, element) => {\n const actualPadding = element.style.paddingRight\n const calculatedPadding = $(element).css('padding-right')\n $(element)\n .data('padding-right', actualPadding)\n .css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`)\n })\n\n // Adjust sticky content margin\n $(stickyContent).each((index, element) => {\n const actualMargin = element.style.marginRight\n const calculatedMargin = $(element).css('margin-right')\n $(element)\n .data('margin-right', actualMargin)\n .css('margin-right', `${parseFloat(calculatedMargin) - this._scrollbarWidth}px`)\n })\n\n // Adjust body padding\n const actualPadding = document.body.style.paddingRight\n const calculatedPadding = $(document.body).css('padding-right')\n $(document.body)\n .data('padding-right', actualPadding)\n .css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`)\n }\n\n $(document.body).addClass(ClassName.OPEN)\n }\n\n _resetScrollbar() {\n // Restore fixed content padding\n const fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT))\n $(fixedContent).each((index, element) => {\n const padding = $(element).data('padding-right')\n $(element).removeData('padding-right')\n element.style.paddingRight = padding ? padding : ''\n })\n\n // Restore sticky content\n const elements = [].slice.call(document.querySelectorAll(`${Selector.STICKY_CONTENT}`))\n $(elements).each((index, element) => {\n const margin = $(element).data('margin-right')\n if (typeof margin !== 'undefined') {\n $(element).css('margin-right', margin).removeData('margin-right')\n }\n })\n\n // Restore body padding\n const padding = $(document.body).data('padding-right')\n $(document.body).removeData('padding-right')\n document.body.style.paddingRight = padding ? padding : ''\n }\n\n _getScrollbarWidth() { // thx d.walsh\n const scrollDiv = document.createElement('div')\n scrollDiv.className = ClassName.SCROLLBAR_MEASURER\n document.body.appendChild(scrollDiv)\n const scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth\n document.body.removeChild(scrollDiv)\n return scrollbarWidth\n }\n\n // Static\n\n static _jQueryInterface(config, relatedTarget) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = {\n ...Default,\n ...$(this).data(),\n ...typeof config === 'object' && config ? config : {}\n }\n\n if (!data) {\n data = new Modal(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config](relatedTarget)\n } else if (_config.show) {\n data.show(relatedTarget)\n }\n })\n }\n}\n\n/**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n$(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n let target\n const selector = Util.getSelectorFromElement(this)\n\n if (selector) {\n target = document.querySelector(selector)\n }\n\n const config = $(target).data(DATA_KEY)\n ? 'toggle' : {\n ...$(target).data(),\n ...$(this).data()\n }\n\n if (this.tagName === 'A' || this.tagName === 'AREA') {\n event.preventDefault()\n }\n\n const $target = $(target).one(Event.SHOW, (showEvent) => {\n if (showEvent.isDefaultPrevented()) {\n // Only register focus restorer if modal will actually get shown\n return\n }\n\n $target.one(Event.HIDDEN, () => {\n if ($(this).is(':visible')) {\n this.focus()\n }\n })\n })\n\n Modal._jQueryInterface.call($(target), config, this)\n})\n\n/**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n$.fn[NAME] = Modal._jQueryInterface\n$.fn[NAME].Constructor = Modal\n$.fn[NAME].noConflict = () => {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Modal._jQueryInterface\n}\n\nexport default Modal\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.3.1): tools/sanitizer.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst uriAttrs = [\n 'background',\n 'cite',\n 'href',\n 'itemtype',\n 'longdesc',\n 'poster',\n 'src',\n 'xlink:href'\n]\n\nconst ARIA_ATTRIBUTE_PATTERN = /^aria-[\\w-]*$/i\n\nexport const DefaultWhitelist = {\n // Global attributes allowed on any supplied element below.\n '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],\n a: ['target', 'href', 'title', 'rel'],\n area: [],\n b: [],\n br: [],\n col: [],\n code: [],\n div: [],\n em: [],\n hr: [],\n h1: [],\n h2: [],\n h3: [],\n h4: [],\n h5: [],\n h6: [],\n i: [],\n img: ['src', 'alt', 'title', 'width', 'height'],\n li: [],\n ol: [],\n p: [],\n pre: [],\n s: [],\n small: [],\n span: [],\n sub: [],\n sup: [],\n strong: [],\n u: [],\n ul: []\n}\n\n/**\n * A pattern that recognizes a commonly useful subset of URLs that are safe.\n *\n * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts\n */\nconst SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi\n\n/**\n * A pattern that matches safe data URLs. Only matches image, video and audio types.\n *\n * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts\n */\nconst DATA_URL_PATTERN = /^data:(?:image\\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\\/(?:mpeg|mp4|ogg|webm)|audio\\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i\n\nfunction allowedAttribute(attr, allowedAttributeList) {\n const attrName = attr.nodeName.toLowerCase()\n\n if (allowedAttributeList.indexOf(attrName) !== -1) {\n if (uriAttrs.indexOf(attrName) !== -1) {\n return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN))\n }\n\n return true\n }\n\n const regExp = allowedAttributeList.filter((attrRegex) => attrRegex instanceof RegExp)\n\n // Check if a regular expression validates the attribute.\n for (let i = 0, l = regExp.length; i < l; i++) {\n if (attrName.match(regExp[i])) {\n return true\n }\n }\n\n return false\n}\n\nexport function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {\n if (unsafeHtml.length === 0) {\n return unsafeHtml\n }\n\n if (sanitizeFn && typeof sanitizeFn === 'function') {\n return sanitizeFn(unsafeHtml)\n }\n\n const domParser = new window.DOMParser()\n const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html')\n const whitelistKeys = Object.keys(whiteList)\n const elements = [].slice.call(createdDocument.body.querySelectorAll('*'))\n\n for (let i = 0, len = elements.length; i < len; i++) {\n const el = elements[i]\n const elName = el.nodeName.toLowerCase()\n\n if (whitelistKeys.indexOf(el.nodeName.toLowerCase()) === -1) {\n el.parentNode.removeChild(el)\n\n continue\n }\n\n const attributeList = [].slice.call(el.attributes)\n const whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || [])\n\n attributeList.forEach((attr) => {\n if (!allowedAttribute(attr, whitelistedAttributes)) {\n el.removeAttribute(attr.nodeName)\n }\n })\n }\n\n return createdDocument.body.innerHTML\n}\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.3.1): tooltip.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport {\n DefaultWhitelist,\n sanitizeHtml\n} from './tools/sanitizer'\nimport $ from 'jquery'\nimport Popper from 'popper.js'\nimport Util from './util'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'tooltip'\nconst VERSION = '4.3.1'\nconst DATA_KEY = 'bs.tooltip'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst JQUERY_NO_CONFLICT = $.fn[NAME]\nconst CLASS_PREFIX = 'bs-tooltip'\nconst BSCLS_PREFIX_REGEX = new RegExp(`(^|\\\\s)${CLASS_PREFIX}\\\\S+`, 'g')\nconst DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn']\n\nconst DefaultType = {\n animation : 'boolean',\n template : 'string',\n title : '(string|element|function)',\n trigger : 'string',\n delay : '(number|object)',\n html : 'boolean',\n selector : '(string|boolean)',\n placement : '(string|function)',\n offset : '(number|string|function)',\n container : '(string|element|boolean)',\n fallbackPlacement : '(string|array)',\n boundary : '(string|element)',\n sanitize : 'boolean',\n sanitizeFn : '(null|function)',\n whiteList : 'object'\n}\n\nconst AttachmentMap = {\n AUTO : 'auto',\n TOP : 'top',\n RIGHT : 'right',\n BOTTOM : 'bottom',\n LEFT : 'left'\n}\n\nconst Default = {\n animation : true,\n template : '
' +\n '
' +\n '
',\n trigger : 'hover focus',\n title : '',\n delay : 0,\n html : false,\n selector : false,\n placement : 'top',\n offset : 0,\n container : false,\n fallbackPlacement : 'flip',\n boundary : 'scrollParent',\n sanitize : true,\n sanitizeFn : null,\n whiteList : DefaultWhitelist\n}\n\nconst HoverState = {\n SHOW : 'show',\n OUT : 'out'\n}\n\nconst Event = {\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n INSERTED : `inserted${EVENT_KEY}`,\n CLICK : `click${EVENT_KEY}`,\n FOCUSIN : `focusin${EVENT_KEY}`,\n FOCUSOUT : `focusout${EVENT_KEY}`,\n MOUSEENTER : `mouseenter${EVENT_KEY}`,\n MOUSELEAVE : `mouseleave${EVENT_KEY}`\n}\n\nconst ClassName = {\n FADE : 'fade',\n SHOW : 'show'\n}\n\nconst Selector = {\n TOOLTIP : '.tooltip',\n TOOLTIP_INNER : '.tooltip-inner',\n ARROW : '.arrow'\n}\n\nconst Trigger = {\n HOVER : 'hover',\n FOCUS : 'focus',\n CLICK : 'click',\n MANUAL : 'manual'\n}\n\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\nclass Tooltip {\n constructor(element, config) {\n /**\n * Check for Popper dependency\n * Popper - https://popper.js.org\n */\n if (typeof Popper === 'undefined') {\n throw new TypeError('Bootstrap\\'s tooltips require Popper.js (https://popper.js.org/)')\n }\n\n // private\n this._isEnabled = true\n this._timeout = 0\n this._hoverState = ''\n this._activeTrigger = {}\n this._popper = null\n\n // Protected\n this.element = element\n this.config = this._getConfig(config)\n this.tip = null\n\n this._setListeners()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n static get NAME() {\n return NAME\n }\n\n static get DATA_KEY() {\n return DATA_KEY\n }\n\n static get Event() {\n return Event\n }\n\n static get EVENT_KEY() {\n return EVENT_KEY\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n // Public\n\n enable() {\n this._isEnabled = true\n }\n\n disable() {\n this._isEnabled = false\n }\n\n toggleEnabled() {\n this._isEnabled = !this._isEnabled\n }\n\n toggle(event) {\n if (!this._isEnabled) {\n return\n }\n\n if (event) {\n const dataKey = this.constructor.DATA_KEY\n let context = $(event.currentTarget).data(dataKey)\n\n if (!context) {\n context = new this.constructor(\n event.currentTarget,\n this._getDelegateConfig()\n )\n $(event.currentTarget).data(dataKey, context)\n }\n\n context._activeTrigger.click = !context._activeTrigger.click\n\n if (context._isWithActiveTrigger()) {\n context._enter(null, context)\n } else {\n context._leave(null, context)\n }\n } else {\n if ($(this.getTipElement()).hasClass(ClassName.SHOW)) {\n this._leave(null, this)\n return\n }\n\n this._enter(null, this)\n }\n }\n\n dispose() {\n clearTimeout(this._timeout)\n\n $.removeData(this.element, this.constructor.DATA_KEY)\n\n $(this.element).off(this.constructor.EVENT_KEY)\n $(this.element).closest('.modal').off('hide.bs.modal')\n\n if (this.tip) {\n $(this.tip).remove()\n }\n\n this._isEnabled = null\n this._timeout = null\n this._hoverState = null\n this._activeTrigger = null\n if (this._popper !== null) {\n this._popper.destroy()\n }\n\n this._popper = null\n this.element = null\n this.config = null\n this.tip = null\n }\n\n show() {\n if ($(this.element).css('display') === 'none') {\n throw new Error('Please use show on visible elements')\n }\n\n const showEvent = $.Event(this.constructor.Event.SHOW)\n if (this.isWithContent() && this._isEnabled) {\n $(this.element).trigger(showEvent)\n\n const shadowRoot = Util.findShadowRoot(this.element)\n const isInTheDom = $.contains(\n shadowRoot !== null ? shadowRoot : this.element.ownerDocument.documentElement,\n this.element\n )\n\n if (showEvent.isDefaultPrevented() || !isInTheDom) {\n return\n }\n\n const tip = this.getTipElement()\n const tipId = Util.getUID(this.constructor.NAME)\n\n tip.setAttribute('id', tipId)\n this.element.setAttribute('aria-describedby', tipId)\n\n this.setContent()\n\n if (this.config.animation) {\n $(tip).addClass(ClassName.FADE)\n }\n\n const placement = typeof this.config.placement === 'function'\n ? this.config.placement.call(this, tip, this.element)\n : this.config.placement\n\n const attachment = this._getAttachment(placement)\n this.addAttachmentClass(attachment)\n\n const container = this._getContainer()\n $(tip).data(this.constructor.DATA_KEY, this)\n\n if (!$.contains(this.element.ownerDocument.documentElement, this.tip)) {\n $(tip).appendTo(container)\n }\n\n $(this.element).trigger(this.constructor.Event.INSERTED)\n\n this._popper = new Popper(this.element, tip, {\n placement: attachment,\n modifiers: {\n offset: this._getOffset(),\n flip: {\n behavior: this.config.fallbackPlacement\n },\n arrow: {\n element: Selector.ARROW\n },\n preventOverflow: {\n boundariesElement: this.config.boundary\n }\n },\n onCreate: (data) => {\n if (data.originalPlacement !== data.placement) {\n this._handlePopperPlacementChange(data)\n }\n },\n onUpdate: (data) => this._handlePopperPlacementChange(data)\n })\n\n $(tip).addClass(ClassName.SHOW)\n\n // If this is a touch-enabled device we add extra\n // empty mouseover listeners to the body's immediate children;\n // only needed because of broken event delegation on iOS\n // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n if ('ontouchstart' in document.documentElement) {\n $(document.body).children().on('mouseover', null, $.noop)\n }\n\n const complete = () => {\n if (this.config.animation) {\n this._fixTransition()\n }\n const prevHoverState = this._hoverState\n this._hoverState = null\n\n $(this.element).trigger(this.constructor.Event.SHOWN)\n\n if (prevHoverState === HoverState.OUT) {\n this._leave(null, this)\n }\n }\n\n if ($(this.tip).hasClass(ClassName.FADE)) {\n const transitionDuration = Util.getTransitionDurationFromElement(this.tip)\n\n $(this.tip)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n } else {\n complete()\n }\n }\n }\n\n hide(callback) {\n const tip = this.getTipElement()\n const hideEvent = $.Event(this.constructor.Event.HIDE)\n const complete = () => {\n if (this._hoverState !== HoverState.SHOW && tip.parentNode) {\n tip.parentNode.removeChild(tip)\n }\n\n this._cleanTipClass()\n this.element.removeAttribute('aria-describedby')\n $(this.element).trigger(this.constructor.Event.HIDDEN)\n if (this._popper !== null) {\n this._popper.destroy()\n }\n\n if (callback) {\n callback()\n }\n }\n\n $(this.element).trigger(hideEvent)\n\n if (hideEvent.isDefaultPrevented()) {\n return\n }\n\n $(tip).removeClass(ClassName.SHOW)\n\n // If this is a touch-enabled device we remove the extra\n // empty mouseover listeners we added for iOS support\n if ('ontouchstart' in document.documentElement) {\n $(document.body).children().off('mouseover', null, $.noop)\n }\n\n this._activeTrigger[Trigger.CLICK] = false\n this._activeTrigger[Trigger.FOCUS] = false\n this._activeTrigger[Trigger.HOVER] = false\n\n if ($(this.tip).hasClass(ClassName.FADE)) {\n const transitionDuration = Util.getTransitionDurationFromElement(tip)\n\n $(tip)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n } else {\n complete()\n }\n\n this._hoverState = ''\n }\n\n update() {\n if (this._popper !== null) {\n this._popper.scheduleUpdate()\n }\n }\n\n // Protected\n\n isWithContent() {\n return Boolean(this.getTitle())\n }\n\n addAttachmentClass(attachment) {\n $(this.getTipElement()).addClass(`${CLASS_PREFIX}-${attachment}`)\n }\n\n getTipElement() {\n this.tip = this.tip || $(this.config.template)[0]\n return this.tip\n }\n\n setContent() {\n const tip = this.getTipElement()\n this.setElementContent($(tip.querySelectorAll(Selector.TOOLTIP_INNER)), this.getTitle())\n $(tip).removeClass(`${ClassName.FADE} ${ClassName.SHOW}`)\n }\n\n setElementContent($element, content) {\n if (typeof content === 'object' && (content.nodeType || content.jquery)) {\n // Content is a DOM node or a jQuery\n if (this.config.html) {\n if (!$(content).parent().is($element)) {\n $element.empty().append(content)\n }\n } else {\n $element.text($(content).text())\n }\n\n return\n }\n\n if (this.config.html) {\n if (this.config.sanitize) {\n content = sanitizeHtml(content, this.config.whiteList, this.config.sanitizeFn)\n }\n\n $element.html(content)\n } else {\n $element.text(content)\n }\n }\n\n getTitle() {\n let title = this.element.getAttribute('data-original-title')\n\n if (!title) {\n title = typeof this.config.title === 'function'\n ? this.config.title.call(this.element)\n : this.config.title\n }\n\n return title\n }\n\n // Private\n\n _getOffset() {\n const offset = {}\n\n if (typeof this.config.offset === 'function') {\n offset.fn = (data) => {\n data.offsets = {\n ...data.offsets,\n ...this.config.offset(data.offsets, this.element) || {}\n }\n\n return data\n }\n } else {\n offset.offset = this.config.offset\n }\n\n return offset\n }\n\n _getContainer() {\n if (this.config.container === false) {\n return document.body\n }\n\n if (Util.isElement(this.config.container)) {\n return $(this.config.container)\n }\n\n return $(document).find(this.config.container)\n }\n\n _getAttachment(placement) {\n return AttachmentMap[placement.toUpperCase()]\n }\n\n _setListeners() {\n const triggers = this.config.trigger.split(' ')\n\n triggers.forEach((trigger) => {\n if (trigger === 'click') {\n $(this.element).on(\n this.constructor.Event.CLICK,\n this.config.selector,\n (event) => this.toggle(event)\n )\n } else if (trigger !== Trigger.MANUAL) {\n const eventIn = trigger === Trigger.HOVER\n ? this.constructor.Event.MOUSEENTER\n : this.constructor.Event.FOCUSIN\n const eventOut = trigger === Trigger.HOVER\n ? this.constructor.Event.MOUSELEAVE\n : this.constructor.Event.FOCUSOUT\n\n $(this.element)\n .on(\n eventIn,\n this.config.selector,\n (event) => this._enter(event)\n )\n .on(\n eventOut,\n this.config.selector,\n (event) => this._leave(event)\n )\n }\n })\n\n $(this.element).closest('.modal').on(\n 'hide.bs.modal',\n () => {\n if (this.element) {\n this.hide()\n }\n }\n )\n\n if (this.config.selector) {\n this.config = {\n ...this.config,\n trigger: 'manual',\n selector: ''\n }\n } else {\n this._fixTitle()\n }\n }\n\n _fixTitle() {\n const titleType = typeof this.element.getAttribute('data-original-title')\n\n if (this.element.getAttribute('title') || titleType !== 'string') {\n this.element.setAttribute(\n 'data-original-title',\n this.element.getAttribute('title') || ''\n )\n\n this.element.setAttribute('title', '')\n }\n }\n\n _enter(event, context) {\n const dataKey = this.constructor.DATA_KEY\n context = context || $(event.currentTarget).data(dataKey)\n\n if (!context) {\n context = new this.constructor(\n event.currentTarget,\n this._getDelegateConfig()\n )\n $(event.currentTarget).data(dataKey, context)\n }\n\n if (event) {\n context._activeTrigger[\n event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER\n ] = true\n }\n\n if ($(context.getTipElement()).hasClass(ClassName.SHOW) || context._hoverState === HoverState.SHOW) {\n context._hoverState = HoverState.SHOW\n return\n }\n\n clearTimeout(context._timeout)\n\n context._hoverState = HoverState.SHOW\n\n if (!context.config.delay || !context.config.delay.show) {\n context.show()\n return\n }\n\n context._timeout = setTimeout(() => {\n if (context._hoverState === HoverState.SHOW) {\n context.show()\n }\n }, context.config.delay.show)\n }\n\n _leave(event, context) {\n const dataKey = this.constructor.DATA_KEY\n context = context || $(event.currentTarget).data(dataKey)\n\n if (!context) {\n context = new this.constructor(\n event.currentTarget,\n this._getDelegateConfig()\n )\n $(event.currentTarget).data(dataKey, context)\n }\n\n if (event) {\n context._activeTrigger[\n event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER\n ] = false\n }\n\n if (context._isWithActiveTrigger()) {\n return\n }\n\n clearTimeout(context._timeout)\n\n context._hoverState = HoverState.OUT\n\n if (!context.config.delay || !context.config.delay.hide) {\n context.hide()\n return\n }\n\n context._timeout = setTimeout(() => {\n if (context._hoverState === HoverState.OUT) {\n context.hide()\n }\n }, context.config.delay.hide)\n }\n\n _isWithActiveTrigger() {\n for (const trigger in this._activeTrigger) {\n if (this._activeTrigger[trigger]) {\n return true\n }\n }\n\n return false\n }\n\n _getConfig(config) {\n const dataAttributes = $(this.element).data()\n\n Object.keys(dataAttributes)\n .forEach((dataAttr) => {\n if (DISALLOWED_ATTRIBUTES.indexOf(dataAttr) !== -1) {\n delete dataAttributes[dataAttr]\n }\n })\n\n config = {\n ...this.constructor.Default,\n ...dataAttributes,\n ...typeof config === 'object' && config ? config : {}\n }\n\n if (typeof config.delay === 'number') {\n config.delay = {\n show: config.delay,\n hide: config.delay\n }\n }\n\n if (typeof config.title === 'number') {\n config.title = config.title.toString()\n }\n\n if (typeof config.content === 'number') {\n config.content = config.content.toString()\n }\n\n Util.typeCheckConfig(\n NAME,\n config,\n this.constructor.DefaultType\n )\n\n if (config.sanitize) {\n config.template = sanitizeHtml(config.template, config.whiteList, config.sanitizeFn)\n }\n\n return config\n }\n\n _getDelegateConfig() {\n const config = {}\n\n if (this.config) {\n for (const key in this.config) {\n if (this.constructor.Default[key] !== this.config[key]) {\n config[key] = this.config[key]\n }\n }\n }\n\n return config\n }\n\n _cleanTipClass() {\n const $tip = $(this.getTipElement())\n const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX)\n if (tabClass !== null && tabClass.length) {\n $tip.removeClass(tabClass.join(''))\n }\n }\n\n _handlePopperPlacementChange(popperData) {\n const popperInstance = popperData.instance\n this.tip = popperInstance.popper\n this._cleanTipClass()\n this.addAttachmentClass(this._getAttachment(popperData.placement))\n }\n\n _fixTransition() {\n const tip = this.getTipElement()\n const initConfigAnimation = this.config.animation\n\n if (tip.getAttribute('x-placement') !== null) {\n return\n }\n\n $(tip).removeClass(ClassName.FADE)\n this.config.animation = false\n this.hide()\n this.show()\n this.config.animation = initConfigAnimation\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = typeof config === 'object' && config\n\n if (!data && /dispose|hide/.test(config)) {\n return\n }\n\n if (!data) {\n data = new Tooltip(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config]()\n }\n })\n }\n}\n\n/**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n$.fn[NAME] = Tooltip._jQueryInterface\n$.fn[NAME].Constructor = Tooltip\n$.fn[NAME].noConflict = () => {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Tooltip._jQueryInterface\n}\n\nexport default Tooltip\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.3.1): popover.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport $ from 'jquery'\nimport Tooltip from './tooltip'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'popover'\nconst VERSION = '4.3.1'\nconst DATA_KEY = 'bs.popover'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst JQUERY_NO_CONFLICT = $.fn[NAME]\nconst CLASS_PREFIX = 'bs-popover'\nconst BSCLS_PREFIX_REGEX = new RegExp(`(^|\\\\s)${CLASS_PREFIX}\\\\S+`, 'g')\n\nconst Default = {\n ...Tooltip.Default,\n placement : 'right',\n trigger : 'click',\n content : '',\n template : '
' +\n '
' +\n '

' +\n '
'\n}\n\nconst DefaultType = {\n ...Tooltip.DefaultType,\n content : '(string|element|function)'\n}\n\nconst ClassName = {\n FADE : 'fade',\n SHOW : 'show'\n}\n\nconst Selector = {\n TITLE : '.popover-header',\n CONTENT : '.popover-body'\n}\n\nconst Event = {\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n INSERTED : `inserted${EVENT_KEY}`,\n CLICK : `click${EVENT_KEY}`,\n FOCUSIN : `focusin${EVENT_KEY}`,\n FOCUSOUT : `focusout${EVENT_KEY}`,\n MOUSEENTER : `mouseenter${EVENT_KEY}`,\n MOUSELEAVE : `mouseleave${EVENT_KEY}`\n}\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\nclass Popover extends Tooltip {\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n static get NAME() {\n return NAME\n }\n\n static get DATA_KEY() {\n return DATA_KEY\n }\n\n static get Event() {\n return Event\n }\n\n static get EVENT_KEY() {\n return EVENT_KEY\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n // Overrides\n\n isWithContent() {\n return this.getTitle() || this._getContent()\n }\n\n addAttachmentClass(attachment) {\n $(this.getTipElement()).addClass(`${CLASS_PREFIX}-${attachment}`)\n }\n\n getTipElement() {\n this.tip = this.tip || $(this.config.template)[0]\n return this.tip\n }\n\n setContent() {\n const $tip = $(this.getTipElement())\n\n // We use append for html objects to maintain js events\n this.setElementContent($tip.find(Selector.TITLE), this.getTitle())\n let content = this._getContent()\n if (typeof content === 'function') {\n content = content.call(this.element)\n }\n this.setElementContent($tip.find(Selector.CONTENT), content)\n\n $tip.removeClass(`${ClassName.FADE} ${ClassName.SHOW}`)\n }\n\n // Private\n\n _getContent() {\n return this.element.getAttribute('data-content') ||\n this.config.content\n }\n\n _cleanTipClass() {\n const $tip = $(this.getTipElement())\n const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX)\n if (tabClass !== null && tabClass.length > 0) {\n $tip.removeClass(tabClass.join(''))\n }\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = typeof config === 'object' ? config : null\n\n if (!data && /dispose|hide/.test(config)) {\n return\n }\n\n if (!data) {\n data = new Popover(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config]()\n }\n })\n }\n}\n\n/**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n$.fn[NAME] = Popover._jQueryInterface\n$.fn[NAME].Constructor = Popover\n$.fn[NAME].noConflict = () => {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Popover._jQueryInterface\n}\n\nexport default Popover\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.3.1): scrollspy.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport $ from 'jquery'\nimport Util from './util'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'scrollspy'\nconst VERSION = '4.3.1'\nconst DATA_KEY = 'bs.scrollspy'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\nconst JQUERY_NO_CONFLICT = $.fn[NAME]\n\nconst Default = {\n offset : 10,\n method : 'auto',\n target : ''\n}\n\nconst DefaultType = {\n offset : 'number',\n method : 'string',\n target : '(string|element)'\n}\n\nconst Event = {\n ACTIVATE : `activate${EVENT_KEY}`,\n SCROLL : `scroll${EVENT_KEY}`,\n LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}`\n}\n\nconst ClassName = {\n DROPDOWN_ITEM : 'dropdown-item',\n DROPDOWN_MENU : 'dropdown-menu',\n ACTIVE : 'active'\n}\n\nconst Selector = {\n DATA_SPY : '[data-spy=\"scroll\"]',\n ACTIVE : '.active',\n NAV_LIST_GROUP : '.nav, .list-group',\n NAV_LINKS : '.nav-link',\n NAV_ITEMS : '.nav-item',\n LIST_ITEMS : '.list-group-item',\n DROPDOWN : '.dropdown',\n DROPDOWN_ITEMS : '.dropdown-item',\n DROPDOWN_TOGGLE : '.dropdown-toggle'\n}\n\nconst OffsetMethod = {\n OFFSET : 'offset',\n POSITION : 'position'\n}\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\nclass ScrollSpy {\n constructor(element, config) {\n this._element = element\n this._scrollElement = element.tagName === 'BODY' ? window : element\n this._config = this._getConfig(config)\n this._selector = `${this._config.target} ${Selector.NAV_LINKS},` +\n `${this._config.target} ${Selector.LIST_ITEMS},` +\n `${this._config.target} ${Selector.DROPDOWN_ITEMS}`\n this._offsets = []\n this._targets = []\n this._activeTarget = null\n this._scrollHeight = 0\n\n $(this._scrollElement).on(Event.SCROLL, (event) => this._process(event))\n\n this.refresh()\n this._process()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n refresh() {\n const autoMethod = this._scrollElement === this._scrollElement.window\n ? OffsetMethod.OFFSET : OffsetMethod.POSITION\n\n const offsetMethod = this._config.method === 'auto'\n ? autoMethod : this._config.method\n\n const offsetBase = offsetMethod === OffsetMethod.POSITION\n ? this._getScrollTop() : 0\n\n this._offsets = []\n this._targets = []\n\n this._scrollHeight = this._getScrollHeight()\n\n const targets = [].slice.call(document.querySelectorAll(this._selector))\n\n targets\n .map((element) => {\n let target\n const targetSelector = Util.getSelectorFromElement(element)\n\n if (targetSelector) {\n target = document.querySelector(targetSelector)\n }\n\n if (target) {\n const targetBCR = target.getBoundingClientRect()\n if (targetBCR.width || targetBCR.height) {\n // TODO (fat): remove sketch reliance on jQuery position/offset\n return [\n $(target)[offsetMethod]().top + offsetBase,\n targetSelector\n ]\n }\n }\n return null\n })\n .filter((item) => item)\n .sort((a, b) => a[0] - b[0])\n .forEach((item) => {\n this._offsets.push(item[0])\n this._targets.push(item[1])\n })\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n $(this._scrollElement).off(EVENT_KEY)\n\n this._element = null\n this._scrollElement = null\n this._config = null\n this._selector = null\n this._offsets = null\n this._targets = null\n this._activeTarget = null\n this._scrollHeight = null\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...typeof config === 'object' && config ? config : {}\n }\n\n if (typeof config.target !== 'string') {\n let id = $(config.target).attr('id')\n if (!id) {\n id = Util.getUID(NAME)\n $(config.target).attr('id', id)\n }\n config.target = `#${id}`\n }\n\n Util.typeCheckConfig(NAME, config, DefaultType)\n\n return config\n }\n\n _getScrollTop() {\n return this._scrollElement === window\n ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop\n }\n\n _getScrollHeight() {\n return this._scrollElement.scrollHeight || Math.max(\n document.body.scrollHeight,\n document.documentElement.scrollHeight\n )\n }\n\n _getOffsetHeight() {\n return this._scrollElement === window\n ? window.innerHeight : this._scrollElement.getBoundingClientRect().height\n }\n\n _process() {\n const scrollTop = this._getScrollTop() + this._config.offset\n const scrollHeight = this._getScrollHeight()\n const maxScroll = this._config.offset +\n scrollHeight -\n this._getOffsetHeight()\n\n if (this._scrollHeight !== scrollHeight) {\n this.refresh()\n }\n\n if (scrollTop >= maxScroll) {\n const target = this._targets[this._targets.length - 1]\n\n if (this._activeTarget !== target) {\n this._activate(target)\n }\n return\n }\n\n if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {\n this._activeTarget = null\n this._clear()\n return\n }\n\n const offsetLength = this._offsets.length\n for (let i = offsetLength; i--;) {\n const isActiveTarget = this._activeTarget !== this._targets[i] &&\n scrollTop >= this._offsets[i] &&\n (typeof this._offsets[i + 1] === 'undefined' ||\n scrollTop < this._offsets[i + 1])\n\n if (isActiveTarget) {\n this._activate(this._targets[i])\n }\n }\n }\n\n _activate(target) {\n this._activeTarget = target\n\n this._clear()\n\n const queries = this._selector\n .split(',')\n .map((selector) => `${selector}[data-target=\"${target}\"],${selector}[href=\"${target}\"]`)\n\n const $link = $([].slice.call(document.querySelectorAll(queries.join(','))))\n\n if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {\n $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE)\n $link.addClass(ClassName.ACTIVE)\n } else {\n // Set triggered link as active\n $link.addClass(ClassName.ACTIVE)\n // Set triggered links parents as active\n // With both
    and