Commit 9542b035a3a028179672213abd9e5e21326046be
1 parent
4d16c20f
Refactor: 优化订单管理和配送订单列表分页功能,新增状态筛选卡片和交互逻辑,提升用户体验。
Showing
2 changed files
with
220 additions
and
16 deletions
src/views/delivery/DeliveryOrderList.vue
| @@ -6,18 +6,25 @@ | @@ -6,18 +6,25 @@ | ||
| 6 | <a-select v-if="isAdmin" v-model:value="filterCityId" placeholder="租户" allowClear class="list-filter" @change="handleAdminCityChange"> | 6 | <a-select v-if="isAdmin" v-model:value="filterCityId" placeholder="租户" allowClear class="list-filter" @change="handleAdminCityChange"> |
| 7 | <a-select-option v-for="item in cityList" :key="item.id" :value="item.id">{{ item.name }}</a-select-option> | 7 | <a-select-option v-for="item in cityList" :key="item.id" :value="item.id">{{ item.name }}</a-select-option> |
| 8 | </a-select> | 8 | </a-select> |
| 9 | - <a-input v-if="isAdmin" v-model:value="filterAppKey" placeholder="接入方 AppKey" class="list-search appkey-search" @pressEnter="loadList" /> | ||
| 10 | - <a-select v-model:value="filterStatus" placeholder="状态" allowClear class="list-filter" @change="loadList"> | 9 | + <a-input v-if="isAdmin" v-model:value="filterAppKey" placeholder="接入方 AppKey" class="list-search appkey-search" @pressEnter="handleAppKeySearch" /> |
| 10 | + <a-select v-model:value="filterStatus" placeholder="状态" allowClear class="list-filter" @change="handleStatusChange"> | ||
| 11 | <a-select-option :value="2">待接单</a-select-option> | 11 | <a-select-option :value="2">待接单</a-select-option> |
| 12 | <a-select-option :value="3">已接单</a-select-option> | 12 | <a-select-option :value="3">已接单</a-select-option> |
| 13 | <a-select-option :value="4">配送中</a-select-option> | 13 | <a-select-option :value="4">配送中</a-select-option> |
| 14 | <a-select-option :value="6">已完成</a-select-option> | 14 | <a-select-option :value="6">已完成</a-select-option> |
| 15 | <a-select-option :value="10">已取消</a-select-option> | 15 | <a-select-option :value="10">已取消</a-select-option> |
| 16 | </a-select> | 16 | </a-select> |
| 17 | - <a-input-search v-model:value="keyword" placeholder="外部订单号" @search="loadList" class="list-search" /> | 17 | + <a-input-search v-model:value="keyword" placeholder="外部订单号" @search="handleKeywordSearch" class="list-search" /> |
| 18 | </div> | 18 | </div> |
| 19 | </div> | 19 | </div> |
| 20 | - <a-table :dataSource="list" :columns="columns" :loading="loading" rowKey="id" :pagination="false"> | 20 | + <a-table |
| 21 | + :dataSource="list" | ||
| 22 | + :columns="columns" | ||
| 23 | + :loading="loading" | ||
| 24 | + rowKey="id" | ||
| 25 | + :pagination="pagination" | ||
| 26 | + @change="handleTableChange" | ||
| 27 | + > | ||
| 21 | <template #bodyCell="{ column, record }"> | 28 | <template #bodyCell="{ column, record }"> |
| 22 | <template v-if="column.key === 'cityName'"> | 29 | <template v-if="column.key === 'cityName'"> |
| 23 | {{ getCityName(record.cityId) }} | 30 | {{ getCityName(record.cityId) }} |
| @@ -61,12 +68,18 @@ | @@ -61,12 +68,18 @@ | ||
| 61 | <script setup lang="ts"> | 68 | <script setup lang="ts"> |
| 62 | import { computed, ref, onMounted } from 'vue' | 69 | import { computed, ref, onMounted } from 'vue' |
| 63 | import { message } from 'ant-design-vue' | 70 | import { message } from 'ant-design-vue' |
| 71 | +import type { TablePaginationConfig } from 'ant-design-vue' | ||
| 64 | import { riderApi } from '@/api' | 72 | import { riderApi } from '@/api' |
| 65 | import { useRoleCityList } from '@/composables/useRoleCityList' | 73 | import { useRoleCityList } from '@/composables/useRoleCityList' |
| 66 | 74 | ||
| 75 | +const PAGE_SIZE = 20 | ||
| 76 | + | ||
| 67 | const loading = ref(false) | 77 | const loading = ref(false) |
| 68 | const detailLoading = ref(false) | 78 | const detailLoading = ref(false) |
| 69 | const list = ref<any[]>([]) | 79 | const list = ref<any[]>([]) |
| 80 | +const total = ref(0) | ||
| 81 | +const currentPage = ref(1) | ||
| 82 | +const pageSize = ref(PAGE_SIZE) | ||
| 70 | const filterCityId = ref<number | undefined>() | 83 | const filterCityId = ref<number | undefined>() |
| 71 | const filterAppKey = ref('') | 84 | const filterAppKey = ref('') |
| 72 | const filterStatus = ref<number | undefined>() | 85 | const filterStatus = ref<number | undefined>() |
| @@ -104,6 +117,42 @@ const columns = computed(() => { | @@ -104,6 +117,42 @@ const columns = computed(() => { | ||
| 104 | ] | 117 | ] |
| 105 | }) | 118 | }) |
| 106 | 119 | ||
| 120 | +const pagination = computed<TablePaginationConfig>(() => ({ | ||
| 121 | + current: currentPage.value, | ||
| 122 | + pageSize: pageSize.value, | ||
| 123 | + total: total.value, | ||
| 124 | + showSizeChanger: false, | ||
| 125 | + showTotal: (count) => `共 ${count} 条`, | ||
| 126 | +})) | ||
| 127 | + | ||
| 128 | +function resetToFirstPage() { | ||
| 129 | + currentPage.value = 1 | ||
| 130 | +} | ||
| 131 | + | ||
| 132 | +function handleStatusChange() { | ||
| 133 | + resetToFirstPage() | ||
| 134 | + loadList() | ||
| 135 | +} | ||
| 136 | + | ||
| 137 | +function handleKeywordSearch() { | ||
| 138 | + resetToFirstPage() | ||
| 139 | + loadList() | ||
| 140 | +} | ||
| 141 | + | ||
| 142 | +function handleAppKeySearch() { | ||
| 143 | + resetToFirstPage() | ||
| 144 | + loadList() | ||
| 145 | +} | ||
| 146 | + | ||
| 147 | +function handleTableChange(page: TablePaginationConfig) { | ||
| 148 | + const nextPage = page.current ?? 1 | ||
| 149 | + if (nextPage === currentPage.value) { | ||
| 150 | + return | ||
| 151 | + } | ||
| 152 | + currentPage.value = nextPage | ||
| 153 | + loadList() | ||
| 154 | +} | ||
| 155 | + | ||
| 107 | async function loadList() { | 156 | async function loadList() { |
| 108 | loading.value = true | 157 | loading.value = true |
| 109 | try { | 158 | try { |
| @@ -112,9 +161,17 @@ async function loadList() { | @@ -112,9 +161,17 @@ async function loadList() { | ||
| 112 | appKey: filterAppKey.value || undefined, | 161 | appKey: filterAppKey.value || undefined, |
| 113 | status: filterStatus.value, | 162 | status: filterStatus.value, |
| 114 | outOrderNo: keyword.value || undefined, | 163 | outOrderNo: keyword.value || undefined, |
| 115 | - page: 1 | 164 | + page: currentPage.value |
| 116 | }) | 165 | }) |
| 117 | - list.value = Array.isArray(res?.data) ? res.data : [] | 166 | + const data = res?.data ?? {} |
| 167 | + list.value = Array.isArray(data.list) ? data.list : [] | ||
| 168 | + total.value = Number(data.total ?? 0) | ||
| 169 | + currentPage.value = Number(data.page ?? currentPage.value) | ||
| 170 | + pageSize.value = Number(data.pageSize ?? PAGE_SIZE) | ||
| 171 | + if (!list.value.length && total.value > 0 && currentPage.value > 1) { | ||
| 172 | + currentPage.value -= 1 | ||
| 173 | + await loadList() | ||
| 174 | + } | ||
| 118 | } finally { loading.value = false } | 175 | } finally { loading.value = false } |
| 119 | } | 176 | } |
| 120 | 177 | ||
| @@ -123,6 +180,7 @@ function handleAdminCityChange() { | @@ -123,6 +180,7 @@ function handleAdminCityChange() { | ||
| 123 | queryVisible.value = false | 180 | queryVisible.value = false |
| 124 | queryResult.value = null | 181 | queryResult.value = null |
| 125 | } | 182 | } |
| 183 | + resetToFirstPage() | ||
| 126 | loadList() | 184 | loadList() |
| 127 | } | 185 | } |
| 128 | 186 | ||
| @@ -143,7 +201,7 @@ async function cancelOrder(record: any) { | @@ -143,7 +201,7 @@ async function cancelOrder(record: any) { | ||
| 143 | queryVisible.value = false | 201 | queryVisible.value = false |
| 144 | queryResult.value = null | 202 | queryResult.value = null |
| 145 | } | 203 | } |
| 146 | - loadList() | 204 | + await loadList() |
| 147 | } | 205 | } |
| 148 | 206 | ||
| 149 | onMounted(async () => { | 207 | onMounted(async () => { |
src/views/order/OrderList.vue
| 1 | <template> | 1 | <template> |
| 2 | <div> | 2 | <div> |
| 3 | <a-card title="订单管理" :bordered="false" class="list-table-card"> | 3 | <a-card title="订单管理" :bordered="false" class="list-table-card"> |
| 4 | + <div class="order-status-cards"> | ||
| 5 | + <button | ||
| 6 | + v-for="item in statusCardItems" | ||
| 7 | + :key="item.key" | ||
| 8 | + type="button" | ||
| 9 | + class="order-status-card" | ||
| 10 | + :class="{ 'is-active': isStatusCardActive(item.value) }" | ||
| 11 | + @click="handleStatusCardClick(item.value)" | ||
| 12 | + > | ||
| 13 | + <span class="order-status-card__label">{{ item.label }}</span> | ||
| 14 | + <strong class="order-status-card__count">{{ statusSummary[item.key] ?? 0 }}</strong> | ||
| 15 | + </button> | ||
| 16 | + </div> | ||
| 4 | <div class="list-toolbar"> | 17 | <div class="list-toolbar"> |
| 5 | <div class="list-toolbar-left"> | 18 | <div class="list-toolbar-left"> |
| 6 | <a-select v-if="isAdmin" v-model:value="filterCityId" placeholder="租户" allowClear class="list-filter" @change="handleAdminCityChange"> | 19 | <a-select v-if="isAdmin" v-model:value="filterCityId" placeholder="租户" allowClear class="list-filter" @change="handleAdminCityChange"> |
| 7 | <a-select-option v-for="item in cityList" :key="item.id" :value="item.id">{{ item.name }}</a-select-option> | 20 | <a-select-option v-for="item in cityList" :key="item.id" :value="item.id">{{ item.name }}</a-select-option> |
| 8 | </a-select> | 21 | </a-select> |
| 9 | - <a-select v-model:value="filterStatus" placeholder="订单状态" allowClear class="list-filter" @change="loadList"> | 22 | + <a-select v-model:value="filterStatus" placeholder="订单状态" allowClear class="list-filter" @change="handleStatusChange"> |
| 10 | <a-select-option :value="2">已支付</a-select-option> | 23 | <a-select-option :value="2">已支付</a-select-option> |
| 11 | <a-select-option :value="3">已接单</a-select-option> | 24 | <a-select-option :value="3">已接单</a-select-option> |
| 12 | <a-select-option :value="4">服务中</a-select-option> | 25 | <a-select-option :value="4">服务中</a-select-option> |
| @@ -14,15 +27,22 @@ | @@ -14,15 +27,22 @@ | ||
| 14 | <a-select-option :value="7">退款申请</a-select-option> | 27 | <a-select-option :value="7">退款申请</a-select-option> |
| 15 | <a-select-option :value="10">已取消</a-select-option> | 28 | <a-select-option :value="10">已取消</a-select-option> |
| 16 | </a-select> | 29 | </a-select> |
| 17 | - <a-select v-model:value="filterTrans" placeholder="转单状态" allowClear class="list-filter" @change="loadList"> | 30 | + <a-select v-model:value="filterTrans" placeholder="转单状态" allowClear class="list-filter" @change="handleTransChange"> |
| 18 | <a-select-option :value="2">转单申请中</a-select-option> | 31 | <a-select-option :value="2">转单申请中</a-select-option> |
| 19 | <a-select-option :value="1">已转单</a-select-option> | 32 | <a-select-option :value="1">已转单</a-select-option> |
| 20 | <a-select-option :value="3">转单拒绝</a-select-option> | 33 | <a-select-option :value="3">转单拒绝</a-select-option> |
| 21 | </a-select> | 34 | </a-select> |
| 22 | - <a-input-search v-model:value="keyword" placeholder="订单号" @search="loadList" class="list-search" /> | 35 | + <a-input-search v-model:value="keyword" placeholder="订单号" @search="handleKeywordSearch" class="list-search" /> |
| 23 | </div> | 36 | </div> |
| 24 | </div> | 37 | </div> |
| 25 | - <a-table :dataSource="list" :columns="columns" :loading="loading" rowKey="id" :pagination="false"> | 38 | + <a-table |
| 39 | + :dataSource="list" | ||
| 40 | + :columns="columns" | ||
| 41 | + :loading="loading" | ||
| 42 | + rowKey="id" | ||
| 43 | + :pagination="pagination" | ||
| 44 | + @change="handleTableChange" | ||
| 45 | + > | ||
| 26 | <template #bodyCell="{ column, record }"> | 46 | <template #bodyCell="{ column, record }"> |
| 27 | <template v-if="column.key === 'cityName'"> | 47 | <template v-if="column.key === 'cityName'"> |
| 28 | {{ cityList.find(item => item.id === record.cityId)?.name || `租户#${record.cityId}` }} | 48 | {{ cityList.find(item => item.id === record.cityId)?.name || `租户#${record.cityId}` }} |
| @@ -129,12 +149,28 @@ | @@ -129,12 +149,28 @@ | ||
| 129 | <script setup lang="ts"> | 149 | <script setup lang="ts"> |
| 130 | import { computed, ref, onMounted } from 'vue' | 150 | import { computed, ref, onMounted } from 'vue' |
| 131 | import { message } from 'ant-design-vue' | 151 | import { message } from 'ant-design-vue' |
| 152 | +import type { TablePaginationConfig } from 'ant-design-vue' | ||
| 132 | import { riderApi, refundApi } from '@/api' | 153 | import { riderApi, refundApi } from '@/api' |
| 133 | import { useRoleCityList } from '@/composables/useRoleCityList' | 154 | import { useRoleCityList } from '@/composables/useRoleCityList' |
| 134 | 155 | ||
| 156 | +const PAGE_SIZE = 20 | ||
| 157 | +const STATUS_CARD_ITEMS = [ | ||
| 158 | + { key: 'all', label: '全部', value: undefined }, | ||
| 159 | + { key: '2', label: '已支付', value: 2 }, | ||
| 160 | + { key: '3', label: '已接单', value: 3 }, | ||
| 161 | + { key: '4', label: '服务中', value: 4 }, | ||
| 162 | + { key: '6', label: '已完成', value: 6 }, | ||
| 163 | + { key: '7', label: '退款申请', value: 7 }, | ||
| 164 | + { key: '10', label: '已取消', value: 10 }, | ||
| 165 | +] as const | ||
| 166 | + | ||
| 135 | const loading = ref(false) | 167 | const loading = ref(false) |
| 136 | const saving = ref(false) | 168 | const saving = ref(false) |
| 137 | const list = ref<any[]>([]) | 169 | const list = ref<any[]>([]) |
| 170 | +const total = ref(0) | ||
| 171 | +const currentPage = ref(1) | ||
| 172 | +const pageSize = ref(PAGE_SIZE) | ||
| 173 | +const statusSummary = ref<Record<string, number>>({ all: 0, '2': 0, '3': 0, '4': 0, '6': 0, '7': 0, '10': 0 }) | ||
| 138 | const filterCityId = ref<number | undefined>() | 174 | const filterCityId = ref<number | undefined>() |
| 139 | const filterStatus = ref<number | undefined>() | 175 | const filterStatus = ref<number | undefined>() |
| 140 | const filterTrans = ref<number | undefined>() | 176 | const filterTrans = ref<number | undefined>() |
| @@ -151,6 +187,7 @@ const refundRecord = ref<any>(null) | @@ -151,6 +187,7 @@ const refundRecord = ref<any>(null) | ||
| 151 | const currentRefundRecordId = ref(0) | 187 | const currentRefundRecordId = ref(0) |
| 152 | const { isAdmin, cityList, loadCities } = useRoleCityList() | 188 | const { isAdmin, cityList, loadCities } = useRoleCityList() |
| 153 | const canOperate = computed(() => !isAdmin.value || !!filterCityId.value) | 189 | const canOperate = computed(() => !isAdmin.value || !!filterCityId.value) |
| 190 | +const statusCardItems = STATUS_CARD_ITEMS | ||
| 154 | 191 | ||
| 155 | const statusMap: Record<number, string> = { | 192 | const statusMap: Record<number, string> = { |
| 156 | 1: '待支付', 2: '已支付', 3: '已接单', 4: '服务中', | 193 | 1: '待支付', 2: '已支付', 3: '已接单', 4: '服务中', |
| @@ -180,6 +217,52 @@ const columns = computed(() => { | @@ -180,6 +217,52 @@ const columns = computed(() => { | ||
| 180 | ] | 217 | ] |
| 181 | }) | 218 | }) |
| 182 | 219 | ||
| 220 | +const pagination = computed<TablePaginationConfig>(() => ({ | ||
| 221 | + current: currentPage.value, | ||
| 222 | + pageSize: pageSize.value, | ||
| 223 | + total: total.value, | ||
| 224 | + showSizeChanger: false, | ||
| 225 | + showTotal: (count) => `共 ${count} 条`, | ||
| 226 | +})) | ||
| 227 | + | ||
| 228 | +function resetToFirstPage() { | ||
| 229 | + currentPage.value = 1 | ||
| 230 | +} | ||
| 231 | + | ||
| 232 | +function isStatusCardActive(value: number | undefined) { | ||
| 233 | + return value === undefined ? filterStatus.value === undefined : filterStatus.value === value | ||
| 234 | +} | ||
| 235 | + | ||
| 236 | +function handleStatusCardClick(value: number | undefined) { | ||
| 237 | + filterStatus.value = value | ||
| 238 | + resetToFirstPage() | ||
| 239 | + loadList() | ||
| 240 | +} | ||
| 241 | + | ||
| 242 | +function handleStatusChange() { | ||
| 243 | + resetToFirstPage() | ||
| 244 | + loadList() | ||
| 245 | +} | ||
| 246 | + | ||
| 247 | +function handleTransChange() { | ||
| 248 | + resetToFirstPage() | ||
| 249 | + loadList() | ||
| 250 | +} | ||
| 251 | + | ||
| 252 | +function handleKeywordSearch() { | ||
| 253 | + resetToFirstPage() | ||
| 254 | + loadList() | ||
| 255 | +} | ||
| 256 | + | ||
| 257 | +function handleTableChange(page: TablePaginationConfig) { | ||
| 258 | + const nextPage = page.current ?? 1 | ||
| 259 | + if (nextPage === currentPage.value) { | ||
| 260 | + return | ||
| 261 | + } | ||
| 262 | + currentPage.value = nextPage | ||
| 263 | + loadList() | ||
| 264 | +} | ||
| 265 | + | ||
| 183 | async function loadList() { | 266 | async function loadList() { |
| 184 | loading.value = true | 267 | loading.value = true |
| 185 | try { | 268 | try { |
| @@ -188,9 +271,26 @@ async function loadList() { | @@ -188,9 +271,26 @@ async function loadList() { | ||
| 188 | status: filterStatus.value, | 271 | status: filterStatus.value, |
| 189 | isTrans: filterTrans.value, | 272 | isTrans: filterTrans.value, |
| 190 | keyword: keyword.value, | 273 | keyword: keyword.value, |
| 191 | - page: 1 | 274 | + page: currentPage.value |
| 192 | }) | 275 | }) |
| 193 | - list.value = Array.isArray(res?.data) ? res.data : [] | 276 | + const data = res?.data ?? {} |
| 277 | + list.value = Array.isArray(data.list) ? data.list : [] | ||
| 278 | + total.value = Number(data.total ?? 0) | ||
| 279 | + currentPage.value = Number(data.page ?? currentPage.value) | ||
| 280 | + pageSize.value = Number(data.pageSize ?? PAGE_SIZE) | ||
| 281 | + statusSummary.value = { | ||
| 282 | + all: Number(data.statusSummary?.all ?? 0), | ||
| 283 | + '2': Number(data.statusSummary?.['2'] ?? 0), | ||
| 284 | + '3': Number(data.statusSummary?.['3'] ?? 0), | ||
| 285 | + '4': Number(data.statusSummary?.['4'] ?? 0), | ||
| 286 | + '6': Number(data.statusSummary?.['6'] ?? 0), | ||
| 287 | + '7': Number(data.statusSummary?.['7'] ?? 0), | ||
| 288 | + '10': Number(data.statusSummary?.['10'] ?? 0), | ||
| 289 | + } | ||
| 290 | + if (!list.value.length && total.value > 0 && currentPage.value > 1) { | ||
| 291 | + currentPage.value -= 1 | ||
| 292 | + await loadList() | ||
| 293 | + } | ||
| 194 | } finally { loading.value = false } | 294 | } finally { loading.value = false } |
| 195 | } | 295 | } |
| 196 | 296 | ||
| @@ -200,6 +300,7 @@ function handleAdminCityChange() { | @@ -200,6 +300,7 @@ function handleAdminCityChange() { | ||
| 200 | refundVisible.value = false | 300 | refundVisible.value = false |
| 201 | rejectVisible.value = false | 301 | rejectVisible.value = false |
| 202 | } | 302 | } |
| 303 | + resetToFirstPage() | ||
| 203 | loadList() | 304 | loadList() |
| 204 | } | 305 | } |
| 205 | 306 | ||
| @@ -228,14 +329,14 @@ async function handleDesignate() { | @@ -228,14 +329,14 @@ async function handleDesignate() { | ||
| 228 | await riderApi.designate(designateOrderId.value, designateRiderId.value) | 329 | await riderApi.designate(designateOrderId.value, designateRiderId.value) |
| 229 | message.success('指派成功') | 330 | message.success('指派成功') |
| 230 | designateVisible.value = false | 331 | designateVisible.value = false |
| 231 | - loadList() | 332 | + await loadList() |
| 232 | } finally { saving.value = false } | 333 | } finally { saving.value = false } |
| 233 | } | 334 | } |
| 234 | 335 | ||
| 235 | async function handleTrans(orderId: number, trans: number) { | 336 | async function handleTrans(orderId: number, trans: number) { |
| 236 | await riderApi.setTrans(orderId, trans) | 337 | await riderApi.setTrans(orderId, trans) |
| 237 | message.success('操作成功') | 338 | message.success('操作成功') |
| 238 | - loadList() | 339 | + await loadList() |
| 239 | } | 340 | } |
| 240 | 341 | ||
| 241 | async function openRefund(record: any) { | 342 | async function openRefund(record: any) { |
| @@ -257,7 +358,7 @@ async function handleRefund(status: number) { | @@ -257,7 +358,7 @@ async function handleRefund(status: number) { | ||
| 257 | message.success('操作成功') | 358 | message.success('操作成功') |
| 258 | refundVisible.value = false | 359 | refundVisible.value = false |
| 259 | rejectVisible.value = false | 360 | rejectVisible.value = false |
| 260 | - loadList() | 361 | + await loadList() |
| 261 | } finally { saving.value = false } | 362 | } finally { saving.value = false } |
| 262 | } | 363 | } |
| 263 | 364 | ||
| @@ -266,3 +367,48 @@ onMounted(async () => { | @@ -266,3 +367,48 @@ onMounted(async () => { | ||
| 266 | await loadList() | 367 | await loadList() |
| 267 | }) | 368 | }) |
| 268 | </script> | 369 | </script> |
| 370 | + | ||
| 371 | +<style scoped> | ||
| 372 | +.order-status-cards { | ||
| 373 | + display: grid; | ||
| 374 | + grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); | ||
| 375 | + gap: 12px; | ||
| 376 | + margin-bottom: 16px; | ||
| 377 | +} | ||
| 378 | + | ||
| 379 | +.order-status-card { | ||
| 380 | + display: flex; | ||
| 381 | + flex-direction: column; | ||
| 382 | + align-items: flex-start; | ||
| 383 | + gap: 8px; | ||
| 384 | + min-height: 88px; | ||
| 385 | + padding: 16px; | ||
| 386 | + border: 1px solid #e5e7eb; | ||
| 387 | + border-radius: 12px; | ||
| 388 | + background: #fff; | ||
| 389 | + cursor: pointer; | ||
| 390 | + transition: all 0.2s ease; | ||
| 391 | +} | ||
| 392 | + | ||
| 393 | +.order-status-card:hover { | ||
| 394 | + border-color: #1677ff; | ||
| 395 | + box-shadow: 0 8px 24px rgba(22, 119, 255, 0.08); | ||
| 396 | +} | ||
| 397 | + | ||
| 398 | +.order-status-card.is-active { | ||
| 399 | + border-color: #1677ff; | ||
| 400 | + background: #f0f7ff; | ||
| 401 | + box-shadow: 0 8px 24px rgba(22, 119, 255, 0.12); | ||
| 402 | +} | ||
| 403 | + | ||
| 404 | +.order-status-card__label { | ||
| 405 | + color: #64748b; | ||
| 406 | + font-size: 14px; | ||
| 407 | +} | ||
| 408 | + | ||
| 409 | +.order-status-card__count { | ||
| 410 | + color: #0f172a; | ||
| 411 | + font-size: 28px; | ||
| 412 | + line-height: 1; | ||
| 413 | +} | ||
| 414 | +</style> |