@@ -160,7 +160,13 @@ export default [ | |||
return true | |||
}) | |||
const List = mockList.filter((item, index) => index < limit * page && index >= limit * (page - 1)) | |||
return resultSuccess(List) | |||
const data = { | |||
list: List, | |||
page: Number(page), | |||
limit: Number(limit), | |||
total: count | |||
} | |||
return resultSuccess(data) | |||
} | |||
}, | |||
{ |
@@ -12,6 +12,7 @@ | |||
"@vicons/antd": "^0.10.0", | |||
"@vicons/ionicons5": "^0.10.0", | |||
"axios": "^0.26.1", | |||
"dayjs": "^1.11.0", | |||
"mockjs": "^1.1.0", | |||
"pinia": "^2.0.13", | |||
"vue": "^3.2.16", |
@@ -13,26 +13,78 @@ | |||
</div> | |||
</div> | |||
<div class="s-table"> | |||
<n-data-table v-bind="getBindProps" /> | |||
<n-data-table | |||
ref="tableElRef" | |||
v-bind="getBindProps" | |||
:pagination="pagination" | |||
@update:page="updatePage" | |||
@update:page-size="updatePageSize" | |||
/> | |||
</div> | |||
</template> | |||
<script> | |||
import { NDataTable } from 'naive-ui' | |||
import { unref, computed } from 'vue' | |||
import { tableProps } from './tools/props.js' | |||
import { useDataSource } from './tools/useDataSource.js' | |||
import { usePagination } from './tools/usePagination.js' | |||
import { ref, unref, computed, toRaw, provide } from 'vue' | |||
export default { | |||
name: 'DataTable', | |||
props: { | |||
...NDataTable.props | |||
...tableProps | |||
}, | |||
setup(props, { emit }) { | |||
const getProps = computed(() => { | |||
return { ...props } | |||
}) | |||
/* loading--start */ | |||
const loadingRef = ref(unref(getProps).loading) | |||
const getLoading = computed(() => unref(loadingRef)) | |||
function setLoading(loading) { | |||
loadingRef.value = loading | |||
} | |||
/* loading--end */ | |||
/* pagination-start */ | |||
const { getPaginationInfo, setPagination } = usePagination(getProps) | |||
const pagination = computed(() => toRaw(unref(getPaginationInfo))) | |||
/* 页码切换 */ | |||
function updatePage(page) { | |||
setPagination({ page: page }) | |||
reload() | |||
} | |||
/* 分页数量切换 */ | |||
function updatePageSize(size) { | |||
setPagination({ page: 1, pageSize: size }) | |||
reload() | |||
} | |||
/* pagination-end */ | |||
/* tableData-start */ | |||
const tableData = ref([]) | |||
const { getDataSourceRef, getRowKey, reload } = useDataSource(getProps, { getPaginationInfo, setPagination, tableData, setLoading }, emit) | |||
const getBindProps = computed(() => { | |||
return { | |||
...unref(props) | |||
...unref(getProps), | |||
loading: unref(getLoading), | |||
rowKey: unref(getRowKey), | |||
data: unref(getDataSourceRef), | |||
remote: true | |||
} | |||
}) | |||
const key = Symbol('s-table') | |||
provide(key, { getBindProps }) | |||
/* tableData-end */ | |||
return { | |||
getBindProps | |||
getBindProps, | |||
pagination, | |||
updatePage, | |||
updatePageSize | |||
} | |||
} | |||
} |
@@ -0,0 +1,39 @@ | |||
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: 'limit', | |||
// 接口返回的数据字段名 | |||
listField: 'list', | |||
// 接口返回总页数字段名 | |||
totalField: 'total', | |||
// 默认分页数量 | |||
pageSize: 10, | |||
// 可切换每页数量集合 | |||
pageSizes: [10, 20, 30, 40, 50], | |||
// 是否显示每页条数的选择器 | |||
showSizePicker: false, | |||
// 是否显示快速跳转 | |||
showQuickJumper: false | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,111 @@ | |||
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 { | |||
/* 设置loading */ | |||
setLoading(true) | |||
const { request, pagination, paginationSetting } = unref(propsRef) | |||
/* 无接口请求中断 */ | |||
if (!request) return | |||
/* 获取分页信息 */ | |||
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 response = await request(params) | |||
const res = response.data | |||
const resultTotal = res[totalField] || 0 | |||
const currentPage = res[pageField] | |||
// 如果数据异常,需获取正确的页码再次执行 | |||
if (resultTotal) { | |||
if (page > Math.ceil(resultTotal / pageSize)) { | |||
setPagination({ | |||
[pageField]: Math.ceil(resultTotal / pageSize) | |||
}) | |||
fetch(opt) | |||
} | |||
} | |||
const resultInfo = res[listField] ? res[listField] : [] | |||
dataSourceRef.value = resultInfo | |||
setPagination({ | |||
[pageField]: currentPage, | |||
[totalField]: Math.ceil(resultTotal / pageSize) | |||
}) | |||
/* 更新页码数据 */ | |||
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() { | |||
return getDataSourceRef.value | |||
} | |||
function setTableData(values) { | |||
dataSourceRef.value = values | |||
} | |||
const getRowKey = computed(() => { | |||
const { rowKey } = unref(propsRef) | |||
return rowKey || (() => { | |||
return 'key' | |||
}) | |||
}) | |||
async function reload(opt) { | |||
await fetch(opt) | |||
} | |||
onMounted(() => { | |||
setTimeout(() => { | |||
fetch() | |||
}, 15) | |||
}) | |||
return { | |||
fetch, | |||
getDataSourceRef, | |||
getDataSource, | |||
setTableData, | |||
getRowKey, | |||
reload | |||
} | |||
} |
@@ -0,0 +1,37 @@ | |||
import { computed, unref, ref } from 'vue' | |||
import { isBoolean } from '@/utils/is' | |||
export function usePagination(refProps) { | |||
const configRef = ref({}) | |||
const getPaginationInfo = computed(() => { | |||
const { pagination, paginationSetting } = unref(refProps) | |||
/* 判断是否需要展示分页 */ | |||
if ((isBoolean(pagination) && !pagination)) { | |||
return false | |||
} | |||
/* 返回配置的分页信息 */ | |||
return { | |||
pageSize: paginationSetting.pageSize, | |||
pageSizes: paginationSetting.pageSizes, | |||
showSizePicker: paginationSetting.showSizePicker, | |||
showQuickJumper: paginationSetting.showQuickJumper, | |||
...(isBoolean(pagination) ? {} : pagination), | |||
...unref(configRef), | |||
pageCount: unref(configRef)[paginationSetting.totalField] | |||
} | |||
}) | |||
function setPagination(info) { | |||
const paginationInfo = unref(getPaginationInfo) | |||
configRef.value = { | |||
...(!isBoolean(paginationInfo) ? paginationInfo : {}), | |||
...info | |||
} | |||
} | |||
function getPagination() { | |||
return unref(getPaginationInfo) | |||
} | |||
return { getPaginationInfo, setPagination, getPagination } | |||
} |
@@ -1,13 +1,13 @@ | |||
<template> | |||
<div class="tabs-view" :class="{'tabs-view-fix': tagsMenuSetting.fixed,}"> | |||
<div class="tabs-view" :class="{'tabs-view-fix': tagsMenuSetting.fixed,}" :style="getChangeStyle"> | |||
<div class="tabs-view-main"> | |||
<div ref="navWrap" class="tabs-card" :class="{ 'tabs-card-scrollable': scrollable }"> | |||
<span class="tabs-card-prev" :class="{ 'tabs-card-prev-hide': !scrollable }" @click="scrollPrev"> | |||
<div ref="navWrap" class="tabs-card" :class="{ 'tabs-card-scrollable': state.scrollable }"> | |||
<span class="tabs-card-prev" :class="{ 'tabs-card-prev-hide': !state.scrollable }" @click="scrollPrev"> | |||
<n-icon size="16" color="#515a6e"> | |||
<LeftOutlined /> | |||
</n-icon> | |||
</span> | |||
<span class="tabs-card-next" :class="{ 'tabs-card-next-hide': !scrollable }" @click="scrollNext"> | |||
<span class="tabs-card-next" :class="{ 'tabs-card-next-hide': !state.scrollable }" @click="scrollNext"> | |||
<n-icon size="16" color="#515a6e"> | |||
<RightOutlined /> | |||
</n-icon> | |||
@@ -31,6 +31,31 @@ | |||
</Draggable> | |||
</div> | |||
</div> | |||
<div class="tabs-close"> | |||
<n-dropdown | |||
trigger="hover" | |||
placement="bottom-end" | |||
:options="tagsMemuOptions" | |||
@select="closeHandleSelect" | |||
> | |||
<div class="tabs-close-btn"> | |||
<n-icon size="16" color="#515a6e"> | |||
<DownOutlined /> | |||
</n-icon> | |||
</div> | |||
</n-dropdown> | |||
</div> | |||
<n-dropdown | |||
:show="state.showDropdown" | |||
:x="state.dropdownX" | |||
:y="state.dropdownY" | |||
placement="bottom-start" | |||
:options="tagsMemuOptions" | |||
@clickoutside="onClickOutside" | |||
@select="closeHandleSelect" | |||
/> | |||
</div> | |||
</div> | |||
</template> | |||
@@ -39,26 +64,59 @@ | |||
import { | |||
LeftOutlined, | |||
RightOutlined, | |||
CloseOutlined | |||
CloseOutlined, | |||
DownOutlined, | |||
ReloadOutlined, | |||
ColumnWidthOutlined, | |||
MinusOutlined | |||
} from '@vicons/antd' | |||
import Draggable from 'vuedraggable' | |||
import { reactive, computed, watch } from 'vue' | |||
import { reactive, computed, watch, defineProps, ref, unref, provide, nextTick } from 'vue' | |||
import { useRoute, useRouter } from 'vue-router' | |||
import { useTagsMenuStore } from '@/store/modules/tagsMenu.js' | |||
import { useSettingStore } from '@/store/modules/setting.js' | |||
import { getTags, setTags } from '@/utils/tags.js' | |||
import { isString } from '@/utils/is.js' | |||
import { renderIcon } from '@/utils' | |||
const props = defineProps({ | |||
collapsed: { | |||
type: Boolean | |||
}, | |||
menuMode: { | |||
type: String, | |||
default: 'sidebar' | |||
} | |||
}) | |||
/* 白名单 */ | |||
const whiteList = ['Login', 'NOT_FOUND'] | |||
/* 基础页面 */ | |||
const baseMenu = '/home' | |||
/* 获取路由器 */ | |||
const route = useRoute() | |||
const router = useRouter() | |||
const { push, replace } = router | |||
/* 使用store数据 */ | |||
const tagsMenuStore = useTagsMenuStore() | |||
const settingStore = useSettingStore() | |||
const tabsList = computed(() => tagsMenuStore.tabsList) | |||
const tagsMenuSetting = computed(() => settingStore.getTagsMenuSetting) | |||
/* 组装样式 */ | |||
const getChangeStyle = computed(() => { | |||
const { collapsed, menuMode } = props | |||
const { cWidth, width } = unref(settingStore.getSidebarSetting) | |||
const { fixed } = unref(settingStore.getTagsMenuSetting) | |||
const lenNum = menuMode === 'header' ? '0px' : collapsed ? `${cWidth}px` : `${width}px` | |||
return { | |||
left: lenNum, | |||
width: `calc(100% - ${!fixed ? '0px' : lenNum})` | |||
} | |||
}) | |||
let cacheRoutes = [] | |||
const simpleRoute = getSimpleRoute(route) | |||
try { | |||
@@ -82,13 +140,15 @@ tagsMenuStore.initTabs(cacheRoutes) | |||
const state = reactive({ | |||
activeKey: route.fullPath, | |||
scrollable: false | |||
scrollable: false, | |||
showDropdown: false, | |||
dropdownX: 0, | |||
dropdownY: 0 | |||
}) | |||
watch( | |||
() => route.fullPath, | |||
(to) => { | |||
console.log('to', to) | |||
// if (whiteList.includes(route.name)) return | |||
state.activeKey = to | |||
tagsMenuStore.addTabs(getSimpleRoute(route)) | |||
@@ -143,27 +203,147 @@ function goPage(e) { | |||
* @description: 删除项 | |||
* @return {*} | |||
*/ | |||
// 删除tab | |||
function closeTabItem(e) { | |||
// const { fullPath } = e | |||
// const routeInfo = tabsList.value.find((item) => item.fullPath == fullPath) | |||
// removeTab(routeInfo) | |||
const { fullPath } = e | |||
const routeInfo = tabsList.value.find((item) => item.fullPath === fullPath) | |||
removeTab(routeInfo) | |||
} | |||
/** | |||
* @description: | |||
* @return {*} | |||
*/ | |||
const removeTab = (route) => { | |||
if (tabsList.value.length === 1) { | |||
// return message.warning('这已经是最后一页,不能再关闭了!') | |||
} | |||
// delKeepAliveCompName() | |||
tagsMenuStore.closeCurrentTab(route) | |||
// 如果关闭的是当前页 | |||
if (state.activeKey === route.fullPath) { | |||
const currentRoute = tabsList.value[Math.max(0, tabsList.value.length - 1)] | |||
state.activeKey = currentRoute.fullPath | |||
router.push(currentRoute) | |||
} | |||
// updateNavScroll() | |||
} | |||
// const delKeepAliveCompName = () => { | |||
// if (route.meta.keepAlive) { | |||
// const name = router.currentRoute.value.matched.find((item) => item.name === route.name) | |||
// ?.components?.default.name | |||
// if (name) { | |||
// asyncRouteStore.keepAliveComponents = asyncRouteStore.keepAliveComponents.filter( | |||
// (item) => item != name | |||
// ) | |||
// } | |||
// } | |||
// } | |||
/* dropdown--start */ | |||
/* 右侧下拉菜单 */ | |||
const isCurrent = ref(false) | |||
const tagsMemuOptions = computed(() => { | |||
const isDisabled = unref(tabsList).length <= 1 | |||
return [ | |||
{ | |||
label: '刷新当前', | |||
key: '1', | |||
icon: renderIcon(ReloadOutlined) | |||
}, | |||
{ | |||
label: `关闭当前`, | |||
key: '2', | |||
disabled: unref(isCurrent) || isDisabled, | |||
icon: renderIcon(CloseOutlined) | |||
}, | |||
{ | |||
label: '关闭其他', | |||
key: '3', | |||
disabled: isDisabled, | |||
icon: renderIcon(ColumnWidthOutlined) | |||
}, | |||
{ | |||
label: '关闭全部', | |||
key: '4', | |||
disabled: isDisabled, | |||
icon: renderIcon(MinusOutlined) | |||
} | |||
] | |||
}) | |||
/* 操作右侧下拉菜单 */ | |||
const closeHandleSelect = (key) => { | |||
switch (key) { | |||
// 刷新 | |||
case '1': | |||
reloadPage() | |||
break | |||
// 关闭 | |||
case '2': | |||
removeTab(route) | |||
break | |||
// 关闭其他 | |||
case '3': | |||
closeOther(route) | |||
break | |||
// 关闭所有 | |||
case '4': | |||
closeAll() | |||
break | |||
} | |||
// updateNavScroll() | |||
state.showDropdown = false | |||
} | |||
/* 刷新页面 */ | |||
const reloadPage = () => { | |||
// delKeepAliveCompName() | |||
router.push({ | |||
path: '/redirect' + unref(route).fullPath | |||
}) | |||
} | |||
/* 注入刷新页面方法 */ | |||
provide('reloadPage', reloadPage) | |||
/* 关闭其他 */ | |||
const closeOther = (route) => { | |||
tagsMenuStore.closeOtherTabs(route) | |||
state.activeKey = route.fullPath | |||
router.replace(route.fullPath) | |||
// updateNavScroll() | |||
} | |||
/* 关闭全部 */ | |||
const closeAll = () => { | |||
tagsMenuStore.closeAllTabs() | |||
router.replace(baseMenu) | |||
// updateNavScroll() | |||
} | |||
/* dropdown--end */ | |||
/* contextMenu--start */ | |||
/** | |||
* @description: 右键菜单 | |||
* @return {*} | |||
*/ | |||
function handleContextMenu(e, item) { | |||
// e.preventDefault() | |||
// isCurrent.value = PageEnum.BASE_HOME_REDIRECT === item.path | |||
// state.showDropdown = false | |||
// nextTick().then(() => { | |||
// state.showDropdown = true | |||
// state.dropdownX = e.clientX | |||
// state.dropdownY = e.clientY | |||
// }) | |||
e.preventDefault() | |||
isCurrent.value = baseMenu === item.path | |||
state.showDropdown = false | |||
nextTick().then(() => { | |||
state.showDropdown = true | |||
state.dropdownX = e.clientX | |||
state.dropdownY = e.clientY | |||
}) | |||
} | |||
function onClickOutside() { | |||
state.showDropdown = false | |||
} | |||
/* contextMenu--end */ | |||
/** | |||
* @description: 页面跳转 | |||
* @param undefined | |||
* @param undefined | |||
* @return {*} | |||
*/ | |||
function go(opt, isReplace = false) { | |||
if (!opt) { | |||
return | |||
@@ -258,6 +438,24 @@ function go(opt, isReplace = false) { | |||
} | |||
} | |||
} | |||
.tabs-close { | |||
min-width: 32px; | |||
width: 32px; | |||
height: 32px; | |||
line-height: 32px; | |||
text-align: center; | |||
// background: var(--color); | |||
border-radius: 2px; | |||
cursor: pointer; | |||
.tabs-close-btn { | |||
// color: var(--color); | |||
height: 100%; | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
} | |||
} | |||
} | |||
.tabs-view-fix { |
@@ -1,6 +1,6 @@ | |||
import { useUserStore } from '@/store/modules/user' | |||
import { usePermissionStore } from '@/store/modules/permission' | |||
import { NOT_FOUND_ROUTE } from '@/router/routes' | |||
import { NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '@/router/routes' | |||
import { getToken } from '@/utils/token' | |||
const WHITE_LIST = ['/login', '/redirect'] | |||
@@ -14,7 +14,6 @@ export function createPermissionGuard(router) { | |||
next({ path: '/' }) | |||
} else { | |||
const hasRoutes = !!permissionStore.permissionRoutes.length | |||
console.log(permissionStore.permissionRoutes) | |||
if (hasRoutes) { | |||
next() | |||
} else { | |||
@@ -23,6 +22,7 @@ export function createPermissionGuard(router) { | |||
const routes = await permissionStore.generateRoutes() | |||
router.addRoute(routes[0]) | |||
router.addRoute(NOT_FOUND_ROUTE) | |||
router.addRoute(REDIRECT_ROUTE) | |||
next({ ...to, replace: true }) | |||
} catch (error) { | |||
// removeToken() |
@@ -25,7 +25,8 @@ export const basicRoutes = [ | |||
name: 'Home', | |||
component: Home, | |||
meta: { | |||
title: '首页' | |||
title: '首页', | |||
affix: true | |||
} | |||
} | |||
] | |||
@@ -39,6 +40,27 @@ export const NOT_FOUND_ROUTE = { | |||
isHidden: true | |||
} | |||
export const REDIRECT_ROUTE = { | |||
path: '/redirect', | |||
name: 'Redirect', | |||
component: Layout, | |||
meta: { | |||
title: 'Redirect', | |||
hideBreadcrumb: true | |||
}, | |||
children: [ | |||
{ | |||
path: '/redirect/:path(.*)', | |||
name: 'Redirect', | |||
component: () => import('@/views/redirect/index.vue'), | |||
meta: { | |||
title: 'Redirect', | |||
hideBreadcrumb: true | |||
} | |||
} | |||
] | |||
} | |||
const modules = import.meta.globEager('./modules/*.js') | |||
const asyncRoutes = [] | |||
Object.keys(modules).forEach((key) => { |
@@ -1,3 +1,5 @@ | |||
import { h } from 'vue' | |||
import { NIcon } from 'naive-ui' | |||
import dayjs from 'dayjs' | |||
/** | |||
@@ -74,3 +76,11 @@ export function debounce(method, wait, immediate) { | |||
} | |||
} | |||
} | |||
/** | |||
* @description: 渲染图标 | |||
* @return {*} | |||
*/ | |||
export function renderIcon(icon) { | |||
return () => h(NIcon, null, { default: () => h(icon) }) | |||
} |
@@ -0,0 +1,20 @@ | |||
<script> | |||
import { defineComponent, onBeforeMount } from 'vue' | |||
import { useRoute, useRouter } from 'vue-router' | |||
export default defineComponent({ | |||
name: 'RedirectPage', | |||
setup() { | |||
const route = useRoute() | |||
const router = useRouter() | |||
onBeforeMount(() => { | |||
const { params, query } = route | |||
const { path } = params | |||
router.replace({ | |||
path: '/' + (Array.isArray(path) ? path.join('/') : path), | |||
query | |||
}) | |||
}) | |||
} | |||
}) | |||
</script> |
@@ -1,19 +1,20 @@ | |||
<template> | |||
<div> | |||
<data-table :columns="data.columns" :data="data.data" size="large"> | |||
<template #tableTitle> | |||
<n-button type="primary"> | |||
添加角色 | |||
</n-button> | |||
</template> | |||
</data-table> | |||
<n-card> | |||
<data-table :columns="data.columns" :pagination="false" :data="data.data" size="large"> | |||
<template #tableTitle> | |||
<n-button type="primary"> | |||
添加角色 | |||
</n-button> | |||
</template> | |||
</data-table> | |||
</n-card> | |||
</div> | |||
</template> | |||
<script> | |||
import dataTable from '@/components/DataTable/index.vue' | |||
import Action from '@/components/DataTable/tools/action.vue' | |||
import Action from '@/components/DataTable/tools/Action.vue' | |||
import { getMenuList } from '@/api/system/index.js' | |||
import { h, onMounted } from 'vue' | |||
import { reactive } from 'vue' |
@@ -1,17 +1,181 @@ | |||
<template> | |||
<div> | |||
1 | |||
<n-card> | |||
<data-table | |||
:columns="data.columns" | |||
:row-key="(row) => row.id" | |||
:request="loadDataTable" | |||
size="large" | |||
scroll-x="1200" | |||
> | |||
<template #tableTitle> | |||
<n-button type="primary"> | |||
新建 | |||
</n-button> | |||
<n-button type="primary"> | |||
删除 | |||
</n-button> | |||
</template> | |||
</data-table> | |||
</n-card> | |||
</div> | |||
</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 { getUserList } from '@/api/system/index.js' | |||
import { h, onMounted, unref } from 'vue' | |||
import { reactive } from 'vue' | |||
export default { | |||
name: '', | |||
name: 'MenuPage', | |||
components: { dataTable }, | |||
setup() { | |||
const data = reactive({ | |||
columns: [ | |||
{ | |||
title: '用户编号', | |||
key: 'code', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '头像', | |||
key: 'avatar', | |||
align: 'center', | |||
render(row) { | |||
return h(TableImage, { | |||
images: { | |||
width: 36, | |||
height: 36, | |||
src: row.avatar | |||
} | |||
}) | |||
} | |||
}, | |||
{ | |||
title: '用户账号', | |||
key: 'username', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '用户姓名', | |||
key: 'realname', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '用户类型', | |||
key: 'type', | |||
align: 'center', | |||
width: 100 | |||
}, | |||
{ | |||
title: '角色', | |||
key: 'roles', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '状态', | |||
key: 'status', | |||
align: 'center', | |||
width: 100 | |||
}, | |||
{ | |||
title: '部门', | |||
key: 'deptName', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '创建时间', | |||
key: 'createTime', | |||
align: 'center', | |||
width: 160 | |||
}, | |||
{ | |||
title: '更新时间', | |||
key: 'updateTime', | |||
align: 'center', | |||
width: 160 | |||
}, | |||
{ | |||
title: '操作', | |||
align: 'center', | |||
width: 150, | |||
fixed: 'right', | |||
render(row) { | |||
return h(TableAction, { | |||
actions: [ | |||
{ | |||
label: '添加', | |||
type: 'button', | |||
props: { | |||
type: 'primary', | |||
onClick: play.bind(null, row) | |||
}, | |||
auth: 'basic_list' | |||
}, | |||
{ | |||
label: '修改', | |||
auth: 'basic_list' | |||
}, | |||
{ | |||
label: '删除', | |||
type: 'popconfirm', | |||
auth: 'basic_list' | |||
} | |||
], | |||
align: 'center' | |||
}) | |||
} | |||
} | |||
], | |||
data: [], | |||
pagination: { | |||
pageSize: 10 | |||
} | |||
}) | |||
function play(row) { | |||
console.log(row) | |||
} | |||
/** | |||
* @description: 获取用户数据 | |||
* @return {*} | |||
*/ | |||
async function fetchList() { | |||
const params = { | |||
page: 1, | |||
limit: 10 | |||
} | |||
const res = await getUserList(params) | |||
data.data = res.data | |||
} | |||
const params = reactive({ | |||
name: 'xiaoMa' | |||
}) | |||
const loadDataTable = async(res) => { | |||
const _params = { | |||
...unref(params), | |||
...res | |||
} | |||
return await getUserList(_params) | |||
} | |||
onMounted(() => { | |||
fetchList() | |||
}) | |||
return { data, loadDataTable } | |||
} | |||
} | |||
</script> | |||
<style scoped lang='scss'> | |||
.n-button+.n-button{ | |||
margin-left: 10px; | |||
} | |||
</style> |