feat: 细码改独立页并优化首屏,修改密码简化并升至1.1.27
This commit is contained in:
@@ -80,6 +80,8 @@ const install = (Vue, vm) => {
|
|||||||
// PDA登录接口
|
// PDA登录接口
|
||||||
pdaLogin: (params = {}) => vm.$u.postJson('/login', params),
|
pdaLogin: (params = {}) => vm.$u.postJson('/login', params),
|
||||||
pdaLogout: (params = {}) => vm.$u.postJson('/logout', params),
|
pdaLogout: (params = {}) => vm.$u.postJson('/logout', params),
|
||||||
|
// 修改密码:PUT pda/v1/user/updatePassword(system.UpdateUserPasswordParam: password, user_id)
|
||||||
|
updatePassword: (params = {}) => vm.$u.putJson('/user/updatePassword', params),
|
||||||
// 获取配布单列表
|
// 获取配布单列表
|
||||||
getFpmArrangeOrderList: (params = {}) => vm.$u.get('/product/fpmArrangeOrder/getFpmArrangeOrderList', params),
|
getFpmArrangeOrderList: (params = {}) => vm.$u.get('/product/fpmArrangeOrder/getFpmArrangeOrderList', params),
|
||||||
// 获取成品配布单详情
|
// 获取成品配布单详情
|
||||||
|
|||||||
@@ -506,8 +506,8 @@ export function orderToFormFields(order) {
|
|||||||
|
|
||||||
export function getFineCodeTableColumns(readonly) {
|
export function getFineCodeTableColumns(readonly) {
|
||||||
const cols = [...FINE_CODE_TABLE_COLUMNS];
|
const cols = [...FINE_CODE_TABLE_COLUMNS];
|
||||||
// 操作列放前面,避免 PDA 小屏横向滚动后才看到删除
|
// 非只读:勾选列放前面,支持多选批量删除
|
||||||
if (!readonly) cols.splice(1, 0, { label: '操作', key: 'action', width: 160 });
|
if (!readonly) cols.unshift({ label: '选择', key: 'select', width: 100 });
|
||||||
return cols;
|
return cols;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -519,7 +519,7 @@ export function mapFineCodeTableRows(list, readonly) {
|
|||||||
weight: item.weight != null && item.weight !== '' ? `${item.weight}` : '-',
|
weight: item.weight != null && item.weight !== '' ? `${item.weight}` : '-',
|
||||||
bar_code: item.bar_code || '-',
|
bar_code: item.bar_code || '-',
|
||||||
position: item.position || '-',
|
position: item.position || '-',
|
||||||
action: readonly ? '' : '删除',
|
select: readonly ? '' : 'select',
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -528,6 +528,81 @@ export function getFineCodeTableWidth(columns) {
|
|||||||
return `${total}rpx`;
|
return `${total}rpx`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 按 group_key 在汇总表或明细表中定位细码分组 */
|
||||||
|
export function findFineCodeGroup(order, groupKey) {
|
||||||
|
if (!order || !groupKey) return null;
|
||||||
|
const fromSummary = (order.summary_rows || []).find((row) => row.group_key === groupKey);
|
||||||
|
if (fromSummary) return fromSummary;
|
||||||
|
return (order.item_data || []).find(
|
||||||
|
(row) => row.group_key === groupKey || String(row.id) === String(groupKey),
|
||||||
|
) || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 细码列表合计(条数 / 匹数 / 重量,数值已是展示单位) */
|
||||||
|
export function sumFineCodeList(list) {
|
||||||
|
let roll = 0;
|
||||||
|
let weight = 0;
|
||||||
|
const count = (list || []).length;
|
||||||
|
(list || []).forEach((fc) => {
|
||||||
|
roll += Number(fc.roll) || 0;
|
||||||
|
weight += Number(fc.weight) || 0;
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
count,
|
||||||
|
roll: Number.isInteger(roll) ? roll : Number(roll.toFixed(2)),
|
||||||
|
weight: Number(weight.toFixed(2)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 细码明细页入参缓存(避免进页再拉整单详情卡住;必须带 orderId 防串单) */
|
||||||
|
export const FINE_CODE_PAGE_CACHE_KEY = 'fabric_out_fine_code_page';
|
||||||
|
|
||||||
|
export function buildFineCodePagePayload(orderId, row) {
|
||||||
|
if (!orderId || !row) return null;
|
||||||
|
return {
|
||||||
|
order_id: Number(orderId),
|
||||||
|
group_key: row.group_key || String(row.id || ''),
|
||||||
|
grey_fabric_code: row.grey_fabric_code || '',
|
||||||
|
grey_fabric_name: row.grey_fabric_name || '',
|
||||||
|
yarn_batch: row.yarn_batch || '',
|
||||||
|
machine_number: row.machine_number || '',
|
||||||
|
fine_codes: [...(row.fine_codes || [])],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function saveFineCodePagePayload(orderId, row) {
|
||||||
|
const payload = buildFineCodePagePayload(orderId, row);
|
||||||
|
if (!payload) return null;
|
||||||
|
try {
|
||||||
|
uni.setStorageSync(FINE_CODE_PAGE_CACHE_KEY, payload);
|
||||||
|
} catch (e) {
|
||||||
|
// 存储失败时仍可通过 eventChannel 传参
|
||||||
|
}
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 读取并清除缓存;仅当 orderId + groupKey 同时匹配时返回,避免串单 */
|
||||||
|
export function takeFineCodePagePayload(orderId, groupKey) {
|
||||||
|
try {
|
||||||
|
const payload = uni.getStorageSync(FINE_CODE_PAGE_CACHE_KEY) || null;
|
||||||
|
uni.removeStorageSync(FINE_CODE_PAGE_CACHE_KEY);
|
||||||
|
if (!payload) return null;
|
||||||
|
if (Number(payload.order_id) !== Number(orderId)) return null;
|
||||||
|
if (String(payload.group_key || '') !== String(groupKey || '')) return null;
|
||||||
|
return payload;
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function clearFineCodePagePayload() {
|
||||||
|
try {
|
||||||
|
uni.removeStorageSync(FINE_CODE_PAGE_CACHE_KEY);
|
||||||
|
} catch (e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 确认并执行审核状态变更(新增/编辑/查看页共用)
|
* 确认并执行审核状态变更(新增/编辑/查看页共用)
|
||||||
* @param {Vue} vm 页面实例,需有 $u.api 与 showError
|
* @param {Vue} vm 页面实例,需有 $u.api 与 showError
|
||||||
|
|||||||
@@ -3,35 +3,60 @@
|
|||||||
<view class="popupWrap">
|
<view class="popupWrap">
|
||||||
<view class="popupTitle">细码</view>
|
<view class="popupTitle">细码</view>
|
||||||
<view v-if="!list.length" class="emptyTip">暂无细码数据</view>
|
<view v-if="!list.length" class="emptyTip">暂无细码数据</view>
|
||||||
<scroll-view v-else scroll-x class="tableScroll">
|
<template v-else>
|
||||||
<view class="fineTable" :style="{ width: tableWidth }">
|
<scroll-view scroll-x class="tableScroll">
|
||||||
<view class="tableRow tableHead">
|
<view class="fineTable" :style="{ width: tableWidth }">
|
||||||
|
<view class="tableRow tableHead">
|
||||||
|
<view
|
||||||
|
v-for="col in columns"
|
||||||
|
:key="col.key"
|
||||||
|
class="tableCell headCell"
|
||||||
|
:class="{ selectCell: col.key === 'select' }"
|
||||||
|
:style="cellStyle(col)"
|
||||||
|
@click="col.key === 'select' && !readonly ? toggleSelectAll() : null"
|
||||||
|
>
|
||||||
|
<checkbox
|
||||||
|
v-if="col.key === 'select' && !readonly"
|
||||||
|
:checked="isAllSelected"
|
||||||
|
@click.stop="toggleSelectAll"
|
||||||
|
/>
|
||||||
|
<template v-else>{{ col.label }}</template>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
<view
|
<view
|
||||||
v-for="col in columns"
|
v-for="(row, rowIndex) in tableRows"
|
||||||
:key="col.key"
|
:key="rowIndex"
|
||||||
class="tableCell headCell"
|
class="tableRow"
|
||||||
:style="cellStyle(col)"
|
@click="!readonly && toggleRow(rowIndex)"
|
||||||
>{{ 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)"
|
|
||||||
>
|
>
|
||||||
<text
|
<view
|
||||||
v-if="col.key === 'action' && !readonly"
|
v-for="col in columns"
|
||||||
class="deleteBtn"
|
:key="col.key"
|
||||||
>{{ row[col.key] }}</text>
|
class="tableCell"
|
||||||
<template v-else>{{ row[col.key] }}</template>
|
:class="{ selectCell: col.key === 'select' && !readonly }"
|
||||||
|
:style="cellStyle(col)"
|
||||||
|
>
|
||||||
|
<checkbox
|
||||||
|
v-if="col.key === 'select' && !readonly"
|
||||||
|
:checked="isRowSelected(rowIndex)"
|
||||||
|
@click.stop="toggleRow(rowIndex)"
|
||||||
|
/>
|
||||||
|
<template v-else>{{ row[col.key] }}</template>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
<view v-if="!readonly" class="batchBar">
|
||||||
|
<text class="batchHint">已选 {{ selectedCount }} 条</text>
|
||||||
|
<u-button
|
||||||
|
type="error"
|
||||||
|
size="medium"
|
||||||
|
:disabled="selectedCount === 0"
|
||||||
|
@click="emitBatchDelete"
|
||||||
|
>删除选中({{ selectedCount }})</u-button>
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
<view v-if="!readonly" class="tableTip">勾选细码后点击「删除选中」批量删除</view>
|
||||||
<view v-if="!readonly && list.length" class="tableTip">点击「删除」将调用扫码删除接口</view>
|
</template>
|
||||||
</view>
|
</view>
|
||||||
</u-popup>
|
</u-popup>
|
||||||
</template>
|
</template>
|
||||||
@@ -49,6 +74,11 @@ export default {
|
|||||||
list: { type: Array, default: () => [] },
|
list: { type: Array, default: () => [] },
|
||||||
readonly: { type: Boolean, default: false },
|
readonly: { type: Boolean, default: false },
|
||||||
},
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
selectedIndexes: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
visible: {
|
visible: {
|
||||||
get() { return this.show; },
|
get() { return this.show; },
|
||||||
@@ -63,11 +93,19 @@ export default {
|
|||||||
tableWidth() {
|
tableWidth() {
|
||||||
return getFineCodeTableWidth(this.columns);
|
return getFineCodeTableWidth(this.columns);
|
||||||
},
|
},
|
||||||
tableScrollHeight() {
|
selectedCount() {
|
||||||
const rowHeight = 56;
|
return this.selectedIndexes.length;
|
||||||
const headerHeight = 56;
|
},
|
||||||
const total = headerHeight + this.list.length * rowHeight;
|
isAllSelected() {
|
||||||
return `${Math.min(Math.max(total, 112), 480)}rpx`;
|
return this.list.length > 0 && this.selectedIndexes.length === this.list.length;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
show(val) {
|
||||||
|
if (!val) this.clearSelection();
|
||||||
|
},
|
||||||
|
list() {
|
||||||
|
this.clearSelection();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -78,10 +116,38 @@ export default {
|
|||||||
maxWidth: `${col.width}rpx`,
|
maxWidth: `${col.width}rpx`,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
onCellTap(key, rowIndex) {
|
clearSelection() {
|
||||||
if (this.readonly || key !== 'action') return;
|
this.selectedIndexes = [];
|
||||||
const item = this.list[rowIndex];
|
},
|
||||||
if (item) this.$emit('delete', item);
|
isRowSelected(rowIndex) {
|
||||||
|
return this.selectedIndexes.indexOf(rowIndex) !== -1;
|
||||||
|
},
|
||||||
|
toggleRow(rowIndex) {
|
||||||
|
if (this.readonly) return;
|
||||||
|
const idx = this.selectedIndexes.indexOf(rowIndex);
|
||||||
|
if (idx === -1) {
|
||||||
|
this.selectedIndexes = this.selectedIndexes.concat(rowIndex);
|
||||||
|
} else {
|
||||||
|
this.selectedIndexes = this.selectedIndexes.filter((i) => i !== rowIndex);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toggleSelectAll() {
|
||||||
|
if (this.readonly) return;
|
||||||
|
if (this.isAllSelected) {
|
||||||
|
this.clearSelection();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.selectedIndexes = this.list.map((_, index) => index);
|
||||||
|
},
|
||||||
|
emitBatchDelete() {
|
||||||
|
if (this.readonly || !this.selectedCount) return;
|
||||||
|
const items = this.selectedIndexes
|
||||||
|
.slice()
|
||||||
|
.sort((a, b) => a - b)
|
||||||
|
.map((index) => this.list[index])
|
||||||
|
.filter(Boolean);
|
||||||
|
if (!items.length) return;
|
||||||
|
this.$emit('batch-delete', items);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -115,6 +181,7 @@ export default {
|
|||||||
.tableScroll {
|
.tableScroll {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
max-height: 52vh;
|
||||||
}
|
}
|
||||||
.fineTable {
|
.fineTable {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@@ -161,25 +228,23 @@ export default {
|
|||||||
color: #3e3e3e;
|
color: #3e3e3e;
|
||||||
min-height: 80rpx;
|
min-height: 80rpx;
|
||||||
}
|
}
|
||||||
.actionCell {
|
.selectCell {
|
||||||
padding: 12rpx 8rpx;
|
padding: 12rpx 8rpx;
|
||||||
}
|
}
|
||||||
.deleteBtn {
|
.batchBar {
|
||||||
display: inline-flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: space-between;
|
||||||
min-width: 120rpx;
|
gap: 20rpx;
|
||||||
min-height: 72rpx;
|
margin-top: 24rpx;
|
||||||
padding: 0 20rpx;
|
flex-shrink: 0;
|
||||||
border-radius: 8rpx;
|
}
|
||||||
background: #fff1f0;
|
.batchHint {
|
||||||
border: 1rpx solid #ffa39e;
|
font-size: $pda-font-popup-sub;
|
||||||
color: #f5222d;
|
color: #666;
|
||||||
font-size: $pda-font-action;
|
|
||||||
line-height: 1.2;
|
|
||||||
}
|
}
|
||||||
.tableTip {
|
.tableTip {
|
||||||
margin-top: 20rpx;
|
margin-top: 16rpx;
|
||||||
font-size: $pda-font-popup-sub;
|
font-size: $pda-font-popup-sub;
|
||||||
color: #999;
|
color: #999;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|||||||
+2
-2
@@ -2,8 +2,8 @@
|
|||||||
"name" : "浩拓织厂",
|
"name" : "浩拓织厂",
|
||||||
"appid" : "__UNI__F79F300",
|
"appid" : "__UNI__F79F300",
|
||||||
"description" : "周尚-浩拓织厂",
|
"description" : "周尚-浩拓织厂",
|
||||||
"versionName" : "1.1.26",
|
"versionName" : "1.1.27",
|
||||||
"versionCode" : 126,
|
"versionCode" : 127,
|
||||||
"transformPx" : false,
|
"transformPx" : false,
|
||||||
"app-plus" : {
|
"app-plus" : {
|
||||||
"optimization" : {
|
"optimization" : {
|
||||||
|
|||||||
@@ -605,6 +605,13 @@
|
|||||||
"navigationBarTitleText": "查看坯布出仓单",
|
"navigationBarTitleText": "查看坯布出仓单",
|
||||||
"enablePullDownRefresh": false
|
"enablePullDownRefresh": false
|
||||||
}
|
}
|
||||||
|
},{
|
||||||
|
"path" : "pages/storefabric/storeFabricBusinessOutFineCode",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText": "细码明细",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
},{
|
},{
|
||||||
"path" : "pages/storefabric/storeFabricWarehouseGroupList",
|
"path" : "pages/storefabric/storeFabricWarehouseGroupList",
|
||||||
"style" :
|
"style" :
|
||||||
|
|||||||
@@ -92,14 +92,12 @@
|
|||||||
@confirm="selectConfirmFun"
|
@confirm="selectConfirmFun"
|
||||||
/>
|
/>
|
||||||
<FabricInfoPopup :show.sync="fabricInfoShow" :data="currentFabricInfo" />
|
<FabricInfoPopup :show.sync="fabricInfoShow" :data="currentFabricInfo" />
|
||||||
<FineCodePopup :show.sync="fineCodeShow" :list="currentFineCodes" :readonly="false" @delete="onDeleteFineCode" />
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import formMixin from './storeFabricBusinessOutMixin.js';
|
import formMixin from './storeFabricBusinessOutMixin.js';
|
||||||
import FabricInfoPopup from '@/components/storefabric/FabricInfoPopup.vue';
|
import FabricInfoPopup from '@/components/storefabric/FabricInfoPopup.vue';
|
||||||
import FineCodePopup from '@/components/storefabric/FineCodePopup.vue';
|
|
||||||
import OrderStatusBar from '@/components/storefabric/OrderStatusBar.vue';
|
import OrderStatusBar from '@/components/storefabric/OrderStatusBar.vue';
|
||||||
import FabricOutScanBar from '@/components/storefabric/FabricOutScanBar.vue';
|
import FabricOutScanBar from '@/components/storefabric/FabricOutScanBar.vue';
|
||||||
import FabricOutScanDetail from '@/components/storefabric/FabricOutScanDetail.vue';
|
import FabricOutScanDetail from '@/components/storefabric/FabricOutScanDetail.vue';
|
||||||
@@ -111,7 +109,6 @@ import PlusBarcodePanel from '@/components/common/PlusBarcodePanel.vue';
|
|||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
FabricInfoPopup,
|
FabricInfoPopup,
|
||||||
FineCodePopup,
|
|
||||||
OrderStatusBar,
|
OrderStatusBar,
|
||||||
FabricOutScanBar,
|
FabricOutScanBar,
|
||||||
FabricOutScanDetail,
|
FabricOutScanDetail,
|
||||||
|
|||||||
@@ -75,14 +75,12 @@
|
|||||||
@confirm="selectConfirmFun"
|
@confirm="selectConfirmFun"
|
||||||
/>
|
/>
|
||||||
<FabricInfoPopup :show.sync="fabricInfoShow" :data="currentFabricInfo" />
|
<FabricInfoPopup :show.sync="fabricInfoShow" :data="currentFabricInfo" />
|
||||||
<FineCodePopup :show.sync="fineCodeShow" :list="currentFineCodes" :readonly="false" @delete="onDeleteFineCode" />
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import formMixin from './storeFabricBusinessOutMixin.js';
|
import formMixin from './storeFabricBusinessOutMixin.js';
|
||||||
import FabricInfoPopup from '@/components/storefabric/FabricInfoPopup.vue';
|
import FabricInfoPopup from '@/components/storefabric/FabricInfoPopup.vue';
|
||||||
import FineCodePopup from '@/components/storefabric/FineCodePopup.vue';
|
|
||||||
import OrderStatusBar from '@/components/storefabric/OrderStatusBar.vue';
|
import OrderStatusBar from '@/components/storefabric/OrderStatusBar.vue';
|
||||||
import FabricOutScanBar from '@/components/storefabric/FabricOutScanBar.vue';
|
import FabricOutScanBar from '@/components/storefabric/FabricOutScanBar.vue';
|
||||||
import FabricOutScanDetail from '@/components/storefabric/FabricOutScanDetail.vue';
|
import FabricOutScanDetail from '@/components/storefabric/FabricOutScanDetail.vue';
|
||||||
@@ -94,7 +92,6 @@ import PlusBarcodePanel from '@/components/common/PlusBarcodePanel.vue';
|
|||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
FabricInfoPopup,
|
FabricInfoPopup,
|
||||||
FineCodePopup,
|
|
||||||
OrderStatusBar,
|
OrderStatusBar,
|
||||||
FabricOutScanBar,
|
FabricOutScanBar,
|
||||||
FabricOutScanDetail,
|
FabricOutScanDetail,
|
||||||
|
|||||||
@@ -0,0 +1,566 @@
|
|||||||
|
<template>
|
||||||
|
<view class="fine-code-page">
|
||||||
|
<scroll-view
|
||||||
|
scroll-y
|
||||||
|
class="pageScroll"
|
||||||
|
:style="{ height: scrollHeight }"
|
||||||
|
refresher-enabled
|
||||||
|
:refresher-triggered="triggered"
|
||||||
|
@refresherrefresh="onRefresh"
|
||||||
|
@scrolltolower="onScrollToLower"
|
||||||
|
>
|
||||||
|
<view class="infoCard">
|
||||||
|
<view class="infoTitle">汇总信息</view>
|
||||||
|
<view class="infoRow">
|
||||||
|
<text class="infoLabel">坯布编号</text>
|
||||||
|
<text class="infoValue">{{ summary.grey_fabric_code || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="infoRow">
|
||||||
|
<text class="infoLabel">坯布名称</text>
|
||||||
|
<text class="infoValue">{{ summary.grey_fabric_name || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="infoRow">
|
||||||
|
<text class="infoLabel">纱 批</text>
|
||||||
|
<text class="infoValue">{{ summary.yarn_batch || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="infoRow">
|
||||||
|
<text class="infoLabel">机 台 号</text>
|
||||||
|
<text class="infoValue">{{ summary.machine_number || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="infoRow">
|
||||||
|
<text class="infoLabel">合计条数</text>
|
||||||
|
<text class="infoValue">{{ totals.count }} 条</text>
|
||||||
|
</view>
|
||||||
|
<view class="infoRow">
|
||||||
|
<text class="infoLabel">合计重量</text>
|
||||||
|
<text class="infoValue">{{ totals.weight }} KG</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="summaryBar">
|
||||||
|
<text>细码明细:{{ totals.count }} 条 / {{ totals.roll }} 匹 / {{ totals.weight }} KG</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-if="!fineCodes.length" class="emptyTip">{{ loading ? '加载中...' : '暂无细码数据' }}</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"
|
||||||
|
:class="{ selectCell: col.key === 'select' }"
|
||||||
|
:style="cellStyle(col)"
|
||||||
|
@click="col.key === 'select' && !readonly ? toggleSelectAll() : null"
|
||||||
|
>
|
||||||
|
<checkbox
|
||||||
|
v-if="col.key === 'select' && !readonly"
|
||||||
|
:checked="isAllSelected"
|
||||||
|
@click.stop="toggleSelectAll"
|
||||||
|
/>
|
||||||
|
<template v-else>{{ col.label }}</template>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
v-for="(row, rowIndex) in tableRows"
|
||||||
|
:key="rowIndex"
|
||||||
|
class="tableRow"
|
||||||
|
@click="!readonly && toggleRow(rowIndex)"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
v-for="col in columns"
|
||||||
|
:key="col.key"
|
||||||
|
class="tableCell"
|
||||||
|
:class="{ selectCell: col.key === 'select' && !readonly }"
|
||||||
|
:style="cellStyle(col)"
|
||||||
|
>
|
||||||
|
<checkbox
|
||||||
|
v-if="col.key === 'select' && !readonly"
|
||||||
|
:checked="!!selectedMap[rowIndex]"
|
||||||
|
@click.stop="toggleRow(rowIndex)"
|
||||||
|
/>
|
||||||
|
<template v-else>{{ row[col.key] }}</template>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
<view v-if="hasMore" class="moreTip">正在加载更多细码({{ visibleCount }}/{{ fineCodes.length }})...</view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<view v-if="!readonly" class="pageFooter">
|
||||||
|
<view class="batchBar">
|
||||||
|
<text class="batchHint">已选 {{ selectedCount }} 条</text>
|
||||||
|
<u-button
|
||||||
|
type="error"
|
||||||
|
size="medium"
|
||||||
|
:disabled="selectedCount === 0"
|
||||||
|
@click="onBatchDelete"
|
||||||
|
>删除选中({{ selectedCount }})</u-button>
|
||||||
|
</view>
|
||||||
|
<view class="tableTip">勾选细码后点击「删除选中」批量删除</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import util from '@/common/util';
|
||||||
|
import {
|
||||||
|
normalizeOrder,
|
||||||
|
getFineCodeTableColumns,
|
||||||
|
getFineCodeTableWidth,
|
||||||
|
mapFineCodeTableRows,
|
||||||
|
getFineCodeScanCode,
|
||||||
|
buildScanUpdateParams,
|
||||||
|
findFineCodeGroup,
|
||||||
|
sumFineCodeList,
|
||||||
|
canScanAtStatus,
|
||||||
|
takeFineCodePagePayload,
|
||||||
|
clearFineCodePagePayload,
|
||||||
|
} from '@/common/storeFabricBusinessOut';
|
||||||
|
|
||||||
|
const RENDER_CHUNK = 80;
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
orderId: 0,
|
||||||
|
groupKey: '',
|
||||||
|
readonly: true,
|
||||||
|
loading: false,
|
||||||
|
fineCodes: [],
|
||||||
|
visibleCount: 0,
|
||||||
|
summary: {
|
||||||
|
grey_fabric_code: '',
|
||||||
|
grey_fabric_name: '',
|
||||||
|
yarn_batch: '',
|
||||||
|
machine_number: '',
|
||||||
|
},
|
||||||
|
selectedMap: {},
|
||||||
|
scrollHeight: '100%',
|
||||||
|
triggered: false,
|
||||||
|
changed: false,
|
||||||
|
_chunkTimer: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
columns() {
|
||||||
|
return getFineCodeTableColumns(this.readonly);
|
||||||
|
},
|
||||||
|
visibleFineCodes() {
|
||||||
|
return this.fineCodes.slice(0, this.visibleCount);
|
||||||
|
},
|
||||||
|
tableRows() {
|
||||||
|
return mapFineCodeTableRows(this.visibleFineCodes, this.readonly);
|
||||||
|
},
|
||||||
|
tableWidth() {
|
||||||
|
return getFineCodeTableWidth(this.columns);
|
||||||
|
},
|
||||||
|
totals() {
|
||||||
|
return sumFineCodeList(this.fineCodes);
|
||||||
|
},
|
||||||
|
selectedCount() {
|
||||||
|
return Object.keys(this.selectedMap).filter((k) => this.selectedMap[k]).length;
|
||||||
|
},
|
||||||
|
isAllSelected() {
|
||||||
|
return this.fineCodes.length > 0 && this.selectedCount === this.fineCodes.length;
|
||||||
|
},
|
||||||
|
hasMore() {
|
||||||
|
return this.visibleCount < this.fineCodes.length;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
onLoad(options) {
|
||||||
|
uni.setNavigationBarTitle({ title: '细码明细' });
|
||||||
|
this.orderId = Number(options.id || 0);
|
||||||
|
this.groupKey = decodeURIComponent(options.groupKey || '');
|
||||||
|
this.readonly = String(options.readonly || '1') === '1';
|
||||||
|
if (!this.orderId || !this.groupKey) {
|
||||||
|
uni.showToast({ title: '缺少参数', icon: 'none' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 优先用上一页传入的数据立刻出屏;必须 orderId + groupKey 双匹配,防止串单
|
||||||
|
const cached = takeFineCodePagePayload(this.orderId, this.groupKey);
|
||||||
|
if (cached) this.applyPayload(cached);
|
||||||
|
const channel = this.getOpenerEventChannel && this.getOpenerEventChannel();
|
||||||
|
if (channel) {
|
||||||
|
channel.on('initData', (payload) => {
|
||||||
|
if (!this.isPayloadMatch(payload)) return;
|
||||||
|
this.applyPayload(payload);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 无匹配缓存时再拉接口;有缓存则不阻塞首屏
|
||||||
|
if (!this.fineCodes.length) {
|
||||||
|
this.loadDetail();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onReady() {
|
||||||
|
this.updateScrollHeight();
|
||||||
|
},
|
||||||
|
onUnload() {
|
||||||
|
this.clearChunkTimer();
|
||||||
|
clearFineCodePagePayload();
|
||||||
|
if (!this.changed) return;
|
||||||
|
const channel = this.getOpenerEventChannel && this.getOpenerEventChannel();
|
||||||
|
if (channel) channel.emit('fineCodeChanged');
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
updateScrollHeight() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
uni.getSystemInfo({
|
||||||
|
success: (sys) => {
|
||||||
|
if (this.readonly) {
|
||||||
|
this.scrollHeight = `${sys.windowHeight}px`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const query = uni.createSelectorQuery().in(this);
|
||||||
|
query.select('.pageFooter').boundingClientRect();
|
||||||
|
query.exec((rects) => {
|
||||||
|
const footerH = (rects[0] && rects[0].height) || 0;
|
||||||
|
const h = sys.windowHeight - footerH;
|
||||||
|
this.scrollHeight = `${Math.max(Math.floor(h), 200)}px`;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
cellStyle(col) {
|
||||||
|
return {
|
||||||
|
width: `${col.width}rpx`,
|
||||||
|
minWidth: `${col.width}rpx`,
|
||||||
|
maxWidth: `${col.width}rpx`,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
clearChunkTimer() {
|
||||||
|
if (this._chunkTimer) {
|
||||||
|
clearTimeout(this._chunkTimer);
|
||||||
|
this._chunkTimer = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 分批渲染,避免一次挂载几百行卡住 PDA */
|
||||||
|
scheduleChunkRender(reset) {
|
||||||
|
this.clearChunkTimer();
|
||||||
|
if (reset) this.visibleCount = 0;
|
||||||
|
const step = () => {
|
||||||
|
if (this.visibleCount >= this.fineCodes.length) {
|
||||||
|
this._chunkTimer = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.visibleCount = Math.min(this.visibleCount + RENDER_CHUNK, this.fineCodes.length);
|
||||||
|
if (this.visibleCount < this.fineCodes.length) {
|
||||||
|
this._chunkTimer = setTimeout(step, 16);
|
||||||
|
} else {
|
||||||
|
this._chunkTimer = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 首批同步渲染,马上可见
|
||||||
|
this.visibleCount = Math.min(RENDER_CHUNK, this.fineCodes.length);
|
||||||
|
if (this.visibleCount < this.fineCodes.length) {
|
||||||
|
this._chunkTimer = setTimeout(step, 16);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onScrollToLower() {
|
||||||
|
if (!this.hasMore) return;
|
||||||
|
this.visibleCount = Math.min(this.visibleCount + RENDER_CHUNK, this.fineCodes.length);
|
||||||
|
},
|
||||||
|
isPayloadMatch(payload) {
|
||||||
|
if (!payload) return false;
|
||||||
|
if (Number(payload.order_id) !== Number(this.orderId)) return false;
|
||||||
|
if (String(payload.group_key || '') !== String(this.groupKey || '')) return false;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
applyPayload(payload) {
|
||||||
|
if (!this.isPayloadMatch(payload)) return;
|
||||||
|
this.applyGroup({
|
||||||
|
grey_fabric_code: payload.grey_fabric_code,
|
||||||
|
grey_fabric_name: payload.grey_fabric_name,
|
||||||
|
yarn_batch: payload.yarn_batch,
|
||||||
|
machine_number: payload.machine_number,
|
||||||
|
fine_codes: payload.fine_codes || [],
|
||||||
|
});
|
||||||
|
},
|
||||||
|
applyGroup(row) {
|
||||||
|
if (!row) {
|
||||||
|
this.fineCodes = [];
|
||||||
|
this.visibleCount = 0;
|
||||||
|
this.summary = {
|
||||||
|
grey_fabric_code: '',
|
||||||
|
grey_fabric_name: '',
|
||||||
|
yarn_batch: '',
|
||||||
|
machine_number: '',
|
||||||
|
};
|
||||||
|
this.clearSelection();
|
||||||
|
this.clearChunkTimer();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.summary = {
|
||||||
|
grey_fabric_code: row.grey_fabric_code || '',
|
||||||
|
grey_fabric_name: row.grey_fabric_name || '',
|
||||||
|
yarn_batch: row.yarn_batch || '',
|
||||||
|
machine_number: row.machine_number || '',
|
||||||
|
};
|
||||||
|
this.fineCodes = [...(row.fine_codes || [])];
|
||||||
|
this.clearSelection();
|
||||||
|
this.scheduleChunkRender(true);
|
||||||
|
this.updateScrollHeight();
|
||||||
|
},
|
||||||
|
loadDetail() {
|
||||||
|
this.loading = true;
|
||||||
|
return this.$u.api.gfmOtherDeliveryOrder.detail({ id: this.orderId })
|
||||||
|
.then((res) => {
|
||||||
|
this.triggered = false;
|
||||||
|
this.loading = false;
|
||||||
|
const order = normalizeOrder(res);
|
||||||
|
if (!order) {
|
||||||
|
this.showError('单据不存在');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (!this.readonly && !canScanAtStatus(order.audit_status)) {
|
||||||
|
this.readonly = true;
|
||||||
|
}
|
||||||
|
const row = findFineCodeGroup(order, this.groupKey);
|
||||||
|
if (!row) {
|
||||||
|
this.applyGroup(null);
|
||||||
|
uni.showToast({ title: '未找到对应细码分组', icon: 'none' });
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
this.applyGroup(row);
|
||||||
|
return order;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
this.triggered = false;
|
||||||
|
this.loading = false;
|
||||||
|
this.showError(err.message || '加载失败');
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onRefresh() {
|
||||||
|
this.triggered = true;
|
||||||
|
this.loadDetail();
|
||||||
|
},
|
||||||
|
clearSelection() {
|
||||||
|
this.selectedMap = {};
|
||||||
|
},
|
||||||
|
toggleRow(rowIndex) {
|
||||||
|
if (this.readonly) return;
|
||||||
|
const next = { ...this.selectedMap };
|
||||||
|
if (next[rowIndex]) delete next[rowIndex];
|
||||||
|
else next[rowIndex] = true;
|
||||||
|
this.selectedMap = next;
|
||||||
|
},
|
||||||
|
toggleSelectAll() {
|
||||||
|
if (this.readonly) return;
|
||||||
|
if (this.isAllSelected) {
|
||||||
|
this.clearSelection();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const next = {};
|
||||||
|
for (let i = 0; i < this.fineCodes.length; i += 1) next[i] = true;
|
||||||
|
this.selectedMap = next;
|
||||||
|
},
|
||||||
|
onBatchDelete() {
|
||||||
|
if (this.readonly || !this.selectedCount) return;
|
||||||
|
const indexes = Object.keys(this.selectedMap)
|
||||||
|
.map((k) => Number(k))
|
||||||
|
.filter((i) => this.selectedMap[i])
|
||||||
|
.sort((a, b) => a - b);
|
||||||
|
const targets = indexes
|
||||||
|
.map((index) => this.fineCodes[index])
|
||||||
|
.filter(Boolean)
|
||||||
|
.map((item) => ({
|
||||||
|
item,
|
||||||
|
scanCode: getFineCodeScanCode(item),
|
||||||
|
}))
|
||||||
|
.filter((row) => row.scanCode);
|
||||||
|
if (!targets.length) {
|
||||||
|
this.showError('选中细码缺少条码,无法删除');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: `确认删除选中的 ${targets.length} 条细码?`,
|
||||||
|
success: async (res) => {
|
||||||
|
if (!res.confirm) return;
|
||||||
|
uni.showLoading({ title: `删除中 0/${targets.length}` });
|
||||||
|
let successCount = 0;
|
||||||
|
let failMessage = '';
|
||||||
|
for (let i = 0; i < targets.length; i += 1) {
|
||||||
|
uni.showLoading({ title: `删除中 ${i + 1}/${targets.length}` });
|
||||||
|
try {
|
||||||
|
await this.$u.api.gfmOtherDeliveryOrder.scanUpdate(buildScanUpdateParams({
|
||||||
|
id: this.orderId,
|
||||||
|
scanCode: targets[i].scanCode,
|
||||||
|
scanType: 2,
|
||||||
|
groupKeys: [],
|
||||||
|
detail: {},
|
||||||
|
}));
|
||||||
|
successCount += 1;
|
||||||
|
} catch (e) {
|
||||||
|
failMessage = (e && e.message) || '删除失败';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uni.hideLoading();
|
||||||
|
if (successCount > 0) this.changed = true;
|
||||||
|
await this.loadDetail();
|
||||||
|
if (successCount === targets.length) {
|
||||||
|
this.showSuccess(`已删除 ${successCount} 条`, '删除成功');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (successCount > 0) {
|
||||||
|
this.showError(`已删除 ${successCount} 条,其余失败:${failMessage}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.showError(failMessage || '删除失败');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
showError(message) {
|
||||||
|
util.playErrorAudio();
|
||||||
|
uni.showModal({ title: '提示', content: message, showCancel: false });
|
||||||
|
},
|
||||||
|
showSuccess(message, speakText) {
|
||||||
|
if (speakText) util.playSpeak(speakText);
|
||||||
|
else util.playSuccessAudio();
|
||||||
|
uni.showToast({ title: message, icon: 'success' });
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
page { background-color: #F8F8F8; height: 100%; }
|
||||||
|
.fine-code-page {
|
||||||
|
height: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.pageScroll {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.infoCard {
|
||||||
|
margin: 20rpx 24rpx 0;
|
||||||
|
padding: 20rpx 24rpx;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
}
|
||||||
|
.infoTitle {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.infoRow {
|
||||||
|
display: flex;
|
||||||
|
font-size: 26rpx;
|
||||||
|
padding: 8rpx 0;
|
||||||
|
}
|
||||||
|
.infoLabel {
|
||||||
|
width: 160rpx;
|
||||||
|
color: #999;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.infoValue {
|
||||||
|
flex: 1;
|
||||||
|
color: #333;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
.summaryBar {
|
||||||
|
margin: 16rpx 24rpx 0;
|
||||||
|
padding: 12rpx 16rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #666;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
}
|
||||||
|
.emptyTip {
|
||||||
|
text-align: center;
|
||||||
|
color: #999;
|
||||||
|
padding: 80rpx 0;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
.moreTip {
|
||||||
|
text-align: center;
|
||||||
|
color: #999;
|
||||||
|
padding: 16rpx 0 28rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
.tableScroll {
|
||||||
|
width: auto;
|
||||||
|
margin: 16rpx 24rpx 8rpx;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.fineTable {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
border: 1rpx solid #e1e1e1;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.tableRow {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
align-items: stretch;
|
||||||
|
border-bottom: 1rpx solid #e1e1e1;
|
||||||
|
}
|
||||||
|
.tableRow:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
.tableHead {
|
||||||
|
background: #f1f1f1;
|
||||||
|
}
|
||||||
|
.tableCell {
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: 72rpx;
|
||||||
|
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;
|
||||||
|
min-height: 80rpx;
|
||||||
|
}
|
||||||
|
.selectCell {
|
||||||
|
padding: 12rpx 8rpx;
|
||||||
|
}
|
||||||
|
.pageFooter {
|
||||||
|
flex-shrink: 0;
|
||||||
|
padding: 16rpx 24rpx calc(24rpx + env(safe-area-inset-bottom));
|
||||||
|
background: #fff;
|
||||||
|
border-top: 1rpx solid #eee;
|
||||||
|
box-shadow: 0 -4rpx 12rpx rgba(0, 0, 0, 0.04);
|
||||||
|
}
|
||||||
|
.batchBar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 20rpx;
|
||||||
|
}
|
||||||
|
.batchHint {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.tableTip {
|
||||||
|
margin-top: 12rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -16,7 +16,6 @@ import {
|
|||||||
BUSINESS_UNIT_TYPE_DYEING_FACTORY,
|
BUSINESS_UNIT_TYPE_DYEING_FACTORY,
|
||||||
normalizeOrder,
|
normalizeOrder,
|
||||||
mapToSelectOptions,
|
mapToSelectOptions,
|
||||||
getFineCodeScanCode,
|
|
||||||
canScanAtStatus,
|
canScanAtStatus,
|
||||||
isLockedOrderStatus,
|
isLockedOrderStatus,
|
||||||
getFormStatusActionButtons,
|
getFormStatusActionButtons,
|
||||||
@@ -32,6 +31,7 @@ import {
|
|||||||
buildScanUpdateParams,
|
buildScanUpdateParams,
|
||||||
getOrderDisplayWeight,
|
getOrderDisplayWeight,
|
||||||
getFineCodeDisplayWeight,
|
getFineCodeDisplayWeight,
|
||||||
|
saveFineCodePagePayload,
|
||||||
} from '@/common/storeFabricBusinessOut';
|
} from '@/common/storeFabricBusinessOut';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -53,10 +53,7 @@ export default {
|
|||||||
BillDataMessage: '',
|
BillDataMessage: '',
|
||||||
currentScanItem: null,
|
currentScanItem: null,
|
||||||
fabricInfoShow: false,
|
fabricInfoShow: false,
|
||||||
fineCodeShow: false,
|
|
||||||
currentFabricInfo: {},
|
currentFabricInfo: {},
|
||||||
currentFineCodes: [],
|
|
||||||
currentGroupKey: '',
|
|
||||||
scanDetail: getEmptyScanDetail(),
|
scanDetail: getEmptyScanDetail(),
|
||||||
scanGroupKeys: [],
|
scanGroupKeys: [],
|
||||||
lastScanCode: '',
|
lastScanCode: '',
|
||||||
@@ -342,8 +339,7 @@ export default {
|
|||||||
this.BarCodeDelStatus = (e.detail.value || []).length > 0;
|
this.BarCodeDelStatus = (e.detail.value || []).length > 0;
|
||||||
},
|
},
|
||||||
/** 扫码新增/删除细码,统一走 scanUpdate 接口 */
|
/** 扫码新增/删除细码,统一走 scanUpdate 接口 */
|
||||||
doScanUpdate(scanCode, scanType, options = {}) {
|
doScanUpdate(scanCode, scanType) {
|
||||||
const { refreshFineCodes = false } = options;
|
|
||||||
uni.showLoading({ title: scanType === 2 ? '删除中...' : '处理中...' });
|
uni.showLoading({ title: scanType === 2 ? '删除中...' : '处理中...' });
|
||||||
return this.$u.api.gfmOtherDeliveryOrder.scanUpdate(buildScanUpdateParams({
|
return this.$u.api.gfmOtherDeliveryOrder.scanUpdate(buildScanUpdateParams({
|
||||||
id: this.orderId,
|
id: this.orderId,
|
||||||
@@ -359,20 +355,17 @@ export default {
|
|||||||
this.form.summary_rows = order.summary_rows || [];
|
this.form.summary_rows = order.summary_rows || [];
|
||||||
this.auditStatus = order.audit_status;
|
this.auditStatus = order.audit_status;
|
||||||
this.applyScanDetail(scanCode, order, scanType);
|
this.applyScanDetail(scanCode, order, scanType);
|
||||||
if (refreshFineCodes) {
|
|
||||||
const rows = order.summary_rows || [];
|
|
||||||
const row = rows.find((i) => i.group_key === this.currentGroupKey);
|
|
||||||
this.currentFineCodes = row ? [...(row.fine_codes || [])] : [];
|
|
||||||
}
|
|
||||||
this.BillDataMessage = scanType === 2 ? '删除成功' : '扫码出仓成功';
|
this.BillDataMessage = scanType === 2 ? '删除成功' : '扫码出仓成功';
|
||||||
this.QRBarCode = '';
|
this.QRBarCode = '';
|
||||||
if (scanType === 2) this.showSuccess('删除成功', '删除成功');
|
if (scanType === 2) this.showSuccess('删除成功', '删除成功');
|
||||||
else util.playSpeak('扫码出仓成功');
|
else util.playSpeak('扫码出仓成功');
|
||||||
|
return order;
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
uni.hideLoading();
|
uni.hideLoading();
|
||||||
this.showError(e.message || (scanType === 2 ? '删除失败' : '扫码失败'));
|
this.showError(e.message || (scanType === 2 ? '删除失败' : '扫码失败'));
|
||||||
this.QRBarCode = '';
|
this.QRBarCode = '';
|
||||||
|
throw e;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
openFabricInfo(row) {
|
openFabricInfo(row) {
|
||||||
@@ -380,9 +373,30 @@ export default {
|
|||||||
this.fabricInfoShow = true;
|
this.fabricInfoShow = true;
|
||||||
},
|
},
|
||||||
openFineCode(row) {
|
openFineCode(row) {
|
||||||
this.currentGroupKey = row.group_key || String(row.id);
|
if (!this.orderId) {
|
||||||
this.currentFineCodes = [...(row.fine_codes || [])];
|
this.showError('请先提交保存后再查看细码');
|
||||||
this.fineCodeShow = true;
|
return;
|
||||||
|
}
|
||||||
|
const groupKey = row.group_key || String(row.id || '');
|
||||||
|
if (!groupKey) {
|
||||||
|
this.showError('缺少细码分组信息');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const readonly = (this.isReadonly || !this.canScan) ? 1 : 0;
|
||||||
|
const payload = saveFineCodePagePayload(this.orderId, row);
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `./storeFabricBusinessOutFineCode?id=${this.orderId}&groupKey=${encodeURIComponent(groupKey)}&readonly=${readonly}`,
|
||||||
|
events: {
|
||||||
|
fineCodeChanged: () => {
|
||||||
|
if (this.orderId) this.loadOrder(this.orderId);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
success: (res) => {
|
||||||
|
if (payload && res.eventChannel) {
|
||||||
|
res.eventChannel.emit('initData', payload);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
},
|
},
|
||||||
onSummaryCellClick(event) {
|
onSummaryCellClick(event) {
|
||||||
const row = event && event.lineData;
|
const row = event && event.lineData;
|
||||||
@@ -393,22 +407,6 @@ export default {
|
|||||||
}
|
}
|
||||||
this.openFineCode(row);
|
this.openFineCode(row);
|
||||||
},
|
},
|
||||||
onDeleteFineCode(fineCode) {
|
|
||||||
if (this.isReadonly || !this.canScan) return;
|
|
||||||
const scanCode = getFineCodeScanCode(fineCode);
|
|
||||||
if (!scanCode) {
|
|
||||||
this.showError('该细码缺少条码,无法删除');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uni.showModal({
|
|
||||||
title: '提示',
|
|
||||||
content: `确认删除细码 ${scanCode}?`,
|
|
||||||
success: (res) => {
|
|
||||||
if (!res.confirm) return;
|
|
||||||
this.doScanUpdate(scanCode, 2, { refreshFineCodes: true });
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleStatusAction(action) {
|
handleStatusAction(action) {
|
||||||
confirmOrderStatusAction(this, {
|
confirmOrderStatusAction(this, {
|
||||||
orderId: this.orderId,
|
orderId: this.orderId,
|
||||||
|
|||||||
@@ -36,14 +36,12 @@
|
|||||||
<FabricOutFooter :buttons="actionButtons" @action="handleAction" />
|
<FabricOutFooter :buttons="actionButtons" @action="handleAction" />
|
||||||
|
|
||||||
<FabricInfoPopup :show.sync="fabricInfoShow" :data="currentFabricInfo" />
|
<FabricInfoPopup :show.sync="fabricInfoShow" :data="currentFabricInfo" />
|
||||||
<FineCodePopup :show.sync="fineCodeShow" :list="currentFineCodes" :readonly="true" />
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import util from '@/common/util';
|
import util from '@/common/util';
|
||||||
import FabricInfoPopup from '@/components/storefabric/FabricInfoPopup.vue';
|
import FabricInfoPopup from '@/components/storefabric/FabricInfoPopup.vue';
|
||||||
import FineCodePopup from '@/components/storefabric/FineCodePopup.vue';
|
|
||||||
import OrderStatusBar from '@/components/storefabric/OrderStatusBar.vue';
|
import OrderStatusBar from '@/components/storefabric/OrderStatusBar.vue';
|
||||||
import FabricOutDetailList from '@/components/storefabric/FabricOutDetailList.vue';
|
import FabricOutDetailList from '@/components/storefabric/FabricOutDetailList.vue';
|
||||||
import FabricOutFooter from '@/components/storefabric/FabricOutFooter.vue';
|
import FabricOutFooter from '@/components/storefabric/FabricOutFooter.vue';
|
||||||
@@ -54,19 +52,18 @@ import {
|
|||||||
confirmOrderStatusAction,
|
confirmOrderStatusAction,
|
||||||
formatDisplayTime,
|
formatDisplayTime,
|
||||||
STATUS_ACTION_VOICE,
|
STATUS_ACTION_VOICE,
|
||||||
|
saveFineCodePagePayload,
|
||||||
} from '@/common/storeFabricBusinessOut';
|
} from '@/common/storeFabricBusinessOut';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { FabricInfoPopup, FineCodePopup, OrderStatusBar, FabricOutDetailList, FabricOutFooter },
|
components: { FabricInfoPopup, OrderStatusBar, FabricOutDetailList, FabricOutFooter },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
orderId: 0,
|
orderId: 0,
|
||||||
order: {},
|
order: {},
|
||||||
billTypeName: (BILL_TYPES[0] || {}).label || '坯布其他出货单',
|
billTypeName: (BILL_TYPES[0] || {}).label || '坯布其他出货单',
|
||||||
fabricInfoShow: false,
|
fabricInfoShow: false,
|
||||||
fineCodeShow: false,
|
|
||||||
currentFabricInfo: {},
|
currentFabricInfo: {},
|
||||||
currentFineCodes: [],
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -108,8 +105,24 @@ export default {
|
|||||||
this.fabricInfoShow = true;
|
this.fabricInfoShow = true;
|
||||||
},
|
},
|
||||||
openFineCode(row) {
|
openFineCode(row) {
|
||||||
this.currentFineCodes = [...(row.fine_codes || [])];
|
if (!this.orderId) {
|
||||||
this.fineCodeShow = true;
|
this.showError('单据未加载');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const groupKey = row.group_key || String(row.id || '');
|
||||||
|
if (!groupKey) {
|
||||||
|
this.showError('缺少细码分组信息');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const payload = saveFineCodePagePayload(this.orderId, row);
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `./storeFabricBusinessOutFineCode?id=${this.orderId}&groupKey=${encodeURIComponent(groupKey)}&readonly=1`,
|
||||||
|
success: (res) => {
|
||||||
|
if (payload && res.eventChannel) {
|
||||||
|
res.eventChannel.emit('initData', payload);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
},
|
},
|
||||||
handleAction(action) {
|
handleAction(action) {
|
||||||
if (action === 'edit') {
|
if (action === 'edit') {
|
||||||
|
|||||||
+32
-46
@@ -3,19 +3,10 @@
|
|||||||
<view class="remind-text">请设置登录密码<br>
|
<view class="remind-text">请设置登录密码<br>
|
||||||
定期更新密码提高安全性</view>
|
定期更新密码提高安全性</view>
|
||||||
<u-form class="form" :model="model" :rules="rules" ref="uForm">
|
<u-form class="form" :model="model" :rules="rules" ref="uForm">
|
||||||
<u-form-item label="旧密码" prop="oldPassword" label-width="180">
|
<u-form-item label="密码" prop="password" label-width="180">
|
||||||
<u-input type="password" v-model="model.oldPassword" placeholder="请输入旧密码"></u-input>
|
<u-input type="password" v-model="model.password" placeholder="请输入密码"></u-input>
|
||||||
</u-form-item>
|
|
||||||
<u-form-item label="新密码" prop="newPassword" label-width="180">
|
|
||||||
<u-input type="password" v-model="model.newPassword" placeholder="请输入新密码"></u-input>
|
|
||||||
</u-form-item>
|
|
||||||
<u-form-item label="确认密码" prop="confirmPassword" label-width="180">
|
|
||||||
<u-input type="password" v-model="model.confirmPassword" placeholder="请确认新密码"></u-input>
|
|
||||||
</u-form-item>
|
</u-form-item>
|
||||||
</u-form>
|
</u-form>
|
||||||
<view class="remind-text">
|
|
||||||
<u-icon name="question-circle" color="#2767dc" size="28"></u-icon>
|
|
||||||
密码必须是8-16位的数字,字符组合(不能是纯数字)</view>
|
|
||||||
<view class="form-footer">
|
<view class="form-footer">
|
||||||
<u-button class="btn" type="primary" @click="submit">提交</u-button>
|
<u-button class="btn" type="primary" @click="submit">提交</u-button>
|
||||||
<!-- <u-button class="btn" type="default" @click="cancel">关闭</u-button> -->
|
<!-- <u-button class="btn" type="default" @click="cancel">关闭</u-button> -->
|
||||||
@@ -26,46 +17,17 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) 2013-Now http://aidex.vip All rights reserved.
|
* Copyright (c) 2013-Now http://aidex.vip All rights reserved.
|
||||||
*/
|
*/
|
||||||
import base64 from '@/common/base64.js';
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
model: {
|
model: {
|
||||||
oldPassword: '',
|
password: ''
|
||||||
newPassword: '',
|
|
||||||
confirmPassword: ''
|
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
oldPassword: [
|
password: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请输入旧密码',
|
message: '请输入密码',
|
||||||
trigger: ['change','blur'],
|
|
||||||
}
|
|
||||||
],
|
|
||||||
newPassword: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: '请输入新密码',
|
|
||||||
trigger: ['change','blur'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
pattern: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]+\S{5,12}$/,
|
|
||||||
message: '需同时含有字母和数字,长度在6-12之间',
|
|
||||||
trigger: ['change','blur'],
|
|
||||||
}
|
|
||||||
],
|
|
||||||
confirmPassword: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: '请重新输入密码',
|
|
||||||
trigger: ['change','blur'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
validator: (rule, value, callback) => {
|
|
||||||
return value === this.model.newPassword;
|
|
||||||
},
|
|
||||||
message: '两次输入的密码不相等',
|
|
||||||
trigger: ['change','blur'],
|
trigger: ['change','blur'],
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -76,16 +38,37 @@ export default {
|
|||||||
this.$refs.uForm.setRules(this.rules);
|
this.$refs.uForm.setRules(this.rules);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
getCurrentUserId() {
|
||||||
|
const app = getApp();
|
||||||
|
const loginId = app && app.globalData ? app.globalData.LoginID : 0;
|
||||||
|
if (loginId) return Number(loginId);
|
||||||
|
const loginData = uni.getStorageSync('RemoteTokenData');
|
||||||
|
if (loginData && loginData.user_id != null) return Number(loginData.user_id);
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
submit() {
|
submit() {
|
||||||
this.$refs.uForm.validate(valid => {
|
this.$refs.uForm.validate(valid => {
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
this.$u.toast('您填写的信息有误,请根据提示修正。');
|
this.$u.toast('您填写的信息有误,请根据提示修正。');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.$u.api.user.infoSavePwd({
|
const userId = this.getCurrentUserId();
|
||||||
oldPassword: this.model.oldPassword,
|
if (!userId) {
|
||||||
newPassword: this.model.newPassword
|
this.$u.toast('缺少用户信息,请重新登录');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// OpenAPI: system.UpdateUserPasswordParam
|
||||||
|
this.$u.api.updatePassword({
|
||||||
|
password: this.model.password,
|
||||||
|
user_id: userId,
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
const saved = uni.getStorageSync('UserInfo');
|
||||||
|
if (saved && typeof saved === 'object') {
|
||||||
|
uni.setStorageSync('UserInfo', {
|
||||||
|
...saved,
|
||||||
|
password: this.model.password
|
||||||
|
});
|
||||||
|
}
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
title: '提示',
|
title: '提示',
|
||||||
content: '密码修改成功',
|
content: '密码修改成功',
|
||||||
@@ -122,4 +105,7 @@ page{
|
|||||||
padding: 20rpx 30rpx;
|
padding: 20rpx 30rpx;
|
||||||
color: #666666;
|
color: #666666;
|
||||||
}
|
}
|
||||||
|
.form-footer {
|
||||||
|
padding: 40rpx 30rpx;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user