|
|
@@ -0,0 +1,248 @@
|
|
|
+<script setup lang="tsx">
|
|
|
+import {
|
|
|
+ ElButton,
|
|
|
+ ElSwitch,
|
|
|
+ ElDrawer,
|
|
|
+ ElForm,
|
|
|
+ ElFormItem,
|
|
|
+ ElInput,
|
|
|
+ ElMessageBox,
|
|
|
+ ElMessage
|
|
|
+} from 'element-plus'
|
|
|
+import { ContentWrap } from '@/components/ContentWrap'
|
|
|
+import { useI18n } from '@/hooks/web/useI18n'
|
|
|
+import { Table, TableColumn } from '@/components/Table'
|
|
|
+import { BaseButton } from '@/components/Button'
|
|
|
+import type { ChannelData } from '@/api/channel/types'
|
|
|
+import { ref, reactive } from 'vue'
|
|
|
+import { getChannelListApi, addChannelApi, editChannelApi, delChannelApi } from '@/api/channel'
|
|
|
+
|
|
|
+const { t } = useI18n()
|
|
|
+
|
|
|
+const columns: TableColumn[] = [
|
|
|
+ {
|
|
|
+ field: 'name',
|
|
|
+ label: t('channel.name')
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'code',
|
|
|
+ label: t('channel.code')
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'description',
|
|
|
+ label: t('channel.description'),
|
|
|
+ showOverflowTooltip: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'status',
|
|
|
+ label: t('channel.status'),
|
|
|
+ slots: {
|
|
|
+ default: (data) => {
|
|
|
+ return (
|
|
|
+ <ElSwitch
|
|
|
+ modelValue={data.row.status}
|
|
|
+ onUpdate:modelValue={(val) => updateStatus(data.row, val)}
|
|
|
+ />
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'createTime',
|
|
|
+ label: t('channel.createTime')
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'action',
|
|
|
+ label: t('channel.action'),
|
|
|
+ width: 180,
|
|
|
+ slots: {
|
|
|
+ default: (data) => {
|
|
|
+ return (
|
|
|
+ <>
|
|
|
+ <BaseButton type="primary" onClick={() => actionFn('edit', data.row)}>
|
|
|
+ {t('channel.edit')}
|
|
|
+ </BaseButton>
|
|
|
+ <BaseButton type="danger" onClick={() => deleteFn(data.row)}>
|
|
|
+ {t('channel.delete')}
|
|
|
+ </BaseButton>
|
|
|
+ </>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+]
|
|
|
+
|
|
|
+const loading = ref(true)
|
|
|
+const channelList = ref<ChannelData[]>([])
|
|
|
+const drawer = ref(false)
|
|
|
+const drawerTitle = ref('')
|
|
|
+const searchName = ref('')
|
|
|
+
|
|
|
+const form = reactive({
|
|
|
+ type: 'add',
|
|
|
+ data: {
|
|
|
+ id: '',
|
|
|
+ name: '',
|
|
|
+ code: '',
|
|
|
+ description: '',
|
|
|
+ status: true
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+const formReset = () => {
|
|
|
+ form.data.id = ''
|
|
|
+ form.data.name = ''
|
|
|
+ form.data.code = ''
|
|
|
+ form.data.description = ''
|
|
|
+ form.data.status = true
|
|
|
+}
|
|
|
+
|
|
|
+const getList = async () => {
|
|
|
+ loading.value = true
|
|
|
+ const res = await getChannelListApi({
|
|
|
+ name: searchName.value || undefined,
|
|
|
+ pageIndex: 1,
|
|
|
+ pageSize: 100
|
|
|
+ })
|
|
|
+ .catch(() => ({}))
|
|
|
+ .finally(() => {
|
|
|
+ loading.value = false
|
|
|
+ })
|
|
|
+ if (res?.data) {
|
|
|
+ channelList.value = res.data.list || []
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const updateStatus = async (row: ChannelData, val: boolean) => {
|
|
|
+ if (!row.id) return
|
|
|
+ await editChannelApi({ id: row.id, status: val })
|
|
|
+ .then(() => {
|
|
|
+ ElMessage.success(t('channel.updateSuccess'))
|
|
|
+ row.status = val
|
|
|
+ })
|
|
|
+ .catch(() => {})
|
|
|
+}
|
|
|
+
|
|
|
+const actionFn = (type: 'add' | 'edit', row?: ChannelData) => {
|
|
|
+ formReset()
|
|
|
+ if (type === 'add') {
|
|
|
+ form.type = 'add'
|
|
|
+ drawerTitle.value = t('channel.add')
|
|
|
+ } else if (row) {
|
|
|
+ form.type = 'edit'
|
|
|
+ drawerTitle.value = t('channel.edit')
|
|
|
+ form.data.id = row.id!
|
|
|
+ form.data.name = row.name
|
|
|
+ form.data.code = row.code
|
|
|
+ form.data.description = row.description || ''
|
|
|
+ form.data.status = row.status !== false
|
|
|
+ }
|
|
|
+ drawer.value = true
|
|
|
+}
|
|
|
+
|
|
|
+const onSubmit = async () => {
|
|
|
+ if (!form.data.name?.trim()) {
|
|
|
+ ElMessage.warning(t('channel.nameRequired'))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (!form.data.code?.trim()) {
|
|
|
+ ElMessage.warning(t('channel.codeRequired'))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (form.type === 'add') {
|
|
|
+ await addChannelApi(form.data)
|
|
|
+ .then(() => {
|
|
|
+ ElMessage.success(t('channel.addSuccess'))
|
|
|
+ drawer.value = false
|
|
|
+ getList()
|
|
|
+ })
|
|
|
+ .catch(() => {})
|
|
|
+ } else {
|
|
|
+ await editChannelApi(form.data)
|
|
|
+ .then(() => {
|
|
|
+ ElMessage.success(t('channel.editSuccess'))
|
|
|
+ drawer.value = false
|
|
|
+ getList()
|
|
|
+ })
|
|
|
+ .catch(() => {})
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const deleteFn = (row: ChannelData) => {
|
|
|
+ ElMessageBox.confirm(t('channel.deleteConfirm'), t('common.delWarning'), {
|
|
|
+ confirmButtonText: t('common.delOk'),
|
|
|
+ cancelButtonText: t('common.cancel'),
|
|
|
+ type: 'warning'
|
|
|
+ })
|
|
|
+ .then(async () => {
|
|
|
+ await delChannelApi([row.id!])
|
|
|
+ ElMessage.success(t('channel.deleteSuccess'))
|
|
|
+ getList()
|
|
|
+ })
|
|
|
+ .catch(() => {})
|
|
|
+}
|
|
|
+
|
|
|
+const onSearch = () => {
|
|
|
+ getList()
|
|
|
+}
|
|
|
+
|
|
|
+const onReset = () => {
|
|
|
+ searchName.value = ''
|
|
|
+ getList()
|
|
|
+}
|
|
|
+
|
|
|
+getList()
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <ContentWrap>
|
|
|
+ <div class="mb-4 flex flex-wrap items-center gap-3">
|
|
|
+ <ElButton type="primary" @click="actionFn('add')">
|
|
|
+ {{ t('channel.add') }}
|
|
|
+ </ElButton>
|
|
|
+ <div class="flex items-center gap-2">
|
|
|
+ <el-input
|
|
|
+ v-model="searchName"
|
|
|
+ :placeholder="t('channel.searchPlaceholder')"
|
|
|
+ clearable
|
|
|
+ style="width: 200px"
|
|
|
+ @keyup.enter="onSearch"
|
|
|
+ />
|
|
|
+ <ElButton type="primary" @click="onSearch">{{ t('common.query') }}</ElButton>
|
|
|
+ <ElButton @click="onReset">{{ t('common.reset') }}</ElButton>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </ContentWrap>
|
|
|
+ <ContentWrap>
|
|
|
+ <Table :columns="columns" :data="channelList" :loading="loading" row-key="id" />
|
|
|
+ </ContentWrap>
|
|
|
+ <ElDrawer v-model="drawer" direction="rtl" size="40%" :title="drawerTitle">
|
|
|
+ <ElForm :model="form.data" label-width="auto" style="max-width: 500px">
|
|
|
+ <ElFormItem :label="t('channel.name')" required>
|
|
|
+ <ElInput v-model="form.data.name" :placeholder="t('channel.namePlaceholder')" />
|
|
|
+ </ElFormItem>
|
|
|
+ <ElFormItem :label="t('channel.code')" required>
|
|
|
+ <ElInput
|
|
|
+ v-model="form.data.code"
|
|
|
+ :placeholder="t('channel.codePlaceholder')"
|
|
|
+ :disabled="form.type === 'edit'"
|
|
|
+ />
|
|
|
+ </ElFormItem>
|
|
|
+ <ElFormItem :label="t('channel.description')">
|
|
|
+ <ElInput
|
|
|
+ v-model="form.data.description"
|
|
|
+ type="textarea"
|
|
|
+ :rows="3"
|
|
|
+ :placeholder="t('channel.descriptionPlaceholder')"
|
|
|
+ />
|
|
|
+ </ElFormItem>
|
|
|
+ <ElFormItem :label="t('channel.status')">
|
|
|
+ <ElSwitch v-model="form.data.status" />
|
|
|
+ </ElFormItem>
|
|
|
+ <ElFormItem>
|
|
|
+ <ElButton type="primary" @click="onSubmit">{{ t('common.ok') }}</ElButton>
|
|
|
+ <ElButton @click="drawer = false">{{ t('common.cancel') }}</ElButton>
|
|
|
+ </ElFormItem>
|
|
|
+ </ElForm>
|
|
|
+ </ElDrawer>
|
|
|
+</template>
|