#
zhou zhou
2026-01-28 7e84f102a8424e9ac4f5bf52011cf6460f54306e
pages/login/index.vue
@@ -1,5 +1,9 @@
<template>
   <view class="bodyView">
      <view>
         <uni-nav-bar :fixed="true" :title="$t('page.login')" right-icon="gear" @clickRight="openSettings"></uni-nav-bar>
      </view>
      <view class="topView">
         <image src="/static/img/login_top.png" mode="aspectFill">            
         </image>
@@ -39,25 +43,83 @@
               </view>
            </view>
            <view class="langView">
               <!-- 语言选择下拉菜单 -->
               <view class="language-dropdown">
                  <view class="selected-language" @click="toggleLanguageDropdown">
                     <text>{{getCurrentLanguageText()}}</text>
                     <uni-icons type="bottom" size="14" color="#707070"></uni-icons>
                  </view>
                  <view class="language-options" v-if="showLanguageDropdown">
                     <view class="language-option" v-for="(item, index) in locales" :key="index" @click="onLocaleChange(item)">
                        <text>{{item.text}}</text>
                        <uni-icons type="checkmarkempty" size="14" color="#007AFF" v-if="item.code == applicationLocale"></uni-icons>
                     </view>
                  </view>
               </view>
            </view>
         </view>
         <view class="itemView">
            <button class="loadingButton" @click="onLogin()"  :loading="loading">{{btnText}}</button>
         </view>
      </view>
      <!-- 设置菜单 -->
      <uni-popup ref="settingsMenu" type="bottom" background-color="#fff">
         <view class="settings-menu">
            <view class="settings-item" @click="openIpSetting">
               <text>设置IP</text>
               <uni-icons type="arrowright" size="16" color="#999"></uni-icons>
            </view>
            <view class="settings-item" @click="openLangSetting">
               <text>国际化</text>
               <uni-icons type="arrowright" size="16" color="#999"></uni-icons>
            </view>
            <view class="settings-cancel" @click="closeSettingsMenu">取消</view>
         </view>
      </uni-popup>
      <!-- IP配置弹窗 -->
      <uni-popup ref="inputDialog" type="center" :mask-click="false">
         <view class="modal-container">
            <view class="modal-header">
               <text class="cuIcon-settings" style="font-size: 48rpx; color: #0081ff"></text>
               <text class="modal-title">配置</text>
            </view>
            <view class="modal-body">
               <view class="form-item">
                  <text class="form-label">IP</text>
                  <view class="modal-input-wrapper">
                     <input class="agv-input" type="text" v-model="url.ip" />
                  </view>
               </view>
               <view class="form-item">
                  <text class="form-label">端口</text>
                  <view class="modal-input-wrapper">
                     <input class="agv-input" type="text" v-model="url.port" />
                  </view>
               </view>
               <view class="form-item">
                  <text class="form-label">项目</text>
                  <view class="modal-input-wrapper">
                     <input class="agv-input" type="text" v-model="url.project" />
                  </view>
               </view>
            </view>
            <view class="modal-footer">
               <button class="modal-btn modal-btn-cancel" @click="closeIpDialog">取消</button>
               <button class="modal-btn modal-btn-confirm" @click="settingConfirm">确认</button>
            </view>
         </view>
      </uni-popup>
      <!-- 语言设置弹窗 -->
      <uni-popup ref="langDialog" type="center">
         <view class="modal-container">
            <view class="modal-header">
               <text class="cuIcon-global" style="font-size: 48rpx; color: #0081ff"></text>
               <text class="modal-title">选择语言</text>
            </view>
            <view class="modal-body">
               <view class="language-list">
                  <view class="language-item" v-for="(item, index) in locales" :key="index" @click="onLocaleConfirm(item)">
                     <text>{{item.text}}</text>
                     <uni-icons type="checkmarkempty" size="20" color="#007AFF" v-if="item.code == applicationLocale"></uni-icons>
                  </view>
               </view>
            </view>
            <view class="modal-footer">
               <button class="modal-btn modal-btn-cancel" @click="closeLangDialog" style="width: 100%; border-right: none;">取消</button>
            </view>
         </view>
      </uni-popup>
   </view>
</template>
@@ -80,6 +142,12 @@
            userName: '',
            password: '',
         },
         url: {
            ip: '',
            port: '',
            project: ''
         },
         baseUrl: '',
      }
   },
   computed:{
@@ -210,6 +278,46 @@
         this.showLanguageDropdown = !this.showLanguageDropdown;
      },
      
      openSettings() {
         this.$refs.settingsMenu.open()
      },
      openIpSetting() {
         this.$refs.settingsMenu.close()
         setTimeout(() => {
            this.$refs.inputDialog.open()
         }, 300)
      },
      openLangSetting() {
         this.$refs.settingsMenu.close()
         setTimeout(() => {
            this.$refs.langDialog.open()
         }, 300)
      },
      closeSettingsMenu() {
         this.$refs.settingsMenu.close()
      },
      closeIpDialog() {
         this.$refs.inputDialog.close()
      },
      closeLangDialog() {
         this.$refs.langDialog.close()
      },
      settingConfirm() {
         this.baseUrl = "http://" + this.url.ip + ':' + this.url.port + '/' + this.url.project
         uni.setStorageSync('baseUrl', this.baseUrl);
         uni.setStorageSync('url', this.url);
         // uni.setStorageSync('project', 'tzsk')
         this.$refs.inputDialog.close()
         uni.showToast({
            title: '配置已保存',
            icon: 'success'
         })
      },
      onLocaleConfirm(item) {
         this.onLocaleChange(item)
         this.$refs.langDialog.close()
      },
      // 获取当前选择的语言文本
      getCurrentLanguageText() {
         const currentLocale = this.locales.find(item => item.code === this.applicationLocale);
@@ -412,4 +520,156 @@
   .language-option:active {
      background-color: #f5f5f5;
   }
   /* Settings Menu */
   .settings-menu {
      background-color: #fff;
      padding: 20rpx 0;
      border-radius: 20rpx 20rpx 0 0;
   }
   .settings-item {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 30rpx 40rpx;
      border-bottom: 1px solid #f0f0f0;
      font-size: 32rpx;
      color: #333;
   }
   .settings-item:active {
      background-color: #f5f5f5;
   }
   .settings-cancel {
      text-align: center;
      padding: 30rpx;
      margin-top: 20rpx;
      border-top: 10rpx solid #f8f8f8;
      font-size: 32rpx;
      color: #333;
   }
   /* Custom Popup Styles */
   /* 弹窗容器 */
   .modal-container {
      width: 600rpx;
      background-color: #ffffff;
      border-radius: 24rpx;
      overflow: hidden;
      box-shadow: 0 8rpx 40rpx rgba(0, 0, 0, 0.15);
   }
   /* 弹窗头部 */
   .modal-header {
      padding: 40rpx 30rpx 20rpx;
      display: flex;
      flex-direction: column;
      align-items: center;
      background: linear-gradient(135deg, #f0f7ff 0%, #e8f4ff 100%);
   }
   .modal-title {
      font-size: 34rpx;
      font-weight: bold;
      color: #333;
      margin-top: 16rpx;
   }
   /* 弹窗内容 */
   .modal-body {
      padding: 30rpx;
   }
   .form-item {
      display: flex;
      align-items: center;
      margin-bottom: 24rpx;
   }
   .form-item:last-child {
      margin-bottom: 0;
   }
   .form-label {
      width: 100rpx;
      font-size: 28rpx;
      color: #333;
      font-weight: 500;
      margin-right: 20rpx;
      text-align: right;
   }
   /* 输入框容器 - 弹窗专用 */
   .modal-input-wrapper {
      flex: 1;
      background-color: #f5f7fa;
      border-radius: 12rpx;
      padding: 10rpx;
      border: 2rpx solid #e4e7ed;
      transition: border-color 0.2s;
   }
   .modal-input-wrapper:focus-within {
      border-color: #0081ff;
   }
   .agv-input {
      width: 100%;
      height: 70rpx;
      line-height: 70rpx;
      font-size: 30rpx;
      color: #333;
      background-color: transparent;
   }
   /* 弹窗底部按钮 */
   .modal-footer {
      display: flex;
      border-top: 1rpx solid #eee;
   }
   .modal-btn {
      flex: 1;
      height: 100rpx;
      line-height: 100rpx;
      font-size: 32rpx;
      border: none;
      border-radius: 0;
      background-color: #fff;
   }
   .modal-btn::after {
      border: none;
   }
   .modal-btn-cancel {
      color: #999;
      border-right: 1rpx solid #eee;
   }
   .modal-btn-confirm {
      color: #fff;
      background: linear-gradient(135deg, #0081ff 0%, #1890ff 100%);
      font-weight: bold;
   }
   .modal-btn-confirm:active {
      background: linear-gradient(135deg, #0070dd 0%, #1480e8 100%);
   }
   .modal-btn-cancel:active {
      background-color: #f5f5f5;
   }
   /* Language List in Popup */
   .language-list {
      max-height: 200px;
      overflow-y: auto;
   }
   .language-item {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 15px 0;
      border-bottom: 1px solid #f0f0f0;
   }
</style>