瀏覽代碼

first commit

Changpeng Duan 5 年之前
當前提交
96a20e445c
共有 100 個文件被更改,包括 15079 次插入0 次删除
  1. 15 0
      .gitignore
  2. 4 0
      .idea/encodings.xml
  3. 6 0
      .idea/misc.xml
  4. 8 0
      .idea/modules.xml
  5. 8 0
      .idea/w.iml
  6. 333 0
      .idea/workspace.xml
  7. 21 0
      app/.gitignore
  8. 46 0
      app/README.md
  9. 5 0
      app/babel.config.js
  10. 50 0
      app/package.json
  11. 二進制
      app/public/favicon.ico
  12. 20 0
      app/public/index.html
  13. 47 0
      app/src/App.vue
  14. 161 0
      app/src/Global.js
  15. 145 0
      app/src/Mock/index.js
  16. 160 0
      app/src/api/getApiRes.js
  17. 二進制
      app/src/assets/font/UnidreamLED.ttf
  18. 二進制
      app/src/assets/wille.png
  19. 110 0
      app/src/components/BaseCharts.js
  20. 150 0
      app/src/components/Hand.vue
  21. 63 0
      app/src/components/LineExample.js
  22. 93 0
      app/src/components/LineExample2.js
  23. 3833 0
      app/src/components/address3.json
  24. 32 0
      app/src/components/alert.vue
  25. 388 0
      app/src/components/appHeader.vue
  26. 62 0
      app/src/components/bottomTab.vue
  27. 139 0
      app/src/components/cityPicker.vue
  28. 396 0
      app/src/components/mapDrag.vue
  29. 581 0
      app/src/components/mapPage.vue
  30. 218 0
      app/src/components/statischart.vue
  31. 152 0
      app/src/components/statischart2.vue
  32. 370 0
      app/src/components/timePart.vue
  33. 134 0
      app/src/language/en-US.js
  34. 135 0
      app/src/language/ru-RU.js
  35. 135 0
      app/src/language/zh-CN.js
  36. 16 0
      app/src/libs/rem.js
  37. 151 0
      app/src/main.js
  38. 44 0
      app/src/page/404.vue
  39. 715 0
      app/src/page/appoint.vue
  40. 257 0
      app/src/page/detector.vue
  41. 140 0
      app/src/page/detectorDetail.vue
  42. 176 0
      app/src/page/enterpriseDetail.vue
  43. 376 0
      app/src/page/enterprisemanage.vue
  44. 31 0
      app/src/page/index.vue
  45. 518 0
      app/src/page/lesson.vue
  46. 354 0
      app/src/page/listDetail.vue
  47. 666 0
      app/src/page/login.vue
  48. 184 0
      app/src/page/mainpage.vue
  49. 51 0
      app/src/page/map.vue
  50. 542 0
      app/src/page/mine.vue
  51. 47 0
      app/src/page/modal.vue
  52. 61 0
      app/src/page/notFound.vue
  53. 332 0
      app/src/page/plane.vue
  54. 265 0
      app/src/page/profile.vue
  55. 613 0
      app/src/page/record.vue
  56. 318 0
      app/src/page/runtime.vue
  57. 148 0
      app/src/page/setting.vue
  58. 63 0
      app/src/page/sport.vue
  59. 50 0
      app/src/page/statis.vue
  60. 101 0
      app/src/page/test.vue
  61. 157 0
      app/src/page/userDetail.vue
  62. 212 0
      app/src/page/usermanage.vue
  63. 360 0
      app/src/page/white.vue
  64. 111 0
      app/src/router/index.js
  65. 二進制
      app/src/static/images/appoint/tri.png
  66. 二進制
      app/src/static/images/appoint/x.png
  67. 二進制
      app/src/static/images/bottom/Calendar@2x.png
  68. 二進制
      app/src/static/images/bottom/CalendarRed@2x.png
  69. 二進制
      app/src/static/images/bottom/Newspaper@2x.png
  70. 二進制
      app/src/static/images/bottom/NewspaperRed@2x.png
  71. 二進制
      app/src/static/images/bottom/User@2x.png
  72. 二進制
      app/src/static/images/bottom/UserRed@2x.png
  73. 二進制
      app/src/static/images/bottom/sport.png
  74. 二進制
      app/src/static/images/comm/arrow-left.png
  75. 二進制
      app/src/static/images/comm/b11.png
  76. 二進制
      app/src/static/images/comm/b11_1.png
  77. 二進制
      app/src/static/images/comm/b12.png
  78. 二進制
      app/src/static/images/comm/b12_1.png
  79. 二進制
      app/src/static/images/comm/b13.png
  80. 二進制
      app/src/static/images/comm/b13_1.png
  81. 二進制
      app/src/static/images/comm/b14.png
  82. 二進制
      app/src/static/images/comm/b14_1.png
  83. 二進制
      app/src/static/images/comm/cityPicker.png
  84. 二進制
      app/src/static/images/comm/headerBg.png
  85. 二進制
      app/src/static/images/comm/iconEquipmanage.png
  86. 二進制
      app/src/static/images/comm/iconEquipmanage_a.png
  87. 二進制
      app/src/static/images/comm/iconHome.png
  88. 二進制
      app/src/static/images/comm/iconHome_a.png
  89. 二進制
      app/src/static/images/comm/iconMap.png
  90. 二進制
      app/src/static/images/comm/iconMap_a.png
  91. 二進制
      app/src/static/images/comm/iconProfile.png
  92. 二進制
      app/src/static/images/comm/iconProfile_a.png
  93. 二進制
      app/src/static/images/comm/iconRecord.png
  94. 二進制
      app/src/static/images/comm/iconRecord_a.png
  95. 二進制
      app/src/static/images/comm/iconRuntime.png
  96. 二進制
      app/src/static/images/comm/iconRuntime_a.png
  97. 二進制
      app/src/static/images/comm/iconStatis.png
  98. 二進制
      app/src/static/images/comm/iconStatis_a.png
  99. 二進制
      app/src/static/images/comm/iconUser.png
  100. 二進制
      app/src/static/images/comm/iconUser_a.png

+ 15 - 0
.gitignore

@@ -0,0 +1,15 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+
+node_modules/
+platforms/
+dist/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+package-lock.json
+/hbuild/GoAllOutTv/build/
+/hbuild/GoAllOutTv/GoAllOutTv/

+ 4 - 0
.idea/encodings.xml

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Encoding" addBOMForNewFiles="with NO BOM" />
+</project>

+ 6 - 0
.idea/misc.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="JavaScriptSettings">
+    <option name="languageLevel" value="ES6" />
+  </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/w.iml" filepath="$PROJECT_DIR$/.idea/w.iml" />
+    </modules>
+  </component>
+</project>

+ 8 - 0
.idea/w.iml

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

+ 333 - 0
.idea/workspace.xml

@@ -0,0 +1,333 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ChangeListManager">
+    <list default="true" id="d2d14daa-fcc9-421d-abb9-b81e7b0e4169" name="Default Changelist" comment="" />
+    <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
+    <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="FileEditorManager">
+    <leaf SIDE_TABS_SIZE_LIMIT_KEY="375">
+      <file pinned="false" current-in-tab="true">
+        <entry file="file://$PROJECT_DIR$/app/src/page/mainpage.vue">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="273">
+              <caret line="120" column="17" selection-start-line="120" selection-start-column="17" selection-end-line="120" selection-end-column="17" />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/app/src/page/index.vue">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="546">
+              <caret line="26" column="23" selection-start-line="26" selection-start-column="23" selection-end-line="26" selection-end-column="23" />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/app/src/page/sport.vue">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="651">
+              <caret line="33" column="34" selection-start-line="33" selection-start-column="34" selection-end-line="33" selection-end-column="34" />
+            </state>
+          </provider>
+        </entry>
+      </file>
+    </leaf>
+  </component>
+  <component name="FileTemplateManagerImpl">
+    <option name="RECENT_TEMPLATES">
+      <list>
+        <option value="Vue Single File Component" />
+      </list>
+    </option>
+  </component>
+  <component name="FindInProjectRecents">
+    <findStrings>
+      <find>GoAllO</find>
+      <find>goallout</find>
+      <find>goall</find>
+      <find>rem</find>
+      <find>#01355B</find>
+      <find>number</find>
+      <find>fade</find>
+      <find>walk</find>
+    </findStrings>
+    <replaceStrings>
+      <replace>red</replace>
+      <replace>step</replace>
+      <replace>scale</replace>
+    </replaceStrings>
+    <dirStrings>
+      <dir>D:\wwwroot\w\app</dir>
+    </dirStrings>
+  </component>
+  <component name="Git.Settings">
+    <option name="PATH_TO_GIT" value="git.exe" />
+    <option name="ROOT_SYNC" value="DONT_SYNC" />
+  </component>
+  <component name="IdeDocumentHistory">
+    <option name="CHANGED_PATHS">
+      <list>
+        <option value="$PROJECT_DIR$/app/package.json" />
+        <option value="$PROJECT_DIR$/app/src/router/index.js" />
+        <option value="$PROJECT_DIR$/app/src/Global.js" />
+        <option value="$PROJECT_DIR$/app/src/page/mainpage.vue" />
+        <option value="$PROJECT_DIR$/app/src/page/index.vue" />
+        <option value="$PROJECT_DIR$/app/src/components/bottomTab.vue" />
+        <option value="$PROJECT_DIR$/app/src/components/timePart.vue" />
+        <option value="$PROJECT_DIR$/app/src/components/Hand.vue" />
+        <option value="$PROJECT_DIR$/app/src/page/sport.vue" />
+      </list>
+    </option>
+  </component>
+  <component name="ProjectFrameBounds" extendedState="7">
+    <option name="x" value="-2568" />
+    <option name="y" value="-8" />
+    <option name="width" value="2576" />
+    <option name="height" value="1395" />
+  </component>
+  <component name="ProjectView">
+    <navigator proportions="" version="1">
+      <foldersAlwaysOnTop value="true" />
+    </navigator>
+    <panes>
+      <pane id="ProjectPane">
+        <subPane>
+          <expand>
+            <path>
+              <item name="w" type="b2602c69:ProjectViewProjectNode" />
+              <item name="w" type="462c0819:PsiDirectoryNode" />
+            </path>
+            <path>
+              <item name="w" type="b2602c69:ProjectViewProjectNode" />
+              <item name="w" type="462c0819:PsiDirectoryNode" />
+              <item name="app" type="462c0819:PsiDirectoryNode" />
+            </path>
+            <path>
+              <item name="w" type="b2602c69:ProjectViewProjectNode" />
+              <item name="w" type="462c0819:PsiDirectoryNode" />
+              <item name="app" type="462c0819:PsiDirectoryNode" />
+              <item name="src" type="462c0819:PsiDirectoryNode" />
+            </path>
+            <path>
+              <item name="w" type="b2602c69:ProjectViewProjectNode" />
+              <item name="w" type="462c0819:PsiDirectoryNode" />
+              <item name="app" type="462c0819:PsiDirectoryNode" />
+              <item name="src" type="462c0819:PsiDirectoryNode" />
+              <item name="components" type="462c0819:PsiDirectoryNode" />
+            </path>
+            <path>
+              <item name="w" type="b2602c69:ProjectViewProjectNode" />
+              <item name="w" type="462c0819:PsiDirectoryNode" />
+              <item name="app" type="462c0819:PsiDirectoryNode" />
+              <item name="src" type="462c0819:PsiDirectoryNode" />
+              <item name="libs" type="462c0819:PsiDirectoryNode" />
+            </path>
+          </expand>
+          <select />
+        </subPane>
+      </pane>
+      <pane id="Scope" />
+    </panes>
+  </component>
+  <component name="PropertiesComponent">
+    <property name="WebServerToolWindowFactoryState" value="false" />
+    <property name="last_opened_file_path" value="$PROJECT_DIR$" />
+    <property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
+    <property name="nodejs_npm_path_reset_for_default_project" value="true" />
+    <property name="nodejs_package_manager_path" value="npm" />
+    <property name="restartRequiresConfirmation" value="false" />
+    <property name="settings.editor.selected.configurable" value="preferences.pluginManager" />
+  </component>
+  <component name="RecentsManager">
+    <key name="CopyFile.RECENT_KEYS">
+      <recent name="D:\wwwroot\w\app\src\assets" />
+      <recent name="D:\wwwroot\w\app\src\components" />
+      <recent name="D:\wwwroot\w\app\src" />
+      <recent name="D:\wwwroot\w\app\src\static\images\comm" />
+      <recent name="D:\wwwroot\w\app\public" />
+    </key>
+  </component>
+  <component name="RunDashboard">
+    <option name="ruleStates">
+      <list>
+        <RuleState>
+          <option name="name" value="ConfigurationTypeDashboardGroupingRule" />
+        </RuleState>
+        <RuleState>
+          <option name="name" value="StatusDashboardGroupingRule" />
+        </RuleState>
+      </list>
+    </option>
+  </component>
+  <component name="RunManager">
+    <configuration name="serve" type="js.build_tools.npm" nameIsGenerated="true">
+      <package-json value="$PROJECT_DIR$/app/package.json" />
+      <command value="run" />
+      <scripts>
+        <script value="serve" />
+      </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="d2d14daa-fcc9-421d-abb9-b81e7b0e4169" name="Default Changelist" comment="" />
+      <created>1605261565825</created>
+      <option name="number" value="Default" />
+      <option name="presentableId" value="Default" />
+      <updated>1605261565825</updated>
+      <workItem from="1605261567466" duration="8935000" />
+      <workItem from="1605406240238" duration="4707000" />
+    </task>
+    <servers />
+  </component>
+  <component name="TimeTrackingManager">
+    <option name="totallyTimeSpent" value="13642000" />
+  </component>
+  <component name="ToolWindowManager">
+    <frame x="-2568" y="-8" width="2576" height="1395" extended-state="7" />
+    <editor active="true" />
+    <layout>
+      <window_info content_ui="combo" id="Project" order="0" weight="0.21491228" />
+      <window_info id="Structure" order="1" side_tool="true" weight="0.24973656" />
+      <window_info id="Favorites" order="2" side_tool="true" weight="0.32982087" />
+      <window_info anchor="bottom" id="Message" order="0" />
+      <window_info anchor="bottom" id="Find" order="1" weight="0.32692307" />
+      <window_info anchor="bottom" id="Run" order="2" weight="0.39005896" />
+      <window_info anchor="bottom" id="Debug" order="3" weight="0.21468298" />
+      <window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
+      <window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
+      <window_info anchor="bottom" id="TODO" order="6" />
+      <window_info anchor="bottom" id="PHP-CGI Server" order="7" />
+      <window_info anchor="bottom" id="Event Log" order="8" side_tool="true" />
+      <window_info anchor="bottom" id="Version Control" order="9" weight="0.32918552" />
+      <window_info anchor="bottom" id="Terminal" order="10" weight="0.17354676" />
+      <window_info anchor="bottom" id="Database Changes" order="11" />
+      <window_info anchor="right" id="Commander" order="0" weight="0.4" />
+      <window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
+      <window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
+      <window_info anchor="right" id="Database" order="3" />
+    </layout>
+  </component>
+  <component name="TypeScriptGeneratedFilesManager">
+    <option name="version" value="1" />
+  </component>
+  <component name="editorHistoryManager">
+    <entry file="file://$PROJECT_DIR$/app/src/page/login.vue">
+      <provider selected="true" editor-type-id="text-editor" />
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/vue.config.js">
+      <provider selected="true" editor-type-id="text-editor" />
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/package.json">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="21">
+          <caret line="1" column="12" selection-start-line="1" selection-start-column="12" selection-end-line="1" selection-end-column="12" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/public/index.html">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="315">
+          <caret line="15" column="11" lean-forward="true" selection-start-line="15" selection-start-column="11" selection-end-line="15" selection-end-column="11" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/src/components/appHeader.vue">
+      <provider selected="true" editor-type-id="text-editor" />
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/public/favicon.ico">
+      <provider selected="true" editor-type-id="images" />
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/src/main.js">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="1176">
+          <caret line="56" column="23" selection-start-line="56" selection-start-column="23" selection-end-line="56" selection-end-column="23" />
+          <folding>
+            <element signature="e#0#21#0" expanded="true" />
+            <element signature="e#179#213#0" expanded="true" />
+          </folding>
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/icon/logo.png">
+      <provider selected="true" editor-type-id="images" />
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/src/router/index.js">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="194">
+          <caret line="13" column="2" selection-start-line="13" selection-start-column="2" selection-end-line="13" selection-end-column="2" />
+          <folding>
+            <element signature="e#0#21#0" expanded="true" />
+          </folding>
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/src/libs/rem.js">
+      <provider selected="true" editor-type-id="text-editor" />
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/src/Global.js">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="941">
+          <caret line="161" lean-forward="true" selection-start-line="161" selection-end-line="161" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/src/App.vue">
+      <provider selected="true" editor-type-id="text-editor" />
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/src/components/bottomTab.vue">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="950">
+          <caret line="59" column="22" selection-start-line="59" selection-start-column="22" selection-end-line="59" selection-end-column="22" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/src/components/timePart.vue">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="777">
+          <caret line="64" column="38" selection-end-line="370" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/src/page/index.vue">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="546">
+          <caret line="26" column="23" selection-start-line="26" selection-start-column="23" selection-end-line="26" selection-end-column="23" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/src/components/Hand.vue">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="295">
+          <caret line="16" column="45" selection-start-line="16" selection-start-column="45" selection-end-line="16" selection-end-column="45" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/src/page/sport.vue">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="651">
+          <caret line="33" column="34" selection-start-line="33" selection-start-column="34" selection-end-line="33" selection-end-column="34" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/src/page/mainpage.vue">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="273">
+          <caret line="120" column="17" selection-start-line="120" selection-start-column="17" selection-end-line="120" selection-end-column="17" />
+        </state>
+      </provider>
+    </entry>
+  </component>
+</project>

+ 21 - 0
app/.gitignore

@@ -0,0 +1,21 @@
+.DS_Store
+node_modules
+/dist
+
+# local env files
+.env.local
+.env.*.local
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?

+ 46 - 0
app/README.md

@@ -0,0 +1,46 @@
+# musevue
+
+## Project setup
+```
+npm install
+```
+
+### Compiles and hot-reloads for development
+```
+npm run serve
+```
+
+### Compiles and minifies for production
+```
+npm run build
+```
+
+### Lints and fixes files
+```
+npm run lint
+```
+
+### Customize configuration
+See [Configuration Reference](https://cli.vuejs.org/config/).
+
+##
+
+=====
+toast
+
+<mu-snackbar :position="normal.position" :open.sync="normal.open" :color="normal.color">
+{{normal.message}}
+<mu-button flat slot="action" color="secondary" @click="normal.open = false">关闭</mu-button>
+</mu-snackbar>
+    
+data
+
+normal:normal,
+
+使用
+Toast(msg,color);
+
+###
+20200831
+1. 把新框架结构加入新版 app-template 中
+2. 优化项目结构,删掉无用的页面和资源

+ 5 - 0
app/babel.config.js

@@ -0,0 +1,5 @@
+module.exports = {
+  presets: [
+    '@vue/cli-plugin-babel/preset'
+  ]
+}

+ 50 - 0
app/package.json

@@ -0,0 +1,50 @@
+{
+  "name": "W",
+  "version": "0.1.0",
+  "private": true,
+  "scripts": {
+    "serve": "vue-cli-service serve",
+    "build": "vue-cli-service build",
+    "lint": "vue-cli-service lint"
+  },
+  "dependencies": {
+    "axios": "^0.19.2",
+    "chart.js": "^2.9.3",
+    "core-js": "^3.6.4",
+    "muse-ui": "^3.0.2",
+    "muse-ui-loading": "^0.2.0",
+    "muse-ui-message": "^0.2.1",
+    "muse-ui-progress": "^0.1.0",
+    "muse-ui-toast": "^0.3.0",
+    "vue": "^2.6.11",
+    "vue-router": "^3.1.5"
+  },
+  "devDependencies": {
+    "@vue/cli-plugin-babel": "~4.2.0",
+    "@vue/cli-plugin-eslint": "~4.2.0",
+    "@vue/cli-plugin-router": "^4.2.2",
+    "@vue/cli-service": "~4.2.0",
+    "babel-eslint": "^10.0.3",
+    "eslint": "^6.7.2",
+    "eslint-plugin-vue": "^6.1.2",
+    "vue-cli-plugin-axios": "0.0.4",
+    "vue-template-compiler": "^2.6.11"
+  },
+  "eslintConfig": {
+    "root": true,
+    "env": {
+      "node": true
+    },
+    "extends": [
+      "plugin:vue/essential",
+      "eslint:recommended"
+    ],
+    "parserOptions": {
+      "parser": "babel-eslint"
+    }
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions"
+  ]
+}

二進制
app/public/favicon.ico


+ 20 - 0
app/public/index.html

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+<!--    <meta name="viewport" content="width=device-width,initial-scale=1.0">-->
+    <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"/>
+    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
+    <title><%= htmlWebpackPlugin.options.title %></title>
+    <link rel="stylesheet" href="https://cdn.bootcss.com/material-design-icons/3.0.1/iconfont/material-icons.css">
+</head>
+<body>
+<noscript>
+    <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
+        Please enable it to continue.</strong>
+</noscript>
+<div id="app"></div>
+<!-- built files will be auto injected -->
+</body>
+</html>

+ 47 - 0
app/src/App.vue

@@ -0,0 +1,47 @@
+<template>
+    <div id="app">
+        <transition name="fade">
+            <router-view/>
+        </transition>
+    </div>
+</template>
+
+<style>
+    #app {
+        position: absolute;
+        top: 0;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        width: 100%;
+        height: 100%;
+        overflow-y: hidden;
+    }
+
+    ul, li {
+        list-style: none;
+        padding: 0;
+    }
+
+    s, i, em {
+        text-decoration: none;
+        font-style: normal;
+    }
+
+    /*叹号问题*/
+    .mu-warning-text-color {
+      float: left;
+    }
+</style>
+<script>
+window.onload = function() {
+  document.addEventListener('touchstart', function(event) {
+    if (event.touches.length > 1) {
+      event.preventDefault()
+    }
+  })
+  document.addEventListener('gesturestart', function(event) {
+    event.preventDefault()
+  })
+}
+</script>

+ 161 - 0
app/src/Global.js

@@ -0,0 +1,161 @@
+headapi = process.env.NODE_ENV === 'development' ? '/api/' : '../';
+
+//Toast
+Toast = function (message, color) {
+    // normal.open = true;
+    // normal.message = message;
+    // normal.color = !color ? 'warning' : color;
+    // normal.timer = setTimeout(() => {
+    //     normal.open = false;
+    // }, normal.timeout);
+    this.$toast.message(message);
+};
+
+// Toast default setting
+normal = {
+    color: 'warning', // ['success', 'info', 'error', 'warning'],
+    position: 'top',
+    message: 'Hello World, Snackbar !',
+    open: false,
+    timeout: 3000
+};
+
+globaltime2StringNoMin = function (time) {
+    let datetime = new Date();
+    datetime.setTime(time);
+    let year = datetime.getFullYear();
+    let month = datetime.getMonth() + 1 < 10 ? "0" + (datetime.getMonth() + 1) : datetime.getMonth() + 1;
+    let date = datetime.getDate() < 10 ? "0" + datetime.getDate() : datetime.getDate();
+    let hour = datetime.getHours() < 10 ? "0" + datetime.getHours() : datetime.getHours();
+    let minus = datetime.getMinutes() < 10 ? "0" + datetime.getMinutes() : datetime.getMinutes();
+    return year + "-" + month + "-" + date;
+};
+
+globalBt2 = function () {
+    const et = new Date();
+    const bt = new Date();
+    bt.setTime(bt.getTime() - 3600 * 1000 * 24 * 7);
+    return [bt, et];
+};
+
+globalTimeToYY = function () {
+    let datetime = new Date();
+    let year = datetime.getFullYear();
+    let month = datetime.getMonth() + 1 < 10 ? "0" + (datetime.getMonth() + 1) : datetime.getMonth() + 1;
+    let date = datetime.getDate() < 10 ? "0" + datetime.getDate() : datetime.getDate();
+    console.log(year + "-" + month + "-" + date);
+    return year + "-" + month + "-" + date;
+
+};
+// 获取当前时间
+globalcurrent = function () {
+    let date = new Date();
+    let seperator1 = "-";
+    let year = date.getFullYear();
+    let month = date.getMonth() + 1;
+    let strDate = date.getDate();
+    if (month >= 1 && month <= 9) {
+        month = "0" + month;
+    }
+    if (strDate >= 0 && strDate <= 9) {
+        strDate = "0" + strDate;
+    }
+    let thisdata = year + seperator1 + month + seperator1 + strDate;
+    return thisdata;
+};
+
+// 手机号码格式
+globalCheckPhone = function (val) {
+    let re = /^1[3|4|5|6|7|8|9][0-9]\d{8}$/;
+    val = val.toString();
+    if (val.search(re) == -1) {
+        return false;
+    } else {
+        return true;
+    }
+};
+
+// 格式化时间
+globalfmtDate = function (datetime, length) {
+    if ((datetime == '') || (datetime == undefined))
+        return '';
+    if ((datetime == '1900-01-01') || (datetime == '1900-01-01 00:00:00.000'))
+        return '';
+    length = !length ? 10 : length;//缺省参数
+    return (datetime != null) ? datetime.substr(0, length) : '';
+};
+//格式化日期  年月日
+globaltime2String = function (time) {
+    let datetime = new Date();
+    datetime.setTime(time);
+    let year = datetime.getFullYear();
+    let month = datetime.getMonth() + 1 < 10 ? "0" + (datetime.getMonth() + 1) : datetime.getMonth() + 1;
+    let date = datetime.getDate() < 10 ? "0" + datetime.getDate() : datetime.getDate();
+    let hour = datetime.getHours() < 10 ? "0" + datetime.getHours() : datetime.getHours();
+    let minus = datetime.getMinutes() < 10 ? "0" + datetime.getMinutes() : datetime.getMinutes();
+    return year + "-" + month + "-" + date + " " + hour + ":" + minus + ":00";
+};
+
+address = {
+    '北京': ['北京'],
+    '广东': ['广州', '深圳', '珠海', '汕头', '韶关', '佛山', '江门', '湛江', '茂名', '肇庆', '惠州', '梅州', '汕尾', '河源', '阳江', '清远', '东莞', '中山', '潮州', '揭阳', '云浮'],
+    '上海': ['上海'],
+    '天津': ['天津'],
+    '重庆': ['重庆'],
+    '辽宁': ['沈阳', '大连', '鞍山', '抚顺', '本溪', '丹东', '锦州', '营口', '阜新', '辽阳', '盘锦', '铁岭', '朝阳', '葫芦岛'],
+    '江苏': ['南京', '苏州', '无锡', '常州', '镇江', '南通', '泰州', '扬州', '盐城', '连云港', '徐州', '淮安', '宿迁'],
+    '湖北': ['武汉', '黄石', '十堰', '荆州', '宜昌', '襄樊', '鄂州', '荆门', '孝感', '黄冈', '咸宁', '随州', '恩施土家族苗族自治州', '仙桃', '天门', '潜江', '神农架林区'],
+    '四川': ['成都', '自贡', '攀枝花', '泸州', '德阳', '绵阳', '广元', '遂宁', '内江', '乐山', '南充', '眉山', '宜宾', '广安', '达州', '雅安', '巴中', '资阳', '阿坝藏族羌族自治州', '甘孜藏族自治州', '凉山彝族自治州'],
+    '陕西': ['西安', '铜川', '宝鸡', '咸阳', '渭南', '延安', '汉中', '榆林', '安康', '商洛'],
+    '河北': ['石家庄', '唐山', '秦皇岛', '邯郸', '邢台', '保定', '张家口', '承德', '沧州', '廊坊', '衡水'],
+    '山西': ['太原', '大同', '阳泉', '长治', '晋城', '朔州', '晋中', '运城', '忻州', '临汾', '吕梁'],
+    '河南': ['郑州', '开封', '洛阳', '平顶山', '安阳', '鹤壁', '新乡', '焦作', '濮阳', '许昌', '漯河', '三门峡', '南阳', '商丘', '信阳', '周口', '驻马店'],
+    '吉林': ['长春', '吉林', '四平', '辽源', '通化', '白山', '松原', '白城', '延边朝鲜族自治州'],
+    '黑龙江': ['哈尔滨', '齐齐哈尔', '鹤岗', '双鸭山', '鸡西', '大庆', '伊春', '牡丹江', '佳木斯', '七台河', '黑河', '绥化', '大兴安岭地区'],
+    '内蒙古': ['呼和浩特', '包头', '乌海', '赤峰', '通辽', '鄂尔多斯', '呼伦贝尔', '巴彦淖尔', '乌兰察布', '锡林郭勒盟', '兴安盟', '阿拉善盟'],
+    '山东': ['济南', '青岛', '淄博', '枣庄', '东营', '烟台', '潍坊', '济宁', '泰安', '威海', '日照', '莱芜', '临沂', '德州', '聊城', '滨州', '菏泽'],
+    '安徽': ['合肥', '芜湖', '蚌埠', '淮南', '马鞍山', '淮北', '铜陵', '安庆', '黄山', '滁州', '阜阳', '宿州', '巢湖', '六安', '亳州', '池州', '宣城'],
+    '浙江': ['杭州', '宁波', '温州', '嘉兴', '湖州', '绍兴', '金华', '衢州', '舟山', '台州', '丽水'],
+    '福建': ['福州', '厦门', '莆田', '三明', '泉州', '漳州', '南平', '龙岩', '宁德'],
+    '湖南': ['长沙', '株洲', '湘潭', '衡阳', '邵阳', '岳阳', '常德', '张家界', '益阳', '郴州', '永州', '怀化', '娄底', '湘西土家族苗族自治州'],
+    '广西': ['南宁', '柳州', '桂林', '梧州', '北海', '防城港', '钦州', '贵港', '玉林', '百色', '贺州', '河池', '来宾', '崇左'],
+    '江西': ['南昌', '景德镇', '萍乡', '九江', '新余', '鹰潭', '赣州', '吉安', '宜春', '抚州', '上饶'],
+    '贵州': ['贵阳', '六盘水', '遵义', '安顺', '铜仁地区', '毕节地区', '黔西南布依族苗族自治州', '黔东南苗族侗族自治州', '黔南布依族苗族自治州'],
+    '云南': ['昆明', '曲靖', '玉溪', '保山', '昭通', '丽江', '普洱', '临沧', '德宏傣族景颇族自治州', '怒江傈僳族自治州', '迪庆藏族自治州', '大理白族自治州', '楚雄彝族自治州', '红河哈尼族彝族自治州', '文山壮族苗族自治州', '西双版纳傣族自治州'],
+    '西藏': ['拉萨', '那曲地区', '昌都地区', '林芝地区', '山南地区', '日喀则地区', '阿里地区'],
+    '海南': ['海口', '三亚', '五指山', '琼海', '儋州', '文昌', '万宁', '东方', '澄迈县', '定安县', '屯昌县', '临高县', '白沙黎族自治县', '昌江黎族自治县', '乐东黎族自治县', '陵水黎族自治县', '保亭黎族苗族自治县', '琼中黎族苗族自治县'],
+    '甘肃': ['兰州', '嘉峪关', '金昌', '白银', '天水', '武威', '酒泉', '张掖', '庆阳', '平凉', '定西', '陇南', '临夏回族自治州', '甘南藏族自治州'],
+    '宁夏': ['银川', '石嘴山', '吴忠', '固原', '中卫'],
+    '青海': ['西宁', '海东地区', '海北藏族自治州', '海南藏族自治州', '黄南藏族自治州', '果洛藏族自治州', '玉树藏族自治州', '海西蒙古族藏族自治州'],
+    '新疆': ['乌鲁木齐', '克拉玛依', '吐鲁番地区', '哈密地区', '和田地区', '阿克苏地区', '喀什地区', '克孜勒苏柯尔克孜自治州', '巴音郭楞蒙古自治州', '昌吉回族自治州', '博尔塔拉蒙古自治州', '石河子', '阿拉尔', '图木舒克', '五家渠', '伊犁哈萨克自治州'],
+    '香港': ['香港'],
+    '澳门': ['澳门'],
+    '台湾': ['台北市', '高雄市', '台北县', '桃园县', '新竹县', '苗栗县', '台中县', '彰化县', '南投县', '云林县', '嘉义县', '台南县', '高雄县', '屏东县', '宜兰县', '花莲县', '台东县', '澎湖县', '基隆市', '新竹市', '台中市', '嘉义市', '台南市']
+};
+if (localStorage.language == 'zh') {
+    dayAbbreviation = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
+    dayList = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
+    monthList = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月',
+        '十月', '十一月', '十二月'];
+    monthLongList = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月',
+        '十月', '十一月', '十二月'];
+} else {
+    dayAbbreviation = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
+    dayList = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
+    monthList = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
+        'Oct', 'Nov', 'Dec'];
+    monthLongList = ['January', 'February', 'March', 'April', 'May', 'June',
+        'July', 'August', 'September', 'October', 'November', 'December'];
+
+}
+
+globalcurrentTime = function () {
+    let date = new Date();
+    let Hours = date.getHours();
+    let Minutes = date.getMinutes();
+    let Seconds = date.getSeconds();
+    Hours = Hours < 10 ? '0' + Hours : Hours;
+    Minutes = Minutes < 10 ? '0' + Minutes : Minutes;
+    Seconds = Seconds < 10 ? '0' + Seconds : Seconds;
+    return Hours + ":" + Minutes + ":" + Seconds;
+};

+ 145 - 0
app/src/Mock/index.js

@@ -0,0 +1,145 @@
+import Mock from 'mockjs'
+
+let Random = Mock.Random;
+
+// worldDetail
+let worldDetail = function () {
+    let item = [];
+    for (var i = 0; i < 30; i++) {
+        item.push({
+            "id": "@guid",
+            "name": "@region",
+            "Confirmed": "@integer(36844, 368449)",
+            "Deaths": "@integer(1099, 10993)",
+            "Recovered": "@integer(1986, 19865)",
+        })
+    }
+
+    let res = {
+        Rs: item,
+        Code: 0,
+        Memo: ''
+    };
+    return res;
+};
+
+let testPic = function () {
+    let res = {
+        pic:  Random.image('200x100', '#894FC4', '#FFF', '@natural(1111, 9999)'),
+        id: "@guid",
+        Code: 0,
+        Memo: ''
+    };
+    return res;
+};
+
+let testTable = function () {
+    let item = [];
+
+    let members = [
+        {id: 1, name: '霍元甲', userCode: '15253135600', vipType: 1},
+        {id: 2, name: '陈真', userCode: '15253135602', vipType: 2},
+        {id: 3, name: '成龙', userCode: '15253135604', vipType: 1},
+    ]
+
+    for (var i = 0; i < 6; i++) {
+        item.push({
+            "id": "@guid",
+            "userCode": "@integer(15253135600, 15253135699)",
+            "name": "@region",
+            "tel": "@integer(15253135600, 15253135699)",
+            "shop": "@region",
+            "create": "@datetime",
+            "expTime": "@date",
+            "valid": "@datetime",
+            "Confirmed": "@integer(36844, 368449)",
+            "Deaths": "@integer(1099, 10993)",
+            "kick": "@integer(199, 993)",
+            "Recovered": "@integer(1986, 9999)",
+            "Status": "0",
+            "level": "0",
+            // "Status": "@integer(1, 2)",
+            "color": "@hex",
+            "memo": "@paragraph(1, 1)",
+            "dialogValue": "@range(1, 3)",
+            "vipType": "@integer(1, 2)",
+            "members": members,
+            "wxVisible": "@integer(0, 1)",
+            "timeLong": "14:00-16:00",
+            "timeScope":  [new Date(2016, 9, 10, 8, 40), new Date(2016, 9, 10, 9, 40)],
+        })
+    }
+
+    let res = {
+        Rs: item,
+        Code: 0,
+        Memo: ''
+    };
+    return res;
+};
+
+let testSelect = function () {
+    let item = [];
+    for (var i = 0; i < 30; i++) {
+        item.push({
+            "key": i + 1,
+            "value": i + 1,
+            "label": "@region",
+        })
+    }
+
+    let res = {
+        Rs: item,
+        Code: 0,
+        Memo: ''
+    };
+    return res;
+};
+
+let SignIn = function () {
+
+    let Rs = {
+        token: "@guid"
+    };
+    let res = {
+        Rs: Rs,
+        Code: 0,
+        Memo: '登陆成功'
+    };
+    return res;
+};
+
+let editbasicinfo = function () {
+
+    let res = {
+        Code: 0,
+        Memo: '修改成功'
+    };
+    return res;
+};
+
+let modPwd = function () {
+    let res = {
+        Code: 0,
+        Memo: '修改成功'
+    };
+    return res;
+};
+let logout = function () {
+    let res = {
+        Code: 0,
+        Memo: '退出成功'
+    };
+    return res;
+};
+
+Mock.mock('/api/testPic', 'post', testPic());
+Mock.mock('/api/testSelect', 'post', testSelect());
+Mock.mock('/api/testTable', 'post', testTable());
+Mock.mock('/api/worldDetail', 'post', worldDetail());
+Mock.mock('/api/SignIn', 'post', SignIn());//用户登录
+Mock.mock('/api/editbasicinfo', 'post', editbasicinfo());//用户设置修改
+Mock.mock('/api/modPwd', 'post', modPwd());//密码修改
+Mock.mock('/api/logout', 'post', logout());//退出登陆
+
+export default Mock;

+ 160 - 0
app/src/api/getApiRes.js

@@ -0,0 +1,160 @@
+import axios from 'axios';
+import global from '../Global.js'
+// 基础方法进行封装
+function getApiBasic(url, postdata) {
+    return  axios.post(url, postdata).then(function(data){
+        let json = data.data;
+        return json
+    },function(response){
+        console.info(response);
+    })
+}
+
+// 调用的api改写成方法
+export function worldDetail(postdata) {
+        let url = headapi + 'worldDetail';
+        return getApiBasic(url,postdata);
+}
+
+
+
+export function editbasicinfo(postdata) {
+    let url = headapi + 'editbasicinfo';
+    return getApiBasic(url,postdata);
+}
+export function modPwd(postdata) {
+    let url = headapi + 'modPwd';
+    return getApiBasic(url,postdata);
+}
+export function logout(postdata) {
+    let url = headapi + 'logout';
+    return getApiBasic(url,postdata);
+}
+
+// 调用的api改写成方法
+export function testTable(postdata) {
+    let url = headapi + 'testTable';
+    return getApiBasic(url,postdata);
+}
+export function testSelect(postdata) {
+    let url = headapi + 'testSelect';
+    return getApiBasic(url,postdata);
+}
+
+export function testPic(postdata) {
+    let url = headapi + 'testPic';
+    return getApiBasic(url,postdata);
+}
+
+
+// 正式接口
+
+// 获取验证图片
+export function GenVerifyPic(postdata) {
+    let url = headapi + 'v1/Auth/GenVerifyPic';
+    return getApiBasic(url, postdata);
+}
+
+// 手机获取验证码
+export function GetPhoneVFCode(postdata) {
+    let url = headapi + 'v1/Auth/GetPhoneVFCode';
+    return getApiBasic(url, postdata);
+}
+
+export function SignIn(postdata) {
+    let url = headapi + 'v1/Auth/SignIn';
+    return getApiBasic(url,postdata);
+}
+// 手机登录
+export function PhoneSignIn(postdata) {
+    let url = headapi + 'v1/Auth/PhoneSignIn';
+    return getApiBasic(url,postdata);
+}
+
+// 用户微信绑定
+export function WXBind(postdata) {
+    let url = headapi + 'v1/Auth/WXBind';
+    return getApiBasic(url,postdata);
+}
+
+// 用户微信登录
+export function WXSignIn(postdata) {
+    let url = headapi + 'v1/Auth/WXSignIn';
+    return getApiBasic(url,postdata);
+}
+
+// 用户微信解除绑定
+export function WXUnbind(postdata) {
+    let url = headapi + 'v1/Auth/WXUnbind';
+    return getApiBasic(url,postdata);
+}
+
+
+// Weixin
+
+// 预约课程
+export function OderAddByVipUser(postdata) {
+    let url = headapi + 'v1/Weixin/OderAddByVipUser';
+    return getApiBasic(url,postdata);
+}
+
+// 取消预约
+export function OderCancelByVipUser(postdata) {
+    let url = headapi + 'v1/Weixin/OderCancelByVipUser';
+    return getApiBasic(url,postdata);
+}
+// 预约记录查询
+export function OrderListQuery(postdata) {
+    let url = headapi + 'v1/Weixin/OrderListQuery';
+    return getApiBasic(url,postdata);
+}
+// 可预约店铺信息查询
+export function OrderShopQuery(postdata) {
+    let url = headapi + 'v1/Weixin/OrderShopQuery';
+    return getApiBasic(url,postdata);
+}
+// 可预约课程列表查询(未完成)
+export function CanOrderSchoolTimeTableListQuery(postdata) {
+    let url = headapi + 'v1/Weixin/CanOrderSchoolTimeTableListQuery';
+    return getApiBasic(url,postdata);
+}
+// 消费记录查询
+export function VipUserConsumeListQuery(postdata) {
+    let url = headapi + 'v1/Weixin/VipUserConsumeListQuery';
+    return getApiBasic(url,postdata);
+}
+// 用户自身信息查询
+export function VipUserSelfQuery(postdata) {
+    let url = headapi + 'v1/Weixin/VipUserSelfQuery';
+    return getApiBasic(url,postdata);
+}
+
+// 某日课程表查询
+export function SchoolTimeQueryByDate(postdata) {
+    let url = headapi + 'v1/Weixin/SchoolTimeQueryByDate';
+    return getApiBasic(url,postdata);
+}
+
+// 通过session查询用户自身信息
+export function ManagerSelfQuery(postdata) {
+    let url = headapi + 'v1/User/ManagerSelfQuery';
+    return getApiBasic(url,postdata);
+}
+
+// 课程表预览
+export function SchoolTimetablePreview(postdata) {
+    let url = headapi + 'v1/SchoolTimeTable/SchoolTimetablePreview';
+    return getApiBasic(url, postdata);
+}
+// CleCk查询
+export function VipUserCleCkSum(postdata) {
+    let url = headapi + 'v1/Weixin/VipUserCleCkSum';
+    return getApiBasic(url, postdata);
+}
+// 查询下周是否有课
+export function QueryNextWeek(postdata) {
+    let url = headapi + 'v1/Weixin/QueryNextWeek';
+    return getApiBasic(url, postdata);
+}
+
+

二進制
app/src/assets/font/UnidreamLED.ttf


二進制
app/src/assets/wille.png


+ 110 - 0
app/src/components/BaseCharts.js

@@ -0,0 +1,110 @@
+import Chart from 'chart.js'
+
+export function generateChart (chartId, chartType) {
+    return {
+        render: function (createElement) {
+            return createElement(
+                'div', {
+                    style: this.styles,
+                    class: this.cssClasses
+                },
+                [
+                    createElement(
+                        'canvas', {
+                            attrs: {
+                                id: this.chartId,
+                                width: this.width,
+                                height: this.height
+                            },
+                            ref: 'canvas'
+                        }
+                    )
+                ]
+            )
+        },
+
+        props: {
+            chartId: {
+                default: chartId,
+                type: String
+            },
+            width: {
+                default: 400,
+                type: Number
+            },
+            height: {
+                default: 400,
+                type: Number
+            },
+            cssClasses: {
+                type: String,
+                default: ''
+            },
+            styles: {
+                type: Object
+            },
+            plugins: {
+                type: Array,
+                default () {
+                    return []
+                }
+            }
+        },
+
+        data () {
+            return {
+                _chart: null,
+                _plugins: this.plugins
+            }
+        },
+
+        methods: {
+            addPlugin (plugin) {
+                this.$data._plugins.push(plugin)
+            },
+            generateLegend () {
+                if (this.$data._chart) {
+                    return this.$data._chart.generateLegend()
+                }
+            },
+            renderChart (data, options) {
+                if (this.$data._chart) this.$data._chart.destroy()
+                this.$data._chart = new Chart(
+                    this.$refs.canvas.getContext('2d'), {
+                        type: chartType,
+                        data: data,
+                        options: options,
+                        plugins: this.$data._plugins
+                    }
+                )
+            }
+        },
+        beforeDestroy () {
+            if (this.$data._chart) {
+                this.$data._chart.destroy()
+            }
+        }
+    }
+}
+
+export const Bar = generateChart('bar-chart', 'bar')
+export const HorizontalBar = generateChart('horizontalbar-chart', 'horizontalBar')
+export const Doughnut = generateChart('doughnut-chart', 'doughnut')
+export const Line = generateChart('line-chart', 'line')
+export const Pie = generateChart('pie-chart', 'pie')
+export const PolarArea = generateChart('polar-chart', 'polarArea')
+export const Radar = generateChart('radar-chart', 'radar')
+export const Bubble = generateChart('bubble-chart', 'bubble')
+export const Scatter = generateChart('scatter-chart', 'scatter')
+
+export default {
+    Bar,
+    HorizontalBar,
+    Doughnut,
+    Line,
+    Pie,
+    PolarArea,
+    Radar,
+    Bubble,
+    Scatter
+}

+ 150 - 0
app/src/components/Hand.vue

@@ -0,0 +1,150 @@
+<template>
+    <div class="hand">
+        <transition name="el-zoom-in-center">
+            <mu-scale-transition>
+                <div class="container" v-show="state">
+                    <div class="subtitle">
+                        <div class="lt">
+                            > SELECTED >STAT
+                        </div>
+                        <div class="rt">
+                            USR:M.KATSURAGI
+                        </div>
+                        <div class="main">
+                            <div class="text">
+                                <p> > DETONATION FUNCTION</p>
+                                <h5>
+                                    <em>READY</em>
+                                    <I></I>
+                                </h5>
+                            </div>
+                            <div class="logo">
+                                <img src="../assets/wille.png" height="208" width="219"/>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </mu-scale-transition>
+        </transition>
+    </div>
+</template>
+
+<script>
+    export default {
+        props: ['state'],
+
+    }
+</script>
+
+<style scoped>
+    .hand {
+        height: 100%;
+        padding: 0.3rem;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+
+    .container {
+        width: 86%;
+        height:100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        padding: 5px;
+    }
+
+    .main {
+        width: 100%;
+        height: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        background: red;
+        color: #fff;
+        border: 2px solid #fff;
+        padding: 5px;
+    }
+
+    .container .subtitle {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        color: #fff;
+    }
+
+    .subtitle .lt {
+        width: 40%;
+        height: 20px;
+        float: left;;
+        font-size: 12px;
+        text-align: left;
+        padding-left: 10px;
+        line-height: 20px;
+    }
+
+    .subtitle .rt {
+        width: 40%;
+        height: 20px;
+        float: right;;
+        font-size: 18px;
+        text-align: right;
+        padding-right: 10px;
+        font-weight: bold;
+    }
+
+    .text {
+        width: 50%;
+        float: left;
+        font-weight: bold;
+    }
+
+    .text p {
+        margin: 0;
+        padding-top: 10px;
+        font-size: 20px;
+        text-align: left;
+    }
+
+    .text h5 {
+        margin: 0;
+        font-size: 50px;
+        text-align: left;
+    }
+
+    .text h5 em {
+        font-style: normal;
+        float: left;
+    }
+
+    .text h5 i {
+        width: 0.4rem;
+        height: 1rem;;
+        background: #fff;
+        float: left;
+        margin-top: 0.4rem;
+        margin-left: 10px;
+        animation: myAnimation 1s infinite
+    }
+
+    .logo {
+        float: right;
+    }
+
+    .logo img {
+        width: 2rem;
+        height: 2rem;
+        float: right;
+        margin-top: 10px;
+    }
+
+    @keyframes myAnimation {
+        0% {
+            opacity: 0
+        }
+        100% {
+            opacity: 1
+        }
+    }
+</style>

+ 63 - 0
app/src/components/LineExample.js

@@ -0,0 +1,63 @@
+import {Line} from './BaseCharts'
+import axios from 'axios';
+
+let qs = require('qs');
+export default {
+    extends: Line,
+    data() {
+        return {
+            labels: [],
+            datasets: [],
+        }
+    },
+    props: ['dataLabels','datadatasets'],
+    watch:{
+        dataLabels(e){
+            this.drawCanvas();
+        },
+        datadatasets(e){
+            this.drawCanvas();
+        }
+    },
+    mounted() {
+      this.drawCanvas();
+    },
+    methods:{
+        drawCanvas(){
+            this.renderChart({
+                labels: this.dataLabels,
+                datasets: [
+                    {
+                        title: {
+                            display: false,
+                            text: 'Custom Chart Title'
+                        },
+                        Legend: {
+                            display: false,
+                        },
+                        label: '',
+                        color: '#FFA200',
+                        borderColor: '#FFA200',
+                        backgroundColor: 'rgba(255,255,255,0)',
+                        data: this.datadatasets
+                    }
+                ]
+            }, {
+                responsive: false,
+                maintainAspectRatio: false,
+                scales: {
+                    yAxes: [{
+                        ticks: {
+                            beginAtZero: true,
+                            callback: function (value) {
+                                if (value % 1 === 0) {
+                                    return value;
+                                }
+                            }
+                        }
+                    }]
+                }
+            })
+        }
+    }
+}

+ 93 - 0
app/src/components/LineExample2.js

@@ -0,0 +1,93 @@
+import { Line } from './BaseCharts'
+export default {
+    extends: Line,
+    props: {
+        firstDate: {  // 必须提供字段
+            required: true,
+            default:false
+        },
+        labels: {  // 必须提供字段
+            required: false,
+            default:false
+        },
+    },
+    watch: {
+        // 动态加载
+        firstDate(curVal, oldVal) {
+            const that = this;
+            if (curVal) {
+                this.firstDate = curVal;
+                that.renderChart({
+                    datasets: this.firstDate,
+                    labels: this.labels,
+                    // labels: '',
+                }, {
+                    responsive: true,
+                    maintainAspectRatio: false,
+                    cutoutPercentage: 90,//环粗细
+                    showTooltips:false,
+                    title:false,
+                    tooltips:{
+                        mode:'index',
+                        intersect:false
+                    },
+                    legend: {
+                        position:'bottom',
+                        labels: {
+                            boxWidth:12,
+                            fontSize:10
+                        }
+                    },
+                    scales: {
+                        yAxes: [{
+                            ticks: {
+                                beginAtZero: true,
+                                callback: function (value) {
+                                    if (value % 1 === 0) {
+                                        return value;
+                                    }
+                                }
+                            }
+                        }]
+                    }
+                })
+            }
+        },
+    },
+    mounted() {
+        const that = this;
+        that.renderChart({
+            labels: this.labels,
+            datasets:this.firstDate
+        }, {
+            responsive: true,
+            maintainAspectRatio: false,
+            cutoutPercentage: 90,//环粗细
+            showTooltips:false,
+            title:false,
+            tooltips:{
+                mode:'index',
+                intersect:false
+            },
+            legend: {
+                position:'bottom',
+                labels: {
+                    boxWidth:12,
+                    fontSize:10
+                }
+            },
+            scales: {
+                yAxes: [{
+                    ticks: {
+                        beginAtZero: true,
+                        callback: function (value) {
+                            if (value % 1 === 0) {
+                                return value;
+                            }
+                        }
+                    }
+                }]
+            }
+        })
+    }
+}

+ 3833 - 0
app/src/components/address3.json

@@ -0,0 +1,3833 @@
+{
+  "北京市": {
+    "市辖区": [
+      "东城区",
+      "西城区",
+      "朝阳区",
+      "丰台区",
+      "石景山区",
+      "海淀区",
+      "门头沟区",
+      "房山区",
+      "通州区",
+      "顺义区",
+      "昌平区",
+      "大兴区",
+      "怀柔区",
+      "平谷区",
+      "密云区",
+      "延庆区"
+    ]
+  },
+  "天津市": {
+    "市辖区": [
+      "和平区",
+      "河东区",
+      "河西区",
+      "南开区",
+      "河北区",
+      "红桥区",
+      "东丽区",
+      "西青区",
+      "津南区",
+      "北辰区",
+      "武清区",
+      "宝坻区",
+      "滨海新区",
+      "宁河区",
+      "静海区",
+      "蓟州区"
+    ]
+  },
+  "河北省": {
+    "石家庄市": [
+      "长安区",
+      "桥西区",
+      "新华区",
+      "井陉矿区",
+      "裕华区",
+      "藁城区",
+      "鹿泉区",
+      "栾城区",
+      "井陉县",
+      "正定县",
+      "行唐县",
+      "灵寿县",
+      "高邑县",
+      "深泽县",
+      "赞皇县",
+      "无极县",
+      "平山县",
+      "元氏县",
+      "赵县",
+      "石家庄高新技术产业开发区",
+      "石家庄循环化工园区",
+      "辛集市",
+      "晋州市",
+      "新乐市"
+    ],
+    "唐山市": [
+      "路南区",
+      "路北区",
+      "古冶区",
+      "开平区",
+      "丰南区",
+      "丰润区",
+      "曹妃甸区",
+      "滦南县",
+      "乐亭县",
+      "迁西县",
+      "玉田县",
+      "唐山市芦台经济技术开发区",
+      "唐山市汉沽管理区",
+      "唐山高新技术产业开发区",
+      "河北唐山海港经济开发区",
+      "遵化市",
+      "迁安市",
+      "滦州市"
+    ],
+    "秦皇岛市": [
+      "海港区",
+      "山海关区",
+      "北戴河区",
+      "抚宁区",
+      "青龙满族自治县",
+      "昌黎县",
+      "卢龙县",
+      "秦皇岛市经济技术开发区",
+      "北戴河新区"
+    ],
+    "邯郸市": [
+      "邯山区",
+      "丛台区",
+      "复兴区",
+      "峰峰矿区",
+      "肥乡区",
+      "永年区",
+      "临漳县",
+      "成安县",
+      "大名县",
+      "涉县",
+      "磁县",
+      "邱县",
+      "鸡泽县",
+      "广平县",
+      "馆陶县",
+      "魏县",
+      "曲周县",
+      "邯郸经济技术开发区",
+      "邯郸冀南新区",
+      "武安市"
+    ],
+    "邢台市": [
+      "桥东区",
+      "桥西区",
+      "邢台县",
+      "临城县",
+      "内丘县",
+      "柏乡县",
+      "隆尧县",
+      "任县",
+      "南和县",
+      "宁晋县",
+      "巨鹿县",
+      "新河县",
+      "广宗县",
+      "平乡县",
+      "威县",
+      "清河县",
+      "临西县",
+      "河北邢台经济开发区",
+      "南宫市",
+      "沙河市"
+    ],
+    "保定市": [
+      "竞秀区",
+      "莲池区",
+      "满城区",
+      "清苑区",
+      "徐水区",
+      "涞水县",
+      "阜平县",
+      "定兴县",
+      "唐县",
+      "高阳县",
+      "容城县",
+      "涞源县",
+      "望都县",
+      "安新县",
+      "易县",
+      "曲阳县",
+      "蠡县",
+      "顺平县",
+      "博野县",
+      "雄县",
+      "保定高新技术产业开发区",
+      "保定白沟新城",
+      "涿州市",
+      "定州市",
+      "安国市",
+      "高碑店市"
+    ],
+    "张家口市": [
+      "桥东区",
+      "桥西区",
+      "宣化区",
+      "下花园区",
+      "万全区",
+      "崇礼区",
+      "张北县",
+      "康保县",
+      "沽源县",
+      "尚义县",
+      "蔚县",
+      "阳原县",
+      "怀安县",
+      "怀来县",
+      "涿鹿县",
+      "赤城县",
+      "张家口市高新技术产业开发区",
+      "张家口市察北管理区",
+      "张家口市塞北管理区"
+    ],
+    "承德市": [
+      "双桥区",
+      "双滦区",
+      "鹰手营子矿区",
+      "承德县",
+      "兴隆县",
+      "滦平县",
+      "隆化县",
+      "丰宁满族自治县",
+      "宽城满族自治县",
+      "围场满族蒙古族自治县",
+      "承德高新技术产业开发区",
+      "平泉市"
+    ],
+    "沧州市": [
+      "新华区",
+      "运河区",
+      "沧县",
+      "青县",
+      "东光县",
+      "海兴县",
+      "盐山县",
+      "肃宁县",
+      "南皮县",
+      "吴桥县",
+      "献县",
+      "孟村回族自治县",
+      "河北沧州经济开发区",
+      "沧州高新技术产业开发区",
+      "沧州渤海新区",
+      "泊头市",
+      "任丘市",
+      "黄骅市",
+      "河间市"
+    ],
+    "廊坊市": [
+      "安次区",
+      "广阳区",
+      "固安县",
+      "永清县",
+      "香河县",
+      "大城县",
+      "文安县",
+      "大厂回族自治县",
+      "廊坊经济技术开发区",
+      "霸州市",
+      "三河市"
+    ],
+    "衡水市": [
+      "桃城区",
+      "冀州区",
+      "枣强县",
+      "武邑县",
+      "武强县",
+      "饶阳县",
+      "安平县",
+      "故城县",
+      "景县",
+      "阜城县",
+      "河北衡水高新技术产业开发区",
+      "衡水滨湖新区",
+      "深州市"
+    ]
+  },
+  "山西省": {
+    "太原市": [
+      "小店区",
+      "迎泽区",
+      "杏花岭区",
+      "尖草坪区",
+      "万柏林区",
+      "晋源区",
+      "清徐县",
+      "阳曲县",
+      "娄烦县",
+      "山西转型综合改革示范区",
+      "古交市"
+    ],
+    "大同市": [
+      "新荣区",
+      "平城区",
+      "云冈区",
+      "云州区",
+      "阳高县",
+      "天镇县",
+      "广灵县",
+      "灵丘县",
+      "浑源县",
+      "左云县",
+      "山西大同经济开发区"
+    ],
+    "阳泉市": [
+      "城区",
+      "矿区",
+      "郊区",
+      "平定县",
+      "盂县"
+    ],
+    "长治市": [
+      "潞州区",
+      "上党区",
+      "屯留区",
+      "潞城区",
+      "襄垣县",
+      "平顺县",
+      "黎城县",
+      "壶关县",
+      "长子县",
+      "武乡县",
+      "沁县",
+      "沁源县",
+      "山西长治高新技术产业园区"
+    ],
+    "晋城市": [
+      "城区",
+      "沁水县",
+      "阳城县",
+      "陵川县",
+      "泽州县",
+      "高平市"
+    ],
+    "朔州市": [
+      "朔城区",
+      "平鲁区",
+      "山阴县",
+      "应县",
+      "右玉县",
+      "山西朔州经济开发区",
+      "怀仁市"
+    ],
+    "晋中市": [
+      "榆次区",
+      "榆社县",
+      "左权县",
+      "和顺县",
+      "昔阳县",
+      "寿阳县",
+      "太谷县",
+      "祁县",
+      "平遥县",
+      "灵石县",
+      "介休市"
+    ],
+    "运城市": [
+      "盐湖区",
+      "临猗县",
+      "万荣县",
+      "闻喜县",
+      "稷山县",
+      "新绛县",
+      "绛县",
+      "垣曲县",
+      "夏县",
+      "平陆县",
+      "芮城县",
+      "永济市",
+      "河津市"
+    ],
+    "忻州市": [
+      "忻府区",
+      "定襄县",
+      "五台县",
+      "代县",
+      "繁峙县",
+      "宁武县",
+      "静乐县",
+      "神池县",
+      "五寨县",
+      "岢岚县",
+      "河曲县",
+      "保德县",
+      "偏关县",
+      "五台山风景名胜区",
+      "原平市"
+    ],
+    "临汾市": [
+      "尧都区",
+      "曲沃县",
+      "翼城县",
+      "襄汾县",
+      "洪洞县",
+      "古县",
+      "安泽县",
+      "浮山县",
+      "吉县",
+      "乡宁县",
+      "大宁县",
+      "隰县",
+      "永和县",
+      "蒲县",
+      "汾西县",
+      "侯马市",
+      "霍州市"
+    ],
+    "吕梁市": [
+      "离石区",
+      "文水县",
+      "交城县",
+      "兴县",
+      "临县",
+      "柳林县",
+      "石楼县",
+      "岚县",
+      "方山县",
+      "中阳县",
+      "交口县",
+      "孝义市",
+      "汾阳市"
+    ]
+  },
+  "内蒙古自治区": {
+    "呼和浩特市": [
+      "新城区",
+      "回民区",
+      "玉泉区",
+      "赛罕区",
+      "土默特左旗",
+      "托克托县",
+      "和林格尔县",
+      "清水河县",
+      "武川县",
+      "呼和浩特金海工业园区",
+      "呼和浩特经济技术开发区"
+    ],
+    "包头市": [
+      "东河区",
+      "昆都仑区",
+      "青山区",
+      "石拐区",
+      "白云鄂博矿区",
+      "九原区",
+      "土默特右旗",
+      "固阳县",
+      "达尔罕茂明安联合旗",
+      "包头稀土高新技术产业开发区"
+    ],
+    "乌海市": [
+      "海勃湾区",
+      "海南区",
+      "乌达区"
+    ],
+    "赤峰市": [
+      "红山区",
+      "元宝山区",
+      "松山区",
+      "阿鲁科尔沁旗",
+      "巴林左旗",
+      "巴林右旗",
+      "林西县",
+      "克什克腾旗",
+      "翁牛特旗",
+      "喀喇沁旗",
+      "宁城县",
+      "敖汉旗"
+    ],
+    "通辽市": [
+      "科尔沁区",
+      "科尔沁左翼中旗",
+      "科尔沁左翼后旗",
+      "开鲁县",
+      "库伦旗",
+      "奈曼旗",
+      "扎鲁特旗",
+      "通辽经济技术开发区",
+      "霍林郭勒市"
+    ],
+    "鄂尔多斯市": [
+      "东胜区",
+      "康巴什区",
+      "达拉特旗",
+      "准格尔旗",
+      "鄂托克前旗",
+      "鄂托克旗",
+      "杭锦旗",
+      "乌审旗",
+      "伊金霍洛旗"
+    ],
+    "呼伦贝尔市": [
+      "海拉尔区",
+      "扎赉诺尔区",
+      "阿荣旗",
+      "莫力达瓦达斡尔族自治旗",
+      "鄂伦春自治旗",
+      "鄂温克族自治旗",
+      "陈巴尔虎旗",
+      "新巴尔虎左旗",
+      "新巴尔虎右旗",
+      "满洲里市",
+      "牙克石市",
+      "扎兰屯市",
+      "额尔古纳市",
+      "根河市"
+    ],
+    "巴彦淖尔市": [
+      "临河区",
+      "五原县",
+      "磴口县",
+      "乌拉特前旗",
+      "乌拉特中旗",
+      "乌拉特后旗",
+      "杭锦后旗"
+    ],
+    "乌兰察布市": [
+      "集宁区",
+      "卓资县",
+      "化德县",
+      "商都县",
+      "兴和县",
+      "凉城县",
+      "察哈尔右翼前旗",
+      "察哈尔右翼中旗",
+      "察哈尔右翼后旗",
+      "四子王旗",
+      "丰镇市"
+    ],
+    "兴安盟": [
+      "乌兰浩特市",
+      "阿尔山市",
+      "科尔沁右翼前旗",
+      "科尔沁右翼中旗",
+      "扎赉特旗",
+      "突泉县"
+    ],
+    "锡林郭勒盟": [
+      "二连浩特市",
+      "锡林浩特市",
+      "阿巴嘎旗",
+      "苏尼特左旗",
+      "苏尼特右旗",
+      "东乌珠穆沁旗",
+      "西乌珠穆沁旗",
+      "太仆寺旗",
+      "镶黄旗",
+      "正镶白旗",
+      "正蓝旗",
+      "多伦县",
+      "乌拉盖管委会"
+    ],
+    "阿拉善盟": [
+      "阿拉善左旗",
+      "阿拉善右旗",
+      "额济纳旗",
+      "内蒙古阿拉善经济开发区"
+    ]
+  },
+  "辽宁省": {
+    "沈阳市": [
+      "和平区",
+      "沈河区",
+      "大东区",
+      "皇姑区",
+      "铁西区",
+      "苏家屯区",
+      "浑南区",
+      "沈北新区",
+      "于洪区",
+      "辽中区",
+      "康平县",
+      "法库县",
+      "新民市"
+    ],
+    "大连市": [
+      "中山区",
+      "西岗区",
+      "沙河口区",
+      "甘井子区",
+      "旅顺口区",
+      "金州区",
+      "普兰店区",
+      "长海县",
+      "瓦房店市",
+      "庄河市"
+    ],
+    "鞍山市": [
+      "铁东区",
+      "铁西区",
+      "立山区",
+      "千山区",
+      "台安县",
+      "岫岩满族自治县",
+      "海城市"
+    ],
+    "抚顺市": [
+      "新抚区",
+      "东洲区",
+      "望花区",
+      "顺城区",
+      "抚顺县",
+      "新宾满族自治县",
+      "清原满族自治县"
+    ],
+    "本溪市": [
+      "平山区",
+      "溪湖区",
+      "明山区",
+      "南芬区",
+      "本溪满族自治县",
+      "桓仁满族自治县"
+    ],
+    "丹东市": [
+      "元宝区",
+      "振兴区",
+      "振安区",
+      "宽甸满族自治县",
+      "东港市",
+      "凤城市"
+    ],
+    "锦州市": [
+      "古塔区",
+      "凌河区",
+      "太和区",
+      "黑山县",
+      "义县",
+      "凌海市",
+      "北镇市"
+    ],
+    "营口市": [
+      "站前区",
+      "西市区",
+      "鲅鱼圈区",
+      "老边区",
+      "盖州市",
+      "大石桥市"
+    ],
+    "阜新市": [
+      "海州区",
+      "新邱区",
+      "太平区",
+      "清河门区",
+      "细河区",
+      "阜新蒙古族自治县",
+      "彰武县"
+    ],
+    "辽阳市": [
+      "白塔区",
+      "文圣区",
+      "宏伟区",
+      "弓长岭区",
+      "太子河区",
+      "辽阳县",
+      "灯塔市"
+    ],
+    "盘锦市": [
+      "双台子区",
+      "兴隆台区",
+      "大洼区",
+      "盘山县"
+    ],
+    "铁岭市": [
+      "银州区",
+      "清河区",
+      "铁岭县",
+      "西丰县",
+      "昌图县",
+      "调兵山市",
+      "开原市"
+    ],
+    "朝阳市": [
+      "双塔区",
+      "龙城区",
+      "朝阳县",
+      "建平县",
+      "喀喇沁左翼蒙古族自治县",
+      "北票市",
+      "凌源市"
+    ],
+    "葫芦岛市": [
+      "连山区",
+      "龙港区",
+      "南票区",
+      "绥中县",
+      "建昌县",
+      "兴城市"
+    ]
+  },
+  "吉林省": {
+    "长春市": [
+      "南关区",
+      "宽城区",
+      "朝阳区",
+      "二道区",
+      "绿园区",
+      "双阳区",
+      "九台区",
+      "农安县",
+      "长春经济技术开发区",
+      "长春净月高新技术产业开发区",
+      "长春高新技术产业开发区",
+      "长春汽车经济技术开发区",
+      "榆树市",
+      "德惠市"
+    ],
+    "吉林市": [
+      "昌邑区",
+      "龙潭区",
+      "船营区",
+      "丰满区",
+      "永吉县",
+      "吉林经济开发区",
+      "吉林高新技术产业开发区",
+      "吉林中国新加坡食品区",
+      "蛟河市",
+      "桦甸市",
+      "舒兰市",
+      "磐石市"
+    ],
+    "四平市": [
+      "铁西区",
+      "铁东区",
+      "梨树县",
+      "伊通满族自治县",
+      "公主岭市",
+      "双辽市"
+    ],
+    "辽源市": [
+      "龙山区",
+      "西安区",
+      "东丰县",
+      "东辽县"
+    ],
+    "通化市": [
+      "东昌区",
+      "二道江区",
+      "通化县",
+      "辉南县",
+      "柳河县",
+      "梅河口市",
+      "集安市"
+    ],
+    "白山市": [
+      "浑江区",
+      "江源区",
+      "抚松县",
+      "靖宇县",
+      "长白朝鲜族自治县",
+      "临江市"
+    ],
+    "松原市": [
+      "宁江区",
+      "前郭尔罗斯蒙古族自治县",
+      "长岭县",
+      "乾安县",
+      "吉林松原经济开发区",
+      "扶余市"
+    ],
+    "白城市": [
+      "洮北区",
+      "镇赉县",
+      "通榆县",
+      "吉林白城经济开发区",
+      "洮南市",
+      "大安市"
+    ],
+    "延边朝鲜族自治州": [
+      "延吉市",
+      "图们市",
+      "敦化市",
+      "珲春市",
+      "龙井市",
+      "和龙市",
+      "汪清县",
+      "安图县"
+    ]
+  },
+  "黑龙江省": {
+    "哈尔滨市": [
+      "道里区",
+      "南岗区",
+      "道外区",
+      "平房区",
+      "松北区",
+      "香坊区",
+      "呼兰区",
+      "阿城区",
+      "双城区",
+      "依兰县",
+      "方正县",
+      "宾县",
+      "巴彦县",
+      "木兰县",
+      "通河县",
+      "延寿县",
+      "尚志市",
+      "五常市"
+    ],
+    "齐齐哈尔市": [
+      "龙沙区",
+      "建华区",
+      "铁锋区",
+      "昂昂溪区",
+      "富拉尔基区",
+      "碾子山区",
+      "梅里斯达斡尔族区",
+      "龙江县",
+      "依安县",
+      "泰来县",
+      "甘南县",
+      "富裕县",
+      "克山县",
+      "克东县",
+      "拜泉县",
+      "讷河市"
+    ],
+    "鸡西市": [
+      "鸡冠区",
+      "恒山区",
+      "滴道区",
+      "梨树区",
+      "城子河区",
+      "麻山区",
+      "鸡东县",
+      "虎林市",
+      "密山市"
+    ],
+    "鹤岗市": [
+      "向阳区",
+      "工农区",
+      "南山区",
+      "兴安区",
+      "东山区",
+      "兴山区",
+      "萝北县",
+      "绥滨县"
+    ],
+    "双鸭山市": [
+      "尖山区",
+      "岭东区",
+      "四方台区",
+      "宝山区",
+      "集贤县",
+      "友谊县",
+      "宝清县",
+      "饶河县"
+    ],
+    "大庆市": [
+      "萨尔图区",
+      "龙凤区",
+      "让胡路区",
+      "红岗区",
+      "大同区",
+      "肇州县",
+      "肇源县",
+      "林甸县",
+      "杜尔伯特蒙古族自治县",
+      "大庆高新技术产业开发区"
+    ],
+    "伊春市": [
+      "伊春区",
+      "南岔区",
+      "友好区",
+      "西林区",
+      "翠峦区",
+      "新青区",
+      "美溪区",
+      "金山屯区",
+      "五营区",
+      "乌马河区",
+      "汤旺河区",
+      "带岭区",
+      "乌伊岭区",
+      "红星区",
+      "上甘岭区",
+      "嘉荫县",
+      "铁力市"
+    ],
+    "佳木斯市": [
+      "向阳区",
+      "前进区",
+      "东风区",
+      "郊区",
+      "桦南县",
+      "桦川县",
+      "汤原县",
+      "同江市",
+      "富锦市",
+      "抚远市"
+    ],
+    "七台河市": [
+      "新兴区",
+      "桃山区",
+      "茄子河区",
+      "勃利县"
+    ],
+    "牡丹江市": [
+      "东安区",
+      "阳明区",
+      "爱民区",
+      "西安区",
+      "林口县",
+      "牡丹江经济技术开发区",
+      "绥芬河市",
+      "海林市",
+      "宁安市",
+      "穆棱市",
+      "东宁市"
+    ],
+    "黑河市": [
+      "爱辉区",
+      "嫩江县",
+      "逊克县",
+      "孙吴县",
+      "北安市",
+      "五大连池市"
+    ],
+    "绥化市": [
+      "北林区",
+      "望奎县",
+      "兰西县",
+      "青冈县",
+      "庆安县",
+      "明水县",
+      "绥棱县",
+      "安达市",
+      "肇东市",
+      "海伦市"
+    ],
+    "大兴安岭地区": [
+      "漠河市",
+      "呼玛县",
+      "塔河县",
+      "加格达奇区",
+      "松岭区",
+      "新林区",
+      "呼中区"
+    ]
+  },
+  "上海市": {
+    "市辖区": [
+      "黄浦区",
+      "徐汇区",
+      "长宁区",
+      "静安区",
+      "普陀区",
+      "虹口区",
+      "杨浦区",
+      "闵行区",
+      "宝山区",
+      "嘉定区",
+      "浦东新区",
+      "金山区",
+      "松江区",
+      "青浦区",
+      "奉贤区",
+      "崇明区"
+    ]
+  },
+  "江苏省": {
+    "南京市": [
+      "玄武区",
+      "秦淮区",
+      "建邺区",
+      "鼓楼区",
+      "浦口区",
+      "栖霞区",
+      "雨花台区",
+      "江宁区",
+      "六合区",
+      "溧水区",
+      "高淳区"
+    ],
+    "无锡市": [
+      "锡山区",
+      "惠山区",
+      "滨湖区",
+      "梁溪区",
+      "新吴区",
+      "江阴市",
+      "宜兴市"
+    ],
+    "徐州市": [
+      "鼓楼区",
+      "云龙区",
+      "贾汪区",
+      "泉山区",
+      "铜山区",
+      "丰县",
+      "沛县",
+      "睢宁县",
+      "徐州经济技术开发区",
+      "新沂市",
+      "邳州市"
+    ],
+    "常州市": [
+      "天宁区",
+      "钟楼区",
+      "新北区",
+      "武进区",
+      "金坛区",
+      "溧阳市"
+    ],
+    "苏州市": [
+      "虎丘区",
+      "吴中区",
+      "相城区",
+      "姑苏区",
+      "吴江区",
+      "苏州工业园区",
+      "常熟市",
+      "张家港市",
+      "昆山市",
+      "太仓市"
+    ],
+    "南通市": [
+      "崇川区",
+      "港闸区",
+      "通州区",
+      "如东县",
+      "南通经济技术开发区",
+      "启东市",
+      "如皋市",
+      "海门市",
+      "海安市"
+    ],
+    "连云港市": [
+      "连云区",
+      "海州区",
+      "赣榆区",
+      "东海县",
+      "灌云县",
+      "灌南县",
+      "连云港经济技术开发区",
+      "连云港高新技术产业开发区"
+    ],
+    "淮安市": [
+      "淮安区",
+      "淮阴区",
+      "清江浦区",
+      "洪泽区",
+      "涟水县",
+      "盱眙县",
+      "金湖县",
+      "淮安经济技术开发区"
+    ],
+    "盐城市": [
+      "亭湖区",
+      "盐都区",
+      "大丰区",
+      "响水县",
+      "滨海县",
+      "阜宁县",
+      "射阳县",
+      "建湖县",
+      "盐城经济技术开发区",
+      "东台市"
+    ],
+    "扬州市": [
+      "广陵区",
+      "邗江区",
+      "江都区",
+      "宝应县",
+      "扬州经济技术开发区",
+      "仪征市",
+      "高邮市"
+    ],
+    "镇江市": [
+      "京口区",
+      "润州区",
+      "丹徒区",
+      "镇江新区",
+      "丹阳市",
+      "扬中市",
+      "句容市"
+    ],
+    "泰州市": [
+      "海陵区",
+      "高港区",
+      "姜堰区",
+      "泰州医药高新技术产业开发区",
+      "兴化市",
+      "靖江市",
+      "泰兴市"
+    ],
+    "宿迁市": [
+      "宿城区",
+      "宿豫区",
+      "沭阳县",
+      "泗阳县",
+      "泗洪县",
+      "宿迁经济技术开发区"
+    ]
+  },
+  "浙江省": {
+    "杭州市": [
+      "上城区",
+      "下城区",
+      "江干区",
+      "拱墅区",
+      "西湖区",
+      "滨江区",
+      "萧山区",
+      "余杭区",
+      "富阳区",
+      "临安区",
+      "桐庐县",
+      "淳安县",
+      "建德市"
+    ],
+    "宁波市": [
+      "海曙区",
+      "江北区",
+      "北仑区",
+      "镇海区",
+      "鄞州区",
+      "奉化区",
+      "象山县",
+      "宁海县",
+      "余姚市",
+      "慈溪市"
+    ],
+    "温州市": [
+      "鹿城区",
+      "龙湾区",
+      "瓯海区",
+      "洞头区",
+      "永嘉县",
+      "平阳县",
+      "苍南县",
+      "文成县",
+      "泰顺县",
+      "温州经济技术开发区",
+      "瑞安市",
+      "乐清市"
+    ],
+    "嘉兴市": [
+      "南湖区",
+      "秀洲区",
+      "嘉善县",
+      "海盐县",
+      "海宁市",
+      "平湖市",
+      "桐乡市"
+    ],
+    "湖州市": [
+      "吴兴区",
+      "南浔区",
+      "德清县",
+      "长兴县",
+      "安吉县"
+    ],
+    "绍兴市": [
+      "越城区",
+      "柯桥区",
+      "上虞区",
+      "新昌县",
+      "诸暨市",
+      "嵊州市"
+    ],
+    "金华市": [
+      "婺城区",
+      "金东区",
+      "武义县",
+      "浦江县",
+      "磐安县",
+      "兰溪市",
+      "义乌市",
+      "东阳市",
+      "永康市"
+    ],
+    "衢州市": [
+      "柯城区",
+      "衢江区",
+      "常山县",
+      "开化县",
+      "龙游县",
+      "江山市"
+    ],
+    "舟山市": [
+      "定海区",
+      "普陀区",
+      "岱山县",
+      "嵊泗县"
+    ],
+    "台州市": [
+      "椒江区",
+      "黄岩区",
+      "路桥区",
+      "三门县",
+      "天台县",
+      "仙居县",
+      "温岭市",
+      "临海市",
+      "玉环市"
+    ],
+    "丽水市": [
+      "莲都区",
+      "青田县",
+      "缙云县",
+      "遂昌县",
+      "松阳县",
+      "云和县",
+      "庆元县",
+      "景宁畲族自治县",
+      "龙泉市"
+    ]
+  },
+  "安徽省": {
+    "合肥市": [
+      "瑶海区",
+      "庐阳区",
+      "蜀山区",
+      "包河区",
+      "长丰县",
+      "肥东县",
+      "肥西县",
+      "庐江县",
+      "合肥高新技术产业开发区",
+      "合肥经济技术开发区",
+      "合肥新站高新技术产业开发区",
+      "巢湖市"
+    ],
+    "芜湖市": [
+      "镜湖区",
+      "弋江区",
+      "鸠江区",
+      "三山区",
+      "芜湖县",
+      "繁昌县",
+      "南陵县",
+      "无为县",
+      "芜湖经济技术开发区",
+      "安徽芜湖长江大桥经济开发区"
+    ],
+    "蚌埠市": [
+      "龙子湖区",
+      "蚌山区",
+      "禹会区",
+      "淮上区",
+      "怀远县",
+      "五河县",
+      "固镇县",
+      "蚌埠市高新技术开发区",
+      "蚌埠市经济开发区"
+    ],
+    "淮南市": [
+      "大通区",
+      "田家庵区",
+      "谢家集区",
+      "八公山区",
+      "潘集区",
+      "凤台县",
+      "寿县"
+    ],
+    "马鞍山市": [
+      "花山区",
+      "雨山区",
+      "博望区",
+      "当涂县",
+      "含山县",
+      "和县"
+    ],
+    "淮北市": [
+      "杜集区",
+      "相山区",
+      "烈山区",
+      "濉溪县"
+    ],
+    "铜陵市": [
+      "铜官区",
+      "义安区",
+      "郊区",
+      "枞阳县"
+    ],
+    "安庆市": [
+      "迎江区",
+      "大观区",
+      "宜秀区",
+      "怀宁县",
+      "太湖县",
+      "宿松县",
+      "望江县",
+      "岳西县",
+      "安徽安庆经济开发区",
+      "桐城市",
+      "潜山市"
+    ],
+    "黄山市": [
+      "屯溪区",
+      "黄山区",
+      "徽州区",
+      "歙县",
+      "休宁县",
+      "黟县",
+      "祁门县"
+    ],
+    "滁州市": [
+      "琅琊区",
+      "南谯区",
+      "来安县",
+      "全椒县",
+      "定远县",
+      "凤阳县",
+      "苏滁现代产业园",
+      "滁州经济技术开发区",
+      "天长市",
+      "明光市"
+    ],
+    "阜阳市": [
+      "颍州区",
+      "颍东区",
+      "颍泉区",
+      "临泉县",
+      "太和县",
+      "阜南县",
+      "颍上县",
+      "阜阳合肥现代产业园区",
+      "阜阳经济技术开发区",
+      "界首市"
+    ],
+    "宿州市": [
+      "埇桥区",
+      "砀山县",
+      "萧县",
+      "灵璧县",
+      "泗县",
+      "宿州马鞍山现代产业园区",
+      "宿州经济技术开发区"
+    ],
+    "六安市": [
+      "金安区",
+      "裕安区",
+      "叶集区",
+      "霍邱县",
+      "舒城县",
+      "金寨县",
+      "霍山县"
+    ],
+    "亳州市": [
+      "谯城区",
+      "涡阳县",
+      "蒙城县",
+      "利辛县"
+    ],
+    "池州市": [
+      "贵池区",
+      "东至县",
+      "石台县",
+      "青阳县"
+    ],
+    "宣城市": [
+      "宣州区",
+      "郎溪县",
+      "广德县",
+      "泾县",
+      "绩溪县",
+      "旌德县",
+      "宣城市经济开发区",
+      "宁国市"
+    ]
+  },
+  "福建省": {
+    "福州市": [
+      "鼓楼区",
+      "台江区",
+      "仓山区",
+      "马尾区",
+      "晋安区",
+      "长乐区",
+      "闽侯县",
+      "连江县",
+      "罗源县",
+      "闽清县",
+      "永泰县",
+      "平潭县",
+      "福清市"
+    ],
+    "厦门市": [
+      "思明区",
+      "海沧区",
+      "湖里区",
+      "集美区",
+      "同安区",
+      "翔安区"
+    ],
+    "莆田市": [
+      "城厢区",
+      "涵江区",
+      "荔城区",
+      "秀屿区",
+      "仙游县"
+    ],
+    "三明市": [
+      "梅列区",
+      "三元区",
+      "明溪县",
+      "清流县",
+      "宁化县",
+      "大田县",
+      "尤溪县",
+      "沙县",
+      "将乐县",
+      "泰宁县",
+      "建宁县",
+      "永安市"
+    ],
+    "泉州市": [
+      "鲤城区",
+      "丰泽区",
+      "洛江区",
+      "泉港区",
+      "惠安县",
+      "安溪县",
+      "永春县",
+      "德化县",
+      "金门县",
+      "石狮市",
+      "晋江市",
+      "南安市"
+    ],
+    "漳州市": [
+      "芗城区",
+      "龙文区",
+      "云霄县",
+      "漳浦县",
+      "诏安县",
+      "长泰县",
+      "东山县",
+      "南靖县",
+      "平和县",
+      "华安县",
+      "龙海市"
+    ],
+    "南平市": [
+      "延平区",
+      "建阳区",
+      "顺昌县",
+      "浦城县",
+      "光泽县",
+      "松溪县",
+      "政和县",
+      "邵武市",
+      "武夷山市",
+      "建瓯市"
+    ],
+    "龙岩市": [
+      "新罗区",
+      "永定区",
+      "长汀县",
+      "上杭县",
+      "武平县",
+      "连城县",
+      "漳平市"
+    ],
+    "宁德市": [
+      "蕉城区",
+      "霞浦县",
+      "古田县",
+      "屏南县",
+      "寿宁县",
+      "周宁县",
+      "柘荣县",
+      "福安市",
+      "福鼎市"
+    ]
+  },
+  "江西省": {
+    "南昌市": [
+      "东湖区",
+      "西湖区",
+      "青云谱区",
+      "湾里区",
+      "青山湖区",
+      "新建区",
+      "南昌县",
+      "安义县",
+      "进贤县"
+    ],
+    "景德镇市": [
+      "昌江区",
+      "珠山区",
+      "浮梁县",
+      "乐平市"
+    ],
+    "萍乡市": [
+      "安源区",
+      "湘东区",
+      "莲花县",
+      "上栗县",
+      "芦溪县"
+    ],
+    "九江市": [
+      "濂溪区",
+      "浔阳区",
+      "柴桑区",
+      "武宁县",
+      "修水县",
+      "永修县",
+      "德安县",
+      "都昌县",
+      "湖口县",
+      "彭泽县",
+      "瑞昌市",
+      "共青城市",
+      "庐山市"
+    ],
+    "新余市": [
+      "渝水区",
+      "分宜县"
+    ],
+    "鹰潭市": [
+      "月湖区",
+      "余江区",
+      "贵溪市"
+    ],
+    "赣州市": [
+      "章贡区",
+      "南康区",
+      "赣县区",
+      "信丰县",
+      "大余县",
+      "上犹县",
+      "崇义县",
+      "安远县",
+      "龙南县",
+      "定南县",
+      "全南县",
+      "宁都县",
+      "于都县",
+      "兴国县",
+      "会昌县",
+      "寻乌县",
+      "石城县",
+      "瑞金市"
+    ],
+    "吉安市": [
+      "吉州区",
+      "青原区",
+      "吉安县",
+      "吉水县",
+      "峡江县",
+      "新干县",
+      "永丰县",
+      "泰和县",
+      "遂川县",
+      "万安县",
+      "安福县",
+      "永新县",
+      "井冈山市"
+    ],
+    "宜春市": [
+      "袁州区",
+      "奉新县",
+      "万载县",
+      "上高县",
+      "宜丰县",
+      "靖安县",
+      "铜鼓县",
+      "丰城市",
+      "樟树市",
+      "高安市"
+    ],
+    "抚州市": [
+      "临川区",
+      "东乡区",
+      "南城县",
+      "黎川县",
+      "南丰县",
+      "崇仁县",
+      "乐安县",
+      "宜黄县",
+      "金溪县",
+      "资溪县",
+      "广昌县"
+    ],
+    "上饶市": [
+      "信州区",
+      "广丰区",
+      "上饶县",
+      "玉山县",
+      "铅山县",
+      "横峰县",
+      "弋阳县",
+      "余干县",
+      "鄱阳县",
+      "万年县",
+      "婺源县",
+      "德兴市"
+    ]
+  },
+  "山东省": {
+    "济南市": [
+      "历下区",
+      "市中区",
+      "槐荫区",
+      "天桥区",
+      "历城区",
+      "长清区",
+      "章丘区",
+      "济阳区",
+      "平阴县",
+      "商河县",
+      "济南高新技术产业开发区"
+    ],
+    "青岛市": [
+      "市南区",
+      "市北区",
+      "黄岛区",
+      "崂山区",
+      "李沧区",
+      "城阳区",
+      "即墨区",
+      "青岛高新技术产业开发区",
+      "胶州市",
+      "平度市",
+      "莱西市"
+    ],
+    "淄博市": [
+      "淄川区",
+      "张店区",
+      "博山区",
+      "临淄区",
+      "周村区",
+      "桓台县",
+      "高青县",
+      "沂源县"
+    ],
+    "枣庄市": [
+      "市中区",
+      "薛城区",
+      "峄城区",
+      "台儿庄区",
+      "山亭区",
+      "滕州市"
+    ],
+    "东营市": [
+      "东营区",
+      "河口区",
+      "垦利区",
+      "利津县",
+      "广饶县",
+      "东营经济技术开发区",
+      "东营港经济开发区"
+    ],
+    "烟台市": [
+      "芝罘区",
+      "福山区",
+      "牟平区",
+      "莱山区",
+      "长岛县",
+      "烟台高新技术产业开发区",
+      "烟台经济技术开发区",
+      "龙口市",
+      "莱阳市",
+      "莱州市",
+      "蓬莱市",
+      "招远市",
+      "栖霞市",
+      "海阳市"
+    ],
+    "潍坊市": [
+      "潍城区",
+      "寒亭区",
+      "坊子区",
+      "奎文区",
+      "临朐县",
+      "昌乐县",
+      "潍坊滨海经济技术开发区",
+      "青州市",
+      "诸城市",
+      "寿光市",
+      "安丘市",
+      "高密市",
+      "昌邑市"
+    ],
+    "济宁市": [
+      "任城区",
+      "兖州区",
+      "微山县",
+      "鱼台县",
+      "金乡县",
+      "嘉祥县",
+      "汶上县",
+      "泗水县",
+      "梁山县",
+      "济宁高新技术产业开发区",
+      "曲阜市",
+      "邹城市"
+    ],
+    "泰安市": [
+      "泰山区",
+      "岱岳区",
+      "宁阳县",
+      "东平县",
+      "新泰市",
+      "肥城市"
+    ],
+    "威海市": [
+      "环翠区",
+      "文登区",
+      "威海火炬高技术产业开发区",
+      "威海经济技术开发区",
+      "威海临港经济技术开发区",
+      "荣成市",
+      "乳山市"
+    ],
+    "日照市": [
+      "东港区",
+      "岚山区",
+      "五莲县",
+      "莒县",
+      "日照经济技术开发区"
+    ],
+    "莱芜市": [
+      "莱城区",
+      "钢城区"
+    ],
+    "临沂市": [
+      "兰山区",
+      "罗庄区",
+      "河东区",
+      "沂南县",
+      "郯城县",
+      "沂水县",
+      "兰陵县",
+      "费县",
+      "平邑县",
+      "莒南县",
+      "蒙阴县",
+      "临沭县",
+      "临沂高新技术产业开发区",
+      "临沂经济技术开发区",
+      "临沂临港经济开发区"
+    ],
+    "德州市": [
+      "德城区",
+      "陵城区",
+      "宁津县",
+      "庆云县",
+      "临邑县",
+      "齐河县",
+      "平原县",
+      "夏津县",
+      "武城县",
+      "德州经济技术开发区",
+      "德州运河经济开发区",
+      "乐陵市",
+      "禹城市"
+    ],
+    "聊城市": [
+      "东昌府区",
+      "阳谷县",
+      "莘县",
+      "茌平县",
+      "东阿县",
+      "冠县",
+      "高唐县",
+      "临清市"
+    ],
+    "滨州市": [
+      "滨城区",
+      "沾化区",
+      "惠民县",
+      "阳信县",
+      "无棣县",
+      "博兴县",
+      "邹平市"
+    ],
+    "菏泽市": [
+      "牡丹区",
+      "定陶区",
+      "曹县",
+      "单县",
+      "成武县",
+      "巨野县",
+      "郓城县",
+      "鄄城县",
+      "东明县",
+      "菏泽经济技术开发区",
+      "菏泽高新技术开发区"
+    ]
+  },
+  "河南省": {
+    "郑州市": [
+      "中原区",
+      "二七区",
+      "管城回族区",
+      "金水区",
+      "上街区",
+      "惠济区",
+      "中牟县",
+      "郑州经济技术开发区",
+      "郑州高新技术产业开发区",
+      "郑州航空港经济综合实验区",
+      "巩义市",
+      "荥阳市",
+      "新密市",
+      "新郑市",
+      "登封市"
+    ],
+    "开封市": [
+      "龙亭区",
+      "顺河回族区",
+      "鼓楼区",
+      "禹王台区",
+      "祥符区",
+      "杞县",
+      "通许县",
+      "尉氏县",
+      "兰考县"
+    ],
+    "洛阳市": [
+      "老城区",
+      "西工区",
+      "瀍河回族区",
+      "涧西区",
+      "吉利区",
+      "洛龙区",
+      "孟津县",
+      "新安县",
+      "栾川县",
+      "嵩县",
+      "汝阳县",
+      "宜阳县",
+      "洛宁县",
+      "伊川县",
+      "洛阳高新技术产业开发区",
+      "偃师市"
+    ],
+    "平顶山市": [
+      "新华区",
+      "卫东区",
+      "石龙区",
+      "湛河区",
+      "宝丰县",
+      "叶县",
+      "鲁山县",
+      "郏县",
+      "平顶山高新技术产业开发区",
+      "平顶山市新城区",
+      "舞钢市",
+      "汝州市"
+    ],
+    "安阳市": [
+      "文峰区",
+      "北关区",
+      "殷都区",
+      "龙安区",
+      "安阳县",
+      "汤阴县",
+      "滑县",
+      "内黄县",
+      "安阳高新技术产业开发区",
+      "林州市"
+    ],
+    "鹤壁市": [
+      "鹤山区",
+      "山城区",
+      "淇滨区",
+      "浚县",
+      "淇县",
+      "鹤壁经济技术开发区"
+    ],
+    "新乡市": [
+      "红旗区",
+      "卫滨区",
+      "凤泉区",
+      "牧野区",
+      "新乡县",
+      "获嘉县",
+      "原阳县",
+      "延津县",
+      "封丘县",
+      "长垣县",
+      "新乡高新技术产业开发区",
+      "新乡经济技术开发区",
+      "新乡市平原城乡一体化示范区",
+      "卫辉市",
+      "辉县市"
+    ],
+    "焦作市": [
+      "解放区",
+      "中站区",
+      "马村区",
+      "山阳区",
+      "修武县",
+      "博爱县",
+      "武陟县",
+      "温县",
+      "焦作城乡一体化示范区",
+      "沁阳市",
+      "孟州市"
+    ],
+    "濮阳市": [
+      "华龙区",
+      "清丰县",
+      "南乐县",
+      "范县",
+      "台前县",
+      "濮阳县",
+      "河南濮阳工业园区",
+      "濮阳经济技术开发区"
+    ],
+    "许昌市": [
+      "魏都区",
+      "建安区",
+      "鄢陵县",
+      "襄城县",
+      "许昌经济技术开发区",
+      "禹州市",
+      "长葛市"
+    ],
+    "漯河市": [
+      "源汇区",
+      "郾城区",
+      "召陵区",
+      "舞阳县",
+      "临颍县",
+      "漯河经济技术开发区"
+    ],
+    "三门峡市": [
+      "湖滨区",
+      "陕州区",
+      "渑池县",
+      "卢氏县",
+      "河南三门峡经济开发区",
+      "义马市",
+      "灵宝市"
+    ],
+    "南阳市": [
+      "宛城区",
+      "卧龙区",
+      "南召县",
+      "方城县",
+      "西峡县",
+      "镇平县",
+      "内乡县",
+      "淅川县",
+      "社旗县",
+      "唐河县",
+      "新野县",
+      "桐柏县",
+      "南阳高新技术产业开发区",
+      "南阳市城乡一体化示范区",
+      "邓州市"
+    ],
+    "商丘市": [
+      "梁园区",
+      "睢阳区",
+      "民权县",
+      "睢县",
+      "宁陵县",
+      "柘城县",
+      "虞城县",
+      "夏邑县",
+      "豫东综合物流产业聚集区",
+      "河南商丘经济开发区",
+      "永城市"
+    ],
+    "信阳市": [
+      "浉河区",
+      "平桥区",
+      "罗山县",
+      "光山县",
+      "新县",
+      "商城县",
+      "固始县",
+      "潢川县",
+      "淮滨县",
+      "息县",
+      "信阳高新技术产业开发区"
+    ],
+    "周口市": [
+      "川汇区",
+      "扶沟县",
+      "西华县",
+      "商水县",
+      "沈丘县",
+      "郸城县",
+      "淮阳县",
+      "太康县",
+      "鹿邑县",
+      "河南周口经济开发区",
+      "项城市"
+    ],
+    "驻马店市": [
+      "驿城区",
+      "西平县",
+      "上蔡县",
+      "平舆县",
+      "正阳县",
+      "确山县",
+      "泌阳县",
+      "汝南县",
+      "遂平县",
+      "新蔡县",
+      "河南驻马店经济开发区"
+    ],
+    "省直辖县级行政区划": [
+      "济源市"
+    ]
+  },
+  "湖北省": {
+    "武汉市": [
+      "江岸区",
+      "江汉区",
+      "硚口区",
+      "汉阳区",
+      "武昌区",
+      "青山区",
+      "洪山区",
+      "东西湖区",
+      "汉南区",
+      "蔡甸区",
+      "江夏区",
+      "黄陂区",
+      "新洲区"
+    ],
+    "黄石市": [
+      "黄石港区",
+      "西塞山区",
+      "下陆区",
+      "铁山区",
+      "阳新县",
+      "大冶市"
+    ],
+    "十堰市": [
+      "茅箭区",
+      "张湾区",
+      "郧阳区",
+      "郧西县",
+      "竹山县",
+      "竹溪县",
+      "房县",
+      "丹江口市"
+    ],
+    "宜昌市": [
+      "西陵区",
+      "伍家岗区",
+      "点军区",
+      "猇亭区",
+      "夷陵区",
+      "远安县",
+      "兴山县",
+      "秭归县",
+      "长阳土家族自治县",
+      "五峰土家族自治县",
+      "宜都市",
+      "当阳市",
+      "枝江市"
+    ],
+    "襄阳市": [
+      "襄城区",
+      "樊城区",
+      "襄州区",
+      "南漳县",
+      "谷城县",
+      "保康县",
+      "老河口市",
+      "枣阳市",
+      "宜城市"
+    ],
+    "鄂州市": [
+      "梁子湖区",
+      "华容区",
+      "鄂城区"
+    ],
+    "荆门市": [
+      "东宝区",
+      "掇刀区",
+      "沙洋县",
+      "钟祥市",
+      "京山市"
+    ],
+    "孝感市": [
+      "孝南区",
+      "孝昌县",
+      "大悟县",
+      "云梦县",
+      "应城市",
+      "安陆市",
+      "汉川市"
+    ],
+    "荆州市": [
+      "沙市区",
+      "荆州区",
+      "公安县",
+      "监利县",
+      "江陵县",
+      "荆州经济技术开发区",
+      "石首市",
+      "洪湖市",
+      "松滋市"
+    ],
+    "黄冈市": [
+      "黄州区",
+      "团风县",
+      "红安县",
+      "罗田县",
+      "英山县",
+      "浠水县",
+      "蕲春县",
+      "黄梅县",
+      "龙感湖管理区",
+      "麻城市",
+      "武穴市"
+    ],
+    "咸宁市": [
+      "咸安区",
+      "嘉鱼县",
+      "通城县",
+      "崇阳县",
+      "通山县",
+      "赤壁市"
+    ],
+    "随州市": [
+      "曾都区",
+      "随县",
+      "广水市"
+    ],
+    "恩施土家族苗族自治州": [
+      "恩施市",
+      "利川市",
+      "建始县",
+      "巴东县",
+      "宣恩县",
+      "咸丰县",
+      "来凤县",
+      "鹤峰县"
+    ],
+    "省直辖县级行政区划": [
+      "仙桃市",
+      "潜江市",
+      "天门市",
+      "神农架林区"
+    ]
+  },
+  "湖南省": {
+    "长沙市": [
+      "芙蓉区",
+      "天心区",
+      "岳麓区",
+      "开福区",
+      "雨花区",
+      "望城区",
+      "长沙县",
+      "浏阳市",
+      "宁乡市"
+    ],
+    "株洲市": [
+      "荷塘区",
+      "芦淞区",
+      "石峰区",
+      "天元区",
+      "渌口区",
+      "攸县",
+      "茶陵县",
+      "炎陵县",
+      "云龙示范区",
+      "醴陵市"
+    ],
+    "湘潭市": [
+      "雨湖区",
+      "岳塘区",
+      "湘潭县",
+      "湖南湘潭高新技术产业园区",
+      "湘潭昭山示范区",
+      "湘潭九华示范区",
+      "湘乡市",
+      "韶山市"
+    ],
+    "衡阳市": [
+      "珠晖区",
+      "雁峰区",
+      "石鼓区",
+      "蒸湘区",
+      "南岳区",
+      "衡阳县",
+      "衡南县",
+      "衡山县",
+      "衡东县",
+      "祁东县",
+      "衡阳综合保税区",
+      "湖南衡阳高新技术产业园区",
+      "湖南衡阳松木经济开发区",
+      "耒阳市",
+      "常宁市"
+    ],
+    "邵阳市": [
+      "双清区",
+      "大祥区",
+      "北塔区",
+      "邵东县",
+      "新邵县",
+      "邵阳县",
+      "隆回县",
+      "洞口县",
+      "绥宁县",
+      "新宁县",
+      "城步苗族自治县",
+      "武冈市"
+    ],
+    "岳阳市": [
+      "岳阳楼区",
+      "云溪区",
+      "君山区",
+      "岳阳县",
+      "华容县",
+      "湘阴县",
+      "平江县",
+      "岳阳市屈原管理区",
+      "汨罗市",
+      "临湘市"
+    ],
+    "常德市": [
+      "武陵区",
+      "鼎城区",
+      "安乡县",
+      "汉寿县",
+      "澧县",
+      "临澧县",
+      "桃源县",
+      "石门县",
+      "常德市西洞庭管理区",
+      "津市市"
+    ],
+    "张家界市": [
+      "永定区",
+      "武陵源区",
+      "慈利县",
+      "桑植县"
+    ],
+    "益阳市": [
+      "资阳区",
+      "赫山区",
+      "南县",
+      "桃江县",
+      "安化县",
+      "益阳市大通湖管理区",
+      "湖南益阳高新技术产业园区",
+      "沅江市"
+    ],
+    "郴州市": [
+      "北湖区",
+      "苏仙区",
+      "桂阳县",
+      "宜章县",
+      "永兴县",
+      "嘉禾县",
+      "临武县",
+      "汝城县",
+      "桂东县",
+      "安仁县",
+      "资兴市"
+    ],
+    "永州市": [
+      "零陵区",
+      "冷水滩区",
+      "祁阳县",
+      "东安县",
+      "双牌县",
+      "道县",
+      "江永县",
+      "宁远县",
+      "蓝山县",
+      "新田县",
+      "江华瑶族自治县",
+      "永州经济技术开发区",
+      "永州市金洞管理区",
+      "永州市回龙圩管理区"
+    ],
+    "怀化市": [
+      "鹤城区",
+      "中方县",
+      "沅陵县",
+      "辰溪县",
+      "溆浦县",
+      "会同县",
+      "麻阳苗族自治县",
+      "新晃侗族自治县",
+      "芷江侗族自治县",
+      "靖州苗族侗族自治县",
+      "通道侗族自治县",
+      "怀化市洪江管理区",
+      "洪江市"
+    ],
+    "娄底市": [
+      "娄星区",
+      "双峰县",
+      "新化县",
+      "冷水江市",
+      "涟源市"
+    ],
+    "湘西土家族苗族自治州": [
+      "吉首市",
+      "泸溪县",
+      "凤凰县",
+      "花垣县",
+      "保靖县",
+      "古丈县",
+      "永顺县",
+      "龙山县",
+      "湖南吉首经济开发区",
+      "湖南永顺经济开发区"
+    ]
+  },
+  "广东省": {
+    "广州市": [
+      "荔湾区",
+      "越秀区",
+      "海珠区",
+      "天河区",
+      "白云区",
+      "黄埔区",
+      "番禺区",
+      "花都区",
+      "南沙区",
+      "从化区",
+      "增城区"
+    ],
+    "韶关市": [
+      "武江区",
+      "浈江区",
+      "曲江区",
+      "始兴县",
+      "仁化县",
+      "翁源县",
+      "乳源瑶族自治县",
+      "新丰县",
+      "乐昌市",
+      "南雄市"
+    ],
+    "深圳市": [
+      "罗湖区",
+      "福田区",
+      "南山区",
+      "宝安区",
+      "龙岗区",
+      "盐田区",
+      "龙华区",
+      "坪山区",
+      "光明区"
+    ],
+    "珠海市": [
+      "香洲区",
+      "斗门区",
+      "金湾区"
+    ],
+    "汕头市": [
+      "龙湖区",
+      "金平区",
+      "濠江区",
+      "潮阳区",
+      "潮南区",
+      "澄海区",
+      "南澳县"
+    ],
+    "佛山市": [
+      "禅城区",
+      "南海区",
+      "顺德区",
+      "三水区",
+      "高明区"
+    ],
+    "江门市": [
+      "蓬江区",
+      "江海区",
+      "新会区",
+      "台山市",
+      "开平市",
+      "鹤山市",
+      "恩平市"
+    ],
+    "湛江市": [
+      "赤坎区",
+      "霞山区",
+      "坡头区",
+      "麻章区",
+      "遂溪县",
+      "徐闻县",
+      "廉江市",
+      "雷州市",
+      "吴川市"
+    ],
+    "茂名市": [
+      "茂南区",
+      "电白区",
+      "高州市",
+      "化州市",
+      "信宜市"
+    ],
+    "肇庆市": [
+      "端州区",
+      "鼎湖区",
+      "高要区",
+      "广宁县",
+      "怀集县",
+      "封开县",
+      "德庆县",
+      "四会市"
+    ],
+    "惠州市": [
+      "惠城区",
+      "惠阳区",
+      "博罗县",
+      "惠东县",
+      "龙门县"
+    ],
+    "梅州市": [
+      "梅江区",
+      "梅县区",
+      "大埔县",
+      "丰顺县",
+      "五华县",
+      "平远县",
+      "蕉岭县",
+      "兴宁市"
+    ],
+    "汕尾市": [
+      "城区",
+      "海丰县",
+      "陆河县",
+      "陆丰市"
+    ],
+    "河源市": [
+      "源城区",
+      "紫金县",
+      "龙川县",
+      "连平县",
+      "和平县",
+      "东源县"
+    ],
+    "阳江市": [
+      "江城区",
+      "阳东区",
+      "阳西县",
+      "阳春市"
+    ],
+    "清远市": [
+      "清城区",
+      "清新区",
+      "佛冈县",
+      "阳山县",
+      "连山壮族瑶族自治县",
+      "连南瑶族自治县",
+      "英德市",
+      "连州市"
+    ],
+    "东莞市": [
+      "东城街道",
+      "南城街道",
+      "万江街道",
+      "莞城街道",
+      "石碣镇",
+      "石龙镇",
+      "茶山镇",
+      "石排镇",
+      "企石镇",
+      "横沥镇",
+      "桥头镇",
+      "谢岗镇",
+      "东坑镇",
+      "常平镇",
+      "寮步镇",
+      "樟木头镇",
+      "大朗镇",
+      "黄江镇",
+      "清溪镇",
+      "塘厦镇",
+      "凤岗镇",
+      "大岭山镇",
+      "长安镇",
+      "虎门镇",
+      "厚街镇",
+      "沙田镇",
+      "道滘镇",
+      "洪梅镇",
+      "麻涌镇",
+      "望牛墩镇",
+      "中堂镇",
+      "高埗镇",
+      "松山湖管委会",
+      "东莞港",
+      "东莞生态园"
+    ],
+    "中山市": [
+      "石岐区街道",
+      "东区街道",
+      "火炬开发区街道",
+      "西区街道",
+      "南区街道",
+      "五桂山街道",
+      "小榄镇",
+      "黄圃镇",
+      "民众镇",
+      "东凤镇",
+      "东升镇",
+      "古镇镇",
+      "沙溪镇",
+      "坦洲镇",
+      "港口镇",
+      "三角镇",
+      "横栏镇",
+      "南头镇",
+      "阜沙镇",
+      "南朗镇",
+      "三乡镇",
+      "板芙镇",
+      "大涌镇",
+      "神湾镇"
+    ],
+    "潮州市": [
+      "湘桥区",
+      "潮安区",
+      "饶平县"
+    ],
+    "揭阳市": [
+      "榕城区",
+      "揭东区",
+      "揭西县",
+      "惠来县",
+      "普宁市"
+    ],
+    "云浮市": [
+      "云城区",
+      "云安区",
+      "新兴县",
+      "郁南县",
+      "罗定市"
+    ]
+  },
+  "广西壮族自治区": {
+    "南宁市": [
+      "兴宁区",
+      "青秀区",
+      "江南区",
+      "西乡塘区",
+      "良庆区",
+      "邕宁区",
+      "武鸣区",
+      "隆安县",
+      "马山县",
+      "上林县",
+      "宾阳县",
+      "横县"
+    ],
+    "柳州市": [
+      "城中区",
+      "鱼峰区",
+      "柳南区",
+      "柳北区",
+      "柳江区",
+      "柳城县",
+      "鹿寨县",
+      "融安县",
+      "融水苗族自治县",
+      "三江侗族自治县"
+    ],
+    "桂林市": [
+      "秀峰区",
+      "叠彩区",
+      "象山区",
+      "七星区",
+      "雁山区",
+      "临桂区",
+      "阳朔县",
+      "灵川县",
+      "全州县",
+      "兴安县",
+      "永福县",
+      "灌阳县",
+      "龙胜各族自治县",
+      "资源县",
+      "平乐县",
+      "恭城瑶族自治县",
+      "荔浦市"
+    ],
+    "梧州市": [
+      "万秀区",
+      "长洲区",
+      "龙圩区",
+      "苍梧县",
+      "藤县",
+      "蒙山县",
+      "岑溪市"
+    ],
+    "北海市": [
+      "海城区",
+      "银海区",
+      "铁山港区",
+      "合浦县"
+    ],
+    "防城港市": [
+      "港口区",
+      "防城区",
+      "上思县",
+      "东兴市"
+    ],
+    "钦州市": [
+      "钦南区",
+      "钦北区",
+      "灵山县",
+      "浦北县"
+    ],
+    "贵港市": [
+      "港北区",
+      "港南区",
+      "覃塘区",
+      "平南县",
+      "桂平市"
+    ],
+    "玉林市": [
+      "玉州区",
+      "福绵区",
+      "容县",
+      "陆川县",
+      "博白县",
+      "兴业县",
+      "北流市"
+    ],
+    "百色市": [
+      "右江区",
+      "田阳县",
+      "田东县",
+      "平果县",
+      "德保县",
+      "那坡县",
+      "凌云县",
+      "乐业县",
+      "田林县",
+      "西林县",
+      "隆林各族自治县",
+      "靖西市"
+    ],
+    "贺州市": [
+      "八步区",
+      "平桂区",
+      "昭平县",
+      "钟山县",
+      "富川瑶族自治县"
+    ],
+    "河池市": [
+      "金城江区",
+      "宜州区",
+      "南丹县",
+      "天峨县",
+      "凤山县",
+      "东兰县",
+      "罗城仫佬族自治县",
+      "环江毛南族自治县",
+      "巴马瑶族自治县",
+      "都安瑶族自治县",
+      "大化瑶族自治县"
+    ],
+    "来宾市": [
+      "兴宾区",
+      "忻城县",
+      "象州县",
+      "武宣县",
+      "金秀瑶族自治县",
+      "合山市"
+    ],
+    "崇左市": [
+      "江州区",
+      "扶绥县",
+      "宁明县",
+      "龙州县",
+      "大新县",
+      "天等县",
+      "凭祥市"
+    ]
+  },
+  "海南省": {
+    "海口市": [
+      "秀英区",
+      "龙华区",
+      "琼山区",
+      "美兰区"
+    ],
+    "三亚市": [
+      "海棠区",
+      "吉阳区",
+      "天涯区",
+      "崖州区"
+    ],
+    "三沙市": [
+      "西沙群岛",
+      "南沙群岛",
+      "中沙群岛的岛礁及其海域"
+    ],
+    "儋州市": [
+      "那大镇",
+      "和庆镇",
+      "南丰镇",
+      "大成镇",
+      "雅星镇",
+      "兰洋镇",
+      "光村镇",
+      "木棠镇",
+      "海头镇",
+      "峨蔓镇",
+      "王五镇",
+      "白马井镇",
+      "中和镇",
+      "排浦镇",
+      "东成镇",
+      "新州镇",
+      "洋浦经济开发区",
+      "华南热作学院"
+    ],
+    "省直辖县级行政区划": [
+      "五指山市",
+      "琼海市",
+      "文昌市",
+      "万宁市",
+      "东方市",
+      "定安县",
+      "屯昌县",
+      "澄迈县",
+      "临高县",
+      "白沙黎族自治县",
+      "昌江黎族自治县",
+      "乐东黎族自治县",
+      "陵水黎族自治县",
+      "保亭黎族苗族自治县",
+      "琼中黎族苗族自治县"
+    ]
+  },
+  "重庆市": {
+    "市辖区": [
+      "万州区",
+      "涪陵区",
+      "渝中区",
+      "大渡口区",
+      "江北区",
+      "沙坪坝区",
+      "九龙坡区",
+      "南岸区",
+      "北碚区",
+      "綦江区",
+      "大足区",
+      "渝北区",
+      "巴南区",
+      "黔江区",
+      "长寿区",
+      "江津区",
+      "合川区",
+      "永川区",
+      "南川区",
+      "璧山区",
+      "铜梁区",
+      "潼南区",
+      "荣昌区",
+      "开州区",
+      "梁平区",
+      "武隆区"
+    ],
+    "县": [
+      "城口县",
+      "丰都县",
+      "垫江县",
+      "忠县",
+      "云阳县",
+      "奉节县",
+      "巫山县",
+      "巫溪县",
+      "石柱土家族自治县",
+      "秀山土家族苗族自治县",
+      "酉阳土家族苗族自治县",
+      "彭水苗族土家族自治县"
+    ]
+  },
+  "四川省": {
+    "成都市": [
+      "锦江区",
+      "青羊区",
+      "金牛区",
+      "武侯区",
+      "成华区",
+      "龙泉驿区",
+      "青白江区",
+      "新都区",
+      "温江区",
+      "双流区",
+      "郫都区",
+      "金堂县",
+      "大邑县",
+      "蒲江县",
+      "新津县",
+      "都江堰市",
+      "彭州市",
+      "邛崃市",
+      "崇州市",
+      "简阳市"
+    ],
+    "自贡市": [
+      "自流井区",
+      "贡井区",
+      "大安区",
+      "沿滩区",
+      "荣县",
+      "富顺县"
+    ],
+    "攀枝花市": [
+      "东区",
+      "西区",
+      "仁和区",
+      "米易县",
+      "盐边县"
+    ],
+    "泸州市": [
+      "江阳区",
+      "纳溪区",
+      "龙马潭区",
+      "泸县",
+      "合江县",
+      "叙永县",
+      "古蔺县"
+    ],
+    "德阳市": [
+      "旌阳区",
+      "罗江区",
+      "中江县",
+      "广汉市",
+      "什邡市",
+      "绵竹市"
+    ],
+    "绵阳市": [
+      "涪城区",
+      "游仙区",
+      "安州区",
+      "三台县",
+      "盐亭县",
+      "梓潼县",
+      "北川羌族自治县",
+      "平武县",
+      "江油市"
+    ],
+    "广元市": [
+      "利州区",
+      "昭化区",
+      "朝天区",
+      "旺苍县",
+      "青川县",
+      "剑阁县",
+      "苍溪县"
+    ],
+    "遂宁市": [
+      "船山区",
+      "安居区",
+      "蓬溪县",
+      "射洪县",
+      "大英县"
+    ],
+    "内江市": [
+      "市中区",
+      "东兴区",
+      "威远县",
+      "资中县",
+      "内江经济开发区",
+      "隆昌市"
+    ],
+    "乐山市": [
+      "市中区",
+      "沙湾区",
+      "五通桥区",
+      "金口河区",
+      "犍为县",
+      "井研县",
+      "夹江县",
+      "沐川县",
+      "峨边彝族自治县",
+      "马边彝族自治县",
+      "峨眉山市"
+    ],
+    "南充市": [
+      "顺庆区",
+      "高坪区",
+      "嘉陵区",
+      "南部县",
+      "营山县",
+      "蓬安县",
+      "仪陇县",
+      "西充县",
+      "阆中市"
+    ],
+    "眉山市": [
+      "东坡区",
+      "彭山区",
+      "仁寿县",
+      "洪雅县",
+      "丹棱县",
+      "青神县"
+    ],
+    "宜宾市": [
+      "翠屏区",
+      "南溪区",
+      "叙州区",
+      "江安县",
+      "长宁县",
+      "高县",
+      "珙县",
+      "筠连县",
+      "兴文县",
+      "屏山县"
+    ],
+    "广安市": [
+      "广安区",
+      "前锋区",
+      "岳池县",
+      "武胜县",
+      "邻水县",
+      "华蓥市"
+    ],
+    "达州市": [
+      "通川区",
+      "达川区",
+      "宣汉县",
+      "开江县",
+      "大竹县",
+      "渠县",
+      "达州经济开发区",
+      "万源市"
+    ],
+    "雅安市": [
+      "雨城区",
+      "名山区",
+      "荥经县",
+      "汉源县",
+      "石棉县",
+      "天全县",
+      "芦山县",
+      "宝兴县"
+    ],
+    "巴中市": [
+      "巴州区",
+      "恩阳区",
+      "通江县",
+      "南江县",
+      "平昌县",
+      "巴中经济开发区"
+    ],
+    "资阳市": [
+      "雁江区",
+      "安岳县",
+      "乐至县"
+    ],
+    "阿坝藏族羌族自治州": [
+      "马尔康市",
+      "汶川县",
+      "理县",
+      "茂县",
+      "松潘县",
+      "九寨沟县",
+      "金川县",
+      "小金县",
+      "黑水县",
+      "壤塘县",
+      "阿坝县",
+      "若尔盖县",
+      "红原县"
+    ],
+    "甘孜藏族自治州": [
+      "康定市",
+      "泸定县",
+      "丹巴县",
+      "九龙县",
+      "雅江县",
+      "道孚县",
+      "炉霍县",
+      "甘孜县",
+      "新龙县",
+      "德格县",
+      "白玉县",
+      "石渠县",
+      "色达县",
+      "理塘县",
+      "巴塘县",
+      "乡城县",
+      "稻城县",
+      "得荣县"
+    ],
+    "凉山彝族自治州": [
+      "西昌市",
+      "木里藏族自治县",
+      "盐源县",
+      "德昌县",
+      "会理县",
+      "会东县",
+      "宁南县",
+      "普格县",
+      "布拖县",
+      "金阳县",
+      "昭觉县",
+      "喜德县",
+      "冕宁县",
+      "越西县",
+      "甘洛县",
+      "美姑县",
+      "雷波县"
+    ]
+  },
+  "贵州省": {
+    "贵阳市": [
+      "南明区",
+      "云岩区",
+      "花溪区",
+      "乌当区",
+      "白云区",
+      "观山湖区",
+      "开阳县",
+      "息烽县",
+      "修文县",
+      "清镇市"
+    ],
+    "六盘水市": [
+      "钟山区",
+      "六枝特区",
+      "水城县",
+      "盘州市"
+    ],
+    "遵义市": [
+      "红花岗区",
+      "汇川区",
+      "播州区",
+      "桐梓县",
+      "绥阳县",
+      "正安县",
+      "道真仡佬族苗族自治县",
+      "务川仡佬族苗族自治县",
+      "凤冈县",
+      "湄潭县",
+      "余庆县",
+      "习水县",
+      "赤水市",
+      "仁怀市"
+    ],
+    "安顺市": [
+      "西秀区",
+      "平坝区",
+      "普定县",
+      "镇宁布依族苗族自治县",
+      "关岭布依族苗族自治县",
+      "紫云苗族布依族自治县"
+    ],
+    "毕节市": [
+      "七星关区",
+      "大方县",
+      "黔西县",
+      "金沙县",
+      "织金县",
+      "纳雍县",
+      "威宁彝族回族苗族自治县",
+      "赫章县"
+    ],
+    "铜仁市": [
+      "碧江区",
+      "万山区",
+      "江口县",
+      "玉屏侗族自治县",
+      "石阡县",
+      "思南县",
+      "印江土家族苗族自治县",
+      "德江县",
+      "沿河土家族自治县",
+      "松桃苗族自治县"
+    ],
+    "黔西南布依族苗族自治州": [
+      "兴义市",
+      "兴仁市",
+      "普安县",
+      "晴隆县",
+      "贞丰县",
+      "望谟县",
+      "册亨县",
+      "安龙县"
+    ],
+    "黔东南苗族侗族自治州": [
+      "凯里市",
+      "黄平县",
+      "施秉县",
+      "三穗县",
+      "镇远县",
+      "岑巩县",
+      "天柱县",
+      "锦屏县",
+      "剑河县",
+      "台江县",
+      "黎平县",
+      "榕江县",
+      "从江县",
+      "雷山县",
+      "麻江县",
+      "丹寨县"
+    ],
+    "黔南布依族苗族自治州": [
+      "都匀市",
+      "福泉市",
+      "荔波县",
+      "贵定县",
+      "瓮安县",
+      "独山县",
+      "平塘县",
+      "罗甸县",
+      "长顺县",
+      "龙里县",
+      "惠水县",
+      "三都水族自治县"
+    ]
+  },
+  "云南省": {
+    "昆明市": [
+      "五华区",
+      "盘龙区",
+      "官渡区",
+      "西山区",
+      "东川区",
+      "呈贡区",
+      "晋宁区",
+      "富民县",
+      "宜良县",
+      "石林彝族自治县",
+      "嵩明县",
+      "禄劝彝族苗族自治县",
+      "寻甸回族彝族自治县",
+      "安宁市"
+    ],
+    "曲靖市": [
+      "麒麟区",
+      "沾益区",
+      "马龙区",
+      "陆良县",
+      "师宗县",
+      "罗平县",
+      "富源县",
+      "会泽县",
+      "宣威市"
+    ],
+    "玉溪市": [
+      "红塔区",
+      "江川区",
+      "澄江县",
+      "通海县",
+      "华宁县",
+      "易门县",
+      "峨山彝族自治县",
+      "新平彝族傣族自治县",
+      "元江哈尼族彝族傣族自治县"
+    ],
+    "保山市": [
+      "隆阳区",
+      "施甸县",
+      "龙陵县",
+      "昌宁县",
+      "腾冲市"
+    ],
+    "昭通市": [
+      "昭阳区",
+      "鲁甸县",
+      "巧家县",
+      "盐津县",
+      "大关县",
+      "永善县",
+      "绥江县",
+      "镇雄县",
+      "彝良县",
+      "威信县",
+      "水富市"
+    ],
+    "丽江市": [
+      "古城区",
+      "玉龙纳西族自治县",
+      "永胜县",
+      "华坪县",
+      "宁蒗彝族自治县"
+    ],
+    "普洱市": [
+      "思茅区",
+      "宁洱哈尼族彝族自治县",
+      "墨江哈尼族自治县",
+      "景东彝族自治县",
+      "景谷傣族彝族自治县",
+      "镇沅彝族哈尼族拉祜族自治县",
+      "江城哈尼族彝族自治县",
+      "孟连傣族拉祜族佤族自治县",
+      "澜沧拉祜族自治县",
+      "西盟佤族自治县"
+    ],
+    "临沧市": [
+      "临翔区",
+      "凤庆县",
+      "云县",
+      "永德县",
+      "镇康县",
+      "双江拉祜族佤族布朗族傣族自治县",
+      "耿马傣族佤族自治县",
+      "沧源佤族自治县"
+    ],
+    "楚雄彝族自治州": [
+      "楚雄市",
+      "双柏县",
+      "牟定县",
+      "南华县",
+      "姚安县",
+      "大姚县",
+      "永仁县",
+      "元谋县",
+      "武定县",
+      "禄丰县"
+    ],
+    "红河哈尼族彝族自治州": [
+      "个旧市",
+      "开远市",
+      "蒙自市",
+      "弥勒市",
+      "屏边苗族自治县",
+      "建水县",
+      "石屏县",
+      "泸西县",
+      "元阳县",
+      "红河县",
+      "金平苗族瑶族傣族自治县",
+      "绿春县",
+      "河口瑶族自治县"
+    ],
+    "文山壮族苗族自治州": [
+      "文山市",
+      "砚山县",
+      "西畴县",
+      "麻栗坡县",
+      "马关县",
+      "丘北县",
+      "广南县",
+      "富宁县"
+    ],
+    "西双版纳傣族自治州": [
+      "景洪市",
+      "勐海县",
+      "勐腊县"
+    ],
+    "大理白族自治州": [
+      "大理市",
+      "漾濞彝族自治县",
+      "祥云县",
+      "宾川县",
+      "弥渡县",
+      "南涧彝族自治县",
+      "巍山彝族回族自治县",
+      "永平县",
+      "云龙县",
+      "洱源县",
+      "剑川县",
+      "鹤庆县"
+    ],
+    "德宏傣族景颇族自治州": [
+      "瑞丽市",
+      "芒市",
+      "梁河县",
+      "盈江县",
+      "陇川县"
+    ],
+    "怒江傈僳族自治州": [
+      "泸水市",
+      "福贡县",
+      "贡山独龙族怒族自治县",
+      "兰坪白族普米族自治县"
+    ],
+    "迪庆藏族自治州": [
+      "香格里拉市",
+      "德钦县",
+      "维西傈僳族自治县"
+    ]
+  },
+  "西藏自治区": {
+    "拉萨市": [
+      "城关区",
+      "堆龙德庆区",
+      "达孜区",
+      "林周县",
+      "当雄县",
+      "尼木县",
+      "曲水县",
+      "墨竹工卡县",
+      "格尔木藏青工业园区",
+      "拉萨经济技术开发区",
+      "西藏文化旅游创意园区",
+      "达孜工业园区"
+    ],
+    "日喀则市": [
+      "桑珠孜区",
+      "南木林县",
+      "江孜县",
+      "定日县",
+      "萨迦县",
+      "拉孜县",
+      "昂仁县",
+      "谢通门县",
+      "白朗县",
+      "仁布县",
+      "康马县",
+      "定结县",
+      "仲巴县",
+      "亚东县",
+      "吉隆县",
+      "聂拉木县",
+      "萨嘎县",
+      "岗巴县"
+    ],
+    "昌都市": [
+      "卡若区",
+      "江达县",
+      "贡觉县",
+      "类乌齐县",
+      "丁青县",
+      "察雅县",
+      "八宿县",
+      "左贡县",
+      "芒康县",
+      "洛隆县",
+      "边坝县"
+    ],
+    "林芝市": [
+      "巴宜区",
+      "工布江达县",
+      "米林县",
+      "墨脱县",
+      "波密县",
+      "察隅县",
+      "朗县"
+    ],
+    "山南市": [
+      "乃东区",
+      "扎囊县",
+      "贡嘎县",
+      "桑日县",
+      "琼结县",
+      "曲松县",
+      "措美县",
+      "洛扎县",
+      "加查县",
+      "隆子县",
+      "错那县",
+      "浪卡子县"
+    ],
+    "那曲市": [
+      "色尼区",
+      "嘉黎县",
+      "比如县",
+      "聂荣县",
+      "安多县",
+      "申扎县",
+      "索县",
+      "班戈县",
+      "巴青县",
+      "尼玛县",
+      "双湖县"
+    ],
+    "阿里地区": [
+      "普兰县",
+      "札达县",
+      "噶尔县",
+      "日土县",
+      "革吉县",
+      "改则县",
+      "措勤县"
+    ]
+  },
+  "陕西省": {
+    "西安市": [
+      "新城区",
+      "碑林区",
+      "莲湖区",
+      "灞桥区",
+      "未央区",
+      "雁塔区",
+      "阎良区",
+      "临潼区",
+      "长安区",
+      "高陵区",
+      "鄠邑区",
+      "蓝田县",
+      "周至县"
+    ],
+    "铜川市": [
+      "王益区",
+      "印台区",
+      "耀州区",
+      "宜君县"
+    ],
+    "宝鸡市": [
+      "渭滨区",
+      "金台区",
+      "陈仓区",
+      "凤翔县",
+      "岐山县",
+      "扶风县",
+      "眉县",
+      "陇县",
+      "千阳县",
+      "麟游县",
+      "凤县",
+      "太白县"
+    ],
+    "咸阳市": [
+      "秦都区",
+      "杨陵区",
+      "渭城区",
+      "三原县",
+      "泾阳县",
+      "乾县",
+      "礼泉县",
+      "永寿县",
+      "长武县",
+      "旬邑县",
+      "淳化县",
+      "武功县",
+      "兴平市",
+      "彬州市"
+    ],
+    "渭南市": [
+      "临渭区",
+      "华州区",
+      "潼关县",
+      "大荔县",
+      "合阳县",
+      "澄城县",
+      "蒲城县",
+      "白水县",
+      "富平县",
+      "韩城市",
+      "华阴市"
+    ],
+    "延安市": [
+      "宝塔区",
+      "安塞区",
+      "延长县",
+      "延川县",
+      "子长县",
+      "志丹县",
+      "吴起县",
+      "甘泉县",
+      "富县",
+      "洛川县",
+      "宜川县",
+      "黄龙县",
+      "黄陵县"
+    ],
+    "汉中市": [
+      "汉台区",
+      "南郑区",
+      "城固县",
+      "洋县",
+      "西乡县",
+      "勉县",
+      "宁强县",
+      "略阳县",
+      "镇巴县",
+      "留坝县",
+      "佛坪县"
+    ],
+    "榆林市": [
+      "榆阳区",
+      "横山区",
+      "府谷县",
+      "靖边县",
+      "定边县",
+      "绥德县",
+      "米脂县",
+      "佳县",
+      "吴堡县",
+      "清涧县",
+      "子洲县",
+      "神木市"
+    ],
+    "安康市": [
+      "汉滨区",
+      "汉阴县",
+      "石泉县",
+      "宁陕县",
+      "紫阳县",
+      "岚皋县",
+      "平利县",
+      "镇坪县",
+      "旬阳县",
+      "白河县"
+    ],
+    "商洛市": [
+      "商州区",
+      "洛南县",
+      "丹凤县",
+      "商南县",
+      "山阳县",
+      "镇安县",
+      "柞水县"
+    ]
+  },
+  "甘肃省": {
+    "兰州市": [
+      "城关区",
+      "七里河区",
+      "西固区",
+      "安宁区",
+      "红古区",
+      "永登县",
+      "皋兰县",
+      "榆中县",
+      "兰州新区"
+    ],
+    "嘉峪关市": [
+      "新城镇",
+      "峪泉镇",
+      "文殊镇",
+      "雄关区",
+      "镜铁区",
+      "长城区"
+    ],
+    "金昌市": [
+      "金川区",
+      "永昌县"
+    ],
+    "白银市": [
+      "白银区",
+      "平川区",
+      "靖远县",
+      "会宁县",
+      "景泰县"
+    ],
+    "天水市": [
+      "秦州区",
+      "麦积区",
+      "清水县",
+      "秦安县",
+      "甘谷县",
+      "武山县",
+      "张家川回族自治县"
+    ],
+    "武威市": [
+      "凉州区",
+      "民勤县",
+      "古浪县",
+      "天祝藏族自治县"
+    ],
+    "张掖市": [
+      "甘州区",
+      "肃南裕固族自治县",
+      "民乐县",
+      "临泽县",
+      "高台县",
+      "山丹县"
+    ],
+    "平凉市": [
+      "崆峒区",
+      "泾川县",
+      "灵台县",
+      "崇信县",
+      "庄浪县",
+      "静宁县",
+      "华亭市"
+    ],
+    "酒泉市": [
+      "肃州区",
+      "金塔县",
+      "瓜州县",
+      "肃北蒙古族自治县",
+      "阿克塞哈萨克族自治县",
+      "玉门市",
+      "敦煌市"
+    ],
+    "庆阳市": [
+      "西峰区",
+      "庆城县",
+      "环县",
+      "华池县",
+      "合水县",
+      "正宁县",
+      "宁县",
+      "镇原县"
+    ],
+    "定西市": [
+      "安定区",
+      "通渭县",
+      "陇西县",
+      "渭源县",
+      "临洮县",
+      "漳县",
+      "岷县"
+    ],
+    "陇南市": [
+      "武都区",
+      "成县",
+      "文县",
+      "宕昌县",
+      "康县",
+      "西和县",
+      "礼县",
+      "徽县",
+      "两当县"
+    ],
+    "临夏回族自治州": [
+      "临夏市",
+      "临夏县",
+      "康乐县",
+      "永靖县",
+      "广河县",
+      "和政县",
+      "东乡族自治县",
+      "积石山保安族东乡族撒拉族自治县"
+    ],
+    "甘南藏族自治州": [
+      "合作市",
+      "临潭县",
+      "卓尼县",
+      "舟曲县",
+      "迭部县",
+      "玛曲县",
+      "碌曲县",
+      "夏河县"
+    ]
+  },
+  "青海省": {
+    "西宁市": [
+      "城东区",
+      "城中区",
+      "城西区",
+      "城北区",
+      "大通回族土族自治县",
+      "湟中县",
+      "湟源县"
+    ],
+    "海东市": [
+      "乐都区",
+      "平安区",
+      "民和回族土族自治县",
+      "互助土族自治县",
+      "化隆回族自治县",
+      "循化撒拉族自治县"
+    ],
+    "海北藏族自治州": [
+      "门源回族自治县",
+      "祁连县",
+      "海晏县",
+      "刚察县"
+    ],
+    "黄南藏族自治州": [
+      "同仁县",
+      "尖扎县",
+      "泽库县",
+      "河南蒙古族自治县"
+    ],
+    "海南藏族自治州": [
+      "共和县",
+      "同德县",
+      "贵德县",
+      "兴海县",
+      "贵南县"
+    ],
+    "果洛藏族自治州": [
+      "玛沁县",
+      "班玛县",
+      "甘德县",
+      "达日县",
+      "久治县",
+      "玛多县"
+    ],
+    "玉树藏族自治州": [
+      "玉树市",
+      "杂多县",
+      "称多县",
+      "治多县",
+      "囊谦县",
+      "曲麻莱县"
+    ],
+    "海西蒙古族藏族自治州": [
+      "格尔木市",
+      "德令哈市",
+      "茫崖市",
+      "乌兰县",
+      "都兰县",
+      "天峻县",
+      "大柴旦行政委员会"
+    ]
+  },
+  "宁夏回族自治区": {
+    "银川市": [
+      "兴庆区",
+      "西夏区",
+      "金凤区",
+      "永宁县",
+      "贺兰县",
+      "灵武市"
+    ],
+    "石嘴山市": [
+      "大武口区",
+      "惠农区",
+      "平罗县"
+    ],
+    "吴忠市": [
+      "利通区",
+      "红寺堡区",
+      "盐池县",
+      "同心县",
+      "青铜峡市"
+    ],
+    "固原市": [
+      "原州区",
+      "西吉县",
+      "隆德县",
+      "泾源县",
+      "彭阳县"
+    ],
+    "中卫市": [
+      "沙坡头区",
+      "中宁县",
+      "海原县"
+    ]
+  },
+  "新疆维吾尔自治区": {
+    "乌鲁木齐市": [
+      "天山区",
+      "沙依巴克区",
+      "新市区",
+      "水磨沟区",
+      "头屯河区",
+      "达坂城区",
+      "米东区",
+      "乌鲁木齐县",
+      "乌鲁木齐经济技术开发区",
+      "乌鲁木齐高新技术产业开发区"
+    ],
+    "克拉玛依市": [
+      "独山子区",
+      "克拉玛依区",
+      "白碱滩区",
+      "乌尔禾区"
+    ],
+    "吐鲁番市": [
+      "高昌区",
+      "鄯善县",
+      "托克逊县"
+    ],
+    "哈密市": [
+      "伊州区",
+      "巴里坤哈萨克自治县",
+      "伊吾县"
+    ],
+    "昌吉回族自治州": [
+      "昌吉市",
+      "阜康市",
+      "呼图壁县",
+      "玛纳斯县",
+      "奇台县",
+      "吉木萨尔县",
+      "木垒哈萨克自治县"
+    ],
+    "博尔塔拉蒙古自治州": [
+      "博乐市",
+      "阿拉山口市",
+      "精河县",
+      "温泉县"
+    ],
+    "巴音郭楞蒙古自治州": [
+      "库尔勒市",
+      "轮台县",
+      "尉犁县",
+      "若羌县",
+      "且末县",
+      "焉耆回族自治县",
+      "和静县",
+      "和硕县",
+      "博湖县",
+      "库尔勒经济技术开发区"
+    ],
+    "阿克苏地区": [
+      "阿克苏市",
+      "温宿县",
+      "库车县",
+      "沙雅县",
+      "新和县",
+      "拜城县",
+      "乌什县",
+      "阿瓦提县",
+      "柯坪县"
+    ],
+    "克孜勒苏柯尔克孜自治州": [
+      "阿图什市",
+      "阿克陶县",
+      "阿合奇县",
+      "乌恰县"
+    ],
+    "喀什地区": [
+      "喀什市",
+      "疏附县",
+      "疏勒县",
+      "英吉沙县",
+      "泽普县",
+      "莎车县",
+      "叶城县",
+      "麦盖提县",
+      "岳普湖县",
+      "伽师县",
+      "巴楚县",
+      "塔什库尔干塔吉克自治县"
+    ],
+    "和田地区": [
+      "和田市",
+      "和田县",
+      "墨玉县",
+      "皮山县",
+      "洛浦县",
+      "策勒县",
+      "于田县",
+      "民丰县"
+    ],
+    "伊犁哈萨克自治州": [
+      "伊宁市",
+      "奎屯市",
+      "霍尔果斯市",
+      "伊宁县",
+      "察布查尔锡伯自治县",
+      "霍城县",
+      "巩留县",
+      "新源县",
+      "昭苏县",
+      "特克斯县",
+      "尼勒克县"
+    ],
+    "塔城地区": [
+      "塔城市",
+      "乌苏市",
+      "额敏县",
+      "沙湾县",
+      "托里县",
+      "裕民县",
+      "和布克赛尔蒙古自治县"
+    ],
+    "阿勒泰地区": [
+      "阿勒泰市",
+      "布尔津县",
+      "富蕴县",
+      "福海县",
+      "哈巴河县",
+      "青河县",
+      "吉木乃县"
+    ],
+    "自治区直辖县级行政区划": [
+      "石河子市",
+      "阿拉尔市",
+      "图木舒克市",
+      "五家渠市",
+      "铁门关市"
+    ]
+  }
+}

+ 32 - 0
app/src/components/alert.vue

@@ -0,0 +1,32 @@
+<template>
+  <div>
+    <mu-dialog title="警告" width="360" :open.sync="openSimple">
+       {{text}}
+      <mu-button slot="actions" flat color="primary" @click="closeSimpleDialog">关闭</mu-button>
+    </mu-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      openSimple: false,
+      text:'1111'
+    };
+  },
+  methods: {
+    openSimpleDialog(info) {
+      this.openSimple = true;
+      this.text = info;
+    },
+    closeSimpleDialog() {
+      this.openSimple = false;
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 388 - 0
app/src/components/appHeader.vue

@@ -0,0 +1,388 @@
+<template>
+    <div id="appHeader">
+        <div id="headerContent">
+            <mu-appbar style="width: 100%;" color="primary">
+                <mu-button icon slot="left">
+                    <mu-button ref="button" @click="open = !open">
+                        <img src="../static/images/comm/list.png" alt="" class="listBtn">
+                    </mu-button>
+                    <mu-popover cover :open.sync="open" :trigger="trigger">
+                        <mu-list>
+                            <mu-list-item button :class="[{'active':t == curLi},'modalLi' ]"
+                                          v-for="(panel,t) in panelData" :key="panel.tabs" @click="goPage(panel)">
+                                <mu-list-item-title>
+                                    <!--<span :class="panel.img"></span>-->
+                                    <mu-icon :value="panel.img"></mu-icon>
+                                    <s>{{panel.name}}</s>
+                                </mu-list-item-title>
+                            </mu-list-item>
+                        </mu-list>
+                    </mu-popover>
+                </mu-button>
+                {{curTitle}}
+                <mu-menu slot="right">
+                    <img src="../static/images/comm/user.png" alt="" class="userBtn">
+                </mu-menu>
+            </mu-appbar>
+            <div class="alertRed" v-show="alertState && title == '系统首页'">
+                <em>
+                    <i class="curIcon yellowTri"></i>
+                    发现危险设备{{dangerNum}} {{$t("item")}}
+                </em>
+                <span @click="goRuntime">{{$t("Suspicious device")}}MAC:{{mac}} 品牌:{{MacCom}} <i
+                        @click="closeAlert">×</i></span>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+    import axios from 'axios';
+
+    let qs = require('qs');
+    export default {
+        data() {
+            return {
+                open: false,
+                trigger: null,
+                curLi: 0,
+                curTitle: this.title,
+                alertState: false,
+                dangerNum: 0,
+                mac: '',
+                MacCom: '',
+                panelData: [
+                    {name: this.$t('System home page'), path: '', img: 'home', tabs: 1},
+                    {name: this.$t('User list'), path: 'usermanage', img: 'account_box', tabs: 2},
+                    {name: this.$t('Enterprise list'), path: 'enterprisemanage', img: 'assignment', tabs: 3},
+                    {name: this.$t('Detection equipment'), path: 'detector', img: 'laptop', tabs: 4},
+                    {name: this.$t('Detection record'), path: 'record', img: 'reorder', tabs: 5},
+                    {name: this.$t('Statistical report forms'), path: 'statis', img: 'receipt', tabs: 6},
+                    {name: this.$t('System setup'), path: 'setting', img: 'settings', tabs: 7},
+                    {name: this.$t('whiteList'), path: 'white', img: 'view_list', tabs: 8},
+                    {name: this.$t('Real-time monitoring'), path: 'runtime', img: 'poll', tabs: 9},
+                ]
+            }
+        },
+        props: ['title'],
+        mounted() {
+            this.trigger = this.$refs.button.$el;
+            this.timer = setInterval(() => {
+                this.readAlert();
+            }, 5000);
+        },
+        beforeDestroy() {
+            clearInterval(this.timer);
+        },
+        methods: {
+            goPage(panel) {
+                console.log(panel);
+                this.$emit('goNewpage', panel.path);
+                this.open = false;
+            },
+            goRuntime() {
+                this.alertState = false;
+                this.$emit('goNewpage', 'runtime');
+                this.open = false;
+            },
+            // 读取警告信息
+            readAlert() {
+                const that = this;
+                let url = headapi + 'v1/Detector/DetectedMacs';
+                // let url = headapi + 'v1/Detector/DetectedMacsTest';//test
+                let param = {
+                    token: localStorage.token,
+                };
+                let postdata = qs.stringify(param);
+                axios.post(url, postdata).then(function (data) {
+                    let json = data.data;
+                    if (json.Code == 0) {
+                        if (json.Rs) {
+                            if (localStorage.alertState == true) {
+                                that.alertState = true;
+                            } else {
+                                that.alertState = false;
+                            }
+                            that.dangerNum = json.Rs.length;
+                            that.mac = json.Rs[0].Mac;
+                            if (json.Rs[0].MacCom) {
+                                that.MacCom = json.Rs[0].MacCom.substr(0, 9) + '...';
+                            }
+
+                        }
+                    }
+                    if (json.Code == 1010) {
+                        that.$router.push({path: '/login'});
+                    }
+                }, function (response) {
+                    that.$router.push({path: '/login'});
+                    console.info(response);
+                })
+            },
+            closeAlert() {
+                this.alertState = false
+            }
+        },
+    }
+</script>
+
+<style scoped>
+    #appHeader {
+        width: 100%;
+        height: 55px;
+        z-index: 99999;
+    }
+    #headerContent {
+        width: 100%;
+        position: absolute;
+        z-index: 99999;
+        top: 0;
+    }
+    /deep/ .mu-appbar-title {
+        text-align: center;
+    }
+
+    .mu-raised-button {
+        background: none;
+        box-shadow: none;
+    }
+
+    .listBtn {
+        width: 20px;
+        height: 14px;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        margin-top: 0px;
+    }
+
+    .userBtn {
+        width: 28px;
+        height: 28px;
+        margin-top: 15px;
+        margin-right: 15px;
+    }
+
+    .mu-appbar {
+        background: url("../static/images/comm/headerBg.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    /*icon iconHome*/
+    .iconHome {
+        width: 20px;
+        height: 20px;
+        float: left;
+        margin-right: 10px;
+        background: url("../static/images/comm/iconHome.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    .active .iconHome {
+        width: 20px;
+        height: 20px;
+        float: left;
+        margin-right: 10px;
+        background: url("../static/images/comm/iconHome_a.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    .iconUser {
+        width: 20px;
+        height: 20px;
+        float: left;
+        margin-right: 10px;
+        background: url("../static/images/comm/iconUser.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    .active .iconUser {
+        width: 20px;
+        height: 20px;
+        float: left;
+        margin-right: 10px;
+        background: url("../static/images/comm/iconUser_a.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    .iconProfile {
+        width: 20px;
+        height: 20px;
+        float: left;
+        margin-right: 10px;
+        background: url("../static/images/comm/iconProfile.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    .active .iconProfile {
+        width: 20px;
+        height: 20px;
+        float: left;
+        margin-right: 10px;
+        background: url("../static/images/comm/iconProfile_a.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    .iconEquipmanage {
+        width: 20px;
+        height: 20px;
+        float: left;
+        margin-right: 10px;
+        background: url("../static/images/comm/iconEquipmanage.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    .active .iconEquipmanage {
+        width: 20px;
+        height: 20px;
+        float: left;
+        margin-right: 10px;
+        background: url("../static/images/comm/iconEquipmanage_a.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    .iconRecord {
+        width: 20px;
+        height: 20px;
+        float: left;
+        margin-right: 10px;
+        background: url("../static/images/comm/iconRecord.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    .active .iconRecord {
+        width: 20px;
+        height: 20px;
+        float: left;
+        margin-right: 10px;
+        background: url("../static/images/comm/iconRecord_a.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    .iconStatis {
+        width: 20px;
+        height: 20px;
+        float: left;
+        margin-right: 10px;
+        background: url("../static/images/comm/iconStatis.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    .active .iconStatis {
+        width: 20px;
+        height: 20px;
+        float: left;
+        margin-right: 10px;
+        background: url("../static/images/comm/iconStatis_a.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    .iconMap {
+        width: 20px;
+        height: 20px;
+        float: left;
+        margin-right: 10px;
+        background: url("../static/images/comm/iconMap.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    .active .iconMap {
+        width: 20px;
+        height: 20px;
+        float: left;
+        margin-right: 10px;
+        background: url("../static/images/comm/iconMap_a.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    .iconRuntime {
+        width: 20px;
+        height: 20px;
+        float: left;
+        margin-right: 10px;
+        background: url("../static/images/comm/iconRuntime.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    .active .iconRuntime {
+        width: 20px;
+        height: 20px;
+        float: left;
+        margin-right: 10px;
+        background: url("../static/images/comm/iconRuntime_a.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    .modalLi span {
+        width: 20px;
+        height: 20px;
+        margin-right: 0px !important;
+    }
+
+    .modalLi s {
+        text-decoration: none;
+        font-size: 14px;
+        line-height: 30px;
+        padding-left: 10px;
+        float: right;
+    }
+
+    .alertRed {
+        position: absolute;
+        width: 100%;
+        overflow: visible;
+        display: block;
+        margin: 0 auto;
+        background: #FFF8DB;
+        padding-left: 2%;
+        padding-right: 2%;
+    }
+
+    .alertRed em {
+        position: relative;
+        top: -10px;
+        width: 139px;
+        height: 18px;
+        line-height: 18px;
+        background: red;
+        color: #fff;
+        margin: 0 auto;
+        display: block;
+        border-radius: 9px;
+        text-align: center;
+        font-size: 12px;
+    }
+
+    .yellowTri {
+        width: 9px;
+        height: 8px;
+        float: left;
+        margin-left: 15px;
+        margin-top: 4px;
+        background: url("../static/images/icon/triIcon.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    .alertRed span {
+        width: 100%;
+        height: 30px;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        text-align: center;
+        color: red;
+        font-size: 12px;
+    }
+
+    .alertRed span i {
+        float: right;
+        color: #ccc;
+        font-size: 18px;
+        line-height: 20px;
+    }
+    /deep/ .mu-item-title s {
+        width: 65px;
+        text-align: justify;
+        text-align-last: justify;
+    }
+</style>

+ 62 - 0
app/src/components/bottomTab.vue

@@ -0,0 +1,62 @@
+<template>
+    <div id="bottomTab">
+        <mu-container style="width: 100%;"  >
+            <mu-bottom-nav :value="nowTab" color="red" >
+                <mu-bottom-nav-item v-for="tab in tabs" :title="tab.name" :icon="tab.src" :to="tab.class" :key="tab.tabindex"
+                                    :value="tab.name"></mu-bottom-nav-item>
+            </mu-bottom-nav>
+        </mu-container>
+    </div>
+</template>
+
+<script>
+    export default {
+        data() {
+            return {
+                nowTab: this.curTab,
+                tabs: [
+                    {name: 'STATE', class: '/', src: 'home', tabindex: 1},
+                    {name: 'SPORT', class: 'sport', src: 'alarm', tabindex: 2},
+                    {name: 'MAP', class: 'map', src: 'map', tabindex: 3},
+                    {name: 'RADIO', class: 'radio', src: 'radio', tabindex: 4},
+                    {name: 'SET', class: 'mine', src: 'settings', tabindex: 5},
+                    //laptop
+                ]
+            }
+        },
+        props: ['curTab'],
+        methods: {},
+        watch: {
+            '$route': function (e) {
+                this.nowTab = e.meta.title;
+            }
+        },
+    }
+</script>
+
+<style scoped>
+    #bottomTab {
+        position: absolute;
+        top: 0;
+        width: 100%;
+        background: #000;
+        z-index: 9999;
+    }
+
+    .container {
+        padding: 0;
+    }
+
+
+     .mu-bottom-item-text {
+        color: #fff
+    }
+
+    .mu-bottom-item-active .mu-bottom-item-text {
+        color: red;
+    }
+    .mu-bottom-nav {
+        background: #000;
+        color: #fcfcfc;
+    }
+</style>

+ 139 - 0
app/src/components/cityPicker.vue

@@ -0,0 +1,139 @@
+<template>
+    <div>
+        <div class="demo-picker-container citypickerContainer">
+            <p @click="pickerState = true">
+                <span> {{addressProvince}} <img src="../static/images/comm/cityPicker.png" alt=""></span>
+                <span> {{addressCity}} <img src="../static/images/comm/cityPicker.png" alt=""></span>
+                <span> {{addressCounty}} <img src="../static/images/comm/cityPicker.png" alt=""></span>
+            </p>
+            <mu-slide-picker
+                    v-show="pickerState"
+                    :slots="addressSlots"
+                             :visible-item-count="7"
+                             @change="addressChange"
+                             :values="address"></mu-slide-picker>
+            <mu-button id="closeBtn" color="warning" @click="pickerState = false" v-show="pickerState">收起</mu-button>
+
+        </div>
+    </div>
+</template>
+
+<script>
+    import myaddress from '../components/address3.json'
+
+    export default {
+        data() {
+            return {
+                addressSlots: [
+                    {
+                        width: '100%',
+                        textAlign: 'right',
+                        values: Object.keys(myaddress)
+                    }, {
+                        width: '100%',
+                        textAlign: 'left',
+                        values: Object.keys(myaddress['山东省']),
+                    }, {
+                        width: '100%',
+                        textAlign: 'left',
+                        values: myaddress['山东省']['济南市'],
+                    }
+                ],
+                address: ['山东省', '济南市', '历下区'],
+                addressProvince: '山东省',
+                addressCity: '济南市',
+                addressCounty: '历下区',
+                pickerState: false,
+            }
+        },
+        created() {
+        },
+        methods: {
+            addressChange(value, index) {
+                switch (index) {
+                    case 0:
+                        this.addressProvince = value;
+                        let ProvinceName = value.substring(0, value.length - 1);
+                        this.addressSlots[1].values = address[ProvinceName];
+                        this.addressCity = address[ProvinceName][0] + '市';
+                        break;
+                    case 1:
+                        this.addressCity = value;
+                        let arrCity = myaddress[this.addressProvince][value];
+                        this.addressSlots[2].values = arrCity;
+                        this.addressCounty = arrCity[0];
+                        break;
+                    case 2:
+                        this.addressCounty = value;
+                        break
+                }
+                this.address = [this.addressProvince, this.addressCity, this.addressCounty];
+                localStorage.defaultProv =this.addressProvince.substring(0, this.addressProvince.length - 1);
+                localStorage.defaultCity =this.addressCity.substring(0, this.addressCity.length - 1);
+                localStorage.defaultArea =this.addressCounty;
+            }
+        }
+    }
+</script>
+
+<style scoped>
+    .demo-picker-container {
+        width: 100%;
+    }
+    .citypickerContainer {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+
+    .citypickerContainer p {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+
+    .citypickerContainer p span {
+        width: 94px;
+        float: left;
+        border: 1px solid #D5D5D5;
+        height: 30px;
+        line-height: 30px;
+        font-size: 12px;
+        padding-left: 10px;
+        padding-right: 10px;
+        margin-right: 3%;
+    }
+
+    .citypickerContainer p span:nth-child(3) {
+        margin-right: 0;
+        float: left;
+    }
+
+    .citypickerContainer p span img {
+        float: right;
+        width: 8px;
+        margin-top: 10px;
+    }
+    .pickerPart {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+
+    .center {
+        width: 100px;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        font-size: 12px;
+    }
+    #closeBtn {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+</style>

+ 396 - 0
app/src/components/mapDrag.vue

@@ -0,0 +1,396 @@
+<!--
+  描述:拖放地图组件,默认尺寸是 500 * 300
+  接收属性参数:
+    lat: 纬度
+    lng: 经度
+  自定义事件:
+    drag: 拖放完成事件
+  示例:
+    <mapDrag @drag="dragMap" lat="22.574405" lng="114.095388"></mapDrag>
+-->
+<template>
+    <div class="m-map" :style="{ height: curheight + 'px' }">
+        <div id="js-container" class="map">
+            <h5 style="text-align: center">{{$t("Loading data")}} ...</h5>
+        </div>
+    </div>
+</template>
+
+<script>
+    import remoteLoad from '../utils/remoteLoad.js'
+    import {MapKey, MapCityName} from '../tools/map'
+
+    let qs = require('qs');
+    import axios from 'axios';
+    import Global from '../../src/Global.js'
+
+    export default {
+        data() {
+            return {
+                searchKey: '',
+                placeSearch: null,
+                dragStatus: false,
+                AMapUI: null,
+                AMap: null,
+            }
+        },
+        props: {
+            curheight: {
+                default: 310,
+                type: Number
+            }
+        },
+        watch: {
+            searchKey() {
+                if (this.searchKey === '') {
+                    this.placeSearch.clear()
+                }
+            },
+        },
+        beforeDestroy() {
+            clearInterval(this.getPoint);
+        },
+        methods: {
+            // 实例化地图
+            initMap() {
+                let AMapUI = this.AMapUI = window.AMapUI;
+                let AMap = this.AMap = window.AMap;
+                let timeInterval = 5000;
+                let lang = localStorage.language == 'zh' ? 'zh' : 'en';
+                AMapUI.loadUI(['misc/PositionPicker'], PositionPicker => {
+                    let mapConfig = {
+                        resizeEnable: true, //是否监控地图容器尺寸变化
+                        // mapStyle: mapStyle,//地图颜色风格
+                        zoom: 16,
+                        cityName: MapCityName,
+                        lang: lang
+                    };
+                    let map = new AMap.Map('js-container', mapConfig);
+                    // 获取点位置
+                    this.getPoint(map);
+                    setInterval(this.getPoint(map), 5000);
+                    // 获取围栏信息
+                    this.getFenceInfo(map);
+
+                    // 启用工具条
+                    AMap.plugin(['AMap.ToolBar'], function () {
+                        map.addControl(new AMap.ToolBar({
+                            position: 'RB'
+                        }))
+                    });
+                })
+            },
+
+            // 实例化点标记
+            addMarker(map, lng, lat, content, imgState) {
+                let marker = new AMap.Marker({
+                    position: [lng, lat],
+                    offset: new AMap.Pixel(-13, -30),
+                    content: imgState,
+                });
+                marker.setMap(map);
+
+                // 弹窗偏移度
+                let infoWindow = new AMap.InfoWindow({offset: new AMap.Pixel(14, -20)});
+
+                marker.on('click', function (e) {
+                    infoWindow.setContent(content);
+                    infoWindow.open(map, e.target.getPosition());
+                });
+            },
+            // 获取所有的点位置
+            getPoint(map) {
+                const that = this;
+                let lnglats = [];
+                let url = '';
+                if (localStorage.userLevel == this.$t('单位管理员')) {
+                    url = headapi + 'v1/Company/GetRegionMapinfo';//获取 单个企业获取
+                } else {
+                    url = headapi + 'v1/Company/GetMapinfo';//获取
+                }
+                let param = {
+                    token: localStorage.token
+                };
+                let postdata = qs.stringify(param);
+                axios.post(url, postdata).then(function (data) {
+                    let json = data.data;
+                    if (json) {
+                        // 单个企业
+                        map.setCenter([json.Rs[0].Lng, json.Rs[0].Lat]);
+                        // todo 使用数学中心计算显示点中心
+                        localStorage.lnglats = JSON.stringify(json.Rs);
+                        if (localStorage.lnglats != JSON.stringify(lnglats)) {
+                            that.wirtePoint(map, json);
+                        }
+                        map.setFitView();
+                    }
+                }, function (response) {
+                    console.info(response);
+                })
+            },
+            // 画点
+            wirtePoint(map, json) {
+                let that = this;
+                let markers = [];
+                let curPointName = '';
+                let lnglats = json.Rs;
+                map.remove(markers);
+                // 根据状态判断图标显示颜色
+                for (var i = 0; i < lnglats.length; i++) {
+                    let imgState = '';
+                    curPointName = !lnglats[i].RegionName ? lnglats[i].ComName : lnglats[i].RegionName;
+                    switch (parseInt(lnglats[i].Detstatus)) {
+                        // 0 safe 1 warning 2 danger
+                        case 0:
+                            imgState = '<i class="green_point"></i> <span class="point_name">' + curPointName + '</span>';
+                            break;
+                        case 1:
+                            imgState = '<i class="green_point"></i> <span class="point_name">' + curPointName + '</span>';
+                            break;
+                        case 2:
+                            imgState = '<i class="red_point"></i> <span class="point_name">' + curPointName + '</span>';
+                            break;
+                    }
+
+                    var position;
+                    position = [json.Rs[i].Lng, json.Rs[i].Lat];
+
+                    let content = '';
+                        var state = '';
+                        switch (parseInt(lnglats[i].Detstatus)) {
+                            // 0 safe 1 warning 2 danger
+                            case 0:
+                                state = this.$t('normal');
+                                break;
+                            case 1:
+                                state = '<span style="color:#ffe943">' + this.$t('abnormal') + '</span>';
+                                break;
+                            case 2:
+                                state = '<span style="color:#ff0000">' + this.$t('danger') + '</span>';
+                                break;
+                        }
+
+                        let DecList = !json.Rs[i].DecList ? that.$t('not found') : json.Rs[i].DecList;
+                        content =
+                            '<span class="map_a" href="profile.html?hotelid=' + localStorage.comId + '&Regionid=' + json.Rs[i].Regionid + '">' +
+                            this.$t('region') + json.Rs[i].RegionName
+                            + '<br>' + this.$t('state') + ':' + state
+                            + '<br>' + this.$t('Detection') + ':' + json.Rs[i].DectorNum
+                            + '<br>' + this.$t('phone signal') + ':' + DecList
+                            + '<br>' + json.Rs[i].Wifiname + ':' + json.Rs[i].CamNum
+                            + '<br>' + this.$t('Suspicious') + json.Rs[i].Wifiname + ':' + json.Rs[i].DancapNum
+                            + '</span><em class="jumper" Regionid=' + json.Rs[i].Regionid + '>' +
+                            '<i class="icon iconProfile"  href="profile.html?hotelid=' + localStorage.comId + '&Regionid=' + json.Rs[i].Regionid + '"></i>' +
+                            '<i class="icon iconPlane" href="plane.html?hotelid=' + localStorage.comId + '&Regionid=' + json.Rs[i].Regionid + '"></i></em>';
+
+                    that.addMarker(map, json.Rs[i].Lng, json.Rs[i].Lat, content, imgState);
+                }
+            },
+            // 获取围栏信息
+            getFenceInfo(map) {
+                const that = this;
+                let url = headapi + 'v1/Company/GetComfencelist';
+                let param = {
+                    token: localStorage.token,
+                    comid: localStorage.comId
+                };
+                let postdata = qs.stringify(param);
+                axios.post(url, postdata).then(function (data) {
+                    let json = data.data;
+                    if (json.Code == 0) {
+                        let fence = json.Rs.Fence;
+                        let fenceArr = fence.split(",");
+                        let path = [];
+                        for (var i = 0; i < fenceArr.length; i++) {
+                            if (i % 2 == 0) {
+                                path.push([fenceArr[i], fenceArr[i + 1]]);
+                            }
+                        }
+                        let polygon = new AMap.Polygon({
+                            path: path,
+                            strokeColor: "#6496FF",
+                            strokeWeight: 6,
+                            strokeOpacity: 0.15,
+                            fillOpacity: 0.4,
+                            fillColor: '#6496FF',
+                            zIndex: 50,
+                        });
+
+                        map.add(polygon);
+
+                        // 缩放地图到合适的视野级别
+                        map.setFitView([polygon]);
+                    }
+                }, function (response) {
+                    console.info(response);
+                })
+            },
+            // 计算点中心
+            calcCenterBySingle(data) {
+                var total = data.length;
+                var lat = 0, lon = 0;
+                for (var i = 0; i < total; i++) {
+                    lat += data[i].Lat * Math.PI / 180;
+                    lon += data[i].Lng * Math.PI / 180;
+                }
+                lat /= total;
+                lon /= total;
+                return [lon * 180 / Math.PI, lat * 180 / Math.PI];
+            },
+            // 计算多点的数学圆心
+            calcCenter(data) {
+                var total = data.length;
+                var lat = 0, lon = 0;
+                for (var i = 0; i < total; i++) {
+                    lat += data[i][0] * Math.PI / 180;
+                    lon += data[i][1] * Math.PI / 180;
+                }
+                lat /= total;
+                lon /= total;
+                return [lat * 180 / Math.PI, lon * 180 / Math.PI];
+            }
+        },
+        async created() {
+            // 已载入高德地图API,则直接初始化地图
+            if (window.AMap && window.AMapUI) {
+                this.initMap()
+                // 未载入高德地图API,则先载入API再初始化
+            } else {
+                await remoteLoad(`http://webapi.amap.com/maps?v=1.3&key=${MapKey}`);
+                await remoteLoad('http://webapi.amap.com/ui/1.0/main.js');
+                this.initMap()
+            }
+        }
+    }
+</script>
+
+<style scoped>
+    .m-map {
+        width: 100%;
+        /*max-height: 317px;*/
+        /*height: 317px;*/
+        position: relative;
+    }
+
+    .m-map .map {
+        width: 100%;
+        height: 100%;
+    }
+
+    .m-map .search {
+        position: absolute;
+        top: 10px;
+        left: 10px;
+        width: 285px;
+        z-index: 1;
+    }
+
+    .m-map .search input {
+        width: 180px;
+        border: 1px solid #ccc;
+        line-height: 20px;
+        padding: 5px;
+        outline: none;
+    }
+
+    .m-map .search button {
+        line-height: 26px;
+        background: #fff;
+        border: 1px solid #ccc;
+        width: 50px;
+        text-align: center;
+    }
+
+    .m-map .result {
+        max-height: 300px;
+        overflow: auto;
+        margin-top: 10px;
+    }
+
+    /deep/ .green_point {
+        margin: 16px;
+        height: 16px;
+        width: 16px;
+        border-radius: 50% !important;
+        display: inline-block;
+        background-color: #1eff30;
+    }
+
+    /deep/ .yellow_point {
+        margin: 16px;
+        height: 16px;
+        width: 16px;
+        border-radius: 50% !important;
+        display: inline-block;
+        background-color: #f2ff24;
+    }
+
+    /deep/ .red_point {
+        margin: 16px;
+        height: 16px;
+        width: 16px;
+        border-radius: 50% !important;
+        display: inline-block;
+        transform: scale(0.5);
+        animation: bulge 2s infinite ease-in-out;
+        background-color: #ff0000;
+        animation-delay: 0s;
+    }
+
+    /deep/ .red_point::after {
+        position: absolute;
+        display: inline-block;
+        content: '';
+        height: 100%;
+        width: 100%;
+        border-radius: 50%;
+        background-color: inherit;
+        top: 0;
+        left: 0;
+        z-index: -1;
+        transform: scale(1);
+        animation: blow 2s infinite ease-in-out;
+    }
+
+    /deep/ .point_name {
+        position: relative;
+        left: -30px;
+        top: -15px;
+        width: 100%;
+        min-width: 90px;
+        padding: 1px;
+        text-align: center;
+        background-color: rgb(26, 34, 41);
+        border: 1px solid #060D16;
+        border-radius: 10px !important;
+        color: #eeeeee;
+        display: block;
+        overflow: hidden;
+        opacity: 0.9;
+        font-size: 12px;
+    }
+
+
+    @keyframes bulge {
+        50% {
+            transform: scale(1);
+        }
+    }
+
+
+    @keyframes blow {
+        25% {
+            opacity: 0.4;
+        }
+        50% {
+            opacity: 0.1;
+        }
+        90% {
+            opacity: 0;
+        }
+        100% {
+            transform: scale(9);
+            opacity: 0;
+        }
+    }
+</style>

+ 581 - 0
app/src/components/mapPage.vue

@@ -0,0 +1,581 @@
+<!--
+  描述:拖放地图组件,默认尺寸是 500 * 300
+  接收属性参数:
+    lat: 纬度
+    lng: 经度
+  自定义事件:
+    drag: 拖放完成事件
+  示例:
+    <mapDrag @drag="dragMap" lat="22.574405" lng="114.095388"></mapDrag>
+-->
+<template>
+    <div class="m-map" :style="{ height: curheight + 'px' }">
+        <div id="js-containerPage" class="map">
+            <h5 style="text-align: center">{{$t("Loading data")}} ...</h5>
+        </div>
+        <mu-bottom-sheet :open.sync="detailState">
+            <div class="detailContianer">
+                <h5>
+                    <span class="name">{{row.RegionName}}</span>
+                </h5>
+                <ul>
+                    <li class="lt">{{$t("state")}}:<em
+                            :class="{'red':row.Detstatus != '正常','green':row.Detstatus == '正常'}">{{row.Detstatus}}</em>
+                    </li>
+                    <li class="lt">{{$t("Detection equipment")}}:{{row.DectorNum}} {{$t("pcs")}}</li>
+                    <li class="lt">{{$t("phone signal")}}:{{row.DecList}}</li>
+                    <li class="lt">{{$t("Camera")}}:{{row.CamNum}} {{$t("pcs")}}</li>
+                    <li class="lt">{{$t("Suspicious camera")}}:{{row.DancapNum}} {{$t("pcs")}}</li>
+                </ul>
+                <div class="btnContainer">
+                    <button class="goPlane" @click="goPlane">{{$t("Plane details")}}</button>
+                    <button class="goProfile" @click="goProfile">{{$t("Company details")}}</button>
+                </div>
+            </div>
+        </mu-bottom-sheet>
+    </div>
+</template>
+
+<script>
+    import remoteLoad from '../utils/remoteLoad.js'
+    import {MapKey, MapCityName} from '../tools/map'
+
+    let qs = require('qs');
+    import axios from 'axios';
+    import Global from '../../src/Global.js'
+
+    export default {
+        data() {
+            return {
+                searchKey: '',
+                placeSearch: null,
+                dragStatus: false,
+                AMapUI: null,
+                AMap: null,
+                ComId: 0,
+                detailState: false,
+                row: {
+                    RegionName: '',
+                    Detstatus: '',
+                    DectorNum: '',
+                    CamNum: '',
+                    DecList: '',
+                    DancapNum: '',
+                    Regionid: '',
+                },
+            }
+        },
+        props: {
+            curheight: {
+                default: 310,
+                type: Number
+            }
+        },
+        watch: {
+            searchKey() {
+                if (this.searchKey === '') {
+                    this.placeSearch.clear()
+                }
+            },
+        },
+        beforeDestroy() {
+            clearInterval(this.getPoint);
+        },
+        methods: {
+            goPlane() {
+                let that = this;
+                that.$router.push({path: '/plane', query: {Regionid: that.row.Regionid, ComId: that.ComId}});
+            },
+            goProfile() {
+                let that = this;
+                that.$router.push({path: '/profile', query: {Regionid: that.row.Regionid, ComId: that.ComId}});
+            },
+            // 实例化地图
+            initMap() {
+                let AMapUI = this.AMapUI = window.AMapUI;
+                let AMap = this.AMap = window.AMap;
+                let timeInterval = 5000;
+                let lang = localStorage.language == 'zh' ? 'zh' : 'en';
+                AMapUI.loadUI(['misc/PositionPicker'], PositionPicker => {
+                    let mapConfig = {
+                        resizeEnable: true, //是否监控地图容器尺寸变化
+                        // mapStyle: mapStyle,//地图颜色风格
+                        zoom: 16,
+                        cityName: MapCityName,
+                        lang: lang
+                    };
+                    let map = new AMap.Map('js-containerPage', mapConfig);
+                    // 获取点位置
+                    this.getPoint(map);
+
+                    setInterval(this.getPoint(map), 5000);
+                    // 获取围栏信息
+                    this.getFenceInfo(map);
+                    // 启用工具条
+                    AMap.plugin(['AMap.ToolBar'], function () {
+                        map.addControl(new AMap.ToolBar({
+                            position: 'RB'
+                        }))
+                    });
+                })
+            },
+
+            // 实例化点标记
+            addMarker(map, lng, lat, content, imgState, row) {
+                let that = this;
+                let marker = new AMap.Marker({
+                    position: [lng, lat],
+                    offset: new AMap.Pixel(-13, -30),
+                    content: imgState,
+                });
+                marker.setMap(map);
+
+                // 弹窗偏移度
+                let infoWindow = new AMap.InfoWindow({offset: new AMap.Pixel(14, -20)});
+                marker.on('click', function (e) {
+                    // 自定义的弹窗
+                        that.detailState = true;
+                        that.row.RegionName = row.RegionName;
+                        that.row.Detstatus = row.Detstatus == 1 ? that.$t('normal') : that.$t('abnormal');
+                        that.row.DecList = !row.DecList ? that.$t('Not found') : row.DecList;
+                        that.row.DectorNum = row.DectorNum;
+                        that.row.CamNum = row.CamNum;
+                        that.row.DancapNum = row.DancapNum;
+                        that.row.Regionid = row.Regionid;
+                        // 原生的弹窗
+                        // infoWindow.setContent(content);
+                        // infoWindow.open(map, e.target.getPosition());
+                });
+            },
+            // 获取所有的点位置
+            getPoint(map) {
+                const that = this;
+                let lnglats = [];
+                let url = '';
+                if (localStorage.userLevel == '单位管理员') {
+                    url = headapi + 'v1/Company/GetRegionMapinfo';//获取 单个企业获取
+                } else {
+                    url = headapi + 'v1/Company/GetMapinfo';//获取
+                }
+                let param = {
+                    token: localStorage.token
+                };
+                let postdata = qs.stringify(param);
+                axios.post(url, postdata).then(function (data) {
+                    let json = data.data;
+                    if (json.Rs) {
+                        map.setCenter([json.Rs[0].Lng, json.Rs[0].Lat]);
+                        // todo 使用数学中心计算显示点中心
+                        if (localStorage.lnglats != JSON.stringify(lnglats)) {
+                            that.wirtePoint(map, json);
+                        }
+                        localStorage.lnglats = JSON.stringify(json.Rs)
+                    }
+                    map.setFitView();
+                }, function (response) {
+                    console.info(response);
+                })
+            },
+            // 画点
+            wirtePoint(map, json) {
+                let that = this;
+                let markers = [];
+                let curPointName = '';
+                let lnglats = json.Rs;
+                map.remove(markers);
+                // 根据状态判断图标显示颜色
+                for (var i = 0; i < lnglats.length; i++) {
+                    let imgState = '';
+                    curPointName = !lnglats[i].RegionName ? lnglats[i].ComName : lnglats[i].RegionName;
+                    switch (parseInt(lnglats[i].Detstatus)) {
+                        // 0 safe 1 warning 2 danger
+                        case 0:
+                            imgState = '<i class="green_point"></i> <span class="point_name">' + curPointName + '</span>';
+                            break;
+                        case 1:
+                            imgState = '<i class="green_point"></i> <span class="point_name">' + curPointName + '</span>';
+                            break;
+                        case 2:
+                            imgState = '<i class="red_point"></i> <span class="point_name">' + curPointName + '</span>';
+                            break;
+                    }
+                    var position;
+                    position = [json.Rs[i].Lng, json.Rs[i].Lat];
+
+                    let content = '';
+                    if (localStorage.userLevel == '单位管理员') {
+                        let state = json.Rs[i].Detstatus == 1 ? this.$t("normal") : '<span style="color:#ff0000">this.$t("abnormal")</span>';
+                        let DecList = !json.Rs[i].DecList ? this.$t("Not found") : json.Rs[i].DecList;
+                        content =
+                            '<span class="map_a" href="profile.html?hotelid=' + localStorage.comId + '&Regionid=' + json.Rs[i].Regionid + '">' +
+                            +this.$t("region") + ':' + json.Rs[i].RegionName
+                            + '<br>' + this.$t("state") + ':' + state
+                            + '<br>' + this.$t("Detection equipment") + ':' + json.Rs[i].DectorNum
+                            + '<br>' + this.$t("phone signal") + ':' + DecList
+                            + '<br>' + json.Rs[i].Wifiname + ':' + json.Rs[i].CamNum
+                            + '<br>可疑' + json.Rs[i].Wifiname + ':' + json.Rs[i].DancapNum
+                            + '</span><em class="jumper" Regionid=' + json.Rs[i].Regionid + '>' +
+                            '<i class="icon iconProfile"  href="profile.html?hotelid=' + localStorage.comId + '&Regionid=' + json.Rs[i].Regionid + '"></i>' +
+                            '<i class="icon iconPlane" href="plane.html?hotelid=' + localStorage.comId + '&Regionid=' + json.Rs[i].Regionid + '"></i></em>';
+                    } else {
+                        let state = json.Rs[i][3] == 1 ? '正常' : '<span style="color:#ff0000">异常</span>';
+                        let macAddr = !json.Rs[i][7] ? '无' : json.Rs[i][7];
+                        content =
+                            '<span class="map_a" href="profile.html?hotelid=' + json.Rs[i][8] + '">' +
+                            '企业:' + json.Rs[i][5]
+                            + '<br>' + this.$t("state") + ':' + state
+                            + '<br>' + this.$t("Detection equipment") + ':' + json.Rs[i][4]
+                            + '<br>' + this.$t("phone signal") + ':' + json.Rs[i][2]
+                            + '<br>可疑' + json.Rs[i][9] + ':' + json.Rs[i][6]
+                            + '<br>可疑MAC地址:' + macAddr
+                            + '</span><em class="jumper" Regionid=' + json.Rs[i][9] + '>' +
+                            '<i class="icon iconProfile"  href="profile.html?hotelid=' + json.Rs[i][8] + '"></i>' +
+                            '<i class="icon iconPlane" href="plane.html?hotelid=' + json.Rs[i][8] + '"></i></em>';
+                    }
+                    that.addMarker(map, json.Rs[i].Lng, json.Rs[i].Lat, content, imgState, json.Rs[i]);
+                }
+            },
+            // 给总管理员的画点
+            wirtePointForAdmin(map, json) {
+                let that = this;
+                let markers = [];
+                map.remove(markers);
+                // 根据状态判断图标显示颜色
+                for (var i = 0; i < json.length; i++) {
+                    let imgState = '';
+                    switch (parseInt(json[i][3])) {
+                        case 1:
+                            imgState = '<i class="green_point"></i> <span class="point_name">' + json[i][5] + '</span>';
+                            break;
+                        case 2:
+                            imgState = '<i class="yellow_point"></i> <span class="point_name">' + json[i][5] + '</span>';
+                            break;
+                        case 0:
+                            imgState = '<i class="red_point"></i> <span class="point_name">' + json[i][5] + '</span>';
+                            break
+                    }
+                    var position = json[i];
+                    let content = '';
+                    let state = json[i][3] == 1 ? this.$t('normal') : '<span style="color:#ff0000">' + this.$t('abnormal') + '</span>';
+                    let macAddr = !json[i][7] ? this.$t('nothing') : json[i][7];
+                    content = '<span class="map_a" href="profile.html?hotelid=' + json[i][8] + '">' +
+                        '企业:' + json[i][5]
+                        + '<br>状态:' + state
+                        + '<br>探测设备:' + json[i][4]
+                        + '<br>' + json[i][9] + ':' + json[i][2]
+                        + '<br>可疑' + json[i][9] + ':' + json[i][6]
+                        + '<br>可疑MAC地址:' + macAddr
+                        + '</span><em class="jumper" Regionid=' + json[i][9] + '>' +
+                        '<i class="icon iconProfile"  href="profile.html?hotelid=' + json[i][8] + '"></i>' +
+                        '<i class="icon iconPlane" href="plane.html?hotelid=' + json[i][8] + '"></i></em>';
+                    that.addMarker(map, json[i][0], json[i][1], content, imgState,json[i]);
+                }
+            },
+            // 获取围栏信息
+            getFenceInfo(map) {
+                const that = this;
+                let url = headapi + 'v1/Company/GetComfencelist';
+                let param = {
+                    token: localStorage.token,
+                    comid: localStorage.comId
+                };
+                let postdata = qs.stringify(param);
+                axios.post(url, postdata).then(function (data) {
+                    let json = data.data;
+                    if (json.Code == 0) {
+                        that.ComId = json.Rs.ComId;
+                        let fence = json.Rs.Fence;
+                        let fenceArr = fence.split(",");
+                        let path = [];
+                        for (var i = 0; i < fenceArr.length; i++) {
+                            if (i % 2 == 0) {
+                                path.push([fenceArr[i], fenceArr[i + 1]]);
+                            }
+                        }
+                        let polygon = new AMap.Polygon({
+                            path: path,
+                            strokeColor: "#6496FF",
+                            strokeWeight: 6,
+                            strokeOpacity: 0.15,
+                            fillOpacity: 0.4,
+                            fillColor: '#6496FF',
+                            zIndex: 50,
+                        });
+
+                        map.add(polygon);
+
+                        // 缩放地图到合适的视野级别
+                        map.setFitView([polygon]);
+                    }
+                }, function (response) {
+                    console.info(response);
+                })
+            },
+            // 计算点中心
+            calcCenterBySingle(data) {
+                var total = data.length;
+                var lat = 0, lon = 0;
+                for (var i = 0; i < total; i++) {
+                    lat += data[i].Lat * Math.PI / 180;
+                    lon += data[i].Lng * Math.PI / 180;
+                }
+                lat /= total;
+                lon /= total;
+                return [lon * 180 / Math.PI, lat * 180 / Math.PI];
+            },
+            // 计算多点的数学圆心
+            calcCenter(data) {
+                var total = data.length;
+                var lat = 0, lon = 0;
+                for (var i = 0; i < total; i++) {
+                    lat += data[i][0] * Math.PI / 180;
+                    lon += data[i][1] * Math.PI / 180;
+                }
+                lat /= total;
+                lon /= total;
+                return [lat * 180 / Math.PI, lon * 180 / Math.PI];
+            }
+        },
+        async created() {
+            // 已载入高德地图API,则直接初始化地图
+            if (window.AMap && window.AMapUI) {
+                this.initMap()
+                // 未载入高德地图API,则先载入API再初始化
+            } else {
+                await remoteLoad(`http://webapi.amap.com/maps?v=1.3&key=${MapKey}`);
+                await remoteLoad('http://webapi.amap.com/ui/1.0/main.js');
+                this.initMap()
+            }
+        }
+    }
+</script>
+
+<style scoped>
+    .m-map {
+        width: 100%;
+        /*max-height: 317px;*/
+        /*height: 317px;*/
+        position: relative;
+    }
+
+    .m-map .map {
+        width: 100%;
+        height: 100%;
+    }
+
+    .m-map .search {
+        position: absolute;
+        top: 10px;
+        left: 10px;
+        width: 285px;
+        z-index: 1;
+    }
+
+    .m-map .search input {
+        width: 180px;
+        border: 1px solid #ccc;
+        line-height: 20px;
+        padding: 5px;
+        outline: none;
+    }
+
+    .m-map .search button {
+        line-height: 26px;
+        background: #fff;
+        border: 1px solid #ccc;
+        width: 50px;
+        text-align: center;
+    }
+
+    .m-map .result {
+        max-height: 300px;
+        overflow: auto;
+        margin-top: 10px;
+    }
+
+    /deep/ .green_point {
+        margin: 16px;
+        height: 16px;
+        width: 16px;
+        border-radius: 50% !important;
+        display: inline-block;
+        background-color: #1eff30;
+    }
+
+    /deep/ .yellow_point {
+        margin: 16px;
+        height: 16px;
+        width: 16px;
+        border-radius: 50% !important;
+        display: inline-block;
+        background-color: #f2ff24;
+    }
+
+    /deep/ .red_point {
+        margin: 16px;
+        height: 16px;
+        width: 16px;
+        border-radius: 50% !important;
+        display: inline-block;
+        transform: scale(0.5);
+        animation: bulge 2s infinite ease-in-out;
+        background-color: #ff0000;
+        animation-delay: 0s;
+    }
+
+    /deep/ .red_point::after {
+        position: absolute;
+        display: inline-block;
+        content: '';
+        height: 100%;
+        width: 100%;
+        border-radius: 50%;
+        background-color: inherit;
+        top: 0;
+        left: 0;
+        z-index: -1;
+        transform: scale(1);
+        animation: blow 2s infinite ease-in-out;
+    }
+
+    /deep/ .point_name {
+        position: relative;
+        left: -30px;
+        top: -15px;
+        width: 100%;
+        min-width: 90px;
+        padding: 1px;
+        text-align: center;
+        background-color: rgb(26, 34, 41);
+        border: 1px solid #060D16;
+        border-radius: 10px !important;
+        color: #eeeeee;
+        display: block;
+        overflow: hidden;
+        opacity: 0.9;
+        font-size: 12px;
+    }
+
+    .red {
+        color: red;
+    }
+
+    .green {
+        color: greenyellow;
+    }
+
+    @keyframes bulge {
+        50% {
+            transform: scale(1);
+        }
+    }
+
+
+    @keyframes blow {
+        25% {
+            opacity: 0.4;
+        }
+        50% {
+            opacity: 0.1;
+        }
+        90% {
+            opacity: 0;
+        }
+        100% {
+            transform: scale(9);
+            opacity: 0;
+        }
+    }
+
+    .detailContianer {
+        position: absolute;
+        bottom: 85px;
+        left: 0;
+        right: 0;
+        width: 96%;
+        height: 257px;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        background: #fff;
+        box-shadow: #333333 0 0 7px;
+        z-index: 9999;
+        border-radius: 8px;
+        padding: 18px 10px;
+    }
+
+    .detailContianer h5 {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        font-size: 16px;
+    }
+
+    .detailContianer h5 .name {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        text-align: center;
+    }
+
+    .detailContianer h5 .state {
+        float: right;
+    }
+
+    .detailContianer ul {
+        width: 88%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        margin-top: 15px;
+        margin-bottom: 10px;
+        border-top: 1px solid #EBEBEB;
+        border-bottom: 1px solid #EBEBEB;
+        padding-top: 10px;
+        padding-bottom: 10px;
+    }
+
+    .detailContianer li {
+        width: 100%;
+        float: left;
+        margin-bottom: 3px;
+    }
+
+    .detailContianer .rt {
+        text-align: right;
+    }
+
+    .detailContianer .btnContainer {
+        width: 88%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+
+    .btnContainer button {
+        width: 120px;
+        height: 32px;
+        line-height: 32px;
+        text-align: center;
+        border-radius: 250px;
+        outline: none;
+        border: none;
+    }
+
+    .btnContainer .goPlane {
+        border: 1px solid #FFCC00;
+        background: #fff;
+    }
+
+    .btnContainer .goProfile {
+        border: 1px solid #FFCC00;
+        background: #FFCC00;
+        float: right;
+    }
+
+    /deep/ .amap-zoomcontrol {
+        bottom: 10px !important;
+    }
+</style>

+ 218 - 0
app/src/components/statischart.vue

@@ -0,0 +1,218 @@
+<template>
+    <div id="statischart">
+        <div class="time">
+    <span @click="changeTime(1)">
+    {{bt}}
+    </span>
+            <span @click="changeTime(2)">
+    {{et}}
+    </span>
+            <mu-select label="" v-model="selectVal">
+                <mu-option v-for="option in options" :key="option.optionsVal" :label="option.name"
+                           :value="option.optionsVal"></mu-option>
+            </mu-select>
+            <mu-button color="warning" @click="getNewChart" small>{{$t('search')}}</mu-button>
+        </div>
+
+        <Line-example
+                :width="390"
+                :height="200"
+                :dataLabels="dataLabels"
+                :datadatasets="datadatasets"
+        />
+
+        <mu-bottom-sheet :open.sync="open">
+            <mu-flex justify-content="between" align-items="end" wrap="wrap">
+                <mu-paper :z-depth="1" class="demo-date-picker">
+                    <mu-date-picker :date.sync="date" color="#FFA200" :date-time-format="enDateFormat"
+                                    @change="confirmDay"></mu-date-picker>
+                </mu-paper>
+            </mu-flex>
+        </mu-bottom-sheet>
+    </div>
+</template>
+<script>
+    import Global from '../Global'
+    import Vue from 'vue'
+    import LineExample from './LineExample'
+
+    let qs = require('qs');
+    import axios from 'axios';
+
+    const enDateFormat = {
+        formatDisplay(date) {
+            return `${dayList[date.getDay()]}, ${monthList[date.getMonth()]} ${date.getDate()}`;
+        },
+        formatMonth(date) {
+            return `${monthLongList[date.getMonth()]} ${date.getFullYear()}`;
+        },
+        getWeekDayArray(firstDayOfWeek) {
+            let beforeArray = [];
+            let afterArray = [];
+            for (let i = 0; i < dayAbbreviation.length; i++) {
+                if (i < firstDayOfWeek) {
+                    afterArray.push(dayAbbreviation[i]);
+                } else {
+                    beforeArray.push(dayAbbreviation[i]);
+                }
+            }
+            return beforeArray.concat(afterArray);
+        },
+        getMonthList() {
+            return monthList;
+        }
+    };
+    export default {
+        data() {
+            return {
+                enDateFormat,
+                bt: globaltime2StringNoMin(new Date() - 3 * 24 * 3600 * 1000),//test
+                et: globaltime2StringNoMin(new Date()),
+                date: new Date(),
+                pickerValue: '',
+                open: false,
+                selectTime: 0,
+                selectVal: 1,
+                pickerItem: 0,
+                dataLabels: [],
+                datadatasets: [],
+                options: [
+                    {name: this.$t('Total detection record'), optionsVal: 1},
+                ]
+            }
+        },
+        mounted() {
+            this.getNewChart()
+        },
+        methods: {
+            changeTime(val) {
+                this.open = true;
+                let curVal = val == 1 ? new Date(this.bt) : new Date(this.et);
+                this.selectTime = val;
+                this.date = curVal;
+            },
+            confirmDay(date) {
+                if (this.selectTime == 1) {
+                    this.bt = globaltime2StringNoMin(date);
+                } else {
+                    this.et = globaltime2StringNoMin(date);
+                }
+                this.open = false;
+            },
+            getNewChart() {
+                const that = this;
+                let url = headapi + 'v1/Detector/GetCtNumStatisticByday';
+                let param = {
+                    token: localStorage.token,
+                    bt: that.bt + ' 00:00:00',
+                    et: that.et + ' 23:59:59',
+                    dailytype: that.selectVal,
+                };
+                let postdata = qs.stringify(param);
+                axios.post(url, postdata).then(function (data) {
+                    let json = data.data;
+                    if (json.Code == 0) {
+                        let detectorArr = json.Rs;
+                        that.dataLabels = detectorArr.RsX;
+                        that.datadatasets = detectorArr.RsY;
+                    } else {
+                        if (!localStorage.token) { //未登录状态
+                            console.log(json.Memo);
+                        } else { //已登录状态
+                            that.Toast(that.TransMemo(json.Memo));
+                        }
+                    }
+                }, function (response) {
+                    console.info(response);
+                });
+            },
+        },
+        components: {
+            LineExample
+        },
+    }
+</script>
+
+<style scoped>
+    .container {
+        width: 100%;
+        height: 230px;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+
+    #statischart {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        margin-bottom: 10px;
+    }
+
+    .time {
+        width: 100%;
+        height: 48px;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        padding-left: 2%;
+        padding-right: 2%;
+        padding-top: 15px;
+        margin-bottom: 15px;
+        border-bottom: 1px solid #f2f2f2;
+    }
+
+    .time span {
+        width: 80px;
+        height: 27px;
+        float: left;
+        border: 1px solid #DEDEDE;
+        text-align: center;
+        line-height: 27px;
+        font-size: 12px;
+        margin-right: 10px;
+    }
+
+    .time select {
+        width: 96px;
+        height: 27px;
+        float: left;
+        border: 1px solid #DEDEDE;
+        text-align: center;
+        line-height: 27px;
+        font-size: 12px;
+        margin-right: 10px;
+    }
+
+    .time .mint-button {
+        height: 27px;
+        border-radius: 0;
+    }
+
+    .mu-input {
+        width: 100px;
+        float: left;
+        padding: 0;
+        margin: 0;
+    }
+
+    /deep/ .mu-select-input {
+        font-size: 12px !important;
+    }
+
+    .mu-button {
+        float: left;
+        min-width: 66px;
+    }
+
+    .demo-date-picker {
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+
+    /deep/ .mu-button-wrapper {
+        color: #000 !important;
+    }
+</style>

+ 152 - 0
app/src/components/statischart2.vue

@@ -0,0 +1,152 @@
+<template>
+    <div class="container">
+        <div class="Chart">
+            <div class="time">
+                <span @click="changeTime(1)">
+                    {{bt}}
+                </span>
+                <span @click="changeTime(2)">
+                    {{et}}
+                </span>
+                <select name="" id="" v-model="selectVal">
+                    <option value="1">总探测记录</option>
+                </select>
+                <mt-button size="small" type="primary" @click="getNewChart">查询</mt-button>
+            </div>
+            <Line-example
+                    :width="414"
+                    :height="200"
+                    :dataLabels="dataLabels"
+                    :datadatasets="datadatasets"
+            />
+        </div>
+        <mt-datetime-picker
+                ref="picker"
+                type="date"
+                v-model="pickerValue"
+                @confirm="handleConfirm"
+        >
+        </mt-datetime-picker>
+    </div>
+</template>
+
+<script>
+    import {DatetimePicker} from 'mint-ui';
+    import {Toast} from 'mint-ui';
+    import LineExample from './LineExample'
+    import Global from '../Global'
+    import Vue from 'vue'
+
+    let qs = require('qs');
+    import axios from 'axios';
+
+    Vue.component(DatetimePicker.name, DatetimePicker);
+    export default {
+        data() {
+            return {
+                bt: globaltime2StringNoMin(new Date() - 3 * 24 * 3600 * 1000),
+                et: globaltime2StringNoMin(new Date()),
+                pickerValue: '',
+                selectVal: 1,
+                pickerItem: 0,
+                dataLabels: [],
+                datadatasets: [],
+            }
+        },
+        mounted() {
+            this.getNewChart();
+        },
+        methods: {
+            changeTime(val) {
+                this.$refs.picker.open();
+                this.pickerValue = val == 1 ? this.bt : this.et;
+                this.pickerItem = val;
+            },
+            handleConfirm(e) {
+                let that = this;
+                console.log(this.pickerItem);
+                if (this.pickerItem == 1) {
+                    that.bt = globaltime2String(e)
+                } else {
+                    that.et = globaltime2String(e)
+                }
+                this.$refs.picker.close();
+            },
+            // 查询
+            getNewChart() {
+                const that = this;
+                let url = headapi + 'v1/Detector/GetCtNumStatisticByday';
+                let param = {
+                    token: localStorage.token,
+                    bt: that.bt + ' 00:00:00',
+                    et: that.et + ' 23:59:59',
+                    dailytype: that.selectVal,
+                };
+                let postdata = qs.stringify(param);
+                axios.post(url, postdata).then(function (data) {
+                    let json = data.data;
+                    if (json.Code == 0) {
+                        let detectorArr = json.Rs;
+                        that.dataLabels = detectorArr.RsX;
+                        that.datadatasets = detectorArr.RsY;
+                    } else {
+                        // Toast(json.memo);
+                        console.log(json.Memo);
+                    }
+                }, function (response) {
+                    console.info(response);
+                });
+            }
+        },
+        components: {
+            LineExample
+        },
+    }
+</script>
+
+<style>
+    .container {
+        width: 100%;
+        height: 230px;
+        margin: 0 auto;
+    }
+
+    .time {
+        width: 96%;
+        height: 48px;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        padding-left: 2%;
+        padding-right: 2%;
+        padding-top: 15px;
+        border-bottom: 1px solid #f2f2f2;
+    }
+
+    .time span {
+        width: 96px;
+        height: 27px;
+        float: left;
+        border: 1px solid #DEDEDE;
+        text-align: center;
+        line-height: 27px;
+        font-size: 12px;
+        margin-right: 10px;
+    }
+
+    .time select {
+        width: 96px;
+        height: 27px;
+        float: left;
+        border: 1px solid #DEDEDE;
+        text-align: center;
+        line-height: 27px;
+        font-size: 12px;
+        margin-right: 10px;
+    }
+
+    .time .mint-button {
+        height: 27px;
+        border-radius: 0;
+    }
+</style>

+ 370 - 0
app/src/components/timePart.vue

@@ -0,0 +1,370 @@
+<template>
+    <div class="timePart">
+        <div class="lt">
+            <h5>ACTIVE RANGE </h5>
+            <P>{{ time }}</P>
+            <em>step
+                <i class="number">
+                    {{ step }}
+                </i>
+                CK
+                <i class="number">
+                    {{ step }}
+                </i>
+                CALORIE
+                <i class="number">
+                    {{ calorie }}
+                </i>
+                oxygen
+                <i class="number">
+                    {{ calorie }}
+                </i>
+            </em>
+            <span>{{ percent }}%</span>
+            <ul>
+                <li>
+                    <em>STOP</em>
+                    <mu-scale-transition>
+                        <i v-show="i == 1"></i>
+                    </mu-scale-transition>
+                </li>
+                <li>
+                    <em>SLOW</em>
+                    <mu-scale-transition>
+                        <i v-show="i == 2"></i>
+                    </mu-scale-transition>
+                </li>
+                <li>
+                    <em>NORMAL</em>
+                    <mu-scale-transition>
+                        <i v-show="i == 3"></i>
+                    </mu-scale-transition>
+                </li>
+                <li>
+                    <em>RACING</em>
+                    <mu-scale-transition>
+                        <i v-show="i == 4"></i>
+                    </mu-scale-transition>
+                </li>
+            </ul>
+        </div>
+        <div class="rt">
+            <div class="top">
+                <h5>INTERNAL</h5>
+                <mu-scale-transition>
+                    <i v-show="type"></i>
+                </mu-scale-transition>
+            </div>
+            <div class="middle">
+                <span>MAIN POWER SUPPLE</span>
+            </div>
+            <div class="bottom">
+                <h5>EXTERNAL</h5>
+                <mu-scale-transition>
+                    <i v-show="!type"></i>
+                </mu-scale-transition>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+    import global from '../Global'
+    import '../libs/rem';
+
+    export default {
+        data() {
+            return {
+                i: 1,
+                type: true,
+                time: '8:88:88',
+                step: '4302',
+                calorie: '763',
+                percent: '00',
+            }
+        },
+        mounted() {
+            this.mockDate();
+            this.timer = setInterval(() => {
+                this.mockDate();
+            }, 1000);
+        },
+        beforeDestroy() {
+            clearInterval(this.timer);
+        },
+        methods: {
+            mockDate() {
+                this.time = globalcurrentTime();
+                this.percent = (Math.random(0, 100) * 100).toFixed(0);
+                // this.type = !this.type;
+                this.i = parseInt(Math.random(1, 3) * 4 + 1);
+                console.log(this.i);
+            }
+        }
+    }
+</script>
+
+<style scoped>
+    @font-face {
+        font-family: UnidreamLED;
+        src: url('../assets/font/UnidreamLED.ttf');
+    }
+
+    ul, li {
+        list-style: none;
+        margin: 0;
+        padding: 0;
+    }
+
+    em, s, i {
+        font-style: normal;
+        text-decoration: none;
+    }
+
+    .timePart {
+        width: 100%;
+        height: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+
+    }
+
+    .timePart .lt {
+        width: 70%;
+        overflow: hidden;
+        float: left;
+    }
+
+    .timePart .rt {
+        width: 28%;
+        overflow: hidden;
+        float: right;
+    }
+
+    .timePart .lt h5 {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        font-size: 1rem;
+        font-weight: normal;
+        color: red;
+        text-align: left;
+    }
+
+    .timePart .lt s {
+        font-size: 0.2rem;
+    }
+
+    .timePart .lt p {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        font-size: 1.4rem;
+        color: red;
+        text-align: left;
+        font-family: UniDreamLED;
+        letter-spacing: 3px;
+    }
+
+    .timePart .lt > em {
+        width: 100%;
+        height: 1rem;
+        line-height: 1rem;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        font-size: 0.4rem;
+        color: red;
+        text-align: left;
+        letter-spacing: 3px;
+        margin-top: 0;
+        margin-bottom: 0;
+    }
+
+    .timePart .lt em div {
+        float: right;
+        text-align: right;
+    }
+
+    .lt .number {
+        font-family: UniDreamLED;
+        font-size: 0.45rem;
+    }
+
+    .timePart .lt span {
+        position: relative;
+        top: -4.2rem;
+        width: 100%;
+        height: 0.01rem;
+        overflow: visible;
+        display: block;
+        margin: 0 auto;
+        font-size: 1rem;
+        text-align: right;
+        font-family: UniDreamLED;
+    }
+
+    .timePart .lt ul {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        margin-top: 0.2rem;
+        color: #fff;
+    }
+
+    .timePart .lt ul em {
+        color: #fff;
+        text-align: center;
+    }
+
+    .timePart .lt li {
+        width: 23%;
+        height: 1.5rem;
+        background: red;
+        color: #fff;
+        text-align: center;
+        float: left;
+        margin-right: 0.2rem;
+        font-size: 0.4rem;
+        padding-top: 0.2rem;
+        padding-bottom: 0.2rem;
+    }
+
+    .timePart .lt li:nth-child(4) {
+        margin-right: 0;
+    }
+
+    .timePart .lt li i {
+        width: 90%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        margin-top: 0.2rem;
+        height: 0.2rem;
+        background: #fff;
+        color: #fff;
+    }
+
+    .rt .top {
+        width: 100%;
+        height: 2rem;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        background: red;
+        color: #fff;
+    }
+
+    .rt .top h5 {
+        width: 100%;
+        height: 2rem;
+        line-height: 2rem;
+        font-size: 0.7rem;
+        margin: 0;
+        float: left;
+        text-align: left;
+        padding-left: 0.2rem;
+    }
+
+    .rt .top s {
+        float: left;
+        font-size: 0.7rem;
+        text-align: left;
+        padding-left: 1.2rem;
+    }
+
+    .rt .top i {
+        position: relative;
+        top: -1.5rem;
+        right: 10px;
+        float: right;
+        width: 15px;
+        height: 1.2rem;
+        background: linear-gradient(135deg, #fff 25%, red 0,
+        red 50%, #fff 0,
+        #fff 75%, red 0);
+        background-size: 12px 12px;
+    }
+
+    .rt .middle {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        margin-top: 0.5rem;
+        margin-bottom: 0.5rem;
+        background: red;
+        color: #fff;
+        padding-bottom: 3px;
+    }
+
+    .middle span {
+        width: 100%;
+        height: 1.3rem;
+        line-height: 1.3rem;
+        margin: 0 auto;
+        display: block;
+        font-size: 0.4rem;
+        text-align: left;
+        padding-left: 10px;
+    }
+
+    .middle s {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        font-size: 12px;
+    }
+
+    .rt .bottom {
+        width: 100%;
+        height: 2rem;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        background: red;
+        color: #fff;
+        padding-top: 3px;
+        padding-bottom: 3px;
+    }
+
+    .rt .bottom h5 {
+        width: 100%;
+        height: 2rem;
+        line-height: 2rem;
+        font-size: 0.7rem;
+        margin: 0;
+        float: left;
+        text-align: left;
+        padding-left: 0.2rem;
+    }
+
+    .rt .bottom s {
+        float: left;
+        font-size: 12px;
+        text-align: left;
+        padding-left: 20px;
+    }
+
+    .rt .bottom s {
+        font-size: 12px;
+    }
+
+    .rt .bottom i {
+        position: relative;
+        top: -1.6rem;
+        right: 10px;
+        float: right;
+        width: 15px;
+        height: 1.2rem;
+        background: linear-gradient(135deg, #fff 25%, red 0,
+        red 50%, #fff 0,
+        #fff 75%, red 0);
+        background-size: 12px 12px;
+    }
+</style>

+ 134 - 0
app/src/language/en-US.js

@@ -0,0 +1,134 @@
+export default {
+    "whiteList": "whiteList",
+    "search": "search",
+    "index": "index",
+    "keyword": "keyword",
+    "order": "order",
+    "detect tag": "detect tag",
+    "detect local": "detect local",
+    "be detect MAC": "be detect MAC",
+    "sign time": "sign time",
+    "operator": "operator",
+    "memo": "memo",
+    "control": "control",
+    "close": "close",
+    "remove white": "remove white",
+    "no use data": "no use data",
+    "Wireless device detection system management": "Wireless device detection system management",
+    "Management system for wireless camera detection and equipment detection": "Management system for wireless camera detection and equipment detection",
+    "login": "login",
+    "User name or email address": "User name or email address",
+    "Password": "Password",
+    "Verification Code": "Verification Code",
+    "Invisibility? Give it a try!": "Invisibility? Give it a try!",
+    "cancel": "cancel",
+    "usercode": "usercode",
+    "can not be empty": "can not be empty",
+    "least": "least",
+    "character": "character!",
+    "Limit exceeded": "Limit exceeded",
+    "The verification code has timed out. Please re-enter": "The verification code has timed out. Please re-enter",
+    "System home page": "System home page",
+    "home": "home",
+    "Real-time monitoring": "Real-time monitoring",
+    "Real-time": "Real-time",
+    "Detection record": "Detection record",
+    "Detection": "Detection",
+    "Record": "Record",
+    "item": "item",
+    "Suspicious device": "Suspicious device",
+    "Detection equipment": "Detection equipment",
+    "Supervision quantity": "Supervision quantity",
+    "Statistical report forms": "Statistical report forms",
+    "Dangerous equipment found": "Dangerous equipment found",
+    "brand": "brand",
+    "User list": "User list",
+    "Enterprise list": "Enterprise list",
+    "System setup": "System setup",
+    "Map display": "Map display",
+    "Map": "Map",
+    "Loading data": "Loading data",
+    "region": "region",
+    "state": "state",
+    "pcs": "pcs",
+    "phone signal": "phone signal",
+    "Camera": "Camera",
+    "Suspicious camera": "Suspicious camera",
+    "Plane details": "Plane details",
+    "Company details": "Company details",
+    "normal": "normal",
+    "abnormal": "abnormal",
+    "Not found": "Not found",
+    "enterprise": "enterprise",
+    "Suspicious": "Suspicious",
+    "Prohibit": "Prohibit",
+    "fault": "fault",
+    "Off-line": "Off-line",
+    "Depot repair": "Depot repair",
+    "delete": "delete",
+    "other": "other",
+    "total": "total",
+    "Back to previous page": "Back to previous page",
+    "detail": "detail",
+    "Affiliated Enterprises": "Affiliated Enterprises",
+    "Tag name": "Tag name",
+    "local": "local",
+    "wireless device": "wireless device",
+    "No mobile signal detected": "No mobile signal detected",
+    "disabled": "disabled",
+    "Enabled": "Enabled",
+    "nothing": "nothing",
+    "user management": "user management",
+    "User details": "User details",
+    "User roles": "User roles",
+    "Business management": "Business management",
+    "query criteria": "query criteria",
+    "Keyword query": "Keyword query",
+    "Reset": "Reset",
+    "query": "query",
+    "hotel": "hotel",
+    "tavern": "tavern",
+    "Prison": "Prison",
+    "Enterprise name": "Enterprise name",
+    "Enterprise types": "Enterprise types",
+    "Enterprise address": "Enterprise address",
+    "Subordinate supervision": "Subordinate supervision",
+    "Contacts": "Contacts",
+    "Total detection record": "Total detection record",
+    "to": "to",
+    "Please go to the webpage for more records": "Please go to the webpage for more records",
+    "Query already": "Query already",
+    "Please select a device first": "Please select a device first",
+    "No records found": "No records found",
+    "Alarm sound": "Alarm sound",
+    "Alarm flicker": "Alarm flicker",
+    "Quit landing": "Quit landing",
+    "Confirm to exit the current account": "Confirm to exit the current account",
+    "confirm": "confirm",
+    // error code
+    "Record does not exist": "Record does not exist",
+    "Successful implementation": "Successful implementation",
+    "The server is busy. Please try again later": "The server is busy. Please try again later",
+    "Service is temporarily unavailable": "Service is temporarily unavailable",
+    "Key does not exist": "Key does not exist",
+    "Wrong user name or password": "Wrong user name or password",
+    "Graphic verification code error": "Graphic verification code error",
+    "Password format error": "Password format error",
+    "Password error": "Password error",
+    "User already exists": "User already exists",
+    "Transmission frequency too high": "Transmission frequency too high",
+    "User is disabled": "User is disabled",
+    "Abnormal user status": "Abnormal user status",
+    "user does not exist": "user does not exist",
+    "Verification code error": "Verification code error",
+    "Logon failure": "Logon failure",
+    "MAC already exists": "MAC already exists",
+    "Is not a complete comma separated list format": "Is not a complete comma separated list format",
+    "HBase error": "HBase error",
+    "Please upload the picture again": "Please upload the picture again",
+    "not found": "not found",
+    "danger": "danger",
+    "warning": "warning",
+    "deal": "deal",
+    "white": "deal",
+};

+ 135 - 0
app/src/language/ru-RU.js

@@ -0,0 +1,135 @@
+export default {
+    "whiteList": "белый список",
+    "search": "запрос",
+    "index": "Первая страница",
+    "keyword": "ключевые слова",
+    "order": "порядковый номер",
+    "detect tag": "метка детектора",
+    "detect local": "место обнаружения",
+    "be detect MAC": "измерительное устройство MAC",
+    "sign time": "время отметки",
+    "operator": "оператор",
+    "memo": "Примечание",
+    "control": "операция",
+    "close": "Выключить",
+    "remove white": "Выключить белый список",
+    "no use data": "неиспользуемые данные",
+    "Wireless device detection system management": "управление системой обнаружения",
+    "Management system for wireless camera detection and equipment detection": "система управления обнаружением радиокамер, обнаружением фотоаппарата и т.д.",
+    "login": "входить",
+    "User name or email address": "Имя пользователя или почтовый адрес",
+    "Password": "пароль",
+    "Verification Code": "код проверки",
+    "Invisibility? Give it a try!": "не видишь?примерить кистью!",
+    "cancel": "отмена",
+    "usercode": "Имя пользователя",
+    "can not be empty": "не может быть пустым!",
+    "least": "минимум",
+    "character": "знак!",
+    "Limit exceeded": "превышать лимит",
+    "The verification code has timed out. Please re-enter": "код проверки истек, повторите ввод",
+    "System home page": "системная страница",
+    "home": "страница",
+    "Real-time monitoring": "контроль реального времени",
+    "Real-time": "истинное",
+    "Detection record": "запись обнаружения",
+    "Detection": "энергопитающая",
+    "Record": "запись",
+    "item": "полоса",
+    "Suspicious device": "подозрительное оборудование",
+    "Detection equipment": "энергопитающая",
+    "Supervision quantity": "контрольный количество",
+    "Statistical report forms": "статистический отчет",
+    "Dangerous equipment found": "обнаружение опасного оборудования",
+    "brand": "бренд",
+    "User list": "Список пользователей",
+    "Enterprise list": "Список предприятий",
+    "System setup": "Настройки системы",
+    "Map display": "карта",
+    "Map": "карта",
+    "Loading data": "Загрузка данных",
+    "region": "область",
+    "state": "состояние",
+    "pcs": "стол",
+    "phone signal": "сотовый сигнал",
+    "phone": "мобильный",
+    "Camera": "камера",
+    "Suspicious camera": "подозрительная камера",
+    "Plane details": "плоская деталь",
+    "Company details": "сведения о предприятии",
+    "normal": "нормальный",
+    "abnormal": "аномалия",
+    "Not found": "Не найдено",
+    "enterprise": "предприятие",
+    "Suspicious": "сомнительный",
+    "Prohibit": "Отключить",
+    "fault": "неисправность",
+    "Off-line": "оффлайн",
+    "Depot repair": "ремонт на заводе",
+    "delete": "Удалить",
+    "other": "Прочее",
+    "total": "весь",
+    "Back to previous page": "вернуться на предыдущую страницу",
+    "detail": "подробности",
+    "Affiliated Enterprises": "подведомственное предприятие",
+    "Tag name": "название метки",
+    "local": "место",
+    "wireless device": "радиооборудование",
+    "No mobile signal detected": "сигнал телефона не обнаружен",
+    "disabled": "Отключено",
+    "Enabled": "Включено",
+    "nothing": "Нет",
+    "user management": "Управление пользователями",
+    "User details": "сведения о пользователе",
+    "User roles": "роль пользователя",
+    "Business management": "управление предприятием",
+    "query criteria": "условия запроса",
+    "Keyword query": "запрос ключевого слова",
+    "Reset": "сбросить",
+    "query": "запрос",
+    "hotel": "гостиница",
+    "tavern": "кабак",
+    "Prison": "тюрьма",
+    "Enterprise name": "название компании",
+    "Enterprise types": "тип предприятия",
+    "Enterprise address": "адрес предприятия",
+    "Subordinate supervision": "подведомственный контроль",
+    "Contacts": "контакт",
+    "Total detection record": "запись общего обнаружения",
+    "to": "to",
+    "Please go to the webpage for more records": "Пожалуйста, Просматривайте страницу",
+    "Query already": "опрос",
+    "Please select a device first": "Выберите устройство",
+    "No records found": "Нет запроса на запись",
+    "Alarm sound": "сигнал тревоги",
+    "Alarm flicker": "мигание тревоги",
+    "Quit landing": "выход из десанта",
+    "Confirm to exit the current account": "установить выход из текущего счета",
+    "confirm": "определение",
+    // error code
+    "Record does not exist": "запись не существует",
+    "Successful implementation": "успешная реализация",
+    "The server is busy. Please try again later": "Сервер загружен, попробуйте позже",
+    "Service is temporarily unavailable": "обслуживание временно недоступно",
+    "Key does not exist.": "Key не существует",
+    "Wrong user name or password": "ошибка по имени или паролю",
+    "Graphic verification code error": "ошибка графического кода",
+    "Password format error": "ошибка формата пароля",
+    "Password error": "ошибка пароля",
+    "User already exists": "пользователь уже существует",
+    "Transmission frequency too high": "частота пересылки",
+    "User is disabled": "пользователь отключен",
+    "Abnormal user status": "аномалия состояния пользователя",
+    "user does not exist": "пользователь не существует",
+    "Verification code error": "Ошибка проверки кода",
+    "Logon failure": "Ошибка регистрации",
+    "MAC already exists": "MAC уже существует",
+    "Is not a complete comma separated list format": "не весь формат разделённых запятыми списков",
+    "HBase error": "ошибка HBase",
+    "Please upload the picture again": "Перезагрузите изображение",
+    "not found": "не найдено",
+    "danger": "Опасности",
+    "warning": "Предупреждение",
+    "deal": "Сделки",
+    "white": "Белый",
+};

+ 135 - 0
app/src/language/zh-CN.js

@@ -0,0 +1,135 @@
+export default {
+    "whiteList": "白名单",
+    "search": "搜索",
+    "index": "首页",
+    "keyword": "关键词",
+    "order": "序号",
+    "detect tag": "探测器标签",
+    "detect local": "探测位置",
+    "be detect MAC": "被测设备MAC",
+    "sign time": "标注时间",
+    "operator": "操作员",
+    "memo": "备注",
+    "control": "操作",
+    "close": "关闭",
+    "remove white": "移出白名单",
+    "no use data": "暂没有符合条件的数据",
+    "Wireless device detection system management": "无线设备探测系统管理",
+    "Management system for wireless camera detection and equipment detection": "无线摄像头探测、偷拍设备探测等管理系统",
+    "login": "登录",
+    "User name or email address": "用户名或邮件地址",
+    "Password": "密码",
+    "Verification Code": "验证码",
+    "Invisibility? Give it a try!": "看不清?刷一下试试!",
+    "cancel": "取消",
+    "usercode": "用户名",
+    "can not be empty": "不能为空!",
+    "least": "最少",
+    "character": "字符!",
+    "Limit exceeded": "超出限制数量",
+    "The verification code has timed out. Please re-enter": "验证码已超时,请重新输入",
+    "System home page": "系统首页",
+    "home": "系统首页",
+    "Real-time monitoring": "实时监控",
+    "Real-time": "实时监控",
+    "Detection record": "探测记录",
+    "Detection": "探测设备",
+    "Record": "记录",
+    "item": "条",
+    "Suspicious device": "可疑设备",
+    "Detection equipment": "探测设备",
+    "Supervision quantity": "监管数量",
+    "Statistical report forms": "统计报表",
+    "Dangerous equipment found": "发现危险设备",
+    "brand": "品牌",
+    "User list": "用户列表",
+    "Enterprise list": "企业列表",
+    "System setup": "系统设置",
+    "Map display": "地图展示",
+    "Map": "地图展示",
+    "Loading data": "正在加载数据",
+    "region": "区域",
+    "state": "状态",
+    "pcs": "台",
+    "phone signal": "手机信号",
+    "phone": "手机",
+    "Camera": "摄像头",
+    "Suspicious camera": "可疑摄像头",
+    "Plane details": "平面详情",
+    "Company details": "企业详情",
+    "normal": "正常",
+    "abnormal": "异常",
+    "Not found": "没有发现",
+    "enterprise": "企业",
+    "Suspicious": "可疑",
+    "Prohibit": "禁用",
+    "fault": "故障",
+    "Off-line": "离线",
+    "Depot repair": "返厂维修",
+    "delete": "删除",
+    "other": "其他",
+    "total": "共",
+    "Back to previous page": "返回上一页",
+    "detail": "详情",
+    "Affiliated Enterprises": "所属企业",
+    "Tag name": "标签名",
+    "local": "位置",
+    "wireless device": "无线设备",
+    "No mobile signal detected": "未检测到手机信号",
+    "disabled": "已禁用",
+    "Enabled": "已启用",
+    "nothing": "无",
+    "user management": "用户管理",
+    "User details": "用户详情",
+    "User roles": "用户角色",
+    "Business management": "企业管理",
+    "query criteria": "查询条件",
+    "Keyword query": "关键字查询",
+    "Reset": "重 置",
+    "query": "查 询",
+    "hotel": "宾馆",
+    "tavern": "酒店",
+    "Prison": "监狱",
+    "Enterprise name": "企业名称",
+    "Enterprise types": "企业类型",
+    "Enterprise address": "企业地址",
+    "Subordinate supervision": "所属监管",
+    "Contacts": "联 系 人",
+    "Total detection record": "总探测记录",
+    "to": "至",
+    "Please go to the webpage for more records": "更多记录请前往网页端查看",
+    "Query already": "已查询",
+    "Please select a device first": "请先选择一个设备",
+    "No records found": "没有查询到记录",
+    "Alarm sound": "报警声音",
+    "Alarm flicker": "报警闪烁",
+    "Quit landing": "退出登陆",
+    "Confirm to exit the current account": "确定退出当前账户",
+    "confirm": "确定",
+    // error code
+    "Record does not exist": "记录不存在",
+    "Successful implementation": "执行成功",
+    "The server is busy. Please try again later": "服务器繁忙,请稍后再试",
+    "Service is temporarily unavailable": "服务暂不可用",
+    "Key does not exist.": "key不存在",
+    "Wrong user name or password": "用户名或密码错误",
+    "Graphic verification code error": "图形验证码错误",
+    "Password format error": "密码格式错误",
+    "Password error": "密码错误",
+    "User already exists": "用户已存在",
+    "Transmission frequency too high": "发送频率过高",
+    "User is disabled": "用户被禁用",
+    "Abnormal user status": "用户状态异常",
+    "user does not exist": "用户不存在",
+    "Verification code error": "验证码错误",
+    "Logon failure": "登录失效",
+    "MAC already exists": "MAC已存在",
+    "Is not a complete comma separated list format": "不是完整的逗号分隔列表格式",
+    "HBase error": "HBase错误",
+    "Please upload the picture again": "请重新上传图片",
+    "not found": "没有发现",
+    "danger": "高危",
+    "warning": "低危",
+    "deal": "已处理",
+    "white": "白名单",
+};

+ 16 - 0
app/src/libs/rem.js

@@ -0,0 +1,16 @@
+// 设置 rem 函数
+function setRem () {
+
+    // 320 默认大小16px; 320px = 20rem ;每个元素px基础上/16
+    let htmlWidth = document.documentElement.clientWidth || document.body.clientWidth;
+//得到html的Dom元素
+    let htmlDom = document.getElementsByTagName('html')[0];
+//设置根元素字体大小
+    htmlDom.style.fontSize= htmlWidth/20 + 'px';
+}
+// 初始化
+setRem();
+// 改变窗口大小时重新设置 rem
+window.onresize = function () {
+    setRem()
+}

+ 151 - 0
app/src/main.js

@@ -0,0 +1,151 @@
+import Vue from 'vue'
+import App from './App.vue'
+import router from './router'
+import axios from 'axios'
+import MuseUI from 'muse-ui';
+import 'muse-ui/dist/muse-ui.css';
+// 全局插件
+import Toast from 'muse-ui-toast';
+import Loading from 'muse-ui-loading';
+
+
+import Message from 'muse-ui-message';
+Vue.use(Message);
+import NProgress from 'muse-ui-progress';
+Vue.use(NProgress);
+
+// import VConsole from 'vconsole/dist/vconsole.min.js' //import vconsole
+// let vConsole = new VConsole() // 初始化
+
+Vue.use(MuseUI);
+Vue.locale = () => {
+};
+
+let ToastConfig = {
+    position: 'bottom',               // 弹出的位置
+    time: 2000,                       // 显示的时长
+    closeIcon: 'close',               // 关闭的图标
+    close: true,                      // 是否显示关闭按钮
+    successIcon: 'check_circle',      // 成功信息图标
+    infoIcon: 'info',                 // 信息信息图标
+    warningIcon: 'priority_high',     // 提醒信息图标
+    errorIcon: 'warning'
+};
+
+Vue.use(Toast, ToastConfig);
+
+Vue.use(Loading);
+
+// 演示版本数据
+require('./Mock/index.js');
+
+Vue.config.productionTip = false;
+
+new Vue({
+    render: h => h(App),
+    router,
+}).$mount('#app');
+
+Vue.prototype.axios = axios;
+
+
+//Toast
+Vue.prototype.Toast = function (e, color) {
+    let ToastColor = !color ? 'warning' : color;
+    let that = this;
+    switch (ToastColor) {
+        case 'message':
+            that.$toast.message(e);
+            break;
+        case 'success':
+            that.$toast.success(e);
+            break;
+        case 'info':
+            that.$toast.info(e);
+            break;
+        case 'warning':
+            that.$toast.warning(e);
+            break;
+        case 'error':
+            that.$toast.error(e);
+            break;
+    }
+};
+
+// loading
+Vue.prototype.Loading = function (target) {
+    let loading = this.$loading({
+        overlayColor: 'hsla(0,0%,100%,.9)',        // 背景色
+        size: 48,
+        color: 'warning',                           // color
+    });
+    setTimeout(() => {
+        loading.close();
+    }, 3000)
+};
+
+Vue.prototype.TransMemo = function (text) {
+    let that = this;
+    switch (text) {
+        case '记录不存在':
+            that.$toast.error(that.$t('Record does not exist'));
+            break;
+        case '服务器繁忙,请稍后再试':
+            that.$toast.error(that.$t('The server is busy. Please try again later'));
+            break;
+        case '服务暂不可用':
+            that.$toast.error(that.$t('Service is temporarily unavailable'));
+            break;
+        case 'key不存在':
+            that.$toast.error(that.$t('Key does not exist'));
+            break;
+        case '用户名或密码错误':
+            that.$toast.error(that.$t('Wrong user name or password'));
+            break;
+        case '图形验证码错误':
+            that.$toast.error(that.$t('Graphic verification code error'));
+            break;
+        case '密码格式错误':
+            that.$toast.error(that.$t('Password format error'));
+            break;
+        case '密码错误':
+            that.$toast.error(that.$t('Password error'));
+            break;
+        case '用户已存在':
+            that.$toast.error(that.$t('User already exists'));
+            break;
+        case '发送频率过高':
+            that.$toast.error(that.$t('Transmission frequency too high'));
+            break;
+        case '用户被禁用':
+            that.$toast.error(that.$t('User is disabled'));
+            break;
+        case '用户状态异常':
+            that.$toast.error(that.$t('Abnormal user status'));
+            break;
+        case '用户不存在':
+            that.$toast.error(that.$t('user does not exist'));
+            break;
+        case '验证码错误':
+            that.$toast.error(that.$t('Verification code error'));
+            break;
+        case '登录失效':
+            that.$toast.error(that.$t('Logon failure'));
+            break;
+        case 'MAC已存在':
+            that.$toast.error(that.$t('MAC already exists'));
+            break;
+        case '不是完整的逗号分隔列表格式':
+            that.$toast.error(that.$t('Is not a complete comma separated list format'));
+            break;
+        case 'HBase错误':
+            that.$toast.error(that.$t('HBase error'));
+            break;
+        case '请重新上传图片':
+            that.$toast.error(that.$t('Please upload the picture again'));
+            break;
+        default:
+            that.$toast.error(text);
+            break
+    }
+};

+ 44 - 0
app/src/page/404.vue

@@ -0,0 +1,44 @@
+<template>
+    <div class="container">
+        <h5 class="title">404</h5>
+        <p class="content">网络状况不佳,请改善网络状况后重启本应用</p>
+    </div>
+</template>
+
+<script>
+    import axios from 'axios';
+    let qs = require('qs');
+    import Global from '../Global.js'
+    export default {
+        data() {
+            return {
+                lists: []
+            }
+        },
+        mounted() {
+        },
+        methods: {},
+    }
+</script>
+
+<style scoped>
+    /*mu-header*/
+    .mu-primary-color {
+        line-height: 60px;
+        height: 60px;
+        background: url("../static/images/comm/headerBg.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    /deep/ .mu-appbar-left {
+        padding-top: 15px;
+    }
+
+    /deep/ .material-icons {
+        color: #fff;
+    }
+
+   /deep/ .mu-appbar-title {
+        text-align: center;
+    }
+</style>

+ 715 - 0
app/src/page/appoint.vue

@@ -0,0 +1,715 @@
+<template>
+  <div class="pages">
+
+    <div class="as">
+      <img src="../static/images/main/banner.png" height="121" width="414"/>
+      <mu-tabs :value.sync="active" color="#F2F2F2" indicator-color="#ffffff">
+        <mu-tab v-for="(day,i) in weeks">{{ day.data }} <br> <em>{{ day.name }}</em></mu-tab>
+      </mu-tabs>
+      <span class="sum">
+        {{ today }} 预约名额剩余
+        <em class="green" v-if="num > 0">{{ num }}</em>
+        <em class="red" v-else>{{ num }}</em>
+        人
+    </span>
+    </div>
+    <div class="context">
+      <ul class="list">
+        <li v-for="l in list"
+            v-show="l.WxVisible == 1"
+            :class="[{'greenLi':l.remain > 0},{'redLi':l.Status == 1},{'yellowLi':l.remain == 0},{'whiteLi':l.WxOrder == 0}]">
+          <div class="dotContainer">
+            <!--                        正常-->
+            <i class="dot" v-if="l.remain>0 && l.WxOrder != 0"></i>
+
+            <i class="cubes" v-if="l.Status==1"></i>
+            <!--                        已满-->
+            <i class="tri" v-if="l.remain == 0 && l.remain == 0"></i>
+            <!--                        不可约-->
+            <i class="x" v-if="l.WxOrder==0"></i>
+          </div>
+          <div class="title">
+            <h5><span class="lessons" :style="{ background:l.ClassColor }">{{ l.ClassName }}</span></h5>
+            <span>{{ l.BeginStr }} - {{ l.EndStr }}</span>
+          </div>
+          <div class="current">
+            <h5>剩余
+              <em class="green" v-if="l.remain > 0">{{ l.remain }}</em>
+              <em class="red" v-else>{{ l.remain }}</em>
+              人</h5>
+            <span>总名额 {{ l.OrderToplimit }} 人</span>
+          </div>
+          <mu-button class="appointBtn greenBtn" v-if="l.remain > 0 && l.OrderId == 0 && l.WxOrder != 0"
+                     @click="appointNow(l)">
+            预约
+          </mu-button>
+          <mu-button class="appointBtn redBtn" v-if="l.remain == 0 && l.OrderId == 0" @click="isFulled">已满</mu-button>
+          <mu-button class="appointBtn yellowBtn" v-if="l.OrderId != 0" @click="isAppointed(l)">已约</mu-button>
+          <mu-button class="appointBtn disableBtn" v-if="l.WxOrder == 0" @click="isDisable">不可约</mu-button>
+        </li>
+        <div class="tips" v-if="list == ''">
+          <p style="text-align: center">
+            暂无可预约的课程
+          </p>
+        </div>
+      </ul>
+      <mu-avatar color="rgb(231, 82, 150)" @click.native="goPage('lesson')">
+        <mu-icon value="reorder"></mu-icon>
+      </mu-avatar>
+    </div>
+    <bottomTab :curTab="thisTab"></bottomTab>
+    <div class="doalog">
+      <mu-dialog title="预约课程" width="600" max-width="80%" :esc-press-close="false"
+                 :overlay-close="false" :open.sync="openAlert">
+        <p>
+          是否预约 课程:{{ dialog.ClassName }} ,时间:{{ dialog.BeginStr }} - {{ dialog.EndStr }}
+          <br>
+        </p>
+        <mu-button slot="actions" flat color="primary" @click="closeAlertDialog">取消</mu-button>
+        <mu-button slot="actions" flat color="primary" @click="confirmAppoint">确定</mu-button>
+      </mu-dialog>
+    </div>
+    <alert ref="alertPart"></alert>
+  </div>
+</template>
+
+<script>
+import axios from 'axios';
+import bottomTab from '../components/bottomTab'
+import {
+  CanOrderSchoolTimeTableListQuery,
+  OderAddByVipUser,
+  OderCancelByVipUser,
+  QueryNextWeek,
+  testSelect,
+  testTable,
+} from '../api/getApiRes.js'
+
+import alert from '../components/alert'
+
+let qs = require('qs');
+import Global from '../Global.js'
+
+export default {
+  data() {
+    return {
+      num: 0,
+      thisTab: '预约课程',
+      active: 0,
+      sum: 0,
+      HaveDays: 0,
+      openAlert: false,
+      list: [],
+      weeks: [],
+      today: '',
+      dialog: {
+        id: '',
+        name: '',
+        timeLong: '',
+      },
+    }
+  },
+  mounted() {
+    this.getQueryNextWeek();
+    // this.alertInfo(document.body.clientWidth);
+    // this.alertInfo( window.screen.height);
+  },
+  methods: {
+    getQueryNextWeek(){
+      let that = this;
+      let param = {
+      token: localStorage.token,
+        shopId : this.$route.query.shopId,
+      };
+      let postdata = qs.stringify(param);
+      QueryNextWeek(postdata).then(res => {
+          let json = res;
+          if (json.Code == 0) {
+              this.HaveDays = json.Rs;
+            this.getFurtherDays(this.HaveDays);
+          } else {
+              that.$message.error(json.Memo);
+          }
+      })
+    },
+    alertInfo(info) {
+      this.$refs.alertPart.openSimpleDialog(info);
+    },
+    goPage(url) {
+      this.$router.push({
+        path: '/' + url, query: {
+          shopId: this.$route.query.shopId
+        }
+      });
+    },
+    // 计算距离11/8号还有集体那
+    calcHaveDays(sDate1) {
+      var date2 = new Date();
+      var date1 = new Date(Date.parse(sDate1.replace(/-/g, "/")));
+      var iDays = parseInt(Math.abs(date2.getTime() - date1.getTime()) / 1000 / 60 / 60 / 24) + 2;
+      return iDays;
+
+    },
+    // 获取未来7天的
+    getFurtherDays(HaveDays) {
+      let now = new Date();
+      let nowTime = now.getTime();
+      let oneDayTime = 24 * 60 * 60 * 1000;
+      let days = '';
+      let item = [];
+      let month = 0;
+      let day = 0;
+      this.weeks = [];
+      for (let i = 0; i < HaveDays; i++) {
+        days = new Date(nowTime + (i) * oneDayTime);//显示周日
+        month = days.getMonth() + 1;
+        day = days.getDate();
+        month = month < 10 ? '0' + month : month;
+        day = day < 10 ? '0' + day : day;
+        item = {
+          name: this.numberToWeek(days.getDay()),
+          data: days.getMonth() + 1 + '月' + days.getDate() + '日',
+          orderDate: new Date().getFullYear() + '-' + month + '-' + day
+        }
+        this.weeks.push(item);
+      }
+      this.today = this.weeks[0].name;
+      this.getList();
+    },
+    numberToWeek(val) {
+      switch (parseInt(val)) {
+        case 1:
+          return '星期一'
+          break;
+        case 2:
+          return '星期二'
+          break;
+        case 3:
+          return '星期三'
+          break;
+        case 4:
+          return '星期四'
+          break;
+        case 5:
+          return '星期五'
+          break;
+        case 6:
+          return '星期六'
+          break;
+        case 0:
+          return '星期天'
+          break;
+      }
+    },
+    confirmAppoint() {
+      let that = this;
+      let param = {
+        token: localStorage.token,
+        stdId: that.dialog.StdId
+      };
+      let postdata = qs.stringify(param);
+      OderAddByVipUser(postdata).then(res => {
+        let json = res;
+        if (json.Code == 0) {
+          that.alertInfo('已成功预约', 'success');
+          that.openAlert = false;
+          that.getList();
+        } else {
+          that.alertInfo(json.Memo + ',错误码:' + json.Code);
+        }
+      })
+    },
+    closeAlertDialog() {
+      this.openAlert = false;
+    },
+    appointNow(row) {
+      this.dialog = row;
+      this.openAlert = true;
+    },
+    isFulled() {
+      let that = this;
+      that.$alert('当前课程已满,请选择其他课程或其他时间预约', '提示', {
+        okLabel: '知道了'
+      }).then(() => {
+        that.getList();
+      });
+    },
+    isAppointed(row) {
+      let that = this;
+      this.$confirm('是否取消前课程预约?', '提示', {
+        type: 'warning'
+      }).then(({result}) => {
+        if (result) {
+          let param = {
+            token: localStorage.token,
+            orderId: row.OrderId,
+          };
+          let postdata = qs.stringify(param);
+          OderCancelByVipUser(postdata).then(res => {
+            let json = res;
+            if (json.Code == 0) {
+              that.alertInfo('当前课程已取消预约', 'success');
+              that.getList();
+            } else {
+              that.alertInfo(json.Memo + ',错误码:' + json.Code);
+            }
+          })
+        } else {
+          this.alertInfo('点击了取消');
+        }
+      });
+    },
+    isDisable(row) {
+      this.alertInfo('课程不可预约,请选择其他课程或其他时间预约', 'info');
+    },
+    getList() {
+      let that = this;
+      this.today = this.weeks[this.active].name;
+      let curDay = this.weeks[this.active].orderDate;
+      let param = {
+        token: localStorage.token,
+        orderDate: curDay,
+        shopId: this.$route.query.shopId,
+      };
+      let postdata = qs.stringify(param);
+      CanOrderSchoolTimeTableListQuery(postdata).then(res => {
+        let json = res;
+        if (json.Code == 0) {
+          that.list = json.Rs;
+          that.num = 0;
+          if (that.list) {
+            // 计算剩余
+            that.list.map(function (item) {
+              item.remain = parseInt(item.OrderToplimit) - parseInt(item.OrderCount);
+              that.num = that.num + item.remain
+            })
+          }
+        } else {
+          that.alertInfo(json.Memo + ',错误码:' + json.Code);
+        }
+      })
+    },
+  },
+  beforeRouteEnter(to, from, next) {
+    next(vm => {
+      //因为当钩子执行前,组件实例还没被创建
+      // vm 就是当前组件的实例相当于上面的 this,所以在 next 方法里你就可以把 vm 当 this 来用了。
+      if (to.name == 'appoint') {
+        // vm.getList();
+        vm.getQueryNextWeek();
+      }
+    });
+  },
+  watch: {
+    'active'() {
+      this.getList();
+
+    }
+  },
+  components: {
+    bottomTab, alert
+  }
+}
+</script>
+
+<style scoped>
+.pages {
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+}
+
+/*mu-header*/
+.mu-primary-color {
+  line-height: 60px;
+  height: 60px;
+  background: url("../static/images/comm/headerBg.png") top center no-repeat;
+  background-size: 100%;
+}
+
+/deep/ .mu-appbar-left {
+  padding-top: 15px;
+}
+
+/deep/ .material-icons {
+  color: #fff;
+}
+
+/deep/ .mu-appbar-title {
+  text-align: center;
+}
+
+/deep/ .mu-tabs {
+  /*display: flex;*/
+  /*width: 414px;*/
+  overflow-x: scroll;
+  overflow-y: hidden;
+  /*display:inline;*/
+  /*float: left;*/
+}
+
+/deep/ .mu-tab {
+  width: 85px;
+  min-width: 85px;
+  float: left;
+  height: 51px;
+  margin-right: 6px;
+}
+
+/*/deep/ .mu-tab:nth-child(5) {*/
+/*    margin-right: 0px;*/
+/*}*/
+
+/deep/ .mu-tab-wrapper {
+  height: 51px;
+  background: #f4f4f4;
+  color: #363636;
+  box-shadow: 1px 0px 6px rgba(0, 0, 0, 0.16);
+  border-radius: 8px 8px 0px 0px;
+  font-size: 14px;
+}
+
+/deep/ .mu-tab-active .mu-tab-wrapper {
+  height: 56px;
+  border-radius: 8px 8px 0px 0px;
+  background: #ffffff;
+  box-shadow: 1px 0px 6px rgba(0, 0, 0, 0.16);
+  color: #000;
+}
+
+/deep/ .mu-tab-wrapper em {
+  font-size: 12px;
+}
+
+.sum {
+  width: 100%;
+  height: 55px;
+  line-height: 55px;
+  background: #fff;
+  font-family: "PingFang SC";
+  font-weight: 300;
+  font-size: 16px;
+  text-align: center;
+  color: #909090;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+}
+
+.green {
+  color: #37CB00;
+}
+
+.red {
+  color: #F8847F;
+}
+
+.list {
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  margin-top: 8px;
+  padding-bottom: 30px;
+}
+
+.list li {
+  width: 100%;
+  height: 70px;
+  margin-bottom: 8px;
+  padding-top: 16px;
+  padding-bottom: 16px;
+}
+
+.list .dotContainer {
+  width: 50px;
+  float: left;
+  height: 60px;
+  padding-left: 22px;
+  padding-top: 10px;
+}
+
+.dotContainer .dot {
+  width: 12px;
+  height: 12px;
+  background: #37cb00;
+  border-radius: 250px;
+  float: left;
+}
+
+.cubes {
+  width: 12px;
+  height: 12px;
+  background: #f8847f;
+  float: left;
+}
+
+.tri {
+  width: 12px;
+  height: 12px;
+  background: url("../static/images/appoint/tri.png") top center no-repeat;
+  background-size: 100% 100%;
+  float: left;
+}
+
+.x {
+  width: 12px;
+  height: 12px;
+  background: url("../static/images/appoint/x.png") top center no-repeat;
+  background-size: 100% 100%;
+  float: left;
+}
+
+
+.yellowLi {
+  background: #FFFBED;
+}
+
+.redLi {
+  background: #FFF7F7;
+}
+
+.greenLi {
+  background: #F7FFF4;
+}
+
+.whiteLi {
+  background: #fff;
+}
+
+.list li .title {
+  /*width: 90px;*/
+  width: 27%;
+  height: 60px;
+  float: left;
+}
+
+li .title h5 {
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  font-weight: normal;
+  font-size: 14px;
+  text-align: left;
+  color: #3b3b3b;
+}
+
+li .title span {
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  font-weight: normal;
+  font-size: 12px;
+  text-align: left;
+  color: #909090;
+}
+
+.list li .current {
+  width: 120px;
+  height: 60px;
+  float: left;
+}
+
+li .current h5 {
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  font-family: "PingFang SC";
+  font-weight: normal;
+  font-size: 14px;
+  text-align: left;
+  color: #3b3b3b;
+}
+
+.current h5 em {
+  font-family: "PingFang SC";
+  font-weight: normal;
+  font-size: 14px;
+  text-align: left;
+}
+
+.current span {
+  font-family: "PingFang SC";
+  font-weight: normal;
+  font-size: 12px;
+  text-align: left;
+  color: #909090;
+}
+
+.appointBtn {
+  width: 79px;
+  height: 37px;
+  border-radius: 18.5px;
+  background: #fff;
+  float: right;
+  font-family: "PingFang SC";
+  font-weight: normal;
+  font-size: 18px;
+  margin-right: 2%;
+}
+
+.greenBtn {
+  border: 1px solid #37cb00;
+  color: #37cb00;
+}
+
+.redBtn {
+  border: 1px solid #F8847F;
+  color: #F8847F;
+}
+
+.yellowBtn {
+  border: 1px solid #FFB43C;
+  color: #fff;
+  background: #FFB43C;
+}
+
+.disableBtn {
+  border: 1px solid #C9C9C9;
+  color: #C9C9C9;
+}
+
+/deep/ .mu-tabs-center {
+  display: flex;
+  overflow-x: auto;
+  overflow-y: hidden;
+  white-space: nowrap;
+}
+
+/deep/ .mu-tabs-center::-webkit-scrollbar {
+  display: none;
+}
+
+/deep/ .mu-modal-inner {
+  width: 90%;
+  float: left;
+}
+
+/deep/ .mu-tab-link-highlight {
+  display: none !important;
+}
+
+li .title span.lessons {
+  width: auto;
+  padding: 1px 11px;
+  border-radius: 250px;
+  float: left;
+  text-align: center;
+  color: #000;
+  font-size: 14px;
+}
+
+/deep/ .mu-avatar {
+  position: fixed;
+  bottom: 9%;
+  float: left;
+  left: 1%;
+}
+
+.context {
+  position: absolute;
+  left: 0;
+  right: 0;
+  top: 30%;
+  bottom: 0;
+  overflow-y: scroll;
+  padding-bottom: 50px;
+}
+
+.as {
+  position: fixed;
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  z-index: 222;
+  background: #F2F2F2;
+}
+
+/deep/ .mu-raised-button {
+  box-shadow: none;
+}
+
+@media only screen and (max-width: 640px) {
+
+}
+
+@media only screen and (max-width: 480px) {
+
+}
+
+@media only screen and (max-width: 375px) {
+  .context {
+    top: 34%;
+  }
+}
+
+@media only screen and (max-width: 414px) {
+  .context {
+    top: 38%;
+  }
+}
+@media only screen and (max-width: 414px) and (device-height: 739px) {
+  .context {
+    top: 36%;
+    /*background: red;*/
+  }
+}
+
+@media only screen and (max-width: 414px) and (device-height: 889px) {
+  .context {
+    top: 30%;
+    /*background: red;*/
+  }
+}@media only screen and (max-width: 414px) and (device-height: 896px) {
+  .context {
+    top: 33%;
+    /*background: red;*/
+  }
+}
+
+@media only screen and (max-width: 375px) and (device-height: 812px) {
+  .context {
+    top: 35%;
+    /*background: red;*/
+  }
+}
+
+@media only screen and (max-width: 360px) {
+  .list li .current {
+    width: 32%;
+  }
+
+  .context {
+    top: 34%;
+  }
+}
+
+@media only screen and (max-width: 320px) {
+  .list .dotContainer {
+    width: 20px;
+    padding-left: 5px;
+  }
+
+  .list li .title {
+    width: 30%;
+  }
+
+  .list li .current {
+    width: 32%;
+  }
+
+  .context {
+    top: 41%;
+  }
+}
+
+@media only screen and (min-width: 641px) {
+  .context {
+    top: 21%;
+  }
+}
+</style>

+ 257 - 0
app/src/page/detector.vue

@@ -0,0 +1,257 @@
+<template>
+    <div class="">
+        <appHeader @goNewpage="onGoNewPage" :title="this.pagetitle"></appHeader>
+        <bottomTab :curTab="thisTab"></bottomTab>
+        <div class="listContainer">
+            <ul class="deteUl">
+                <li v-if="!lists.length">
+                    <h4>{{$t("no use data")}}</h4>
+                </li>
+                <transition-group name="fade">
+                    <li v-for="list in stus" v-if="lists" @click="goPage(list)" v-bind:key="list.Id">
+                        <div class="lt">
+                            <div class="rowTop">
+                                <h5>{{list.TagName}}</h5>
+                                <!--<span>{{list.Status | typeFileter}}</span>-->
+                                <span>{{list.stusType}}</span>
+                            </div>
+                            <div class="rowDetail">
+                                <span>{{list.Mac}}</span>
+                                <span class="pull-right">{{list.Memo}}</span>
+                            </div>
+                            <div class="rowDetail">
+                                <span>{{list.RegisterTime  | timeFileter}}</span>
+                                <span class="pull-right">{{list.ComName}}{{list.Name}}</span>
+                            </div>
+                        </div>
+                        <div class="rt">
+                            <mu-icon value="keyboard_arrow_right"></mu-icon>
+                        </div>
+                    </li>
+                </transition-group>
+                <div class="tips" v-if="lists">
+                    {{$t("total")}}{{lists.length}}{{$t("pcs")}} {{$t("Detection equipment")}}
+                </div>
+            </ul>
+        </div>
+    </div>
+</template>
+
+<script>
+    import appHeader from '../components/appHeader'
+    import bottomTab from '../components/bottomTab'
+    import axios from 'axios';
+
+    let qs = require('qs');
+    import Global from '../Global.js'
+
+    export default {
+        data() {
+            return {
+                pagetitle: this.$t('Detection'),
+                thisTab: this.$t('Detection'),
+                lists: [],
+                show: true
+            }
+        },
+        mounted() {
+            this.writeData();
+        },
+        methods: {
+            onGoNewPage(path) {
+                this.$router.push({path: '/' + path});
+            },
+            goPage(list) {
+                this.$router.push({path: '/detectorDetail', query: {detector: JSON.stringify(list)}});
+            },
+            writeData() {
+                const that = this;
+                let url = headapi + 'v1/Detector/DetectorQuery';
+                let pageIndex = 1;
+                let tableMax = 100;
+                let prov = localStorage.defaultProv;
+                let city = localStorage.defaultCity;
+                let area = localStorage.defaultArea;
+                let comid = localStorage.Comid;
+                let searchs = '';
+                let param = {
+                    token: localStorage.token,
+                    prov: prov,
+                    city: city,
+                    area: area,
+                    supregionid: 0,
+                    regionid: 0,
+                    comid: 48,
+                    keyword: '',
+                    pageIndex: pageIndex,
+                    tableMax: tableMax
+                };
+                let postdata = qs.stringify(param);
+                axios.post(url, postdata).then(function (data) {
+                    let json = data.data;
+                    if (json.Code == 0) {
+                        that.lists = json.Rs;
+                    } else {
+                        this.Toast(that.TransMemo(json.Memo));
+                    }
+                }, function (response) {
+                    console.info(response);
+                })
+            }
+        },
+        computed: {
+            stus() {
+                let that = this;
+                let text = '';
+                /*es6写法 防止用不了this.type*/
+                return this.lists.filter((v) => {
+                    switch (parseInt(v.Status)) {
+                        case 0:
+                            text = that.$t('Prohibit');
+                            break;
+                        case 1:
+                            text = that.$t('normal');
+                            break;
+                        case 2:
+                            text = that.$t('Off-line');
+                            break;
+                        case 3:
+                            text = that.$t('fault');
+                            break;
+                        case 9:
+                            text = that.$t('delete');
+                            break;
+                        default:
+                            text = that.$t('other');
+                            break;
+                    }
+                    return v.stusType = text;
+                })
+            }
+        },
+        filters: {
+            timeFileter: function (time) {
+                return globalfmtDate(time, 10)
+            },
+        },
+        components: {
+            appHeader, bottomTab
+        }
+    }
+</script>
+
+<style scoped>
+    #pages {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin-top: 0px;
+        padding-bottom: 10px;
+        background: #f2f2f2;
+    }
+
+    /*!*index mu-header*!*/
+    /deep/ .mint-header {
+        line-height: 60px;
+        height: 60px;
+        background: url("../static/images/comm/headerBg.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    /deep/ .mint-button--default {
+        background: none;
+        color: #fff;
+        font-size: 14px;
+    }
+
+    /deep/ .mint-header-title {
+        padding-top: 0 !important;
+    }
+
+    .listContainer ul {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+
+    .listContainer li {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        padding: 10px 20px;
+        border-bottom: 2px solid #f2f2f2;
+        background: #fff;
+    }
+
+    .listContainer .rowTop {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+
+    .rowTop .red {
+        color: #FFA200;
+    }
+
+    .listContainer h5 {
+        margin: 0;
+        float: left;
+        font-size: 16px;
+    }
+
+    .listContainer .rowTop {
+        margin-bottom: 10px;
+    }
+
+    .listContainer .rowTop span {
+        float: right;
+        font-size: 14px;
+    }
+
+    .listContainer .rowDetail {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        color: #999999;
+        font-size: 14px;
+    }
+
+    .deteUl .lt {
+        width: 95%;
+        float: left;
+    }
+
+    .deteUl .rt {
+        float: right;
+    }
+
+    .rt i {
+        width: 8px;
+        height: 14px;
+        margin-top: 20px;
+        margin-right: 5px;
+        color: #ccc;
+    }
+
+    .pull-right {
+        float: right;
+        text-align: right;
+    }
+
+    .tips {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        text-align: center;
+        font-size: 12px;
+        color: #999999;
+        margin-top: 20px;
+    }
+
+
+</style>

+ 140 - 0
app/src/page/detectorDetail.vue

@@ -0,0 +1,140 @@
+<template>
+    <div id="pages">
+        <mu-appbar style="width: 100%;" color="primary" :title="titletext">
+            <router-link to="/detector" slot="left">
+                <mu-icon value="arrow_back"></mu-icon>
+            </router-link>
+        </mu-appbar>
+        <div class="row">
+            <h5>{{detail.ComName}}</h5>
+            <ul>
+                <li><em>Mac:</em><span>{{detail.Mac}}</span></li>
+                <li><em>{{$t("Affiliated Enterprises")}}:</em><span>{{detail.ComName  | filterContent}}</span></li>
+                <li><em>{{$t("Tag name")}}:</em><span>{{detail.TagName  | filterContent}}</span></li>
+                <li><em>{{$t("local")}}:</em><span>{{detail.Prov}}{{detail.City}}{{detail.Area}}{{detail.Name}}</span></li>
+                <li><em>{{$t("memo")}}:</em><span>{{detail.Memo  | filterContent}}</span></li>
+            </ul>
+        </div>
+    </div>
+</template>
+
+<script>
+    import axios from 'axios';
+
+    let qs = require('qs');
+    import Global from '../Global.js'
+
+    export default {
+        data() {
+            return {
+                detail: {},
+                titletext:this.$t('Detection') + this.$t('detail'),
+            }
+        },
+        mounted() {
+            this.writeData();
+        },
+        methods: {
+            writeData() {
+                let content = this.$route.query.detector;
+                this.detail = JSON.parse(content);
+                console.log(this.detail);
+            }
+        },
+        filters: {
+            filterContent: function (value) {
+                if (value == '' || value == undefined) {
+                    return '-'
+                } else {
+                    return value
+                }
+            },
+        },
+        components: {}
+    }
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped>
+    /*mu-header*/
+    /deep/ .mu-primary-color {
+        line-height: 60px;
+        height: 60px;
+        background: url("../static/images/comm/headerBg.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    /deep/ .mu-appbar-left {
+        padding-top: 15px;
+    }
+
+    /deep/ .material-icons {
+        color: #fff;
+    }
+
+    /deep/ .mu-appbar-title {
+        text-align: center;
+    }
+
+
+    #pages {
+        position: absolute;
+        top: 0;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        padding-bottom: 200px;
+        background: #f2f2f2;
+    }
+
+    .row {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        background: #fff;
+    }
+
+    .row h5 {
+        width: 80%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        text-align: center;
+        font-size: 20px;
+        color: #FFA200;
+        padding: 20px;
+        border-bottom: 1px solid rgba(112, 112, 112, 0.14);
+        margin-bottom: 20px;
+    }
+
+    .row ul {
+        width: 80%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        margin-top: 10px;
+    }
+
+    .row li {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        margin-bottom: 10px;
+        font-size: 16px;
+    }
+
+
+    .row li em {
+        float: left;
+        min-width: 80px;
+    }
+
+    .row li span {
+        color: #6E6E6E;
+    }
+</style>

+ 176 - 0
app/src/page/enterpriseDetail.vue

@@ -0,0 +1,176 @@
+<template>
+    <div id="pages">
+        <mu-appbar style="width: 100%;" color="primary" :title="$t('Company details')">
+            <router-link to="/enterprisemanage" slot="left">
+                <mu-icon value="arrow_back"></mu-icon>
+            </router-link>
+        </mu-appbar>
+        <div class="container">
+            <div class="row">
+                <h5>{{detail.ComName}}</h5>
+                <ul>
+                    <li><em>{{$t("Enterprise name")}}:</em><span>{{detail.ComName}}</span></li>
+                    <li><em>{{$t("Enterprise types")}}:</em><span>{{ComType}}</span></li>
+                    <li>
+                        <em>{{$t("Enterprise address")}}:</em><span>{{detail.ProvCode}}{{detail.CityCode}}{{detail.AreaCode}}{{detail.Addr}}</span>
+                    </li>
+                    <li><em>{{$t("Subordinate supervision")}}:</em><span>
+                        <em v-for="(org,index) in detail.Orgs">{{org.Orgname}} <i
+                                v-if="detail.Orgs.length-1 != index">、</i></em>
+                    </span></li>
+                    <li><em>{{$t("Contacts")}}:</em><span>{{Legal}}</span></li>
+                    <li><em>{{$t("phone")}}:</em><span>{{Phone}}</span></li>
+                </ul>
+            </div>
+        </div>
+    </div>
+
+</template>
+
+<script>
+    import axios from 'axios';
+
+    let qs = require('qs');
+    import Global from '../Global.js'
+
+    export default {
+        data() {
+            return {
+                detail: {},
+                // Legal:'',
+                // Phone:'',
+                // ComType:'',
+            }
+        },
+        mounted() {
+            this.writeData();
+        },
+        computed: {
+            Legal() {
+                if (this.detail.Legal == '' || this.detail.Legal == undefined) {
+                    return this.$t('nothing')
+                } else {
+                    return this.detail.Legal
+                }
+            },
+            Phone() {
+                if (this.detail.Phone == '' || this.detail.Phone == undefined) {
+                    return this.$t('nothing')
+                } else {
+                    return this.detail.Legal
+                }
+            },
+            ComType() {
+                if (this.detail.ComType == '' || this.detail.ComType == undefined) {
+                    return this.$t('nothing')
+                } else {
+                    return this.detail.Legal
+                }
+            },
+        },
+        methods: {
+            writeData() {
+                const that = this;
+                let url = headapi + 'v1/Company/ComInfoDetail';
+                let param = {
+                    token: localStorage.token,
+                    comId: that.$route.query.ComId
+                };
+                let postdata = qs.stringify(param);
+                axios.post(url, postdata).then(function (data) {
+                    let json = data.data;
+                    if (json.Code == 0) {
+                        that.detail = json.Rs;
+                    } else {
+                        this.Toast(that.TransMemo(json.Memo));
+                    }
+                }, function (response) {
+                    console.info(response);
+                })
+            }
+        },
+    }
+</script>
+
+<style scoped>
+    /*mu-header*/
+    .mu-primary-color {
+        line-height: 60px;
+        height: 60px;
+        background: url("../static/images/comm/headerBg.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    /deep/ .mu-appbar-left {
+        padding-top: 15px;
+    }
+
+    /deep/ .material-icons {
+        color: #fff;
+    }
+
+    /deep/ .mu-appbar-title {
+        text-align: center;
+    }
+
+    #pages {
+        position: absolute;
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin-top: 0px;
+        top: 0;
+        bottom: 0;
+        padding-bottom: 200px;
+        background: #f2f2f2;
+    }
+
+    .row {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        margin-top: 10px;
+        background: #fff;
+    }
+
+    .row h5 {
+        width: 80%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        text-align: center;
+        font-size: 20px;
+        color: #FFA200;
+        padding: 20px;
+        border-bottom: 1px solid rgba(112, 112, 112, 0.14);
+        margin-bottom: 20px;
+    }
+
+    .row ul {
+        width: 80%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        margin-top: 10px;
+    }
+
+    .row li {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        margin-bottom: 10px;
+        font-size: 16px;
+    }
+
+
+    .row li em {
+        float: left;
+        min-width: 80px;
+    }
+
+    .row li span {
+        color: #6E6E6E;
+    }
+</style>

+ 376 - 0
app/src/page/enterprisemanage.vue

@@ -0,0 +1,376 @@
+<template>
+    <div id="pages">
+        <mu-appbar style="width: 100%;" color="primary" :title="$t('Business management')">
+            <router-link to="/" slot="left">
+                <mu-icon value="arrow_back"></mu-icon>
+            </router-link>
+            <mu-button flat color="primary" slot="right" @click="showPanel">{{btnText}}</mu-button>
+        </mu-appbar>
+        <mu-bottom-sheet :open.sync="popupVisible" @close="whenClose">
+            <div class="modal-content">
+                <div class="modal-body">
+                    <div class="location">
+                        <span>{{$t("query criteria")}}</span>
+                        <cityPicker></cityPicker>
+                        <span>{{$t("Keyword query")}}</span>
+                        <input type="text" placeholder="" v-model="keywords">
+                    </div>
+                </div>
+                <div class="modalBottom">
+                    <div class="reset" @click="resetModal">
+                        {{$t("Reset")}}
+                    </div>
+                    <div class="pullUp" @click="searchModal">
+                        {{$t("query")}}
+                    </div>
+                </div>
+            </div>
+        </mu-bottom-sheet>
+        <div class="listContainer">
+            <ul class="deteUl">
+                <li v-if="!lists.length">
+                    <h4>{{$t("no use data")}}</h4>
+                </li>
+                <li v-for="list in stus" v-if="lists" @click="goPage(list)">
+                    <div class="lt">
+                        <div class="rowTop">
+                            <h5>{{list.ComName}}</h5>
+                            <span>{{list.stusType}}</span>
+                            <!--<span>{{list.ComType | typeFileter}}</span>-->
+                        </div>
+                        <div class="rowDetail">
+                            <span>{{list.ProvCode}}{{list.CityCode}}{{list.AreaCode}}</span>
+                            <span class="pull-right" v-if="list.Orgs">{{list.Orgs[0].Orgname}}</span>
+                        </div>
+                    </div>
+                    <div class="rt">
+                        <mu-icon value="keyboard_arrow_right"></mu-icon>
+                    </div>
+                </li>
+                <div class="tips" v-if="lists">{{$t("total")}}{{lists.length}} {{$t("enterprise")}}</div>
+            </ul>
+        </div>
+    </div>
+</template>
+
+<script>
+    import axios from 'axios';
+
+    let qs = require('qs');
+    import Global from '../Global.js'
+    import cityPicker from '../components/cityPicker'
+
+    export default {
+        data() {
+            return {
+                popupVisible: false,//true false
+                keywords: '',
+                btnText: this.$t("search"),
+                lists: []
+            }
+        },
+        mounted() {
+            this.writeData();
+        },
+        computed: {
+            stus() {
+                let that = this;
+                let text = '';
+                /*es6写法 防止用不了this.type*/
+                return this.lists.filter((v) => {
+                    switch (parseInt(v.Status)) {
+                        case 1:
+                            text = that.$t('hotel');
+                            break;
+                        case 2:
+                            text = that.$t('tavern');
+                            break;
+                        case 3:
+                            text = 'KTV';
+                            break;
+                        case 4:
+                            text = that.$t('Prison');
+                            break;
+                        default:
+                            text = that.$t('other');
+                            break;
+                    }
+                    return v.stusType = text;
+                })
+            }
+        },
+        methods: {
+            // 重置
+            resetModal() {
+                this.keywords = '';
+                localStorage.defaultProv = '';
+                localStorage.defaultCity = '';
+                localStorage.defaultArea = '';
+            },
+            showPanel() {
+                this.popupVisible = true;
+                this.btnText = this.$t("close");
+            },
+            whenClose() {
+                this.popupVisible = false;
+                this.btnText = this.$t("search");
+            },
+            // 查询
+            searchModal() {
+                this.writeData();
+                this.popupVisible = false;
+                this.Toast('已查询', 'success');
+            },
+            goPage(list) {
+                this.$router.push({path: '/enterpriseDetail', query: {ComId: list.ComId}});
+            },
+            writeData() {
+                const that = this;
+                let url = headapi + 'v1/Company/GetComlist';
+                let pageIndex = 1;
+                let tableMax = 100;
+                let prov = localStorage.defaultProv;
+                let city = localStorage.defaultCity;
+                let area = localStorage.defaultArea;
+                let searchs = this.keywords;
+                let param = {
+                    token: localStorage.token,
+                    prov: prov,
+                    city: city,
+                    area: area,
+                    searchs: searchs,
+                    pageIndex: pageIndex,
+                    tableMax: tableMax
+                };
+                let postdata = qs.stringify(param);
+                axios.post(url, postdata).then(function (data) {
+                    let json = data.data;
+                    if (json.Code == 0) {
+                        that.lists = json.Rs;
+                    } else {
+                        this.Toast(that.TransMemo(json.Memo));
+                    }
+                }, function (response) {
+                    console.info(response);
+                })
+            }
+        },
+        components: {
+            cityPicker
+        }
+    }
+</script>
+
+<style scoped>
+    /*mu-header*/
+    .mu-primary-color {
+        line-height: 60px;
+        height: 60px;
+        background: url("../static/images/comm/headerBg.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    /deep/ .mu-appbar-left {
+        padding-top: 15px;
+    }
+
+    /deep/ .mu-appbar .material-icons {
+        color: #fff;
+    }
+
+    /deep/ .mu-appbar-title {
+        text-align: center;
+    }
+
+    #pages {
+        width: 100%;
+        height: 100%;
+        overflow: hidden;
+        overflow-y: scroll;
+        display: block;
+        margin-top: 0px;
+        padding-bottom: 20px;
+        background: #f2f2f2;
+    }
+
+    .modalSkip {
+        position: absolute;
+        top: 60px;
+        left: 0;
+        bottom: 0;
+        right: 0;
+        width: 100%;
+        height: 100%;
+        min-height: 736px;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        background: rgba(0, 0, 0, 0.35);
+    }
+
+    .listContainer {
+        width: 100%;
+        height: 100%;
+        display: block;
+        margin: 0 auto;
+        overflow-y: scroll;
+    }
+
+    .listContainer ul {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        padding-bottom: 100px;
+    }
+
+    .listContainer li {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        margin-bottom: 2px;
+        padding: 10px 20px;
+        background: #fff;
+    }
+
+    .listContainer .rowTop {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+
+    .rowTop .red {
+        color: #FFA200;
+    }
+
+    .listContainer h5 {
+        margin: 0;
+        float: left;
+        font-size: 16px;
+    }
+
+    .listContainer .rowTop span {
+        float: right;
+        font-size: 14px;
+    }
+
+    .listContainer .rowDetail {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        color: #999999;
+        font-size: 14px;
+        margin-top: 10px;
+        margin-bottom: 10px;
+    }
+
+    .deteUl .lt {
+        width: 88%;
+        float: left;
+    }
+
+    .deteUl .rt {
+        float: right;
+    }
+
+    .rt i {
+        margin-top: 20px;
+    }
+
+    .pull-right {
+        float: right;
+        text-align: right;
+    }
+
+    .tips {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        text-align: center;
+        font-size: 12px;
+        color: #999999;
+        margin-top: 20px;
+    }
+
+    /*mu-bottom-sheet*/
+    .mu-bottom-sheet {
+        top: 60px !important;
+        bottom: 405px;
+        background: none;
+    }
+
+    .location {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        /*padding-bottom: 40px;*/
+    }
+
+    .location span {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        margin-top: 10px;
+        margin-bottom: 10px;
+    }
+
+    .location input {
+        width: 95px;
+        height: 30px;
+        border: 1px solid #D5D5D5;
+        float: left;
+        text-indent: 10px;
+    }
+
+    .modal-content {
+        width: 100%;
+        display: block;
+        margin: 0 auto;
+        z-index: 99999;
+        overflow: hidden;
+    }
+
+    .modal-body {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        background: #fff;
+        padding-top: 20px;
+        padding-left: 5%;
+        padding-right: 5%;
+        padding-bottom: 40px;
+    }
+
+    .modalBottom {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        background: #fff;
+    }
+
+    .modalBottom .reset {
+        width: 50%;
+        float: left;
+        height: 40px;
+        line-height: 40px;
+        background: #FFF6CF;
+        text-align: center;
+    }
+
+    .modalBottom .pullUp {
+        width: 50%;
+        float: right;
+        height: 40px;
+        line-height: 40px;
+        background: #FFCC00;
+        text-align: center;
+    }
+</style>

+ 31 - 0
app/src/page/index.vue

@@ -0,0 +1,31 @@
+<template>
+    <div id="index">
+        <keep-alive>
+            <router-view></router-view>
+        </keep-alive>
+    </div>
+</template>
+
+<script>
+    export default {
+        data() {
+            return {}
+        },
+    }
+</script>
+<style>
+    #index {
+        position: absolute;
+        top: 0;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        height: 100%;
+        padding-top: 55px;
+        background: #333;
+        overflow-y: scroll;
+    }
+</style>

+ 518 - 0
app/src/page/lesson.vue

@@ -0,0 +1,518 @@
+<template>
+  <div class="pages">
+    <img src="../static/images/main/banner.png" height="121" width="414"/>
+    <h5 class="lessonName">
+      {{ lessonName }}
+    </h5>
+    <mu-tabs :value.sync="active" color="#F2F2F2" indicator-color="#33CAF7">
+      <mu-tab v-for="(day,i) in weeks">{{ day.name }} <br> <em>{{ day.data }}</em></mu-tab>
+    </mu-tabs>
+
+    <bottomTab :curTab="thisTab"></bottomTab>
+    <div class="context">
+      <ul class="list">
+        <li v-for="(l,index) in previewDate"
+            :style="{background:l.ClassColor}"
+        >
+          <em>
+            {{ l.BeginStr }} - {{ l.EndStr }}
+          </em>
+          <span>
+                         {{ l.ClassName }}
+                    </span>
+        </li>
+      </ul>
+    </div>
+
+  </div>
+</template>
+
+<script>
+import axios from 'axios';
+import bottomTab from '../components/bottomTab'
+import {
+  SchoolTimeQueryByDate,
+} from '../api/getApiRes.js'
+
+let qs = require('qs');
+import Global from '../Global.js'
+
+export default {
+  data() {
+    return {
+      lessonName: '本周课程表',
+      num: 0,
+      thisTab: '预约课程',
+      active: 0,
+      sum: 0,
+      openAlert: false,
+      list: [],
+      previewDate: [],
+      weeks: [],
+      dialog: {
+        id: '',
+        name: '',
+        timeLong: '',
+      },
+    }
+  },
+  mounted() {
+    this.getFurtherDays();
+  },
+  methods: {
+    // 获取未来7天的
+    getFurtherDays() {
+      let now = new Date();
+      let nowTime = now.getTime();
+      let oneDayTime = 24 * 60 * 60 * 1000;
+      let days = '';
+      let item = [];
+      let month = 0;
+      let day = 0;
+      for (let i = 0; i < 7; i++) {
+        days = new Date(nowTime + (i) * oneDayTime);//显示周日
+        month = days.getMonth() + 1;
+        day = days.getDate();
+        month = month < 10 ? '0' + month : month;
+        day = day < 10 ? '0' + day : day;
+        item = {
+          name: this.numberToWeek(days.getDay()),
+          data: days.getMonth() + 1 + '月' + days.getDate() + '日',
+          orderDate: new Date().getFullYear() + '-' + month + '-' + day
+        }
+        this.weeks.push(item);
+      }
+      this.getList();
+    },
+    numberToWeek(val) {
+      switch (parseInt(val)) {
+        case 1:
+          return '星期一'
+          break;
+        case 2:
+          return '星期二'
+          break;
+        case 3:
+          return '星期三'
+          break;
+        case 4:
+          return '星期四'
+          break;
+        case 5:
+          return '星期五'
+          break;
+        case 6:
+          return '星期六'
+          break;
+        case 0:
+          return '星期天'
+          break;
+      }
+    },
+    getList() {
+      let that = this;
+      let param = {
+        token: localStorage.token,
+        shopId: this.$route.query.shopId,
+        queryDate: that.weeks[that.active].orderDate,//(字符串 年-月-日  格式)
+      };
+      let postdata = qs.stringify(param);
+      SchoolTimeQueryByDate(postdata).then(res => {
+        let json = res;
+        if (json.Code == 0) {
+          // that.BigTitle = row.Name;
+          // that.smallTitle = row.BeginDate + '至' + row.EndDate;
+          that.previewDate = json.Rs;
+          // 前台排序
+          that.previewDate.sort((a, b) => a.ClassIndex - b.ClassIndex);//升序
+          that.previewShow = true;
+        } else {
+          that.$message.error(json.Memo);
+        }
+      })
+    },
+  },
+  beforeRouteEnter(to, from, next) {
+    next(vm => {
+      //因为当钩子执行前,组件实例还没被创建
+      // vm 就是当前组件的实例相当于上面的 this,所以在 next 方法里你就可以把 vm 当 this 来用了。
+      if (to.name == 'appoint') {
+        vm.getList();
+      }
+    });
+  },
+  watch: {
+    'active'() {
+      this.getList();
+    }
+  },
+  components: {
+    bottomTab
+  }
+}
+</script>
+
+
+<style scoped>
+.pages {
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+}
+
+.lessonName {
+  width: 100%;
+  height: 40px;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  text-align: center;
+  font-size: 18px;
+}
+
+/*mu-header*/
+.mu-primary-color {
+  line-height: 60px;
+  height: 60px;
+  background: url("../static/images/comm/headerBg.png") top center no-repeat;
+  background-size: 100%;
+}
+
+/deep/ .mu-appbar-left {
+  padding-top: 15px;
+}
+
+/deep/ .material-icons {
+  color: #fff;
+}
+
+/deep/ .mu-appbar-title {
+  text-align: center;
+}
+
+/deep/ .mu-tabs {
+  display: flex;
+  overflow-x: scroll;
+  float: left;
+}
+
+/deep/ .mu-tab {
+  width: 85px;
+  min-width: 85px;
+  float: left;
+  height: 51px;
+  margin-right: 6px;
+}
+
+/*/deep/ .mu-tab:nth-child(5) {*/
+/*    margin-right: 0px;*/
+/*}*/
+
+/deep/ .mu-tab-wrapper {
+  height: 51px;
+  background: #fff;
+  color: #363636;
+  box-shadow: 1px 0px 6px rgba(0, 0, 0, 0.16);
+  border-radius: 8px 8px 0px 0px;
+  font-size: 14px;
+}
+
+/deep/ .mu-tab-active .mu-tab-wrapper {
+  height: 56px;
+  border-radius: 8px 8px 0px 0px;
+  background: #33caf7;
+  box-shadow: 1px 0px 6px rgba(0, 0, 0, 0.16);
+  color: #fff;
+}
+
+/deep/ .mu-tab-wrapper em {
+  font-size: 12px;
+}
+
+.sum {
+  width: 100%;
+  height: 55px;
+  line-height: 55px;
+  background: #fff;
+  font-family: "PingFang SC";
+  font-weight: 300;
+  font-size: 16px;
+  text-align: center;
+  color: #909090;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+}
+
+.green {
+  color: #37CB00;
+}
+
+.red {
+  color: #F8847F;
+}
+
+.list {
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  margin-top: 8px;
+  padding-bottom: 30px;
+  border-top: 5px solid #fff;
+}
+
+.list li {
+  width: 100%;
+  height: 50px;
+  margin: 0;
+  border-bottom: 1px solid #fff;
+  list-style: none;
+  line-height: 50px;
+  /*padding-top: 16px;*/
+  /*padding-bottom: 16px;*/
+}
+
+li em {
+  width: 50%;
+  float: left;
+  padding-left: 10%;
+  /*height: 40px;*/
+  /*line-height: 40px;*/
+  overflow: hidden;
+  border-right: 1px solid #fff;
+  color: #333;
+  /*font-size: 16px;*/
+}
+
+li span {
+  width: 45%;
+  float: right;
+  padding-left: 3px;
+  /*height: 40px;*/
+  /*line-height: 40px;*/
+  overflow: hidden;
+  text-align: center;
+  color: #333;
+  /*font-size: 16px;*/
+}
+
+.list .dotContainer {
+  width: 50px;
+  float: left;
+  height: 60px;
+  padding-left: 22px;
+  padding-top: 10px;
+}
+
+.dotContainer .dot {
+  width: 12px;
+  height: 12px;
+  background: #37cb00;
+  border-radius: 250px;
+  float: left;
+}
+
+.cubes {
+  width: 12px;
+  height: 12px;
+  background: #f8847f;
+  float: left;
+}
+
+.tri {
+  width: 12px;
+  height: 12px;
+  background: url("../static/images/appoint/tri.png") top center no-repeat;
+  background-size: 100% 100%;
+  float: left;
+}
+
+.x {
+  width: 12px;
+  height: 12px;
+  background: url("../static/images/appoint/x.png") top center no-repeat;
+  background-size: 100% 100%;
+  float: left;
+}
+
+
+.yellowLi {
+  background: #FFFBED;
+}
+
+.redLi {
+  background: #FFF7F7;
+}
+
+.greenLi {
+  background: #F7FFF4;
+}
+
+.whiteLi {
+  background: #fff;
+}
+
+.list li .title {
+  width: 90px;
+  height: 60px;
+  float: left;
+}
+
+li .title h5 {
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  font-weight: normal;
+  font-size: 14px;
+  text-align: left;
+  color: #3b3b3b;
+}
+
+li .title span {
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  font-weight: normal;
+  font-size: 12px;
+  text-align: left;
+  color: #909090;
+}
+
+.list li .current {
+  width: 120px;
+  height: 60px;
+  float: left;
+}
+
+li .current h5 {
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  font-family: "PingFang SC";
+  font-weight: normal;
+  font-size: 14px;
+  text-align: left;
+  color: #3b3b3b;
+}
+
+.current h5 em {
+  font-family: "PingFang SC";
+  font-weight: normal;
+  font-size: 14px;
+  text-align: left;
+}
+
+.current span {
+  font-family: "PingFang SC";
+  font-weight: normal;
+  font-size: 12px;
+  text-align: left;
+  color: #909090;
+}
+
+.appointBtn {
+  width: 79px;
+  height: 37px;
+  border-radius: 18.5px;
+  background: #fff;
+  float: right;
+  font-family: "PingFang SC";
+  font-weight: normal;
+  font-size: 18px;
+  margin-right: 2%;
+}
+
+.greenBtn {
+  border: 1px solid #37cb00;
+  color: #37cb00;
+}
+
+.redBtn {
+  border: 1px solid #F8847F;
+  color: #F8847F;
+}
+
+.yellowBtn {
+  border: 1px solid #FFB43C;
+  color: #fff;
+  background: #FFB43C;
+}
+
+.disableBtn {
+  border: 1px solid #C9C9C9;
+  color: #C9C9C9;
+}
+
+/deep/ .mu-tabs-center {
+  display: flex;
+  overflow-x: auto;
+  overflow-y: hidden;
+  white-space: nowrap;
+}
+
+/deep/ .mu-tabs-center::-webkit-scrollbar {
+  display: none;
+}
+
+/deep/ .mu-modal-inner {
+  width: 90%;
+  float: left;
+}
+
+/deep/ .mu-tab-link-highlight {
+  display: none !important;
+}
+
+li .title span.lessons {
+  width: auto;
+  padding: 1px 11px;
+  border-radius: 250px;
+  float: left;
+  text-align: center;
+  color: #000;
+  font-size: 14px;
+}
+
+/deep/ .mu-avatar {
+  position: fixed;
+  bottom: 10%;
+  float: right;
+  right: 10%;
+}
+
+
+@media only screen and (max-width: 640px) {
+
+}
+
+@media only screen and (max-width: 480px) {
+
+}
+
+@media only screen and (max-width: 375px) {
+
+}
+
+@media only screen and (max-width: 360px) {
+
+}
+
+@media only screen and (max-width: 320px) {
+  .list .dotContainer {
+    width: 20px;
+    padding-left: 5px;
+  }
+
+  .list li .title {
+    width: 85px;
+  }
+}
+
+@media only screen and (min-width: 641px) {
+
+}
+</style>

+ 354 - 0
app/src/page/listDetail.vue

@@ -0,0 +1,354 @@
+<template>
+    <div id="pages">
+        <mu-appbar style="width: 100%;" color="primary" :title="$t('detail')">
+                <span @click="$router.back(-1)" slot="left">
+                       <mu-icon value="arrow_back"></mu-icon>
+                </span>
+        </mu-appbar>
+        <div class="container listContainer">
+            <div class="row ">
+                <ul class="deteUl" v-if="selected == 1">
+                    <li v-if="!lists.length">
+                        <h4>{{$t("no use data")}}</h4>
+                    </li>
+                    <li v-for="list in lists" v-if="lists">
+                        <div class="rowTop"><h5>{{list.Name}}</h5>
+                            <span v-if="list.DangerLevel == -1" class="green">{{$t("other")}}</span>
+                            <span v-if="list.DangerLevel == 0" class="green">{{$t("white")}}</span>
+                            <span v-if="list.DangerLevel == 2" class="yellow">{{$t("deal")}}</span>
+                            <span v-if="list.DangerLevel == 3" class="red">{{$t("warning")}}</span>
+                            <span v-if="list.DangerLevel == 4" class="red">{{$t("danger")}}</span>
+                        </div>
+                        <div class="rowDetail">
+                            <span>{{list.MacCom.length > 16 ? list.MacCom.slice(0, 16)+'...':list.MacCom}}</span>
+                            <s>{{list.Mac}}</s>
+                        </div>
+                        <div class="rowBottom">
+                            {{list.Memo}}
+                        </div>
+                    </li>
+                    <s class="tips" v-if="lists"> {{$t("total")}} {{lists.length}} {{$t("pcs")}} {{$t("wireless device")}}</s>
+                </ul>
+                <ul class="phoneUl" v-if="selected == 2">
+                    <li v-if="!phones">
+                        <h4>{{$t("no use data")}}</h4>
+                    </li>
+                    <li v-for="phone in phones" v-if="phones">
+                        <div class="peTop">
+                            {{phone.DetectorName}} <span>{{phone.RegionName}}</span>
+                        </div>
+                        <div class="peMemo">
+                            {{phone.Signalstr == ''?$t('No mobile signal detected'):phone.Signalstr}}
+                        </div>
+                    </li>
+                    <s class="tips" v-if="phones">  {{$t("total")}}{{phones.length}} {{$t("pcs")}} {{$t("Detection")}}</s>
+                </ul>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+    import axios from 'axios';
+
+    let qs = require('qs');
+    import Global from '../Global.js'
+
+    export default {
+        data() {
+            return {
+                selected: "1",
+                location: {
+                    ComName: this.$route.query.comName,
+                    Region: this.$route.query.Region,
+                },
+                RegionList: [],
+                unite: {
+                    ComName: '',
+                    Legal: '',
+                    Introduction: '',
+                },
+                lists: [],
+                phones: [],
+            }
+        },
+        mounted() {
+            this.readList();
+        },
+        methods: {
+            // 读取无线设备具体分布
+            readList() {
+                const that = this;
+                let url = headapi + 'v1/Company/RegionDetectDeviceDetailList';
+                let param = {
+                    token: localStorage.token,
+                    regionId: this.$route.query.RegionId
+                };
+                let postdata = qs.stringify(param);
+                axios.post(url, postdata).then(function (data) {
+                    let json = data.data;
+                    if (json.Code == 0) {
+                        that.lists = json.Rs;
+                    } else {
+                        this.Toast(that.TransMemo(json.Memo));
+                    }
+                }, function (response) {
+                    console.info(response);
+                })
+            },
+            goListDetail(list) {
+                this.$router.push({path: '/list', query: {RegionId: list.RegionId}});
+            },
+            readPhone() {
+                const that = this;
+                let url = headapi + 'v1/Detector/SignalDeviceByregion';
+                let param = {
+                    token: localStorage.token,
+                    regionid: this.$route.query.RegionId
+                };
+                let postdata = qs.stringify(param);
+                axios.post(url, postdata).then(function (data) {
+                    let json = data.data;
+                    if (json.Code == 0) {
+                        that.phones = json.Rs;
+                    } else {
+                        this.Toast(that.TransMemo(json.Memo));
+                    }
+                }, function (response) {
+                    console.info(response);
+                })
+            }
+        },
+    }
+</script>
+
+<style scoped>
+    /*mu-header*/
+    .mu-primary-color {
+        line-height: 60px;
+        height: 60px;
+        background: url("../static/images/comm/headerBg.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    /deep/ .mu-appbar-left {
+        padding-top: 15px;
+    }
+
+    /deep/ .material-icons {
+        color: #fff;
+    }
+
+    /deep/ .mu-appbar-title {
+        text-align: center;
+    }
+ #pages {
+     width: 100%;
+     overflow: hidden;
+     overflow-y: scroll;
+     display: block;
+     margin: 0 auto;
+     height: 100%;
+     position: absolute;
+     top: 0;
+     bottom: 0;
+     background: #f2f2f2;
+     padding-bottom: 20px;
+ }
+    .detail {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        padding-top: 0px;
+        padding-bottom: 20px;
+        padding-left: 2%;
+        padding-right: 2%;
+        margin-bottom: 10px;
+        background: #fff;
+    }
+    .detail ul {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        padding-left: 2%;
+        padding-right: 2%;
+    }
+
+    .detail h5 span {
+        font-size: 16px;
+    }
+
+    .detail h5 em {
+        float: right;
+        color: #666666;
+        font-size: 12px;
+        font-weight: normal;
+        text-align: right;
+    }
+
+    .detail p {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        font-size: 12px;
+        color: #666666;
+        line-height: 16px;
+    }
+
+    /deep/ .mint-navbar .mint-tab-item.is-selected {
+        border-bottom: 3px solid #FFA200;
+        color: #FFA200;
+    }
+
+    /deep/ .mint-navbar .mint-tab-item.is-selected .mint-tab-item-label {
+        color: #FFA200;
+    }
+
+    .listContainer ul {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+
+    .listContainer li {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        margin-bottom: 2px;
+        padding: 10px 20px;
+        background: #fff;
+    }
+
+    .listContainer .rowTop {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+
+    .rowTop .red {
+        color: #FFA200;
+    }
+
+    .listContainer h5 {
+        margin: 0;
+        float: left;
+        font-size: 16px;
+    }
+
+    .listContainer .rowTop span {
+        float: right;
+        font-size: 14px;
+    }
+
+    .listContainer .rowDetail {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        color: #999999;
+        font-size: 14px;
+        margin-top: 10px;
+        margin-bottom: 10px;
+    }
+
+    .rowDetail span {
+        float: left;
+    }
+
+    .rowDetail s {
+        float: right;
+    }
+
+    .rowBottom {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        font-size: 12px;
+        color: #999999;
+    }
+
+
+    .location {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        padding: 11px 4%;
+        font-size: 12px;
+        color: #999999;
+    }
+
+    .tips {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        text-align: center;
+        font-size: 12px;
+        color: #999999;
+        margin-top: 10px;
+    }
+
+    .phoneUl {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+
+    .phoneUl li {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        margin-bottom: 2px;
+        padding: 10px 20px;
+        background: #fff;
+    }
+
+    .phoneUl .peTop {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        font-size: 16px;
+        margin-bottom: 10px;
+    }
+
+    .peTop span {
+        float: right;
+        text-align: right;
+        font-size: 14px;
+    }
+
+    .peMemo {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        font-size: 14px;
+        color: #999999;
+    }
+    .deteUl {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+    .deteUl li h4 {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        text-align: center;
+        font-weight: normal;
+        line-height: 30px;
+    }
+</style>

+ 666 - 0
app/src/page/login.vue

@@ -0,0 +1,666 @@
+<template>
+  <div id="skin-blur-violate">
+    <section id="login">
+      <header>
+        <img src="../static/images/login/logo.png" height="109" width="109" id="logo"/>
+        <img src="../static/images/login/title.png" height="100%" width="274px"/>
+      </header>
+      <div class="clearfix"></div>
+      <!-- Login -->
+      <form class="box tile animated active" id="box-login">
+        <h2 class="m-t-0 m-b-15"></h2>
+        <div class="rowHeight">
+          <input type="text" class="login-control login_account" placeholder="输入手机号"
+                 v-model="login.phone">
+        </div>
+        <div class="rowHeight">
+          <input type="number" class="login-control login_valid" placeholder="输入右侧图形码"
+                 v-model="login.uservalid">
+          <img id="imgValidcode" :src="valImgSrc" :title="InvisibilityGiveitatry" @click="getValImgSrc">
+        </div>
+        <div class="rowHeight">
+          <input type="number" class="login-control login_pwd" placeholder="输入验证码" v-model="login.userpwd"
+                 @keyup.enter="pwdLoginBtn">
+          <mu-button id="getValidSms" :disabled="getValidSmsState" color="success" @click="getValidSmsBtn">
+            {{ btnText }}
+          </mu-button>
+        </div>
+        <div class="btn_center">
+          <span class="btn btn-md login_btn" @click="pwdLoginBtn">登    录</span>
+        </div>
+      </form>
+    </section>
+    <mu-snackbar :position="normal.position" :open.sync="normal.open" :color="normal.color">
+      {{ normal.message }}
+      <mu-button flat slot="action" color="secondary" @click="normal.open = false">{{ "close" }}</mu-button>
+    </mu-snackbar>
+  </div>
+</template>
+
+<script>
+import {
+  SignIn,
+  GenVerifyPic,
+  GetPhoneVFCode,
+  PhoneSignIn,
+  WXBind,
+  testSelect
+} from '../api/getApiRes.js'
+
+let qs = require('qs');
+
+export default {
+  data() {
+    let samepass = (rule, value, callback) => {
+      if (value !== this.form.newpwd) {
+        callback(new Error('两次输入密码不一致!'));
+      } else {
+        callback();
+      }
+    };
+    let pwdPass = (rule, value, callback) => {
+      let re = /^[0-9a-zA-Z_]{1,}$/;
+      if (value.search(re) == -1) {
+        callback(new Error('错了哦,密码只能由字母、数字及下划线组成'));
+      } else {
+        callback()
+      }
+    };
+    let phonetest = (rule, value, callback) => {
+      let re = /^1[3|4|5|7|8|9][0-9]\d{8}$/;
+      if (value.search(re) == -1) {
+        callback(new Error('错了哦,手机号码格式不正确'));
+      } else {
+        callback()
+      }
+    };
+    return {
+      Password: "Password",
+      VerificationCode: "Verification Code",
+      InvisibilityGiveitatry: "无效?再点一下试试吧!",
+      valImgSrc: '',//
+      picId: '',//
+      getValidSmsState: false,//
+      overtime: '',
+      btnText: '获取验证码',
+      normal: normal,
+      login: {
+        phone: '',
+        userpwd: '',
+        uservalid: '',
+      },
+      rules: {
+        username: [
+          {required: true, message: '请输入用户名', trigger: 'blur'},
+          {min: 6, max: 32, message: '长度在 6 到 32 个字符', trigger: 'blur'},
+        ],
+        phone: [
+          {required: true, message: '请输入手机号', trigger: 'blur'},
+          {min: 11, max: 12, message: '手机号长度是11位', trigger: 'blur'},
+          {validator: phonetest, trigger: 'blur'}
+        ],
+        re_phonevalid: [
+          {required: true, message: '请输入验证码', trigger: 'blur'},
+          {min: 4, max: 4, message: '长度在 4 个字符', trigger: 'blur'},
+        ],
+        newpwd: [
+          {required: true, message: '请输入新密码', trigger: 'blur'},
+          {min: 6, max: 32, message: '长度在 6 到 32 个字符', trigger: 'blur'},
+          {validator: pwdPass, trigger: 'blur'}
+        ],
+        again: [
+          {required: true, message: '请输入确认密码', trigger: 'blur'},
+          {min: 6, max: 32, message: '长度在 6 到 32 个字符', trigger: 'blur'},
+          {validator: pwdPass, trigger: 'blur'},
+          {validator: samepass, trigger: 'blur'},
+        ],
+      }
+    }
+  },
+  mounted() {
+    // 入口状态有 3 种
+    // 1.全新登入,拿weixinId 拿验证码 ,绑定 ,登陆
+    // 2.token 未失效用户,直接进入内页,继续凭token使用
+    // 3.token 已失效用户,删掉本地token ,重新按照1的模式登陆
+    if (localStorage.token) {
+      // 凭借旧token直接登陆
+      this.$router.push({path: '/'});
+    } else {
+      // 获取图形验证码
+      this.getValImgSrc();
+      this.overtime = new Date();
+      let from = this.$route.query.from;//获取来源
+      let userAgent = navigator.userAgent;
+      let host = window.location.host;
+      console.log(host);
+      if (from == 'app' || host == '192.168.0.162:8080') {//判断是否微信浏览器
+        // 浏览器测试
+        console.log('from app & brower');
+      } else {
+        console.log('form wx');
+        this.checkcode();
+      }
+    }
+  },
+  methods: {
+    // 获取CODE
+    checkcode() {
+      // 0213tIFa1fBjAz0OVDIa1LfXwc03tIFK
+      if (this.getUrlKey('state') == 123) {
+        // 取到值了
+        localStorage.code = this.getUrlKey('code');
+        // console.log('code:' + localStorage.code);
+      } else {
+        // 第一次加载
+        this.GetOpenId();
+      }
+    },
+    // 获取公众号ID
+    GetOpenId() {
+      let origin = location.href;
+      // let origin = 'http://wx.xfeilong.com';
+      let urlNow = encodeURIComponent(origin);
+      let scope = 'snsapi_userinfo';    //snsapi_userinfo   //静默授权 用户无感知
+      let appid = 'wx36cb8b6661d71811';//正式
+      let state = '123';
+      let url = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=' + appid + '&redirect_uri=' + urlNow + '&response_type=code&scope=' + scope + '&state=' + state + '#wechat_redirect';
+      self.location = url;
+    },
+    getUrlKey(name) {
+      return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.href) || [, ""])[1].replace(/\+/g, '%20')) || null;
+    },
+    // 获取验证码
+    getValidSmsBtn() {
+      let that = this;
+      let phone = that.login.phone;
+      let uservalid = that.login.uservalid;
+      if (!phone) {
+        that.Toast('手机号不能为空');
+        return false
+      }
+      if (phone.length != 11) {
+        that.Toast('手机号只能是11位');
+        return false
+      }
+      if (!globalCheckPhone(phone)) {
+        that.Toast('手机号格式不正确');
+        return false
+      }
+      if (!uservalid) {
+        that.Toast('图形验证码不能为空');
+        return false
+      }
+      if (uservalid.length != 4) {
+        that.Toast('图形验证码只能是4位');
+        return false
+      }
+      let param = {
+        token: localStorage.token,
+        phone: phone,
+        codeType: 1,
+        picId: this.valImgId,
+        picCode: uservalid,
+      };
+      let postdata = qs.stringify(param);
+      GetPhoneVFCode(postdata).then(res => {
+        let json = res;
+        if (json.Code == 0) {
+          that.Toast('短信验证码已发送', 'success');
+          that.calcTime();
+        } else {
+          that.Toast(json.Memo);
+        }
+      })
+    },
+    calcTime() {
+      // 短信倒数计时
+      let countdown = 60;
+      let that = this;
+      //设置button效果,开始计时
+      that.getValidSmsState = true;
+      that.btnText = countdown + "S"
+      //启动计时器,1秒执行一次
+      let timer = setInterval(function () {
+        if (countdown == 0) {
+          clearInterval(timer);//停止计时器
+          that.getValidSmsState = false;
+          that.btnText = "重新发送"
+        } else {
+          countdown--;
+          that.btnText = countdown + "S"
+        }
+      }, 1000);
+    },
+    clearLogin() {
+      this.login.username = '';
+      this.login.userpwd = '';
+      this.login.uservalid = '';
+      this.getValImgSrc();
+    },
+    // 点击验证码切换
+    getValImgSrc() {
+      let that = this;
+      let param = {
+        token: localStorage.token,
+        width: 100,
+        height: 30,
+        noiseCount: 1,
+        length: 4,
+        source: 123456789,
+      };
+      let postdata = qs.stringify(param);
+      GenVerifyPic(postdata).then(res => {
+        let json = res;
+        that.valImgSrc = json.Pic;
+        that.valImgId = json.Id;
+      })
+    },
+    // pwd登录
+    pwdLoginBtn() {
+      let that = this;
+      let phone = this.login.phone;
+      let userpwd = this.login.userpwd;
+      // 重置验证码超时
+      that.overtime = new Date();
+      if (!that.globalValid(phone, 10, 12, '手机号', that)) return;
+      if (!that.globalValid(userpwd, 5, 7, '短信验证码', that)) return;
+      this.loginInfo();
+    },
+    // 校验内容长度
+    globalValid(data, mins, maxs, text, that) {
+      let thisVal = data;
+      let thisLeng = thisVal.length;
+      let min = parseInt(mins);
+      let max = parseInt(maxs);
+      let dispalyMin = min + 1;
+      if (thisVal == '') {
+        this.Toast(text + ' ' + '不能为空');
+        return false
+      } else if (thisLeng <= min) {
+        this.Toast(text + '最少' + dispalyMin + '字符');
+        return false
+      } else if (thisLeng > max) {
+        this.Toast(text + '超过限制长度');
+        return false
+      } else {
+        return true
+      }
+    },
+    // pwd登陆
+    loginInfo: function () {
+      const that = this;
+      let current = new Date();
+      let betweenTime = current - that.overtime;
+      let s = 120;
+      if (betweenTime > s * 1000) {
+        that.changeValImg();
+        that.$toast.message('验证码已超时,请重新输入');
+        return false
+      }
+      let param = {
+        phone: that.login.phone,
+        code: that.login.userpwd,
+        channel: 3
+      };
+      let postdata = qs.stringify(param);
+      PhoneSignIn(postdata).then(res => {
+        if (res.Code == 0) {
+          that.res = res.Rs;
+          // 使用token做免校验登陆
+          localStorage.token = res.Rs.token;
+          // 如果是wx登陆就执行绑定操作
+          let from = this.$route.query.from;//获取来源
+          if (from != 'app') {
+            that.bindWx();
+          }
+
+          // 607862e8828013be90c2ccb78468b43a
+          // test
+          that.$router.push({path: '/'});
+        } else {
+          this.getValImgSrc();
+          if (res.Code == 10005) {
+            that.$refs.userpwd.value = '';
+            that.Toast('密码错误,请重新输入');
+          } else {
+            that.Toast(res.Memo + ',错误代码:' + res.Code);
+            that.form.valid = '';
+          }
+        }
+      })
+    },
+    bindWx() {
+      let that = this;
+      let param = {
+        token: localStorage.token,
+        code: localStorage.code,
+      };
+      let postdata = qs.stringify(param);
+      WXBind(postdata).then(res => {
+        let json = res;
+        if (json.Code == 0) {
+          // that.$router.push({path: '/'});
+        } else {
+          // that.Toast(res.Memo + ',错误代码:' + res.Code);
+        }
+      })
+    },
+    getUserInfo(token) {
+      let that = this;
+      let param = {
+        token: token,
+      };
+      let postdata = qs.stringify(param);
+      testSelect(postdata).then(res => {
+        let json = res;
+        if (json.Code == 0) {
+          var userLevel = json.Rs.Rolesname;
+          localStorage.userLevel = userLevel;
+          localStorage.comId = json.Rs.Comid;
+          localStorage.Insname = json.Rs.Insname;
+          that.$router.push({path: '/'});
+        } else {
+          that.$toast.message(json.Memo);
+        }
+      })
+    }
+  },
+  components: {}
+}
+</script>
+
+<style scoped>
+#skin-blur-violate {
+  position: relative;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  background: #3B3B3B;
+  background: url("../static/images/login/bg.png") top center no-repeat;
+  background-size: 100% 100%;
+}
+
+#login {
+  width: 90%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+}
+
+#login .box {
+  margin: 0 auto;
+  position: inherit;
+  margin-top: 20px;
+  border-radius: 9px;
+  padding: 20px 20px;
+}
+
+h1 {
+  color: #FFA200;
+  font-size: 30px;
+}
+
+header p {
+  font-size: 14px;
+  color: #7B7B7B;
+}
+
+#login header {
+  text-align: center;
+  margin-top: 15%;
+}
+
+#box-login h2 {
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  margin-bottom: 20px;
+  text-align: center;
+  font-size: 24px;
+  color: #fff;
+}
+
+#tableBordered {
+  margin: 0;
+  padding: 0;
+}
+
+#tableBordered h5 {
+  margin: 0;
+  text-align: center;
+  padding: 0;
+}
+
+#login .box {
+  margin: 0 auto;
+  position: inherit;
+  margin-top: 20px;
+  border-radius: 9px !important;
+}
+
+#login header {
+  text-align: center;
+  margin-top: 15%;
+}
+
+#tableBordered {
+  margin: 0;
+  padding: 0;
+}
+
+#tableBordered h5 {
+  margin: 0;
+  text-align: center;
+  padding: 0;
+}
+
+#imgValidcode {
+  position: relative;
+  float: right;
+  /*bottom: 54px;*/
+  /*width: 100px;*/
+  width: 30%;
+  height: 50px;
+  background: #eee;
+}
+
+.login_btn {
+  width: 100%;
+  height: 50px;
+  line-height: 50px;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  margin-top: 42px;
+  background: #E75296;
+  color: #fff;
+  font-size: 14px;
+  text-align: center;
+  border: none;
+  padding: 0;
+  font-size: 24px;
+  margin-bottom: 3%;
+}
+
+.clear_btn {
+  width: 100%;
+  height: 40px;
+  line-height: 40px;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  background: rgba(255, 255, 255, 0.32);
+  color: #FFCC00;
+  font-size: 14px;
+  text-align: center;
+  border: none;
+  padding: 0;
+}
+
+header p {
+  margin-top: 10px;
+}
+
+#login .login-control {
+  width: 100%;
+  height: 50px;
+  line-height: 50px;
+  background: rgba(255, 255, 255, 0.4);
+  margin-bottom: 3px;
+  text-indent: 10px;
+  border: none;
+
+}
+
+#login .login-control::placeholder {
+  color: #000000;
+  font-size: 16px;
+}
+
+#logo {
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  margin-top: 10%;
+  margin-bottom: 10px;
+}
+
+.rowHeight {
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  height: 50px;
+  margin-bottom: 3px;
+}
+
+#getValidSms {
+  /*width: 100px;*/
+  width: 30%;
+  height: 50px;
+  background: #fff;
+  border: 1px solid #fff;
+  opacity: 0.6;
+  position: relative;
+  /*bottom: 55px;*/
+  float: right;
+  text-align: center;
+  color: #E75296;
+  line-height: 20px;
+  font-size: 12px;
+  min-width: 30px;
+}
+
+#login .login_valid {
+  /*width: 173px;*/
+  width:65%;
+  float: left;
+}
+
+#login .login_pwd {
+  width: 173px;
+  float: left;
+}
+
+@media only screen and (max-width: 640px) {
+
+}
+
+@media only screen and (max-width: 480px) {
+  #login .login_valid {
+    /*width: 195px;*/
+    width:65%;
+  }
+
+  #login .login_pwd {
+    /*width: 195px;*/
+    width:65%;
+  }
+}
+
+@media only screen and (max-width: 414px) {
+  #login .login_valid {
+    width:65%;
+    /*width: 223px;*/
+  }
+
+  #login .login_pwd {
+    /*width: 223px;*/
+    width:65%;
+  }
+}
+
+@media only screen and (max-width: 400px) {
+
+  #login .login_valid {
+    width:65%;
+    /*width: 218px;*/
+  }
+
+  #login .login_pwd {
+    /*width: 218px;*/
+    width:65%;
+  }
+
+  #getValidSms {
+    font-size: 13px;
+  }
+}
+
+@media only screen and (max-width: 375px) {
+  #login .login_valid {
+    /*width: 190px;*/
+    width:65%;
+  }
+
+  #login .login_pwd {
+    /*width: 190px;*/
+    width:65%;
+  }
+
+  #getValidSms {
+    font-size: 14px;
+  }
+}
+
+@media only screen and (max-width: 360px) {
+  #login .login_valid {
+    /*width: 160px;*/
+    width:65%;
+  }
+
+  #login .login_pwd {
+    /*width: 160px;*/
+    width:65%;
+  }
+
+  #getValidSms {
+    font-size: 14px;
+  }
+}
+
+@media only screen and (max-width: 320px) {
+  #login .login_valid {
+    /*width: 144px;*/
+    width:65%;
+  }
+
+  #login .login_pwd {
+    width:65%;
+    /*width: 144px;*/
+  }
+
+  #getValidSms {
+    font-size: 12px;
+  }
+}
+
+
+</style>

+ 184 - 0
app/src/page/mainpage.vue

@@ -0,0 +1,184 @@
+<template>
+    <div id="mainPage">
+        <bottomTab :curTab="thisTab"></bottomTab>
+        <alert ref="alertPart"></alert>
+        <div class="container">
+            <mu-row gutter>
+                <mu-col span="12">
+                    <div class="grid-cell">
+                        <timePart></timePart>
+                    </div>
+                </mu-col>
+            </mu-row>
+
+        </div>
+    </div>
+</template>
+
+<script>
+    import {
+        ManagerSelfQuery,
+        OrderShopQuery,
+    } from '../api/getApiRes.js'
+
+    import bottomTab from '../components/bottomTab'
+    import alert from '../components/alert'
+    import axios from 'axios';
+    import timePart from '@/components/timePart.vue'
+    let qs = require('qs');
+    import Global from '../Global.js'
+
+    export default {
+        data() {
+            return {
+                thisTab: 'STATE',
+            }
+        },
+        mounted() {
+            // this.getManagerSelfQuery();
+        },
+        destroyed() {
+        },
+        methods: {
+            alertInfo(info) {
+                this.$refs.alertPart.openSimpleDialog(info);
+            },
+            getManagerSelfQuery() {
+                let that = this;
+                let param = {
+                    token: localStorage.token,
+                };
+                let postdata = qs.stringify(param);
+                ManagerSelfQuery(postdata).then(res => {
+                    let json = res;
+                    if (json.Code == 0) {
+                        this.currShopId = json.Rs.ShopId;
+                        this.getList();
+                    } else {
+                        that.alertInfo(json.Memo);
+                        if (json.Code == 1010) {
+                            localStorage.clear();
+                            console.log(1010);
+                            that.$router.push({path: '/login'});
+                        }
+                    }
+                })
+            },
+            getList() {
+                let that = this;
+                let param = {
+                    token: localStorage.token,
+                };
+                let postdata = qs.stringify(param);
+                OrderShopQuery(postdata).then(res => {
+                    let json = res;
+                    if (json.Code == 0) {
+                        that.list = json.Rs;
+                        if (that.list) {
+                            that.shopNum = json.Rs.length;
+                        }
+                    } else {
+                        that.alertInfo(json.Memo);
+                        // 权限失效后,删掉本地token
+                        if (json.Code == 1004) {
+                            localStorage.clear();
+                            console.log(1010);
+                            // this.$router.push({path: '/login'});
+                        }
+                    }
+                })
+            },
+            onGoNewPage(path) {
+                this.$router.push({path: '/' + path});
+            },
+            goPage(pages) {
+                this.$router.push({path: pages});
+            },
+            goAppoint(row) {
+                let that = this;
+                if (row.IsJoin == 0) {
+                    that.alertInfo('您不是该店会员,不可预约');
+                    return false
+                }
+                if (row.Status == 2) {
+                    that.alertInfo(row.name + '不可预约');
+                    return false
+                } else {
+                    this.$router.push({
+                        path: '/appoint', query: {
+                            shopId: row.ShopID
+                        }
+                    });
+                }
+            }
+        },
+        beforeRouteEnter(to, from, next) {
+            next(vm => {
+                //因为当钩子执行前,组件实例还没被创建
+                // vm 就是当前组件的实例相当于上面的 this,所以在 next 方法里你就可以把 vm 当 this 来用了。
+                if (to.name == '') {
+                    vm.getList();
+                }
+            });
+        },
+        watch: {
+            $route(to) {
+                if (to.name == '') {
+                    this.getList();
+                }
+            },
+            'active'() {
+                this.getList();
+            }
+        },
+        components: {
+            bottomTab, alert ,timePart
+        }
+    }
+</script>
+
+<style scoped>
+    #mainPage {
+        width: 100%;
+        height: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        background: #000;
+        /*background-image: url("../static/images/comm/logo.png");*/
+        /*background-position: top center;*/
+        /*background-repeat: no-repeat;*/
+        overflow-y: scroll;
+        color: red;
+    }
+
+    .imgContainer {
+        width: 100%;
+        height: 2rem;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        border: 2px solid red;
+    }
+
+    .imgContainer img {
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+
+    h5 {
+        font-size: 30px;
+        margin: 0;
+        text-align: center;
+    }
+
+    /deep/ .mu-item-action {
+        color: red;
+    }
+
+    /deep/ .mu-item-title {
+        color: red;
+    }
+
+</style>

+ 51 - 0
app/src/page/map.vue

@@ -0,0 +1,51 @@
+<template>
+    <div id="map">
+        <appHeader @goNewpage="onGoNewPage" :title="this.pagetitle"></appHeader>
+        <bottomTab :curTab="thisTab"></bottomTab>
+        <mapPage @drag="dragMap" :curheight="curheight" :divcontainer="'js-container2'"></mapPage>
+    </div>
+</template>
+
+<script>
+    import appHeader from '../components/appHeader'
+    import bottomTab from '../components/bottomTab'
+    import mapPage from '../components/mapPage'
+    export default {
+        data() {
+            return {
+                pagetitle: this.$t('Map'),
+                thisTab:  this.$t('Map'),
+                curheight:  window.screen.height,
+            }
+        },
+        mounted(){
+            console.log(window.screen.height);
+        },
+        methods: {
+            onGoNewPage(path) {
+                this.$router.push({path: '/' + path});
+            },
+            dragMap() {
+            },
+        },
+      components: {
+          mapPage,appHeader,bottomTab
+      }
+    }
+</script>
+
+<style scoped>
+    #map {
+        position: absolute;
+        top: 0;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin-top: 0px;
+        padding-bottom: 0px;
+        background: #f2f2f2;
+    }
+</style>

+ 542 - 0
app/src/page/mine.vue

@@ -0,0 +1,542 @@
+<template>
+  <div class="pages">
+    <img src="../static/images/main/banner.png" height="121" width="414"/>
+    <div class="context">
+              <span class="num">
+                会员卡信息
+            </span>
+      <div class="user">
+        <img src="../static/images/mine/User.png" height="53" width="53"/>
+        <span>{{ user.Name }}</span>
+        <em>{{ user.Phone  | hidePhone}}</em>
+      </div>
+      <div class="value" v-for="s in schools" v-if="s.IsJoin == 1">
+        <div class="vTitle year" v-if="s.VipType == 1"><i></i>年会员</div>
+        <div class="vTitle price" v-if="s.VipType == 2"><i></i>充值会员</div>
+        <div class="vNum">
+          <span> {{ s.ShopName }}</span>
+          <div class="center">
+            总计{{ s.ClassHourToatal }}课时
+          </div>
+          <em v-if="s.VipType == 1">(有效期至{{ s.ExpTime |fmtTime }})</em>
+        </div>
+        <mu-flex class="linear-progress">
+          <mu-linear-progress mode="determinate" :value="s.ClassHourRemain / s.ClassHourToatal *100" :size="10"
+                              color="secondary"></mu-linear-progress>
+        </mu-flex>
+        <div class="limit">
+          <em>剩余 {{ s.ClassHourRemain }} 课时</em>
+          <span>完成 {{ s.ClassHourConsume }} 课时</span>
+        </div>
+      </div>
+      <div class="dataSum">
+        <div class="row">
+          <em>卡路里(月度)</em>
+          <span>{{ ckRs.CleMonth }}</span>
+        </div>
+      </div>
+      <div class="dataSum">
+        <div class="row">
+          <em>总卡路里</em>
+          <span>{{ ckRs.Cle }}</span>
+        </div>
+      </div>
+      <div class="dataSum">
+        <div class="row">
+          <em>CK(月度)</em>
+          <span>{{ ckRs.CkMonth }}</span>
+        </div>
+      </div>
+      <div class="dataSum">
+        <div class="row">
+          <em>总CK</em>
+          <span>{{ ckRs.Ck }}</span>
+        </div>
+      </div>
+      <div class="btn_center">
+        <span class="btn btn-md login_btn" @click="logoutBtn">退出</span>
+      </div>
+    </div>
+    <bottomTab :curTab="thisTab"></bottomTab>
+  </div>
+</template>
+
+<script>
+import axios from 'axios';
+import bottomTab from '../components/bottomTab'
+import {
+  VipUserSelfQuery,
+  OrderShopQuery,
+  VipUserCleCkSum,
+  testSelect,
+  testTable,
+} from '../api/getApiRes.js'
+
+let qs = require('qs');
+import Global from '../Global.js'
+
+export default {
+  data() {
+    return {
+      num: 0,
+      thisTab: '我的',
+      active: 0,
+      sum: 0,
+      openAlert: false,
+      list: [],
+      dialog: {
+        id: '',
+        name: '',
+        timeLong: '',
+      },
+      user: {
+        Ck: 0,
+        CKMonth: 0,
+        Cle: 0,
+        CleMonth: 0,
+        CalorieMonth: 0,
+        CalorieTotal: 0,
+        ClassFinish: 0,
+        ClassRemain: 0,
+        ClassTotal: 0,
+        ExpTime: 0,
+        Name: '',
+        Phone: '',
+        VipType: 0,
+      },
+      ckRs:{
+        Ck: 0,
+        CKMonth: 0,
+        Cle: 0,
+        CleMonth: 0,
+      },
+      schools: [],
+    }
+  },
+  mounted() {
+    this.getInfo();
+    this.getOrderShopQuery();
+    this.getCalorie()
+  },
+  methods: {
+    // 获得卡路里
+    getCalorie() {
+      let that = this;
+      let param = {
+        token: localStorage.token,
+      };
+      let postdata = qs.stringify(param);
+      VipUserCleCkSum(postdata).then(res => {
+        let json = res;
+        if (json.Code == 0) {
+          that.ckRs = json;
+        } else {
+          that.$toast.message(json.Memo);
+        }
+      })
+    },
+    getOrderShopQuery() {
+      let that = this;
+      let param = {
+        token: localStorage.token,
+      };
+      let postdata = qs.stringify(param);
+      OrderShopQuery(postdata).then(res => {
+        let json = res;
+        if (json.Code == 0) {
+          that.schools = json.Rs;
+        } else {
+         that.$toast.message(json.Memo);
+        }
+      })
+    },
+    logoutBtn() {
+      let that = this;
+      this.$confirm('是否退出账号?', '提示', {
+        type: 'warning'
+      }).then(({result}) => {
+        if (result) {
+          localStorage.token = '';
+          that.$router.push({path: '/login'});
+        } else {
+          that.$toast.message('点击了取消');
+        }
+      });
+    },
+    getInfo() {
+      let that = this;
+      let param = {
+        token: localStorage.token,
+        active: this.active
+      };
+      let postdata = qs.stringify(param);
+      VipUserSelfQuery(postdata).then(res => {
+        let json = res;
+        if (json.Code == 0) {
+          that.user = json.Rs;
+        } else {
+          that.$toast.message(json.Memo);
+        }
+      })
+    },
+  },
+  filters: {
+    hidePhone:function (val){
+      var str = String(val)
+      var len = str.length;
+      if (len >= 7) {
+        var reg = str.slice(-8, -4)
+        return str.replace(reg, "****")
+      } else if (len < 7 && len >= 6) {
+        var reg = str.slice(-4, -2)
+        return str.replace(reg, "**")
+      }
+    },
+    fmtTime: function (value) {
+      if (!value) {
+        return 0
+      } else {
+        // js默认使用毫秒
+        value = value * 1000
+        let date = new Date(value);
+        let y = date.getFullYear();
+        let MM = date.getMonth() + 1;
+        MM = MM < 10 ? ('0' + MM) : MM;
+        let d = date.getDate();
+        d = d < 10 ? ('0' + d) : d;
+        let h = date.getHours();
+        h = h < 10 ? ('0' + h) : h;
+        let m = date.getMinutes();
+        m = m < 10 ? ('0' + m) : m;
+        let s = date.getSeconds();
+        s = s < 10 ? ('0' + s) : s;
+        return y + '-' + MM + '-' + d;
+      }
+    },
+  },
+  beforeRouteEnter(to, from, next) {
+    next(vm => {
+      //因为当钩子执行前,组件实例还没被创建
+      // vm 就是当前组件的实例相当于上面的 this,所以在 next 方法里你就可以把 vm 当 this 来用了。
+      if (to.name == 'mine') {
+        vm.getInfo();
+      }
+    });
+  },
+  watch: {
+    'active'() {
+      console.log(123);
+      this.getList();
+    }
+  },
+  components: {
+    bottomTab
+  }
+}
+</script>
+
+<style scoped>
+.pages {
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  background: #F2F2F2;
+}
+
+.num {
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  font-family: "PingFang SC";
+  font-weight: 300;
+  font-size: 14px;
+  text-align: center;
+  color: #909090;
+  padding: 13px 0;
+}
+
+.user {
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  height: 58px;
+  background: #fff;
+  padding: 17px 3%;
+  margin-bottom: 10px;
+}
+
+.user img {
+  width: 26.29px;
+  height: 26.29px;
+  float: left;
+  margin-right: 11px;
+}
+
+.user span {
+  font-family: "PingFang SC";
+  font-weight: 500;
+  font-size: 18px;
+  text-align: left;
+  color: #3b3b3b;
+}
+
+.user em {
+  font-family: "PingFang SC";
+  font-weight: normal;
+  font-size: 18px;
+  text-align: left;
+  color: #3b3b3b;
+  float: right;
+}
+
+.user p {
+  font-family: "PingFang SC";
+  font-weight: normal;
+  font-size: 14px;
+  text-align: left;
+  color: #ffb43c;
+  float: right;
+  padding: 0;
+  margin: 0;
+  margin-left: 3px;
+  line-height: 26px;
+}
+
+.value {
+  width: 100%;
+  /*height: 131px;*/
+  background: #fff;
+  padding: 13px 0;
+}
+
+.value .vTitle {
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  text-align: center;
+
+  font-family: "PingFang SC";
+  font-weight: 300;
+  font-size: 15px;
+}
+
+.vTitle i {
+  width: 8px;
+  height: 8px;
+  display: inline-block;
+  border-radius: 250px;
+  margin-right: 3px;
+}
+
+.vTitle.year {
+  color: #E75296;
+}
+
+.vTitle.year i {
+  background: #e75296;
+}
+
+.vTitle.price {
+  color: #FFB43C;
+}
+
+.vTitle.price i {
+  background: #FFB43C;
+}
+
+.vNum {
+  width: 100%;
+  /*height: 25px;*/
+  overflow: hidden;
+  display: block;
+  margin: 5px auto;
+  margin-bottom: 0;
+}
+
+.center {
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  text-align: center;
+}
+
+.vNum em {
+  position: relative;
+  float: right;
+  bottom: 20px;
+  font-family: "PingFang SC";
+  font-weight: 500;
+  font-size: 12px;
+  color: #c9c9c9;
+  padding-right: 3%;
+}
+
+/deep/ .linear-progress {
+  width: 90%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  border-radius: 250px;
+}
+
+.limit {
+  width: 90%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  margin-top: 8px;
+}
+
+.limit em {
+  font-family: "PingFang SC";
+  font-weight: 300;
+  font-size: 12px;
+  text-align: right;
+  color: #e75296;
+  padding-left: 10px;
+}
+
+.limit span {
+  font-family: "PingFang SC";
+  font-weight: 300;
+  font-size: 12px;
+  text-align: right;
+  color: #909090;
+  float: right;
+  text-align: right;
+  padding-right: 10px;
+}
+
+.dataSum {
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  background: #fff;
+  margin-top: 10px;
+}
+
+.dataSum .row {
+  width: 90%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  padding: 2% 0;
+}
+
+.dataSum .row em {
+  float: left;
+  font-family: "PingFang SC";
+  font-weight: 300;
+  font-size: 18px;
+  text-align: right;
+  color: #3b3b3b;
+}
+
+.dataSum .row span {
+  font-family: "PingFang SC";
+  font-weight: 500;
+  font-size: 18px;
+  text-align: right;
+  color: #3b3b3b;
+  float: right;
+}
+
+.row .mid {
+  width: 66%;
+  height: 0px;
+  background: transparent;
+  border: 1px dotted #e0e0e0;
+  float: left;
+  margin-top: 11px;
+  margin-right: 5px;
+  margin-left: 10px;
+}
+
+.row .midl {
+  width: 54%;
+  height: 0px;
+}
+
+.login_btn {
+  width: 96%;
+  height: 50px;
+  line-height: 50px;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  margin-top: 10px;
+  margin-bottom: 30px;
+  padding-left: 3%;
+  padding-right: 3%;
+  background: #E75296;
+  color: #fff;
+  font-size: 14px;
+  text-align: center;
+  border: none;
+  padding: 0;
+  font-size: 24px;
+}
+
+/deep/ .mu-warning-text-color {
+  float: left;
+}
+
+.vNum span {
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  text-align: center;
+}
+
+@media only screen and (max-width: 640px) {
+
+}
+
+@media only screen and (max-width: 480px) {
+
+}
+
+@media only screen and (max-width: 375px) {
+  .vNum em {
+    padding-right: 0 !important;
+  }
+
+  .row .mid {
+    width: 49%;
+  }
+
+  .row .midl {
+    width: 44%;
+    height: 0px;
+  }
+}
+
+@media only screen and (max-width: 360px) {
+  .vNum em {
+    padding-right: 0 !important;
+  }
+
+  .row .mid {
+    width: 49%;
+  }
+
+  .row .midl {
+    width: 44%;
+    height: 0px;
+  }
+}
+
+@media only screen and (max-width: 320px) {
+
+}
+
+@media only screen and (min-width: 641px) {
+
+}
+</style>

+ 47 - 0
app/src/page/modal.vue

@@ -0,0 +1,47 @@
+<template>
+    <div>
+        <mu-appbar style="width: 100%;" color="primary" title="详情信息">
+            <router-link to="/" slot="left">
+                <mu-icon value="arrow_back"></mu-icon>
+            </router-link>
+        </mu-appbar>
+    </div>
+</template>
+
+<script>
+    import axios from 'axios';
+    let qs = require('qs');
+    import Global from '../Global.js'
+    export default {
+        data() {
+            return {
+                lists: []
+            }
+        },
+        mounted() {
+        },
+        methods: {},
+    }
+</script>
+
+<style scoped>
+    /*mu-header*/
+    .mu-primary-color {
+        line-height: 60px;
+        height: 60px;
+        background: url("../static/images/comm/headerBg.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    /deep/ .mu-appbar-left {
+        padding-top: 15px;
+    }
+
+    /deep/ .material-icons {
+        color: #fff;
+    }
+
+   /deep/ .mu-appbar-title {
+        text-align: center;
+    }
+</style>

+ 61 - 0
app/src/page/notFound.vue

@@ -0,0 +1,61 @@
+<template>
+    <div id="pages">
+            <h5>404</h5>
+            <span @click="$router.back(-1)">{{$t("Back to previous page")}}</span>
+    </div>
+</template>
+
+<script>
+export default {
+    data () {
+    return {
+      msg: 'Welcome to Your Vue.js App'
+    }
+    },
+}
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped>
+    #pages {
+        position: absolute;
+        top:0;
+        bottom: 0;
+        left: 0;
+        right: 0;
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        background:#2c2e2f
+    }
+    h5 {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        font-size: 160px;
+        text-align: center;
+        margin-top: 10%;
+        color: #fff;
+        font-weight: normal;
+    }
+    span {
+        width: 200px;
+        height: 45px;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        margin-top: 10%;
+        background:#FFA200 ;
+        color: #fff;
+        font-size: 18px;
+        text-align: center;
+        border-radius: 250px;
+        line-height: 45px;
+        cursor: pointer;
+    }
+    span:hover {
+        background: #FFA200;
+    }
+</style>

+ 332 - 0
app/src/page/plane.vue

@@ -0,0 +1,332 @@
+<template>
+    <div id="pages">
+        <mu-appbar style="width: 100%;" color="primary" :title="$t('Plane details')">
+            <router-link to="/map" slot="left">
+                <mu-icon value="arrow_back"></mu-icon>
+            </router-link>
+        </mu-appbar>
+        <mu-tabs :value.sync="active" inverse color="warning" full-width>
+            <mu-tab :id="Region.RegionId" v-for="(Region,index) in RegionList" :key="Region.RegionId">
+                {{Region.Region}}
+            </mu-tab>
+        </mu-tabs>
+        <div class="planeContainer">
+            <ul>
+                <li v-if="!lists.length">
+                    <h4>{{$t("no use data")}}</h4>
+                </li>
+                <li v-for="(list,index) in lists" v-if="lists">
+                    <div class="basic">
+                        <h5>{{list.Region}}</h5>
+                        <span>
+                                 {{$t("Detection")}} :{{list.DetectorCount}}台|
+                                {{$t("Dangerous equipment found")}} :{{list.DangerCamCount}}台|
+                                {{$t("phone")}}:{{list.Signalstr == ' '? $t("No mobile signal detected"):list.Signalstr}}
+                            </span>
+                        <div v-if="imgSrc[index]" class="imgSrcContainer">
+                            <img :src="imgSrc[index]" alt="">
+                            <span class="imgContainer">
+                                <em :class="[{'green':pointStates[index].DetectorType == 0},{'red':pointStates[index].DetectorType != 0}]"
+                                    v-for="(point,index) in points[index]"
+                                    :style="{left:point.Width*0.30+'px',top:point.Height * -0.4+'px'}"
+                                ></em>
+                            </span>
+                        </div>
+                        <div v-else>
+                            <p class="tips">{{$t("No records found")}}</p>
+                        </div>
+                    </div>
+                </li>
+            </ul>
+        </div>
+    </div>
+</template>
+
+<script>
+    import axios from 'axios';
+
+    let qs = require('qs');
+    import Global from '../Global.js'
+
+    export default {
+        data() {
+            return {
+                active: 0,
+                selected: 0,
+                RegionList: [],
+                lists: [],
+                imgSrc: [],
+                points: [],
+                pointStates: [],
+            }
+        },
+        mounted() {
+            this.RegionDetectList();
+        },
+        watch: {
+            active(val) {
+                this.readList(this.RegionList[val]['RegionId']);
+            }
+        },
+        methods: {
+            // 读取楼栋信息
+            RegionDetectList() {
+                const that = this;
+                let url = headapi + 'v1/Company/ComRegionDetectList';
+                let comId = this.$route.query.ComId;
+                let param = {
+                    token: localStorage.token,
+                    comId: comId
+                };
+                that.RegionList = [];
+                let postdata = qs.stringify(param);
+                axios.post(url, postdata).then(function (data) {
+                    let json = data.data;
+                    if (json.Code == 0) {
+                        that.RegionList = json.Rs;
+                        if (json.Rs) {
+                            // that.selected = json.Rs[0].RegionId;
+                            that.selected = parseInt(that.$route.query.Regionid);
+                            that.readList( that.selected);
+                        }
+                    } else {
+                        that.Toast(that.TransMemo(json.Memo));
+                    }
+                }, function (response) {
+                    console.info(response);
+                })
+            },
+            readList(regionId) {
+                const that = this;
+                let url = headapi + 'v1/Company/RegionDetectList';
+                let param = {
+                    token: localStorage.token,
+                    regionId: regionId // regionId
+                };
+                that.lists = [];
+                let postdata = qs.stringify(param);
+                axios.post(url, postdata).then(function (data) {
+                    let json = data.data;
+                    if (json.Code == 0) {
+                        that.lists = json.Rs;
+                        that.imgFileter(json.Rs);
+                        that.DetectListByRegionID(json.Rs)
+                    } else {
+                        that.Toast(that.TransMemo(json.Memo));
+                    }
+                }, function (response) {
+                    console.info(response);
+                })
+            },
+            imgFileter(Rs) {
+                const that = this;
+                let url = headapi + 'v1/Company/RegionPictureGetByRegionId';
+                that.imgSrc = [];
+                for (var i = 0; i < Rs.length; i++) {
+                    let param = {
+                        token: localStorage.token,
+                        regionID: Rs[i].RegionId// regionId
+                    };
+                    let postdata = qs.stringify(param);
+                    axios.post(url, postdata).then(function (data) {
+                        let json = data.data;
+                        if (json.Code == 0) {
+                            that.imgSrc.push(json.EncodeString);
+                        }
+                    }, function (response) {
+                        console.info(response);
+                    })
+                }
+            },
+            DetectListByRegionID(Rs) {
+                const that = this;
+                let url = headapi + 'v1/Company/DetectListByRegionID';
+                let comId = this.$route.query.ComId;
+                for (var i = 0; i < Rs.length; i++) {
+                    let param = {
+                        token: localStorage.token,
+                        comId: comId, // regionId
+                        regionId: Rs[i].RegionId// regionId
+                    };
+                    let postdata = qs.stringify(param);
+                    axios.post(url, postdata).then(function (data) {
+                        let json = data.data;
+                        if (json.Code == 0) {
+                            if (json.Rs) {
+                                that.points.push(json.Rs);
+                                console.log(that.points);
+                            } else {
+                                that.points = [];
+                            }
+                            if (json.DetectorType != undefined && json.DetectorType != null) {
+                                that.pointStates = json.DetectorType;
+                            } else {
+                                that.pointStates = [];
+                                return false
+                            }
+                        }
+                    }, function (response) {
+                        console.info(response);
+                    })
+                }
+            },
+        },
+    }
+</script>
+
+<style scoped>
+    /*mu-header*/
+    .mu-primary-color {
+        line-height: 60px;
+        height: 60px;
+        background: url("../static/images/comm/headerBg.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    /deep/ .mu-appbar-left {
+        padding-top: 15px;
+    }
+
+    /deep/ .material-icons {
+        color: #fff;
+    }
+
+    /deep/ .mu-appbar-title {
+        text-align: center;
+    }
+
+    .mu-warning-text-color {
+        color: #FFA200;
+    }
+
+    /deep/ .mu-tab-link-highlight {
+        background-color: #FFA200 !important;
+    }
+
+    #pages {
+        position: absolute;
+        width: 100%;
+        height: 100%;
+        overflow-y: scroll;
+        display: block;
+        margin: 0 auto;
+        background-color: #f2f2f2;
+        top: 0;
+        bottom: 0;
+    }
+
+    .info {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        background: #fff;
+        margin-bottom: 10px;
+        padding-left: 20px;
+    }
+
+    .planeContainer li {
+        width: 100%;
+        height: 360px;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+
+    .basic {
+        width: 100%;
+        height: 360px;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        border-bottom: 1px solid #f2f2f2;
+        background: #fff;
+        padding: 5px 0px;
+    }
+
+    .basic h5 {
+        border: 2px solid #f2f2f2;
+        border-left: 0;
+        border-right: 0;
+        padding: 10px 0;
+        padding-left: 20px;
+        font-size: 14px;
+    }
+
+    .basic > span {
+        width: 88%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        font-size: 12px;
+    }
+
+    .basic img {
+        width: 96%;
+        height: 200px;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        margin-top: 15px;
+        margin-bottom: 5px;
+    }
+
+    .red {
+        width: 20px;
+        height: 20px;
+        border-radius: 250px !important;
+        float: left;
+        margin: 0;
+        padding: 0;
+        background-color: red;
+        color: red;
+    }
+
+    .green {
+        width: 20px;
+        height: 20px;
+        border-radius: 250px !important;
+        float: left;
+        margin: 0;
+        padding: 0;
+        background-color: yellowgreen;
+        color: yellowgreen;
+    }
+    .imgSrcContainer {
+        width: 100%;
+        height: 220px;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+
+    .imgContainer {
+        position: relative;
+        bottom: 200px;
+        width: 96%;
+        height: 200px;
+        display: block;
+        margin: 0 auto;
+    }
+    .imgContainer em {
+        position: relative;
+    }
+
+    .tips {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        text-align: center;
+        margin-top: 10px;
+        margin-bottom: 10px;
+    }
+
+    ul li h4 {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        text-align: center;
+    }
+</style>

+ 265 - 0
app/src/page/profile.vue

@@ -0,0 +1,265 @@
+<template>
+    <div>
+        <mu-appbar style="width: 100%;" color="primary" :title="$t('detail')">
+            <router-link to="/map" slot="left">
+                <mu-icon value="arrow_back"></mu-icon>
+            </router-link>
+        </mu-appbar>
+        <div class="container">
+            <div class="row">
+                <div class="detail">
+                    <h5>
+                        <span>{{unite.ComName}}</span>
+                        <em>{{unite.Legal}}</em>
+                    </h5>
+                    <p>
+                        {{unite.Introduction}}
+                    </p>
+                </div>
+                <div class="listContainer">
+                    <ul>
+                        <li v-if="!lists.length">
+                            <h4>{{$t("no use data")}}</h4>
+                        </li>
+                        <li v-for="list in lists" v-if="lists" @click="goListDetail(list)">
+                            <h5>{{list.Region}}</h5>
+                            <div>
+                                <mu-icon value="keyboard_arrow_right"></mu-icon>
+                                <span>
+                                    {{$t("Camera")}}:{{list.CamCount}}  {{$t("pcs")}} |
+                                     {{$t("Detection")}} :{{list.DetectorCount}} {{$t("pcs")}} |
+                                     {{$t("Suspicious camera")}}:{{list.DangerCamCount}} {{$t("pcs")}}
+                                </span>
+                                <span>
+                                      {{$t("phone")}}:{{list.Signalstr == ' '?  $t("No mobile signal detected"):list.Signalstr}}
+                                </span>
+                            </div>
+                        </li>
+                    </ul>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+    import axios from 'axios';
+
+    let qs = require('qs');
+    import Global from '../Global.js'
+
+    export default {
+        data() {
+            return {
+                selected: "1",
+                RegionList: [],
+                unite: {
+                    ComName: '',
+                    Legal: '',
+                    Introduction: '',
+                },
+                lists: [],
+            }
+        },
+        mounted() {
+            this.readInfo();
+            this.RegionDetectList();
+        },
+        methods: {
+            // 基本信息
+            readInfo() {
+                const that = this;
+                let url = headapi + 'v1/Company/ComInfoDetail';
+                let comId = this.$route.query.ComId;
+                let param = {
+                    token: localStorage.token,
+                    comId: comId
+                };
+                let postdata = qs.stringify(param);
+                axios.post(url, postdata).then(function (data) {
+                    let json = data.data;
+                    if (json.Code == 0) {
+                        that.unite.ComName = json.Rs.ComName;
+                        that.unite.Legal = json.Rs.Legal;
+                        that.unite.Introduction = json.Rs.Introduction;
+                    } else {
+                        this.Toast(that.TransMemo(json.Memo));
+                    }
+                }, function (response) {
+                    console.info(response);
+                })
+            },
+            // 读取楼栋信息
+            RegionDetectList() {
+                const that = this;
+                let url = headapi + 'v1/Company/ComRegionDetectList';
+                let comId = this.$route.query.ComId;
+                let param = {
+                    token: localStorage.token,
+                    comId: comId
+                };
+                let postdata = qs.stringify(param);
+                axios.post(url, postdata).then(function (data) {
+                    let json = data.data;
+                    if (json.Code == 0) {
+                        that.RegionList = json.Rs;
+                        if (json.Rs) {
+                            that.selected = json.Rs[0].RegionId;
+                            that.readList();
+                        }
+                    } else {
+                        this.Toast(that.TransMemo(json.Memo));
+                    }
+                }, function (response) {
+                    console.info(response);
+                })
+            },
+            // 读取无线设备具体分布
+            readList() {
+                const that = this;
+                let url = headapi + 'v1/Company/RegionDetectList';
+                let param = {
+                    token: localStorage.token,
+                    regionId: this.selected
+                };
+                let postdata = qs.stringify(param);
+                axios.post(url, postdata).then(function (data) {
+                    let json = data.data;
+                    if (json.Code == 0) {
+                        that.lists = json.Rs;
+                    } else {
+                        this.Toast(that.TransMemo(json.Memo));
+                    }
+                }, function (response) {
+                    console.info(response);
+                })
+            },
+            goListDetail(list) {
+                let that = this;
+                that.$router.push(
+                    {
+                        path: '/listDetail',
+                        query: {
+                            RegionId: list.RegionId,
+                            Region: list.Region,
+                            comName: that.unite.ComName
+                        }
+                    });
+            }
+        },
+    }
+</script>
+
+<style scoped>
+    /*mu-header*/
+    .mu-primary-color {
+        line-height: 60px;
+        height: 60px;
+        background: url("../static/images/comm/headerBg.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    /deep/ .mu-appbar-left {
+        padding-top: 15px;
+    }
+
+    /deep/ .material-icons {
+        color: #fff;
+    }
+
+    /deep/ .mu-appbar-title {
+        text-align: center;
+    }
+
+    #pages {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin-top: 0px;
+        padding-bottom: 200px;
+        background: #f2f2f2;
+        overflow-y: scroll;
+    }
+
+    .detail {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        background: #fff;
+        padding-top: 0px;
+        padding-bottom: 20px;
+        padding-left: 2%;
+        padding-right: 2%;
+        margin-bottom: 10px;
+    }
+
+    .detail h5 span {
+        font-size: 16px;
+    }
+
+    .detail h5 em {
+        float: right;
+        color: #666666;
+        font-size: 12px;
+        font-weight: normal;
+        text-align: right;
+    }
+
+    .detail p {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        font-size: 12px;
+        color: #666666;
+        line-height: 16px;
+    }
+
+    /deep/ .mint-navbar .mint-tab-item.is-selected {
+        border-bottom: 3px solid #FFA200;
+        color: #FFA200;
+    }
+
+    /deep/ .mint-navbar .mint-tab-item.is-selected .mint-tab-item-label {
+        color: #FFA200;
+    }
+
+    .listContainer ul {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        margin-top: 10px;
+
+    }
+
+    .listContainer li {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        margin-bottom: 2px;
+        padding: 10px 20px;
+        background: #fff;
+    }
+
+    .listContainer li h5 {
+        font-size: 14px;
+        margin: 10px 0;
+    }
+
+    .listContainer li span {
+        width: 80%;
+        float: left;
+        font-size: 12px;
+        color: #606060;
+        line-height: 20px;
+    }
+
+    .listContainer li img {
+        width: 8px;
+        height: 14px;
+        float: right;
+    }
+</style>

+ 613 - 0
app/src/page/record.vue

@@ -0,0 +1,613 @@
+<template>
+  <div class="pages">
+    <img src="../static/images/main/banner.png" height="121" width="414"/>
+    <div class="context">
+            <span class="num">
+                记录共 {{ num }} 条
+            </span>
+      <mu-tabs :value.sync="active" color="#F2F2F2" indicator-color="#ffffff" center>
+        <mu-tab>已预约</mu-tab>
+        <mu-tab>预约记录</mu-tab>
+        <mu-tab>消费记录</mu-tab>
+      </mu-tabs>
+<!--      <div class="whiteCube"></div>-->
+      <ul class="list">
+        <mu-load-more @refresh="refresh" :refreshing="refreshing" :loading="loading" @load="load">
+          <li v-for="l in list">
+            <div class="lt" v-if="active != 2">
+              <h5>{{ l.CurrentDate }}</h5>
+              <em>{{ l.CurrentDate |filterWeek}}</em>
+              <span>{{ l.BeginStr }}-{{ l.EndStr }}</span>
+            </div>
+            <div class="lt" v-if="active == 2">
+              <h5>{{ l.CreatedAt|filterTime }}</h5>
+              <span>剩余课时 {{ l.AfterNormalhour }}</span>
+            </div>
+            <div class="md">
+              <em>
+                                <span class="lessons" :style="{ background:l.ClassColor }">
+                                     {{ l.ClassName }}
+                                </span>
+              </em>
+<!--              <span class="green" v-if="l.Status == 0">-->
+<!--                            预约上课-->
+<!--                        </span>-->
+<!--              <span class="green" v-if="l.Status == 1 && active == 0">-->
+<!--                            已预约-->
+<!--                        </span>-->
+            </div>
+            <div class="rt">
+              <mu-button color="error" flat  v-if="l.Status == 0"  @click="cancleAppoint(l)">取消预约</mu-button>
+              <span v-if="l.Status == 1" class="isFinish">
+<!--                            已预约-->
+                             <mu-button color="error" flat  @click="cancleAppoint(l)">取消预约</mu-button>
+                        </span>
+              <span class="red" v-if="l.Status == 2">
+                            已取消
+                        </span>
+              <span class="red" v-if="l.Status == 3">
+                            预约未到
+                        </span>
+              <span class="green" v-if="l.Status == 4">
+                            已完成
+                        </span>
+              <em v-if="active == 2">
+                - {{ l.NormalHour }}课时
+              </em>
+            </div>
+          </li>
+        </mu-load-more>
+        <div class="tips">
+          <p v-if="active == 0 && list == null">
+            暂无已预约
+          </p>
+          <p v-if="active == 1 && list == null">
+            暂无预约记录
+          </p>
+          <p v-if="active == 2 && list == ''">
+            暂无消费记录
+          </p>
+        </div>
+      </ul>
+    </div>
+    <bottomTab :curTab="thisTab"></bottomTab>
+    <!--        <span v-if="scope.row.Status == 1">已预约</span>-->
+    <!--        <span v-if="scope.row.Status == 2">已取消</span>-->
+    <!--        <span v-if="scope.row.Status == 3">预约未到</span>-->
+    <!--        <span v-if="scope.row.Status == 4">已完成</span>-->
+    <alert ref="alertPart"></alert>
+  </div>
+</template>
+
+<script>
+import axios from 'axios';
+import bottomTab from '../components/bottomTab'
+import {
+  OrderListQuery,
+  VipUserConsumeListQuery,
+  OderCancelByVipUser,
+  testSelect,
+  testTable,
+} from '../api/getApiRes.js'
+import alert from '../components/alert'
+
+let qs = require('qs');
+import Global from '../Global.js'
+
+export default {
+  data() {
+    return {
+      num: 0,
+      thisTab: '预约记录',
+      active: 0,
+      sum: 0,
+      openAlert: false,
+      list: [],
+      dialog: {
+        id: '',
+        name: '',
+        timeLong: '',
+      },
+      refreshing: false,
+      loading: false,
+      start: 1,
+      tableMax: 6,
+    }
+  },
+  mounted() {
+    this.getList();
+  },
+  methods: {
+    alertInfo(info){
+      this.$refs.alertPart.openSimpleDialog(info);
+    },
+    refresh() {
+    },
+    load() {
+      if (this.active != 2) {
+        return false
+      }
+      this.loading = true;
+      setTimeout(() => {
+        this.loading = false;
+        this.start = this.start + 6;
+        this.getVipUserConsumeListQuery();
+      }, 2000);
+    },
+    cancleAppoint(row) {
+      let that = this;
+      this.$confirm('是否取消' + row.ClassName + '课程预约?', '提示', {
+        type: 'warning'
+      }).then(({result}) => {
+        if (result) {
+          let param = {
+            token: localStorage.token,
+            orderId: row.OrderId,
+          };
+          let postdata = qs.stringify(param);
+          OderCancelByVipUser(postdata).then(res => {
+            let json = res;
+            if (json.Code == 0) {
+              that.alertInfo('当前课程已取消预约', 'success');
+              that.getList();
+            } else {
+              that.alertInfo(json.Memo + ',错误码:' + json.Code);
+            }
+          })
+        } else {
+          this.alertInfo('点击了取消');
+        }
+      });
+    },
+    getOrderListQuery(statusList) {
+      let that = this;
+      let param = {
+        token: localStorage.token,
+        statusList: statusList,
+        start: 1,
+        tableMax: 299,
+      };
+      let postdata = qs.stringify(param);
+      if (parseInt(this.active) == 0 || parseInt(this.active) == 1) {
+        OrderListQuery(postdata).then(res => {
+          let json = res;
+          if (json.Code == 0) {
+            that.list = json.Rs;
+            if (that.list) {
+              that.num = json.Rs.length;
+            } else {
+              that.num = 0
+            }
+          } else {
+            that.alertInfo(json.Memo + ',错误码:' + json.Code);
+          }
+        });
+      }
+    },
+    getVipUserConsumeListQuery() {
+      let that = this;
+      let param = {
+        token: localStorage.token,
+        start: this.start,
+        tableMax: this.tableMax,
+      };
+      let postdata = qs.stringify(param);
+      VipUserConsumeListQuery(postdata).then(res => {
+        let json = res;
+        if (json.Code == 0) {
+          // that.list = json.Rs;
+          that.list = that.list.concat(json.Rs);
+          if (that.list) {
+            that.num = json.Rs.length;
+          }
+        } else {
+          that.alertInfo(json.Memo);
+        }
+      })
+    },
+    getList() {
+      let statusList = '';
+      this.list = [];
+      switch (parseInt(this.active)) {
+          // 已预约
+        case 0:
+          statusList = 1;
+          this.getOrderListQuery(statusList);
+          break;
+          // 预约记录
+        case 1:
+          statusList = '2,3,4';
+          this.getOrderListQuery(statusList);
+          break;
+          // 消费记录
+        case 2:
+          statusList = 1;
+          this.getVipUserConsumeListQuery(statusList);
+          break;
+      }
+    },
+    numberToWeek(val) {
+      switch (parseInt(val)) {
+        case 1:
+          return '星期一'
+          break;
+        case 2:
+          return '星期二'
+          break;
+        case 3:
+          return '星期三'
+          break;
+        case 4:
+          return '星期四'
+          break;
+        case 5:
+          return '星期五'
+          break;
+        case 6:
+          return '星期六'
+          break;
+        case 0:
+          return '星期天'
+          break;
+      }
+    },
+  },
+  beforeRouteEnter(to, from, next) {
+    next(vm => {
+      //因为当钩子执行前,组件实例还没被创建
+      // vm 就是当前组件的实例相当于上面的 this,所以在 next 方法里你就可以把 vm 当 this 来用了。
+      if (to.name == 'record') {
+        vm.getList();
+      }
+    });
+  },
+  filters: {
+    filterTime: function (value) {
+      if (!value) {
+        return 0
+      } else {
+        return globalfmtDate(value);
+      }
+    },
+    filterWeek:function (value){
+      if (!value) return false
+      let days = new Date(value).getDay();
+      switch (parseInt(days)) {
+        case 1:
+          return '星期一'
+          break;
+        case 2:
+          return '星期二'
+          break;
+        case 3:
+          return '星期三'
+          break;
+        case 4:
+          return '星期四'
+          break;
+        case 5:
+          return '星期五'
+          break;
+        case 6:
+          return '星期六'
+          break;
+        case 0:
+          return '星期天'
+          break;
+      }
+    }
+  },
+  watch: {
+    '$route'(to) {
+      if (to.name == 'record') {
+        this.getList();
+      }
+    },
+    'active'() {
+      this.start = 1;
+      this.getList();
+    }
+  },
+  components: {
+    bottomTab,alert
+  }
+}
+</script>
+
+<style scoped>
+.pages {
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  background: #F2F2F2;
+}
+
+.num {
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  font-family: "PingFang SC";
+  font-weight: 300;
+  font-size: 14px;
+  text-align: center;
+  color: #909090;
+  padding: 13px 0;
+}
+
+/deep/ .mu-appbar-title {
+  text-align: center;
+}
+
+/deep/ .mu-tab {
+  width: 115px;
+  height: 35px;
+  margin-right: 6px;
+}
+
+/deep/ .mu-tab-wrapper {
+  height: 35px;
+  line-height: 25px;
+  background: #f4f4f4;
+  color: #363636;
+  box-shadow: 1px 0px 6px rgba(0, 0, 0, 0.16);
+  border-radius: 8px 8px 0px 0px;
+  font-size: 16px;
+  padding-top: 5px;
+}
+
+/deep/ .mu-tab-active .mu-tab-wrapper {
+  height: 35px;
+  line-height: 25px;
+  border-radius: 8px 8px 0px 0px;
+  background: #ffffff;
+  box-shadow: 1px 0px 6px rgba(0, 0, 0, 0.16);
+  color: #000;
+}
+
+/deep/ .mu-tab-wrapper em {
+  font-size: 12px;
+}
+
+.list {
+  position: relative;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  width: 100%;
+  height: 100%;
+  min-height: 410px;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  padding-top: 0px;
+  padding-bottom: 30px;
+  background: #f2f2f2;
+}
+
+.list li {
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  background: #fff;
+  padding: 20px 3%;
+  margin-bottom: 10px;
+}
+
+.whiteCube {
+  width: 100%;
+  height: 6px;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  background: #fff;
+  border-bottom: 1px solid #ccc;
+}
+
+.list .lt {
+  width: 100px;
+  float: left;
+  overflow: visible;
+}
+
+.list .lt h5 {
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  font-family: "PingFang SC";
+  font-weight: normal;
+  font-size: 13px;
+  text-align: center;
+  color: #4e4e4e;
+  margin: 0;
+}
+
+.list .lt span {
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  font-family: "PingFang SC";
+  font-weight: normal;
+  font-size: 12px;
+  text-align: center;
+  color: #909090;
+
+}
+.list .lt em {
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  font-size: 12px;
+  text-align: center;
+}
+
+.list .md {
+  max-width: 200px;
+  /*width: 220px;*/
+  float: left;
+  margin-left: 10%;
+  padding-top: 14px;
+}
+
+.list .rt {
+  float: right;
+  margin-right: 2%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  padding-top: 9px;
+}
+
+.md em {
+  float: left;
+  font-family: "PingFang SC";
+  font-weight: normal;
+  font-size: 18px;
+  text-align: left;
+  color: #3b3b3b;
+  margin-right: 20px;
+}
+
+.md span {
+  font-family: "PingFang SC";
+  font-weight: normal;
+  font-size: 14px;
+  text-align: left;
+  /*color: #37cb00;*/
+  line-height: 30px;
+}
+
+span.green {
+  color: #37cb00;
+}
+
+span.red {
+  color: #FF453C;
+}
+
+.rt span {
+  float: right;
+  line-height: 35px;
+  font-family: "PingFang SC";
+  font-weight: normal;
+  font-size: 14px;
+  text-align: left;
+  color: #909090;
+  overflow: hidden;
+  padding-bottom: 6px;
+}
+
+.rt .red {
+  font-family: "PingFang SC";
+  font-weight: normal;
+  font-size: 14px;
+  text-align: left;
+  color: #f8847f;
+}
+
+.rt .cancleBtn {
+  width: 55px;
+  height: 24px;
+  border-radius: 12px;
+  background: #ff453c;
+  padding: 0;
+  overflow: hidden;
+  text-align: center;
+  color: #fff;
+  line-height: 24px;
+  margin-top: 6px;
+}
+
+.rt em {
+  font-family: "PingFang SC";
+  font-weight: normal;
+  font-size: 14px;
+  text-align: left;
+  color: #909090;
+  margin-top: 6px;
+}
+
+.tips {
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+}
+
+.tips p {
+  width: 100%;
+  overflow: hidden;
+  display: block;
+  margin: 0 auto;
+  text-align: center;
+  font-size: 14px;
+  line-height: 35px;
+}
+
+.green {
+  color: #37cb00;
+}
+
+/deep/ .mu-raised-button.mu-button-small {
+  width: 54px;
+  min-width: 40px;
+  float: right;
+  padding-left: 3px;
+  padding-right: 3px;
+}
+
+.lessons {
+  width: 100%;
+  overflow: hidden;
+  padding: 1px 11px;
+  border-radius: 250px;
+  float: left;
+  text-align: center;
+  color: #333;
+}
+/deep/ .mu-button-wrapper {
+  border: 1px solid #F8847F;
+  color: #F8847F;
+  background: #FFF7F7;
+  border-radius: 5px;
+}
+
+@media only screen and (max-width: 640px) {
+
+}
+
+@media only screen and (max-width: 480px) {
+
+}
+
+@media only screen and (max-width: 375px) {
+
+}
+
+@media only screen and (max-width: 360px) {
+
+}
+
+@media only screen and (max-width: 320px) {
+  .list .lt {
+    width: 80px;
+  }
+
+  .list .lt h5 {
+    font-size: 12px;
+  }
+
+  .md em {
+    margin-right: 3px;
+  }
+}
+
+@media only screen and (min-width: 641px) {
+
+}
+</style>

+ 318 - 0
app/src/page/runtime.vue

@@ -0,0 +1,318 @@
+<template>
+    <div id="pages">
+        <appHeader @goNewpage="onGoNewPage" :title="this.pagetitle"></appHeader>
+        <bottomTab :curTab="thisTab"></bottomTab>
+        <div class="container">
+            <div class="row">
+                <mu-tabs :value.sync="active" inverse color="warning" full-width>
+                    <mu-tab>{{$t("wireless device")}}</mu-tab>
+                    <mu-tab> {{$t("phone signal")}}</mu-tab>
+                </mu-tabs>
+                <div class="demo-text" v-if="active === 0">
+                    <ul class="deteUl">
+                        <li v-if="!lists">
+                            <h4>{{$t("no use data")}}</h4>
+                        </li>
+                        <transition-group name="fade">
+                            <li v-for="(list,i) in lists" v-if="lists"  v-bind:key="i">
+                                <div class="lt">
+                                    <div class="rowTop">
+                                        <h5>{{list.DetectorLocation}}</h5>
+                                        <span v-if="list.DangerLevel == -1" class="green">{{$t("other")}}</span>
+                                        <span v-if="list.DangerLevel == 0" class="green">{{$t("white")}}</span>
+                                        <span v-if="list.DangerLevel == 2" class="yellow">{{$t("deal")}}</span>
+                                        <span v-if="list.DangerLevel == 3" class="red">{{$t("warning")}}</span>
+                                        <span v-if="list.DangerLevel == 4" class="red">{{$t("danger")}}</span>
+                                    </div>
+                                    <div class="rowDetail">
+                                        <span>{{list.MacCom.length > 16 ? list.MacCom.slice(0, 16)+'...':list.MacCom}}</span>
+                                        <span class="pull-right">{{list.Mac}}</span>
+                                    </div>
+                                </div>
+                            </li>
+                        </transition-group>
+                        <s class="tips" v-if="lists"> {{$t("total")}}{{lists.length}}{{$t("item")}} {{$t("Record")}}</s>
+                    </ul>
+                </div>
+                <div class="demo-text" v-if="active === 1">
+                    <ul class="deteUl">
+                        <li v-if="!phones">
+                            <h4>{{$t("no use data")}}</h4>
+                        </li>
+                        <li v-for="phone in phones" v-if="phones">
+                            <div class="lt">
+                                <div class="rowTop">
+                                    <h5>{{phone.DetectorName}}</h5>
+                                    <span>{{phone.RegionName | filterContent}}</span>
+                                </div>
+                                <div class="rowDetail">
+                                    <span>{{phone.ComName}}</span>
+                                    <s :class="{'red':phone.Signalstr != ''}">{{phone.Signalstr | filterSignalstr}}</s>
+                                </div>
+                            </div>
+                        </li>
+                        <s class="tips" v-if="phones"> {{$t("total")}}{{phones.length}}{{$t("item")}}
+                            {{$t("Record")}}</s>
+                    </ul>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+    import appHeader from '../components/appHeader'
+    import bottomTab from '../components/bottomTab'
+    import axios from 'axios';
+
+    let qs = require('qs');
+    import Global from '../Global.js'
+
+    export default {
+        data() {
+            return {
+                pagetitle: this.$t('Real-time'),
+                thisTab: this.$t('Real-time'),
+                active: 0,
+                loading: true,
+                lists: [],
+                phones: [],
+            }
+        },
+        mounted() {
+            this.readList();
+            this.readPhone();
+        },
+        filters: {
+            filterContent: function (value) {
+                if (value == '' || value == undefined) {
+                    return '-'
+                } else {
+                    return value
+                }
+            },
+            filterSignalstr: function (value) {
+                switch (value) {
+                    case "":
+                        return '未检测到';
+                        break;
+                    default:
+                        return value;
+                        break;
+                }
+            }
+        },
+        watch: {
+            active(val) {
+                let that = this;
+                console.log(val);
+                if (val == 1) {
+                    that.readList();
+                } else {
+                    that.readPhone();
+                }
+            }
+        },
+        methods: {
+            onGoNewPage(path) {
+                this.$router.push({path: '/' + path});
+            },
+            // 实时监测无线设备
+            readList() {
+                const that = this;
+                let url = headapi + 'v1/Detector/DetectedMacs';
+                // let url = headapi + 'v1/Detector/DetectedMacsTest';//test
+                let param = {
+                    token: localStorage.token,
+                };
+                this.lists = [];
+                let postdata = qs.stringify(param);
+                axios.post(url, postdata).then(function (data) {
+                    let json = data.data;
+                    if (json.Code == 0) {
+                        that.lists = json.Rs;
+                    } else {
+                        that.Toast(that.TransMemo(json.Memo));
+                    }
+                }, function (response) {
+                    console.info(response);
+                })
+            },
+            readPhone() {
+                const that = this;
+                let url = headapi + 'v1/Detector/SignalDeviceList';
+                let pageIndex = 1;
+                let tableMax = 100;
+                let param = {
+                    token: localStorage.token,
+                    pageIndex: pageIndex,
+                    tableMax: tableMax
+                };
+                let postdata = qs.stringify(param);
+                axios.post(url, postdata).then(function (data) {
+                    let json = data.data;
+                    if (json.Code == 0) {
+                        that.phones = json.Rs;
+                    } else {
+                        that.Toast(that.TransMemo(json.Memo));
+                    }
+                }, function (response) {
+                    console.info(response);
+                })
+            },
+        },
+        components: {
+            appHeader, bottomTab
+        }
+    }
+</script>
+
+<style scoped>
+    .mu-warning-text-color {
+        color: #FFA200;
+    }
+
+    /deep/ .mu-tab-link-highlight {
+        background-color: #FFA200 !important;
+    }
+
+    /deep/ .mu-tab {
+        width: 50%;
+    }
+
+    #pages {
+        width: 100%;
+        height: 100%;
+        overflow: hidden;
+        display: block;
+        margin-top: 0px;
+        padding-bottom: 20px;
+        background: #f2f2f2;
+        overflow-y: scroll;
+    }
+
+    .demo-text {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+
+    .demo-text ul {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        border-top: 2px solid #f2f2f2;
+    }
+
+    .demo-text li {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        padding: 10px 20px;
+        background: #fff;
+        border-bottom: 2px solid #f2f2f2;
+    }
+
+    .deteUl h5 {
+        margin: 0;
+        float: left;
+        font-size: 16px;
+    }
+
+    .deteUl .rowTop span {
+        float: right;
+        font-size: 14px;
+    }
+
+    .deteUl .rowDetail {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        color: #999999;
+        font-size: 14px;
+    }
+
+    .rowDetail span {
+        float: left;
+    }
+
+    .rowDetail s {
+        float: right;
+    }
+
+    .rowBottom {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        font-size: 12px;
+        color: #999999;
+    }
+
+    .tips {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        text-align: center;
+        font-size: 12px;
+        color: #999999;
+        margin-top: 10px;
+    }
+
+    .deteUl img {
+        width: 8px;
+        height: 14px;
+        margin-top: 20px;
+        float: right;
+    }
+
+    .deteUl .lt {
+        width: 100%;
+        float: left;
+    }
+
+    .deteUl .rt {
+        float: right;
+    }
+
+    .row .pull-right {
+        float: right;
+        text-align: right;
+    }
+
+    .deteUl h4 {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        text-align: center;
+        font-weight: normal;
+    }
+
+    .rowDetail s {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        text-align: left;
+    }
+
+    .red {
+        color: red;
+    }
+    .green {
+        color: yellowgreen;
+    }
+    .yellow {
+        color: rgb(255, 162, 0);
+    }
+
+    /deep/ .mu-tab-wrapper {
+        font-size: 16px;
+    }
+</style>

+ 148 - 0
app/src/page/setting.vue

@@ -0,0 +1,148 @@
+<template>
+    <div id="pages">
+        <mu-appbar style="width: 100%;" color="primary" :title="$t('System setup')">
+            <router-link to="/" slot="left">
+                <mu-icon value="arrow_back"></mu-icon>
+            </router-link>
+        </mu-appbar>
+        <div class="">
+            <div class="row">
+                <mu-list>
+                    <mu-list-item button :ripple="false">
+                        <mu-list-item-title>{{$t("Alarm sound")}}</mu-list-item-title>
+                        <mu-list-item-action>
+                            <mu-switch v-model="voiceState"></mu-switch>
+                        </mu-list-item-action>
+                    </mu-list-item>
+                    <mu-divider></mu-divider>
+                    <mu-list-item button :ripple="false">
+                        <mu-list-item-title>{{$t("Alarm flicker")}}</mu-list-item-title>
+                        <mu-list-item-action>
+                            <mu-switch v-model="alertState"></mu-switch>
+                        </mu-list-item-action>
+                    </mu-list-item>
+                    <div class="grip"></div>
+                    <mu-list-item button :ripple="false" @click="openAlertDialog">
+                        <mu-list-item-title>{{$t("Quit landing")}}</mu-list-item-title>
+                    </mu-list-item>
+                </mu-list>
+            </div>
+        </div>
+        <mu-dialog width="600" max-width="80%" :esc-press-close="false"
+                   :overlay-close="false" :open.sync="openAlert">
+            {{$t("Confirm to exit the current account")}}?
+            <mu-button slot="actions" flat color="info" @click="closeAlertDialog">{{$t("cancel")}}</mu-button>
+            <mu-button slot="actions" flat color="warning" @click="logout">{{$t("confirm")}}</mu-button>
+        </mu-dialog>
+    </div>
+</template>
+
+<script>
+    import axios from 'axios';
+
+    let qs = require('qs');
+    import Global from '../Global.js'
+
+    export default {
+        data() {
+            return {
+                lists: [],
+                voiceState: false,
+                alertState: false,
+                openAlert: false
+            }
+        },
+        mounted() {
+            localStorage.voiceState = localStorage.voiceState || false;
+            localStorage.alertState = localStorage.alertState || false;
+            this.voiceState = JSON.parse(localStorage.voiceState);
+            this.alertState = JSON.parse(localStorage.alertState);
+        },
+        watch: {
+            voiceState: function (val) {
+                localStorage.voiceState = val;
+            },
+            alertState: function (val) {
+                localStorage.alertState = val;
+            },
+        },
+        methods: {
+            openAlertDialog() {
+                this.openAlert = true;
+            },
+            closeAlertDialog() {
+                this.openAlert = false;
+            },
+            // 退出
+            logout() {
+                this.openAlert = false;
+                const that = this;
+                localStorage.token = '';
+                that.$router.push({path: '/login'});
+            },
+        },
+    }
+</script>
+
+<style scoped>
+    #pages {
+        width: 100%;
+        top: 0;
+        bottom: 0;
+        height: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        background: #f2f2f2;
+    }
+
+    /*mu-header*/
+    .mu-primary-color {
+        line-height: 60px;
+        height: 60px;
+        background: url("../static/images/comm/headerBg.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    /deep/ .mu-appbar-left {
+        padding-top: 15px;
+    }
+
+    /deep/ .material-icons {
+        color: #fff;
+    }
+
+    /deep/ .mu-appbar-title {
+        text-align: center;
+    }
+
+    .mu-button {
+        display: block;
+        margin: 0 auto;
+    }
+
+    .row {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+
+    .mu-switch-checked {
+        color: #FFCC00;
+    }
+
+    .grip {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        height: 10px;
+    }
+
+    /deep/ .mu-item-wrapper {
+        background: #fff;
+        font-size: 16px;
+        color: #000;
+    }
+</style>

+ 63 - 0
app/src/page/sport.vue

@@ -0,0 +1,63 @@
+<template>
+    <div id="mainPage">
+        <bottomTab :curTab="thisTab"></bottomTab>
+
+        <mu-paper :z-depth="1">
+            <mu-time-picker :no-display="!display" :view-type="viewType" :time.sync="time" :format="type" :landscape="landscape"></mu-time-picker>
+        </mu-paper>
+
+        <div @click="turnSport">
+            <Hand :state="state"></Hand>
+        </div>
+        <div>
+
+        </div>
+
+    </div>
+</template>
+
+<script>
+    import axios from 'axios';
+    import bottomTab from '../components/bottomTab'
+    import Hand from '@/components/Hand.vue'
+    let qs = require('qs');
+    import Global from '../Global.js'
+    export default {
+        data() {
+            return {
+                thisTab: 'SPORT',
+                state:true,
+                time: undefined,
+                landscape: false,
+                display: true,
+                type: 'ampm',
+                viewType: 'clock',
+                lists: []
+            }
+        },
+        mounted() {
+        },
+        methods: {
+            turnSport(){
+                console.log(123);
+                this.state = false
+            }
+        },
+        components: {
+            bottomTab,Hand
+        }
+    }
+</script>
+
+<style scoped>
+    #mainPage {
+        width: 100%;
+        height: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        background: #000;
+        overflow-y: scroll;
+        color: red;
+    }
+</style>

+ 50 - 0
app/src/page/statis.vue

@@ -0,0 +1,50 @@
+<template>
+    <div>
+        <appHeader @goNewpage="onGoNewPage" :title="this.pagetitle"></appHeader>
+        <div class="container">
+            <div class="row">
+                <statischart></statischart>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+    import appHeader from '../components/appHeader'
+    import axios from 'axios';
+    let qs = require('qs');
+    import Global from '../Global.js'
+    import statischart from '../components/statischart'
+    export default {
+        data() {
+            return {
+                pagetitle:this.$t('Statistical report forms'),
+                lists: []
+            }
+        },
+        mounted() {
+        },
+        methods: {
+            onGoNewPage(path) {
+                this.$router.push({path: '/' + path});
+            },
+        },
+        components: {
+            statischart,appHeader
+        }
+    }
+</script>
+
+<style scoped>
+    .container {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+    /deep/ #statischart {
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+</style>

+ 101 - 0
app/src/page/test.vue

@@ -0,0 +1,101 @@
+<template>
+    <div>
+        <mu-paper :z-depth="1" class="demo-loadmore-wrap">
+            <mu-container ref="container" class="demo-loadmore-content">
+                <mu-load-more @refresh="refresh" :refreshing="refreshing" :loading="loading" @load="load">
+                    <li v-for="i in list">
+                        {{text}} Item {{i.ClassName}}
+                    </li>
+
+                </mu-load-more>
+            </mu-container>
+        </mu-paper>
+    </div>
+</template>
+
+<script>
+    import axios from 'axios';
+    import {
+        VipUserConsumeListQuery,
+    } from '../api/getApiRes.js'
+
+    let qs = require('qs');
+    import Global from '../Global.js'
+
+    export default {
+        data() {
+            return {
+                num: 20,
+                refreshing: false,
+                loading: false,
+                text: 'List',
+                list: [],
+                start: 1,
+                tableMax: 5,
+            }
+        },
+        mounted() {
+            this.getVipUserConsumeListQuery();
+        },
+        methods: {
+            refresh() {
+            },
+            load() {
+                this.loading = true;
+                setTimeout(() => {
+                    this.loading = false;
+                    this.start =  this.start + 5;
+                    this.getVipUserConsumeListQuery();
+                }, 2000);
+            },
+            getVipUserConsumeListQuery() {
+                let that = this;
+                let param = {
+                    token: localStorage.token,
+                    start: this.start,
+                    tableMax: this.tableMax,
+                };
+                let postdata = qs.stringify(param);
+                VipUserConsumeListQuery(postdata).then(res => {
+                    let json = res;
+                    if (json.Code == 0) {
+                        that.list =  that.list.concat(json.Rs);
+                    } else {
+                        that.Toast(json.Memo + ',错误码:' + json.Code);
+                    }
+                })
+            },
+        }
+    };
+</script>
+
+<style scoped>
+    .demo-loadmore-wrap {
+        position: absolute;
+        width: 100%;
+        height: 100%;
+        display: flex;
+        overflow-y: scroll;
+        flex-direction: column;
+    }
+
+    .mu-appbar {
+        width: 100%;
+    }
+
+    .demo-loadmore-content {
+        flex: 1;
+        overflow: auto;
+        -webkit-overflow-scrolling: touch;
+    }
+    li {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        height: 160px;
+        line-height: 160px;
+        border: 1px solid #ccc;
+        text-align: center;
+    }
+</style>

+ 157 - 0
app/src/page/userDetail.vue

@@ -0,0 +1,157 @@
+<template>
+    <div>
+        <mu-appbar style="width: 100%;" color="primary" :title="$t('User details')">
+            <router-link to="/usermanage" slot="left">
+                <mu-icon value="arrow_back"></mu-icon>
+            </router-link>
+        </mu-appbar>
+        <div class="container">
+            <div class="row">
+                <h5>{{detail.Name}}</h5>
+                <ul>
+                    <li><em>{{$t("usercode")}}:</em><span>{{detail.Usercode}}</span></li>
+                    <li><em>Email:</em><span>{{detail.Email | filterContent}}</span></li>
+                    <li><em>{{$t("phone")}}:</em><span>{{detail.Phone}}</span></li>
+                    <!--<li><em>{{$t("state")}}:</em><span>{{detail.Status | typeFileter}}</span></li>-->
+                    <li><em>{{$t("state")}}:</em><span>{{Status}}</span></li>
+                    <li><em>{{$t("User roles")}}:</em><span>{{detail.Rolesname | filterContent}}</span></li>
+                    <li><em>{{$t("memo")}}:</em><span>{{detail.Memo | filterContent}}</span></li>
+                </ul>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+    import axios from 'axios';
+
+    let qs = require('qs');
+    import Global from '../Global.js'
+
+    export default {
+        data() {
+            return {
+                detail: {}
+            }
+        },
+        mounted() {
+            this.writeData();
+        },
+        methods: {
+            writeData() {
+                let content = this.$route.query.detector;
+                this.detail = JSON.parse(content);
+                console.log(this.detail);
+            }
+        },
+        computed:{
+            Status() {
+                switch (this.detail.Status) {
+                    case 1:
+                        return this.$t('disabled');
+                        break;
+                    default:
+                        return this.$t('Enabled');
+                        break;
+                }
+            },
+        },
+        filters: {
+            typeFileter: function (value) {
+                switch (parseInt(value)) {
+                    case 1:
+                        return '已禁用';
+                        break;
+                    default:
+                        return '已启用';
+                        break;
+                }
+            },
+            filterContent: function (value) {
+                if (value == '' || value == undefined) {
+                    return '-'
+                } else {
+                    return value
+                }
+            },
+        }
+    }
+</script>
+
+<style scoped>
+    /*mu-header*/
+    /deep/ .mu-primary-color {
+        line-height: 60px;
+        height: 60px;
+        background: url("../static/images/comm/headerBg.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    /deep/ .mu-appbar-left {
+        padding-top: 15px;
+    }
+
+    /deep/ .material-icons {
+        color: #fff;
+    }
+
+    /deep/ .mu-appbar-title {
+        text-align: center;
+    }
+
+    #pages {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin-top: 0px;
+        padding-bottom: 200px;
+        background: #f2f2f2;
+    }
+
+    .row {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        background: #fff;
+    }
+
+    .row h5 {
+        width: 80%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        text-align: center;
+        font-size: 20px;
+        color: #FFA200;
+        padding: 20px;
+        border-bottom: 1px solid rgba(112, 112, 112, 0.14);
+        margin-bottom: 20px;
+    }
+
+    .row ul {
+        width: 80%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        margin-top: 10px;
+    }
+
+    .row li {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        margin-bottom: 10px;
+        font-size: 16px;
+    }
+
+    .row li em {
+        float: left;
+        min-width: 80px;
+    }
+
+    .row li span {
+        color: #6E6E6E;
+    }
+</style>

+ 212 - 0
app/src/page/usermanage.vue

@@ -0,0 +1,212 @@
+<template>
+    <div id="pages">
+        <appHeader @goNewpage="onGoNewPage" :title="this.pagetitle"></appHeader>
+        <div class="listContainer">
+            <ul class="deteUl">
+                <li v-if="!lists.length">
+                    <h4>{{$t("no use data")}}</h4>
+                </li>
+                <transition-group name="fade">
+                <li v-for="list in stus" v-if="lists" @click="goPage(list)" v-bind:key="list.Id">
+                    <div class="lt">
+                        <div class="rowTop">
+                            <h5>{{list.Name}}</h5>
+                            <!--<span>{{list.Status | typeFileter}}</span>-->
+                            <span>{{list.stusType}}</span>
+                        </div>
+                        <div class="rowDetail">
+                            <span>{{list.Rolesname}}</span>
+                            <span class="pull-right">{{list.Insname | filterContent}}</span>
+                        </div>
+                    </div>
+                    <div class="rt">
+                         <mu-icon value="keyboard_arrow_right"></mu-icon>
+                    </div>
+                </li>
+                </transition-group>
+                <div class="tips" v-if="lists">{{$t("total")}} {{lists.length}} {{$t("enterprise")}}</div>
+            </ul>
+        </div>
+    </div>
+</template>
+
+<script>
+    import appHeader from '../components/appHeader'
+    import axios from 'axios';
+    let qs = require('qs');
+    import Global from '../Global.js'
+    export default {
+        data() {
+            return {
+                pagetitle:this.$t('user management'),
+                lists: []
+            }
+        },
+        mounted() {
+            this.writeData();
+        },
+        computed:{
+            stus(){
+                let that = this;
+                let text = '';
+                /*es6写法 防止用不了this.type*/
+                return this.lists.filter((v)=>{
+                    console.log(v.Status);
+                    switch (parseInt(v.Status)) {
+                        case 1:
+                            text = that.$t('disabled');
+                            break;
+                        default:
+                            text = that.$t('Enabled');
+                            break;
+                    }
+                    return v.stusType = text;
+                })
+            }
+        },
+        methods: {
+            onGoNewPage(path) {
+                this.$router.push({path: '/' + path});
+            },
+            goPage(list) {
+                this.$router.push({path: '/userDetail', query: {detector: JSON.stringify(list)}});
+            },
+            writeData() {
+                const that = this;
+                let url = headapi + 'v1/User/UserListInfo';
+                let pageIndex = 1;
+                let tableMax = 100;
+                let param = {
+                    token: localStorage.token,
+                    usertype: '0',
+                    searchs: '',
+                    pageIndex: pageIndex,
+                    tableMax: tableMax
+                };
+                let postdata = qs.stringify(param);
+                axios.post(url, postdata).then(function (data) {
+                    let json = data.data;
+                    if (json.Code == 0) {
+                        that.lists = json.Rs;
+                    } else {
+                        that.Toast(that.TransMemo(json.Memo));
+                    }
+                }, function (response) {
+                    console.info(response);
+                })
+            }
+        },
+        filters: {
+            typeFileter: function (value) {
+                switch (parseInt(value)) {
+                    case 1:
+                        return '已禁用';
+                        break;
+                    default:
+                        return '已启用';
+                        break;
+                }
+            },
+            filterContent: function (value) {
+                if (value == '' || value == undefined) {
+                    return '-'
+                } else {
+                    return value
+                }
+            },
+        },
+        components: {
+            appHeader
+        }
+    }
+</script>
+
+<style scoped>
+    #pages {
+        width: 100%;
+        height: 100%;
+        overflow: hidden;
+        display: block;
+        margin-top: 0px;
+        padding-bottom: 20px;
+        background: #f2f2f2;
+        overflow-y: scroll;
+    }
+
+    .listContainer ul {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+
+    .listContainer li {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        margin-bottom: 2px;
+        padding: 10px 20px;
+        background: #fff;
+    }
+
+    .listContainer .rowTop {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+
+    .rowTop .red {
+        color: #FFA200;
+    }
+
+    .listContainer h5 {
+        margin: 0;
+        float: left;
+        font-size: 16px;
+    }
+
+    .listContainer .rowTop span {
+        float: right;
+        font-size: 14px;
+    }
+
+    .listContainer .rowDetail {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        color: #999999;
+        font-size: 14px;
+        margin-top: 10px;
+        margin-bottom: 10px;
+    }
+
+    .deteUl .lt {
+        width: 88%;
+        float: left;
+    }
+
+    .deteUl .rt {
+        float: right;
+    }
+
+    .rt i {
+        margin-top: 20px;
+    }
+    .pull-right {
+        float: right;
+        text-align: right;
+    }
+    .tips {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        text-align: center;
+        font-size: 12px;
+        color: #999999;
+        margin-top: 20px;
+    }
+</style>

+ 360 - 0
app/src/page/white.vue

@@ -0,0 +1,360 @@
+<template>
+    <div id="pages">
+        <mu-appbar style="width: 100%;" color="primary" :title="curTitle">
+            <router-link to="/" slot="left">
+                <mu-icon value="arrow_back"></mu-icon>
+            </router-link>
+            <mu-button flat color="primary" slot="right" @click="showPanel">{{btnText}}</mu-button>
+        </mu-appbar>
+        <mu-bottom-sheet :open.sync="popupVisible">
+            <div class="modal-content">
+                <div class="modal-body">
+                    <div class="location">
+                        <span>{{$t("query criteria")}}</span>
+                        <div class="timePickerPart">
+                            <span @click="changeTime(1)">{{bt}}</span> <em>{{$t("to")}}</em>
+                            <span @click="changeTime(2)">{{et}}</span>
+                        </div>
+                        <div v-show="open">
+                            <mu-flex justify-content="between" align-items="end" wrap="wrap">
+                                <mu-paper :z-depth="1" class="demo-date-picker">
+                                    <mu-date-picker :date.sync="date" color="#FFA200" :date-time-format="enDateFormat"
+                                                    @change="confirmDay"></mu-date-picker>
+                                </mu-paper>
+                            </mu-flex>
+                        </div>
+                        <input type="text" placeholder="MAC" v-model="MAC" id="macInput">
+                        <input type="text" :placeholder="$t('keyword')" v-model="keyWord" id="keyWordInput">
+                    </div>
+                </div>
+                <div class="modalBottom">
+                    <div class="reset" @click="resetModal">
+                        {{$t("Reset")}}
+                    </div>
+                    <div class="pullUp" @click="searchModal">
+                        {{$t("query")}}
+                    </div>
+                </div>
+            </div>
+        </mu-bottom-sheet>
+        <div class="container">
+            <div class="row">
+                <p class="tips" v-if="!lists">{{$t("no use data")}}</p>
+                <mu-list textline="two-line" v-for="list in lists" :key="list.Id">
+                    <mu-list-item avatar :ripple="false" button>
+                        <mu-list-item-content>
+                            <mu-list-item-title>{{list.Name}}</mu-list-item-title>
+                            <mu-list-item-sub-title>{{list.Mac}}</mu-list-item-sub-title>
+                            <mu-list-item-sub-title>{{list.Memo}}</mu-list-item-sub-title>
+                        </mu-list-item-content>
+                        <mu-list-item-action>
+                            <mu-list-item-after-text>{{list.CreateTime | timeFileter}}</mu-list-item-after-text>
+                            <mu-list-item-after-text>{{list.Regionname}}</mu-list-item-after-text>
+                            <mu-list-item-after-text>{{$t("operator")}}: {{list.Usercode}}</mu-list-item-after-text>
+                        </mu-list-item-action>
+                    </mu-list-item>
+                    <mu-divider></mu-divider>
+                </mu-list>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+    import axios from 'axios';
+
+    let qs = require('qs');
+    import Global from '../Global.js'
+    const enDateFormat = {
+        formatDisplay (date) {
+            return `${dayList[date.getDay()]}, ${monthList[date.getMonth()]} ${date.getDate()}`;
+        },
+        formatMonth (date) {
+            return `${monthLongList[date.getMonth()]} ${date.getFullYear()}`;
+        },
+        getWeekDayArray (firstDayOfWeek) {
+            let beforeArray = [];
+            let afterArray = [];
+            for (let i = 0; i < dayAbbreviation.length; i++) {
+                if (i < firstDayOfWeek) {
+                    afterArray.push(dayAbbreviation[i]);
+                } else {
+                    beforeArray.push(dayAbbreviation[i]);
+                }
+            }
+            return beforeArray.concat(afterArray);
+        },
+        getMonthList () {
+            return monthList;
+        }
+    };
+    export default {
+        data() {
+            return {
+                enDateFormat,
+                curTitle:this.$t("whiteList"),
+                lists: [],
+                popupVisible:false,//true false
+                open:false,//true false
+                MAC:'',//
+                keyWord:'',//
+                bt: globaltime2StringNoMin(new Date() - 3 * 24 * 3600 * 1000),
+                et: globaltime2StringNoMin(new Date()),
+                date: new Date(),
+                btnText: this.$t("search"),
+            }
+        },
+        mounted() {
+            this.writeData();
+        },
+        filters: {
+            timeFileter: function (time) {
+                return globalfmtDate(time, 10)
+            },
+        },
+        methods: {
+            changeTime(val) {
+                this.open = true;
+                let curVal = val == 1 ? new Date(this.bt) : new Date(this.et);
+                this.selectTime = val;
+                this.date = curVal;
+            },
+            showPanel() {
+                this.popupVisible = true;
+                this.btnText = this.$t("close");
+            },
+            whenClose(){
+                this.popupVisible = false;
+                this.btnText = this.$t("search");
+            },
+            confirmDay(date) {
+                if (this.selectTime == 1) {
+                    this.bt = globaltime2StringNoMin(date);
+                } else {
+                    this.et = globaltime2StringNoMin(date);
+                }
+                this.open = false;
+            },
+            // 重置
+            resetModal() {
+                this.MAC = '';
+                this.keyWord = '';
+                this.bt = globaltime2StringNoMin(new Date() - 3 * 24 * 3600 * 1000);
+                this.et = globaltime2StringNoMin(new Date());
+                this.Toast('已重置','success');
+            },
+            // 查询
+            searchModal() {
+                let that = this;
+                this.popupVisible = false;
+                this.writeData();
+                this.Toast('已查询','success');
+            },
+            writeData() {
+                const that = this;
+                let url = headapi + 'v1/Detector/WhiteListQuery';
+                let param = {
+                    token: localStorage.token,
+                    detectedmac:that.MAC,
+                    keywords:that.keyWord,
+                    bt:that.bt + ' 00:00:00',
+                    et:that.et + ' 23:59:59',
+                };
+                let postdata = qs.stringify(param);
+                axios.post(url, postdata).then(function (data) {
+                    let json = data.data;
+                    if (json.Code == 0) {
+                        that.lists = json.Rs;
+                    } else {
+                        that.Toast(that.TransMemo(json.Memo));
+                    }
+                }, function (response) {
+                    console.info(response);
+                })
+            }
+        },
+    }
+</script>
+
+<style scoped>
+    /*mu-header*/
+    .mu-primary-color {
+        line-height: 60px;
+        height: 60px;
+        background: url("../static/images/comm/headerBg.png") top center no-repeat;
+        background-size: 100%;
+    }
+
+    /deep/ .mu-appbar-left {
+        padding-top: 15px;
+    }
+
+    /deep/ .material-icons {
+        color: #fff;
+    }
+
+    /deep/ .mu-appbar-title {
+        text-align: center;
+    }
+    #pages {
+        position: absolute;
+        top: 0;
+        bottom: 0;
+        width: 100%;
+        height: 100%;
+        overflow: hidden;
+        overflow-y: scroll;
+        display: block;
+        margin: 0 auto;
+    }
+    .modal-content {
+        width: 100%;
+        display: block;
+        margin: 0 auto;
+        z-index: 99999;
+        overflow: hidden;
+    }
+
+    /*mu-bottom-sheet*/
+    .mu-bottom-sheet {
+        top: 60px !important;
+        bottom: 410px;
+        background: none;
+    }
+
+    .location {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+
+    .location span {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        margin-top: 10px;
+        margin-bottom: 10px;
+    }
+
+    .location input {
+        width: 95px;
+        height: 30px;
+        border: 1px solid #D5D5D5;
+        float: left;
+        text-indent: 10px;
+    }
+
+    .modal-body {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        background: #fff;
+        padding-top: 20px;
+        padding-left: 5%;
+        padding-right: 5%;
+        padding-bottom: 20px;
+    }
+
+    .modalBottom {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        background: #fff;
+    }
+
+    .modalBottom .reset {
+        width: 50%;
+        float: left;
+        height: 40px;
+        line-height: 40px;
+        background: #FFF6CF;
+        text-align: center;
+    }
+
+    .modalBottom .pullUp {
+        width: 50%;
+        float: right;
+        height: 40px;
+        line-height: 40px;
+        background: #FFCC00;
+        text-align: center;
+    }
+
+    .location select {
+        width: 95px;
+        height: 30px;
+        border: 1px solid #D5D5D5;
+        float: left;
+        margin-right: 10px;
+        margin-top: 10px;
+        margin-bottom: 10px;
+    }
+
+    .location select#detector {
+        margin-right: 0;
+        float: left;
+    }
+
+    #macInput {
+        width: 200px;
+        margin-bottom: 10px;
+    }
+    #keyWordInput {
+        width: 200px;
+    }
+
+    .timePickerPart {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+
+    .timePickerPart em {
+        width: 25px;
+        height: 30px;
+        line-height: 50px;
+        float: left;
+    }
+
+    .timePickerPart span {
+        width: 135px;
+        height: 30px;
+        line-height: 30px;
+        border: 1px solid #D5D5D5;
+        float: left;
+        margin-right: 8px;
+        margin-top: 10px;
+        margin-bottom: 10px;
+        text-align: center;
+    }
+    .demo-date-picker {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        border: none;
+        box-shadow: none;
+    }
+    .mu-datepicker {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+    }
+    .mu-list {
+        background: #fff;
+    }
+    .tips {
+        width: 100%;
+        overflow: hidden;
+        display: block;
+        margin: 0 auto;
+        text-align: center;
+        margin-top: 20px;
+    }
+</style>

+ 111 - 0
app/src/router/index.js

@@ -0,0 +1,111 @@
+import Vue from 'vue'
+import VueRouter from 'vue-router'
+import NProgress from 'muse-ui-progress';
+
+Vue.use(VueRouter);
+
+let NPconfig = {
+    zIndex: 2000,          // progress z-index
+    top: 0,                // position fixed top
+    speed: 300,            // progress speed
+    color: '#E75296',      // color
+    size: 2,               // progress size
+    className: ''          // progress custom class
+};
+Vue.use(NProgress,NPconfig);
+
+const routes = [
+    {
+        path: '/',
+        name: '',
+        component: () => import( '../page/index.vue'),
+        meta: {index: 0},//meta对象的index用来定义当前路由的层级,由小到大,由低到高
+        children: [
+            {
+                path: '/',
+                name: 'main',
+                meta: {
+                    title: '预约课程',
+                    index: 1
+                },
+                component: () => import( '../page/mainpage.vue')
+            },
+            {
+                path: '/sport',
+                name: 'sport',
+                meta: {
+                    title: '运动',
+                    index: 2
+                },
+                component: () => import( '../page/sport.vue')
+            },  {
+                path: '/record',
+                name: 'record',
+                meta: {
+                    title: '预约记录',
+                    index: 1
+                },
+                component: () => import( '../page/record.vue')
+            }, {
+                path: '/mine',
+                name: 'mine',
+                meta: {
+                    title: '我的',
+                    index: 1
+                },
+                component: () => import( '../page/mine.vue')
+            },{
+                path: '/lesson',
+                name: 'lesson',
+                meta: {
+                    title: '课程表',
+                    index: 1
+                },
+                component: () => import( '../page/lesson.vue')
+            },
+        ]
+    },
+    {
+        path: '/login',
+        name: 'login',
+        meta: {
+            title: '登陆',
+            index: 1
+        },
+        component: () => import( '../page/login.vue')
+    }, {
+        path: '/test',
+        name: 'test',
+        meta: {
+            title: 'test',
+            index: 1
+        },
+        component: () => import( '../page/test.vue')
+    }, {
+        path: '*',
+        name: 'notFound',
+        meta: {
+            title: '404',
+            index: 3
+        },
+        component: () => import( '../page/notFound.vue')
+    },
+];
+
+const router = new VueRouter({
+    mode: 'history',
+    base: process.env.BASE_URL,
+    routes
+});
+
+// 路由守卫
+router.beforeEach((to,from,next)=>{
+    NProgress.start();
+    next();
+});
+
+router.afterEach(() => {
+    NProgress.done()
+});
+
+export default router

二進制
app/src/static/images/appoint/tri.png


二進制
app/src/static/images/appoint/x.png


二進制
app/src/static/images/bottom/Calendar@2x.png


二進制
app/src/static/images/bottom/CalendarRed@2x.png


二進制
app/src/static/images/bottom/Newspaper@2x.png


二進制
app/src/static/images/bottom/NewspaperRed@2x.png


二進制
app/src/static/images/bottom/User@2x.png


二進制
app/src/static/images/bottom/UserRed@2x.png


二進制
app/src/static/images/bottom/sport.png


二進制
app/src/static/images/comm/arrow-left.png


二進制
app/src/static/images/comm/b11.png


二進制
app/src/static/images/comm/b11_1.png


二進制
app/src/static/images/comm/b12.png


二進制
app/src/static/images/comm/b12_1.png


二進制
app/src/static/images/comm/b13.png


二進制
app/src/static/images/comm/b13_1.png


二進制
app/src/static/images/comm/b14.png


二進制
app/src/static/images/comm/b14_1.png


二進制
app/src/static/images/comm/cityPicker.png


二進制
app/src/static/images/comm/headerBg.png


二進制
app/src/static/images/comm/iconEquipmanage.png


二進制
app/src/static/images/comm/iconEquipmanage_a.png


二進制
app/src/static/images/comm/iconHome.png


二進制
app/src/static/images/comm/iconHome_a.png


二進制
app/src/static/images/comm/iconMap.png


二進制
app/src/static/images/comm/iconMap_a.png


二進制
app/src/static/images/comm/iconProfile.png


二進制
app/src/static/images/comm/iconProfile_a.png


二進制
app/src/static/images/comm/iconRecord.png


二進制
app/src/static/images/comm/iconRecord_a.png


二進制
app/src/static/images/comm/iconRuntime.png


二進制
app/src/static/images/comm/iconRuntime_a.png


二進制
app/src/static/images/comm/iconStatis.png


二進制
app/src/static/images/comm/iconStatis_a.png


二進制
app/src/static/images/comm/iconUser.png


二進制
app/src/static/images/comm/iconUser_a.png


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