caner 1 year ago
parent
commit
26f7ccb573
4 changed files with 106 additions and 109 deletions
  1. 23 16
      src/App.vue
  2. 31 82
      src/components/edit.vue
  3. 1 0
      src/components/head.vue
  4. 51 11
      src/components/ssh.vue

+ 23 - 16
src/App.vue

@@ -1,17 +1,9 @@
 <template>
-  <n-config-provider
-    preflight-style-disabled
-    inline-theme-disabled
-  >
+  <n-config-provider preflight-style-disabled inline-theme-disabled>
     <div class="box">
-      <Head
-        v-model:show-add="showAdd"
-        v-model:list="tabs"
-        :select-tab="selectKey"
-        @on-change="onChange"
-      />
+      <Head v-model:show-add="showAdd" v-model:list="tabs" :select-tab="selectKey" @on-change="onChange" />
       <div class="box-content">
-        <SSH />
+        <component :is="currentCom.sshCom" />
       </div>
     </div>
     <!-- 弹窗 -->
@@ -21,23 +13,37 @@
   </n-config-provider>
 </template>
 <script setup lang='ts'>
-import { onMounted, ref } from 'vue'
+import {
+  defineAsyncComponent, onMounted, ref, shallowRef
+} from 'vue'
 import Head from '@/components/head.vue'
 import Add from '@/components/add.vue'
 import { FormData } from '@/components/edit.vue'
-import SSH from '@/components/ssh.vue'
 
+// TODO 每个tab都会存储相应组件用户操作过的数据
 const showAdd = ref(false)
-const tabs = ref([
+const tabs = shallowRef([
   {
-    label: 'Home', icon: 'home', size: 14
+    label: 'Home',
+    icon: 'home',
+    size: 14,
+    sshCom: defineAsyncComponent(() => import('@/components/ssh.vue')),
+    sftpCom: undefined
   }
 ] as FormData[])
 const selectKey = ref(0)
+const currentCom = shallowRef(tabs.value[selectKey.value])
 
 function addBack(params: FormData) {
-  tabs.value.push({ ...params, icon: 'cmd', size: 13 })
+  tabs.value.push({
+    ...params,
+    icon: 'cmd',
+    size: 13,
+    sshCom: defineAsyncComponent(() => import('@/components/ssh.vue')),
+    sftpCom: undefined
+  })
   selectKey.value = tabs.value.length - 1
+  currentCom.value = tabs.value[selectKey.value]
   showAdd.value = false
 }
 
@@ -45,6 +51,7 @@ function onChange(params: { id: number, type: string }) {
   const { id, type } = params
   if (type === 'del' && id !== 0) tabs.value.splice(id, 1)
   selectKey.value = type === 'change' ? id : id - 1
+  currentCom.value = tabs.value[selectKey.value]
 }
 
 onMounted(() => {

+ 31 - 82
src/components/edit.vue

@@ -2,93 +2,37 @@
   <div class="edit">
     <div class="edit-top">
       <span>Host Setting</span>
-      <Icon
-        name="close"
-        :size="20"
-        @click="callBack(false)"
-      />
+      <Icon name="close" :size="20" @click="callBack(false)" />
     </div>
     <div class="edit-content">
-      <Icon
-        name="form"
-        :size="240"
-      />
+      <Icon name="form" :size="240" />
 
       <div>
-        <n-form
-          ref="formRef"
-          :model="formData"
-          :rules="rules"
-        >
+        <n-form ref="formRef" :model="formData" :rules="rules">
           <div>
-            <n-form-item
-              label="Address"
-              path="host"
-              inline
-            >
-              <n-input
-                v-model:value="formData.host"
-                placeholder="请输入"
-                clearable
-              />
+            <n-form-item label="Address" path="host" inline>
+              <n-input v-model:value="formData.host" placeholder="请输入" clearable />
             </n-form-item>
-            <n-form-item
-              label="Port"
-              path="port"
-              inline
-            >
-              <n-input
-                v-model:value="formData.port"
-                placeholder="请输入"
-                clearable
-              />
+            <n-form-item label="Port" path="port" inline>
+              <n-input v-model:value="formData.port" placeholder="请输入" clearable />
             </n-form-item>
           </div>
 
-          <n-form-item
-            label="Label"
-            path="label"
-          >
-            <n-input
-              v-model:value="formData.label"
-              placeholder="请输入"
-              clearable
-            />
+          <n-form-item label="Label" path="label">
+            <n-input v-model:value="formData.label" placeholder="请输入" clearable />
           </n-form-item>
-          <n-form-item
-            label="UserName"
-            path="userName"
-          >
-            <n-input
-              v-model:value="formData.userName"
-              placeholder="请输入"
-              clearable
-            />
+          <n-form-item label="UserName" path="userName">
+            <n-input v-model:value="formData.userName" placeholder="请输入" clearable />
           </n-form-item>
-          <n-form-item
-            label="Passord"
-            path="password"
-          >
-            <n-input
-              v-model:value="formData.password"
-              placeholder="请输入"
-              clearable
-            />
+          <n-form-item label="Passord" path="password">
+            <n-input v-model:value="formData.password" placeholder="请输入" clearable />
           </n-form-item>
         </n-form>
         <div>
-          <n-button
-            ghost
-            type="tertiary"
-            @click="callBack(false)"
-          >
+          <n-button ghost type="tertiary" @click="callBack(false)">
             Cancel
           </n-button>
-          <n-button
-            type="info"
-            ghost
-            @click="callBack(true)"
-          >
+          <n-button type="info" ghost @click="callBack(true)">
             Save
           </n-button>
         </div>
@@ -107,11 +51,13 @@ export interface FormData {
   label: string,
   userName: string,
   password: string,
-  icon?:string,
-  size?:number
+  icon?: string,
+  size?: number,
+  sshCom?: any,
+  sftpCom?: any
 }
 const props = withDefaults(defineProps<{
-  data?:FormData
+  data?: FormData
 }>(), {
   data: () => ({
     host: '',
@@ -121,7 +67,7 @@ const props = withDefaults(defineProps<{
     password: ''
   })
 })
-const emit = defineEmits<{(evt: 'callBack', value: FormData | null): void}>()
+const emit = defineEmits<{ (evt: 'callBack', value: FormData | null): void }>()
 const formRef = ref()
 class FormOldData {
   host: string
@@ -161,7 +107,7 @@ const rules = ref({
   }
 })
 
-async function callBack(type:boolean) {
+async function callBack(type: boolean) {
   const data = type ? { ...formData.value } : null
   if (type) await formRef.value.validate()
   emit('callBack', data)
@@ -208,9 +154,11 @@ async function callBack(type:boolean) {
           --n-border-hover: rgba(0, 0, 0, 0);
           --n-box-shadow-focus: 0 0 0 2px rgba(0, 0, 0, .2);
         }
-        &>div:first-child{
+
+        &>div:first-child {
           display: flex;
-          &>div:first-child{
+
+          &>div:first-child {
             width: 78%;
             margin-right: 2%;
           }
@@ -225,10 +173,11 @@ async function callBack(type:boolean) {
         &>button:last-child {
           margin-left: 15px;
         }
-        :deep(.n-button){
-          --n-text-color-hover:none;
-          --n-border-focus:1px solid #0000;
-          --n-border-hover:1px solid #0000;
+
+        :deep(.n-button) {
+          --n-text-color-hover: none;
+          --n-border-focus: 1px solid #0000;
+          --n-border-hover: 1px solid #0000;
         }
       }
     }

+ 1 - 0
src/components/head.vue

@@ -63,6 +63,7 @@ const emit = defineEmits<{(evt: 'update:showAdd', value: boolean): void,
 }>()
 
 function onChange(id: number, type: string) {
+  if (id === 0 && type === 'del') return
   emit('onChange', { id, type })
 }
 

+ 51 - 11
src/components/ssh.vue

@@ -5,16 +5,29 @@
       :key="index"
       v-html="item"
     /> -->
-    <textarea
+    <!-- <textarea
       v-model="data"
       style="width: 100%;height: 100%;"
-    />
+    /> -->
+
+    <div class="ssh-input">
+      <span
+        ref="inputTitle"
+        class="ssh-input-title"
+      >root@orangepi:~#</span>
+      <span
+        class="ssh-input-content"
+        contenteditable="plaintext-only"
+        @input="onInput"
+      />
+    </div>
   </div>
 </template>
 
 <script setup lang='ts'>
 import { onMounted, ref } from 'vue'
 
+const inputTitle = ref()
 const data = ref('')
 const conn = ref()
 
@@ -43,19 +56,46 @@ function newClient(option: { host: string, port: number, username: string, passw
   return conn
 }
 
-onMounted(() => {
-  conn.value = newClient({
-    host: 'caner.top', port: 49657, username: 'root', password: 'dongdong0707'
-  })
-})
+function onInput(e:any) {
+  console.log(6666, e.target.textContent)
+}
+
+// onMounted(() => {
+//   conn.value = newClient({
+//     host: 'caner.top', port: 49657, username: 'root', password: 'dongdong0707'
+//   })
+// })
 
 </script>
 <style lang="scss" scoped>
 .ssh {
-    width: 100%;
-    height: 100%;
-    background: black;
+  width: 100%;
+  height: 100%;
+  background: black;
+
+  &-input {
     color: white;
-    font-size: 12px;
+    font-size: 16px;
+    position: relative;
+
+    &-title {
+      position: absolute;
+      left: 0;
+      top: 0;
+    }
+
+    &-content {
+      display: inline-block;
+      min-width: 300px;
+      max-width: 100%;
+      overflow: hidden;
+      text-indent: 200px;
+      word-wrap: break-word;
+      &:focus-visible {
+        outline: none;
+      }
+    }
+
+  }
 }
 </style>