产品信息的三张表适配手机端

This commit is contained in:
2026-03-11 18:00:43 +08:00
parent 21abd429e5
commit 87430999e9
6 changed files with 775 additions and 565 deletions

View File

@@ -1,32 +1,47 @@
<template> <template>
<Dialog :title="dialogTitle" v-model="dialogVisible"> <el-drawer
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<div class="mobile-form" v-loading="formLoading">
<el-form <el-form
ref="formRef" ref="formRef"
:model="formData" :model="formData"
:rules="formRules" :rules="formRules"
label-width="100px" label-position="top"
v-loading="formLoading"
> >
<el-form-item label="上级编号" prop="parentId"> <div class="mobile-form-section">
<div class="mobile-form-section__title">基础信息</div>
<el-form-item label="上级分类" prop="parentId">
<el-tree-select <el-tree-select
v-model="formData.parentId" v-model="formData.parentId"
:data="productCategoryTree" :data="productCategoryTree"
:props="defaultProps" :props="defaultProps"
check-strictly check-strictly
default-expand-all default-expand-all
placeholder="请选择上级编号" placeholder="请选择上级分类"
/> />
</el-form-item> </el-form-item>
<el-form-item label="名称" prop="name"> <el-form-item label="分类名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入名称" /> <el-input v-model="formData.name" placeholder="请输入分类名称" clearable />
</el-form-item> </el-form-item>
<el-form-item label="编码" prop="code"> <el-form-item label="分类编码" prop="code">
<el-input v-model="formData.code" placeholder="请输入编码" /> <el-input v-model="formData.code" placeholder="请输入分类编码" clearable />
</el-form-item> </el-form-item>
<el-form-item label="排序" prop="sort"> <el-form-item label="排序" prop="sort">
<el-input v-model="formData.sort" placeholder="请输入排序" /> <el-input-number v-model="formData.sort" placeholder="请输入排序" :precision="0" controls-position="right" />
</el-form-item> </el-form-item>
<el-form-item label="状态" prop="status"> </div>
<div class="mobile-form-section">
<div class="mobile-form-section__title">状态信息</div>
<el-form-item label="开启状态" prop="status">
<el-radio-group v-model="formData.status"> <el-radio-group v-model="formData.status">
<el-radio <el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
@@ -37,12 +52,16 @@
</el-radio> </el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</div>
</el-form> </el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button> <!-- 底部操作按钮 -->
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false"> </el-button> <el-button @click="dialogVisible = false"> </el-button>
</template> <el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
</Dialog> </div>
</div>
</el-drawer>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict' import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
@@ -143,3 +162,54 @@ const getProductCategoryTree = async () => {
productCategoryTree.value.push(root) productCategoryTree.value.push(root)
} }
</script> </script>
<style lang="scss" scoped>
.mobile-form {
padding: 12px;
}
.mobile-form-section {
background: #fff;
border-radius: 10px;
padding: 14px;
margin-bottom: 12px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
}
.mobile-form-section__title {
font-size: 15px;
font-weight: 600;
color: #303133;
margin-bottom: 12px;
padding-bottom: 8px;
border-bottom: 1px solid #f0f0f0;
}
.mobile-form__footer {
position: sticky;
bottom: 0;
background: #fff;
padding: 12px 16px;
padding-bottom: calc(12px + constant(safe-area-inset-bottom));
padding-bottom: calc(12px + env(safe-area-inset-bottom));
border-top: 1px solid #eee;
display: flex;
justify-content: flex-end;
gap: 12px;
z-index: 10;
margin: 0 -12px -12px;
.el-button {
flex: 1;
height: 40px;
font-size: 15px;
}
}
:deep(.el-form-item) {
margin-bottom: 16px;
}
:deep(.el-input),
:deep(.el-select),
:deep(.el-input-number),
:deep(.el-tree-select) {
width: 100% !important;
}
</style>

View File

@@ -1,31 +1,61 @@
<template> <template>
<doc-alert title="【产品】产品信息、分类、单位" url="https://doc.iocoder.cn/erp/product/" /> <div class="mobile-product-category">
<!-- 搜索操作栏 -->
<div class="mobile-header">
<div class="mobile-header__search">
<el-input v-model="queryParams.name" placeholder="搜索分类名称" clearable @keyup.enter="handleQuery" :prefix-icon="Search" />
</div>
<div class="mobile-header__actions">
<el-button :icon="Filter" circle @click="filterVisible = true" />
<el-button type="primary" :icon="Plus" circle @click="openForm('create')" v-hasPermi="['erp:product-category:create']" />
</div>
</div>
<ContentWrap> <!-- 快捷操作 -->
<!-- 搜索工作栏 --> <div class="mobile-quick-actions">
<el-form <el-button size="small" type="success" plain @click="handleExport" :loading="exportLoading" v-hasPermi="['erp:product-category:export']">导出</el-button>
class="-mb-15px" <el-button size="small" type="danger" plain @click="toggleExpandAll">{{ isExpandAll ? '折叠' : '展开' }}</el-button>
:model="queryParams" </div>
ref="queryFormRef"
:inline="true" <!-- 卡片列表 -->
label-width="68px" <div class="mobile-list" v-loading="loading">
> <div v-if="list.length === 0 && !loading" class="mobile-empty">
<el-form-item label="分类名称" prop="name"> <el-empty description="暂无产品分类" />
<el-input </div>
v-model="queryParams.name" <div v-for="item in flatList" :key="item.id" class="mobile-card" @click="handleCardClick(item)" :style="{ marginLeft: (item.level || 0) * 12 + 'px' }">
placeholder="请输入分类名称" <div class="mobile-card__header">
clearable <span class="mobile-card__name">
@keyup.enter="handleQuery" <span v-if="item.level > 0" class="mobile-card__indent"></span>
class="!w-240px" {{ item.name || '-' }}
/> </span>
</el-form-item> <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="item.status" />
</div>
<div class="mobile-card__body">
<div class="mobile-card__row">
<span class="mobile-card__label">编码</span>
<span class="mobile-card__value">{{ item.code || '-' }}</span>
</div>
<div class="mobile-card__row">
<span class="mobile-card__label">排序</span>
<span class="mobile-card__value">{{ item.sort || '-' }}</span>
</div>
<div class="mobile-card__row">
<span class="mobile-card__label">创建时间</span>
<span class="mobile-card__value">{{ formatDate(item.createTime) }}</span>
</div>
</div>
<div class="mobile-card__footer">
<el-button size="small" type="primary" @click.stop="openForm('update', item.id)" v-hasPermi="['erp:product-category:update']">编辑</el-button>
<el-button size="small" type="danger" @click.stop="handleDelete(item.id)" v-hasPermi="['erp:product-category:delete']">删除</el-button>
</div>
</div>
</div>
<!-- 筛选抽屉 -->
<el-drawer v-model="filterVisible" title="筛选条件" direction="btt" size="50%">
<el-form :model="queryParams" ref="queryFormRef" label-position="top">
<el-form-item label="开启状态" prop="status"> <el-form-item label="开启状态" prop="status">
<el-select <el-select v-model="queryParams.status" placeholder="请选择开启状态" clearable style="width:100%">
v-model="queryParams.status"
placeholder="请选择开启状态"
clearable
class="!w-240px"
>
<el-option <el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value" :key="dict.value"
@@ -34,96 +64,20 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:product-category:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:product-category:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
<el-button type="danger" plain @click="toggleExpandAll">
<Icon icon="ep:sort" class="mr-5px" /> 展开/折叠
</el-button>
</el-form-item>
</el-form> </el-form>
</ContentWrap> <template #footer>
<el-button @click="resetQuery">重置</el-button>
<!-- 列表 --> <el-button type="primary" @click="handleFilterConfirm">确认筛选</el-button>
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
row-key="id"
:default-expand-all="isExpandAll"
v-if="refreshTable"
@row-click="handleRowClick"
>
<el-table-column label="编码" align="center" prop="code" />
<el-table-column label="名称" align="center" prop="name" />
<el-table-column label="排序" align="center" prop="sort" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template> </template>
</el-table-column> </el-drawer>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
sortable
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:product-category:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['erp:product-category:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 --> <!-- 表单弹窗添加/修改 -->
<ProductCategoryForm ref="formRef" @success="getList" /> <ProductCategoryForm ref="formRef" @success="getList" />
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { Search, Filter, Plus } from '@element-plus/icons-vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict' import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime' import { dateFormatter } from '@/utils/formatTime'
import { handleTree } from '@/utils/tree' import { handleTree } from '@/utils/tree'
@@ -139,6 +93,8 @@ const { t } = useI18n() // 国际化
const loading = ref(true) // 列表的加载中 const loading = ref(true) // 列表的加载中
const list = ref<ProductCategoryVO[]>([]) // 列表的数据 const list = ref<ProductCategoryVO[]>([]) // 列表的数据
const flatList = ref<ProductCategoryVO[]>([]) // 扁平化列表
const filterVisible = ref(false) // 筛选抽屉
const queryParams = reactive({ const queryParams = reactive({
name: undefined, name: undefined,
status: undefined status: undefined
@@ -152,11 +108,27 @@ const getList = async () => {
try { try {
const data = await ProductCategoryApi.getProductCategoryList(queryParams) const data = await ProductCategoryApi.getProductCategoryList(queryParams)
list.value = handleTree(data, 'id', 'parentId') list.value = handleTree(data, 'id', 'parentId')
flattenTree()
} finally { } finally {
loading.value = false loading.value = false
} }
} }
/** 扁平化树形结构 */
const flattenTree = () => {
const result: any[] = []
const flatten = (nodes: any[], level = 0) => {
nodes.forEach(node => {
result.push({ ...node, level })
if (node.children && node.children.length > 0 && isExpandAll.value) {
flatten(node.children, level + 1)
}
})
}
flatten(list.value)
flatList.value = result
}
/** 搜索按钮操作 */ /** 搜索按钮操作 */
const handleQuery = () => { const handleQuery = () => {
queryParams.pageNo = 1 queryParams.pageNo = 1
@@ -165,7 +137,13 @@ const handleQuery = () => {
/** 重置按钮操作 */ /** 重置按钮操作 */
const resetQuery = () => { const resetQuery = () => {
queryFormRef.value.resetFields() queryFormRef.value?.resetFields()
handleQuery()
}
/** 筛选确认 */
const handleFilterConfirm = () => {
filterVisible.value = false
handleQuery() handleQuery()
} }
@@ -175,10 +153,16 @@ const openForm = (type: string, id?: number) => {
formRef.value.open(type, id) formRef.value.open(type, id)
} }
/** 行点击操作 */ /** 卡片点击 */
const handleRowClick = (row: ProductCategoryVO) => { const handleCardClick = (row: ProductCategoryVO) => {
openForm('update', row.id) openForm('update', row.id)
} }
/** 格式化日期 */
const formatDate = (date: any) => {
if (!date) return '-'
return dateFormatter({ cellValue: date })
}
/** 删除按钮操作 */ /** 删除按钮操作 */
const handleDelete = async (id: number) => { const handleDelete = async (id: number) => {
try { try {
@@ -209,12 +193,9 @@ const handleExport = async () => {
/** 展开/折叠操作 */ /** 展开/折叠操作 */
const isExpandAll = ref(true) // 是否展开,默认全部展开 const isExpandAll = ref(true) // 是否展开,默认全部展开
const refreshTable = ref(true) // 重新渲染表格状态 const toggleExpandAll = () => {
const toggleExpandAll = async () => {
refreshTable.value = false
isExpandAll.value = !isExpandAll.value isExpandAll.value = !isExpandAll.value
await nextTick() flattenTree()
refreshTable.value = true
} }
/** 初始化 **/ /** 初始化 **/
@@ -222,3 +203,32 @@ onMounted(() => {
getList() getList()
}) })
</script> </script>
<style lang="scss" scoped>
.mobile-product-category {
padding: 12px;
background: #f5f5f5;
min-height: 100vh;
}
.mobile-header {
display: flex; gap: 8px; align-items: center; margin-bottom: 12px;
&__search { flex: 1; }
&__actions { display: flex; gap: 4px; flex-shrink: 0; }
}
.mobile-quick-actions {
display: flex; gap: 8px; margin-bottom: 12px;
}
.mobile-list { display: flex; flex-direction: column; gap: 10px; }
.mobile-empty { padding: 40px 0; }
.mobile-card {
background: #fff; border-radius: 10px; padding: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06);
&__header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }
&__name { font-weight: 600; font-size: 15px; color: #303133; }
&__indent { color: #909399; margin-right: 4px; }
&__body { font-size: 13px; }
&__row { display: flex; justify-content: space-between; padding: 3px 0; }
&__label { color: #909399; flex-shrink: 0; margin-right: 12px; }
&__value { color: #606266; text-align: right; }
&__footer { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; padding-top: 10px; border-top: 1px solid #f0f0f0; }
}
</style>

View File

@@ -1,40 +1,41 @@
<!-- ERP 产品的新增/修改 -->
<template> <template>
<Dialog :title="dialogTitle" v-model="dialogVisible"> <el-drawer
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<div class="mobile-form" v-loading="formLoading">
<el-form <el-form
ref="formRef" ref="formRef"
:model="formData" :model="formData"
:rules="formRules" :rules="formRules"
label-width="100px" label-position="top"
v-loading="formLoading"
> >
<el-row :gutter="20"> <div class="mobile-form-section">
<el-col :span="12"> <div class="mobile-form-section__title">基础信息</div>
<el-form-item label="名称" prop="name"> <el-form-item label="产品名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入名称" /> <el-input v-model="formData.name" placeholder="请输入产品名称" clearable />
</el-form-item> </el-form-item>
</el-col> <el-form-item label="产品条码" prop="barCode">
<el-col :span="12"> <el-input v-model="formData.barCode" placeholder="请输入产品条码" clearable />
<el-form-item label="条码" prop="barCode">
<el-input v-model="formData.barCode" placeholder="请输入条码" />
</el-form-item> </el-form-item>
</el-col> <el-form-item label="产品分类" prop="categoryId">
<el-col :span="12">
<el-form-item label="分类" prop="categoryId">
<el-tree-select <el-tree-select
v-model="formData.categoryId" v-model="formData.categoryId"
:data="categoryList" :data="categoryList"
:props="defaultProps" :props="defaultProps"
check-strictly check-strictly
default-expand-all default-expand-all
placeholder="请选择分类" placeholder="请选择产品分类"
class="w-1/1"
/> />
</el-form-item> </el-form-item>
</el-col> <el-form-item label="产品单位" prop="unitId">
<el-col :span="12"> <el-select v-model="formData.unitId" clearable placeholder="请选择产品单位">
<el-form-item label="单位" prop="unitId">
<el-select v-model="formData.unitId" clearable placeholder="请选择单位" class="w-1/1">
<el-option <el-option
v-for="unit in unitList" v-for="unit in unitList"
:key="unit.id" :key="unit.id"
@@ -43,9 +44,96 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> <el-form-item label="产品规格" prop="standard">
<el-col :span="12"> <el-input v-model="formData.standard" placeholder="请输入产品规格" clearable />
<el-form-item label="状态" prop="status"> </el-form-item>
</div>
<div class="mobile-form-section">
<div class="mobile-form-section__title">价格信息</div>
<el-form-item label="采购价格(元)" prop="purchasePrice">
<el-input-number
v-model="formData.purchasePrice"
placeholder="请输入采购价格"
:min="0"
:precision="4"
controls-position="right"
/>
</el-form-item>
<el-form-item label="销售价格(元)" prop="salePrice">
<el-input-number
v-model="formData.salePrice"
placeholder="请输入销售价格"
:min="0"
:precision="4"
controls-position="right"
/>
</el-form-item>
<el-form-item label="货值(元)" prop="minPrice">
<el-input-number
v-model="formData.minPrice"
placeholder="请输入最低价格"
:min="0"
:precision="4"
controls-position="right"
/>
</el-form-item>
</div>
<div class="mobile-form-section">
<div class="mobile-form-section__title">库存信息</div>
<el-form-item label="库存预警数量" prop="stockAlertCount">
<el-input-number
v-model="formData.stockAlertCount"
placeholder="请输入库存预警数量"
:min="0"
:precision="2"
controls-position="right"
/>
</el-form-item>
<el-form-item label="保质期天数" prop="expiryDay">
<el-input-number
v-model="formData.expiryDay"
placeholder="请输入保质期天数"
:min="0"
:precision="0"
controls-position="right"
/>
</el-form-item>
<el-form-item label="重量kg" prop="weight">
<el-input-number
v-model="formData.weight"
placeholder="请输入重量"
:min="0"
controls-position="right"
/>
</el-form-item>
</div>
<div class="mobile-form-section">
<div class="mobile-form-section__title">供应商信息</div>
<el-form-item label="供应商" prop="supplierId">
<el-select v-model="formData.supplierId" clearable filterable placeholder="请选择供应商">
<el-option
v-for="item in supplierList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</div>
<div class="mobile-form-section">
<div class="mobile-form-section__title">其他信息</div>
<el-form-item label="备注" prop="remark">
<el-input type="textarea" v-model="formData.remark" placeholder="请输入备注" :rows="3" />
</el-form-item>
</div>
<div class="mobile-form-section">
<div class="mobile-form-section__title">状态信息</div>
<el-form-item label="开启状态" prop="status">
<el-radio-group v-model="formData.status"> <el-radio-group v-model="formData.status">
<el-radio <el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
@@ -56,101 +144,16 @@
</el-radio> </el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </div>
<el-col :span="12">
<el-form-item label="规格" prop="standard">
<el-input v-model="formData.standard" placeholder="请输入规格" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="保质期天数" prop="expiryDay">
<el-input-number
v-model="formData.expiryDay"
placeholder="请输入保质期天数"
:min="0"
:precision="0"
class="!w-1/1"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="重量kg" prop="weight">
<el-input-number
v-model="formData.weight"
placeholder="请输入重量kg"
:min="0"
class="!w-1/1"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="采购价格" prop="purchasePrice">
<el-input-number
v-model="formData.purchasePrice"
placeholder="请输入采购价格,单位:元"
:min="0"
:precision="4"
class="!w-1/1"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="销售价格" prop="salePrice">
<el-input-number
v-model="formData.salePrice"
placeholder="请输入销售价格,单位:元"
:min="0"
:precision="4"
class="!w-1/1"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="货值" prop="minPrice">
<el-input-number
v-model="formData.minPrice"
placeholder="请输入最低价格,单位:元"
:min="0"
:precision="4"
class="!w-1/1"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="库存预警" prop="stockAlertCount">
<el-input-number
v-model="formData.stockAlertCount"
placeholder="请输入库存预警数量"
:min="0"
:precision="2"
class="!w-1/1"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="供应商" prop="supplierId">
<el-select v-model="formData.supplierId" clearable filterable placeholder="请选择供应商" class="w-1/1">
<el-option
v-for="item in supplierList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注" prop="remark">
<el-input type="textarea" v-model="formData.remark" placeholder="请输入备注" />
</el-form-item>
</el-col>
</el-row>
</el-form> </el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button> <!-- 底部操作按钮 -->
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false"> </el-button> <el-button @click="dialogVisible = false"> </el-button>
</template> <el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
</Dialog> </div>
</div>
</el-drawer>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ProductApi, ProductVO } from '@/api/erp/product/product' import { ProductApi, ProductVO } from '@/api/erp/product/product'
@@ -269,3 +272,54 @@ const resetForm = () => {
formRef.value?.resetFields() formRef.value?.resetFields()
} }
</script> </script>
<style lang="scss" scoped>
.mobile-form {
padding: 12px;
}
.mobile-form-section {
background: #fff;
border-radius: 10px;
padding: 14px;
margin-bottom: 12px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
}
.mobile-form-section__title {
font-size: 15px;
font-weight: 600;
color: #303133;
margin-bottom: 12px;
padding-bottom: 8px;
border-bottom: 1px solid #f0f0f0;
}
.mobile-form__footer {
position: sticky;
bottom: 0;
background: #fff;
padding: 12px 16px;
padding-bottom: calc(12px + constant(safe-area-inset-bottom));
padding-bottom: calc(12px + env(safe-area-inset-bottom));
border-top: 1px solid #eee;
display: flex;
justify-content: flex-end;
gap: 12px;
z-index: 10;
margin: 0 -12px -12px;
.el-button {
flex: 1;
height: 40px;
font-size: 15px;
}
}
:deep(.el-form-item) {
margin-bottom: 16px;
}
:deep(.el-input),
:deep(.el-select),
:deep(.el-input-number),
:deep(.el-tree-select) {
width: 100% !important;
}
</style>

View File

@@ -1,138 +1,97 @@
<!-- ERP 产品列表 -->
<template> <template>
<doc-alert title="【产品】产品信息、分类、单位" url="https://doc.iocoder.cn/erp/product/" /> <div class="mobile-product">
<!-- 搜索操作栏 -->
<div class="mobile-header">
<div class="mobile-header__search">
<el-input v-model="queryParams.name" placeholder="搜索产品名称" clearable @keyup.enter="handleQuery" :prefix-icon="Search" />
</div>
<div class="mobile-header__actions">
<el-button :icon="Filter" circle @click="filterVisible = true" />
<el-button type="primary" :icon="Plus" circle @click="openForm('create')" v-hasPermi="['erp:product:create']" />
</div>
</div>
<ContentWrap> <!-- 快捷操作 -->
<!-- 搜索工作栏 --> <div class="mobile-quick-actions">
<el-form <el-button size="small" type="success" plain @click="handleExport" :loading="exportLoading" v-hasPermi="['erp:product:export']">导出</el-button>
class="-mb-15px" </div>
:model="queryParams"
ref="queryFormRef" <!-- 卡片列表 -->
:inline="true" <div class="mobile-list" v-loading="loading">
label-width="68px" <div v-if="list.length === 0 && !loading" class="mobile-empty">
> <el-empty description="暂无产品" />
<el-form-item label="名称" prop="name"> </div>
<el-input <div v-for="item in list" :key="item.id" class="mobile-card" @click="handleCardClick(item)">
v-model="queryParams.name" <div class="mobile-card__header">
placeholder="请输入名称" <span class="mobile-card__name">{{ item.name || '-' }}</span>
clearable <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="item.status" />
@keyup.enter="handleQuery" </div>
class="!w-240px" <div class="mobile-card__body">
/> <div class="mobile-card__row">
</el-form-item> <span class="mobile-card__label">条码</span>
<el-form-item label="分类" prop="categoryId"> <span class="mobile-card__value">{{ item.barCode || '-' }}</span>
</div>
<div class="mobile-card__row">
<span class="mobile-card__label">规格</span>
<span class="mobile-card__value">{{ item.standard || '-' }}</span>
</div>
<div class="mobile-card__row">
<span class="mobile-card__label">分类</span>
<span class="mobile-card__value">{{ item.categoryName || '-' }}</span>
</div>
<div class="mobile-card__row">
<span class="mobile-card__label">单位</span>
<span class="mobile-card__value">{{ item.unitName || '-' }}</span>
</div>
<div class="mobile-card__row">
<span class="mobile-card__label">供应商</span>
<span class="mobile-card__value">{{ item.supplierName || '-' }}</span>
</div>
<div class="mobile-card__row">
<span class="mobile-card__label">货值</span>
<span class="mobile-card__value">{{ formatPrice(item.minPrice) }}</span>
</div>
</div>
<div class="mobile-card__footer">
<el-button size="small" type="primary" @click.stop="openForm('update', item.id)" v-hasPermi="['erp:product:update']" :disabled="item.name === '番茄' || item.name === '甜菊糖' || item.name === '番茄酱' || item.name === '甜叶菊'">编辑</el-button>
<el-button size="small" type="danger" @click.stop="handleDelete(item.id)" v-hasPermi="['erp:product:delete']" :disabled="item.name === '番茄' || item.name === '甜菊糖' || item.name === '番茄酱' || item.name === '甜叶菊'">删除</el-button>
</div>
</div>
</div>
<!-- 分页 -->
<div class="mobile-pagination" v-if="total > 0">
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" :page-sizes="[10, 20]" layout="total, prev, pager, next" :pager-count="5" @pagination="getList" />
</div>
<!-- 筛选抽屉 -->
<el-drawer v-model="filterVisible" title="筛选条件" direction="btt" size="50%">
<el-form :model="queryParams" ref="queryFormRef" label-position="top">
<el-form-item label="产品分类" prop="categoryId">
<el-tree-select <el-tree-select
v-model="queryParams.categoryId" v-model="queryParams.categoryId"
:data="categoryList" :data="categoryList"
:props="defaultProps" :props="defaultProps"
check-strictly check-strictly
default-expand-all default-expand-all
placeholder="请输入分类" placeholder="请选择分类"
class="!w-240px" style="width:100%"
/> />
</el-form-item> </el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:product:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:product:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form> </el-form>
</ContentWrap> <template #footer>
<el-button @click="resetQuery">重置</el-button>
<!-- 列表 --> <el-button type="primary" @click="handleFilterConfirm">确认筛选</el-button>
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" @row-click="handleRowClick">
<el-table-column label="条码" align="center" prop="barCode" />
<el-table-column label="名称" align="center" prop="name" />
<el-table-column label="规格" align="center" prop="standard" />
<el-table-column label="分类" align="center" prop="categoryName" />
<el-table-column label="单位" align="center" prop="unitName" />
<el-table-column label="供应商" align="center" prop="supplierName" />
<!-- <el-table-column-->
<!-- label="采购价格"-->
<!-- align="center"-->
<!-- prop="purchasePrice"-->
<!-- :formatter="erpPriceTableColumnFormatter"-->
<!-- />-->
<!-- <el-table-column-->
<!-- label="销售价格"-->
<!-- align="center"-->
<!-- prop="salePrice"-->
<!-- :formatter="erpPriceTableColumnFormatter"-->
<!-- />-->
<el-table-column
label="货值"
align="center"
prop="minPrice"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column label="库存预警" align="center" prop="stockAlertCount" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template> </template>
</el-table-column> </el-drawer>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
sortable
/>
<el-table-column label="操作" align="center" width="110">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:product:update']"
:disabled="scope.row.name === '番茄' || scope.row.name === '甜菊糖' || scope.row.name === '番茄酱' ||scope.row.name === '甜叶菊'"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['erp:product:delete']"
:disabled="scope.row.name === '番茄' || scope.row.name === '甜菊糖' || scope.row.name === '番茄酱' ||scope.row.name === '甜叶菊'"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 --> <!-- 表单弹窗添加/修改 -->
<ProductForm ref="formRef" @success="getList" /> <ProductForm ref="formRef" @success="getList" />
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { Search, Filter, Plus } from '@element-plus/icons-vue'
import { dateFormatter } from '@/utils/formatTime' import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download' import download from '@/utils/download'
import { ProductApi, ProductVO } from '@/api/erp/product/product' import { ProductApi, ProductVO } from '@/api/erp/product/product'
@@ -151,6 +110,7 @@ const { t } = useI18n() // 国际化
const loading = ref(true) // 列表的加载中 const loading = ref(true) // 列表的加载中
const list = ref<ProductVO[]>([]) // 列表的数据 const list = ref<ProductVO[]>([]) // 列表的数据
const total = ref(0) // 列表的总页数 const total = ref(0) // 列表的总页数
const filterVisible = ref(false) // 筛选抽屉
const queryParams = reactive({ const queryParams = reactive({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
@@ -181,16 +141,26 @@ const handleQuery = () => {
/** 重置按钮操作 */ /** 重置按钮操作 */
const resetQuery = () => { const resetQuery = () => {
queryFormRef.value.resetFields() queryFormRef.value?.resetFields()
handleQuery() handleQuery()
} }
/** 行点击操作 */
const handleRowClick = (row: ProductVO) => { /** 筛选确认 */
if (row.name === '番茄' || row.name === '甜菊糖' || row.name === '番茄酱' || row.name === '甜叶菊'){ const handleFilterConfirm = () => {
return; filterVisible.value = false
}else { handleQuery()
}
/** 卡片点击 */
const handleCardClick = (row: ProductVO) => {
if (row.name === '番茄' || row.name === '甜菊糖' || row.name === '番茄酱' || row.name === '甜叶菊') return
openForm('update', row.id) openForm('update', row.id)
} }
/** 格式化价格 */
const formatPrice = (price: any) => {
if (!price) return '-'
return erpPriceTableColumnFormatter({ cellValue: price })
} }
/** 添加/修改操作 */ /** 添加/修改操作 */
const formRef = ref() const formRef = ref()
@@ -234,3 +204,35 @@ onMounted(async () => {
categoryList.value = handleTree(categoryData, 'id', 'parentId') categoryList.value = handleTree(categoryData, 'id', 'parentId')
}) })
</script> </script>
<style lang="scss" scoped>
.mobile-product {
padding: 12px;
background: #f5f5f5;
min-height: 100vh;
}
.mobile-header {
display: flex; gap: 8px; align-items: center; margin-bottom: 12px;
&__search { flex: 1; }
&__actions { display: flex; gap: 4px; flex-shrink: 0; }
}
.mobile-quick-actions {
display: flex; gap: 8px; margin-bottom: 12px;
}
.mobile-list { display: flex; flex-direction: column; gap: 10px; }
.mobile-empty { padding: 40px 0; }
.mobile-card {
background: #fff; border-radius: 10px; padding: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06);
&__header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }
&__name { font-weight: 600; font-size: 15px; color: #303133; }
&__body { font-size: 13px; }
&__row { display: flex; justify-content: space-between; padding: 3px 0; }
&__label { color: #909399; flex-shrink: 0; margin-right: 12px; }
&__value { color: #606266; text-align: right; }
&__footer { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; padding-top: 10px; border-top: 1px solid #f0f0f0; }
}
.mobile-pagination {
margin-top: 12px; display: flex; justify-content: center;
:deep(.el-pagination) { flex-wrap: wrap; justify-content: center; }
}
</style>

View File

@@ -1,16 +1,31 @@
<template> <template>
<Dialog :title="dialogTitle" v-model="dialogVisible"> <el-drawer
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<div class="mobile-form" v-loading="formLoading">
<el-form <el-form
ref="formRef" ref="formRef"
:model="formData" :model="formData"
:rules="formRules" :rules="formRules"
label-width="100px" label-position="top"
v-loading="formLoading"
> >
<el-form-item label="单位名字" prop="name"> <div class="mobile-form-section">
<el-input v-model="formData.name" placeholder="请输入单位名字" /> <div class="mobile-form-section__title">基础信息</div>
<el-form-item label="单位名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入单位名称" clearable />
</el-form-item> </el-form-item>
<el-form-item label="单位状态" prop="status"> </div>
<div class="mobile-form-section">
<div class="mobile-form-section__title">状态信息</div>
<el-form-item label="开启状态" prop="status">
<el-radio-group v-model="formData.status"> <el-radio-group v-model="formData.status">
<el-radio <el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
@@ -21,12 +36,16 @@
</el-radio> </el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</div>
</el-form> </el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button> <!-- 底部操作按钮 -->
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false"> </el-button> <el-button @click="dialogVisible = false"> </el-button>
</template> <el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
</Dialog> </div>
</div>
</el-drawer>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ProductUnitApi } from '@/api/erp/product/unit' import { ProductUnitApi } from '@/api/erp/product/unit'
@@ -106,3 +125,52 @@ const resetForm = () => {
formRef.value?.resetFields() formRef.value?.resetFields()
} }
</script> </script>
<style lang="scss" scoped>
.mobile-form {
padding: 12px;
}
.mobile-form-section {
background: #fff;
border-radius: 10px;
padding: 14px;
margin-bottom: 12px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
}
.mobile-form-section__title {
font-size: 15px;
font-weight: 600;
color: #303133;
margin-bottom: 12px;
padding-bottom: 8px;
border-bottom: 1px solid #f0f0f0;
}
.mobile-form__footer {
position: sticky;
bottom: 0;
background: #fff;
padding: 12px 16px;
padding-bottom: calc(12px + constant(safe-area-inset-bottom));
padding-bottom: calc(12px + env(safe-area-inset-bottom));
border-top: 1px solid #eee;
display: flex;
justify-content: flex-end;
gap: 12px;
z-index: 10;
margin: 0 -12px -12px;
.el-button {
flex: 1;
height: 40px;
font-size: 15px;
}
}
:deep(.el-form-item) {
margin-bottom: 16px;
}
:deep(.el-input),
:deep(.el-select) {
width: 100% !important;
}
</style>

View File

@@ -1,31 +1,54 @@
<template> <template>
<doc-alert title="【产品】产品信息、分类、单位" url="https://doc.iocoder.cn/erp/product/" /> <div class="mobile-product-unit">
<!-- 搜索操作栏 -->
<div class="mobile-header">
<div class="mobile-header__search">
<el-input v-model="queryParams.name" placeholder="搜索单位名称" clearable @keyup.enter="handleQuery" :prefix-icon="Search" />
</div>
<div class="mobile-header__actions">
<el-button :icon="Filter" circle @click="filterVisible = true" />
<el-button type="primary" :icon="Plus" circle @click="openForm('create')" v-hasPermi="['erp:product-unit:create']" />
</div>
</div>
<ContentWrap> <!-- 快捷操作 -->
<!-- 搜索工作栏 --> <div class="mobile-quick-actions">
<el-form <el-button size="small" type="success" plain @click="handleExport" :loading="exportLoading" v-hasPermi="['erp:product-unit:export']">导出</el-button>
class="-mb-15px" </div>
:model="queryParams"
ref="queryFormRef" <!-- 卡片列表 -->
:inline="true" <div class="mobile-list" v-loading="loading">
label-width="68px" <div v-if="list.length === 0 && !loading" class="mobile-empty">
> <el-empty description="暂无产品单位" />
<el-form-item label="单位名字" prop="name"> </div>
<el-input <div v-for="item in list" :key="item.id" class="mobile-card" @click="handleCardClick(item)">
v-model="queryParams.name" <div class="mobile-card__header">
placeholder="请输入单位名字" <span class="mobile-card__name">{{ item.name || '-' }}</span>
clearable <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="item.status" />
@keyup.enter="handleQuery" </div>
class="!w-240px" <div class="mobile-card__body">
/> <div class="mobile-card__row">
</el-form-item> <span class="mobile-card__label">创建时间</span>
<span class="mobile-card__value">{{ formatDate(item.createTime) }}</span>
</div>
</div>
<div class="mobile-card__footer">
<el-button size="small" type="primary" @click.stop="openForm('update', item.id)" v-hasPermi="['erp:product-unit:update']">编辑</el-button>
<el-button size="small" type="danger" @click.stop="handleDelete(item.id)" v-hasPermi="['erp:product-unit:delete']">删除</el-button>
</div>
</div>
</div>
<!-- 分页 -->
<div class="mobile-pagination" v-if="total > 0">
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" :page-sizes="[10, 20]" layout="total, prev, pager, next" :pager-count="5" @pagination="getList" />
</div>
<!-- 筛选抽屉 -->
<el-drawer v-model="filterVisible" title="筛选条件" direction="btt" size="50%">
<el-form :model="queryParams" ref="queryFormRef" label-position="top">
<el-form-item label="单位状态" prop="status"> <el-form-item label="单位状态" prop="status">
<el-select <el-select v-model="queryParams.status" placeholder="请选择单位状态" clearable style="width:100%">
v-model="queryParams.status"
placeholder="请选择单位状态"
clearable
class="!w-240px"
>
<el-option <el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value" :key="dict.value"
@@ -34,82 +57,20 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:product-unit:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:product-unit:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form> </el-form>
</ContentWrap> <template #footer>
<el-button @click="resetQuery">重置</el-button>
<!-- 列表 --> <el-button type="primary" @click="handleFilterConfirm">确认筛选</el-button>
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" @row-click="handleRowClick">
<el-table-column label="名字" align="center" prop="name" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template> </template>
</el-table-column> </el-drawer>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
sortable
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:product-unit:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['erp:product-unit:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 --> <!-- 表单弹窗添加/修改 -->
<ProductUnitForm ref="formRef" @success="getList" /> <ProductUnitForm ref="formRef" @success="getList" />
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { Search, Filter, Plus } from '@element-plus/icons-vue'
import { dateFormatter } from '@/utils/formatTime' import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download' import download from '@/utils/download'
import { ProductUnitApi, ProductUnitVO } from '@/api/erp/product/unit' import { ProductUnitApi, ProductUnitVO } from '@/api/erp/product/unit'
@@ -125,6 +86,7 @@ const { t } = useI18n() // 国际化
const loading = ref(true) // 列表的加载中 const loading = ref(true) // 列表的加载中
const list = ref<ProductUnitVO[]>([]) // 列表的数据 const list = ref<ProductUnitVO[]>([]) // 列表的数据
const total = ref(0) // 列表的总页数 const total = ref(0) // 列表的总页数
const filterVisible = ref(false) // 筛选抽屉
const queryParams = reactive({ const queryParams = reactive({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
@@ -154,7 +116,13 @@ const handleQuery = () => {
/** 重置按钮操作 */ /** 重置按钮操作 */
const resetQuery = () => { const resetQuery = () => {
queryFormRef.value.resetFields() queryFormRef.value?.resetFields()
handleQuery()
}
/** 筛选确认 */
const handleFilterConfirm = () => {
filterVisible.value = false
handleQuery() handleQuery()
} }
@@ -177,11 +145,17 @@ const handleDelete = async (id: number) => {
} catch {} } catch {}
} }
/** 行点击操作 */ /** 卡片点击 */
const handleRowClick = (row: ProductUnitVO) => { const handleCardClick = (row: ProductUnitVO) => {
openForm('update', row.id) openForm('update', row.id)
} }
/** 格式化日期 */
const formatDate = (date: any) => {
if (!date) return '-'
return dateFormatter({ cellValue: date })
}
/** 导出按钮操作 */ /** 导出按钮操作 */
const handleExport = async () => { const handleExport = async () => {
try { try {
@@ -202,3 +176,35 @@ onMounted(() => {
getList() getList()
}) })
</script> </script>
<style lang="scss" scoped>
.mobile-product-unit {
padding: 12px;
background: #f5f5f5;
min-height: 100vh;
}
.mobile-header {
display: flex; gap: 8px; align-items: center; margin-bottom: 12px;
&__search { flex: 1; }
&__actions { display: flex; gap: 4px; flex-shrink: 0; }
}
.mobile-quick-actions {
display: flex; gap: 8px; margin-bottom: 12px;
}
.mobile-list { display: flex; flex-direction: column; gap: 10px; }
.mobile-empty { padding: 40px 0; }
.mobile-card {
background: #fff; border-radius: 10px; padding: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06);
&__header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }
&__name { font-weight: 600; font-size: 15px; color: #303133; }
&__body { font-size: 13px; }
&__row { display: flex; justify-content: space-between; padding: 3px 0; }
&__label { color: #909399; flex-shrink: 0; margin-right: 12px; }
&__value { color: #606266; text-align: right; }
&__footer { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; padding-top: 10px; border-top: 1px solid #f0f0f0; }
}
.mobile-pagination {
margin-top: 12px; display: flex; justify-content: center;
:deep(.el-pagination) { flex-wrap: wrap; justify-content: center; }
}
</style>