Merge remote-tracking branch 'origin/master'
17 files modified
5 files added
1 files deleted
| | |
| | | function messageFun(e) { |
| | | if (e.data.type === "WEB_INVOKE_APPSERVICE") { |
| | | if (e.data.data.arg.type === "tokenExpired") { |
| | | return uni.redirectTo({ |
| | | return uni.reLaunch({ |
| | | url: "/pages/login/index", |
| | | }); |
| | | } |
| | |
| | | "dSYMs" : false |
| | | }, |
| | | /* SDK配置 */ |
| | | "sdkConfigs" : {} |
| | | "sdkConfigs" : {}, |
| | | "icons" : { |
| | | "android" : { |
| | | "hdpi" : "src/static/images/app-logo.png", |
| | | "xhdpi" : "src/static/images/app-logo.png", |
| | | "xxhdpi" : "src/static/images/app-logo.png", |
| | | "xxxhdpi" : "src/static/images/app-logo.png" |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | /* 快应用特有相关 */ |
| | |
| | | "backgroundColor": "#ffffff", |
| | | "list": [ |
| | | { |
| | | "iconPath": "static/images/tabbar/icon_home.svg", |
| | | "selectedIconPath": "static/images/tabbar/icon_home_selected.svg", |
| | | "iconPath": "static/images/tabbar/icon_home1.png", |
| | | "selectedIconPath": "static/images/tabbar/icon_home_selected.png", |
| | | "pagePath": "pages/map/index", |
| | | "text": "地图" |
| | | }, |
| | | { |
| | | "iconPath": "static/images/tabbar/icon_list.svg", |
| | | "selectedIconPath": "static/images/tabbar/icon_list_selected.svg", |
| | | "iconPath": "static/images/tabbar/icon_list.png", |
| | | "selectedIconPath": "static/images/tabbar/icon_list_selected.png", |
| | | "pagePath": "pages/inspectionTask/index", |
| | | "text": "任务" |
| | | }, |
| | |
| | | "visible": "true" |
| | | }, |
| | | { |
| | | "iconPath": "static/images/tabbar/icon_order.svg", |
| | | "selectedIconPath": "static/images/tabbar/icon_order_selected.svg", |
| | | "iconPath": "static/images/tabbar/icon_order.png", |
| | | "selectedIconPath": "static/images/tabbar/icon_order_selected.png", |
| | | "pagePath": "pages/work/index", |
| | | "text": "工单" |
| | | }, |
| | | { |
| | | "iconPath": "static/images/tabbar/icon_me.svg", |
| | | "selectedIconPath": "static/images/tabbar/icon_me_selected.svg", |
| | | "iconPath": "static/images/tabbar/icon_me.png", |
| | | "selectedIconPath": "static/images/tabbar/icon_me_selected.png", |
| | | "pagePath": "pages/user/index", |
| | | "text": "我的" |
| | | } |
| | |
| | | onShow(() => { |
| | | isApp.value = true |
| | | // 清除数据 |
| | | const encodedData = encodeURIComponent(JSON.stringify({ device_sn: '', latitude: '25.9922904974658', longitude: '114.82299452904442' })) |
| | | const encodedData = encodeURIComponent(JSON.stringify({ device_sn: '' })) |
| | | uni.setStorageSync('webview_params', encodedData); |
| | | uni.setTabBarItem({ |
| | | index: 2, // Tab 的索引(从0开始) |
| | |
| | | <!-- 登录页 --> |
| | | <template> |
| | | <view class="login-form-wrap"> |
| | | <img class="logo" src="@/static/images/login/logo.svg" alt=""/> |
| | | <div class="title">掌控智飞</div> |
| | | <div class="user-name"> |
| | | <img :src="usernameSvg" alt=""> |
| | | <input |
| | | v-model="loginForm.username" |
| | | placeholder="请输入用户名" |
| | | /> |
| | | <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> |
| | | |
| | | </div> |
| | | <div class="pass-word"> |
| | | <img :src="passwordSvg" alt=""> |
| | | <input |
| | | v-model="loginForm.password" |
| | | type="password" |
| | | placeholder="请输入密码" |
| | | /> |
| | | </div> |
| | | |
| | | <button class="login-btn" :style="[inputStyle]" @tap="submit"> |
| | | 登录 |
| | | </button> |
| | | |
| | | <img class="lowerRightCorner" :src="droneSvg" alt=""/> |
| | | </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 {HOME_PATH, LOGIN_PATH, removeQueryString} from "@/router"; |
| | | 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'; |
| | | |
| | | const userStore = useUserStore(); |
| | | const loginForm = ref({ |
| | | username: "", |
| | | password: "", |
| | | }); |
| | | const inputStyle = computed(() => { |
| | | const style = {}; |
| | | if (loginForm.value.username && loginForm.value.password) { |
| | | style.color = "#fff"; |
| | | style.backgroundColor = '#1D6FE9'; |
| | | } |
| | | return style; |
| | | }); |
| | | let redirect = HOME_PATH; |
| | | 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; |
| | | } |
| | | |
| | | async function submit() { |
| | | let userInfo = { |
| | | tenantId: "000000", |
| | | deptId: "", |
| | | roleId: "", |
| | | username: loginForm.value.username, |
| | | password: loginForm.value.password, |
| | | type: "account", |
| | | code: "", |
| | | key: "", |
| | | }; |
| | | loginByUsername( |
| | | userInfo.tenantId, |
| | | userInfo.deptId, |
| | | userInfo.roleId, |
| | | userInfo.username, |
| | | md5(userInfo.password), |
| | | userInfo.type, |
| | | userInfo.key, |
| | | userInfo.code |
| | | ).then((res) => { |
| | | userStore.setUserInfo(res.data); |
| | | uni.reLaunch({ |
| | | url: "/pages/user/index", |
| | | }); |
| | | }); |
| | | } |
| | | async function submit() { |
| | | let userInfo = { |
| | | tenantId: "000000", |
| | | deptId: "", |
| | | roleId: "", |
| | | username: loginForm.value.username, |
| | | password: loginForm.value.password, |
| | | type: "account", |
| | | code: "", |
| | | key: "", |
| | | }; |
| | | |
| | | onLoad((options) => { |
| | | if (options.redirect && removeQueryString(options.redirect) !== LOGIN_PATH) { |
| | | redirect = decodeURIComponent(options.redirect); |
| | | } |
| | | }); |
| | | 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/user/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; |
| | | } |
| | | .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; |
| | | img { |
| | | width: 40rpx; |
| | | height: 40rpx; |
| | | margin-right: 12rpx; |
| | | } |
| | | :deep(uni-input) { |
| | | height: 40rpx; |
| | | line-height: 40rpx; |
| | | width: 80%; |
| | | margin-top: 20rpx; |
| | | } |
| | | :deep(.uni-input-placeholder) { |
| | | font-size: 32rpx; |
| | | color: #E3E3E3; |
| | | font-weight: 500; |
| | | } |
| | | //:deep(.uni-input-input) { |
| | | // top: 10px !important; |
| | | //} |
| | | } |
| | | .pass-word { |
| | | } |
| | | .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; |
| | | } |
| | | |
| | | input { |
| | | @apply pb-6rpx mb-10rpx text-left; |
| | | } |
| | | .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; |
| | | |
| | | .tips { |
| | | @apply mt-8rpx mb-60rpx; |
| | | image { |
| | | width: 40rpx; |
| | | height: 40rpx; |
| | | margin-right: 12rpx; |
| | | } |
| | | |
| | | color: $u-info; |
| | | } |
| | | :deep(uni-input) { |
| | | height: 40rpx; |
| | | line-height: 40rpx; |
| | | width: 80%; |
| | | margin-top: 20rpx; |
| | | } |
| | | |
| | | .login-btn { |
| | | @apply flex items-center justify-center py-12rpx px-0 text-30rpx border-none; |
| | | background: #5a93e6; |
| | | color: white; |
| | | width: 590rpx; |
| | | height: 76rpx; |
| | | border-radius: 40rpx 40rpx 40rpx 40rpx; |
| | | margin-top: 100rpx; |
| | | :deep(.uni-input-placeholder) { |
| | | font-size: 32rpx; |
| | | color: #E3E3E3; |
| | | font-weight: 500; |
| | | } |
| | | } |
| | | |
| | | &::after { |
| | | @apply border-none; |
| | | } |
| | | } |
| | | .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; |
| | | |
| | | label { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | } |
| | | |
| | | .alternative { |
| | | @apply flex justify-between mt-30rpx; |
| | | input { |
| | | @apply pb-6rpx mb-10rpx text-left; |
| | | } |
| | | |
| | | color: $u-tips-color; |
| | | } |
| | | } |
| | | .tips { |
| | | @apply mt-8rpx mb-60rpx; |
| | | color: $u-info; |
| | | } |
| | | |
| | | .login-type-wrap { |
| | | @apply flex justify-between pt-350rpx px-150rpx pb-150rpx; |
| | | .login-btn { |
| | | z-index: 1; |
| | | @apply flex items-center justify-center py-12rpx px-0 text-30rpx border-none; |
| | | background: #5a93e6; |
| | | color: white; |
| | | width: 590rpx; |
| | | height: 76rpx; |
| | | border-radius: 40rpx 40rpx 40rpx 40rpx; |
| | | margin-top: 100rpx; |
| | | |
| | | .item { |
| | | @apply flex items-center flex-col text-28rpx; |
| | | &::after { |
| | | @apply border-none; |
| | | } |
| | | } |
| | | |
| | | color: $u-content-color; |
| | | } |
| | | } |
| | | .alternative { |
| | | @apply flex justify-between mt-30rpx; |
| | | color: $u-tips-color; |
| | | } |
| | | } |
| | | |
| | | .hint { |
| | | @apply px-40rpx py-20rpx text-24rpx; |
| | | .login-type-wrap { |
| | | @apply flex justify-between pt-350rpx px-150rpx pb-150rpx; |
| | | |
| | | color: $u-tips-color; |
| | | .item { |
| | | @apply flex items-center flex-col text-28rpx; |
| | | color: $u-content-color; |
| | | } |
| | | } |
| | | |
| | | .link { |
| | | color: $u-warning; |
| | | } |
| | | } |
| | | </style> |
| | | .hint { |
| | | @apply px-40rpx py-20rpx text-24rpx; |
| | | color: $u-tips-color; |
| | | |
| | | .link { |
| | | color: $u-warning; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <!-- 我的 --> |
| | | <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="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"> |
| | | <img src="/src/static/images/user/mobile.svg" alt="" /> |
| | | <span>{{user.deptName}}</span> |
| | | </view> |
| | | </view> |
| | | <view class="rightLogo"> |
| | | <img src="/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)">点击编辑 |
| | | <img src="/src/static/images/user/rightBtn.svg" alt="" /> |
| | | </div> |
| | | </div> |
| | | <div class="passwordBox"> |
| | | <div class="messagebox">修改密码</div> |
| | | <div class="editInfo" @click="handelEdit(2)">点击编辑 <img src="/src/static/images/user/rightBtn.svg" alt="" /> |
| | | </div> |
| | | </div> |
| | | </view> |
| | | |
| | | <view class="mt-20rpx"> |
| | | <div class="goOutStyle" @click="logOut">退出登录</div> |
| | | </view> |
| | | <div class="bottomLogo"><img src="/src/static/images/user/logo1.png" alt="" /></div> |
| | | <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> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { |
| | | getUserInfo, |
| | | updateInfo, |
| | | updatePassword |
| | | |
| | | } from '@/api/user/index.js'; |
| | | import { |
| | | useClipboard |
| | |
| | | |
| | | function logOut() { |
| | | userStore.setUserInfo(null) |
| | | uni.redirectTo({ |
| | | uni.reLaunch({ |
| | | url: '/pages/login/index' |
| | | }) |
| | | } |
| | | |
| | | function getDeviceRegion() { |
| | | getDeviceRegionApi().then(res => { |
| | | // console.log(res.data.data, '用户设备') |
| | | |
| | | }) |
| | | } |
| | | const handelEdit = (val) => { |
| | |
| | | width: 100%; |
| | | height: 100%; |
| | | |
| | | padding-top: 88rpx; |
| | | } |
| | | |
| | | .userBox { |
| | | padding-top: 88rpx; |
| | | } |
| | | .userName { |
| | | font-weight: 700; |
| | | font-size: 36rpx; |
| | |
| | | display: flex; |
| | | align-items: center; |
| | | margin-top: 22rpx; |
| | | |
| | | image { |
| | | width: 28rpx; |
| | | height: 28rpx; |
| | | } |
| | | |
| | | span { |
| | | font-family: "Source Han Sans CN"; |
| | |
| | | width: 200rpx; |
| | | height: 80rpx; |
| | | |
| | | img { |
| | | image { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | |
| | | margin: 0 auto; |
| | | text-align: center; |
| | | |
| | | img { |
| | | image { |
| | | width: 128rpx; |
| | | height: 52rpx; |
| | | } |
| | |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | img { |
| | | image { |
| | | width: 28rpx; |
| | | height: 28rpx; |
| | | } |
| | |
| | | } |
| | | |
| | | .message { |
| | | background: url('/src/static/images/user/info.png') no-repeat center; |
| | | background: url(@/static/images/user/info.png) no-repeat center; |
| | | background-size: 100% 100%; |
| | | |
| | | } |
| | | |
| | | .passwordBox { |
| | | background: url('/src/static/images/user/password.png') no-repeat center; |
| | | background: url(@/static/images/user/password.png) no-repeat center; |
| | | background-size: 100% 100%; |
| | | |
| | | } |
| | |
| | | import dayjs from "dayjs"; |
| | | import {useUserStore} from "@/store/index.js"; |
| | | |
| | | const wayLineJodInfoId = ref(null) |
| | | const queryParams = ref({}) |
| | | |
| | | const viewUrl = computed(() => { |
| | | return getWebViewUrl('/DroneConsole', { |
| | | wayLineJodInfoId: wayLineJodInfoId.value, |
| | | }) |
| | | return getWebViewUrl('/DroneConsole', queryParams.value) |
| | | }) |
| | | |
| | | function onPostMessage(data) { |
| | |
| | | } |
| | | |
| | | onLoad((options) => { |
| | | wayLineJodInfoId.value = options.wayLineJodInfoId |
| | | queryParams.value = options |
| | | }) |
| | | |
| | | |
| | | // onShow(() => { |
| | | // // #ifdef APP-PLUS |
| | | // plus.screen.lockOrientation("landscape-primary"); |
| | | // // #endif |
| | | // }); |
| | | // |
| | | // onHide(() => { |
| | | // // #ifdef APP-PLUS |
| | | // plus.screen.lockOrientation("portrait-primary"); |
| | | // // #endif |
| | | // }); |
| | | onShow(() => { |
| | | // #ifdef APP-PLUS |
| | | plus.navigator.setFullscreen(true); // 加入全屏 |
| | | plus.screen.lockOrientation("landscape-primary");//横屏 |
| | | // #endif |
| | | }); |
| | | |
| | | onHide(() => { |
| | | // #ifdef APP-PLUS |
| | | plus.navigator.setFullscreen(false); |
| | | plus.screen.lockOrientation("portrait-primary"); |
| | | // #endif |
| | | }); |
| | | </script> |
| | | <style scoped lang="scss"> |
| | | |
| | |
| | | }); |
| | | } else if (data.type === 'control') { |
| | | uni.navigateTo({ |
| | | url: `/subPackages/droneConsole/index?wayLineJodInfoId=${wayLineJodInfoId.value}` |
| | | url: `/subPackages/droneConsole/index?wayLineJodInfoId=${wayLineJodInfoId.value}&dockSn=${data.dockSn}` |
| | | }); |
| | | } |
| | | } |
| | |
| | | |
| | | onShow(function () { |
| | | showComponent.value = true |
| | | // #ifdef APP-PLUS |
| | | plus.navigator.setFullscreen(false); |
| | | plus.screen.lockOrientation("portrait-primary"); |
| | | // #endif |
| | | }) |
| | | |
| | | onHide(() =>{ |
| | |
| | | <div class="rowTitle">手机号</div> |
| | | <u-input input-align="right" v-model="userInfo.phone" type="number" placeholder="请输入手机号" |
| | | class="input-item" /> |
| | | |
| | | |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">邮箱</div> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {getEnvObj, getWebViewUrl} from "@/utils/index.js"; |
| | | import { |
| | | getEnvObj, |
| | | getWebViewUrl |
| | | } from "@/utils/index.js"; |
| | | import { |
| | | getUserInfo, |
| | | updateInfo, |
| | | updatePassword |
| | | } from '@/api/user/index.js'; |
| | | import {useUserStore} from "@/store/index.js"; |
| | | import { |
| | | useUserStore |
| | | } from "@/store/index.js"; |
| | | const userInfo = ref({ |
| | | id: '', |
| | | avatar: '', |
| | |
| | | if (!phone) return true |
| | | const phoneRegex = /^1[3-9]\d{9}$/ |
| | | if (!phoneRegex.test(phone)) { |
| | | |
| | | |
| | | uni.showToast({ |
| | | title: '请输入正确的手机号码', |
| | | icon: 'none', |
| | |
| | | } |
| | | // 校验邮箱 |
| | | const validateEmail = () => { |
| | | if (!userInfo.value.email) return true |
| | | if (!userInfo.value.email) return true |
| | | const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/ |
| | | if (!emailRegex.test(userInfo.value.email)) { |
| | | |
| | | |
| | | uni.showToast({ |
| | | title: '请输入正确的邮箱地址', |
| | | icon: 'none', |
| | |
| | | getUserInfoData(); |
| | | }; |
| | | |
| | | const {VITE_API_BASE_URL} = getEnvObj() |
| | | const { |
| | | VITE_API_BASE_URL |
| | | } = getEnvObj() |
| | | |
| | | function uploadUtil(options) { |
| | | const {formData, file, url} = options |
| | | |
| | | return new Promise((resolve, reject) => { |
| | | let accessToken = useUserStore()?.$state?.userInfo?.access_token; |
| | | |
| | | uni.uploadFile({ |
| | | url: `${VITE_API_BASE_URL}${url}`, |
| | | name: 'file', |
| | | header: {'Blade-Auth': 'bearer ' + accessToken}, |
| | | file, |
| | | formData, |
| | | success: (res) => { |
| | | const resData = JSON.parse(res.data) |
| | | if (resData.code === 200 || resData.code === 0) { |
| | | resolve(res) |
| | | } else { |
| | | showToast(resData.message) |
| | | |
| | | reject(res) |
| | | } |
| | | }, |
| | | fail: (err) => { |
| | | reject(err) |
| | | } |
| | | }); |
| | | }) |
| | | const { |
| | | formData, |
| | | filePath, |
| | | url |
| | | } = options; |
| | | |
| | | return new Promise((resolve, reject) => { |
| | | let accessToken = useUserStore()?.$state?.userInfo?.access_token; |
| | | |
| | | uni.uploadFile({ |
| | | url: `${VITE_API_BASE_URL}${url}`, |
| | | name: 'file', |
| | | header: { |
| | | 'Blade-Auth': 'bearer ' + accessToken |
| | | }, |
| | | filePath: filePath, |
| | | formData, |
| | | success: (res) => { |
| | | const resData = JSON.parse(res.data) |
| | | if (resData.code === 200 || resData.code === 0) { |
| | | resolve(res) |
| | | } else { |
| | | showToast(resData.message) |
| | | |
| | | reject(res) |
| | | } |
| | | }, |
| | | fail: (err) => { |
| | | reject(err) |
| | | } |
| | | }); |
| | | }) |
| | | } |
| | | const uploadAvatar = () => { |
| | | uni.chooseImage({ |
| | | count: 1, |
| | | success: (res) => { |
| | | const tempFilePaths = res.tempFiles[0]; |
| | | // 显示加载中 |
| | | uni.showLoading({ |
| | | title: '上传中...' |
| | | }); |
| | | |
| | | // 上传文件 |
| | | uploadUtil({ |
| | | file: tempFilePaths, |
| | | formData: { |
| | | fileName: tempFilePaths.name, |
| | | sn: 'avatar_upload' |
| | | }, |
| | | url: '/blade-resource/oss/endpoint/put-file' |
| | | }).then(res => { |
| | | const resData = JSON.parse(res.data); |
| | | if (resData.code === 200 || resData.code === 0) { |
| | | // 更新头像显示 |
| | | userInfo.value.avatar = resData.data.link || resData.data.url; |
| | | uni.hideLoading(); |
| | | uni.showToast({ |
| | | title: '头像上传成功', |
| | | icon: 'success' |
| | | }); |
| | | } else { |
| | | throw new Error(resData.message || '上传失败'); |
| | | |
| | | } |
| | | }).catch(err => { |
| | | uni.hideLoading(); |
| | | uni.showToast({ |
| | | title: err.message || '上传失败', |
| | | icon: 'none' |
| | | }); |
| | | }); |
| | | } |
| | | }); |
| | | uni.chooseImage({ |
| | | count: 1, |
| | | success: (res) => { |
| | | const tempFile = res.tempFiles[0]; // 获取文件对象 |
| | | const filePath = tempFile.path || tempFile.tempFilePath; |
| | | if (!filePath) { |
| | | uni.showToast({ |
| | | title: '获取文件路径失败', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | let fileName = tempFile.name; |
| | | if (!fileName) { |
| | | const pathWithoutProtocol = filePath.replace(/^file:\/\//, ''); |
| | | fileName = pathWithoutProtocol.split('/').pop() || 'unknown.png'; |
| | | } |
| | | |
| | | // 显示加载中 |
| | | uni.showLoading({ |
| | | title: '上传中...' |
| | | }); |
| | | |
| | | // 上传文件 |
| | | uploadUtil({ |
| | | filePath: filePath, |
| | | formData: { |
| | | fileName: fileName, |
| | | sn: 'avatar_upload' |
| | | }, |
| | | url: '/blade-resource/oss/endpoint/put-file' |
| | | }).then(res => { |
| | | const resData = JSON.parse(res.data); |
| | | if (resData.code === 200 || resData.code === 0) { |
| | | // 更新头像显示 |
| | | userInfo.value.avatar = resData.data.link || resData.data.url; |
| | | uni.hideLoading(); |
| | | uni.showToast({ |
| | | title: '头像上传成功', |
| | | icon: 'success' |
| | | }); |
| | | } else { |
| | | throw new Error(resData.message || '上传失败'); |
| | | |
| | | } |
| | | }).catch(err => { |
| | | uni.hideLoading(); |
| | | uni.showToast({ |
| | | title: err.message || '上传失败', |
| | | icon: 'none' |
| | | }); |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | const submit = () => { |
| | | if (!validatePhone() || !validateEmail()) return |
| | |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | getUserInfoData() |
| | | |
| | | } else { |
| | | uni.showToast({ |
| | |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | getUserInfoData() |
| | | } |
| | | |
| | | |
| | | }); |
| | | getUserInfoData() |
| | | |
| | | }; |
| | | onShow(async () => { |
| | | getUserInfoData() |
| | |
| | | |
| | | <style lang="scss" scoped> |
| | | .container { |
| | | width: 100%; |
| | | width: 100%; |
| | | height: 100%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | |
| | | |
| | | } |
| | | |
| | | .avatarBox { |
| | | width: 228rpx; |
| | | height: 228rpx; |
| | | margin:76rpx 0; |
| | | margin: 76rpx 0; |
| | | } |
| | | |
| | | .detailBox { |
| | |
| | | background: #FFFFFF; |
| | | border-radius: 12rpx; |
| | | box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05); |
| | | |
| | | .detailCon { |
| | | padding: 0 24rpx; |
| | | } |
| | | |
| | | .orderRow { |
| | | display: flex; |
| | | justify-content: space-between; |
| | |
| | | height: 96rpx; |
| | | border-bottom: 2rpx solid #f5f5f5; |
| | | color: #7b7b7b; |
| | | |
| | | |
| | | .rowTitle { |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | |
| | | color: #222324; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | ::v-deep .u-input { |
| | | border: none !important; |
| | | background: transparent !important; |
| | |
| | | .btngroup { |
| | | display: flex; |
| | | position: absolute; |
| | | bottom:150rpx; |
| | | bottom: 150rpx; |
| | | } |
| | | .u-button:first-child{ |
| | | |
| | | .u-button:first-child { |
| | | margin-right: 30rpx; |
| | | } |
| | | |
| | | |
| | | .custom-style { |
| | | width: 276rpx; |
| | | height: 76rpx; |
| | |
| | | <div class="orderRow"> |
| | | <!-- type="password" :password-icon="passwordIcon" --> |
| | | <div class="rowTitle">原始密码</div> |
| | | <u-input input-align="right" v-model="passwordForm.oldPassword" placeholder="请输入" |
| | | class="input-item" /> |
| | | <input type="password" v-model="passwordForm.oldPassword" placeholder="请输入" class="input-item" /> |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">新密码</div> |
| | | <u-input input-align="right" v-model="passwordForm.newPassword" placeholder="请输入" |
| | | class="input-item" /> |
| | | |
| | | <input type="password" v-model="passwordForm.newPassword" placeholder="请输入" class="input-item" /> |
| | | |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">确认密码</div> |
| | | <u-input input-align="right" v-model="passwordForm.newPassword1" placeholder="请输入" |
| | | class="input-item" /> |
| | | <input type="password" v-model="passwordForm.newPassword1" placeholder="请输入" class="input-item" /> |
| | | </div> |
| | | </div> |
| | | </view> |
| | |
| | | updateInfo, |
| | | updatePassword |
| | | } from '@/api/user/index.js'; |
| | | const passwordIcon={ |
| | | show: 'fas fa-eye', // 显示密码时的图标 |
| | | hide: 'fas fa-eye-slash' // 隐藏密码时的图标 |
| | | } |
| | | const passwordIcon = { |
| | | show: 'fas fa-eye', // 显示密码时的图标 |
| | | hide: 'fas fa-eye-slash' // 隐藏密码时的图标 |
| | | } |
| | | const userStore = useUserStore(); |
| | | const passwordForm = ref({ |
| | | oldPassword: '', |
| | | newPassword: '', |
| | | newPassword1: '', |
| | | }); |
| | | // 校验密码不能包含中文 |
| | | const validatePasswordNoChinese = (password) => { |
| | | const chineseRegex = /[\u4e00-\u9fa5]/; |
| | | if (chineseRegex.test(password)) { |
| | | |
| | | uni.showToast({ |
| | | title: '密码不能包含中文字符', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | return false; |
| | | } |
| | | return true; |
| | | }; |
| | | // 校验密码复杂度(长度≥6位,包含字母和数字) |
| | | const validatePasswordStrength = (password) => { |
| | | if (password.length < 6) { |
| | | |
| | | uni.showToast({ |
| | | title: '密码长度不能少于6位', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | return false; |
| | | } |
| | | // const hasLetter = /[a-zA-Z]/.test(password); |
| | | // const hasNumber = /\d/.test(password); |
| | | // if (!hasLetter || !hasNumber) { |
| | | // ElMessage.error('密码需同时包含字母和数字'); |
| | | // return false; |
| | | // } |
| | | return true; |
| | | }; |
| | | const clearForm = () => { |
| | | passwordForm.value = { |
| | | oldPassword: '', |
| | |
| | | clearForm(); |
| | | }; |
| | | const submit = () => { |
| | | // 原始密码校验 |
| | | if (!passwordForm.value.oldPassword) { |
| | | |
| | | uni.showToast({ |
| | | title: '请输入原始密码', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | return; |
| | | } |
| | | // 中文校验 |
| | | if (!validatePasswordNoChinese(passwordForm.value.newPassword)) return; |
| | | // 新密码校验 |
| | | if (!passwordForm.value.newPassword) { |
| | | |
| | | uni.showToast({ |
| | | title: '请输入新密码', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | return; |
| | | } |
| | | // 确认密码校验 |
| | | if (passwordForm.value.newPassword !== passwordForm.value.newPassword1) { |
| | | |
| | | uni.showToast({ |
| | | title: '两次输入的新密码不一致', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | // 复杂度校验 |
| | | if (!validatePasswordStrength(passwordForm.value.newPassword)) return; |
| | | updatePassword(md5(passwordForm.value.oldPassword), |
| | | md5(passwordForm.value.newPassword), |
| | | md5(passwordForm.value.newPassword1)).then(res => { |
| | |
| | | }); |
| | | clearForm(); |
| | | userStore.setUserInfo(null) |
| | | uni.redirectTo({ |
| | | uni.removeStorageSync('rememberedUser'); |
| | | uni.reLaunch({ |
| | | url: '/pages/login/index' |
| | | }) |
| | | |
| | |
| | | |
| | | .detailBox { |
| | | margin-top: 40rpx; |
| | | width: 702rpx; |
| | | width: 702rpx; |
| | | |
| | | min-height: 326rpx; |
| | | background: #FFFFFF; |
| | | border-radius: 12rpx; |
| | | box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05); |
| | | .detailCon { |
| | | |
| | | .detailCon { |
| | | padding: 0 24rpx; |
| | | } |
| | | |
| | | .orderRow { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | height: 96rpx; |
| | | border-bottom: 2rpx solid #f5f5f5; |
| | | color: #7b7b7b; |
| | | |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | height: 96rpx; |
| | | border-bottom: 2rpx solid #f5f5f5; |
| | | color: #7b7b7b; |
| | | |
| | | |
| | | .rowTitle { |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | |
| | | color: #222324; |
| | | white-space: nowrap; |
| | | } |
| | | ::v-deep .u-input { |
| | | border: none !important; |
| | | background: transparent !important; |
| | | } |
| | | |
| | | ::v-deep .u-input__input { |
| | | input.input-item { |
| | | text-align: right; |
| | | border: none !important; |
| | | box-shadow: none !important; |
| | | background: transparent !important; |
| | | box-shadow: none !important; |
| | | padding: 0 !important; |
| | | margin: 0 !important; |
| | | height: auto !important; |
| | | |
| | | outline: none; |
| | | font-size: 30rpx; |
| | | color: #222324; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | } |
| | | |
| | | input.input-item::placeholder { |
| | | color: #c9c9c9; |
| | | font-size: 30rpx; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .btngroup { |
| | | .btngroup { |
| | | display: flex; |
| | | position: absolute; |
| | | bottom:150rpx; |
| | | bottom: 150rpx; |
| | | } |
| | | .u-button:first-child{ |
| | | |
| | | .u-button:first-child { |
| | | margin-right: 30rpx; |
| | | } |
| | | |
| | | |
| | | .custom-style { |
| | | width: 276rpx; |
| | | height: 76rpx; |
| | |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | export function getStatusBarHeight() { |
| | | try { |
| | | const systemInfo = uni.getSystemInfoSync(); |
| | | return systemInfo.statusBarHeight || 0; |
| | | } catch (error) { |
| | | return 0; |
| | | } |
| | | } |
| | | export function getEnvObj() { |
| | | const envName = JSON.parse(__APP_ENV__?.UNI_CUSTOM_DEFINE||null)?.ENV_NAME |
| | | return configEnv[envName || import.meta.env.VITE_APP_ENV] || {} |
| | |
| | | export function getWebViewUrl (targetUrl, otherParams) { |
| | | const userStore = useUserStore() |
| | | const url = getEnvObj().VITE_APP_WEBVIEW_URL |
| | | const uniPlatform = __APP_ENV__.UNI_PLATFORM |
| | | const statusBarHeight = getStatusBarHeight(); |
| | | // 1. 处理用户参数 |
| | | const userParams = userStore?.userInfo ? JSON.stringify(userStore.userInfo) : '{}' |
| | | // 2. 构建查询参数字符串 |
| | | let queryString = `params=${encodeURIComponent(userParams)}` |
| | | let queryString = `params=${encodeURIComponent(userParams)}&topMargin=${statusBarHeight}&uniPlatform=${uniPlatform}` |
| | | |
| | | // 3. 处理 otherParams 对象 |
| | | if (otherParams && typeof otherParams === 'object') { |
| | | Object.keys(otherParams).forEach(key => { |
| | |
| | | if (response.statusCode === 401) { |
| | | const pages = getCurrentPages() |
| | | const currentPage = pages[pages.length - 1] |
| | | uni.redirectTo({ |
| | | uni.reLaunch({ |
| | | url: `/pages/login/index?redirect=/${currentPage.route}` |
| | | }) |
| | | } |