ljw 1 год назад
Родитель
Сommit
8be855ff3e

+ 4 - 2
src/layout/components/menu/item.vue

@@ -7,7 +7,7 @@
7 7
       <el-icon v-if="route.meta?.icon">
8 8
         <component :is="`el-icon-${route.meta.icon}`"></component>
9 9
       </el-icon>
10
-      <span>{{route.meta?.title||route.name}}</span>
10
+      <span>{{ T(route.meta?.title) || T(route.name) }}</span>
11 11
     </template>
12 12
     <menu-item v-for="(_route,_index) in route.children"
13 13
                :route="_route"
@@ -18,12 +18,13 @@
18 18
     <el-icon v-if="parseRoute(route).meta?.icon">
19 19
       <component :is="`el-icon-${parseRoute(route).meta.icon}`"></component>
20 20
     </el-icon>
21
-    <span>{{parseRoute(route).meta?.title||parseRoute(route).name}}</span>
21
+    <span>{{ T(parseRoute(route).meta?.title) || T(parseRoute(route).name) }}</span>
22 22
   </el-menu-item>
23 23
 </template>
24 24
 
25 25
 <script>
26 26
   import { defineComponent } from 'vue'
27
+  import { T } from '@/utils/i18n'
27 28
 
28 29
   export default defineComponent({
29 30
     name: 'MenuItem',
@@ -43,6 +44,7 @@
43 44
       }
44 45
       return {
45 46
         parseRoute,
47
+        T,
46 48
       }
47 49
     },
48 50
   })

+ 12 - 2
src/layout/components/setting/index.vue

@@ -1,5 +1,8 @@
1 1
 <template>
2 2
   <div class="setting">
3
+    <div>
4
+      <el-button size="small" @click="changeLang" style="width: 100px">{{ T('ChangeLang') }}</el-button>
5
+    </div>
3 6
     <el-dropdown class="menu-item">
4 7
       <div class="title">
5 8
         <!--        <el-image class="avatar" :src="user.avatar"></el-image>-->
@@ -7,12 +10,13 @@
7 10
         <el-icon>
8 11
           <el-icon-arrow-down/>
9 12
         </el-icon>
13
+
10 14
       </div>
11 15
 
12 16
       <template #dropdown>
13 17
         <el-dropdown-menu>
14
-          <el-dropdown-item @click="showChangePwd">修改密码</el-dropdown-item>
15
-          <el-dropdown-item @click="logout">退出登录</el-dropdown-item>
18
+          <el-dropdown-item @click="showChangePwd">{{T('ChangePassword')}}</el-dropdown-item>
19
+          <el-dropdown-item @click="logout">{{ T('Logout')}}</el-dropdown-item>
16 20
         </el-dropdown-menu>
17 21
       </template>
18 22
     </el-dropdown>
@@ -22,11 +26,14 @@
22 26
 
23 27
 <script setup>
24 28
   import { useUserStore } from '@/store/user'
29
+  import { useAppStore } from '@/store/app'
25 30
   import changePwdDialog from '@/components/changePwdDialog.vue'
26 31
   import { ref } from 'vue'
32
+  import { T } from '@/utils/i18n'
27 33
 
28 34
   const userStore = useUserStore()
29 35
   const user = userStore
36
+  const appStore = useAppStore()
30 37
 
31 38
   const logout = () => {
32 39
     userStore.logout()
@@ -37,6 +44,9 @@
37 44
   const showChangePwd = () => {
38 45
     changePwdVisible.value = true
39 46
   }
47
+  const changeLang = () => {
48
+    appStore.changeLang()
49
+  }
40 50
 </script>
41 51
 
42 52
 <style lang="scss" scoped>

+ 9 - 6
src/layout/components/tags/index.vue

@@ -7,7 +7,7 @@
7 7
           @click="toTag(t)"
8 8
           :type="t.active?'primary':'info'"
9 9
           :effect="t.active?'dark':'plain'">
10
-    {{t.title}}
10
+    {{ T(t.title) }}
11 11
   </el-tag>
12 12
 </template>
13 13
 
@@ -15,6 +15,7 @@
15 15
   import { defineComponent, ref, onMounted, watch } from 'vue'
16 16
   import { useTagsStore } from '@/store/tags'
17 17
   import { useRoute, useRouter } from 'vue-router'
18
+  import { T } from '@/utils/i18n'
18 19
 
19 20
   export default defineComponent({
20 21
     name: 'Index',
@@ -64,6 +65,7 @@
64 65
         close,
65 66
         toLastTag,
66 67
         toTag,
68
+        T,
67 69
       }
68 70
     },
69 71
   })
@@ -71,10 +73,11 @@
71 73
 
72 74
 <style lang="scss" scoped>
73 75
 
74
-  .tag {
75
-    border-radius: 0;
76
-    cursor: pointer;
77
-    &.active {
78
-    }
76
+.tag {
77
+  border-radius: 0;
78
+  cursor: pointer;
79
+
80
+  &.active {
79 81
   }
82
+}
80 83
 </style>

+ 49 - 61
src/layout/index.vue

@@ -1,85 +1,73 @@
1 1
 <template>
2
-  <el-container>
3
-    <el-aside :width="leftWidth" class="app-left">
4
-      <g-aside></g-aside>
5
-    </el-aside>
6
-    <el-container class="app-container ">
7
-      <el-header class="app-header">
8
-        <g-header></g-header>
9
-      </el-header>
10
-      <div class="header-tags">
11
-        <tags></tags>
12
-      </div>
2
+  <el-config-provider :locale="appStore.setting.locale">
3
+    <el-container>
4
+      <el-aside :width="leftWidth" class="app-left">
5
+        <g-aside></g-aside>
6
+      </el-aside>
7
+      <el-container class="app-container ">
8
+        <el-header class="app-header">
9
+          <g-header></g-header>
10
+        </el-header>
11
+        <div class="header-tags">
12
+          <tags></tags>
13
+        </div>
13 14
 
14
-      <el-main class="app-main">
15
-        <router-view v-slot="{ Component }">
16
-          <transition mode="out-in" name="el-fade-in-linear">
17
-            <keep-alive :include="[...cachedTags]">
18
-              <component :is="Component"/>
19
-            </keep-alive>
20
-          </transition>
21
-        </router-view>
22
-      </el-main>
15
+        <el-main class="app-main">
16
+          <router-view v-slot="{ Component }">
17
+            <transition mode="out-in" name="el-fade-in-linear">
18
+              <keep-alive :include="[...cachedTags]">
19
+                <component :is="Component"/>
20
+              </keep-alive>
21
+            </transition>
22
+          </router-view>
23
+        </el-main>
24
+      </el-container>
23 25
     </el-container>
24
-  </el-container>
26
+  </el-config-provider>
25 27
 </template>
26 28
 
27
-<script>
29
+<script setup>
28 30
   import { useUserStore } from '@/store/user'
29
-  import { useRouteStore } from '@/store/router'
30 31
   import { useAppStore } from '@/store/app'
31 32
   import { useTagsStore } from '@/store/tags'
32
-  import LayerHeader from '@/layout/components/header.vue'
33
-  import { defineComponent, ref, onMounted, watch, reactive, computed, toRef } from 'vue'
33
+  import { ref, computed } from 'vue'
34 34
   import Tags from '@/layout/components/tags/index.vue'
35 35
   import GAside from '@/layout/components/aside.vue'
36 36
   import GHeader from '@/layout/components/header.vue'
37 37
 
38
-  export default defineComponent({
39
-    name: 'Layout',
40
-    components: { LayerHeader, Tags, GAside, GHeader },
41
-    setup (props) {
42
-      const userStore = useUserStore()
43
-      const appStore = useAppStore()
44
-      const tagStore = useTagsStore()
38
+  const appStore = useAppStore()
39
+  const tagStore = useTagsStore()
45 40
 
46
-      const leftWidth = computed(() => appStore.setting.sideIsCollapse ? '64px' : '210px')
41
+  const leftWidth = computed(() => appStore.setting.sideIsCollapse ? '64px' : '210px')
47 42
 
48
-      const cachedTags = ref([])
43
+  const cachedTags = ref([])
49 44
 
50
-      cachedTags.value = tagStore.cached
51
-
52
-      return {
53
-        cachedTags,
54
-        leftWidth,
55
-      }
56
-    },
57
-  })
45
+  cachedTags.value = tagStore.cached
58 46
 </script>
59 47
 
60 48
 <style lang="scss" scoped>
61
-  .app-header {
62
-    background-color: #3f454b;
63
-    color: var(--basicWhite);
64
-    display: flex;
65
-    height: 50px;
66
-  }
49
+.app-header {
50
+  background-color: #3f454b;
51
+  color: var(--basicWhite);
52
+  display: flex;
53
+  height: 50px;
54
+}
67 55
 
68
-  .header-tags {
69
-    height: auto;
70
-    border-bottom: 1px solid #eee;
71
-    display: flex;
72
-    padding: 0;
73
-  }
56
+.header-tags {
57
+  height: auto;
58
+  border-bottom: 1px solid #eee;
59
+  display: flex;
60
+  padding: 0;
61
+}
74 62
 
75
-  .app-left {
76
-    height: 100%;
77
-    transition: width 0.5s;
78
-  }
63
+.app-left {
64
+  height: 100%;
65
+  transition: width 0.5s;
66
+}
79 67
 
80
-  .app-container {
81
-    min-height: 100vh;
82
-  }
68
+.app-container {
69
+  min-height: 100vh;
70
+}
83 71
 </style>
84 72
 
85 73
 

+ 15 - 15
src/router/index.js

@@ -4,7 +4,7 @@ const constantRoutes = [
4 4
   {
5 5
     path: '/login',
6 6
     name: 'Login',
7
-    meta: { title: '登录' },
7
+    meta: { title: 'Login' },
8 8
     component: () => import('@/views/login/login.vue'),
9 9
   },
10 10
 
@@ -45,25 +45,25 @@ export const asyncRoutes = [
45 45
     path: '/my',
46 46
     name: 'My',
47 47
     redirect: '/my/info',
48
-    meta: { title: '我的', icon: 'UserFilled' },
48
+    meta: { title: 'My', icon: 'UserFilled' },
49 49
     component: () => import('@/layout/index.vue'),
50 50
     children: [
51 51
       {
52 52
         path: '/',
53 53
         name: 'MyInfo',
54
-        meta: { title: '个人信息', icon: 'User' /*keepAlive: true*/ },
54
+        meta: { title: 'Info', icon: 'User' /*keepAlive: true*/ },
55 55
         component: () => import('@/views/my/info.vue'),
56 56
       },
57 57
       {
58 58
         path: 'address_book',
59 59
         name: 'MyAddressBookList',
60
-        meta: { title: '地址簿管理', icon: 'Notebook' /*keepAlive: true*/ },
60
+        meta: { title: 'AddressBooks', icon: 'Notebook' /*keepAlive: true*/ },
61 61
         component: () => import('@/views/my/address_book/index.vue'),
62 62
       },
63 63
       {
64 64
         path: 'tag',
65 65
         name: 'MyTagList',
66
-        meta: { title: '标签管理', icon: 'CollectionTag' /*keepAlive: true*/ },
66
+        meta: { title: 'Tags', icon: 'CollectionTag' /*keepAlive: true*/ },
67 67
         component: () => import('@/views/my/tag/index.vue'),
68 68
       },
69 69
     ],
@@ -72,62 +72,62 @@ export const asyncRoutes = [
72 72
     path: '/user',
73 73
     name: 'User',
74 74
     redirect: '/user/index',
75
-    meta: { title: '系统', icon: 'Setting' },
75
+    meta: { title: 'System', icon: 'Setting' },
76 76
     component: () => import('@/layout/index.vue'),
77 77
     children: [
78 78
       {
79 79
         path: 'peer',
80 80
         name: 'Peer',
81
-        meta: { title: '设备管理', icon: 'Monitor' /*keepAlive: true*/ },
81
+        meta: { title: 'PeerManage', icon: 'Monitor' /*keepAlive: true*/ },
82 82
         component: () => import('@/views/peer/index.vue'),
83 83
       },
84 84
       {
85 85
         path: 'group',
86 86
         name: 'UserGroup',
87
-        meta: { title: '群组管理', icon: 'ChatRound' /*keepAlive: true*/ },
87
+        meta: { title: 'GroupManage', icon: 'ChatRound' /*keepAlive: true*/ },
88 88
         component: () => import('@/views/group/index.vue'),
89 89
       },
90 90
       {
91 91
         path: 'index',
92 92
         name: 'UserList',
93
-        meta: { title: '用户列表', icon: 'User' /*keepAlive: true*/ },
93
+        meta: { title: 'UserManage', icon: 'User' /*keepAlive: true*/ },
94 94
         component: () => import('@/views/user/index.vue'),
95 95
       },
96 96
       {
97 97
         path: 'add',
98 98
         name: 'UserAdd',
99
-        meta: { title: '用户添加', hide: true },
99
+        meta: { title: 'UserAdd', hide: true },
100 100
         component: () => import('@/views/user/edit.vue'),
101 101
       },
102 102
       {
103 103
         path: 'edit/:id',
104 104
         name: 'UserEdit',
105
-        meta: { title: '用户编辑', hide: true },
105
+        meta: { title: 'UserEdit', hide: true },
106 106
         component: () => import('@/views/user/edit.vue'),
107 107
       },
108 108
 
109 109
       {
110 110
         path: 'addressBook',
111 111
         name: 'UserAddressBook',
112
-        meta: { title: '地址簿管理', icon: 'Notebook' /*keepAlive: true*/ },
112
+        meta: { title: 'AddressBookManage', icon: 'Notebook' /*keepAlive: true*/ },
113 113
         component: () => import('@/views/address_book/index.vue'),
114 114
       },
115 115
       {
116 116
         path: 'tag',
117 117
         name: 'UserTag',
118
-        meta: { title: '标签管理', icon: 'CollectionTag' /*keepAlive: true*/ },
118
+        meta: { title: 'TagsManage', icon: 'CollectionTag' /*keepAlive: true*/ },
119 119
         component: () => import('@/views/tag/index.vue'),
120 120
       },
121 121
       {
122 122
         path: '/oauth',
123 123
         name: 'Oauth',
124
-        meta: { title: 'Oauth管理', icon: 'Link' /*keepAlive: true*/ },
124
+        meta: { title: 'OauthManage', icon: 'Link' /*keepAlive: true*/ },
125 125
         component: () => import('@/views/oauth/index.vue'),
126 126
       },
127 127
       {
128 128
         path: '/loginLog',
129 129
         name: 'LoginLog',
130
-        meta: { title: '登录日志', icon: 'List' /*keepAlive: true*/ },
130
+        meta: { title: 'LoginLog', icon: 'List' /*keepAlive: true*/ },
131 131
         component: () => import('@/views/login/log.vue'),
132 132
       },
133 133
     ],

+ 13 - 1
src/store/app.js

@@ -1,13 +1,17 @@
1 1
 import { defineStore, acceptHMRUpdate } from 'pinia'
2 2
 import logo from '@/assets/logo.png'
3
+import zhCn from 'element-plus/es/locale/lang/zh-cn'
4
+import en from 'element-plus/es/locale/lang/en'
3 5
 
4 6
 export const useAppStore = defineStore({
5 7
   id: 'App',
6 8
   state: () => ({
7 9
     setting: {
8
-      title: 'Gwen-Admin',
10
+      title: 'Rustdesk-Api-Admin',
9 11
       sideIsCollapse: false,
10 12
       logo,
13
+      lang: localStorage.getItem('lang') || 'zh-CN',
14
+      locale: zhCn,
11 15
     },
12 16
   }),
13 17
 
@@ -15,6 +19,14 @@ export const useAppStore = defineStore({
15 19
     sideCollapse () {
16 20
       this.setting.sideIsCollapse = !this.setting.sideIsCollapse
17 21
     },
22
+    setLang (lang) {
23
+      this.setting.lang = lang
24
+      this.setting.locale = lang === 'zh-CN' ? zhCn : en
25
+      localStorage.setItem('lang', lang)
26
+    },
27
+    changeLang () {
28
+      this.setLang(this.setting.lang === 'zh-CN' ? 'en' : 'zh-CN')
29
+    },
18 30
   },
19 31
 })
20 32
 

+ 9 - 9
src/store/tags.js

@@ -8,15 +8,15 @@ export const useTagsStore = defineStore({
8 8
   }),
9 9
   actions: {
10 10
     initTags () {
11
-      this.tags.push(
12
-        {
13
-          name: 'Home',
14
-          path: '/Home',
15
-          title: '首页',
16
-          active: false,
17
-          closeable: false,
18
-          keepAlive: false,
19
-        })
11
+      // this.tags.push(
12
+      //   {
13
+      //     name: 'Home',
14
+      //     path: '/Home',
15
+      //     title: '首页',
16
+      //     active: false,
17
+      //     closeable: false,
18
+      //     keepAlive: false,
19
+      //   })
20 20
     },
21 21
     addTag (route) {
22 22
       const tags = this.tags

+ 21 - 0
src/utils/i18n.js

@@ -0,0 +1,21 @@
1
+import en from '@/utils/i18n/en.json'
2
+import zhCN from '@/utils/i18n/zh_CN.json'
3
+import { useAppStore } from '@/store/app'
4
+import { pinia } from '@/store'
5
+
6
+export function T (key, params, num = 0) {
7
+  const appStore = useAppStore(pinia)
8
+  const lang = appStore.setting.lang
9
+  const trans = lang === 'zh-CN' ? zhCN : en
10
+  const tran = trans[key]
11
+  if (!tran) {
12
+    return key
13
+  }
14
+  const msg = num > 0 ? (tran.Other ? tran.Other : tran.One) : tran.One
15
+  //msg 是这样 {name} is name
16
+  //params 是这样 {name: 'zhangsan'}
17
+  //替换
18
+  return msg.replace(/{(\w+)}/g, function (match, key) {
19
+    return params[key] || match
20
+  })
21
+}

+ 236 - 0
src/utils/i18n/en.json

@@ -0,0 +1,236 @@
1
+{
2
+  "Login": {
3
+    "One": "Login"
4
+  },
5
+  "Logout": {
6
+    "One": "Logout"
7
+  },
8
+  "Register": {
9
+    "One": "Register"
10
+  },
11
+  "Confirm": {
12
+    "One": "Confirm"
13
+  },
14
+  "Username": {
15
+    "One": "Username"
16
+  },
17
+  "Password": {
18
+    "One": "Password"
19
+  },
20
+  "LoginSuccess": {
21
+    "One": "Login Success"
22
+  },
23
+  "ForgotPassword": {
24
+    "One": "Forgot Password"
25
+  },
26
+  "ResetPassword": {
27
+    "One": "Reset Password"
28
+  },
29
+  "ChangePassword": {
30
+    "One": "Change Password"
31
+  },
32
+  "Userinfo": {
33
+    "One": "User Info"
34
+  },
35
+  "ParamRequired": {
36
+    "One": "{param} is required"
37
+  },
38
+  "HasBind": {
39
+    "One": "Has bind"
40
+  },
41
+  "NoBind": {
42
+    "One": "No bind"
43
+  },
44
+  "UnBind": {
45
+    "One": "UnBind"
46
+  },
47
+  "ToBind": {
48
+    "One": "To Bind"
49
+  },
50
+  "Confirm?": {
51
+    "One": "{param} Confirm?"
52
+  },
53
+  "Cancel": {
54
+    "One": "Cancel"
55
+  },
56
+  "Platform": {
57
+    "One": "Platform"
58
+  },
59
+  "Status": {
60
+    "One": "Status"
61
+  },
62
+  "Actions": {
63
+    "One": "Actions"
64
+  },
65
+  "Filter": {
66
+    "One": "Filter"
67
+  },
68
+  "Add": {
69
+    "One": "Add"
70
+  },
71
+  "Hostname": {
72
+    "One": "Hostname"
73
+  },
74
+  "Alias": {
75
+    "One": "Alias"
76
+  },
77
+  "Hash": {
78
+    "One": "Hash"
79
+  },
80
+  "Tags": {
81
+    "One": "Tags"
82
+  },
83
+  "Edit": {
84
+    "One": "Edit"
85
+  },
86
+  "Delete": {
87
+    "One": "Delete"
88
+  },
89
+  "Create": {
90
+    "One": "Create"
91
+  },
92
+  "Update": {
93
+    "One": "Update"
94
+  },
95
+  "LoginName": {
96
+    "One": "Login Name"
97
+  },
98
+  "Submit": {
99
+    "One": "Submit"
100
+  },
101
+  "OperationSuccess": {
102
+    "One": "Operation Success"
103
+  },
104
+  "Owner": {
105
+    "One": "Owner"
106
+  },
107
+  "Name": {
108
+    "One": "Name"
109
+  },
110
+  "Color": {
111
+    "One": "Color"
112
+  },
113
+  "CreatedAt": {
114
+    "One": "Created At"
115
+  },
116
+  "UpdatedAt": {
117
+    "One": "Updated At"
118
+  },
119
+  "Memory": {
120
+    "One": "Memory"
121
+  },
122
+  "Os": {
123
+    "One": "Os"
124
+  },
125
+  "Uuid": {
126
+    "One": "Uuid"
127
+  },
128
+  "Version": {
129
+    "One": "Version"
130
+  },
131
+  "Type": {
132
+    "One": "Type"
133
+  },
134
+  "Group": {
135
+    "One": "Group"
136
+  },
137
+  "CommonGroup": {
138
+    "One": "Common Group"
139
+  },
140
+  "CommonGroupNote": {
141
+    "One": "Only admins can see group members and their devices"
142
+  },
143
+  "SharedGroup": {
144
+    "One": "Shared Group"
145
+  },
146
+  "SharedGroupNote": {
147
+    "One": "All users can see group members and their devices"
148
+  },
149
+  "Nickname": {
150
+    "One": "Nickname"
151
+  },
152
+  "UserTags": {
153
+    "One": "User Tags"
154
+  },
155
+  "UserAddressBook": {
156
+    "One": "User Address Book"
157
+  },
158
+  "IsAdmin": {
159
+    "One": "Is Admin"
160
+  },
161
+  "PleaseInputNewPassword": {
162
+    "One": "Please input new password"
163
+  },
164
+  "AutoRegister": {
165
+    "One": "Auto Register"
166
+  },
167
+  "AutoRegisterNote": {
168
+    "One": "If Enable,An account will be automatically registered when a user logs in with OAuth without binding an existing account"
169
+  },
170
+  "ThirdName": {
171
+    "One": "Third Name"
172
+  },
173
+  "Close": {
174
+    "One": "Close"
175
+  },
176
+  "OauthBinding": {
177
+    "One": "You are authorizing the binding"
178
+  },
179
+  "OauthLogining": {
180
+    "One": "You are authorizing the login"
181
+  },
182
+  "OauthCloseNote": {
183
+    "One": "If it is not authorized by you, please close the page directly"
184
+  },
185
+  "OperationSuccessAndCloseAfter3Seconds": {
186
+    "One": "Operation Success,Close after 3 seconds"
187
+  },
188
+  "ConfirmOauth": {
189
+    "One": "Confirm Oauth"
190
+  },
191
+  "Device": {
192
+    "One": "Device"
193
+  },
194
+  "ChangeLang": {
195
+    "One": "切换中文"
196
+  },
197
+  "My": {
198
+    "One": "My"
199
+  },
200
+  "Info": {
201
+    "One": "Info"
202
+  },
203
+  "AddressBooks": {
204
+    "One": "Address Books"
205
+  },
206
+  "System": {
207
+    "One": "System"
208
+  },
209
+  "PeerManage": {
210
+    "One": "Peers"
211
+  },
212
+  "AddressBookManage": {
213
+    "One": "Address Books"
214
+  },
215
+  "GroupManage": {
216
+    "One": "Groups"
217
+  },
218
+  "UserManage": {
219
+    "One": "Users"
220
+  },
221
+  "UserAdd": {
222
+    "One": "User Add"
223
+  },
224
+  "UserEdit": {
225
+    "One": "User Edit"
226
+  },
227
+  "TagsManage": {
228
+    "One": "Tags"
229
+  },
230
+  "OauthManage": {
231
+    "One": "Oauth"
232
+  },
233
+  "LoginLog": {
234
+    "One": "Login Log"
235
+  }
236
+}

+ 236 - 0
src/utils/i18n/zh_CN.json

@@ -0,0 +1,236 @@
1
+{
2
+  "Login": {
3
+    "One": "登录"
4
+  },
5
+  "Logout": {
6
+    "One": "退出登录"
7
+  },
8
+  "Register": {
9
+    "One": "注册"
10
+  },
11
+  "Confirm": {
12
+    "One": "确认"
13
+  },
14
+  "Username": {
15
+    "One": "用户名"
16
+  },
17
+  "Password": {
18
+    "One": "密码"
19
+  },
20
+  "LoginSuccess": {
21
+    "One": "登录成功"
22
+  },
23
+  "ForgotPassword": {
24
+    "One": "忘记密码"
25
+  },
26
+  "ResetPassword": {
27
+    "One": "重置密码"
28
+  },
29
+  "ChangePassword": {
30
+    "One": "修改密码"
31
+  },
32
+  "Userinfo": {
33
+    "One": "用户信息"
34
+  },
35
+  "ParamRequired": {
36
+    "One": "{param} 是必须的"
37
+  },
38
+  "HasBind": {
39
+    "One": "已绑定"
40
+  },
41
+  "NoBind": {
42
+    "One": "未绑定"
43
+  },
44
+  "UnBind": {
45
+    "One": "解绑"
46
+  },
47
+  "ToBind": {
48
+    "One": "绑定"
49
+  },
50
+  "Confirm?": {
51
+    "One": "确定{param}?"
52
+  },
53
+  "Cancel": {
54
+    "One": "取消"
55
+  },
56
+  "Platform": {
57
+    "One": "平台"
58
+  },
59
+  "Status": {
60
+    "One": "状态"
61
+  },
62
+  "Actions": {
63
+    "One": "操作"
64
+  },
65
+  "Filter": {
66
+    "One": "筛选"
67
+  },
68
+  "Add": {
69
+    "One": "添加"
70
+  },
71
+  "Hostname": {
72
+    "One": "主机名"
73
+  },
74
+  "Alias": {
75
+    "One": "别名"
76
+  },
77
+  "Hash": {
78
+    "One": "哈希"
79
+  },
80
+  "Tags": {
81
+    "One": "标签"
82
+  },
83
+  "Edit": {
84
+    "One": "编辑"
85
+  },
86
+  "Delete": {
87
+    "One": "删除"
88
+  },
89
+  "Create": {
90
+    "One": "创建"
91
+  },
92
+  "Update": {
93
+    "One": "更新"
94
+  },
95
+  "LoginName": {
96
+    "One": "登录名"
97
+  },
98
+  "Submit": {
99
+    "One": "提交"
100
+  },
101
+  "OperationSuccess": {
102
+    "One": "操作成功"
103
+  },
104
+  "Owner": {
105
+    "One": "所有者"
106
+  },
107
+  "Name": {
108
+    "One": "名称"
109
+  },
110
+  "Color": {
111
+    "One": "颜色"
112
+  },
113
+  "CreatedAt": {
114
+    "One": "创建时间"
115
+  },
116
+  "UpdatedAt": {
117
+    "One": "更新时间"
118
+  },
119
+  "Memory": {
120
+    "One": "内存"
121
+  },
122
+  "Os": {
123
+    "One": "操作系统"
124
+  },
125
+  "Uuid": {
126
+    "One": "UUID"
127
+  },
128
+  "Version": {
129
+    "One": "版本"
130
+  },
131
+  "Type": {
132
+    "One": "类型"
133
+  },
134
+  "Group": {
135
+    "One": "组"
136
+  },
137
+  "CommonGroup": {
138
+    "One": "普通组"
139
+  },
140
+  "CommonGroupNote": {
141
+    "One": "只有管理员才能查看群组成员及其设备"
142
+  },
143
+  "SharedGroup": {
144
+    "One": "共享组"
145
+  },
146
+  "SharedGroupNote": {
147
+    "One": "所有用户都可以查看群组成员及其设备"
148
+  },
149
+  "Nickname": {
150
+    "One": "昵称"
151
+  },
152
+  "UserTags": {
153
+    "One": "用户标签"
154
+  },
155
+  "UserAddressBook": {
156
+    "One": "用户地址簿"
157
+  },
158
+  "IsAdmin": {
159
+    "One": "是否管理员"
160
+  },
161
+  "PleaseInputNewPassword": {
162
+    "One": "请输入新密码"
163
+  },
164
+  "AutoRegister": {
165
+    "One": "自动注册"
166
+  },
167
+  "AutoRegisterNote": {
168
+    "One": "如果启用,则当用户使用 OAuth 登录时,将自动注册一个帐户,而无需绑定现有帐户"
169
+  },
170
+  "ThirdName": {
171
+    "One": "第三方名称"
172
+  },
173
+  "Close": {
174
+    "One": "关闭"
175
+  },
176
+  "OauthBinding": {
177
+    "One": "您正在授权绑定"
178
+  },
179
+  "OauthLogining": {
180
+    "One": "您正在授权登录"
181
+  },
182
+  "OauthCloseNote": {
183
+    "One": "如不是您发起的授权,请直接关闭页面"
184
+  },
185
+  "OperationSuccessAndCloseAfter3Seconds": {
186
+    "One": "操作成功,3秒后将自动关闭页面"
187
+  },
188
+  "ConfirmOauth": {
189
+    "One": "确认授权"
190
+  },
191
+  "Device": {
192
+    "One": "设备"
193
+  },
194
+  "ChangeLang": {
195
+    "One": "ToEnglish"
196
+  },
197
+  "My": {
198
+    "One": "我的"
199
+  },
200
+  "Info": {
201
+    "One": "信息"
202
+  },
203
+  "AddressBooks": {
204
+    "One": "地址簿"
205
+  },
206
+  "System": {
207
+    "One": "系统"
208
+  },
209
+  "PeerManage": {
210
+    "One": "设备管理"
211
+  },
212
+  "AddressBookManage": {
213
+    "One": "地址簿管理"
214
+  },
215
+  "GroupManage": {
216
+    "One": "群组管理"
217
+  },
218
+  "UserManage": {
219
+    "One": "用户管理"
220
+  },
221
+  "UserAdd": {
222
+    "One": "用户添加"
223
+  },
224
+  "UserEdit": {
225
+    "One": "用户编辑"
226
+  },
227
+  "TagsManage": {
228
+    "One": "标签管理"
229
+  },
230
+  "OauthManage": {
231
+    "One": "Oauth管理"
232
+  },
233
+  "LoginLog": {
234
+    "One": "登录日志"
235
+  }
236
+}

+ 13 - 4
src/utils/request.js

@@ -3,6 +3,7 @@ import { ElMessage } from 'element-plus'
3 3
 import { getToken, removeToken } from '@/utils/auth'
4 4
 import { useUserStore } from '@/store/user'
5 5
 import { pinia } from '@/store'
6
+import { useAppStore } from '@/store/app'
6 7
 
7 8
 // create an axios instance
8 9
 const service = axios.create({
@@ -14,15 +15,23 @@ const service = axios.create({
14 15
 // request interceptor
15 16
 service.interceptors.request.use(
16 17
   config => {
18
+    if (!config.headers) {
19
+      config.headers = {}
20
+    }
17 21
     const userStore = useUserStore(pinia)
18 22
 
19 23
     const token = userStore.token || getToken()
20 24
     if (token) {
21
-      if (!config.headers) {
22
-        config.headers = {}
23
-      }
24 25
       config.headers['api-token'] = token
25 26
     }
27
+
28
+    const app = useAppStore()
29
+    const lang = app.setting.lang
30
+    if (lang) {
31
+      console.log('lang', lang)
32
+      config.headers['Accept-Language'] = lang
33
+    }
34
+
26 35
     return config
27 36
   },
28 37
   error => {
@@ -66,7 +75,7 @@ service.interceptors.response.use(
66 75
   error => {
67 76
     if (error.code === 'ECONNABORTED'
68 77
       && error.message.indexOf('timeout') > -1) {
69
-      error.message = '请求超时!'
78
+      error.message = 'Connection Time Out!'
70 79
     }
71 80
     ElMessage({
72 81
       message: error.message,

+ 7 - 6
src/views/address_book/index.js

@@ -1,7 +1,8 @@
1
-import { onActivated, onMounted, reactive, ref, watch } from 'vue'
1
+import { reactive, ref } from 'vue'
2 2
 import { create, list, remove, update } from '@/api/address_book'
3 3
 import { ElMessage, ElMessageBox } from 'element-plus'
4 4
 import { useRoute } from 'vue-router'
5
+import { T } from '@/utils/i18n'
5 6
 
6 7
 export function useRepositories () {
7 8
   const route = useRoute()
@@ -35,9 +36,9 @@ export function useRepositories () {
35 36
   }
36 37
 
37 38
   const del = async (row) => {
38
-    const cf = await ElMessageBox.confirm('确定删除么?', {
39
-      confirmButtonText: '确定',
40
-      cancelButtonText: '取消',
39
+    const cf = await ElMessageBox.confirm(T('Confirm?', { param: T('Delete') }), {
40
+      confirmButtonText: T('Confirm'),
41
+      cancelButtonText: T('Cancel'),
41 42
       type: 'warning',
42 43
     }).catch(_ => false)
43 44
     if (!cf) {
@@ -46,7 +47,7 @@ export function useRepositories () {
46 47
 
47 48
     const res = await remove({ row_id: row.row_id }).catch(_ => false)
48 49
     if (res) {
49
-      ElMessage.success('操作成功')
50
+      ElMessage.success(T('OperationSuccess'))
50 51
       getList()
51 52
     }
52 53
   }
@@ -110,7 +111,7 @@ export function useRepositories () {
110 111
     const api = formData.row_id ? update : create
111 112
     const res = await api(formData).catch(_ => false)
112 113
     if (res) {
113
-      ElMessage.success('操作成功')
114
+      ElMessage.success(T('OperationSuccess'))
114 115
       formVisible.value = false
115 116
       getList()
116 117
     }

+ 27 - 29
src/views/address_book/index.vue

@@ -1,8 +1,8 @@
1 1
 <template>
2 2
   <div>
3 3
     <el-card class="list-query" shadow="hover">
4
-      <el-form inline label-width="60px">
5
-        <el-form-item label="用户">
4
+      <el-form inline label-width="80px">
5
+        <el-form-item :label="T('Owner')">
6 6
           <el-select v-model="listQuery.user_id" clearable>
7 7
             <el-option
8 8
                 v-for="item in allUsers"
@@ -13,8 +13,8 @@
13 13
           </el-select>
14 14
         </el-form-item>
15 15
         <el-form-item>
16
-          <el-button type="primary" @click="handlerQuery">筛选</el-button>
17
-          <el-button type="danger" @click="toAdd">添加</el-button>
16
+          <el-button type="primary" @click="handlerQuery">{{ T('Filter') }}</el-button>
17
+          <el-button type="danger" @click="toAdd">{{ T('Add') }}</el-button>
18 18
         </el-form-item>
19 19
       </el-form>
20 20
     </el-card>
@@ -22,24 +22,24 @@
22 22
       <!--      <el-tag type="danger" style="margin-bottom: 10px">不建议在此操作地址簿,可能会造成数据不同步</el-tag>-->
23 23
       <el-table :data="listRes.list" v-loading="listRes.loading" border>
24 24
         <el-table-column prop="id" label="id" align="center"/>
25
-        <el-table-column label="所属用户" align="center">
25
+        <el-table-column :label="T('Owner')" align="center">
26 26
           <template #default="{row}">
27 27
             <span v-if="row.user_id"> <el-tag>{{ allUsers?.find(u => u.id === row.user_id)?.username }}</el-tag> </span>
28 28
           </template>
29 29
         </el-table-column>
30
-        <el-table-column prop="username" label="用户名" align="center"/>
31
-        <el-table-column prop="hostname" label="主机名" align="center"/>
32
-        <el-table-column prop="alias" label="别名" align="center"/>
33
-        <el-table-column prop="platform" label="平台" align="center"/>
34
-        <el-table-column prop="hash" label="hash" align="center"/>
35
-        <el-table-column prop="tags" label="标签" align="center"/>
30
+        <el-table-column prop="username" :label="T('Username')" align="center"/>
31
+        <el-table-column prop="hostname" :label="T('Hostname')" align="center"/>
32
+        <el-table-column prop="alias" :label="T('Alias')" align="center"/>
33
+        <el-table-column prop="platform" :label="T('Platform')" align="center"/>
34
+        <el-table-column prop="hash" :label="T('Hash')" align="center"/>
35
+        <el-table-column prop="tags" :label="T('Tags')" align="center"/>
36 36
         <!--        <el-table-column prop="created_at" label="创建时间" align="center"/>-->
37 37
         <!--        <el-table-column prop="updated_at" label="更新时间" align="center"/>-->
38 38
         <el-table-column label="操作" align="center" width="400">
39 39
           <template #default="{row}">
40 40
             <el-button type="success" @click="toWebClientLink(row)">Web-Client</el-button>
41
-            <el-button @click="toEdit(row)">编辑</el-button>
42
-            <el-button type="danger" @click="del(row)">删除</el-button>
41
+            <el-button @click="toEdit(row)">{{ T('Edit') }}</el-button>
42
+            <el-button type="danger" @click="del(row)">{{ T('Delete') }}</el-button>
43 43
           </template>
44 44
         </el-table-column>
45 45
       </el-table>
@@ -53,9 +53,9 @@
53 53
                      :total="listRes.total">
54 54
       </el-pagination>
55 55
     </el-card>
56
-    <el-dialog v-model="formVisible" width="800" :title="!formData.row_id?'创建':'修改'">
56
+    <el-dialog v-model="formVisible" width="800" :title="!formData.row_id?T('Create') :T('Update') ">
57 57
       <el-form class="dialog-form" ref="form" :model="formData" label-width="120px">
58
-        <el-form-item label="用户" prop="user_id" required>
58
+        <el-form-item :label="T('Owner')" prop="user_id" required>
59 59
           <el-select v-model="formData.user_id" @change="changeUser">
60 60
             <el-option
61 61
                 v-for="item in allUsers"
@@ -68,25 +68,25 @@
68 68
         <el-form-item label="id" prop="id" required>
69 69
           <el-input v-model="formData.id"></el-input>
70 70
         </el-form-item>
71
-        <el-form-item label="用户名" prop="username">
71
+        <el-form-item :label="T('Username')" prop="username">
72 72
           <el-input v-model="formData.username"></el-input>
73 73
         </el-form-item>
74
-        <el-form-item label="别名" prop="alias">
74
+        <el-form-item :label="T('Alias')" prop="alias">
75 75
           <el-input v-model="formData.alias"></el-input>
76 76
         </el-form-item>
77
-        <el-form-item label="hash" prop="hash">
77
+        <el-form-item :label="T('Hash')" prop="hash">
78 78
           <el-input v-model="formData.hash"></el-input>
79 79
         </el-form-item>
80
-        <el-form-item label="主机名" prop="hostname">
80
+        <el-form-item :label="T('Hostname')" prop="hostname">
81 81
           <el-input v-model="formData.hostname"></el-input>
82 82
         </el-form-item>
83
-        <el-form-item label="登录名" prop="login_name">
84
-          <el-input v-model="formData.login_name"></el-input>
83
+        <el-form-item :label="T('LoginName')" prop="loginName">
84
+          <el-input v-model="formData.loginName"></el-input>
85 85
         </el-form-item>
86
-        <el-form-item label="密码" prop="password">
86
+        <el-form-item :label="T('Password')" prop="password">
87 87
           <el-input v-model="formData.password"></el-input>
88 88
         </el-form-item>
89
-        <el-form-item label="平台" prop="platform">
89
+        <el-form-item :label="T('Platform')" prop="platform">
90 90
           <el-select v-model="formData.platform">
91 91
             <el-option
92 92
                 v-for="item in platformList"
@@ -97,7 +97,7 @@
97 97
           </el-select>
98 98
         </el-form-item>
99 99
 
100
-        <el-form-item label="标签" prop="tags">
100
+        <el-form-item :label="T('Tags')" prop="tags">
101 101
           <el-select v-model="formData.tags" multiple>
102 102
             <el-option
103 103
                 v-for="item in tagList"
@@ -125,8 +125,8 @@
125 125
 
126 126
 
127 127
         <el-form-item>
128
-          <el-button @click="formVisible = false">取消</el-button>
129
-          <el-button @click="submit" type="primary">提交</el-button>
128
+          <el-button @click="formVisible = false">{{ T('Cancel') }}</el-button>
129
+          <el-button @click="submit" type="primary">{{ T('Submit') }}</el-button>
130 130
         </el-form-item>
131 131
       </el-form>
132 132
     </el-dialog>
@@ -135,13 +135,11 @@
135 135
 
136 136
 <script setup>
137 137
   import { onActivated, onMounted, reactive, ref, watch } from 'vue'
138
-  import { create, list, remove, update } from '@/api/address_book'
139 138
   import { list as fetchTagList } from '@/api/tag'
140
-  import { ElMessage, ElMessageBox } from 'element-plus'
141 139
   import { loadAllUsers } from '@/global'
142
-  import { useRoute } from 'vue-router'
143 140
   import { useRepositories } from '@/views/address_book/index'
144 141
   import { toWebClientLink } from '@/utils/webclient'
142
+  import { T } from '@/utils/i18n'
145 143
 
146 144
   const { allUsers, getAllUsers } = loadAllUsers()
147 145
   getAllUsers()

+ 22 - 21
src/views/group/index.vue

@@ -1,26 +1,26 @@
1 1
 <template>
2 2
   <div>
3 3
     <el-card class="list-query" shadow="hover">
4
-      <el-form inline label-width="60px">
4
+      <el-form inline label-width="80px">
5 5
         <!--        <el-form-item label="名称">
6 6
                   <el-input v-model="listQuery.name"></el-input>
7 7
                 </el-form-item>-->
8 8
         <el-form-item>
9
-          <el-button type="primary" @click="handlerQuery">筛选</el-button>
10
-          <el-button type="danger" @click="toAdd">添加</el-button>
9
+          <el-button type="primary" @click="handlerQuery">{{ T('Filter') }}</el-button>
10
+          <el-button type="danger" @click="toAdd">{{ T('Add') }}</el-button>
11 11
         </el-form-item>
12 12
       </el-form>
13 13
     </el-card>
14 14
     <el-card class="list-body" shadow="hover">
15 15
       <el-table :data="listRes.list" v-loading="listRes.loading" border>
16 16
         <el-table-column prop="id" label="id" align="center"></el-table-column>
17
-        <el-table-column prop="name" label="名称" align="center"/>
18
-        <el-table-column prop="created_at" label="创建时间" align="center"/>
19
-        <el-table-column prop="updated_at" label="更新时间" align="center"/>
20
-        <el-table-column label="操作" align="center">
17
+        <el-table-column prop="name" :label="T('Name')" align="center"/>
18
+        <el-table-column prop="created_at" :label="T('CreatedAt')" align="center"/>
19
+        <el-table-column prop="updated_at" :label="T('UpdatedAt')" align="center"/>
20
+        <el-table-column :label="T('Actions')" align="center">
21 21
           <template #default="{row}">
22
-            <el-button @click="toEdit(row)">编辑</el-button>
23
-            <el-button type="danger" @click="del(row)">删除</el-button>
22
+            <el-button @click="toEdit(row)">{{ T('Edit') }}</el-button>
23
+            <el-button type="danger" @click="del(row)">{{ T('Delete') }}</el-button>
24 24
           </template>
25 25
         </el-table-column>
26 26
       </el-table>
@@ -34,12 +34,12 @@
34 34
                      :total="listRes.total">
35 35
       </el-pagination>
36 36
     </el-card>
37
-    <el-dialog v-model="formVisible" :title="!formData.id?'创建':'修改'" width="800">
37
+    <el-dialog v-model="formVisible" :title="!formData.id?T('Create'):T('Update')" width="800">
38 38
       <el-form class="dialog-form" ref="form" :model="formData" label-width="120px">
39
-        <el-form-item label="名称" prop="name" required>
39
+        <el-form-item :label="T('Name')" prop="name" required>
40 40
           <el-input v-model="formData.name"></el-input>
41 41
         </el-form-item>
42
-        <el-form-item label="类型" prop="type" required>
42
+        <el-form-item :label="T('Type')" prop="type" required>
43 43
           <el-radio-group v-model="formData.type">
44 44
             <el-radio v-for="item in groupTypes" :key="item.value" :label="item.value" style="display: block">
45 45
               {{ item.label }}
@@ -48,8 +48,8 @@
48 48
           </el-radio-group>
49 49
         </el-form-item>
50 50
         <el-form-item>
51
-          <el-button @click="formVisible = false">取消</el-button>
52
-          <el-button @click="submit" type="primary">提交</el-button>
51
+          <el-button @click="formVisible = false">{{ T('Cancel') }}</el-button>
52
+          <el-button @click="submit" type="primary">{{ T('Submit') }}</el-button>
53 53
         </el-form-item>
54 54
       </el-form>
55 55
     </el-dialog>
@@ -60,6 +60,7 @@
60 60
   import { onMounted, reactive, watch, ref, onActivated } from 'vue'
61 61
   import { list, create, update, detail, remove } from '@/api/group'
62 62
   import { ElMessage, ElMessageBox } from 'element-plus'
63
+  import { T } from '@/utils/i18n'
63 64
 
64 65
   const listRes = reactive({
65 66
     list: [], total: 0, loading: false,
@@ -87,9 +88,9 @@
87 88
   }
88 89
 
89 90
   const del = async (row) => {
90
-    const cf = await ElMessageBox.confirm('确定删除么?', {
91
-      confirmButtonText: '确定',
92
-      cancelButtonText: '取消',
91
+    const cf = await ElMessageBox.confirm(T('Confirm?', { param: T('Delete') }), {
92
+      confirmButtonText: T('Confirm'),
93
+      cancelButtonText: T('Cancel'),
93 94
       type: 'warning',
94 95
     }).catch(_ => false)
95 96
     if (!cf) {
@@ -98,7 +99,7 @@
98 99
 
99 100
     const res = await remove({ id: row.id }).catch(_ => false)
100 101
     if (res) {
101
-      ElMessage.success('操作成功')
102
+      ElMessage.success(T('OperationSuccess'))
102 103
       getList()
103 104
     }
104 105
   }
@@ -110,8 +111,8 @@
110 111
   watch(() => listQuery.page_size, handlerQuery)
111 112
 
112 113
   const groupTypes = [
113
-    { label: '普通组', value: 1, note: '只有管理员能看到小组成员和成员的设备' },
114
-    { label: '共享组', value: 2, note: '所有用户都能看到小组成员和成员的设备' },
114
+    { label: T('CommonGroup'), value: 1, note: T('CommonGroupNote') },
115
+    { label: T('SharedGroup'), value: 2, note: T('SharedGroupNote') },
115 116
   ]
116 117
   const formVisible = ref(false)
117 118
   const formData = reactive({
@@ -136,7 +137,7 @@
136 137
     const api = formData.id ? update : create
137 138
     const res = await api(formData).catch(_ => false)
138 139
     if (res) {
139
-      ElMessage.success('操作成功')
140
+      ElMessage.success(T('OperationSuccess'))
140 141
       formVisible.value = false
141 142
       getList()
142 143
     }

+ 1 - 1
src/views/login/log.vue

@@ -1,7 +1,7 @@
1 1
 <template>
2 2
   <div>
3 3
     <el-card class="list-query" shadow="hover">
4
-      <el-form inline label-width="60px">
4
+      <el-form inline label-width="80px">
5 5
         <el-form-item label="用户">
6 6
           <el-select v-model="listQuery.user_id" clearable>
7 7
             <el-option

+ 32 - 40
src/views/login/login.vue

@@ -1,65 +1,57 @@
1 1
 <template>
2 2
   <div class="login">
3 3
     <el-card class="login-card">
4
-      <h1>登录</h1>
5
-      <el-form label-width="60px">
6
-        <el-form-item label="用户名">
4
+      <h1>{{ T('Login') }}</h1>
5
+      <el-form label-width="100px">
6
+        <el-form-item :label=" T('Username') ">
7 7
           <el-input v-model="form.username"></el-input>
8 8
         </el-form-item>
9
-        <el-form-item label="密码">
9
+        <el-form-item :label=" T('Password') ">
10 10
           <el-input v-model="form.password" type="password" @keyup.enter.native="login" show-password></el-input>
11 11
         </el-form-item>
12 12
         <el-form-item>
13
-          <el-button @click="login" type="primary">登录</el-button>
13
+          <el-button @click="login" type="primary">{{ T('Login') }}</el-button>
14 14
         </el-form-item>
15 15
       </el-form>
16 16
     </el-card>
17 17
   </div>
18 18
 </template>
19 19
 
20
-<script>
20
+<script setup>
21 21
   import { defineComponent, reactive } from 'vue'
22 22
   import { useUserStore } from '@/store/user'
23 23
   import { ElMessage } from 'element-plus'
24 24
   import { useRoute, useRouter } from 'vue-router'
25
+  import { T } from '@/utils/i18n'
25 26
 
26
-  export default defineComponent({
27
-    setup (props) {
28
-      const userStore = useUserStore()
29
-      const route = useRoute()
30
-      const router = useRouter()
27
+  const userStore = useUserStore()
28
+  const route = useRoute()
29
+  const router = useRouter()
31 30
 
32
-      let platform = window.navigator.platform
33
-      if (navigator.platform.indexOf('Mac') === 0) {
34
-        platform = 'mac'
35
-      } else if (navigator.platform.indexOf('Win') === 0) {
36
-        platform = 'windows'
37
-      } else if (navigator.platform.indexOf('Linux armv') === 0) {
38
-        platform = 'android'
39
-      } else if (navigator.platform.indexOf('Linux') === 0) {
40
-        platform = 'linux'
41
-      }
31
+  let platform = window.navigator.platform
32
+  if (navigator.platform.indexOf('Mac') === 0) {
33
+    platform = 'mac'
34
+  } else if (navigator.platform.indexOf('Win') === 0) {
35
+    platform = 'windows'
36
+  } else if (navigator.platform.indexOf('Linux armv') === 0) {
37
+    platform = 'android'
38
+  } else if (navigator.platform.indexOf('Linux') === 0) {
39
+    platform = 'linux'
40
+  }
42 41
 
43
-      const form = reactive({
44
-        username: '',
45
-        password: '',
46
-        platform: platform,
47
-      })
48
-      const redirect = route.query?.redirect
49
-      const login = async () => {
50
-        const res = await userStore.login(form)
51
-        if (res) {
52
-          ElMessage.success('登录成功')
53
-          router.push({ path: redirect || '/', replace: true })
54
-        }
55
-      }
56
-      return {
57
-        redirect,
58
-        form,
59
-        login,
60
-      }
61
-    },
42
+  const form = reactive({
43
+    username: '',
44
+    password: '',
45
+    platform: platform,
62 46
   })
47
+  const redirect = route.query?.redirect
48
+  const login = async () => {
49
+    const res = await userStore.login(form)
50
+    if (res) {
51
+      ElMessage.success(T('LoginSuccess'))
52
+      router.push({ path: redirect || '/', replace: true })
53
+    }
54
+  }
63 55
 </script>
64 56
 
65 57
 <style scoped lang="scss">

+ 25 - 50
src/views/my/address_book/index.vue

@@ -1,10 +1,10 @@
1 1
 <template>
2 2
   <div>
3 3
     <el-card class="list-query" shadow="hover">
4
-      <el-form inline label-width="60px">
4
+      <el-form inline label-width="80px">
5 5
         <el-form-item>
6
-          <el-button type="primary" @click="handlerQuery">筛选</el-button>
7
-          <el-button type="danger" @click="toAdd">添加</el-button>
6
+          <el-button type="primary" @click="handlerQuery">{{ T('Filter') }}</el-button>
7
+          <el-button type="danger" @click="toAdd">{{ T('Add') }}</el-button>
8 8
         </el-form-item>
9 9
       </el-form>
10 10
     </el-card>
@@ -12,19 +12,19 @@
12 12
       <!--      <el-tag type="danger" style="margin-bottom: 10px">不建议在此操作地址簿,可能会造成数据不同步</el-tag>-->
13 13
       <el-table :data="listRes.list" v-loading="listRes.loading" border>
14 14
         <el-table-column prop="id" label="id" align="center"/>
15
-        <el-table-column prop="username" label="用户名" align="center"/>
16
-        <el-table-column prop="hostname" label="主机名" align="center"/>
17
-        <el-table-column prop="alias" label="别名" align="center"/>
18
-        <el-table-column prop="platform" label="平台" align="center"/>
19
-        <el-table-column prop="hash" label="hash" align="center"/>
20
-        <el-table-column prop="tags" label="标签" align="center"/>
15
+        <el-table-column prop="username" :label="T('Username')" align="center"/>
16
+        <el-table-column prop="hostname" :label="T('Hostname')" align="center"/>
17
+        <el-table-column prop="alias" :label="T('Alias')" align="center"/>
18
+        <el-table-column prop="platform" :label="T('Platform')" align="center"/>
19
+        <el-table-column prop="hash" :label="T('Hash')" align="center"/>
20
+        <el-table-column prop="tags" :label="T('Tags')" align="center"/>
21 21
         <!--        <el-table-column prop="created_at" label="创建时间" align="center"/>-->
22 22
         <!--        <el-table-column prop="updated_at" label="更新时间" align="center"/>-->
23
-        <el-table-column label="操作" align="center" width="400">
23
+        <el-table-column :label="T('Actions')" align="center" width="400">
24 24
           <template #default="{row}">
25 25
             <el-button type="success" @click="toWebClientLink(row)">Web-Client</el-button>
26
-            <el-button @click="toEdit(row)">编辑</el-button>
27
-            <el-button type="danger" @click="del(row)">删除</el-button>
26
+            <el-button @click="toEdit(row)">{{ T('Edit') }}</el-button>
27
+            <el-button type="danger" @click="del(row)">{{ T('Delete') }}</el-button>
28 28
           </template>
29 29
         </el-table-column>
30 30
       </el-table>
@@ -38,30 +38,30 @@
38 38
                      :total="listRes.total">
39 39
       </el-pagination>
40 40
     </el-card>
41
-    <el-dialog v-model="formVisible" width="800" :title="!formData.row_id?'创建':'修改'">
41
+    <el-dialog v-model="formVisible" width="800" :title="!formData.row_id?T('Create') :T('Update') ">
42 42
       <el-form class="dialog-form" ref="form" :model="formData" label-width="120px">
43 43
         <el-form-item label="id" prop="id" required>
44 44
           <el-input v-model="formData.id"></el-input>
45 45
         </el-form-item>
46
-        <el-form-item label="用户名" prop="username">
46
+        <el-form-item :label="T('Username')" prop="username">
47 47
           <el-input v-model="formData.username"></el-input>
48 48
         </el-form-item>
49
-        <el-form-item label="别名" prop="alias">
49
+        <el-form-item :label="T('Alias')" prop="alias">
50 50
           <el-input v-model="formData.alias"></el-input>
51 51
         </el-form-item>
52
-        <el-form-item label="hash" prop="hash">
52
+        <el-form-item :label="T('Hash')" prop="hash">
53 53
           <el-input v-model="formData.hash"></el-input>
54 54
         </el-form-item>
55
-        <el-form-item label="主机名" prop="hostname">
55
+        <el-form-item :label="T('Hostname')" prop="hostname">
56 56
           <el-input v-model="formData.hostname"></el-input>
57 57
         </el-form-item>
58
-        <el-form-item label="登录名" prop="login_name">
59
-          <el-input v-model="formData.login_name"></el-input>
58
+        <el-form-item :label="T('LoginName')" prop="loginName">
59
+          <el-input v-model="formData.loginName"></el-input>
60 60
         </el-form-item>
61
-        <el-form-item label="密码" prop="password">
61
+        <el-form-item :label="T('Password')" prop="password">
62 62
           <el-input v-model="formData.password"></el-input>
63 63
         </el-form-item>
64
-        <el-form-item label="平台" prop="platform">
64
+        <el-form-item :label="T('Platform')" prop="platform">
65 65
           <el-select v-model="formData.platform">
66 66
             <el-option
67 67
                 v-for="item in platformList"
@@ -72,7 +72,7 @@
72 72
           </el-select>
73 73
         </el-form-item>
74 74
 
75
-        <el-form-item label="标签" prop="tags">
75
+        <el-form-item :label="T('Tags')" prop="tags">
76 76
           <el-select v-model="formData.tags" multiple>
77 77
             <el-option
78 78
                 v-for="item in tagList"
@@ -100,8 +100,8 @@
100 100
 
101 101
 
102 102
         <el-form-item>
103
-          <el-button @click="formVisible = false">取消</el-button>
104
-          <el-button @click="submit" type="primary">提交</el-button>
103
+          <el-button @click="formVisible = false">{{ T('Cancel') }}</el-button>
104
+          <el-button @click="submit" type="primary">{{ T('Submit') }}</el-button>
105 105
         </el-form-item>
106 106
       </el-form>
107 107
     </el-dialog>
@@ -110,10 +110,10 @@
110 110
 
111 111
 <script setup>
112 112
   import { onActivated, onMounted, reactive, ref, watch } from 'vue'
113
-  import { create, list, remove, update } from '@/api/address_book'
114 113
   import { list as fetchTagList } from '@/api/tag'
115 114
   import { useRepositories } from '@/views/address_book'
116 115
   import { toWebClientLink } from '@/utils/webclient'
116
+  import { T } from '@/utils/i18n'
117 117
 
118 118
   const tagList = ref([])
119 119
   const fetchTagListData = async () => {
@@ -136,8 +136,6 @@
136 136
     toEdit,
137 137
     toAdd,
138 138
     submit,
139
-    activeChange,
140
-    currentColor,
141 139
   } = useRepositories()
142 140
 
143 141
   listQuery.is_my = 1
@@ -149,29 +147,6 @@
149 147
 
150 148
   watch(() => listQuery.page_size, handlerQuery)
151 149
 
152
-  /*watch(() => listRes.list, () => {
153
-        const peers = {}
154
-        listRes.list.map(item => {
155
-          peers[item.id] = {
156
-            'view-style': 'shrink',
157
-            tm: new Date().getTime(),
158
-            info: {
159
-              'id': item.id,
160
-              'username': item.username,
161
-              'hostname': item.hostname,
162
-              'alias': item.alias,
163
-              'platform': item.platform,
164
-              'hash': item.hash,
165
-              'tags': item.tags,
166
-            },
167
-          }
168
-        })
169
-        localStorage.setItem('peers', JSON.stringify(peers))
170
-      },
171
-      {
172
-        immediate: true,
173
-      })*/
174
-
175 150
 </script>
176 151
 
177 152
 <style scoped lang="scss">

+ 15 - 14
src/views/my/info.vue

@@ -1,26 +1,26 @@
1 1
 <template>
2 2
   <div>
3
-    <el-card title="个人信息">
3
+    <el-card :title="T('Userinfo')">
4 4
       <el-form class="info-form" ref="form" label-width="120px" label-suffix=":">
5
-        <el-form-item label="用户名">
5
+        <el-form-item :label="T('Username')">
6 6
           <div>{{ userStore.username }}</div>
7 7
         </el-form-item>
8
-        <el-form-item label="密码" prop="password">
9
-          <el-button type="danger" @click="showChangePwd">修改密码</el-button>
8
+        <el-form-item :label="T('Password')" prop="password">
9
+          <el-button type="danger" @click="showChangePwd">{{ T('ChangePassword') }}</el-button>
10 10
         </el-form-item>
11 11
         <el-form-item label="OIDC">
12 12
           <el-table :data="oidcData" border fit>
13
-            <el-table-column label="平台" prop="third_type" align="center"></el-table-column>
14
-            <el-table-column label="状态" prop="status" align="center">
13
+            <el-table-column :label="T('Platform')" prop="third_type" align="center"></el-table-column>
14
+            <el-table-column :label="T('Status')" prop="status" align="center">
15 15
               <template #default="{ row }">
16
-                <el-tag v-if="row.status === 1" type="success">已绑定</el-tag>
17
-                <el-tag v-else type="danger">未绑定</el-tag>
16
+                <el-tag v-if="row.status === 1" type="success">{{ T('HasBind') }}</el-tag>
17
+                <el-tag v-else type="danger">{{ T('NoBind') }}</el-tag>
18 18
               </template>
19 19
             </el-table-column>
20
-            <el-table-column label="操作" align="center" width="200">
20
+            <el-table-column :label="T('Actions')" align="center" width="200">
21 21
               <template #default="{ row }">
22
-                <el-button v-if="row.status === 1" type="danger" size="small" @click="toUnBind(row)">解除绑定</el-button>
23
-                <el-button v-else type="success" size="small" @click="toBind(row)">去绑定</el-button>
22
+                <el-button v-if="row.status === 1" type="danger" size="small" @click="toUnBind(row)">{{ T('UnBind') }}</el-button>
23
+                <el-button v-else type="success" size="small" @click="toBind(row)">{{ T('ToBind') }}</el-button>
24 24
               </template>
25 25
             </el-table-column>
26 26
           </el-table>
@@ -38,6 +38,7 @@
38 38
   import { bind, unbind } from '@/api/oauth'
39 39
   import { myOauth } from '@/api/user'
40 40
   import { ElMessageBox } from 'element-plus'
41
+  import { T } from '@/utils/i18n'
41 42
 
42 43
   const userStore = useUserStore()
43 44
   const changePwdVisible = ref(false)
@@ -61,9 +62,9 @@
61 62
     }
62 63
   }
63 64
   const toUnBind = async (row) => {
64
-    const cf = await ElMessageBox.confirm('确定解除绑定么?', {
65
-      confirmButtonText: '确定',
66
-      cancelButtonText: '取消',
65
+    const cf = await ElMessageBox.confirm(T('Confirm?', { param: T('UnBind') }), {
66
+      confirmButtonText: T('Confirm'),
67
+      cancelButtonText: T('Cancel'),
67 68
       type: 'warning',
68 69
     }).catch(_ => false)
69 70
     if (!cf) {

+ 15 - 14
src/views/my/tag/index.vue

@@ -1,18 +1,18 @@
1 1
 <template>
2 2
   <div>
3 3
     <el-card class="list-query" shadow="hover">
4
-      <el-form inline label-width="60px">
4
+      <el-form inline label-width="80px">
5 5
         <el-form-item>
6
-          <el-button type="primary" @click="handlerQuery">筛选</el-button>
7
-          <el-button type="danger" @click="toAdd">添加</el-button>
6
+          <el-button type="primary" @click="handlerQuery">{{ T('Filter') }}</el-button>
7
+          <el-button type="danger" @click="toAdd">{{ T('Add') }}</el-button>
8 8
         </el-form-item>
9 9
       </el-form>
10 10
     </el-card>
11 11
     <el-card class="list-body" shadow="hover">
12 12
       <el-table :data="listRes.list" v-loading="listRes.loading" border>
13 13
         <el-table-column prop="id" label="id" align="center"/>
14
-        <el-table-column prop="name" label="名称" align="center"/>
15
-        <el-table-column prop="color" label="颜色" align="center">
14
+        <el-table-column prop="name" :label="T('Name')" align="center"/>
15
+        <el-table-column prop="color" :label="T('Color')" align="center">
16 16
           <template #default="{row}">
17 17
             <div class="colors">
18 18
               <div style="background-color: #efeff2" class="colorbox">
@@ -26,12 +26,12 @@
26 26
             </div>
27 27
           </template>
28 28
         </el-table-column>
29
-        <el-table-column prop="created_at" label="创建时间" align="center"/>
30
-        <el-table-column prop="updated_at" label="更新时间" align="center"/>
29
+        <el-table-column prop="created_at" :label="T('CreatedAt')" align="center"/>
30
+        <el-table-column prop="updated_at" :label="T('UpdatedAt')" align="center"/>
31 31
         <el-table-column label="操作" align="center">
32 32
           <template #default="{row}">
33
-            <el-button @click="toEdit(row)">编辑</el-button>
34
-            <el-button type="danger" @click="del(row)">删除</el-button>
33
+            <el-button @click="toEdit(row)">{{ T('Edit') }}</el-button>
34
+            <el-button type="danger" @click="del(row)">{{ T('Delete') }}</el-button>
35 35
           </template>
36 36
         </el-table-column>
37 37
       </el-table>
@@ -45,12 +45,12 @@
45 45
                      :total="listRes.total">
46 46
       </el-pagination>
47 47
     </el-card>
48
-    <el-dialog v-model="formVisible" :title="!formData.id?'创建':'修改'" width="800">
48
+    <el-dialog v-model="formVisible" :title="!formData.id?T('Create'):T('Update')" width="800">
49 49
       <el-form class="dialog-form" ref="form" :model="formData" label-width="120px">
50
-        <el-form-item label="名称" prop="name" required>
50
+        <el-form-item :label="T('Name')" prop="name" required>
51 51
           <el-input v-model="formData.name"></el-input>
52 52
         </el-form-item>
53
-        <el-form-item label="颜色" prop="color" required>
53
+        <el-form-item :label="T('Color')" prop="color" required>
54 54
           <el-color-picker v-model="formData.color" show-alpha @active-change="activeChange"></el-color-picker>
55 55
           <br>
56 56
           <div class="colors">
@@ -65,8 +65,8 @@
65 65
           </div>
66 66
         </el-form-item>
67 67
         <el-form-item>
68
-          <el-button @click="formVisible = false">取消</el-button>
69
-          <el-button @click="submit" type="primary">提交</el-button>
68
+          <el-button @click="formVisible = false">{{ T('Cancel') }}</el-button>
69
+          <el-button @click="submit" type="primary">{{ T('Submit') }}</el-button>
70 70
         </el-form-item>
71 71
       </el-form>
72 72
     </el-dialog>
@@ -76,6 +76,7 @@
76 76
 <script setup>
77 77
   import { onMounted, watch, onActivated } from 'vue'
78 78
   import { useRepositories } from '@/views/tag'
79
+  import { T } from '@/utils/i18n'
79 80
 
80 81
   const {
81 82
     listRes,

+ 8 - 7
src/views/oauth/bind.vue

@@ -1,22 +1,22 @@
1 1
 <template>
2 2
   <div class="oauth">
3 3
     <el-card class="card">
4
-      <h2>您正在授权绑定</h2>
4
+      <h2>{{ T('OauthBinding') }}</h2>
5 5
       <el-form class="info" label-width="100px">
6
-        <el-form-item label="平台">
6
+        <el-form-item :label="T('Op')">
7 7
           <div class="impt">{{ oauthInfo.op }}</div>
8 8
         </el-form-item>
9
-        <el-form-item label="用户名">
9
+        <el-form-item :label="T('ThirdName')">
10 10
           <div class="impt">{{ oauthInfo.third_name }}</div>
11 11
         </el-form-item>
12 12
         <el-form-item label-width="0">
13
-          <el-button style="width: 100%" v-if="!resStatus" type="success" size="large" @click="toConfirm">绑定</el-button>
13
+          <el-button style="width: 100%" v-if="!resStatus" type="success" size="large" @click="toConfirm">{{ T('Bind') }}</el-button>
14 14
         </el-form-item>
15 15
         <el-form-item label-width="0">
16
-          <el-button style="width: 100%" size="large" @click="out">关闭页面</el-button>
16
+          <el-button style="width: 100%" size="large" @click="out">{{ T('Close') }}</el-button>
17 17
         </el-form-item>
18 18
       </el-form>
19
-      如果不是您操作的授权,请直接关闭页面
19
+      {{ T('OauthCloseNote') }}
20 20
     </el-card>
21 21
   </div>
22 22
 </template>
@@ -26,6 +26,7 @@
26 26
   import { info, confirm, bindConfirm } from '@/api/oauth'
27 27
   import { useRoute, useRouter } from 'vue-router'
28 28
   import { ElMessage } from 'element-plus'
29
+  import { T } from '@/utils/i18n'
29 30
 
30 31
   const oauthInfo = ref({})
31 32
   const route = useRoute()
@@ -48,7 +49,7 @@
48 49
     const res = await bindConfirm({ code }).catch(_ => false)
49 50
     if (res) {
50 51
       resStatus.value = 1
51
-      ElMessage.success('操作成功,3秒后将自动关闭本页面')
52
+      ElMessage.success(T('OperationSuccessAndCloseAfter3Seconds'))
52 53
       setTimeout(_ => {
53 54
         out()
54 55
       }, 3000)

+ 27 - 26
src/views/oauth/index.vue

@@ -1,24 +1,24 @@
1 1
 <template>
2 2
   <div>
3 3
     <el-card class="list-query" shadow="hover">
4
-      <el-form inline label-width="60px">
4
+      <el-form inline label-width="80px">
5 5
         <el-form-item>
6
-          <el-button type="primary" @click="handlerQuery">筛选</el-button>
7
-          <el-button type="danger" @click="toAdd">添加</el-button>
6
+          <el-button type="primary" @click="handlerQuery">{{ T('Filter') }}</el-button>
7
+          <el-button type="danger" @click="toAdd">{{ T('Add') }}</el-button>
8 8
         </el-form-item>
9 9
       </el-form>
10 10
     </el-card>
11 11
     <el-card class="list-body" shadow="hover">
12 12
       <el-table :data="listRes.list" v-loading="listRes.loading" border>
13 13
         <el-table-column prop="id" label="id" align="center"/>
14
-        <el-table-column prop="op" label="名称" align="center"/>
15
-        <el-table-column prop="auto_register" label="自动注册" align="center"/>
16
-        <el-table-column prop="created_at" label="创建时间" align="center"/>
17
-        <el-table-column prop="updated_at" label="更新时间" align="center"/>
18
-        <el-table-column label="操作" align="center">
14
+        <el-table-column prop="op" :label="T('Op')" align="center"/>
15
+        <el-table-column prop="auto_register" :label="T('AutoRegister')" align="center"/>
16
+        <el-table-column prop="created_at" :label="T('CreatedAt')" align="center"/>
17
+        <el-table-column prop="updated_at" :label="T('UpdatedAt')" align="center"/>
18
+        <el-table-column :label="T('Actions')" align="center">
19 19
           <template #default="{row}">
20
-            <el-button @click="toEdit(row)">编辑</el-button>
21
-            <el-button type="danger" @click="del(row)">删除</el-button>
20
+            <el-button @click="toEdit(row)">{{ T('Edit') }}</el-button>
21
+            <el-button type="danger" @click="del(row)">{{ T('Delete') }}</el-button>
22 22
           </template>
23 23
         </el-table-column>
24 24
       </el-table>
@@ -32,7 +32,7 @@
32 32
                      :total="listRes.total">
33 33
       </el-pagination>
34 34
     </el-card>
35
-    <el-dialog v-model="formVisible" :title="!formData.id?'创建':'修改'" width="800">
35
+    <el-dialog v-model="formVisible" :title="!formData.id?T('Create') :T('Update')" width="800">
36 36
       <el-form class="dialog-form" ref="form" :model="formData" :rules="rules" label-width="120px">
37 37
         <el-form-item label="ClientId" prop="client_id">
38 38
           <el-input v-model="formData.client_id"></el-input>
@@ -43,23 +43,23 @@
43 43
         <el-form-item label="RedirectUrl" prop="redirect_url">
44 44
           <el-input v-model="formData.redirect_url"></el-input>
45 45
         </el-form-item>
46
-        <el-form-item label="类型" prop="op" >
46
+        <el-form-item label="op" prop="op">
47 47
           <el-radio-group v-model="formData.op" :disabled="!!formData.id">
48
-            <el-radio v-for="item in ops" :key="item.value" :label="item.value" style="display: block">
48
+            <el-radio v-for="item in ops" :key="item.value" :value="item.value" style="display: block">
49 49
               {{ item.label }}
50 50
             </el-radio>
51 51
           </el-radio-group>
52 52
         </el-form-item>
53
-        <el-form-item label="自动注册" prop="open_auto_register">
53
+        <el-form-item :label="T('AutoRegister')" prop="auto_register">
54 54
           <el-switch v-model="formData.auto_register"
55 55
                      :active-value="true"
56 56
                      :inactive-value="false"
57 57
           ></el-switch>
58
-          <div style="display: block;margin-left: 10px">如果开启,当用户使用oauth登录而没绑定时,会自动注册一个账号</div>
58
+          <div style="display: block;margin-left: 10px">{{ T('AutoRegisterNote') }}</div>
59 59
         </el-form-item>
60 60
         <el-form-item>
61
-          <el-button @click="formVisible = false">取消</el-button>
62
-          <el-button @click="submit" type="primary">提交</el-button>
61
+          <el-button @click="formVisible = false">{{ T('Cancel') }}</el-button>
62
+          <el-button @click="submit" type="primary">{{ T('Submit') }}</el-button>
63 63
         </el-form-item>
64 64
       </el-form>
65 65
     </el-dialog>
@@ -70,6 +70,7 @@
70 70
   import { onMounted, reactive, watch, ref, onActivated } from 'vue'
71 71
   import { list, create, update, detail, remove } from '@/api/oauth'
72 72
   import { ElMessage, ElMessageBox } from 'element-plus'
73
+  import { T } from '@/utils/i18n'
73 74
 
74 75
   const listRes = reactive({
75 76
     list: [], total: 0, loading: false,
@@ -100,9 +101,9 @@
100 101
   }
101 102
 
102 103
   const del = async (row) => {
103
-    const cf = await ElMessageBox.confirm('确定删除么?', {
104
-      confirmButtonText: '确定',
105
-      cancelButtonText: '取消',
104
+    const cf = await ElMessageBox.confirm(T('Confirm?', { param: T('Delete') }), {
105
+      confirmButtonText: T('Confirm'),
106
+      cancelButtonText: T('Cancel'),
106 107
       type: 'warning',
107 108
     }).catch(_ => false)
108 109
     if (!cf) {
@@ -111,7 +112,7 @@
111 112
 
112 113
     const res = await remove({ id: row.id }).catch(_ => false)
113 114
     if (res) {
114
-      ElMessage.success('操作成功')
115
+      ElMessage.success(T('OperationSuccess'))
115 116
       getList()
116 117
     }
117 118
   }
@@ -132,10 +133,10 @@
132 133
     auto_register: false,
133 134
   })
134 135
   const rules = {
135
-    client_id: [{ required: true, message: '请输入ClientId', trigger: 'blur' }],
136
-    client_secret: [{ required: true, message: '请输入ClientSecret', trigger: 'blur' }],
137
-    redirect_url: [{ required: true, message: '请输入RedirectUrl', trigger: 'blur' }],
138
-    op: [{ required: true, message: '请选择类型', trigger: 'blur' }],
136
+    client_id: [{ required: true, message: T('ParamRequired', { param: 'client_id' }), trigger: 'blur' }],
137
+    client_secret: [{ required: true, message: T('ParamRequired', { param: 'client_secret' }), trigger: 'blur' }],
138
+    redirect_url: [{ required: true, message: T('ParamRequired', { param: 'redirect_url' }), trigger: 'blur' }],
139
+    op: [{ required: true, message: T('ParamRequired', { param: 'op' }), trigger: 'blur' }],
139 140
   }
140 141
   const toEdit = (row) => {
141 142
     formVisible.value = true
@@ -165,7 +166,7 @@
165 166
     const api = formData.id ? update : create
166 167
     const res = await api(formData).catch(_ => false)
167 168
     if (res) {
168
-      ElMessage.success('操作成功')
169
+      ElMessage.success(T('OperationSuccess'))
169 170
       formVisible.value = false
170 171
       getList()
171 172
     }

+ 6 - 6
src/views/oauth/login.vue

@@ -1,22 +1,22 @@
1 1
 <template>
2 2
   <div class="oauth">
3 3
     <el-card class="card">
4
-      <h2>您正在授权登录</h2>
4
+      <h2>{{ T('OauthLogining') }}</h2>
5 5
       <el-form class="info" label-width="100px">
6
-        <el-form-item label="设备">
6
+        <el-form-item :label="T('Device')">
7 7
           <div class="impt">{{ oauthInfo.device_name }}</div>
8 8
         </el-form-item>
9 9
         <el-form-item label="ID">
10 10
           <div class="impt">{{ oauthInfo.id }}</div>
11 11
         </el-form-item>
12 12
         <el-form-item label-width="0">
13
-          <el-button style="width: 100%" v-if="!resStatus" type="success" size="large" @click="toConfirm">授权登录</el-button>
13
+          <el-button style="width: 100%" v-if="!resStatus" type="success" size="large" @click="toConfirm">{{ T('ConfirmOauth') }}</el-button>
14 14
         </el-form-item>
15 15
         <el-form-item label-width="0">
16
-          <el-button style="width: 100%" size="large" @click="out">关闭页面</el-button>
16
+          <el-button style="width: 100%" size="large" @click="out">{{ T('Close') }}</el-button>
17 17
         </el-form-item>
18 18
       </el-form>
19
-      如果不是您操作的授权,请直接关闭页面
19
+      {{ T('OauthCloseNote') }}
20 20
     </el-card>
21 21
   </div>
22 22
 </template>
@@ -48,7 +48,7 @@
48 48
     const res = await confirm({ code }).catch(_ => false)
49 49
     if (res) {
50 50
       resStatus.value = 1
51
-      ElMessage.success('操作成功,3秒后将自动关闭本页面')
51
+      ElMessage.success(T('OperationSuccessAndCloseAfter3Seconds'))
52 52
       setTimeout(_ => {
53 53
         out()
54 54
       }, 3000)

+ 29 - 30
src/views/peer/index.vue

@@ -1,10 +1,10 @@
1 1
 <template>
2 2
   <div>
3 3
     <el-card class="list-query" shadow="hover">
4
-      <el-form inline label-width="60px">
4
+      <el-form inline label-width="80px">
5 5
         <el-form-item>
6
-          <el-button type="primary" @click="handlerQuery">筛选</el-button>
7
-          <el-button type="danger" @click="toAdd">添加</el-button>
6
+          <el-button type="primary" @click="handlerQuery">{{ T('Filter') }}</el-button>
7
+          <el-button type="danger" @click="toAdd">{{ T('Add') }}</el-button>
8 8
         </el-form-item>
9 9
       </el-form>
10 10
     </el-card>
@@ -12,19 +12,19 @@
12 12
       <el-table :data="listRes.list" v-loading="listRes.loading" border size="small">
13 13
         <el-table-column prop="id" label="id" align="center"/>
14 14
         <el-table-column prop="cpu" label="cpu" align="center"/>
15
-        <el-table-column prop="hostname" label="主机名" align="center"/>
16
-        <el-table-column prop="memory" label="内存" align="center"/>
17
-        <el-table-column prop="os" label="系统" align="center"/>
18
-        <el-table-column prop="username" label="username" align="center"/>
19
-        <el-table-column prop="uuid" label="uuid" align="center"/>
20
-        <el-table-column prop="version" label="版本号" align="center"/>
21
-        <el-table-column prop="created_at" label="创建时间" align="center"/>
22
-        <el-table-column prop="updated_at" label="更新时间" align="center"/>
23
-        <el-table-column label="操作" align="center" width="400">
15
+        <el-table-column prop="hostname" :label="T('Hostname')" align="center"/>
16
+        <el-table-column prop="memory" :label="T('Memory')" align="center"/>
17
+        <el-table-column prop="os" :label="T('Os')" align="center"/>
18
+        <el-table-column prop="username" :label="T('Username')" align="center"/>
19
+        <el-table-column prop="uuid" :label="T('Uuid')" align="center"/>
20
+        <el-table-column prop="version" :label="T('Version')" align="center"/>
21
+        <el-table-column prop="created_at" :label="T('CreatedAt')" align="center"/>
22
+        <el-table-column prop="updated_at" :label="T('UpdatedAt')" align="center"/>
23
+        <el-table-column :label="T('Actions')" align="center" width="400">
24 24
           <template #default="{row}">
25 25
             <el-button type="success" @click="toWebClientLink(row)">Web-Client</el-button>
26
-            <el-button @click="toEdit(row)">编辑</el-button>
27
-            <el-button type="danger" @click="del(row)">删除</el-button>
26
+            <el-button @click="toEdit(row)">{{ T('Edit') }}</el-button>
27
+            <el-button type="danger" @click="del(row)">{{ T('Delete') }}</el-button>
28 28
           </template>
29 29
         </el-table-column>
30 30
       </el-table>
@@ -38,36 +38,36 @@
38 38
                      :total="listRes.total">
39 39
       </el-pagination>
40 40
     </el-card>
41
-    <el-dialog v-model="formVisible" :title="!formData.row_id?'创建':'修改'" width="800">
41
+    <el-dialog v-model="formVisible" :title="!formData.row_id?T('Create'):T('Update')" width="800">
42 42
       <el-form class="dialog-form" ref="form" :model="formData" label-width="120px">
43 43
         <el-form-item label="id" prop="id" required>
44 44
           <el-input v-model="formData.id"></el-input>
45 45
         </el-form-item>
46
-        <el-form-item label="用户名" prop="username">
46
+        <el-form-item :label="T('Username')" prop="username">
47 47
           <el-input v-model="formData.username"></el-input>
48 48
         </el-form-item>
49
-        <el-form-item label="主机名" prop="hostname">
49
+        <el-form-item :label="T('Hostname')" prop="hostname">
50 50
           <el-input v-model="formData.hostname"></el-input>
51 51
         </el-form-item>
52 52
         <el-form-item label="cpu" prop="cpu">
53 53
           <el-input v-model="formData.cpu"></el-input>
54 54
         </el-form-item>
55
-        <el-form-item label="内存" prop="memory">
55
+        <el-form-item :label="T('Memory')" prop="memory">
56 56
           <el-input v-model="formData.memory"></el-input>
57 57
         </el-form-item>
58
-        <el-form-item label="系统" prop="os">
58
+        <el-form-item :label="T('Os')" prop="os">
59 59
           <el-input v-model="formData.os"></el-input>
60 60
         </el-form-item>
61
-        <el-form-item label="uuid" prop="uuid">
61
+        <el-form-item :label="T('Uuid')" prop="uuid">
62 62
           <el-input v-model="formData.uuid"></el-input>
63 63
         </el-form-item>
64
-        <el-form-item label="版本" prop="version">
64
+        <el-form-item :label="T('Version')" prop="version">
65 65
           <el-input v-model="formData.version"></el-input>
66 66
         </el-form-item>
67 67
 
68 68
         <el-form-item>
69
-          <el-button @click="formVisible = false">取消</el-button>
70
-          <el-button @click="submit" type="primary">提交</el-button>
69
+          <el-button @click="formVisible = false">{{ T('Cancel') }}</el-button>
70
+          <el-button @click="submit" type="primary">{{ T('Submit') }}</el-button>
71 71
         </el-form-item>
72 72
       </el-form>
73 73
     </el-dialog>
@@ -77,10 +77,9 @@
77 77
 <script setup>
78 78
   import { onActivated, onMounted, reactive, ref, watch } from 'vue'
79 79
   import { create, list, remove, update } from '@/api/peer'
80
-  import { list as fetchTagList } from '@/api/tag'
81 80
   import { ElMessage, ElMessageBox } from 'element-plus'
82
-  import { loadAllUsers } from '@/global'
83 81
   import { toWebClientLink } from '@/utils/webclient'
82
+  import { T } from '@/utils/i18n'
84 83
 
85 84
   const listRes = reactive({
86 85
     list: [], total: 0, loading: false,
@@ -108,9 +107,9 @@
108 107
   }
109 108
 
110 109
   const del = async (row) => {
111
-    const cf = await ElMessageBox.confirm('确定删除么?', {
112
-      confirmButtonText: '确定',
113
-      cancelButtonText: '取消',
110
+    const cf = await ElMessageBox.confirm(T('Confirm?', { param: T('Delete') }), {
111
+      confirmButtonText: T('Confirm'),
112
+      cancelButtonText: T('Cancel'),
114 113
       type: 'warning',
115 114
     }).catch(_ => false)
116 115
     if (!cf) {
@@ -119,7 +118,7 @@
119 118
 
120 119
     const res = await remove({ row_id: row.row_id }).catch(_ => false)
121 120
     if (res) {
122
-      ElMessage.success('操作成功')
121
+      ElMessage.success(T('OperationSuccess'))
123 122
       getList()
124 123
     }
125 124
   }
@@ -173,7 +172,7 @@
173 172
     const api = formData.row_id ? update : create
174 173
     const res = await api(formData).catch(_ => false)
175 174
     if (res) {
176
-      ElMessage.success('操作成功')
175
+      ElMessage.success(T('OperationSuccess'))
177 176
       formVisible.value = false
178 177
       getList()
179 178
     }

+ 6 - 5
src/views/tag/index.js

@@ -2,6 +2,7 @@ import { onActivated, onMounted, reactive, ref, watch } from 'vue'
2 2
 import { create, list, remove, update } from '@/api/tag'
3 3
 import { ElMessage, ElMessageBox } from 'element-plus'
4 4
 import { useRoute } from 'vue-router'
5
+import { T } from '@/utils/i18n'
5 6
 
6 7
 export function useRepositories () {
7 8
   //获取query
@@ -74,9 +75,9 @@ export function useRepositories () {
74 75
   }
75 76
 
76 77
   const del = async (row) => {
77
-    const cf = await ElMessageBox.confirm('确定删除么?', {
78
-      confirmButtonText: '确定',
79
-      cancelButtonText: '取消',
78
+    const cf = await ElMessageBox.confirm(T('Confirm?', { param: T('Delete') }), {
79
+      confirmButtonText: T('Confirm'),
80
+      cancelButtonText: T('Cancel'),
80 81
       type: 'warning',
81 82
     }).catch(_ => false)
82 83
     if (!cf) {
@@ -85,7 +86,7 @@ export function useRepositories () {
85 86
 
86 87
     const res = await remove({ id: row.id }).catch(_ => false)
87 88
     if (res) {
88
-      ElMessage.success('操作成功')
89
+      ElMessage.success(T('OperationSuccess'))
89 90
       getList()
90 91
     }
91 92
   }
@@ -133,7 +134,7 @@ export function useRepositories () {
133 134
     console.log(data)
134 135
     const res = await api(data).catch(_ => false)
135 136
     if (res) {
136
-      ElMessage.success('操作成功')
137
+      ElMessage.success(T('OperationSuccess'))
137 138
       formVisible.value = false
138 139
       getList()
139 140
     }

+ 19 - 23
src/views/tag/index.vue

@@ -1,8 +1,8 @@
1 1
 <template>
2 2
   <div>
3 3
     <el-card class="list-query" shadow="hover">
4
-      <el-form inline label-width="60px">
5
-        <el-form-item label="用户">
4
+      <el-form inline label-width="80px">
5
+        <el-form-item :label="T('Owner')">
6 6
           <el-select v-model="listQuery.user_id" clearable>
7 7
             <el-option
8 8
                 v-for="item in allUsers"
@@ -13,21 +13,21 @@
13 13
           </el-select>
14 14
         </el-form-item>
15 15
         <el-form-item>
16
-          <el-button type="primary" @click="handlerQuery">筛选</el-button>
17
-          <el-button type="danger" @click="toAdd">添加</el-button>
16
+          <el-button type="primary" @click="handlerQuery">{{ T('Filter') }}</el-button>
17
+          <el-button type="danger" @click="toAdd">{{ T('Add') }}</el-button>
18 18
         </el-form-item>
19 19
       </el-form>
20 20
     </el-card>
21 21
     <el-card class="list-body" shadow="hover">
22 22
       <el-table :data="listRes.list" v-loading="listRes.loading" border>
23 23
         <el-table-column prop="id" label="id" align="center"/>
24
-        <el-table-column label="所属用户" align="center">
24
+        <el-table-column :label="T('Owner')" align="center">
25 25
           <template #default="{row}">
26 26
             <span v-if="row.user_id"> <el-tag>{{ allUsers?.find(u => u.id === row.user_id)?.username }}</el-tag> </span>
27 27
           </template>
28 28
         </el-table-column>
29
-        <el-table-column prop="name" label="名称" align="center"/>
30
-        <el-table-column prop="color" label="颜色" align="center">
29
+        <el-table-column prop="name" :label="T('Name')" align="center"/>
30
+        <el-table-column prop="color" :label="T('Color')" align="center">
31 31
           <template #default="{row}">
32 32
             <div class="colors">
33 33
               <div style="background-color: #efeff2" class="colorbox">
@@ -41,12 +41,12 @@
41 41
             </div>
42 42
           </template>
43 43
         </el-table-column>
44
-        <el-table-column prop="created_at" label="创建时间" align="center"/>
45
-        <el-table-column prop="updated_at" label="更新时间" align="center"/>
44
+        <el-table-column prop="created_at" :label="T('CreatedAt')" align="center"/>
45
+        <el-table-column prop="updated_at" :label="T('UpdatedAt')" align="center"/>
46 46
         <el-table-column label="操作" align="center">
47 47
           <template #default="{row}">
48
-            <el-button @click="toEdit(row)">编辑</el-button>
49
-            <el-button type="danger" @click="del(row)">删除</el-button>
48
+            <el-button @click="toEdit(row)">{{ T('Edit') }}</el-button>
49
+            <el-button type="danger" @click="del(row)">{{ T('Delete') }}</el-button>
50 50
           </template>
51 51
         </el-table-column>
52 52
       </el-table>
@@ -60,12 +60,12 @@
60 60
                      :total="listRes.total">
61 61
       </el-pagination>
62 62
     </el-card>
63
-    <el-dialog v-model="formVisible" :title="!formData.id?'创建':'修改'" width="800">
63
+    <el-dialog v-model="formVisible" :title="!formData.id?T('Create'):T('Update')" width="800">
64 64
       <el-form class="dialog-form" ref="form" :model="formData" label-width="120px">
65
-        <el-form-item label="名称" prop="name" required>
65
+        <el-form-item :label="T('Name')" prop="name" required>
66 66
           <el-input v-model="formData.name"></el-input>
67 67
         </el-form-item>
68
-        <el-form-item label="颜色" prop="color" required>
68
+        <el-form-item :label="T('Color')" prop="color" required>
69 69
           <el-color-picker v-model="formData.color" show-alpha @active-change="activeChange"></el-color-picker>
70 70
           <br>
71 71
           <div class="colors">
@@ -79,7 +79,7 @@
79 79
             </div>
80 80
           </div>
81 81
         </el-form-item>
82
-        <el-form-item label="用户" prop="user_id" required>
82
+        <el-form-item :label="T('Owner')" prop="user_id" required>
83 83
           <el-select v-model="formData.user_id">
84 84
             <el-option
85 85
                 v-for="item in allUsers"
@@ -90,8 +90,8 @@
90 90
           </el-select>
91 91
         </el-form-item>
92 92
         <el-form-item>
93
-          <el-button @click="formVisible = false">取消</el-button>
94
-          <el-button @click="submit" type="primary">提交</el-button>
93
+          <el-button @click="formVisible = false">{{ T('Cancel') }}</el-button>
94
+          <el-button @click="submit" type="primary">{{ T('Submit') }}</el-button>
95 95
         </el-form-item>
96 96
       </el-form>
97 97
     </el-dialog>
@@ -100,13 +100,9 @@
100 100
 
101 101
 <script setup>
102 102
   import { onMounted, reactive, watch, ref, onActivated } from 'vue'
103
-  import { list, create, update, detail, remove } from '@/api/tag'
104
-  import { ElMessage, ElMessageBox } from 'element-plus'
105 103
   import { loadAllUsers } from '@/global'
106
-  import { useRoute } from 'vue-router'
107 104
   import { useRepositories } from '@/views/tag/index'
108
-
109
-
105
+  import { T } from '@/utils/i18n'
110 106
 
111 107
   const { allUsers, getAllUsers } = loadAllUsers()
112 108
   getAllUsers()
@@ -123,7 +119,7 @@
123 119
     submit,
124 120
     activeChange,
125 121
     currentColor,
126
-  } = useRepositories(0)
122
+  } = useRepositories()
127 123
 
128 124
   onMounted(getList)
129 125
   onActivated(getList)

+ 6 - 4
src/views/user/composables/edit.js

@@ -3,6 +3,7 @@ import { create, detail, update, remove } from '@/api/user'
3 3
 import { ElMessage, ElMessageBox } from 'element-plus'
4 4
 import { useRouter } from 'vue-router'
5 5
 import { list as groups } from '@/api/group'
6
+import { T } from '@/utils/i18n'
6 7
 
7 8
 export function useGetDetail (id) {
8 9
   let item = ref({})  //保留原始值
@@ -28,7 +29,7 @@ export function useGetDetail (id) {
28 29
     form,
29 30
     item,
30 31
     getDetail,
31
-    groupsList
32
+    groupsList,
32 33
   }
33 34
 }
34 35
 
@@ -36,9 +37,10 @@ export function useSubmit (form, id) {
36 37
   const root = ref(null)
37 38
   const router = useRouter()
38 39
   const rules = reactive({
39
-    username: [{ required: true, message: '用户名是必须的' }],
40
+    username: [{ required: true, message: T('ParamRequired', { param: T('Username') }) }],
41
+    group_id: [{ required: true, message: T('ParamRequired', { param: T('Group') }) }],
40 42
     // nickname: [{ required: true, message: '昵称是必须的' }],
41
-    status: [{ required: true, message: '请选择状态' }],
43
+    status: [{ required: true, message: T('ParamRequired', { param: T('Status') }) }],
42 44
   })
43 45
 
44 46
   const validate = async () => {
@@ -65,7 +67,7 @@ export function useSubmit (form, id) {
65 67
 
66 68
     const res = await submitFunc()
67 69
     if (res) {
68
-      ElMessage.success('操作成功')
70
+      ElMessage.success(T('OperationSuccess'))
69 71
       router.back()
70 72
     }
71 73
   }

+ 12 - 11
src/views/user/composables/index.js

@@ -3,6 +3,7 @@ import { list, remove, changePwd } from '@/api/user'
3 3
 import { list as groups } from '@/api/group'
4 4
 import { useRouter } from 'vue-router'
5 5
 import { ElMessageBox, ElMessage } from 'element-plus'
6
+import { T } from '@/utils/i18n'
6 7
 
7 8
 export function useRepositories () {
8 9
 
@@ -74,15 +75,15 @@ export function useToEditOrAdd () {
74 75
     toAdd,
75 76
     toEdit,
76 77
     toTag,
77
-    toAddressBook
78
+    toAddressBook,
78 79
   }
79 80
 }
80 81
 
81 82
 export function useDel () {
82 83
   const del = async (id) => {
83
-    const cf = await ElMessageBox.confirm('确定删除么?', {
84
-      confirmButtonText: '确定',
85
-      cancelButtonText: '取消',
84
+    const cf = await ElMessageBox.confirm(T('Confirm?', { param: T('Delete') }), {
85
+      confirmButtonText: T('Confirm'),
86
+      cancelButtonText: T('Cancel'),
86 87
       type: 'warning',
87 88
     }).catch(_ => false)
88 89
     if (!cf) {
@@ -99,16 +100,16 @@ export function useDel () {
99 100
 
100 101
 export function useChangePwd () {
101 102
   const changePass = async (admin) => {
102
-    const input = await ElMessageBox.prompt('请输入新密码', '重置密码', {
103
-      confirmButtonText: '确定',
104
-      cancelButtonText: '取消',
103
+    const input = await ElMessageBox.prompt(T('PleaseInputNewPassword'), T('ResetPassword'), {
104
+      confirmButtonText: T('Confirm'),
105
+      cancelButtonText: T('Cancel'),
105 106
     }).catch(_ => false)
106 107
     if (!input) {
107 108
       return
108 109
     }
109
-    const confirm = await ElMessageBox.confirm('确定重置密码么?', {
110
-      confirmButtonText: '确定',
111
-      cancelButtonText: '取消',
110
+    const confirm = await ElMessageBox.confirm(T('Confirm?', { param: T('ResetPassword') }), {
111
+      confirmButtonText: T('Confirm'),
112
+      cancelButtonText: T('Cancel'),
112 113
     }).catch(_ => false)
113 114
     if (!confirm) {
114 115
       return
@@ -117,7 +118,7 @@ export function useChangePwd () {
117 118
     if (!res) {
118 119
       return
119 120
     }
120
-    ElMessage.success('修改成功')
121
+    ElMessage.success(T('OperationSuccess'))
121 122
   }
122 123
 
123 124
   return { changePass }

+ 13 - 33
src/views/user/edit.vue

@@ -1,14 +1,14 @@
1 1
 <template>
2 2
   <div class="form-card">
3 3
     <el-form ref="root" label-width="120px" :model="form" :rules="rules">
4
-      <el-form-item label="用户名" prop="username">
4
+      <el-form-item :label="T('Username')" prop="username">
5 5
         <el-input v-model="form.username"></el-input>
6 6
       </el-form-item>
7
-      <el-form-item label="昵称" prop="nickname">
7
+      <el-form-item :label="T('Nickname')" prop="nickname">
8 8
         <el-input v-model="form.nickname"></el-input>
9 9
       </el-form-item>
10
-      <el-form-item label="小组" prop="group_id">
11
-        <el-select v-model="form.group_id" placeholder="请选择小组">
10
+      <el-form-item :label="T('Group')" prop="group_id">
11
+        <el-select v-model="form.group_id">
12 12
           <el-option
13 13
               v-for="item in groupsList"
14 14
               :key="item.id"
@@ -17,57 +17,37 @@
17 17
           ></el-option>
18 18
         </el-select>
19 19
       </el-form-item>
20
-      <el-form-item label="是否是管理员" prop="is_admin">
20
+      <el-form-item :label="T('IsAdmin')" prop="is_admin">
21 21
         <el-switch v-model="form.is_admin"
22 22
                    :active-value="true"
23 23
                    :inactive-value="false"
24 24
         ></el-switch>
25 25
       </el-form-item>
26
-      <el-form-item label="状态" prop="status">
26
+      <el-form-item :label="T('Status')" prop="status">
27 27
         <el-switch v-model="form.status"
28 28
                    :active-value="ENABLE_STATUS"
29 29
                    :inactive-value="DISABLE_STATUS"
30 30
         ></el-switch>
31 31
       </el-form-item>
32 32
       <el-form-item>
33
-        <el-button @click="cancel">取消</el-button>
34
-        <el-button @click="submit" type="primary">提交</el-button>
33
+        <el-button @click="cancel">{{ T('Cancel') }}</el-button>
34
+        <el-button @click="submit" type="primary">{{ T('Submit') }}</el-button>
35 35
       </el-form-item>
36 36
     </el-form>
37 37
   </div>
38 38
 </template>
39 39
 
40
-<script>
41
-  import { defineComponent, toRef } from 'vue'
40
+<script setup>
42 41
   import { useRoute } from 'vue-router'
43 42
   import { useGetDetail, useSubmit } from '@/views/user/composables/edit'
44 43
   import { ENABLE_STATUS, DISABLE_STATUS } from '@/utils/common_options'
44
+  import { T } from '@/utils/i18n'
45 45
 
46
-  export default defineComponent({
47
-    name: 'UserEdit',
48
-    props: {},
49
-    setup (props, context) {
46
+  const route = useRoute()
47
+  const { form, item, getDetail, groupsList } = useGetDetail(route.params.id)
50 48
 
51
-      const route = useRoute()
52
-      const { form, item, getDetail, groupsList } = useGetDetail(route.params.id)
49
+  const { root, rules, validate, submit, cancel } = useSubmit(form, route.params.id)
53 50
 
54
-      const { root, rules, validate, submit, cancel } = useSubmit(form, route.params.id)
55
-
56
-      return {
57
-        form,
58
-        item,
59
-        getDetail,
60
-
61
-        rules,
62
-        validate,
63
-        root,
64
-        submit,
65
-        cancel,
66
-        groupsList,
67
-        ENABLE_STATUS, DISABLE_STATUS,
68
-      }
69
-    },
70
-  })
71 51
 </script>
72 52
 
73 53
 <style lang="scss" scoped>

+ 17 - 17
src/views/user/index.vue

@@ -1,36 +1,36 @@
1 1
 <template>
2 2
   <div>
3 3
     <el-card class="list-query" shadow="hover">
4
-      <el-form inline label-width="60px">
5
-        <el-form-item label="用户名">
4
+      <el-form inline label-width="80px">
5
+        <el-form-item :label="T('Username')">
6 6
           <el-input v-model="listQuery.username"></el-input>
7 7
         </el-form-item>
8 8
         <el-form-item>
9
-          <el-button type="primary" @click="handlerQuery">筛选</el-button>
10
-          <el-button type="danger" @click="toAdd">添加</el-button>
9
+          <el-button type="primary" @click="handlerQuery">{{ T('Filter') }}</el-button>
10
+          <el-button type="danger" @click="toAdd">{{ T('Add') }}</el-button>
11 11
         </el-form-item>
12 12
       </el-form>
13 13
     </el-card>
14 14
     <el-card class="list-body" shadow="hover">
15 15
       <el-table :data="listRes.list" v-loading="listRes.loading" border>
16 16
         <el-table-column prop="id" label="id" align="center"></el-table-column>
17
-        <el-table-column prop="username" label="用户名" align="center"/>
18
-        <el-table-column prop="nickname" label="昵称" align="center"/>
19
-        <el-table-column label="所在小组" align="center">
17
+        <el-table-column prop="username" :label="T('Username')" align="center"/>
18
+        <el-table-column prop="nickname" :label="T('Nickname')" align="center"/>
19
+        <el-table-column :label="T('Group')" align="center">
20 20
           <template #default="{row}">
21 21
             <span v-if="row.group_id"> <el-tag>{{ listRes.groups?.find(g => g.id === row.group_id)?.name }} </el-tag> </span>
22
-            <span v-else> 未分组 </span>
22
+            <span v-else> - </span>
23 23
           </template>
24 24
         </el-table-column>
25
-        <el-table-column prop="created_at" label="创建时间" align="center"/>
26
-        <el-table-column prop="updated_at" label="更新时间" align="center"/>
27
-        <el-table-column label="操作" align="center" width="550">
25
+        <el-table-column prop="created_at" :label="T('CreatedAt')" align="center"/>
26
+        <el-table-column prop="updated_at" :label="T('UpdatedAt')" align="center"/>
27
+        <el-table-column :label="T('Actions')" align="center" width="650">
28 28
           <template #default="{row}">
29
-            <el-button @click="toTag(row)">他的标签</el-button>
30
-            <el-button @click="toAddressBook(row)">他的地址簿</el-button>
31
-            <el-button @click="toEdit(row)">编辑</el-button>
32
-            <el-button type="warning" @click="changePass(row)">重置密码</el-button>
33
-            <el-button type="danger" @click="remove(row)">删除</el-button>
29
+            <el-button @click="toTag(row)">{{ T('UserTags') }}</el-button>
30
+            <el-button @click="toAddressBook(row)">{{ T('UserAddressBook') }}</el-button>
31
+            <el-button @click="toEdit(row)">{{ T('Edit') }}</el-button>
32
+            <el-button type="warning" @click="changePass(row)">{{ T('ResetPassword') }}</el-button>
33
+            <el-button type="danger" @click="remove(row)">{{ T('Delete') }}</el-button>
34 34
           </template>
35 35
         </el-table-column>
36 36
       </el-table>
@@ -49,7 +49,7 @@
49 49
 
50 50
 <script setup>
51 51
   import { useRepositories, useDel, useToEditOrAdd, useChangePwd } from '@/views/user/composables'
52
-
52
+  import { T } from '@/utils/i18n'
53 53
   //列表
54 54
   const {
55 55
     listRes,