迁移托盘追溯模块
This commit is contained in:
31
docs/功能测试-托盘追溯.md
Normal file
31
docs/功能测试-托盘追溯.md
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# 功能测试 - 托盘追溯
|
||||||
|
|
||||||
|
> 模块:数据中台 / 基础追溯 / 托盘追溯 (Tray Traceability)
|
||||||
|
> 路由:`/data_middleground/produce/traceability/tray`
|
||||||
|
|
||||||
|
## 测试前置条件
|
||||||
|
|
||||||
|
- 测试账号具备访问“托盘追溯”和“电池追溯”的菜单权限。
|
||||||
|
- 准备至少 1 个存在电池明细和工序时间线的托盘号。
|
||||||
|
- 后端接口 `tray`、`traydetail`、`batteryactive` 可正常访问。
|
||||||
|
|
||||||
|
## 测试任务列表
|
||||||
|
|
||||||
|
| 序号 | 测试项 | 操作步骤 | 预期结果 |
|
||||||
|
|---:|---|---|---|
|
||||||
|
| 1 | 页面入口 | 进入“托盘追溯”页面 | 页面显示托盘号输入框、查询、重置按钮和托盘列表 |
|
||||||
|
| 2 | 托盘查询 | 输入有效托盘号并查询 | 表格展示托盘、批次、LOT、激活状态、投入电池数和时间信息 |
|
||||||
|
| 3 | 空数据查询 | 输入无数据托盘号并查询 | 表格显示空态,页面不报错 |
|
||||||
|
| 4 | 打开电池明细 | 点击某行“电池明细” | 打开全屏抽屉,展示左侧工序时间线和右侧电池明细表 |
|
||||||
|
| 5 | 明细搜索 | 在抽屉内输入电池条码关键字 | 明细表按电池条码过滤 |
|
||||||
|
| 6 | 取消激活校验 | 不选择电池,点击取消电池激活 | 页面提示请至少选择一个电池 |
|
||||||
|
| 7 | 取消激活 | 选择一个或多个电池后点击取消电池激活 | 调用取消激活接口,成功后刷新明细 |
|
||||||
|
| 8 | 跳转电池追溯 | 点击明细中的电池条码 | 跳转到电池追溯页面并携带 battery_id 查询参数 |
|
||||||
|
| 9 | 重置功能 | 查询后点击重置 | 托盘号、列表和分页状态清空 |
|
||||||
|
| 10 | 国际化检查 | 切换中英文语言后重新进入页面 | 页面按钮、表格列和抽屉文案随语言切换显示 |
|
||||||
|
|
||||||
|
## 回归关注点
|
||||||
|
|
||||||
|
- 电池明细过滤需要排除空电池条码和 0。
|
||||||
|
- 取消激活接口参数 `batterData` 必须是已选择电池数组的 JSON 字符串。
|
||||||
|
- 电池条码跳转需保留 `battery_id` 查询参数。
|
||||||
@@ -3,8 +3,8 @@
|
|||||||
> 根据 `后台Webman界面截图对照表.md` 生成。状态以当前 V2 项目中已落地的页面目录为准。
|
> 根据 `后台Webman界面截图对照表.md` 生成。状态以当前 V2 项目中已落地的页面目录为准。
|
||||||
|
|
||||||
- 总功能数:79
|
- 总功能数:79
|
||||||
- 已迁移:30
|
- 已迁移:31
|
||||||
- 未迁移:49
|
- 未迁移:48
|
||||||
|
|
||||||
| 状态 | 一级模块 | 二级模块 | 三级模块 | 功能说明 | V2 目标路径 |
|
| 状态 | 一级模块 | 二级模块 | 三级模块 | 功能说明 | V2 目标路径 |
|
||||||
|:---:|---|---|---|---|---|
|
|:---:|---|---|---|---|---|
|
||||||
@@ -82,7 +82,7 @@
|
|||||||
| ✅ | 数据中台 (Data Platform) | 基础追溯 (Traceability) | 反向追溯 (Backward Traceability) | 反向追溯 | `src/views/data-platform/traceability/backward/` |
|
| ✅ | 数据中台 (Data Platform) | 基础追溯 (Traceability) | 反向追溯 (Backward Traceability) | 反向追溯 | `src/views/data-platform/traceability/backward/` |
|
||||||
| ✅ | 数据中台 (Data Platform) | 基础追溯 (Traceability) | 正向追溯 (Forward Traceability) | 正向追溯 | `src/views/data-platform/traceability/forward/` |
|
| ✅ | 数据中台 (Data Platform) | 基础追溯 (Traceability) | 正向追溯 (Forward Traceability) | 正向追溯 | `src/views/data-platform/traceability/forward/` |
|
||||||
| ✅ | 数据中台 (Data Platform) | 基础追溯 (Traceability) | 电池曲线 (Battery Curve) | 电池曲线 | `src/views/data-platform/traceability/battery-curve/` |
|
| ✅ | 数据中台 (Data Platform) | 基础追溯 (Traceability) | 电池曲线 (Battery Curve) | 电池曲线 | `src/views/data-platform/traceability/battery-curve/` |
|
||||||
| ⬜ | 数据中台 (Data Platform) | 基础追溯 (Traceability) | 托盘追溯 (Tray Traceability) | | 待确认 |
|
| ✅ | 数据中台 (Data Platform) | 基础追溯 (Traceability) | 托盘追溯 (Tray Traceability) | 托盘追溯 | `src/views/data-platform/traceability/tray/` |
|
||||||
| ⬜ | 数据中台 (Data Platform) | 基础追溯 (Traceability) | 电池追溯 (Battery Traceability) | | 待确认 |
|
| ⬜ | 数据中台 (Data Platform) | 基础追溯 (Traceability) | 电池追溯 (Battery Traceability) | | 待确认 |
|
||||||
| ⬜ | 数据中台 (Data Platform) | 生产报表 (Production Reports) | 设备履历报表 (Equipment History Report) | | 待确认 |
|
| ⬜ | 数据中台 (Data Platform) | 生产报表 (Production Reports) | 设备履历报表 (Equipment History Report) | | 待确认 |
|
||||||
| ⬜ | 数据中台 (Data Platform) | 生产报表 (Production Reports) | 电池详情报表 (Battery Detail Report) | | 待确认 |
|
| ⬜ | 数据中台 (Data Platform) | 生产报表 (Production Reports) | 电池详情报表 (Battery Detail Report) | | 待确认 |
|
||||||
|
|||||||
31
src/api/data-platform/traceability/tray.js
Normal file
31
src/api/data-platform/traceability/tray.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { request } from '@/api/_service'
|
||||||
|
|
||||||
|
const BASE = 'planning_production/produce/traceability/'
|
||||||
|
|
||||||
|
function apiParams (method, data = {}) {
|
||||||
|
return { method, platform: 'background', ...data }
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTrayTraceList (data) {
|
||||||
|
return request({
|
||||||
|
url: BASE + 'tray',
|
||||||
|
method: 'get',
|
||||||
|
params: apiParams('planning_production_produce_traceability_tray', data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTrayTraceDetail (data) {
|
||||||
|
return request({
|
||||||
|
url: BASE + 'traydetail',
|
||||||
|
method: 'get',
|
||||||
|
params: apiParams('planning_production_produce_traceability_traydetail', data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function cancelTraceBatteryActive (data) {
|
||||||
|
return request({
|
||||||
|
url: BASE + 'batteryactive',
|
||||||
|
method: 'get',
|
||||||
|
params: apiParams('planning_production_produce_traceability_batteryactive', data)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1268,6 +1268,42 @@
|
|||||||
"current": "Current",
|
"current": "Current",
|
||||||
"voltage": "Voltage",
|
"voltage": "Voltage",
|
||||||
"capacity": "Capacity"
|
"capacity": "Capacity"
|
||||||
|
},
|
||||||
|
"tray": {
|
||||||
|
"query": "Search",
|
||||||
|
"reset": "Reset",
|
||||||
|
"tray_code": "Tray No.",
|
||||||
|
"tray_code_placeholder": "Enter tray no.",
|
||||||
|
"data_empty": "No data",
|
||||||
|
"id": "ID",
|
||||||
|
"tray": "Tray",
|
||||||
|
"login_batch": "Login Batch",
|
||||||
|
"lot": "LOT",
|
||||||
|
"is_active": "Active",
|
||||||
|
"active": "Active",
|
||||||
|
"inactive": "Inactive",
|
||||||
|
"input_battery_count": "Input Battery Count",
|
||||||
|
"login_time": "Login Time",
|
||||||
|
"cancel_active_time": "Cancel Active Time",
|
||||||
|
"battery_detail": "Battery Detail",
|
||||||
|
"battery_detail_data": "Battery Detail Data",
|
||||||
|
"process": "Process",
|
||||||
|
"start_time": "Start Time",
|
||||||
|
"end_time": "End Time",
|
||||||
|
"device_no": "Device No.",
|
||||||
|
"battery_id": "Battery Barcode",
|
||||||
|
"search_battery_id": "Search battery barcode",
|
||||||
|
"cancel_battery_active": "Cancel Battery Active",
|
||||||
|
"sort": "No.",
|
||||||
|
"production_batch": "Production Batch",
|
||||||
|
"model": "Model",
|
||||||
|
"process_flow_name": "Process Flow Name",
|
||||||
|
"tray_no": "Tray No.",
|
||||||
|
"activation_status": "Activation Status",
|
||||||
|
"category": "Category",
|
||||||
|
"grade": "Grade",
|
||||||
|
"please_select_at_least_one_battery": "Select at least one battery",
|
||||||
|
"cancel_success": "Cancel active successfully"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1268,6 +1268,42 @@
|
|||||||
"current": "电流",
|
"current": "电流",
|
||||||
"voltage": "电压",
|
"voltage": "电压",
|
||||||
"capacity": "容量"
|
"capacity": "容量"
|
||||||
|
},
|
||||||
|
"tray": {
|
||||||
|
"query": "查询",
|
||||||
|
"reset": "重置",
|
||||||
|
"tray_code": "托盘号",
|
||||||
|
"tray_code_placeholder": "请输入托盘号",
|
||||||
|
"data_empty": "暂无数据",
|
||||||
|
"id": "ID",
|
||||||
|
"tray": "托盘",
|
||||||
|
"login_batch": "登录批次",
|
||||||
|
"lot": "LOT",
|
||||||
|
"is_active": "是否激活",
|
||||||
|
"active": "激活",
|
||||||
|
"inactive": "未激活",
|
||||||
|
"input_battery_count": "投入电池数",
|
||||||
|
"login_time": "登录时间",
|
||||||
|
"cancel_active_time": "取消激活时间",
|
||||||
|
"battery_detail": "电池明细",
|
||||||
|
"battery_detail_data": "电池明细数据",
|
||||||
|
"process": "工序",
|
||||||
|
"start_time": "开始时间",
|
||||||
|
"end_time": "结束时间",
|
||||||
|
"device_no": "设备编号",
|
||||||
|
"battery_id": "电池条码",
|
||||||
|
"search_battery_id": "搜索电池条码",
|
||||||
|
"cancel_battery_active": "取消电池激活",
|
||||||
|
"sort": "序号",
|
||||||
|
"production_batch": "生产批次",
|
||||||
|
"model": "型号",
|
||||||
|
"process_flow_name": "工艺流程名称",
|
||||||
|
"tray_no": "托盘号",
|
||||||
|
"activation_status": "激活状态",
|
||||||
|
"category": "类别",
|
||||||
|
"grade": "等级",
|
||||||
|
"please_select_at_least_one_battery": "请至少选择一个电池",
|
||||||
|
"cancel_success": "取消激活成功"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,12 @@ export default {
|
|||||||
name: `${pre}traceability-curve`,
|
name: `${pre}traceability-curve`,
|
||||||
meta: { ...meta, cache: true, title: '电池曲线' },
|
meta: { ...meta, cache: true, title: '电池曲线' },
|
||||||
component: _import('data-platform/traceability/battery-curve')
|
component: _import('data-platform/traceability/battery-curve')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'produce/traceability/tray',
|
||||||
|
name: `${pre}traceability-tray`,
|
||||||
|
meta: { ...meta, cache: true, title: '托盘追溯' },
|
||||||
|
component: _import('data-platform/traceability/tray')
|
||||||
}
|
}
|
||||||
])('data_middleground-')
|
])('data_middleground-')
|
||||||
}
|
}
|
||||||
|
|||||||
199
src/views/data-platform/traceability/tray/index.vue
Normal file
199
src/views/data-platform/traceability/tray/index.vue
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
<template>
|
||||||
|
<d2-container>
|
||||||
|
<template #header>
|
||||||
|
<div class="search-bar">
|
||||||
|
<el-form ref="searchForm" :inline="true" :model="search" size="mini">
|
||||||
|
<el-form-item :label="$t(key('tray_code'))" prop="tray_id">
|
||||||
|
<el-input v-model.trim="search.tray_id" :placeholder="$t(key('tray_code_placeholder'))" clearable style="width:220px" @keyup.enter.native="fetchData" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="el-icon-search" :disabled="loading" @click="fetchData">{{ $t(key('query')) }}</el-button>
|
||||||
|
<el-button icon="el-icon-refresh" :disabled="loading" @click="resetSearch">{{ $t(key('reset')) }}</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<page-table
|
||||||
|
:columns="columns"
|
||||||
|
:data="tableData"
|
||||||
|
:loading="loading"
|
||||||
|
:toolbar-buttons="[]"
|
||||||
|
:row-buttons="rowButtons"
|
||||||
|
:pagination="pagination"
|
||||||
|
:table-attrs="{ size: 'mini', rowKey: 'id', highlightCurrentRow: true }"
|
||||||
|
auto-height
|
||||||
|
@page-change="onPageChange"
|
||||||
|
>
|
||||||
|
<template #col-active="{ row }">
|
||||||
|
<el-tag :type="Number(row.active) === 1 ? 'success' : 'info'" size="mini">
|
||||||
|
{{ Number(row.active) === 1 ? $t(key('active')) : $t(key('inactive')) }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
<template #empty>
|
||||||
|
<el-empty :description="$t(key('data_empty'))" :image-size="80" />
|
||||||
|
</template>
|
||||||
|
</page-table>
|
||||||
|
|
||||||
|
<el-drawer :visible.sync="detailVisible" :with-header="false" size="100%" append-to-body>
|
||||||
|
<div class="drawer-header">
|
||||||
|
<el-page-header @back="detailVisible = false" :content="$t(key('battery_detail_data'))" />
|
||||||
|
</div>
|
||||||
|
<div class="detail-layout">
|
||||||
|
<aside v-if="timeLine.length" class="detail-timeline">
|
||||||
|
<el-timeline>
|
||||||
|
<el-timeline-item v-for="(item, index) in timeLine" :key="index">
|
||||||
|
<p>{{ $t(key('process')) }}: {{ item.process_name || '-' }}</p>
|
||||||
|
<el-card shadow="never">
|
||||||
|
<p>{{ $t(key('start_time')) }}: {{ item.beginTime || '-' }}</p>
|
||||||
|
<p>{{ $t(key('end_time')) }}: {{ item.endTime || '-' }}</p>
|
||||||
|
<p>{{ $t(key('device_no')) }}: {{ item.device_code || '-' }}</p>
|
||||||
|
</el-card>
|
||||||
|
</el-timeline-item>
|
||||||
|
</el-timeline>
|
||||||
|
</aside>
|
||||||
|
<main class="detail-main">
|
||||||
|
<el-form :inline="true" :model="detailSearch" size="mini">
|
||||||
|
<el-form-item :label="$t(key('battery_id'))">
|
||||||
|
<el-input v-model.trim="detailSearch.battery_id" :placeholder="$t(key('search_battery_id'))" clearable style="width:220px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="el-icon-close" @click="cancelBatteryActive">{{ $t(key('cancel_battery_active')) }}</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-table :data="filteredDetails" border size="mini" height="calc(100vh - 170px)" @selection-change="selection = $event">
|
||||||
|
<el-table-column type="selection" width="48" />
|
||||||
|
<el-table-column prop="id" :label="$t(key('sort'))" width="70" />
|
||||||
|
<el-table-column prop="battery_id" :label="$t(key('battery_id'))" min-width="180" show-overflow-tooltip>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-link type="primary" @click="goBatteryTrace(scope.row.battery_id)">{{ scope.row.battery_id }}</el-link>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="batch" :label="$t(key('production_batch'))" min-width="140" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="model" :label="$t(key('model'))" min-width="120" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="flow_name" :label="$t(key('process_flow_name'))" min-width="160" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="tray" :label="$t(key('tray_no'))" min-width="130" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="lot" :label="$t(key('lot'))" min-width="120" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="active" :label="$t(key('activation_status'))" min-width="120" />
|
||||||
|
<el-table-column prop="class" :label="$t(key('category'))" min-width="120" />
|
||||||
|
<el-table-column prop="classname" :label="$t(key('grade'))" min-width="120" />
|
||||||
|
</el-table>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</el-drawer>
|
||||||
|
</d2-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { useTableColumns } from '@/composables/useTableColumns'
|
||||||
|
import { i18nMixin } from '@/composables/useI18n'
|
||||||
|
import PageTable from '@/components/page-table'
|
||||||
|
import { cancelTraceBatteryActive, getTrayTraceDetail, getTrayTraceList } from '@/api/data-platform/traceability/tray'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'data-platform-traceability-tray',
|
||||||
|
components: { PageTable },
|
||||||
|
mixins: [i18nMixin('page.data_platform.traceability.tray')],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
detailLoading: false,
|
||||||
|
search: { tray_id: this.$route.query.tray || '' },
|
||||||
|
tableData: [],
|
||||||
|
pagination: { current: 1, size: 10, total: 0 },
|
||||||
|
detailVisible: false,
|
||||||
|
activeTrayId: '',
|
||||||
|
detailData: [],
|
||||||
|
timeLine: [],
|
||||||
|
detailSearch: { battery_id: '' },
|
||||||
|
selection: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
columns () {
|
||||||
|
return useTableColumns([
|
||||||
|
{ prop: 'id', label: this.key('id'), width: 90, sortable: 'custom' },
|
||||||
|
{ prop: 'tray', label: this.key('tray'), minWidth: 140, showOverflowTooltip: true },
|
||||||
|
{ prop: 'batch', label: this.key('login_batch'), minWidth: 140, showOverflowTooltip: true },
|
||||||
|
{ prop: 'lot', label: this.key('lot'), minWidth: 120, showOverflowTooltip: true },
|
||||||
|
{ prop: 'active', label: this.key('is_active'), minWidth: 110, slot: 'active' },
|
||||||
|
{ prop: 'input_battery_count', label: this.key('input_battery_count'), minWidth: 140 },
|
||||||
|
{ prop: 'create_time', label: this.key('login_time'), minWidth: 170, showOverflowTooltip: true },
|
||||||
|
{ prop: 'cancel_active_time', label: this.key('cancel_active_time'), minWidth: 170, showOverflowTooltip: true }
|
||||||
|
], { selectionWidth: 0, indexWidth: 55, operationWidth: 130 })
|
||||||
|
},
|
||||||
|
rowButtons () {
|
||||||
|
return [{ key: 'detail', label: this.key('battery_detail'), type: 'primary', icon: 'el-icon-document', size: 'mini', onClick: this.openDetail }]
|
||||||
|
},
|
||||||
|
filteredDetails () {
|
||||||
|
const keyword = String(this.detailSearch.battery_id || '').toLowerCase()
|
||||||
|
return this.detailData.filter(item => !keyword || String(item.battery_id || '').toLowerCase().includes(keyword))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
if (this.search.tray_id) this.fetchData()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
responseData (res) { return res && res.data !== undefined ? res.data : res },
|
||||||
|
async fetchData () {
|
||||||
|
this.loading = true
|
||||||
|
try {
|
||||||
|
const res = await getTrayTraceList({ ...this.search, page_no: this.pagination.current, page_size: this.pagination.size })
|
||||||
|
const data = this.responseData(res)
|
||||||
|
this.tableData = Array.isArray(data) ? data : []
|
||||||
|
this.pagination.total = Number(data && data.count) || this.tableData.length
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resetSearch () {
|
||||||
|
this.search.tray_id = ''
|
||||||
|
this.tableData = []
|
||||||
|
this.pagination.current = 1
|
||||||
|
this.pagination.total = 0
|
||||||
|
},
|
||||||
|
onPageChange (page) {
|
||||||
|
this.pagination = { ...this.pagination, ...page }
|
||||||
|
this.fetchData()
|
||||||
|
},
|
||||||
|
async openDetail (row) {
|
||||||
|
this.activeTrayId = row.id
|
||||||
|
this.detailVisible = true
|
||||||
|
await this.loadDetail()
|
||||||
|
},
|
||||||
|
async loadDetail () {
|
||||||
|
if (!this.activeTrayId) return
|
||||||
|
this.detailLoading = true
|
||||||
|
try {
|
||||||
|
const res = await getTrayTraceDetail({ tray_id: this.activeTrayId })
|
||||||
|
const data = this.responseData(res) || {}
|
||||||
|
this.detailData = Array.isArray(data.data) ? data.data.filter(item => item.battery_id !== 0 && item.battery_id !== '') : []
|
||||||
|
this.timeLine = Array.isArray(data.date_log) ? data.date_log : []
|
||||||
|
} finally {
|
||||||
|
this.detailLoading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async cancelBatteryActive () {
|
||||||
|
if (!this.selection.length) {
|
||||||
|
this.$message.error(this.$t(this.key('please_select_at_least_one_battery')))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
await cancelTraceBatteryActive({ batterData: JSON.stringify(this.selection) })
|
||||||
|
this.$message.success(this.$t(this.key('cancel_success')))
|
||||||
|
this.loadDetail()
|
||||||
|
},
|
||||||
|
goBatteryTrace (batteryId) {
|
||||||
|
this.detailVisible = false
|
||||||
|
this.$router.push({ path: '/data_middleground/produce/traceability/battery', query: { battery_id: batteryId } })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.search-bar { margin-bottom: -18px; }
|
||||||
|
.drawer-header { padding: 20px 24px; border-bottom: 1px solid #ebeef5; }
|
||||||
|
.detail-layout { display: grid; grid-template-columns: 320px minmax(0, 1fr); height: calc(100vh - 73px); }
|
||||||
|
.detail-timeline { overflow: auto; padding: 18px; background: #f5f7fa; border-right: 1px solid #ebeef5; }
|
||||||
|
.detail-main { min-width: 0; padding: 16px; }
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user