@@ -0,0 +1,97 @@ | |||
<template> | |||
<template v-if="isFilter"> | |||
<n-tag | |||
v-for="(item,index) in getData.data" | |||
:key="`tag_${index}`" | |||
v-bind="getProps" | |||
:color="getFilter(item[getData.rowKey]).color || getProps.color" | |||
> | |||
{{ getFilter(item[getData.rowKey]).label }} | |||
</n-tag> | |||
</template> | |||
<template v-else> | |||
<n-tag v-for="(item,index) in getData.data" :key="`tag_${index}`" v-bind="getProps"> | |||
{{ item[getData.rowKey] }} | |||
</n-tag> | |||
</template> | |||
</template> | |||
<script> | |||
import { defineComponent, computed, unref } from 'vue' | |||
export default defineComponent({ | |||
name: 'TableTags', | |||
props: { | |||
/* 展示的数据 */ | |||
data: { | |||
type: Object, | |||
defalut: [], | |||
required: true | |||
}, | |||
/* 展示数据取的字段 */ | |||
rowKey: { | |||
type: String, | |||
default: 'name' | |||
}, | |||
/* 过滤的数据 */ | |||
// filters: [ | |||
// { | |||
// key: '', | |||
// label: '', | |||
// color: {} | |||
// } | |||
// ], | |||
filters: { | |||
type: Array, | |||
default: null | |||
}, | |||
/* tag标签的属性 */ | |||
tags: { | |||
type: Object, | |||
default: null | |||
} | |||
}, | |||
setup(props, { emit }) { | |||
const isFilter = computed(() => { | |||
return !!(props.filters) | |||
}) | |||
const { filters } = unref(props) | |||
function getFilter(value) { | |||
const data = filters.find(item => { | |||
return item.key === value | |||
}) | |||
return data | |||
} | |||
/* 获取传递的数据 */ | |||
const getData = computed(() => { | |||
return { | |||
rowKey: unref(props.rowKey), | |||
data: { ...unref(props.data) }, | |||
filters: { ...unref(props.filters) } | |||
} | |||
}) | |||
/* 获取tags的属性 */ | |||
const getProps = computed(() => { | |||
return { | |||
...unref(props.tags), | |||
closable: false, | |||
bordered: props.tags?.bordered || false | |||
} | |||
}) | |||
return { | |||
isFilter, | |||
getFilter, | |||
getData, | |||
getProps | |||
} | |||
} | |||
}) | |||
</script> | |||
<style scoped lang='scss'> | |||
.n-tag{ | |||
background: transparent; | |||
} | |||
</style> |
@@ -1,134 +0,0 @@ | |||
<template> | |||
<!-- <n-data-table> | |||
n-data-table | |||
</n-data-table> --> | |||
<div class="table-toolbar"> | |||
<!--顶部左侧区域--> | |||
<div class="flex items-center table-toolbar-left"> | |||
<slot name="tableTitle" /> | |||
</div> | |||
<div class="flex items-center table-toolbar-right"> | |||
<!--顶部右侧区域--> | |||
<slot name="toolbar" /> | |||
<!--刷新--> | |||
<!-- <n-tooltip trigger="hover"> | |||
<template #trigger> | |||
<div class="table-toolbar-right-icon" @click="reload"> | |||
<n-icon size="18"> | |||
<ReloadOutlined /> | |||
</n-icon> | |||
</div> | |||
</template> --> | |||
<span @click="reload">刷新</span> | |||
<!-- </n-tooltip> --> | |||
<!--表格设置单独抽离成组件--> | |||
<!-- <ColumnSetting /> --> | |||
</div> | |||
</div> | |||
<div class="s-table"> | |||
<n-data-table | |||
ref="tableElRef" | |||
v-bind="getBindValues" | |||
:pagination="pagination" | |||
> | |||
<template v-for="item in Object.keys($slots)" #[item]="data" :key="item"> | |||
<slot :name="item" v-bind="data" /> | |||
</template> | |||
</n-data-table> | |||
</div> | |||
</template> | |||
<script> | |||
import { tableProps } from './tools/props.js' | |||
import { useDataSource } from './tools/useDataSource.js' | |||
import { usePagination } from './tools/usePagination.js' | |||
import { unref, ref, computed, toRaw } from 'vue' | |||
export default { | |||
name: 'DataTable', | |||
props: { | |||
...tableProps | |||
}, | |||
emits: [ | |||
'fetch-success', | |||
'fetch-error', | |||
'update:checked-row-keys', | |||
'edit-end', | |||
'edit-cancel', | |||
'edit-row-end', | |||
'edit-change' | |||
], | |||
setup(props, { emit }) { | |||
const loadingRef = ref(unref(props).loading) | |||
const getLoading = computed(() => unref(loadingRef)) | |||
function setLoading(loading) { | |||
loadingRef.value = loading | |||
} | |||
/* pagination-start */ | |||
const pagination = computed(() => toRaw(unref(getPaginationInfo))) | |||
const { getPaginationInfo, setPagination } = usePagination(props) | |||
/* pagination-end */ | |||
/* tableData-start */ | |||
const tableData = ref([]) | |||
const { getDataSourceRef, reload } = useDataSource(props, { getPaginationInfo, setPagination, tableData, setLoading }, emit) | |||
// 组装表格信息 | |||
const getBindValues = computed(() => { | |||
const tableData = unref(getDataSourceRef) | |||
return { | |||
...unref(props), | |||
loading: unref(getLoading), | |||
// columns: toRaw(unref(getPageColumns)), | |||
// rowKey: unref(getRowKey), | |||
data: tableData, | |||
// size: unref(getTableSize), | |||
remote: true, | |||
'max-height': 'auto' | |||
} | |||
}) | |||
/* tableData-end */ | |||
return { | |||
pagination, | |||
fetch, | |||
reload, | |||
getBindValues | |||
} | |||
} | |||
} | |||
</script> | |||
<style scoped lang='scss'> | |||
.table-toolbar { | |||
display: flex; | |||
justify-content: space-between; | |||
padding: 0 0 16px 0; | |||
.table-toolbar-left { | |||
display: flex; | |||
align-items: center; | |||
justify-content: flex-start; | |||
flex: 1; | |||
} | |||
.table-toolbar-right { | |||
display: flex; | |||
justify-content: flex-end; | |||
flex: 1; | |||
.table-toolbar-icon { | |||
margin-left: 12px; | |||
font-size: 16px; | |||
cursor: pointer; | |||
color: var(--text-color); | |||
&:hover { | |||
color: #1890ff; | |||
} | |||
} | |||
} | |||
} | |||
.table-toolbar-inner-popover-title { | |||
padding: 2px 0; | |||
} | |||
</style> |
@@ -1,35 +0,0 @@ | |||
import { NDataTable } from 'naive-ui' | |||
export const tableProps = { | |||
...NDataTable.props, | |||
/* 初始化接口请求 */ | |||
request: { | |||
type: Function, | |||
default: null | |||
}, | |||
/* 分页信息 */ | |||
pagination: { | |||
type: [Object, Boolean], | |||
default: () => {} | |||
}, | |||
/* 分页设置信息 */ | |||
paginationSetting: { | |||
type: Object, | |||
default: () => { | |||
return { | |||
// 当前页的字段名 | |||
pageField: 'page', | |||
// 每页数量字段名 | |||
sizeField: 'pageSize', | |||
// 接口返回的数据字段名 | |||
listField: 'list', | |||
// 接口返回总页数字段名 | |||
totalField: 'pageCount', | |||
// 默认分页数量 | |||
defaultPageSize: 10, | |||
// 可切换每页数量集合 | |||
pageSizes: [10, 20, 30, 40, 50] | |||
} | |||
} | |||
} | |||
} |
@@ -1,99 +0,0 @@ | |||
import { ref, unref, computed, onMounted } from 'vue' | |||
import { isBoolean } from '@/utils/is' | |||
export function useDataSource(propsRef, { getPaginationInfo, setPagination, setLoading, tableData }, emit) { | |||
const dataSourceRef = ref([]) | |||
async function fetch(opt) { | |||
try { | |||
// setLoading(true) | |||
const { request, pagination } = unref(propsRef) | |||
/* 无接口请求中断 */ | |||
if (!request) return | |||
/* 获取分页信息 */ | |||
const paginationSetting = propsRef.paginationSetting | |||
const pageField = paginationSetting.pageField | |||
const sizeField = paginationSetting.sizeField | |||
const totalField = paginationSetting.totalField | |||
const listField = paginationSetting.listField | |||
let pageParams = {} | |||
const { page = 1, pageSize = 10 } = unref(getPaginationInfo) | |||
if ((isBoolean(pagination) && !pagination) || isBoolean(getPaginationInfo)) { | |||
pageParams = {} | |||
} else { | |||
pageParams[pageField] = (opt && opt[pageField]) || page | |||
pageParams[sizeField] = pageSize | |||
} | |||
const params = { | |||
...pageParams | |||
} | |||
const res = await request(params) | |||
console.log('res', res) | |||
const resultTotal = res[totalField] || 0 | |||
const currentPage = res[pageField] | |||
// // 如果数据异常,需获取正确的页码再次执行 | |||
// if (resultTotal) { | |||
// if (page > resultTotal) { | |||
// setPagination({ | |||
// [pageField]: resultTotal | |||
// }) | |||
// fetch(opt) | |||
// } | |||
// } | |||
const resultInfo = res[listField] ? res[listField] : [] | |||
dataSourceRef.value = resultInfo | |||
setPagination({ | |||
[pageField]: currentPage, | |||
[totalField]: resultTotal | |||
}) | |||
// if (opt && opt[pageField]) { | |||
// setPagination({ | |||
// [pageField]: opt[pageField] || 1 | |||
// }) | |||
// } | |||
emit('fetch-success', { | |||
items: unref(resultInfo), | |||
resultTotal | |||
}) | |||
} catch (error) { | |||
console.error(error) | |||
// emit('fetch-error', error) | |||
// dataSourceRef.value = [] | |||
} finally { | |||
setLoading(false) | |||
} | |||
} | |||
const getDataSourceRef = computed(() => { | |||
const dataSource = unref(dataSourceRef) | |||
if (!dataSource || dataSource.length === 0) { | |||
return unref(dataSourceRef) | |||
} | |||
return unref(dataSourceRef) | |||
}) | |||
function getDataSource() { | |||
console.log(getDataSourceRef.value) | |||
return getDataSourceRef.value | |||
} | |||
function setTableData(values) { | |||
dataSourceRef.value = values | |||
} | |||
onMounted(() => { | |||
setTimeout(() => { | |||
fetch() | |||
}, 15) | |||
}) | |||
return { | |||
fetch, | |||
getDataSourceRef, | |||
getDataSource, | |||
setTableData | |||
} | |||
} |
@@ -1,34 +0,0 @@ | |||
import { computed, unref, ref } from 'vue' | |||
import { isBoolean } from '@/utils/is' | |||
export function usePagination(refProps) { | |||
const configRef = ref({}) | |||
const show = ref(true) | |||
console.log('configRef', configRef) | |||
console.log('refProps', refProps) | |||
const getPaginationInfo = computed(() => { | |||
const { pagination, paginationSetting } = unref(refProps) | |||
if (!unref(show) || (isBoolean(pagination) && !pagination)) { | |||
return false | |||
} | |||
return { | |||
pageSize: paginationSetting.defaultPageSize, | |||
pageSizes: paginationSetting.pageSizes, | |||
showSizePicker: true, | |||
showQuickJumper: true, | |||
...(isBoolean(pagination) ? {} : pagination), | |||
...unref(configRef), | |||
pageCount: unref(configRef)[paginationSetting.totalField] | |||
} | |||
}) | |||
function setPagination(info) { | |||
const paginationInfo = unref(getPaginationInfo) | |||
configRef.value = { | |||
...(!isBoolean(paginationInfo) ? paginationInfo : {}), | |||
...info | |||
} | |||
} | |||
return { getPaginationInfo, setPagination } | |||
} |
@@ -29,8 +29,6 @@ const getMenuOptions = computed(() => { | |||
return generateOptions(permissionStore.routes, '') | |||
}) | |||
console.log('getMenuOptions', getMenuOptions) | |||
function resolvePath(basePath, path) { | |||
if (isExternal(path)) return path | |||
return ( |
@@ -114,7 +114,6 @@ export const usePermissionStore = defineStore('permission', { | |||
const res = await getMenu() | |||
if (res.code === 0) { | |||
const result = dataArrayToRoutes(res.data) | |||
console.log(result) | |||
this.accessRoutes = result | |||
return Promise.resolve(result) | |||
} else { |
@@ -3,29 +3,28 @@ | |||
<n-card> | |||
<data-table | |||
:columns="data.columns" | |||
:data="data.data" | |||
:pagination="data.pagination" | |||
:row-key="(row) => row.id" | |||
:request="loadDataTable" | |||
size="large" | |||
> | |||
<template #tableTitle> | |||
<n-button type="primary" @click="handleUser"> 新建 </n-button> | |||
<n-button type="primary" @click="deleteUsers"> 删除 </n-button> | |||
<!-- <n-button type="primary" @click="deleteUsers"> 删除 </n-button> --> | |||
</template> | |||
</data-table> | |||
</n-card> | |||
</div> | |||
<!-- 新增、编辑弹窗 --> | |||
<user-modal v-model:visible="data.modalShow" :row="rowData" :title="modalTitle" /> | |||
<user-modal v-if="data.modalShow" v-model:visible="data.modalShow" :row="rowData" :title="modalTitle" /> | |||
</template> | |||
<script> | |||
import dataTable from '@/components/DataTable/index.vue' | |||
import TableAction from '@/components/DataTable/tools/Action.vue' | |||
import TableImage from '@/components/DataTable/tools/Image.vue' | |||
import TableTags from '@/components/DataTable/tools/Tags.vue' | |||
import { getUserList } from '@/api/system/user/index.js' | |||
import { h, onMounted, unref, ref } from 'vue' | |||
import { h, unref, ref } from 'vue' | |||
import { reactive } from 'vue' | |||
import UserModal from './components/UserModal.vue' | |||
export default { | |||
@@ -72,7 +71,12 @@ export default { | |||
{ | |||
title: '角色', | |||
key: 'roles', | |||
align: 'center' | |||
align: 'center', | |||
render(row) { | |||
return h(TableTags, { | |||
data: row.roles | |||
}) | |||
} | |||
}, | |||
{ | |||
title: '状态', | |||
@@ -125,10 +129,6 @@ export default { | |||
} | |||
} | |||
], | |||
data: [], | |||
pagination: { | |||
pageSize: 10 | |||
}, | |||
modalShow: false | |||
}) | |||
const modalTitle = ref('添加用户') | |||
@@ -141,21 +141,8 @@ export default { | |||
data.modalShow = true | |||
} | |||
/** | |||
* @description: 获取用户数据 | |||
* @return {*} | |||
*/ | |||
async function fetchList() { | |||
const params = { | |||
page: 1, | |||
limit: 10 | |||
} | |||
const res = await getUserList(params) | |||
data.data = res.data.list | |||
} | |||
const params = reactive({ | |||
name: 'xiaoMa' | |||
name: '' | |||
}) | |||
const loadDataTable = async(res) => { | |||
@@ -170,9 +157,6 @@ export default { | |||
modalTitle.value = '添加用户' | |||
data.modalShow = true | |||
} | |||
onMounted(() => { | |||
fetchList() | |||
}) | |||
return { data, loadDataTable, handleUser, rowData, modalTitle } | |||
}, |