|
@@ -34,7 +34,7 @@ export default {
|
|
|
name: 'WmsHome',
|
|
name: 'WmsHome',
|
|
|
components: { HomeOverview, DashboardDetail, DashboardActions },
|
|
components: { HomeOverview, DashboardDetail, DashboardActions },
|
|
|
data() { return {
|
|
data() { return {
|
|
|
- view: 'home', warehouseId: '', unit: '', filters: {}, options: {}, summary: {}, result: {}, updatedAt: '', error: '', loading: false, exporting: false, portalRoots: [], optionsLoaded: false, receiveQueue: [], preparedReceipts: [], receiving: false, homeLoading: true
|
|
|
|
|
|
|
+ view: 'home', warehouseId: '', unit: '', filters: {}, homeFilters: null, options: {}, summary: {}, result: {}, updatedAt: '', error: '', loading: false, exporting: false, portalRoots: [], optionsLoaded: false, receiveQueue: [], preparedReceipts: [], receiving: false, homeLoading: true
|
|
|
}; },
|
|
}; },
|
|
|
computed: {
|
|
computed: {
|
|
|
// 呆滞阈值向下透传:优先用首页已请求到的同一份 home-summary.stagnantDays(不额外发请求),
|
|
// 呆滞阈值向下透传:优先用首页已请求到的同一份 home-summary.stagnantDays(不额外发请求),
|
|
@@ -66,7 +66,8 @@ export default {
|
|
|
this.readRoute();
|
|
this.readRoute();
|
|
|
try {
|
|
try {
|
|
|
this.options = await homeOptions({ warehouseId: this.warehouseId }); this.optionsLoaded = true;
|
|
this.options = await homeOptions({ warehouseId: this.warehouseId }); this.optionsLoaded = true;
|
|
|
- // 默认单位来自筛选项(后缀 defaultUnit),第一条 readRoute 时 options 还没到,这里必须再兜一次。
|
|
|
|
|
|
|
+ // 首页默认单位:仓库默认「全部授权仓库」,但基本单位必须默认选中后端给的 defaultUnit(当前是 KG)——
|
|
|
|
|
+ // 多基本单位下不选单位,库存总量/周转天数/库龄/分类分布会整片为空。首条 readRoute 时 options 还没到,这里补一次。
|
|
|
this.applyDefaultUnit(Object.prototype.hasOwnProperty.call(this.$route.query, 'unit'));
|
|
this.applyDefaultUnit(Object.prototype.hasOwnProperty.call(this.$route.query, 'unit'));
|
|
|
this.filters = { ...this.filters, unit: this.unit };
|
|
this.filters = { ...this.filters, unit: this.unit };
|
|
|
await this.refresh();
|
|
await this.refresh();
|
|
@@ -86,12 +87,20 @@ export default {
|
|
|
const query = this.$route.query;
|
|
const query = this.$route.query;
|
|
|
const knownView = screens[query.dashboardView] || businessViews[query.dashboardView] || query.dashboardView === 'home';
|
|
const knownView = screens[query.dashboardView] || businessViews[query.dashboardView] || query.dashboardView === 'home';
|
|
|
this.view = knownView ? query.dashboardView : 'home';
|
|
this.view = knownView ? query.dashboardView : 'home';
|
|
|
- this.filters = filterKeys.reduce((r,key) => { if (query[key] != null) r[key] = query[key]; return r; }, { ...monthRange(), page: 1 });
|
|
|
|
|
|
|
+ // 筛选键先统一落「空字符串 = 全部」:URL 上没有的键不能留成 undefined,
|
|
|
|
|
+ // 否则下钻页 select 的 v-model 匹配不上 value="" 的「全部」选项,下拉会渲染成空白(仓库/物料空白就是这么来的)。
|
|
|
|
|
+ const blanks = { warehouseId:'', factoryId:'', unit:'', categoryId:'', keyword:'', type:'', direction:'', stockBatchId:'', age:'', level:'', inspection:'', status:'' };
|
|
|
|
|
+ this.filters = filterKeys.reduce((r,key) => { if (query[key] != null) r[key] = query[key]; return r; }, { ...blanks, ...monthRange(), page: 1 });
|
|
|
this.warehouseId = this.filters.warehouseId || ''; this.unit = this.filters.unit || '';
|
|
this.warehouseId = this.filters.warehouseId || ''; this.unit = this.filters.unit || '';
|
|
|
- if (this.view === 'home') this.applyDefaultUnit(Object.prototype.hasOwnProperty.call(query, 'unit'));
|
|
|
|
|
|
|
+ if (this.view === 'home') {
|
|
|
|
|
+ // 首页默认单位兜底(仓库保持「全部授权仓库」):URL 没写 unit 时才算没表态,显式 unit=(全部单位)不动。
|
|
|
|
|
+ this.applyDefaultUnit(Object.prototype.hasOwnProperty.call(query, 'unit'));
|
|
|
|
|
+ // 首页筛选快照:只存首页真正拥有的两项(仓库/基本单位)。下钻时用它当基线带过去,
|
|
|
|
|
+ // 回首页时用它还原,明细里改的仓库/物料/关键词不会反写首页(单位默认值补完后才快照)。
|
|
|
|
|
+ this.homeFilters = { warehouseId: this.filters.warehouseId || '', unit: this.filters.unit || '' };
|
|
|
|
|
+ }
|
|
|
},
|
|
},
|
|
|
- // 首页默认基本单位:多基本单位下不选单位,库存总量/周转天数/库龄/分类分布会整片为空,
|
|
|
|
|
- // 用户进首页看到的就是「没有数据」。优先用后端 home-options 的 defaultUnit(已按授权仓库算好),
|
|
|
|
|
|
|
+ // 首页默认基本单位:优先用后端 home-options 的 defaultUnit(已按授权仓库算好,当前是 KG),
|
|
|
// 缺失时回退 units 里的第一个非空单位。
|
|
// 缺失时回退 units 里的第一个非空单位。
|
|
|
defaultUnit() {
|
|
defaultUnit() {
|
|
|
const options = this.options || {};
|
|
const options = this.options || {};
|
|
@@ -107,10 +116,13 @@ export default {
|
|
|
if (!unit) return;
|
|
if (!unit) return;
|
|
|
this.unit = unit;
|
|
this.unit = unit;
|
|
|
this.filters = { ...this.filters, unit };
|
|
this.filters = { ...this.filters, unit };
|
|
|
|
|
+ // 首屏 readRoute 时 options 还没到,快照里存的是空单位;这里补完默认单位必须同步刷快照,
|
|
|
|
|
+ // 否则「返回首页」会从快照还原成全部单位,和首次进入的 KG 不一致。
|
|
|
|
|
+ if (this.view === 'home') this.homeFilters = { warehouseId: this.filters.warehouseId || '', unit };
|
|
|
},
|
|
},
|
|
|
route(view, filters, replace = false) {
|
|
route(view, filters, replace = false) {
|
|
|
const query = cleanQuery({ ...filters, unit: filters.unit || '', dashboard: '1', dashboardView: view });
|
|
const query = cleanQuery({ ...filters, unit: filters.unit || '', dashboard: '1', dashboardView: view });
|
|
|
- // 单位始终写进 query:空值也要显式落成 unit=,代表用户主动选了「全部单位」,下钻/返回时不能被默认单位覆盖。
|
|
|
|
|
|
|
+ // 单位始终写进 query:空值也要显式落成 unit=,代表「全部单位」,下钻/返回时不会被当成未表态。
|
|
|
query.unit = filters.unit || '';
|
|
query.unit = filters.unit || '';
|
|
|
if (this.$route.query.dashboardView === view && JSON.stringify(query) === JSON.stringify(this.$route.query)) return;
|
|
if (this.$route.query.dashboardView === view && JSON.stringify(query) === JSON.stringify(this.$route.query)) return;
|
|
|
this.$router[replace ? 'replace' : 'push']({ path: this.$route.path, query }).catch((e) => { if (e.name !== 'NavigationDuplicated') this.$message.error(e.message); });
|
|
this.$router[replace ? 'replace' : 'push']({ path: this.$route.path, query }).catch((e) => { if (e.name !== 'NavigationDuplicated') this.$message.error(e.message); });
|
|
@@ -124,7 +136,11 @@ export default {
|
|
|
// 没有 extra 时 query 是 {},与改动前的「只跳转不过滤」完全等价。
|
|
// 没有 extra 时 query 是 {},与改动前的「只跳转不过滤」完全等价。
|
|
|
// 顺手吞掉 NavigationDuplicated:重复点击「查看台账」不应该弹错误提示。
|
|
// 顺手吞掉 NavigationDuplicated:重复点击「查看台账」不应该弹错误提示。
|
|
|
if (view === 'stockLedger') return this.$router.push({ path: '/warehouseManagement/stockLedger', query: cleanQuery(extra) }).catch((e) => { if (e.name !== 'NavigationDuplicated') this.$message.error(e.message); });
|
|
if (view === 'stockLedger') return this.$router.push({ path: '/warehouseManagement/stockLedger', query: cleanQuery(extra) }).catch((e) => { if (e.name !== 'NavigationDuplicated') this.$message.error(e.message); });
|
|
|
- const filters = { ...this.filters, page: 1, ...extra };
|
|
|
|
|
|
|
+ // 首页 → 明细:筛选条原样继承首页当前的选择(仓库/单位是什么就带什么);
|
|
|
|
|
+ // 明细 → 首页:回到进入明细前的首页筛选快照,避免明细里选的仓库/物料/关键词反写首页,
|
|
|
|
|
+ // 否则下次再下钻就会带着上次列表里的筛选(「仓库/物料不是全部」就是这么来的)。
|
|
|
|
|
+ const base = view === 'home' ? (this.homeFilters || this.filters) : this.filters;
|
|
|
|
|
+ const filters = { ...base, page: 1, ...extra };
|
|
|
if (view !== this.view) ['stockBatchId','age','level','inspection','type','direction'].forEach((key) => { if (!(key in extra)) delete filters[key]; });
|
|
if (view !== this.view) ['stockBatchId','age','level','inspection','type','direction'].forEach((key) => { if (!(key in extra)) delete filters[key]; });
|
|
|
if (view === 'ioapp' && !filters.direction) filters.direction = 'in';
|
|
if (view === 'ioapp' && !filters.direction) filters.direction = 'in';
|
|
|
if (['ioapp','inapp'].includes(view)) {
|
|
if (['ioapp','inapp'].includes(view)) {
|
|
@@ -132,15 +148,24 @@ export default {
|
|
|
// 出入库申请/入总库申请按单位过滤会把申请单筛空,这两个视图不继承首页单位。
|
|
// 出入库申请/入总库申请按单位过滤会把申请单筛空,这两个视图不继承首页单位。
|
|
|
delete filters.categoryId; filters.unit = ''; Object.assign(filters,monthRange());
|
|
delete filters.categoryId; filters.unit = ''; Object.assign(filters,monthRange());
|
|
|
}
|
|
}
|
|
|
- // 回到首页时把单位补回来:上面的业务视图清了 unit,不补就会落到「全部单位」,KPI 又变成没有数据。
|
|
|
|
|
- if (view === 'home' && this.view !== 'home' && !filters.unit) filters.unit = this.defaultUnit();
|
|
|
|
|
|
|
+ // 回到首页:按首页快照还原;只有拿不到快照(直接带 URL 进出明细页)且单位为空时才补默认单位,
|
|
|
|
|
+ // 用户首页显式选的「全部单位」不会被覆盖。
|
|
|
|
|
+ if (view === 'home' && this.view !== 'home' && !this.homeFilters && !filters.unit) filters.unit = this.defaultUnit();
|
|
|
this.route(view, filters);
|
|
this.route(view, filters);
|
|
|
},
|
|
},
|
|
|
// 切换仓库不再清空基本单位:单位列表是「全部授权仓库」口径,与单仓无关;
|
|
// 切换仓库不再清空基本单位:单位列表是「全部授权仓库」口径,与单仓无关;
|
|
|
// 清空后落到「全部单位」会立刻变成没有数据,正是要避免的情况。
|
|
// 清空后落到「全部单位」会立刻变成没有数据,正是要避免的情况。
|
|
|
setWarehouse(warehouseId) { this.route('home', { ...this.filters, warehouseId, page: 1 }); },
|
|
setWarehouse(warehouseId) { this.route('home', { ...this.filters, warehouseId, page: 1 }); },
|
|
|
setUnit(unit) { this.route('home', { ...this.filters, unit, page: 1 }); },
|
|
setUnit(unit) { this.route('home', { ...this.filters, unit, page: 1 }); },
|
|
|
- search(filters) { this.route(this.view, filters); },
|
|
|
|
|
|
|
+ search(filters) {
|
|
|
|
|
+ // 「查询」必须每次都真实生效:参数与当前 URL 完全一致时 route() 会因去重直接 return,
|
|
|
|
|
+ // 一个请求都不发,按钮看起来失灵。这种情况跳过路由去重,强制整页重新拉一次明细(带 loading)。
|
|
|
|
|
+ const query = cleanQuery({ ...filters, unit: filters.unit || '', dashboard: '1', dashboardView: this.view });
|
|
|
|
|
+ query.unit = filters.unit || '';
|
|
|
|
|
+ const same = this.$route.query.dashboardView === this.view && JSON.stringify(query) === JSON.stringify(this.$route.query);
|
|
|
|
|
+ if (same) return this.refresh();
|
|
|
|
|
+ this.route(this.view, filters);
|
|
|
|
|
+ },
|
|
|
parameters(extra = {}) { return cleanQuery({ ...this.filters, ...extra }); },
|
|
parameters(extra = {}) { return cleanQuery({ ...this.filters, ...extra }); },
|
|
|
async refresh() {
|
|
async refresh() {
|
|
|
// 全量刷新入口:路由切换、手动重试、15 分钟定时器都会走到这里,先记录触发上下文。
|
|
// 全量刷新入口:路由切换、手动重试、15 分钟定时器都会走到这里,先记录触发上下文。
|