feat(storefabric): 新增坯布出库相关页面及功能

- 在 manifest.json 中添加 Android 包名配置
- 在 package.json 中添加 pnpm 依赖覆盖配置
- 在 pages.json 中注册坯布出库相关页面路由
- 重命名 storefabricBusinessOutAdd.vue 为 storeFabricBusinessOutAdd.vue
- 重构坯布出库新增页面,优化界面布局和交互逻辑
- 添加坯布出库列表、编辑、查看等功能页面
- 集成订单状态栏、面料信息弹窗、细码弹窗等组件
- 实现坯布出库详情列表和扫码功能模块
- 优化表单验证和数据提交流程
This commit is contained in:
2026-06-17 16:59:31 +08:00
parent d5b2e19658
commit 567da03aea
20 changed files with 3065 additions and 1057 deletions
@@ -0,0 +1,160 @@
<template>
<u-popup v-model="visible" mode="center" width="94%" border-radius="14" :closeable="true">
<view class="popupWrap">
<view class="popupTitle">细码</view>
<view v-if="!list.length" class="emptyTip">暂无细码数据</view>
<scroll-view v-else scroll-x class="tableScroll">
<view class="fineTable" :style="{ width: tableWidth }">
<view class="tableRow tableHead">
<view
v-for="col in columns"
:key="col.key"
class="tableCell headCell"
:style="cellStyle(col)"
>{{ col.label }}</view>
</view>
<view v-for="(row, rowIndex) in tableRows" :key="rowIndex" class="tableRow">
<view
v-for="col in columns"
:key="col.key"
class="tableCell"
:class="{ actionCell: col.key === 'action' && !readonly }"
:style="cellStyle(col)"
@click="onCellTap(col.key, rowIndex)"
>{{ row[col.key] }}</view>
</view>
</view>
</scroll-view>
<view v-if="!readonly && list.length" class="tableTip">点击「操作」列删除,将调用扫码删除接口</view>
</view>
</u-popup>
</template>
<script>
import {
getFineCodeTableColumns,
getFineCodeTableWidth,
mapFineCodeTableRows,
} from '@/common/storeFabricBusinessOut';
export default {
props: {
show: { type: Boolean, default: false },
list: { type: Array, default: () => [] },
readonly: { type: Boolean, default: false },
},
computed: {
visible: {
get() { return this.show; },
set(val) { this.$emit('update:show', val); },
},
columns() {
return getFineCodeTableColumns(this.readonly);
},
tableRows() {
return mapFineCodeTableRows(this.list, this.readonly);
},
tableWidth() {
return getFineCodeTableWidth(this.columns);
},
tableScrollHeight() {
const rowHeight = 56;
const headerHeight = 56;
const total = headerHeight + this.list.length * rowHeight;
return `${Math.min(Math.max(total, 112), 480)}rpx`;
},
},
methods: {
cellStyle(col) {
return {
width: `${col.width}rpx`,
minWidth: `${col.width}rpx`,
maxWidth: `${col.width}rpx`,
};
},
onCellTap(key, rowIndex) {
if (this.readonly || key !== 'action') return;
const item = this.list[rowIndex];
if (item) this.$emit('delete', item);
},
},
};
</script>
<style scoped>
.popupWrap {
padding: 24rpx 16rpx 30rpx;
max-height: 80vh;
box-sizing: border-box;
display: flex;
flex-direction: column;
overflow: hidden;
}
.popupTitle {
font-size: 32rpx;
font-weight: bold;
text-align: center;
margin-bottom: 20rpx;
color: #333;
flex-shrink: 0;
}
.emptyTip {
text-align: center;
color: #999;
padding: 40rpx 0;
font-size: 28rpx;
}
.tableScroll {
width: 100%;
flex-shrink: 0;
}
.fineTable {
display: inline-block;
vertical-align: top;
border: 1rpx solid #e1e1e1;
box-sizing: border-box;
}
.tableRow {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
border-bottom: 1rpx solid #e1e1e1;
}
.tableRow:last-child {
border-bottom: none;
}
.tableHead {
background: #f1f1f1;
position: sticky;
top: 0;
z-index: 2;
}
.tableCell {
flex-shrink: 0;
padding: 12rpx 8rpx;
font-size: 22rpx;
color: #333;
text-align: center;
border-right: 1rpx solid #e1e1e1;
box-sizing: border-box;
word-break: break-all;
white-space: normal;
}
.tableCell:last-child {
border-right: none;
}
.headCell {
font-weight: bold;
color: #3e3e3e;
}
.actionCell {
color: #f5222d;
}
.tableTip {
margin-top: 16rpx;
font-size: 22rpx;
color: #999;
text-align: center;
flex-shrink: 0;
}
</style>