feat: 细码改独立页并优化首屏,修改密码简化并升至1.1.27
This commit is contained in:
@@ -80,6 +80,8 @@ const install = (Vue, vm) => {
|
||||
// PDA登录接口
|
||||
pdaLogin: (params = {}) => vm.$u.postJson('/login', 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),
|
||||
// 获取成品配布单详情
|
||||
|
||||
@@ -506,8 +506,8 @@ export function orderToFormFields(order) {
|
||||
|
||||
export function getFineCodeTableColumns(readonly) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -519,7 +519,7 @@ export function mapFineCodeTableRows(list, readonly) {
|
||||
weight: item.weight != null && item.weight !== '' ? `${item.weight}` : '-',
|
||||
bar_code: item.bar_code || '-',
|
||||
position: item.position || '-',
|
||||
action: readonly ? '' : '删除',
|
||||
select: readonly ? '' : 'select',
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -528,6 +528,81 @@ export function getFineCodeTableWidth(columns) {
|
||||
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
|
||||
|
||||
@@ -3,35 +3,60 @@
|
||||
<view class="popupWrap">
|
||||
<view class="popupTitle">细码</view>
|
||||
<view v-if="!list.length" class="emptyTip">暂无细码数据</view>
|
||||
<scroll-view v-else scroll-x class="tableScroll">
|
||||
<template v-else>
|
||||
<scroll-view 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)"
|
||||
>{{ col.label }}</view>
|
||||
@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 v-for="(row, rowIndex) in tableRows" :key="rowIndex" class="tableRow">
|
||||
</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="{ actionCell: col.key === 'action' && !readonly }"
|
||||
:class="{ selectCell: col.key === 'select' && !readonly }"
|
||||
:style="cellStyle(col)"
|
||||
@click="onCellTap(col.key, rowIndex)"
|
||||
>
|
||||
<text
|
||||
v-if="col.key === 'action' && !readonly"
|
||||
class="deleteBtn"
|
||||
>{{ row[col.key] }}</text>
|
||||
<checkbox
|
||||
v-if="col.key === 'select' && !readonly"
|
||||
:checked="isRowSelected(rowIndex)"
|
||||
@click.stop="toggleRow(rowIndex)"
|
||||
/>
|
||||
<template v-else>{{ row[col.key] }}</template>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view v-if="!readonly && list.length" class="tableTip">点击「删除」将调用扫码删除接口</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 v-if="!readonly" class="tableTip">勾选细码后点击「删除选中」批量删除</view>
|
||||
</template>
|
||||
</view>
|
||||
</u-popup>
|
||||
</template>
|
||||
@@ -49,6 +74,11 @@ export default {
|
||||
list: { type: Array, default: () => [] },
|
||||
readonly: { type: Boolean, default: false },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedIndexes: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
visible: {
|
||||
get() { return this.show; },
|
||||
@@ -63,11 +93,19 @@ export default {
|
||||
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`;
|
||||
selectedCount() {
|
||||
return this.selectedIndexes.length;
|
||||
},
|
||||
isAllSelected() {
|
||||
return this.list.length > 0 && this.selectedIndexes.length === this.list.length;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
show(val) {
|
||||
if (!val) this.clearSelection();
|
||||
},
|
||||
list() {
|
||||
this.clearSelection();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
@@ -78,10 +116,38 @@ export default {
|
||||
maxWidth: `${col.width}rpx`,
|
||||
};
|
||||
},
|
||||
onCellTap(key, rowIndex) {
|
||||
if (this.readonly || key !== 'action') return;
|
||||
const item = this.list[rowIndex];
|
||||
if (item) this.$emit('delete', item);
|
||||
clearSelection() {
|
||||
this.selectedIndexes = [];
|
||||
},
|
||||
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 {
|
||||
width: 100%;
|
||||
flex-shrink: 0;
|
||||
max-height: 52vh;
|
||||
}
|
||||
.fineTable {
|
||||
display: inline-block;
|
||||
@@ -161,25 +228,23 @@ export default {
|
||||
color: #3e3e3e;
|
||||
min-height: 80rpx;
|
||||
}
|
||||
.actionCell {
|
||||
.selectCell {
|
||||
padding: 12rpx 8rpx;
|
||||
}
|
||||
.deleteBtn {
|
||||
display: inline-flex;
|
||||
.batchBar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 120rpx;
|
||||
min-height: 72rpx;
|
||||
padding: 0 20rpx;
|
||||
border-radius: 8rpx;
|
||||
background: #fff1f0;
|
||||
border: 1rpx solid #ffa39e;
|
||||
color: #f5222d;
|
||||
font-size: $pda-font-action;
|
||||
line-height: 1.2;
|
||||
justify-content: space-between;
|
||||
gap: 20rpx;
|
||||
margin-top: 24rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.batchHint {
|
||||
font-size: $pda-font-popup-sub;
|
||||
color: #666;
|
||||
}
|
||||
.tableTip {
|
||||
margin-top: 20rpx;
|
||||
margin-top: 16rpx;
|
||||
font-size: $pda-font-popup-sub;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
|
||||
+2
-2
@@ -2,8 +2,8 @@
|
||||
"name" : "浩拓织厂",
|
||||
"appid" : "__UNI__F79F300",
|
||||
"description" : "周尚-浩拓织厂",
|
||||
"versionName" : "1.1.26",
|
||||
"versionCode" : 126,
|
||||
"versionName" : "1.1.27",
|
||||
"versionCode" : 127,
|
||||
"transformPx" : false,
|
||||
"app-plus" : {
|
||||
"optimization" : {
|
||||
|
||||
@@ -605,6 +605,13 @@
|
||||
"navigationBarTitleText": "查看坯布出仓单",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},{
|
||||
"path" : "pages/storefabric/storeFabricBusinessOutFineCode",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText": "细码明细",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},{
|
||||
"path" : "pages/storefabric/storeFabricWarehouseGroupList",
|
||||
"style" :
|
||||
|
||||
@@ -92,14 +92,12 @@
|
||||
@confirm="selectConfirmFun"
|
||||
/>
|
||||
<FabricInfoPopup :show.sync="fabricInfoShow" :data="currentFabricInfo" />
|
||||
<FineCodePopup :show.sync="fineCodeShow" :list="currentFineCodes" :readonly="false" @delete="onDeleteFineCode" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import formMixin from './storeFabricBusinessOutMixin.js';
|
||||
import FabricInfoPopup from '@/components/storefabric/FabricInfoPopup.vue';
|
||||
import FineCodePopup from '@/components/storefabric/FineCodePopup.vue';
|
||||
import OrderStatusBar from '@/components/storefabric/OrderStatusBar.vue';
|
||||
import FabricOutScanBar from '@/components/storefabric/FabricOutScanBar.vue';
|
||||
import FabricOutScanDetail from '@/components/storefabric/FabricOutScanDetail.vue';
|
||||
@@ -111,7 +109,6 @@ import PlusBarcodePanel from '@/components/common/PlusBarcodePanel.vue';
|
||||
export default {
|
||||
components: {
|
||||
FabricInfoPopup,
|
||||
FineCodePopup,
|
||||
OrderStatusBar,
|
||||
FabricOutScanBar,
|
||||
FabricOutScanDetail,
|
||||
|
||||
@@ -75,14 +75,12 @@
|
||||
@confirm="selectConfirmFun"
|
||||
/>
|
||||
<FabricInfoPopup :show.sync="fabricInfoShow" :data="currentFabricInfo" />
|
||||
<FineCodePopup :show.sync="fineCodeShow" :list="currentFineCodes" :readonly="false" @delete="onDeleteFineCode" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import formMixin from './storeFabricBusinessOutMixin.js';
|
||||
import FabricInfoPopup from '@/components/storefabric/FabricInfoPopup.vue';
|
||||
import FineCodePopup from '@/components/storefabric/FineCodePopup.vue';
|
||||
import OrderStatusBar from '@/components/storefabric/OrderStatusBar.vue';
|
||||
import FabricOutScanBar from '@/components/storefabric/FabricOutScanBar.vue';
|
||||
import FabricOutScanDetail from '@/components/storefabric/FabricOutScanDetail.vue';
|
||||
@@ -94,7 +92,6 @@ import PlusBarcodePanel from '@/components/common/PlusBarcodePanel.vue';
|
||||
export default {
|
||||
components: {
|
||||
FabricInfoPopup,
|
||||
FineCodePopup,
|
||||
OrderStatusBar,
|
||||
FabricOutScanBar,
|
||||
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,
|
||||
normalizeOrder,
|
||||
mapToSelectOptions,
|
||||
getFineCodeScanCode,
|
||||
canScanAtStatus,
|
||||
isLockedOrderStatus,
|
||||
getFormStatusActionButtons,
|
||||
@@ -32,6 +31,7 @@ import {
|
||||
buildScanUpdateParams,
|
||||
getOrderDisplayWeight,
|
||||
getFineCodeDisplayWeight,
|
||||
saveFineCodePagePayload,
|
||||
} from '@/common/storeFabricBusinessOut';
|
||||
|
||||
export default {
|
||||
@@ -53,10 +53,7 @@ export default {
|
||||
BillDataMessage: '',
|
||||
currentScanItem: null,
|
||||
fabricInfoShow: false,
|
||||
fineCodeShow: false,
|
||||
currentFabricInfo: {},
|
||||
currentFineCodes: [],
|
||||
currentGroupKey: '',
|
||||
scanDetail: getEmptyScanDetail(),
|
||||
scanGroupKeys: [],
|
||||
lastScanCode: '',
|
||||
@@ -342,8 +339,7 @@ export default {
|
||||
this.BarCodeDelStatus = (e.detail.value || []).length > 0;
|
||||
},
|
||||
/** 扫码新增/删除细码,统一走 scanUpdate 接口 */
|
||||
doScanUpdate(scanCode, scanType, options = {}) {
|
||||
const { refreshFineCodes = false } = options;
|
||||
doScanUpdate(scanCode, scanType) {
|
||||
uni.showLoading({ title: scanType === 2 ? '删除中...' : '处理中...' });
|
||||
return this.$u.api.gfmOtherDeliveryOrder.scanUpdate(buildScanUpdateParams({
|
||||
id: this.orderId,
|
||||
@@ -359,20 +355,17 @@ export default {
|
||||
this.form.summary_rows = order.summary_rows || [];
|
||||
this.auditStatus = order.audit_status;
|
||||
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.QRBarCode = '';
|
||||
if (scanType === 2) this.showSuccess('删除成功', '删除成功');
|
||||
else util.playSpeak('扫码出仓成功');
|
||||
return order;
|
||||
})
|
||||
.catch((e) => {
|
||||
uni.hideLoading();
|
||||
this.showError(e.message || (scanType === 2 ? '删除失败' : '扫码失败'));
|
||||
this.QRBarCode = '';
|
||||
throw e;
|
||||
});
|
||||
},
|
||||
openFabricInfo(row) {
|
||||
@@ -380,9 +373,30 @@ export default {
|
||||
this.fabricInfoShow = true;
|
||||
},
|
||||
openFineCode(row) {
|
||||
this.currentGroupKey = row.group_key || String(row.id);
|
||||
this.currentFineCodes = [...(row.fine_codes || [])];
|
||||
this.fineCodeShow = true;
|
||||
if (!this.orderId) {
|
||||
this.showError('请先提交保存后再查看细码');
|
||||
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) {
|
||||
const row = event && event.lineData;
|
||||
@@ -393,22 +407,6 @@ export default {
|
||||
}
|
||||
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) {
|
||||
confirmOrderStatusAction(this, {
|
||||
orderId: this.orderId,
|
||||
|
||||
@@ -36,14 +36,12 @@
|
||||
<FabricOutFooter :buttons="actionButtons" @action="handleAction" />
|
||||
|
||||
<FabricInfoPopup :show.sync="fabricInfoShow" :data="currentFabricInfo" />
|
||||
<FineCodePopup :show.sync="fineCodeShow" :list="currentFineCodes" :readonly="true" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import util from '@/common/util';
|
||||
import FabricInfoPopup from '@/components/storefabric/FabricInfoPopup.vue';
|
||||
import FineCodePopup from '@/components/storefabric/FineCodePopup.vue';
|
||||
import OrderStatusBar from '@/components/storefabric/OrderStatusBar.vue';
|
||||
import FabricOutDetailList from '@/components/storefabric/FabricOutDetailList.vue';
|
||||
import FabricOutFooter from '@/components/storefabric/FabricOutFooter.vue';
|
||||
@@ -54,19 +52,18 @@ import {
|
||||
confirmOrderStatusAction,
|
||||
formatDisplayTime,
|
||||
STATUS_ACTION_VOICE,
|
||||
saveFineCodePagePayload,
|
||||
} from '@/common/storeFabricBusinessOut';
|
||||
|
||||
export default {
|
||||
components: { FabricInfoPopup, FineCodePopup, OrderStatusBar, FabricOutDetailList, FabricOutFooter },
|
||||
components: { FabricInfoPopup, OrderStatusBar, FabricOutDetailList, FabricOutFooter },
|
||||
data() {
|
||||
return {
|
||||
orderId: 0,
|
||||
order: {},
|
||||
billTypeName: (BILL_TYPES[0] || {}).label || '坯布其他出货单',
|
||||
fabricInfoShow: false,
|
||||
fineCodeShow: false,
|
||||
currentFabricInfo: {},
|
||||
currentFineCodes: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -108,8 +105,24 @@ export default {
|
||||
this.fabricInfoShow = true;
|
||||
},
|
||||
openFineCode(row) {
|
||||
this.currentFineCodes = [...(row.fine_codes || [])];
|
||||
this.fineCodeShow = true;
|
||||
if (!this.orderId) {
|
||||
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) {
|
||||
if (action === 'edit') {
|
||||
|
||||
+32
-46
@@ -3,19 +3,10 @@
|
||||
<view class="remind-text">请设置登录密码<br>
|
||||
定期更新密码提高安全性</view>
|
||||
<u-form class="form" :model="model" :rules="rules" ref="uForm">
|
||||
<u-form-item label="旧密码" prop="oldPassword" label-width="180">
|
||||
<u-input type="password" v-model="model.oldPassword" 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 label="密码" prop="password" label-width="180">
|
||||
<u-input type="password" v-model="model.password" placeholder="请输入密码"></u-input>
|
||||
</u-form-item>
|
||||
</u-form>
|
||||
<view class="remind-text">
|
||||
<u-icon name="question-circle" color="#2767dc" size="28"></u-icon>
|
||||
密码必须是8-16位的数字,字符组合(不能是纯数字)</view>
|
||||
<view class="form-footer">
|
||||
<u-button class="btn" type="primary" @click="submit">提交</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.
|
||||
*/
|
||||
import base64 from '@/common/base64.js';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
model: {
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: ''
|
||||
password: ''
|
||||
},
|
||||
rules: {
|
||||
oldPassword: [
|
||||
password: [
|
||||
{
|
||||
required: true,
|
||||
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: '两次输入的密码不相等',
|
||||
message: '请输入密码',
|
||||
trigger: ['change','blur'],
|
||||
}
|
||||
],
|
||||
@@ -76,16 +38,37 @@ export default {
|
||||
this.$refs.uForm.setRules(this.rules);
|
||||
},
|
||||
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() {
|
||||
this.$refs.uForm.validate(valid => {
|
||||
if (!valid) {
|
||||
this.$u.toast('您填写的信息有误,请根据提示修正。');
|
||||
return;
|
||||
}
|
||||
this.$u.api.user.infoSavePwd({
|
||||
oldPassword: this.model.oldPassword,
|
||||
newPassword: this.model.newPassword
|
||||
const userId = this.getCurrentUserId();
|
||||
if (!userId) {
|
||||
this.$u.toast('缺少用户信息,请重新登录');
|
||||
return;
|
||||
}
|
||||
// OpenAPI: system.UpdateUserPasswordParam
|
||||
this.$u.api.updatePassword({
|
||||
password: this.model.password,
|
||||
user_id: userId,
|
||||
}).then(() => {
|
||||
const saved = uni.getStorageSync('UserInfo');
|
||||
if (saved && typeof saved === 'object') {
|
||||
uni.setStorageSync('UserInfo', {
|
||||
...saved,
|
||||
password: this.model.password
|
||||
});
|
||||
}
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '密码修改成功',
|
||||
@@ -122,4 +105,7 @@ page{
|
||||
padding: 20rpx 30rpx;
|
||||
color: #666666;
|
||||
}
|
||||
.form-footer {
|
||||
padding: 40rpx 30rpx;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user