Jelajahi Sumber

first commit

ming 1 tahun lalu
melakukan
f24f96d7ba
100 mengubah file dengan 4311 tambahan dan 0 penghapusan
  1. 26 0
      .gitignore
  2. 18 0
      AndroidManifest.xml
  3. 10 0
      README.md
  4. TEMPAT SAMPAH
      favicon.ico
  5. 29 0
      index.html
  6. 9 0
      jsconfig.json
  7. TEMPAT SAMPAH
      nativeplugins/Fvv-AutoStart/android/autostart-release.aar
  8. 20 0
      nativeplugins/Fvv-AutoStart/package.json
  9. 79 0
      package.json
  10. 35 0
      project.config.json
  11. 7 0
      project.private.config.json
  12. 171 0
      src/App.vue
  13. 81 0
      src/api/business/zhaf/xunJian/plan.js
  14. 28 0
      src/api/common/index.js
  15. 64 0
      src/api/index/index.js
  16. 54 0
      src/api/login.js
  17. 52 0
      src/api/system/dict.js
  18. 21 0
      src/api/system/setting.js
  19. 93 0
      src/api/system/user.js
  20. 51 0
      src/config.js
  21. 34 0
      src/main.js
  22. 235 0
      src/manifest.json
  23. 91 0
      src/pages.json
  24. 31 0
      src/pages/index.vue
  25. 12 0
      src/pages/info.vue
  26. 508 0
      src/pages/login.vue
  27. 12 0
      src/pages/mine.vue
  28. 217 0
      src/pages/register.vue
  29. 220 0
      src/pages/serveConfig.vue
  30. 266 0
      src/pages/serveConfigSelect.vue
  31. 60 0
      src/permission.js
  32. 60 0
      src/plugins/auth.plugins.js
  33. 306 0
      src/plugins/common.plugins.js
  34. 292 0
      src/plugins/constData.plugins.js
  35. 68 0
      src/plugins/index.js
  36. 134 0
      src/plugins/keyListen.plugins.js
  37. 76 0
      src/plugins/modal.plugins.js
  38. 299 0
      src/plugins/nfc.plugins.js
  39. 98 0
      src/plugins/setting.plugins.js
  40. 32 0
      src/plugins/tab.plugins.js
  41. 217 0
      src/plugins/time.plugins.js
  42. 195 0
      src/static/iconfont/iconfont.css
  43. TEMPAT SAMPAH
      src/static/iconfont/iconfont.ttf
  44. TEMPAT SAMPAH
      src/static/images/tabBar/analyse-selected.png
  45. TEMPAT SAMPAH
      src/static/images/tabBar/analyse.png
  46. TEMPAT SAMPAH
      src/static/images/tabBar/info-selected.png
  47. TEMPAT SAMPAH
      src/static/images/tabBar/info.png
  48. TEMPAT SAMPAH
      src/static/images/tabBar/tab-cate-black.png
  49. TEMPAT SAMPAH
      src/static/images/tabBar/tab-cate-blue.png
  50. TEMPAT SAMPAH
      src/static/images/tabBar/tab-cate-brown.png
  51. TEMPAT SAMPAH
      src/static/images/tabBar/tab-cate-cyan.png
  52. TEMPAT SAMPAH
      src/static/images/tabBar/tab-cate-gray.png
  53. TEMPAT SAMPAH
      src/static/images/tabBar/tab-cate-green.png
  54. TEMPAT SAMPAH
      src/static/images/tabBar/tab-cate-grey.png
  55. TEMPAT SAMPAH
      src/static/images/tabBar/tab-cate-mauve.png
  56. TEMPAT SAMPAH
      src/static/images/tabBar/tab-cate-olive.png
  57. TEMPAT SAMPAH
      src/static/images/tabBar/tab-cate-orange.png
  58. TEMPAT SAMPAH
      src/static/images/tabBar/tab-cate-pink.png
  59. TEMPAT SAMPAH
      src/static/images/tabBar/tab-cate-purple.png
  60. TEMPAT SAMPAH
      src/static/images/tabBar/tab-cate-red.png
  61. TEMPAT SAMPAH
      src/static/images/tabBar/tab-cate-rf.png
  62. TEMPAT SAMPAH
      src/static/images/tabBar/tab-cate-yellow.png
  63. TEMPAT SAMPAH
      src/static/images/tabBar/tab-cate.png
  64. TEMPAT SAMPAH
      src/static/images/tabBar/tab-home-black.png
  65. TEMPAT SAMPAH
      src/static/images/tabBar/tab-home-blue.png
  66. TEMPAT SAMPAH
      src/static/images/tabBar/tab-home-brown.png
  67. TEMPAT SAMPAH
      src/static/images/tabBar/tab-home-cyan.png
  68. TEMPAT SAMPAH
      src/static/images/tabBar/tab-home-gray.png
  69. TEMPAT SAMPAH
      src/static/images/tabBar/tab-home-green.png
  70. TEMPAT SAMPAH
      src/static/images/tabBar/tab-home-grey.png
  71. TEMPAT SAMPAH
      src/static/images/tabBar/tab-home-mauve.png
  72. TEMPAT SAMPAH
      src/static/images/tabBar/tab-home-olive.png
  73. TEMPAT SAMPAH
      src/static/images/tabBar/tab-home-orange.png
  74. TEMPAT SAMPAH
      src/static/images/tabBar/tab-home-pink.png
  75. TEMPAT SAMPAH
      src/static/images/tabBar/tab-home-purple.png
  76. TEMPAT SAMPAH
      src/static/images/tabBar/tab-home-red.png
  77. TEMPAT SAMPAH
      src/static/images/tabBar/tab-home-rf.png
  78. TEMPAT SAMPAH
      src/static/images/tabBar/tab-home-yellow.png
  79. TEMPAT SAMPAH
      src/static/images/tabBar/tab-home.png
  80. TEMPAT SAMPAH
      src/static/images/tabBar/tab-info-black.png
  81. TEMPAT SAMPAH
      src/static/images/tabBar/tab-info-blue.png
  82. TEMPAT SAMPAH
      src/static/images/tabBar/tab-info-brown.png
  83. TEMPAT SAMPAH
      src/static/images/tabBar/tab-info-cyan.png
  84. TEMPAT SAMPAH
      src/static/images/tabBar/tab-info-gray.png
  85. TEMPAT SAMPAH
      src/static/images/tabBar/tab-info-green.png
  86. TEMPAT SAMPAH
      src/static/images/tabBar/tab-info-grey.png
  87. TEMPAT SAMPAH
      src/static/images/tabBar/tab-info-mauve.png
  88. TEMPAT SAMPAH
      src/static/images/tabBar/tab-info-olive.png
  89. TEMPAT SAMPAH
      src/static/images/tabBar/tab-info-orange.png
  90. TEMPAT SAMPAH
      src/static/images/tabBar/tab-info-pink.png
  91. TEMPAT SAMPAH
      src/static/images/tabBar/tab-info-purple.png
  92. TEMPAT SAMPAH
      src/static/images/tabBar/tab-info-red.png
  93. TEMPAT SAMPAH
      src/static/images/tabBar/tab-info-yellow.png
  94. TEMPAT SAMPAH
      src/static/images/tabBar/tab-info.png
  95. TEMPAT SAMPAH
      src/static/images/tabBar/tab-my-black.png
  96. TEMPAT SAMPAH
      src/static/images/tabBar/tab-my-blue.png
  97. TEMPAT SAMPAH
      src/static/images/tabBar/tab-my-brown.png
  98. TEMPAT SAMPAH
      src/static/images/tabBar/tab-my-cyan.png
  99. TEMPAT SAMPAH
      src/static/images/tabBar/tab-my-gray.png
  100. TEMPAT SAMPAH
      src/static/images/tabBar/tab-my-green.png

+ 26 - 0
.gitignore

@@ -0,0 +1,26 @@
+.DS_Store
+.history/
+.hbuilderx/
+package-lock.json
+node_modules/
+dist/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+**/*.log
+
+tests/**/coverage/
+tests/e2e/reports
+selenium-debug.log
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.local
+*.zip
+
+yarn.lock

+ 18 - 0
AndroidManifest.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="no" ?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:compileSdkVersion="33" android:compileSdkVersionCodename="13" package="android.dcloud.uskyMobile" platformBuildVersionCode="33" platformBuildVersionName="13">
+	<application android:allowBackup="false" android:allowClearUserData="true" android:appComponentFactory="androidx.core.app.CoreComponentFactory" android:debuggable="false" android:extractNativeLibs="true" android:hardwareAccelerated="true" android:icon="@drawable/icon" android:label="@string/app_name" android:largeHeap="true" android:name="io.dcloud.application.DCloudApplication" android:supportsRtl="true" android:usesCleartextTraffic="true">
+        <activity android:configChanges="fontScale|keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenLayout|screenSize|smallestScreenSize" android:exported="true" android:hardwareAccelerated="true" android:label="@string/app_name" android:name="io.dcloud.PandoraEntry" android:screenOrientation="user" android:theme="@style/DCloudTranslucentTheme" android:windowSoftInputMode="adjustResize">
+            <intent-filter>
+				<action android:name="android.intent.action.MAIN"/>
+				<category android:name="android.intent.category.LAUNCHER"/>
+				<category android:name="android.intent.category.HOME"/>
+				<category android:name="android.intent.category.DEFAULT"/>
+			</intent-filter>
+			<intent-filter>
+				<action android:name="android.intent.action.VIEW"/>
+				<category android:name="android.intent.category.DEFAULT"/>
+				<category android:name="android.intent.category.BROWSABLE"/>
+			</intent-filter>
+		</activity>	
+    </application>
+</manifest>

+ 10 - 0
README.md

@@ -0,0 +1,10 @@
+# sass移动端
+
+### 账号:fire_admin
+### 密码:FIRE_admin123
+
+
+## node>18.1.0||16.17.1
+ 
+
+

TEMPAT SAMPAH
favicon.ico


+ 29 - 0
index.html

@@ -0,0 +1,29 @@
+<!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">
+	<link rel="shortcut icon" type="image/x-icon" href="./favicon.ico">
+	<script>
+		var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
+			CSS.supports('top: constant(a)'))
+		document.write(
+			'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
+			(coverSupport ? ', viewport-fit=cover' : '') + '" />')
+	</script>
+
+	<title></title>
+	<!--preload-links-->
+	<!--app-context-->
+</head>
+
+<body>
+	<div id="app">
+		<!--app-html-->
+	</div>
+	<script type="module" src="/src/main.js"></script>
+</body>
+
+</html>

+ 9 - 0
jsconfig.json

@@ -0,0 +1,9 @@
+{
+  "compilerOptions": {
+    "types": [
+      "@dcloudio/types",
+      "miniprogram-api-typings",
+      "mini-types"
+    ]
+  }
+}

TEMPAT SAMPAH
nativeplugins/Fvv-AutoStart/android/autostart-release.aar


+ 20 - 0
nativeplugins/Fvv-AutoStart/package.json

@@ -0,0 +1,20 @@
+{
+    "name": "AutoStart",
+    "id": "Fvv-AutoStart",
+    "version": "1.0.0",
+    "description": "安卓开机自启动",
+    "_dp_type":"nativeplugin",
+    "_dp_nativeplugin":{
+        "android": {
+            "plugins": [
+                {
+                    "type": "module",
+                    "name": "Fvv-AutoStart",
+                    "class": "uni.fvv.autostart"
+                }
+            ],
+			"integrateType": "aar",
+            "minSdkVersion": "17"
+        }
+    }
+}

+ 79 - 0
package.json

@@ -0,0 +1,79 @@
+{
+    "name": "uni-preset-vue",
+    "version": "0.0.0",
+    "scripts": {
+        "dev:app": "uni -p app",
+        "dev:custom": "uni -p",
+        "dev:h5": "uni",
+        "dev:h5:prod": "uni --mode production",
+        "dev:h5:ssr": "uni --ssr",
+        "dev:mp-alipay": "uni -p mp-alipay",
+        "dev:mp-baidu": "uni -p mp-baidu",
+        "dev:mp-kuaishou": "uni -p mp-kuaishou",
+        "dev:mp-lark": "uni -p mp-lark",
+        "dev:mp-qq": "uni -p mp-qq",
+        "dev:mp-toutiao": "uni -p mp-toutiao",
+        "dev:mp-weixin": "uni -p mp-weixin",
+        "dev:quickapp-webview": "uni -p quickapp-webview",
+        "dev:quickapp-webview-huawei": "uni -p quickapp-webview-huawei",
+        "dev:quickapp-webview-union": "uni -p quickapp-webview-union",
+        "build:app": "uni build -p app",
+        "build:custom": "uni build -p",
+        "build:h5:prod": "rimraf dist && uni build --mode production",
+        "build:h5:dev": "rimraf dist && uni build --mode development",
+        "build:h5:ssr": "uni build --ssr",
+        "build:mp-alipay": "uni build -p mp-alipay",
+        "build:mp-baidu": "uni build -p mp-baidu",
+        "build:mp-kuaishou": "uni build -p mp-kuaishou",
+        "build:mp-lark": "uni build -p mp-lark",
+        "build:mp-qq": "uni build -p mp-qq",
+        "build:mp-toutiao": "uni build -p mp-toutiao",
+        "build:mp-weixin": "uni build -p mp-weixin",
+        "build:quickapp-webview": "uni build -p quickapp-webview",
+        "build:quickapp-webview-huawei": "uni build -p quickapp-webview-huawei",
+        "build:quickapp-webview-union": "uni build -p quickapp-webview-union",
+        "clear": "rimraf node_modules && npm install --force",
+        "clean": "npm cache clean --force",
+        "update:setting": "node unpackage/config/setting.js"
+    },
+    "dependencies": {
+        "@amap/amap-jsapi-loader": "^1.0.1",
+        "@dcloudio/uni-app": "3.0.0-alpha-4020320240703001",
+        "@dcloudio/uni-app-harmony": "3.0.0-alpha-4020320240703001",
+        "@dcloudio/uni-app-plus": "3.0.0-alpha-4020320240703001",
+        "@dcloudio/uni-components": "3.0.0-alpha-4020320240703001",
+        "@dcloudio/uni-h5": "3.0.0-alpha-4020320240703001",
+        "@dcloudio/uni-mp-alipay": "3.0.0-alpha-4020320240703001",
+        "@dcloudio/uni-mp-baidu": "3.0.0-alpha-4020320240703001",
+        "@dcloudio/uni-mp-jd": "3.0.0-alpha-4020320240703001",
+        "@dcloudio/uni-mp-kuaishou": "3.0.0-alpha-4020320240703001",
+        "@dcloudio/uni-mp-lark": "3.0.0-alpha-4020320240703001",
+        "@dcloudio/uni-mp-qq": "3.0.0-alpha-4020320240703001",
+        "@dcloudio/uni-mp-toutiao": "3.0.0-alpha-4020320240703001",
+        "@dcloudio/uni-mp-weixin": "3.0.0-alpha-4020320240703001",
+        "@dcloudio/uni-mp-xhs": "3.0.0-alpha-4020320240703001",
+        "@dcloudio/uni-quickapp-webview": "3.0.0-alpha-4020320240703001",
+        "echarts": "^5.3.3",
+        "pinia": "2.0.14",
+        "pinia-plugin-persistedstate": "^3.1.0",
+        "vue": "^3.4.21",
+        "vue-echarts": "^6.2.3",
+        "vue-i18n": "^9.1.9",
+        "vue-json-excel": "^0.3.0",
+        "vuex": "^4.0.2",
+        "weixin-js-sdk": "^1.6.0"
+    },
+    "devDependencies": {
+        "@dcloudio/types": "^3.4.8",
+        "@dcloudio/uni-automator": "3.0.0-alpha-4020320240703001",
+        "@dcloudio/uni-cli-shared": "3.0.0-alpha-4020320240703001",
+        "@dcloudio/uni-stacktracey": "3.0.0-alpha-4020320240703001",
+        "@dcloudio/vite-plugin-uni": "3.0.0-alpha-4020320240703001",
+        "@vitejs/plugin-vue": "^2.3.3",
+        "@vue/runtime-core": "^3.4.21",
+        "cross-env": "^7.0.3",
+        "dayjs": "^1.11.7",
+        "sass": "1.57.1",
+        "vite": "5.2.8"
+    }
+}

+ 35 - 0
project.config.json

@@ -0,0 +1,35 @@
+{
+  "appid": "wxadd37e2692c771db",
+  "compileType": "miniprogram",
+  "libVersion": "2.32.2",
+  "packOptions": {
+    "ignore": [],
+    "include": []
+  },
+  "setting": {
+    "packNpmManually": true,
+    "coverView": true,
+    "es6": true,
+    "postcss": true,
+    "minified": true,
+    "enhance": true,
+    "showShadowRootInWxmlPanel": true,
+    "packNpmRelationList": [
+      {
+        "packageJsonPath": "./package.json",
+        "miniprogramNpmDistDir": "./miniprogram/"
+      }
+    ],
+    "babelSetting": {
+      "ignore": [],
+      "disablePlugins": [],
+      "outputPath": ""
+    },
+    "condition": false
+  },
+  "condition": {},
+  "editorSetting": {
+    "tabIndent": "insertSpaces",
+    "tabSize": 2
+  }
+}

+ 7 - 0
project.private.config.json

@@ -0,0 +1,7 @@
+{
+  "description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
+  "projectname": "usky-web-mobile",
+  "setting": {
+    "compileHotReLoad": true
+  }
+}

+ 171 - 0
src/App.vue

@@ -0,0 +1,171 @@
+<script setup>
+/*----------------------------------依赖引入-----------------------------------*/
+import { onLoad, onShow, onHide, onLaunch, onReady, onBackPress } from "@dcloudio/uni-app";
+import { defineComponent, getCurrentInstance, inject, nextTick, onMounted, watchEffect, ref } from "vue";
+/*----------------------------------接口引入-----------------------------------*/
+/*----------------------------------组件引入-----------------------------------*/
+/*----------------------------------store引入-----------------------------------*/
+/*----------------------------------公共方法引入-----------------------------------*/
+import config from "./config";
+import { storageSystem } from "@/utils/storage";
+/*----------------------------------公共变量-----------------------------------*/
+const { proxy } = getCurrentInstance();
+/*----------------------------------变量声明-----------------------------------*/
+function initApp() {
+  proxy.$settingStore.initThemeColor(storageSystem.get("themeColor")); //初始化默认主题
+  proxy.$settingStore.systemHeightTop(); //初始化获取安全区高度
+  //#ifdef APP-PLUS
+  stteingInit();
+  //#endif
+}
+
+//设置初始化
+function stteingInit() {
+  plus.screen.unlockOrientation(); //解除屏幕方向的锁定,但是不一定是竖屏;
+
+  // 综合智慧云
+  if (config.appInfo.appid === "__UNI__36DE3A0") {
+    plus.screen.lockOrientation("portrait-primary"); //设置屏幕方向(1.竖屏正方向:portrait-primary 2.竖屏反方向:portrait-secondary 3.横屏正方向:landscape-primary 4.横屏反方向:landscape-secondary 5.自然方向:default)
+  }
+  // 智能巡更
+  else if (config.appInfo.appid === "__UNI__BF1A1F0") {
+    plus.screen.lockOrientation("portrait-primary"); //设置屏幕方向(1.竖屏正方向:portrait-primary 2.竖屏反方向:portrait-secondary 3.横屏正方向:landscape-primary 4.横屏反方向:landscape-secondary 5.自然方向:default)
+    proxy.$keyListen.startListen(true); //开启物理按钮监听
+  }
+  // 智能会议
+  else if (config.appInfo.appid === "__UNI__F3963F8") {
+    plus.screen.lockOrientation("landscape-primary"); //设置屏幕方向(1.竖屏正方向:portrait-primary 2.竖屏反方向:portrait-secondary 3.横屏正方向:landscape-primary 4.横屏反方向:landscape-secondary 5.自然方向:default)
+    plus.navigator.hideSystemNavigation(); //隐藏安卓底部虚拟导航键
+  }
+
+  proxy.$settingStore.pushListener(); //开启消息推送监听
+}
+
+// 设置手机通知权限
+function setPermissions() {
+  // #ifdef APP-PLUS
+  if (plus.os.name == "Android") {
+    // 判断是Android
+    var main = plus.android.runtimeMainActivity();
+    var pkName = main.getPackageName();
+    var uid = main.getApplicationInfo().plusGetAttribute("uid");
+    var NotificationManagerCompat = plus.android.importClass("android.support.v4.app.NotificationManagerCompat");
+    //android.support.v4升级为androidx
+    if (NotificationManagerCompat == null) {
+      NotificationManagerCompat = plus.android.importClass("androidx.core.app.NotificationManagerCompat");
+    }
+    var areNotificationsEnabled = NotificationManagerCompat.from(main).areNotificationsEnabled();
+    // 未开通‘允许通知’权限,则弹窗提醒开通,并点击确认后,跳转到系统设置页面进行设置
+    if (!areNotificationsEnabled) {
+      uni.showModal({
+        title: "通知权限开启提醒",
+        content: "您还没有开启通知权限,无法接受到消息通知,请前往设置!",
+        showCancel: false,
+        confirmText: "去设置",
+        success: function (res) {
+          if (res.confirm) {
+            var Intent = plus.android.importClass("android.content.Intent");
+            var Build = plus.android.importClass("android.os.Build");
+            //android 8.0引导
+            if (Build.VERSION.SDK_INT >= 26) {
+              var intent = new Intent("android.settings.APP_NOTIFICATION_SETTINGS");
+              intent.putExtra("android.provider.extra.APP_PACKAGE", pkName);
+            } else if (Build.VERSION.SDK_INT >= 21) {
+              //android 5.0-7.0
+              var intent = new Intent("android.settings.APP_NOTIFICATION_SETTINGS");
+              intent.putExtra("app_package", pkName);
+              intent.putExtra("app_uid", uid);
+            } else {
+              //(<21)其他--跳转到该应用管理的详情页
+              intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+              var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);
+              intent.setData(uri);
+            }
+            // 跳转到该应用的系统通知设置页
+            main.startActivity(intent);
+          }
+        },
+      });
+    }
+  } else if (plus.os.name == "iOS") {
+    // 判断是ISO
+    var isOn = undefined;
+    var types = 0;
+    var app = plus.ios.invoke("UIApplication", "sharedApplication");
+    var settings = plus.ios.invoke(app, "currentUserNotificationSettings");
+    if (settings) {
+      types = settings.plusGetAttribute("types");
+      plus.ios.deleteObject(settings);
+    } else {
+      types = plus.ios.invoke(app, "enabledRemoteNotificationTypes");
+    }
+    plus.ios.deleteObject(app);
+    isOn = 0 != types;
+    if (isOn == false) {
+      uni.showModal({
+        title: "通知权限开启提醒",
+        content: "您还没有开启通知权限,无法接受到消息通知,请前往设置!",
+        showCancel: false,
+        confirmText: "去设置",
+        success: function (res) {
+          if (res.confirm) {
+            var app = plus.ios.invoke("UIApplication", "sharedApplication");
+            var setting = plus.ios.invoke("NSURL", "URLWithString:", "app-settings:");
+            plus.ios.invoke(app, "openURL:", setting);
+            plus.ios.deleteObject(setting);
+            plus.ios.deleteObject(app);
+          }
+        },
+      });
+    }
+  }
+  // #endif
+}
+
+watchEffect(() => {
+  //#ifdef APP-PLUS || MP-WEIXIN
+  if (uni.getStorageSync("serveUrl")) {
+    config.baseUrl = "https://" + uni.getStorageSync("serveUrl") + "/prod-api";
+  }
+  //#endif
+});
+
+onLaunch(() => {
+  console.log("App Launch");
+  initApp();
+});
+
+onReady(() => {});
+
+onShow(() => {
+  console.log("App Show");
+});
+
+onHide(() => {
+  console.log("App Hide");
+});
+</script>
+
+<style lang="scss">
+@import "@/static/scss/index.scss";
+</style>
+
+<style lang="scss">
+@import "@/uni_modules/uview-plus/index.scss";
+
+uni-page-body,
+uni-page-refresh {
+  height: 100%;
+}
+
+//默认返回按钮样式
+:deep(.uni-page-head-btn) {
+  background-color: rgba(0, 0, 0, 0) !important;
+}
+
+//默认头部导航title样式
+:deep(.uni-page-head__title) {
+  font-size: $uni-font-size-lg;
+  font-weight: bold;
+}
+</style>

+ 81 - 0
src/api/business/zhaf/xunJian/plan.js

@@ -0,0 +1,81 @@
+import { request, uploads } from "@/utils/request";
+
+//
+export function recordList(param) {
+  return request({
+    url: "/service-fire/appPatrolInspection/recordList",
+    method: "GET",
+    data: param,
+  });
+}
+
+//巡检记录-查看巡检项
+export function recordOption(param) {
+  return request({
+    url: "/service-fire/appPatrolInspection/recordOption",
+    method: "GET",
+    data: param,
+  });
+}
+
+//
+export function planList(param) {
+  return request({
+    url: "/service-fire/appPatrolInspection/planList",
+    method: "GET",
+    data: param,
+  });
+}
+
+//
+export function patrolInspectionPlan(param) {
+  return request({
+    url: "/service-fire/appPatrolInspection/patrolInspectionPlan",
+    method: "GET",
+    data: param,
+  });
+}
+
+//统计接口请求
+export function appPlanStatistics(param) {
+  return request({
+    url: "/service-fire/appPatrolInspection/appPlanStatistics",
+    method: "GET",
+    data: param,
+  });
+}
+
+/**
+ * @站点详情
+ * @siteList站点详情信息存储
+ * @contentList内容详情信息存储
+ */
+export function siteDetails(param) {
+  return request({
+    url: "/service-fire/appPatrolInspection/siteDetails",
+    method: "GET",
+    data: param,
+  });
+}
+
+/**
+ * @地点列表
+ */
+export function planSonSiteDetails(param) {
+  return request({
+    url: "/service-fire/appPatrolInspection/planSonSiteDetails",
+    method: "GET",
+    data: param,
+  });
+}
+
+/**
+ * @提交
+ */
+export function updatePlan(param) {
+  return request({
+    url: "/service-fire/appPatrolInspection/updatePlan",
+    method: "POST",
+    data: param,
+  });
+}

+ 28 - 0
src/api/common/index.js

@@ -0,0 +1,28 @@
+import { request } from "@/utils/request";
+
+//手机号验证
+export function phoneVerify(param) {
+    return request({
+        url: "/service-iot/crmDeviceRepair/phoneVerify",
+        method: "POST",
+        data: param,
+    });
+}
+
+//服务评价
+export function score(param) {
+    return request({
+        url: "/service-iot/crmDeviceRepair/score",
+        method: "POST",
+        data: param,
+    });
+}
+
+//APP心跳
+export function baseAppInfoApi(param) {
+    return request({
+        url: "/service-iot/baseAppInfo/add",
+        method: "POST",
+        data: param,
+    });
+}

+ 64 - 0
src/api/index/index.js

@@ -0,0 +1,64 @@
+import { request } from "@/utils/request";
+
+// 动态菜单请求
+export function getAppRouters(param) {
+  return request({
+    url: "/system/sysMobileMenu/getAppRouters",
+    method: "GET",
+    data: param,
+  });
+}
+
+// 动态菜单请求
+export function getRouters(param) {
+  return request({
+    url: "/system/sysMobileMenu/getRouters",
+    method: "GET",
+    data: param,
+  });
+}
+
+
+// 扫码请求
+export function scan_push(param) {
+  return request({
+    url: "/ScanPush/scan_push",
+    method: "GET",
+    data: param,
+  });
+}
+
+//echarts图表请求
+export function getHomePageData(param) {
+  return request({
+    url: "/Index/getHomePageData",
+    method: "GET",
+    data: param,
+  });
+}
+
+// 未处理告警请求
+export function getFunctionalModuleStatistics(param) {
+  return request({
+    url: "/Index/getFunctionalModuleStatistics",
+    method: "GET",
+    data: param,
+  });
+}
+
+//扫码登录PC端
+export function qrCodeSend(param) {
+  return request({
+    url: "/system/qrCodeSend",
+    method: "GET",
+    data: param,
+  });
+}
+
+//移动端banner图查询
+export function getMobileBanner(param) {
+  return request({
+    url: "/system/sysMobileBanner/getMobileBanner?tenantId=" + param.tenantId,
+    method: "GET",
+  });
+}

+ 54 - 0
src/api/login.js

@@ -0,0 +1,54 @@
+import { request } from "@/utils/request";
+
+// 登录方法
+export function login(data) {
+  return request({
+    url: "/system/appLogin",
+    headers: {
+      isToken: false,
+    },
+    method: "POST",
+    data: data,
+  });
+}
+
+// 获取用户详细信息
+export function getInfo() {
+  return request({
+    url: "/system/getInfo",
+    method: "get",
+  });
+}
+
+// 退出方法
+export function logout(data) {
+  return request({
+    url: "/system/logout",
+    method: "delete",
+    params: data
+  });
+}
+
+// 获取验证码
+export function getCodeImg(data) {
+  return request({
+    url: "/system/SendSms/noteSending",
+    headers: {
+      isToken: false,
+    },
+    method: "GET",
+    data: data,
+  });
+}
+
+/** 获取登录页数据 */
+export function getMobileTenantConfig(data) {
+  return request({
+    url: "/system/sysMobileTenantConfig/getAppTenantConfig",
+    headers: {
+      isToken: false,
+    },
+    method: "GET",
+    data: data,
+  });
+}

+ 52 - 0
src/api/system/dict.js

@@ -0,0 +1,52 @@
+import { request } from "@/utils/request";
+
+// 查询字典数据列表
+export function listData(query) {
+  return request({
+    url: '/system/dict/data/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询字典数据详细
+export function getData(dictCode) {
+  return request({
+    url: '/system/dict/data/' + dictCode,
+    method: 'get'
+  })
+}
+
+// 根据字典类型查询字典数据信息
+export function getDicts(dictType) {
+  return request({
+    url: '/system/dict/data/type/' + dictType,
+    method: 'get'
+  })
+}
+
+// 新增字典数据
+export function addData(data) {
+  return request({
+    url: '/system/dict/data',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改字典数据
+export function updateData(data) {
+  return request({
+    url: '/system/dict/data',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除字典数据
+export function delData(dictCode) {
+  return request({
+    url: '/system/dict/data/' + dictCode,
+    method: 'delete'
+  })
+}

+ 21 - 0
src/api/system/setting.js

@@ -0,0 +1,21 @@
+import { request, uploads } from '@/utils/request';
+
+// 检测App是否有更新
+export function checkUpdates(data) {
+    return request({
+        baseUrl: "https://www.pgyer.com",
+        url: '/apiv2/app/check',
+        method: 'POST',
+        params: data
+    })
+}
+
+// 安装 App
+export function install(data) {
+    return request({
+        baseUrl: "https://www.pgyer.com",
+        url: '/apiv2/app/install',
+        method: 'GET',
+        params: data
+    })
+}

+ 93 - 0
src/api/system/user.js

@@ -0,0 +1,93 @@
+import { request, uploads } from '@/utils/request';
+
+// 用户密码重置
+export function updateUserPwd(oldPassword, newPassword) {
+  const data = {
+    oldPassword,
+    newPassword
+  }
+  return request({
+    url: '/system/user/profile/updatePwd',
+    method: 'put',
+    params: data
+  })
+}
+
+// 查询用户个人信息
+export function getUserProfile() {
+  return request({
+    url: '/system/user/profile',
+    method: 'get'
+  })
+}
+
+// 修改用户个人信息
+export function updateUserProfile(data) {
+  return request({
+    url: '/system/user/profile',
+    method: 'put',
+    data: data
+  })
+}
+
+// 用户头像上传
+export function uploadAvatar(data) {
+  return uploads({
+    url: "/service-file/upload",
+    name: data.name,
+    filePath: data.filePath,
+  });
+}
+
+// 注册用户个人信息
+export function appAdd(data) {
+  return request({
+    url: '/system/user/appAdd',
+    method: 'POST',
+    data: data
+  })
+}
+
+// 注销用户个人信息
+export function appDel(data) {
+  return request({
+    url: `/system/user/${data.id}`,
+    method: 'DELETE',
+  })
+}
+
+// 树结构查询部门--用户列表
+export function deptUserTreeSelect(query) {
+  return request({
+    url: '/system/dept/deptUserTreeSelect',
+    method: 'GET',
+    params: query
+  })
+}
+
+// 用户列表
+export function UserList(query) {
+  return request({
+    url: '/system/user/list',
+    method: 'GET',
+    params: query
+  })
+}
+
+// 用户列表(无数据权限)
+export function dUserList(query) {
+  return request({
+    url: '/system/user/dUserList',
+    method: 'GET',
+    params: query
+  })
+}
+
+// 微信用户验证
+export function getPageAuthorization(data) {
+  return request({
+    url: '/service-iot/weChat/getPageAuthorization',
+    method: 'GET',
+    data: data,
+  })
+}

+ 51 - 0
src/config.js

@@ -0,0 +1,51 @@
+import manifest from './manifest.json'
+
+// 应用全局配置
+export default {
+  //#ifdef APP-PLUS || MP-WEIXIN
+  baseUrl: "https://gateWay.usky.cn/prod-api",
+  //#endif
+
+  //#ifdef H5
+  baseUrl: import.meta.env.MODE === "production" ? `https://${window.location.host}/prod-api` : `http://172.16.120.165:801/dev-api`,
+  //#endif
+
+  websiteUrl: "https://qhome.usky.cn",
+  // 应用信息
+  appInfo: {
+    // 应用id
+    appid: manifest.appid,
+    // 应用名称
+    name: manifest.name,
+    // 应用版本
+    version: uni.getSystemInfoSync().appWgtVersion || uni.getSystemInfoSync().appVersion,
+    // 应用logo
+    logo: "/static/logo.png",
+    // 官网邮箱
+    email: "admin@chinausky.com",
+    // 服务热线
+    hotline: "021-65376655",
+    // 官方网站
+    site_url: "http://www.usky.cn/",
+    // 版权
+    copyright: "Copyright © 2021- 2025 Usky. All Rights Reserved. 永天股份 版权所有",
+    // 备案编号
+    filingInfo: {
+      code: "ICP备案号:沪ICP备09005762号-15A",
+      href: "https://beian.miit.gov.cn/#/Integrated/index"
+    },
+    // 政策协议
+    agreements: [
+      {
+        title: "用户服务协议",
+        content: "暂无数据",
+        url: "http://file.usky.cn/uskycloud/user_protocol.html",
+      },
+      {
+        title: "隐私政策",
+        content: "暂无数据",
+        url: "http://file.usky.cn/uskycloud/privacy_protocol.html",
+      },
+    ],
+  },
+};

+ 34 - 0
src/main.js

@@ -0,0 +1,34 @@
+import { createSSRApp } from "vue";
+import App from "./App";
+import store from "./store"; // store
+import plugins from "./plugins"; // plugins
+import "./permission"; // permission
+
+// 引入json导出组件
+import JsonExcel from "vue-json-excel";
+
+// 引入UI组件
+import uviewPlus from "@/uni_modules/uview-plus";
+
+export function createApp() {
+  const app = createSSRApp(App);
+
+  //挂载全局组件
+
+  
+
+  // 挂载全局json导出
+  app.component("downloadExcel", JsonExcel);
+  // 添加全局变量
+  app.provide("$store", store);
+  app.config.globalProperties.$store = store;
+
+  app
+    .use(uviewPlus)
+    .use(store)
+    .use(plugins);
+
+  return {
+    app,
+  };
+}

+ 235 - 0
src/manifest.json

@@ -0,0 +1,235 @@
+{
+    "name" : "综合智慧云",
+    "appid" : "__UNI__36DE3A0",
+    "description" : "综合智慧云APP,是一款助力于企业数字化的应用平台,帮助企业提升办公效率,实现组织数字化和业务数字化。",
+    "versionName" : "2.2.4",
+    "versionCode" : 24,
+    "transformPx" : false,
+    "app-plus" : {
+        "compatible" : {
+            "ignoreVersion" : true
+        },
+        "kernel" : {
+            "ios" : "WKWebview"
+        },
+        "usingComponents" : true,
+        "nvueStyleCompiler" : "uni-app",
+        "compilerVersion" : 3,
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        "screenOrientation" : [
+            "portrait-primary",
+            "portrait-secondary",
+            "landscape-primary",
+            "landscape-secondary"
+        ],
+        "modules" : {
+            "VideoPlayer" : {},
+            "iBeacon" : {},
+            "Geolocation" : {},
+            "Maps" : {},
+            "Barcode" : {},
+            "Fingerprint" : {},
+            "Push" : {},
+            "Camera" : {},
+            "LivePusher" : {}
+        },
+        "distribute" : {
+            "android" : {
+                "permissions" : [
+                    "<uses-feature android:name=\"android.hardware.camera\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.BIND_DREAM_SERVICE\"/>",
+                    "<uses-permission android:name=\"android.permission.BIND_NFC_SERVICE\"/>",
+                    "<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
+                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+                    "<uses-permission android:name=\"android.permission.INSTALL_PACKAGES\"/>",
+                    "<uses-permission android:name=\"android.permission.INTERNET\"/>",
+                    "<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
+                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+                    "<uses-permission android:name=\"android.permission.NFC\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_CONTACTS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
+                    "<uses-permission android:name=\"android.permission.REQUEST_INSTALL_PACKAGES\"/>",
+                    "<uses-permission android:name=\"android.permission.USE_FINGERPRINT\"/>",
+                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_CONTACTS\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_SMS\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_LOCATION_EXTRA_COMMANDS\"/>",
+                    "<uses-permission android:name=\"android.permission.FOREGROUND_SERVICE\"/>",
+                    "<uses-permission android:name=\"android.permission.BLUETOOTH\"/>",
+                    "<uses-permission android:name=\"android.permission.BLUETOOTH_ADMIN\"/>",
+                    "<uses-permission android:name=\"android.permission.RECEIVE_BOOT_COMPLETED\"/>",
+                    "<uses-permission android:name=\"android.permission.SYSTEM_ALERT_WINDOW\"/>"
+                ],
+                "minSdkVersion" : "",
+                "abiFilters" : [ "armeabi-v7a", "arm64-v8a" ],
+                "targetSdkVersion" : 30
+            },
+            "ios" : {
+                "dSYMs" : false,
+                "privacyDescription" : {
+                    "NSPhotoLibraryUsageDescription" : "该应用需要读取你的相册,用于上传头像",
+                    "NSPhotoLibraryAddUsageDescription" : "该应用需要读取你的相册,用于拍照保存图片",
+                    "NSCameraUsageDescription" : "该应用需要你的相机,用于你拍摄上传头像信息",
+                    "NSMicrophoneUsageDescription" : "该应用需要使用你的麦克风,用于语音播放",
+                    "NSLocationWhenInUseUsageDescription" : "该应用需要你的地理位置,用于天气、签到等功能",
+                    "NSLocationAlwaysUsageDescription" : "该应用需要持续获取用户地理位置,用于天气、签到等功能",
+                    "NSLocationAlwaysAndWhenInUseUsageDescription" : "该应用需要你的地理位置,用于天气、签到等功能",
+                    "NSCalendarsUsageDescription" : "该应用需要获取你的日历,以便更好的体验",
+                    "NSContactsUsageDescription" : "该应用需要读取你的通讯录,以便联系同事",
+                    "NSBluetoothPeripheralUsageDescription" : "该应用需要你的蓝牙,以便读取相关蓝牙设备",
+                    "NFCReaderUsageDescription" : "",
+                    "NSBluetoothAlwaysUsageDescription" : "该应用需要你的蓝牙,以便读取相关蓝牙设备"
+                },
+                "UIBackgroundModes" : ""
+            },
+            "sdkConfigs" : {
+                "ad" : {},
+                "maps" : {
+                    "amap" : {
+                        "appkey_ios" : "fb35d03fbb17cbf7a8743a522da3c7fc",
+                        "appkey_android" : "ffc71dfd4e576596027f8f45a1b8fb2f",
+                        "name" : "amapBOujshtbA"
+                    }
+                },
+                "geolocation" : {
+                    "system" : {
+                        "__platform__" : [ "ios", "android" ]
+                    },
+                    "amap" : {
+                        "__platform__" : [ "ios", "android" ],
+                        "appkey_ios" : "fb35d03fbb17cbf7a8743a522da3c7fc",
+                        "appkey_android" : "ffc71dfd4e576596027f8f45a1b8fb2f",
+                        "name" : "amapBOujshtbA"
+                    }
+                },
+                "push" : {
+                    "unipush" : {
+                        "version" : "2",
+                        "offline" : true,
+                        "icons" : {
+                            "small" : {
+                                "hdpi" : "unpackage/res/push/36x36.png",
+                                "ldpi" : "unpackage/res/push/18x18.png",
+                                "mdpi" : "unpackage/res/push/24x24.png",
+                                "xhdpi" : "unpackage/res/push/48x48.png",
+                                "xxhdpi" : "unpackage/res/push/72x72.png"
+                            }
+                        }
+                    }
+                }
+            },
+            "icons" : {
+                "android" : {
+                    "hdpi" : "unpackage/res/icons/72x72.png",
+                    "xhdpi" : "unpackage/res/icons/96x96.png",
+                    "xxhdpi" : "unpackage/res/icons/144x144.png",
+                    "xxxhdpi" : "unpackage/res/icons/192x192.png"
+                },
+                "ios" : {
+                    "appstore" : "unpackage/res/icons/1024x1024.png",
+                    "ipad" : {
+                        "app" : "unpackage/res/icons/76x76.png",
+                        "app@2x" : "unpackage/res/icons/152x152.png",
+                        "notification" : "unpackage/res/icons/20x20.png",
+                        "notification@2x" : "unpackage/res/icons/40x40.png",
+                        "proapp@2x" : "unpackage/res/icons/167x167.png",
+                        "settings" : "unpackage/res/icons/29x29.png",
+                        "settings@2x" : "unpackage/res/icons/58x58.png",
+                        "spotlight" : "unpackage/res/icons/40x40.png",
+                        "spotlight@2x" : "unpackage/res/icons/80x80.png"
+                    },
+                    "iphone" : {
+                        "app@2x" : "unpackage/res/icons/120x120.png",
+                        "app@3x" : "unpackage/res/icons/180x180.png",
+                        "notification@2x" : "unpackage/res/icons/40x40.png",
+                        "notification@3x" : "unpackage/res/icons/60x60.png",
+                        "settings@2x" : "unpackage/res/icons/58x58.png",
+                        "settings@3x" : "unpackage/res/icons/87x87.png",
+                        "spotlight@2x" : "unpackage/res/icons/80x80.png",
+                        "spotlight@3x" : "unpackage/res/icons/120x120.png"
+                    }
+                }
+            },
+            "splashscreen" : {
+                "androidStyle" : "default",
+                "android" : {
+                    "hdpi" : "src/static/images/wt/bg.png"
+                },
+                "iosStyle" : "common"
+            }
+        },
+        "nativePlugins" : {},
+        "safearea" : {
+            "offset" : "none"
+        }
+    },
+    "quickapp" : {},
+    "mp-weixin" : {
+        "appid" : "",
+        "setting" : {
+            "urlCheck" : false,
+            "checkSiteMap" : false
+        },
+        "usingComponents" : true
+    },
+    "mp-alipay" : {
+        "usingComponents" : true
+    },
+    "mp-baidu" : {
+        "usingComponents" : true
+    },
+    "mp-toutiao" : {
+        "usingComponents" : true
+    },
+    "uniStatistics" : {
+        "enable" : false
+    },
+    "h5" : {
+        "publicPath" : "./",
+        "title" : "综合智慧云",
+        "router" : {
+            "mode" : "hash"
+        },
+        "devServer" : {
+            "https" : false,
+            "proxy" : {}
+        },
+        "sdkConfigs" : {
+            "maps" : {
+                "amap" : {
+                    "key" : "d4d73a7d572b6ff6028d5f67de62029a",
+                    "securityJsCode" : "be916fcd16d0b33d228c49f0ff096b17",
+                    "serviceHost" : ""
+                }
+            }
+        },
+        "optimization" : {
+            "treeShaking" : {
+                "enable" : true
+            }
+        },
+        "template" : "index.html"
+    },
+    "vueVersion" : "3",
+    "locale" : "zh-Hans"
+}

+ 91 - 0
src/pages.json

@@ -0,0 +1,91 @@
+{
+    "pages": [
+        {
+            "path": "pages/login",
+            "style": {
+                "navigationBarTitleText": "登录",
+                "navigationStyle": "custom",
+                "navigationBarTextStyle": "black"
+            }
+        },
+        {
+            "path": "pages/index",
+            "style": {
+                "navigationStyle": "custom",
+                "navigationBarTitleText": "工作台",
+                "app-plus": {
+                    "bounce": "none",
+                    "titleNView": false
+                }
+            }
+        },
+        
+        {
+            "path": "pages/register",
+            "style": {
+                "navigationBarTitleText": "注册",
+                "navigationStyle": "custom",
+                "navigationBarTextStyle": "black"
+            }
+        },
+        {
+            "path": "pages/serveConfigSelect",
+            "style": {
+                "navigationBarTitleText": "服务器配置",
+                "navigationStyle": "custom",
+                "navigationBarTextStyle": "black"
+            }
+        },
+        {
+            "path": "pages/serveConfig",
+            "style": {
+                "navigationBarTitleText": "服务器配置",
+                "navigationStyle": "custom",
+                "navigationBarTextStyle": "black"
+            }
+        },
+        {
+            "path": "pages/info",
+            "style": {
+                "navigationBarTitleText": "消息",
+                "navigationStyle": "custom",
+                "enablePullDownRefresh": false,
+                "app-plus": {
+                    "bounce": "none",
+                    "titleNView": false
+                }
+            }
+        },
+        {
+            "path": "pages/mine",
+            "style": {
+                "navigationBarTitleText": "我的",
+                "navigationStyle": "custom",
+                "app-plus": {
+                    "bounce": "none",
+                    "titleNView": false
+                }
+            }
+        }
+       
+    ],
+    "subPackages": [
+
+    ],
+    "globalStyle": {
+        "navigationBarTextStyle": "white",
+        "navigationBarTitleText": "uni-app",
+        "backgroundColor": "#F8F8F8"
+    },
+   
+    "condition": {
+        "current": 0,
+        "list": [
+            {
+                "name": "",
+                "path": "pages/login",
+                "query": ""
+            }
+        ]
+    }
+}

+ 31 - 0
src/pages/index.vue

@@ -0,0 +1,31 @@
+<template>
+  <!-- <view style="color:red">登录了</view> -->
+        <web-view src="https://manager.usky.cn/mobile/#/">跳转</web-view>
+</template>
+
+<script setup>
+import { onLoad, onShow, onHide, onLaunch, onReady } from "@dcloudio/uni-app";
+
+
+onShow(() => {
+
+  
+
+// 正确示范
+uni.setNavigationBarColor({
+	frontColor:"#ffffff",
+	backgroundColor:"#149EFF",
+});
+
+uni.setNavigationBarTitle({
+  title: ''
+});
+
+})
+
+
+</script> 
+
+<style lang="scss" scoped>
+
+</style>

+ 12 - 0
src/pages/info.vue

@@ -0,0 +1,12 @@
+<template>
+  <view>消息</view>
+  <!--       <web-view src="https://manager.usky.cn/mobile/#/">跳转</web-view> -->
+</template>
+
+<script setup>
+
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 508 - 0
src/pages/login.vue

@@ -0,0 +1,508 @@
+<template>
+  <view id="login-container" class="login-container">
+    <image class="bgImage" :src="useStore.loginBg" v-if="useStore.loginBg" />
+
+    <view class="middle">
+      <view class="middle-top">
+        <image class="logo" mode="heightFix" :src="useStore.loginLogo" v-if="useStore.loginLogo" />
+        <text class="title" :style="{ color: useStore.loginBg ? '#FFFFFF' : '#000000' }" v-if="useStore.loginTitle">{{ useStore.loginTitle }}</text>
+      </view>
+
+      <view class="middle-content">
+        <text class="title" :style="{ color: useStore.loginBg ? '#FFFFFF' : '#000000' }">请登录</text>
+        <!-- #ifdef APP-PLUS || MP-WEIXIN -->
+        <view class="prompt" v-if="!linkUrl">首次账号登录请先配置服务器</view>
+        <view class="setting" @tap="goSeverConfig"> 配置服务器 </view>
+        <!--#endif-->
+      </view>
+
+      <view class="middle-input" v-if="switchText == '验证码登录'">
+        <u-input v-model="phone" prefixIcon="phone" placeholder="请输入手机号" :maxlength="11" :adjustPosition="false" />
+        <u-input v-model="verify" prefixIcon="email" placeholder="请输入验证码" :maxlength="6" :adjustPosition="false">
+          <template #suffix>
+            <button class="verify" @click="getVerifyCode">{{ !useStore.codeTime ? "获取验证码" : useStore.codeTime + "s" }}</button>
+          </template>
+        </u-input>
+      </view>
+
+      <view class="middle-input" v-if="switchText == '账号密码登录'">
+        <u-input type="text" v-model="username" prefixIcon="account" placeholder="请输入账号" :adjustPosition="false" />
+        <u-input v-model="password" prefixIcon="lock" placeholder="请输入密码" :password="isPassword" :adjustPosition="false">
+          <template #suffix>
+            <text :class="!isPassword ? 'iconfont oaIcon-eye' : 'iconfont oaIcon-eye-close'" @click="isPassword = !isPassword"></text>
+          </template>
+        </u-input>
+      </view>
+
+      <button class="middle-submit" @click="submitRes">登 录</button>
+
+      <!-- #ifdef APP-PLUS || MP-WEIXIN || H5 -->
+      <view class="middle-switch">
+        <text class="switch-loginMethod" @click="switchMode(1)">{{ switchText === "验证码登录" ? "账号密码登录" : "验证码登录" }}</text>
+        <view style="margin: auto"></view>
+        <text class="switch-register" @click="switchMode(2)">注册账号</text>
+      </view>
+      <!--#endif-->
+
+      <!-- #ifdef APP-PLUS || MP-WEIXIN -->
+      <view class="middle-agreed text-center">
+        <u-checkbox shape="circle" inactiveColor="#0081ff" size="13" :usedAlone="true" :checked="uChecked" @change="uCheckedChange"></u-checkbox>
+        <!-- <text>登录即已代表阅读并同意</text> -->
+        <text>我已阅读并同意</text>
+        <text @click="handleUserAgrement" class="text-blue">用户协议</text>
+        <text>和</text>
+        <text @click="handlePrivacy" class="text-blue">隐私政策</text>
+      </view>
+      <!--#endif-->
+    </view>
+
+    <view class="bottom">
+      <div class="title">{{ useStore.loginBottomTitle }}</div>
+    </view>
+  </view>
+
+  <u-modal :show="modalShow" title="用户协议及隐私政策" :confirmText="'同意'" :cancelText="'不同意'" :zoom="false" :showCancelButton="true" @confirm="modalConfirm()" @cancel="modalShow = false">
+    <view class="slot-content">
+      <view>
+        您在使用我们的服务时,我们可能会收集和使用您的相关信息。我们希望通过本
+        <text class="text-blue underline">《用户协议及隐私政策》</text>
+        向您说明,在使用我们的服务时,我们如何收集、使用、 储存和分享这些信息,以及我们为您提供的访问、更新、控制和保护这些信息的方式。本
+        <text @click="handleUserAgrement" class="text-blue underline">《用户协议</text>
+        <text class="text-blue">及</text>
+        <text @click="handlePrivacy" class="text-blue underline">隐私政策》</text>,希望您仔细阅读,充分理解协议中的内容后再点击同意。
+      </view>
+    </view>
+  </u-modal>
+
+  <u-modal
+    :show="xunJianStore.modal.show"
+    title="提醒"
+    :zoom="false"
+    :showConfirmButton="true"
+    :showCancelButton="true"
+    :closeOnClickOverlay="true"
+    @confirm="xunJianStore.modalConfirm"
+    @cancel="xunJianStore.modal.show = false"
+    @close="xunJianStore.modal.show = false"
+  >
+    <view class="slot-content">
+      <view class="mb20">
+        <u-input v-model="xunJianStore.modal.exitPassword" placeholder="霸屏退出密码(必填)" border="bottom" style="padding: 6px 0px" />
+      </view>
+    </view>
+  </u-modal>
+</template>
+
+<script setup>
+/*----------------------------------依赖引入-----------------------------------*/
+import { onLoad, onShow, onHide, onLaunch, onReady } from "@dcloudio/uni-app";
+import { reactive, getCurrentInstance, toRefs, inject, nextTick } from "vue";
+/*----------------------------------接口引入-----------------------------------*/
+/*----------------------------------组件引入-----------------------------------*/
+/*----------------------------------store引入-----------------------------------*/
+import { useStores, commonStores, xunJianStores } from "@/store/modules/index";
+/*----------------------------------公共方法引入-----------------------------------*/
+import config from "@/config";
+import { storageSystem } from "@/utils/storage";
+/*----------------------------------公共变量-----------------------------------*/
+const { proxy } = getCurrentInstance();
+const useStore = useStores();
+const commonStore = commonStores();
+const xunJianStore = xunJianStores();
+/*----------------------------------变量声明-----------------------------------*/
+const state = reactive({
+  /** login数据 */
+  phone: undefined,
+  verify: undefined,
+  switchText: "验证码登录",
+  username: undefined,
+  password: undefined,
+  isPassword: true,
+  /** 服务器配置数据 */
+  linkUrl: uni.getStorageSync("serveUrl"),
+  /** 用户隐私协议数据 */
+  uChecked: false,
+  modalShow: false,
+});
+
+const { phone, verify, switchText, username, password, isPassword, linkUrl, uChecked, modalShow } = toRefs(state);
+
+/**
+ * @跳转服务器配置
+ */
+function goSeverConfig() {
+  proxy.$tab.navigateTo("/pages/serveConfigSelect");
+}
+
+/**
+ * @登录方式切换
+ */
+function switchMode(value) {
+  if (value == 1) {
+    switchText.value = switchText.value == "验证码登录" ? "账号密码登录" : "验证码登录";
+    if (switchText.value == "验证码登录") {
+      phone.value = username.value;
+    } else {
+      username.value = phone.value;
+    }
+  } else if (value == 2) {
+    proxy.$tab.navigateTo("/pages/register");
+  }
+}
+
+/**
+ * @点击发送验证码
+ */
+function getVerifyCode() {
+  //#ifdef APP-PLUS || MP-WEIXIN
+  if (!uni.getStorageSync("serveUrl")) {
+    proxy.$modal.msg("首次账号登录请先配置服务器");
+    return;
+  }
+  //#endif
+
+  verify.value = undefined;
+  useStore.GetCodeImg({
+    phone: phone.value,
+    success: (res) => {
+      proxy.$modal.msgSuccess("发送成功");
+    },
+  });
+}
+
+/**
+ * @初始化
+ */
+function init() {
+  useStore.SetInterval("codeTime"); //调用倒计时定时器
+
+  //#ifdef H5
+  useStore.GetWxOpenId(1); //调用获取微信公众号openId
+
+  if (window.location.host) {
+    linkUrl.value = window.location.host;
+    // linkUrl.value = "172.16.120.165:13200";
+    // linkUrl.value = "localhost:81";
+    useStore.GetMobileTenantConfig({ url: linkUrl.value });
+  }
+  //#endif
+
+  //#ifdef APP-PLUS || MP-WEIXIN
+  if (uni.getStorageSync("serveUrl")) {
+    linkUrl.value = uni.getStorageSync("serveUrl");
+    // linkUrl.value = "localhost:81";
+    useStore.GetMobileTenantConfig({ url: linkUrl.value });
+  } else {
+    uni.setStorageSync("serveUrl", "manager.usky.cn");
+    commonStore.setServeList("manager.usky.cn", "");
+    linkUrl.value = uni.getStorageSync("serveUrl");
+    // linkUrl.value = "localhost:81";
+    useStore.GetMobileTenantConfig({ url: linkUrl.value });
+  }
+  //#endif
+}
+
+/** 点击提交按钮 */
+function submitRes() {
+  //#ifdef APP-PLUS || MP-WEIXIN
+  if (!uni.getStorageSync("serveUrl")) {
+    proxy.$modal.msg("首次登录请先进行服务器配置");
+    return;
+  }
+
+  if (!uChecked.value) {
+    modalShow.value = true;
+    return;
+  }
+  //#endif
+
+  if (switchText.value == "验证码登录") {
+    if (!phone.value) {
+      proxy.$modal.msg("请输入手机号");
+      return;
+    }
+    if (!/^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$/.test(phone.value)) {
+      proxy.$modal.msg("请输入正确的手机号");
+      return;
+    }
+    if (!verify.value) {
+      proxy.$modal.msg("请输入验证码");
+      return;
+    }
+  } else {
+    if (!username.value) {
+      proxy.$modal.msg("请输入账户");
+      return;
+    }
+    if (!password.value) {
+      proxy.$modal.msg("请输入密码");
+      return;
+    }
+  }
+
+  login({
+    username: state.switchText == "账号密码登录" ? state.username : undefined,
+    password: state.switchText == "账号密码登录" ? state.password : undefined,
+    phone: state.switchText == "验证码登录" ? state.phone : undefined,
+    verify: state.switchText == "验证码登录" ? state.verify : undefined,
+    tenantId: useStore.tenantId,
+    cids: proxy.$settingStore.pushClientId || undefined,
+    type: proxy.$common.isWechatMp() ? "wx" : "app",
+    openId: proxy.$common.isWechatMp() ? localStorage.getItem("wxOpenId") : undefined,
+  });
+}
+
+/** 获取登录数据 */
+function login(data) {
+  proxy.$modal.loading("登录中,请耐心等待...");
+
+  useStore.Login(data).then(() => {
+    /** 获取用户信息 */
+    proxy.$modal.closeLoading();
+    useStore.GetInfo().then((res) => {
+      proxy.$tab.reLaunch("/pages/index");
+      proxy.$settingStore.initThemeColor(storageSystem.get("themeColor")); //初始化默认主题
+    });
+  });
+}
+
+/** 隐私弹窗确定事件 */
+function modalConfirm() {
+  state.uChecked = true;
+  state.modalShow = false;
+  setTimeout(() => {
+    submitRes();
+  });
+}
+
+// 复选框chage事件
+function uCheckedChange(e) {
+  state.uChecked = e;
+}
+
+// 用户协议
+function handleUserAgrement() {
+  let site = config.appInfo.agreements[0];
+  proxy.$tab.navigateTo(`/pages/common/webview/index?title=${site.title}&url=${site.url}`);
+}
+
+// 隐私协议
+function handlePrivacy() {
+  let site = config.appInfo.agreements[1];
+  proxy.$tab.navigateTo(`/pages/common/webview/index?title=${site.title}&url=${site.url}`);
+}
+
+onShow(() => {
+  nextTick(() => {
+    init();
+  });
+});
+
+onLoad((options) => {});
+</script>
+
+<style lang="scss" scoped>
+:deep() {
+  .u-modal {
+    .slot-content {
+      font-size: 16px;
+      width: 100%;
+    }
+  }
+}
+.login-container {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  display: flex;
+  width: 100%;
+  height: 100vh;
+  background-color: $uni-bg-color;
+
+  .bgImage {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    z-index: 0;
+    width: 100%;
+    height: 100%;
+  }
+
+  .middle {
+    position: relative;
+    z-index: 1;
+    width: 100%;
+    padding: 0 30px;
+    margin: auto;
+    margin-top: 30%;
+
+    &-top {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      margin-bottom: 60px;
+
+      .logo {
+        height: 40px;
+        width: auto;
+        margin-right: 10px;
+      }
+
+      .title {
+        font-size: 20px;
+        color: #000;
+        max-width: 50%;
+        // white-space: nowrap;
+        // overflow: hidden; //超出的文本隐藏
+        // text-overflow: ellipsis; //溢出用省略号显示
+      }
+    }
+
+    &-content {
+      display: flex;
+      position: relative;
+      margin: 30px 0 30px 0;
+      .title {
+        margin: auto auto auto 0;
+        color: #000;
+        font-size: 18px;
+      }
+
+      .setting {
+        color: #2a98ff;
+        margin: auto 0;
+      }
+
+      .prompt {
+        position: absolute;
+        top: -35px;
+        right: 0px;
+        background-color: #2a98ff;
+        text-align: center;
+        line-height: 25px;
+        display: inline-block;
+        color: #fff;
+        padding: 3px 5px;
+        border-radius: 3px;
+
+        &::after {
+          content: "";
+          position: absolute;
+          border: 5px solid transparent;
+          transform: rotate(90deg);
+          right: 5px;
+          bottom: -9px;
+          border-left-color: #2a98ff;
+        }
+      }
+    }
+
+    // 登录页-服务器配置样式 开始
+    &-input {
+      :deep() {
+        .u-input {
+          height: 45px;
+          border: 0 !important;
+          border-radius: 8px;
+          margin-bottom: 15px;
+          padding: 5px 12px !important;
+          background-color: #f5f6fa !important;
+        }
+        .input-placeholder {
+          color: #c0c4cc !important;
+        }
+        .uni-input-wrapper {
+          font-size: 16px;
+        }
+        .u-icon__icon {
+          font-size: 24px !important;
+          line-height: 24px !important;
+          color: gray !important;
+        }
+        .iconfont {
+          color: gray !important;
+        }
+        :-webkit-autofill {
+          caret-color: #000; // 设置光标颜色
+          // -webkit-text-fill-color: gray !important;
+          -webkit-box-shadow: 0 0 0px 1000px transparent inset !important;
+          background-color: transparent;
+          background-image: none;
+          transition: background-color 50000s ease-in-out 0s; //背景色透明  生效时长  过渡效果  启用时延迟的时间
+        }
+      }
+    }
+
+    &-switch {
+      width: 100%;
+      display: flex;
+      margin-top: 20px;
+      color: #96a6b5;
+
+      &-loginMethod {
+        display: block;
+      }
+
+      &-register {
+        display: block;
+      }
+    }
+
+    &-submit {
+      height: 45px;
+      line-height: 45px;
+      border-radius: 24px;
+      background: #2a98ff;
+      color: #fff;
+      border: 0px;
+    }
+
+    &-agreed {
+      color: #96a6b5;
+      margin-top: 30px;
+      display: flex;
+      flex-wrap: wrap;
+      justify-content: center;
+      > uni-view {
+        margin: auto 0;
+      }
+      > uni-text {
+        margin: auto 0;
+      }
+      // animation: roundRule 0.5s linear infinite;
+    }
+
+    @keyframes roundRule {
+      0% {
+        transform: translateX(0);
+      }
+      50% {
+        transform: translateX(-5px);
+      }
+      100% {
+        transform: translateX(0);
+      }
+    }
+  }
+
+  .bottom {
+    position: fixed;
+    width: 100%;
+    bottom: 20px;
+    .title {
+      text-align: center;
+      color: #96a6b5;
+      font-size: 14px;
+    }
+  }
+}
+
+@media (min-width: 1280px) {
+  .middle {
+    margin-top: auto !important;
+  }
+}
+</style>

+ 12 - 0
src/pages/mine.vue

@@ -0,0 +1,12 @@
+<template>
+  <view>我的</view>
+  <!--       <web-view src="https://manager.usky.cn/mobile/#/">跳转</web-view> -->
+</template>
+
+<script setup>
+
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 217 - 0
src/pages/register.vue

@@ -0,0 +1,217 @@
+<template>
+  <view id="register-container">
+    <view class="top-area">
+      <u-icon name="arrow-left" size="17px" color="#000" :bold="true" @click="navigateTo"></u-icon>
+    </view>
+
+    <view class="content-area">
+      <text class="content-area-title">注册</text>
+    </view>
+
+    <view class="bottom-area">
+      <u-input v-model="phone" prefixIcon="phone" placeholder="手机号(必填)" border="none" />
+      <u-input v-model="verify" prefixIcon="chat" placeholder="验证码(必填)" border="none" :maxlength="6">
+        <template #suffix>
+          <button class="verify" @click="getVerifyCode">{{ !useStore.codeTime ? "获取验证码" : useStore.codeTime + "s" }}</button>
+        </template>
+      </u-input>
+      <u-input v-model="userName" prefixIcon="account" placeholder="用户名(必填)" border="none" />
+      <u-input v-model="email" prefixIcon="email" placeholder="邮箱(必填)" border="none" />
+      <u-input v-model="nickName" prefixIcon="coupon" placeholder="真实姓名(必填)" border="none" />
+      <u-input v-model="newPassword" prefixIcon="lock" placeholder="密码(必填)" border="none" :password="newPasswordBool">
+        <template #suffix>
+          <text :class="!newPasswordBool ? 'iconfont oaIcon-eye' : 'iconfont oaIcon-eye-close'" @click="newPasswordBool = !newPasswordBool"></text>
+        </template>
+      </u-input>
+      <u-input v-model="confirmPassword" prefixIcon="lock" placeholder="再次输入密码(必填)" border="none" :password="confirmPasswordBool">
+        <template #suffix>
+          <text :class="!confirmPasswordBool ? 'iconfont oaIcon-eye' : 'iconfont oaIcon-eye-close'" @click="confirmPasswordBool = !confirmPasswordBool"></text>
+        </template>
+      </u-input>
+
+      <u-button
+        type="primary"
+        shape="circle"
+        :customStyle="{
+          display: 'block',
+          width: '100%',
+          height: '45px',
+          lineHeight: '45px',
+          fontSize: '17px',
+        }"
+        @click="handleSubmit()"
+      >
+        注 册
+      </u-button>
+    </view>
+  </view>
+</template>
+
+<script setup>
+/*----------------------------------依赖引入-----------------------------------*/
+import { onLoad, onShow, onHide, onLaunch } from "@dcloudio/uni-app";
+import { ref, onMounted, inject, shallowRef, reactive, toRefs, getCurrentInstance } from "vue";
+/*----------------------------------接口引入-----------------------------------*/
+/*----------------------------------组件引入-----------------------------------*/
+/*----------------------------------store引入-----------------------------------*/
+import { useStores, commonStores } from "@/store/modules/index";
+/*----------------------------------公共方法引入-----------------------------------*/
+/*----------------------------------公共变量-----------------------------------*/
+const { proxy } = getCurrentInstance();
+const useStore = useStores();
+const commonStore = commonStores();
+/*----------------------------------变量声明-----------------------------------*/
+const state = reactive({
+  userName: undefined,
+  nickName: undefined,
+  phone: undefined,
+  verify: undefined,
+  email: undefined,
+  newPassword: undefined,
+  newPasswordBool: true,
+  confirmPassword: undefined,
+  confirmPasswordBool: true,
+});
+
+const { userName, nickName, phone, verify, email, newPassword, newPasswordBool, confirmPassword, confirmPasswordBool } = toRefs(state);
+
+/**
+ * @点击发送验证码
+ */
+function getVerifyCode() {
+  verify.value = undefined;
+  useStore.GetCodeImg({
+    phone: phone.value,
+    success: (res) => {
+      proxy.$modal.msgSuccess("发送成功");
+    },
+  });
+}
+
+/**
+ * @注册
+ * @按钮点击事件
+ */
+function handleSubmit() {
+  useStore.PhoneVerify({
+    data: {
+      phone: phone.value,
+      verify: verify.value,
+    },
+    success: (res) => {
+      useStore.UserAdd({
+        data: {
+          userName: userName.value,
+          nickName: nickName.value,
+          phone: phone.value,
+          verify: verify.value,
+          email: email.value,
+          newPassword: newPassword.value,
+          confirmPassword: confirmPassword.value,
+        },
+        success: (res) => {
+          proxy.$modal.msgSuccess("注册成功");
+
+          setTimeout(() => {
+            proxy.$modal.loading("登录中,请耐心等待...");
+            useStore
+              .Login({
+                username: phone.value,
+                password: newPassword.value,
+                tenantId: useStore.tenantId,
+              })
+              .then(() => {
+                /** 获取用户信息 */
+                proxy.$modal.closeLoading();
+                useStore.GetInfo().then((res) => {
+                  proxy.$tab.reLaunch("/pages/index");
+                });
+              });
+          }, 1000);
+        },
+      });
+    },
+    error: (res) => {
+      return false;
+    },
+  });
+}
+
+/**
+ * @跳转登录
+ */
+function navigateTo() {
+  proxy.$tab.navigateBack(1);
+}
+
+onLoad((options) => {});
+</script>
+
+<style lang="scss" scoped>
+#register-container {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  z-index: 1;
+  width: 100%;
+  margin: auto;
+  padding: 0 30px;
+  padding-top: 20%;
+  //#ifdef MP-WEIXIN
+  padding-top: 30%;
+  //#endif
+  background-color: #ffffff;
+  overflow: auto;
+  .top-area {
+  }
+
+  .content-area {
+    display: flex;
+    margin: 30px 0;
+
+    &-title {
+      margin: auto auto auto 0;
+      color: #000;
+      font-size: 18px;
+    }
+  }
+
+  .bottom-area {
+    :deep() {
+      .u-input {
+        height: 45px;
+        border-radius: 8px;
+        padding: 5px 12px !important;
+        border: 0 !important;
+        background-color: #f5f6fa !important;
+        margin-bottom: 15px;
+      }
+      .u-icon__icon {
+        font-size: 24px !important;
+        line-height: 24px !important;
+        color: gray !important;
+      }
+      .iconfont {
+        color: gray !important;
+      }
+      .input-placeholder {
+        color: #c0c4cc !important;
+      }
+      .uni-input-wrapper {
+        font-size: 16px;
+      }
+      .u-line {
+        display: none !important;
+      }
+    }
+  }
+}
+
+@media (min-width: 1280px) {
+  #register-container {
+    padding-top: 10% !important;
+  }
+}
+</style>

+ 220 - 0
src/pages/serveConfig.vue

@@ -0,0 +1,220 @@
+<template>
+  <view id="serveConfig-container">
+    <view class="top-area">
+      <u-icon name="arrow-left" size="17px" color="#000" :bold="true" @click="navigateTo"></u-icon>
+    </view>
+
+    <view class="content-area">
+      <text class="content-area-title">设置服务器地址</text>
+      <u-icon class="content-area-icons" name="scan" color="#2a98ff" size="22"></u-icon>
+      <text class="content-area-setting" @tap="scanClick"> 扫码添加 </text>
+    </view>
+
+    <view class="bottom-area">
+      <u-input v-model="linkUrl" placeholder="服务器地址(必填)" border="none" clearable> </u-input>
+      <u-input v-model="port" type="number" placeholder="服务器端口(非必填)" border="none" maxlength="5" clearable> </u-input>
+      <u-input v-model="content" placeholder="备注(非必填)" border="none" maxlength="20" clearable> </u-input>
+
+      <u-button
+        type="primary"
+        shape="circle"
+        :customStyle="{
+          display: 'block',
+          width: '100%',
+          height: '45px',
+          lineHeight: '45px',
+          fontSize: '17px',
+        }"
+        @click="handleSubmit()"
+      >
+        保 存
+      </u-button>
+    </view>
+  </view>
+</template>
+
+<script setup>
+/*----------------------------------依赖引入-----------------------------------*/
+import { onLoad, onShow, onHide, onLaunch } from "@dcloudio/uni-app";
+import { ref, onMounted, inject, shallowRef, reactive, toRefs, getCurrentInstance } from "vue";
+/*----------------------------------接口引入-----------------------------------*/
+/*----------------------------------组件引入-----------------------------------*/
+/*----------------------------------store引入-----------------------------------*/
+import { useStores, commonStores } from "@/store/modules/index";
+/*----------------------------------公共方法引入-----------------------------------*/
+import config from "@/config";
+/*----------------------------------公共变量-----------------------------------*/
+const { proxy } = getCurrentInstance();
+const useStore = useStores();
+const commonStore = commonStores();
+/*----------------------------------变量声明-----------------------------------*/
+const state = reactive({
+  linkUrl: "", //链接地址
+  port: "",
+  content: "",
+  index: "",
+});
+const { linkUrl, port, content, index } = toRefs(state);
+
+/**
+ * @扫一扫
+ * @按钮点击事件
+ */
+function scanClick() {
+  uni.scanCode({
+    autoZoom: false,
+    success: async (e) => {
+      uni.showToast({
+        title: "扫码成功",
+        icon: "none",
+      });
+
+      linkUrl.value = e.result.split(":")[0];
+      port.value = e.result.split(":")[1];
+    },
+    fail: (err) => {
+      uni.showToast({
+        title: "扫码失败",
+        icon: "none",
+      });
+      console.log("扫码失败", err);
+    },
+    complete: () => {
+      // uni.showToast({
+      //   title: "扫码结束",
+      //   icon: "none",
+      // });
+      console.log("扫码结束");
+    },
+  });
+}
+
+/**
+ * @保存
+ * @按钮点击事件
+ */
+function handleSubmit() {
+  if (!linkUrl.value) {
+    proxy.$modal.msg("请输入链接地址");
+    return;
+  }
+
+  if (!/^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}(?:\.[a-zA-Z0-9]{2,})+$/.test(linkUrl.value)) {
+    proxy.$modal.msg("请输入正确的链接地址");
+    return;
+  }
+
+  // if (!port.value) {
+  //   proxy.$modal.msg("请输入端口号");
+  //   return;
+  // }
+
+  if (index.value) {
+    let serveList = uni.getStorageSync("serveList");
+    serveList[0].radiolist[index.value].linkUrl = !port.value ? linkUrl.value : linkUrl.value + ":" + port.value;
+    serveList[0].radiolist[index.value].content = content.value;
+    uni.setStorageSync("serveUrl", !port.value ? linkUrl.value : linkUrl.value + ":" + port.value);
+    uni.setStorageSync("serveList", serveList);
+  } else {
+    if (!port.value) {
+      uni.setStorageSync("serveUrl", linkUrl.value);
+      commonStore.setServeList(linkUrl.value, content.value);
+    } else {
+      uni.setStorageSync("serveUrl", linkUrl.value + ":" + port.value);
+      commonStore.setServeList(linkUrl.value + ":" + port.value, content.value);
+    }
+  }
+
+  config.baseUrl = "https://" + uni.getStorageSync("serveUrl") + "/prod-api";
+  navigateTo();
+}
+
+/**
+ * @跳转登录
+ */
+function navigateTo() {
+  proxy.$tab.navigateBack(1);
+}
+
+onLoad((options) => {
+  if ("index" in options) {
+    index.value = options.index;
+    let serveList = uni.getStorageSync("serveList");
+    var serveArray = serveList[0].radiolist[options.index];
+
+    if (serveArray.linkUrl.indexOf(":") != -1) {
+      linkUrl.value = serveArray.linkUrl.split(":")[0];
+      port.value = serveArray.linkUrl.split(":")[1];
+      content.value = serveArray.content;
+    } else {
+      linkUrl.value = serveArray.linkUrl;
+      port.value = "";
+      content.value = serveArray.content;
+    }
+  }
+});
+</script>
+
+<style lang="scss" scoped>
+#serveConfig-container {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  z-index: 1;
+  width: 100%;
+  margin: auto;
+  padding: 0 30px;
+  padding-top: 20%;
+  //#ifdef MP-WEIXIN
+  padding-top: 30%;
+  //#endif
+  background-color: #ffffff;
+
+  .top-area {
+  }
+
+  .content-area {
+    display: flex;
+    margin: 30px 0;
+
+    &-title {
+      margin: auto auto auto 0;
+      color: #000;
+      font-size: 18px;
+    }
+
+    &-icons {
+      margin: auto 5px auto 0;
+    }
+
+    &-setting {
+      color: #2a98ff;
+      margin: auto 0;
+    }
+  }
+
+  .bottom-area {
+    :deep() {
+      .u-input {
+        height: 45px;
+        border-radius: 8px;
+        padding: 5px 12px !important;
+        border: 0 !important;
+        background-color: #f5f6fa !important;
+        margin-bottom: 15px;
+      }
+      .input-placeholder {
+        color: #c0c4cc !important;
+      }
+      .uni-input-wrapper {
+        font-size: 16px;
+      }
+      .u-line {
+        display: none !important;
+      }
+    }
+  }
+}
+</style>

+ 266 - 0
src/pages/serveConfigSelect.vue

@@ -0,0 +1,266 @@
+<template>
+  <view id="serveConfigSelect-container">
+    <view class="top-area">
+      <u-icon name="arrow-left" size="17px" color="#000" :bold="true" @click="navigateTo()"></u-icon>
+    </view>
+
+    <view class="content-area">
+      <text class="content-area-title">选择服务器地址</text>
+      <u-icon class="content-area-icons" name="scan" color="#2a98ff" size="22" @tap="serveClick(1)"></u-icon>
+      <text class="content-area-setting" @click="serveClick(2)"> 添加 </text>
+    </view>
+
+    <view class="bottom-area">
+      <div class="serveList">
+        <u-radio-group v-model="radiovalue" placement="column" @change="handleRadio">
+          <div class="serveList-item" v-for="(item, index) in radiolist" :key="index">
+            <u-radio :customStyle="{ display: 'block', margin: 'auto 0' }" :value="item.id" :name="item.id"></u-radio>
+
+            <div class="serveList-item-center" @click="handleRadio(item.id)">
+              <div class="serveList-item-center-title">{{ item.linkUrl }}</div>
+              <div class="serveList-item-center-content">备注:{{ item.content }}</div>
+            </div>
+
+            <div v-if="item.id != radiovalue" class="serveList-item-icon" @click="deleteRadio(index)">
+              <u-icon name="close" color="#a0a4af" size="14"></u-icon>
+            </div>
+
+            <div v-if="item.id == radiovalue" class="serveList-item-icon" @click="editRadio(index)">
+              <u-icon name="arrow-right" color="#a0a4af" size="14"></u-icon>
+            </div>
+          </div>
+        </u-radio-group>
+      </div>
+
+      <u-button
+        v-if="radiolist.length > 0"
+        type="primary"
+        :customStyle="{
+          display: 'block',
+          width: '100%',
+          height: '45px',
+          lineHeight: '45px',
+          fontSize: '17px',
+        }"
+        @click="handleSubmit()"
+        shape="circle"
+      >
+        保 存</u-button
+      >
+    </view>
+  </view>
+</template>
+
+<script setup>
+/*----------------------------------依赖引入-----------------------------------*/
+import { onLoad, onShow, onHide, onLaunch } from "@dcloudio/uni-app";
+import { ref, onMounted, inject, shallowRef, reactive, toRefs, getCurrentInstance, watchEffect } from "vue";
+/*----------------------------------接口引入-----------------------------------*/
+/*----------------------------------组件引入-----------------------------------*/
+/*----------------------------------store引入-----------------------------------*/
+import { useStores, commonStores } from "@/store/modules/index";
+/*----------------------------------公共方法引入-----------------------------------*/
+import config from "@/config";
+/*----------------------------------公共变量-----------------------------------*/
+const { proxy } = getCurrentInstance();
+const useStore = useStores();
+const commonStore = commonStores();
+/*----------------------------------变量声明-----------------------------------*/
+const state = reactive({
+  radiolist: [],
+  radiovalue: "",
+});
+const { radiolist, radiovalue } = toRefs(state);
+
+/**
+ * @切换单选
+ * @按钮点击事件
+ */
+function handleRadio(id) {
+  radiovalue.value = id;
+  let serveList = uni.getStorageSync("serveList");
+  serveList[0].radiovalue = radiovalue.value;
+  uni.setStorageSync("serveList", serveList);
+}
+
+/**
+ * @删除
+ * @按钮点击事件
+ */
+function deleteRadio(index) {
+  let serveList = uni.getStorageSync("serveList");
+  serveList[0].radiolist.splice(index, 1);
+  uni.setStorageSync("serveList", serveList);
+
+  init();
+
+  proxy.$tab.redirectTo("/pages/serveConfigSelect"); //重载当前页
+}
+
+/**
+ * @编辑
+ * @按钮点击事件
+ */
+function editRadio(index) {
+  proxy.$tab.navigateTo("/pages/serveConfig?index=" + index);
+}
+
+/**
+ * @扫一扫
+ * @按钮点击事件
+ */
+function serveClick(type) {
+  if (type == 1) {
+    uni.scanCode({
+      autoZoom: false,
+      success: async (e) => {
+        uni.showToast({
+          title: "扫码成功",
+          icon: "none",
+        });
+
+        commonStore.setServeList(e.result, "");
+
+        init();
+
+        proxy.$tab.redirectTo("/pages/serveConfigSelect"); //重载当前页
+      },
+      fail: (err) => {
+        uni.showToast({
+          title: "扫码失败",
+          icon: "none",
+        });
+        console.log("扫码失败", err);
+      },
+      complete: () => {
+        // uni.showToast({
+        //   title: "扫码结束",
+        //   icon: "none",
+        // });
+        console.log("扫码结束");
+      },
+    });
+  } else if (type == 2) {
+    proxy.$tab.navigateTo("/pages/serveConfig");
+  }
+}
+
+/**
+ * @保存
+ * @按钮点击事件
+ */
+function handleSubmit() {
+  let serveList = uni.getStorageSync("serveList");
+  if (serveList.length > 0) {
+    serveList[0].radiolist.forEach((el) => {
+      if (el.id == serveList[0].radiovalue) {
+        uni.setStorageSync("serveUrl", el.linkUrl);
+        config.baseUrl = "https://" + uni.getStorageSync("serveUrl") + "/prod-api";
+        navigateTo();
+      }
+    });
+  }
+}
+
+/**
+ * @跳转登录
+ */
+function navigateTo() {
+  proxy.$tab.navigateBack(1);
+}
+
+/**
+ * @初始化
+ */
+function init() {
+  let serveList = uni.getStorageSync("serveList");
+  if (serveList.length > 0) {
+    radiolist.value = serveList[0].radiolist;
+    radiovalue.value = serveList[0].radiovalue;
+  }
+}
+
+onShow(() => {
+  init();
+});
+
+onLoad((options) => {});
+</script>
+
+<style lang="scss" scoped>
+#serveConfigSelect-container {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  z-index: 1;
+  width: 100%;
+  height: 100vh;
+  margin: auto;
+  padding: 0 30px;
+  padding-top: 20%;
+  //#ifdef MP-WEIXIN
+  padding-top: 30%;
+  //#endif
+  background-color: #ffffff;
+
+  .top-area {
+  }
+
+  .content-area {
+    display: flex;
+    margin: 30px 0;
+
+    &-title {
+      margin: auto auto auto 0;
+      color: #000;
+      font-size: 18px;
+    }
+
+    &-icons {
+      margin: auto 5px auto 0;
+    }
+
+    &-setting {
+      color: #2a98ff;
+      margin: auto 0;
+    }
+  }
+
+  .bottom-area {
+    .serveList {
+      max-height: calc(59px * 6);
+      overflow: auto;
+
+      &-item {
+        display: flex;
+        background-color: #f5f6fa !important;
+        margin-bottom: 15px;
+        padding: 10px;
+        border-radius: 8px;
+
+        &-center {
+          margin: auto 0 auto 0;
+          width: 100%;
+
+          &-title {
+            margin-bottom: 5px;
+            font-weight: 600;
+          }
+
+          &-content {
+            color: #a0a4af;
+            font-size: 12px;
+          }
+        }
+
+        &-icon {
+          margin: auto 0 auto 0;
+          height: 100%;
+        }
+      }
+    }
+  }
+}
+</style>

+ 60 - 0
src/permission.js

@@ -0,0 +1,60 @@
+import { getToken } from "@/utils/auth";
+import setting from "@/plugins/setting.plugins";
+
+// 登录页面
+const loginPage = "/pages/login";
+
+// 页面白名单
+const whiteList = [
+  "/pages/login",//登录
+  "/pages/register",//注册
+  "/pages/serveConfig",//服务器配置
+  "/pages/serveConfigSelect",//服务器配置
+  "/pages/common/textview/index",//浏览文本
+  "/pages/common/webview/index",
+  "/pages/business/mhxf/unitInfoCollection/index",//单位信息采集
+  "/pages/common/invoicing/index",//开票管理
+  "/pages/common/success/index",//成功
+  "/pages/common/phoneVerify/index",//手机号验证
+  "/pages/business/fireIot/repairReport/index",//报修申请
+  "/pages/business/fireIot/repairReport/record",//报修历史
+  "/pages/common/evaluate/record",//服务评价
+  "/pages/common/NFC/index",//NFC读取
+  "/pages/common/appMessage/details",//消息详情
+  "/pages/common/face/index",//人脸识别
+];
+
+// 检查地址白名单
+function checkWhite(url) {
+  const path = url.split("?")[0];
+  return whiteList.indexOf(path) !== -1;
+}
+
+// 页面跳转验证拦截器
+let list = ["navigateTo", "redirectTo", "reLaunch", "switchTab"];
+list.forEach((item) => {
+  uni.addInterceptor(item, {
+    invoke(to) {
+      // #ifdef APP-PLUS
+      setting.formatSize(); //获取缓存大小
+      // #endif
+
+      if (getToken()) {
+        if (to.url === loginPage) {
+          uni.reLaunch({ url: "/pages/index" });
+        }
+        return true;
+      } else {
+
+        if (checkWhite(to.url)) {
+          return true;
+        }
+        uni.reLaunch({ url: loginPage });
+        return false;
+      }
+    },
+    fail(err) {
+      console.log(err);
+    },
+  });
+});

+ 60 - 0
src/plugins/auth.plugins.js

@@ -0,0 +1,60 @@
+import store from '@/store'
+
+function authPermission(permission) {
+  const all_permission = "*:*:*"
+  const permissions = store.getters && store.getters.permissions
+  if (permission && permission.length > 0) {
+    return permissions.some(v => {
+      return all_permission === v || v === permission
+    })
+  } else {
+    return false
+  }
+}
+
+function authRole(role) {
+  const super_admin = "admin"
+  const roles = store.getters && store.getters.roles
+  if (role && role.length > 0) {
+    return roles.some(v => {
+      return super_admin === v || v === role
+    })
+  } else {
+    return false
+  }
+}
+
+export default {
+  // 验证用户是否具备某权限
+  hasPermi(permission) {
+    return authPermission(permission)
+  },
+  // 验证用户是否含有指定权限,只需包含其中一个
+  hasPermiOr(permissions) {
+    return permissions.some(item => {
+      return authPermission(item)
+    })
+  },
+  // 验证用户是否含有指定权限,必须全部拥有
+  hasPermiAnd(permissions) {
+    return permissions.every(item => {
+      return authPermission(item)
+    })
+  },
+  // 验证用户是否具备某角色
+  hasRole(role) {
+    return authRole(role)
+  },
+  // 验证用户是否含有指定角色,只需包含其中一个
+  hasRoleOr(roles) {
+    return roles.some(item => {
+      return authRole(item)
+    })
+  },
+  // 验证用户是否含有指定角色,必须全部拥有
+  hasRoleAnd(roles) {
+    return roles.every(item => {
+      return authRole(item)
+    })
+  }
+}

+ 306 - 0
src/plugins/common.plugins.js

@@ -0,0 +1,306 @@
+import modal from "./modal.plugins";
+
+export default {
+  /**
+   * 参数处理
+   * @param params 参数
+   */
+  tansParams(params) {
+    let result = "";
+    for (const propName of Object.keys(params)) {
+      const value = params[propName];
+      var part = encodeURIComponent(propName) + "=";
+      if (value !== null && value !== "" && typeof value !== "undefined") {
+        if (typeof value === "object") {
+          for (const key of Object.keys(value)) {
+            if (value[key] !== null && value[key] !== "" && typeof value[key] !== "undefined") {
+              let params = propName + "[" + key + "]";
+              var subPart = encodeURIComponent(params) + "=";
+              result += subPart + encodeURIComponent(value[key]) + "&";
+            }
+          }
+        } else {
+          result += part + encodeURIComponent(value) + "&";
+        }
+      }
+    }
+    return result;
+  },
+  /**
+   * 数据映射
+   * @param reKey 需要返回的key
+   * @param isKey 需要比对的key
+   * @param value 对比值
+   * @param data 数据集
+   */
+  mapping(reKey, isKey, value, data) {
+    if (typeof value == "string" && value.indexOf(",") > -1) {
+      //value为字符串的id集合
+      let arr = value.split(",");
+      let returnValue = "";
+
+      arr.forEach((e, index) => {
+        data.forEach((f) => {
+          if (e == f[isKey]) {
+
+            returnValue = returnValue ? `${returnValue},${f[reKey]}` : f[reKey];
+          }
+        })
+      })
+
+      return returnValue;
+    } else {
+      if (!data) return;
+      for (let i = 0; i < data.length; i++) {
+        if (value == data[i][isKey]) {
+          return data[i][reKey];
+        }
+      }
+    }
+  },
+  /**
+   * @一键拨号
+   */
+  makePhoneCall(phone) {
+    uni.makePhoneCall({
+      phoneNumber: phone,
+      success: function () {
+        console.log('success');
+      },
+      fail: function () {
+      }
+    });
+  },
+  /**
+   * 树结构过滤
+   * @param {*} treeData 
+   * @param {*} ids 
+   * @returns 
+   */
+  findTreeNodes(treeData, ids) {
+    const result = [];
+    const findNodes_ = (nodes, idArray) => {
+      nodes.forEach(node => {
+        if (idArray.includes(node.id)) {
+          result.push(node);
+        }
+        if (node.children && node.children.length > 0) {
+          findNodes_(node.children, idArray);
+        }
+      });
+    };
+
+    findNodes_(treeData, ids);
+    return result;
+  },
+  /**
+   * @复制粘贴板
+   * @param {传入值} content 
+   * @returns 
+   */
+  uniCopy({ content, success, error }) {
+    if (!content) return error('复制的内容不能为空 !')
+    content = typeof content === 'string' ? content : content.toString() // 复制内容,必须字符串,数字需要转换为字符串
+    /**
+     * 小程序端 和 app端的复制逻辑
+     */
+    //#ifdef APP-PLUS || MP-WEIXIN
+    uni.setClipboardData({
+      data: content,
+      success: function () {
+        success("复制成功~")
+        console.log('success');
+      },
+      fail: function () {
+        success("复制失败~")
+      }
+    });
+    //#endif
+
+    /**
+     * H5端的复制逻辑
+     */
+    // #ifdef H5
+    if (!document.queryCommandSupported('copy')) { //为了兼容有些浏览器 queryCommandSupported 的判断
+      // 不支持
+      error('浏览器不支持')
+    }
+    let textarea = document.createElement("textarea")
+    textarea.value = content
+    textarea.readOnly = "readOnly"
+    document.body.appendChild(textarea)
+    textarea.select() // 选择对象
+    textarea.setSelectionRange(0, content.length) //核心
+    let result = document.execCommand("copy") // 执行浏览器复制命令
+    if (result) {
+      success("复制成功~")
+    } else {
+      error("复制失败,请检查h5中调用该方法的方式,是不是用户点击的方式调用的,如果不是请改为用户点击的方式触发该方法,因为h5中安全性,不能js直接调用!")
+    }
+    textarea.remove()
+    // #endif
+  },
+  /**
+   * @根据时间分类数据
+   * @param {数据集} data 
+   * @param {需要处理的时间key} timeKey 
+   * @returns 
+   */
+  groupedItems(data, timeKey) {
+    if (data <= 0) {
+      return false
+    }
+
+    const grouped = {};
+    data.forEach((item) => {
+      const date = item[timeKey].split("T")[0];
+      grouped[date] = grouped[date] || [];
+      grouped[date].push(item);
+    });
+    return grouped;
+  },
+  /**
+   * @公共获取URL中的参数
+   */
+  getUrlList() {
+    // 截取url中的list
+    var url = window.location.href;
+    var theRequest = new Object();
+    if (url.indexOf("?") != -1) {
+      var str = url.split("?")[1];
+      var strs = str.split("&");
+      for (var i = 0; i < strs.length; i++) {
+        theRequest[strs[i].split("=")[0]] = strs[i].split("=")[1];
+      }
+    }
+    return theRequest;
+  },
+  /**
+   * @数组对象排序
+   * @return
+   * @param {数据} data
+   * @param {0 从小到大 1 从大到小} sort
+   */
+  sortEvent(data, sort) {
+    let arr = [];
+    // 将需要排序的 key, 进行排列
+    let sortKeys = Object.keys(JSON.parse(JSON.stringify(data))).sort((a, b) => {
+      return sort == 0 ? JSON.parse(JSON.stringify(data))[a].sort - JSON.parse(JSON.stringify(data))[b].sort : JSON.parse(JSON.stringify(data))[b].sort - JSON.parse(JSON.stringify(data))[a].sort;
+    });
+    // 循环排列好的 key, 重新组成一个新的数组
+    for (var sortIndex in sortKeys) {
+      arr.push(JSON.parse(JSON.stringify(data))[sortKeys[sortIndex]]);
+    }
+
+    return arr;
+  },
+  /**
+   * @数组对象去重
+   * @methods data 需要去重的数据
+   * @methods objectName 需要去重的对象名称
+   */
+  uniq(data, objectName) {
+    if (!objectName) {
+      var newArr = [...new Set(data)]
+
+      return newArr;
+    } else {
+      let obj = {};
+
+      let peon = data.reduce((cur, next) => {
+        obj[next[objectName]] ? "" : obj[next[objectName]] = true && cur.push(next);
+        return cur;
+      }, []) //设置cur默认类型为数组,并且初始值为空的数组
+
+      return peon;
+    }
+  },
+  /**
+   * @判断当前是否有网络
+   */
+  isNetwork() {
+    let status = true
+    // 获取网络状态
+    uni.getNetworkType({
+      success: function (res) {
+        if (res.networkType === "none") {
+          modal.msg("网络异常,请稍后重试!");
+          status = false
+        } else {
+          status = true
+        }
+      },
+    });
+
+    return status
+  },
+  /**
+   * @判断用户拒绝权限是否超过48小时
+   */
+  isExpirationTime() {
+    let sotrTime = uni.getStorageSync("expirationTime");
+    if (sotrTime) {
+      if (sotrTime + 3600 * 24 * 2 <= Date.parse(new Date()) / 1000) {
+        return true
+      } else {
+        return false
+      }
+    } else {
+      return true
+    }
+  },
+  /**
+   * @判断是否为微信公众号
+   */
+  isWechatMp() {
+    var ua = navigator?.userAgent.toLowerCase();
+    if (ua?.match(/MicroMessenger/i) == 'micromessenger') {
+      return true;
+    } else {
+      // 不在微信内置浏览器中
+      return false;
+    }
+  },
+  /**
+   * @是否显示容器
+   * @判断是否为微信公众号
+   */
+  isVisible() {
+    let visible = true;
+    //#ifdef H5
+    visible = !this.isWechatMp();
+    //#endif
+
+    //#ifdef APP-PLUS || MP-WEIXIN
+    visible = true;
+    //#endif
+    return visible;
+  },
+  /**
+   * 图片点击放大
+   * @param {*类型} type (1:string:图片地址  2:array(数组对象))
+   * @param {*数据} data
+   */
+  imgEnlarge(type, data) {
+    let param = {}
+    if (type == 1) {
+      param = {
+        urls: [data],
+        current: data
+      }
+    }
+    if (type == 2) {
+      let arr = []
+      for (let i = 0; i < data.length; i++) {
+        arr.push(data[i].url)
+      }
+      param = {
+        urls: arr,
+        current: arr[0]
+      }
+    }
+    if (data && data.length > 0) {
+      uni.previewImage(param)
+    }
+  },
+};

+ 292 - 0
src/plugins/constData.plugins.js

@@ -0,0 +1,292 @@
+// 首页九宫格
+let homeRouter = [
+	{
+		imgUrl: "/static/icons/index/APP-xunjian.svg",
+		badge: 0,
+		name: "巡检",
+		redirectUrl: "/pages/business/zhaf/xunJian/xunJian",
+	},
+	// {
+	//   imgUrl: "/static/images/square/square-xf.png",
+	//   badge: 0,
+	//   name: "未开发",
+	//   redirectUrl: "",
+	// },
+];
+
+// 首页报警数据
+let staticData = {
+	msg: "\u64cd\u4f5c\u6210\u529f",
+	flag: true,
+	companyCode: "1,2,3,4,5,6,7,8,12,13,14,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39",
+	data: [
+		{
+			statisticalPeriod: "2021-03-16~2021-04-16",
+			smartElectricityCount: "178",
+			videoMonitoringCount: "12456",
+			alarmCount: 12627,
+			eventCount: 2,
+			hiddenDangerCount: 4,
+			offlineCount: 20,
+			faultCount: 30,
+			earlyWarningCount: 100,
+			otherCount: 99,
+			normalCount: 66,
+			integratedAlarmCount: 12627,
+			unprocessedCount: 0,
+		},
+	],
+};
+
+// 巡检模块
+let xunJianList = [
+	{
+		id: 1,
+		title: "巡检任务",
+		num: "0",
+		imgUrl: "/static/images/xunjian/xunJian-icon1.png",
+		redirectUrl: "/pages/business/zhaf/xunJian/plan/index",
+	},
+	{
+		id: 2,
+		title: "巡检记录",
+		num: "0",
+		imgUrl: "/static/images/xunjian/xunJian-icon2.png",
+		redirectUrl: "/pages/business/zhaf/xunJian/plan/index",
+	},
+	{
+		id: 3,
+		title: "巡检采集",
+		num: "0",
+		imgUrl: "/static/images/xunjian/xunJian-icon3.png",
+		redirectUrl: "/pages/business/zhaf/xunJian/collect/index",
+	},
+];
+
+// 首页底部导航栏
+let homeTabbar = [
+	{
+		pagePath: "/pages/index",
+		iconClass: "oaIcon-tab-home",
+		iconPath: "/static/images/tabBar/tab-home.png",
+		selectedIconPath: "/static/images/tabBar/tab-home-blue.png",
+		text: "工作台",
+		dot: false,
+	},
+	// {
+	//   "pagePath": "pages/analyse/analyse",
+	//   "iconPath": "/static/images/tabBar/analyse.png",
+	//   "selectedIconPath": "/static/images/tabBar/analyse-selected.png",
+	//   "text": "分析"
+	// },
+	// {
+	// 	pagePath: "/pages/info",
+	// 	iconClass: "oaIcon-tab-info",
+	// 	iconPath: "/static/images/tabBar/tab-info.png",
+	// 	selectedIconPath: "/static/images/tabBar/tab-info-blue.png",
+	// 	text: "消息",
+	// 	dot: false,
+	// },
+	// {
+	// 	pagePath: "/pages/mine",
+	// 	iconClass: "oaIcon-tab-mine",
+	// 	iconPath: "/static/images/tabBar/tab-my.png",
+	// 	selectedIconPath: "/static/images/tabBar/tab-my-blue.png",
+	// 	text: "我的",
+	// 	dot: false,
+	// },
+]
+
+// 工作报告底部导航栏
+let projectTabbar = [
+	{
+		pagePath: "/pages/business/common/projectMange/record/index",
+		iconClass: "oaIcon-tab-reportRecord",
+		iconPath: "/static/images/tabBar/tab-home.png",
+		selectedIconPath: "/static/images/tabBar/tab-home-blue.png",
+		text: "报告记录",
+		dot: false,
+	},
+	{
+		pagePath: "/pages/business/common/projectMange/write/index",
+		iconClass: "oaIcon-tab-reportInsert",
+		iconPath: "/static/images/tabBar/tab-info.png",
+		selectedIconPath: "/static/images/tabBar/tab-info-blue.png",
+		text: "报告填写",
+		dot: false,
+	},
+	{
+		pagePath: "/pages/business/common/projectMange/list/index",
+		iconClass: "oaIcon-tab-projectsList",
+		iconPath: "/static/images/tabBar/tab-my.png",
+		selectedIconPath: "/static/images/tabBar/tab-my-blue.png",
+		text: "项目列表",
+		dot: false,
+	},
+	// {
+	// 	pagePath: "/pages/mine",
+	// 	iconPath: "/static/images/tabBar/tab-my.png",
+	// 	selectedIconPath: "/static/images/tabBar/tab-my-blue.png",
+	// 	text: "统计导出",
+	// 	dot: false,
+	// },
+	// {
+	// 	pagePath: "/pages/info",
+	// 	iconPath: "/static/images/tabBar/tab-info.png",
+	// 	selectedIconPath: "/static/images/tabBar/tab-info-blue.png",
+	// 	text: "模板管理",
+	// 	dot: false,
+	// },
+]
+
+
+export default {
+	// 主题列表
+	themeList: [
+		{
+			title: '官方',
+			name: 'rf',
+			color: '#149eff',
+			tabList: [
+				'/static/images/tabBar/tab-home-blue.png',
+				'/static/images/tabBar/tab-info-blue.png',
+				'/static/images/tabBar/tab-my-blue.png'
+			]
+		},
+		{
+			title: '海蓝',
+			name: 'blue',
+			color: '#0081ff',
+			tabList: [
+				'/static/images/tabBar/tab-home-blue.png',
+				'/static/images/tabBar/tab-info-blue.png',
+				'/static/images/tabBar/tab-my-blue.png'
+			]
+		},
+		{
+			title: '嫣红',
+			name: 'red',
+			color: '#e54d42',
+			tabList: [
+				'/static/images/tabBar/tab-home-red.png',
+				'/static/images/tabBar/tab-info-red.png',
+				'/static/images/tabBar/tab-my-red.png'
+			]
+		},
+		{
+			title: '桔橙',
+			name: 'orange',
+			color: '#f37b1d',
+			tabList: [
+				'/static/images/tabBar/tab-home-orange.png',
+				'/static/images/tabBar/tab-info-orange.png',
+				'/static/images/tabBar/tab-my-orange.png'
+			]
+		},
+		{
+			title: '明黄',
+			name: 'yellow',
+			color: '#fbbd08',
+			tabList: [
+				'/static/images/tabBar/tab-home-yellow.png',
+				'/static/images/tabBar/tab-info-yellow.png',
+				'/static/images/tabBar/tab-my-yellow.png'
+			]
+		},
+		{
+			title: '橄榄',
+			name: 'olive',
+			color: '#8dc63f',
+			tabList: [
+				'/static/images/tabBar/tab-home-olive.png',
+				'/static/images/tabBar/tab-info-olive.png',
+				'/static/images/tabBar/tab-my-olive.png'
+			]
+		},
+		{
+			title: '森绿',
+			name: 'green',
+			color: '#39b54a',
+			tabList: [
+				'/static/images/tabBar/tab-home-green.png',
+				'/static/images/tabBar/tab-info-green.png',
+				'/static/images/tabBar/tab-my-green.png'
+			]
+		},
+		{
+			title: '天青',
+			name: 'cyan',
+			color: '#1cbbb4',
+			tabList: [
+				'/static/images/tabBar/tab-home-cyan.png',
+				'/static/images/tabBar/tab-info-cyan.png',
+				'/static/images/tabBar/tab-my-cyan.png'
+			]
+		},
+		{
+			title: '姹紫',
+			name: 'purple',
+			color: '#6739b6',
+			tabList: [
+				'/static/images/tabBar/tab-home-purple.png',
+				'/static/images/tabBar/tab-info-purple.png',
+				'/static/images/tabBar/tab-my-purple.png'
+			]
+		},
+		{
+			title: '木槿',
+			name: 'mauve',
+			color: '#9c26b0',
+			tabList: [
+				'/static/images/tabBar/tab-home-mauve.png',
+				'/static/images/tabBar/tab-info-mauve.png',
+				'/static/images/tabBar/tab-my-mauve.png'
+			]
+		},
+		{
+			title: '桃粉',
+			name: 'pink',
+			color: '#e03997',
+			tabList: [
+				'/static/images/tabBar/tab-home-pink.png',
+				'/static/images/tabBar/tab-info-pink.png',
+				'/static/images/tabBar/tab-my-pink.png'
+			]
+		},
+		{
+			title: '棕褐',
+			name: 'brown',
+			color: '#a5673f',
+			tabList: [
+				'/static/images/tabBar/tab-home-brown.png',
+				'/static/images/tabBar/tab-info-brown.png',
+				'/static/images/tabBar/tab-my-brown.png'
+			]
+		},
+		{
+			title: '玄灰',
+			name: 'grey',
+			color: '#8799a3',
+			tabList: [
+				'/static/images/tabBar/tab-home-grey.png',
+				'/static/images/tabBar/tab-info-grey.png',
+				'/static/images/tabBar/tab-my-grey.png'
+			]
+		},
+		{
+			title: '墨黑',
+			name: 'black',
+			color: '#333333',
+			tabList: [
+				'/static/images/tabBar/tab-home-black.png',
+				'/static/images/tabBar/tab-info-black.png',
+				'/static/images/tabBar/tab-my-black.png'
+			]
+		}
+	],
+	staticData: staticData,
+	homeRouter: homeRouter,
+	xunJianList: xunJianList,
+	homeTabbar: homeTabbar,
+	projectTabbar: projectTabbar
+};

+ 68 - 0
src/plugins/index.js

@@ -0,0 +1,68 @@
+import tab from "./tab.plugins";
+import auth from "./auth.plugins";
+import modal from "./modal.plugins";
+import common from "./common.plugins";
+import setting from "./setting.plugins";
+import time from "./time.plugins.js";
+import constData from "./constData.plugins.js";
+import nfc from "./nfc.plugins.js";
+import keyListen from "./keyListen.plugins.js";
+
+import config from "@/config"; // config
+import { useDict } from '@/utils/dict'
+import { settingStores } from "@/store/modules/index";
+
+import dayjs from 'dayjs'
+import isBetween from 'dayjs/plugin/isBetween';
+import isSameOrAfter from 'dayjs/plugin/isSameOrAfter';
+import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
+dayjs.extend(isBetween);
+dayjs.extend(isSameOrAfter)
+dayjs.extend(isSameOrBefore)
+
+export default {
+  install(app) {
+    // 公共请求路径
+    app.provide("$BASE_URL", config.baseUrl);
+    app.config.globalProperties.$BASE_URL = config.baseUrl;
+    // 公共website路径
+    app.provide("$websiteUrl", config.websiteUrl);
+    app.config.globalProperties.$websiteUrl = config.websiteUrl;
+    // 页签操作
+    app.provide("$tab", tab);
+    app.config.globalProperties.$tab = tab;
+    // 认证对象
+    app.provide("$auth", auth);
+    app.config.globalProperties.$auth = auth;
+    // 模态框对象
+    app.provide("$modal", modal);
+    app.config.globalProperties.$modal = modal;
+    // 数据处理
+    app.provide("$common", common);
+    app.config.globalProperties.$common = common;
+    // 公共设置方法
+    app.provide("$setting", setting);
+    app.config.globalProperties.$setting = setting;
+    // 公共时间处理方法
+    app.provide("$time", time);
+    app.config.globalProperties.$time = time;
+    // 公共默认数据存储
+    app.provide("$constData", constData);
+    app.config.globalProperties.$constData = constData;
+    // 公共NFC
+    app.provide("$nfc", nfc);
+    app.config.globalProperties.$nfc = nfc;
+    // 公共设置stroe
+    app.provide("$settingStore", settingStores());
+    app.config.globalProperties.$settingStore = settingStores();
+    // 公共时间处理方法dayjs
+    app.provide("$dayjs", dayjs);
+    app.config.globalProperties.$dayjs = dayjs;
+    // 公共字典模块
+    app.config.globalProperties.useDict = useDict
+    // 公共物理按钮监听
+    app.provide("$keyListen", keyListen);
+    app.config.globalProperties.$keyListen = keyListen;
+
+  },
+};

+ 134 - 0
src/plugins/keyListen.plugins.js

@@ -0,0 +1,134 @@
+import { xunJianStores } from "@/store/modules/index";
+
+const SYSTEM_REASON = "reason";
+//Home键
+const SYSTEM_HOME_KEY = "homekey";
+//最近使用的应用键
+const SYSTEM_RECENT_APPS = "recentapps";
+
+let receiver, Intent = false;
+export default {
+    startListen: function (needStopSystem = false) {//开始监听,初始化
+        //参数needStopSystem默认不阻止系统响应,如需阻止调用startListen(true)
+        /*特别提醒,全面屏手势Home和recent部分机型是监听不到的,自行测试,如遇卡死电脑控制台直接重新运行项目即可解决!*/
+        let that = this;
+        let main = plus.android.runtimeMainActivity();
+        that.openListen();
+        if (needStopSystem) {
+            plus.key.addEventListener("backbutton", function (e) {
+                // main.stopLockTask()//按返回键恢复
+                // main.startLockTask()//阻止系统home建和近期任务键
+                // main.unregisterReceiver(receiver); //同时停止接收home和recent点击
+                const pages = getCurrentPages(); // 获取当前页面栈
+                const currentPage = pages[pages.length - 1]; // 最后一个元素即为当前页面
+                xunJianStores().modal.show = currentPage.route === 'pages/login' ? true : false
+                console.log('监听返回')
+                e.preventDefault();
+            });
+        } else {
+        }
+
+    },
+    openListen: function () {//注册监听
+        let that = this;
+        try {
+            let main = plus.android.runtimeMainActivity();
+            Intent = plus.android.importClass('android.content.Intent');
+            let IntentFilter = plus.android.importClass('android.content.IntentFilter');
+            var filter = new IntentFilter();
+            filter.addAction(Intent.ACTION_SCREEN_ON);
+            filter.addAction(Intent.ACTION_SCREEN_OFF);
+            filter.addAction(Intent.ACTION_USER_PRESENT);
+            filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+            filter.addAction('android.intent.action.MEDIA_BUTTON');
+            receiver = plus.android.implements('io.dcloud.feature.internal.reflect.BroadcastReceiver', {
+                onReceive: function (context, intent) { //实现onReceiver回调函数  
+                    let act = intent.getAction();
+                    if (act == Intent.ACTION_SCREEN_ON) {
+                        console.log('开屏')
+                    } else if (act == Intent.ACTION_SCREEN_OFF) {
+                        console.log('锁屏')
+                    } else if (act == Intent.ACTION_USER_PRESENT) {
+                        console.log('解锁')
+                    } else if (act == Intent.ACTION_CLOSE_SYSTEM_DIALOGS) {
+                        let systemReason = intent.getStringExtra(SYSTEM_REASON);
+                        console.log("关闭原因", systemReason);
+                        if (systemReason != null) {
+                            if (systemReason == SYSTEM_HOME_KEY) {
+                                // System.out.println("按下HOME键");
+                                console.log('按下HOME键')
+                                that.launchApp();//启动APP
+
+                            } else if (systemReason == SYSTEM_RECENT_APPS) {
+                                // System.out.println("按下多任务键");
+                                console.log('按下多任务键')
+                                that.launchApp();//启动APP
+                            }
+                        }
+                    }
+                    // main.unregisterReceiver(receiver);
+                    /*在这里取消会出现第二次监听无效,可根据不同业务要求
+                    在不同时刻停止接收两个按键的广播,我的处理是在返回的时候停*/
+                    // context.unregisterReceiver(receiver);
+                }
+            });
+            main.registerReceiver(receiver, filter); //注册监听  
+        } catch (e) {
+            console.error(e);
+            that.toast('初始化错误');
+        }
+    },
+    // 全屏函数
+    fullScreen() {
+        // Android全屏
+        if (uni.getSystemInfoSync().platform === "android") {
+            plus.android.invoke("setFullScreen", true);
+        }
+
+        // iOS全屏
+        if (uni.getSystemInfoSync().platform === "ios") {
+            // iOS无法通过API直接全屏,可以尝试隐藏所有导航栏
+            plus.navigator.hideSystemBar();
+        }
+    },
+    // 进入固定屏幕模式
+    stopHomeEmit() {
+        let main = plus.android.runtimeMainActivity();
+        main.stopLockTask()//按返回键恢复
+        main.startLockTask()//阻止系统home建和近期任务键
+    },
+    // 启动APP
+    launchApp() {
+        var isApp = plus.runtime.isApplicationExist({
+            //查看安卓系统手机有没有下载这款app
+            pname: 'android.dcloud.uskyMobile' //本地浏览器的包名
+        })
+
+        if (isApp) {
+            //安装了app则运行
+            plus.runtime.launchApplication(
+                {
+                    pname: "android.dcloud.uskyMobile",
+                    newTask: false
+                },
+                (e) => {
+                    console.log("e", e);
+                }
+            );
+        }
+        plus.runtime.launcher('shortcut');
+        plus.runtime.restart();
+    },
+    // 退出APP
+    quitApp() {
+        plus.runtime.quit();
+    },
+    // 提示
+    toast(content) {
+        uni.showToast({
+            title: content,
+            icon: 'none'
+
+        })
+    }
+}

+ 76 - 0
src/plugins/modal.plugins.js

@@ -0,0 +1,76 @@
+export default {
+  // 消息提示
+  msg(content) {
+    uni.showToast({
+      title: content,
+      icon: "none",
+    });
+  },
+  // 错误消息
+  msgError(content) {
+    uni.showToast({
+      title: content,
+      icon: "error",
+    });
+  },
+  // 成功消息
+  msgSuccess(content) {
+    uni.showToast({
+      title: content,
+      icon: "success",
+    });
+  },
+  // 隐藏消息
+  hideMsg(content) {
+    uni.hideToast();
+  },
+  // 弹出提示
+  alert(title, content) {
+    uni.showModal({
+      title: title,
+      content: content,
+      showCancel: false,
+      mask: true,
+    });
+  },
+  // 确认窗体
+  confirm(content) {
+    return new Promise((resolve, reject) => {
+      uni.showModal({
+        title: "系统提示",
+        content: content,
+        cancelText: "取消",
+        confirmText: "确定",
+        success: function (res) {
+          if (res.confirm) {
+            resolve(res.confirm);
+          }
+        },
+      });
+    });
+  },
+  // 提示信息
+  showToast(option) {
+    if (typeof option === "object") {
+      uni.showToast(option);
+    } else {
+      uni.showToast({
+        title: option,
+        icon: "none",
+        duration: 2500,
+      });
+    }
+  },
+  // 打开遮罩层
+  loading(content) {
+    uni.showLoading({
+      title: content,
+      icon: "none",
+      mask: true,
+    });
+  },
+  // 关闭遮罩层
+  closeLoading() {
+    uni.hideLoading();
+  },
+};

+ 299 - 0
src/plugins/nfc.plugins.js

@@ -0,0 +1,299 @@
+import tab from "./tab.plugins";
+import { settingStores } from "@/store/modules/index";
+
+var NfcAdapter;
+var NdefRecord;
+var NdefMessage;
+var waiting;
+var readyWriteData = false; //开启写
+var readyRead = false; //开启读
+var whetherNFC = false; //是否有NFC
+var techListsArray = [
+    ["android.nfc.tech.IsoDep"],
+    ["android.nfc.tech.NfcA"],
+    ["android.nfc.tech.NfcB"],
+    ["android.nfc.tech.NfcF"],
+    ["android.nfc.tech.Nfcf"],
+    ["android.nfc.tech.NfcV"],
+    ["android.nfc.tech.NdefFormatable"],
+    ["android.nfc.tech.MifareClassic"],
+    ["android.nfc.tech.MifareUltralight"],
+];
+
+export default {
+    initNFC() {
+        if (uni.getSystemInfoSync().platform == "android") {
+            listenNFCStatus();
+        }
+
+        if (uni.getSystemInfoSync().platform == "ios") {
+            uni.showToast({
+                title: "设备不支持NFC!",
+                icon: "none",
+            });
+            return;
+        }
+    },
+    readNFC(callback) {
+        if (uni.getSystemInfoSync().platform == "android") {
+            readData(callback);
+        }
+    },
+    closeNFC() {
+        if (uni.getSystemInfoSync().platform == "android") {
+            closeReadAndWrite();
+        }
+    }
+}
+
+function listenNFCStatus() {
+    try {
+        var main = plus.android.runtimeMainActivity();
+        var Intent = plus.android.importClass("android.content.Intent");
+        var Activity = plus.android.importClass("android.app.Activity");
+        var PendingIntent = plus.android.importClass("android.app.PendingIntent");
+        var IntentFilter = plus.android.importClass("android.content.IntentFilter");
+        NfcAdapter = plus.android.importClass("android.nfc.NfcAdapter");
+        var nfcAdapter = NfcAdapter.getDefaultAdapter(main);
+
+        if (nfcAdapter == null) {
+            uni.showToast({
+                title: "设备不支持NFC!",
+                icon: "none",
+            });
+            return;
+        }
+
+        if (!nfcAdapter.isEnabled()) {
+            uni.showToast({
+                title: "请在系统设置中先启用NFC功能!",
+                icon: "none",
+            });
+            return;
+        }
+
+        uni.navigateTo({
+            url: "/pages/common/nfc/index",
+        });
+
+        var intent = new Intent(main, main.getClass());
+        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
+        var pendingIntent = PendingIntent.getActivity(main, 0, intent, 0);
+        var ndef = new IntentFilter("android.nfc.action.TECH_DISCOVERED");
+        ndef.addDataType("*/*");
+        var intentFiltersArray = [ndef];
+
+        plus.globalEvent.addEventListener(
+            "newintent",
+            function () {
+                plus.device.vibrate(500);//调用手机震动
+                setTimeout(handleNFCData, 1000);// 轮询调用 NFC
+            },
+            false
+        );
+        plus.globalEvent.addEventListener(
+            "pause",
+            function (e) {
+                if (nfcAdapter) {
+                    //关闭前台调度系统
+                    //恢复默认状态
+                    nfcAdapter.disableForegroundDispatch(main);
+                }
+            },
+            false
+        );
+        plus.globalEvent.addEventListener(
+            "resume",
+            function (e) {
+                if (nfcAdapter) {
+                    //开启前台调度系统
+                    // 优于所有其他NFC
+                    nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);
+                }
+            },
+            false
+        );
+        nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);
+    } catch (e) {
+        console.error(e);
+    }
+}
+
+function handleNFCData() {
+    NdefRecord = plus.android.importClass("android.nfc.NdefRecord");
+    NdefMessage = plus.android.importClass("android.nfc.NdefMessage");
+    var main = plus.android.runtimeMainActivity();
+    var intent = main.getIntent();
+    if ("android.nfc.action.TECH_DISCOVERED" == intent.getAction()) {
+        if (readyWriteData) {
+            //__write(intent);
+            readyWriteData = false;
+        } else if (readyRead) {
+            __read(intent);
+            readyRead = false;
+        }
+    }
+}
+
+function showToast(msg) {
+    plus.nativeUI.toast(msg);
+}
+
+/**
+ * @NFC写入
+ * @param {*} intent
+ * @returns
+ */
+function __write(intent) {
+    try {
+        waiting.setTitle("请勿移开标签\n正在写入...");
+        var text = document.getElementById("text").value;
+        console.log("text=" + text);
+
+        var textBytes = plus.android.invoke(text, "getBytes");
+        var textRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, plus.android.invoke("text/plain", "getBytes"), plus.android.invoke("", "getBytes"), textBytes);
+        var message = new NdefMessage([textRecord]);
+        var Ndef = plus.android.importClass("android.nfc.tech.Ndef");
+        var NdefFormatable = plus.android.importClass("android.nfc.tech.NdefFormatable");
+        var tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
+        var ndef = Ndef.get(tag);
+        if (ndef != null) {
+            var size = message.toByteArray().length;
+            console.log("size=" + size);
+            ndef.connect();
+            if (!ndef.isWritable()) {
+                showToast("tag不允许写入");
+                waiting.close();
+                return;
+            }
+            if (ndef.getMaxSize() < size) {
+                showToast("文件大小超出容量");
+                waiting.close();
+                return;
+            }
+
+            ndef.writeNdefMessage(message);
+            waiting.close();
+            showToast("写入数据成功.");
+            return;
+        } else {
+            var format = NdefFormatable.get(tag);
+            if (format != null) {
+                try {
+                    format.connect();
+                    format.format(message);
+                    showToast("格式化tag并且写入message");
+                    waiting.close();
+                    return;
+                } catch (e) {
+                    showToast("格式化tag失败.");
+                    waiting.close();
+                    return;
+                }
+            } else {
+                showToast("Tag不支持NDEF");
+                waiting.close();
+                return;
+            }
+        }
+    } catch (e) {
+        console.log("error=" + e);
+        waiting.close();
+        alert("写入失败");
+    }
+}
+
+/**
+ * @NFC读取
+ * @param {*} intent
+ * @returns
+ */
+function __read(intent) {
+    try {
+        settingStores().nfcWaiting = '请勿移开标签\n正在读取数据...'
+        // waiting.setTitle("请勿移开标签\n正在读取数据...");
+        var tag = plus.android.importClass("android.nfc.Tag");
+        tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
+        var bytesId = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);
+        // waiting.close();
+        var tagid = bytesToHexString(tag.getId());
+
+        setTimeout(() => {
+            uni.$emit("NFC_readID", tagid); //将值存储监听器
+            tab.navigateBack(1); //返回上一级页面
+            closeReadAndWrite();
+        }, 1000);
+    } catch (e) {
+        uni.showToast({
+            title: e,
+            icon: "none",
+        });
+    }
+}
+
+function bytesToHexString(inarray) {
+    var i, j, x;
+    var hex = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"];
+    var out = "";
+    for (j = 0; j < inarray.length; ++j) {
+        x = parseInt(inarray[j]) & 0xff;
+        i = (x >> 4) & 0x0f;
+        out += hex[i];
+        i = x & 0x0f;
+        out += hex[i];
+    }
+    return out;
+}
+
+function reverseTwo(str) {
+    var str1 = "";
+    for (var i = 1; i <= str.length; i++) {
+        str1 += str[i - 1];
+        if (i % 2 == 0) {
+            if (i == str.length) {
+                break;
+            }
+            str1 += ":";
+        }
+    }
+    var str2 = "";
+    for (var i = str1.split(":").length - 1; i >= 0; i--) {
+        str2 += str1.split(":")[i];
+    }
+    return str2;
+}
+
+if (uni.getSystemInfoSync().platform == "android") {
+    //plus.globalEvent.addEventListener('plusready', listenNFCStatus, false);
+}
+
+function writeData() {
+    var textEle = plus.globalEvent.getElementById("text");
+    if (!textEle.value) {
+        uni.showToast({
+            title: "请输入要写入的内容!",
+            icon: "none",
+        });
+        return;
+    }
+    readyWriteData = true;
+    settingStores().nfcWaiting = '请将手机靠近NFC标签'
+    // waiting = plus.nativeUI.showWaiting("请将手机靠近NFC标签!");
+}
+
+function readData() {
+    readyRead = true;
+    settingStores().nfcWaiting = '请将手机靠近NFC标签'
+    // waiting = plus.nativeUI.showWaiting("请将手机靠近NFC标签!", {
+    //     modal: false,
+    // });
+}
+
+function closeReadAndWrite() {
+    readyWriteData = false;
+    readyRead = false;
+
+    if (waiting) {
+        waiting.close();
+    }
+}

+ 98 - 0
src/plugins/setting.plugins.js

@@ -0,0 +1,98 @@
+import { settingStores } from "@/store/modules/index";
+
+/**
+ * @获取缓存
+ */
+const formatSize = () => {
+  let currentSize = "";
+  plus.cache.calculate(function (size) {
+    let sizeCache = parseInt(size);
+    if (sizeCache == 0) {
+      currentSize = "0B";
+    } else if (sizeCache < 1024) {
+      currentSize = sizeCache + "B";
+    } else if (sizeCache < 1048576) {
+      currentSize = (sizeCache / 1024).toFixed(2) + "KB";
+    } else if (sizeCache < 1073741824) {
+      currentSize = (sizeCache / 1048576).toFixed(2) + "MB";
+    } else {
+      v = (sizeCache / 1073741824).toFixed(2) + "GB";
+    }
+
+    settingStores().currentSize = currentSize
+  });
+  return currentSize;
+};
+
+/**
+ * @清理缓存
+ */
+const clearCache = () => {
+  let os = plus.os.name;
+  if (os == "Android") {
+    let main = plus.android.runtimeMainActivity();
+    let sdRoot = main.getCacheDir();
+    let files = plus.android.invoke(sdRoot, "listFiles");
+    let len = files.length;
+
+    if (len <= 0) {
+      uni.showToast({
+        title: "暂无缓存可清理",
+        icon: "none",
+        duration: 2000,
+        mask: true,
+      });
+    }
+
+    for (let i = 0; i < len; i++) {
+      let filePath = "" + files[i]; // 没有找到合适的方法获取路径,这样写可以转成文件路径
+      plus.io.resolveLocalFileSystemURL(
+        filePath,
+        function (entry) {
+          if (entry.isDirectory) {
+            entry.removeRecursively(
+              function (entry) {
+                //递归删除其下的所有文件及子目录
+                uni.showToast({
+                  title: "缓存清理完成",
+                  duration: 2000,
+                  mask: true,
+                });
+                formatSize(); // 重新计算缓存
+              },
+              function (e) {
+                console.log(e.message);
+              }
+            );
+          } else {
+            entry.remove();
+          }
+        },
+        function (e) {
+          console.log("文件路径读取失败");
+        }
+      );
+    }
+  } else {
+    // ios
+    plus.cache.clear(function () {
+      uni.showToast({
+        title: "缓存清理完成",
+        duration: 2000,
+        mask: true,
+      });
+      formatSize();
+    });
+  }
+};
+
+export default {
+  // 设置角标
+  setBadge(value) {
+    //#ifdef APP-PLUS
+    plus.runtime.setBadgeNumber(value);
+    //#endif
+  },
+  formatSize,
+  clearCache,
+};

+ 32 - 0
src/plugins/tab.plugins.js

@@ -0,0 +1,32 @@
+export default {
+  // 关闭所有页面,打开到应用内的某个页面
+  reLaunch(url) {
+    return uni.reLaunch({
+      url: url
+    })
+  },
+  // 跳转到tabBar页面,并关闭其他所有非tabBar页面
+  switchTab(url) {
+    return uni.switchTab({
+      url: url
+    })
+  },
+  // 关闭当前页面,跳转到应用内的某个页面
+  redirectTo(url) {
+    return uni.redirectTo({
+      url: url
+    })
+  },
+  // 保留当前页面,跳转到应用内的某个页面
+  navigateTo(url) {
+    return uni.navigateTo({
+      url: url
+    })
+  },
+  // 关闭当前页面,返回上一页面或多级页面
+  navigateBack(value) {
+    return uni.navigateBack({
+      delta: value, //返回到需要执行方法的页面
+    })
+  }
+}

+ 217 - 0
src/plugins/time.plugins.js

@@ -0,0 +1,217 @@
+export default {
+    /**
+     * @param {时间处理(今日,昨日)} 
+     * @param {传入值} time 
+     * @param {是否携带时分秒} isTime
+     * @returns 
+     */
+    jktTimes(time, isTime) {
+        if (time == undefined) return "";
+        var today = new Date().getDate();//当前时间-日
+        var day = new Date(time).getDate();//传入时间-日
+
+        var newday = today - day
+        if (newday == 0) {
+            if (isTime == "否") {
+                return "今天";
+            } else {
+                var newTime = time.split(" ")[1]
+                var newTime2 = newTime.split(":")
+                return newTime2[0] + ":" + newTime2[1];
+            }
+        } else if (newday == 1) {
+            if (isTime == "否") {
+                return "昨天";
+            } else {
+                var newTime = time.split(" ")[1]
+                var newTime2 = newTime.split(":")
+                return newTime2[0] + ":" + newTime2[1];
+            }
+        } else {
+            var newTime = time.split(" ")
+
+            if (isTime == "否") {
+                return newTime[0]
+            } else {
+                var newTime2 = newTime[1].split(":")
+                return newTime2[0] + ":" + newTime2[1];
+            }
+        }
+    },
+    /**
+     * @指定获取开始时间结束时间
+     */
+    getDays(value) {
+        let oneDay = 24 * 60 * 60 * 1000;
+        let endTime = new Date(Date.now());
+        endTime = this.formatterDate(endTime, "yyyy-MM-dd");
+        let startTime = new Date(Date.now() - value * oneDay);
+        startTime = this.formatterDate(startTime, "yyyy-MM-dd");
+        const days = [startTime, endTime]
+        return days;
+    },
+    /**
+     * @处理公共日期格式
+     */
+    formatterDate(date, fmt) {
+        let nowDate = {
+            yyyy: date.getFullYear(), // 年
+            MM: date.getMonth() + 1, // 月份
+            dd: date.getDate(), //日
+            hh: date.getHours(),
+            mm: date.getMinutes(),
+            ss: date.getSeconds(),
+        };
+        if (/(y+)/.test(fmt)) {
+            fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
+        }
+        for (var k in nowDate) {
+            if (new RegExp("(" + k + ")").test(fmt)) {
+                fmt = fmt.replace(RegExp.$1, RegExp.$1.length == 1 ? nowDate[k] : ("00" + nowDate[k]).substr(("" + nowDate[k]).length));
+            }
+        }
+        return fmt;
+    },
+    /**
+     * @获取年月日时分秒
+     * @returns
+     */
+    getFormatterDate(time3) {
+        var date = new Date(time3);
+        var Y = date.getFullYear() + "-";
+        var M = (date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1) + "-";
+        var D = (date.getDate() < 10 ? "0" + date.getDate() : date.getDate()) + " ";
+
+        var h = (date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":";
+        var m = (date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()) + ":";
+        var s = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
+        var strDate = Y + M + D + h + m + s;
+
+        return strDate;
+    },
+    /**
+     * @获取当前日期前一年的日期
+     */
+    getYearLast(dateStr) {
+        // 假设要获取的日期为dateStr,格式为"YYYY-MM-DD"
+        let date = new Date(dateStr);
+        let Y = date.getFullYear() - 1; // 获取前一年的年份
+        let M = date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1; // 月
+        let D; // 日
+
+        var h = (date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":";
+        var m = (date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()) + ":";
+        var s = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
+
+        // 判断原日期的月份是否为2月份
+        if (date.getMonth() === 1) { // 2月份
+            // 判断前一年是否为闰年
+            if (Y % 4 === 0 && Y % 100 !== 0 || Y % 400 === 0) { // 闰年
+                D = Math.min(date.getDate(), 29); // 新日期的日期最大为29
+            } else { // 平年
+                D = Math.min(date.getDate(), 28); // 新日期的日期最大为28
+            }
+        } else { // 非2月份
+            D = date.getDate(); // 新日期的日期为原日期的日期
+        }
+        let newDateStr = Y + "-" + M + "-" + (D < 10 ? "0" + D : D) + " " + h + m + s; // 格式化日期字符串
+        return newDateStr
+    },
+    /**
+     * @统计两个日期之间的月份
+     */
+    getMonths(date1, date2) {
+        //用-分成数组
+        date1 = date1.split("-");
+        date2 = date2.split("-");
+        //获取年,月数
+        var year1 = parseInt(date1[0]),
+            month1 = parseInt(date1[1]),
+            year2 = parseInt(date2[0]),
+            month2 = parseInt(date2[1]),
+            //通过年,月差计算月份差
+            months = (year2 - year1) * 12 + (month2 - month1) + 1;
+        return months;
+    },
+    /**
+     * @获取年月日星期几
+     */
+    getDate() {
+        var date = new Date();
+        var year = date.getFullYear(); //  返回的是年份
+        var month = date.getMonth() + 1; //  返回的月份上个月的月份,记得+1才是当月
+        if (month < 10) {
+            month = "0" + month;
+        }
+        var dates = date.getDate(); //  返回的是几号
+        if (dates < 10) {
+            dates = "0" + dates;
+        }
+        var day = date.getDay(); //  周一返回的是1,周六是6,但是周日是0
+        var arr = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"];
+        return { year, month, dates, day, arr, };
+    },
+    /**
+     * @获取当前周开始结束日期
+     */
+    getCurrentWeekDate() {
+        const now = new Date();
+        const startOfWeek = new Date(now.getFullYear(), now.getMonth(), now.getDate() - now.getDay() + 1); // 本周开始日期
+        const endOfWeek = new Date(startOfWeek);
+        endOfWeek.setDate(endOfWeek.getDate() + 6); // 本周结束日期
+
+        const startDate = this.getFormatterDate(startOfWeek).split(' ')[0];
+        const endDate = this.getFormatterDate(endOfWeek).split(' ')[0];
+
+        return {
+            startDate: startDate,
+            endDate: endDate
+        }
+    },
+    /**
+     * @时间重组
+     * @param { 时间段 } chooseTime 
+     */
+    timeRestructuring(chooseTime) {
+        var startTime = "";
+        var endTime = "";
+        let start = chooseTime[0];
+        let end = chooseTime[1];
+
+        if (start == 0 && end == 0) {
+            startTime = "00:00";
+            endTime = "00:30";
+        }
+
+        if ((!start && start !== 0) || !end) {
+            startTime = "";
+            endTime = "";
+            return;
+        }
+
+        if (start % 1 === 0.5) {
+            start = (start - 0.5 < 10 ? "0" : "") + (start - 0.5) + ":30";
+        } else {
+            start = (start < 10 ? "0" : "") + start + ":00";
+        }
+
+        if (Number.isInteger(end)) {
+            if (end === 24) {
+                end = "23:30";
+            } else {
+                end = (end - 0.5 < 10 ? "0" : "") + end + ":00";
+            }
+        } else {
+            if (end === 24) {
+                end = "23:30";
+            } else {
+                end = (end < 10 ? "0" : "") + (end - 0.5) + ":30";
+            }
+        }
+
+        return {
+            startTime: start,
+            endTime: end,
+        };
+    }
+}

+ 195 - 0
src/static/iconfont/iconfont.css

@@ -0,0 +1,195 @@
+@font-face {
+  font-family: "iconfont"; /* Project id 4510027 */
+  src: url('https://at.alicdn.com/t/c/font_4510027_p1rynf6nken.woff2?t=1723634694993') format('woff2'),
+       url('https://at.alicdn.com/t/c/font_4510027_p1rynf6nken.woff?t=1723634694993') format('woff'),
+       url('https://at.alicdn.com/t/c/font_4510027_p1rynf6nken.ttf?t=1723634694993') format('truetype');
+}
+
+.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.oaIcon-tab-home:before {
+  content: "\e60e";
+}
+
+.oaIcon-tab-info:before {
+  content: "\e610";
+}
+
+.oaIcon-tab-mine:before {
+  content: "\e613";
+}
+
+.oaIcon-tab-projectsList:before {
+  content: "\e61c";
+}
+
+.oaIcon-tab-reportInsert:before {
+  content: "\e61e";
+}
+
+.oaIcon-tab-reportRecord:before {
+  content: "\e622";
+}
+
+.oaIcon-zhiwen1:before {
+  content: "\e60b";
+}
+
+.oaIcon-bianji1:before {
+  content: "\e60d";
+}
+
+.oaIcon-qinglihuancun:before {
+  content: "\e623";
+}
+
+.oaIcon-shaixuan:before {
+  content: "\e625";
+}
+
+.oaIcon-shezhi:before {
+  content: "\e626";
+}
+
+.oaIcon-shouji:before {
+  content: "\e627";
+}
+
+.oaIcon-jianchagengxin:before {
+  content: "\e628";
+}
+
+.oaIcon-sousuo:before {
+  content: "\e629";
+}
+
+.oaIcon-ditu:before {
+  content: "\e61d";
+}
+
+.oaIcon-dial:before {
+  content: "\e621";
+}
+
+.oaIcon-aixin:before {
+  content: "\e609";
+}
+
+.oaIcon-tongzhi:before {
+  content: "\e601";
+}
+
+.oaIcon-yanzheng:before {
+  content: "\e608";
+}
+
+.oaIcon-user:before {
+  content: "\e603";
+}
+
+.oaIcon-phone:before {
+  content: "\e614";
+}
+
+.oaIcon-map:before {
+  content: "\e615";
+}
+
+.oaIcon-Help:before {
+  content: "\e616";
+}
+
+.oaIcon-eye-close:before {
+  content: "\e617";
+}
+
+.oaIcon-eye:before {
+  content: "\e618";
+}
+
+.oaIcon-colorlens:before {
+  content: "\e619";
+}
+
+.oaIcon-fenxiang:before {
+  content: "\e611";
+}
+
+.oaIcon-aixin2:before {
+  content: "\e612";
+}
+
+.oaIcon-tongzhi2:before {
+  content: "\e606";
+}
+
+.oaIcon-filter:before {
+  content: "\e60c";
+}
+
+.oaIcon-appstore:before {
+  content: "\e600";
+}
+
+.oaIcon-people:before {
+  content: "\e736";
+}
+
+.oaIcon-user1:before {
+  content: "\e632";
+}
+
+.oaIcon-shezhi2:before {
+  content: "\e70f";
+}
+
+.oaIcon-saoyisao:before {
+  content: "\e607";
+}
+
+.oaIcon-zhiwen:before {
+  content: "\e74f";
+}
+
+.oaIcon-bianji:before {
+  content: "\e602";
+}
+
+.oaIcon-copy:before {
+  content: "\e604";
+}
+
+.oaIcon-shangchuan:before {
+  content: "\e605";
+}
+
+.oaIcon-app-map:before {
+  content: "\e60a";
+}
+
+.oaIcon-address:before {
+  content: "\e60f";
+}
+
+.oaIcon-nfc:before {
+  content: "\e61a";
+}
+
+.oaIcon-upgrade:before {
+  content: "\e61b";
+}
+
+.oaIcon-jiahao:before {
+  content: "\e620";
+}
+
+.oaIcon-qingchu:before {
+  content: "\e61f";
+}
+

TEMPAT SAMPAH
src/static/iconfont/iconfont.ttf


TEMPAT SAMPAH
src/static/images/tabBar/analyse-selected.png


TEMPAT SAMPAH
src/static/images/tabBar/analyse.png


TEMPAT SAMPAH
src/static/images/tabBar/info-selected.png


TEMPAT SAMPAH
src/static/images/tabBar/info.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-cate-black.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-cate-blue.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-cate-brown.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-cate-cyan.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-cate-gray.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-cate-green.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-cate-grey.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-cate-mauve.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-cate-olive.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-cate-orange.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-cate-pink.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-cate-purple.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-cate-red.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-cate-rf.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-cate-yellow.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-cate.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-home-black.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-home-blue.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-home-brown.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-home-cyan.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-home-gray.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-home-green.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-home-grey.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-home-mauve.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-home-olive.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-home-orange.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-home-pink.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-home-purple.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-home-red.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-home-rf.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-home-yellow.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-home.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-info-black.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-info-blue.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-info-brown.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-info-cyan.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-info-gray.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-info-green.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-info-grey.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-info-mauve.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-info-olive.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-info-orange.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-info-pink.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-info-purple.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-info-red.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-info-yellow.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-info.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-my-black.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-my-blue.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-my-brown.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-my-cyan.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-my-gray.png


TEMPAT SAMPAH
src/static/images/tabBar/tab-my-green.png


Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini