index.vue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. <template>
  2. <t-layout class="app-container">
  3. <t-header class="app-nav">
  4. <t-head-menu
  5. theme="light"
  6. :default-value="menuValue"
  7. @change="changeHandler"
  8. >
  9. <template #logo>
  10. <img src="../assets/logo.png" height="32" alt="logo" />
  11. </template>
  12. <t-menu-item value="homeIndex"> 首页 </t-menu-item>
  13. <t-menu-item value="runDataIndex"> 运行数据 </t-menu-item>
  14. <t-menu-item value="logsDataIndex"> 日志数据 </t-menu-item>
  15. <template #operations>
  16. <t-space>
  17. <t-tooltip placement="bottom" content="全屏">
  18. <t-button
  19. theme="default"
  20. shape="square"
  21. variant="text"
  22. @click="toggleFullScreen"
  23. >
  24. <t-icon name="fullscreen-2" size="24" />
  25. </t-button>
  26. </t-tooltip>
  27. <t-button theme="default" variant="text">
  28. <template #icon>
  29. <t-icon
  30. class="header-user-avatar"
  31. name="user-circle"
  32. size="18"
  33. />
  34. </template>
  35. {{ userName }}
  36. </t-button>
  37. </t-space>
  38. <t-button theme="default" variant="text" @click="updatedPassword">
  39. <template #icon>
  40. <t-icon class="header-user-avatar" name="edit" />
  41. </template>
  42. 修改密码
  43. </t-button>
  44. <t-button variant="text" @click="handleLogout">
  45. <template #icon><t-icon name="poweroff" /></template>
  46. 退出登录
  47. </t-button>
  48. </template>
  49. </t-head-menu>
  50. </t-header>
  51. <t-content class="app-content">
  52. <div class="app-main">
  53. <router-view v-slot="{ Component }">
  54. <transition name="fade" mode="out-in">
  55. <keep-alive>
  56. <component :is="Component" />
  57. </keep-alive>
  58. </transition>
  59. </router-view>
  60. </div>
  61. </t-content>
  62. <!-- 修改密码 -->
  63. <t-dialog
  64. header="修改密码"
  65. v-model:visible="visible"
  66. :cancel-btn="null"
  67. :confirm-btn="null"
  68. >
  69. <t-form
  70. ref="form"
  71. :data="formData"
  72. :rules="rules"
  73. @reset="onReset"
  74. @submit="onSubmit"
  75. >
  76. <t-form-item label="原密码" name="oldPasswd">
  77. <t-input
  78. v-model="formData.oldPasswd"
  79. :readonly="true"
  80. type="password"
  81. ></t-input>
  82. </t-form-item>
  83. <t-form-item label="新密码" name="passwd">
  84. <t-input v-model="formData.passwd" type="password"></t-input>
  85. </t-form-item>
  86. <t-form-item label="确认密码" name="surePassword">
  87. <t-input v-model="formData.surePassword" type="password"></t-input>
  88. </t-form-item>
  89. <t-form-item>
  90. <t-space size="small">
  91. <t-button theme="primary" type="submit">确定</t-button>
  92. <t-button theme="default" variant="base" type="reset"
  93. >取消</t-button
  94. >
  95. </t-space>
  96. </t-form-item>
  97. </t-form>
  98. </t-dialog>
  99. </t-layout>
  100. </template>
  101. <script lang="ts" setup>
  102. import { ref, computed, reactive, nextTick } from 'vue';
  103. import screenfull from 'screenfull';
  104. import { useUserStore } from '@/store';
  105. import { useRouter, useRoute } from 'vue-router';
  106. import { editPassword } from '@/api/login';
  107. import { MessagePlugin } from 'tdesign-vue-next';
  108. const route = useRoute();
  109. const { push } = useRouter();
  110. const userStore = useUserStore();
  111. const isFullscreen = ref(false);
  112. const menuValue = computed(() => route.name);
  113. const userName = computed(() => userStore.userInfo.nickname || '');
  114. const visible = ref(false);
  115. const form = ref(null);
  116. const passwordValidator = (val) => {
  117. if (val === userStore.userInfo.passwd) {
  118. return { result: false, message: '新密码不能和旧密码一致', type: 'error' };
  119. }
  120. return true;
  121. };
  122. const rePasswordValidator = (val) => {
  123. if (val !== formData.passwd) {
  124. return { result: false, message: '两次密码不一致', type: 'error' };
  125. }
  126. return true;
  127. };
  128. const formData = reactive({
  129. username: '',
  130. oldPasswd: '',
  131. passwd: '',
  132. surePassword: '',
  133. });
  134. const rules = {
  135. passwd: [
  136. { required: true, message: '新密码必填' },
  137. { validator: passwordValidator },
  138. ],
  139. surePassword: [
  140. { required: true, message: '确认密码必填' },
  141. { validator: rePasswordValidator },
  142. ],
  143. };
  144. const changeHandler = (active: string) => {
  145. push({ name: active });
  146. };
  147. /** 全屏切换 */
  148. const toggleFullScreen = () => {
  149. isFullscreen.value = !isFullscreen.value;
  150. if (menuValue.value == 'homeIndex') {
  151. screenfull.toggle(document.querySelector('.home-container'));
  152. } else {
  153. screenfull.toggle();
  154. }
  155. };
  156. /**修改密码 */
  157. const updatedPassword = () => {
  158. visible.value = true;
  159. nextTick(() => {
  160. form.value.clearValidate();
  161. formData.username = userStore.userInfo.username;
  162. formData.oldPasswd = userStore.userInfo.passwd;
  163. formData.passwd = '';
  164. formData.surePassword = '';
  165. });
  166. };
  167. const onSubmit = async ({ validateResult, firstError, e }) => {
  168. e.preventDefault();
  169. if (validateResult === true) {
  170. const { username, oldPasswd, passwd } = formData;
  171. const resp = await editPassword({ username, oldPasswd, passwd });
  172. MessagePlugin.success(resp.data);
  173. userStore.userInfo.passwd = passwd;
  174. setTimeout(() => {
  175. visible.value = false;
  176. form.value.reset();
  177. }, 500);
  178. } else {
  179. console.log('Validate Errors: ', firstError, validateResult);
  180. }
  181. };
  182. /**取消 */
  183. const onReset = () => {
  184. visible.value = false;
  185. };
  186. /** 退出登录 */
  187. const handleLogout = async () => {
  188. await userStore.logout();
  189. push({
  190. path: '/login',
  191. });
  192. };
  193. </script>
  194. <style lang="less" scoped>
  195. .app-container {
  196. width: 100%;
  197. height: 100vh;
  198. }
  199. .app-nav {
  200. padding: 0 25px;
  201. border-bottom: 1px solid #e5e6eb;
  202. }
  203. .app-content {
  204. padding: 20px 28px;
  205. box-sizing: border-box;
  206. .app-main {
  207. width: 100%;
  208. height: 100%;
  209. background: #fff;
  210. border-radius: 6px;
  211. // padding: 15px;
  212. // box-sizing: border-box;
  213. }
  214. }
  215. :deep(.t-button--variant-text) {
  216. padding: 0 10px;
  217. }
  218. .operations-dropdown-container-item {
  219. width: 100%;
  220. display: flex;
  221. align-items: center;
  222. :deep(.t-dropdown__item-text) {
  223. display: flex;
  224. align-items: center;
  225. }
  226. .t-icon {
  227. font-size: var(--td-comp-size-xxxs);
  228. margin-right: var(--td-comp-margin-s);
  229. }
  230. }
  231. </style>