罗广辉
2025-12-26 e3e6a984ee20e3a77852442b68ddb1d887e2e769
Merge branch 'feature/v9.0/9.0.3' into prod
20 files modified
3 files added
21 files deleted
2519 ■■■■■ changed files
src/App.vue 12 ●●●● patch | view | raw | blame | history
src/components/WebViewPlus.vue 7 ●●●●● patch | view | raw | blame | history
src/config/env.js 31 ●●●● patch | view | raw | blame | history
src/manifest.json 2 ●●● patch | view | raw | blame | history
src/pages.json 31 ●●●● patch | view | raw | blame | history
src/pages/dispatcher/index.vue 85 ●●●●● patch | view | raw | blame | history
src/pages/inspectionTask/index.vue 84 ●●●●● patch | view | raw | blame | history
src/pages/login/index.vue 485 ●●●● patch | view | raw | blame | history
src/pages/map/index copy.vue 510 ●●●●● patch | view | raw | blame | history
src/pages/map/index.vue 26 ●●●● patch | view | raw | blame | history
src/pages/placeholder/placeholder.vue 11 ●●●●● patch | view | raw | blame | history
src/pages/user/index.vue 397 ●●●● patch | view | raw | blame | history
src/pages/work/index.vue 154 ●●●●● patch | view | raw | blame | history
src/static/fonts/font.css 18 ●●●●● patch | view | raw | blame | history
src/static/images/login/droneSvg.svg 11 ●●●●● patch | view | raw | blame | history
src/static/images/login/logo.svg 11 ●●●●● patch | view | raw | blame | history
src/static/images/login/password.svg 11 ●●●●● patch | view | raw | blame | history
src/static/images/login/username.svg 11 ●●●●● patch | view | raw | blame | history
src/static/images/user/allBg.svg 26 ●●●●● patch | view | raw | blame | history
src/static/images/user/bg.png patch | view | raw | blame | history
src/static/images/user/info.png patch | view | raw | blame | history
src/static/images/user/info.svg 19 ●●●●● patch | view | raw | blame | history
src/static/images/user/logo1.png patch | view | raw | blame | history
src/static/images/user/logo1.svg 9 ●●●●● patch | view | raw | blame | history
src/static/images/user/logo2.png patch | view | raw | blame | history
src/static/images/user/logo2.svg 9 ●●●●● patch | view | raw | blame | history
src/static/images/user/mobile.svg 11 ●●●●● patch | view | raw | blame | history
src/static/images/user/password.png patch | view | raw | blame | history
src/static/images/user/password.svg 19 ●●●●● patch | view | raw | blame | history
src/static/images/user/rightBtn.svg 9 ●●●●● patch | view | raw | blame | history
src/static/images/user/userBg.svg 25 ●●●●● patch | view | raw | blame | history
src/subPackages/404/index.vue 9 ●●●●● patch | view | raw | blame | history
src/subPackages/inProgress/index.vue 52 ●●●●● patch | view | raw | blame | history
src/subPackages/qrCode/index.vue 47 ●●●●● patch | view | raw | blame | history
src/subPackages/taskDetail/addTask/index.vue 76 ●●●●● patch | view | raw | blame | history
src/subPackages/taskDetail/inExecution/index.vue 8 ●●●●● patch | view | raw | blame | history
src/subPackages/taskDetail/inProgress/index.vue 61 ●●●●● patch | view | raw | blame | history
src/subPackages/taskDetail/index.vue 18 ●●●●● patch | view | raw | blame | history
src/subPackages/userDetail/infos/index.vue 8 ●●●● patch | view | raw | blame | history
src/subPackages/userDetail/password/index.vue 8 ●●●● patch | view | raw | blame | history
src/subPackages/workDetail/addWork/index.vue 72 ●●●●● patch | view | raw | blame | history
src/subPackages/workDetail/index.vue 91 ●●●●● patch | view | raw | blame | history
src/subPackages/workDetail/mapWork/index.vue 7 ●●●● patch | view | raw | blame | history
src/utils/common/index.js 38 ●●●● patch | view | raw | blame | history
src/App.vue
@@ -1,12 +1,12 @@
<script setup>
import {onHide, onLaunch, onShow} from "@dcloudio/uni-app";
import {useAppStore, useUserStore} from "@/store";
import {useGlobalWS} from "@/hooks/useGlobalWS.js";
import { onHide, onLaunch, onShow } from "@dcloudio/uni-app";
import { useAppStore, useUserStore } from "@/store";
import { useGlobalWS } from "@/hooks/useGlobalWS.js";
const appStore = useAppStore();
const userStore = useUserStore();
useGlobalWS()
useGlobalWS();
onShow(() => {
  console.log("App Show");
@@ -23,7 +23,7 @@
    //不存在则跳转至登录页
    uni.reLaunch({
      url: "/pages/login/index",
    })
    });
  }
});
</script>
@@ -41,7 +41,7 @@
}
page {
  background-image: url('~@/static/images/user/bg.png');
  background-image: url("https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/images/user/bg.png");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
src/components/WebViewPlus.vue
@@ -33,6 +33,13 @@
  }
}
onLoad((obj) => {
  // const h5Params = obj?.cs && JSON.parse(obj?.cs)
  // console.log('h5Params', h5Params)
  // h5Params && viewMessage({detail: {data: [h5Params.data]}})
})
onShow(() => {
  if (window && window.addEventListener)
    window.addEventListener("message", messageFun);
src/config/env.js
@@ -1,26 +1,43 @@
/*
 * @Author       : yuan
 * @Date         : 2025-12-15 17:51:08
 * @LastEditors  : yuan
 * @LastEditTime : 2025-12-16 15:01:04
 * @FilePath     : \src\config\env.js
 * @Description  :
 * Copyright 2025 OBKoro1, All Rights Reserved.
 * 2025-12-15 17:51:08
 */
// 如果是打包app,需要改这里,h5不需要改这里
const development = {
  VITE_APP_ENV:'development',
  // 开发环境这里改为自己的
  // VITE_APP_WEBVIEW_URL: 'https://wrj.shuixiongit.com/drone-app-web-view/#/webViewWrapper',
  VITE_APP_WEBVIEW_URL: 'http://localhost:5173/drone-app-web-view/#/webViewWrapper',
  VITE_APP_WEBVIEW_URL: 'https://wrj.shuixiongit.com/drone-app-web-view/#/webViewWrapper',
  // VITE_APP_WEBVIEW_URL: 'http://localhost:5173/drone-app-web-view/#/webViewWrapper',
  VITE_API_BASE_URL: 'https://wrj.shuixiongit.com/api',
  // VITE_API_BASE_URL: 'https://aisky.org.cn/api',
  VITE_APP_WS_API_URL:'wss://wrj.shuixiongit.com/drone-wss/api/v1/ws'
  VITE_APP_WS_API_URL:'wss://wrj.shuixiongit.com/drone-wss/api/v1/ws',
  // 静态资源存放地址'
  VITE_APP_ASSETS_URL: 'https://wrj.shuixiongit.com/drone-app/assets/static'
}
const test = {
  VITE_APP_ENV:'test',
  VITE_APP_ENV: 'test',
  VITE_APP_WEBVIEW_URL: 'https://wrj.shuixiongit.com/drone-app-web-view/#/webViewWrapper',
  VITE_API_BASE_URL: 'https://wrj.shuixiongit.com/api',
  VITE_APP_WS_API_URL:'wss://wrj.shuixiongit.com/drone-wss/api/v1/ws'
  VITE_APP_WS_API_URL: 'wss://wrj.shuixiongit.com/drone-wss/api/v1/ws',
  // 静态资源存放地址'
  VITE_APP_ASSETS_URL: 'https://wrj.shuixiongit.com/drone-app/assets/static'
}
const production = {
  VITE_APP_ENV:'production',
  VITE_APP_ENV: 'production',
  VITE_APP_WEBVIEW_URL: 'https://aisky.org.cn/drone-app-web-view/#/webViewWrapper',
  VITE_API_BASE_URL: 'https://aisky.org.cn/api',
  VITE_APP_WS_API_URL:'wss://aisky.org.cn/drone-wss/api/v1/ws'
  VITE_APP_WS_API_URL: 'wss://aisky.org.cn/drone-wss/api/v1/ws',
  // 静态资源存放地址'
  VITE_APP_ASSETS_URL: 'https://wrj.shuixiongit.com/drone-app/assets/static'
}
export default {
src/manifest.json
@@ -89,7 +89,7 @@
    "quickapp" : {},
    /* 小程序特有相关 */
    "mp-weixin" : {
        "appid" : "wx1ff4bbc24b343ef1",
        "appid" : "wx05742eafb412a57a",
        "setting" : {
            "urlCheck" : false
        },
src/pages.json
@@ -56,24 +56,6 @@
          }
        },
        {
          "path": "theme/index",
          "style": {
            "navigationBarTitleText": "主题设置"
          }
        },
        {
          "path": "taskDetail/index",
          "style": {
            "navigationBarTitleText": "任务详情"
          }
        },
        {
          "path": "inProgress/index",
          "style": {
            "navigationBarTitleText": "任务详情"
          }
        },
        {
          "path": "droneConsole/index",
          "style": {
            "navigationBarTitleText": "直播监控",
@@ -83,7 +65,8 @@
        {
          "path": "taskDetail/addTask/index",
          "style": {
            "navigationBarTitleText": "新建任务"
            "navigationBarTitleText": "新建任务",
            "navigationStyle": "custom"
          }
        },
        {
@@ -93,9 +76,9 @@
          }
        },
        {
          "path": "taskDetail/inExecution/index",
          "path": "taskDetail/inProgress/index",
          "style": {
            "navigationBarTitleText": "执行中"
            "navigationBarTitleText": "任务详情"
          }
        },
        {
@@ -114,7 +97,7 @@
          "path": "workDetail/mapWork/index",
          "style": {
            "navigationBarTitleText": "地图展示",
             "navigationStyle": "custom"
            "navigationStyle": "custom"
          }
        },
        {
@@ -169,6 +152,7 @@
        "pagePath": "pages/inspectionTask/index",
        "text": "任务"
      },
      // #ifndef MP-WEIXIN
      {
        "iconPath": "static/images/tabbar/add.png",
        "pagePath": "subPackages/taskDetail/addTask/index"
@@ -177,6 +161,7 @@
        "iconPath": "static/images/tabbar/drone.png",
        "visible": "true"
      },
      // #endif
      {
        "iconPath": "static/images/tabbar/icon_order.png",
        "selectedIconPath": "static/images/tabbar/icon_order_selected.png",
@@ -197,4 +182,4 @@
    "navigationBarBackgroundColor": "#F8F8F8",
    "backgroundColor": "#F8F8F8"
  }
}
}
src/pages/dispatcher/index.vue
New file
@@ -0,0 +1,85 @@
<template>
  <view></view>
</template>
<script setup>
import { onShow, onHide } from "@dcloudio/uni-app";
import { ref } from "vue";
// 标记是否已经跳转过,防止从子页面返回时再次触发跳转
const isNavigating = ref(false);
onShow(() => {
  const lastTab = uni.getStorageSync("lastTab");
  // 如果是跳转后返回的状态(isNavigating为true),则说明用户取消了操作或完成了操作返回
  // 此时应该回到之前的Tab页
  if (isNavigating.value) {
    isNavigating.value = false; // 重置标志位
    if (lastTab === "task") {
      uni.switchTab({ url: "/pages/inspectionTask/index" });
    } else if (lastTab === "work") {
      uni.switchTab({ url: "/pages/work/index" });
    } else if (lastTab === "user") {
      uni.switchTab({ url: "/pages/user/index" });
    } else {
      uni.switchTab({ url: "/pages/map/index" });
    }
    return;
  }
  // 根据上一个页面决定跳转逻辑
  if (lastTab === "task") {
    // 任务页面 -> 跳转新建任务
    isNavigating.value = true;
    uni.navigateTo({
      url: "/subPackages/taskDetail/addTask/index",
      fail: (err) => {
        console.error("Navigate to addTask failed:", err);
        isNavigating.value = false;
        // 如果跳转失败,返回上一页
        uni.switchTab({ url: "/pages/inspectionTask/index" });
      },
    });
  } else if (lastTab === "work") {
    // 工单页面 -> 跳转新建工单
    isNavigating.value = true;
    uni.navigateTo({
      url: "/subPackages/workDetail/addWork/index",
      fail: (err) => {
        console.error("Navigate to addWork failed:", err);
        isNavigating.value = false;
        uni.switchTab({ url: "/pages/work/index" });
      },
    });
  } else {
    // 地图或我的页面 -> 仅占位,不跳转,提示并返回
    uni.showToast({
      title: "此功能暂未开放",
      icon: "none",
      duration: 2000,
    });
    // 返回上一个Tab
    if (lastTab === "user") {
      uni.switchTab({ url: "/pages/user/index" });
    } else {
      // 默认为地图
      uni.switchTab({ url: "/pages/map/index" });
    }
  }
});
onHide(() => {
  // 页面隐藏时,如果是切换到了其他Tab(不是navigateTo),可能需要重置?
  // 不,如果是navigateTo,页面隐藏是正常的,flag保持true。
  // 如果是switchTab出去,flag应该是false(因为已经处理过了)。
  // 唯一风险是:如果navigateTo之前就switchTab了?(不可能,逻辑是同步的)
});
</script>
<style>
page {
  background-color: transparent;
}
</style>
src/pages/inspectionTask/index.vue
@@ -1,72 +1,100 @@
<!-- 巡检任务 -->
<template>
  <WebViewPlus :src="`${viewUrl}`" @webMessage="onPostMessage"/>
  <view>
    <WebViewPlus :src="`${viewUrl}`" @webMessage="onPostMessage" />
  </view>
</template>
<script setup>
import { getWebViewUrl } from "@/utils/index.js";
import WebViewPlus from "@/components/WebViewPlus.vue";
import {onHide, onShow} from "@dcloudio/uni-app";
import {errorFactory} from "sass-loader/dist/utils.js";
import { useAppStore } from "@/store/index.js"
import { onHide, onShow } from "@dcloudio/uni-app";
import { errorFactory } from "sass-loader/dist/utils.js";
import { useAppStore } from "@/store/index.js";
const appStore = useAppStore()
const appStore = useAppStore();
// const viewUrl = getWebViewUrl('/inspectionTask')
const updateKey = ref(0)
const sxListKey = ref(0)
const updateKey = ref(0);
const sxListKey = ref(0);
const viewUrl = computed(() => {
  return getWebViewUrl(  '/inspectionTask', { updateKey: updateKey.value,sxListKey: sxListKey.value })
})
  // #ifdef MP-WEIXIN
  return getWebViewUrl("/inspectionTask", {
    updateKey: updateKey.value,
    sxListKey: sxListKey.value,
    showAddBtn: 1,
  });
  // #endif
watch(() => [appStore.jobUpdateKey, appStore.deviceUpdateKey], () => {
  sxListKey.value = sxListKey.value + 1
})
  // #ifndef MP-WEIXIN
  return getWebViewUrl("/inspectionTask", {
    updateKey: updateKey.value,
    sxListKey: sxListKey.value,
    showAddBtn: 0,
  });
  // #endif
});
watch(
  () => [appStore.jobUpdateKey, appStore.deviceUpdateKey],
  () => {
    sxListKey.value = sxListKey.value + 1;
  }
);
function onPostMessage(data) {
  if (data.type === 'taskDetails'){
    if ([1,2].includes(data.rowItem.status)){
  if (data.type === "taskDetails") {
    // #ifdef MP-WEIXIN
    // #endif
    // #ifndef MP-WEIXIN
    if ([1, 2].includes(data.rowItem.status)) {
      uni.navigateTo({
        url: `/subPackages/inProgress/index?wayLineJobInfoId=${data.rowItem.id}&batchNo=${data.rowItem.batch_no}`
        url: `/subPackages/taskDetail/inProgress/index?wayLineJobInfoId=${data.rowItem.id}&batchNo=${data.rowItem.batch_no}`,
      });
    } else {
      uni.navigateTo({
        url: `/subPackages/taskDetail/execution/index?wayLineJobInfoId=${data.rowItem.id}&waylineJobId=${data.rowItem.wayline_job_id}&batch_no=${data.rowItem.batch_no}`
        url: `/subPackages/taskDetail/execution/index?wayLineJobInfoId=${data.rowItem.id}&waylineJobId=${data.rowItem.wayline_job_id}&batch_no=${data.rowItem.batch_no}`,
      });
    }
    // #endif
  }
  if (data.type === "addTask") {
    // #ifdef MP-WEIXIN
    // #endif
  }
}
const isApp = ref(false)
onShow(() => {
  const joinParams = uni.getStorageSync('joinParams');
  const joinParams = uni.getStorageSync("joinParams");
  if (joinParams) {
    // 使用后清除
    console.log('是否打印', updateKey.value)
    updateKey.value = updateKey.value + 1
    uni.removeStorageSync('joinParams');
    console.log("是否打印", updateKey.value);
    updateKey.value = updateKey.value + 1;
    uni.removeStorageSync("joinParams");
  }
  // isApp.value = true
  // 清除数据
  const encodedData = encodeURIComponent(JSON.stringify({ device_sn: '' }))
  uni.setStorageSync('webview_params', encodedData);
  const encodedData = encodeURIComponent(JSON.stringify({ device_sn: "" }));
  uni.setStorageSync("webview_params", encodedData);
  // #ifndef MP-WEIXIN
  uni.setTabBarItem({
    index: 2, // Tab 的索引(从0开始)
    visible: true,
    pagePath: "subPackages/taskDetail/addTask/index"
    pagePath: "subPackages/taskDetail/addTask/index",
  });
  uni.setTabBarItem({
    index: 3, // Tab
    visible: false,
  });
  // #endif
});
onHide(() => {
  // isApp.value = false
});
</script>
<style scoped lang="scss">
</style>
<style scoped lang="scss"></style>
src/pages/login/index.vue
@@ -1,204 +1,207 @@
<!-- 登录页 -->
<template>
    <view class="login-form-wrap">
        <image class="logo" :src="logoSvg" />
        <div class="title">掌控智飞</div>
        <div class="user-name">
            <image :src="usernameSvg" />
            <input v-model="loginForm.username" placeholder="请输入用户名" />
        </div>
        <div class="pass-word">
            <image :src="passwordSvg" />
            <input v-model="loginForm.password" type="password" placeholder="请输入密码" />
        </div>
        <div class="remember-password">
            <label>
                <checkbox-group @change="toggleRemember">
                    <checkbox :checked="rememberPassword" color="#1D6FE9" style="transform:scale(0.7)" />
                </checkbox-group>
                记住密码
            </label>
        </div>
  <view class="login-form-wrap">
    <image class="logo" :src="logoSvg" />
    <div class="title">掌控智飞</div>
    <div class="user-name">
      <image :src="usernameSvg" />
      <input v-model="loginForm.username" placeholder="请输入用户名" />
    </div>
    <div class="pass-word">
      <image :src="passwordSvg" />
      <input
        v-model="loginForm.password"
        type="password"
        placeholder="请输入密码"
      />
    </div>
    <div class="remember-password">
      <label>
        <checkbox-group @change="toggleRemember">
          <checkbox
            :checked="rememberPassword"
            color="#1D6FE9"
            style="transform: scale(0.7)"
          />
        </checkbox-group>
        记住密码
      </label>
    </div>
        <button class="login-btn"  :style="[inputStyle]" @tap="submit">
            登录
        </button>
        <image class="lowerRightCorner" :src="droneSvg" />
    </view>
    <button class="login-btn" :style="[inputStyle]" @tap="submit">登录</button>
    <image class="lowerRightCorner" :src="droneSvg" />
  </view>
</template>
<script setup>
    import md5 from "js-md5";
    import {
        loginByUsername
    } from "@/api/user/index.js";
    import {
        useUserStore
    } from "@/store/index.js";
    import droneSvg from '@/static/images/login/droneSvg.svg'
    import usernameSvg from '@/static/images/login/username.svg'
    import passwordSvg from '@/static/images/login/password.svg'
    import logoSvg from '@/static/images/login/logo.svg'
    import {
        HOME_PATH,
        LOGIN_PATH,
        removeQueryString
    } from "@/router";
    import { onMounted } from 'vue';
import { getAssetsImage } from "@/utils/index.js";
import md5 from "js-md5";
import { loginByUsername } from "@/api/user/index.js";
import { useUserStore } from "@/store/index.js";
    const userStore = useUserStore();
    const loginForm = ref({
        username: "",
        password: "",
    });
    const rememberPassword = ref(false);
    const inputStyle = computed(() => {
        const style = {};
        if (loginForm.value.username && loginForm.value.password) {
            style.color = "#fff";
            style.backgroundColor = '#1D6FE9';
        }
        return style;
    });
    let redirect = HOME_PATH;
    function toggleRemember(e) {
        rememberPassword.value = e.detail.value.length > 0;
    }
import { HOME_PATH, LOGIN_PATH, removeQueryString } from "@/router";
import { onMounted } from "vue";
    async function submit() {
         if (!loginForm.value.username.trim()) {
            uni.showToast({
              title: "请输入用户名",
              icon: "none",
              duration: 2000
            });
            return;
          }
const droneSvg = getAssetsImage("/images/login/droneSvg.svg");
const usernameSvg = getAssetsImage("/images/login/username.svg");
const passwordSvg = getAssetsImage("/images/login/password.svg");
const logoSvg = getAssetsImage("/images/login/logo.svg");
          if (!loginForm.value.password.trim()) {
            uni.showToast({
              title: "请输入密码",
              icon: "none",
              duration: 2000
            });
            return;
          }
        let userInfo = {
            tenantId: "000000",
            deptId: "",
            roleId: "",
            username: loginForm.value.username,
            password: loginForm.value.password,
            type: "account",
            code: "",
            key: "",
        };
const userStore = useUserStore();
const loginForm = ref({
  username: "",
  password: "",
});
const rememberPassword = ref(false);
const inputStyle = computed(() => {
  const style = {};
  if (loginForm.value.username && loginForm.value.password) {
    style.color = "#fff";
    style.backgroundColor = "#1D6FE9";
  }
  return style;
});
let redirect = HOME_PATH;
function toggleRemember(e) {
  rememberPassword.value = e.detail.value.length > 0;
}
        if (rememberPassword.value) {
            uni.setStorageSync('rememberedUser', {
                username: loginForm.value.username,
                password: loginForm.value.password
            });
        } else {
            uni.removeStorageSync('rememberedUser');
        }
async function submit() {
  if (!loginForm.value.username.trim()) {
    uni.showToast({
      title: "请输入用户名",
      icon: "none",
      duration: 2000,
    });
    return;
  }
        try {
            const res = await loginByUsername(
                userInfo.tenantId,
                userInfo.deptId,
                userInfo.roleId,
                userInfo.username,
                md5(userInfo.password),
                userInfo.type,
                userInfo.key,
                userInfo.code
            );
            userStore.setUserInfo(res.data);
            uni.reLaunch({
                url: "/pages/map/index",
            });
        } catch (error) {
            const errorMsg =error.data?.error_description !=="Bad credentials" ? error.data?.error_description:  "登录失败,请重试";
            uni.showToast({
                title: errorMsg,
                icon: "none",
                duration: 2000
            });
        }
    }
    // 从本地存储加载记住的密码
    onMounted(() => {
        const savedUserInfo = uni.getStorageSync('rememberedUser');
        console.log('记住密码',savedUserInfo)
        if (savedUserInfo) {
            loginForm.value.username = savedUserInfo.username;
            loginForm.value.password = savedUserInfo.password;
            rememberPassword.value = true;
        }
    });
    onLoad((options) => {
        if (options.redirect && removeQueryString(options.redirect) !== LOGIN_PATH) {
            redirect = decodeURIComponent(options.redirect);
        }
    });
  if (!loginForm.value.password.trim()) {
    uni.showToast({
      title: "请输入密码",
      icon: "none",
      duration: 2000,
    });
    return;
  }
  let userInfo = {
    tenantId: "000000",
    deptId: "",
    roleId: "",
    username: loginForm.value.username,
    password: loginForm.value.password,
    type: "account",
    code: "",
    key: "",
  };
  if (rememberPassword.value) {
    uni.setStorageSync("rememberedUser", {
      username: loginForm.value.username,
      password: loginForm.value.password,
    });
  } else {
    uni.removeStorageSync("rememberedUser");
  }
  try {
    const res = await loginByUsername(
      userInfo.tenantId,
      userInfo.deptId,
      userInfo.roleId,
      userInfo.username,
      md5(userInfo.password),
      userInfo.type,
      userInfo.key,
      userInfo.code
    );
    userStore.setUserInfo(res.data);
    uni.reLaunch({
      url: "/pages/map/index",
    });
  } catch (error) {
    const errorMsg =
      error.data?.error_description !== "Bad credentials"
        ? error.data?.error_description
        : "登录失败,请重试";
    uni.showToast({
      title: errorMsg,
      icon: "none",
      duration: 2000,
    });
  }
}
// 从本地存储加载记住的密码
onMounted(() => {
  const savedUserInfo = uni.getStorageSync("rememberedUser");
  console.log("记住密码", savedUserInfo);
  if (savedUserInfo) {
    loginForm.value.username = savedUserInfo.username;
    loginForm.value.password = savedUserInfo.password;
    rememberPassword.value = true;
  }
});
onLoad((options) => {
  if (options.redirect && removeQueryString(options.redirect) !== LOGIN_PATH) {
    redirect = decodeURIComponent(options.redirect);
  }
});
</script>
<style lang="scss" scoped>
    .login-form-wrap {
        position: relative;
        text-align: center;
        height: 100%;
        width: 100%;
.login-form-wrap {
  position: relative;
  text-align: center;
  height: 100%;
  width: 100%;
        .logo {
            width: 127px;
            height: 51px;
            margin: 0 auto;
            margin-top: 104px;
            margin-bottom: 16px;
        }
  .logo {
    width: 127px;
    height: 51px;
    margin: 0 auto;
    margin-top: 104px;
    margin-bottom: 16px;
  }
        .lowerRightCorner {
            position: absolute;
            right: 0;
            bottom: 0;
            width: 425.61rpx;
            height: 316.46rpx;
        }
  .lowerRightCorner {
    position: absolute;
    right: 0;
    bottom: 0;
    width: 425.61rpx;
    height: 316.46rpx;
  }
        .title {
            font-family: YouSheBiaoTiHei, YouSheBiaoTiHei;
            font-weight: 400;
            font-size: 84rpx;
            line-height: 82rpx;
            letter-spacing: 1px;
            text-shadow: 0px 8px 8px rgba(0, 0, 0, 0.18);
            text-align: center;
            font-style: normal;
            text-transform: none;
            color: #1452D3;
            text-align: center;
            margin-bottom: 168rpx;
        }
  .title {
    font-family: YouSheBiaoTiHei, YouSheBiaoTiHei;
    font-weight: 400;
    font-size: 84rpx;
    line-height: 82rpx;
    letter-spacing: 1px;
    text-shadow: 0px 8px 8px rgba(0, 0, 0, 0.18);
    text-align: center;
    font-style: normal;
    text-transform: none;
    color: #1452d3;
    text-align: center;
    margin-bottom: 168rpx;
  }
        .user-name,
        .pass-word {
            display: flex;
            //justify-content: center;
            align-items: center;
            margin-left: 62rpx;
            margin-right: 58rpx;
            height: 118rpx;
            border-bottom: 2rpx solid #E3E3E3;
  .user-name,
  .pass-word {
    display: flex;
    //justify-content: center;
    align-items: center;
    margin-left: 62rpx;
    margin-right: 58rpx;
    height: 118rpx;
    border-bottom: 2rpx solid #e3e3e3;
            image {
                width: 40rpx;
                height: 40rpx;
                margin-right: 12rpx;
            }
    image {
      width: 40rpx;
      height: 40rpx;
      margin-right: 12rpx;
    }
    :deep(uni-input) {
      height: 40rpx;
@@ -214,78 +217,78 @@
      width: 80%;
      margin-top: 20rpx;
      padding: 0 !important;
      margin: 0 !important;
      margin: 0 !important;
    }
            :deep(.uni-input-placeholder) {
                font-size: 32rpx;
                color: #E3E3E3;
                font-weight: 500;
            }
        }
    :deep(.uni-input-placeholder) {
      font-size: 32rpx;
      color: #e3e3e3;
      font-weight: 500;
    }
  }
        .remember-password {
            display: flex;
            justify-content: flex-end;
            align-items: center;
            margin-left: 62rpx;
            margin-right: 58rpx;
            margin-top: 20rpx;
  .remember-password {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    margin-left: 62rpx;
    margin-right: 58rpx;
    margin-top: 20rpx;
            color: #666;
            font-size: 28rpx;
    color: #666;
    font-size: 28rpx;
            label {
                display: flex;
                align-items: center;
            }
        }
    label {
      display: flex;
      align-items: center;
    }
  }
        input {
            @apply pb-6rpx mb-10rpx text-left;
        }
  input {
    @apply pb-6rpx mb-10rpx text-left;
  }
        .tips {
            @apply mt-8rpx mb-60rpx;
            color: $u-info;
        }
  .tips {
    @apply mt-8rpx mb-60rpx;
    color: $u-info;
  }
        .login-btn {
            z-index: 1;
            @apply flex items-center justify-center py-12rpx px-0 text-30rpx border-none;
            background: #1D6FE9;
            color: white;
            width: 590rpx;
            height: 76rpx;
            border-radius: 40rpx 40rpx 40rpx 40rpx;
            margin-top: 100rpx;
  .login-btn {
    z-index: 1;
    @apply flex items-center justify-center py-12rpx px-0 text-30rpx border-none;
    background: #1d6fe9;
    color: white;
    width: 590rpx;
    height: 76rpx;
    border-radius: 40rpx 40rpx 40rpx 40rpx;
    margin-top: 100rpx;
            &::after {
                @apply border-none;
            }
        }
    &::after {
      @apply border-none;
    }
  }
        .alternative {
            @apply flex justify-between mt-30rpx;
            color: $u-tips-color;
        }
    }
  .alternative {
    @apply flex justify-between mt-30rpx;
    color: $u-tips-color;
  }
}
    .login-type-wrap {
        @apply flex justify-between pt-350rpx px-150rpx pb-150rpx;
.login-type-wrap {
  @apply flex justify-between pt-350rpx px-150rpx pb-150rpx;
        .item {
            @apply flex items-center flex-col text-28rpx;
            color: $u-content-color;
        }
    }
  .item {
    @apply flex items-center flex-col text-28rpx;
    color: $u-content-color;
  }
}
    .hint {
        @apply px-40rpx py-20rpx text-24rpx;
        color: $u-tips-color;
.hint {
  @apply px-40rpx py-20rpx text-24rpx;
  color: $u-tips-color;
        .link {
            color: $u-warning;
        }
    }
  .link {
    color: $u-warning;
  }
}
</style>
src/pages/map/index copy.vue
File was deleted
src/pages/map/index.vue
@@ -2,10 +2,10 @@
 * @Author       : yuan
 * @Date         : 2025-12-03 14:20:57
 * @LastEditors  : yuan
 * @LastEditTime : 2025-12-03 14:20:57
 * @FilePath     : \src\pages\map\index copy 2.vue
 * @Description  :
 * Copyright 2025 OBKoro1, All Rights Reserved.
 * @LastEditTime : 2025-12-20 16:49:02
 * @FilePath     : \src\pages\map\index.vue
 * @Description  :
 * Copyright 2025 OBKoro1, All Rights Reserved.
 * 2025-12-03 14:20:57
-->
<template>
@@ -17,7 +17,7 @@
<script setup>
import { getWebViewUrl } from "@/utils/index.js";
import WebViewPlus from "@/components/WebViewPlus.vue";
import { onHide } from "@dcloudio/uni-app";
import { onHide, onShow } from "@dcloudio/uni-app";
// const viewUrl = getWebViewUrl("/defaultMap");
let envParam = "";
@@ -37,6 +37,17 @@
});
const onPostMessage = (data) => {
  // #ifdef MP-WEIXIN
  if (data.type === "scanCode") {
  } else if (data.type === "jumpAddWork") {
  } else if (data.type === "jumpMapNav") {
    //事件导航
  } else if (data.type === "workid") {
    //事件详情
  }
  // #endif
  // #ifndef MP-WEIXIN
  if (data.type === "scanCode") {
    uni.navigateTo({
      url: "/subPackages/qrCode/index",
@@ -45,7 +56,7 @@
    //新建任务
    const encodedData = encodeURIComponent(JSON.stringify(data.rowItem));
    uni.setStorageSync("webview_params", encodedData);
    uni.switchTab({
    uni.navigateTo({
      url: `/subPackages/taskDetail/addTask/index`,
    });
  } else if (data.type === "jumpMapNav") {
@@ -59,9 +70,11 @@
      url: `/subPackages/workDetail/index?eventNum=${data.eventNum}`,
    });
  }
  // #endif
};
onShow(() => {
  // #ifndef MP-WEIXIN
  uni.setTabBarItem({
    index: 2, // Tab 的索引(从0开始)
    visible: false,
@@ -71,6 +84,7 @@
    index: 3, // Tab
    visible: true,
  });
  // #endif
});
onHide(() => {
src/pages/placeholder/placeholder.vue
New file
@@ -0,0 +1,11 @@
<!-- 登录页 -->
<template>
  <view>占位页</view>
</template>
<script setup>
</script>
<style lang="scss" scoped>
</style>
src/pages/user/index.vue
@@ -1,231 +1,228 @@
<!-- 我的 -->
<template>
  <view class="page-wrap">
  <view class="userBox">
      <view class="flex items-center pb-30rpx pl-30rpx pr-20rpx">
        <view class="mr-20rpx">
          <u-avatar :src="user.avatar" size="70" />
        </view>
        <view class="flex-1">
          <view class="userName">{{ userStore?.userInfo?.nick_name }}</view>
          <view class="departs">
            <image src="@/static/images/user/mobile.svg" alt="" />
            <span>{{user.deptName}}</span>
          </view>
        </view>
        <view class="rightLogo">
          <image src="@/static/images/user/logo2.png" alt="" />
        </view>
      </view>
      <view class="personalInformation">
        <div class="message">
          <div class="messagebox">个人信息</div>
          <div class="editInfo" @click="handelEdit(1)">点击编辑
            <image src="@/static/images/user/rightBtn.svg" alt="" />
          </div>
        </div>
        <div class="passwordBox">
          <div class="messagebox">修改密码</div>
          <div class="editInfo" @click="handelEdit(2)">点击编辑 <image src="@/static/images/user/rightBtn.svg" alt="" />
          </div>
        </div>
      </view>
    <view class="userBox">
      <view class="flex items-center pb-30rpx pl-30rpx pr-20rpx">
        <view class="mr-20rpx">
          <u-avatar :src="user.avatar" size="70" />
        </view>
        <view class="flex-1">
          <view class="userName">{{ userStore?.userInfo?.nick_name }}</view>
          <view class="departs">
            <image
              src="https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/images/user/mobile.svg"
              alt=""
            />
            <span>{{ user.deptName }}</span>
          </view>
        </view>
        <view class="rightLogo">
          <image
            src="https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/images/user/logo2.png"
            alt=""
          />
        </view>
      </view>
      <view class="personalInformation">
        <div class="message">
          <div class="messagebox">个人信息</div>
          <div class="editInfo" @click="handelEdit(1)">
            点击编辑
            <image :src="rightImage" alt="" />
          </div>
        </div>
        <div class="passwordBox">
          <div class="messagebox">修改密码</div>
          <div class="editInfo" @click="handelEdit(2)">
            点击编辑
            <image :src="rightImage" alt="" />
          </div>
        </div>
      </view>
      <view class="mt-20rpx">
        <div class="goOutStyle" @click="logOut">退出登录</div>
      </view>
      <div class="bottomLogo"><image src="@/static/images/user/logo1.png" alt="" /></div>
  </view>
      <view class="mt-20rpx">
        <div class="goOutStyle" @click="logOut">退出登录</div>
      </view>
      <div class="bottomLogo">
        <image :src="logoImage" alt="" />
      </div>
    </view>
  </view>
</template>
<script setup>
  import {
    getUserInfo,
import { getAssetsImage } from "@/utils/index.js";
import { getUserInfo } from "@/api/user/index.js";
import { useClipboard } from "@/hooks";
import { useUserStore } from "@/store/index.js";
import { onShow } from "@dcloudio/uni-app";
import { getDeviceRegionApi } from "@/api/map.js";
  } from '@/api/user/index.js';
  import {
    useClipboard
  } from "@/hooks";
  import {
    useUserStore
  } from "@/store/index.js";
  import {
    onShow
  } from "@dcloudio/uni-app";
  import {
    getDeviceRegionApi
  } from "@/api/map.js";
const { setClipboardData, getClipboardData } = useClipboard();
  const {
    setClipboardData,
    getClipboardData
  } = useClipboard();
  const userStore = useUserStore();
  const user = ref('')
  const getUserInfoData = () => {
    getUserInfo().then(res => {
      user.value = res.data.data;
    });
  };
const rightImage = getAssetsImage("/images/user/rightBtn.svg");
const logoImage = getAssetsImage("/images/user/logo1.png");
  function logOut() {
    userStore.setUserInfo(null)
    uni.reLaunch({
      url: '/pages/login/index'
    })
  }
  function getDeviceRegion() {
    getDeviceRegionApi().then(res => {
    })
  }
  const handelEdit = (val) => {
    if (val === 1) {
      uni.navigateTo({
        url: `/subPackages/userDetail/infos/index`
      });
    } else {
      uni.navigateTo({
        url: `/subPackages/userDetail/password/index`
      });
    }
  }
  // 登录鉴权,微信小程序端点击tabbar的底层逻辑不触发uni.switchTab,需要在页面onShow生命周期中校验权限
  onShow(async () => {
    getDeviceRegion()
    getUserInfoData()
    uni.setTabBarItem({
      index: 2, // Tab 的索引(从0开始)
      visible: false,
    })
    uni.setTabBarItem({
      index: 3, // Tab
      visible: true,
    });
const userStore = useUserStore();
const user = ref("");
const getUserInfoData = () => {
  getUserInfo().then((res) => {
    user.value = res.data.data;
  });
};
function logOut() {
  userStore.setUserInfo(null);
  uni.reLaunch({
    url: "/pages/login/index",
  });
}
function getDeviceRegion() {
  getDeviceRegionApi().then((res) => {});
}
const handelEdit = (val) => {
  if (val === 1) {
    uni.navigateTo({
      url: `/subPackages/userDetail/infos/index`,
    });
  } else {
    uni.navigateTo({
      url: `/subPackages/userDetail/password/index`,
    });
  }
};
onShow(() => {
  getUserInfoData();
  // #ifndef MP-WEIXIN
  uni.setTabBarItem({
    index: 2, // Tab 的索引(从0开始)
    visible: false,
  });
  uni.setTabBarItem({
    index: 3, // Tab
    visible: true,
  });
  // #endif
});
</script>
<style scoped lang="scss">
  .page-wrap {
    width: 100%;
    height: 100%;
  }
.userBox {
     padding-top: 88rpx;
.page-wrap {
  width: 100%;
  height: 100%;
}
  .userName {
    font-weight: 700;
    font-size: 36rpx;
    color: #000000;
.userBox {
  padding-top: 88rpx;
}
.userName {
  font-weight: 700;
  font-size: 36rpx;
  color: #000000;
}
.departs {
  display: flex;
  align-items: center;
  margin-top: 22rpx;
  image {
    width: 28rpx;
    height: 28rpx;
  }
  .departs {
    display: flex;
    align-items: center;
    margin-top: 22rpx;
    image {
      width: 28rpx;
      height: 28rpx;
    }
    span {
      font-family: "Source Han Sans CN";
      font-weight: 400;
      font-size: 28rpx;
      color: rgba(0, 0, 0, 0.6);
      margin-left: 6rpx;
    }
  }
  .rightLogo {
    width: 200rpx;
    height: 80rpx;
    image {
      width: 100%;
      height: 100%;
    }
  }
  .bottomLogo {
    position: absolute;
    bottom: 50rpx;
    left: 0;
    right: 0;
    margin: 0 auto;
    text-align: center;
    image {
      width: 128rpx;
      height: 52rpx;
    }
  }
  .goOutStyle {
    width: 590rpx;
    height: 76rpx;
    background: #1D6FE9;
    border-radius: 40rpx;
  span {
    font-family: "Source Han Sans CN";
    font-weight: 400;
    font-size: 28rpx;
    color: #FFFFFF;
    text-align: center;
    line-height: 76rpx;
    margin: auto;
    margin-top: 114rpx;
    color: rgba(0, 0, 0, 0.6);
    margin-left: 6rpx;
  }
}
  .personalInformation {
    display: flex;
    justify-content: space-between;
    padding: 0 24rpx;
.rightLogo {
  width: 200rpx;
  height: 80rpx;
    .message,
    .passwordBox {
      width: 340rpx;
      height: 160rpx;
  image {
    width: 100%;
    height: 100%;
  }
}
      .messagebox {
        padding: 20rpx 24rpx;
        font-family: "Source Han Sans CN";
        font-weight: 500;
        font-size: 28rpx;
        color: #000000;
      }
.bottomLogo {
  position: absolute;
  bottom: 50rpx;
  left: 0;
  right: 0;
  margin: 0 auto;
  text-align: center;
      .editInfo {
        padding: 20rpx 24rpx;
        color: rgba(0, 0, 0, 0.5);
        font-family: "Source Han Sans CN";
        font-weight: 400;
        font-size: 24rpx;
        display: flex;
        align-items: center;
  image {
    width: 128rpx;
    height: 52rpx;
  }
}
        image {
          width: 28rpx;
          height: 28rpx;
        }
.goOutStyle {
  width: 590rpx;
  height: 76rpx;
  background: #1d6fe9;
  border-radius: 40rpx;
  font-family: "Source Han Sans CN";
  font-weight: 400;
  font-size: 28rpx;
  color: #ffffff;
  text-align: center;
  line-height: 76rpx;
  margin: auto;
  margin-top: 114rpx;
}
.personalInformation {
  display: flex;
  justify-content: space-between;
  padding: 0 24rpx;
  .message,
  .passwordBox {
    width: 340rpx;
    height: 160rpx;
    .messagebox {
      padding: 20rpx 24rpx;
      font-family: "Source Han Sans CN";
      font-weight: 500;
      font-size: 28rpx;
      color: #000000;
    }
    .editInfo {
      padding: 20rpx 24rpx;
      color: rgba(0, 0, 0, 0.5);
      font-family: "Source Han Sans CN";
      font-weight: 400;
      font-size: 24rpx;
      display: flex;
      align-items: center;
      image {
        width: 28rpx;
        height: 28rpx;
      }
    }
    .message {
      background: url(@/static/images/user/info.png) no-repeat center;
      background-size: 100% 100%;
    }
    .passwordBox {
      background: url(@/static/images/user/password.png) no-repeat center;
      background-size: 100% 100%;
    }
  }
  .message {
    background: url(https://wrj.shuixiongit.com/drone-app/assets/static/images/user/info.png)
      no-repeat center;
    background-size: 100% 100%;
  }
  .passwordBox {
    background: url(https://wrj.shuixiongit.com/drone-app/assets/static/images/user/password.png)
      no-repeat center;
    background-size: 100% 100%;
  }
}
</style>
src/pages/work/index.vue
@@ -1,76 +1,102 @@
<!--
 * @Author       : yuan
 * @Date         : 2025-12-18 10:06:30
 * @LastEditors  : yuan
 * @LastEditTime : 2025-12-20 14:18:42
 * @FilePath     : \src\pages\work\index.vue
 * @Description  :
 * Copyright 2025 OBKoro1, All Rights Reserved.
 * 2025-12-18 10:06:30
-->
<template>
    <view class="eventTickets">
        <WebViewPlus ref="sWebViewRef" :src="`${viewUrl}`" @webMessage="onPostMessage" />
    </view>
  <view class="eventTickets">
    <WebViewPlus
      ref="sWebViewRef"
      :src="`${viewUrl}`"
      @webMessage="onPostMessage"
    />
  </view>
</template>
<script setup>
    import {
        getWebViewUrl
    } from "@/utils/index.js";
    import WebViewPlus from "@/components/WebViewPlus.vue";
    import {
        useTabAddButton
    } from "@/hooks/index.js";
    const sWebViewRef = ref(null);
    // const viewUrl = getWebViewUrl('/work', {})
    const updateKey = ref(0)
    const viewUrl = computed(() => {
        return getWebViewUrl('/work', {
            updateKey: updateKey.value
        })
    })
import { getWebViewUrl } from "@/utils/index.js";
import WebViewPlus from "@/components/WebViewPlus.vue";
import { useTabAddButton } from "@/hooks/index.js";
import { onShow, onHide } from "@dcloudio/uni-app";
    function onPostMessage(data) {
        if (data.type === 'jumpMapNav') {
            uni.navigateTo({
                url: `/subPackages/workDetail/mapWork/index?currentItem=${data.eventNum}`
            });
const sWebViewRef = ref(null);
// const viewUrl = getWebViewUrl('/work', {})
const updateKey = ref(0);
const viewUrl = computed(() => {
  // #ifdef MP-WEIXIN
  return getWebViewUrl("/work", {
    updateKey: updateKey.value,
    showAddBtn: 1,
  });
  // #endif
        } else if (data.type === 'workid') {
            uni.navigateTo({
                url: `/subPackages/workDetail/index?eventNum=${data.eventNum}&totalNum=${data.totalNum}&keyword=${data.keyword}&aiType=${data.aiType}&status=${data.status}`
            });
        } else if (data.type === 'bigImage') {
            uni.navigateTo({
                url: `/subPackages/workDetail/photoMagnify/index?eventNum=${data.eventNum}`
            });
  // #ifndef MP-WEIXIN
  return getWebViewUrl("/work", {
    updateKey: updateKey.value,
    showAddBtn: 0,
  });
  // #endif
});
        }
function onPostMessage(data) {
  // #ifdef MP-WEIXIN
  if (data.type === "addWork") {
  }
  // #endif
    }
    const isApp = ref(false)
    onShow(() => {
        const joinParams = uni.getStorageSync('joinParams');
        if (joinParams) {
            updateKey.value = updateKey.value + 1
            uni.removeStorageSync('joinParams');
        }
        uni.setTabBarItem({
            index: 2, // Tab 的索引(从0开始)
            // text: '新建工单',
            visible: true,
            "pagePath": "subPackages/workDetail/addWork/index"
        });
        uni.setTabBarItem({
            index: 3, // Tab
            visible: false,
        });
        // isApp.value = true
    });
  // #ifndef MP-WEIXIN
  if (data.type === "jumpMapNav") {
    uni.navigateTo({
      url: `/subPackages/workDetail/mapWork/index?currentItem=${data.eventNum}`,
    });
  } else if (data.type === "workid") {
    uni.navigateTo({
      url: `/subPackages/workDetail/index?eventNum=${data.eventNum}&totalNum=${data.totalNum}&keyword=${data.keyword}&aiType=${data.aiType}&status=${data.status}`,
    });
  } else if (data.type === "bigImage") {
    uni.navigateTo({
      url: `/subPackages/workDetail/photoMagnify/index?eventNum=${data.eventNum}`,
    });
  }
  // #endif
}
const isApp = ref(false);
onShow(() => {
  const joinParams = uni.getStorageSync("joinParams");
  if (joinParams) {
    updateKey.value = updateKey.value + 1;
    uni.removeStorageSync("joinParams");
  }
    onHide(() => {
        // isApp.value = false
    });
  // #ifndef MP-WEIXIN
  uni.setTabBarItem({
    index: 2, // Tab 的索引(从0开始)
    // text: '新建工单',
    visible: true,
    pagePath: "subPackages/workDetail/addWork/index",
  });
  uni.setTabBarItem({
    index: 3, // Tab
    visible: false,
  });
  // #endif
  // isApp.value = true
});
onHide(() => {
  // isApp.value = false
});
</script>
<style scoped lang="scss">
    .eventTickets {
        width: 100%;
        height: 100%;
    }
</style>
.eventTickets {
  width: 100%;
  height: 100%;
}
</style>
src/static/fonts/font.css
@@ -1,6 +1,7 @@
@font-face {
  font-family: "Source Han Sans CN";
  src: url("SourceHanSansCN-Regular.woff2") format("opentype");
  src: url("https://wrj.shuixiongit.com/drone-app/assets/static/fonts/SourceHanSansCN-Regular.woff2")
    format("opentype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
@@ -8,35 +9,36 @@
@font-face {
  font-family: "Source Han Sans CN";
  src: url("SourceHanSansCN-Bold.woff2") format("opentype") ;
  src: url("https://wrj.shuixiongit.com/drone-app/assets/static/fonts/SourceHanSansCN-Bold.woff2")
    format("opentype");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Segoe UI";
  src: url("SourceHanSansCN-Regular.woff2") format("opentype");
  src: url("https://wrj.shuixiongit.com/drone-app/assets/static/fonts/SourceHanSansCN-Regular.woff2")
    format("opentype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Segoe UI";
  src: url("SourceHanSansCN-Bold.woff2") format("opentype") ;
  src: url("https://wrj.shuixiongit.com/drone-app/assets/static/fonts/SourceHanSansCN-Bold.woff2")
    format("opentype");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
/* 额外的标题字体 */
@font-face {
  font-family: "YouSheBiaoTiHei";
  src: url("YouSheBiaoTiHei.TTF") format("truetype");
  src: url("https://wrj.shuixiongit.com/drone-app/assets/static/fonts/YouSheBiaoTiHei.TTF")
    format("truetype");
  font-weight: normal;
  font-style: normal;
  font-display: swap;
src/static/images/login/droneSvg.svg
File was deleted
src/static/images/login/logo.svg
File was deleted
src/static/images/login/password.svg
File was deleted
src/static/images/login/username.svg
File was deleted
src/static/images/user/allBg.svg
File was deleted
src/static/images/user/bg.png
Binary files differ
src/static/images/user/info.png
Binary files differ
src/static/images/user/info.svg
File was deleted
src/static/images/user/logo1.png
Binary files differ
src/static/images/user/logo1.svg
File was deleted
src/static/images/user/logo2.png
Binary files differ
src/static/images/user/logo2.svg
File was deleted
src/static/images/user/mobile.svg
File was deleted
src/static/images/user/password.png
Binary files differ
src/static/images/user/password.svg
File was deleted
src/static/images/user/rightBtn.svg
File was deleted
src/static/images/user/userBg.svg
File was deleted
src/subPackages/404/index.vue
@@ -2,8 +2,8 @@
 * @Author       : yuan
 * @Date         : 2025-09-28 09:31:16
 * @LastEditors  : yuan
 * @LastEditTime : 2025-09-28 09:50:32
 * @FilePath     : \src\pages\common\404\index.vue
 * @LastEditTime : 2025-12-16 11:02:27
 * @FilePath     : \src\subPackages\404\index.vue
 * @Description  : 
 * Copyright 2025 OBKoro1, All Rights Reserved. 
 * 2025-09-28 09:31:16
@@ -15,7 +15,7 @@
      mode="page"
      text-size="20"
      text="页面不存在"
      icon="/static/images/404.png"
      :icon="errorImage"
      width="380"
      height="380"
    />
@@ -23,8 +23,11 @@
</template>
<script setup>
import { getAssetsImage } from "@/utils/index.js";
import { HOME_PATH } from "@/router";
const errorImage = getAssetsImage("/404.png");
function handleBack() {
  uni.$u.route({
    type: "switchTab",
src/subPackages/inProgress/index.vue
File was deleted
src/subPackages/qrCode/index.vue
@@ -1,3 +1,13 @@
<!--
 * @Author       : yuan
 * @Date         : 2025-10-14 17:43:52
 * @LastEditors  : yuan
 * @LastEditTime : 2025-12-19 15:33:48
 * @FilePath     : \src\subPackages\qrCode\index.vue
 * @Description  :
 * Copyright 2025 OBKoro1, All Rights Reserved.
 * 2025-10-14 17:43:52
-->
<template>
  <view class="page-wrap">
    <WebViewPlus :src="`${viewUrl}`" @webMessage="onPostMessage" />
@@ -5,26 +15,31 @@
</template>
<script setup>
  import {
    getWebViewUrl
  } from "@/utils/index.js";
  import WebViewPlus from "@/components/WebViewPlus.vue";
import { getWebViewUrl } from "@/utils/index.js";
import WebViewPlus from "@/components/WebViewPlus.vue";
  const viewUrl = getWebViewUrl("/QrCodeScanner");
const viewUrl = getWebViewUrl("/QrCodeScanner");
  const onPostMessage = (data) => {
    if (data.type === 'browser') {
      uni.navigateTo({
        url: '/subPackages/browser/index?url=' + encodeURIComponent(data.data.url)
      });
    }
  };
const onPostMessage = (data) => {
  if (data.type === "browser") {
    // #ifdef MP-WEIXIN
  onLoad(() => {});
    // #endif
    // #ifndef MP-WEIXIN
    uni.navigateTo({
      url:
        "/subPackages/browser/index?url=" + encodeURIComponent(data.data.url),
    });
    // #endif
  }
};
onLoad(() => {});
</script>
<style lang="scss" scoped>
  .page-wrap {
    font-size: 20px;
  }
.page-wrap {
  font-size: 20px;
}
</style>
src/subPackages/taskDetail/addTask/index.vue
@@ -1,27 +1,38 @@
<!-- 新建任务 -->
<template>
  <WebViewPlus v-if="isApp" :src="`${viewUrl}`" @webMessage="onPostMessage"/>
  <WebViewPlus v-if="isApp" :src="`${viewUrl}`" @webMessage="onPostMessage" />
</template>
<script setup>
import WebViewPlus from "@/components/WebViewPlus.vue";
import {getWebViewUrl} from "@/utils/index.js";
import {onHide, onLoad, onShow} from "@dcloudio/uni-app";
import { getWebViewUrl } from "@/utils/index.js";
import { onHide, onLoad, onShow } from "@dcloudio/uni-app";
// const viewUrl = ref(getWebViewUrl('/addTask'))
const sWebViewRef = ref(null);
const viewUrl = ref('')
const viewUrl = ref("");
function onPostMessage(data) {
  if (data.type === 'submitSuccess'){
    uni.setStorageSync('joinParams', {
      type: 'add'
  if (data.type === "submitSuccess") {
    // #ifdef MP-WEIXIN
    if ("fun" in data && data.fun === "add") {
      uni.setStorageSync("joinParams", {
        type: "add",
      });
    }
    // #endif
    // #ifndef MP-WEIXIN
    uni.setStorageSync("joinParams", {
      type: "add",
    });
    // console.log('打印新增成功')
    uni.switchTab({
      url: '/pages/inspectionTask/index'
      url: "/pages/inspectionTask/index",
    });
    // #endif
    // uni.redirectTo({
    //   url: `/pages/inspectionTask/index?addLog=1111`
    // });
@@ -33,28 +44,41 @@
//   const sns = options.device_sn
//
// });
const isApp = ref(false);
const isApp = ref(false)
onShow(() => {
  isApp.value = true
  let params = {}
  const encodedData = uni.getStorageSync('webview_params')
  params = JSON.parse(decodeURIComponent(encodedData))
  viewUrl.value = getWebViewUrl('/addTask', params)
  uni.setTabBarItem({
    index: 3, // Tab
    visible: false,
  });
  uni.setTabBarItem({
    index: 2, // Tab 的索引(从0开始)
    // text: '新建任务',
    visible: true,
    "pagePath": "subPackages/taskDetail/addTask/index"
  });
// #ifdef MP-WEIXIN
onLoad((options) => {
  isApp.value = true;
  let params = {};
  if ("data" in options) {
    try {
      params = JSON.parse(options.data);
    } catch (e) {
      console.error(e);
    }
  }
  viewUrl.value = getWebViewUrl("/addTask", params);
});
// #endif
// #ifndef MP-WEIXIN
onShow(() => {
  isApp.value = true;
  let params = {};
  const encodedData = uni.getStorageSync("webview_params");
  if (encodedData) {
    try {
      params = JSON.parse(decodeURIComponent(encodedData));
    } catch (e) {
      console.error(e);
    }
  }
  viewUrl.value = getWebViewUrl("/addTask", params);
});
// #endif
onHide(() => {
  isApp.value = false
  isApp.value = false;
});
</script>
src/subPackages/taskDetail/inExecution/index.vue
File was deleted
src/subPackages/taskDetail/inProgress/index.vue
New file
@@ -0,0 +1,61 @@
<template>
  <WebViewPlus
    v-if="showComponent"
    :src="`${viewUrl}`"
    @webMessage="onPostMessage"
  />
</template>
<script setup>
import WebViewPlus from "@/components/WebViewPlus.vue";
import { getWebViewUrl } from "@/utils/index.js";
import { onHide, onLoad, onShow } from "@dcloudio/uni-app";
const wayLineJobInfoId = ref(null);
const batchNo = ref(null)
const viewUrl = ref("");
const showComponent = ref(false);
function onPostMessage(data) {
  // #ifdef MP-WEIXIN
  // #endif
  // #ifndef MP-WEIXIN
  if (data.type === "back") {
    uni.switchTab({
      url: "/pages/inspectionTask/index",
    });
  } else if (data.type === "control") {
    uni.navigateTo({
      url: `/subPackages/droneConsole/index?wayLineJobInfoId=${wayLineJobInfoId.value}&dockSn=${data.dockSn}&batchNo=${batchNo.value}`,
    });
  }
  // #endif
}
onLoad((queryParams) => {
  wayLineJobInfoId.value = queryParams.wayLineJobInfoId;
  batchNo.value = queryParams.batchNo
  viewUrl.value = getWebViewUrl("/TaskInProgress", {
    wayLineJobInfoId: wayLineJobInfoId.value,
    batchNo: batchNo.value,
  });
});
onShow(function () {
  showComponent.value = true;
  // #ifdef APP-PLUS
  plus.navigator.setFullscreen(false);
  plus.screen.lockOrientation("portrait-primary");
  // #endif
});
onHide(() => {
  showComponent.value = false;
});
</script>
<style scoped lang="scss">
.page-wrap {
  font-size: 20px;
}
</style>
src/subPackages/taskDetail/index.vue
File was deleted
src/subPackages/userDetail/infos/index.vue
@@ -292,12 +292,16 @@
        bottom: 150rpx;
    }
    .u-button:first-child {
        margin-right: 30rpx;
    :deep(.u-button:first-child) {
        margin-right: 30rpx !important;
    }
    .custom-style {
        width: 276rpx;
        height: 76rpx;
    }
    :deep(.u-button.data-v-461e713c){
        width: 276rpx !important;
        height: 76rpx !important;
    }
</style>
src/subPackages/userDetail/password/index.vue
@@ -225,12 +225,16 @@
        bottom: 150rpx;
    }
    .u-button:first-child {
        margin-right: 30rpx;
    :deep(.u-button:first-child) {
        margin-right: 30rpx !important;
    }
    .custom-style {
        width: 276rpx;
        height: 76rpx;
    }
    :deep(.u-button.data-v-461e713c){
        width: 276rpx !important;
        height: 76rpx !important;
    }
</style>
src/subPackages/workDetail/addWork/index.vue
@@ -1,34 +1,52 @@
<!--
 * @Author       : yuan
 * @Date         : 2025-11-13 18:14:52
 * @LastEditors  : yuan
 * @LastEditTime : 2025-12-20 16:56:27
 * @FilePath     : \src\subPackages\workDetail\addWork\index.vue
 * @Description  :
 * Copyright 2025 OBKoro1, All Rights Reserved.
 * 2025-11-13 18:14:52
-->
<template>
    <view>
        <WebViewPlus @webMessage="onPostMessage" ref="sWebViewRef" :src="`${viewUrl}`" />
    </view>
  <view>
    <WebViewPlus
      @webMessage="onPostMessage"
      ref="sWebViewRef"
      :src="`${viewUrl}`"
    />
  </view>
</template>
<script setup>
    import {
        getWebViewUrl
    } from "@/utils/index.js";
    import WebViewPlus from "@/components/WebViewPlus.vue";
    const sWebViewRef = ref(null);
    const viewUrl = getWebViewUrl('/addWork')
import { getWebViewUrl } from "@/utils/index.js";
import WebViewPlus from "@/components/WebViewPlus.vue";
const sWebViewRef = ref(null);
const viewUrl = getWebViewUrl("/addWork");
    function onPostMessage(data) {
        if (data.type === 'submitSuccess') {
            uni.setStorageSync('joinParams', {
                type: 'add'
            });
            // uni.switchTab({
            //   url: '/pages/work/index'
            // });
            uni.switchTab({
                url: `/pages/work/index?addLog=111`
            });
        }
    }
function onPostMessage(data) {
  if (data.type === "submitSuccess") {
    // #ifdef MP-WEIXIN
    if ("fun" in data && data.fun === "add") {
      uni.setStorageSync("joinParams", {
        type: "add",
      });
    }
    // #endif
    // #ifndef MP-WEIXIN
    uni.setStorageSync("joinParams", {
      type: "add",
    });
    // uni.switchTab({
    //   url: '/pages/work/index'
    // });
    uni.switchTab({
      url: `/pages/work/index?addLog=111`,
    });
    // #endif
  }
}
</script>
<style scoped lang="scss">
</style>
<style scoped lang="scss"></style>
src/subPackages/workDetail/index.vue
@@ -1,48 +1,67 @@
<!-- 工单详情 - 包含待审核、待处理、处理中、已完成 -->
<template>
    <div class="workDetailContainer">
         <WebViewPlus ref="sWebViewRef" :src="`${viewUrl}`" @webMessage="onPostMessage"/>
    </div>
  <div class="workDetailContainer">
    <WebViewPlus
      ref="sWebViewRef"
      :src="`${viewUrl}`"
      @webMessage="onPostMessage"
    />
  </div>
</template>
<script setup>
        import {getWebViewUrl} from "@/utils/index.js";
    import { onLoad } from '@dcloudio/uni-app';
    import { useUserStore } from '@/store/index.js'
    const userStore = useUserStore()
    const userInfo = userStore.userInfo
    const sWebViewRef = ref(null);
    const viewUrl = ref('')
    onLoad( (options) => {
        const eventNum= options.eventNum;
        viewUrl.value = getWebViewUrl('/workDetail', {eventNum:eventNum,totalNum:options.totalNum,keyword:options.keyword,aiType:options.aiType,wLJobInfoId:options.wLJobInfoId,status:options.status})
    });
import { getWebViewUrl } from "@/utils/index.js";
import { onLoad } from "@dcloudio/uni-app";
import { useUserStore } from "@/store/index.js";
const userStore = useUserStore();
const userInfo = userStore.userInfo;
const sWebViewRef = ref(null);
const viewUrl = ref("");
onLoad((options) => {
  const eventNum = options.eventNum;
  viewUrl.value = getWebViewUrl("/workDetail", {
    eventNum: eventNum,
    totalNum: options.totalNum,
    keyword: options.keyword,
    aiType: options.aiType,
    wLJobInfoId: options.wLJobInfoId,
    status: options.status,
  });
});
    function onPostMessage(data) {
function onPostMessage(data) {
  if (data.type === "workback") {
    // #ifdef MP-WEIXIN
    if ("fun" in data && data.fun === "add") {
      uni.setStorageSync("joinParams", {
        type: "add",
      });
    }
    // #endif
      if (data.type === 'workback'){
      uni.setStorageSync('joinParams', {
                type: 'add'
            });
        uni.switchTab({
            url: `/pages/work/index?addLog=111`
          // url: '/pages/work/index'
        });
      }else if(data.type === 'jumpMapNav'){
           uni.navigateTo({
            url:`/subPackages/workDetail/mapWork/index?currentItem=${data.eventNum}`
          });
      }
    }
    // #ifndef MP-WEIXIN
    uni.setStorageSync("joinParams", {
      type: "add",
    });
    uni.switchTab({
      url: `/pages/work/index?addLog=111`,
      // url: '/pages/work/index'
    });
    // #endif
  } else if (data.type === "jumpMapNav") {
    // #ifndef MP-WEIXIN
    uni.navigateTo({
      url: `/subPackages/workDetail/mapWork/index?currentItem=${data.eventNum}`,
    });
    // #endif
  }
}
</script>
<style lang="scss" scoped>
    .workDetailContainer {
.workDetailContainer {
  width: 100%;
    height: 100%;
    background-size: cover;
    }
  height: 100%;
  background-size: cover;
}
</style>
src/subPackages/workDetail/mapWork/index.vue
@@ -2,7 +2,7 @@
 * @Author       : yuan
 * @Date         : 2025-10-22 14:59:10
 * @LastEditors  : yuan
 * @LastEditTime : 2025-10-22 19:41:27
 * @LastEditTime : 2025-12-19 14:52:54
 * @FilePath     : \src\subPackages\workDetail\mapWork\index.vue
 * @Description  : 
 * Copyright 2025 OBKoro1, All Rights Reserved. 
@@ -29,6 +29,10 @@
  viewUrl.value = getWebViewUrl("/mapWork", { currentItem: currentItem });
});
function onPostMessage(data) {
  // #ifdef MP-WEIXIN
  // #endif
  // #ifndef MP-WEIXIN
  if (data.type === "workDetailback") {
    // uni.navigateTo({
    //   url: '/subPackages/workDetail/index'
@@ -44,6 +48,7 @@
        "/subPackages/browser/index?url=" + encodeURIComponent(data.data.url),
    });
  }
  // #endif
}
</script>
src/utils/common/index.js
@@ -2,7 +2,7 @@
 * @Author       : yuan
 * @Date         : 2025-10-15 15:52:12
 * @LastEditors  : yuan
 * @LastEditTime : 2025-10-16 17:57:16
 * @LastEditTime : 2025-12-17 14:09:14
 * @FilePath     : \src\utils\common\index.js
 * @Description  :
 * Copyright 2025 OBKoro1, All Rights Reserved.
@@ -10,8 +10,8 @@
 */
// 小程序更新检测
import { useUserStore } from "@/store/index.js"
import configEnv from "@/config/env.js";
import process from "node:process";
import configEnv from "@/config/env.js"
import process from "node:process"
export function mpUpdate () {
  const updateManager = uni.getUpdateManager()
@@ -40,26 +40,39 @@
    })
  })
}
export function getStatusBarHeight() {
export function getStatusBarHeight () {
  try {
    const systemInfo = uni.getSystemInfoSync();
    return systemInfo.statusBarHeight || 0;
    const systemInfo = uni.getWindowInfo()
    // #ifdef APP-PLUS
    return systemInfo.statusBarHeight || 0
    // #endif
    // #ifdef MP-WEIXIN
    return 0
    // #endif
    // #ifdef H5
    return systemInfo.statusBarHeight || 0
    // #endif
    return systemInfo.statusBarHeight || 0
  } catch (error) {
    return 0;
    return 0
  }
}
export function getEnvObj() {
export function getEnvObj () {
  return configEnv[__APP_ENV__?.ENV_NAME] || {}
}
export function getWebViewUrl (targetUrl, otherParams) {
  const userStore = useUserStore()
  const url = getEnvObj().VITE_APP_WEBVIEW_URL
  const uniPlatform = __APP_ENV__.UNI_PLATFORM
  const statusBarHeight = getStatusBarHeight();
  const statusBarHeight = getStatusBarHeight()
  // 1. 处理用户参数
  const userParams = userStore?.userInfo ? JSON.stringify(userStore.userInfo) : '{}'
  // 2. 构建查询参数字符串
let queryString = `params=${encodeURIComponent(userParams)}&topMargin=${statusBarHeight}&uniPlatform=${uniPlatform}`
  let queryString = `params=${encodeURIComponent(userParams)}&topMargin=${statusBarHeight}&uniPlatform=${uniPlatform}`
  // 3. 处理 otherParams 对象
  if (otherParams && typeof otherParams === 'object') {
@@ -73,3 +86,8 @@
  // 4. 拼接完整 URL
  return `${url}${targetUrl}?${queryString}`
}
export function getAssetsImage (targetUrl) {
  const url = getEnvObj().VITE_APP_ASSETS_URL
  return `${url}${targetUrl}`
}