user5 před 2 roky
revize
cd78c445e9
100 změnil soubory, kde provedl 17092 přidání a 0 odebrání
  1. binární
      .DS_Store
  2. 11 0
      .hbuilderx/launch.json
  3. 0 0
      .idea/.gitignore
  4. 9 0
      .idea/jp-mobile.iml
  5. 9 0
      .idea/misc.xml
  6. 8 0
      .idea/modules.xml
  7. 134 0
      .idea/workspace.xml
  8. 251 0
      App.vue
  9. 144 0
      Readme.md
  10. binární
      api/.DS_Store
  11. 23 0
      api/auth/LoginService.js
  12. 34 0
      api/flowable/ActCategoryService.js
  13. 18 0
      api/flowable/AppModelsService.js
  14. 50 0
      api/flowable/ButtonService.js
  15. 35 0
      api/flowable/ConditionService.js
  16. 28 0
      api/flowable/FlowCopyService.js
  17. 34 0
      api/flowable/FormCategoryService.js
  18. 43 0
      api/flowable/FormDefinitionJsonService.js
  19. 42 0
      api/flowable/FormDefinitionService.js
  20. 52 0
      api/flowable/FormService.js
  21. 35 0
      api/flowable/ListenerService.js
  22. 28 0
      api/flowable/LoginService.js
  23. 57 0
      api/flowable/ModelService.js
  24. 43 0
      api/flowable/NodeSettingService.js
  25. 101 0
      api/flowable/ProcessService.js
  26. 43 0
      api/flowable/TaskDefExtensionService.js
  27. 116 0
      api/flowable/TaskService.js
  28. 36 0
      api/form/GenerateFormService.js
  29. 92 0
      api/form/MakeFormService.js
  30. 33 0
      api/mail/MailBoxService.js
  31. 35 0
      api/mail/MailComposeService.js
  32. 27 0
      api/mail/MailTrashService.js
  33. 42 0
      api/notify/NotifyService.js
  34. 34 0
      api/sys/AreaService.js
  35. 25 0
      api/sys/ConfigService.js
  36. 41 0
      api/sys/DataRuleService.js
  37. 80 0
      api/sys/DictService.js
  38. 15 0
      api/sys/FileService.js
  39. 34 0
      api/sys/LogService.js
  40. 35 0
      api/sys/MenuService.js
  41. 35 0
      api/sys/OfficeService.js
  42. 35 0
      api/sys/PostService.js
  43. 69 0
      api/sys/RoleService.js
  44. 66 0
      api/sys/UserService.js
  45. binární
      api/test/.DS_Store
  46. 35 0
      api/test/activiti/TestActivitiLeaveService.js
  47. 35 0
      api/test/mobile/TestMobileService.js
  48. 184 0
      colorui/animation.css
  49. 75 0
      colorui/components/cu-custom.vue
  50. 1226 0
      colorui/icon.css
  51. 4008 0
      colorui/main.css
  52. 128 0
      common/auth.js
  53. 14 0
      common/config.js
  54. 64 0
      common/dictUtils.js
  55. 11 0
      common/filter.js
  56. 167 0
      common/graceChecker.js
  57. 114 0
      common/helper.js
  58. 146 0
      common/request.js
  59. 88 0
      common/util.js
  60. 20 0
      components/Am-FontAwesome/css/_animated.scss
  61. 20 0
      components/Am-FontAwesome/css/_bordered-pulled.scss
  62. 21 0
      components/Am-FontAwesome/css/_core.scss
  63. 6 0
      components/Am-FontAwesome/css/_fixed-width.scss
  64. 1441 0
      components/Am-FontAwesome/css/_icons.scss
  65. 23 0
      components/Am-FontAwesome/css/_larger.scss
  66. 18 0
      components/Am-FontAwesome/css/_list.scss
  67. 56 0
      components/Am-FontAwesome/css/_mixins.scss
  68. 24 0
      components/Am-FontAwesome/css/_rotated-flipped.scss
  69. 5 0
      components/Am-FontAwesome/css/_screen-reader.scss
  70. 2066 0
      components/Am-FontAwesome/css/_shims.scss
  71. 31 0
      components/Am-FontAwesome/css/_stacked.scss
  72. 1458 0
      components/Am-FontAwesome/css/_variables.scss
  73. 17 0
      components/Am-FontAwesome/css/brands.scss
  74. 16 0
      components/Am-FontAwesome/css/fontawesome.scss
  75. 18 0
      components/Am-FontAwesome/css/regular.scss
  76. 19 0
      components/Am-FontAwesome/css/solid.scss
  77. 6 0
      components/Am-FontAwesome/css/v4-shims.scss
  78. 194 0
      components/Am-FontAwesome/index.vue
  79. 187 0
      components/generate-form/generate-form.vue
  80. 120 0
      components/jp-area-select/jp-area-select.vue
  81. 26 0
      components/jp-checkbox-group/jp-checkbox-group.vue
  82. 26 0
      components/jp-checkbox-group2/jp-checkbox-group2.vue
  83. 52 0
      components/jp-color-picker/README.md
  84. 320 0
      components/jp-color-picker/colorPicker.vue
  85. 86 0
      components/jp-color-picker/jp-color-picker.vue
  86. 49 0
      components/jp-datetime-picker/jp-datetime-picker.vue
  87. 106 0
      components/jp-image-upload/jp-image-upload.vue
  88. 107 0
      components/jp-image-upload2/jp-image-upload2.vue
  89. 123 0
      components/jp-office-select/jp-office-select.vue
  90. 77 0
      components/jp-picker/jp-picker.vue
  91. 33 0
      components/jp-radio-group/jp-radio-group.vue
  92. 31 0
      components/jp-slider/jp-slider.vue
  93. 31 0
      components/jp-switch/jp-switch.vue
  94. 9 0
      components/ly-tree-nvue/components/icons.js
  95. 94 0
      components/ly-tree-nvue/components/ly-checkbox.vue
  96. 331 0
      components/ly-tree-nvue/ly-tree-node.vue
  97. 536 0
      components/ly-tree-nvue/ly-tree.vue
  98. 498 0
      components/ly-tree-nvue/model/node.js
  99. 414 0
      components/ly-tree-nvue/model/tree-store.js
  100. 0 0
      components/ly-tree-nvue/tool/util.js

binární
.DS_Store


+ 11 - 0
.hbuilderx/launch.json

@@ -0,0 +1,11 @@
+{ // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
+  // launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
+    "version": "0.0",
+    "configurations": [{
+            "type": "uniCloud",
+            "default": {
+                "launchtype": "remote"
+            }
+        }
+    ]
+}

+ 0 - 0
.idea/.gitignore


+ 9 - 0
.idea/jp-mobile.iml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 9 - 0
.idea/misc.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="JavaScriptSettings">
+    <option name="languageLevel" value="ES6" />
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/out" />
+  </component>
+</project>

+ 8 - 0
.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/jp-mobile.iml" filepath="$PROJECT_DIR$/.idea/jp-mobile.iml" />
+    </modules>
+  </component>
+</project>

+ 134 - 0
.idea/workspace.xml

@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ChangeListManager">
+    <list default="true" id="8c121a16-4b7d-4f3a-a94d-fa4a54222ad4" name="Default Changelist" comment="" />
+    <option name="SHOW_DIALOG" value="false" />
+    <option name="HIGHLIGHT_CONFLICTS" value="true" />
+    <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
+    <option name="LAST_RESOLUTION" value="IGNORE" />
+  </component>
+  <component name="ProjectId" id="2ACAwm2QvoMFkCeOHuwwmOsFw1G" />
+  <component name="ProjectViewState">
+    <option name="showLibraryContents" value="true" />
+  </component>
+  <component name="PropertiesComponent">
+    <property name="AnalyzeApkAction.lastApkPath" value="$PROJECT_DIR$" />
+    <property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
+    <property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
+    <property name="WebServerToolWindowFactoryState" value="false" />
+    <property name="aspect.path.notification.shown" value="true" />
+    <property name="last_opened_file_path" value="$PROJECT_DIR$" />
+    <property name="nodejs_package_manager_path" value="npm" />
+  </component>
+  <component name="RunManager">
+    <configuration name="test" type="js.build_tools.npm" nameIsGenerated="true">
+      <package-json value="$PROJECT_DIR$/package.json" />
+      <command value="run" />
+      <scripts>
+        <script value="test" />
+      </scripts>
+      <node-interpreter value="project" />
+      <envs />
+      <method v="2" />
+    </configuration>
+  </component>
+  <component name="SvnConfiguration">
+    <configuration />
+  </component>
+  <component name="TaskManager">
+    <task active="true" id="Default" summary="Default task">
+      <changelist id="8c121a16-4b7d-4f3a-a94d-fa4a54222ad4" name="Default Changelist" comment="" />
+      <created>1654503433782</created>
+      <option name="number" value="Default" />
+      <option name="presentableId" value="Default" />
+      <updated>1654503433782</updated>
+      <workItem from="1654503435018" duration="703000" />
+      <workItem from="1669941895492" duration="9000" />
+      <workItem from="1669942450728" duration="3684000" />
+      <workItem from="1670132004253" duration="58000" />
+      <workItem from="1677576267940" duration="1223000" />
+    </task>
+    <servers />
+  </component>
+  <component name="TypeScriptGeneratedFilesManager">
+    <option name="version" value="2" />
+  </component>
+  <component name="WindowStateProjectService">
+    <state x="730" y="346" key="#com.intellij.execution.impl.EditConfigurationsDialog" timestamp="1677576315373">
+      <screen x="0" y="0" width="2560" height="1400" />
+    </state>
+    <state x="730" y="346" key="#com.intellij.execution.impl.EditConfigurationsDialog/0.0.2560.1400@0.0.2560.1400" timestamp="1677576315373" />
+    <state width="2507" height="272" key="GridCell.Tab.0.bottom" timestamp="1677577503534">
+      <screen x="0" y="0" width="2560" height="1400" />
+    </state>
+    <state width="2507" height="272" key="GridCell.Tab.0.bottom/0.0.2560.1400@0.0.2560.1400" timestamp="1677577503534" />
+    <state width="2507" height="272" key="GridCell.Tab.0.center" timestamp="1677577503534">
+      <screen x="0" y="0" width="2560" height="1400" />
+    </state>
+    <state width="2507" height="272" key="GridCell.Tab.0.center/0.0.2560.1400@0.0.2560.1400" timestamp="1677577503534" />
+    <state width="2507" height="272" key="GridCell.Tab.0.left" timestamp="1677577503534">
+      <screen x="0" y="0" width="2560" height="1400" />
+    </state>
+    <state width="2507" height="272" key="GridCell.Tab.0.left/0.0.2560.1400@0.0.2560.1400" timestamp="1677577503534" />
+    <state width="2507" height="272" key="GridCell.Tab.0.right" timestamp="1677577503534">
+      <screen x="0" y="0" width="2560" height="1400" />
+    </state>
+    <state width="2507" height="272" key="GridCell.Tab.0.right/0.0.2560.1400@0.0.2560.1400" timestamp="1677577503534" />
+    <state width="2507" height="272" key="GridCell.Tab.1.bottom" timestamp="1677577503534">
+      <screen x="0" y="0" width="2560" height="1400" />
+    </state>
+    <state width="2507" height="272" key="GridCell.Tab.1.bottom/0.0.2560.1400@0.0.2560.1400" timestamp="1677577503534" />
+    <state width="2507" height="272" key="GridCell.Tab.1.center" timestamp="1677577503534">
+      <screen x="0" y="0" width="2560" height="1400" />
+    </state>
+    <state width="2507" height="272" key="GridCell.Tab.1.center/0.0.2560.1400@0.0.2560.1400" timestamp="1677577503534" />
+    <state width="2507" height="272" key="GridCell.Tab.1.left" timestamp="1677577503534">
+      <screen x="0" y="0" width="2560" height="1400" />
+    </state>
+    <state width="2507" height="272" key="GridCell.Tab.1.left/0.0.2560.1400@0.0.2560.1400" timestamp="1677577503534" />
+    <state width="2507" height="272" key="GridCell.Tab.1.right" timestamp="1677577503534">
+      <screen x="0" y="0" width="2560" height="1400" />
+    </state>
+    <state width="2507" height="272" key="GridCell.Tab.1.right/0.0.2560.1400@0.0.2560.1400" timestamp="1677577503534" />
+    <state width="2507" height="272" key="GridCell.Tab.2.bottom" timestamp="1677577503534">
+      <screen x="0" y="0" width="2560" height="1400" />
+    </state>
+    <state width="2507" height="272" key="GridCell.Tab.2.bottom/0.0.2560.1400@0.0.2560.1400" timestamp="1677577503534" />
+    <state width="2507" height="272" key="GridCell.Tab.2.center" timestamp="1677577503534">
+      <screen x="0" y="0" width="2560" height="1400" />
+    </state>
+    <state width="2507" height="272" key="GridCell.Tab.2.center/0.0.2560.1400@0.0.2560.1400" timestamp="1677577503534" />
+    <state width="2507" height="272" key="GridCell.Tab.2.left" timestamp="1677577503534">
+      <screen x="0" y="0" width="2560" height="1400" />
+    </state>
+    <state width="2507" height="272" key="GridCell.Tab.2.left/0.0.2560.1400@0.0.2560.1400" timestamp="1677577503534" />
+    <state width="2507" height="272" key="GridCell.Tab.2.right" timestamp="1677577503534">
+      <screen x="0" y="0" width="2560" height="1400" />
+    </state>
+    <state width="2507" height="272" key="GridCell.Tab.2.right/0.0.2560.1400@0.0.2560.1400" timestamp="1677577503534" />
+    <state width="2507" height="272" key="GridCell.Tab.3.bottom" timestamp="1677577503534">
+      <screen x="0" y="0" width="2560" height="1400" />
+    </state>
+    <state width="2507" height="272" key="GridCell.Tab.3.bottom/0.0.2560.1400@0.0.2560.1400" timestamp="1677577503534" />
+    <state width="2507" height="272" key="GridCell.Tab.3.center" timestamp="1677577503534">
+      <screen x="0" y="0" width="2560" height="1400" />
+    </state>
+    <state width="2507" height="272" key="GridCell.Tab.3.center/0.0.2560.1400@0.0.2560.1400" timestamp="1677577503534" />
+    <state width="2507" height="272" key="GridCell.Tab.3.left" timestamp="1677577503534">
+      <screen x="0" y="0" width="2560" height="1400" />
+    </state>
+    <state width="2507" height="272" key="GridCell.Tab.3.left/0.0.2560.1400@0.0.2560.1400" timestamp="1677577503534" />
+    <state width="2507" height="272" key="GridCell.Tab.3.right" timestamp="1677577503534">
+      <screen x="0" y="0" width="2560" height="1400" />
+    </state>
+    <state width="2507" height="272" key="GridCell.Tab.3.right/0.0.2560.1400@0.0.2560.1400" timestamp="1677577503534" />
+    <state x="909" y="377" width="994" height="886" key="find.popup" timestamp="1677576480996">
+      <screen x="0" y="0" width="2560" height="1400" />
+    </state>
+    <state x="909" y="377" width="994" height="886" key="find.popup/0.0.2560.1400@0.0.2560.1400" timestamp="1677576480996" />
+    <state x="859" y="308" width="840" height="1034" key="search.everywhere.popup" timestamp="1677576722321">
+      <screen x="0" y="0" width="2560" height="1400" />
+    </state>
+    <state x="859" y="308" width="840" height="1034" key="search.everywhere.popup/0.0.2560.1400@0.0.2560.1400" timestamp="1677576722321" />
+  </component>
+</project>

+ 251 - 0
App.vue

@@ -0,0 +1,251 @@
+<script>
+	import Vue from 'vue'
+	export default {
+		onLaunch: function() {
+			uni.getSystemInfo({
+				success: function(e) {
+					// #ifndef MP
+					Vue.prototype.StatusBar = e.statusBarHeight;
+					if (e.platform == 'android') {
+						Vue.prototype.CustomBar = e.statusBarHeight + 50;
+					} else {
+						Vue.prototype.CustomBar = e.statusBarHeight + 45;
+					};
+					// #endif
+
+					// #ifdef MP-WEIXIN
+					Vue.prototype.StatusBar = e.statusBarHeight;
+					let custom = wx.getMenuButtonBoundingClientRect();
+					Vue.prototype.Custom = custom;
+					Vue.prototype.CustomBar = custom.bottom + custom.top - e.statusBarHeight;
+					// #endif		
+
+					// #ifdef MP-ALIPAY
+					Vue.prototype.StatusBar = e.statusBarHeight;
+					Vue.prototype.CustomBar = e.statusBarHeight + e.titleBarHeight;
+					// #endif
+				}
+			})
+
+			Vue.prototype.ColorList = [{
+					title: '嫣红',
+					name: 'red',
+					color: '#e54d42'
+				},
+				{
+					title: '桔橙',
+					name: 'orange',
+					color: '#f37b1d'
+				},
+				{
+					title: '明黄',
+					name: 'yellow',
+					color: '#fbbd08'
+				},
+				{
+					title: '橄榄',
+					name: 'olive',
+					color: '#8dc63f'
+				},
+				{
+					title: '森绿',
+					name: 'green',
+					color: '#39b54a'
+				},
+				{
+					title: '天青',
+					name: 'cyan',
+					color: '#1cbbb4'
+				},
+				{
+					title: '海蓝',
+					name: 'blue',
+					color: '#0081ff'
+				},
+				{
+					title: '姹紫',
+					name: 'purple',
+					color: '#6739b6'
+				},
+				{
+					title: '木槿',
+					name: 'mauve',
+					color: '#9c26b0'
+				},
+				{
+					title: '桃粉',
+					name: 'pink',
+					color: '#e03997'
+				},
+				{
+					title: '棕褐',
+					name: 'brown',
+					color: '#a5673f'
+				},
+				{
+					title: '玄灰',
+					name: 'grey',
+					color: '#8799a3'
+				},
+				{
+					title: '草灰',
+					name: 'gray',
+					color: '#aaaaaa'
+				},
+				{
+					title: '墨黑',
+					name: 'black',
+					color: '#333333'
+				},
+				{
+					title: '雅白',
+					name: 'white',
+					color: '#ffffff'
+				},
+			]
+
+		},
+		onShow: function() {
+			console.log('App Show')
+		},
+		onHide: function() {
+			console.log('App Hide')
+		}
+
+	}
+</script>
+
+<style>
+	/* @import 'jeeplus-flowable/lib/jeeplus-flowable.css'; */
+	@import "colorui/main.css";
+	@import "colorui/icon.css";
+
+	.nav-list {
+		display: flex;
+		flex-wrap: wrap;
+		padding: 0px 40upx 0px;
+		justify-content: space-between;
+	}
+
+	.nav-li {
+		padding: 30upx;
+		border-radius: 12upx;
+		width: 45%;
+		margin: 0 2.5% 40upx;
+		background-image: url(https://cdn.nlark.com/yuque/0/2019/png/280374/1552996358352-assets/web-upload/cc3b1807-c684-4b83-8f80-80e5b8a6b975.png);
+		background-size: cover;
+		background-position: center;
+		position: relative;
+		z-index: 1;
+	}
+
+	.nav-li::after {
+		content: "";
+		position: absolute;
+		z-index: -1;
+		background-color: inherit;
+		width: 100%;
+		height: 100%;
+		left: 0;
+		bottom: -10%;
+		border-radius: 10upx;
+		opacity: 0.2;
+		transform: scale(0.9, 0.9);
+	}
+
+	.nav-li.cur {
+		color: #fff;
+		background: rgb(94, 185, 94);
+		box-shadow: 4upx 4upx 6upx rgba(94, 185, 94, 0.4);
+	}
+
+	.nav-title {
+		font-size: 32upx;
+		font-weight: 300;
+	}
+
+	.nav-title::first-letter {
+		font-size: 40upx;
+		margin-right: 4upx;
+	}
+
+	.nav-name {
+		font-size: 28upx;
+		text-transform: Capitalize;
+		margin-top: 20upx;
+		position: relative;
+	}
+
+	.nav-name::before {
+		content: "";
+		position: absolute;
+		display: block;
+		width: 40upx;
+		height: 6upx;
+		background: #fff;
+		bottom: 0;
+		right: 0;
+		opacity: 0.5;
+	}
+
+	.nav-name::after {
+		content: "";
+		position: absolute;
+		display: block;
+		width: 100upx;
+		height: 1px;
+		background: #fff;
+		bottom: 0;
+		right: 40upx;
+		opacity: 0.3;
+	}
+
+	.nav-name::first-letter {
+		font-weight: bold;
+		font-size: 36upx;
+		margin-right: 1px;
+	}
+
+	.nav-li text {
+		position: absolute;
+		right: 30upx;
+		top: 30upx;
+		font-size: 52upx;
+		width: 60upx;
+		height: 60upx;
+		text-align: center;
+		line-height: 60upx;
+	}
+
+	.text-light {
+		font-weight: 300;
+	}
+
+	@keyframes show {
+		0% {
+			transform: translateY(-50px);
+		}
+
+		60% {
+			transform: translateY(40upx);
+		}
+
+		100% {
+			transform: translateY(0px);
+		}
+	}
+
+	@-webkit-keyframes show {
+		0% {
+			transform: translateY(-50px);
+		}
+
+		60% {
+			transform: translateY(40upx);
+		}
+
+		100% {
+			transform: translateY(0px);
+		}
+	}
+</style>

+ 144 - 0
Readme.md

@@ -0,0 +1,144 @@
+<p style="text-align: center;"><img src="https://image.weilanwl.com/uni/UniAppReadme.jpg" alt="ColorUI简介"></img></p>
+
+## 前言
+ColorUI是一个css库!!!在你引入样式后可以根据class来调用组件,一些含有交互的操作我也有简单写,可以为你开发提供一些思路。插件市场版本如果和更新日志不一样,请移步Github下载。有组件需求或者Bug提交也可以移步到issues。
+
+## 交流
+微信群:加入微信群请先添加开发者微信,备注UniApp插件市场。QQ群:240787041 或扫描二维码。
+<p style="text-align: center;"><img src="https://image.weilanwl.com/colorui/githubQrcode.jpg" alt="" style="max-width:100%;" width="748"></p>				  
+
+## 素材
+ColorUI在语雀有个群友共同在维护的知识库,里面有一些群友改的模板和UI素材供开发使用哦!
+[语雀-ColorUI群资源](https://www.yuque.com/colorui)
+ 
+## 开始使用
+下载源码解压,复制根目录的 `/colorui` 文件夹到你的根目录
+
+`App.vue` 引入关键Css `main.css` `icon.css`
+```
+<style>
+    @import "colorui/main.css";
+	@import "colorui/icon.css";
+	@import "app.css"; /* 你的项目css */
+	....
+</style>
+```
+
+------
+
+## 使用自定义导航栏
+导航栏作为常用组件有做简单封装,当然你也可以直接复制代码结构自己修改,达到个性化目的。
+
+`App.vue` 获得系统信息
+```
+onLaunch: function() {
+	uni.getSystemInfo({
+		success: function(e) {
+			// #ifndef MP
+			Vue.prototype.StatusBar = e.statusBarHeight;
+			if (e.platform == 'android') {
+				Vue.prototype.CustomBar = e.statusBarHeight + 50;
+			} else {
+				Vue.prototype.CustomBar = e.statusBarHeight + 45;
+			};
+			// #endif
+			// #ifdef MP-WEIXIN
+			Vue.prototype.StatusBar = e.statusBarHeight;
+			let custom = wx.getMenuButtonBoundingClientRect();
+			Vue.prototype.Custom = custom;
+			Vue.prototype.CustomBar = custom.bottom + custom.top - e.statusBarHeight;
+			// #endif		
+			// #ifdef MP-ALIPAY
+			Vue.prototype.StatusBar = e.statusBarHeight;
+			Vue.prototype.CustomBar = e.statusBarHeight + e.titleBarHeight;
+			// #endif
+		}
+	})
+},
+```
+
+`pages.json` 配置取消系统导航栏
+```
+"globalStyle": {
+	"navigationStyle": "custom"
+},
+```
+复制代码结构可以直接使用,注意全局变量的获取。
+
+使用封装,在`main.js` 引入 `cu-custom` 组件。
+```
+import cuCustom from './colorui/components/cu-custom.vue'
+Vue.component('cu-custom',cuCustom)
+```
+
+`page.vue` 页面可以直接调用了
+```
+<cu-custom bgColor="bg-gradual-blue" :isBack="true">
+	<block slot="backText">返回</block>
+	<block slot="content">导航栏</block>
+</cu-custom>
+```
+| 参数       | 作用   |类型    |  默认值 |
+| --------   | -----:  |-----:  | :----:  |
+| bgColor    | 背景颜色类名 |String  |   ''    |
+| isBack     | 是否开启返回 | Boolean |   false |
+| bgImage    | 背景图片路径 | String  |  ''     |
+
+| slot块       | 作用   |
+| --------   | -----:  |
+| backText    | 返回时的文字 | 
+| content     | 中间区域 | 
+| right    | 右侧区域(小程序端可使用范围很窄!)  | 
+
+
+------
+
+
+## 使用自定义Tabbar
+这部分暂时没有封装,思路可以参考下我的源码,原理是一个主页面引入多个页面,在主页面进行切换显示。这样可以解决切换时闪烁的问题。
+
+
+------
+
+
+## 更新日志
+
+ * 2019年4月25日 v2.1.6
+    *  删除var变量 向下兼容安卓APP
+	*  优化单选等表单控件
+
+ * 2019年4月25日 v2.1.5
+    *  优化图片上传
+    *  优化一些点击区域过小
+    *  优化图标旋转
+    *  优化demo显示
+    *  优化阴影
+    *  修复支付宝小程序编译出错
+
+ * 2019年4月14日 v2.1.4
+    *  新增多种阴影
+	*  修复一些var属性的错误
+	*  修复轮播图控制点隐藏不了
+	*  修改图标类名
+	*  修复表单组件里上传图片 ios没有图片显示问题
+
+ 
+ * 2019年4月01日 v2.1.3
+    *  优化代码,支持支付宝小程序
+	*  textarea 样式还原
+
+ * 2019年3月28日 v2.1.2
+	*  修复列表组件样式
+	*  优化主样式代码
+
+ * 2019年3月27日 v2.1.1
+    *  新增多种扩展
+    *  优化堆叠轮播图
+    *  优化消息列表
+	*  优化导航栏的封装
+	*  修复卡片评论错位(3月27日16:32:17)
+
+* 2019年3月25日 v2.1.0
+    *  完成元素,组件移植
+	*  icon文件更改名称,避免图标冲突
+	*  针对不同端口做了优化

binární
api/.DS_Store


+ 23 - 0
api/auth/LoginService.js

@@ -0,0 +1,23 @@
+import request from "../../common/request"
+
+export default class LoginService {
+  getCode () {
+    return request({
+      url: '/sys/getCode',
+      method: 'get'
+    })
+  }
+  login (data) {
+    return request({
+      url: '/sys/login',
+      method: 'post',
+      data: data
+    })
+  }
+  logout () {
+    return request({
+      url: '/sys/logout',
+      method: 'get'
+    })
+  }
+}

+ 34 - 0
api/flowable/ActCategoryService.js

@@ -0,0 +1,34 @@
+import request from "../../common/request"
+
+export default class ActCategoryService {
+  treeData () {
+    return request({
+      url: `/extension/actCategory/treeData`,
+      method: 'get'
+    })
+  }
+
+  save (inputForm) {
+    return request({
+      url: '/extension/actCategory/save',
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  delete (ids) {
+    return request({
+      url: '/extension/actCategory/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+
+  queryById (id) {
+    return request({
+      url: `/extension/actCategory/queryById`,
+      method: 'get',
+      params: {id: id}
+    })
+  }
+}

+ 18 - 0
api/flowable/AppModelsService.js

@@ -0,0 +1,18 @@
+import request from "../../common/request"
+
+export default class AppModelsService {
+  models (data) {
+    return request({
+      url: '/app/rest/models',
+      method: 'post',
+      data: data
+    })
+  }
+
+  editorJson (modelId) {
+    return request({
+      url: `/app/rest/models/${modelId}/editor/json?version=${new Date().getTime()}`,
+      method: 'get'
+    })
+  }
+}

+ 50 - 0
api/flowable/ButtonService.js

@@ -0,0 +1,50 @@
+import request from "../../common/request"
+
+export default class ButtonService {
+  save (inputForm) {
+    return request({
+      url: '/extension/button/save',
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  delete (ids) {
+    return request({
+      url: '/extension/button/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+
+  queryById (id) {
+    return request({
+      url: `/extension/button/queryById`,
+      method: 'get',
+      params: {id: id}
+    })
+  }
+  validateCodeNoExist (params) {
+    return request({
+      url: `/extension/button/validateCodeNoExist`,
+      method: 'get',
+      params: params
+    })
+  }
+
+  validateNameNoExist (params) {
+    return request({
+      url: `/extension/button/validateNameNoExist`,
+      method: 'get',
+      params: params
+    })
+  }
+
+  list (params) {
+    return request({
+      url: '/extension/button/list',
+      method: 'get',
+      params: params
+    })
+  }
+}

+ 35 - 0
api/flowable/ConditionService.js

@@ -0,0 +1,35 @@
+import request from "../../common/request"
+
+export default class ConditionService {
+  save (inputForm) {
+    return request({
+      url: '/extension/condition/save',
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  delete (ids) {
+    return request({
+      url: '/extension/condition/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+
+  queryById (id) {
+    return request({
+      url: `/extension/condition/queryById`,
+      method: 'get',
+      params: {id: id}
+    })
+  }
+
+  list (params) {
+    return request({
+      url: '/extension/condition/list',
+      method: 'get',
+      params: params
+    })
+  }
+}

+ 28 - 0
api/flowable/FlowCopyService.js

@@ -0,0 +1,28 @@
+import request from "../../common/request"
+
+export default class FlowCopyService {
+  save (inputForm) {
+    return request({
+      url: '/extension/flowCopy/save',
+      method: 'post',
+      header: { 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' },
+      data: inputForm
+    })
+  }
+
+  delete (ids) {
+    return request({
+      url: '/extension/flowCopy/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+
+  list (params) {
+    return request({
+      url: '/extension/flowCopy/list',
+      method: 'get',
+      params: params
+    })
+  }
+}

+ 34 - 0
api/flowable/FormCategoryService.js

@@ -0,0 +1,34 @@
+import request from "../../common/request"
+
+export default class FormCategoryService {
+  save (inputForm) {
+    return request({
+      url: '/extension/formCategory/save',
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  delete (id) {
+    return request({
+      url: '/extension/formCategory/delete',
+      method: 'delete',
+      params: {id: id}
+    })
+  }
+
+  queryById (id) {
+    return request({
+      url: `/extension/formCategory/queryById`,
+      method: 'get',
+      params: {id: id}
+    })
+  }
+
+  treeData () {
+    return request({
+      url: '/extension/formCategory/treeData',
+      method: 'get'
+    })
+  }
+}

+ 43 - 0
api/flowable/FormDefinitionJsonService.js

@@ -0,0 +1,43 @@
+import request from "../../common/request"
+
+export default class FormDefinitionJsonService {
+  save (inputForm) {
+    return request({
+      url: '/extension/formDefinitionJson/save',
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  updatePrimary (id) {
+    return request({
+      url: '/extension/formDefinitionJson/updatePrimary',
+      method: 'put',
+      params: {id: id}
+    })
+  }
+
+  delete (ids) {
+    return request({
+      url: '/extension/formDefinitionJson/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+
+  queryById (id) {
+    return request({
+      url: `/extension/formDefinitionJson/queryById`,
+      method: 'get',
+      params: {id: id}
+    })
+  }
+
+  list (params) {
+    return request({
+      url: '/extension/formDefinitionJson/list',
+      method: 'get',
+      params: params
+    })
+  }
+}

+ 42 - 0
api/flowable/FormDefinitionService.js

@@ -0,0 +1,42 @@
+import request from "../../common/request"
+
+export default class FormDefinitionService {
+  save (inputForm) {
+    return request({
+      url: '/extension/formDefinition/save',
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  delete (ids) {
+    return request({
+      url: '/extension/formDefinition/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+
+  queryById (id) {
+    return request({
+      url: `/extension/formDefinition/queryById`,
+      method: 'get',
+      params: {id: id}
+    })
+  }
+  queryByJsonId (jsonId) {
+    return request({
+      url: `/extension/formDefinition/queryByJsonId`,
+      method: 'get',
+      params: {jsonId: jsonId}
+    })
+  }
+
+  list (params) {
+    return request({
+      url: '/extension/formDefinition/list',
+      method: 'get',
+      params: params
+    })
+  }
+}

+ 52 - 0
api/flowable/FormService.js

@@ -0,0 +1,52 @@
+import request from "../../common/request"
+
+export default class FormService {
+  submitStartFormData (inputForm) {
+    return request({
+      url: '/flowable/form/submitStartFormData',
+      method: 'post',
+      header: { 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' },
+      data: inputForm
+    })
+  }
+
+  submitTaskFormData (inputForm) {
+    return request({
+      url: '/flowable/form/submitTaskFormData',
+      method: 'post',
+      header: { 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' },
+      data: inputForm
+    })
+  }
+
+  getStartFormData (params) {
+    return request({
+      url: '/flowable/form/getStartFormData',
+      method: 'get',
+      params: params
+    })
+  }
+  getHistoryTaskFormData (params) {
+    return request({
+      url: '/flowable/form/getHistoryTaskFormData',
+      method: 'get',
+      params: params
+    })
+  }
+
+  getTaskFormData (params) {
+    return request({
+      url: '/flowable/form/getTaskFormData',
+      method: 'get',
+      params: params
+    })
+  }
+  
+  getMobileForm (formDefinitionJsonId) {
+    return request({
+      url: '/flowable/form/getMobileForm',
+      method: 'get',
+      params: {formDefinitionJsonId: formDefinitionJsonId}
+    })
+  }
+}

+ 35 - 0
api/flowable/ListenerService.js

@@ -0,0 +1,35 @@
+import request from "../../common/request"
+
+export default class ListenerService {
+  save (inputForm) {
+    return request({
+      url: '/extension/listener/save',
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  delete (ids) {
+    return request({
+      url: '/extension/listener/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+
+  queryById (id) {
+    return request({
+      url: `/extension/listener/queryById`,
+      method: 'get',
+      params: {id: id}
+    })
+  }
+
+  list (params) {
+    return request({
+      url: '/extension/listener/list',
+      method: 'get',
+      params: params
+    })
+  }
+}

+ 28 - 0
api/flowable/LoginService.js

@@ -0,0 +1,28 @@
+import request from "../../common/request"
+
+export default class LoginService {
+  getCode () {
+    return request({
+      url: '/app/sys/getCode',
+      method: 'get',
+      responseType: "arraybuffer"
+    })
+  }
+  login (username, password, code) {
+    return request({
+      url: '/app/sys/login',
+      method: 'post',
+      data: {
+        'username': username,
+        'password': password,
+        'code': code
+      }
+    })
+  }
+  logout () {
+    return request({
+      url: '/app/sys/logout',
+      method: 'get'
+    })
+  }
+}

+ 57 - 0
api/flowable/ModelService.js

@@ -0,0 +1,57 @@
+import request from "../../common/request"
+
+export default class ModelService {
+  deploy (params) {
+    return request({
+      url: '/flowable/model/deploy',
+      method: 'put',
+      params: params
+    })
+  }
+  updateCategory (params) {
+    return request({
+      url: '/flowable/model/updateCategory',
+      method: 'put',
+      params: params
+    })
+  }
+  copy (id) {
+    return request({
+      url: '/flowable/model/copy',
+      method: 'get',
+      params: {id: id}
+    })
+  }
+
+  getBpmnXml (id) {
+    return request({
+      url: '/flowable/model/getBpmnXml',
+      method: 'get',
+      params: {id: id}
+    })
+  }
+  delete (ids) {
+    return request({
+      url: '/flowable/model/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+
+  saveModel (modelId, data) {
+    return request({
+      url: `/flowable/model/saveModel/${modelId}`,
+      method: 'post',
+      header: { 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' },
+      data: data
+    })
+  }
+
+  list (params) {
+    return request({
+      url: '/flowable/model/list',
+      method: 'get',
+      params: params
+    })
+  }
+}

+ 43 - 0
api/flowable/NodeSettingService.js

@@ -0,0 +1,43 @@
+import request from "../../common/request"
+
+export default class NodeSettingService {
+  save (inputForm) {
+    return request({
+      url: '/extension/nodeSetting/save',
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  delete (ids) {
+    return request({
+      url: '/extension/nodeSetting/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+
+  queryValueByKey (params) {
+    return request({
+      url: `/extension/nodeSetting/queryValueByKey`,
+      method: 'get',
+      params: params
+    })
+  }
+
+  queryById (id) {
+    return request({
+      url: `/extension/nodeSetting/queryById`,
+      method: 'get',
+      params: {id: id}
+    })
+  }
+
+  list (params) {
+    return request({
+      url: '/extension/nodeSetting/list',
+      method: 'get',
+      params: params
+    })
+  }
+}

+ 101 - 0
api/flowable/ProcessService.js

@@ -0,0 +1,101 @@
+import request from "../../common/request"
+
+export default class ProcessService {
+  list (params) {
+    return request({
+      url: '/flowable/process/list',
+      method: 'get',
+      params: params
+    })
+  }
+
+  runningDataList (params) {
+    return request({
+      url: '/flowable/process/runningData',
+      method: 'get',
+      params: params
+    })
+  }
+
+  historyListData (params) {
+    return request({
+      url: '/flowable/process/historyListData',
+      method: 'get',
+      params: params
+    })
+  }
+
+  revokeProcIns (id) {
+    return request({
+      url: `/flowable/process/revokeProcIns`,
+      method: 'put',
+      params: {id: id}
+    })
+  }
+
+  deleteProcIns (ids, reason) {
+    return request({
+      url: '/flowable/process/deleteProcIns',
+      method: 'delete',
+      params: {
+        ids: ids,
+        reason: reason}
+    })
+  }
+
+  deleteAllProcIns (ids) {
+    return request({
+      url: '/flowable/process/history/deleteAllProcIns',
+      method: 'delete',
+      params: {procInsIds: ids}
+    })
+  }
+
+  suspend (procDefId) {
+    return request({
+      url: '/flowable/process/update/suspend',
+      method: 'put',
+      params: {procDefId: procDefId}
+    })
+  }
+
+  active (procDefId) {
+    return request({
+      url: '/flowable/process/update/active',
+      method: 'put',
+      params: {procDefId: procDefId}
+    })
+  }
+
+  stop (id, message) {
+    return request({
+      url: '/flowable/process/stop',
+      method: 'put',
+      params: {id: id, message: message}
+    })
+  }
+
+  getFlowChart (processDefId) {
+    return request({
+      url: '/flowable/process/getFlowChart',
+      method: 'get',
+      params: {processDefId: processDefId}
+    })
+  }
+
+  queryProcessStatus (procDefId, procInsId) {
+    return request({
+      url: '/flowable/process/queryProcessStatus',
+      method: 'get',
+      params: {procDefId: procDefId, procInsId: procInsId}
+    })
+  }
+
+  exist (key) {
+    return request({
+      url: '/flowable/process/exist',
+      method: 'get',
+      params: {key: key}
+    })
+  }
+}

+ 43 - 0
api/flowable/TaskDefExtensionService.js

@@ -0,0 +1,43 @@
+import request from "../../common/request"
+
+export default class TaskDefExtensionService {
+  save (inputForm) {
+    return request({
+      url: '/extension/taskDefExtension/save',
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  delete (ids) {
+    return request({
+      url: '/extension/taskDefExtension/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+
+  queryById (id) {
+    return request({
+      url: `/extension/taskDefExtension/queryById`,
+      method: 'get',
+      params: {id: id}
+    })
+  }
+
+  queryByDefIdAndTaskId (params) {
+    return request({
+      url: `/extension/taskDefExtension/queryByDefIdAndTaskId`,
+      method: 'get',
+      params: params
+    })
+  }
+
+  list (params) {
+    return request({
+      url: '/extension/taskDefExtension/list',
+      method: 'get',
+      params: params
+    })
+  }
+}

+ 116 - 0
api/flowable/TaskService.js

@@ -0,0 +1,116 @@
+import request from "../../common/request"
+
+export default class TaskService {
+  start (params) {
+    return request({
+      url: '/flowable/task/start',
+      method: 'post',
+      params: params
+    })
+  }
+
+  todoList (params) {
+    return request({
+      url: '/flowable/task/todo',
+      method: 'get',
+      params: params
+    })
+  }
+
+  historicList (params) {
+    return request({
+      url: '/flowable/task/historic',
+      method: 'get',
+      params: params
+    })
+  }
+
+  historicTaskList (procInsId) {
+    return request({
+      url: '/flowable/task/historicTaskList',
+      method: 'get',
+      params: {procInsId: procInsId}
+    })
+  }
+
+  myApplyedList (params) {
+    return request({
+      url: '/flowable/task/myApplyed',
+      method: 'get',
+      params: params
+    })
+  }
+
+  getTaskDef (params) {
+    return request({
+      url: '/flowable/task/getTaskDef',
+      method: 'get',
+      params: params
+    })
+  }
+  
+  delegate (taskId, userId) {
+    return request({
+      url: `/flowable/task/delegate`,
+      method: 'put',
+      params: {taskId: taskId, userId: userId}
+    })
+  }
+
+  callback (params) {
+    return request({
+      url: `/flowable/task/callback`,
+      method: 'put',
+      params: params
+    })
+  }
+
+  audit (data) {
+    return request({
+      url: `/flowable/task/audit`,
+      method: 'post',
+      header: { 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' },
+      params: data
+    })
+  }
+
+  backNodes (taskId) {
+    return request({
+      url: `/flowable/task/backNodes`,
+      method: 'put',
+      params: {taskId: taskId}
+    })
+  }
+
+  back (params) {
+    return request({
+      url: `/flowable/task/back`,
+      method: 'put',
+      params: params
+    })
+  }
+
+  transfer (taskId, userId) {
+    return request({
+      url: `/flowable/task/transfer`,
+      method: 'put',
+      params: {taskId: taskId, userId: userId}
+    })
+  }
+
+  addSignTask (data) {
+    return request({
+      url: `/flowable/task/addSignTask`,
+      method: 'post',
+      header: { 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' },
+      data: data
+    })
+  }
+  getFlowChart (processInstanceId) {
+    return request({
+      url: `/flowable/task/getFlowChart`,
+      method: 'get',
+      params: {processInstanceId: processInstanceId}
+    })
+  }
+}

+ 36 - 0
api/form/GenerateFormService.js

@@ -0,0 +1,36 @@
+import request from "../../common/request"
+
+export default class GenerateFormService {
+  save (inputForm) {
+    return request({
+      url: `/form/generate/save`,
+      method: 'post',
+      header: { 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' },
+      data: inputForm
+    })
+  }
+
+  queryById (params) {
+    return request({
+      url: `/form/generate/queryById`,
+      method: 'get',
+      params: params
+    })
+  }
+
+  delete (params) {
+    return request({
+      url: `/form/generate/delete`,
+      method: 'delete',
+      params: params
+    })
+  }
+
+  list (params) {
+    return request({
+      url: '/form/generate/list',
+      method: 'get',
+      params: params
+    })
+  }
+}

+ 92 - 0
api/form/MakeFormService.js

@@ -0,0 +1,92 @@
+import request from "../../common/request"
+
+export default class MakeFormService {
+  save (inputForm) {
+    return request({
+      url: `/form/make/save`,
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  saveFormSource (inputForm) {
+    return request({
+      url: `/form/make/saveFormSource`,
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  saveBasicInfo (inputForm) {
+    return request({
+      url: `/form/make/saveBasicInfo`,
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  delete (ids) {
+    return request({
+      url: '/form/make/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+
+  queryById (id) {
+    return request({
+      url: `/form/make/queryById`,
+      method: 'get',
+      params: {id: id}
+    })
+  }
+
+  getTableColumnList (params) {
+    return request({
+      url: `/form/make/getTableColumnList`,
+      method: 'get',
+      params: params
+    })
+  }
+
+  getTableList (params) {
+    return request({
+      url: `/form/make/getTableList`,
+      method: 'get',
+      params: params
+    })
+  }
+
+  list (params) {
+    return request({
+      url: '/form/make/list',
+      method: 'get',
+      params: params
+    })
+  }
+
+  validateTableNoExist (params) {
+    return request({
+      url: `/form/make/validateTableNoExist`,
+      method: 'get',
+      params: params
+    })
+  }
+
+  validateKeyNoExist (params) {
+    return request({
+      url: `/form/make/validateKeyNoExist`,
+      method: 'get',
+      params: params
+    })
+  }
+
+  createMenu (inputForm) {
+    return request({
+      url: `/form/make/createMenu`,
+      method: 'post',
+      header: { 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' },
+      data: inputForm
+    })
+  }
+}

+ 33 - 0
api/mail/MailBoxService.js

@@ -0,0 +1,33 @@
+import request from "../../common/request"
+
+export default class MailBoxService {
+  delete (ids) {
+    return request({
+      url: '/mail/box/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+
+  queryById (id) {
+    return request({
+      url: `/mail/box/queryById`,
+      method: 'get',
+      params: {id: id}
+    })
+  }
+  queryStatus () {
+    return request({
+      url: `/mail/box/queryStatus`,
+      method: 'get'
+    })
+  }
+
+  list (params) {
+    return request({
+      url: '/mail/box/list',
+      method: 'get',
+      params: params
+    })
+  }
+}

+ 35 - 0
api/mail/MailComposeService.js

@@ -0,0 +1,35 @@
+import request from "../../common/request"
+
+export default class MailComposeService {
+  save (inputForm) {
+    return request({
+      url: `/mail/compose/save`,
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  delete (ids) {
+    return request({
+      url: '/mail/compose/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+
+  queryById (id) {
+    return request({
+      url: `/mail/compose/queryById`,
+      method: 'get',
+      params: {id: id}
+    })
+  }
+
+  list (params) {
+    return request({
+      url: '/mail/compose/list',
+      method: 'get',
+      params: params
+    })
+  }
+}

+ 27 - 0
api/mail/MailTrashService.js

@@ -0,0 +1,27 @@
+import request from "../../common/request"
+
+export default class MailTrashService {
+  delete (ids) {
+    return request({
+      url: '/mail/trash/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+
+  queryById (id) {
+    return request({
+      url: `/mail/trash/queryById`,
+      method: 'get',
+      params: {id: id}
+    })
+  }
+
+  list (params) {
+    return request({
+      url: '/mail/trash/list',
+      method: 'get',
+      params: params
+    })
+  }
+}

+ 42 - 0
api/notify/NotifyService.js

@@ -0,0 +1,42 @@
+import request from "../../common/request"
+
+export default class NotifyService {
+  save (inputForm) {
+    return request({
+      url: `/notify/save`,
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  delete (ids) {
+    return request({
+      url: '/notify/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+
+  queryById (id) {
+    return request({
+      url: `/notify/queryById`,
+      method: 'get',
+      params: {id: id}
+    })
+  }
+  query (params) {
+    return request({
+      url: `/notify/queryById`,
+      method: 'get',
+      params: params
+    })
+  }
+
+  list (params) {
+    return request({
+      url: '/notify/list',
+      method: 'get',
+      params: params
+    })
+  }
+}

+ 34 - 0
api/sys/AreaService.js

@@ -0,0 +1,34 @@
+import request from "../../common/request"
+
+export default class AreaService {
+  save (inputForm) {
+    return request({
+      url: `/sys/area/save`,
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  delete (ids) {
+    return request({
+      url: '/sys/area/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+
+  queryById (id) {
+    return request({
+      url: `/sys/area/queryById`,
+      method: 'get',
+      params: {id: id}
+    })
+  }
+
+  treeData () {
+    return request({
+      url: '/sys/area/treeData',
+      method: 'get'
+    })
+  }
+}

+ 25 - 0
api/sys/ConfigService.js

@@ -0,0 +1,25 @@
+import request from "../../common/request"
+
+export default class ConfigService {
+  getConfig () {
+    return request({
+      url: `/sys/sysConfig/getConfig`,
+      method: 'get'
+    })
+  }
+
+  queryById () {
+    return request({
+      url: `/sys/sysConfig/queryById`,
+      method: 'get'
+    })
+  }
+
+  save (inputForm) {
+    return request({
+      url: `/sys/sysConfig/save`,
+      method: 'post',
+      data: inputForm
+    })
+  }
+}

+ 41 - 0
api/sys/DataRuleService.js

@@ -0,0 +1,41 @@
+import request from "../../common/request"
+
+export default class DateRuleService {
+  save (inputForm) {
+    return request({
+      url: `/sys/dataRule/save`,
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  delete (id) {
+    return request({
+      url: '/sys/dataRule/delete',
+      method: 'delete',
+      params: {id: id}
+    })
+  }
+
+  queryById (id) {
+    return request({
+      url: `/sys/dataRule/queryById`,
+      method: 'get',
+      params: {id: id}
+    })
+  }
+
+  list (params) {
+    return request({
+      url: '/sys/dataRule/list',
+      method: 'get',
+      params: params
+    })
+  }
+  treeData () {
+    return request({
+      url: `/sys/dataRule/treeData`,
+      method: 'get'
+    })
+  }
+}

+ 80 - 0
api/sys/DictService.js

@@ -0,0 +1,80 @@
+import request from "../../common/request"
+
+export default class DictService {
+  queryById (id) {
+    return request({
+      url: `/sys/dict/queryById`,
+      method: 'get',
+      params: {id: id}
+    })
+  }
+
+  save (inputForm) {
+    return request({
+      url: `/sys/dict/save`,
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  list (params) {
+    return request({
+      url: '/sys/dict/type/list',
+      method: 'get',
+      params: params
+    })
+  }
+
+  delete (ids) {
+    return request({
+      url: '/sys/dict/delete',
+      method: 'delete',
+      params: {'ids': ids}
+    })
+  }
+
+  queryDictValue (id) {
+    return request({
+      url: `/sys/dict/queryDictValue`,
+      method: 'get',
+      params: {dictValueId: id},
+      loading: false
+    })
+  }
+
+  saveDictValue (inputForm) {
+    return request({
+      url: `/sys/dict/saveDictValue`,
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  getDictValue (dictTypeId) {
+    return request({
+      url: '/sys/dict/getDictValue',
+      method: 'get',
+      params: {
+        'dictTypeId': dictTypeId
+      }
+    })
+  }
+
+  getDictMap (dictTypeId) {
+    return request({
+      url: '/sys/dict/getDictMap',
+      method: 'get',
+      params: {
+        'dictTypeId': dictTypeId
+      }
+    })
+  }
+
+  deleteDictValue (ids) {
+    return request({
+      url: '/sys/dict/deleteDictValue',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+}

+ 15 - 0
api/sys/FileService.js

@@ -0,0 +1,15 @@
+import {request, upload} from "../../common/request"
+
+export default class FileService {
+  uploadFile (uploadPath) {
+	  return upload('/sys/file/webupload/upload?uploadPath=/app/formbuilder',uploadPath)
+  }
+
+  getUrl (params) {
+    return request({
+      url: `/sys/file/getUrl`,
+      method: 'get',
+      params: params
+    })
+  }
+}

+ 34 - 0
api/sys/LogService.js

@@ -0,0 +1,34 @@
+import request from "../../common/request"
+
+export default class LogService {
+  list (params) {
+    return request({
+      url: '/sys/log/list',
+      method: 'get',
+      params: params
+    })
+  }
+
+  mine (params) {
+    return request({
+      url: '/sys/log/data/mine',
+      method: 'get',
+      params: params
+    })
+  }
+
+  delete (ids) {
+    return request({
+      url: '/sys/log/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+
+  empty () {
+    return request({
+      url: '/sys/log/empty',
+      method: 'delete'
+    })
+  }
+}

+ 35 - 0
api/sys/MenuService.js

@@ -0,0 +1,35 @@
+import request from "../../common/request"
+
+export default class MenuService {
+  save (inputForm) {
+    return request({
+      url: `/sys/menu/save`,
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  delete (ids) {
+    return request({
+      url: '/sys/menu/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+
+  queryById (id) {
+    return request({
+      url: `/sys/menu/queryById`,
+      method: 'get',
+      params: {id: id}
+    })
+  }
+
+  treeData (params) {
+    return request({
+      url: `/sys/menu/treeData`,
+      method: 'get',
+      params: params
+    })
+  }
+}

+ 35 - 0
api/sys/OfficeService.js

@@ -0,0 +1,35 @@
+import request from "../../common/request"
+
+export default class OfficeService {
+  save (inputForm) {
+    return request({
+      url: `/sys/office/save`,
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  delete (ids) {
+    return request({
+      url: '/sys/office/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+
+  queryById (id) {
+    return request({
+      url: `/sys/office/queryById`,
+      method: 'get',
+      params: {id: id}
+    })
+  }
+
+  treeData (params) {
+    return request({
+      url: '/sys/office/treeData',
+      method: 'get',
+      params: params
+    })
+  }
+}

+ 35 - 0
api/sys/PostService.js

@@ -0,0 +1,35 @@
+import request from "../../common/request"
+
+export default class PostService {
+  save (inputForm) {
+    return request({
+      url: `/sys/post/save`,
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  delete (ids) {
+    return request({
+      url: '/sys/post/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+
+  queryById (id) {
+    return request({
+      url: `/sys/post/queryById`,
+      method: 'get',
+      params: {id: id}
+    })
+  }
+
+  list (params) {
+    return request({
+      url: '/sys/post/list',
+      method: 'get',
+      params: params
+    })
+  }
+}

+ 69 - 0
api/sys/RoleService.js

@@ -0,0 +1,69 @@
+import request from "../../common/request"
+
+export default class RoleService {
+  save (inputForm) {
+    return request({
+      url: `/sys/role/save`,
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  delete (ids) {
+    return request({
+      url: '/sys/role/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+
+  queryById (id) {
+    return request({
+      url: `/sys/role/queryById`,
+      method: 'get',
+      params: {id: id}
+    })
+  }
+
+  validateNotExist (obj) {
+    return request({
+      url: `/sys/role/validateNotExist`,
+      method: 'get',
+      params: obj
+    })
+  }
+
+  list (params) {
+    return request({
+      url: '/sys/role/list',
+      method: 'get',
+      params: params
+    })
+  }
+  assign (params) {
+    return request({
+      url: '/sys/role/assign',
+      method: 'get',
+      params: params
+    })
+  }
+
+  removeUserFromRole (userId, roleId) {
+    return request({
+      url: '/sys/role/removeUserFromRole',
+      method: 'delete',
+      params: {userId: userId, roleId: roleId}
+    })
+  }
+
+  addUserToRole (roleId, userIds) {
+    return request({
+      url: '/sys/role/addUserToRole',
+      method: 'put',
+      params: {
+        roleId: roleId,
+        userIds: userIds
+      }
+    })
+  }
+}

+ 66 - 0
api/sys/UserService.js

@@ -0,0 +1,66 @@
+import {request, upload} from "../../common/request"
+
+export default class UserService {
+
+  saveInfo (inputForm) {
+    return request({
+      url: `/sys/user/saveInfo`,
+      method: 'post',
+      header: {arrayFormat: 'repeat'},
+      data: inputForm
+    })
+  }
+
+ upload(filePath) {
+	return upload('/sys/user/imageUpload',filePath)
+ }
+	 
+  savePwd (inputForm) {
+    return request({
+      url: `/sys/user/savePwd`,
+      method: 'put',
+      params: inputForm
+    })
+  }
+
+  queryById (id) {
+    return request({
+      url: `/sys/user/queryById`,
+      method: 'get',
+      params: {id: id}
+    })
+  }
+  
+  imageUpload (filePath) {
+	return upload('/sys/user/imageUpload',filePath)  
+  }
+ 
+  info () {
+    return request({
+      url: `/sys/user/info`,
+      method: 'get'
+    })
+  }
+  
+  getMenus () {
+    return request({
+	  url: `/sys/user/getMenus`,
+	  method: 'get'
+    })
+  }
+
+  list (params) {
+    return request({
+      url: '/sys/user/list',
+      method: 'get',
+      params: params
+    })
+  }
+  
+  treeData () {
+    return request({
+      url: '/sys/user/treeData',
+      method: 'get'
+    })
+  }
+}

binární
api/test/.DS_Store


+ 35 - 0
api/test/activiti/TestActivitiLeaveService.js

@@ -0,0 +1,35 @@
+import request from "../../../common/request"
+
+export default class TestActivitiLeaveService {
+  save (inputForm) {
+    return request({
+      url: '/test/activiti/testActivitiLeave/save',
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  delete (ids) {
+    return request({
+      url: '/test/activiti/testActivitiLeave/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+
+  queryById (id) {
+    return request({
+      url: '/test/activiti/testActivitiLeave/queryById',
+      method: 'get',
+      params: {id: id}
+    })
+  }
+
+  list (params) {
+    return request({
+      url: '/test/activiti/testActivitiLeave/list',
+      method: 'get',
+      params: params
+    })
+  }
+}

+ 35 - 0
api/test/mobile/TestMobileService.js

@@ -0,0 +1,35 @@
+import request from "../../../common/request"
+
+export default class TestMobileService {
+  save (inputForm) {
+    return request({
+      url: '/test/mobile/testMobile/save',
+      method: 'post',
+      data: inputForm
+    })
+  }
+
+  delete (ids) {
+    return request({
+      url: '/test/mobile/testMobile/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+
+  queryById (id) {
+    return request({
+      url: '/test/mobile/testMobile/queryById',
+      method: 'get',
+      params: {id: id}
+    })
+  }
+
+  list (params) {
+    return request({
+      url: '/test/mobile/testMobile/list',
+      method: 'get',
+      params: params
+    })
+  }
+}

+ 184 - 0
colorui/animation.css

@@ -0,0 +1,184 @@
+/* 
+  Animation 微动画  
+  基于ColorUI组建库的动画模块 by 文晓港 2019年3月26日19:52:28
+ */
+
+/* css 滤镜 控制黑白底色gif的 */
+.gif-black{  
+  mix-blend-mode: screen;  
+}
+.gif-white{  
+  mix-blend-mode: multiply; 
+}
+
+
+/* Animation css */
+[class*=animation-] {
+    animation-duration: .5s;
+    animation-timing-function: ease-out;
+    animation-fill-mode: both
+}
+
+.animation-fade {
+    animation-name: fade;
+    animation-duration: .8s;
+    animation-timing-function: linear
+}
+
+.animation-scale-up {
+    animation-name: scale-up
+}
+
+.animation-scale-down {
+    animation-name: scale-down
+}
+
+.animation-slide-top {
+    animation-name: slide-top
+}
+
+.animation-slide-bottom {
+    animation-name: slide-bottom
+}
+
+.animation-slide-left {
+    animation-name: slide-left
+}
+
+.animation-slide-right {
+    animation-name: slide-right
+}
+
+.animation-shake {
+    animation-name: shake
+}
+
+.animation-reverse {
+    animation-direction: reverse
+}
+
+@keyframes fade {
+    0% {
+        opacity: 0
+    }
+
+    100% {
+        opacity: 1
+    }
+}
+
+@keyframes scale-up {
+    0% {
+        opacity: 0;
+        transform: scale(.2)
+    }
+
+    100% {
+        opacity: 1;
+        transform: scale(1)
+    }
+}
+
+@keyframes scale-down {
+    0% {
+        opacity: 0;
+        transform: scale(1.8)
+    }
+
+    100% {
+        opacity: 1;
+        transform: scale(1)
+    }
+}
+
+@keyframes slide-top {
+    0% {
+        opacity: 0;
+        transform: translateY(-100%)
+    }
+
+    100% {
+        opacity: 1;
+        transform: translateY(0)
+    }
+}
+
+@keyframes slide-bottom {
+    0% {
+        opacity: 0;
+        transform: translateY(100%)
+    }
+
+    100% {
+        opacity: 1;
+        transform: translateY(0)
+    }
+}
+
+@keyframes shake {
+
+    0%,
+    100% {
+        transform: translateX(0)
+    }
+
+    10% {
+        transform: translateX(-9px)
+    }
+
+    20% {
+        transform: translateX(8px)
+    }
+
+    30% {
+        transform: translateX(-7px)
+    }
+
+    40% {
+        transform: translateX(6px)
+    }
+
+    50% {
+        transform: translateX(-5px)
+    }
+
+    60% {
+        transform: translateX(4px)
+    }
+
+    70% {
+        transform: translateX(-3px)
+    }
+
+    80% {
+        transform: translateX(2px)
+    }
+
+    90% {
+        transform: translateX(-1px)
+    }
+}
+
+@keyframes slide-left {
+    0% {
+        opacity: 0;
+        transform: translateX(-100%)
+    }
+
+    100% {
+        opacity: 1;
+        transform: translateX(0)
+    }
+}
+
+@keyframes slide-right {
+    0% {
+        opacity: 0;
+        transform: translateX(100%)
+    }
+
+    100% {
+        opacity: 1;
+        transform: translateX(0)
+    }
+}

+ 75 - 0
colorui/components/cu-custom.vue

@@ -0,0 +1,75 @@
+<template>
+	<view>
+		<view class="cu-custom" :style="[{height:CustomBar + 'px'}]">
+			<view class="cu-bar fixed" :style="style" :class="[bgImage!=''?'none-bg text-white bg-img':'',bgColor]">
+				<view class="action" @tap="BackPage" v-if="isBack">
+					<text class="cuIcon-back"></text>
+					<slot name="backText"></slot>
+				</view>
+				<view class="content" :style="[{top:StatusBar + 'px'}]">
+					<slot name="content"></slot>
+				</view>
+				<slot name="right"></slot>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				StatusBar: this.StatusBar,
+				CustomBar: this.CustomBar
+			};
+		},
+		name: 'cu-custom',
+		computed: {
+			style() {
+				var StatusBar= this.StatusBar;
+				var CustomBar= this.CustomBar;
+				var bgImage = this.bgImage;
+				var style = `height:${CustomBar}px;padding-top:${StatusBar}px;`;
+				if (this.bgImage) {
+					style = `${style}background-image:url(${bgImage});`;
+				}
+				return style
+			}
+		},
+		props: {
+			bgColor: {
+				type: String,
+				default: ''
+			},
+			isBack: {
+				type: [Boolean, String],
+				default: false
+			},
+			backUrl: {
+				type: String,
+				default: ''
+			},
+			bgImage: {
+				type: String,
+				default: ''
+			},
+		},
+		methods: {
+			BackPage() {
+				if(this.backUrl){
+					uni.navigateTo({
+						url: this.backUrl
+					})
+				}else{
+					uni.navigateBack({
+						delta: 1
+					});
+				}
+			}
+		}
+	}
+</script>
+
+<style>
+
+</style>

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1226 - 0
colorui/icon.css


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 4008 - 0
colorui/main.css


+ 128 - 0
common/auth.js

@@ -0,0 +1,128 @@
+
+const tokenKey = 'token'
+const refreshTokenKey = 'refreshToken'
+const usernameKey = 'WMS-username'
+const userInfoKey = 'WMS-userinfo'
+const permissionsKey = 'WMS-permission'
+import store from '@/store'
+
+// 获取token值
+function getUserToken(){
+	return uni.getStorageSync(tokenKey);
+}
+
+function setUserToken(token){
+	uni.setStorageSync(tokenKey,token);
+}
+
+function removeUserToken(){
+	uni.removeStorageSync(tokenKey);
+}
+
+// 获取refresh token值
+function getRefreshToken(){
+	return uni.getStorageSync(refreshTokenKey);
+}
+
+function setRefreshToken(token){
+	uni.setStorageSync(refreshTokenKey,token);
+}
+
+function removeRefreshToken(){
+	uni.removeStorageSync(refreshTokenKey);
+}
+
+// 获取用户名
+function getUsername(){
+	return uni.getStorageSync(usernameKey);
+}
+
+function setUsername(username){
+	uni.setStorageSync(usernameKey,username);
+}
+
+function removeUsername(){
+	uni.removeStorageSync(usernameKey);
+}
+
+// 获取用户信息
+function getUserInfo(){
+	return uni.getStorageSync(userInfoKey);
+}
+
+function setUserInfo(userinfo){
+	uni.setStorageSync(userInfoKey,userinfo);
+}
+
+function removeUserInfo(){
+	uni.removeStorageSync(userInfoKey);
+}
+
+// 获取用户权限
+function getPermissions(){
+	return uni.getStorageSync(permissionsKey);
+}
+
+function setPermissions(permissions){
+	uni.setStorageSync(permissionsKey,permissions);
+}
+
+function removePermissions(){
+	uni.removeStorageSync(permissionsKey);
+}
+function hasPermission (key) {
+  return uni.getStorageSync(permissionsKey).indexOf(key) !== -1 || false
+}
+
+function checkLogin () {
+	if (!store.state.user.token) {
+		uni.showModal({
+			title: '未登录',
+			content: '您未登录,需要登录后才能继续',
+			/**
+			 * 如果需要强制登录,不显示取消按钮
+			 */
+			showCancel: !store.state.user.forcedLogin,
+			success: (res) => {
+				if (res.confirm) {
+					/**
+					 * 如果需要强制登录,使用reLaunch方式
+					 */
+					if (store.state.user.forcedLogin) {
+						uni.reLaunch({
+							url: '/pages/login/login'
+						});
+					} else {
+						uni.navigateTo({
+							url: '/pages/login/login'
+						});
+					}
+				}
+			}
+		});
+	}
+}
+
+export {
+	getUserToken,
+	setUserToken,
+	removeUserToken,
+	
+	getRefreshToken,
+	setRefreshToken,
+	removeRefreshToken,
+	
+	getUsername,
+	setUsername,
+	removeUsername,
+	
+	getUserInfo,
+	setUserInfo,
+	removeUserInfo,
+	
+	getPermissions,
+	setPermissions,
+	removePermissions,
+	hasPermission,
+	checkLogin
+}

+ 14 - 0
common/config.js

@@ -0,0 +1,14 @@
+let APP_SERVER_URL = ""
+
+if(process.env.NODE_ENV === 'development'){
+    // 开发环境
+    APP_SERVER_URL = 'api'
+}else{
+    // 生产环境
+    //APP_SERVER_URL = 'http://demo1.jeeplus.org/jeeplus-vue'
+    APP_SERVER_URL = 'http://http://3081089em4.wicp.vip:36186/jeeplus-vue'
+}
+
+APP_SERVER_URL = APP_SERVER_URL + "/app"
+
+export default APP_SERVER_URL

+ 64 - 0
common/dictUtils.js

@@ -0,0 +1,64 @@
+import $http from './request.js'
+const dictListKey = 'dictList'
+
+export function getDictLabel (type, value, defaultLabel) {
+  if ((!value && value !== 0) || (!type && type !== 0)) {
+    if (defaultLabel !== undefined) {
+      return defaultLabel
+    } else {
+      return '--'
+    }
+  }
+  let dictList = uni.getStorageSync(dictListKey)
+  let dicts = dictList[type]
+  if (dicts) {
+    for (let i = 0; i < dicts.length; i++) {
+      if (dicts[i].value && dicts[i].value.toString() === value.toString()) {
+        return dicts[i].label
+      }
+    }
+  }
+  if (defaultLabel !== undefined) {
+    return defaultLabel
+  } else {
+    return '--'
+  }
+}
+
+export function getDictValue (type, label, defaultValue) {
+  if ((!label && label !== 0) || (!type && type !== 0)) {
+    if (defaultValue !== undefined) {
+      return defaultValue
+    } else {
+      return '--'
+    }
+  }
+  let dictList = uni.getStorageSync(dictListKey)
+  let dicts = dictList[type]
+  if (dicts) {
+    for (let i = 0; i < dicts.length; i++) {
+      if (dicts[i].label && dicts[i].label.toString() === label.toString()) {
+        return dicts[i].value
+      }
+    }
+  }
+  if (defaultValue !== undefined) {
+    return defaultValue
+  } else {
+    return '--'
+  }
+}
+
+export function getDictList (type) {
+  let dictList = uni.getStorageSync(dictListKey)
+  if (!type && type !== 0) { // 不传参 返回全部字典
+    return  dictList
+  }
+  let dicts = dictList[type]
+  return dicts || []
+}
+export function setDictList(dictList){
+	uni.setStorageSync(dictListKey,dictList);
+}
+
+export default {getDictLabel, getDictValue, getDictList, setDictList}

+ 11 - 0
common/filter.js

@@ -0,0 +1,11 @@
+import Vue from 'vue'
+import moment from 'moment'
+
+Vue.filter('formatDate', function (value, formatString) {
+  formatString = formatString || 'YYYY-MM-DD HH:mm:ss'
+  if (value) {
+    return moment(value).format(formatString)
+  } else {
+    return '--'
+  }
+})

+ 167 - 0
common/graceChecker.js

@@ -0,0 +1,167 @@
+/**
+数据验证(表单验证)
+来自 grace.hcoder.net 
+作者 hcoder 深海
+*/
+module.exports = {
+	error:'',
+	check : function (data, rule){
+		for(var i = 0; i < rule.length; i++){
+			if (!rule[i].checkType){return true;}
+			if (!rule[i].name) {return true;}
+			if (!rule[i].errorMsg) {return true;}
+			let value = data
+			
+			rule[i].name.split('.').forEach((key)=>{
+				value = value[key]
+			})
+			if (!value) {this.error = rule[i].errorMsg; return false;}
+			switch (rule[i].checkType){
+				case 'string':
+					var reg = new RegExp('^.{' + rule[i].checkRule + '}$');
+					if(!reg.test(value)) {this.error = rule[i].errorMsg; return false;}
+				break;
+				case 'int':
+					var reg = new RegExp('^(-[1-9]|[1-9])[0-9]{' + rule[i].checkRule + '}$');
+					if(!reg.test(value)) {this.error = rule[i].errorMsg; return false;}
+					break;
+				break;
+				case 'between':
+					if (!this.isNumber(value)){
+						this.error = rule[i].errorMsg;
+						return false;
+					}
+					var minMax = rule[i].checkRule.split(',');
+					minMax[0] = Number(minMax[0]);
+					minMax[1] = Number(minMax[1]);
+					if (value > minMax[1] || value < minMax[0]) {
+						this.error = rule[i].errorMsg;
+						return false;
+					}
+				break;
+				case 'betweenD':
+					var reg = /^-?[1-9][0-9]?$/;
+					if (!reg.test(value)) { this.error = rule[i].errorMsg; return false; }
+					var minMax = rule[i].checkRule.split(',');
+					minMax[0] = Number(minMax[0]);
+					minMax[1] = Number(minMax[1]);
+					if (value > minMax[1] || value < minMax[0]) {
+						this.error = rule[i].errorMsg;
+						return false;
+					}
+				break;
+				case 'betweenF': 
+					var reg = /^-?[0-9][0-9]?.+[0-9]+$/;
+					if (!reg.test(value)){this.error = rule[i].errorMsg; return false;}
+					var minMax = rule[i].checkRule.split(',');
+					minMax[0] = Number(minMax[0]);
+					minMax[1] = Number(minMax[1]);
+					if (value > minMax[1] || value < minMax[0]) {
+						this.error = rule[i].errorMsg;
+						return false;
+					}
+				break;
+				case 'same':
+					if (value != rule[i].checkRule) { this.error = rule[i].errorMsg; return false;}
+				break;
+				case 'notsame':
+					if (value == rule[i].checkRule) { this.error = rule[i].errorMsg; return false; }
+				break;
+				case 'isEmail':
+					var reg = /^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
+					if (!reg.test(value)) { this.error = rule[i].errorMsg || rule[i].name + '不是合法的邮箱格式!'; return false; }
+				break;
+				case 'isMobile':
+					var reg = /^1[0-9]{10,10}$/;
+					if (!reg.test(value)) { this.error = rule[i].errorMsg || rule[i].name + '不是合法的手机号码!'; return false; }
+				break;
+				case 'isUrl':
+					var reg = /^http[s]?:\/\/.*/
+					if (!reg.test(value)) { this.error = rule[i].errorMsg|| rule[i].name + '不是合法的URL!'; return false; }
+				break;
+				case 'zipcode':
+					var reg = /^[0-9]{6}$/;
+					if (!reg.test(value)) { this.error = rule[i].errorMsg; return false; }
+				break;
+				case 'reg':
+					var reg = new RegExp(rule[i].checkRule);
+					if (!reg.test(value)) { this.error = rule[i].errorMsg; return false; }
+				break;
+				case 'in':
+					if(rule[i].checkRule.indexOf(value) == -1){
+						this.error = rule[i].errorMsg; return false;
+					}
+				break;
+				case 'notnull':
+					if(value == null || value.length < 1){this.error = rule[i].errorMsg; return false;}
+				break;
+			}
+		}
+		return true;
+	},
+
+	checkFormData : function (data){
+		for(i=0; i<data.length; i++){
+			let item = data[i]
+			let name = item.name
+			let value = item.value
+			if(!(item.readable && item.writable)){
+				continue
+			}
+			if(item.options.required){
+				if(value == null || value.length < 1){
+					return name+": "+ (item.options.requiredMessage || '必填项不能为空!')
+				}
+			}
+			if(item.options.dataType  && item.options.dataTypeCheck){
+				switch (item.options.dataType ){
+					case 'number':
+						var reg = /^-?[0-9]+(\.\d+)?$/
+						if (!reg.test(value)) {
+							return name+": "+ item.options.dataTypeMessage
+						}
+					break;
+					case 'integer':
+						if (!(/^0$/.test(value) || /^(-[1-9]|[1-9])[0-9]*$/.test(value))) { 
+							return name+": "+ item.options.dataTypeMessage
+						}
+					break;
+					case 'float':
+						if (!(/^\d+(\.\d+)?$/.test(value) || /^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$/)) {
+							return name+": "+ item.options.dataTypeMessage
+						}
+					break;
+					case 'url':
+						var reg = /^http[s]?:\/\/.*/
+						if (!reg.test(value)) {
+							return name+": "+ item.options.dataTypeMessage
+						}
+					break;
+					case 'email':
+						var reg = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/
+						if (!reg.test(value)) {
+							return name+": "+ item.options.dataTypeMessage
+						}
+					break;
+					case 'hex':
+						var reg = /^[0-9a-fA-F]{1,3}$/
+						if (!reg.test(value)) {
+							return name+": "+ item.options.dataTypeMessage
+						}
+					break;
+				}
+			};
+			if(item.options.pattern && item.options.patternMessage && item.options.patternCheck){
+				var reg = new RegExp(item.options.pattern)
+				if (!reg.test(value)) {
+					return name+": "+ item.options.patternMessage
+				}
+			}
+		}
+		return ''
+	},
+	isNumber : function (checkVal){
+		var reg = /^-?[1-9][0-9]?.?[0-9]*$/;
+		return reg.test(checkVal);
+	}
+}

+ 114 - 0
common/helper.js

@@ -0,0 +1,114 @@
+/**
+ * 用于定义公用的方法,定义全局参数
+ * 
+ * 
+ */
+// 全局变量
+const globalData = {
+	
+}
+
+// 格式化时间
+const formatDate = function(time, cFormat) {
+	if (arguments.length === 0) {
+		return null
+	}
+	if (!time) {
+		return '';
+	}
+
+	let fmt = cFormat || 'yyyy-MM-dd HH:mm:ss';
+
+	let date;
+	if (typeof time === 'object') {
+		date = time;
+	} else if (typeof time === 'string') {
+		time = time.replace(/-/g,'/');			// 为了兼容ios,ios只能转换2019/12/12这种时间格式
+		date = new Date(time);
+	} else {
+		date = new Date(parseInt(time));
+	}
+
+	var o = {
+		"M+": date.getMonth() + 1, //月份
+		"d+": date.getDate(), //日
+		"h+": date.getHours() % 12 == 0 ? 12 : date.getHours() % 12, //小时
+		"H+": date.getHours(), //小时
+		"m+": date.getMinutes(), //分
+		"s+": date.getSeconds(), //秒
+		"q+": Math.floor((date.getMonth() + 3) / 3), //季度
+		"S": date.getMilliseconds() //毫秒
+	};
+	var week = {
+		"0": "\u65e5",
+		"1": "\u4e00",
+		"2": "\u4e8c",
+		"3": "\u4e09",
+		"4": "\u56db",
+		"5": "\u4e94",
+		"6": "\u516d"
+	};
+	if (/(y+)/.test(fmt)) {
+		fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
+	}
+	if (/(E+)/.test(fmt)) {
+		fmt = fmt.replace(RegExp.$1, ((RegExp.$1.length > 1) ? (RegExp.$1.length > 2 ? "\u661f\u671f" : "\u5468") : "") +
+			week[date.getDay() + ""]);
+	}
+	for (var k in o) {
+		if (new RegExp("(" + k + ")").test(fmt)) {
+			fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
+		}
+	}
+	return fmt;
+}
+
+// 获取随机数
+const getUuid = function() {
+    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
+        return (c === 'x' ? (Math.random() * 16 | 0) : ('r&0x3' | '0x8')).toString(16)
+    })
+}
+
+// ajax错误处理
+const catchError = function(error) {
+    let _this = this;
+    if (error.response) {
+      switch (error.response.status) {
+        case 400:
+          _this.$message({
+            message: error.response.data.msg || '请求参数异常',
+            type: 'error'
+          });
+          break;
+        case 401:
+        //   sessionStorage.removeItem('user');
+          _this.$message({
+            message: error.response.data.msg || '密码错误或账号不存在!',
+            type: 'warning',
+            onClose: function(){
+              location.reload();
+            }
+          });
+          break;
+        case 403:
+          _this.$message({
+            message: error.response.data.msg || '无访问权限,请联系企业管理员',
+            type: 'warning'
+          });
+          break;
+        default:
+          _this.$message({
+            message: error.response.data.msg || '服务端异常,请联系技术支持',
+            type: 'error'
+          });
+      }
+    };
+}
+
+export default {
+	globalData,			// 全局变量
+	formatDate,			// 格式化时间
+	getUuid,			// 获取uuid
+	catchError,			// ajax错误处理
+}

+ 146 - 0
common/request.js

@@ -0,0 +1,146 @@
+import * as $auth from "./auth"
+import BASE_URL from './config.js'
+import qs from 'qs'
+
+function error(res){
+	if (res.statusCode === 408 || res.statusCode === 401) {// 需要重新登录
+		$auth.removeUserToken();
+		uni.showToast({
+			title: res.data,
+			icon:"none"
+		})
+	}else if(res.statusCode === 404){
+		uni.showToast({
+			title:"404,路径找不到:"+res.data.path,
+			icon:"none"
+		})
+	}else if(res.statusCode === 503){
+		uni.showToast({
+			title:"服务不可用",
+			icon:"none"
+		})
+	}else if(res.statusCode === 504){
+		uni.showToast({
+			title:"网络连接错误",
+			icon:"none"
+		})
+	}else{
+		uni.showToast({
+			title:res.data,
+			icon:"none"
+		})
+	}
+}
+export function request(body){
+	let {url,method,data,header, params, responseType} = body
+	data = data || params || {};
+	header = header || {'Content-Type': 'application/json; charset=utf-8'}
+	method = method.toUpperCase() || "GET";
+	responseType = responseType || "text"
+	let token = $auth.getUserToken();
+	if(token){
+		header.token = token;			// 获取token值
+	}
+	if(method === 'POST' && header['Content-Type'] === 'application/x-www-form-urlencoded; charset=utf-8'){
+		data = qs.stringify(data,  { allowDots: true, arrayFormat: 'indices' })
+	}else if(method === 'GET' || method === 'DELETE' || method === 'PUT'){
+		url = url + '?' +  qs.stringify(data, { allowDots: true, arrayFormat: 'indices' }) 
+		data = null
+
+	}
+	
+	let promise = new Promise((resolve,reject)=>{
+		uni.request({
+			url: BASE_URL + url,
+			header:header,
+			data: data,
+			method: method,
+			responseType: responseType,
+			success: res => {
+				if(res && res.statusCode !== 200){
+					error(res);
+					reject(res)
+				}
+				resolve(res);
+			},
+			fail: (res) => {
+				uni.hideLoading();
+				error(res);
+				reject(res);
+			},
+			complete: () => {	
+			}
+		});
+	})
+	return promise;
+}
+
+// 单文件上传
+export function upload(url, filePath,filename, formData,header,success,fail){
+	let name = filename || 'file';
+	header = header || {};
+	let token = $auth.getUserToken();
+	if(token){
+		header.token = token;			// 获取token值
+	}
+	
+	let promise = new Promise((resolve,reject)=>{
+		uni.uploadFile({
+			url: BASE_URL + url,
+			filePath:filePath,
+			name: 'file', 
+			formData: formData || {},
+			header:header,
+			success: res => {
+				resolve(res.data);
+			},
+			fail: (res) => {
+				uni.hideLoading();
+				let err = JSON.parse(res);
+				error(err);
+				reject(err);
+			},
+			complete: () => {	
+			}
+		});
+	})
+	return promise;
+}
+
+export function download(url,header,success,fail){
+	header = header || {};
+	let token = $auth.getUserToken();
+	if(token){
+		header.token = token;			// 获取token值
+	}
+	if(!url){
+		return;
+	}
+	let downloadTask = uni.downloadFile({
+		url: url,
+		success: (res) => {
+			if(res.statusCode===200){
+				if(success){
+					success.call(null,res);
+				}
+			}else{
+				if(fail){
+					fail.call(null,res);
+				}
+			}
+		},
+		fail:(res) => {
+			let err = JSON.parse(res);
+			error(err);
+			if(fail){
+				fail.call(null,err)
+			}
+		},
+		complete: () => {
+			
+		}
+	});
+	return downloadTask;
+}
+
+export default request

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 88 - 0
common/util.js


+ 20 - 0
components/Am-FontAwesome/css/_animated.scss

@@ -0,0 +1,20 @@
+// Animated Icons
+// --------------------------
+
+.#{$fa-css-prefix}-spin {
+  animation: fa-spin 2s infinite linear;
+}
+
+.#{$fa-css-prefix}-pulse {
+  animation: fa-spin 1s infinite steps(8);
+}
+
+@keyframes fa-spin {
+  0% {
+    transform: rotate(0deg);
+  }
+
+  100% {
+    transform: rotate(360deg);
+  }
+}

+ 20 - 0
components/Am-FontAwesome/css/_bordered-pulled.scss

@@ -0,0 +1,20 @@
+// Bordered & Pulled
+// -------------------------
+
+.#{$fa-css-prefix}-border {
+  border: solid .08em $fa-border-color;
+  border-radius: .1em;
+  padding: .2em .25em .15em;
+}
+
+.#{$fa-css-prefix}-pull-left { float: left; }
+.#{$fa-css-prefix}-pull-right { float: right; }
+
+.#{$fa-css-prefix},
+.fas,
+.far,
+.fal,
+.fab {
+  &.#{$fa-css-prefix}-pull-left { margin-right: .3em; }
+  &.#{$fa-css-prefix}-pull-right { margin-left: .3em; }
+}

+ 21 - 0
components/Am-FontAwesome/css/_core.scss

@@ -0,0 +1,21 @@
+// Base Class Definition
+// -------------------------
+
+.#{$fa-css-prefix},
+.fas,
+.far,
+.fal,
+.fad,
+.fab {
+  -moz-osx-font-smoothing: grayscale;
+  -webkit-font-smoothing: antialiased;
+  display: inline-block;
+  font-style: normal;
+  font-variant: normal;
+  text-rendering: auto;
+  line-height: 1;
+}
+
+%fa-icon {
+  @include fa-icon;
+}

+ 6 - 0
components/Am-FontAwesome/css/_fixed-width.scss

@@ -0,0 +1,6 @@
+// Fixed Width Icons
+// -------------------------
+.#{$fa-css-prefix}-fw {
+  text-align: center;
+  width: $fa-fw-width;
+}

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1441 - 0
components/Am-FontAwesome/css/_icons.scss


+ 23 - 0
components/Am-FontAwesome/css/_larger.scss

@@ -0,0 +1,23 @@
+// Icon Sizes
+// -------------------------
+
+// makes the font 33% larger relative to the icon container
+.#{$fa-css-prefix}-lg {
+  font-size: (4em / 3);
+  line-height: (3em / 4);
+  vertical-align: -.0667em;
+}
+
+.#{$fa-css-prefix}-xs {
+  font-size: .75em;
+}
+
+.#{$fa-css-prefix}-sm {
+  font-size: .875em;
+}
+
+@for $i from 1 through 10 {
+  .#{$fa-css-prefix}-#{$i}x {
+    font-size: $i * 1em;
+  }
+}

+ 18 - 0
components/Am-FontAwesome/css/_list.scss

@@ -0,0 +1,18 @@
+// List Icons
+// -------------------------
+
+.#{$fa-css-prefix}-ul {
+  list-style-type: none;
+  margin-left: $fa-li-width * 5/4;
+  padding-left: 0;
+
+  > li { position: relative; }
+}
+
+.#{$fa-css-prefix}-li {
+  left: -$fa-li-width;
+  position: absolute;
+  text-align: center;
+  width: $fa-li-width;
+  line-height: inherit;
+}

+ 56 - 0
components/Am-FontAwesome/css/_mixins.scss

@@ -0,0 +1,56 @@
+// Mixins
+// --------------------------
+
+@mixin fa-icon {
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  display: inline-block;
+  font-style: normal;
+  font-variant: normal;
+  font-weight: normal;
+  line-height: 1;
+}
+
+@mixin fa-icon-rotate($degrees, $rotation) {
+  -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation})";
+  transform: rotate($degrees);
+}
+
+@mixin fa-icon-flip($horiz, $vert, $rotation) {
+  -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}, mirror=1)";
+  transform: scale($horiz, $vert);
+}
+
+
+// Only display content to screen readers. A la Bootstrap 4.
+//
+// See: http://a11yproject.com/posts/how-to-hide-content/
+
+@mixin sr-only {
+  border: 0;
+  clip: rect(0, 0, 0, 0);
+  height: 1px;
+  margin: -1px;
+  overflow: hidden;
+  padding: 0;
+  position: absolute;
+  width: 1px;
+}
+
+// Use in conjunction with .sr-only to only display content when it's focused.
+//
+// Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1
+//
+// Credit: HTML5 Boilerplate
+
+@mixin sr-only-focusable {
+  &:active,
+  &:focus {
+    clip: auto;
+    height: auto;
+    margin: 0;
+    overflow: visible;
+    position: static;
+    width: auto;
+  }
+}

+ 24 - 0
components/Am-FontAwesome/css/_rotated-flipped.scss

@@ -0,0 +1,24 @@
+// Rotated & Flipped Icons
+// -------------------------
+
+.#{$fa-css-prefix}-rotate-90  { @include fa-icon-rotate(90deg, 1);  }
+.#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); }
+.#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); }
+
+.#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); }
+.#{$fa-css-prefix}-flip-vertical   { @include fa-icon-flip(1, -1, 2); }
+.#{$fa-css-prefix}-flip-both, .#{$fa-css-prefix}-flip-horizontal.#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(-1, -1, 2); }
+
+// Hook for IE8-9
+// -------------------------
+
+:root {
+  .#{$fa-css-prefix}-rotate-90,
+  .#{$fa-css-prefix}-rotate-180,
+  .#{$fa-css-prefix}-rotate-270,
+  .#{$fa-css-prefix}-flip-horizontal,
+  .#{$fa-css-prefix}-flip-vertical,
+  .#{$fa-css-prefix}-flip-both {
+    filter: none;
+  }
+}

+ 5 - 0
components/Am-FontAwesome/css/_screen-reader.scss

@@ -0,0 +1,5 @@
+// Screen Readers
+// -------------------------
+
+.sr-only { @include sr-only; }
+.sr-only-focusable { @include sr-only-focusable; }

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 2066 - 0
components/Am-FontAwesome/css/_shims.scss


+ 31 - 0
components/Am-FontAwesome/css/_stacked.scss

@@ -0,0 +1,31 @@
+// Stacked Icons
+// -------------------------
+
+.#{$fa-css-prefix}-stack {
+  display: inline-block;
+  height: 2em;
+  line-height: 2em;
+  position: relative;
+  vertical-align: middle;
+  width: ($fa-fw-width*2);
+}
+
+.#{$fa-css-prefix}-stack-1x,
+.#{$fa-css-prefix}-stack-2x {
+  left: 0;
+  position: absolute;
+  text-align: center;
+  width: 100%;
+}
+
+.#{$fa-css-prefix}-stack-1x {
+  line-height: inherit;
+}
+
+.#{$fa-css-prefix}-stack-2x {
+  font-size: 2em;
+}
+
+.#{$fa-css-prefix}-inverse {
+  color: $fa-inverse;
+}

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1458 - 0
components/Am-FontAwesome/css/_variables.scss


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 17 - 0
components/Am-FontAwesome/css/brands.scss


+ 16 - 0
components/Am-FontAwesome/css/fontawesome.scss

@@ -0,0 +1,16 @@
+/*!
+ * Font Awesome Free 5.11.2 by @fontawesome - https://fontawesome.com
+ * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
+ */
+@import 'variables';
+@import 'mixins';
+@import 'core';
+@import 'larger';
+@import 'fixed-width';
+@import 'list';
+@import 'bordered-pulled';
+@import 'animated';
+@import 'rotated-flipped';
+@import 'stacked';
+@import 'icons';
+@import 'screen-reader';

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 18 - 0
components/Am-FontAwesome/css/regular.scss


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 19 - 0
components/Am-FontAwesome/css/solid.scss


+ 6 - 0
components/Am-FontAwesome/css/v4-shims.scss

@@ -0,0 +1,6 @@
+/*!
+ * Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com
+ * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
+ */
+@import 'variables';
+@import 'shims';

+ 194 - 0
components/Am-FontAwesome/index.vue

@@ -0,0 +1,194 @@
+<template>
+	<block v-if="stack && stop">
+		<view class="fa-stack" :style="{ fontSize: `${ size }rpx` }" @click.stop="onClick">
+			<block v-for="(iconItem, iconIndex) in stack" :key="iconIndex">
+				<FontAwesome
+					:stackIndex="iconItem.stackIndex"
+					:type="iconItem.type"
+					:color="iconItem.color || false"
+					:fw="iconItem.fw || false"
+					:rotate="iconItem.rotate || false"
+					:flip="iconItem.flip || false"
+					:spin="iconItem.spin || false"
+					:pulse="iconItem.pulse || false"
+					:border="iconItem.border || false"
+					:pullLeft="iconItem.pullLeft || false"
+					:pullRight="iconItem.pullRight || false"
+					:inverse="iconItem.inverse || false"
+				></FontAwesome>
+			</block>
+		</view>
+	</block>
+	<block v-else-if="stack">
+		<view class="fa-stack" :style="{ fontSize: `${ size }rpx` }" @click="onClick">
+			<block v-for="(iconItem, iconIndex) in stack" :key="iconIndex">
+				<FontAwesome
+					:stackIndex="iconItem.stackIndex"
+					:type="iconItem.type"
+					:color="iconItem.color || false"
+					:fw="iconItem.fw || false"
+					:rotate="iconItem.rotate || false"
+					:flip="iconItem.flip || false"
+					:spin="iconItem.spin || false"
+					:pulse="iconItem.pulse || false"
+					:border="iconItem.border || false"
+					:pullLeft="iconItem.pullLeft || false"
+					:pullRight="iconItem.pullRight || false"
+					:inverse="iconItem.inverse || false"
+				></FontAwesome>
+			</block>
+		</view>
+	</block>
+	<block v-else-if="stop">
+		<view
+			@click.stop="onClick"
+			:class="[
+				type,
+				{ 'fa-fw' : fw },
+				rotate ? `fa-rotate-${ rotate }` : '',
+				flip ? `fa-flip-${ flip }` : '',
+				{ 'fa-spin' : spin },
+				{ 'fa-pulse' : pulse },
+				{ 'fa-border' : border },
+				{ 'fa-pull-left' : pullLeft },
+				{ 'fa-pull-right' : pullRight },
+				stackIndex ? `fa-stack-${ stackIndex }x` : '',
+				{ 'fa-inverse' : inverse }
+			]"
+			:style="[
+				size ? { fontSize: `${ size }rpx` } : {},
+				color ? { color } : {}
+			]"
+		></view>
+	</block>
+	<block v-else>
+		<view
+			@click="onClick"
+			:class="[
+				type,
+				{ 'fa-fw' : fw },
+				rotate ? `fa-rotate-${ rotate }` : '',
+				flip ? `fa-flip-${ flip }` : '',
+				{ 'fa-spin' : spin },
+				{ 'fa-pulse' : pulse },
+				{ 'fa-border' : border },
+				{ 'fa-pull-left' : pullLeft },
+				{ 'fa-pull-right' : pullRight },
+				stackIndex ? `fa-stack-${ stackIndex }x` : '',
+				{ 'fa-inverse' : inverse }
+			]"
+			:style="[
+				size ? { fontSize: `${ size }rpx` } : {},
+				color ? { color } : {}
+			]"
+		></view>
+	</block>
+	<!-- app端可简写一些class属性 -->
+	<!-- <view
+		@click.stop="onClick"
+		:class="[
+			type,
+			{ 'fa-fw' : fw },
+			{ [`fa-rotate-${ rotate }`] : rotate },
+			{ [`fa-flip-${ flip }`] : flip },
+			{ ' fa-spin' : spin },
+			{ 'fa-pulse' : pulse },
+			{ 'fa-border' : border },
+			{ 'fa-pull-left' : pullLeft },
+			{ 'fa-pull-right' : pullRight },
+			{ [`fa-stack-${ stackIndex }x`] : stackIndex },
+			{ 'fa-inverse' : inverse }
+		]"
+		:style="[
+			{ fontSize: `${ size }rpx` },
+			color ? { color } : {}
+		]">
+	</view>-->
+</template>
+
+<script>
+import FontAwesome from "@/components/Am-FontAwesome/index.vue";
+export default {
+	name: "FontAwesome",
+	components: {
+		FontAwesome,
+	},
+	props: {
+		type: {
+			type: String,
+		},
+		size: {
+			type: [String, Number, Boolean],
+			default: false,
+		},
+		color: {
+			type: [String, Boolean],
+			default: false,
+		},
+		fw: {
+			type: Boolean,
+			default: false,
+		},
+		rotate: {
+			type: [String, Boolean, Number],
+			default: false,
+		},
+		flip: {
+			type: [String, Boolean],
+			default: false,
+		},
+		spin: {
+			type: Boolean,
+			default: false,
+		},
+		pulse: {
+			type: Boolean,
+			default: false,
+		},
+		border: {
+			type: Boolean,
+			default: false,
+		},
+		pullLeft: {
+			type: Boolean,
+			default: false,
+		},
+		pullRight: {
+			type: Boolean,
+			default: false,
+		},
+		stack: {
+			type: [Array, Boolean],
+			default: false,
+		},
+		stackIndex: {
+			type: [String, Boolean, Number],
+			default: false,
+		},
+		inverse: {
+			type: Boolean,
+			default: false,
+		},
+		opacity: {
+			type: Boolean,
+			default: false,
+		},
+		stop: {
+			type: Boolean,
+			default: false,
+		},
+	},
+	methods: {
+		onClick() {
+			this.$emit("click");
+		},
+	},
+};
+</script>
+
+<style lang="scss" scoped>
+@import "css/fontawesome.scss";
+@import "css/solid.scss";
+@import "css/brands.scss";
+@import "css/regular.scss";
+</style>

+ 187 - 0
components/generate-form/generate-form.vue

@@ -0,0 +1,187 @@
+<template>
+	<view>
+		<form>
+			<view class="cu-form-group" v-if="item.readable" :class="index===0?'margin-top':''" v-for="(item,index) in formData" :key="index">
+				<view class="title">
+					<text class="red-color " v-if="item.options.required">* </text> {{item.name}}
+				</view>
+				<template v-if="item.type=='input'">				
+					<!-- 普通输入框 -->
+					<input :placeholder='item.placeholder'  :disabled="!item.writable"  v-model="item.value"></input>
+				</template>	
+				<template v-if="item.type=='textarea' || item.type=='editor'">
+					<!-- 多行文本输入框 -->
+					<textarea maxlength="-1"  :placeholder='item.placeholder' :disabled="!item.writable"   v-model="item.value"></textarea>
+				</template>	
+				<template v-if="item.type=='number'">
+					<!-- 普通输入框 -->
+					<input type="number" :placeholder='item.placeholder' :disabled="!item.writable"   v-model="item.value"></input>
+				</template>	
+				<template v-if="item.type=='radio'">
+					<!-- 单选框 -->
+				
+					<jp-radio-group  v-if="item.options.remote === 3"  v-model="item.value">
+						<label v-for="(option, index) in $dictUtils.getDictList(item.options.dictType)">
+							<view>
+								{{option.label}}
+								<radio class='blue radio' :disabled="!item.writable" :value="option.value"  :class="item.value==option.value?'checked':''" :checked="item.value==option.value?true:false" ></radio>
+							</view>
+						</label>
+					</jp-radio-group>
+					<jp-radio-group  v-else-if="item.options.showLabel"  v-model="item.value">
+						<label v-for="(option, index) in item.options.options">
+							<view>
+								{{option.label}}
+								<radio class='blue radio' :disabled="!item.writable" :value="option.value"  :class="item.value==option.value?'checked':''" :checked="item.value==option.value?true:false" ></radio>
+							</view>
+						</label>
+					</jp-radio-group>
+					<jp-radio-group  v-else  v-model="item.value">
+						<label v-for="(option, index) in item.options.options">
+							<view>
+								{{option.value}}
+								<radio class='blue radio' :disabled="!item.writable"  :value="option.value"  :checked="item.value==option.value?true:false" ></radio>
+							</view>
+						</label>
+					</jp-radio-group>
+				</template>	
+				<template v-if="item.type=='checkbox'">
+					<jp-checkbox-group v-if="item.options.remote === 3" v-model="item.value">
+						<label v-for="(option, index) in $dictUtils.getDictList(item.options.dictType)">
+							<view>
+								{{option.label || option.value}}
+								<checkbox :disabled="!item.writable"  class="blue" :value="option.value"  :class="(','+item.value+',').indexOf(','+option.value+',')>=0?'checked':''" :checked="(','+item.value+',').indexOf(','+option.value+',')>=0" ></checkbox>
+							</view>
+						</label>
+					</jp-checkbox-group>
+					
+					<jp-checkbox-group v-else-if="item.options.showLabel" v-model="item.value">
+						<label v-for="(option, index) in item.options.options">
+							<view>
+								{{option.label}}
+								<checkbox :disabled="!item.writable"  class="blue" :value="option.value"  :class="(','+item.value+',').indexOf(','+option.value+',')>=0?'checked':''" :checked="(','+item.value+',').indexOf(','+option.value+',')>=0" ></checkbox>
+							</view>
+						</label>
+					</jp-checkbox-group>
+					<jp-checkbox-group v-else v-model="item.value">
+						<label v-for="(option, index) in item.options.options">
+							<view>
+								{{option.value}}
+								<checkbox  class="blue" :disabled="!item.writable"  :value="option.value"  :class="(','+item.value+',').indexOf(','+option.value+',')>=0?'checked':''" :checked="(','+item.value+',').indexOf(','+option.value+',')>=0" ></checkbox>
+							</view>
+						</label>
+					</jp-checkbox-group>
+				</template>	
+				<template v-if="item.type=='time'">
+					<!-- 时间控件 -->
+					<jp-datetime-picker  v-model="item.value" :placeholder='item.placeholder' :disabled="!item.writable" mode="time"></jp-datetime-picker>
+				</template>	
+				<template v-if="item.type=='date'">
+					<!-- 日期控件 -->
+					<jp-datetime-picker  v-model="item.value" :placeholder='item.placeholder' :disabled="!item.writable" mode="date"></jp-datetime-picker>
+				</template>	
+				<template v-if="item.type=='rate'">
+					<!-- 评分 -->
+					<uni-rate :size="18":disabled="!item.writable" :allowHalf="item.options.allowHalf" v-model="item.value" :max="item.options.max"/>
+				</template>	
+				<template v-if="item.type=='color'">
+					<!-- 颜色选择框 -->
+					<jp-color-picker :disabled="!item.writable" v-model="item.value" ></jp-color-picker>
+				</template>	
+				<template v-if="item.type=='select'">
+					<!-- 选择框 -->
+					<jp-picker :disabled="!item.writable" v-if="item.options.remote === 3" v-model="item.value" :range="$dictUtils.getDictList(item.options.dictType)">
+					</jp-picker>
+					<jp-picker :disabled="!item.writable" v-else-if="item.options.showLabel" v-model="item.value" :range="item.options.options">
+					</jp-picker>
+					<jp-picker :disabled="!item.writable" v-else v-model="item.value" rangeKey="value" :range="item.options.options">
+					</jp-picker>
+				</template>	
+				<template v-if="item.type=='switch'">
+					<!-- 开关 -->
+					<jp-switch :placeholder='item.placeholder' :disabled="!item.writable"   v-model="item.value"></jp-switch>
+				</template>	
+				<template v-if="item.type=='slider'">
+					<!-- 滑块 -->
+					<jp-slider  :placeholder='item.placeholder' :disabled="!item.writable"   v-model="item.value"></jp-slider>
+				</template>	
+				<template v-if="item.type=='text'">
+					<!-- 普通输入框 -->
+					<text>{{item.value}}</text>
+				</template>	
+				<template v-if="item.type=='html'">
+					<!-- 普通输入框 -->
+					<view v-html="item.value"></view>
+				</template>	
+				<template v-if="item.type=='imgupload' || item.type=='fileupload'">
+					<!-- 图片上传 -->
+					<jp-image-upload :disabled="!item.writable"   v-model="item.value"></jp-image-upload>
+				</template>	
+				<template v-if="item.type=='user'">
+					<!-- 用户选择框 -->
+					<user-select  :disabled="!item.writable"   v-model="item.value"></user-select>
+				</template>	
+				<template v-if="item.type=='office'">
+					<!-- 机构选择框 -->
+					<jp-office-select :disabled="!item.writable"   v-model="item.value"></jp-office-select>
+				</template>	
+				<template v-if="item.type=='area'">
+					<!-- 普通输入框 -->
+					<jp-area-select :disabled="!item.writable"  v-model="item.value"></jp-area-select>
+				</template>	
+				<template v-if="item.type=='dict'">
+					<!-- 字典 -->
+					<jp-picker :disabled="!item.writable"  v-model="item.value" :range="$dictUtils.getDictList(item.options.dictType)"></jp-picker>
+				</template>	
+			</view>								
+		</form>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'activeForm',
+		
+		watch:{
+			formData:{
+				handler (val) {
+					console.log(this.formData)
+				},
+				immediate: true,
+				deep: false
+			}
+		},
+		props: {
+			formData:{
+				type:Array,
+				default:function(){
+					return []
+				}
+			}
+		},
+		methods: {	
+
+		}
+	}
+</script>
+
+<style lang="scss">
+.uni-list-cell {
+    justify-content: flex-start
+}
+.cu-form-group{
+
+    uni-checkbox-group{
+		text-align: right;
+	}
+	uni-radio-group {
+		text-align: right;
+	}
+	uni-checkbox, uni-radio {
+	    position: relative;
+	    margin-top: 7px;
+		margin-left:7px;
+		margin-bottom: 7px;
+	}
+}
+</style>

+ 120 - 0
components/jp-area-select/jp-area-select.vue

@@ -0,0 +1,120 @@
+<template>
+	<view>
+		<view class="action arrow"  @tap="showModal" data-target="bottomModal">
+			<view class="uni-input upicker  ellipsis-description" >{{labels?labels:'请选择'}}</view>
+		</view>
+		<view class="cu-modal bottom-modal" style="min-height: 200upx;" :class="modalName=='bottomModal'?'show':''">
+			<view class="cu-dialog">
+				<view class="cu-bar bg-white">
+					<view class="action text-blue" @tap="hideModal">取消</view>
+					<view class="action text-green" @tap="selectArea">确定</view>
+				</view>
+				<view>
+					  <ly-tree :tree-data="data"
+						:props="props" 
+						node-key="id" 
+						:checkOnClickNode ="true"
+						:showRadio="showRadio"
+						:show-checkbox ="showCheckBox"
+						:checkOnlyLeaf = "checkOnlyLeaf"
+						ref="userTree" />
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import AreaService from "@/api/sys/AreaService"
+	export default {
+		data() {
+			return {
+				data: [],
+				modalName: null,
+				labels: null,
+				treeList: []
+			};
+		},
+		props: {
+		    limit: Number,
+		    value: String,
+		    size: String,
+		    readonly: {
+		      type: Boolean,
+		      default: () => { return false }
+		    },
+			checkOnlyLeaf: {
+		      type: Boolean,
+		      default: () => { return false }
+		    },
+			showRadio: {
+		      type: Boolean,
+		      default: () => { return true }
+		    },
+			showCheckBox: {
+			  type: Boolean,
+			  default: () => { return false }
+			},
+		    disabled: {
+		      type: Boolean,
+		      default: () => { return false }
+		    },
+			props: {
+				type: Object,
+				default: () => {
+					return {
+						children: 'children',
+						label: 'name'
+					}
+				}
+			}
+		  },
+		mounted() {
+			new AreaService().treeData().then(({data})=>{
+				this.data = data
+				this.setTreeList(this.data)
+				let labelArra = []
+				if(this.value){
+					this.treeList.forEach((area) => {
+					  if (this.value === area.id) {
+						labelArra.push(area.name)
+					  }
+					})
+					this.labels = labelArra.join(',')
+				}
+			}).catch((e)=>{
+				 throw e
+			})
+		},
+		methods:{
+			setTreeList (datas) { // 遍历树  获取id数组
+			      for (var i in datas) {
+			        this.treeList.push(datas[i])
+			        if (datas[i].children) {
+			          this.setTreeList(datas[i].children)
+			        }
+			      }
+			    },
+			selectArea () {
+				let ids = this.$refs.userTree.getCheckedNodes().map((item)=>{
+					return item.id
+				}).join(",");
+				let names = this.$refs.userTree.getCheckedNodes().map((item)=>{
+					return item.name
+				}).join(",");
+				this.labels = names
+				this.$emit('input', ids)
+				this.hideModal()
+			},
+			showModal(e) {
+				if(this.disabled){
+					return
+				}
+				this.modalName = e.currentTarget.dataset.target
+			},
+			hideModal(e) {
+				this.modalName = null
+			}
+		}
+	}
+</script>

+ 26 - 0
components/jp-checkbox-group/jp-checkbox-group.vue

@@ -0,0 +1,26 @@
+<template>
+		<checkbox-group @change="CheckboxChange">
+			<slot></slot>
+		</checkbox-group>
+</template>
+
+<script>
+	export default {
+		props: {
+		    value: Array,
+			disabled: {
+				type: Boolean,
+				default: false
+			}
+		},
+		methods:{
+			CheckboxChange(evt) {
+				this.$emit('input', evt.detail.value)
+			},
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 26 - 0
components/jp-checkbox-group2/jp-checkbox-group2.vue

@@ -0,0 +1,26 @@
+<template>
+		<checkbox-group @change="CheckboxChange">
+			<slot></slot>
+		</checkbox-group>
+</template>
+
+<script>
+	export default {
+		props: {
+		    value: String,
+			disabled: {
+				type: Boolean,
+				default: false
+			}
+		},
+		methods:{
+			CheckboxChange(evt) {
+				this.$emit('input', evt.detail.value.join(','))
+			},
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 52 - 0
components/jp-color-picker/README.md

@@ -0,0 +1,52 @@
+支持初始化颜色、自适应容器大小方便自定义开发、返回hex、rgba/rgb两种颜色格式。
+
+## 属性/事件列表:
+
+| 属性/事件 | 必填 |  默认  |  功能  |
+| :-----:  | :-----:  | :-----:  | :-----  |
+| color  | 否 |  ''     | 初始化picker的颜色 |
+| show  | 否 |   true    | 控制picker显示隐藏 |
+| @pickerColor |   否   |   null   | 取色器发生取色动作触发,返回两种颜色格式:`{hex: '#ff0000', rgb: 'rgb(255, 0, 0)'}` |
+
+
+
+## Demo:
+
+```
+
+// 这里演示在uni-modal中显示color-picker,color-picker支持自适应容器
+<uni-modal>
+    <div class="uni-mask"></div>
+    <div class="uni-modal" style="padding: 20rpx;">
+    <color-picker :show='true' :color="color" @pickerColor="pickerColor"></color-picker>
+    <div class="actions">
+        <i class="iconfont icon-del"></i>
+        <i class="iconfont icon-yes"></i>
+    </div>
+    </div>
+</uni-modal>
+
+```
+
+```
+
+import colorPicker from "../../components/colorPicker";
+
+export default {
+  components: { colorPicker },
+  data() {
+    return {
+      color: '#123456f0'
+    };
+  },
+  methods: {
+    pickerColor(color) {
+      this.color = color.hex
+    }
+  }
+};
+
+```
+
+
+

+ 320 - 0
components/jp-color-picker/colorPicker.vue

@@ -0,0 +1,320 @@
+<template>
+    <div class="color-picker" v-if="show">
+      <div ref="slider" class="sv-picker" @touchstart="setSlider($event, 'sv')" @touchmove="moveSlide($event, 'sv')">
+        <div class="sv-picker-background" :style="{backgroundColor: svBackgroundColor}"></div>
+        <div class="sv-picker-background" :style="{background: 'linear-gradient(to right, white, #ffffff00)'}"></div>
+        <div class="sv-picker-background" :style="{background: 'linear-gradient(to top, black, #ffffff00)'}"></div>
+        <view class="sv-slider" :style="svSliderStyle" @touchstart="touchSlider($event, 'sv')" @touchmove="moveSlide($event, 'sv')"></view>
+      </div>
+      <div class="result">
+        <div class="result-color alpha-background-image">
+          <div class="alpha-background" :style="{background: pickedColor.rgb}"></div>
+        </div>
+        <div class="result-text">
+          <p>{{pickedColor.rgb}}</p>
+          <p>{{pickedColor.hex}}</p>
+        </div>
+      </div>
+      <div class="hue-slider" @touchstart="setSlider($event, 'hue')" @touchmove="moveSlide($event, 'hue')">
+        <view class="slider" :style="hueSliderStyle" @touchstart="touchSlider($event, 'hue')" @touchmove="moveSlide($event, 'hue')"></view>
+      </div>
+      <div class="alpha-slider alpha-background-image" @touchstart="setSlider($event, 'alpha')" @touchmove="moveSlide($event, 'alpha')">
+        <div class="alpha-background" :style="{background: alphaBackground}"></div>
+        <view class="slider" :style="alphaSliderStyle" @touchstart="touchSlider($event, 'alpha')" @touchmove="moveSlide($event, 'alpha')"></view>
+      </div>
+    </div>
+</template>
+
+<script>
+export default {
+  props: {
+    color: {
+      value: String,
+      default: ''
+    },
+    show: {
+      value: Boolean,
+      default: ''
+    },
+  },
+  data() {
+    return {
+      hueSlider: 0,
+      alphaSlider: 0,
+      saturationSlider: 0,
+      valueSlider: 0,
+      pickerWidth: 0,
+      pickerOffsetX: 0,
+      halfSilder: uni.getSystemInfoSync().windowWidth / 750 * 15,
+    }
+  },
+  mounted() {
+    const sliderInfo = this.$refs.slider.getBoundingClientRect()
+    
+    this.pickerWidth = sliderInfo.width
+    this.pickerOffsetX = sliderInfo.x
+    this.pickerOffsetY = sliderInfo.y
+
+    this.alphaSlider = sliderInfo.width
+    this.saturationSlider = sliderInfo.width
+  },
+  watch: {
+    color: {
+      handler() {
+        if (this.color && this.color !== this.pickedColor.hex) {
+          this.$nextTick(() => {
+            const {r,g,b,a} = hexToRgba(this.color)
+            const {h, s, v} = rgbToHsv(r, g, b)
+            this.hueSlider = h * this.pickerWidth
+            this.alphaSlider = a * this.pickerWidth
+            this.saturationSlider = s * this.pickerWidth
+            this.valueSlider = this.pickerWidth - v * this.pickerWidth
+          })
+        }
+      },
+      immediate: true
+    }
+  },
+  computed: {
+    pickedHueColor() {
+      const hue = this.hueSlider / this.pickerWidth
+      return hsvToRgb(hue, 1, 1)
+    },
+    pickedColor() {
+      if (!this.pickerWidth) {
+        return {r: 0, g: 0, b: 0, a: 0}
+      }
+      const hue = this.hueSlider / this.pickerWidth
+      const saturation = this.saturationSlider / this.pickerWidth
+      const value = (this.pickerWidth - this.valueSlider) / this.pickerWidth
+      const alpha = this.alphaSlider / this.pickerWidth
+      
+      const rgb = this.pickedHueColor
+      let color
+      if (alpha === 1) {
+        color = {...rgb, a: alpha, rgb: `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`, hex: rgbaToHex(rgb.r, rgb.g, rgb.b, 255)}
+      } else {
+        color = {...rgb, a: alpha, rgb: `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${Math.round(alpha * 100) / 100})`, hex: rgbaToHex(rgb.r, rgb.g, rgb.b, Math.round(alpha * 255))}
+      }
+
+      return color
+    },
+    svBackgroundColor() {
+      return `rgb(${this.pickedHueColor.r}, ${this.pickedHueColor.g}, ${this.pickedHueColor.b})`
+    },
+    alphaBackground() {
+      return `linear-gradient(to right, 
+      rgba(${this.pickedHueColor.r}, ${this.pickedHueColor.g}, ${this.pickedHueColor.b}, 0), 
+      rgba(${this.pickedHueColor.r}, ${this.pickedHueColor.g}, ${this.pickedHueColor.b}, 1))`
+    },
+    hueSliderStyle() {
+      return {transform: `translate(${this.hueSlider - this.halfSilder}px, -50%)`}
+    },
+    alphaSliderStyle() {
+      return {transform: `translate(${this.alphaSlider - this.halfSilder}px, -50%)`}
+    },
+    svSliderStyle() {
+      return {transform: `translate(${this.saturationSlider - this.halfSilder}px, ${this.valueSlider - this.halfSilder}px)`}
+    },
+  },
+  methods: {
+    touchSlider(e, component) {
+      if (component === 'sv') {
+        this.startLeft = this.saturationSlider
+        this.startPageX = e.touches[0].pageX
+        this.startTop = this.valueSlider
+        this.startPageY = e.touches[0].pageY
+      } else {
+        this.startLeft = this[component + 'Slider']
+        this.startPageX = e.touches[0].pageX
+      }
+    },
+    moveSlide(e, component) {
+      if (component === 'sv') {
+        this.setSliderValue('saturation', this.startLeft + e.touches[0].pageX - this.startPageX)
+        this.setSliderValue('value', this.startTop + e.touches[0].pageY - this.startPageY)
+      } else {
+        this.setSliderValue(component, this.startLeft + e.touches[0].pageX - this.startPageX)
+      }
+
+      this.emitPickedColor()
+    },
+    setSlider(e, component) {
+      if (component === 'sv') {
+        this.setSliderValue('saturation', e.touches[0].pageX - this.pickerOffsetX)
+        this.setSliderValue('value', e.touches[0].pageY - this.pickerOffsetY)
+      } else {
+        this.setSliderValue(component, e.touches[0].pageX - this.pickerOffsetX)
+      }
+      this.touchSlider(e, component)
+
+      this.emitPickedColor()
+    },
+    setSliderValue(component, value) {
+      this[component + 'Slider'] = Math.min(Math.max(value, 0), this.pickerWidth)
+    },
+    emitPickedColor() {
+      clearTimeout(this.emitTimer)
+      this.emitTimer = setTimeout(() => {
+        this.$emit('pickerColor', {rgb: this.pickedColor.rgb, hex: this.pickedColor.hex})
+      }, 100);
+    }
+  }
+}
+
+function hsvToRgb(h, s, v) {
+  var r, g, b, i, f, p, q, t;
+  if (arguments.length === 1) {
+      s = h.s, v = h.v, h = h.h;
+  }
+  i = Math.floor(h * 6);
+  f = h * 6 - i;
+  p = v * (1 - s);
+  q = v * (1 - f * s);
+  t = v * (1 - (1 - f) * s);
+  switch (i % 6) {
+      case 0: r = v, g = t, b = p; break;
+      case 1: r = q, g = v, b = p; break;
+      case 2: r = p, g = v, b = t; break;
+      case 3: r = p, g = q, b = v; break;
+      case 4: r = t, g = p, b = v; break;
+      case 5: r = v, g = p, b = q; break;
+  }
+  return {
+      r: Math.round(r * 255),
+      g: Math.round(g * 255),
+      b: Math.round(b * 255)
+  }
+}
+
+function rgbToHsv(r, g, b) {
+    if (arguments.length === 1) {
+        g = r.g, b = r.b, r = r.r;
+    }
+    var max = Math.max(r, g, b), min = Math.min(r, g, b),
+        d = max - min,
+        h,
+        s = (max === 0 ? 0 : d / max),
+        v = max / 255;
+    switch (max) {
+        case min: h = 0; break;
+        case r: h = (g - b) + d * (g < b ? 6: 0); h /= 6 * d; break;
+        case g: h = (b - r) + d * 2; h /= 6 * d; break;
+        case b: h = (r - g) + d * 4; h /= 6 * d; break;
+    }
+    return { h, s, v };
+}
+
+function rgbaToHex(r, g, b, a) {
+  let hex = "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)
+  if (a !== 255) {
+    hex += ((1 << 8) + a).toString(16).slice(1)
+  }
+  return hex
+}
+
+function hexToRgba(hex) {
+  // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
+  var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
+  hex = hex.replace(shorthandRegex, function(m, r, g, b) {
+    return r + r + g + g + b + b;
+  });
+
+  var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i.exec(hex);
+  return result ? {
+    r: parseInt(result[1], 16),
+    g: parseInt(result[2], 16),
+    b: parseInt(result[3], 16),
+    a: result[4] ? parseInt(result[4], 16)  / 255 : 1,
+  } : null;
+}
+</script>
+
+<style lang="scss" scoped>
+.color-picker {
+  position: relative;
+  width: 100%;
+}
+.sv-picker {
+  position: relative;
+  width: 100%;
+  padding-top: 100%;
+  .sv-slider {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 30rpx;
+    height: 30rpx;
+    border: 1px solid #FFF;
+    background-color: rgba(73, 73, 73, 0.5);
+    border-radius: 50rpx;
+  }
+  
+  .sv-picker-background {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+  }
+}
+
+.hue-slider, .alpha-slider {
+  margin-top: 20rpx;
+  position: relative;
+  width: 100%;
+  height: 35rpx;
+}
+.hue-slider {
+  background: linear-gradient(90deg, red 0, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, red);
+}
+.alpha-background-image {
+  background-size: 35rpx;
+  background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAWElEQVRIiWM8fubkfwYygKWJOSM5+mCAhRLNoxaPWjxq8ajFoxbTyeL/DAfJ0Xjs3Cl7Siwmu4Yht1aDgZEYx6MWj1o8avGoxaMWD3qLya5X//4nqx6HAQC7RBGFzolqTAAAAABJRU5ErkJggg==");
+}
+
+.slider {
+  position: absolute;
+  left: 0;
+  top: 50%;
+  transform: translateY(-50%);
+  height: 50rpx;
+  width: 30rpx;
+  border: 1px solid #FFF;
+  box-sizing: border-box;
+  background-color: rgba(199, 199, 199, .7);
+}
+.alpha-background {
+  width: 100%;
+  height: 100%;
+}
+
+.result {
+  margin-top: 20rpx;
+  display: flex;
+  align-items: center;
+
+  .result-color {
+    width: 100rpx;
+    height: 100rpx;
+    border-radius: 100rpx;
+    overflow: hidden;
+  }
+  .result-text {
+    margin-left: 20rpx;
+    flex: 1;
+    padding: 10rpx 20rpx;
+    border: 1px solid #CCC;
+    border-radius: 10rpx;
+    color: #333;
+    display: flex;
+    align-items: center;
+    flex-wrap: wrap;
+
+    p {
+      width: 100%;
+    }
+  }
+}
+
+</style>

+ 86 - 0
components/jp-color-picker/jp-color-picker.vue

@@ -0,0 +1,86 @@
+<template>
+<view>
+<view class="action">
+	<button class="cu-btn  shadow round" :disabled="disabled" :style="'color:white;background-color:'+color" @tap="showModal" data-target="DialogModal1">{{color}}</button>
+</view>
+ <view class="cu-modal" :class="modalName=='DialogModal1'?'show':''">
+ 	<view class="cu-dialog">
+ 		<view class="padding-xl">
+ 			 <color-picker :show='true' :color="color" @pickerColor="pickerColor"></color-picker>
+ 		</view>
+ 		<view class="cu-bar bg-white justify-end">
+ 			<view class="action">
+ 				<button class="cu-btn line-green text-green" @tap="hideModal">取消</button>
+ 				<button class="cu-btn bg-green margin-left" @tap="confirm">确定</button>
+ 
+ 			</view>
+ 		</view>
+ 	</view>
+ </view>
+ </view>
+</template>
+<script>
+import colorPicker from "./colorPicker.vue";
+
+export default {
+  components: { colorPicker },
+  props: {
+    value: String,
+  	disabled: {
+  		type: Boolean,
+  		default: false
+  	}
+  },
+  data() {
+    return {
+	  modalName: null,
+	  color: null,
+	  colorRgb: ''
+    };
+  },
+  watch:{
+  	value:{
+  		handler (val) {
+  			this.color = val
+  		},
+  		immediate: true,
+  		deep: false
+  	}
+  },
+  methods: {
+    pickerColor(color) {
+      this.color = color.rgb
+    },
+	showModal(e) {
+		this.modalName = e.currentTarget.dataset.target
+	},
+	hideModal(e) {
+		this.modalName = null
+	},
+	confirm () {
+		this.$emit('input', this.color)
+		this.modalName = null
+	}
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+#container {
+  width: 100vw;
+  height: 100vh;
+}
+.actions {
+  margin-top: 20rpx;
+  display: flex;
+  justify-content: space-between;
+  .iconfont {
+    color: #777;
+    font-size: 56rpx;
+  }
+  .icon-yes {
+    color: rgb(14, 165, 0)
+  }
+}
+
+</style>

+ 49 - 0
components/jp-datetime-picker/jp-datetime-picker.vue

@@ -0,0 +1,49 @@
+<template>
+		<picker :mode="mode" :value="value" :disabled="disabled" :start="start" :end="end" @change="TimeChange">
+			<view class=" picker action">
+				<view class="text-grey ">{{label || '请选择'}}</view>
+			</view>
+		</picker>
+</template>
+
+<script>
+	import moment from 'moment'
+	export default {
+		data () {
+			return {
+				label: ''
+			}
+		},
+		props: {
+		    value: {
+				type: String,
+				default: '2020-09-12'
+			},
+			start: String,
+			end: String,
+			mode: String,
+			disabled: {
+				type: Boolean,
+				default: false
+			}
+		},
+		watch:{
+			value:{
+				handler (val) {
+					this.label = val
+				},
+				immediate: true,
+				deep: false
+			}
+		},
+		methods:{
+			TimeChange(e) {
+				if(this.mode === 'date'){
+					this.label = moment(e.detail.value).format('YYYY-MM-DD HH:mm:ss')
+				}
+				this.$emit('input', this.label)
+			}
+		}
+	}
+</script>
+

+ 106 - 0
components/jp-image-upload/jp-image-upload.vue

@@ -0,0 +1,106 @@
+<template>
+		<view class="margin-top grid col-4 grid-square flex-sub">
+			<view class="bg-img"  v-for="(item,index) in imgList" :key="index" @tap="ViewImage" :data-url="item.url">
+			 <image :src="item.url" mode="aspectFill"></image>
+				<view class="cu-tag bg-red" v-if="!disabled" @tap.stop="DelImg" :data-index="index">
+					<text class='cuIcon-close'></text>
+				</view>
+			</view>
+			<view class="solids" v-if="!disabled" @tap="ChooseImage">
+				<text class='cuIcon-cameraadd'></text>
+			</view>
+		</view>
+</template>
+
+<script>
+	import FileService from "@/api/sys/FileService"
+	export default {
+		data() {
+			return {
+				imgList: []
+			}
+		},
+		watch:{
+			value:{
+				handler (val) {
+					this.imgList = val
+				},
+				immediate: true,
+				deep: false
+			}
+		},
+		props: {
+		    value: {
+				type: Array,
+				default: function () {
+					return []
+				}
+			},
+			disabled: {
+				type: Boolean,
+				default: false
+			}
+		},
+		methods: {
+			ChooseImage() {
+				uni.chooseImage({
+					count: 4, //默认9
+					sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
+					sourceType: ['album'], //从相册选择
+					success: (res) => {
+						this.upload(res.tempFilePaths[0])
+					}
+				});
+			},
+			ViewImage(e) {
+				let urls = this.imgList.map((img)=>{
+					return img.url
+				})
+				uni.previewImage({
+					urls: urls,
+					current: e.currentTarget.dataset.url
+				});
+			},
+			DelImg(e) {
+				uni.showModal({
+					title: '提示',
+					content: '确定要删除图片吗?',
+					cancelText: '取消',
+					confirmText: '确定',
+					success: res => {
+						if (res.confirm) {
+							this.imgList.splice(e.currentTarget.dataset.index, 1)
+							console.log(this.imgList)
+							this.$emit('input', this.imgList)
+						}
+					}
+				})
+			},
+			upload(img) {
+				new FileService().uploadFile(img).then((res)=>{
+					this.imgList.push(JSON.parse(res))
+					this.$emit('input', this.imgList)
+				})
+			}
+		}
+	}
+</script>
+
+<style>
+  .btn-logout {
+    margin-top: 100upx;
+    width: 80%;
+    border-radius: 50upx;
+    font-size: 16px;
+    color: #fff;
+    background: linear-gradient(to right, #365fff, #36bbff);
+  }
+
+  .btn-logout-hover {
+    background: linear-gradient(to right, #365fdd, #36bbfa);
+  }
+  uni-image>div, uni-image>img {
+      width: 100upx !important;
+      height: 100upx !important;
+  }
+</style>

+ 107 - 0
components/jp-image-upload2/jp-image-upload2.vue

@@ -0,0 +1,107 @@
+<template>
+		<view class="margin-top grid col-4 grid-square flex-sub">
+			<view class="bg-img"  v-for="(item,index) in imgList" :key="index" @tap="ViewImage" :data-url="item">
+			 <image :src="item" mode="aspectFill"></image>
+				<view class="cu-tag bg-red" v-if="!disabled" @tap.stop="DelImg" :data-index="index">
+					<text class='cuIcon-close'></text>
+				</view>
+			</view>
+			<view class="solids" v-if="!disabled" @tap="ChooseImage">
+				<text class='cuIcon-cameraadd'></text>
+			</view>
+		</view>
+</template>
+
+<script>
+	import FileService from "@/api/sys/FileService"
+	export default {
+		data() {
+			return {
+				imgList: []
+			}
+		},
+		watch:{
+			value:{
+				handler (val) {
+					if(val){
+						this.imgList = val.split(',')
+					}
+				},
+				immediate: true,
+				deep: false
+			}
+		},
+		props: {
+		    value: {
+				type: String,
+				default: function () {
+					return ''
+				}
+			},
+			disabled: {
+				type: Boolean,
+				default: false
+			}
+		},
+		methods: {
+			ChooseImage() {
+				uni.chooseImage({
+					count: 4, //默认9
+					sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
+					sourceType: ['album'], //从相册选择
+					success: (res) => {
+						this.upload(res.tempFilePaths[0])
+					}
+				});
+			},
+			ViewImage(e) {
+				let urls = this.imgList.map((img)=>{
+					return img.url
+				})
+				uni.previewImage({
+					urls: urls,
+					current: e.currentTarget.dataset.url
+				});
+			},
+			DelImg(e) {
+				uni.showModal({
+					title: '提示',
+					content: '确定要删除图片吗?',
+					cancelText: '取消',
+					confirmText: '确定',
+					success: res => {
+						if (res.confirm) {
+							this.imgList.splice(e.currentTarget.dataset.index, 1)
+							this.$emit('input', this.imgList.join(','))
+						}
+					}
+				})
+			},
+			upload(img) {
+				new FileService().uploadFile(img).then((res)=>{
+					this.imgList.push(JSON.parse(res).url)
+					this.$emit('input', this.imgList.join(','))
+				})
+			}
+		}
+	}
+</script>
+
+<style>
+  .btn-logout {
+    margin-top: 100upx;
+    width: 80%;
+    border-radius: 50upx;
+    font-size: 16px;
+    color: #fff;
+    background: linear-gradient(to right, #365fff, #36bbff);
+  }
+
+  .btn-logout-hover {
+    background: linear-gradient(to right, #365fdd, #36bbfa);
+  }
+  uni-image>div, uni-image>img {
+      width: 100upx !important;
+      height: 100upx !important;
+  }
+</style>

+ 123 - 0
components/jp-office-select/jp-office-select.vue

@@ -0,0 +1,123 @@
+<template>
+	<view>
+		<view class="action arrow" :disabled="disabled" @tap="showModal" data-target="bottomModal">
+			<view class="upicker uni-input ellipsis-description">{{labels?labels:'请选择'}}</view>
+		</view>
+		<view class="cu-modal bottom-modal" style="min-height: 200upx;" :class="modalName=='bottomModal'?'show':''">
+			<view class="cu-dialog">
+				<view class="cu-bar bg-white">
+					<view class="action text-blue" @tap="hideModal">取消</view>
+					<view class="action text-green" @tap="selectOffice">确定</view>
+				</view>
+				<view>
+					  <ly-tree :tree-data="data"
+						:props="props" 
+						node-key="id" 
+						:checkOnClickNode ="true"
+						:showRadio="showRadio"
+						:show-checkbox ="showCheckBox"
+						:checkOnlyLeaf = "checkOnlyLeaf"
+						ref="officeTree" />
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import OfficeService from "@/api/sys/OfficeService"
+	export default {
+		data() {
+			return {
+				data: [],
+				modalName: null,
+				labels: '',
+				treeList: []
+			};
+		},
+		props: {
+		    limit: Number,
+		    value: String,
+		    size: String,
+		    readonly: {
+		      type: Boolean,
+		      default: () => { return false }
+		    },
+			checkOnlyLeaf: {
+		      type: Boolean,
+		      default: () => { return false }
+		    },
+			showRadio: {
+		      type: Boolean,
+		      default: () => { return true }
+		    },
+			showCheckBox: {
+			  type: Boolean,
+			  default: () => { return false }
+			},
+		    disabled: {
+		      type: Boolean,
+		      default: () => { return false }
+		    },
+			props: {
+				type: Object,
+				default: () => {
+					return {
+						children: 'children',
+						label: 'name'
+					}
+				}
+			}
+		  },
+		mounted() {
+			new OfficeService().treeData().then(({data})=>{
+				this.data = data
+				this.setTreeList(this.data)
+				if(this.value){
+					let keys = this.value.split(',')
+					let labelArra = []
+					keys.forEach((id) => {
+						this.treeList.forEach((node) => {
+						  if (id === node.id) {
+							labelArra.push(node.name)
+						  }
+						})
+					 })
+					this.labels = labelArra.join(',')
+					this.$refs.officeTree.setCheckedKeys(keys);
+				}
+			})
+		},
+		methods:{
+			setTreeList (datas) { // 遍历树  获取id数组
+			      for (var i in datas) {
+			        this.treeList.push(datas[i])
+			        if (datas[i].children) {
+			          this.setTreeList(datas[i].children)
+			        }
+			      }
+			    },
+			selectOffice () {
+				let ids = this.$refs.officeTree.getCheckedNodes().map((item)=>{
+					return item.id
+				}).join(",");
+				let names = this.$refs.officeTree.getCheckedNodes().map((item)=>{
+					return item.name
+				}).join(",");
+				this.labels = names
+				this.$emit('input', ids)
+				this.hideModal()
+			},
+			showModal(e) {
+				if(this.disabled){
+					return
+				}
+				this.modalName = e.currentTarget.dataset.target
+			},
+			hideModal(e) {
+				this.modalName = null
+			}
+		}
+	}
+</script>
+

+ 77 - 0
components/jp-picker/jp-picker.vue

@@ -0,0 +1,77 @@
+<template>
+	<view>
+		<picker @change="PickerChange" :value="index" :disabled="disabled" :range-value="rangeValue"  :range-key="rangeKey" :range="range">
+			<view class=" picker action">
+				<view class="text-grey ">{{label || '请选择'}}</view>
+			</view>
+		</picker>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				index: -1,
+				label: '请选择'
+			};
+		},
+		props: {
+		    value: String,
+			rangeKey: {
+				type: String,
+				default: 'label'
+			},
+			rangeValue: {
+				type: String,
+				default: 'value'
+			},
+			range: {
+				type: Array,
+				default: []
+			},
+			disabled: {
+				type: Boolean,
+				default: false
+			}
+		},
+		mounted() {
+			
+		},
+		watch:{
+			value: {
+				handler (val) {
+					if(val) {
+						let options = this.range.filter((option)=>{
+							return option.value === val
+						})
+						if(options.length === 0){
+							this.label = '请选择'
+						} else {
+							this.label = options[0][this.rangeKey]
+						}
+					}
+				},
+				immediate: true,
+				deep: false
+			}
+		},
+		methods:{
+			PickerChange(e) {
+				this.index = e.detail.value;
+				if(this.index !== -1){
+					this.label = this.range[this.index][this.rangeKey]
+					this.$emit('input', this.range[this.index][this.rangeValue])
+				}else{
+					this.label = '请选择'
+					this.$emit('input', null)
+				}
+				
+			}
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 33 - 0
components/jp-radio-group/jp-radio-group.vue

@@ -0,0 +1,33 @@
+<template>
+	<view>
+		<radio-group @change="radioChange">
+			<slot></slot>
+		</radio-group>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				
+			};
+		},
+		props: {
+		    value: String,
+			disabled: {
+				type: Boolean,
+				default: false
+			}
+		},
+		methods:{
+			radioChange (evt) {
+				this.$emit('input', evt.detail.value)
+			}
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 31 - 0
components/jp-slider/jp-slider.vue

@@ -0,0 +1,31 @@
+<template>
+	 <view class="uni-padding-wrap uni-common-mt">
+		 <slider value="0" :disabled="disabled" @change="sliderChange" step="5" />
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				valueStr: ''+this.value
+			};
+		},
+		props: {
+		    value: Number,
+			disabled: {
+				type: Boolean,
+				default: false
+			}
+		},
+		methods:{
+			 sliderChange(e) {
+				this.$emit('input', e.detail.value)
+			}
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 31 - 0
components/jp-switch/jp-switch.vue

@@ -0,0 +1,31 @@
+<template>
+	<view>
+		<switch @change="SwitchA" :class="value?'checked':''" :disabled="disabled" :checked="value?true:false"></switch>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				
+			};
+		},
+		props: {
+		    value: Boolean,
+			disabled: {
+				type: Boolean,
+				default: false
+			}
+		},
+		methods:{
+			SwitchA(e) {
+				this.$emit('input', e.detail.value)
+			}
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 9 - 0
components/ly-tree-nvue/components/icons.js

@@ -0,0 +1,9 @@
+export default {
+	'icon-unchecked': "\ue852",
+	'icon-radio-disabled': "\ue853",
+	'icon-radio-unchecked': "\ue854",
+	'icon-checked': "\ue855",
+	'icon-check-disabled': "\ue856",
+	'icon-indeterminate': "\ue85a",
+	'icon-radio-checked': "\ue86b"
+}

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 94 - 0
components/ly-tree-nvue/components/ly-checkbox.vue


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 331 - 0
components/ly-tree-nvue/ly-tree-node.vue


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 536 - 0
components/ly-tree-nvue/ly-tree.vue


+ 498 - 0
components/ly-tree-nvue/model/node.js

@@ -0,0 +1,498 @@
+import {
+	markNodeData,
+	objectAssign,
+	arrayFindIndex,
+	getChildState,
+	reInitChecked,
+	getPropertyFromData,
+	isNull,
+	NODE_KEY
+} from '../tool/util';
+
+const getStore = function(store) {
+	let thisStore = store;
+	
+	return function() {
+		return thisStore;
+	}
+}
+
+let nodeIdSeed = 0;
+
+export default class Node {
+	constructor(options) {
+		this.time = new Date().getTime();
+		this.id = nodeIdSeed++;
+		this.text = null;
+		this.checked = false;
+		this.indeterminate = false;
+		this.data = null;
+		this.expanded = false;
+		this.parentId = null;
+		this.visible = true;
+		this.isCurrent = false;
+
+		for (let name in options) {
+			if (options.hasOwnProperty(name)) {
+				if (name === 'store') {
+					this.store = getStore(options[name]);
+				} else {
+					this[name] = options[name];
+				}
+			}
+		}
+
+		// internal
+		this.level = 0;
+		this.loaded = false;
+		this.childNodesId = [];
+		this.loading = false;
+		this.label = getPropertyFromData(this, 'label');
+		this.key = this.data ? this.data[this.store().key] : null;
+		this.disabled = getPropertyFromData(this, 'disabled');
+		this.nextSibling = null;
+		this.previousSibling = null;
+		this.icon = '';
+
+		if (this.parentId !== null) {
+			let parent = this.getParent(this.parentId);
+			
+			if (this.store().isInjectParentInNode) {
+				this.parent = parent;
+			}
+			
+			// 由于这里做了修改,默认第一个对象不会被注册到nodesMap中,所以找不到parent会报错,所以默认parent的level是0
+			if (!parent) {
+				parent = {
+					level: 0
+				}
+			} else {
+				const parentChildNodes = parent.getChildNodes(parent.childNodesId);
+				const index = parent.childNodesId.indexOf(this.key);
+				this.nextSibling = index > -1 ? parentChildNodes[index + 1] : null;
+				this.previousSibling = index > 0 ? parentChildNodes[index - 1] : null;
+			}
+			this.level = parent.level + 1;
+		}
+
+		if (!this.store()) {
+			throw new Error('[Node]store is required!');
+		}
+		
+		const props = this.store().props;
+		
+		if (this.store().showNodeIcon && props && typeof props.icon !== 'undefined') {
+			this.icon = getPropertyFromData(this, props.icon);
+		}
+		
+		this.store().registerNode(this);
+		
+		if (props && typeof props.isLeaf !== 'undefined') {
+			const isLeaf = getPropertyFromData(this, 'isLeaf');
+			if (typeof isLeaf === 'boolean') {
+				this.isLeafByUser = isLeaf;
+			}
+		}
+
+		if (this.store().lazy !== true && this.data) {
+			this.setData(this.data);
+
+			if (this.store().defaultExpandAll) {
+				this.expanded = true;
+			}
+		} else if (this.level > 0 && this.store().lazy && this.store().defaultExpandAll) {
+			this.expand();
+		}
+		
+		if (!Array.isArray(this.data)) {
+			markNodeData(this, this.data);
+		}
+		
+		if (!this.data) return;
+		
+		const defaultExpandedKeys = this.store().defaultExpandedKeys;
+		const key = this.store().key;
+		if (key && defaultExpandedKeys && defaultExpandedKeys.indexOf(this.key) !== -1) {
+			this.expand(null, this.store().autoExpandparent);
+		}
+
+		if (key && this.store().currentNodeKey !== undefined && this.key === this.store().currentNodeKey) {
+			this.store().currentNode = this;
+			this.store().currentNode.isCurrent = true;
+		}
+
+		if (this.store().lazy) {
+			this.store()._initDefaultCheckedNode(this);
+		}
+
+		this.updateLeafState();
+	}
+	
+	destroyStore() {
+		getStore(null)
+	}
+
+	setData(data) {
+		if (!Array.isArray(data)) {
+			markNodeData(this, data);
+		}
+
+		this.data = data;
+		this.childNodesId = [];
+
+		let children;
+		if (this.level === 0 && Array.isArray(this.data)) {
+			children = this.data;
+		} else {
+			children = getPropertyFromData(this, 'children') || [];
+		}
+
+		for (let i = 0, j = children.length; i < j; i++) {
+			this.insertChild({
+				data: children[i]
+			});
+		}
+	}
+
+	contains(target, deep = true) {
+		const walk = function(parent) {
+			const children = parent.getChildNodes(parent.childNodesId) || [];
+			let result = false;
+			for (let i = 0, j = children.length; i < j; i++) {
+				const child = children[i];
+				if (child === target || (deep && walk(child))) {
+					result = true;
+					break;
+				}
+			}
+			return result;
+		};
+
+		return walk(this);
+	}
+
+	remove() {
+		if (this.parentId !== null) {
+			const parent = this.getParent(this.parentId);
+			parent.removeChild(this);
+		}
+	}
+
+	insertChild(child, index, batch) {
+		if (!child) throw new Error('insertChild error: child is required.');
+
+		if (!(child instanceof Node)) {
+			if (!batch) {
+				const children = this.getChildren(true);
+				if (children.indexOf(child.data) === -1) {
+					if (typeof index === 'undefined' || index < 0) {
+						children.push(child.data);
+					} else {
+						children.splice(index, 0, child.data);
+					}
+				}
+			}
+			objectAssign(child, {
+				parentId: isNull(this.key) ? '' : this.key,
+				store: this.store()
+			});
+			child = new Node(child);
+		}
+
+		child.level = this.level + 1;
+
+		if (typeof index === 'undefined' || index < 0) {
+			this.childNodesId.push(child.key);
+		} else {
+			this.childNodesId.splice(index, 0, child.key);
+		}
+
+		this.updateLeafState();
+	}
+
+	insertBefore(child, ref) {
+		let index;
+		if (ref) {
+			index = this.childNodesId.indexOf(ref.id);
+		}
+		this.insertChild(child, index);
+	}
+
+	insertAfter(child, ref) {
+		let index;
+		if (ref) {
+			index = this.childNodesId.indexOf(ref.id);
+			if (index !== -1) index += 1;
+		}
+		this.insertChild(child, index);
+	}
+
+	removeChild(child) {
+		const children = this.getChildren() || [];
+		const dataIndex = children.indexOf(child.data);
+		if (dataIndex > -1) {
+			children.splice(dataIndex, 1);
+		}
+		
+		const index = this.childNodesId.indexOf(child.key);
+		
+		if (index > -1) {
+			this.store() && this.store().deregisterNode(child);
+			child.parentId = null;
+			this.childNodesId.splice(index, 1);
+		}
+		
+		this.updateLeafState();
+	}
+
+	removeChildByData(data) {
+		let targetNode = null;
+
+		for (let i = 0; i < this.childNodesId.length; i++) {
+			let node = this.getChildNodes(this.childNodesId);
+			if (node[i].data === data) {
+				targetNode = node[i];
+				break;
+			}
+		}
+
+		if (targetNode) {
+			this.removeChild(targetNode);
+		}
+	}
+
+	// 为了避免APP端parent嵌套结构导致报错,这里parent需要从nodesMap中获取
+	getParent(parentId) {
+		if (!parentId) return null;
+		return this.store().nodesMap[parentId];
+	}
+
+	// 为了避免APP端childNodes嵌套结构导致报错,这里childNodes需要从nodesMap中获取
+	getChildNodes(childNodesId) {
+		let childNodes = [];
+		if (childNodesId.length === 0) return childNodes;
+		childNodesId.forEach((key) => {
+			childNodes.push(this.store().nodesMap[key]);
+		})
+		return childNodes;
+	}
+
+	expand(callback, expandparent) {
+		const done = () => {
+			if (expandparent) {
+				let parent = this.getParent(this.parentId);
+				while (parent && parent.level > 0) {
+					parent.expanded = true;
+					parent = this.getParent(parent.parentId);
+				}
+			}
+			this.expanded = true;
+			if (callback) callback();
+		};
+
+		if (this.shouldLoadData()) {
+			this.loadData((data) => {
+				if (Array.isArray(data)) {
+					if (this.checked) {
+						this.setChecked(true, true);
+					} else if (!this.store().checkStrictly) {
+						reInitChecked(this);
+					}
+					done();
+				}
+			});
+		} else {
+			done();
+		}
+	}
+
+	doCreateChildren(array, defaultProps = {}) {
+		array.forEach((item) => {
+			this.insertChild(objectAssign({
+				data: item
+			}, defaultProps), undefined, true);
+		});
+	}
+
+	collapse() {
+		this.expanded = false;
+	}
+
+	shouldLoadData() {
+		return this.store().lazy === true && this.store().load && !this.loaded;
+	}
+
+	updateLeafState() {
+		if (this.store().lazy === true && this.loaded !== true && typeof this.isLeafByUser !== 'undefined') {
+			this.isLeaf = this.isLeafByUser;
+			return;
+		}
+		const childNodesId = this.childNodesId;
+		if (!this.store().lazy || (this.store().lazy === true && this.loaded === true)) {
+			this.isLeaf = !childNodesId || childNodesId.length === 0;
+			return;
+		}
+		this.isLeaf = false;
+	}
+
+	setChecked(value, deep, recursion, passValue) {
+		this.indeterminate = value === 'half';
+		this.checked = value === true;
+		
+		if (this.checked && this.store().expandOnCheckNode) {
+			this.expand(null, true)
+		}
+		
+		if (this.store().checkStrictly) return;
+		if (this.store().showRadio) return;
+
+		if (!(this.shouldLoadData() && !this.store().checkDescendants)) {
+			let childNodes = this.getChildNodes(this.childNodesId);
+			let {
+				all,
+				allWithoutDisable
+			} = getChildState(childNodes);
+
+			if (!this.isLeaf && (!all && allWithoutDisable)) {
+				this.checked = false;
+				value = false;
+			}
+
+			const handleDescendants = () => {
+				if (deep) {
+					let childNodes = this.getChildNodes(this.childNodesId)
+					for (let i = 0, j = childNodes.length; i < j; i++) {
+						const child = childNodes[i];
+						passValue = passValue || value !== false;
+						const isCheck = child.disabled ? child.checked : passValue;
+						child.setChecked(isCheck, deep, true, passValue);
+					}
+					const {
+						half,
+						all
+					} = getChildState(childNodes);
+					if (!all) {
+						this.checked = all;
+						this.indeterminate = half;
+					}
+				}
+			};
+
+			if (this.shouldLoadData()) {
+				this.loadData(() => {
+					handleDescendants();
+					reInitChecked(this);
+				}, {
+					checked: value !== false
+				});
+				return;
+			} else {
+				handleDescendants();
+			}
+		}
+
+		if (!this.parentId) return;
+
+		let parent = this.getParent(this.parentId);
+		if (parent && parent.level === 0) return;
+
+		if (!recursion) {
+			reInitChecked(parent);
+		}
+	}
+
+	setRadioChecked(value) {
+		const allNodes = this.store()._getAllNodes().sort((a, b) => b.level - a.level);
+		allNodes.forEach(node => node.setChecked(false, false));
+		this.checked = value === true;
+	}
+
+	getChildren(forceInit = false) {
+		if (this.level === 0) return this.data;
+		const data = this.data;
+		if (!data) return null;
+
+		const props = this.store().props;
+		let children = 'children';
+		if (props) {
+			children = props.children || 'children';
+		}
+
+		if (data[children] === undefined) {
+			data[children] = null;
+		}
+
+		if (forceInit && !data[children]) {
+			data[children] = [];
+		}
+
+		return data[children];
+	}
+
+	updateChildren() {
+		let childNodes = this.getChildNodes(this.childNodesId);
+		const newData = this.getChildren() || [];
+		const oldData = childNodes.map((node) => node.data);
+
+		const newDataMap = {};
+		const newNodes = [];
+
+		newData.forEach((item, index) => {
+			const key = item[NODE_KEY];
+			const isNodeExists = !!key && arrayFindIndex(oldData, data => data[NODE_KEY] === key) >= 0;
+			if (isNodeExists) {
+				newDataMap[key] = {
+					index,
+					data: item
+				};
+			} else {
+				newNodes.push({
+					index,
+					data: item
+				});
+			}
+		});
+
+		if (!this.store().lazy) {
+			oldData.forEach((item) => {
+				if (!newDataMap[item[NODE_KEY]]) this.removeChildByData(item);
+			});
+		}
+
+		newNodes.forEach(({
+			index,
+			data
+		}) => {
+			this.insertChild({
+				data
+			}, index);
+		});
+
+		this.updateLeafState();
+	}
+
+	loadData(callback, defaultProps = {}) {
+		if (this.store().lazy === true && this.store().load && !this.loaded && (!this.loading || Object.keys(defaultProps).length)) {
+			this.loading = true;
+
+			const resolve = (children) => {
+				this.loaded = true;
+				this.loading = false;
+				this.childNodesId = [];
+
+				this.doCreateChildren(children, defaultProps);
+
+				this.updateLeafState();
+				if (callback) {
+					callback.call(this, children);
+				}
+			};
+
+			this.store().load(this, resolve);
+		} else {
+			if (callback) {
+				callback.call(this);
+			}
+		}
+	}
+}

+ 414 - 0
components/ly-tree-nvue/model/tree-store.js

@@ -0,0 +1,414 @@
+import Node from './node';
+import {
+	getNodeKey,
+	getPropertyFromData
+} from '../tool/util';
+
+export default class TreeStore {
+	constructor(options) {
+		this.ready = false;
+		this.currentNode = null;
+		this.currentNodeKey = null;
+
+		Object.assign(this, options);
+
+		if (!this.key) {
+			throw new Error('[Tree] nodeKey is required');
+		}
+
+		this.nodesMap = {};
+		this.root = new Node({
+			data: this.data,
+			store: this
+		});
+
+		if (this.lazy && this.load) {
+			const loadFn = this.load;
+			loadFn(this.root, (data) => {
+				this.root.doCreateChildren(data);
+				this._initDefaultCheckedNodes();
+				this.ready = true;
+			});
+		} else {
+			this._initDefaultCheckedNodes();
+			this.ready = true;
+		}
+	}
+
+	filter(value, data) {
+		const filterNodeMethod = this.filterNodeMethod;
+		const lazy = this.lazy;
+		const _self = this;
+		const traverse = function(node) {
+			const childNodes = node.root ? node.root.getChildNodes(node.root.childNodesId) : node.getChildNodes(node.childNodesId);
+
+			childNodes.forEach((child) => {
+				if (data && typeof data === 'object') {
+					let nodePath = _self.getNodePath(child.data);
+					if (!nodePath.some(pathItem => pathItem[_self.key] === data[_self.key])) {
+						child.visible = false;
+						traverse(child);
+						return;
+					}
+				}
+				
+				if (_self.childVisibleForFilterNode) {
+					let parent = child.getParent(child.parentId);
+					child.visible = filterNodeMethod.call(child, value, child.data, child) || (parent && parent.visible);
+				} else {
+					child.visible = filterNodeMethod.call(child, value, child.data, child);
+				}
+				
+				traverse(child);
+			});
+
+			if (!node.visible && childNodes.length) {
+				let allHidden = true;
+				allHidden = !childNodes.some(child => child.visible);
+
+				if (node.root) {
+					node.root.visible = allHidden === false;
+				} else {
+					node.visible = allHidden === false;
+				}
+			}
+			
+			if (!value) return;
+
+			if (node.visible && !node.isLeaf && !lazy) node.expand();
+		};
+
+		traverse(this);
+	}
+
+	setData(newVal) {
+		const instanceChanged = newVal !== this.root.data;
+		if (instanceChanged) {
+			this.root.setData(newVal);
+			this._initDefaultCheckedNodes();
+		} else {
+			this.root.updateChildren();
+		}
+	}
+
+	getNode(data) {
+		if (data instanceof Node) return data;
+		const key = typeof data !== 'object' ? data : getNodeKey(this.key, data);
+		return this.nodesMap[key] || null;
+	}
+
+	insertBefore(data, refData) {
+		const refNode = this.getNode(refData);
+		let parent = refNode.getParent(refNode.parentId);
+		parent.insertBefore({
+			data
+		}, refNode);
+	}
+
+	insertAfter(data, refData) {
+		const refNode = this.getNode(refData);
+		let parent = refNode.getParent(refNode.parentId);
+		parent.insertAfter({
+			data
+		}, refNode);
+	}
+
+	remove(data) {
+		const node = this.getNode(data);
+
+		if (node && node.parentId !== null) {
+			let parent = node.getParent(node.parentId);
+			if (node === this.currentNode) {
+				this.currentNode = null;
+			}
+			parent.removeChild(node);
+		}
+	}
+
+	append(data, parentData) {
+		const parentNode = parentData ? this.getNode(parentData) : this.root;
+
+		if (parentNode) {
+			parentNode.insertChild({
+				data
+			});
+		}
+	}
+
+	_initDefaultCheckedNodes() {
+		const defaultCheckedKeys = this.defaultCheckedKeys || [];
+		const nodesMap = this.nodesMap;
+		let checkedKeyfromData = [];
+		let totalCheckedKeys = []
+		
+		for (let key in nodesMap) {
+			let checked = getPropertyFromData(nodesMap[key], 'checked') || false;
+			checked && checkedKeyfromData.push(key);
+		}
+		
+		totalCheckedKeys = Array.from(new Set([...defaultCheckedKeys, ...checkedKeyfromData]));
+		totalCheckedKeys.forEach((checkedKey) => {
+			const node = nodesMap[checkedKey];
+			
+			if (node) {
+				node.setChecked(true, !this.checkStrictly);
+			}
+		});
+	}
+
+	_initDefaultCheckedNode(node) {
+		const defaultCheckedKeys = this.defaultCheckedKeys || [];
+
+		if (defaultCheckedKeys.indexOf(node.key) !== -1) {
+			node.setChecked(true, !this.checkStrictly);
+		}
+	}
+	
+	toggleExpendAll(isExpandAll) {
+		const allNodes = this._getAllNodes();
+		
+		allNodes.forEach(item => {
+			const node = this.getNode(item.key); 
+			
+			if (node) isExpandAll ? node.expand() : node.collapse();
+		});
+	}
+	
+	setCheckAll(isCkeckAll) {
+		const allNodes = this._getAllNodes();
+		
+		allNodes.forEach(item => {
+			item.setChecked(isCkeckAll, false);
+		}); 
+	}
+
+	setDefaultCheckedKey(newVal) {
+		if (newVal !== this.defaultCheckedKeys) {
+			this.defaultCheckedKeys = newVal;
+			this._initDefaultCheckedNodes();
+		}
+	}
+
+	registerNode(node) {
+
+		const key = this.key;
+		if (!key || !node || !node.data) return;
+
+		const nodeKey = node.key;
+		if (nodeKey !== undefined) this.nodesMap[node.key] = node;
+	}
+
+	deregisterNode(node) {
+		const key = this.key;
+		if (!key || !node || !node.data) return;
+
+		let childNodes = node.getChildNodes(node.childNodesId);
+		childNodes.forEach(child => {
+			this.deregisterNode(child);
+		});
+
+		delete this.nodesMap[node.key];
+	}
+	
+	getNodePath(data) {
+		if (!this.key) throw new Error('[Tree] nodeKey is required in getNodePath');
+		const node = this.getNode(data);
+		if (!node) return [];
+		
+		const path = [node.data];
+		let parent = node.getParent(node.parentId);
+		while (parent && parent !== this.root) {
+			path.push(parent.data);
+			parent = parent.getParent(parent.parentId);
+		}
+		return path.reverse();
+	}
+
+	getCheckedNodes(leafOnly = false, includeHalfChecked = false) {
+		const checkedNodes = [];
+		const traverse = function(node) {
+			const childNodes = node.root ? node.root.getChildNodes(node.root.childNodesId) : node.getChildNodes(node.childNodesId);
+
+			childNodes.forEach((child) => {
+				if ((child.checked || (includeHalfChecked && child.indeterminate)) && (!leafOnly || (leafOnly && child.isLeaf))) {
+					checkedNodes.push(child.data);
+				}
+
+				traverse(child);
+			});
+		};
+
+		traverse(this);
+
+		return checkedNodes;
+	}
+
+	getCheckedKeys(leafOnly = false, includeHalfChecked = false) {
+		return this.getCheckedNodes(leafOnly, includeHalfChecked).map((data) => (data || {})[this.key]);
+	}
+
+	getHalfCheckedNodes() {
+		const nodes = [];
+		const traverse = function(node) {
+			const childNodes = node.root ? node.root.getChildNodes(node.root.childNodesId) : node.getChildNodes(node.childNodesId);
+
+			childNodes.forEach((child) => {
+				if (child.indeterminate) {
+					nodes.push(child.data);
+				}
+
+				traverse(child);
+			});
+		};
+
+		traverse(this);
+
+		return nodes;
+	}
+
+	getHalfCheckedKeys() {
+		return this.getHalfCheckedNodes().map((data) => (data || {})[this.key]);
+	}
+
+	_getAllNodes() {
+		const allNodes = [];
+		const nodesMap = this.nodesMap;
+		for (let nodeKey in nodesMap) {
+			if (nodesMap.hasOwnProperty(nodeKey)) {
+				allNodes.push(nodesMap[nodeKey]);
+			}
+		}
+
+		return allNodes;
+	}
+
+	updateChildren(key, data) {
+		const node = this.nodesMap[key];
+		if (!node) return;
+		const childNodes = node.getChildNodes(node.childNodesId);
+		for (let i = childNodes.length - 1; i >= 0; i--) {
+			const child = childNodes[i];
+			this.remove(child.data);
+		}
+		for (let i = 0, j = data.length; i < j; i++) {
+			const child = data[i];
+			this.append(child, node.data);
+		}
+	}
+
+	_setCheckedKeys(key, leafOnly = false, checkedKeys) {
+		const allNodes = this._getAllNodes().sort((a, b) => b.level - a.level);
+		const cache = Object.create(null);
+		const keys = Object.keys(checkedKeys);
+		allNodes.forEach(node => node.setChecked(false, false));
+		for (let i = 0, j = allNodes.length; i < j; i++) {
+			const node = allNodes[i];
+			const nodeKey = node.data[key].toString();
+			let checked = keys.indexOf(nodeKey) > -1;
+			if (!checked) {
+				if (node.checked && !cache[nodeKey]) {
+					node.setChecked(false, false);
+				}
+				continue;
+			}
+
+			let parent = node.getParent(node.parentId);
+			while (parent && parent.level > 0) {
+				cache[parent.data[key]] = true;
+				parent = parent.getParent(parent.parentId);
+			}
+
+			if (node.isLeaf || this.checkStrictly) {
+				node.setChecked(true, false);
+				continue;
+			}
+			node.setChecked(true, true);
+
+			if (leafOnly) {
+				node.setChecked(false, false);
+				const traverse = function(node) {
+					const childNodes = node.getChildNodes(node.childNodesId);
+					childNodes.forEach((child) => {
+						if (!child.isLeaf) {
+							child.setChecked(false, false);
+						}
+						traverse(child);
+					});
+				};
+				traverse(node);
+			}
+		}
+	}
+
+	setCheckedNodes(array, leafOnly = false) {
+		const key = this.key;
+		const checkedKeys = {};
+		array.forEach((item) => {
+			checkedKeys[(item || {})[key]] = true;
+		});
+
+		this._setCheckedKeys(key, leafOnly, checkedKeys);
+	}
+
+	setCheckedKeys(keys, leafOnly = false) {
+		this.defaultCheckedKeys = keys;
+		const key = this.key;
+		const checkedKeys = {};
+		keys.forEach((key) => {
+			checkedKeys[key] = true;
+		});
+
+		this._setCheckedKeys(key, leafOnly, checkedKeys);
+	}
+
+	setDefaultExpandedKeys(keys) {
+		keys = keys || [];
+		this.defaultExpandedKeys = keys;
+
+		keys.forEach((key) => {
+			const node = this.getNode(key);
+			if (node) node.expand(null, this.autoExpandParent);
+		});
+	}
+
+	setChecked(data, checked, deep) {
+		const node = this.getNode(data);
+
+		if (node) {
+			node.setChecked(!!checked, deep);
+		}
+	}
+
+	getCurrentNode() {
+		return this.currentNode;
+	}
+
+	setCurrentNode(currentNode) {
+		const prevCurrentNode = this.currentNode;
+		if (prevCurrentNode) {
+			prevCurrentNode.isCurrent = false;
+		}
+		this.currentNode = currentNode;
+		this.currentNode.isCurrent = true;
+		
+		this.expandCurrentNodeParent && this.currentNode.expand(null, true)
+	}
+
+	setUserCurrentNode(node) {
+		const key = node[this.key];
+		const currNode = this.nodesMap[key];
+		this.setCurrentNode(currNode);
+	}
+
+	setCurrentNodeKey(key) {
+		if (key === null || key === undefined) {
+			this.currentNode && (this.currentNode.isCurrent = false);
+			this.currentNode = null;
+			return;
+		}
+		const node = this.getNode(key);
+		if (node) {
+			this.setCurrentNode(node);
+		}
+	}
+};

+ 0 - 0
components/ly-tree-nvue/tool/util.js


Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů