front/src/views/channel/components/KpiAreaPage.vue
2026-10-07 17:34:36 +08:00

373 lines
12 KiB
Vue

<template>
<div class="channel-config-page">
<div class="layout-content">
<BasicLayoutLeftRight :left-width="280">
<template #left>
<div class="left-sidebar">
<CustomLeftMenu
:tree-data="leftTreeData"
:selected-keys="leftSelectedKeys"
v-model:expanded-keys="leftExpandedKeys"
:search-keyword="searchModel.keyword"
:loading="leftLoading"
@update:search-keyword="(v) => (searchModel.keyword = v)"
:search-placeholder="t('channel.area.search.placeholder')"
:refresh-title="t('channel.area.search.refresh')"
:add-title="t('common.add')"
show-node-index
:show-method="false"
:show-map-count="false"
:show-node-code="false"
show-node-actions
:delete-label="t('channel.area.actions.delete')"
@search="onFormSubmitClick"
@refresh="onFormSubmitClick"
@add="handleOpenModal('add')"
@select="handleSelectFromTree"
@delete-node="handleDeleteLeftNode"
>
<template #node-menu="{ nodeData }">
<a-doption value="edit" @click="handleOpenModal('edit', nodeData)">
<IconEdit />
{{ t('channel.area.actions.edit') }}
</a-doption>
<a-doption value="delete" @click="handleDelData(nodeData?.id, nodeData?.name)">
<IconDelete />
{{ t('channel.area.actions.delete') }}
</a-doption>
</template>
</CustomLeftMenu>
<ModalForm
ref="modalFormLeftRef"
:edit-api="postForewarningServiceKpiAreaModifyKpiArea"
:add-api="postForewarningServiceKpiAreaCreateKpiArea"
:info-api="returnEditRowParams"
:api-params="editFormParams"
:form-props="formTopProps()"
@on-submit="onSubmitLeft"
>
<template #BasicMsgTop>
<a-alert type="info" :show-icon="false" class="modal-form-tip">
{{ leftModalTip }}
</a-alert>
</template>
</ModalForm>
</div>
</template>
<template #right>
<ChannelConfigRightPanel
:selected="!!currentId?.id"
:selected-name="selectedAreaName"
:item-count="totalCount"
:count-label="t('channel.config.detailCount', { count: totalCount })"
:loading="tableLoading"
:total-count="totalCount"
v-model:current-page="currentPage"
v-model:page-size="pageSize"
@page-change="handlePageChange"
@page-size-change="handlePageSizeChange"
>
<template #toolbar-left>
<div class="toolbar-actions">
<a-button
class="btn-add app-btn-primary-soft"
:disabled="!currentId?.id"
@click="handleOpenRightModal('add')"
>
{{ t('common.add') }}
</a-button>
<a-button :disabled="!currentId?.id" @click="openImportModal">
{{ t('channel.area.actions.import') }}
</a-button>
<a-button :disabled="!currentId?.id" :loading="exporting" @click="handleExport">
{{ t('channel.area.actions.export') }}
</a-button>
<a-button
status="danger"
:disabled="!currentId?.id"
@click="handleToolbarDelete"
>
{{ t('channel.area.actions.delete') }}
</a-button>
<a-button :disabled="!currentId?.id" @click="openPackModal">
{{ t('channel.area.actions.packVersions') }}
</a-button>
</div>
</template>
<ChannelConfigHotTable
:columns="hotColumns"
:data="tableData"
:total-count="totalCount"
:current-page="currentPage"
:page-size="pageSize"
@edit="(row) => handleOpenRightModal('edit', row)"
@delete="(row) => handleDelRightData(row.id)"
/>
</ChannelConfigRightPanel>
<ModalForm
ref="modalFormRightRef"
:width="560"
:mask-closable="false"
:edit-api="postForewarningServiceKpiAreaModifyKpiAreaInfo"
:add-api="postForewarningServiceKpiAreaAddAreaInfo"
:info-api="returnRightEditRowParams"
:api-params="editFormRightParams"
:form-props="formPros"
:before-submit="beforeSubmitRightAreaInfo"
@on-submit="onSubmitRight"
>
<template #BasicMsgTop>
<a-alert type="info" :show-icon="false" class="modal-form-tip">
{{ rightModalTip }}
</a-alert>
</template>
<template #sectionMatch>
<div class="form-section-title">{{ t('channel.area.section.match') }}</div>
</template>
<template #sectionPostcode>
<div class="form-section-title">{{ t('channel.area.section.postcode') }}</div>
</template>
<template #_countryQuickTags="{ model }">
<div class="country-quick-tags">
<a-tag
v-for="label in DESTINATION_COUNTRY_QUICK_LABELS"
:key="label"
class="country-quick-tag"
@click="handleCountryQuickTagClick(model, label)"
>
{{ label }}
</a-tag>
</div>
</template>
</ModalForm>
<KpiAreaImportModal
ref="importModalRef"
:area-type="importAreaType"
@success="onImportSuccess"
/>
<a-modal
v-model:visible="packModalVisible"
:title="t('channel.area.pack.modalTitle', { name: selectedAreaName || '--' })"
:width="880"
:footer="false"
unmount-on-close
>
<div class="pack-modal-toolbar table-toolbar">
<div class="toolbar-left">
<span class="pack-modal-tip">{{ t('channel.area.pack.tip') }}</span>
</div>
<div class="toolbar-right">
<a-button size="small" :loading="packLoading" @click="loadPackList">
{{ t('channel.area.search.refresh') }}
</a-button>
</div>
</div>
<a-table
row-key="id"
:loading="packLoading"
:data="packList"
:pagination="false"
:bordered="{ cell: true }"
:scroll="{ y: 420 }"
>
<template #columns>
<a-table-column
:title="t('channel.area.pack.col.version')"
data-index="version"
:width="160"
/>
<a-table-column
:title="t('channel.area.pack.col.status')"
data-index="status"
:width="88"
/>
<a-table-column
:title="t('channel.area.pack.col.contentHash')"
data-index="contentHash"
:width="140"
>
<template #cell="{ record }">
<a-typography-text :copyable="{ text: record.contentHash }">
{{ shortHash(record.contentHash) }}
</a-typography-text>
</template>
</a-table-column>
<a-table-column
:title="t('channel.area.pack.col.publishUser')"
data-index="publishUser"
:width="100"
/>
<a-table-column
:title="t('channel.area.pack.col.publishTime')"
data-index="publishTime"
:width="170"
/>
<a-table-column
:title="t('channel.area.pack.col.description')"
data-index="description"
ellipsis
tooltip
/>
<a-table-column
:title="t('common.actions')"
:width="88"
align="center"
fixed="right"
>
<template #cell="{ record }">
<a-button type="text" size="mini" @click="viewPackDetail(record)">
{{ t('channel.area.pack.viewContent') }}
</a-button>
</template>
</a-table-column>
</template>
<template #empty>
<a-empty :description="t('channel.area.pack.empty')" />
</template>
</a-table>
</a-modal>
<a-modal
v-model:visible="packDetailVisible"
:title="packDetailTitle"
:width="720"
:footer="false"
unmount-on-close
>
<a-spin :loading="packDetailLoading" style="width: 100%">
<pre class="pack-detail-pre">{{
packDetailLoading
? ''
: packDetailJson || t('channel.area.pack.emptyContent')
}}</pre>
</a-spin>
</a-modal>
</template>
</BasicLayoutLeftRight>
</div>
</div>
</template>
<script setup lang="ts">
import { IconEdit, IconDelete } from '@arco-design/web-vue/es/icon';
import {
postForewarningServiceKpiAreaCreateKpiArea,
postForewarningServiceKpiAreaAddAreaInfo,
postForewarningServiceKpiAreaModifyKpiAreaInfo,
postForewarningServiceKpiAreaModifyKpiArea,
} from '@/api/channel/kpiArea';
import CustomLeftMenu from '@/components/CustomLeftMenu/index.vue';
import ChannelConfigRightPanel from '@/views/channel/components/ChannelConfigRightPanel.vue';
import ChannelConfigHotTable from '@/views/channel/components/ChannelConfigHotTable.vue';
import KpiAreaImportModal from '@/views/channel/components/KpiAreaImportModal.vue';
import { useKpiAreaPage, type KpiAreaType } from '@/views/channel/composables/useKpiAreaPage';
const props = defineProps<{
areaType: KpiAreaType;
importAreaType: KpiAreaType;
}>();
const {
t,
DESTINATION_COUNTRY_QUICK_LABELS,
formTopProps,
formPros,
editFormParams,
editFormRightParams,
currentId,
modalFormLeftRef,
modalFormRightRef,
importModalRef,
tableData,
hotColumns,
leftModalTip,
rightModalTip,
searchModel,
totalCount,
currentPage,
pageSize,
tableLoading,
leftLoading,
leftTreeData,
leftExpandedKeys,
leftSelectedKeys,
selectedAreaName,
beforeSubmitRightAreaInfo,
handleCountryQuickTagClick,
handleSelectFromTree,
handleDeleteLeftNode,
handleOpenModal,
handleOpenRightModal,
returnEditRowParams,
returnRightEditRowParams,
handleDelData,
handleToolbarDelete,
handleDelRightData,
handlePageChange,
handlePageSizeChange,
onFormSubmitClick,
onSubmitLeft,
onSubmitRight,
openImportModal,
onImportSuccess,
exporting,
handleExport,
packModalVisible,
packLoading,
packList,
packDetailVisible,
packDetailLoading,
packDetailTitle,
packDetailJson,
shortHash,
openPackModal,
loadPackList,
viewPackDetail,
} = useKpiAreaPage(props.areaType);
</script>
<style scoped lang="less">
@import '@/views/channel/components/channel-config-page.less';
.form-section-title {
margin: 0 0 12px;
padding: 0 0 8px;
font-size: 13px;
font-weight: 600;
color: var(--color-text-2);
border-bottom: 1px solid var(--color-border-2);
}
.pack-modal-toolbar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
margin-bottom: 12px;
}
.pack-modal-tip {
font-size: 12px;
color: var(--color-text-3);
}
.pack-detail-pre {
margin: 0;
max-height: 520px;
overflow: auto;
padding: 12px;
font-size: 12px;
line-height: 1.5;
background: #f7f8fa;
border-radius: 4px;
white-space: pre-wrap;
word-break: break-all;
}
</style>