Commit 0d7b48e1 by qinjianhui

feat: 页面样式修改

parent bb6917a9
......@@ -3,9 +3,27 @@ description
glob
alwaysApply: true
---
## 技术栈
Vue3 + Element Plus + Pinia + Axios + TypeScript + Vite
## UI 相关编码要求
-- 当有上下两个子表时,使用 `src/components/splitDiv/splitDiv.vue` 组件,使用时注意传递对应的 props 和插槽
-- 所有按钮都需要使用 `span` 标签包裹,并添加 `class="item"` 类名
-- 所有按钮都需要使用 `type` 属性,并且值为 `primary`、`success`、`warning`、`danger`
-- 表格相关布局时,使用 `src/components/TableView.vue` 组件,使用时注意传递对应的 props 和插槽
## 接口相关
-- 所有接口统一放在 `src/api/`目录下,当模块多时,可按模块创建子目录,例如 `src/api/factoryOrderNew/xxx1`、`src/api/factoryOrderNew/xxx2`、`src/api/factoryOrderNew/xxx3`
## TS 类型定义相关
-- 所有类型定义统一放在 `src/types/`目录下,当模块多时,可按模块创建子目录,例如 `src/types/factoryOrderNew/xxx1`、`src/types/factoryOrderNew/xxx2`、`src/types/factoryOrderNew/xxx3`
## 代码编写原则
-- 只编写解决问题所需的最少代码
-- 避免冗余实现和过渡设计
-- 实现一个复杂功能时,需要合理拆分组件,使每个文件的代码更易维护
......
<template>
<div class="batch-manage">
<div class="batch-manage-filter">
<ElForm :inline="true" :model="filterForm" size="default">
<ElForm class="search-form" :inline="true" :model="filterForm">
<ElFormItem label="创建时间">
<el-date-picker
v-model="filterForm.createTimeRange"
......@@ -12,26 +12,6 @@
style="width: 320px"
/>
</ElFormItem>
<ElFormItem label="开始时间">
<el-date-picker
v-model="filterForm.startTimeRange"
type="datetimerange"
value-format="YYYY-MM-DD HH:mm:ss"
start-placeholder="开始时间"
end-placeholder="结束时间"
style="width: 320px"
/>
</ElFormItem>
<ElFormItem label="完成时间">
<el-date-picker
v-model="filterForm.finishTimeRange"
type="datetimerange"
value-format="YYYY-MM-DD HH:mm:ss"
start-placeholder="开始时间"
end-placeholder="结束时间"
style="width: 320px"
/>
</ElFormItem>
<ElFormItem label="创建人">
<ElInput
v-model="filterForm.creator"
......@@ -40,14 +20,6 @@
style="width: 120px"
/>
</ElFormItem>
<ElFormItem label="编排组">
<ElInput
v-model="filterForm.arrangeGroup"
placeholder="编排组"
clearable
style="width: 120px"
/>
</ElFormItem>
<ElFormItem label="工艺类型">
<ElSelect
v-model="filterForm.craftType"
......@@ -105,45 +77,40 @@
</div>
<div class="batch-manage-actions">
<ElButton type="danger" @click="handleBatchDelete">批量删除</ElButton>
<span class="item">
<ElButton type="danger" @click="handleBatchDelete">批量删除</ElButton>
</span>
</div>
<div class="batch-manage-table">
<ElTable
v-loading="loading"
:data="tableData"
border
style="width: 100%"
<TableView
:paginated-data="tableData"
:columns="columns"
selectionable
@selection-change="handleSelectionChange"
>
<ElTableColumn type="selection" width="45" />
<ElTableColumn prop="batchNo" label="批次号" min-width="120" />
<ElTableColumn prop="downloadStatus" label="下载状态" min-width="90" align="center">
<template #default="{ row }">
<el-tag :type="row.downloadStatus === '已下载' ? 'success' : 'info'" size="small">
{{ row.downloadStatus || '未下载' }}
</el-tag>
</template>
</ElTableColumn>
<ElTableColumn prop="orderCount" label="订单数量" min-width="90" align="center" />
<ElTableColumn prop="totalCount" label="全部数量" min-width="90" align="center" />
<ElTableColumn prop="creator" label="创建人" min-width="80" />
<ElTableColumn prop="craftType" label="工艺类型" min-width="90" />
<ElTableColumn prop="timesRange" label="次数范围" min-width="90" />
<ElTableColumn prop="createTime" label="创建时间" min-width="160" sortable />
<ElTableColumn prop="createTime" label="创建时间排序" min-width="110" sortable />
<ElTableColumn prop="extractTimes" label="提取次数排序" min-width="110" sortable />
<ElTableColumn label="操作" min-width="200" fixed="right">
<template #default="{ row }">
<ElButton type="primary" link size="small" @click="handleView(row)">
查看
</ElButton>
<ElButton type="primary" link size="small" @click="handleDownload(row)">
下载
</ElButton>
</template>
</ElTableColumn>
</ElTable>
<template #downloadStatus="{ row }">
<el-tag
:type="row.downloadStatus === '已下载' ? 'success' : 'info'"
size="small"
>
{{ row.downloadStatus || '未下载' }}
</el-tag>
</template>
<template #operation="{ row }">
<ElButton type="primary" link size="small" @click="handleView(row)">
查看
</ElButton>
<ElButton
type="primary"
link
size="small"
@click="handleDownload(row)"
>
下载
</ElButton>
</template>
</TableView>
</div>
<ElPagination
......@@ -153,7 +120,7 @@
background
layout="total, sizes, prev, pager, next, jumper"
:total="total"
style="margin-top: 10px"
style="margin: 10px auto 0"
@size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange"
/>
......@@ -165,6 +132,8 @@ import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { getBatchManageListApi, batchDeleteApi } from '@/api/factoryOrderNew'
import type { BatchManageData } from '@/types/api/factoryOrderNew'
import type { CustomColumn } from '@/types/table'
import TableView from '@/components/TableView.vue'
const loading = ref(false)
const tableData = ref<BatchManageData[]>([])
......@@ -173,6 +142,63 @@ const currentPage = ref(1)
const pageSize = ref(50)
const total = ref(0)
const columns: CustomColumn<BatchManageData>[] = [
{ key: 'batchNo', prop: 'batchNo', label: '批次号', minWidth: 120 },
{
key: 'downloadStatus',
prop: 'downloadStatus',
label: '下载状态',
minWidth: 90,
align: 'center',
slot: 'downloadStatus',
},
{
key: 'orderCount',
prop: 'orderCount',
label: '订单数量',
minWidth: 90,
align: 'center',
},
{
key: 'totalCount',
prop: 'totalCount',
label: '全部数量',
minWidth: 90,
align: 'center',
},
{ key: 'creator', prop: 'creator', label: '创建人', minWidth: 80 },
{ key: 'craftType', prop: 'craftType', label: '工艺类型', minWidth: 90 },
{ key: 'timesRange', prop: 'timesRange', label: '次数范围', minWidth: 90 },
{
key: 'createTime',
prop: 'createTime',
label: '创建时间',
minWidth: 160,
sortable: true,
},
{
key: 'createTimeSort',
prop: 'createTime',
label: '创建时间排序',
minWidth: 110,
sortable: true,
},
{
key: 'extractTimes',
prop: 'extractTimes',
label: '提取次数排序',
minWidth: 110,
sortable: true,
},
{
key: 'operation',
label: '操作',
minWidth: 120,
fixed: 'right',
slot: 'operation',
},
]
const filterForm = reactive({
createTimeRange: [] as string[],
startTimeRange: [] as string[],
......@@ -220,8 +246,9 @@ const handleBatchDelete = async () => {
await batchDeleteApi(selectedRows.value.map((r) => r.id))
ElMessage.success('删除成功')
loadData()
} catch (e: any) {
ElMessage.error(e?.message || '删除失败')
} catch (e) {
const err = e as Error & { message?: string }
ElMessage.error(err?.message || '删除失败')
}
}
......@@ -266,7 +293,8 @@ defineExpose({ refresh })
.batch-manage-filter {
flex-shrink: 0;
padding-bottom: 10px;
width: 100%;
min-width: 0;
}
.batch-manage-actions {
......@@ -278,4 +306,20 @@ defineExpose({ refresh })
flex: 1;
overflow: auto;
}
.search-form {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0;
min-width: 0;
:deep(.el-form-item) {
margin-right: 10px;
margin-bottom: 10px;
}
:deep(.el-form-item__content) {
min-width: 0;
}
}
</style>
......@@ -26,7 +26,7 @@
</template>
<template #top_right>
<img
v-if="item.craftCode && ['ZPZY', 'CXZY', 'THZY'].includes(item.craftCode)"
v-if="item.craftCode && ['ZPZY', 'CXZY', 'THZY'].includes(item.craftCode as string)"
:src="`/images/pic/${item.craftCode}.png`"
width="60"
height="60"
......@@ -40,7 +40,7 @@
<template #info>
<div class="card-info-grid">
<div class="card-info-row full">
<span class="info-value ellipsis" :title="item.productName || ''">
<span class="info-value ellipsis" :title="(item.productName as string) || ''">
{{ item.productName }}
</span>
</div>
......@@ -60,8 +60,8 @@
<span class="info-label">变体SKU</span>
<span
class="info-value clickable ellipsis"
:title="item.variantSku || ''"
@click.stop="copyText(item.variantSku || '')"
:title="(item.variantSku as string) || ''"
@click.stop="copyText((item.variantSku as string) || '')"
>
{{ item.variantSku }}
</span>
......@@ -70,8 +70,8 @@
<span class="info-label">库存SKU</span>
<span
class="info-value clickable ellipsis"
:title="item.thirdSkuCode || ''"
@click.stop="copyText(item.thirdSkuCode || '')"
:title="(item.thirdSkuCode as string) || ''"
@click.stop="copyText((item.thirdSkuCode as string) || '')"
>
{{ item.thirdSkuCode }}
</span>
......@@ -108,6 +108,7 @@
background
layout="total, sizes, prev, pager, next, jumper"
:total="total"
style="margin: 0 auto"
@size-change="$emit('page-size-change', $event)"
@current-change="$emit('current-page-change', $event)"
/>
......
<template>
<div class="waiting-restock">
<div class="restock-filter">
<ElForm :inline="true" :model="filterForm" size="default">
<ElFormItem label="仓库筛选" />
<ElForm :inline="true" :model="filterForm" size="default" class="search-form">
<ElFormItem label="库存SKU">
<ElInput
v-model="filterForm.stockSku"
......@@ -27,63 +26,133 @@
</div>
<div class="restock-table">
<ElTable v-loading="loading" :data="tableData" border style="width: 100%">
<ElTableColumn type="index" label="序号" width="60" align="center" />
<ElTableColumn prop="warehouseName" label="仓库名称" min-width="100" />
<ElTableColumn label="SKU图片" width="80" align="center">
<template #default="{ row }">
<el-image
v-if="row.skuImage"
:src="row.skuImage"
style="width: 50px; height: 50px"
fit="contain"
:preview-src-list="[row.skuImage]"
preview-teleported
/>
</template>
</ElTableColumn>
<ElTableColumn prop="productName" label="商品名称" min-width="120" show-overflow-tooltip />
<ElTableColumn prop="styleNo" label="款号" min-width="80" />
<ElTableColumn prop="stockSku" label="库存SKU" min-width="120" />
<ElTableColumn prop="shortageQuantity" label="缺货数量" min-width="90" align="center">
<template #default="{ row }">
<span style="color: #f56c6c; font-weight: bold">{{ row.shortageQuantity }}</span>
</template>
</ElTableColumn>
<ElTableColumn prop="availableQuantity" label="可用数量" min-width="90" align="center">
<template #default="{ row }">
<span :style="{ color: (row.availableQuantity || 0) < 0 ? '#f56c6c' : '' }">
{{ row.availableQuantity }}
</span>
</template>
</ElTableColumn>
<ElTableColumn prop="stockQuantity" label="库存数量" min-width="90" align="center" />
<ElTableColumn prop="occupiedQuantity" label="占用数量" min-width="90" align="center" />
<ElTableColumn label="操作" width="120" align="center" fixed="right">
<template #default="{ row }">
<ElButton
type="primary"
link
size="small"
@click="handleRestockCheck(row)"
>
补货校验
</ElButton>
</template>
</ElTableColumn>
</ElTable>
<TableView
v-loading="loading"
:paginated-data="pageData"
:columns="columns"
serial-numberable
>
<template #skuImage="{ row }">
<el-image
v-if="row.skuImage"
:src="row.skuImage"
style="width: 50px; height: 50px"
fit="contain"
:preview-src-list="[row.skuImage]"
preview-teleported
/>
</template>
<template #shortageQuantity="{ row }">
<span style="color: #f56c6c; font-weight: bold">{{ row.shortageQuantity }}</span>
</template>
<template #availableQuantity="{ row }">
<span :style="{ color: (row.availableQuantity || 0) < 0 ? '#f56c6c' : '' }">
{{ row.availableQuantity }}
</span>
</template>
<template #operation="{ row }">
<ElButton type="primary" link size="small" @click="handleRestockCheck(row)">
补货校验
</ElButton>
</template>
</TableView>
</div>
<ElPagination
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:page-sizes="[50, 100, 200, 300]"
background
layout="total, sizes, prev, pager, next, jumper"
:total="total"
style="margin: 10px auto 0;"
@size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange"
/>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { computed, ref, reactive, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { getRestockListApi, restockCheckApi } from '@/api/factoryOrderNew'
import type { RestockData } from '@/types/api/factoryOrderNew'
import type { CustomColumn } from '@/types/table'
import TableView from '@/components/TableView.vue'
const loading = ref(false)
const tableData = ref<RestockData[]>([])
const allData = ref<RestockData[]>([])
const currentPage = ref(1)
const pageSize = ref(50)
const total = ref(0)
const pageData = computed(() => {
const start = (currentPage.value - 1) * pageSize.value
return allData.value.slice(start, start + pageSize.value)
})
const columns: CustomColumn<RestockData>[] = [
{
key: 'warehouseName',
prop: 'warehouseName',
label: '仓库名称',
minWidth: 100,
},
{
key: 'skuImage',
label: 'SKU图片',
width: 100,
align: 'center',
slot: 'skuImage',
},
{
key: 'productName',
prop: 'productName',
label: '商品名称',
minWidth: 120,
showOverflowTooltip: true,
},
{ key: 'styleNo', prop: 'styleNo', label: '款号', minWidth: 80 },
{ key: 'stockSku', prop: 'stockSku', label: '库存SKU', minWidth: 120 },
{
key: 'shortageQuantity',
prop: 'shortageQuantity',
label: '缺货数量',
minWidth: 90,
align: 'center',
slot: 'shortageQuantity',
},
{
key: 'availableQuantity',
prop: 'availableQuantity',
label: '可用数量',
minWidth: 90,
align: 'center',
slot: 'availableQuantity',
},
{
key: 'stockQuantity',
prop: 'stockQuantity',
label: '库存数量',
minWidth: 90,
align: 'center',
},
{
key: 'occupiedQuantity',
prop: 'occupiedQuantity',
label: '占用数量',
minWidth: 90,
align: 'center',
},
{
key: 'operation',
label: '操作',
width: 120,
align: 'center',
fixed: 'right',
slot: 'operation',
},
]
const filterForm = reactive({
stockSku: '',
......@@ -97,35 +166,50 @@ const loadData = async () => {
stockSku: filterForm.stockSku || undefined,
styleNo: filterForm.styleNo || undefined,
})
tableData.value = res.data || []
allData.value = res.data || []
total.value = allData.value.length
} catch (_e) {
tableData.value = []
allData.value = []
total.value = 0
} finally {
loading.value = false
}
}
const handleSearch = () => {
currentPage.value = 1
loadData()
}
const handleReset = () => {
filterForm.stockSku = ''
filterForm.styleNo = ''
currentPage.value = 1
loadData()
}
const handlePageSizeChange = (size: number) => {
pageSize.value = size
currentPage.value = 1
}
const handleCurrentPageChange = (page: number) => {
currentPage.value = page
}
const handleRestockCheck = async (row: RestockData) => {
try {
await restockCheckApi(row.id)
ElMessage.success('补货校验成功')
loadData()
} catch (e: any) {
ElMessage.error(e?.message || '补货校验失败')
} catch (e) {
const err = e as Error & { message?: string }
ElMessage.error(err?.message || '补货校验失败')
}
}
const refresh = () => {
currentPage.value = 1
loadData()
}
......@@ -153,4 +237,20 @@ defineExpose({ refresh })
flex: 1;
overflow: auto;
}
.search-form {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0;
min-width: 0;
:deep(.el-form-item) {
margin-right: 10px;
margin-bottom: 10px;
}
:deep(.el-form-item__content) {
min-width: 0;
}
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment