feat: Add example-dialog demo

This commit is contained in:
kailong321200875 2022-02-19 13:17:38 +08:00
parent 41533c15e7
commit 262f4211cf
16 changed files with 311 additions and 24 deletions

View File

@ -92,5 +92,46 @@ export default [
}
}
}
},
// 详情接口
{
url: '/example/detail',
method: 'get',
response: ({ query }) => {
const { id } = query
for (const example of List) {
if (example.id === id) {
return {
code: result_code,
data: example
}
}
}
}
},
// 删除接口
{
url: '/example/delete',
method: 'post',
response: ({ body }) => {
const ids = body.ids
if (!ids) {
return {
code: '500',
message: '请选择需要删除的数据'
}
} else {
let i = List.length
while (i--) {
if (ids.indexOf(List[i].id) !== -1) {
List.splice(i, 1)
}
}
return {
code: result_code,
data: 'success'
}
}
}
}
] as MockMethod[]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -10,6 +10,28 @@ export const getTableListApi = ({ params }: AxiosConfig) => {
}>({ url: '/example/list', method: 'get', params })
}
export const saveTableApi = ({ data }: AxiosConfig) => {
export const saveTableApi = ({ data }: AxiosConfig<Recordable, TableData>) => {
return request({ url: '/example/save', method: 'post', data })
}
export const getTableDetApi = ({
params
}: AxiosConfig<
{
id: string
},
Recordable
>) => {
return request<TableData>({ url: '/example/detail', method: 'get', params })
}
export const delTableListApi = ({
data
}: AxiosConfig<
Recordable,
{
id: string[] | number[]
}
>) => {
return request({ url: '/example/delete', method: 'post', data })
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -100,7 +100,7 @@ const toggleClick = () => {
</template>
<template #default>
<slot :name="item.field">{{ data[item.field] }}</slot>
<slot :name="item.field" :row="data">{{ data[item.field] }}</slot>
</template>
</ElDescriptionsItem>
</ElDescriptions>

View File

@ -3,6 +3,7 @@ import Table from './src/Table.vue'
export interface TableExpose {
setProps: (props: Recordable) => void
setColumn: (columnProps: TableSetPropsType[]) => void
selections: Recordable[]
}
export { Table }

View File

@ -89,9 +89,16 @@ export default defineComponent({
}
}
const selections = ref<Recordable[]>([])
const selectionChange = (selection: Recordable[]) => {
selections.value = selection
}
expose({
setProps,
setColumn
setColumn,
selections
})
const pagination = computed(() => {
@ -226,7 +233,7 @@ export default defineComponent({
align={v.align || align}
headerAlign={v.headerAlign || headerAlign}
label={v.label}
width="100px"
width="65px"
></ElTableColumn>
)
} else {
@ -264,6 +271,7 @@ export default defineComponent({
// @ts-ignore
ref={elTableRef}
data={unref(getProps).data}
onSelection-change={selectionChange}
{...getBindValue}
>
{{

View File

@ -1,12 +1,16 @@
import { Table, TableExpose } from '@/components/Table'
import { ElTable } from 'element-plus'
import { ElTable, ElMessageBox, ElMessage } from 'element-plus'
import { ref, reactive, watch, computed, unref, nextTick } from 'vue'
import { AxiosPromise } from 'axios'
import { get, assign } from 'lodash-es'
import type { TableProps } from '@/components/Table/src/types'
import { useI18n } from '@/hooks/web/useI18n'
const { t } = useI18n()
interface UseTableConfig<T, L> {
getListApi: (option: L) => AxiosPromise<T>
delListApi?: (option: AxiosConfig) => AxiosPromise<unknown>
// 返回数据格式配置
response: {
list: string
@ -22,7 +26,6 @@ interface TableObject<K, L> {
tableList: K[]
parmasObj: L
loading: boolean
dialogVisible: boolean
currentRow: Nullable<K>
}
@ -42,8 +45,6 @@ export const useTable = <T, K, L extends AxiosConfig = AxiosConfig>(
parmasObj: {} as L,
// 加载中
loading: true,
// 弹窗
dialogVisible: false,
// 当前行的数据
currentRow: null
})
@ -95,11 +96,31 @@ export const useTable = <T, K, L extends AxiosConfig = AxiosConfig>(
return table
}
const delData = async (paramsObj: AxiosConfig, ids: string[] | number[]) => {
const res = await (config?.delListApi && config?.delListApi(paramsObj))
if (res) {
ElMessage.success(t('common.delSuccess'))
// 计算出临界点
const currentPage =
tableObject.total % tableObject.pageSize === ids.length || tableObject.pageSize === 1
? tableObject.currentPage > 1
? tableObject.currentPage - 1
: tableObject.currentPage
: tableObject.currentPage
tableObject.currentPage = currentPage
methods.getList()
}
}
const methods: {
setProps: (props: Recordable) => void
getList: () => Promise<void>
setColumn: (columnProps: TableSetPropsType[]) => void
setSearchParmas: (data: Recordable) => void
getSelections: () => Promise<K[]>
delList: (ids: string[] | number[], multiple: boolean, message?: boolean) => Promise<void>
} = {
getList: async () => {
tableObject.loading = true
@ -122,6 +143,10 @@ export const useTable = <T, K, L extends AxiosConfig = AxiosConfig>(
const table = await getTable()
table?.setColumn(columnProps)
},
getSelections: async () => {
const table = await getTable()
return (table?.selections || []) as K[]
},
// 与Search组件结合
setSearchParmas: (data: Recordable) => {
tableObject.currentPage = 1
@ -133,6 +158,39 @@ export const useTable = <T, K, L extends AxiosConfig = AxiosConfig>(
}
})
methods.getList()
},
// 删除数据
delList: async (ids: string[] | number[], multiple: boolean, message = true) => {
const tableRef = await getTable()
if (multiple) {
if (!tableRef?.selections.length) {
ElMessage.warning(t('common.delNoData'))
return
}
} else {
if (!tableObject.currentRow) {
ElMessage.warning(t('common.delNoData'))
return
}
}
const paramsObj: AxiosConfig = {
data: {
ids
}
}
if (message) {
ElMessageBox.confirm(t('common.delMessage'), t('common.delWarning'), {
confirmButtonText: t('common.delOk'),
cancelButtonText: t('common.delCancel'),
type: 'warning'
})
.then(async () => {
await delData(paramsObj, ids)
})
.catch(() => {})
} else {
await delData(paramsObj, ids)
}
}
}

View File

@ -33,7 +33,13 @@ export default {
query: 'Query',
reset: 'Reset',
shrink: 'Put away',
expand: 'Expand'
expand: 'Expand',
delMessage: 'Delete the selected data?',
delWarning: 'Warning',
delOk: 'OK',
delCancel: 'Cancel',
delNoData: 'Please select the data to delete',
delSuccess: 'Deleted successfully'
},
setting: {
projectSetting: 'Project setting',
@ -374,6 +380,7 @@ export default {
pageviews: 'Pageviews',
important: 'Important',
content: 'Content',
save: 'Save'
save: 'Save',
detail: 'Detail'
}
}

View File

@ -33,7 +33,13 @@ export default {
query: '查询',
reset: '重置',
shrink: '收起',
expand: '展开'
expand: '展开',
delMessage: '是否删除所选中数据?',
delWarning: '提示',
delOk: '确定',
delCancel: '取消',
delNoData: '请选择需要删除的数据',
delSuccess: '删除成功'
},
setting: {
projectSetting: '项目配置',
@ -371,6 +377,7 @@ export default {
pageviews: '阅读数',
important: '重要',
content: '内容',
save: '保存'
save: '保存',
detail: '详情'
}
}

View File

@ -1,10 +1,13 @@
import { defineStore } from 'pinia'
import { store } from '../index'
import { useCache } from '@/hooks/web/useCache'
import { appModules } from '@/config/app'
import type { AppState, LayoutType, ThemeTypes } from '@/config/app'
import { setCssVar, humpToUnderline } from '@/utils'
import { ElMessage } from 'element-plus'
const { wsCache } = useCache()
export const useAppStore = defineStore({
id: 'app',
state: (): AppState => appModules,
@ -119,6 +122,7 @@ export const useAppStore = defineStore({
return
}
this.layout = layout
wsCache.set('layout', this.layout)
},
setTitle(title: string) {
this.title = title
@ -132,15 +136,18 @@ export const useAppStore = defineStore({
document.documentElement.classList.add('light')
document.documentElement.classList.remove('dark')
}
wsCache.set('isDark', this.isDark)
},
setCurrentSize(currentSize: ElememtPlusSzie) {
this.currentSize = currentSize
wsCache.set('currentSize', this.currentSize)
},
setMobile(mobile: boolean) {
this.mobile = mobile
},
setTheme(theme: ThemeTypes) {
this.theme = Object.assign(this.theme, theme)
wsCache.set('theme', this.theme)
},
setCssVarTheme() {
for (const key in this.theme) {

View File

@ -1,8 +1,11 @@
import { defineStore } from 'pinia'
import { store } from '../index'
import { useCache } from '@/hooks/web/useCache'
import { localeModules, elLocaleMap } from '@/config/locale'
import type { LocaleState } from '@/config/locale'
const { wsCache } = useCache()
export const useLocaleStore = defineStore({
id: 'locales',
state: (): LocaleState => localeModules,
@ -22,6 +25,7 @@ export const useLocaleStore = defineStore({
// this.locale = Object.assign(this.locale, localeMap)
this.currentLocale.lang = localeMap?.lang
this.currentLocale.elLocale = elLocaleMap[localeMap?.lang]
wsCache.set('lang', localeMap?.lang)
}
}
})

View File

@ -5,11 +5,12 @@ import { Dialog } from '@/components/Dialog'
import { useI18n } from '@/hooks/web/useI18n'
import { ElButton, ElTag } from 'element-plus'
import { Table } from '@/components/Table'
import { getTableListApi, saveTableApi } from '@/api/table'
import { getTableListApi, saveTableApi, delTableListApi } from '@/api/table'
import { useTable } from '@/hooks/web/useTable'
import { TableData } from '@/api/table/types'
import { h, reactive, ref, unref } from 'vue'
import Write from './components/Write.vue'
import Detail from './components/Detail.vue'
const { register, tableObject, methods } = useTable<
{
@ -19,6 +20,7 @@ const { register, tableObject, methods } = useTable<
TableData
>({
getListApi: getTableListApi,
delListApi: delTableListApi,
response: {
list: 'list',
total: 'total'
@ -82,18 +84,43 @@ const columns = reactive<TableColumn[]>([
},
{
field: 'action',
width: '260px',
label: t('tableDemo.action')
}
])
const dialogVisible = ref(false)
const dialogTitle = ref('')
const AddAction = () => {
dialogTitle.value = t('exampleDemo.add')
tableObject.currentRow = null
tableObject.dialogVisible = true
dialogVisible.value = true
}
const editAction = (row: TableData) => {
const delLoading = ref(false)
const delData = async (row: TableData | null, multiple: boolean) => {
tableObject.currentRow = row
tableObject.dialogVisible = true
const { delList, getSelections } = methods
const selections = await getSelections()
delLoading.value = true
await delList(
multiple ? selections.map((v) => v.id) : [tableObject.currentRow?.id as string],
multiple
).finally(() => {
delLoading.value = false
})
}
const actionType = ref('')
const action = (row: TableData, type: string) => {
dialogTitle.value = t(type === 'edit' ? 'exampleDemo.edit' : 'exampleDemo.detail')
actionType.value = type
tableObject.currentRow = row
dialogVisible.value = true
}
const writeRef = ref<ComponentRef<typeof Write>>()
@ -105,7 +132,7 @@ const save = async () => {
const validate = await write?.elFormRef?.validate()?.catch(() => {})
if (validate) {
loading.value = true
const data = await write?.getFormData()
const data = (await write?.getFormData()) as TableData
const res = await saveTableApi({
data
})
@ -114,7 +141,7 @@ const save = async () => {
loading.value = false
})
if (res) {
tableObject.dialogVisible = false
dialogVisible.value = false
tableObject.currentPage = 1
getList()
}
@ -128,7 +155,9 @@ const save = async () => {
<div class="mb-10px">
<ElButton type="primary" @click="AddAction">{{ t('exampleDemo.add') }}</ElButton>
<ElButton type="danger">{{ t('exampleDemo.del') }}</ElButton>
<ElButton :loading="delLoading" type="danger" @click="delData(null, true)">
{{ t('exampleDemo.del') }}
</ElButton>
</div>
<Table
@ -143,21 +172,29 @@ const save = async () => {
@register="register"
>
<template #action="{ row }">
<ElButton type="primary" @click="editAction(row)">
<ElButton type="primary" @click="action(row, 'edit')">
{{ t('exampleDemo.edit') }}
</ElButton>
<ElButton type="success" @click="action(row, 'detail')">
{{ t('exampleDemo.detail') }}
</ElButton>
<ElButton type="danger" @click="delData(row, false)">
{{ t('exampleDemo.del') }}
</ElButton>
</template>
</Table>
</ContentWrap>
<Dialog v-model="tableObject.dialogVisible" :title="t('exampleDemo.add')">
<Write ref="writeRef" :current-row="tableObject.currentRow" />
<Dialog v-model="dialogVisible" :title="dialogTitle">
<Write v-if="actionType === 'edit'" ref="writeRef" :current-row="tableObject.currentRow" />
<Detail v-if="actionType === 'detail'" :current-row="tableObject.currentRow" />
<template #footer>
<ElButton type="primary" :loading="loading" @click="save">
<ElButton v-if="actionType !== 'detail'" type="primary" :loading="loading" @click="save">
{{ t('exampleDemo.save') }}
</ElButton>
<ElButton @click="tableObject.dialogVisible = false">{{ t('dialogDemo.close') }}</ElButton>
<ElButton @click="dialogVisible = false">{{ t('dialogDemo.close') }}</ElButton>
</template>
</Dialog>
</template>

View File

@ -0,0 +1,95 @@
<script setup lang="ts">
import { getTableDetApi } from '@/api/table'
import { PropType, watch, ref, reactive } from 'vue'
import type { TableData } from '@/api/table/types'
import { Descriptions } from '@/components/Descriptions'
import { useI18n } from '@/hooks/web/useI18n'
import { ElTag } from 'element-plus'
const { t } = useI18n()
const props = defineProps({
currentRow: {
type: Object as PropType<Nullable<TableData>>,
default: () => null
}
})
const currentRow = ref<Nullable<TableData>>(null)
const loading = ref(false)
const getTableDet = async () => {
loading.value = true
const res = await getTableDetApi({
params: {
id: props.currentRow?.id as string
}
}).finally(() => {
loading.value = false
})
if (res) {
currentRow.value = res.data
}
}
watch(
() => props.currentRow,
() => {
getTableDet()
},
{
deep: true,
immediate: true
}
)
const schema = reactive<DescriptionsSchema[]>([
{
field: 'title',
label: t('exampleDemo.title'),
span: 24
},
{
field: 'author',
label: t('exampleDemo.author')
},
{
field: 'display_time',
label: t('exampleDemo.displayTime')
},
{
field: 'importance',
label: t('exampleDemo.importance')
},
{
field: 'pageviews',
label: t('exampleDemo.pageviews')
},
{
field: 'content',
label: t('exampleDemo.content'),
span: 24
}
])
</script>
<template>
<Descriptions v-loading="loading" :schema="schema" :data="currentRow || {}">
<template #importance="{ row }: { row: TableData }">
<ElTag :type="row.importance === 1 ? 'success' : row.importance === 2 ? 'warning' : 'danger'">
{{
row.importance === 1
? t('tableDemo.important')
: row.importance === 2
? t('tableDemo.good')
: t('tableDemo.commonly')
}}
</ElTag>
</template>
<template #content="{ row }: { row: TableData }">
<div v-html="row.content"></div>
</template>
</Descriptions>
</template>