优化
This commit is contained in:
@@ -65,7 +65,7 @@ describe('platform partner API', () => {
|
||||
it('normalizes legacy detail types and uses import contracts', async () => {
|
||||
vi.mocked(http.get)
|
||||
.mockResolvedValueOnce({ code: '200', message: 'success', data: {
|
||||
id: '19001', tenantId: 10001, partnerCode: 'CUS-001', partnerName: '测试单位',
|
||||
id: '19001', tenantId: 0, dataScopeId: 0, partnerCode: 'CUS-001', partnerName: '测试单位',
|
||||
partnerType: 'BOTH', contactName: '张三', contactPhone: '13800000000', contactEmail: null,
|
||||
countryCode: 'CN', province: null, city: '深圳市', district: null, addressLine: '测试地址',
|
||||
postalCode: null, status: 'ACTIVE',
|
||||
@@ -81,7 +81,7 @@ describe('platform partner API', () => {
|
||||
const result = await importPlatformPartners(file)
|
||||
|
||||
expect(detail.types).toEqual(['CUSTOMER', 'SUPPLIER'])
|
||||
expect(detail.dataScopeId).toBe(10001)
|
||||
expect(detail.dataScopeId).toBe(0)
|
||||
expect(template).toBeInstanceOf(Blob)
|
||||
expect(result.success).toBe(true)
|
||||
expect(http.get).toHaveBeenNthCalledWith(1, '/platform/v1/partners/19001', { params: { tenantId: 0 } })
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, reactive, ref, watch } from 'vue'
|
||||
import { ElMessage, ElMessageBox, type FormInstance, type FormRules, type UploadFile } from 'element-plus'
|
||||
import { Building2, Download, Eye, MapPin, Pencil, Plus, Power, Upload } from '@lucide/vue'
|
||||
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus'
|
||||
import { Building2, Eye, MapPin, Pencil, Plus, Power, Upload } from '@lucide/vue'
|
||||
import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue'
|
||||
import BatchImportDialog from '@/shared/components/BatchImportDialog.vue'
|
||||
import DataTable, { type DataTableColumn } from '@/shared/components/DataTable.vue'
|
||||
import QueryToolbar, { type QueryField, type QueryModel } from '@/shared/components/QueryToolbar.vue'
|
||||
import { useUnsavedWorkRegistration } from '@/core/unsaved-work/useUnsavedWorkRegistration'
|
||||
@@ -15,7 +16,6 @@ import {
|
||||
importPlatformPartners,
|
||||
listPlatformPartners,
|
||||
updatePlatformPartner,
|
||||
type PlatformPartnerImportResult,
|
||||
type PlatformPartnerResource,
|
||||
type PlatformPartnerStatus,
|
||||
type PlatformPartnerLegacyType,
|
||||
@@ -33,10 +33,6 @@ const detailOpen = ref(false)
|
||||
const detailLoading = ref(false)
|
||||
const detail = ref<PlatformPartnerResource | null>(null)
|
||||
const importOpen = ref(false)
|
||||
const importFile = ref<File | null>(null)
|
||||
const importing = ref(false)
|
||||
const downloadingTemplate = ref(false)
|
||||
const importResult = ref<PlatformPartnerImportResult | null>(null)
|
||||
const formRef = ref<FormInstance>()
|
||||
const rows = ref<PlatformPartnerResource[]>([])
|
||||
const page = ref(1)
|
||||
@@ -278,74 +274,9 @@ async function openDetail(row: PlatformPartnerResource) {
|
||||
}
|
||||
|
||||
function openImport() {
|
||||
importFile.value = null
|
||||
importResult.value = null
|
||||
importOpen.value = true
|
||||
}
|
||||
|
||||
function selectImportFile(uploadFile: UploadFile) {
|
||||
importFile.value = uploadFile.raw ?? null
|
||||
importResult.value = null
|
||||
}
|
||||
|
||||
function removeImportFile() {
|
||||
importFile.value = null
|
||||
}
|
||||
|
||||
async function downloadTemplate() {
|
||||
downloadingTemplate.value = true
|
||||
try {
|
||||
const blob = await downloadPlatformPartnerImportTemplate()
|
||||
const url = URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = '往来单位导入模板-v1.xlsx'
|
||||
link.click()
|
||||
URL.revokeObjectURL(url)
|
||||
} catch (error) {
|
||||
ElMessage.error(getApiErrorDetails(error, '模板下载失败,请重试').message)
|
||||
} finally {
|
||||
downloadingTemplate.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function submitImport() {
|
||||
if (!importFile.value) {
|
||||
ElMessage.warning('请先选择 XLSX 文件')
|
||||
return
|
||||
}
|
||||
importing.value = true
|
||||
importResult.value = null
|
||||
try {
|
||||
importResult.value = await importPlatformPartners(importFile.value)
|
||||
if (importResult.value.success) {
|
||||
ElMessage.success(`成功导入 ${importResult.value.importedRows} 条往来单位`)
|
||||
await loadPartners()
|
||||
}
|
||||
} catch (error) {
|
||||
const meta = getApiErrorDetails(error, '往来单位导入失败,请重试')
|
||||
ElMessage.error(meta.requestId ? `${meta.message}(requestId: ${meta.requestId})` : meta.message)
|
||||
} finally {
|
||||
importing.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function downloadImportErrors() {
|
||||
if (!importResult.value?.errors.length) return
|
||||
const escapeCsv = (value: string | number) => `"${String(value).replaceAll('"', '""')}"`
|
||||
const rows = [
|
||||
['行号', '字段', '原因'],
|
||||
...importResult.value.errors.map((error) => [error.row || '-', error.field, error.message]),
|
||||
]
|
||||
const csv = rows.map((row) => row.map(escapeCsv).join(',')).join('\r\n')
|
||||
const url = URL.createObjectURL(new Blob(['\ufeff', csv], { type: 'text/csv;charset=utf-8' }))
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = `${importResult.value.fileName.replace(/\.xlsx$/i, '')}-错误报告.csv`
|
||||
link.click()
|
||||
URL.revokeObjectURL(url)
|
||||
}
|
||||
|
||||
async function savePartner() {
|
||||
const valid = await formRef.value?.validate().catch(() => false)
|
||||
if (!valid) return
|
||||
@@ -507,23 +438,15 @@ onMounted(() => {
|
||||
</div>
|
||||
</el-drawer>
|
||||
|
||||
<el-dialog v-model="importOpen" title="批量导入往来单位" width="min(720px, calc(100vw - 32px))" :close-on-click-modal="!importing" :close-on-press-escape="!importing">
|
||||
<div class="import-content">
|
||||
<div class="import-guide"><strong>使用标准模板导入</strong><p>仅新增档案,最多 1000 行。服务端会整批校验;任一行有误时不会写入任何数据。</p><el-button :loading="downloadingTemplate" @click="downloadTemplate"><Download :size="16" />下载 XLSX 模板</el-button></div>
|
||||
<el-upload accept=".xlsx" :auto-upload="false" :limit="1" :on-change="selectImportFile" :on-remove="removeImportFile">
|
||||
<el-button><Upload :size="16" />选择 XLSX 文件</el-button>
|
||||
<template #tip><div class="el-upload__tip">文件不得超过 5MB,请勿修改模板版本或表头。</div></template>
|
||||
</el-upload>
|
||||
<div v-if="importResult" :class="['import-result', importResult.success ? 'is-success' : 'is-error']" role="status">
|
||||
<div class="import-result-heading"><strong>{{ importResult.success ? `已成功导入 ${importResult.importedRows} 条记录` : `发现 ${importResult.errors.length} 个问题,未写入数据` }}</strong><el-button v-if="importResult.errors.length" size="small" @click="downloadImportErrors"><Download :size="15" />下载错误报告</el-button></div>
|
||||
<el-table v-if="importResult.errors.length" :data="importResult.errors" max-height="260" size="small">
|
||||
<el-table-column prop="row" label="行号" width="70"><template #default="{ row }">{{ row.row || '-' }}</template></el-table-column>
|
||||
<el-table-column prop="field" label="字段" width="120" /><el-table-column prop="message" label="原因" min-width="240" />
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer><el-button :disabled="importing" @click="importOpen = false">关闭</el-button><el-button type="primary" :loading="importing" :disabled="!importFile" @click="submitImport">开始导入</el-button></template>
|
||||
</el-dialog>
|
||||
<BatchImportDialog
|
||||
v-model="importOpen"
|
||||
title="批量导入往来单位"
|
||||
entity-label="往来单位"
|
||||
template-file-name="往来单位导入模板-v1.xlsx"
|
||||
:download-template="downloadPlatformPartnerImportTemplate"
|
||||
:import-file="importPlatformPartners"
|
||||
@success="loadPartners"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -551,14 +474,6 @@ onMounted(() => {
|
||||
.detail-grid .detail-span { grid-column: 1 / -1; }
|
||||
.detail-grid dt { margin-bottom: 5px; color: var(--cc-muted); font-size: 12px; }
|
||||
.detail-grid dd { margin: 0; color: var(--cc-text); line-height: 1.55; overflow-wrap: anywhere; }
|
||||
.import-content { display: grid; gap: 18px; }
|
||||
.import-guide { padding: 16px; border: 1px solid #d8e2f0; border-radius: 8px; background: #f8fbff; }
|
||||
.import-guide p { margin: 6px 0 14px; color: var(--cc-muted); font-size: 13px; line-height: 1.6; }
|
||||
.import-result { display: grid; gap: 12px; padding: 14px; border: 1px solid; border-radius: 8px; }
|
||||
.import-result-heading { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
|
||||
.import-result.is-success { border-color: #a6f4c5; background: #f6fef9; color: #067647; }
|
||||
.import-result.is-error { border-color: #fecdca; background: #fffafa; color: #b42318; }
|
||||
|
||||
@media (max-width: 720px) {
|
||||
.partners-error { align-items: stretch; flex-direction: column; }
|
||||
.partners-error .el-button { min-height: 44px; }
|
||||
@@ -568,6 +483,5 @@ onMounted(() => {
|
||||
.partner-detail { padding: 16px; }
|
||||
.detail-grid { grid-template-columns: minmax(0, 1fr); }
|
||||
.detail-grid .detail-span { grid-column: auto; }
|
||||
.import-result-heading { align-items: stretch; flex-direction: column; }
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -10,6 +10,8 @@ import ExpressCompaniesView from './ExpressCompaniesView.vue'
|
||||
vi.mock('@/modules/master-data/express-companies/api/platformExpressCompanies', () => ({
|
||||
listPlatformExpressCompanies: vi.fn(),
|
||||
createPlatformExpressCompany: vi.fn(),
|
||||
downloadPlatformExpressCompanyImportTemplate: vi.fn(),
|
||||
importPlatformExpressCompanies: vi.fn(),
|
||||
updatePlatformExpressCompany: vi.fn(),
|
||||
changePlatformExpressCompanyStatus: vi.fn(),
|
||||
}))
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, reactive, ref, watch } from 'vue'
|
||||
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus'
|
||||
import { Download, ExternalLink, FileSpreadsheet, Pencil, Plus, Power, Truck, Upload } from '@lucide/vue'
|
||||
import { ExternalLink, Pencil, Plus, Power, Truck, Upload } from '@lucide/vue'
|
||||
import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue'
|
||||
import BatchImportDialog from '@/shared/components/BatchImportDialog.vue'
|
||||
import DataTable, { type DataTableColumn } from '@/shared/components/DataTable.vue'
|
||||
import QueryToolbar, { type QueryField, type QueryModel } from '@/shared/components/QueryToolbar.vue'
|
||||
import { useUnsavedWorkRegistration } from '@/core/unsaved-work/useUnsavedWorkRegistration'
|
||||
@@ -15,7 +16,6 @@ import {
|
||||
importPlatformExpressCompanies,
|
||||
listPlatformExpressCompanies,
|
||||
updatePlatformExpressCompany,
|
||||
type PlatformExpressCompanyImportResult,
|
||||
type PlatformExpressCompanyResource,
|
||||
type PlatformExpressCompanyStatus,
|
||||
type SavePlatformExpressCompanyRequest,
|
||||
@@ -28,7 +28,6 @@ const saving = ref(false)
|
||||
const editorOpen = ref(false)
|
||||
const importOpen = ref(false)
|
||||
const formRef = ref<FormInstance>()
|
||||
const fileInputRef = ref<HTMLInputElement>()
|
||||
const rows = ref<PlatformExpressCompanyResource[]>([])
|
||||
const page = ref(1)
|
||||
const pageSize = ref(20)
|
||||
@@ -36,11 +35,6 @@ const total = ref(0)
|
||||
const loadError = ref<ApiErrorDetails | null>(null)
|
||||
const statusLoadingIds = ref(new Set<string>())
|
||||
const editLoadingIds = ref(new Set<string>())
|
||||
const downloadingTemplate = ref(false)
|
||||
const importing = ref(false)
|
||||
const importFile = ref<File | null>(null)
|
||||
const importResult = ref<PlatformExpressCompanyImportResult | null>(null)
|
||||
const importError = ref<ApiErrorDetails | null>(null)
|
||||
type ExpressCompanyFilters = QueryModel & {
|
||||
keyword: string
|
||||
status: PlatformExpressCompanyStatus | ''
|
||||
@@ -81,7 +75,6 @@ const rules: FormRules<typeof form> = {
|
||||
}
|
||||
const editorTitle = computed(() => form.id ? '编辑快递公司' : '新增快递公司')
|
||||
const editorPermission = computed(() => form.id ? 'platform:express:edit' : 'platform:express:create')
|
||||
const displayedImportErrors = computed(() => importResult.value?.errors.slice(0, 100) || [])
|
||||
const { captureBaseline } = useUnsavedWorkRegistration({
|
||||
key: 'express-company-editor',
|
||||
label: editorTitle,
|
||||
@@ -207,92 +200,9 @@ async function openEdit(row: PlatformExpressCompanyResource) {
|
||||
}
|
||||
|
||||
function openImport() {
|
||||
importFile.value = null
|
||||
importResult.value = null
|
||||
importError.value = null
|
||||
if (fileInputRef.value) fileInputRef.value.value = ''
|
||||
importOpen.value = true
|
||||
}
|
||||
|
||||
function saveBlob(blob: Blob, fileName: string) {
|
||||
const url = URL.createObjectURL(blob)
|
||||
const anchor = document.createElement('a')
|
||||
anchor.href = url
|
||||
anchor.download = fileName
|
||||
anchor.click()
|
||||
URL.revokeObjectURL(url)
|
||||
}
|
||||
|
||||
async function downloadImportTemplate() {
|
||||
downloadingTemplate.value = true
|
||||
try {
|
||||
const blob = await downloadPlatformExpressCompanyImportTemplate()
|
||||
saveBlob(blob, '快递公司批量导入模板-v1.xlsx')
|
||||
} catch (error) {
|
||||
const details = getApiErrorDetails(error, '导入模板下载失败,请稍后重试')
|
||||
ElMessage.error(details.requestId ? `${details.message}(requestId: ${details.requestId})` : details.message)
|
||||
} finally {
|
||||
downloadingTemplate.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function selectImportFile(event: Event) {
|
||||
const file = (event.target as HTMLInputElement).files?.[0] || null
|
||||
importResult.value = null
|
||||
importError.value = null
|
||||
if (!file) {
|
||||
importFile.value = null
|
||||
return
|
||||
}
|
||||
if (!file.name.toLowerCase().endsWith('.xlsx')) {
|
||||
importFile.value = null
|
||||
ElMessage.error('请选择 .xlsx 格式的标准模板文件')
|
||||
if (fileInputRef.value) fileInputRef.value.value = ''
|
||||
return
|
||||
}
|
||||
if (file.size > 5 * 1024 * 1024) {
|
||||
importFile.value = null
|
||||
ElMessage.error('导入文件不能超过 5MB')
|
||||
if (fileInputRef.value) fileInputRef.value.value = ''
|
||||
return
|
||||
}
|
||||
importFile.value = file
|
||||
}
|
||||
|
||||
async function submitImport() {
|
||||
if (!importFile.value) {
|
||||
ElMessage.warning('请先选择填写完成的 XLSX 文件')
|
||||
return
|
||||
}
|
||||
importing.value = true
|
||||
importError.value = null
|
||||
importResult.value = null
|
||||
try {
|
||||
const result = await importPlatformExpressCompanies(importFile.value)
|
||||
importResult.value = result
|
||||
if (result.success) {
|
||||
ElMessage.success(`成功导入 ${result.importedRows} 家快递公司`)
|
||||
importFile.value = null
|
||||
if (fileInputRef.value) fileInputRef.value.value = ''
|
||||
await loadExpressCompanies()
|
||||
}
|
||||
} catch (error) {
|
||||
importError.value = getApiErrorDetails(error, '快递公司导入失败,请稍后重试')
|
||||
} finally {
|
||||
importing.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function downloadImportErrors() {
|
||||
if (!importResult.value?.errors.length) return
|
||||
const csvCell = (value: string | number) => `"${String(value).replaceAll('"', '""')}"`
|
||||
const lines = [
|
||||
['行号', '字段', '错误原因'].map(csvCell).join(','),
|
||||
...importResult.value.errors.map((item) => [item.row || '文件', item.field, item.message].map(csvCell).join(',')),
|
||||
]
|
||||
saveBlob(new Blob([`\ufeff${lines.join('\r\n')}`], { type: 'text/csv;charset=utf-8' }), '快递公司导入错误报告.csv')
|
||||
}
|
||||
|
||||
function buildPayload(): SavePlatformExpressCompanyRequest {
|
||||
return {
|
||||
companyCode: form.companyCode.trim(),
|
||||
@@ -432,60 +342,17 @@ onMounted(() => {
|
||||
</DataTable>
|
||||
</section>
|
||||
|
||||
<el-dialog
|
||||
<BatchImportDialog
|
||||
v-model="importOpen"
|
||||
title="批量导入快递公司"
|
||||
width="min(680px, calc(100vw - 32px))"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="!importing"
|
||||
:show-close="!importing"
|
||||
class="import-dialog"
|
||||
>
|
||||
<div class="import-flow">
|
||||
<section class="import-step">
|
||||
<div class="step-heading"><span>1</span><div><strong>下载标准模板</strong><p>请勿修改模板版本或表头,仅填写模板中的数据行。</p></div></div>
|
||||
<el-button :loading="downloadingTemplate" @click="downloadImportTemplate"><Download :size="16" />下载模板</el-button>
|
||||
</section>
|
||||
<section class="import-step">
|
||||
<div class="step-heading"><span>2</span><div><strong>选择填写后的文件</strong><p>仅支持 .xlsx,最大 5MB、1000 行;本期只新增,不更新已有档案。</p></div></div>
|
||||
<label class="file-picker" :class="{ disabled: importing }">
|
||||
<input ref="fileInputRef" type="file" accept=".xlsx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" :disabled="importing" @change="selectImportFile" />
|
||||
<FileSpreadsheet :size="20" />
|
||||
<span>{{ importFile?.name || '选择 XLSX 文件' }}</span>
|
||||
</label>
|
||||
</section>
|
||||
|
||||
<el-alert type="info" :closable="false" show-icon title="整批校验通过后才会写入;任一行有误时整批不写入。" />
|
||||
<el-alert v-if="importError" type="error" :closable="false" show-icon title="导入请求失败">
|
||||
<p>{{ importError.message }}</p>
|
||||
<ApiErrorMeta :details="importError" />
|
||||
</el-alert>
|
||||
<el-alert v-if="importResult?.success" type="success" :closable="false" show-icon :title="`导入完成:成功新增 ${importResult.importedRows} 家快递公司`" />
|
||||
|
||||
<section v-if="importResult && !importResult.success" class="import-errors" aria-live="polite">
|
||||
<div class="error-heading">
|
||||
<div><strong>校验未通过,未写入任何数据</strong><p>发现 {{ importResult.errors.length }} 项问题,请修正后重新上传。</p></div>
|
||||
<el-button size="small" @click="downloadImportErrors"><Download :size="14" />下载错误报告</el-button>
|
||||
</div>
|
||||
<div class="error-list">
|
||||
<div v-for="(item, index) in displayedImportErrors" :key="`${item.row}-${item.field}-${index}`" class="error-item">
|
||||
<span>{{ item.row > 0 ? `第 ${item.row} 行` : '文件' }}</span>
|
||||
<strong>{{ item.field }}</strong>
|
||||
<p>{{ item.message }}</p>
|
||||
</div>
|
||||
<p v-if="importResult.errors.length > displayedImportErrors.length" class="error-overflow-note">
|
||||
仅展示前 {{ displayedImportErrors.length }} 项,完整内容请下载错误报告。
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button :disabled="importing" @click="importOpen = false">关闭</el-button>
|
||||
<el-button type="primary" :loading="importing" :disabled="!importFile" @click="submitImport"><Upload :size="16" />开始导入</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
entity-label="快递公司"
|
||||
success-unit="家"
|
||||
template-file-name="快递公司批量导入模板-v1.xlsx"
|
||||
error-report-file-name="快递公司导入错误报告.csv"
|
||||
:download-template="downloadPlatformExpressCompanyImportTemplate"
|
||||
:import-file="importPlatformExpressCompanies"
|
||||
@success="loadExpressCompanies"
|
||||
/>
|
||||
|
||||
<el-drawer v-model="editorOpen" :title="editorTitle" size="580px" class="business-drawer editor-drawer" :close-on-click-modal="false">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-position="top" class="drawer-form" :disabled="saving">
|
||||
@@ -528,32 +395,7 @@ onMounted(() => {
|
||||
.form-help code { color: #475467; font-family: "Cascadia Code", Consolas, monospace; }
|
||||
.panel-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
|
||||
.panel-actions .el-button { margin-left: 0; }
|
||||
.import-flow { display: grid; gap: 16px; }
|
||||
.import-step { display: flex; align-items: center; justify-content: space-between; gap: 20px; padding: 16px; border: 1px solid var(--cc-border); border-radius: 8px; background: #fafbfc; }
|
||||
.step-heading { display: flex; min-width: 0; align-items: flex-start; gap: 12px; }
|
||||
.step-heading > span { display: grid; width: 24px; height: 24px; flex: 0 0 24px; place-items: center; border-radius: 50%; background: var(--cc-primary); color: #fff; font-size: 12px; font-weight: 700; }
|
||||
.step-heading strong, .error-heading strong { color: var(--cc-text); font-size: 14px; }
|
||||
.step-heading p, .error-heading p { margin: 4px 0 0; color: var(--cc-muted); font-size: 12px; line-height: 1.55; }
|
||||
.file-picker { display: inline-flex; min-width: 180px; max-width: 260px; align-items: center; justify-content: center; gap: 8px; padding: 9px 14px; border: 1px solid var(--cc-border); border-radius: 6px; background: #fff; color: var(--cc-primary); cursor: pointer; }
|
||||
.file-picker:hover { border-color: var(--cc-primary); }
|
||||
.file-picker:focus-within { outline: 2px solid color-mix(in srgb, var(--cc-primary) 28%, transparent); outline-offset: 2px; }
|
||||
.file-picker.disabled { cursor: not-allowed; opacity: .6; }
|
||||
.file-picker input { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }
|
||||
.file-picker span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.import-flow .el-alert p { margin: 5px 0 0; }
|
||||
.import-errors { overflow: hidden; border: 1px solid #f4c7c7; border-radius: 8px; }
|
||||
.error-heading { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 14px 16px; background: #fff5f5; }
|
||||
.error-list { max-height: 220px; overflow: auto; }
|
||||
.error-item { display: grid; grid-template-columns: 72px 130px minmax(0, 1fr); gap: 10px; padding: 10px 16px; border-top: 1px solid #f4dddd; font-size: 12px; }
|
||||
.error-item span { color: #b42318; font-weight: 600; }
|
||||
.error-item p { margin: 0; overflow-wrap: anywhere; }
|
||||
.error-overflow-note { margin: 0; padding: 10px 16px; border-top: 1px solid #f4dddd; color: var(--cc-muted); font-size: 12px; }
|
||||
|
||||
@media (max-width: 720px) {
|
||||
.panel-actions, .panel-actions .el-button { width: 100%; }
|
||||
.import-step, .error-heading { align-items: stretch; flex-direction: column; }
|
||||
.file-picker, .import-step > .el-button { width: 100%; max-width: none; }
|
||||
.error-item { grid-template-columns: 64px minmax(0, 1fr); }
|
||||
.error-item p { grid-column: 1 / -1; }
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user