优化配送订单详情关联与参数展示
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
"gasorder-assignment:check": "node scripts/check-gasorder-assignment-linkage.mjs",
|
||||
"gasorder-list-display:check": "node scripts/check-gasorder-list-display.mjs",
|
||||
"gasorder-status-display:check": "node scripts/check-gasorder-status-display.mjs",
|
||||
"resource-detail-json:check": "node scripts/check-resource-detail-json-display.mjs",
|
||||
"product-ownership:check": "node scripts/check-product-ownership-action.mjs",
|
||||
"product-ownership-display:check": "node scripts/check-product-ownership-display.mjs",
|
||||
"product-lifecycle-display:check": "node scripts/check-product-lifecycle-display.mjs",
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
// 功能描述:静态校验配送订单列表优先显示可读创建方,并保留唯一标识复制入口。
|
||||
// 版本:v1.0.0
|
||||
// 版本:v1.1.0
|
||||
import fs from 'node:fs';
|
||||
|
||||
const resources = fs.readFileSync(new URL('../src/api/resources.ts', import.meta.url), 'utf8');
|
||||
const listPage = fs.readFileSync(new URL('../src/views/shared/CrudListPage.vue', import.meta.url), 'utf8');
|
||||
const detailPage = fs.readFileSync(new URL('../src/views/resource/ResourceDetailContent.vue', import.meta.url), 'utf8');
|
||||
const resourceDisplay = fs.readFileSync(new URL('../src/api/resource-display.ts', import.meta.url), 'utf8');
|
||||
|
||||
const assertions = [
|
||||
[resources.includes("gasorder_basic_identity: '配送订单唯一标识'"), '状态记录中的配送订单标识缺少中文名称'],
|
||||
@@ -13,6 +14,17 @@ const assertions = [
|
||||
[detailPage.includes("'contract_display_name'"), '订单详情未隐藏重复的合同标题辅助字段'],
|
||||
[detailPage.includes("column.endsWith('_at')) return 150"), '关联记录的日期时间列未固定为 150px'],
|
||||
[detailPage.includes("key.endsWith('_masked')"), '详情页未去除重复的脱敏辅助字段'],
|
||||
[detailPage.includes("'order_no',\n 'request_no',\n 'order_status'"), '订单详情未将订单号置于主要位置'],
|
||||
[detailPage.includes("'gasorder_basic.assignments'"), '分配记录缺少固定业务列'],
|
||||
[detailPage.includes("['assignments', 'items', 'statuses'].includes(key)"), '订单关联表仍会泄漏任意英文响应字段'],
|
||||
[detailPage.includes("'gasorder_basic.statuses'"), '状态记录缺少固定中文业务列'],
|
||||
[resourceDisplay.includes("active: '是否有效'"), '订单明细 active 字段未中文化'],
|
||||
[resourceDisplay.includes("String(value) === 'order created'"), '历史订单创建原因未中文化'],
|
||||
[detailPage.includes("creator_identity: 'creator_display_name'"), '订单创建方未使用可读名称'],
|
||||
[resourceDisplay.includes("'gasorder_basic.assignments'"), '分配记录缺少专用中文字段名称'],
|
||||
[resourceDisplay.includes("staff_account_display_name: '配送人员'"), '分配人员名称未中文化'],
|
||||
[resourceDisplay.includes("identity: '系统唯一标识'"), '订单内部标识仍与业务订单号混用'],
|
||||
[resourceDisplay.includes("operator_identity: '建单操作人'"), '建单操作人仍以裸标识单独展示'],
|
||||
[resources.includes("listDisplayKey: 'creator_display_name'"), '创建方未配置可读名称字段'],
|
||||
[resources.includes('listDisplayIdentityCopy: true'), '创建方未保留唯一标识复制入口'],
|
||||
[resources.includes("detailDisplayKey: 'contract_display_name'"), '订单详情未配置合同标题展示字段'],
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* 功能:静态检查资源详情关联表中的设备参数可完整查看且不会撑宽表格。
|
||||
* 版本:v1.1.0
|
||||
*/
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
|
||||
const detail = readFileSync(
|
||||
new URL('../src/views/resource/ResourceDetailContent.vue', import.meta.url),
|
||||
'utf8',
|
||||
);
|
||||
|
||||
assert.match(detail, /isCollectionJsonColumn\(column\)/, '关联表 JSON 字段缺少专用展示分支');
|
||||
assert.match(detail, />查看参数<\/a-button>/, '设备参数缺少完整查看入口');
|
||||
assert.match(detail, /formatCollectionJson\(record\[column\]\)/, '设备参数没有格式化完整内容');
|
||||
assert.match(detail, /JSON\.stringify\(JSON\.parse\(text\), null, 2\)/, '字符串 JSON 未格式化');
|
||||
assert.match(detail, /isCollectionJsonColumn\(column\)\) return 100/, '设备参数列未使用紧凑宽度');
|
||||
assert.match(detail, /max-width: min\(560px, 70vw\)/, '参数浮层缺少视口宽度限制');
|
||||
assert.match(detail, /class="collection-table-shell"/, '关联表缺少独立宽度约束容器');
|
||||
assert.match(detail, /\.detail-stack[\s\S]*?min-width: 0;/, '详情栈仍可能被子内容反向撑宽');
|
||||
assert.match(detail, /\.collection-table-shell[\s\S]*?overflow-x: auto;/, '关联表缺少内部横向溢出兜底');
|
||||
|
||||
console.log('资源详情设备参数检查通过:100% 视口不被关联表撑宽,参数可完整查看。');
|
||||
@@ -1,15 +1,15 @@
|
||||
/**
|
||||
* 功能:统一资源列表与详情页面的字段名称、关系、金额、状态和时间展示。
|
||||
* 版本:v1.4.0
|
||||
* 版本:v1.5.0
|
||||
*/
|
||||
import dayjs from 'dayjs';
|
||||
import type { RecordPageMode, ResourceRow } from './resource-page-rules';
|
||||
import { staffRoleLabel } from './resource-staff-relation';
|
||||
import {
|
||||
defaultResourceFieldLabel,
|
||||
type ResourceField,
|
||||
type ResourceUiDefinition,
|
||||
} from './resources';
|
||||
import type { RecordPageMode, ResourceRow } from './resource-page-rules';
|
||||
|
||||
const aliases: Record<string, string> = {
|
||||
identity: '唯一标识',
|
||||
@@ -54,6 +54,35 @@ const collectionFieldAliases: Record<string, Record<string, string>> = {
|
||||
product_type_name: '设备类型',
|
||||
product_params: '设备参数',
|
||||
unit_price: '成交单价(元)',
|
||||
active: '是否有效',
|
||||
},
|
||||
'gasorder_basic.assignments': {
|
||||
assigned_at: '分配时间',
|
||||
gas_basic_display_name: '气站',
|
||||
delivery_basic_display_name: '配送点',
|
||||
staff_account_display_name: '配送人员',
|
||||
assigner_name: '分配人',
|
||||
reason: '分配原因',
|
||||
},
|
||||
'gasorder_basic.statuses': {
|
||||
occurred_at: '发生时间',
|
||||
from_status: '原状态',
|
||||
to_status: '新状态',
|
||||
operator_name: '操作人',
|
||||
reason: '原因',
|
||||
},
|
||||
};
|
||||
|
||||
/** 主资源详情中的关联标识使用业务名称,技术标识仅作为辅助复制信息。 */
|
||||
const resourceFieldAliases: Record<string, Record<string, string>> = {
|
||||
gasorder_basic: {
|
||||
identity: '系统唯一标识',
|
||||
gas_basic_identity: '履约气站',
|
||||
delivery_basic_identity: '当前配送点',
|
||||
staff_account_identity: '当前配送人员',
|
||||
user_account_identity: '服务用户',
|
||||
creator_identity: '创建方',
|
||||
operator_identity: '建单操作人',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -107,6 +136,9 @@ export function resourceFieldLabel(
|
||||
return (
|
||||
collectionAliases?.[normalized] ??
|
||||
definition.fields.find((field) => field.key === normalized)?.label ??
|
||||
(collectionKey
|
||||
? undefined
|
||||
: resourceFieldAliases[definition.name]?.[normalized]) ??
|
||||
defaultResourceFieldLabel(normalized) ??
|
||||
aliases[normalized] ??
|
||||
key
|
||||
@@ -186,9 +218,10 @@ export function relationOptionLabel(
|
||||
const configuredLabel = field.relationOptionLabelKey
|
||||
? option[field.relationOptionLabelKey]
|
||||
: undefined;
|
||||
const label = configuredLabel == null || configuredLabel === ''
|
||||
? optionLabel(option)
|
||||
: String(configuredLabel);
|
||||
const label =
|
||||
configuredLabel == null || configuredLabel === ''
|
||||
? optionLabel(option)
|
||||
: String(configuredLabel);
|
||||
if (
|
||||
field.relationOptionDefaultKey &&
|
||||
option[field.relationOptionDefaultKey]
|
||||
@@ -253,7 +286,15 @@ export function displayRawValue(key: string, value: unknown) {
|
||||
if (key === 'status') return recordStatusLabel(Number(value));
|
||||
if (key === 'contract_status') return contractStatusLabel(Number(value));
|
||||
if (key === 'previous_order_status' && Number(value) === 0) return '无';
|
||||
if (['order_status', 'previous_order_status', 'from_status', 'to_status'].includes(key))
|
||||
if (key === 'reason' && String(value) === 'order created') return '订单创建';
|
||||
if (
|
||||
[
|
||||
'order_status',
|
||||
'previous_order_status',
|
||||
'from_status',
|
||||
'to_status',
|
||||
].includes(key)
|
||||
)
|
||||
return gasorderStatusLabel(Number(value));
|
||||
if (key === 'action') {
|
||||
return (
|
||||
@@ -301,7 +342,9 @@ export function displayResourceField(
|
||||
Array<{ label: string; value: string | number }>
|
||||
> = {},
|
||||
) {
|
||||
const displayValue = field.detailDisplayKey ? row[field.detailDisplayKey] : undefined;
|
||||
const displayValue = field.detailDisplayKey
|
||||
? row[field.detailDisplayKey]
|
||||
: undefined;
|
||||
const value = displayValue ?? row[field.key] ?? row[`${field.key}_masked`];
|
||||
if (value == null || value === '') return field.emptyText ?? '-';
|
||||
const hasOptionSource =
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<!--
|
||||
功能:以响应式信息卡和子表页签展示标准资源详情。
|
||||
版本:v1.4.0
|
||||
版本:v1.7.0
|
||||
-->
|
||||
<template>
|
||||
<div class="detail-stack">
|
||||
@@ -22,23 +22,38 @@
|
||||
<a-card v-if="collections.length" title="关联记录" :bordered="false" class="detail-card">
|
||||
<a-tabs>
|
||||
<a-tab-pane v-for="collection in collections" :key="collection.key" :title="collection.title">
|
||||
<a-table :data="collection.rows" :pagination="false" size="small" table-layout-fixed>
|
||||
<template #columns>
|
||||
<a-table-column
|
||||
v-for="column in collection.columns"
|
||||
:key="column"
|
||||
:title="resourceFieldLabel(definition, column, collection.key)"
|
||||
:width="collectionColumnWidth(column)"
|
||||
ellipsis
|
||||
tooltip
|
||||
>
|
||||
<template #cell="{ record }">
|
||||
<IdentityText v-if="column.includes('identity') && record[column]" :value="String(record[column])" />
|
||||
<template v-else>{{ displayRawValue(column, record[column]) }}</template>
|
||||
</template>
|
||||
</a-table-column>
|
||||
</template>
|
||||
</a-table>
|
||||
<div class="collection-table-shell">
|
||||
<a-table :data="collection.rows" :pagination="false" size="small" table-layout-fixed>
|
||||
<template #columns>
|
||||
<a-table-column
|
||||
v-for="column in collection.columns"
|
||||
:key="column"
|
||||
:title="resourceFieldLabel(definition, column, collection.key)"
|
||||
:width="collectionColumnWidth(column)"
|
||||
ellipsis
|
||||
tooltip
|
||||
>
|
||||
<template #cell="{ record }">
|
||||
<div v-if="collectionRelationIdentityKey(collection.key, column)" class="collection-relation-value">
|
||||
<span>{{ displayRawValue(column, record[column]) }}</span>
|
||||
<IdentityText
|
||||
v-if="record[collectionRelationIdentityKey(collection.key, column)]"
|
||||
:value="String(record[collectionRelationIdentityKey(collection.key, column)])"
|
||||
/>
|
||||
</div>
|
||||
<IdentityText v-else-if="column.includes('identity') && record[column]" :value="String(record[column])" />
|
||||
<a-popover v-else-if="isCollectionJsonColumn(column)" position="left">
|
||||
<a-button type="text" size="mini">查看参数</a-button>
|
||||
<template #content>
|
||||
<pre class="collection-json-value">{{ formatCollectionJson(record[column]) }}</pre>
|
||||
</template>
|
||||
</a-popover>
|
||||
<template v-else>{{ displayRawValue(column, record[column]) }}</template>
|
||||
</template>
|
||||
</a-table-column>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-card>
|
||||
@@ -47,7 +62,6 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import IdentityText from '@/components/IdentityText.vue';
|
||||
import {
|
||||
displayRawValue,
|
||||
displayResourceField,
|
||||
@@ -55,8 +69,9 @@ import {
|
||||
primaryRecord,
|
||||
resourceFieldLabel,
|
||||
} from '@/api/resource-display';
|
||||
import type { ResourceUiDefinition } from '@/api/resources';
|
||||
import type { ResourceRow } from '@/api/resource-page-rules';
|
||||
import type { ResourceUiDefinition } from '@/api/resources';
|
||||
import IdentityText from '@/components/IdentityText.vue';
|
||||
|
||||
const props = defineProps<{
|
||||
definition: ResourceUiDefinition;
|
||||
@@ -82,9 +97,55 @@ type DetailEntry = {
|
||||
function collectionColumnWidth(column: string) {
|
||||
if (column.endsWith('_at')) return 150;
|
||||
if (column.includes('identity')) return 220;
|
||||
if (isCollectionJsonColumn(column)) return 100;
|
||||
return 160;
|
||||
}
|
||||
|
||||
/** 标识关联子表中需要完整查看的 JSON 快照字段。 */
|
||||
function isCollectionJsonColumn(column: string) {
|
||||
return column === 'product_params';
|
||||
}
|
||||
|
||||
/** 将字符串或对象参数格式化为可读 JSON;历史非 JSON 文本保持原样。 */
|
||||
function formatCollectionJson(value: unknown) {
|
||||
if (value == null || value === '') return '暂无参数';
|
||||
if (typeof value === 'object') return JSON.stringify(value, null, 2);
|
||||
const text = String(value).trim();
|
||||
if (!text) return '暂无参数';
|
||||
try {
|
||||
return JSON.stringify(JSON.parse(text), null, 2);
|
||||
} catch {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
/** 返回集合可读名称对应的稳定标识字段。 */
|
||||
function collectionRelationIdentityKey(collectionKey: string, column: string) {
|
||||
if (collectionKey !== 'assignments') return '';
|
||||
return (
|
||||
{
|
||||
gas_basic_display_name: 'gas_basic_identity',
|
||||
delivery_basic_display_name: 'delivery_basic_identity',
|
||||
staff_account_display_name: 'staff_account_identity',
|
||||
}[column] ?? ''
|
||||
);
|
||||
}
|
||||
|
||||
/** 返回订单详情关联标识对应的服务端可读名称字段。 */
|
||||
function detailRelationDisplayName(row: ResourceRow, key: string) {
|
||||
const displayKey =
|
||||
{
|
||||
creator_identity: 'creator_display_name',
|
||||
user_account_identity: 'user_account_display_name',
|
||||
gas_basic_identity: 'gas_basic_display_name',
|
||||
delivery_basic_identity: 'delivery_basic_display_name',
|
||||
staff_account_identity: 'staff_account_display_name',
|
||||
operator_identity: 'operator_name',
|
||||
}[key] ?? '';
|
||||
if (!displayKey) return '';
|
||||
return String(row[displayKey] ?? '').trim();
|
||||
}
|
||||
|
||||
const entries = computed<DetailEntry[]>(() => {
|
||||
const row = primaryRecord(props.detail);
|
||||
const excluded = new Set([
|
||||
@@ -99,9 +160,25 @@ const entries = computed<DetailEntry[]>(() => {
|
||||
if (props.accountSummary) {
|
||||
for (const key of ['username', 'identity', 'created_at']) excluded.add(key);
|
||||
}
|
||||
const leadingKeys =
|
||||
props.definition.name === 'gasorder_basic'
|
||||
? [
|
||||
'order_no',
|
||||
'request_no',
|
||||
'order_status',
|
||||
'gasorder_contract_identity',
|
||||
'creator_type',
|
||||
'creator_identity',
|
||||
'user_account_identity',
|
||||
'gas_basic_identity',
|
||||
'delivery_basic_identity',
|
||||
'staff_account_identity',
|
||||
'identity',
|
||||
'status',
|
||||
]
|
||||
: ['identity', 'status'];
|
||||
const preferred = [
|
||||
'identity',
|
||||
'status',
|
||||
...leadingKeys,
|
||||
...props.definition.fields.map((field) => field.key),
|
||||
'created_at',
|
||||
'updated_at',
|
||||
@@ -120,20 +197,30 @@ const entries = computed<DetailEntry[]>(() => {
|
||||
: Object.prototype.hasOwnProperty.call(row, maskedKey)
|
||||
? maskedKey
|
||||
: '';
|
||||
if (!actualKey || excluded.has(key) || key.endsWith('_id')) return [];
|
||||
if (
|
||||
!actualKey ||
|
||||
excluded.has(key) ||
|
||||
key.endsWith('_id') ||
|
||||
key.endsWith('_display_name') ||
|
||||
(props.definition.name === 'gasorder_basic' && key === 'operator_name')
|
||||
)
|
||||
return [];
|
||||
const value = row[actualKey];
|
||||
if (Array.isArray(value)) return [];
|
||||
if (['deleted_at', 'DeletedAt'].includes(key) && isEmptyDeletedAt(value))
|
||||
return [];
|
||||
const field = props.definition.fields.find((item) => item.key === key);
|
||||
const display = field
|
||||
? displayResourceField(
|
||||
field,
|
||||
row,
|
||||
props.relationOptions,
|
||||
props.fieldOptions,
|
||||
)
|
||||
: displayRawValue(actualKey, value);
|
||||
const relationDisplayName = detailRelationDisplayName(row, key);
|
||||
const display = relationDisplayName
|
||||
? relationDisplayName
|
||||
: field
|
||||
? displayResourceField(
|
||||
field,
|
||||
row,
|
||||
props.relationOptions,
|
||||
props.fieldOptions,
|
||||
)
|
||||
: displayRawValue(actualKey, value);
|
||||
const objectValue = typeof value === 'object' && value !== null;
|
||||
return [
|
||||
{
|
||||
@@ -142,7 +229,10 @@ const entries = computed<DetailEntry[]>(() => {
|
||||
value: display,
|
||||
objectValue,
|
||||
identityValue:
|
||||
(field?.showIdentityCopy || field?.staffRelation?.showIdentityCopy) && value
|
||||
(relationDisplayName ||
|
||||
field?.showIdentityCopy ||
|
||||
field?.staffRelation?.showIdentityCopy) &&
|
||||
value
|
||||
? String(value)
|
||||
: '',
|
||||
wide:
|
||||
@@ -188,13 +278,31 @@ const collections = computed(() =>
|
||||
'product_type_name',
|
||||
'product_params',
|
||||
'unit_price',
|
||||
'active',
|
||||
'product_info_identity',
|
||||
],
|
||||
'gasorder_basic.assignments': [
|
||||
'assigned_at',
|
||||
'gas_basic_display_name',
|
||||
'delivery_basic_display_name',
|
||||
'staff_account_display_name',
|
||||
'assigner_name',
|
||||
'reason',
|
||||
],
|
||||
'gasorder_basic.statuses': [
|
||||
'occurred_at',
|
||||
'from_status',
|
||||
'to_status',
|
||||
'operator_name',
|
||||
'reason',
|
||||
],
|
||||
};
|
||||
const preferred =
|
||||
preferredColumns[`${props.definition.name}.${key}`] ?? [];
|
||||
const columns = [...new Set([...preferred, ...availableColumns])]
|
||||
const fixedColumns = ['assignments', 'items', 'statuses'].includes(key);
|
||||
const columns = (
|
||||
fixedColumns
|
||||
? preferred
|
||||
: [...new Set([...preferred, ...availableColumns])]
|
||||
)
|
||||
.filter((column) => availableColumns.includes(column))
|
||||
.slice(0, 8);
|
||||
return {
|
||||
@@ -210,9 +318,15 @@ const collections = computed(() =>
|
||||
<style scoped lang="less">
|
||||
.detail-stack {
|
||||
display: grid;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
gap: 12px;
|
||||
}
|
||||
.detail-card {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.detail-card :deep(.arco-card-header) {
|
||||
@@ -220,8 +334,15 @@ const collections = computed(() =>
|
||||
padding: 0 24px;
|
||||
}
|
||||
.detail-card :deep(.arco-card-body) {
|
||||
min-width: 0;
|
||||
padding: 20px 24px;
|
||||
}
|
||||
.detail-card :deep(.arco-tabs),
|
||||
.detail-card :deep(.arco-tabs-content),
|
||||
.detail-card :deep(.arco-tabs-pane) {
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
.detail-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
@@ -237,6 +358,11 @@ const collections = computed(() =>
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px solid var(--color-border-1);
|
||||
}
|
||||
.detail-item,
|
||||
.detail-value,
|
||||
.detail-relation-value {
|
||||
min-width: 0;
|
||||
}
|
||||
.detail-item-wide {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
@@ -263,6 +389,28 @@ const collections = computed(() =>
|
||||
border-radius: 6px;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.collection-json-value {
|
||||
min-width: 280px;
|
||||
max-width: min(560px, 70vw);
|
||||
max-height: 360px;
|
||||
margin: 0;
|
||||
overflow: auto;
|
||||
color: var(--color-text-1);
|
||||
font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
.collection-table-shell {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
.collection-relation-value {
|
||||
display: grid;
|
||||
min-width: 0;
|
||||
gap: 2px;
|
||||
}
|
||||
@media (max-width: 1280px) {
|
||||
.detail-grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
/*
|
||||
* 功能:定义标准资源独立页面的布局、卡片和响应式样式。
|
||||
* 版本:v1.3.0
|
||||
* 版本:v1.4.0
|
||||
*/
|
||||
.record-page {
|
||||
display: grid;
|
||||
align-content: start;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
gap: 12px;
|
||||
min-height: 100%;
|
||||
padding: 16px 20px 20px;
|
||||
@@ -25,6 +28,8 @@
|
||||
}
|
||||
.section-card,
|
||||
.form-card {
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.section-card :deep(.arco-card-header) {
|
||||
|
||||
Reference in New Issue
Block a user