库存盘点和项目的初版

This commit is contained in:
砂糖
2025-07-26 14:06:06 +08:00
parent 56409a9340
commit bf05e84eee
18 changed files with 3112 additions and 4 deletions

View File

@@ -24,9 +24,18 @@
</view>
<view class="entry-item" @click="goExpress">
<image class="entry-icon" src="/static/images/express.svg" mode="aspectFit"></image>
<text class="entry-text">快递信息</text>
<text class="entry-text">快递信息</text>
</view>
<view class="entry-item" @click="goProject">
<image class="entry-icon" src="/static/images/project.png" mode="aspectFit"></image>
<text class="entry-text">项目中心</text>
</view>
<view class="entry-item" @click="goStock">
<image class="entry-icon" src="/static/images/stock.png" mode="aspectFit"></image>
<text class="entry-text">库存盘点</text>
</view>
</view>
</view>
</template>
@@ -81,7 +90,17 @@ export default {
uni.navigateTo({
url: '/pages/workbench/express/express'
})
}
},
goProject() {
uni.navigateTo({
url: '/pages/workbench/project/project'
})
},
goStock() {
uni.navigateTo({
url: '/pages/workbench/wms/wms'
})
}
},
};
</script>

View File

@@ -0,0 +1,139 @@
<template>
<view class="add-project-container">
<uni-forms ref="form" :model="form" label-width="100" class="form-box">
<uni-forms-item label="项目名称" name="projectName" required>
<uni-easyinput v-model="form.projectName" placeholder="请输入项目名称" />
</uni-forms-item>
<uni-forms-item label="项目编号" name="projectNum" required>
<uni-easyinput v-model="form.projectNum" placeholder="请输入项目编号" />
</uni-forms-item>
<uni-forms-item label="项目类型" name="projectType" required>
<oa-dict-select v-model="form.projectType" dict-type="sys_project_type" placeholder="请选择项目类型" />
</uni-forms-item>
<uni-forms-item label="贸易类型" name="tradeType" required>
<uni-data-select v-model="form.tradeType" :localdata="tradeTypeList" placeholder="请选择贸易类型" />
</uni-forms-item>
<uni-forms-item label="代号类型" name="projectCode" required>
<oa-dict-select v-model="form.projectCode" dict-type="sys_project_code" placeholder="请选择代号类型" />
</uni-forms-item>
<uni-forms-item label="优先级" name="projectGrade" required>
<oa-dict-select v-model="form.projectGrade" dict-type="sys_sort_grade" placeholder="请选择优先级" />
</uni-forms-item>
<uni-forms-item label="负责人" name="functionary" required>
<uni-easyinput v-model="form.functionary" placeholder="请输入负责人" />
</uni-forms-item>
<uni-forms-item label="项目地址" name="address">
<uni-easyinput v-model="form.address" placeholder="请输入项目地址" />
</uni-forms-item>
<uni-forms-item label="项目总金额" name="funds" required>
<uni-easyinput v-model="form.funds" placeholder="请输入项目总金额" type="number" />
</uni-forms-item>
<uni-forms-item label="交货期" name="delivery" required>
<uni-easyinput v-model="form.delivery" placeholder="请输入交货期" />
</uni-forms-item>
<uni-forms-item label="项目周期" name="period" required>
<uni-datetime-picker v-model="form.period" type="daterange" rangeSeparator="至" start-placeholder="开始日期"
end-placeholder="结束日期" />
</uni-forms-item>
<uni-forms-item label="质保期" name="guarantee">
<uni-easyinput v-model="form.guarantee" placeholder="请输入质保期" />
</uni-forms-item>
<uni-forms-item label="预付款" name="prePay">
<uni-easyinput v-model="form.prePay" placeholder="请输入预付款" type="number" />
</uni-forms-item>
<uni-forms-item label="项目介绍" name="introduction">
<uni-easyinput v-model="form.introduction" type="textarea" placeholder="请输入项目介绍" />
</uni-forms-item>
<uni-forms-item label="备注" name="remark">
<uni-easyinput v-model="form.remark" type="textarea" placeholder="请输入备注" />
</uni-forms-item>
<!-- <uni-forms-item label="附件" name="accessory">
<uni-file-picker v-model="form.accessory" file-extname=".jpg,.png,.pdf,.doc,.docx" :limit="5" />
</uni-forms-item> -->
<view class="form-actions">
<button type="primary" @click="submitForm">保存</button>
</view>
</uni-forms>
</view>
</template>
<script>
import { addProject } from '@/api/oa/project';
export default {
data() {
return {
form: {
projectName: '',
projectNum: '',
projectType: '',
tradeType: '',
projectCode: '',
projectGrade: '',
functionary: '',
address: '',
funds: '',
delivery: '',
period: [],
guarantee: '',
prePay: '',
introduction: '',
remark: '',
accessory: []
},
tradeTypeList: [
{ value: 0, text: '内贸' },
{ value: 1, text: '外贸' }
// TODO: 替换为实际字典数据
],
projectGradeList: [
{ value: 'high', text: '高' },
{ value: 'middle', text: '中' },
{ value: 'low', text: '低' }
]
}
},
methods: {
submitForm() {
// 校验并提交表单
this.$refs.form.validate().then(res => {
if (res) {
// TODO: 调用新增项目API
console.log(res);
const payload = {
...res,
beginTime: res.period[0] + ' 00:00:00',
finishTime: res.period[1] + ' 00:00:00',
accessory: ''
}
addProject(payload).then(_ => {
uni.showToast({ title: '保存成功', icon: 'success' });
uni.navigateBack()
})
}
}).catch(() => {
uni.showToast({ title: '请完善信息', icon: 'none' });
});
}
}
}
</script>
<style scoped>
.add-project-container {
padding: 24rpx;
}
.form-box {
background: #fff;
border-radius: 16rpx;
padding: 32rpx;
box-shadow: 0 2rpx 12rpx #eee;
}
.form-actions {
margin-top: 32rpx;
text-align: center;
}
</style>

View File

@@ -0,0 +1,197 @@
<template>
<view class="detail-page">
<view class="detail-header">
<text class="header-title">{{ projectDetail.projectName }}</text>
<text class="header-subtitle">{{ projectDetail.projectNum }}</text>
</view>
<view class="detail-content">
<view style="display: flex; justify-content: flex-start; gap: 10rpx">
<uni-tag v-if="projectDetail.projectStatus == 1" size="normal" type="success" text="进度完成"></uni-tag>
<uni-tag v-else-if="projectDetail.projectStatus == 0" size="normal" type="warning" text="进行中"></uni-tag>
<uni-tag v-if="projectDetail.tradeType == 0" size="normal" type="warning" text="内贸"></uni-tag>
<uni-tag v-else-if="projectDetail.tradeType == 1" size="normal" type="success" text="外贸"></uni-tag>
</view>
<view class="info-item">
<text class="info-label">项目类型</text>
<text class="info-value">{{ projectDetail.projectType || '-' }}</text>
</view>
<view class="info-item">
<text class="info-label">项目地址</text>
<text class="info-value">{{ projectDetail.address || '-' }}</text>
</view>
<view class="info-item">
<text class="info-label">项目总金额</text>
<text class="info-value">{{ projectDetail.funds || '-' }}</text>
</view>
<view class="info-item">
<text class="info-label">负责人</text>
<text class="info-value">{{ projectDetail.functionary || '-' }}</text>
</view>
<view class="info-item">
<text class="info-label">项目周期</text>
<text class="info-value">{{ projectDetail.beginTime || '-' }} {{ projectDetail.finishTime || '-' }}</text>
</view>
<view class="info-item">
<text class="info-label">交付时间</text>
<text class="info-value">{{ projectDetail.delivery || '-' }}</text>
</view>
<view class="info-item">
<text class="info-label">保证期</text>
<text class="info-value">{{ projectDetail.guarantee || '-' }}</text>
</view>
<view class="info-item">
<text class="info-label">备注</text>
<text class="info-value">{{ projectDetail.remark || '-' }}</text>
</view>
<view class="info-item">
<text class="info-label">延期原因</text>
<text class="info-value">{{ projectDetail.postponeReason || '无' }}</text>
</view>
<view class="info-item" v-if="projectDetail.prePay > 0">
<text class="info-label">预付款</text>
<text class="info-value">{{ projectDetail.prePay }}</text>
</view>
</view>
<!-- 合同管理 -->
<view class="contract-management">
<text class="contract-title">合同管理</text>
<view v-if="contractDetail && contractDetail.length > 0">
<view class="info-item">
<text class="info-label">合同类型</text>
<text class="info-value">{{ getContractType(contractDetail.contractType) }}</text>
</view>
<view class="info-item">
<text class="info-label">合同编号</text>
<text class="info-value">{{ contractDetail.contractNum || '-' }}</text>
</view>
<view class="info-item">
<text class="info-label">合同金额</text>
<text class="info-value">{{ contractDetail.amount || '-' }}</text>
</view>
</view>
<view v-else>
暂无合同
</view>
</view>
<view v-if="projectDetail.projectStatus == 0" style="margin-top: 20px; text-align: center;">
<button @click="handleClosure">结项</button>
</view>
</view>
</template>
<script>
import { getProject, updateProject } from '@/api/oa/project.js'; // 确保导入正确的 API 方法
import { selectContractByProjectId } from '@/api/oa/oaContract.js';
export default {
data() {
return {
projectDetail: {}, // 存储项目详情
contractDetail: null, // 存储合同详情
};
},
onLoad(options) {
this.fetchProjectDetail(options.id); // 获取项目 ID
},
methods: {
fetchProjectDetail(projectId) {
getProject(projectId).then(res => {
if (res.code === 200) {
this.projectDetail = res.data; // 将返回的数据存储到 projectDetail 中
this.fetchContractDetail(projectId); // 获取合同信息
} else {
console.error('获取项目详情失败:', res.msg);
}
}).catch(error => {
console.error('获取项目详情失败:', error);
});
},
handleClosure() {
// uniapp二次确认
uni.showModal({
title: '提示',
content: '确定要结项吗?',
success: (res) => {
if (res.confirm) {
updateProject({...this.projectDetail, projectStatus: 1}).then(res => {
this.fetchProjectDetail(this.projectDetail.projectId);
});
}
}
});
},
fetchContractDetail(projectId) {
selectContractByProjectId({ projectId }).then(res => {
if (res.code === 200) {
this.contractDetail = res.data; // 将返回的合同信息存储到 contractDetail 中
} else {
console.error('获取合同信息失败:', res.msg);
}
}).catch(error => {
console.error('获取合同信息失败:', error);
});
},
getContractType(contractType) {
const contractTypes = {
1: '采购合同',
2: '项目合同',
};
return contractTypes[contractType] || '未知类型';
},
},
};
</script>
<style scoped>
.detail-page {
padding: 20px; /* 添加内边距 */
}
.detail-header {
margin-bottom: 15px; /* 下边距 */
}
.header-title {
font-size: 24px; /* 标题字号 */
font-weight: bold; /* 加粗 */
}
.header-subtitle {
font-size: 18px; /* 副标题字号 */
color: #666; /* 较淡的字体颜色 */
}
.detail-content {
border: 1px solid #ccc; /* 边框 */
border-radius: 10px; /* 圆角 */
padding: 15px; /* 内边距 */
background-color: #f9f9f9; /* 背景色 */
}
.info-item {
display: flex; /* 使用 Flexbox 布局 */
justify-content: space-between; /* 在一行内均匀分布 */
margin-top: 10px; /* 上边距 */
}
.info-label {
color: #333; /* 标签颜色 */
font-weight: bold; /* 标签加粗 */
}
.info-value {
color: #666; /* 值的颜色 */
}
.contract-management {
margin-top: 20px; /* 上边距 */
}
.contract-title {
font-size: 20px; /* 合同标题字号 */
font-weight: bold; /* 加粗 */
margin-bottom: 10px; /* 下边距 */
}
</style>

View File

@@ -0,0 +1,254 @@
<template>
<view class="project-page">
<!-- 新增按钮 -->
<view class="add-btn-row">
<view class="button-group">
<uni-icons
type="gift"
size="30"
@click="toggleQualityFilter"
:color="qualityFilter ? '#ffcc00' : '#333'"
/>
<!-- <uni-icons
type="gear"
size="30"
@click="openSettingsPopup"
color="#333"
/> -->
<uni-icons
type="plus"
size="30"
@click="handleAdd"
color="#333"
/>
</view>
</view>
<!-- 项目列表 -->
<scroll-view scroll-y @scrolltolower="loadMore" :style="{ height: scrollHeight + 'px' }">
<view class="project-grid">
<view
class="project-card"
v-for="item in projectList"
:key="item.projectId"
@click="handleDetail(item)"
>
<view class="project-title">{{ item.projectName }}</view>
<view class="project-info">
<text>负责人{{ item.functionary }}</text>
<text :style="getRemainTimeStyle(item.remainTime)">
剩余时间{{ item.remainTime }}
</text>
<text>项目总金额{{ item.funds }}</text>
<text v-if="item.prePay > 0" style="color: #ffcc00;">预付款{{ item.prePay }}</text>
<view style="display: flex; justify-content: flex-start; gap: 10rpx; position: absolute; bottom: 20rpx; margin-top: 10rpx;">
<uni-tag v-if="item.projectStatus == 1" size="mini" type="success" text="进度完成"></uni-tag>
<uni-tag v-else-if="item.projectStatus == 0" size="mini" type="warning" text="进行中"></uni-tag>
<uni-tag v-if="item.tradeType == 0" size="mini" type="warning" text="内贸"></uni-tag>
<uni-tag v-else-if="item.tradeType == 1" size="mini" type="success" text="外贸"></uni-tag>
</view>
</view>
</view>
</view>
<!-- 加载更多组件 -->
<uni-load-more :status="loadMoreStatus"></uni-load-more>
</scroll-view>
</view>
</template>
<script>
import { listProject, addProject, updateProject, delProject, getProject } from '@/api/oa/project.js'
export default {
data() {
return {
projectList: [],
form: {},
editType: '', // add/edit
page: 1, // 当前页码
pageSize: 10, // 每页项目数量
selectedProject: {}, // 选中的项目
loadMoreStatus: 'more', // 加载更多状态
scrollHeight: 0, // 滚动区域高度
qualityFilter: false, // 优质筛选开关
}
},
onShow() {
this.getList();
this.calculateScrollHeight();
},
methods: {
calculateScrollHeight() {
const systemInfo = uni.getSystemInfoSync();
const tabHeight = 75; // tab高度
const containerPadding = 40; // 容器padding
this.scrollHeight = systemInfo.windowHeight - tabHeight - containerPadding + 80;
},
getList() {
const params = { pageNum: this.page, pageSize: this.pageSize };
if (this.qualityFilter) {
params.prePay = 0.1; // 添加优质筛选参数
}
listProject(params).then(res => {
const newProjects = (res.rows || []).map(row => ({
...row,
projectTypeLabel: row.projectType,
projectStatusLabel: row.projectStatus,
}));
this.projectList = [...this.projectList, ...newProjects];
if (newProjects.length < this.pageSize) {
this.loadMoreStatus = 'noMore'; // 没有更多数据
} else {
this.loadMoreStatus = 'more'; // 还有更多数据
}
});
},
loadMore() {
if (this.loadMoreStatus === 'more') {
console.log('加载更多');
this.page++;
this.getList();
}
},
handleAdd() {
uni.navigateTo({
url: '/pages/workbench/project/add'
})
},
handleDetail(item) {
uni.navigateTo({
url: '/pages/workbench/project/detail?id=' + item.projectId
})
},
toggleQualityFilter() {
this.qualityFilter = !this.qualityFilter; // 切换优质筛选状态
this.page = 1; // 重置页码
this.projectList = []; // 清空当前项目列表
this.getList(); // 重新获取项目列表
},
openEditPopup(item) {
this.editType = 'edit';
getProject(item.projectId).then(res => {
this.form = { ...res.data };
this.$refs.editPopup.open();
});
},
closePopup() {
this.$refs.editPopup.close();
},
submitForm() {
if (this.editType === 'add') {
addProject(this.form).then(() => {
this.getList();
this.closePopup();
});
} else {
updateProject(this.form).then(() => {
this.getList();
this.closePopup();
});
}
},
handleClosure(item) {
const update = { ...item, projectStatus: '1' };
updateProject(update).then(() => {
this.getList();
});
},
handleDelete(item) {
delProject(item.projectId).then(() => {
this.getList();
});
},
openDetailPopup(item) {
this.selectedProject = item;
this.$refs.detailPopup.open();
},
closeDetailPopup() {
this.$refs.detailPopup.close();
},
getRemainTimeStyle(remainTime) {
if (remainTime > 10) {
return { color: '#3c763d' }; // 绿色
} else if (remainTime > 5) {
return { color: '#8a6d3b' }; // 黄色
} else {
return { color: '#a94442' }; // 红色
}
}
}
}
</script>
<style scoped>
.add-btn-row {
display: flex;
justify-content: flex-end; /* 右对齐 */
align-items: center;
margin: 20rpx;
}
.button-group {
display: flex;
gap: 10px; /* 按钮之间的间距 */
}
.popup-content {
background-color: #fff; /* 设置纯白背景 */
padding: 20px; /* 添加内边距 */
border-radius: 8px; /* 圆角 */
}
.close-button {
display: flex;
justify-content: flex-end; /* 右对齐 */
margin-bottom: 10px; /* 底部间距 */
}
.project-grid {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.project-card {
border: 1px solid #ccc; /* 边框 */
border-radius: 10px; /* 圆角 */
background-color: #fff; /* 背景色 */
margin: 10px;
box-sizing: border-box;
width: calc(50% - 20px); /* 每行两个卡片 */
padding: 20px 15px; /* 添加内边距 */
position: relative;
}
.project-title {
font-size: 20px; /* 项目名称字号 */
font-weight: bold; /* 加粗 */
color: #333; /* 主字体颜色 */
margin-bottom: 5px; /* 下边距 */
}
.project-info text {
display: block; /* 每个信息占一行 */
margin-top: 5px; /* 上边距 */
color: #666; /* 较淡的字体颜色 */
font-size: 16px; /* 信息字号 */
line-height: 1.5; /* 行间距 */
}
.project-info {
margin-top: 10px; /* 项目信息与标题之间的间距 */
}
/* 新增的样式 */
.horizontal-actions {
display: flex;
justify-content: space-between; /* 在一行内均匀分布 */
margin-top: 10px; /* 添加顶部间距 */
}
.horizontal-actions button {
flex: 1; /* 按钮均分宽度 */
margin: 0 5px; /* 按钮之间的间距 */
}
</style>

385
pages/workbench/wms/wms.vue Normal file
View File

@@ -0,0 +1,385 @@
<template>
<view class="container">
<!-- 筛选表单 一行展示 -->
<view class="filter-form-row">
<!-- 型号筛选 -->
<view :class="['filter-item', activeFilter === 'model' ? 'filter-item-expand' : 'filter-item-collapse']">
<template v-if="activeFilter === 'model'">
<view class="input-clear-wrap">
<input
class="filter-input"
v-model="queryParams.model"
placeholder="型号"
@blur="onFilterBlur('model')"
:style="{ color: queryParams.model ? '#2979ff' : '#999' }"
/>
<view v-if="queryParams.model" class="clear-icon" @click="clearFilter('model')">
<uni-icons type="closeempty" color="#bbb" size="18" />
</view>
</view>
</template>
<template v-else>
<view class="filter-icon" @click="toggleFilter('model')">
<uni-icons type="cart" :color="queryParams.model ? '#2979ff' : '#bbb'" size="24" />
</view>
</template>
</view>
<!-- 物料名称筛选 -->
<view :class="['filter-item', activeFilter === 'name' ? 'filter-item-expand' : 'filter-item-collapse']">
<template v-if="activeFilter === 'name'">
<view class="input-clear-wrap">
<input
class="filter-input"
v-model="queryParams.name"
placeholder="物料名称"
@blur="onFilterBlur('name')"
:style="{ color: queryParams.name ? '#2979ff' : '#999' }"
/>
<view v-if="queryParams.name" class="clear-icon" @click="clearFilter('name')">
<uni-icons type="closeempty" color="#bbb" size="18" />
</view>
</view>
</template>
<template v-else>
<view class="filter-icon" @click="toggleFilter('name')">
<uni-icons type="search" :color="queryParams.name ? '#2979ff' : '#bbb'" size="24" />
</view>
</template>
</view>
<!-- 品牌筛选 -->
<view :class="['filter-item', activeFilter === 'brand' ? 'filter-item-expand' : 'filter-item-collapse']">
<template v-if="activeFilter === 'brand'">
<view class="input-clear-wrap">
<input
class="filter-input"
v-model="queryParams.brand"
placeholder="品牌"
@blur="onFilterBlur('brand')"
:style="{ color: queryParams.brand ? '#2979ff' : '#999' }"
/>
<view v-if="queryParams.brand" class="clear-icon" @click="clearFilter('brand')">
<uni-icons type="closeempty" color="#bbb" size="18" />
</view>
</view>
</template>
<template v-else>
<view class="filter-icon" @click="toggleFilter('brand')">
<uni-icons type="circle" :color="queryParams.brand ? '#2979ff' : '#bbb'" size="24" />
</view>
</template>
</view>
<button class="filter-btn" @click="resetQuery">重置</button>
</view>
<!-- 列表展示下拉加载更多 -->
<scroll-view class="list" scroll-y @scrolltolower="loadMore">
<view v-for="(item, index) in oaWarehouseList" :key="item.id" class="list-item">
<view class="row">
<text class="index">{{ index + 1 }}</text>
<text class="name">{{ item.name }}</text>
<text class="model">{{ item.model }}</text>
<text class="brand">{{ item.brand }}</text>
</view>
<view class="row">
<text class="price">单价{{ item.price }}</text>
<text :class="['inventory', item.inventory < item.threshold ? 'low' : '']">
库存{{ item.inventory }}
<text v-if="item.taskInventory !== null">({{ item.taskInventory }})</text>
</text>
<text class="unit">{{ item.unit }}</text>
<text class="specifications">{{ item.specifications }}</text>
</view>
</view>
<view v-if="oaWarehouseList.length === 0" class="empty">暂无数据</view>
<view v-if="loadingMore" class="loading-more">加载中...</view>
<view v-if="!hasMore && oaWarehouseList.length > 0" class="no-more">没有更多了</view>
</scroll-view>
</view>
</template>
<script>
import { listStock } from '@/api/oa/wms/stock.js'
import uniIcons from '@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue'
import uniEasyinput from '@/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue'
export default {
components: {
uniIcons
},
data() {
return {
oaWarehouseList: [],
queryParams: {
pageNum: 1,
pageSize: 20,
model: '',
name: '',
brand: ''
},
total: 0,
loadingMore: false,
hasMore: true,
activeFilter: 'model' // 当前展开的筛选项
}
},
onLoad() {
this.getList()
},
methods: {
getList(isLoadMore = false) {
if (!isLoadMore) {
this.queryParams.pageNum = 1
this.oaWarehouseList = []
this.hasMore = true
}
listStock(this.queryParams).then(res => {
const rows = res.rows || []
this.total = res.total || 0
if (isLoadMore) {
this.oaWarehouseList = this.oaWarehouseList.concat(rows)
} else {
this.oaWarehouseList = rows
}
// 判断是否还有更多
this.hasMore = this.oaWarehouseList.length < this.total
this.loadingMore = false
})
},
handleQuery() {
this.getList(false)
},
toggleFilter(type) {
this.activeFilter = type
},
onFilterBlur(type) {
// 输入框失焦后自动筛选
this.handleQuery()
},
clearFilter(type) {
this.queryParams[type] = ''
this.handleQuery()
},
resetQuery() {
this.queryParams = {
pageNum: 1,
pageSize: 10,
model: '',
name: '',
brand: ''
}
this.getList(false)
},
loadMore() {
if (!this.hasMore || this.loadingMore) return
this.loadingMore = true
this.queryParams.pageNum++
this.getList(true)
}
}
}
</script>
<style scoped>
.input-clear-wrap {
position: relative;
width: 100%;
display: flex;
align-items: center;
}
.clear-icon {
position: absolute;
right: 10rpx;
top: 50%;
transform: translateY(-50%);
z-index: 2;
background: #fff;
border-radius: 50%;
padding: 4rpx;
display: flex;
align-items: center;
justify-content: center;
}
.container {
padding: 20rpx;
}
.filter-form-row {
display: flex;
align-items: center;
margin-bottom: 20rpx;
background: #fff;
border-radius: 8rpx;
box-shadow: 0 2rpx 8rpx #eee;
padding: 8rpx 16rpx;
gap: 12rpx;
}
.filter-item {
display: flex;
align-items: center;
justify-content: center;
height: 56rpx;
transition: all 0.2s;
}
.filter-item-expand {
flex: 1 1 0%;
margin-right: 16rpx;
min-width: 120rpx;
}
.filter-item-collapse {
flex: 0 0 48rpx;
margin-right: 8rpx;
min-width: 48rpx;
max-width: 48rpx;
}
.filter-input {
width: 100%;
padding: 8rpx 12rpx;
border: 1rpx solid #eee;
border-radius: 6rpx;
background: #f8f8f8;
font-size: 28rpx;
transition: color 0.2s;
}
.filter-input {
width: 100%;
padding: 8rpx 12rpx;
border: 1rpx solid #eee;
border-radius: 6rpx;
background: #f8f8f8;
font-size: 28rpx;
transition: color 0.2s;
}
.filter-btn {
margin-right: 12rpx;
padding: 8rpx 24rpx;
background: #2979ff;
color: #fff;
border-radius: 6rpx;
font-size: 28rpx;
border: none;
}
.list {
background: #fff;
border-radius: 8rpx;
box-shadow: 0 2rpx 8rpx #eee;
height: 90vh;
overflow: hidden;
}
.list-item {
margin: 16rpx 16rpx 0 16rpx;
padding: 24rpx 20rpx 16rpx 20rpx;
background: #fff;
border-radius: 12rpx;
box-shadow: 0 2rpx 12rpx #e5e5e5;
display: flex;
flex-direction: column;
position: relative;
}
.row {
display: flex;
flex-wrap: wrap;
align-items: baseline;
margin-bottom: 8rpx;
}
.index {
width: 48rpx;
color: #bbb;
font-size: 28rpx;
font-weight: bold;
margin-right: 16rpx;
}
.name {
font-size: 32rpx;
font-weight: 600;
color: #2979ff;
margin-right: 24rpx;
max-width: 220rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.model {
font-size: 28rpx;
color: #333;
margin-right: 20rpx;
max-width: 160rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.brand {
font-size: 28rpx;
color: #666;
margin-right: 20rpx;
max-width: 120rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.price {
font-size: 28rpx;
color: #faad14;
margin-right: 20rpx;
}
.inventory {
font-size: 28rpx;
font-weight: 600;
margin-right: 20rpx;
color: #52c41a;
}
.inventory.low {
color: #ff4d4f !important;
background: #fff2f0;
border-radius: 6rpx;
padding: 0 8rpx;
}
.unit {
font-size: 26rpx;
color: #999;
margin-right: 16rpx;
}
.specifications {
font-size: 26rpx;
color: #999;
margin-right: 16rpx;
max-width: 120rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.empty {
text-align: center;
color: #999;
padding: 40rpx 0;
}
.loading-more {
text-align: center;
color: #2979ff;
padding: 20rpx 0;
}
.no-more {
text-align: center;
color: #bbb;
padding: 20rpx 0;
}
</style>