Browse Source

待开票列表大数据量的表单请求组件实现

intex_online20250410
王宇飞 1 week ago
parent
commit
2a1ecf173e
  1. 3
      src/components/BasicForm/index.ts
  2. 1320
      src/components/BasicForm/src/BasicFormV3.vue
  3. 3
      src/components/SearchTableV3/index.ts
  4. 324
      src/components/SearchTableV3/src/SearchTable.vue
  5. 226
      src/components/Table/src/TableV2.vue
  6. 6
      src/views/wms/supplierManage/supplierinvoice/supplierinvoiceRequestMain/index.vue

3
src/components/BasicForm/index.ts

@ -1,3 +1,4 @@
import BasicForm from './src/BasicForm.vue'
import BasicFormV3 from './src/BasicFormV3.vue'
export { BasicForm }
export { BasicForm,BasicFormV3 }

1320
src/components/BasicForm/src/BasicFormV3.vue

File diff suppressed because it is too large

3
src/components/SearchTableV3/index.ts

@ -0,0 +1,3 @@
import SearchTableV3 from './src/SearchTable.vue'
export { SearchTableV3}

324
src/components/SearchTableV3/src/SearchTable.vue

@ -0,0 +1,324 @@
<template>
<Dialog :title="dialogTitle" v-model="searchDialogVisible" :width="dialogWidth">
<!-- 搜索工作栏 -->
<slot :name="'searchQuery'+formFieldRef"></slot>
<ContentWrap v-if="searchQuery">
<Search :schema="searchSchema" @search="setSearchParamsRef" @reset="setSearchParamsRef" />
</ContentWrap>
<!-- 列表头部 -->
<TableHead
:HeadButttondata="HeadButttondata"
:routeName="routeName"
@searchFormClick="searchFormClick"
@buttonBaseClick="buttonBaseClick"
:allSchemas="allSchemasRef"
/>
<ContentWrap>
<TableV2
v-clientSearchTable
ref="searchTableRef"
:isCheckStrictly="isCheckStrictly"
:columns="tableColumns"
:data="tableObjectRef.tableList"
:loading="tableObjectRef.loading"
:total="tableObjectRef.total"
v-model:pageSize="tableObjectRef.pageSize"
v-model:currentPage="tableObjectRef.currentPage"
v-model:sort="tableObjectRef.sort"
:searchTableSelectionsList="searchTableSelectionsList"
:selection="true"
:selectionTotal="multipleBol"
:reserveSelection="true"
row-key="id"
@rowClick="rowClick"
/>
<!-- <el-table-v2 style="border: 1px solid red;"
:height="700"
ref="searchTableRef"
v-clientSearchTable
:columns="tableColumns"
:data="tableObjectRef.tableList"
fixed></el-table-v2> -->
</ContentWrap>
<template #footer>
<div class="flex items-center">
<slot :name="'selectionsActions'+formFieldRef" :selections="searchTableRef?searchTableRef.selections:[]"></slot>
<el-button @click="submitForm" type="primary" :disabled="formLoading">{{ sureText }}</el-button>
<slot name="actionsOther"></slot>
<el-button @click="searchDialogVisible = false"> </el-button>
<slot name="actions"></slot>
</div>
</template>
</Dialog>
</template>
<script setup lang="ts">
import * as defaultButtons from '@/utils/disposition/defaultButtons'
const props = defineProps({
showSearchTableQueryFields: {
type: Array,
required: false,
default: []
},
hiddenFilterBtnFields:{
type: Array,
required: false,
default: []
},
// true ; false
isCheckStrictly:{
type:Boolean,
default:false
},
sureText:{
type: String,
required: false,
default:'确 定'
}
})
const { t } = useI18n() //
const message = useMessage() //
const route = useRoute() //
const routeName = ref()
routeName.value = route.name
const searchDialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const multipleBol = ref(false)
//
const HeadButttondata = ref(
multipleBol.value
? [
defaultButtons.defaultWhenPageBtn(null), //
defaultButtons.defaultUnselectPageBtn(null), //
// defaultButtons.defaultDeselectAllBtn(null), //
defaultButtons.defaultFilterBtn(null) //
]
: [
defaultButtons.defaultFilterBtn(null) //
]
)
/** 打开弹窗 */
const getListRef = ref()
const setSearchParamsRef = ref()
const tableObjectRef = ref()
const getPage: any = ref()
const searchSchema = ref()
const tableColumns = ref()
const formFieldRef = ref('')
const searchFieldRef = ref()
const typeRef = ref()
const rowRef = ref()
const allSchemasRef = ref()
const searchConditionRef = ref()
const searchTableSelectionsList = ref() //
const searchQuery = ref(false)
const hiddenFilterBtn = ref(false)
const updateData = (list:any)=>{
tableObjectRef.value.tableList = list
searchTableRef.value.clearSelection()
}
const openData = (titleName: any, tableObject:any ,allSchemas: any,multiple: any) => {
dialogWidth.value = '80%'
multipleBol.value = multiple
HeadButttondata.value = multiple
? [
defaultButtons.defaultWhenPageBtn(null), //
defaultButtons.defaultUnselectPageBtn(null), //
// defaultButtons.defaultDeselectAllBtn(null), //
// defaultButtons.defaultFilterBtn(null) //
]
: [
// defaultButtons.defaultFilterBtn(null) //
]
dialogTitle.value = t(`ts.${titleName}`).replace('ts.', '')
tableObjectRef.value = tableObject
searchDialogVisible.value = true
allSchemasRef.value = allSchemas
searchSchema.value = allSchemas.searchSchema
tableColumns.value = allSchemas.tableColumns
}
const open = (titleName: any, allSchemas: any,getApiPage: any, formField: any, searchField: any,multiple: any, type: any, row: any, searchCondition:any , isCountRequestRe:any,isConcatDetailSchemas=false,detailSchemas: any, searchTableSelections:any) => {
searchQuery.value = props.showSearchTableQueryFields.find(item=>item==formField)?true:false
hiddenFilterBtn.value = props.hiddenFilterBtnFields.find(item=>item==formField)?true:false
dialogWidth.value = '80%'
multipleBol.value = multiple
const filterBtns = hiddenFilterBtn.value?[]:[defaultButtons.defaultFilterBtn(null)]
HeadButttondata.value = multiple?[
defaultButtons.defaultWhenPageBtn(null), //
defaultButtons.defaultUnselectPageBtn(null), //
// defaultButtons.defaultDeselectAllBtn(null), //
...filterBtns, //
]:
[
...filterBtns, //
]
searchDialogVisible.value = true
formFieldRef.value = formField
searchFieldRef.value = searchField
allSchemasRef.value = allSchemas
searchSchema.value = allSchemas.searchSchema
if (isConcatDetailSchemas) {
//
console.log('detailSchemas', detailSchemas)
tableColumns.value = [...allSchemas?.tableColumns, ...detailSchemas?.tableMainColumns].filter(
(item) => item.field !== 'action'
)
} else {
tableColumns.value = allSchemas?.tableColumns.filter((item) => item.field !== 'action')
}
getPage.value = getApiPage
typeRef.value = type
rowRef.value = row
// dialogTitle.value = t('action.' + type)
dialogTitle.value = t(`ts.${titleName}`).replace('ts.', '')
searchTableSelectionsList.value = searchTableSelections
const { tableObject, tableMethods } = useTable({
getListApi: getPage.value //
})
tableObject.pageSize = 20
tableObjectRef.value = tableObject
searchConditionRef.value = searchCondition
if (searchCondition) tableObjectRef.value.params = searchCondition
//
const { getList, setSearchParams } = tableMethods
setSearchParamsRef.value = setSearchParams
getListRef.value = getList
getList()
}
const dialogWidth = ref('80%')
const changeDialogWidth = (width: any) => {
dialogWidth.value = width
}
const hiddenFilterButton = () => {
HeadButttondata.value = []
}
//
const searchFormClick = (searchData) => {
console.log(99, rowRef.value)
console.log(100, searchData)
console.log(101, searchConditionRef.value)
// 20240104 searchData.filters
// 20240321 searchData
if (searchData.filters) {
if (searchConditionRef.value&&searchConditionRef.value.filters) {
Object.keys(searchConditionRef.value.filters).forEach((key) => {
searchData.filters.push(searchConditionRef.value.filters[key])
})
} else if(searchConditionRef.value){
Object.keys(searchConditionRef.value).forEach((key) => {
searchData.filters.push({
action: '==',
column: key,
value: searchConditionRef.value[key]
})
})
}
} else {
if (searchConditionRef.value.filters) {
searchData.filters = searchConditionRef.value.filters
} else if(searchConditionRef.value){
searchData.filters = []
Object.keys(searchConditionRef.value).forEach((key) => {
searchData.filters.push({
action: '==',
column: key,
value: searchConditionRef.value[key]
})
})
}
}
tableObjectRef.value.params = {
isSearch: true,
filters: searchData.filters
}
getListRef.value() //
}
const buttonBaseClick = (val, item) => {
//
if (val == 'DeselectAll') {
//
searchTableRef.value.clearSelection()
} else if (val == 'UnselectPage') {
//
searchTableRef.value.togglePageSelection()
} else if (val == 'WhenPage') {
//
searchTableRef.value.toggleAllSelection(true)
}
}
defineExpose({ open,openData,updateData,hiddenFilterButton ,changeDialogWidth,searchFormClick}) // open
// Table ref
const searchTableRef = ref()
/** 提交表单 */
const emit = defineEmits(['searchTableSuccess']) // searchTableSuccess
const submitForm = async () => {
//
formLoading.value = true
const selections = searchTableRef.value.selections
//
if (!multipleBol.value) {
if (selections.length > 1 || selections.length == 0) {
message.warning('请选择一条数据!')
formLoading.value = false
return
}
//
} else {
if (selections.length == 0) {
message.warning('至少选择一条数据!')
formLoading.value = false
return
}
}
try {
searchDialogVisible.value = false
//
emit(
'searchTableSuccess',
formFieldRef.value,
searchFieldRef.value,
selections,
typeRef.value,
rowRef.value
)
} finally {
formLoading.value = false
}
}
const rowClick = (row: any, column: any, event: Event) => {
const selected = searchTableRef.value?.elTableRef
?.getSelectionRows()
.some((item) => item.id === row.id)
if (!selected) {
searchTableRef.value?.elTableRef?.toggleRowSelection(row, true)
if(props.isCheckStrictly&&row.children){//
row.children.forEach(item => {
searchTableRef.value?.elTableRef?.toggleRowSelection(item, false)
});
}
} else {
//
searchTableRef.value?.elTableRef?.toggleRowSelection(row, false)
}
}
</script>
<style scoped lang="scss">
</style>

226
src/components/Table/src/TableV2.vue

@ -0,0 +1,226 @@
<template>
<div style="height: 400px" v-loading="loading">
<el-auto-resizer>
<template #default="{ height, width }">
<el-table-v2
class="table-v2-container"
row-key="id"
:columns="[selectionColumn,...mColumns]"
:data="mData"
:width="width"
:height="height"
fixed
/>
</template>
</el-auto-resizer>
<div class="mt-15px float-left" style='height:32px;line-height:32px'>已选{{ selections.length }}条数据</div>
<el-pagination v-model:current-page="currentPageRef" v-model:page-size="pageSizeRef" class="float-right mt-15px" layout="total, sizes, prev, pager, next, jumper" :total="total" :page-sizes="[200,500,1000,2000]"/>
</div>
</template>
<script lang="tsx" setup>
import { ref, unref } from 'vue'
import { ElCheckbox } from 'element-plus'
import type { FunctionalComponent } from 'vue'
import type { CheckboxValueType, Column } from 'element-plus'
import {formatDate } from '@/utils/formatTime'
const props = defineProps({
//
columns: {
type: Array as PropType<TableColumn[]>,
default: () => []
},
data: {
type: Array as PropType<Recordable[]>,
default: () => []
},
currentPage: {
type: Number,
default: 1
},
pageSize: {
type: Number,
default: 200
},
total: {
type: Number,
default: 0
},
//
loading: {
type: Boolean,
default: false
},
})
const pageSizeRef = ref(props.pageSize)
const currentPageRef = ref(props.currentPage)
watch(
() => props.currentPage,
(val: number) => {
currentPageRef.value = val
}
)
watch(
() => props.pageSize,
(val: number) => {
pageSizeRef.value = val
}
)
watch(
() => pageSizeRef.value,
(val: number) => {
emit('update:pageSize', val)
}
)
watch(
() => currentPageRef.value,
(val: number) => {
emit('update:currentPage', val)
}
)
console.log('columns====',props.columns)
type SelectionCellProps = {
value: boolean
intermediate?: boolean
onChange: (value: CheckboxValueType) => void
}
const SelectionCell: FunctionalComponent<SelectionCellProps> = ({
value,
intermediate = false,
onChange,
}) => {
return (
<ElCheckbox
onChange={onChange}
modelValue={value}
indeterminate={intermediate}
/>
)
}
const selectionColumn = ref({
key: 'selection',
width: 50,
align:'center',
cellRenderer: ({ rowData,rowIndex }) => {
const onChange = (value: CheckboxValueType) => {
console.log('onChange', value)
rowData.checked = value
selections.value = selections.value.filter(item=>item.id!=rowData.id)
if (value) {
selections.value.push(rowData)
}
}
return <SelectionCell value={rowData.checked} onChange={onChange} />
},
headerCellRenderer: () => {
const _data = unref(mData)
const onChange = (value: CheckboxValueType) =>
{
mData.value = _data.map((row) => {
row.checked = value
return row
})
selections.value = selections.value.filter(item=>mData.value.findIndex(item1=>item1.id==item.id)==-1)
if(value){
selections.value = [...selections.value,...mData.value]
}
}
const allSelected = _data.every((row) => row.checked)
const containsChecked = _data.some((row) => row.checked)
return (
<SelectionCell
value={allSelected}
intermediate={containsChecked && !allSelected}
onChange={onChange}
/>
)
},
})
const mColumns = ref(props.columns.map(item=>({
key: 'id',
dataKey: item['field'],
title: item['label'],
width: 140,
})))
const mData = ref([])
watch(()=>props.data,()=>{
console.log('selections',selections.value )
mData.value = props.data.map(item=>({
...item,
checked: selections.value.find(item1=>item1.id==item.id)?true:false,
createTime:formatDate(item.createTime)
}))
console.log('mData',mData.value)
})
const rowEventHandlers = ({onClick})=>{
}
const selections = ref([])
// const selections = computed(()=>mData.value.filter(item=>item.checked))
// /
const toggleAllSelection = (isAll)=>{
if(isAll){
//
mData.value.forEach((row) => {
row.checked = isAll
})
}
}
const togglePageSelection = (isAll)=>{
mData.value.forEach((row) => {
row.checked = !row.checked
})
}
defineExpose({ selections,toggleAllSelection,togglePageSelection })
const emit = defineEmits(['update:pageSize','update:currentPage'])
console.log('props.data',props.data)
console.log('mData',mData.value)
// const columns = generateColumns(10)
// const data = generateData(columns, 200)
</script>
<style lang="scss" scoped>
.table-v2-container {
border: 1px solid #ebeef5;
::v-deep(.el-table-v2__header-cell) {
border-right: 1px solid #ebeef5;
text-align: center;
&:last-child{
border-right: none;
}
}
::v-deep(.el-table-v2__header-cell-text) {
width: 100%;
}
::v-deep(.el-table-v2__row-cell) {
text-align: center;
border-right: 1px solid #ebeef5;
&:last-child{
border-right: none;
}
}
::v-deep(.el-table-v2__cell-text) {
width: 100%;
}
}
</style>

6
src/views/wms/supplierManage/supplierinvoice/supplierinvoiceRequestMain/index.vue

@ -56,10 +56,12 @@
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<BasicForm
<BasicFormV3
ref="formRef"
@success="getList"
:isOpenSearchTable="true"
:searchTableVirtualized="['poLine']"
:isFullInputNumber="true"
fieldTableColumn="poLine"
:showSearchTableQueryFields="['poLine']"
:rules="SupplierinvoiceRequestMainRules"
@ -288,7 +290,7 @@
</div>
</div>
</template>
</BasicForm>
</BasicFormV3>
<!-- 财务通过窗口 finance_mainPlanSub -->
<BasicForm

Loading…
Cancel
Save