Skip to content

Commit 8b45391

Browse files
authored
Merge pull request #3 from BluemsunOffice/codex-admin-search-export
取消订单
2 parents 4cb54d2 + 0b89257 commit 8b45391

11 files changed

Lines changed: 1614 additions & 14 deletions
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
<template>
2+
<el-table
3+
ref="tableRef"
4+
:data="orders"
5+
border
6+
row-key="id"
7+
v-loading="loading"
8+
class="order-table"
9+
@selection-change="handleSelectionChange"
10+
>
11+
<el-table-column
12+
type="selection"
13+
width="52"
14+
:reserve-selection="true"
15+
:selectable="isSelectableRow"
16+
/>
17+
<el-table-column
18+
v-for="column in columns"
19+
:key="column.key"
20+
:prop="column.prop"
21+
:label="column.label"
22+
:min-width="column.minWidth"
23+
:show-overflow-tooltip="column.showOverflowTooltip"
24+
>
25+
<template #default="scope" v-if="column.type === 'status'">
26+
<el-tag :type="statusTagType(scope.row.status)">
27+
{{ statusText(scope.row.status) }}
28+
</el-tag>
29+
</template>
30+
31+
<template #default="scope" v-else-if="column.type === 'total'">
32+
服装币: {{ scope.row.clothingBalance }}&nbsp;&nbsp; 日用币: {{ scope.row.generalBalance }}
33+
</template>
34+
</el-table-column>
35+
36+
<el-table-column label="操作" min-width="300" fixed="right">
37+
<template #default="scope">
38+
<div class="action-row">
39+
<el-popconfirm
40+
v-if="isOrderCheckable(scope.row.status)"
41+
title="确定核销该订单?"
42+
@confirm="emit('check-one', scope.row.id)"
43+
>
44+
<template #reference>
45+
<el-button text type="primary">核销订单</el-button>
46+
</template>
47+
</el-popconfirm>
48+
49+
<el-popconfirm
50+
v-if="isOrderCheckable(scope.row.status)"
51+
title="确定取消该订单?"
52+
@confirm="emit('cancel-one', scope.row.id)"
53+
>
54+
<template #reference>
55+
<el-button text type="danger">取消订单</el-button>
56+
</template>
57+
</el-popconfirm>
58+
59+
<el-button text type="primary" @click="emit('view-detail', scope.row.id)">
60+
查看详情
61+
</el-button>
62+
</div>
63+
</template>
64+
</el-table-column>
65+
</el-table>
66+
</template>
67+
68+
<script setup lang="ts">
69+
import { nextTick, ref, watch } from 'vue'
70+
import type { ElTable } from 'element-plus'
71+
import type { AdminOrderItem } from '@/api/order.api'
72+
73+
interface OrderTableColumn {
74+
key: string
75+
label: string
76+
minWidth: string
77+
prop?: keyof AdminOrderItem
78+
showOverflowTooltip?: boolean
79+
type?: 'text' | 'status' | 'total'
80+
}
81+
82+
const props = defineProps<{
83+
orders: AdminOrderItem[]
84+
loading: boolean
85+
selectedOrderIds: string[]
86+
statusText: (status: string) => string
87+
statusTagType: (status: string) => 'primary' | 'danger' | 'success'
88+
isOrderCheckable: (status: string) => boolean
89+
}>()
90+
91+
const emit = defineEmits<{
92+
'selection-change': [rows: AdminOrderItem[]]
93+
'check-one': [orderId: string]
94+
'cancel-one': [orderId: string]
95+
'view-detail': [orderId: string]
96+
}>()
97+
98+
const tableRef = ref<InstanceType<typeof ElTable>>()
99+
const isSyncingSelection = ref(false)
100+
101+
const columns: OrderTableColumn[] = [
102+
{
103+
key: 'createTime',
104+
prop: 'createTime',
105+
label: '订单时间',
106+
minWidth: '200',
107+
type: 'text',
108+
},
109+
{
110+
key: 'status',
111+
prop: 'status',
112+
label: '订单状态',
113+
minWidth: '140',
114+
type: 'status',
115+
},
116+
{
117+
key: 'names',
118+
prop: 'names',
119+
label: '商品名称',
120+
minWidth: '200',
121+
showOverflowTooltip: true,
122+
type: 'text',
123+
},
124+
{
125+
key: 'total',
126+
label: '订单总价',
127+
minWidth: '220',
128+
type: 'total',
129+
},
130+
{
131+
key: 'username',
132+
prop: 'username',
133+
label: '用户名称',
134+
minWidth: '120',
135+
type: 'text',
136+
},
137+
]
138+
139+
const isSelectableRow = (row: AdminOrderItem) => props.isOrderCheckable(row.status)
140+
141+
const syncSelection = async () => {
142+
const table = tableRef.value
143+
if (!table) {
144+
return
145+
}
146+
147+
isSyncingSelection.value = true
148+
table.clearSelection()
149+
props.orders.forEach((row) => {
150+
if (props.selectedOrderIds.includes(row.id) && props.isOrderCheckable(row.status)) {
151+
table.toggleRowSelection(row, true)
152+
}
153+
})
154+
155+
await nextTick()
156+
isSyncingSelection.value = false
157+
}
158+
159+
watch(
160+
() => [
161+
props.orders.map((row) => `${row.id}:${row.status}`).join('|'),
162+
props.selectedOrderIds.join('|'),
163+
],
164+
() => {
165+
void syncSelection()
166+
},
167+
{ immediate: true },
168+
)
169+
170+
const handleSelectionChange = (rows: AdminOrderItem[]) => {
171+
if (isSyncingSelection.value) {
172+
return
173+
}
174+
emit('selection-change', rows)
175+
}
176+
</script>
177+
178+
<style scoped>
179+
.order-table {
180+
width: 100%;
181+
}
182+
183+
.action-row {
184+
display: flex;
185+
align-items: center;
186+
flex-wrap: nowrap;
187+
gap: 16px;
188+
white-space: nowrap;
189+
}
190+
</style>
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
<template>
2+
<el-table
3+
ref="tableRef"
4+
:data="orders"
5+
border
6+
row-key="id"
7+
v-loading="loading"
8+
class="order-table"
9+
@selection-change="handleSelectionChange"
10+
>
11+
<el-table-column
12+
type="selection"
13+
width="52"
14+
:reserve-selection="true"
15+
:selectable="isSelectableRow"
16+
/>
17+
<el-table-column
18+
v-for="column in columns"
19+
:key="column.key"
20+
:prop="column.prop"
21+
:label="column.label"
22+
:min-width="column.minWidth"
23+
:show-overflow-tooltip="column.showOverflowTooltip"
24+
>
25+
<template #default="scope" v-if="column.type === 'status'">
26+
<el-tag :type="statusTagType(scope.row.status)">
27+
{{ statusText(scope.row.status) }}
28+
</el-tag>
29+
</template>
30+
31+
<template #default="scope" v-else-if="column.type === 'total'">
32+
服装币: {{ scope.row.clothingBalance }}&nbsp;&nbsp; 日用币: {{ scope.row.generalBalance }}
33+
</template>
34+
</el-table-column>
35+
36+
<el-table-column label="操作" min-width="300" fixed="right">
37+
<template #default="scope">
38+
<div class="action-row">
39+
<el-popconfirm
40+
v-if="isOrderCheckable(scope.row.status)"
41+
title="确定核销该订单?"
42+
@confirm="emit('check-one', scope.row.id)"
43+
>
44+
<template #reference>
45+
<el-button text type="primary">核销订单</el-button>
46+
</template>
47+
</el-popconfirm>
48+
49+
<el-popconfirm
50+
v-if="isOrderCheckable(scope.row.status)"
51+
title="确定取消该订单?"
52+
@confirm="emit('cancel-one', scope.row.id)"
53+
>
54+
<template #reference>
55+
<el-button text type="danger">取消订单</el-button>
56+
</template>
57+
</el-popconfirm>
58+
59+
<el-button text type="primary" @click="emit('view-detail', scope.row.id)">
60+
查看详情
61+
</el-button>
62+
</div>
63+
</template>
64+
</el-table-column>
65+
</el-table>
66+
</template>
67+
68+
<script setup lang="ts">
69+
import { nextTick, ref, watch } from 'vue'
70+
import type { ElTable } from 'element-plus'
71+
import type { AdminOrderItem } from '@/api/order.api'
72+
73+
interface OrderTableColumn {
74+
key: string
75+
label: string
76+
minWidth: string
77+
prop?: keyof AdminOrderItem
78+
showOverflowTooltip?: boolean
79+
type?: 'text' | 'status' | 'total'
80+
}
81+
82+
const props = defineProps<{
83+
orders: AdminOrderItem[]
84+
loading: boolean
85+
selectedOrderIds: string[]
86+
statusText: (status: string) => string
87+
statusTagType: (status: string) => 'primary' | 'danger' | 'success'
88+
isOrderCheckable: (status: string) => boolean
89+
}>()
90+
91+
const emit = defineEmits<{
92+
'selection-change': [rows: AdminOrderItem[]]
93+
'check-one': [orderId: string]
94+
'cancel-one': [orderId: string]
95+
'view-detail': [orderId: string]
96+
}>()
97+
98+
const tableRef = ref<InstanceType<typeof ElTable>>()
99+
const isSyncingSelection = ref(false)
100+
101+
const columns: OrderTableColumn[] = [
102+
{
103+
key: 'createTime',
104+
prop: 'createTime',
105+
label: '订单时间',
106+
minWidth: '200',
107+
type: 'text',
108+
},
109+
{
110+
key: 'status',
111+
prop: 'status',
112+
label: '订单状态',
113+
minWidth: '140',
114+
type: 'status',
115+
},
116+
{
117+
key: 'names',
118+
prop: 'names',
119+
label: '商品名称',
120+
minWidth: '200',
121+
showOverflowTooltip: true,
122+
type: 'text',
123+
},
124+
{
125+
key: 'total',
126+
label: '订单总价',
127+
minWidth: '220',
128+
type: 'total',
129+
},
130+
{
131+
key: 'username',
132+
prop: 'username',
133+
label: '用户名称',
134+
minWidth: '120',
135+
type: 'text',
136+
},
137+
]
138+
139+
const isSelectableRow = (row: AdminOrderItem) => props.isOrderCheckable(row.status)
140+
141+
const syncSelection = async () => {
142+
const table = tableRef.value
143+
if (!table) {
144+
return
145+
}
146+
147+
isSyncingSelection.value = true
148+
table.clearSelection()
149+
props.orders.forEach((row) => {
150+
if (props.selectedOrderIds.includes(row.id) && props.isOrderCheckable(row.status)) {
151+
table.toggleRowSelection(row, true)
152+
}
153+
})
154+
155+
await nextTick()
156+
isSyncingSelection.value = false
157+
}
158+
159+
watch(
160+
() => [
161+
props.orders.map((row) => `${row.id}:${row.status}`).join('|'),
162+
props.selectedOrderIds.join('|'),
163+
],
164+
() => {
165+
void syncSelection()
166+
},
167+
{ immediate: true },
168+
)
169+
170+
const handleSelectionChange = (rows: AdminOrderItem[]) => {
171+
if (isSyncingSelection.value) {
172+
return
173+
}
174+
emit('selection-change', rows)
175+
}
176+
</script>
177+
178+
<style scoped>
179+
.order-table {
180+
width: 100%;
181+
}
182+
183+
.action-row {
184+
display: flex;
185+
align-items: center;
186+
flex-wrap: nowrap;
187+
gap: 16px;
188+
white-space: nowrap;
189+
}
190+
</style>

0 commit comments

Comments
 (0)