Commit 47090e96533d7d7f8395b0d4ad1e91c92d27d8e9
1 parent
32f52c2c
refactor: centralize city management logic into composables for cleaner code and reusability
Showing
14 changed files
with
262 additions
and
168 deletions
src/api/index.ts
| @@ -117,6 +117,10 @@ export const riderApi = { | @@ -117,6 +117,10 @@ export const riderApi = { | ||
| 117 | orderList: (params: any) => request.get('/api/admin/rider/order/list', { params }), | 117 | orderList: (params: any) => request.get('/api/admin/rider/order/list', { params }), |
| 118 | // 配送订单列表(外部系统推入的) | 118 | // 配送订单列表(外部系统推入的) |
| 119 | deliveryOrderList: (params: any) => request.get('/api/admin/rider/order/delivery/list', { params }), | 119 | deliveryOrderList: (params: any) => request.get('/api/admin/rider/order/delivery/list', { params }), |
| 120 | + deliveryOrderDetail: (orderId: number) => | ||
| 121 | + request.get('/api/admin/rider/order/delivery/detail', { params: { orderId } }), | ||
| 122 | + deliveryOrderCancel: (orderId: number) => | ||
| 123 | + request.post('/api/admin/rider/order/delivery/cancel', null, { params: { orderId } }), | ||
| 120 | } | 124 | } |
| 121 | 125 | ||
| 122 | export const riderLevelApi = { | 126 | export const riderLevelApi = { |
src/composables/useRoleCityList.ts
0 → 100644
| 1 | +import { computed, ref } from 'vue' | ||
| 2 | +import { storeToRefs } from 'pinia' | ||
| 3 | +import { cityApi } from '@/api' | ||
| 4 | +import { useAuthStore } from '@/stores/auth' | ||
| 5 | + | ||
| 6 | +export type CityOption = { | ||
| 7 | + id: number | ||
| 8 | + name: string | ||
| 9 | + [key: string]: any | ||
| 10 | +} | ||
| 11 | + | ||
| 12 | +export function useRoleCityList() { | ||
| 13 | + const auth = useAuthStore() | ||
| 14 | + const { isAdmin, user } = storeToRefs(auth) | ||
| 15 | + const cityList = ref<CityOption[]>([]) | ||
| 16 | + const managedCityId = computed<number | undefined>(() => user.value?.cityId) | ||
| 17 | + const managedCityName = computed(() => user.value?.cityName || '') | ||
| 18 | + | ||
| 19 | + function buildManagedCityList() { | ||
| 20 | + return managedCityId.value | ||
| 21 | + ? [{ id: managedCityId.value, name: managedCityName.value || `租户#${managedCityId.value}` }] | ||
| 22 | + : [] | ||
| 23 | + } | ||
| 24 | + | ||
| 25 | + async function loadCities() { | ||
| 26 | + if (!isAdmin.value) { | ||
| 27 | + cityList.value = buildManagedCityList() | ||
| 28 | + return | ||
| 29 | + } | ||
| 30 | + const res: any = await cityApi.openList() | ||
| 31 | + cityList.value = Array.isArray(res?.data) ? res.data : [] | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + function getCityName(cityId?: number) { | ||
| 35 | + const city = cityList.value.find(item => item.id === cityId) | ||
| 36 | + return city?.name || (cityId ? `租户#${cityId}` : '-') | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + return { | ||
| 40 | + isAdmin, | ||
| 41 | + managedCityId, | ||
| 42 | + managedCityName, | ||
| 43 | + cityList, | ||
| 44 | + loadCities, | ||
| 45 | + getCityName, | ||
| 46 | + } | ||
| 47 | +} |
src/composables/useRoleSelectedCity.ts
0 → 100644
| 1 | +import { computed, ref } from 'vue' | ||
| 2 | +import { useRoleCityList } from '@/composables/useRoleCityList' | ||
| 3 | + | ||
| 4 | +export function useRoleSelectedCity() { | ||
| 5 | + const { | ||
| 6 | + isAdmin, | ||
| 7 | + managedCityId, | ||
| 8 | + managedCityName, | ||
| 9 | + cityList, | ||
| 10 | + loadCities: loadRoleCities, | ||
| 11 | + getCityName, | ||
| 12 | + } = useRoleCityList() | ||
| 13 | + const selectedCityId = ref<number | undefined>() | ||
| 14 | + | ||
| 15 | + function resolveSelectedCity(initialCityId?: number) { | ||
| 16 | + if (!isAdmin.value) { | ||
| 17 | + selectedCityId.value = managedCityId.value | ||
| 18 | + return | ||
| 19 | + } | ||
| 20 | + if (initialCityId && cityList.value.some(item => item.id === initialCityId)) { | ||
| 21 | + selectedCityId.value = initialCityId | ||
| 22 | + return | ||
| 23 | + } | ||
| 24 | + if (selectedCityId.value && cityList.value.some(item => item.id === selectedCityId.value)) { | ||
| 25 | + return | ||
| 26 | + } | ||
| 27 | + selectedCityId.value = cityList.value[0]?.id | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + async function loadCities(initialCityId?: number) { | ||
| 31 | + await loadRoleCities() | ||
| 32 | + resolveSelectedCity(initialCityId) | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + const currentCityName = computed(() => | ||
| 36 | + selectedCityId.value ? getCityName(selectedCityId.value) : managedCityName.value || '' | ||
| 37 | + ) | ||
| 38 | + | ||
| 39 | + return { | ||
| 40 | + isAdmin, | ||
| 41 | + cityList, | ||
| 42 | + selectedCityId, | ||
| 43 | + currentCityName, | ||
| 44 | + loadCities, | ||
| 45 | + } | ||
| 46 | +} |
src/layouts/MainLayout.vue
| @@ -88,7 +88,7 @@ | @@ -88,7 +88,7 @@ | ||
| 88 | <span class="profile-avatar">{{ avatarText }}</span> | 88 | <span class="profile-avatar">{{ avatarText }}</span> |
| 89 | <span class="profile-copy"> | 89 | <span class="profile-copy"> |
| 90 | <strong>{{ auth.user?.userNickname || '管理员' }}</strong> | 90 | <strong>{{ auth.user?.userNickname || '管理员' }}</strong> |
| 91 | - <small>{{ auth.user?.role === 'admin' ? '超级管理员' : '分站管理员' }}</small> | 91 | + <small>{{ auth.isAdmin ? '超级管理员' : '分站管理员' }}</small> |
| 92 | </span> | 92 | </span> |
| 93 | <down-outlined /> | 93 | <down-outlined /> |
| 94 | </a-button> | 94 | </a-button> |
src/views/config/FeePlanList.vue
| @@ -424,11 +424,11 @@ | @@ -424,11 +424,11 @@ | ||
| 424 | </template> | 424 | </template> |
| 425 | 425 | ||
| 426 | <script setup lang="ts"> | 426 | <script setup lang="ts"> |
| 427 | -import { computed, onMounted, reactive, ref } from 'vue' | 427 | +import { onMounted, reactive, ref } from 'vue' |
| 428 | import { useRoute } from 'vue-router' | 428 | import { useRoute } from 'vue-router' |
| 429 | import { message } from 'ant-design-vue' | 429 | import { message } from 'ant-design-vue' |
| 430 | -import { adminFeePlanApi, cityApi } from '@/api' | ||
| 431 | -import { useAuthStore } from '@/stores/auth' | 430 | +import { adminFeePlanApi } from '@/api' |
| 431 | +import { useRoleSelectedCity } from '@/composables/useRoleSelectedCity' | ||
| 432 | 432 | ||
| 433 | type TimePeriodForm = { | 433 | type TimePeriodForm = { |
| 434 | startText: string | 434 | startText: string |
| @@ -450,12 +450,13 @@ type PieceRuleForm = { | @@ -450,12 +450,13 @@ type PieceRuleForm = { | ||
| 450 | } | 450 | } |
| 451 | 451 | ||
| 452 | const route = useRoute() | 452 | const route = useRoute() |
| 453 | -const auth = useAuthStore() | ||
| 454 | -const isAdmin = computed(() => auth.user?.role === 'admin') | ||
| 455 | -const managedCityId = computed<number | undefined>(() => auth.user?.cityId) | ||
| 456 | -const cityList = ref<any[]>([]) | ||
| 457 | -const selectedCityId = ref<number | undefined>() | ||
| 458 | -const currentCityName = computed(() => cityList.value.find(item => item.id === selectedCityId.value)?.name || auth.user?.cityName || '') | 453 | +const { |
| 454 | + isAdmin, | ||
| 455 | + cityList, | ||
| 456 | + selectedCityId, | ||
| 457 | + currentCityName, | ||
| 458 | + loadCities, | ||
| 459 | +} = useRoleSelectedCity() | ||
| 459 | 460 | ||
| 460 | const config = ref<any>(null) | 461 | const config = ref<any>(null) |
| 461 | const planList = ref<any[]>([]) | 462 | const planList = ref<any[]>([]) |
| @@ -478,22 +479,9 @@ const previewForm = reactive({ | @@ -478,22 +479,9 @@ const previewForm = reactive({ | ||
| 478 | serviceTime: '', | 479 | serviceTime: '', |
| 479 | }) | 480 | }) |
| 480 | 481 | ||
| 481 | -async function loadCities() { | ||
| 482 | - if (isAdmin.value) { | ||
| 483 | - const res: any = await cityApi.openList() | ||
| 484 | - cityList.value = Array.isArray(res?.data) ? res.data : [] | ||
| 485 | - const queryCityId = Number(route.query.cityId || 0) || undefined | ||
| 486 | - if (queryCityId && cityList.value.some(item => item.id === queryCityId)) { | ||
| 487 | - selectedCityId.value = queryCityId | ||
| 488 | - } | ||
| 489 | - if (!selectedCityId.value && cityList.value.length) { | ||
| 490 | - selectedCityId.value = cityList.value[0].id | ||
| 491 | - } | ||
| 492 | - } else { | ||
| 493 | - selectedCityId.value = managedCityId.value | ||
| 494 | - cityList.value = selectedCityId.value ? [{ id: selectedCityId.value, name: auth.user?.cityName || `租户#${selectedCityId.value}` }] : [] | ||
| 495 | - } | ||
| 496 | - | 482 | +async function loadFeePlanCities() { |
| 483 | + const queryCityId = Number(route.query.cityId || 0) || undefined | ||
| 484 | + await loadCities(queryCityId) | ||
| 497 | if (selectedCityId.value) { | 485 | if (selectedCityId.value) { |
| 498 | await loadPlanList(selectedCityId.value) | 486 | await loadPlanList(selectedCityId.value) |
| 499 | } | 487 | } |
| @@ -833,7 +821,7 @@ function deepClone<T>(value: T): T { | @@ -833,7 +821,7 @@ function deepClone<T>(value: T): T { | ||
| 833 | return JSON.parse(JSON.stringify(value)) | 821 | return JSON.parse(JSON.stringify(value)) |
| 834 | } | 822 | } |
| 835 | 823 | ||
| 836 | -onMounted(loadCities) | 824 | +onMounted(loadFeePlanCities) |
| 837 | </script> | 825 | </script> |
| 838 | 826 | ||
| 839 | <style scoped> | 827 | <style scoped> |
src/views/delivery/DeliveryOrderList.vue
| @@ -3,6 +3,10 @@ | @@ -3,6 +3,10 @@ | ||
| 3 | <a-card title="配送订单" :bordered="false" class="list-table-card"> | 3 | <a-card title="配送订单" :bordered="false" class="list-table-card"> |
| 4 | <div class="list-toolbar"> | 4 | <div class="list-toolbar"> |
| 5 | <div class="list-toolbar-left"> | 5 | <div class="list-toolbar-left"> |
| 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> | ||
| 8 | + </a-select> | ||
| 9 | + <a-input v-if="isAdmin" v-model:value="filterAppKey" placeholder="接入方 AppKey" class="list-search appkey-search" @pressEnter="loadList" /> | ||
| 6 | <a-select v-model:value="filterStatus" placeholder="状态" allowClear class="list-filter" @change="loadList"> | 10 | <a-select v-model:value="filterStatus" placeholder="状态" allowClear class="list-filter" @change="loadList"> |
| 7 | <a-select-option :value="2">待接单</a-select-option> | 11 | <a-select-option :value="2">待接单</a-select-option> |
| 8 | <a-select-option :value="3">已接单</a-select-option> | 12 | <a-select-option :value="3">已接单</a-select-option> |
| @@ -12,33 +16,37 @@ | @@ -12,33 +16,37 @@ | ||
| 12 | </a-select> | 16 | </a-select> |
| 13 | <a-input-search v-model:value="keyword" placeholder="外部订单号" @search="loadList" class="list-search" /> | 17 | <a-input-search v-model:value="keyword" placeholder="外部订单号" @search="loadList" class="list-search" /> |
| 14 | </div> | 18 | </div> |
| 15 | - <div class="list-toolbar-right"> | ||
| 16 | - <a-button type="primary" @click="queryByNo" :loading="querying">查询</a-button> | ||
| 17 | - </div> | ||
| 18 | </div> | 19 | </div> |
| 19 | <a-table :dataSource="list" :columns="columns" :loading="loading" rowKey="id" :pagination="false"> | 20 | <a-table :dataSource="list" :columns="columns" :loading="loading" rowKey="id" :pagination="false"> |
| 20 | <template #bodyCell="{ column, record }"> | 21 | <template #bodyCell="{ column, record }"> |
| 22 | + <template v-if="column.key === 'cityName'"> | ||
| 23 | + {{ getCityName(record.cityId) }} | ||
| 24 | + </template> | ||
| 21 | <template v-if="column.key === 'status'"> | 25 | <template v-if="column.key === 'status'"> |
| 22 | <a-tag :color="statusColor[record.status]">{{ statusMap[record.status] }}</a-tag> | 26 | <a-tag :color="statusColor[record.status]">{{ statusMap[record.status] }}</a-tag> |
| 23 | </template> | 27 | </template> |
| 24 | <template v-if="column.key === 'action'"> | 28 | <template v-if="column.key === 'action'"> |
| 25 | - <a-popconfirm v-if="record.status === 2" title="确认取消该配送订单?" @confirm="cancelOrder(record)"> | ||
| 26 | - <a style="color:red">取消</a> | ||
| 27 | - </a-popconfirm> | ||
| 28 | - <span v-else>-</span> | 29 | + <a-space> |
| 30 | + <a @click="openDetail(record)">详情</a> | ||
| 31 | + <a-popconfirm v-if="record.status === 2 && canOperate" title="确认取消该配送订单?" @confirm="cancelOrder(record)"> | ||
| 32 | + <a style="color:red">取消</a> | ||
| 33 | + </a-popconfirm> | ||
| 34 | + <span v-else-if="isAdmin && record.status === 2 && !canOperate">选择租户后可取消</span> | ||
| 35 | + </a-space> | ||
| 29 | </template> | 36 | </template> |
| 30 | </template> | 37 | </template> |
| 31 | </a-table> | 38 | </a-table> |
| 32 | </a-card> | 39 | </a-card> |
| 33 | 40 | ||
| 34 | - <a-modal v-model:open="queryVisible" title="配送订单详情" :footer="null"> | 41 | + <a-modal v-model:open="queryVisible" title="配送订单详情" :footer="null" :confirmLoading="detailLoading"> |
| 35 | <div v-if="queryResult" class="soft-page-stack"> | 42 | <div v-if="queryResult" class="soft-page-stack"> |
| 36 | <div class="soft-note-card"> | 43 | <div class="soft-note-card"> |
| 37 | - <strong>订单查询结果</strong> | ||
| 38 | - <p>这里展示开放平台配送单的核心状态和计费结果,适合按外部订单号快速核对。</p> | 44 | + <strong>配送订单详情</strong> |
| 45 | + <p>这里展示后台可查看的配送单核心状态和计费结果,便于运营快速核对。</p> | ||
| 39 | </div> | 46 | </div> |
| 40 | <a-descriptions :column="1" bordered size="small"> | 47 | <a-descriptions :column="1" bordered size="small"> |
| 41 | <a-descriptions-item label="配送订单ID">{{ queryResult.deliveryOrderId }}</a-descriptions-item> | 48 | <a-descriptions-item label="配送订单ID">{{ queryResult.deliveryOrderId }}</a-descriptions-item> |
| 49 | + <a-descriptions-item label="配送订单号">{{ queryResult.orderNo }}</a-descriptions-item> | ||
| 42 | <a-descriptions-item label="外部订单号">{{ queryResult.outOrderNo }}</a-descriptions-item> | 50 | <a-descriptions-item label="外部订单号">{{ queryResult.outOrderNo }}</a-descriptions-item> |
| 43 | <a-descriptions-item label="状态">{{ statusMap[queryResult.status] }}</a-descriptions-item> | 51 | <a-descriptions-item label="状态">{{ statusMap[queryResult.status] }}</a-descriptions-item> |
| 44 | <a-descriptions-item label="配送费">¥{{ queryResult.totalFee }}</a-descriptions-item> | 52 | <a-descriptions-item label="配送费">¥{{ queryResult.totalFee }}</a-descriptions-item> |
| @@ -51,17 +59,22 @@ | @@ -51,17 +59,22 @@ | ||
| 51 | </template> | 59 | </template> |
| 52 | 60 | ||
| 53 | <script setup lang="ts"> | 61 | <script setup lang="ts"> |
| 54 | -import { ref, onMounted } from 'vue' | 62 | +import { computed, ref, onMounted } from 'vue' |
| 55 | import { message } from 'ant-design-vue' | 63 | import { message } from 'ant-design-vue' |
| 56 | -import { deliveryOrderApi, riderApi } from '@/api' | 64 | +import { riderApi } from '@/api' |
| 65 | +import { useRoleCityList } from '@/composables/useRoleCityList' | ||
| 57 | 66 | ||
| 58 | const loading = ref(false) | 67 | const loading = ref(false) |
| 59 | -const querying = ref(false) | 68 | +const detailLoading = ref(false) |
| 60 | const list = ref<any[]>([]) | 69 | const list = ref<any[]>([]) |
| 70 | +const filterCityId = ref<number | undefined>() | ||
| 71 | +const filterAppKey = ref('') | ||
| 61 | const filterStatus = ref<number | undefined>() | 72 | const filterStatus = ref<number | undefined>() |
| 62 | const keyword = ref('') | 73 | const keyword = ref('') |
| 63 | const queryVisible = ref(false) | 74 | const queryVisible = ref(false) |
| 64 | const queryResult = ref<any>(null) | 75 | const queryResult = ref<any>(null) |
| 76 | +const { isAdmin, cityList, loadCities, getCityName } = useRoleCityList() | ||
| 77 | +const canOperate = computed(() => !isAdmin.value || !!filterCityId.value) | ||
| 65 | 78 | ||
| 66 | const statusMap: Record<number, string> = { | 79 | const statusMap: Record<number, string> = { |
| 67 | 2: '待接单', 3: '已接单', 4: '配送中', 6: '已完成', 7: '退款申请', | 80 | 2: '待接单', 3: '已接单', 4: '配送中', 6: '已完成', 7: '退款申请', |
| @@ -72,20 +85,31 @@ const statusColor: Record<number, string> = { | @@ -72,20 +85,31 @@ const statusColor: Record<number, string> = { | ||
| 72 | 7: 'orange', 8: 'green', 9: 'red', 10: 'red' | 85 | 7: 'orange', 8: 'green', 9: 'red', 10: 'red' |
| 73 | } | 86 | } |
| 74 | 87 | ||
| 75 | -const columns = [ | ||
| 76 | - { title: 'ID', dataIndex: 'id', width: 80 }, | ||
| 77 | - { title: '外部订单号', dataIndex: 'outOrderNo' }, | ||
| 78 | - { title: '接入方', dataIndex: 'appKey', ellipsis: true }, | ||
| 79 | - { title: '收件人', dataIndex: 'recipName' }, | ||
| 80 | - { title: '配送费', dataIndex: 'moneyDelivery' }, | ||
| 81 | - { title: '状态', key: 'status' }, | ||
| 82 | - { title: '操作', key: 'action' }, | ||
| 83 | -] | 88 | +const columns = computed(() => { |
| 89 | + const base = [ | ||
| 90 | + { title: 'ID', dataIndex: 'id', width: 80 }, | ||
| 91 | + { title: '外部订单号', dataIndex: 'outOrderNo' }, | ||
| 92 | + { title: '接入方', dataIndex: 'appKey', ellipsis: true }, | ||
| 93 | + { title: '收件人', dataIndex: 'recipName' }, | ||
| 94 | + { title: '配送费', dataIndex: 'moneyDelivery' }, | ||
| 95 | + { title: '状态', key: 'status' }, | ||
| 96 | + { title: '操作', key: 'action' }, | ||
| 97 | + ] | ||
| 98 | + if (!isAdmin.value) { | ||
| 99 | + return base | ||
| 100 | + } | ||
| 101 | + return [ | ||
| 102 | + { title: '租户', key: 'cityName' }, | ||
| 103 | + ...base, | ||
| 104 | + ] | ||
| 105 | +}) | ||
| 84 | 106 | ||
| 85 | async function loadList() { | 107 | async function loadList() { |
| 86 | loading.value = true | 108 | loading.value = true |
| 87 | try { | 109 | try { |
| 88 | const res: any = await riderApi.deliveryOrderList({ | 110 | const res: any = await riderApi.deliveryOrderList({ |
| 111 | + cityId: filterCityId.value, | ||
| 112 | + appKey: filterAppKey.value || undefined, | ||
| 89 | status: filterStatus.value, | 113 | status: filterStatus.value, |
| 90 | outOrderNo: keyword.value || undefined, | 114 | outOrderNo: keyword.value || undefined, |
| 91 | page: 1 | 115 | page: 1 |
| @@ -94,21 +118,36 @@ async function loadList() { | @@ -94,21 +118,36 @@ async function loadList() { | ||
| 94 | } finally { loading.value = false } | 118 | } finally { loading.value = false } |
| 95 | } | 119 | } |
| 96 | 120 | ||
| 97 | -async function queryByNo() { | ||
| 98 | - if (!keyword.value) { message.warning('请输入外部订单号'); return } | ||
| 99 | - querying.value = true | 121 | +function handleAdminCityChange() { |
| 122 | + if (!filterCityId.value) { | ||
| 123 | + queryVisible.value = false | ||
| 124 | + queryResult.value = null | ||
| 125 | + } | ||
| 126 | + loadList() | ||
| 127 | +} | ||
| 128 | + | ||
| 129 | +async function openDetail(record: any) { | ||
| 130 | + detailLoading.value = true | ||
| 131 | + queryResult.value = null | ||
| 132 | + queryVisible.value = true | ||
| 100 | try { | 133 | try { |
| 101 | - const res: any = await deliveryOrderApi.query(keyword.value) | 134 | + const res: any = await riderApi.deliveryOrderDetail(record.id) |
| 102 | queryResult.value = res.data | 135 | queryResult.value = res.data |
| 103 | - queryVisible.value = true | ||
| 104 | - } finally { querying.value = false } | 136 | + } finally { detailLoading.value = false } |
| 105 | } | 137 | } |
| 106 | 138 | ||
| 107 | async function cancelOrder(record: any) { | 139 | async function cancelOrder(record: any) { |
| 108 | - await deliveryOrderApi.cancel(record.outOrderNo) | 140 | + await riderApi.deliveryOrderCancel(record.id) |
| 109 | message.success('取消成功') | 141 | message.success('取消成功') |
| 142 | + if (queryVisible.value && queryResult.value?.deliveryOrderId === record.id) { | ||
| 143 | + queryVisible.value = false | ||
| 144 | + queryResult.value = null | ||
| 145 | + } | ||
| 110 | loadList() | 146 | loadList() |
| 111 | } | 147 | } |
| 112 | 148 | ||
| 113 | -onMounted(loadList) | 149 | +onMounted(async () => { |
| 150 | + await loadCities() | ||
| 151 | + await loadList() | ||
| 152 | +}) | ||
| 114 | </script> | 153 | </script> |
src/views/dispatch/DispatchRuleList.vue
| @@ -237,15 +237,16 @@ | @@ -237,15 +237,16 @@ | ||
| 237 | <script setup lang="ts"> | 237 | <script setup lang="ts"> |
| 238 | import { computed, onMounted, reactive, ref } from 'vue' | 238 | import { computed, onMounted, reactive, ref } from 'vue' |
| 239 | import { message } from 'ant-design-vue' | 239 | import { message } from 'ant-design-vue' |
| 240 | -import { cityApi, dispatchRuleApi } from '@/api' | ||
| 241 | -import { useAuthStore } from '@/stores/auth' | ||
| 242 | - | ||
| 243 | -const auth = useAuthStore() | ||
| 244 | -const isAdmin = computed(() => auth.user?.role === 'admin') | ||
| 245 | -const managedCityId = computed<number | undefined>(() => auth.user?.cityId) | ||
| 246 | -const cityList = ref<any[]>([]) | ||
| 247 | -const selectedCityId = ref<number | undefined>() | ||
| 248 | -const currentCityName = computed(() => cityList.value.find(item => item.id === selectedCityId.value)?.name || auth.user?.cityName || '') | 240 | +import { dispatchRuleApi } from '@/api' |
| 241 | +import { useRoleSelectedCity } from '@/composables/useRoleSelectedCity' | ||
| 242 | + | ||
| 243 | +const { | ||
| 244 | + isAdmin, | ||
| 245 | + cityList, | ||
| 246 | + selectedCityId, | ||
| 247 | + currentCityName, | ||
| 248 | + loadCities, | ||
| 249 | +} = useRoleSelectedCity() | ||
| 249 | const templateList = ref<any[]>([]) | 250 | const templateList = ref<any[]>([]) |
| 250 | const selectedTemplateId = ref<number | null>(null) | 251 | const selectedTemplateId = ref<number | null>(null) |
| 251 | const loadingTemplates = ref(false) | 252 | const loadingTemplates = ref(false) |
| @@ -291,18 +292,8 @@ const autoDispatchChecked = computed({ | @@ -291,18 +292,8 @@ const autoDispatchChecked = computed({ | ||
| 291 | 292 | ||
| 292 | const editorVisible = computed(() => !!form.id || creatingNew.value) | 293 | const editorVisible = computed(() => !!form.id || creatingNew.value) |
| 293 | 294 | ||
| 294 | -async function loadCities() { | ||
| 295 | - if (isAdmin.value) { | ||
| 296 | - const res: any = await cityApi.openList() | ||
| 297 | - cityList.value = res.data || [] | ||
| 298 | - if (!selectedCityId.value && cityList.value.length) { | ||
| 299 | - selectedCityId.value = cityList.value[0].id | ||
| 300 | - } | ||
| 301 | - } else { | ||
| 302 | - selectedCityId.value = managedCityId.value | ||
| 303 | - cityList.value = selectedCityId.value ? [{ id: selectedCityId.value, name: auth.user?.cityName || `租户#${selectedCityId.value}` }] : [] | ||
| 304 | - } | ||
| 305 | - | 295 | +async function loadDispatchCities() { |
| 296 | + await loadCities() | ||
| 306 | if (selectedCityId.value) { | 297 | if (selectedCityId.value) { |
| 307 | await loadTemplates() | 298 | await loadTemplates() |
| 308 | } | 299 | } |
| @@ -497,7 +488,7 @@ function resetForm() { | @@ -497,7 +488,7 @@ function resetForm() { | ||
| 497 | selectedTemplateId.value = null | 488 | selectedTemplateId.value = null |
| 498 | } | 489 | } |
| 499 | 490 | ||
| 500 | -onMounted(loadCities) | 491 | +onMounted(loadDispatchCities) |
| 501 | </script> | 492 | </script> |
| 502 | 493 | ||
| 503 | <style scoped> | 494 | <style scoped> |
src/views/merchant/StoreList.vue
| @@ -107,12 +107,12 @@ | @@ -107,12 +107,12 @@ | ||
| 107 | <script setup lang="ts"> | 107 | <script setup lang="ts"> |
| 108 | import { ref, reactive, onMounted } from 'vue' | 108 | import { ref, reactive, onMounted } from 'vue' |
| 109 | import { message } from 'ant-design-vue' | 109 | import { message } from 'ant-design-vue' |
| 110 | -import { merchantApi, cityApi } from '@/api' | 110 | +import { merchantApi } from '@/api' |
| 111 | +import { useRoleCityList } from '@/composables/useRoleCityList' | ||
| 111 | 112 | ||
| 112 | const loading = ref(false) | 113 | const loading = ref(false) |
| 113 | const saving = ref(false) | 114 | const saving = ref(false) |
| 114 | const list = ref<any[]>([]) | 115 | const list = ref<any[]>([]) |
| 115 | -const cityList = ref<any[]>([]) | ||
| 116 | const keyword = ref('') | 116 | const keyword = ref('') |
| 117 | const filterCityId = ref<number | undefined>() | 117 | const filterCityId = ref<number | undefined>() |
| 118 | const modalVisible = ref(false) | 118 | const modalVisible = ref(false) |
| @@ -121,6 +121,7 @@ const editingId = ref<number | null>(null) | @@ -121,6 +121,7 @@ const editingId = ref<number | null>(null) | ||
| 121 | const currentStoreId = ref(0) | 121 | const currentStoreId = ref(0) |
| 122 | const form = reactive<any>({ name: '', cityId: undefined, address: '', lng: '', lat: '', shippingType: 1, automaticOrder: 0, accountMobile: '', about: '', outStoreId: '' }) | 122 | const form = reactive<any>({ name: '', cityId: undefined, address: '', lng: '', lat: '', shippingType: 1, automaticOrder: 0, accountMobile: '', about: '', outStoreId: '' }) |
| 123 | const feeForm = reactive({ freeShipping: 0, upToSend: 0 }) | 123 | const feeForm = reactive({ freeShipping: 0, upToSend: 0 }) |
| 124 | +const { cityList, loadCities, getCityName } = useRoleCityList() | ||
| 124 | 125 | ||
| 125 | const columns = [ | 126 | const columns = [ |
| 126 | { title: 'ID', dataIndex: 'id', width: 80 }, | 127 | { title: 'ID', dataIndex: 'id', width: 80 }, |
| @@ -142,16 +143,6 @@ async function loadList() { | @@ -142,16 +143,6 @@ async function loadList() { | ||
| 142 | } finally { loading.value = false } | 143 | } finally { loading.value = false } |
| 143 | } | 144 | } |
| 144 | 145 | ||
| 145 | -async function loadCities() { | ||
| 146 | - const res: any = await cityApi.openList() | ||
| 147 | - cityList.value = res.data | ||
| 148 | -} | ||
| 149 | - | ||
| 150 | -function getCityName(cityId?: number) { | ||
| 151 | - const city = cityList.value.find(item => item.id === cityId) | ||
| 152 | - return city?.name || (cityId ? `租户#${cityId}` : '-') | ||
| 153 | -} | ||
| 154 | - | ||
| 155 | function openAdd() { | 146 | function openAdd() { |
| 156 | editingId.value = null | 147 | editingId.value = null |
| 157 | Object.assign(form, { name: '', cityId: undefined, address: '', lng: '', lat: '', shippingType: 1, automaticOrder: 0, accountMobile: '', about: '', outStoreId: '' }) | 148 | Object.assign(form, { name: '', cityId: undefined, address: '', lng: '', lat: '', shippingType: 1, automaticOrder: 0, accountMobile: '', about: '', outStoreId: '' }) |
src/views/open/OpenAppList.vue
| @@ -103,19 +103,20 @@ | @@ -103,19 +103,20 @@ | ||
| 103 | <script setup lang="ts"> | 103 | <script setup lang="ts"> |
| 104 | import { ref, reactive, onMounted } from 'vue' | 104 | import { ref, reactive, onMounted } from 'vue' |
| 105 | import { message, Modal } from 'ant-design-vue' | 105 | import { message, Modal } from 'ant-design-vue' |
| 106 | -import { openApi, cityApi } from '@/api' | 106 | +import { openApi } from '@/api' |
| 107 | +import { useRoleCityList } from '@/composables/useRoleCityList' | ||
| 107 | 108 | ||
| 108 | const loading = ref(false) | 109 | const loading = ref(false) |
| 109 | const saving = ref(false) | 110 | const saving = ref(false) |
| 110 | const list = ref<any[]>([]) | 111 | const list = ref<any[]>([]) |
| 111 | const logs = ref<any[]>([]) | 112 | const logs = ref<any[]>([]) |
| 112 | -const cityList = ref<any[]>([]) | ||
| 113 | const addVisible = ref(false) | 113 | const addVisible = ref(false) |
| 114 | const webhookVisible = ref(false) | 114 | const webhookVisible = ref(false) |
| 115 | const logsVisible = ref(false) | 115 | const logsVisible = ref(false) |
| 116 | const currentAppId = ref(0) | 116 | const currentAppId = ref(0) |
| 117 | const addForm = reactive({ appName: '', cityId: undefined as number | undefined, remark: '' }) | 117 | const addForm = reactive({ appName: '', cityId: undefined as number | undefined, remark: '' }) |
| 118 | const webhookForm = reactive({ webhookUrl: '', webhookEvents: '' }) | 118 | const webhookForm = reactive({ webhookUrl: '', webhookEvents: '' }) |
| 119 | +const { cityList, loadCities, getCityName } = useRoleCityList() | ||
| 119 | 120 | ||
| 120 | const columns = [ | 121 | const columns = [ |
| 121 | { title: 'ID', dataIndex: 'id', width: 80 }, | 122 | { title: 'ID', dataIndex: 'id', width: 80 }, |
| @@ -145,16 +146,6 @@ async function loadList() { | @@ -145,16 +146,6 @@ async function loadList() { | ||
| 145 | } finally { loading.value = false } | 146 | } finally { loading.value = false } |
| 146 | } | 147 | } |
| 147 | 148 | ||
| 148 | -async function loadCities() { | ||
| 149 | - const res: any = await cityApi.openList() | ||
| 150 | - cityList.value = res.data | ||
| 151 | -} | ||
| 152 | - | ||
| 153 | -function getCityName(cityId?: number) { | ||
| 154 | - const city = cityList.value.find(item => item.id === cityId) | ||
| 155 | - return city?.name || (cityId ? `租户#${cityId}` : '-') | ||
| 156 | -} | ||
| 157 | - | ||
| 158 | function openAdd() { | 149 | function openAdd() { |
| 159 | Object.assign(addForm, { appName: '', cityId: undefined, remark: '' }) | 150 | Object.assign(addForm, { appName: '', cityId: undefined, remark: '' }) |
| 160 | addVisible.value = true | 151 | addVisible.value = true |
src/views/open/OpenMockDelivery.vue
| @@ -270,7 +270,8 @@ | @@ -270,7 +270,8 @@ | ||
| 270 | <script setup lang="ts"> | 270 | <script setup lang="ts"> |
| 271 | import { computed, onMounted, reactive, ref, watch } from 'vue' | 271 | import { computed, onMounted, reactive, ref, watch } from 'vue' |
| 272 | import { message } from 'ant-design-vue' | 272 | import { message } from 'ant-design-vue' |
| 273 | -import { cityApi, deliveryApi, openApi } from '@/api' | 273 | +import { deliveryApi, openApi } from '@/api' |
| 274 | +import { useRoleCityList } from '@/composables/useRoleCityList' | ||
| 274 | 275 | ||
| 275 | type OpenAppItem = { | 276 | type OpenAppItem = { |
| 276 | id: number | 277 | id: number |
| @@ -288,11 +289,11 @@ type DeliveryItem = { | @@ -288,11 +289,11 @@ type DeliveryItem = { | ||
| 288 | } | 289 | } |
| 289 | 290 | ||
| 290 | const appList = ref<OpenAppItem[]>([]) | 291 | const appList = ref<OpenAppItem[]>([]) |
| 291 | -const cityList = ref<any[]>([]) | ||
| 292 | const saving = ref(false) | 292 | const saving = ref(false) |
| 293 | const calcLoading = ref(false) | 293 | const calcLoading = ref(false) |
| 294 | const feeResult = ref<any>(null) | 294 | const feeResult = ref<any>(null) |
| 295 | const result = ref<any>(null) | 295 | const result = ref<any>(null) |
| 296 | +const { loadCities, getCityName } = useRoleCityList() | ||
| 296 | 297 | ||
| 297 | const statusMap: Record<number, string> = { | 298 | const statusMap: Record<number, string> = { |
| 298 | 2: '待接单', | 299 | 2: '待接单', |
| @@ -332,10 +333,7 @@ function createDefaultForm() { | @@ -332,10 +333,7 @@ function createDefaultForm() { | ||
| 332 | const form = reactive(createDefaultForm()) | 333 | const form = reactive(createDefaultForm()) |
| 333 | 334 | ||
| 334 | const selectedApp = computed(() => appList.value.find(item => item.id === form.appId)) | 335 | const selectedApp = computed(() => appList.value.find(item => item.id === form.appId)) |
| 335 | -const selectedTenantName = computed(() => { | ||
| 336 | - const city = cityList.value.find(item => item.id === selectedApp.value?.cityId) | ||
| 337 | - return city?.name || '' | ||
| 338 | -}) | 336 | +const selectedTenantName = computed(() => getCityName(selectedApp.value?.cityId)) |
| 339 | 337 | ||
| 340 | function generateOutOrderNo() { | 338 | function generateOutOrderNo() { |
| 341 | return `MOCK${Date.now()}` | 339 | return `MOCK${Date.now()}` |
| @@ -451,11 +449,6 @@ async function loadApps() { | @@ -451,11 +449,6 @@ async function loadApps() { | ||
| 451 | appList.value = Array.isArray(res?.data) ? res.data.filter((item: OpenAppItem) => item.status === 1) : [] | 449 | appList.value = Array.isArray(res?.data) ? res.data.filter((item: OpenAppItem) => item.status === 1) : [] |
| 452 | } | 450 | } |
| 453 | 451 | ||
| 454 | -async function loadCities() { | ||
| 455 | - const res: any = await cityApi.openList() | ||
| 456 | - cityList.value = Array.isArray(res?.data) ? res.data : [] | ||
| 457 | -} | ||
| 458 | - | ||
| 459 | async function handleSubmit() { | 452 | async function handleSubmit() { |
| 460 | if (!form.appId) { | 453 | if (!form.appId) { |
| 461 | message.error('请选择开放应用') | 454 | message.error('请选择开放应用') |
src/views/order/OrderList.vue
| @@ -3,6 +3,9 @@ | @@ -3,6 +3,9 @@ | ||
| 3 | <a-card title="订单管理" :bordered="false" class="list-table-card"> | 3 | <a-card title="订单管理" :bordered="false" class="list-table-card"> |
| 4 | <div class="list-toolbar"> | 4 | <div class="list-toolbar"> |
| 5 | <div class="list-toolbar-left"> | 5 | <div class="list-toolbar-left"> |
| 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> | ||
| 8 | + </a-select> | ||
| 6 | <a-select v-model:value="filterStatus" placeholder="订单状态" allowClear class="list-filter" @change="loadList"> | 9 | <a-select v-model:value="filterStatus" placeholder="订单状态" allowClear class="list-filter" @change="loadList"> |
| 7 | <a-select-option :value="2">已支付</a-select-option> | 10 | <a-select-option :value="2">已支付</a-select-option> |
| 8 | <a-select-option :value="3">已接单</a-select-option> | 11 | <a-select-option :value="3">已接单</a-select-option> |
| @@ -21,6 +24,9 @@ | @@ -21,6 +24,9 @@ | ||
| 21 | </div> | 24 | </div> |
| 22 | <a-table :dataSource="list" :columns="columns" :loading="loading" rowKey="id" :pagination="false"> | 25 | <a-table :dataSource="list" :columns="columns" :loading="loading" rowKey="id" :pagination="false"> |
| 23 | <template #bodyCell="{ column, record }"> | 26 | <template #bodyCell="{ column, record }"> |
| 27 | + <template v-if="column.key === 'cityName'"> | ||
| 28 | + {{ cityList.find(item => item.id === record.cityId)?.name || `租户#${record.cityId}` }} | ||
| 29 | + </template> | ||
| 24 | <template v-if="column.key === 'status'"> | 30 | <template v-if="column.key === 'status'"> |
| 25 | <a-tag :color="statusColor[record.status]">{{ statusMap[record.status] }}</a-tag> | 31 | <a-tag :color="statusColor[record.status]">{{ statusMap[record.status] }}</a-tag> |
| 26 | </template> | 32 | </template> |
| @@ -32,8 +38,8 @@ | @@ -32,8 +38,8 @@ | ||
| 32 | </template> | 38 | </template> |
| 33 | <template v-if="column.key === 'action'"> | 39 | <template v-if="column.key === 'action'"> |
| 34 | <a-space> | 40 | <a-space> |
| 35 | - <a @click="openDesignate(record)" v-if="record.status === 2">指派骑手</a> | ||
| 36 | - <template v-if="record.isTrans === 2 && record.status === 4"> | 41 | + <a @click="openDesignate(record)" v-if="record.status === 2 && canOperate">指派骑手</a> |
| 42 | + <template v-if="record.isTrans === 2 && record.status === 4 && canOperate"> | ||
| 37 | <a-popconfirm title="通过转单申请?" @confirm="handleTrans(record.id, 1)"> | 43 | <a-popconfirm title="通过转单申请?" @confirm="handleTrans(record.id, 1)"> |
| 38 | <a style="color:green">通过转单</a> | 44 | <a style="color:green">通过转单</a> |
| 39 | </a-popconfirm> | 45 | </a-popconfirm> |
| @@ -41,7 +47,8 @@ | @@ -41,7 +47,8 @@ | ||
| 41 | <a style="color:red">拒绝转单</a> | 47 | <a style="color:red">拒绝转单</a> |
| 42 | </a-popconfirm> | 48 | </a-popconfirm> |
| 43 | </template> | 49 | </template> |
| 44 | - <a v-if="record.status === 7" @click="openRefund(record)">查看退款</a> | 50 | + <a v-if="record.status === 7 && canOperate" @click="openRefund(record)">查看退款</a> |
| 51 | + <span v-if="isAdmin && !canOperate">选择租户后可操作</span> | ||
| 45 | </a-space> | 52 | </a-space> |
| 46 | </template> | 53 | </template> |
| 47 | </template> | 54 | </template> |
| @@ -54,6 +61,7 @@ | @@ -54,6 +61,7 @@ | ||
| 54 | <strong>指派说明</strong> | 61 | <strong>指派说明</strong> |
| 55 | <p>这里只展示当前订单可指派的骑手候选,列表中会带出手机号和在线/休息状态,避免只能靠 ID 操作。</p> | 62 | <p>这里只展示当前订单可指派的骑手候选,列表中会带出手机号和在线/休息状态,避免只能靠 ID 操作。</p> |
| 56 | </div> | 63 | </div> |
| 64 | + <a-alert v-if="isAdmin" type="info" show-icon message="平台管理员当前正在所选租户上下文中操作。" /> | ||
| 57 | <a-form layout="vertical"> | 65 | <a-form layout="vertical"> |
| 58 | <a-form-item label="选择骑手"> | 66 | <a-form-item label="选择骑手"> |
| 59 | <a-select | 67 | <a-select |
| @@ -119,13 +127,15 @@ | @@ -119,13 +127,15 @@ | ||
| 119 | </template> | 127 | </template> |
| 120 | 128 | ||
| 121 | <script setup lang="ts"> | 129 | <script setup lang="ts"> |
| 122 | -import { ref, onMounted } from 'vue' | 130 | +import { computed, ref, onMounted } from 'vue' |
| 123 | import { message } from 'ant-design-vue' | 131 | import { message } from 'ant-design-vue' |
| 124 | import { riderApi, refundApi } from '@/api' | 132 | import { riderApi, refundApi } from '@/api' |
| 133 | +import { useRoleCityList } from '@/composables/useRoleCityList' | ||
| 125 | 134 | ||
| 126 | const loading = ref(false) | 135 | const loading = ref(false) |
| 127 | const saving = ref(false) | 136 | const saving = ref(false) |
| 128 | const list = ref<any[]>([]) | 137 | const list = ref<any[]>([]) |
| 138 | +const filterCityId = ref<number | undefined>() | ||
| 129 | const filterStatus = ref<number | undefined>() | 139 | const filterStatus = ref<number | undefined>() |
| 130 | const filterTrans = ref<number | undefined>() | 140 | const filterTrans = ref<number | undefined>() |
| 131 | const keyword = ref('') | 141 | const keyword = ref('') |
| @@ -139,6 +149,8 @@ const designateRiderId = ref<number | undefined>() | @@ -139,6 +149,8 @@ const designateRiderId = ref<number | undefined>() | ||
| 139 | const designateCandidates = ref<any[]>([]) | 149 | const designateCandidates = ref<any[]>([]) |
| 140 | const refundRecord = ref<any>(null) | 150 | const refundRecord = ref<any>(null) |
| 141 | const currentRefundRecordId = ref(0) | 151 | const currentRefundRecordId = ref(0) |
| 152 | +const { isAdmin, cityList, loadCities } = useRoleCityList() | ||
| 153 | +const canOperate = computed(() => !isAdmin.value || !!filterCityId.value) | ||
| 142 | 154 | ||
| 143 | const statusMap: Record<number, string> = { | 155 | const statusMap: Record<number, string> = { |
| 144 | 1: '待支付', 2: '已支付', 3: '已接单', 4: '服务中', | 156 | 1: '待支付', 2: '已支付', 3: '已接单', 4: '服务中', |
| @@ -149,20 +161,30 @@ const statusColor: Record<number, string> = { | @@ -149,20 +161,30 @@ const statusColor: Record<number, string> = { | ||
| 149 | 6: 'green', 7: 'orange', 8: 'green', 9: 'red', 10: 'red' | 161 | 6: 'green', 7: 'orange', 8: 'green', 9: 'red', 10: 'red' |
| 150 | } | 162 | } |
| 151 | 163 | ||
| 152 | -const columns = [ | ||
| 153 | - { title: 'ID', dataIndex: 'id', width: 80 }, | ||
| 154 | - { title: '订单号', dataIndex: 'orderNo', ellipsis: true }, | ||
| 155 | - { title: '状态', key: 'status' }, | ||
| 156 | - { title: '骑手ID', dataIndex: 'riderId' }, | ||
| 157 | - { title: '转单', key: 'isTrans' }, | ||
| 158 | - { title: '配送费', dataIndex: 'moneyDelivery' }, | ||
| 159 | - { title: '操作', key: 'action' }, | ||
| 160 | -] | 164 | +const columns = computed(() => { |
| 165 | + const base = [ | ||
| 166 | + { title: 'ID', dataIndex: 'id', width: 80 }, | ||
| 167 | + { title: '订单号', dataIndex: 'orderNo', ellipsis: true }, | ||
| 168 | + { title: '状态', key: 'status' }, | ||
| 169 | + { title: '骑手ID', dataIndex: 'riderId' }, | ||
| 170 | + { title: '转单', key: 'isTrans' }, | ||
| 171 | + { title: '配送费', dataIndex: 'moneyDelivery' }, | ||
| 172 | + { title: '操作', key: 'action' }, | ||
| 173 | + ] | ||
| 174 | + if (!isAdmin.value) { | ||
| 175 | + return base | ||
| 176 | + } | ||
| 177 | + return [ | ||
| 178 | + { title: '租户', dataIndex: 'cityName', key: 'cityName' }, | ||
| 179 | + ...base, | ||
| 180 | + ] | ||
| 181 | +}) | ||
| 161 | 182 | ||
| 162 | async function loadList() { | 183 | async function loadList() { |
| 163 | loading.value = true | 184 | loading.value = true |
| 164 | try { | 185 | try { |
| 165 | const res: any = await riderApi.orderList({ | 186 | const res: any = await riderApi.orderList({ |
| 187 | + cityId: filterCityId.value, | ||
| 166 | status: filterStatus.value, | 188 | status: filterStatus.value, |
| 167 | isTrans: filterTrans.value, | 189 | isTrans: filterTrans.value, |
| 168 | keyword: keyword.value, | 190 | keyword: keyword.value, |
| @@ -172,6 +194,15 @@ async function loadList() { | @@ -172,6 +194,15 @@ async function loadList() { | ||
| 172 | } finally { loading.value = false } | 194 | } finally { loading.value = false } |
| 173 | } | 195 | } |
| 174 | 196 | ||
| 197 | +function handleAdminCityChange() { | ||
| 198 | + if (!filterCityId.value) { | ||
| 199 | + designateVisible.value = false | ||
| 200 | + refundVisible.value = false | ||
| 201 | + rejectVisible.value = false | ||
| 202 | + } | ||
| 203 | + loadList() | ||
| 204 | +} | ||
| 205 | + | ||
| 175 | async function openDesignate(record: any) { | 206 | async function openDesignate(record: any) { |
| 176 | designateOrderId.value = record.id | 207 | designateOrderId.value = record.id |
| 177 | designateRiderId.value = undefined | 208 | designateRiderId.value = undefined |
| @@ -230,5 +261,8 @@ async function handleRefund(status: number) { | @@ -230,5 +261,8 @@ async function handleRefund(status: number) { | ||
| 230 | } finally { saving.value = false } | 261 | } finally { saving.value = false } |
| 231 | } | 262 | } |
| 232 | 263 | ||
| 233 | -onMounted(loadList) | 264 | +onMounted(async () => { |
| 265 | + await loadCities() | ||
| 266 | + await loadList() | ||
| 267 | +}) | ||
| 234 | </script> | 268 | </script> |
src/views/rider/RiderEvaluateList.vue
| @@ -31,13 +31,14 @@ | @@ -31,13 +31,14 @@ | ||
| 31 | 31 | ||
| 32 | <script setup lang="ts"> | 32 | <script setup lang="ts"> |
| 33 | import { ref, onMounted } from 'vue' | 33 | import { ref, onMounted } from 'vue' |
| 34 | -import { cityApi, riderApi } from '@/api' | 34 | +import { riderApi } from '@/api' |
| 35 | +import { useRoleCityList } from '@/composables/useRoleCityList' | ||
| 35 | 36 | ||
| 36 | const loading = ref(false) | 37 | const loading = ref(false) |
| 37 | const list = ref<any[]>([]) | 38 | const list = ref<any[]>([]) |
| 38 | -const cityList = ref<any[]>([]) | ||
| 39 | const filterRiderId = ref<number | undefined>() | 39 | const filterRiderId = ref<number | undefined>() |
| 40 | const filterType = ref(0) | 40 | const filterType = ref(0) |
| 41 | +const { loadCities, getCityName } = useRoleCityList() | ||
| 41 | 42 | ||
| 42 | const columns = [ | 43 | const columns = [ |
| 43 | { title: 'ID', dataIndex: 'id', width: 80 }, | 44 | { title: 'ID', dataIndex: 'id', width: 80 }, |
| @@ -47,16 +48,6 @@ const columns = [ | @@ -47,16 +48,6 @@ const columns = [ | ||
| 47 | { title: '租户', key: 'cityId' }, | 48 | { title: '租户', key: 'cityId' }, |
| 48 | ] | 49 | ] |
| 49 | 50 | ||
| 50 | -async function loadCities() { | ||
| 51 | - const res: any = await cityApi.openList() | ||
| 52 | - cityList.value = Array.isArray(res?.data) ? res.data : [] | ||
| 53 | -} | ||
| 54 | - | ||
| 55 | -function getCityName(cityId?: number) { | ||
| 56 | - const city = cityList.value.find(item => item.id === cityId) | ||
| 57 | - return city?.name || (cityId ? `租户#${cityId}` : '-') | ||
| 58 | -} | ||
| 59 | - | ||
| 60 | async function loadList() { | 51 | async function loadList() { |
| 61 | if (!filterRiderId.value) return | 52 | if (!filterRiderId.value) return |
| 62 | loading.value = true | 53 | loading.value = true |
src/views/rider/RiderList.vue
| @@ -121,16 +121,14 @@ | @@ -121,16 +121,14 @@ | ||
| 121 | </template> | 121 | </template> |
| 122 | 122 | ||
| 123 | <script setup lang="ts"> | 123 | <script setup lang="ts"> |
| 124 | -import { computed, reactive, ref, onMounted } from 'vue' | 124 | +import { reactive, ref, onMounted } from 'vue' |
| 125 | import { message } from 'ant-design-vue' | 125 | import { message } from 'ant-design-vue' |
| 126 | -import { cityApi, riderApi, riderLevelApi } from '@/api' | ||
| 127 | -import { useAuthStore } from '@/stores/auth' | 126 | +import { riderApi, riderLevelApi } from '@/api' |
| 127 | +import { useRoleCityList } from '@/composables/useRoleCityList' | ||
| 128 | 128 | ||
| 129 | -const auth = useAuthStore() | ||
| 130 | const loading = ref(false) | 129 | const loading = ref(false) |
| 131 | const saving = ref(false) | 130 | const saving = ref(false) |
| 132 | const list = ref<any[]>([]) | 131 | const list = ref<any[]>([]) |
| 133 | -const cityList = ref<any[]>([]) | ||
| 134 | const levelOptions = ref<any[]>([]) | 132 | const levelOptions = ref<any[]>([]) |
| 135 | const filterStatus = ref<number | undefined>() | 133 | const filterStatus = ref<number | undefined>() |
| 136 | const keyword = ref('') | 134 | const keyword = ref('') |
| @@ -146,7 +144,7 @@ const levelSaving = ref(false) | @@ -146,7 +144,7 @@ const levelSaving = ref(false) | ||
| 146 | const levelTargetId = ref<number>(0) | 144 | const levelTargetId = ref<number>(0) |
| 147 | const levelTargetName = ref('') | 145 | const levelTargetName = ref('') |
| 148 | const selectedLevelId = ref<number>(0) | 146 | const selectedLevelId = ref<number>(0) |
| 149 | -const isAdmin = computed(() => auth.user?.role === 'admin') | 147 | +const { isAdmin, cityList, loadCities, getCityName } = useRoleCityList() |
| 150 | 148 | ||
| 151 | const statusMap: Record<number, string> = { 0: '已拒绝', 1: '已通过', 2: '待审核' } | 149 | const statusMap: Record<number, string> = { 0: '已拒绝', 1: '已通过', 2: '待审核' } |
| 152 | 150 | ||
| @@ -172,11 +170,6 @@ function getWorkStatus(record: any) { | @@ -172,11 +170,6 @@ function getWorkStatus(record: any) { | ||
| 172 | return record.isRest === 1 ? 1 : 0 | 170 | return record.isRest === 1 ? 1 : 0 |
| 173 | } | 171 | } |
| 174 | 172 | ||
| 175 | -function getCityName(cityId?: number) { | ||
| 176 | - const city = cityList.value.find(item => item.id === cityId) | ||
| 177 | - return city?.name || (cityId ? `租户#${cityId}` : '-') | ||
| 178 | -} | ||
| 179 | - | ||
| 180 | async function loadList() { | 173 | async function loadList() { |
| 181 | loading.value = true | 174 | loading.value = true |
| 182 | try { | 175 | try { |
| @@ -188,11 +181,6 @@ async function loadList() { | @@ -188,11 +181,6 @@ async function loadList() { | ||
| 188 | } finally { loading.value = false } | 181 | } finally { loading.value = false } |
| 189 | } | 182 | } |
| 190 | 183 | ||
| 191 | -async function loadCities() { | ||
| 192 | - const res: any = await cityApi.openList() | ||
| 193 | - cityList.value = Array.isArray(res?.data) ? res.data : [] | ||
| 194 | -} | ||
| 195 | - | ||
| 196 | function openAdd() { | 184 | function openAdd() { |
| 197 | Object.assign(form, { | 185 | Object.assign(form, { |
| 198 | cityId: undefined, | 186 | cityId: undefined, |
src/views/substation/SubstationList.vue
| @@ -97,17 +97,18 @@ | @@ -97,17 +97,18 @@ | ||
| 97 | <script setup lang="ts"> | 97 | <script setup lang="ts"> |
| 98 | import { reactive, ref, onMounted } from 'vue' | 98 | import { reactive, ref, onMounted } from 'vue' |
| 99 | import { message } from 'ant-design-vue' | 99 | import { message } from 'ant-design-vue' |
| 100 | -import { cityApi, substationApi, systemRoleApi } from '@/api' | 100 | +import { substationApi, systemRoleApi } from '@/api' |
| 101 | +import { useRoleCityList } from '@/composables/useRoleCityList' | ||
| 101 | 102 | ||
| 102 | const loading = ref(false) | 103 | const loading = ref(false) |
| 103 | const saving = ref(false) | 104 | const saving = ref(false) |
| 104 | const list = ref<any[]>([]) | 105 | const list = ref<any[]>([]) |
| 105 | -const cityList = ref<any[]>([]) | ||
| 106 | const roleOptions = ref<any[]>([]) | 106 | const roleOptions = ref<any[]>([]) |
| 107 | const keyword = ref('') | 107 | const keyword = ref('') |
| 108 | const modalVisible = ref(false) | 108 | const modalVisible = ref(false) |
| 109 | const editingId = ref<number | null>(null) | 109 | const editingId = ref<number | null>(null) |
| 110 | const form = reactive({ cityId: undefined, roleId: undefined, userLogin: '', userNickname: '', mobile: '', userPass: '' }) | 110 | const form = reactive({ cityId: undefined, roleId: undefined, userLogin: '', userNickname: '', mobile: '', userPass: '' }) |
| 111 | +const { cityList, loadCities, getCityName } = useRoleCityList() | ||
| 111 | 112 | ||
| 112 | const columns = [ | 113 | const columns = [ |
| 113 | { title: 'ID', dataIndex: 'id', width: 80 }, | 114 | { title: 'ID', dataIndex: 'id', width: 80 }, |
| @@ -125,11 +126,6 @@ function getRoleName(roleId?: number) { | @@ -125,11 +126,6 @@ function getRoleName(roleId?: number) { | ||
| 125 | return role?.name || (roleId ? `角色#${roleId}` : '-') | 126 | return role?.name || (roleId ? `角色#${roleId}` : '-') |
| 126 | } | 127 | } |
| 127 | 128 | ||
| 128 | -function getCityName(cityId?: number) { | ||
| 129 | - const city = cityList.value.find(item => item.id === cityId) | ||
| 130 | - return city?.name || (cityId ? `租户#${cityId}` : '-') | ||
| 131 | -} | ||
| 132 | - | ||
| 133 | async function loadList() { | 129 | async function loadList() { |
| 134 | loading.value = true | 130 | loading.value = true |
| 135 | try { | 131 | try { |
| @@ -138,11 +134,6 @@ async function loadList() { | @@ -138,11 +134,6 @@ async function loadList() { | ||
| 138 | } finally { loading.value = false } | 134 | } finally { loading.value = false } |
| 139 | } | 135 | } |
| 140 | 136 | ||
| 141 | -async function loadCities() { | ||
| 142 | - const res: any = await cityApi.openList() | ||
| 143 | - cityList.value = res.data | ||
| 144 | -} | ||
| 145 | - | ||
| 146 | async function loadRoles() { | 137 | async function loadRoles() { |
| 147 | const res: any = await systemRoleApi.list() | 138 | const res: any = await systemRoleApi.list() |
| 148 | roleOptions.value = Array.isArray(res?.data) ? res.data.filter((item: any) => item.roleScope === 'SUBSTATION') : [] | 139 | roleOptions.value = Array.isArray(res?.data) ? res.data.filter((item: any) => item.roleScope === 'SUBSTATION') : [] |