github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/static_source/admin/src/views/Scripts/edit.vue (about)

     1  <script setup lang="ts">
     2  import {computed, onMounted, onUnmounted, ref, unref} from 'vue'
     3  import {useI18n} from '@/hooks/web/useI18n'
     4  import {
     5    ElButton,
     6    ElCol,
     7    ElDescriptions,
     8    ElDescriptionsItem,
     9    ElFormItem,
    10    ElMessage,
    11    ElOption,
    12    ElPopconfirm,
    13    ElRow,
    14    ElSelect,
    15    ElTabPane,
    16    ElTabs
    17  } from 'element-plus'
    18  import {useRoute, useRouter} from 'vue-router'
    19  import api from "@/api/api";
    20  import Form from './components/Form.vue'
    21  import {ApiScript} from "@/api/stub";
    22  import {ScriptEditor} from "@/components/ScriptEditor";
    23  import {ContentWrap} from "@/components/ContentWrap";
    24  import {useEmitt} from "@/hooks/web/useEmitt";
    25  import {Infotip} from '@/components/Infotip'
    26  import {parseTime} from "@/utils";
    27  import {UUID} from "uuid-generator-ts";
    28  import stream from "@/api/stream";
    29  import {MergeEditor} from "@/components/MergeEditor";
    30  import {EventUpdatedScriptModel} from "@/api/types";
    31  
    32  const {emitter} = useEmitt()
    33  const {push} = useRouter()
    34  const route = useRoute();
    35  const {t} = useI18n()
    36  
    37  const writeRef = ref<ComponentRef<typeof Form>>()
    38  const loading = ref(false)
    39  const scriptId = computed(() => parseInt(route.params.id));
    40  const currentScript = ref<Nullable<ApiScript>>(null)
    41  const activeTab = ref('source')
    42  const currentVersionIdx = ref(0)
    43  const currentVersion = ref<Nullable<ApiScript>>(null)
    44  const versions = ref<Nullable<ApiScript[]>>([])
    45  
    46  const currentID = ref('')
    47  
    48  onMounted(() => {
    49    const uuid = new UUID()
    50    currentID.value = uuid.getDashFreeUUID()
    51  
    52    setTimeout(() => {
    53      stream.subscribe('event_updated_script_model', currentID.value, eventHandler)
    54    }, 1000)
    55  })
    56  
    57  onUnmounted(() => {
    58    stream.unsubscribe('event_updated_script_model', currentID.value)
    59  })
    60  
    61  const eventHandler = (event: EventUpdatedScriptModel) => {
    62    if (event.script_id && event.script_id === scriptId.value) {
    63      fetch()
    64    }
    65  }
    66  
    67  const fetch = async () => {
    68    loading.value = true
    69    const res = await api.v1.scriptServiceGetScriptById(scriptId.value)
    70        .catch(() => {
    71        })
    72        .finally(() => {
    73          loading.value = false
    74        })
    75    if (res) {
    76      currentScript.value = res.data
    77      if (res.data?.versions && res.data.versions.length) {
    78        versions.value = res.data.versions;
    79        if (res.data.versions.length > 1) {
    80          currentVersion.value = res.data.versions[1]
    81        }
    82      }
    83    } else {
    84      currentScript.value = null
    85    }
    86  }
    87  
    88  const exec = async () => {
    89    await api.v1.scriptServiceExecSrcScriptById({
    90      name: currentScript.value?.name,
    91      source: currentScript.value?.source,
    92      lang: currentScript.value?.lang
    93    })
    94    ElMessage({
    95      title: t('Success'),
    96      message: t('message.callSuccessful'),
    97      type: 'success',
    98      duration: 2000
    99    })
   100  }
   101  
   102  const copy = async () => {
   103    const res = await api.v1.scriptServiceCopyScriptById(scriptId.value)
   104        .catch(() => {
   105        })
   106        .finally(() => {
   107        })
   108    if (res) {
   109      const {id} = res.data;
   110      push(`/scripts/edit/${id}`)
   111    }
   112  }
   113  
   114  const updateVersions = async () => {
   115    loading.value = true
   116    const res = await api.v1.scriptServiceGetScriptById(scriptId.value)
   117        .catch(() => {
   118        })
   119        .finally(() => {
   120          loading.value = false
   121        })
   122    if (res) {
   123      if (res.data?.versions && res.data.versions.length) {
   124        currentVersion.value = res.data.versions[0]
   125        versions.value = res.data.versions
   126      }
   127    }
   128  }
   129  
   130  const save = async () => {
   131    const write = unref(writeRef)
   132    const validate = await write?.elFormRef?.validate()?.catch(() => {
   133    })
   134    if (validate) {
   135      loading.value = true
   136      const data = (await write?.getFormData()) as ApiScript
   137      const body = {
   138        id: data.id,
   139        lang: data.lang,
   140        name: data.name,
   141        source: currentScript.value?.source || '',
   142        description: data.description,
   143      }
   144      const res = await api.v1.scriptServiceUpdateScriptById(scriptId.value, body)
   145          .catch(() => {
   146          })
   147          .finally(async () => {
   148            updateVersions();
   149          })
   150      if (res) {
   151        ElMessage({
   152          title: t('Success'),
   153          message: t('message.updatedSuccessfully'),
   154          type: 'success',
   155          duration: 2000
   156        })
   157      }
   158    }
   159  }
   160  
   161  const cancel = () => {
   162    push('/scripts')
   163  }
   164  
   165  const remove = async () => {
   166    loading.value = true
   167    const res = await api.v1.scriptServiceDeleteScriptById(scriptId.value)
   168        .catch(() => {
   169        })
   170        .finally(() => {
   171          loading.value = false
   172        })
   173    if (res) {
   174      cancel()
   175    }
   176  }
   177  
   178  const updateCurrentTab = (tab: any, ev: any) => {
   179    const {index, paneName} = tab;
   180    if (paneName == 'source' || paneName == 'versions') {
   181      emitter.emit('updateEditor')
   182    }
   183  }
   184  
   185  const onMergeEditorChange = (val: string) => {
   186    currentScript.value.source = val
   187    reload()
   188  }
   189  
   190  const onScriptEditorChange = (val: string) => {
   191    if (currentScript.value?.source == val) {
   192      return
   193    }
   194    currentScript.value.source = val
   195  }
   196  
   197  const selectVersionHandler = () => {
   198    currentVersion.value = currentScript.value?.versions[currentVersionIdx.value] || null
   199  }
   200  
   201  const reloadKey = ref(0)
   202  const reload = () => reloadKey.value += 1
   203  
   204  fetch()
   205  
   206  </script>
   207  
   208  <template>
   209    <ContentWrap>
   210  
   211      <ElTabs class="demo-tabs" v-model="activeTab" @tab-click="updateCurrentTab">
   212        <!-- main -->
   213        <ElTabPane :label="$t('scripts.main')" name="main">
   214  
   215          <Form ref="writeRef" :current-row="currentScript"/>
   216  
   217        </ElTabPane>
   218        <!-- /main -->
   219  
   220        <!-- source -->
   221        <ElTabPane :label="$t('scripts.source')" name="source">
   222          <Infotip
   223              :show-index="false"
   224              title="INFO"
   225              :schema="[
   226        {
   227          label: t('scripts.info1'),
   228          keys: ['scripts']
   229        },
   230        {
   231          label: t('scripts.info2'),
   232          keys: ['scripts']
   233        },
   234        {
   235          label: t('scripts.info3'),
   236          keys: ['scripts']
   237        },
   238      ]"
   239          />
   240          <ScriptEditor :key="reloadKey"
   241                        v-model="currentScript"
   242                        class="mb-20px"
   243                        @update:source="onScriptEditorChange"
   244                        @save="save"/>
   245        </ElTabPane>
   246        <!-- /source -->
   247  
   248        <!-- versions -->
   249        <ElTabPane :label="$t('scripts.scriptVersions')" name="versions">
   250  
   251          <ElRow v-if="activeTab == 'versions' && !loading && versions" class="mb-20px">
   252            <ElCol>
   253              <ElFormItem :label="$t('scripts.scriptVersions')" prop="action">
   254                <ElSelect
   255                    v-model="currentVersionIdx"
   256                    clearable
   257                    :placeholder="$t('dashboard.editor.selectAction')"
   258                    style="width: 100%"
   259                    @change="selectVersionHandler"
   260                >
   261                  <ElOption
   262                      v-for="(p, index) in versions"
   263                      :key="index"
   264                      :label="parseTime(p.createdAt)"
   265                      :value="index"/>
   266                </ElSelect>
   267  
   268              </ElFormItem>
   269            </ElCol>
   270            <ElCol>
   271              <MergeEditor :source="currentScript"
   272                           :destination="currentVersion"
   273                           @update:source="onMergeEditorChange"/>
   274            </ElCol>
   275          </ElRow>
   276  
   277        </ElTabPane>
   278        <!-- /versions -->
   279  
   280        <!-- info -->
   281        <ElTabPane :label="$t('scripts.scriptInfo')" name="info">
   282          <ElDescriptions v-if="currentScript?.scriptInfo"
   283                          class="ml-10px mr-10px mb-20px"
   284                          :title="$t('scripts.scriptInfo')"
   285                          direction="vertical"
   286                          :column="2"
   287                          border
   288          >
   289            <ElDescriptionsItem :label="$t('scripts.alexaIntents')">{{ currentScript.scriptInfo.alexaIntents }}
   290            </ElDescriptionsItem>
   291            <ElDescriptionsItem :label="$t('scripts.entityActions')">{{ currentScript.scriptInfo.entityActions }}
   292            </ElDescriptionsItem>
   293            <ElDescriptionsItem :label="$t('scripts.entityScripts')">{{ currentScript.scriptInfo.entityScripts }}
   294            </ElDescriptionsItem>
   295            <ElDescriptionsItem :label="$t('scripts.automationTriggers')">
   296              {{ currentScript.scriptInfo.automationTriggers }}
   297            </ElDescriptionsItem>
   298            <ElDescriptionsItem :label="$t('scripts.automationConditions')">
   299              {{ currentScript.scriptInfo.automationConditions }}
   300            </ElDescriptionsItem>
   301            <ElDescriptionsItem :label="$t('scripts.automationActions')">
   302              {{ currentScript.scriptInfo.automationActions }}
   303            </ElDescriptionsItem>
   304          </ElDescriptions>
   305        </ElTabPane>
   306        <!-- /info -->
   307  
   308      </ElTabs>
   309  
   310      <div style="text-align: right">
   311  
   312        <ElButton type="success" @click="exec()">{{ t('main.exec') }}</ElButton>
   313        <ElButton type="primary" @click="save()">{{ t('main.save') }}</ElButton>
   314        <ElButton type="default" @click="copy()">{{ t('main.copy') }}</ElButton>
   315        <ElButton type="default" @click="fetch()">{{ t('main.loadFromServer') }}</ElButton>
   316        <ElButton type="default" @click="cancel()">{{ t('main.return') }}</ElButton>
   317  
   318        <ElPopconfirm
   319            :confirm-button-text="$t('main.ok')"
   320            :cancel-button-text="$t('main.no')"
   321            width="250"
   322            style="margin-left: 10px;"
   323            :title="$t('main.are_you_sure_to_do_want_this?')"
   324            @confirm="remove"
   325        >
   326          <template #reference>
   327            <ElButton class="mr-10px" type="danger" plain>
   328              <Icon icon="ep:delete" class="mr-5px"/>
   329              {{ t('main.remove') }}
   330            </ElButton>
   331          </template>
   332        </ElPopconfirm>
   333  
   334      </div>
   335    </ContentWrap>
   336  
   337  </template>
   338  
   339  <style lang="less" scoped>
   340  
   341  </style>