feat(order): 重构订单页面- 新增 config.js 文件,定义订单搜索和表格配置
- 添加自定义搜索表单和内容组件 - 优化订单列表页面布局和功能 - 实现订单状态标签和操作按钮的自定义渲染
This commit is contained in:
287
src/components/content/index.vue
Normal file
287
src/components/content/index.vue
Normal file
@@ -0,0 +1,287 @@
|
||||
<template>
|
||||
<div class="content">
|
||||
<el-table
|
||||
:border="!!config?.border"
|
||||
:data="computedData"
|
||||
ref="table"
|
||||
row-key="nanoId"
|
||||
v-bind="computedStyle"
|
||||
:show-overflow-tooltip="config.tooltip"
|
||||
:header-row-style="headerRowStyle"
|
||||
:highlight-current-row="!!config.radio ? true : false"
|
||||
:span-method="config?.spanMethod"
|
||||
:tooltip-options="config?.tooltipOptions"
|
||||
@current-change="handleTableCurrentChange"
|
||||
@selection-change="hanldleTableSelectChange"
|
||||
>
|
||||
<el-table-column v-if="config.drag" label="排序" align="center" width="50px" prop="nanoId">
|
||||
<!-- <template #default="{ row, column }"> -->
|
||||
<!-- <span v-show="false">{{ row[column.property] }}</span> -->
|
||||
<div class="move" style="width: 100%; height: 100%">
|
||||
<svg-icon style="cursor: move" icon-class="move" />
|
||||
</div>
|
||||
<!-- </template> -->
|
||||
</el-table-column>
|
||||
<el-table-column v-if="config.select" type="selection" width="50px" />
|
||||
<el-table-column
|
||||
:index="indexMethod"
|
||||
v-if="config.index"
|
||||
type="index"
|
||||
align="center"
|
||||
width="50px"
|
||||
label="序号"
|
||||
/>
|
||||
<template v-for="scheme in config.schemes" :key="scheme.attrs.label">
|
||||
<el-table-column v-bind="scheme.attrs">
|
||||
<template #default="{ row, column, $index }">
|
||||
<slot
|
||||
v-if="!!scheme.slot"
|
||||
:name="scheme.slot"
|
||||
:row="row"
|
||||
:column="column"
|
||||
:index="$index"
|
||||
></slot>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
<template #empty>
|
||||
<el-empty description="获取数据为空" />
|
||||
</template>
|
||||
</el-table>
|
||||
<div class="bottom">
|
||||
<el-pagination
|
||||
class="pagination"
|
||||
v-show="isShow"
|
||||
v-model:current-page="current"
|
||||
v-model:page-size="size"
|
||||
:background="props.background"
|
||||
:layout="props.layout"
|
||||
:total="props.total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, onBeforeMount, onMounted, watch } from 'vue'
|
||||
import Sortable from 'sortablejs'
|
||||
import { nanoid } from '@/utils/jsencrypt'
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
config: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
maxHeight: {
|
||||
type: [String, Number],
|
||||
default: () => ''
|
||||
},
|
||||
headerRowStyle: {
|
||||
type: [Function, Object],
|
||||
default: () => ({
|
||||
background: '#F1F3F7'
|
||||
})
|
||||
},
|
||||
showPagination: {
|
||||
type: Boolean,
|
||||
default: () => true
|
||||
},
|
||||
layout: {
|
||||
type: String,
|
||||
default: () => 'total, sizes, prev, pager, next, jumper'
|
||||
},
|
||||
background: {
|
||||
type: Boolean,
|
||||
default: () => true
|
||||
},
|
||||
minHieght: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
pageSize: {
|
||||
type: Number,
|
||||
default: () => 10
|
||||
},
|
||||
total: {
|
||||
type: Number,
|
||||
default: () => 400
|
||||
},
|
||||
currentPage: {
|
||||
type: Number,
|
||||
default: () => 1
|
||||
}
|
||||
})
|
||||
const emits = defineEmits([
|
||||
'update:page-size',
|
||||
'update:current-page',
|
||||
'update:checkData',
|
||||
'selection',
|
||||
'changePage',
|
||||
'changeSize',
|
||||
'rowSort'
|
||||
])
|
||||
|
||||
const current = ref(props.currentPage)
|
||||
const size = ref(props.pageSize)
|
||||
const computedData = ref([])
|
||||
const table = ref(null)
|
||||
const isShow = computed(() => {
|
||||
return props.showPagination && !!computedData.value.length
|
||||
})
|
||||
const computedStyle = computed(() => {
|
||||
if (props.maxHeight) {
|
||||
return {
|
||||
'max-height': props.maxHeight
|
||||
}
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})
|
||||
watch(
|
||||
() => props.data,
|
||||
(data) => {
|
||||
// if (props.config.drag) {
|
||||
computedData.value = data.map((item) => {
|
||||
if (!item.nanoId) {
|
||||
item.nanoId = nanoid()
|
||||
}
|
||||
return item
|
||||
})
|
||||
// } else {
|
||||
// computedData.value = data
|
||||
// }
|
||||
},
|
||||
{
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => current.value,
|
||||
(newVal) => {
|
||||
emits('update:current-page', newVal)
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => size.value,
|
||||
(newVal) => {
|
||||
emits('update:page-size', newVal)
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => props.currentPage,
|
||||
(newVal) => {
|
||||
current.value = newVal
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => props.pageSize,
|
||||
(newVal) => {
|
||||
size.value = newVal
|
||||
}
|
||||
)
|
||||
|
||||
function reset() {
|
||||
current.value = 1
|
||||
size.value = 10
|
||||
}
|
||||
|
||||
function handleSizeChange(v) {
|
||||
emits('changeSize', v)
|
||||
}
|
||||
|
||||
function handleCurrentChange(v) {
|
||||
emits('changePage', v)
|
||||
}
|
||||
function hanldleTableSelectChange(newSelection) {
|
||||
console.log(newSelection, 'newSelection')
|
||||
emits('selection', { newSelection })
|
||||
}
|
||||
|
||||
function handleTableCurrentChange(data) {
|
||||
console.log(data, 'data')
|
||||
emits('update:checkData', data)
|
||||
}
|
||||
|
||||
function indexMethod(index) {
|
||||
const cur = size.value * (current.value - 1) + index + 1
|
||||
return cur
|
||||
}
|
||||
|
||||
function rowDrag() {
|
||||
const tbody = table.value.$refs.bodyWrapper.querySelector('tbody')
|
||||
Sortable.create(tbody, {
|
||||
ghostClass: 'sortable-ghost',
|
||||
animation: 150,
|
||||
handle: '.move',
|
||||
onEnd: (event) => {
|
||||
if (event.oldIndex !== undefined && event.newIndex !== undefined) {
|
||||
let newArr = computedData.value
|
||||
const curRow = newArr.splice(event.oldIndex, 1)[0]
|
||||
newArr.splice(event.newIndex, 0, curRow)
|
||||
computedData.value = [...newArr]
|
||||
emits('rowSort', newArr)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onBeforeMount(() => {
|
||||
// if (props.config.drag) {
|
||||
computedData.value = props.data.map((item) => {
|
||||
if (!item.nanoId) {
|
||||
item.nanoId = nanoid()
|
||||
}
|
||||
return item
|
||||
})
|
||||
// } else {
|
||||
// computedData.value = props.data
|
||||
// }
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
props.config.drag && rowDrag()
|
||||
})
|
||||
|
||||
defineExpose({
|
||||
table,
|
||||
reset
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
padding: 20px 20px 0 20px;
|
||||
box-sizing: border-box;
|
||||
:deep(.el-table) {
|
||||
.current-row {
|
||||
background-color: #e5f1fd;
|
||||
}
|
||||
.sortable-ghost {
|
||||
opacity: 1;
|
||||
cursor: grab !important;
|
||||
background-color: #ebf5ff !important;
|
||||
}
|
||||
}
|
||||
.bottom {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
.right {
|
||||
margin-top: 20px;
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
.pagination {
|
||||
margin-top: 20px;
|
||||
height: 75px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
Reference in New Issue
Block a user