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

     1  <script setup lang="ts">
     2  import {useI18n} from '@/hooks/web/useI18n'
     3  import {Table} from '@/components/Table'
     4  import {Form} from '@/components/Form'
     5  import {h, reactive, ref, watch} from 'vue'
     6  import {FormSchema} from "@/types/form";
     7  import {Pagination, TableColumn} from '@/types/table'
     8  import {ElButton} from 'element-plus'
     9  import api from "@/api/api";
    10  import {ApiMessage, ApiMessageDelivery} from "@/api/stub";
    11  import {useForm} from "@/hooks/web/useForm";
    12  import {parseTime} from "@/utils";
    13  import {ContentWrap} from "@/components/ContentWrap";
    14  import AttributesViewer from "@/views/MessageDelivery/components/AttributesViewer.vue";
    15  import {Dialog} from '@/components/Dialog'
    16  
    17  const {register, methods} = useForm()
    18  const {t} = useI18n()
    19  
    20  interface TableObject {
    21    tableList: ApiMessageDelivery[]
    22    params?: any
    23    loading: boolean
    24    sort?: string
    25    messageType?: string
    26    startDate?: string;
    27    endDate?: string;
    28  }
    29  
    30  interface Params {
    31    page?: number;
    32    limit?: number;
    33    sort?: string;
    34    messageType?: string;
    35    startDate?: string;
    36    endDate?: string;
    37  }
    38  
    39  const tableObject = reactive<TableObject>(
    40    {
    41      tableList: [],
    42      loading: false,
    43    }
    44  );
    45  
    46  const schema = reactive<FormSchema[]>([
    47    {
    48      field: 'dateTime',
    49      component: 'DatePicker',
    50      label: t('messageDelivery.dateTimerange'),
    51      colProps: {
    52        span: 24
    53      },
    54      value: [],
    55      componentProps: {
    56        type: 'datetimerange',
    57        shortcuts: [
    58          {
    59            text: t('messageDelivery.today'),
    60            value: () => {
    61              const end = new Date()
    62              const start = new Date()
    63              start.setTime(start.getTime() - start.getHours() * 3600 * 1000 - start.getMinutes() * 60 * 1000 - start.getSeconds() * 1000)
    64              return [start, end]
    65            }
    66          },
    67          {
    68            text: t('messageDelivery.yesterday'),
    69            value: () => {
    70              const end = new Date()
    71              const start = new Date()
    72              end.setHours(0)
    73              end.setMinutes(0)
    74              end.setSeconds(0)
    75              start.setTime(end.getTime() - 3600 * 1000 * 24)
    76              return [start, end]
    77            }
    78          },
    79          {
    80            text: t('messageDelivery.aWeekAgo'),
    81            value: () => {
    82              const end = new Date()
    83              const start = new Date()
    84              end.setHours(0)
    85              end.setMinutes(0)
    86              end.setSeconds(0)
    87              start.setTime(end.getTime() - 3600 * 1000 * 24 * 7)
    88              return [start, end]
    89            }
    90          }
    91        ],
    92        onChange: (val: Date[]) => {
    93          if (val && val.length > 1) {
    94            tableObject.startDate = val[0].toISOString()
    95            tableObject.endDate = val[1].toISOString()
    96          } else {
    97            tableObject.startDate = undefined
    98            tableObject.endDate = undefined
    99          }
   100          getList()
   101        }
   102      },
   103    },
   104    {
   105      field: 'messageTypes',
   106      label: t('messageDelivery.messageType'),
   107      component: 'CheckboxButton',
   108      value: [],
   109      colProps: {
   110        span: 24
   111      },
   112      componentProps: {
   113        options: [
   114          {
   115            label: 'web_push',
   116            value: 'web_push'
   117          },
   118          {
   119            label: 'html5_notify',
   120            value: 'html5_notify'
   121          },
   122          {
   123            label: 'email',
   124            value: 'email'
   125          },
   126          {
   127            label: 'sms',
   128            value: 'sms'
   129          },
   130          {
   131            label: 'telegram',
   132            value: 'telegram'
   133          },
   134          {
   135            label: 'slack',
   136            value: 'slack'
   137          },
   138  
   139        ]
   140      }
   141    },
   142  ])
   143  const columns: TableColumn[] = [
   144    {
   145      field: 'id',
   146      label: t('messageDelivery.id'),
   147      sortable: true,
   148      width: "60px"
   149    },
   150    {
   151      field: 'messageType',
   152      label: t('messageDelivery.messageType'),
   153      sortable: true,
   154      width: "130px",
   155      formatter: (row: ApiMessageDelivery) => {
   156        return h(
   157          'span',
   158          row.message?.type
   159        )
   160      }
   161    },
   162    {
   163      field: 'attributes',
   164      label: t('messageDelivery.attributes'),
   165      sortable: true,
   166      formatter: (row: ApiMessageDelivery) => {
   167        return h(
   168          'span',
   169          Object.keys(row.message?.attributes).length || t('messageDelivery.nothing')
   170        )
   171      }
   172    },
   173    {
   174      field: 'address',
   175      label: t('messageDelivery.address'),
   176      sortable: true,
   177      formatter: (row: ApiMessageDelivery) => {
   178        return h(
   179          'span',
   180          row.address || t('messageDelivery.nothing')
   181        )
   182      }
   183    },
   184    {
   185      field: 'status',
   186      label: t('messageDelivery.status'),
   187      sortable: true,
   188      width: "90px"
   189    },
   190    {
   191      field: 'createdAt',
   192      label: t('main.createdAt'),
   193      type: 'time',
   194      sortable: true,
   195      width: "170px",
   196      formatter: (row: ApiMessageDelivery) => {
   197        return h(
   198          'span',
   199          parseTime(row.createdAt)
   200        )
   201      }
   202    },
   203    {
   204      field: 'createdAt',
   205      label: t('main.updatedAt'),
   206      type: 'time',
   207      sortable: true,
   208      width: "170px",
   209      formatter: (row: ApiMessageDelivery) => {
   210        return h(
   211          'span',
   212          parseTime(row.updatedAt)
   213        )
   214      }
   215    },
   216  ]
   217  const paginationObj = ref<Pagination>({
   218    currentPage: 1,
   219    pageSize: 100,
   220    total: 0,
   221    pageSizes: [50, 100, 150, 250],
   222  })
   223  const currentID = ref('')
   224  
   225  const getList = async () => {
   226    tableObject.loading = true
   227    let params: Params = {
   228      page: paginationObj.value.currentPage,
   229      limit: paginationObj.value.pageSize,
   230      sort: tableObject.sort,
   231      messageType: tableObject.messageType,
   232      startDate: tableObject.startDate,
   233      endDate: tableObject.endDate,
   234    }
   235  
   236    const res = await api.v1.messageDeliveryServiceGetMessageDeliveryList(params)
   237      .catch(() => {
   238      })
   239      .finally(() => {
   240        tableObject.loading = false
   241      })
   242    if (res) {
   243      const {items, meta} = res.data;
   244      tableObject.tableList = items;
   245      // paginationObj.value.pageSize = meta.limit;
   246      paginationObj.value.currentPage = meta.pagination.page;
   247      paginationObj.value.total = meta.pagination.total;
   248    } else {
   249      tableObject.tableList = [];
   250    }
   251  }
   252  
   253  const onLogs = (log: ApiMessageDelivery) => {
   254    getList()
   255  }
   256  
   257  watch(
   258    () => paginationObj.value.currentPage,
   259    () => {
   260      getList()
   261    }
   262  )
   263  
   264  watch(
   265    () => paginationObj.value.pageSize,
   266    () => {
   267      getList()
   268    }
   269  )
   270  
   271  const sortChange = (data) => {
   272    const {column, prop, order} = data;
   273    const pref: string = order === 'ascending' ? '+' : '-'
   274    tableObject.sort = pref + prop
   275    getList()
   276  }
   277  
   278  const onFormChange = async () => {
   279    const {getFormData} = methods
   280    const formData = await getFormData()
   281    const {messageTypes} = formData
   282    if (messageTypes && messageTypes.length > 0) {
   283      tableObject.messageType = messageTypes.join(',')
   284    } else {
   285      tableObject.messageType = undefined
   286    }
   287    getList()
   288  }
   289  
   290  const tableRowClassName = (data) => {
   291    const {row, rowIndex} = data
   292    let style = ''
   293    switch (row?.status) {
   294      case 'in_progress':
   295        style = 'in_progress';
   296        break;
   297      case 'succeed':
   298        style = 'succeed';
   299        break;
   300      case 'error':
   301        style = 'error';
   302        break;
   303    }
   304    return style
   305  }
   306  
   307  const dialogVisible = ref(false)
   308  const dialogTitle = ref('')
   309  const dialogSelectedRow = ref<Nullable<ApiMessage>>(null)
   310  const selectRow = (row: ApiMessageDelivery) => {
   311    if (!row) {
   312      return
   313    }
   314    const {message} = row
   315    dialogSelectedRow.value = message || null;
   316    dialogVisible.value = true
   317  }
   318  
   319  
   320  getList()
   321  
   322  </script>
   323  
   324  <template>
   325    <ContentWrap>
   326      <Form
   327        :schema="schema"
   328        label-position="top"
   329        label-width="auto"
   330        hide-required-asterisk
   331        @change="onFormChange"
   332        @register="register"
   333      />
   334  
   335      <Table
   336        v-model:pageSize="paginationObj.pageSize"
   337        v-model:currentPage="paginationObj.currentPage"
   338        :columns="columns"
   339        :data="tableObject.tableList"
   340        :loading="tableObject.loading"
   341        :pagination="paginationObj"
   342        @sort-change="sortChange"
   343        :row-class-name="tableRowClassName"
   344        @current-change="selectRow"
   345        style="width: 100%"
   346        class="messageDeliveryTable"
   347        :selection="false"
   348        :showUpPagination="20"
   349      />
   350    </ContentWrap>
   351  
   352    <Dialog v-model="dialogVisible" :title="t('messageDelivery.dialogTitle')">
   353      <AttributesViewer :message="dialogSelectedRow"/>
   354      <template #footer>
   355        <ElButton @click="dialogVisible = false">{{ t('main.closeDialog') }}</ElButton>
   356      </template>
   357    </Dialog>
   358  
   359  </template>
   360  
   361  <style lang="less">
   362  
   363  .messageDeliveryTable {
   364    .el-table__row {
   365      td.el-table__cell {
   366        padding: 0;
   367        border-bottom: none !important;
   368      }
   369  
   370      &.error {
   371        --el-table-tr-bg-color: var(--el-color-error-light-5);
   372      }
   373  
   374      &.succeed {
   375        background-color: inherit;
   376      }
   377  
   378      &.in_progress {
   379        --el-table-tr-bg-color: var(--el-color-success-light-5);
   380      }
   381    }
   382  
   383    .el-table__row {
   384      cursor: pointer;
   385    }
   386  }
   387  
   388  
   389  </style>