This commit is contained in:
stt
2025-11-14 09:34:42 +08:00
6 changed files with 256 additions and 218 deletions

View File

@@ -1,24 +1,44 @@
<template> <template>
<div :style="{ height: typeof props.height === 'string' ? props.height : tableStore.table.height }"> <div :style="{ height: typeof props.height === 'string' ? props.height : tableStore.table.height }">
<vxe-table ref="tableRef" height="auto" :key="key" :data="tableStore.table.data" <vxe-table
v-loading="tableStore.table.loading" v-bind="Object.assign({}, defaultAttribute, $attrs)" ref="tableRef"
@checkbox-all="selectChangeEvent" @checkbox-change="selectChangeEvent" :showOverflow="showOverflow" height="auto"
:sort-config="{ remote: true }" @sort-change="handleSortChange"> :key="key"
:data="tableStore.table.data"
v-loading="tableStore.table.loading"
v-bind="Object.assign({}, defaultAttribute, $attrs)"
@checkbox-all="selectChangeEvent"
@checkbox-change="selectChangeEvent"
:showOverflow="showOverflow"
:sort-config="{ remote: true }"
@sort-change="handleSortChange"
>
<!-- Column 组件内部是 el-table-column --> <!-- Column 组件内部是 el-table-column -->
<template v-if="isGroup"> <template v-if="isGroup">
<GroupColumn :column="tableStore.table.column" /> <GroupColumn :column="tableStore.table.column" />
</template> </template>
<template v-else> <template v-else>
<Column :attr="item" :key="key + '-column'" v-for="(item, key) in tableStore.table.column" <Column
:tree-node="item.treeNode"> :attr="item"
:key="key + '-column'"
v-for="(item, key) in tableStore.table.column"
:tree-node="item.treeNode"
>
<!-- tableStore 预设的列 render 方案 --> <!-- tableStore 预设的列 render 方案 -->
<template v-if="item.render" #default="scope"> <template v-if="item.render" #default="scope">
<FieldRender :field="item" :row="scope.row" :column="scope.column" :index="scope.rowIndex" :key="key + <FieldRender
'-' + :field="item"
item.render + :row="scope.row"
'-' + :column="scope.column"
(item.field ? '-' + item.field + '-' + scope.row[item.field] : '') :index="scope.rowIndex"
" /> :key="
key +
'-' +
item.render +
'-' +
(item.field ? '-' + item.field + '-' + scope.row[item.field] : '')
"
/>
</template> </template>
</Column> </Column>
</template> </template>
@@ -27,11 +47,16 @@
</div> </div>
<div v-if="tableStore.showPage" class="table-pagination"> <div v-if="tableStore.showPage" class="table-pagination">
<el-pagination :currentPage="tableStore.table.params!.pageNum" :page-size="tableStore.table.params!.pageSize" <el-pagination
:page-sizes="pageSizes" background :currentPage="tableStore.table.params!.pageNum"
:page-size="tableStore.table.params!.pageSize"
:page-sizes="pageSizes"
background
:layout="config.layout.shrink ? 'prev, next, jumper' : 'sizes,total, ->, prev, pager, next, jumper'" :layout="config.layout.shrink ? 'prev, next, jumper' : 'sizes,total, ->, prev, pager, next, jumper'"
:total="tableStore.table.total" @size-change="onTableSizeChange" :total="tableStore.table.total"
@current-change="onTableCurrentChange"></el-pagination> @size-change="onTableSizeChange"
@current-change="onTableCurrentChange"
></el-pagination>
</div> </div>
<slot name="footer"></slot> <slot name="footer"></slot>
</template> </template>
@@ -125,6 +150,7 @@ watch(
() => tableStore.table.allFlag, () => tableStore.table.allFlag,
newVal => { newVal => {
if (tableStore.table.allFlag) { if (tableStore.table.allFlag) {
console.log('🚀 ~ tableStore.table.allData:', tableStore.table.allData)
tableRef.value?.exportData({ tableRef.value?.exportData({
filename: tableStore.exportName || document.querySelectorAll('.ba-nav-tab.active')[0].textContent || '', // 文件名字 filename: tableStore.exportName || document.querySelectorAll('.ba-nav-tab.active')[0].textContent || '', // 文件名字

View File

@@ -18,6 +18,7 @@ interface TableStoreParams {
publicHeight?: number //计算高度 publicHeight?: number //计算高度
resetCallback?: () => void // 重置 resetCallback?: () => void // 重置
loadCallback?: () => void // 接口调用后的回调 loadCallback?: () => void // 接口调用后的回调
exportProcessingData?: () => void //导出处理数据
beforeSearchFun?: () => void // 接口调用前的回调 beforeSearchFun?: () => void // 接口调用前的回调
} }
@@ -47,6 +48,7 @@ export default class TableStore {
column: [], column: [],
loadCallback: null, loadCallback: null,
resetCallback: null, resetCallback: null,
exportProcessingData: null,
beforeSearchFun: null, beforeSearchFun: null,
height: '', height: '',
publicHeight: 0 publicHeight: 0
@@ -64,6 +66,7 @@ export default class TableStore {
this.table.publicHeight = options.publicHeight || 0 this.table.publicHeight = options.publicHeight || 0
this.table.resetCallback = options.resetCallback || null this.table.resetCallback = options.resetCallback || null
this.table.loadCallback = options.loadCallback || null this.table.loadCallback = options.loadCallback || null
this.table.exportProcessingData = options.exportProcessingData || null
this.table.beforeSearchFun = options.beforeSearchFun || null this.table.beforeSearchFun = options.beforeSearchFun || null
Object.assign(this.table.params, options.params) Object.assign(this.table.params, options.params)
this.table.height = mainHeight(20 + (this.showPage ? 58 : 0) + this.table.publicHeight).height as string this.table.height = mainHeight(20 + (this.showPage ? 58 : 0) + this.table.publicHeight).height as string
@@ -187,26 +190,21 @@ export default class TableStore {
[ [
'export', 'export',
() => { () => {
ElMessage({ // this.index()
message: '正在导出,请稍等...',
type: 'info',
duration: 1000
})
let params = { ...this.table.params, pageNum: 1, pageSize: this.table.total } let params = { ...this.table.params, pageNum: 1, pageSize: this.table.total }
setTimeout(() => { createAxios(
createAxios( Object.assign(
Object.assign( {
{ url: this.url,
url: this.url, method: this.method
method: this.method },
}, requestPayload(this.method, params, this.paramsPOST)
requestPayload(this.method, params, this.paramsPOST) )
) ).then(res => {
).then(res => { this.table.allData = filtration(res.data.records || res.data)
this.table.allData = filtration(res.data.records || res.data) this.table.exportProcessingData && this.table.exportProcessingData()
this.table.allFlag = data.showAllFlag || true this.table.allFlag = data.showAllFlag || true
}) })
}, 1500)
} }
] ]
]) ])

View File

@@ -1,162 +1,164 @@
<template> <template>
<div class="default-main" style="display: flex" :style="{ height: height }"> <div class="default-main" style="display: flex" :style="{ height: height }">
<div style="flex: 1; overflow: hidden"> <div style="flex: 1; overflow: hidden">
<div class="custom-table-header"> <div class="custom-table-header">
<div class="title">角色列表</div> <div class="title">角色列表</div>
<el-button :icon="Plus" type="primary" @click="addRole" class="ml10">新增</el-button> <el-button :icon="Plus" type="primary" @click="addRole" class="ml10">新增</el-button>
</div> </div>
<Table ref="tableRef" @currentChange="currentChange" /> <Table ref="tableRef" @currentChange="currentChange" />
</div> </div>
<Tree <Tree
v-if="menuListId" v-if="menuListId"
ref="treeRef" ref="treeRef"
show-checkbox show-checkbox
width="350px" width="350px"
:data="menuTree" :data="menuTree"
:checkStrictly="checkStrictly" :checkStrictly="checkStrictly"
@check-change="checkChange" @check-change="checkChange"
></Tree> ></Tree>
<el-empty style="width: 350px; padding-top: 300px; box-sizing: border-box" description="请选择角色" v-else /> <el-empty style="width: 350px; padding-top: 300px; box-sizing: border-box" description="请选择角色" v-else />
<PopupForm ref="popupRef"></PopupForm> <PopupForm ref="popupRef"></PopupForm>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { Plus } from '@element-plus/icons-vue' import { Plus } from '@element-plus/icons-vue'
import { ref, onMounted, provide } from 'vue' import { ref, onMounted, provide } from 'vue'
import TableStore from '@/utils/tableStore' import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue' import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue' import TableHeader from '@/components/table/header/index.vue'
import Tree from '@/components/tree/index.vue' import Tree from '@/components/tree/index.vue'
import { functionTree } from '@/api/user-boot/function' import { functionTree } from '@/api/user-boot/function'
import { getFunctionsByRoleIndex, updateRoleMenu } from '@/api/user-boot/roleFuction' import { getFunctionsByRoleIndex, updateRoleMenu } from '@/api/user-boot/roleFuction'
import { mainHeight } from '@/utils/layout' import { mainHeight } from '@/utils/layout'
import { del } from '@/api/user-boot/role' import { del } from '@/api/user-boot/role'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import PopupForm from './popupForm.vue' import PopupForm from './popupForm.vue'
import { useAdminInfo } from '@/stores/adminInfo' import { useAdminInfo } from '@/stores/adminInfo'
const adminInfo = useAdminInfo() const adminInfo = useAdminInfo()
defineOptions({ defineOptions({
name: 'auth/role' name: 'auth/role'
}) })
const height = mainHeight(20).height const height = mainHeight(20).height
const treeRef = ref() const treeRef = ref()
const menuTree = ref<treeData[]>([]) const menuTree = ref<treeData[]>([])
const popupRef = ref() const popupRef = ref()
const checkStrictly = ref(true) const checkStrictly = ref(true)
const menuListId = ref('') const menuListId = ref('')
const tableStore = new TableStore({ const tableStore = new TableStore({
showPage: false, showPage: false,
url: '/user-boot/role/selectRoleDetail?id=' + adminInfo.$state.userType, url: '/user-boot/role/selectRoleDetail?id=' + adminInfo.$state.userType,
method: 'POST', method: 'POST',
column: [ column: [
{ title: '角色名称', field: 'name', align: 'center' }, { title: '角色名称', field: 'name', align: 'center' },
{ title: '角色编码', field: 'code', align: 'center' }, { title: '角色编码', field: 'code', align: 'center' },
{ title: '备注', field: 'remark', align: 'center' }, { title: '备注', field: 'remark', align: 'center' },
{ {
title: '状态', title: '状态',
field: 'state', field: 'state',
width: '80', width: '80',
render: 'tag', render: 'tag',
custom: { custom: {
0: 'danger', 0: 'danger',
1: 'success' 1: 'success'
}, },
replaceValue: { replaceValue: {
0: '注销', 0: '注销',
1: '正常' 1: '正常'
} }
}, },
{ {
title: '操作', title: '操作',
align: 'center', align: 'center',
width: '180', width: '180',
render: 'buttons', render: 'buttons',
buttons: [ buttons: [
{ {
name: 'edit', name: 'edit',
title: '编辑', title: '编辑',
type: 'primary', type: 'primary',
icon: 'el-icon-EditPen', icon: 'el-icon-EditPen',
render: 'basicButton', render: 'basicButton',
click: row => { click: row => {
popupRef.value.open('编辑角色', row) popupRef.value.open('编辑角色', row)
} }
}, },
{ {
name: 'del', name: 'del',
title: '删除', title: '删除',
type: 'danger', type: 'danger',
icon: 'el-icon-Delete', icon: 'el-icon-Delete',
render: 'confirmButton', render: 'confirmButton',
popconfirm: { popconfirm: {
confirmButtonText: '确认', confirmButtonText: '确认',
cancelButtonText: '取消', cancelButtonText: '取消',
confirmButtonType: 'danger', confirmButtonType: 'danger',
title: '确定删除该角色吗?' title: '确定删除该角色吗?'
}, },
click: row => { click: row => {
del([row.id]).then(() => { del([row.id]).then(() => {
ElMessage.success('删除成功') ElMessage.success('删除成功')
tableStore.index() tableStore.index()
}) })
} }
} }
] ]
} }
] ]
}) })
tableStore.table.params.searchValue = '' tableStore.table.params.searchValue = ''
provide('tableStore', tableStore) provide('tableStore', tableStore)
const filterData = (arr: any[]) => { const filterData = (arr: any[]) => {
// return arr.filter((item: any) => { // return arr.filter((item: any) => {
// item.name = item.title // item.name = item.title
// if (item.children.length) { // if (item.children.length) {
// item.children = filterData(item.children) // item.children = filterData(item.children)
// } // }
// return item.type === 0 // return item.type === 0
// }) // })
arr.forEach((item: any) => { arr.forEach((item: any) => {
item.name = item.title item.name = item.title
if (item.children.length) { if (item.children.length) {
filterData(item.children) filterData(item.children)
} }
}) })
} }
functionTree().then((res: any) => { functionTree().then((res: any) => {
filterData(res.data) filterData(res.data)
menuTree.value = res.data menuTree.value = res.data
}) })
const currentChange = (data: any) => { const currentChange = (data: any) => {
checkStrictly.value = true checkStrictly.value = true
menuListId.value = data.row.id menuListId.value = data.row.id
getFunctionsByRoleIndex({ id: data.row.id }).then((res: any) => { getFunctionsByRoleIndex({ id: data.row.id }).then((res: any) => {
treeRef.value.treeRef.setCheckedKeys(res.data.map((item: any) => item.id)) treeRef.value.treeRef.setCheckedKeys(res.data.map((item: any) => item.id))
}) })
} }
const timeout = ref<NodeJS.Timeout>() const timeout = ref<NodeJS.Timeout>()
const checkChange = (data: any) => { const checkChange = (data: any) => {
if (checkStrictly.value) { if (checkStrictly.value) {
checkStrictly.value = false checkStrictly.value = false
return return
} }
if (timeout.value) { if (timeout.value) {
clearTimeout(timeout.value) clearTimeout(timeout.value)
} }
timeout.value = setTimeout(() => { timeout.value = setTimeout(() => {
updateRoleMenu({ updateRoleMenu({
id: menuListId.value, id: menuListId.value,
idList: treeRef.value.treeRef.getCheckedNodes(false, true).map((node: any) => node.id) idList: treeRef.value.treeRef.getCheckedNodes(false, true).map((node: any) => node.id)
}) }).then(() => {
}, 1000) ElMessage.success('操作成功!')
} })
onMounted(() => { }, 1000)
tableStore.index() }
}) onMounted(() => {
const addRole = () => { tableStore.index()
popupRef.value.open('新增角色') })
} const addRole = () => {
</script> popupRef.value.open('新增角色')
}
</script>

View File

@@ -96,14 +96,14 @@ const tableStore = new TableStore({
fixed: 'right', fixed: 'right',
render: 'tag', render: 'tag',
custom: { custom: {
功能调试: 'warning', 2: 'warning',
出厂调试: 'warning', 3: 'warning',
正式投运: 'success' 4: 'success'
}, },
replaceValue: { replaceValue: {
功能调试: '功能调试', 2: '功能调试',
出厂调试: '出厂调试', 3: '出厂调试',
正式投运: '正式投运' 4: '正式投运'
}, },
minWidth: 80 minWidth: 80
}, },
@@ -142,11 +142,14 @@ const tableStore = new TableStore({
{ title: '完整性(%)', fixed: 'right', width: 100, field: 'integrity', sortable: true } { title: '完整性(%)', fixed: 'right', width: 100, field: 'integrity', sortable: true }
], ],
beforeSearchFun: () => {}, beforeSearchFun: () => {},
loadCallback: () => { exportProcessingData: () => {
tableStore.table.data.forEach(item => { tableStore.table.allData = tableStore.table.allData.filter(item => {
item.process = item.process == 2 ? '功能调试' : item.process == 3 ? '出厂调试' : '正式投运' item.process = item.process == 2 ? '功能调试' : item.process == 3 ? '出厂调试' : '正式投运'
return item
}) })
console.log('🚀 ~ tableStore.table.allData:', tableStore.table.allData)
},
loadCallback: () => {
let name = tableStore.table.params.name let name = tableStore.table.params.name
let data = tableStore.table.copyData.filter(item => { let data = tableStore.table.copyData.filter(item => {
// 处理latestTime默认值 // 处理latestTime默认值
@@ -182,7 +185,10 @@ const exportTab = () => {
sheetName: 'Sheet1', sheetName: 'Sheet1',
type: 'xlsx', //导出文件类型 xlsx 和 csv type: 'xlsx', //导出文件类型 xlsx 和 csv
useStyle: true, useStyle: true,
data: tableStore.table.copyData, // 数据源 // 过滤那个字段导出 data: tableStore.table.copyData.filter(item => {
item.process = item.process == 2 ? '功能调试' : item.process == 3 ? '出厂调试' : '正式投运'
return item
}), // 数据源 // 过滤那个字段导出
columnFilterMethod: function (column: any) { columnFilterMethod: function (column: any) {
return !( return !(
column.column.title === undefined || column.column.title === undefined ||

View File

@@ -107,8 +107,8 @@ const editd = (e: any) => {
} }
// 设计 // 设计
const Aclick = (e: any) => { const Aclick = (e: any) => {
// window.open(window.location.origin + `/zutai/?id=${e.id}&&name=${e.name}&&preview=false&&graphicDisplay=zl`)
window.open(window.location.origin + `/zutai/?id=${e.id}&&name=${e.name}&&preview=false&&graphicDisplay=zl`) window.open(window.location.origin + `/zutai/?id=${e.id}&&name=${e.name}&&preview=false&&graphicDisplay=zl`)
// window.open('http://192.168.1.128:4001' + `/zutai/?id=${e.id}&&name=${e.name}&&preview=false&&graphicDisplay=zl`)
} }
// 删除 // 删除
@@ -143,8 +143,8 @@ const deleted = (e: any) => {
} }
const imgData = (e: any) => { const imgData = (e: any) => {
// window.open(window.location.origin + `/zutai/?id=${e.id}&&name=${e.name}&&preview=true&&graphicDisplay=zl#/preview_ZL`) window.open(window.location.origin + `/zutai/?id=${e.id}&&name=${e.name}&&preview=true&&graphicDisplay=zl#/preview_ZL`)
window.open(window.location.origin + `/zutai/?id=${e.id}&&name=${e.name}&&preview=true&&graphicDisplay=zl#/preview_ZL`) // window.open('http://192.168.1.128:4001' + `/zutai/?id=${e.id}&&name=${e.name}&&preview=true&&graphicDisplay=zl#/preview_ZL`)
} }

22
types/table.d.ts vendored
View File

@@ -8,8 +8,8 @@ declare global {
interface CnTable { interface CnTable {
ref: VxeTableInstance | null ref: VxeTableInstance | null
data: TableRow[] | any data: TableRow[] | any
copyData: TableRow[] | any
allData: TableRow[] | any allData: TableRow[] | any
filename: any
allFlag: Boolean allFlag: Boolean
// 前端分页数据 // 前端分页数据
webPagingData: TableRow[][] webPagingData: TableRow[][]
@@ -29,6 +29,7 @@ declare global {
loadCallback: (() => void) | null loadCallback: (() => void) | null
resetCallback: (() => void) | null resetCallback: (() => void) | null
beforeSearchFun: (() => void) | null beforeSearchFun: (() => void) | null
exportProcessingData: (() => void) | null
height: string height: string
publicHeight: number publicHeight: number
} }
@@ -50,6 +51,7 @@ declare global {
| 'buttons' | 'buttons'
| 'slot' | 'slot'
| 'customTemplate' | 'customTemplate'
| 'renderFormatter'
| 'customRender' | 'customRender'
// 默认值 // 默认值
default?: any default?: any
@@ -59,14 +61,15 @@ declare global {
custom?: any custom?: any
// 值替换数据,如{open: '开'} // 值替换数据,如{open: '开'}
replaceValue?: any replaceValue?: any
effect?: any
// 时间格式化 // 时间格式化
timeFormat?: string timeFormat?: string
// 开关控制 // 开关控制
onChangeField?: (row: TableRow, value: any) => void onChangeField?: (row: TableRow, value: any) => void
activeValue?: string activeValue?: string
inactiveValue?: string inactiveValue?: string
activeText?: string activeText?: string
inactiveText?: string inactiveText?: string
// 自定义组件/函数渲染 // 自定义组件/函数渲染
customRender?: string | Component customRender?: string | Component
// 使用了 render 属性时,渲染前对字段值的预处理方法,请返回新值 // 使用了 render 属性时,渲染前对字段值的预处理方法,请返回新值
@@ -80,6 +83,8 @@ declare global {
index: number index: number
) => string ) => string
children?: TableColumn[] children?: TableColumn[]
property?: string
clickable?: boolean // 是否可点击
} }
/* 表格右侧操作按钮 */ /* 表格右侧操作按钮 */
@@ -90,15 +95,16 @@ declare global {
title?: string title?: string
text?: string text?: string
class?: string class?: string
loading?: string
type: ButtonType type: ButtonType
icon: string icon: string
popconfirm?: Partial<Mutable<PopconfirmProps>> popconfirm?: Partial<Mutable<PopconfirmProps>>
disabledTip?: boolean disabledTip?: boolean
// 自定义点击事件 // 自定义点击事件
click?: (row: TableRow, field: TableColumn) => void click?: (row: TableRow, field: TableColumn) => void
// 按钮是否禁用,请返回布尔值 // 按钮是否禁用,请返回布尔值
disabled?: (row: TableRow, field: TableColumn) => boolean disabled?: (row: TableRow, field: TableColumn) => boolean
showDisabled?: (row: TableRow, field: TableColumn) => boolean
// 自定义el-button属性 // 自定义el-button属性
attr?: Partial<Mutable<ButtonProps>> attr?: Partial<Mutable<ButtonProps>>
} }