页组件

master
lzq 2026-01-27 18:46:59 +08:00
parent 9b8af50aa9
commit 9d4b5956ad
10 changed files with 763 additions and 133 deletions

View File

@ -209,6 +209,10 @@ const displayData = computed(() => {
</template> </template>
<style lang="stylus" scoped> <style lang="stylus" scoped>
.drop-table {
width 100%;
}
.clear-btn { .clear-btn {
cursor: pointer; cursor: pointer;

View File

@ -0,0 +1,21 @@
<script lang="ts" setup>
</script>
<template>
<div class="page-wrapper">
<slot/>
</div>
</template>
<style lang="stylus" scoped>
.page-wrapper {
height 100%
width 100%;
overflow hidden
padding 0 5px 5px 5px
contain: layout paint;
transform: translateZ(0);
box-sizing border-box
display grid
}
</style>

View File

@ -0,0 +1,405 @@
/* @jsxImportSource vue */
import APage from '@/components/a-page/APage.vue'
import styles from '@/components/a-page/a-table-page/a-table-page.module.styl'
import {
ElButton,
ElDropdown,
ElDropdownItem,
ElDropdownMenu,
ElForm,
ElLoading,
ElPagination,
ElPopconfirm,
ElScrollbar,
ElTable,
ElTableColumn,
ElTooltip,
type TableColumnCtx,
type TableProps,
} from 'element-plus'
import {
defineComponent,
withDirectives,
withModifiers,
} from 'vue'
import type { R } from '@/common/utils/http-util.ts'
import {
elIcons,
type ElIconType,
} from '@/common/element/element.ts'
import type { DefaultRow } from 'element-plus/es/components/table/src/table/defaults'
import type { FormProps } from 'element-plus/es/components/form/src/form'
import Utils, { type ResetAble } from '@/common/utils'
import Strings from '@/common/utils/strings.ts'
import { saveFile } from '@/common/app'
import Colls from '@/common/utils/colls.ts'
import type { SetupContext } from '@vue/runtime-core'
interface ColumnScopeType<T> {
row: T,
column: TableColumnCtx,
$index: number
}
export interface TableActionType<T> {
icon?: ElIconType
type?: 'text' | 'default' | 'primary' | 'success' | 'warning' | 'info' | 'danger'
label?: string | ((data: ColumnScopeType<T>) => string)
tooltip?: string | ((data: ColumnScopeType<T>) => string)
loading?: boolean
textBtn?: boolean
show?: (data: ColumnScopeType<T>) => boolean
action: (data: ColumnScopeType<T>) => Promise<boolean> | void
confirm?: {
title: string | ((data: ColumnScopeType<T>) => string)
width?: string
confirmButtonText?: string
cancelButtonText?: string
}
}
export interface ActionColumnType<T> {
width?: string
tableActions: TableActionType<T>[]
}
export interface ToolType {
icon?: ElIconType
type?: 'text' | 'default' | 'primary' | 'success' | 'warning' | 'info' | 'danger'
label?: string
action: () => void
}
export interface ToolBarType {
leftTools: ToolType[]
rightTools: Required<Omit<ToolType, 'type' | 'label'>>[]
}
export type TablePropsType<T extends DefaultRow, F extends object> = Omit<TableProps<T>, 'data' | 'headerRowClassName' | 'cellClassName' | 'context'> & {
treeLoad?: (param: F, row: T, expanded: any, resolve?: (data: T[]) => void) => void
actionColumn: ActionColumnType<T>
}
export type FormPropsType<P, T> = {
paging?: (param: P) => Promise<R<G.PageResult<T>>>
export?: (param: P) => Promise<R<{ content: Blob, filename: string }>>
defaultData: P
highForm?: Partial<FormProps> & { colCount?: number, vgap?: string, hgap?: string }
simpleForm?: Partial<FormProps>
}
interface PageLayoutType {
/* columns: string[]
rows: string[] */
dataListHeight: string
}
export interface ATablePageType<P extends object, T extends DefaultRow> {
pageLayout: PageLayoutType
searchForm: FormPropsType<P, T>
toolBar: ToolBarType
table: TablePropsType<T, P>
}
function buildSearchForm<P, T>(searchForm: Partial<FormPropsType<P, T>> = {}) {
if (searchForm.defaultData == null) {
searchForm.defaultData = {} as P
}
return searchForm
}
function buildPageLayout(pageLayout: Partial<PageLayoutType> = {}) {
/* if (pageLayout.columns == null) {
pageLayout.columns = [ '1fr' ]
}
if (pageLayout.rows == null) {
pageLayout.rows = [ '1fr', '9fr' ]
} */
if (pageLayout.dataListHeight == null) {
pageLayout.dataListHeight = '9fr'
}
return pageLayout
}
function buildTable<P extends object, T extends DefaultRow>(table: Partial<TablePropsType<T, P>> = {}) {
if (table.actionColumn == null) {
table.actionColumn = {
tableActions: [],
}
}
if (table.actionColumn.tableActions == null) {
table.actionColumn.tableActions = []
}
return table
}
function buildToolBar(toolBar: Partial<ToolBarType> = {}) {
if (toolBar.leftTools == null) toolBar.leftTools = []
if (toolBar.rightTools == null) toolBar.rightTools = []
return toolBar
}
export interface PropsTplType<P extends G.PageParam, T extends DefaultRow> {
pageLayout?: Partial<PageLayoutType>
searchForm?: Partial<FormPropsType<P, T>>
toolBar?: Partial<ToolBarType>
table?: Partial<TablePropsType<T, P>>
}
export function buildProps<P extends G.PageParam, T extends DefaultRow>({pageLayout, searchForm, toolBar, table}: PropsTplType<P, T>) {
return reactive({
pageLayout: buildPageLayout(pageLayout),
searchForm: buildSearchForm(searchForm),
toolBar: buildToolBar(toolBar),
table: buildTable(table),
})
}
interface Exposed extends Record<string, any> {
doSearch: () => void
}
const component = defineComponent(
<P extends G.PageParam, T extends DefaultRow>(props: ATablePageType<P, T>, {slots, expose}: SetupContext) => {
const formData = Utils.resetAble(reactive<P>({
...(props.searchForm.defaultData),
current: 1,
size: 20,
})) as ResetAble<P>
const tableData = Utils.resetAble(reactive<T[]>([])) as ResetAble<T[]>
const totalCount = ref(0)
const loading = ref<boolean>(false)
const showHighForm = ref<boolean>(true)
const doSearch = () => {
loading.value = true
if (props.searchForm.paging != null) {
props.searchForm.paging(formData.$clone() as P)
.then(res => {
totalCount.value = res.data?.total ?? 0
const records = res.data?.records ?? ([] as T[])
tableData.$reset(records)
})
.finally(() => {
loading.value = false
})
return
}
}
expose({doSearch})
const showHighFormHandle = () => {
showHighForm.value = !showHighForm.value
formData.$reset()
}
const doExport = () => {
if (props?.searchForm?.export == null) {
return
}
loading.value = true
saveFile(props?.searchForm?.export(formData.$clone() as P))
.finally(() => {
loading.value = false
})
}
const rowAction = (data: ColumnScopeType<T>, action: TableActionType<T>) => {
if (action.loading != null) {
action.loading = true
}
const result = action.action(data)
if (result instanceof Promise) {
result
.then(reload => {
if (reload) {
doSearch()
}
})
.finally(() => {
if (action.loading != null) {
action.loading = false
}
})
}
}
function doReset() {
formData.$reset()
doSearch()
}
const highFormCssParam = computed(() => {
return {
'--col-count': props.searchForm.highForm?.colCount ?? 3,
'--vgap': props.searchForm.highForm?.vgap ?? '0',
'--hgap': props.searchForm.highForm?.hgap ?? '0',
}
})
const pageCssParam = computed(() => {
return {
'--data-list-height': props.pageLayout.dataListHeight,
}
})
const actionColumnBtnRender = (scope: ColumnScopeType<T>, tableAction: TableActionType<T>) => {
const Btn = <ElButton
icon={tableAction.icon == null ? undefined : elIcons[tableAction.icon]}
loading={tableAction.loading}
type={tableAction.type}
class={tableAction.textBtn ? 'text-btn' : 'icon-btn'}
text>
{tableAction.label}
</ElButton>
const tooltipTxt = tableAction.tooltip == null ? '' : (typeof tableAction.tooltip === 'function' ? tableAction.tooltip(scope) : tableAction.tooltip)
if (Strings.isBlank(tooltipTxt)) {
return (<ElTooltip content={tooltipTxt} placement="top">
{{
default: () => Btn,
}}
</ElTooltip>)
}
return Btn
}
const actionColumnRender = () => {
const actionColumn = props.table?.actionColumn
return Colls.isEmpty(actionColumn?.tableActions) ? <></>
: (<ElTableColumn width={actionColumn?.width ?? '180'} fixed="right" label="操作">
<div class="action-btn">
{{
default: (scope: ColumnScopeType<T>) => (actionColumn?.tableActions!
.filter(it => (it.show == null ? true : it.show(scope)))
.map((tableAction, i) => (tableAction.confirm != null ?
(<ElPopconfirm
key={'action-btn-' + i}
cancel-button-text={tableAction.confirm.cancelButtonText ?? '否'}
confirm-button-text={tableAction.confirm.confirmButtonText ?? '是'}
title={typeof tableAction.confirm.title === 'function' ? tableAction.confirm.title(scope) : tableAction.confirm.title}
width={tableAction.confirm.width ?? '180'}
cancel-button-type="primary"
confirm-button-type="danger"
onConfirm={() => rowAction(scope, tableAction)}>
{{
reference: () => (actionColumnBtnRender(scope, tableAction)),
}}
</ElPopconfirm>) : actionColumnBtnRender(scope, tableAction)))
),
}}
</div>
</ElTableColumn>)
}
onMounted(doSearch)
return () => (<APage class={[ styles.tablePage, showHighForm.value ? '' : styles.folder ]} style={pageCssParam.value}>
{/*@ts-ignore*/}
<div class={styles.searchFormWrapper} style={highFormCssParam.value}>
<ElScrollbar>
{/*@ts-ignore*/}
<ElForm class={styles.searchForm} onSubmit={withModifiers(doSearch, [ 'prevent' ])} labelWidth={props.searchForm.highForm?.labelWidth ?? '90px'}>
{
slots.highFormItem?.(formData)
}
<button style="display: none" type="submit"/>
</ElForm>
</ElScrollbar>
</div>
<div class={styles.dataList}>
<div class={styles.toolBar}>
<div class={styles.toolBarLeft}>
{
props.toolBar?.leftTools?.map((tool, i) => (
<ElButton key={'tool-bar-left-' + i}
icon={Strings.isBlank(tool.icon) ? undefined : elIcons[tool.icon!]}
type={tool.type ?? 'primary'}
onClick={tool.action}>
{tool.label}
</ElButton>
))
}
</div>
<div class={styles.toolBarRight}>
{/*@ts-ignore*/}
<ElForm onSubmit={withModifiers(doSearch, [ 'prevent' ])}>
{
slots.simpleFormItem?.(formData)
}
<button style="display: none" type="submit"/>
</ElForm>
<ElTooltip content="搜索" placement="top">
<ElDropdown split-button onClick={doSearch} onCommand={(command: string) => {
if (command === 'reset') {
doReset()
}
}}>
{{
default: () => (<ElButton icon={elIcons.Search} loading={loading.value} type="default"/>),
dropdown: () => (<ElDropdownMenu>
<ElDropdownItem icon={elIcons.Refresh} command="reset"></ElDropdownItem>
</ElDropdownMenu>),
}}
</ElDropdown>
</ElTooltip>
{
props.toolBar?.rightTools?.map((tool, i) => (
<ElButton key={'tool-bar-right-' + i}
icon={elIcons[tool.icon]}
onClick={tool.action}/>
))
}
<ElTooltip content="导出" placement="top">
<ElButton icon={elIcons.Download} loading={loading.value} type="default" onClick={doExport}/>
</ElTooltip>
<ElTooltip content={showHighForm.value ? '关闭高级搜索' : '打开高级搜索'} placement="top">
<ElButton class={showHighForm.value ? styles.filterBtnActive : ''} icon={elIcons.Filter} type="default" onClick={showHighFormHandle}/>
</ElTooltip>
</div>
</div>
{
withDirectives(<ElTable
data={tableData}
empty-text={props.table?.emptyText ?? '暂无数据'}
row-key={props.table?.rowKey ?? 'id'}
ref="dataTable"
lazy={props.table?.treeLoad == null ? undefined : true}
load={props.table?.treeLoad ? ((row, expanded, resolve) => props.table?.treeLoad!(formData as P, row, expanded, resolve)) : undefined}
onExpand-change={props.table?.treeLoad ? ((row: any, expandedRows: any) => props.table?.treeLoad!(formData as P, row, expandedRows, undefined)) : undefined}
cell-class-name="table-cell"
header-row-class-name="table-header"
>
{
slots.columns?.()
}
{
actionColumnRender()
}
</ElTable>, [ [ ElLoading.directive, loading.value ] ])
}
<ElPagination
current-page={(formData as G.PageParam).current}
page-size={(formData as G.PageParam).size}
onUpdate:current-page={(val) => (formData as G.PageParam).current = val}
onUpdate:page-size={(val) => (formData as G.PageParam).size = val}
hide-on-single-page={false}
page-sizes={[ 10, 20, 50, 100, 500 ]}
teleported={false}
total={totalCount.value}
background={true}
layout="total, prev, pager, next, sizes, jumper"
onChange={doSearch}/>
{
slots?.default?.()
}
</div>
</APage>)
},
{
name: 'ATablePage',
props: [ 'pageLayout', 'searchForm', 'toolBar', 'table' ],
},
)
export interface ATablePageInstance extends InstanceType<typeof component>, Exposed {
}
export default component

View File

@ -0,0 +1,5 @@
export {}
declare global {
interface ATablePageInstance extends InstanceType<typeof ATablePage>, ATablePageExposed {
}
}

View File

@ -0,0 +1,197 @@
.table-page {
grid-template-columns 1fr
grid-template-rows: minmax(0, 1fr) minmax(0, var(--data-list-height));
grid-auto-rows: minmax(0, auto);
gap 10px
&.folder {
grid-template-rows: 0 minmax(0, 3fr);
gap: 0;
.search-form {
padding 0
border-width 0
height 0
}
}
.search-form-wrapper {
border: 1px solid #EAEBF1;
padding: 20px;
border-radius: 8px;
background-color: white;
height 100%
width 100%;
box-sizing: border-box;
& {
}
& > div {
max-height 168px
width 100%;
}
.search-form {
display grid
grid-template-columns repeat(var(--col-count), 1fr)
row-gap var(--vgap);
column-gap var(--hgap);
:global(.el-form-item) {
margin 0
}
:global(.el-form-item).form-action-btn {
grid-column: 1 / -1;
.el-form-item__content {
justify-content end
}
}
}
}
.data-list {
box-sizing: border-box;
display grid
grid-template-columns 1fr
grid-template-rows 50px minmax(0, 1fr) 50px
border: 1px solid #EAEBF1;
padding: 15px 20px 20px 15px;
border-radius: 8px;
background-color: white;
height 100%
width 100%;
gap 20px
.tool-bar {
display flex
justify-content space-between
box-sizing: border-box;
.tool-bar-left {
flex 1
}
.tool-bar-right {
flex 1
display flex
gap 10px
justify-content end
:global(.el-form) {
display flex
gap 10px
flex-shrink 0
.el-form-item {
margin: 0;
flex 1
}
}
:global(.el-button--default) {
width 32px
color #4D5875
background-color #F1F4F4
border-color #F1F4F4
margin 0
&:hover {
color var(--main-color)
background-color #E6EAEB;
border-color #E6EAEB;
}
}
:global(.el-dropdown) {
flex-shrink 0
}
:global(.el-button--default).filter-btn-active {
color var(--main-color)
}
}
}
:global(.el-table) {
width 100%
height: 100%;
:global(.table-header) {
color #454C59
th {
background-color #EDF1F7
font-weight 500
position relative
& > div {
display flex
gap 5px
align-items center
}
&:not(:first-child) > div::before {
position: absolute;
top: 50%;
left: 1px;
width: 1px;
background-color: #D3D7DE;
transform: translateY(-50%);
content: "";
height 50%
}
}
}
:global(.table-cell) {
color #2F3540
}
.action-btn {
width 100%
display flex
flex-wrap wrap
gap: 10px;
.text-btn {
margin 0
}
.icon-btn {
margin 0
padding: 8px;
justify-content: center;
align-items: center;
//#ebf0ff
}
:global(.el-button--default).icon-btn {
color oklch(72% .19 231.6)
background-color oklch(0.96 0.03 224.26)
border-color oklch(0.96 0.03 224.26)
}
:global(.el-button--danger).icon-btn {
color oklch(73% .15 25.3)
background-color oklch(0.96 0.02 22.09)
border-color oklch(0.96 0.02 22.09)
}
}
}
:global(.el-pagination) {
justify-content center
:global(.btn-next),
:global(.btn-prev),
:global(.el-pager) li {
border-radius: 6px !important;
}
}
}
}

View File

@ -1,6 +1,6 @@
<script generic="F extends object,TT extends DefaultRow" lang="ts" setup> <script generic="F extends object,TT extends DefaultRow" lang="ts" setup>
import { elIcons } from '@/common/element/element.ts' import { elIcons } from '@/common/element/element.ts'
import Page from '@/components/page/Page.vue' import APage from '@/components/a-page/APage.vue'
import Utils, { type ResetAble } from '@/common/utils' import Utils, { type ResetAble } from '@/common/utils'
import Colls from '@/common/utils/colls.ts' import Colls from '@/common/utils/colls.ts'
import Strings from '@/common/utils/strings.ts' import Strings from '@/common/utils/strings.ts'
@ -153,7 +153,7 @@ onMounted(doSearch)
</script> </script>
<template> <template>
<Page class="form-page"> <APage class="form-page">
<div v-show="showSearchForm" class="search-form"> <div v-show="showSearchForm" class="search-form">
<ElScrollbar> <ElScrollbar>
<ElForm :class="{'border-form':formStyle.border}" v-bind="searchFormProps" @submit.prevent="doSearch"> <ElForm :class="{'border-form':formStyle.border}" v-bind="searchFormProps" @submit.prevent="doSearch">
@ -334,7 +334,7 @@ onMounted(doSearch)
@change="doSearch"/> @change="doSearch"/>
</div> </div>
<slot/> <slot/>
</Page> </APage>
</template> </template>
<style lang="stylus" scoped> <style lang="stylus" scoped>

View File

@ -7,6 +7,7 @@
export {} export {}
declare global { declare global {
const EffectScope: typeof import('vue').EffectScope const EffectScope: typeof import('vue').EffectScope
const ElLoading: typeof import('element-plus/es').ElLoading
const ElMessage: typeof import('element-plus/es').ElMessage const ElMessage: typeof import('element-plus/es').ElMessage
const acceptHMRUpdate: typeof import('pinia').acceptHMRUpdate const acceptHMRUpdate: typeof import('pinia').acceptHMRUpdate
const computed: typeof import('vue').computed const computed: typeof import('vue').computed

View File

@ -1,30 +1,27 @@
<template> <template>
<FormPage <ATablePage
ref="formPage" ref="tablePage"
:action-column="actionColumn" v-bind="tablePageProps">
:left-tools="leftTools" <template #highFormItem="formData">
:default-search-form="{createTimes:[undefined,undefined]}"
:paging="paging">
<template #searchFormItem="{ searchForm }">
<ElFormItem label="产品分类"> <ElFormItem label="产品分类">
<GoodsCategoryDropTable v-model="searchForm.goodsCategoryId"/> <GoodsCategoryDropTable v-model="formData.goodsCategoryId"/>
</ElFormItem> </ElFormItem>
<ElFormItem label="产品编码"> <ElFormItem label="产品编码">
<ElInput v-model="searchForm.sn" placeholder="产品编码"/> <ElInput v-model="formData.sn" placeholder="产品编码"/>
</ElFormItem> </ElFormItem>
<ElFormItem label="产品名称"> <ElFormItem label="产品名称">
<ElInput v-model="searchForm.goodsName" placeholder="产品名称"/> <ElInput v-model="formData.goodsName" placeholder="产品名称"/>
</ElFormItem> </ElFormItem>
<ElFormItem label="创建时间"> <ElFormItem label="创建时间">
<ADtPicker v-model="searchForm.createTimes" :change-handler="research"/> <ADtPicker v-model="formData.createTimes" :change-handler="research"/>
</ElFormItem> </ElFormItem>
</template> </template>
<template #simpleSearchFormItem="{ searchForm }"> <template #simpleFormItem="formData">
<ElFormItem> <ElFormItem>
<ElInput v-model="searchForm.sn" placeholder="产品编码"/> <ElInput v-model="formData.sn" placeholder="产品编码"/>
</ElFormItem> </ElFormItem>
<ElFormItem> <ElFormItem>
<ElInput v-model="searchForm.goodsName" placeholder="产品名称"/> <ElInput v-model="formData.goodsName" placeholder="产品名称"/>
</ElFormItem> </ElFormItem>
</template> </template>
<template #columns> <template #columns>
@ -46,73 +43,84 @@
<ElTableColumn label="创建时间" prop="createTime" width="160"/> <ElTableColumn label="创建时间" prop="createTime" width="160"/>
</template> </template>
<GoodsForm ref="goodsForm" :research="research"/> <GoodsForm ref="goodsForm" :research="research"/>
</FormPage> </ATablePage>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import GoodsApi from '@/pages/gds/goods/goods-api.ts' import GoodsApi from '@/pages/gds/goods/goods-api.ts'
import GoodsForm from '@/pages/gds/goods/GoodsForm.vue' import GoodsForm from '@/pages/gds/goods/GoodsForm.vue'
import AppApi from '@/common/app/app-api.ts' import AppApi from '@/common/app/app-api.ts'
import FormPage from '@/components/page/FormPage.vue'
import type {
ActionColumnType,
ToolType,
} from '@/components/page/a-page-type.ts'
import type { ComponentExposed } from 'vue-component-type-helpers'
import ADtPicker from '@/components/a-dt-picker/ADtPicker.vue' import ADtPicker from '@/components/a-dt-picker/ADtPicker.vue'
import GoodsCategoryDropTable from '@/pages/gds/goods-category/GoodsCategoryDropTable.vue' import GoodsCategoryDropTable from '@/pages/gds/goods-category/GoodsCategoryDropTable.vue'
import ATablePage, {
type ATablePageInstance,
buildProps,
} from '@/components/a-page/a-table-page/ATablePage.tsx'
const goodsFormIns = useTemplateRef<InstanceType<typeof GoodsForm>>('goodsForm') const goodsFormIns = useTemplateRef<InstanceType<typeof GoodsForm>>('goodsForm')
const formPageIns = useTemplateRef<ComponentExposed<typeof FormPage>>('formPage')
const actionColumn = reactive<ActionColumnType<GoodsTypes.SearchGoodsResult>>({ const tablePageIns = useTemplateRef<ATablePageInstance>('tablePage')
tableActions: [
{
tooltip: '编辑',
icon: 'Edit',
action({row}) {
goodsFormIns.value?.open(row)
},
},
{
icon: 'Delete',
loading: false,
type: 'danger',
tooltip: '删除',
confirm: {
title: '是否删除当前数据',
},
action({row}) {
return GoodsApi.del([ row.id! ])
.then(() => {
ElMessage.success('删除成功')
return true
})
},
},
],
} as ActionColumnType<GoodsTypes.SearchGoodsResult>)
const leftTools: ToolType[] = [
{
icon: 'Plus',
label: '新建',
action() {
goodsFormIns.value?.open()
},
},
]
function research() { function research() {
formPageIns.value?.doSearch() tablePageIns.value?.doSearch()
} }
function paging(param: GoodsTypes.SearchGoodsParam) { const tablePageProps = buildProps({
return GoodsApi.paging({ searchForm: {
...param, defaultData: {createTimes: [ undefined, undefined ]},
createTimeStart: param.createTimes[0], highForm: {
createTimeEnd: param.createTimes[1], colCount: 4,
}) },
} paging(param: GoodsTypes.SearchGoodsParam) {
return GoodsApi.paging({
...param,
createTimeStart: param.createTimes[0],
createTimeEnd: param.createTimes[1],
})
},
},
toolBar: {
leftTools: [
{
icon: 'Plus',
label: '新建',
action() {
goodsFormIns.value?.open()
},
},
],
},
table: {
actionColumn: {
tableActions: [
{
tooltip: '编辑',
icon: 'Edit',
action({row}) {
goodsFormIns.value?.open(row)
},
},
{
icon: 'Delete',
loading: false,
type: 'danger',
tooltip: '删除',
confirm: {
title: '是否删除当前数据',
},
action({row}) {
return GoodsApi.del([ row.id! ])
.then(() => {
ElMessage.success('删除成功')
return true
})
},
},
],
},
},
})
function enableGoodsHandler(enable: boolean, id: string) { function enableGoodsHandler(enable: boolean, id: string) {
GoodsApi.enable({enable, id}) GoodsApi.enable({enable, id})

View File

@ -1,53 +1,46 @@
<template> <template>
<FormPage <ATablePage
ref="formPage" ref="tablePage"
:action-column="actionColumn" v-bind="tablePageProps">
:form-style="{ <template #highFormItem="formData">
border: false,
colCount: 3,
vgap: '20px',
hgap: '20px',
}"
:paging="paging">
<template #searchFormItem="{searchForm}">
<ElFormItem label="站点"> <ElFormItem label="站点">
<ElInput v-model="searchForm.stationId" placeholder="站点"/> <ElInput v-model="formData.stationId" placeholder="站点"/>
</ElFormItem> </ElFormItem>
<ElFormItem label="订单编号"> <ElFormItem label="订单编号">
<ElInput v-model="searchForm.sn" placeholder="订单编号"/> <ElInput v-model="formData.sn" placeholder="订单编号"/>
</ElFormItem> </ElFormItem>
<ElFormItem label="项目名称"> <ElFormItem label="项目名称">
<ElInput v-model="searchForm.projectName" placeholder="项目名称"/> <ElInput v-model="formData.projectName" placeholder="项目名称"/>
</ElFormItem> </ElFormItem>
<ElFormItem label="客户姓名"> <ElFormItem label="客户姓名">
<ElInput v-model="searchForm.contacts" placeholder="客户姓名"/> <ElInput v-model="formData.contacts" placeholder="客户姓名"/>
</ElFormItem> </ElFormItem>
<ElFormItem label="联系方式"> <ElFormItem label="联系方式">
<ElInput v-model="searchForm.phone" placeholder="联系方式"/> <ElInput v-model="formData.phone" placeholder="联系方式"/>
</ElFormItem> </ElFormItem>
<ElFormItem label="订单类型"> <ElFormItem label="订单类型">
<ElInput v-model="searchForm.orderCategory" placeholder="订单类型"/> <ElInput v-model="formData.orderCategory" placeholder="订单类型"/>
</ElFormItem> </ElFormItem>
<!-- <ElFormItem label="订单状态"> <!-- <ElFormItem label="订单状态">
<ElInput v-model="searchForm.orderStatus" placeholder="订单状态"/> <ElInput v-model="formData.orderStatus" placeholder="订单状态"/>
</ElFormItem> --> </ElFormItem> -->
<ElFormItem label="运输企业"> <ElFormItem label="运输企业">
<ElInput v-model="searchForm.transOrgName" placeholder="运输企业"/> <ElInput v-model="formData.transOrgName" placeholder="运输企业"/>
</ElFormItem> </ElFormItem>
<ElFormItem label="下单时间"> <ElFormItem label="下单时间">
<ADtPicker v-model="searchForm.orderTimes" :change-handler="research"/> <ADtPicker v-model="formData.orderTimes" :change-handler="research"/>
</ElFormItem> </ElFormItem>
<ElFormItem label="完结时间"> <ElFormItem label="完结时间">
<ADtPicker v-model="searchForm.finishTimes" :change-handler="research"/> <ADtPicker v-model="formData.finishTimes" :change-handler="research"/>
</ElFormItem> </ElFormItem>
</template> </template>
<template #simpleSearchFormItem="{searchForm}"> <template #simpleFormItem="formData">
<ElFormItem> <ElFormItem>
<ElInput v-model="searchForm.sn" placeholder="订单编号"/> <ElInput v-model="formData.sn" placeholder="订单编号"/>
</ElFormItem> </ElFormItem>
<ElFormItem> <ElFormItem>
<ElInput v-model="searchForm.orderCategory" placeholder="订单类型"/> <ElInput v-model="formData.orderCategory" placeholder="订单类型"/>
</ElFormItem> </ElFormItem>
</template> </template>
<template #columns> <template #columns>
@ -86,53 +79,49 @@
<!-- <ElTableColumn label="客户备注" prop="customerMemo"/> --> <!-- <ElTableColumn label="客户备注" prop="customerMemo"/> -->
</template> </template>
<OrderForm ref="orderForm" :research="research"/> <OrderForm ref="orderForm" :research="research"/>
</FormPage> </ATablePage>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import OrderApi from '@/pages/order/order-api.ts' import OrderApi from '@/pages/order/order-api.ts'
import OrderForm from '@/pages/order/book/BookForm.vue' import OrderForm from '@/pages/order/book/BookForm.vue'
import FormPage from '@/components/page/FormPage.vue'
import ADtPicker from '@/components/a-dt-picker/ADtPicker.vue' import ADtPicker from '@/components/a-dt-picker/ADtPicker.vue'
import type { ComponentExposed } from 'vue-component-type-helpers' import ATablePage, {
import type { ActionColumnType } from '@/components/page/a-page-type.ts' type ATablePageInstance,
buildProps,
} from '@/components/a-page/a-table-page/ATablePage.tsx'
const tablePageIns = useTemplateRef<ATablePageInstance>('tablePage')
const actionColumn = reactive<ActionColumnType<OrderTypes.SearchOrderResult>>({
tableActions: [
{
tooltip: '详情',
icon: 'Postcard',
action({row}) {
},
},
/* {
icon: 'Delete',
loading: false,
type: 'danger',
tooltip: '删除',
confirm: {
title: '是否删除当前数据',
},
action({row}) {
OrgApi.del([ row.id! ])
.then(() => {
ElMessage.success('删除成功')
return true
})
},
}, */
],
})
const formPageIns = useTemplateRef<ComponentExposed<typeof FormPage>>('formPage')
function research() { function research() {
formPageIns.value?.doSearch() tablePageIns.value?.doSearch()
} }
function paging(param: OrderTypes.SearchOrderParam) { const tablePageProps = buildProps({
return OrderApi.paging(param) table: {
} actionColumn: {
tableActions: [
{
tooltip: '详情',
icon: 'Postcard',
action() {
},
},
],
},
},
searchForm: {
paging(param: OrderTypes.SearchOrderParam) {
return OrderApi.paging(param).then(res => {
res.data.records = []
for (let i = 0; i < 5; i++) {
res.data.records.push({})
}
return res
})
},
},
})
</script> </script>

View File

@ -1,14 +1,14 @@
<template> <template>
<Page> <APage>
<div class="dict-page"> <div class="dict-page">
<DictCategory @search-dict="searchDict"/> <DictCategory @search-dict="searchDict"/>
<ElDivider direction="vertical"/> <ElDivider direction="vertical"/>
<DictItem ref="dictItem"/> <DictItem ref="dictItem"/>
</div> </div>
</Page> </APage>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import Page from '@/components/page/Page.vue' import APage from '@/components/a-page/APage.vue'
import DictCategory from '@/pages/sys/dict/DictCategory.vue' import DictCategory from '@/pages/sys/dict/DictCategory.vue'
import DictItem from '@/pages/sys/dict/DictItem.vue' import DictItem from '@/pages/sys/dict/DictItem.vue'