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

     1  <script setup lang="ts">
     2  import {useI18n} from '@/hooks/web/useI18n'
     3  import {Table} from '@/components/Table'
     4  import {h, onMounted, onUnmounted, reactive, ref, watch} from 'vue'
     5  import {Pagination, TableColumn} from '@/types/table'
     6  import api from "@/api/api";
     7  import {ElButton, ElMessage} from 'element-plus'
     8  import {ApiTask} from "@/api/stub";
     9  import {useRouter} from "vue-router";
    10  import {ContentWrap} from "@/components/ContentWrap";
    11  import {parseTime} from "@/utils";
    12  import {EventStateChange, EventTaskCompleted} from "@/api/types";
    13  import {UUID} from "uuid-generator-ts";
    14  import stream from "@/api/stream";
    15  import {useCache} from "@/hooks/web/useCache";
    16  
    17  const {push} = useRouter()
    18  const {t} = useI18n()
    19  const {wsCache} = useCache()
    20  
    21  interface TableObject {
    22    tableList: ApiTask[]
    23    params?: any
    24    loading: boolean
    25    sort?: string
    26  }
    27  
    28  interface Params {
    29    page?: number;
    30    limit?: number;
    31    sort?: string;
    32  }
    33  
    34  const cachePref = 'tasks'
    35  const tableObject = reactive<TableObject>(
    36      {
    37        tableList: [],
    38        loading: false,
    39        sort: wsCache.get(cachePref + 'Sort') || '-createdAt'
    40      }
    41  );
    42  
    43  const currentID = ref('')
    44  
    45  const onStateChanged = (event: EventStateChange) => {
    46    getList()
    47  }
    48  
    49  const onEventTaskActivated = (event: EventTaskCompleted) => {
    50    for (const i in tableObject.tableList) {
    51      if (tableObject.tableList[i].id == event.id) {
    52        tableObject.tableList[i].completed = true;
    53        setTimeout(() => {
    54          tableObject.tableList[i].completed = false
    55        }, 500)
    56        return
    57      }
    58    }
    59  }
    60  
    61  onMounted(() => {
    62    const uuid = new UUID()
    63    currentID.value = uuid.getDashFreeUUID()
    64  
    65    setTimeout(() => {
    66      stream.subscribe('event_task_loaded', currentID.value, onStateChanged);
    67      stream.subscribe('event_task_unloaded', currentID.value, onStateChanged);
    68      stream.subscribe('event_task_completed', currentID.value, onEventTaskActivated);
    69    }, 1000)
    70  })
    71  
    72  onUnmounted(() => {
    73    stream.unsubscribe('event_task_loaded', currentID.value);
    74    stream.unsubscribe('event_task_unloaded', currentID.value);
    75    stream.unsubscribe('event_task_completed', currentID.value);
    76  })
    77  
    78  const columns: TableColumn[] = [
    79    {
    80      field: 'id',
    81      label: t('automation.id'),
    82      sortable: true,
    83      width: "60px"
    84    },
    85    {
    86      field: 'name',
    87      label: t('automation.name'),
    88      sortable: true,
    89      width: "170px"
    90    },
    91    {
    92      field: 'areaId',
    93      label: t('automation.area'),
    94      width: "100px",
    95      sortable: true,
    96      formatter: (row: ApiTask) => {
    97        return h(
    98            'span',
    99            row.area?.name
   100        )
   101      }
   102    },
   103    {
   104      field: 'actions',
   105      label: t('automation.tasks.actions'),
   106      width: "100px",
   107      formatter: (row: ApiTask) => {
   108        return h(
   109            'span',
   110            row?.actions?.length || t('automation.nothing')
   111        )
   112      }
   113    },
   114    {
   115      field: 'triggers',
   116      label: t('automation.tasks.triggers'),
   117      width: "100px",
   118      formatter: (row: ApiTask) => {
   119        return h(
   120            'span',
   121            row?.triggers?.length || t('automation.nothing')
   122        )
   123      }
   124    },
   125    {
   126      field: 'description',
   127      label: t('automation.description'),
   128      sortable: true,
   129      formatter: (row: ApiTask) => {
   130        return h(
   131            'span',
   132            row?.description || t('automation.nothing')
   133        )
   134      }
   135    },
   136    {
   137      field: 'status',
   138      label: t('entities.status'),
   139      width: "70px",
   140    },
   141    {
   142      field: 'createdAt',
   143      label: t('main.createdAt'),
   144      type: 'time',
   145      sortable: true,
   146      width: "170px",
   147      formatter: (row: ApiTask) => {
   148        return h(
   149            'span',
   150            parseTime(row.createdAt)
   151        )
   152      }
   153    },
   154    {
   155      field: 'updatedAt',
   156      label: t('main.updatedAt'),
   157      type: 'time',
   158      sortable: true,
   159      width: "170px",
   160      formatter: (row: ApiTask) => {
   161        return h(
   162            'span',
   163            parseTime(row.updatedAt)
   164        )
   165      }
   166    },
   167  ]
   168  const paginationObj = ref<Pagination>({
   169    currentPage: wsCache.get(cachePref + 'CurrentPage') || 1,
   170    pageSize: wsCache.get(cachePref + 'PageSize') || 50,
   171    total: 0,
   172    pageSizes: [50, 100, 150, 250],
   173  })
   174  
   175  const getList = async () => {
   176    tableObject.loading = true
   177  
   178    wsCache.set(cachePref + 'CurrentPage', paginationObj.value.currentPage)
   179    wsCache.set(cachePref + 'PageSize', paginationObj.value.pageSize)
   180    wsCache.set(cachePref + 'Sort', tableObject.sort)
   181  
   182    let params: Params = {
   183      page: paginationObj.value.currentPage,
   184      limit: paginationObj.value.pageSize,
   185      sort: tableObject.sort,
   186    }
   187  
   188    const res = await api.v1.automationServiceGetTaskList(params)
   189        .catch(() => {
   190        })
   191        .finally(() => {
   192          tableObject.loading = false
   193        })
   194    if (res) {
   195      const {items, meta} = res.data;
   196      tableObject.tableList = items;
   197      paginationObj.value.currentPage = meta.pagination.page;
   198      paginationObj.value.total = meta.pagination.total;
   199    } else {
   200      tableObject.tableList = [];
   201    }
   202  }
   203  
   204  watch(
   205      () => paginationObj.value.currentPage,
   206      () => {
   207        getList()
   208      }
   209  )
   210  
   211  watch(
   212      () => paginationObj.value.pageSize,
   213      () => {
   214        getList()
   215      }
   216  )
   217  
   218  const sortChange = (data) => {
   219    const {column, prop, order} = data;
   220    const pref: string = order === 'ascending' ? '+' : '-'
   221    tableObject.sort = pref + prop
   222    getList()
   223  }
   224  
   225  getList()
   226  
   227  const addNew = () => {
   228    push('/automation/tasks/new')
   229  }
   230  
   231  
   232  const selectRow = (row) => {
   233    if (!row) {
   234      return
   235    }
   236    const {id} = row
   237    push(`/automation/tasks/edit/${id}`)
   238  }
   239  
   240  const enable = async (task: ApiTask) => {
   241    if (!task?.id) return;
   242    await api.v1.automationServiceEnableTask(task.id);
   243    ElMessage({
   244      title: t('Success'),
   245      message: t('message.requestSentSuccessfully'),
   246      type: 'success',
   247      duration: 2000
   248    });
   249  }
   250  
   251  const disable = async (task: ApiTask) => {
   252    if (!task?.id) return;
   253    await api.v1.automationServiceDisableTask(task.id);
   254    ElMessage({
   255      title: t('Success'),
   256      message: t('message.requestSentSuccessfully'),
   257      type: 'success',
   258      duration: 2000
   259    });
   260  }
   261  
   262  const tableRowClassName = (data) => {
   263    const {row, rowIndex} = data
   264    let style = ''
   265    if (row.completed) {
   266      style = 'completed'
   267    }
   268    return style
   269  }
   270  
   271  </script>
   272  
   273  <template>
   274    <ContentWrap>
   275      <ElButton class="flex mb-20px items-left" type="primary" @click="addNew()" plain>
   276        <Icon icon="ep:plus" class="mr-5px"/>
   277        {{ t('automation.addNew') }}
   278      </ElButton>
   279  
   280      <Table
   281          :selection="false"
   282          v-model:pageSize="paginationObj.pageSize"
   283          v-model:currentPage="paginationObj.currentPage"
   284          :columns="columns"
   285          :data="tableObject.tableList"
   286          :loading="tableObject.loading"
   287          :pagination="paginationObj"
   288          @sort-change="sortChange"
   289          :row-class-name="tableRowClassName"
   290          style="width: 100%"
   291          :showUpPagination="20"
   292      >
   293        <template #name="{ row }">
   294          <span @click.prevent.stop="selectRow(row)" style="cursor: pointer">
   295            {{ row.name }}
   296          </span>
   297        </template>
   298  
   299        <template #status="{ row }">
   300          <div class="w-[100%] text-center">
   301            <ElButton :link="true" @click.prevent.stop="enable(row)" v-if="!row?.isLoaded">
   302              <Icon icon="noto:red-circle" class="mr-5px"/>
   303            </ElButton>
   304            <ElButton :link="true" @click.prevent.stop="disable(row)" v-if="row?.isLoaded">
   305              <Icon icon="noto:green-circle" class="mr-5px"/>
   306            </ElButton>
   307          </div>
   308        </template>
   309      </Table>
   310  
   311    </ContentWrap>
   312  
   313  </template>
   314  
   315  <style lang="less">
   316  
   317  .light {
   318    .el-table__row {
   319      &.completed {
   320        --el-table-tr-bg-color: var(--el-color-primary-light-7);
   321        -webkit-transition: background-color 200ms linear;
   322        -ms-transition: background-color 200ms linear;
   323        transition: background-color 200ms linear;
   324      }
   325    }
   326  }
   327  
   328  .dark {
   329    .el-table__row {
   330      &.completed {
   331        --el-table-tr-bg-color: var(--el-color-primary-dark-2);
   332        -webkit-transition: background-color 200ms linear;
   333        -ms-transition: background-color 200ms linear;
   334        transition: background-color 200ms linear;
   335      }
   336    }
   337  }
   338  
   339  </style>