| | |
| | | robotSourceAddressPalletCode: "", |
| | | robotTargetAddressPalletCode: "", |
| | | robotGrade: 2, |
| | | robotExceptionMessage: "", |
| | | robotDispatchertime: "", |
| | | robotRemark: "", |
| | | }); |
| | | |
| | | // ç¼è¾è¡¨åé
ç½® |
| | |
| | | /// <summary> |
| | | /// æºå¨äººæ¥æºå°åè¾é线ç¼å· |
| | | /// </summary> |
| | | [SugarColumn(Length = 20, ColumnDescription = "æºå¨äººæ¥æºå°åè¾é线ç¼å·")] |
| | | [SugarColumn(Length = 20, ColumnDescription = "æºå¨äººæ¥æºå°åè¾é线ç¼å·", IsNullable = true)] |
| | | public string RobotSourceAddressLineCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æºå¨äººç®æ å°åè¾é线ç¼å· |
| | | /// </summary> |
| | | [SugarColumn(Length = 20, ColumnDescription = "æºå¨äººç®æ å°åè¾é线ç¼å·")] |
| | | [SugarColumn(Length = 20, ColumnDescription = "æºå¨äººç®æ å°åè¾é线ç¼å·", IsNullable = true)] |
| | | public string RobotTargetAddressLineCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æºå¨äººæ¥æºå°åè¾é线æçå· |
| | | /// </summary> |
| | | [SugarColumn(Length = 20, ColumnDescription = "æºå¨äººæ¥æºå°åè¾é线æçå·")] |
| | | [SugarColumn(Length = 20, ColumnDescription = "æºå¨äººæ¥æºå°åè¾é线æçå·", IsNullable = true)] |
| | | public string RobotSourceAddressPalletCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æºå¨äººç®æ å°å线æçå· |
| | | /// </summary> |
| | | [SugarColumn(Length = 20, ColumnDescription = "æºå¨äººç®æ å°å线æçå·")] |
| | | [SugarColumn(Length = 20, ColumnDescription = "æºå¨äººç®æ å°å线æçå·", IsNullable = true)] |
| | | public string RobotTargetAddressPalletCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æºå¨äººå¼å¸¸ä¿¡æ¯ |
| | | /// </summary> |
| | | [SugarColumn(ColumnDescription = "æºå¨äººå¼å¸¸ä¿¡æ¯")] |
| | | [SugarColumn(ColumnDescription = "æºå¨äººå¼å¸¸ä¿¡æ¯", IsNullable = true)] |
| | | public string RobotExceptionMessage { get; set; } |
| | | |
| | | /// <summary> |
| | |
| | | /// <summary> |
| | | /// æºå¨äººè°åº¦æ¶é´ |
| | | /// </summary> |
| | | [SugarColumn(ColumnDescription = "æºå¨äººè°åº¦æ¶é´")] |
| | | [SugarColumn(ColumnDescription = "æºå¨äººè°åº¦æ¶é´", IsNullable = true)] |
| | | public DateTime? RobotDispatchertime { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æºå¨äººå¤æ³¨ |
| | | /// </summary> |
| | | [SugarColumn(Length = 50, ColumnDescription = "æºå¨äººå¤æ³¨")] |
| | | [SugarColumn(Length = 50, ColumnDescription = "æºå¨äººå¤æ³¨", IsNullable = true)] |
| | | public string RobotRemark { get; set; } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | //æ¤jsæä»¶æ¯ç¨æ¥èªå®ä¹æ©å±ä¸å¡ä»£ç ï¼å¯ä»¥æ©å±ä¸äºèªå®ä¹é¡µé¢æè
éæ°é
ç½®çæç代ç
|
| | |
|
| | | let extension = {
|
| | | components: {
|
| | | //æ¥è¯¢ç颿©å±ç»ä»¶
|
| | | gridHeader: "",
|
| | | gridBody: "",
|
| | | gridFooter: "",
|
| | | //æ°å»ºãç¼è¾å¼¹åºæ¡æ©å±ç»ä»¶
|
| | | modelHeader: "",
|
| | | modelBody: "",
|
| | | modelFooter: "",
|
| | | },
|
| | | tableAction: "",
|
| | | buttons: { view: [], box: [], detail: [] },
|
| | | methods: {
|
| | | onInit() {
|
| | | // æ·»å MESæä½å
|
| | | this.columns.push({
|
| | | title: "æä½",
|
| | | field: "æä½",
|
| | | align: "center",
|
| | | width: 200,
|
| | | fixed: "right",
|
| | | render: (h, { row, column, index }) => {
|
| | | return (
|
| | | <div>
|
| | | <el-button
|
| | | type="primary"
|
| | | size="small"
|
| | | onClick={($e) => {
|
| | | this.handleInbound(row);
|
| | | }}
|
| | | >
|
| | | è¿ç«
|
| | | </el-button>
|
| | | <el-button
|
| | | type="success"
|
| | | size="small"
|
| | | style="margin-left: 8px"
|
| | | onClick={($e) => {
|
| | | this.handleOutbound(row);
|
| | | }}
|
| | | >
|
| | | åºç«
|
| | | </el-button>
|
| | | </div>
|
| | | );
|
| | | },
|
| | | });
|
| | | },
|
| | |
|
| | | // æçè¿ç«æä½
|
| | | async handleInbound(row) {
|
| | | try {
|
| | | await this.$confirm(
|
| | | `确认æ§è¡æçè¿ç«æä½ï¼\næçç¼å·ï¼${row.palletCode}`,
|
| | | "è¿ç«ç¡®è®¤",
|
| | | {
|
| | | confirmButtonText: "确认",
|
| | | cancelButtonText: "åæ¶",
|
| | | type: "warning",
|
| | | },
|
| | | );
|
| | |
|
| | | const result = await this.http.post(
|
| | | "/api/StockInfo/inboundInContainer",
|
| | | {
|
| | | palletCode: row.palletCode,
|
| | | stockId: row.id,
|
| | | },
|
| | | "æ£å¨è°ç¨MESæ¥å£...",
|
| | | );
|
| | |
|
| | | if (result.status) {
|
| | | this.$Message.success(result.message || "æçè¿ç«æå");
|
| | | this.$refs.table.load();
|
| | | } else {
|
| | | this.$error(result.message || "æçè¿ç«å¤±è´¥");
|
| | | }
|
| | | } catch (error) {
|
| | | if (error !== "cancel") {
|
| | | this.$error(error.message || "ç½ç»é误ï¼è¯·ç¨åéè¯");
|
| | | }
|
| | | }
|
| | | },
|
| | |
|
| | | // æçåºç«æä½
|
| | | async handleOutbound(row) {
|
| | | try {
|
| | | await this.$confirm(
|
| | | `确认æ§è¡æçåºç«æä½ï¼\næçç¼å·ï¼${row.palletCode}`,
|
| | | "åºç«ç¡®è®¤",
|
| | | {
|
| | | confirmButtonText: "确认",
|
| | | cancelButtonText: "åæ¶",
|
| | | type: "warning",
|
| | | },
|
| | | );
|
| | |
|
| | | const result = await this.http.post(
|
| | | "/api/StockInfo/outboundInContainer",
|
| | | {
|
| | | palletCode: row.palletCode,
|
| | | stockId: row.id,
|
| | | },
|
| | | "æ£å¨è°ç¨MESæ¥å£...",
|
| | | );
|
| | |
|
| | | if (result.status) {
|
| | | this.$Message.success(result.message || "æçåºç«æå");
|
| | | this.$refs.table.load();
|
| | | } else {
|
| | | this.$error(result.message || "æçåºç«å¤±è´¥");
|
| | | }
|
| | | } catch (error) {
|
| | | if (error !== "cancel") {
|
| | | this.$error(error.message || "ç½ç»é误ï¼è¯·ç¨åéè¯");
|
| | | }
|
| | | }
|
| | | },
|
| | |
|
| | | onInited() {
|
| | | // æ¡æ¶åå§åé
ç½®å
|
| | | },
|
| | | searchBefore(param) {
|
| | | const stockStatusFilter1 = {
|
| | | name: "stockStatus",
|
| | | value: "6",
|
| | | displayType: "int"
|
| | | };
|
| | | const warehouseIdFilter1 = {
|
| | | name: "warehouseId",
|
| | | value: "3",
|
| | | displayType: "int"
|
| | | };
|
| | | if (!param.wheres) {
|
| | | param.wheres = [];
|
| | | }
|
| | | // å°è¿æ»¤æ¡ä»¶æ·»å å°æ¥è¯¢åæ°ä¸
|
| | | param.wheres.push(stockStatusFilter1);
|
| | | param.wheres.push(warehouseIdFilter1);
|
| | | return true;
|
| | | },
|
| | | searchAfter(result) {
|
| | | return result;
|
| | | },
|
| | | addBefore(formData) {
|
| | | return true;
|
| | | },
|
| | | updateBefore(formData) {
|
| | | return true;
|
| | | },
|
| | | rowClick({ row, column, event }) {
|
| | | this.$refs.table.$refs.table.toggleRowSelection(row);
|
| | | },
|
| | | modelOpenAfter(row) {
|
| | | // ç¹å»ç¼è¾ãæ°å»ºæé®å¼¹åºæ¡å
|
| | | },
|
| | | },
|
| | | };
|
| | |
|
| | | export default extension;
|
| | |
| | | path: '/outboundOrderDetail', |
| | | name: 'outboundOrderDetail', |
| | | component: () => import('@/views/outbound/outboundOrderDetail.vue') |
| | | }, { |
| | | }, |
| | | { |
| | | path: '/stockInfo', |
| | | name: 'stockInfo', |
| | | component: () => import('@/views/stock/stockInfo.vue') |
| | | }, { |
| | | }, |
| | | { |
| | | path: '/hcstockInfo', |
| | | name: 'hcstockInfo', |
| | | component: () => import('@/views/stock/hcstockInfo.vue') |
| | | }, |
| | | { |
| | | path: '/stockInfoDetail', |
| | | name: 'stockInfoDetail', |
| | | component: () => import('@/views/stock/stockInfoDetail.vue') |
| | |
| | | <template> |
| | | <div class="dashboard-container"> |
| | | <!-- åä»åºæåº¦åºå
¥åºå¯¹æ¯å¾ --> |
| | | <div class="chart-row full-width"> |
| | | <!-- é¡¶é¨KPIå¡çï¼æ¾ç¤ºæ»è´§ä½ååä»åºè´§ä½ --> |
| | | <div class="kpi-cards"> |
| | | <div class="kpi-card"> |
| | | <div class="kpi-icon">ðï¸</div> |
| | | <div class="kpi-info"> |
| | | <div class="kpi-label">æ»è´§ä½</div> |
| | | <div class="kpi-value">{{ totalLocation }}</div> |
| | | </div> |
| | | </div> |
| | | <div class="kpi-card"> |
| | | <div class="kpi-icon">ð¥</div> |
| | | <div class="kpi-info"> |
| | | <div class="kpi-label">åæåº</div> |
| | | <div class="kpi-value">{{ warehouseLocations.hc }}</div> |
| | | </div> |
| | | </div> |
| | | <div class="kpi-card"> |
| | | <div class="kpi-icon">ð¡ï¸</div> |
| | | <div class="kpi-info"> |
| | | <div class="kpi-label">髿¸©åº</div> |
| | | <div class="kpi-value">{{ warehouseLocations.gw }}</div> |
| | | </div> |
| | | </div> |
| | | <div class="kpi-card"> |
| | | <div class="kpi-icon">âï¸</div> |
| | | <div class="kpi-info"> |
| | | <div class="kpi-label">常温åº</div> |
| | | <div class="kpi-value">{{ warehouseLocations.cw }}</div> |
| | | </div> |
| | | </div> |
| | | <div class="kpi-card"> |
| | | <div class="kpi-icon">ð</div> |
| | | <div class="kpi-info"> |
| | | <div class="kpi-label">æå·åº</div> |
| | | <div class="kpi-value">{{ warehouseLocations.jj }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 第ä¸è¡ï¼4ä¸ªæ¯æ¥åºå
¥åºè¶å¿å¾ï¼æ¯è¡2ä¸ªï¼ --> |
| | | <div class="chart-row daily-grid"> |
| | | <div class="chart-card" v-for="warehouse in dailyWarehouses" :key="warehouse.code"> |
| | | <div class="card-title">{{ warehouse.name }} - æ¯æ¥è¶å¿</div> |
| | | <!-- ä»åºæ°åæ¾ç¤ºåºåï¼æ¾ç¤ºæ¯æ¥æ»éå空æçæ°é --> |
| | | <div class="warehouse-numbers"> |
| | | <!-- æå·åºæ¾ç¤ºæè´§æçï¼çµæ± æ°éï¼å空æç --> |
| | | <template v-if="warehouse.code === 'ROLL'"> |
| | | <div class="number-item battery"> |
| | | <span class="number-label">çµæ± æ°é</span> |
| | | <span class="number-value">{{ getBatteryCount(warehouse.code) }}</span> |
| | | </div> |
| | | <div class="number-item empty-tray"> |
| | | <span class="number-label">空æçæ°é</span> |
| | | <span class="number-value">{{ getEmptyTrayCount(warehouse.code) }}</span> |
| | | </div> |
| | | </template> |
| | | <!-- å
¶ä»ä»åºæ¾ç¤ºçµæ± æ°éå空æçæ°é --> |
| | | <template v-else> |
| | | <div class="number-item inbound"> |
| | | <span class="number-label">çµæ± æ°é</span> |
| | | <span class="number-value">{{ getBatteryCount(warehouse.code) }}</span> |
| | | </div> |
| | | <div class="number-item empty-tray"> |
| | | <span class="number-label">空æçæ°é</span> |
| | | <span class="number-value">{{ getEmptyTrayCount(warehouse.code) }}</span> |
| | | </div> |
| | | </template> |
| | | </div> |
| | | <div :id="`daily-chart-${warehouse.code}`" class="chart-content"></div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- ä»åºåå¸ï¼æ±ç¶å¾ï¼æ¾ç¤ºåä»åºå·²ç¨/å©ä½å®¹éï¼ --> |
| | | <div class="chart-row"> |
| | | <div class="chart-card"> |
| | | <div class="card-title">åä»åºæåº¦åºå
¥åºå¯¹æ¯</div> |
| | | <div id="chart-warehouse-monthly" class="chart-content"></div> |
| | | <div class="card-title">åä»åºåºååå¸</div> |
| | | <div id="chart-warehouse" class="chart-content"></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | data() { |
| | | return { |
| | | charts: {}, |
| | | monthlyData: [], |
| | | warehouseNames: ['FJSC1', 'ZJSC1', 'GWSC1', 'CWSC1', 'HCSC1'] |
| | | // åä¸ªæ ¸å¿ä»åºï¼åå¹¶äºæ£è´æå·åºä¸ºæå·åºï¼ |
| | | dailyWarehouses: [ |
| | | { code: "HCSC1", name: "åæåº", type: "hc" }, |
| | | { code: "GWSC1", name: "髿¸©åº", type: "gw" }, |
| | | { code: "CWSC1", name: "常温åº", type: "cw" }, |
| | | { code: "ROLL", name: "æå·åº", type: "jj" } |
| | | ], |
| | | // åå§æ¯æ¥æ°æ®åå¨ (å
¶ä¸ROLL为åå¹¶åçæå·åºæ°æ®) |
| | | dailyDataMap: { |
| | | GWSC1: [], |
| | | CWSC1: [], |
| | | HCSC1: [], |
| | | ROLL: [] |
| | | }, |
| | | // å卿¯ä¸ªä»åºççµæ± æ°é |
| | | warehouseStocks: { |
| | | GWSC1: 0, |
| | | CWSC1: 0, |
| | | HCSC1: 0, |
| | | ROLL: 0 |
| | | }, |
| | | // æå·åºç¹æ®æ°æ® |
| | | rollData: { |
| | | batteryCount: 0, // çµæ± æ°é |
| | | emptyTrayCount: 0 // 空æçæ°é |
| | | }, |
| | | // å
¶ä»ä»åºç空æçæ°é |
| | | emptyTrayCounts: { |
| | | GWSC1: 0, |
| | | CWSC1: 0, |
| | | HCSC1: 0 |
| | | }, |
| | | warehouseData: [], // ä»åºåå¸å¾æ°æ® |
| | | // ä»åºè´§ä½æ°æ®ï¼åºå®é
ç½®ï¼ |
| | | warehouseLocations: { |
| | | hc: 35, // åæåº |
| | | gw: 324, // 髿¸©åº |
| | | cw: 140, // å¸¸æ¸©åº |
| | | jj: 104 // æå·åº |
| | | } |
| | | }; |
| | | }, |
| | | computed: { |
| | | // æ»è´§ä½è®¡ç® |
| | | totalLocation() { |
| | | return this.warehouseLocations.hc + this.warehouseLocations.gw + |
| | | this.warehouseLocations.cw + this.warehouseLocations.jj; |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.initCharts(); |
| | |
| | | }, |
| | | beforeUnmount() { |
| | | window.removeEventListener("resize", this.handleResize); |
| | | Object.values(this.charts).forEach(chart => chart.dispose()); |
| | | Object.values(this.charts).forEach(chart => chart && chart.dispose()); |
| | | }, |
| | | methods: { |
| | | handleResize() { |
| | | Object.values(this.charts).forEach(chart => chart.resize()); |
| | | Object.values(this.charts).forEach(chart => chart && chart.resize()); |
| | | }, |
| | | |
| | | initCharts() { |
| | | this.charts.warehouseMonthly = echarts.init(document.getElementById("chart-warehouse-monthly")); |
| | | // åå§åæ¯æ¥å¾è¡¨ |
| | | this.dailyWarehouses.forEach(warehouse => { |
| | | const chartId = `daily-chart-${warehouse.code}`; |
| | | const el = document.getElementById(chartId); |
| | | if (el) { |
| | | this.charts[`daily-${warehouse.code}`] = echarts.init(el); |
| | | } |
| | | }); |
| | | // åå§åä»åºåå¸å¾è¡¨ |
| | | this.charts.warehouse = echarts.init(document.getElementById("chart-warehouse")); |
| | | }, |
| | | |
| | | async loadData() { |
| | | await this.loadMonthlyStats(); |
| | | }, |
| | | |
| | | async loadMonthlyStats() { |
| | | try { |
| | | const promises = this.warehouseNames.map(warehouse => |
| | | this.http.get("/api/Dashboard/MonthlyStats", { |
| | | months: 6, |
| | | Roadway: warehouse |
| | | }) |
| | | ); |
| | | // å¹¶è¡å è½½æææ°æ® |
| | | await Promise.all([ |
| | | this.loadAllDailyStats(), |
| | | this.loadStockAndTrayCount(), |
| | | this.loadStockByWarehouse() |
| | | ]); |
| | | |
| | | const results = await Promise.all(promises); |
| | | |
| | | this.monthlyData = results.map((res, index) => ({ |
| | | warehouse: this.warehouseNames[index], |
| | | warehouseName: this.getWarehouseName(this.warehouseNames[index]), |
| | | data: res.data || [] |
| | | })); |
| | | |
| | | this.updateWarehouseMonthlyChart(); |
| | | } catch (e) { |
| | | console.error("å è½½æ¯æç»è®¡å¤±è´¥", e); |
| | | // æ´æ°ææå¾è¡¨ |
| | | this.updateAllDailyCharts(); |
| | | } catch (error) { |
| | | console.error("å è½½æ°æ®å¤±è´¥:", error); |
| | | this.$message?.error("æ°æ®å 载失败ï¼è¯·ç¨åéè¯"); |
| | | } |
| | | }, |
| | | |
| | | getWarehouseName(code) { |
| | | const nameMap = { |
| | | 'FJSC1': 'è´æå·1å·ä»åº', |
| | | 'ZJSC1': 'æ£æå·1å·ä»åº', |
| | | 'GWSC1': '髿¸©1å·ä»åº', |
| | | 'CWSC1': '常温1å·ä»åº', |
| | | 'HCSC1': 'å容1å·ä»åº' |
| | | }; |
| | | return nameMap[code] || code; |
| | | async loadAllDailyStats() { |
| | | console.log("æ£å¨å è½½ææä»åºçæ¯æ¥ç»è®¡æ°æ®..."); |
| | | const res = await this.http.get("/api/Dashboard/DailyStats?days=10"); |
| | | if (res.status && res.data) { |
| | | console.log("ææä»åºæ¯æ¥ç»è®¡æ°æ®:", res.data); |
| | | |
| | | const dataArray = res.data; |
| | | |
| | | // æä»åºåç±»æ°æ® |
| | | dataArray.forEach(item => { |
| | | const roadway = item.roadway; |
| | | const dailyStats = item.dailyStats || []; |
| | | |
| | | switch(roadway) { |
| | | case "GWSC1": |
| | | this.dailyDataMap.GWSC1 = dailyStats; |
| | | break; |
| | | case "CWSC1": |
| | | this.dailyDataMap.CWSC1 = dailyStats; |
| | | break; |
| | | case "HCSC1": |
| | | this.dailyDataMap.HCSC1 = dailyStats; |
| | | break; |
| | | case "ZJSC1": |
| | | case "FJSC1": |
| | | // æå·åºæ°æ®åå¹¶å¤ç |
| | | this.mergeRollDailyStats(dailyStats); |
| | | break; |
| | | } |
| | | }); |
| | | |
| | | console.log("GWSC1æ°æ®:", this.dailyDataMap.GWSC1); |
| | | console.log("CWSC1æ°æ®:", this.dailyDataMap.CWSC1); |
| | | console.log("HCSC1æ°æ®:", this.dailyDataMap.HCSC1); |
| | | console.log("æå·åºåå¹¶æ°æ®:", this.dailyDataMap.ROLL); |
| | | } else { |
| | | console.error("è·åæ¯æ¥æ°æ®å¤±è´¥"); |
| | | } |
| | | }, |
| | | |
| | | updateWarehouseMonthlyChart() { |
| | | // è·åæææä»½ |
| | | const months = this.monthlyData[0]?.data.map(d => `${d.month}æ`) || []; |
| | | mergeRollDailyStats(newData) { |
| | | // åå¹¶æ£æå·åºåè´æå·åºçæ¯æ¥æ°æ® |
| | | if (!this.dailyDataMap.ROLL.length) { |
| | | this.dailyDataMap.ROLL = [...newData]; |
| | | } else { |
| | | const dateMap = new Map(); |
| | | [...this.dailyDataMap.ROLL, ...newData].forEach(item => { |
| | | const date = item.date; |
| | | if (date) { |
| | | if (!dateMap.has(date)) { |
| | | dateMap.set(date, { date, inbound: 0, outbound: 0 }); |
| | | } |
| | | const existing = dateMap.get(date); |
| | | existing.inbound += item.inbound || 0; |
| | | existing.outbound += item.outbound || 0; |
| | | } |
| | | }); |
| | | |
| | | // 为æ¯ä¸ªä»åºçæç³»åæ°æ® |
| | | const series = []; |
| | | const sortedDates = Array.from(dateMap.keys()).sort(); |
| | | const mergedData = sortedDates.map(date => dateMap.get(date)); |
| | | this.dailyDataMap["ROLL"] = mergedData; |
| | | } |
| | | }, |
| | | |
| | | this.monthlyData.forEach((warehouseData, index) => { |
| | | const data = warehouseData.data; |
| | | async loadStockAndTrayCount() { |
| | | // å è½½çµæ± æ°éå空æçæ°é |
| | | console.log("æ£å¨å è½½çµæ± æ°éå空æçæ°æ®..."); |
| | | const res = await this.http.get("/api/Dashboard/StockAndTrayCount"); |
| | | |
| | | series.push({ |
| | | name: warehouseData.warehouseName, |
| | | type: 'bar', |
| | | data: data.map(d => ({ |
| | | value: (d.inbound || 0) + (d.outbound || 0), |
| | | inbound: d.inbound || 0, |
| | | outbound: d.outbound || 0, |
| | | label: { |
| | | if (res.status && res.data) { |
| | | console.log("çµæ± å空æçæ°æ®:", res.data); |
| | | |
| | | // éç½®æ°æ® |
| | | this.rollData.batteryCount = 0; |
| | | this.rollData.emptyTrayCount = 0; |
| | | |
| | | // æ ¹æ®è¿åçæ°æ®ç»æè§£æ |
| | | res.data.forEach(item => { |
| | | const warehouseName = item.warehouseName; |
| | | const batteryCount = item.batteryCount || 0; |
| | | const emptyTrayCount = item.emptyTrayCount || 0; |
| | | |
| | | // æ ¹æ®ä»åºåç§°æ å°å°å¯¹åºç代ç |
| | | if (warehouseName === "髿¸©åº") { |
| | | this.emptyTrayCounts.GWSC1 = emptyTrayCount; |
| | | this.warehouseStocks.GWSC1 = batteryCount; |
| | | } else if (warehouseName === "常温åº") { |
| | | this.emptyTrayCounts.CWSC1 = emptyTrayCount; |
| | | this.warehouseStocks.CWSC1 = batteryCount; |
| | | } else if (warehouseName === "åæåº") { |
| | | this.emptyTrayCounts.HCSC1 = emptyTrayCount; |
| | | this.warehouseStocks.HCSC1 = batteryCount; |
| | | } else if (warehouseName === "æå·åº") { |
| | | // æå·åºéè¦å并两个æå·åºçæ°æ® |
| | | this.rollData.batteryCount += batteryCount; |
| | | this.rollData.emptyTrayCount += emptyTrayCount; |
| | | } |
| | | }); |
| | | |
| | | // 设置æå·åºæ»çµæ± æ°é |
| | | this.warehouseStocks.ROLL = this.rollData.batteryCount; |
| | | |
| | | console.log("ç¹æ®æ°æ®å è½½å®æ:", { |
| | | rollData: this.rollData, |
| | | emptyTrayCounts: this.emptyTrayCounts, |
| | | warehouseStocks: this.warehouseStocks |
| | | }); |
| | | } else { |
| | | console.error("è·åçµæ± å空æçæ°æ®å¤±è´¥"); |
| | | throw new Error("è·åçµæ± å空æçæ°æ®å¤±è´¥"); |
| | | } |
| | | }, |
| | | |
| | | async loadStockByWarehouse() { |
| | | console.log("æ£å¨å è½½ä»åºå叿°æ®..."); |
| | | const res = await this.http.get("/api/Dashboard/StockByWarehouse"); |
| | | |
| | | if (res.status && res.data) { |
| | | console.log("ä»åºå叿°æ®:", res.data); |
| | | const rawData = res.data.data || res.data; |
| | | |
| | | // å¤çæå·åºåå¹¶ |
| | | let rollHasStock = 0; |
| | | let rollNoStock = 0; |
| | | let rollTotal = 0; |
| | | const otherWarehouses = []; |
| | | |
| | | rawData.forEach(item => { |
| | | if (item.warehouse === "æå·åº" || item.warehouse.includes("æå·åº")) { |
| | | // åå¹¶æå·åºæ°æ® |
| | | rollHasStock += item.hasStock || 0; |
| | | rollNoStock += item.noStock || 0; |
| | | rollTotal += item.total || 0; |
| | | } else { |
| | | otherWarehouses.push(item); |
| | | } |
| | | }); |
| | | |
| | | // æ·»å åå¹¶åçæå·åº |
| | | if (rollTotal > 0) { |
| | | const hasStockPercentage = ((rollHasStock / rollTotal) * 100).toFixed(1) + "%"; |
| | | const noStockPercentage = ((rollNoStock / rollTotal) * 100).toFixed(1) + "%"; |
| | | |
| | | otherWarehouses.push({ |
| | | warehouse: "æå·åº", |
| | | hasStock: rollHasStock, |
| | | noStock: rollNoStock, |
| | | total: rollTotal, |
| | | hasStockPercentage: hasStockPercentage, |
| | | noStockPercentage: noStockPercentage |
| | | }); |
| | | } |
| | | |
| | | this.warehouseData = otherWarehouses; |
| | | this.updateWarehouseChart(); |
| | | } else { |
| | | console.error("è·åä»åºå叿°æ®å¤±è´¥"); |
| | | throw new Error("è·åä»åºå叿°æ®å¤±è´¥"); |
| | | } |
| | | }, |
| | | |
| | | getDailyTotalInbound(warehouseCode) { |
| | | const data = this.dailyDataMap[warehouseCode] || []; |
| | | return data.reduce((sum, item) => sum + (item.inbound || 0), 0); |
| | | }, |
| | | |
| | | getDailyTotalOutbound(warehouseCode) { |
| | | const data = this.dailyDataMap[warehouseCode] || []; |
| | | return data.reduce((sum, item) => sum + (item.outbound || 0), 0); |
| | | }, |
| | | |
| | | getWarehouseStock(warehouseCode) { |
| | | return this.warehouseStocks[warehouseCode] || 0; |
| | | }, |
| | | |
| | | getBatteryCount(warehouseCode) { |
| | | if (warehouseCode === 'ROLL') { |
| | | return this.rollData.batteryCount; |
| | | } else if (warehouseCode === 'GWSC1') { |
| | | return this.warehouseStocks.GWSC1; |
| | | } else if (warehouseCode === 'CWSC1') { |
| | | return this.warehouseStocks.CWSC1; |
| | | } else if (warehouseCode === 'HCSC1') { |
| | | return this.warehouseStocks.HCSC1; |
| | | } |
| | | return 0; |
| | | }, |
| | | |
| | | getEmptyTrayCount(warehouseCode) { |
| | | if (warehouseCode === 'ROLL') { |
| | | return this.rollData.emptyTrayCount; |
| | | } else if (warehouseCode === 'GWSC1') { |
| | | return this.emptyTrayCounts.GWSC1; |
| | | } else if (warehouseCode === 'CWSC1') { |
| | | return this.emptyTrayCounts.CWSC1; |
| | | } else if (warehouseCode === 'HCSC1') { |
| | | return this.emptyTrayCounts.HCSC1; |
| | | } |
| | | return 0; |
| | | }, |
| | | |
| | | updateAllDailyCharts() { |
| | | this.dailyWarehouses.forEach(warehouse => { |
| | | this.updateDailyChartForWarehouse(warehouse.code); |
| | | }); |
| | | }, |
| | | |
| | | updateDailyChartForWarehouse(roadway) { |
| | | const chart = this.charts[`daily-${roadway}`]; |
| | | if (!chart) return; |
| | | |
| | | const data = this.dailyDataMap[roadway] || []; |
| | | |
| | | // å¦ææ²¡ææ°æ®ï¼æ¾ç¤ºç©ºå¾è¡¨æç¤º |
| | | if (!data.length) { |
| | | chart.setOption({ |
| | | title: { |
| | | show: true, |
| | | position: 'top', |
| | | formatter: function(params) { |
| | | return `å
¥:${params.data.inbound}\nåº:${params.data.outbound}`; |
| | | }, |
| | | fontSize: 10, |
| | | color: '#fff', |
| | | lineHeight: 15 |
| | | text: 'ææ æ°æ®', |
| | | left: 'center', |
| | | top: 'center', |
| | | textStyle: { color: '#ccc', fontSize: 14 } |
| | | } |
| | | })), |
| | | barWidth: '15%', |
| | | barGap: '10%', |
| | | itemStyle: { |
| | | color: this.getBarColor(index), |
| | | borderRadius: [3, 3, 0, 0] |
| | | }, true); |
| | | return; |
| | | } |
| | | }); |
| | | }); |
| | | |
| | | const dates = data.map(d => d.date); |
| | | const inboundData = data.map(d => d.inbound || 0); |
| | | const outboundData = data.map(d => d.outbound || 0); |
| | | |
| | | const option = { |
| | | title: { |
| | | text: 'åä»åºæåº¦åºå
¥åºå¯¹æ¯', |
| | | textStyle: { |
| | | color: '#00ffff', |
| | | fontSize: 16 |
| | | }, |
| | | left: 'center', |
| | | top: 10 |
| | | }, |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | | type: 'shadow' |
| | | }, |
| | | trigger: "axis", |
| | | formatter: function(params) { |
| | | let tip = `<strong>${params[0].axisValue}</strong><br/>`; |
| | | let result = params[0].axisValue + "<br/>"; |
| | | params.forEach(p => { |
| | | result += `${p.marker}${p.seriesName}: ${p.value}<br/>`; |
| | | }); |
| | | return result; |
| | | } |
| | | }, |
| | | legend: { |
| | | data: ["å
¥åº", "åºåº"], |
| | | textStyle: { color: "#fff" }, |
| | | top: 0, |
| | | right: 10, |
| | | itemWidth: 20, |
| | | itemHeight: 12 |
| | | }, |
| | | grid: { |
| | | left: "8%", |
| | | right: "8%", |
| | | top: "18%", |
| | | bottom: "12%", |
| | | containLabel: true |
| | | }, |
| | | xAxis: { |
| | | type: "category", |
| | | data: dates, |
| | | axisLabel: { |
| | | color: "#ccc", |
| | | rotate: 45, |
| | | fontSize: 10, |
| | | interval: 0, |
| | | margin: 8 |
| | | }, |
| | | axisLine: { lineStyle: { color: "#4a5b6e" } } |
| | | }, |
| | | yAxis: { |
| | | type: "value", |
| | | name: "æ°é", |
| | | nameTextStyle: { color: "#ccc", fontSize: 11 }, |
| | | axisLabel: { color: "#ccc" }, |
| | | splitLine: { lineStyle: { color: "#2a3a4a", type: "dashed" } } |
| | | }, |
| | | series: [ |
| | | { |
| | | name: "å
¥åº", |
| | | type: "bar", |
| | | data: inboundData, |
| | | itemStyle: { |
| | | color: "#5470c6", |
| | | borderRadius: [4, 4, 0, 0] |
| | | }, |
| | | barWidth: "40%", |
| | | label: { |
| | | show: true, |
| | | position: "top", |
| | | color: "#5470c6", |
| | | fontSize: 10, |
| | | formatter: (params) => params.value |
| | | } |
| | | }, |
| | | { |
| | | name: "åºåº", |
| | | type: "line", |
| | | data: outboundData, |
| | | symbol: "circle", |
| | | symbolSize: 6, |
| | | itemStyle: { color: "#91cc75" }, |
| | | lineStyle: { width: 2, type: "solid" }, |
| | | smooth: false, |
| | | label: { |
| | | show: true, |
| | | position: "top", |
| | | color: "#91cc75", |
| | | fontSize: 10, |
| | | formatter: (params) => params.value |
| | | } |
| | | } |
| | | ] |
| | | }; |
| | | chart.setOption(option, true); |
| | | }, |
| | | |
| | | updateWarehouseChart() { |
| | | if (!this.charts.warehouse) return; |
| | | |
| | | if (!this.warehouseData.length) { |
| | | this.charts.warehouse.setOption({ |
| | | title: { |
| | | show: true, |
| | | text: 'ææ ä»åºæ°æ®', |
| | | left: 'center', |
| | | top: 'center', |
| | | textStyle: { color: '#ccc' } |
| | | } |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | const warehouseNames = this.warehouseData.map(w => w.warehouse); |
| | | const hasStocks = this.warehouseData.map(w => w.hasStock); |
| | | const noStocks = this.warehouseData.map(w => w.noStock); |
| | | const hasStockPercentages = this.warehouseData.map(w => w.hasStockPercentage); |
| | | const noStockPercentages = this.warehouseData.map(w => w.noStockPercentage); |
| | | |
| | | const option = { |
| | | tooltip: { |
| | | trigger: "axis", |
| | | axisPointer: { type: "shadow" }, |
| | | formatter: (params) => { |
| | | let tip = params[0].name + "<br/>"; |
| | | params.forEach(param => { |
| | | tip += `<span style="display:inline-block;width:10px;height:10px;border-radius:50%;background:${param.color};margin-right:5px;"></span>`; |
| | | tip += `${param.seriesName}: `; |
| | | tip += `å
¥åº:${param.data.inbound} | åºåº:${param.data.outbound} | æ»è®¡:${param.value}<br/>`; |
| | | const dataIndex = param.dataIndex; |
| | | const warehouse = this.warehouseData[dataIndex]; |
| | | if (warehouse) { |
| | | if (param.seriesName === "å·²ç¨å®¹é") { |
| | | tip += `${param.marker}${param.seriesName}: ${param.value} (${warehouse.hasStockPercentage})<br/>`; |
| | | tip += `æåºå: ${warehouse.hasStock}<br/>`; |
| | | tip += `æ åºå: ${warehouse.noStock}<br/>`; |
| | | tip += `æ»å®¹é: ${warehouse.total}`; |
| | | } else if (param.seriesName === "å©ä½å®¹é") { |
| | | tip += `${param.marker}${param.seriesName}: ${param.value} (${warehouse.noStockPercentage})<br/>`; |
| | | } |
| | | } else { |
| | | tip += `${param.marker}${param.seriesName}: ${param.value}<br/>`; |
| | | } |
| | | }); |
| | | return tip; |
| | | } |
| | | }, |
| | | legend: { |
| | | data: this.monthlyData.map(d => d.warehouseName), |
| | | textStyle: { color: '#fff', fontSize: 11 }, |
| | | top: 45, |
| | | left: 'center', |
| | | type: 'scroll' |
| | | }, |
| | | grid: { |
| | | left: '3%', |
| | | right: '4%', |
| | | bottom: '10%', |
| | | top: '20%', |
| | | containLabel: true |
| | | data: ["å·²ç¨å®¹é", "å©ä½å®¹é"], |
| | | textStyle: { color: "#fff" } |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | data: months, |
| | | axisLabel: { |
| | | color: '#fff', |
| | | fontSize: 11 |
| | | }, |
| | | axisLine: { |
| | | lineStyle: { color: 'rgba(255,255,255,0.3)' } |
| | | }, |
| | | splitLine: { |
| | | show: true, |
| | | lineStyle: { |
| | | color: 'rgba(255,255,255,0.1)', |
| | | type: 'dashed' |
| | | } |
| | | } |
| | | type: "category", |
| | | data: warehouseNames, |
| | | axisLabel: { color: "#fff", rotate: 30, interval: 0 } |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | name: 'æ°é', |
| | | nameTextStyle: { color: '#fff' }, |
| | | axisLabel: { color: '#fff' }, |
| | | splitLine: { |
| | | lineStyle: { |
| | | color: 'rgba(255,255,255,0.1)', |
| | | type: 'dashed' |
| | | } |
| | | } |
| | | type: "value", |
| | | name: "容é", |
| | | axisLabel: { color: "#fff" } |
| | | }, |
| | | dataZoom: [ |
| | | series: [ |
| | | { |
| | | type: 'inside', |
| | | start: 0, |
| | | end: 100 |
| | | name: "å·²ç¨å®¹é", |
| | | type: "bar", |
| | | data: hasStocks.map((value, index) => ({ |
| | | value: value, |
| | | label: { |
| | | show: true, |
| | | position: "top", |
| | | formatter: () => { |
| | | const pct = hasStockPercentages[index]; |
| | | return `${value} (${pct})`; |
| | | }, |
| | | color: "#91cc75", |
| | | fontSize: 11 |
| | | } |
| | | })), |
| | | itemStyle: { color: "#91cc75" } |
| | | }, |
| | | { |
| | | start: 0, |
| | | end: 100, |
| | | height: 20, |
| | | bottom: 0, |
| | | borderColor: 'rgba(255,255,255,0.3)', |
| | | fillerColor: 'rgba(0,255,255,0.1)', |
| | | handleStyle: { |
| | | color: '#00ffff', |
| | | borderColor: '#00ffff' |
| | | name: "å©ä½å®¹é", |
| | | type: "bar", |
| | | data: noStocks.map((value, index) => ({ |
| | | value: value, |
| | | label: { |
| | | show: true, |
| | | position: "top", |
| | | formatter: () => { |
| | | const pct = noStockPercentages[index]; |
| | | return `${value} (${pct})`; |
| | | }, |
| | | textStyle: { |
| | | color: '#fff' |
| | | color: "#fac858", |
| | | fontSize: 11 |
| | | } |
| | | })), |
| | | itemStyle: { color: "#fac858" } |
| | | } |
| | | ], |
| | | series: series |
| | | ] |
| | | }; |
| | | |
| | | this.charts.warehouseMonthly.setOption(option, true); |
| | | }, |
| | | |
| | | getBarColor(index) { |
| | | const colors = [ |
| | | '#5470c6', // è |
| | | '#fac858', // é» |
| | | '#73c0de', // 天è |
| | | '#fc8452', // æ© |
| | | '#ea7ccc' // ç² |
| | | ]; |
| | | return colors[index] || '#5470c6'; |
| | | this.charts.warehouse.setOption(option, true); |
| | | } |
| | | } |
| | | }; |
| | |
| | | background-attachment: fixed; |
| | | } |
| | | |
| | | .chart-row { |
| | | /* KPI å¡çæ ·å¼ - 5åå¸å± */ |
| | | .kpi-cards { |
| | | display: grid; |
| | | grid-template-columns: repeat(5, 1fr); |
| | | gap: 20px; |
| | | margin-bottom: 24px; |
| | | } |
| | | |
| | | .kpi-card { |
| | | background: rgba(10, 16, 35, 0.7); |
| | | backdrop-filter: blur(10px); |
| | | border: 1px solid rgba(64, 224, 208, 0.3); |
| | | border-radius: 16px; |
| | | padding: 16px 20px; |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 16px; |
| | | transition: all 0.3s ease; |
| | | box-shadow: 0 0 15px rgba(0, 255, 255, 0.1); |
| | | } |
| | | |
| | | .kpi-card:hover { |
| | | transform: translateY(-3px); |
| | | border-color: rgba(64, 224, 208, 0.6); |
| | | box-shadow: 0 0 25px rgba(0, 255, 255, 0.2); |
| | | } |
| | | |
| | | .kpi-icon { |
| | | font-size: 32px; |
| | | opacity: 0.9; |
| | | } |
| | | |
| | | .kpi-info { |
| | | flex: 1; |
| | | } |
| | | |
| | | .kpi-label { |
| | | font-size: 13px; |
| | | color: #8ba0b5; |
| | | margin-bottom: 6px; |
| | | letter-spacing: 1px; |
| | | } |
| | | |
| | | .kpi-value { |
| | | font-size: 28px; |
| | | font-weight: 700; |
| | | color: #00ffff; |
| | | text-shadow: 0 0 10px rgba(0, 255, 255, 0.5); |
| | | line-height: 1.2; |
| | | } |
| | | |
| | | /* æ¯æ¥å¾è¡¨å¸å± - æ¯è¡2个 */ |
| | | .chart-row.daily-grid { |
| | | display: grid; |
| | | grid-template-columns: repeat(2, 1fr); |
| | | gap: 20px; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .chart-row.full-width { |
| | | width: 100%; |
| | | } |
| | | |
| | | .chart-card { |
| | | flex: 1; |
| | | background: rgba(10, 16, 35, 0.6); |
| | | backdrop-filter: blur(10px); |
| | | border: 1px solid rgba(64, 224, 208, 0.3); |
| | | border-radius: 12px; |
| | | padding: 15px; |
| | | position: relative; |
| | | box-shadow: |
| | | 0 0 15px rgba(0, 255, 255, 0.1), |
| | | inset 0 0 10px rgba(64, 224, 208, 0.1); |
| | | box-shadow: 0 0 15px rgba(0, 255, 255, 0.1), inset 0 0 10px rgba(64, 224, 208, 0.1); |
| | | transition: all 0.3s ease; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .chart-card:hover { |
| | | transform: translateY(-5px); |
| | | box-shadow: |
| | | 0 0 25px rgba(0, 255, 255, 0.3), |
| | | inset 0 0 15px rgba(64, 224, 208, 0.2); |
| | | box-shadow: 0 0 25px rgba(0, 255, 255, 0.3), inset 0 0 15px rgba(64, 224, 208, 0.2); |
| | | border: 1px solid rgba(64, 224, 208, 0.6); |
| | | } |
| | | |
| | |
| | | |
| | | .card-title { |
| | | color: #00ffff; |
| | | font-size: 16px; |
| | | font-size: 15px; |
| | | text-align: center; |
| | | margin-bottom: 10px; |
| | | margin-bottom: 12px; |
| | | text-shadow: 0 0 10px rgba(0, 255, 255, 0.7); |
| | | font-weight: 500; |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | } |
| | | |
| | | /* ä»åºæ°åæ¾ç¤ºåºå */ |
| | | .warehouse-numbers { |
| | | display: flex; |
| | | justify-content: space-around; |
| | | margin-bottom: 12px; |
| | | padding: 8px 0; |
| | | background: rgba(0, 0, 0, 0.3); |
| | | border-radius: 8px; |
| | | flex-wrap: wrap; |
| | | } |
| | | |
| | | .number-item { |
| | | text-align: center; |
| | | flex: 1; |
| | | min-width: 80px; |
| | | } |
| | | |
| | | .number-label { |
| | | display: block; |
| | | font-size: 11px; |
| | | color: #8ba0b5; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .number-value { |
| | | display: block; |
| | | font-size: 18px; |
| | | font-weight: 700; |
| | | letter-spacing: 1px; |
| | | } |
| | | |
| | | .number-item.inbound .number-value { |
| | | color: #5470c6; |
| | | } |
| | | |
| | | .number-item.battery .number-value { |
| | | color: #ee6666; |
| | | } |
| | | |
| | | .number-item.empty-tray .number-value { |
| | | color: #fc8452; |
| | | } |
| | | |
| | | .chart-content { |
| | | height: 500px; |
| | | height: 280px; |
| | | width: 100%; |
| | | } |
| | | |
| | | .full-width .chart-card { |
| | | flex: none; |
| | | width: 100%; |
| | | @media (max-width: 768px) { |
| | | .kpi-cards { |
| | | grid-template-columns: repeat(2, 1fr); |
| | | } |
| | | |
| | | .full-width .chart-content { |
| | | height: 500px; |
| | | .chart-row.daily-grid { |
| | | grid-template-columns: 1fr; |
| | | } |
| | | .chart-content { |
| | | height: 240px; |
| | | } |
| | | .card-title { |
| | | font-size: 13px; |
| | | white-space: normal; |
| | | } |
| | | .number-value { |
| | | font-size: 14px; |
| | | } |
| | | .number-item { |
| | | min-width: 60px; |
| | | } |
| | | } |
| | | |
| | | .dashboard-container::before { |
| | |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background-image: |
| | | linear-gradient(rgba(64, 224, 208, 0.05) 1px, transparent 1px), |
| | | background-image: linear-gradient(rgba(64, 224, 208, 0.05) 1px, transparent 1px), |
| | | linear-gradient(90deg, rgba(64, 224, 208, 0.05) 1px, transparent 1px); |
| | | background-size: 30px 30px; |
| | | pointer-events: none; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template>
|
| | | <view-grid ref="grid" :columns="columns" :detail="detail" :editFormFields="editFormFields"
|
| | | :editFormOptions="editFormOptions" :searchFormFields="searchFormFields" :searchFormOptions="searchFormOptions"
|
| | | :table="table" :tableExpand="tableExpand" :extend="extend">
|
| | | </view-grid>
|
| | | </template>
|
| | |
|
| | | <script>
|
| | | import extend from "@/extension/stock/hcstockInfo.jsx";
|
| | | import {
|
| | | defineComponent,
|
| | | getCurrentInstance,
|
| | | h,
|
| | | reactive,
|
| | | ref,
|
| | | resolveComponent,
|
| | | } from "vue";
|
| | |
|
| | | const TEXT = {
|
| | | pageName: "åºåä¿¡æ¯",
|
| | | palletCode: "æçç¼å·",
|
| | | stockStatus: "åºåç¶æ",
|
| | | locationCode: "è´§ä½ç¼å·",
|
| | | outboundDate: "åºåºæ¶é´",
|
| | | warehouse: "ä»åº",
|
| | | creator: "å建人",
|
| | | createDate: "å建æ¶é´",
|
| | | modifier: "ä¿®æ¹äºº",
|
| | | modifyDate: "ä¿®æ¹æ¶é´",
|
| | | detailName: "åºåæç»",
|
| | | materielName: "ç©æåç§°",
|
| | | serialNumber: "çµè¯ç ",
|
| | | stockQuantity: "åºåæ°é",
|
| | | status: "ç¶æ",
|
| | | inboundOrderRowNo: "ééå·",
|
| | | detailLoading: "åºåæç»å è½½ä¸...",
|
| | | detailLoadFailed: "åºåæç»å 载失败",
|
| | | detailEmpty: "å½ååºåå¤´ææ æç»æ°æ®",
|
| | | expandPrefix: "æçï¼",
|
| | | expandMiddle: " / ",
|
| | | expandLocation: "è´§ä½ï¼",
|
| | | };
|
| | |
|
| | | export default defineComponent({
|
| | | setup() {
|
| | | const { proxy } = getCurrentInstance();
|
| | | const ElTable = resolveComponent("el-table");
|
| | | const ElTableColumn = resolveComponent("el-table-column");
|
| | |
|
| | | const table = ref({
|
| | | key: "id",
|
| | | footer: "Foots",
|
| | | cnName: TEXT.pageName,
|
| | | name: "stockInfo",
|
| | | url: "/StockInfo/",
|
| | | sortName: "id",
|
| | | });
|
| | |
|
| | | const editFormFields = ref({
|
| | | palletCode: "",
|
| | | palletType: 0,
|
| | | warehouseId: 0,
|
| | | mesUploadStatus: "",
|
| | | stockStatus: "",
|
| | | locationCode: "",
|
| | | locationDetails: ""
|
| | | });
|
| | |
|
| | |
|
| | | const editFormOptions = ref([
|
| | | [
|
| | | { field: "palletCode", title: TEXT.palletCode, type: "string" },
|
| | | { field: "stockStatus", title: TEXT.stockStatus, type: "select", dataKey: "stockStatusEmun", data: [] },
|
| | | { field: "locationCode", title: TEXT.locationCode, type: "string" },
|
| | | ],
|
| | | ]);
|
| | |
|
| | | const searchFormFields = ref({
|
| | | palletCode: "",
|
| | | warehouseId: "",
|
| | | stockStatus: "",
|
| | | locationCode: "",
|
| | | });
|
| | |
|
| | | const searchFormOptions = ref([
|
| | | [
|
| | | { title: TEXT.palletCode, field: "palletCode", type: "like" },
|
| | | { title: TEXT.warehouse, field: "warehouseId", type: "selectList", dataKey: "warehouseEnum", data: [] },
|
| | | { title: TEXT.stockStatus, field: "stockStatus", type: "selectList", dataKey: "stockStatusEmun", data: [] },
|
| | | { title: TEXT.locationCode, field: "locationCode", type: "like" },
|
| | | ],
|
| | | ]);
|
| | |
|
| | | const columns = ref([
|
| | | {
|
| | | field: "id",
|
| | | title: "Id",
|
| | | type: "int",
|
| | | width: 90,
|
| | | hidden: true,
|
| | | readonly: true,
|
| | | require: true,
|
| | | align: "left",
|
| | | },
|
| | | {
|
| | | field: "palletCode",
|
| | | title: TEXT.palletCode,
|
| | | type: "string",
|
| | | width: 150,
|
| | | align: "left",
|
| | | },
|
| | | {
|
| | | field: "stockStatus",
|
| | | title: TEXT.stockStatus,
|
| | | type: "int",
|
| | | width: 120,
|
| | | align: "left",
|
| | | bind: { key: "stockStatusEmun", data: [] },
|
| | | },
|
| | | {
|
| | | field: "mesUploadStatus",
|
| | | title: "MESç¶æ",
|
| | | type: "int",
|
| | | width: 120,
|
| | | align: "left",
|
| | | bind: { key: "mesUploadStatusEnum", data: [] },
|
| | | },
|
| | | {
|
| | | field: "outboundDate",
|
| | | title: TEXT.outboundDate,
|
| | | type: "string",
|
| | | width: 150,
|
| | | align: "left",
|
| | | }, |
| | | {
|
| | | field: "locationCode",
|
| | | title: TEXT.locationCode,
|
| | | type: "string",
|
| | | width: 120,
|
| | | align: "left",
|
| | | },
|
| | | {
|
| | | field: "warehouseId",
|
| | | title: TEXT.warehouse,
|
| | | type: "select",
|
| | | width: 100,
|
| | | align: "left",
|
| | | bind: { key: "warehouseEnum", data: [] },
|
| | | },
|
| | | {
|
| | | field: "creater",
|
| | | title: TEXT.creator,
|
| | | type: "string",
|
| | | width: 90,
|
| | | align: "left",
|
| | | },
|
| | | {
|
| | | field: "createDate",
|
| | | title: TEXT.createDate,
|
| | | type: "datetime",
|
| | | width: 160,
|
| | | align: "left",
|
| | | },
|
| | | {
|
| | | field: "modifier",
|
| | | title: TEXT.modifier,
|
| | | type: "string",
|
| | | width: 100,
|
| | | align: "left",
|
| | | hidden: true,
|
| | | },
|
| | | {
|
| | | field: "modifyDate",
|
| | | title: TEXT.modifyDate,
|
| | | type: "datetime",
|
| | | width: 160,
|
| | | align: "left",
|
| | | hidden: true,
|
| | | },
|
| | | ]);
|
| | |
|
| | | const detail = ref({
|
| | | cnName: "#detailCnName",
|
| | | table: "",
|
| | | columns: [],
|
| | | sortName: "",
|
| | | });
|
| | |
|
| | | const detailState = reactive({
|
| | | rowsMap: {},
|
| | | loadingMap: {},
|
| | | errorMap: {},
|
| | | });
|
| | |
|
| | | const stockStatusOptions = ref([]);
|
| | |
|
| | | const detailColumns = [
|
| | | { field: "materielName", title: TEXT.materielName, minWidth: 160 },
|
| | | { field: "serialNumber", title: TEXT.serialNumber, minWidth: 160 },
|
| | | { field: "stockQuantity", title: TEXT.stockQuantity, minWidth: 120 },
|
| | | { field: "status", title: TEXT.status, minWidth: 120 },
|
| | | { field: "inboundOrderRowNo", title: TEXT.inboundOrderRowNo, minWidth: 120 },
|
| | | ];
|
| | |
|
| | | const normalizeValue = (value) => {
|
| | | return value === null || value === undefined || value === "" ? "--" : value;
|
| | | };
|
| | |
|
| | | const formatStatusText = (value) => {
|
| | | const matched = stockStatusOptions.value.find((item) => `${item.key}` === `${value}`);
|
| | | return matched ? matched.value || matched.label : normalizeValue(value);
|
| | | };
|
| | |
|
| | | const getDetailRows = (stockId) => {
|
| | | return detailState.rowsMap[stockId] || [];
|
| | | };
|
| | |
|
| | | const loadDetailRows = async (row) => {
|
| | | if (!row || !row.id || detailState.loadingMap[row.id]) {
|
| | | return;
|
| | | }
|
| | | if (detailState.rowsMap[row.id]) {
|
| | | return;
|
| | | }
|
| | |
|
| | | detailState.loadingMap[row.id] = true;
|
| | | detailState.errorMap[row.id] = "";
|
| | | try {
|
| | | const result = await proxy.http.post("/api/StockInfoDetail/getPageData", {
|
| | | page: 1,
|
| | | rows: 200,
|
| | | sort: "id",
|
| | | order: "asc",
|
| | | wheres: JSON.stringify([
|
| | | {
|
| | | name: "stockId",
|
| | | value: String(row.id),
|
| | | displayType: "int",
|
| | | },
|
| | | ]),
|
| | | });
|
| | | detailState.rowsMap[row.id] = (result && result.rows) || [];
|
| | | } catch (error) {
|
| | | detailState.rowsMap[row.id] = null;
|
| | | detailState.errorMap[row.id] = error?.message || TEXT.detailLoadFailed;
|
| | | } finally {
|
| | | detailState.loadingMap[row.id] = false;
|
| | | }
|
| | | };
|
| | |
|
| | | const loadStockStatusOptions = async () => {
|
| | | try {
|
| | | const result = await proxy.http.post("/api/Sys_Dictionary/GetVueDictionary", ["stockStatusEmun", "mesUploadStatusEnum"]);
|
| | | const matched = (result || []).find((item) => item.dicNo === "stockStatusEmun");
|
| | | stockStatusOptions.value = matched ? matched.data || [] : [];
|
| | | } catch (error) {
|
| | | stockStatusOptions.value = [];
|
| | | }
|
| | | };
|
| | |
|
| | | loadStockStatusOptions();
|
| | |
|
| | | const renderStatus = (row) => {
|
| | | if (detailState.loadingMap[row.id]) {
|
| | | return h("div", { class: "stock-detail-status" }, TEXT.detailLoading);
|
| | | }
|
| | | if (detailState.errorMap[row.id]) {
|
| | | return h(
|
| | | "div",
|
| | | { class: "stock-detail-status stock-detail-status--error" },
|
| | | detailState.errorMap[row.id]
|
| | | );
|
| | | }
|
| | | return null;
|
| | | };
|
| | |
|
| | | const renderDetailTable = (row) => {
|
| | | const statusNode = renderStatus(row);
|
| | | if (statusNode) {
|
| | | return statusNode;
|
| | | }
|
| | |
|
| | | const rows = getDetailRows(row.id);
|
| | | if (!rows.length) {
|
| | | return h("div", { class: "stock-detail-status" }, TEXT.detailEmpty);
|
| | | }
|
| | |
|
| | | return h("div", { class: "stock-detail-table-wrapper" }, [
|
| | | h("div", { class: "stock-detail-toolbar" }, [
|
| | | h("div", { class: "stock-detail-toolbar__left" }, TEXT.detailName),
|
| | | h("div", { class: "stock-detail-toolbar__right" }, [
|
| | | h("span", { class: "stock-detail-count" }, `${rows.length} æ¡`),
|
| | | ]),
|
| | | ]),
|
| | | h(
|
| | | ElTable,
|
| | | {
|
| | | data: rows,
|
| | | border: true,
|
| | | stripe: true,
|
| | | size: "small",
|
| | | class: "stock-detail-el-table",
|
| | | maxHeight: 420,
|
| | | emptyText: TEXT.detailEmpty,
|
| | | },
|
| | | () =>
|
| | | detailColumns.map((column) =>
|
| | | h(ElTableColumn, {
|
| | | key: column.field,
|
| | | prop: column.field,
|
| | | label: column.title,
|
| | | minWidth: column.minWidth,
|
| | | showOverflowTooltip: true,
|
| | | formatter: (detailRow) =>
|
| | | column.field === "status"
|
| | | ? formatStatusText(detailRow[column.field])
|
| | | : normalizeValue(detailRow[column.field]),
|
| | | })
|
| | | )
|
| | | ),
|
| | | ]);
|
| | | };
|
| | |
|
| | | const tableExpand = ref({
|
| | | width: 55,
|
| | | onChange(row, expandedRows) {
|
| | | const isExpanded = expandedRows.some((item) => item.id === row.id);
|
| | | if (isExpanded) {
|
| | | loadDetailRows(row);
|
| | | }
|
| | | },
|
| | | render(render, { row }) {
|
| | | return render("div", { class: "stock-detail-panel" }, [
|
| | | render("div", { class: "stock-detail-header" }, [
|
| | | render("div", { class: "stock-detail-header__main" }, [
|
| | | render("div", { class: "stock-detail-title" }, TEXT.detailName),
|
| | | render(
|
| | | "div",
|
| | | { class: "stock-detail-subtitle" },
|
| | | `${TEXT.expandPrefix}${normalizeValue(row.palletCode)}${TEXT.expandMiddle}${TEXT.expandLocation}${normalizeValue(row.locationCode)}`
|
| | | ),
|
| | | ]),
|
| | | // render("div", { class: "stock-detail-tags" }, [
|
| | | // render("span", { class: "stock-detail-tag" }, normalizeValue(row.palletCode)),
|
| | | // render(
|
| | | // "span",
|
| | | // { class: "stock-detail-tag stock-detail-tag--muted" },
|
| | | // normalizeValue(row.locationCode)
|
| | | // ),
|
| | | // ]),
|
| | | ]),
|
| | | renderDetailTable(row),
|
| | | ]);
|
| | | },
|
| | | });
|
| | |
|
| | | return {
|
| | | table,
|
| | | extend,
|
| | | editFormFields,
|
| | | editFormOptions,
|
| | | searchFormFields,
|
| | | searchFormOptions,
|
| | | columns,
|
| | | detail,
|
| | | tableExpand,
|
| | | };
|
| | | },
|
| | | });
|
| | | </script>
|
| | |
|
| | | <style scoped>
|
| | | .stock-detail-panel {
|
| | | margin: 4px 8px 12px;
|
| | | padding: 14px 16px 16px;
|
| | | background: linear-gradient(180deg, #ffffff 0%, #fafbfc 100%);
|
| | | border: 1px solid #e8edf3;
|
| | | border-radius: 10px;
|
| | | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7);
|
| | | }
|
| | |
|
| | | .stock-detail-header {
|
| | | display: flex;
|
| | | align-items: flex-start;
|
| | | justify-content: space-between;
|
| | | gap: 12px;
|
| | | margin-bottom: 12px;
|
| | | padding-bottom: 12px;
|
| | | border-bottom: 1px solid #edf1f5;
|
| | | }
|
| | |
|
| | | .stock-detail-header__main {
|
| | | min-width: 0;
|
| | | }
|
| | |
|
| | | .stock-detail-title {
|
| | | margin-bottom: 4px;
|
| | | font-size: 15px;
|
| | | font-weight: 700;
|
| | | color: #303133;
|
| | | }
|
| | |
|
| | | .stock-detail-subtitle {
|
| | | font-size: 13px;
|
| | | color: #606266;
|
| | | line-height: 1.6;
|
| | | }
|
| | |
|
| | | .stock-detail-tags {
|
| | | display: flex;
|
| | | flex-wrap: wrap;
|
| | | justify-content: flex-end;
|
| | | gap: 8px;
|
| | | }
|
| | |
|
| | | .stock-detail-tag {
|
| | | display: inline-flex;
|
| | | align-items: center;
|
| | | height: 28px;
|
| | | padding: 0 10px;
|
| | | color: #1f5eff;
|
| | | background: #edf4ff;
|
| | | border: 1px solid #d8e6ff;
|
| | | border-radius: 999px;
|
| | | font-size: 12px;
|
| | | font-weight: 600;
|
| | | }
|
| | |
|
| | | .stock-detail-tag--muted {
|
| | | color: #4e5969;
|
| | | background: #f4f6f8;
|
| | | border-color: #e5e9ef;
|
| | | }
|
| | |
|
| | | .stock-detail-status {
|
| | | padding: 14px 12px;
|
| | | color: #606266;
|
| | | background: #f8fafc;
|
| | | border: 1px dashed #d9e2ec;
|
| | | border-radius: 8px;
|
| | | }
|
| | |
|
| | | .stock-detail-status--error {
|
| | | color: #f56c6c;
|
| | | background: #fef0f0;
|
| | | border-color: #fde2e2;
|
| | | }
|
| | |
|
| | | .stock-detail-table-wrapper {
|
| | | overflow-x: auto;
|
| | | border: 1px solid #ebeef5;
|
| | | border-radius: 8px;
|
| | | background: #fff;
|
| | | }
|
| | |
|
| | | .stock-detail-toolbar {
|
| | | display: flex;
|
| | | align-items: center;
|
| | | justify-content: space-between;
|
| | | gap: 12px;
|
| | | padding: 12px 14px;
|
| | | background: #f8fafc;
|
| | | border-bottom: 1px solid #edf1f5;
|
| | | }
|
| | |
|
| | | .stock-detail-toolbar__left {
|
| | | font-size: 13px;
|
| | | font-weight: 600;
|
| | | color: #303133;
|
| | | }
|
| | |
|
| | | .stock-detail-count {
|
| | | display: inline-flex;
|
| | | align-items: center;
|
| | | height: 24px;
|
| | | padding: 0 10px;
|
| | | color: #606266;
|
| | | background: #fff;
|
| | | border: 1px solid #e5e9ef;
|
| | | border-radius: 999px;
|
| | | font-size: 12px;
|
| | | }
|
| | |
|
| | | :deep(.stock-detail-el-table) {
|
| | | border-top: none;
|
| | | }
|
| | |
|
| | | :deep(.stock-detail-el-table .el-table__inner-wrapper::before) {
|
| | | display: none;
|
| | | }
|
| | |
|
| | | :deep(.stock-detail-el-table th.el-table__cell) {
|
| | | background: #f5f7fa;
|
| | | color: #303133;
|
| | | font-weight: 600;
|
| | | }
|
| | |
|
| | | :deep(.stock-detail-el-table td.el-table__cell) {
|
| | | color: #606266;
|
| | | }
|
| | |
|
| | | :deep(.stock-detail-el-table .el-table__body tr:hover > td.el-table__cell) {
|
| | | background: #f0f7ff;
|
| | | }
|
| | | </style>
|
| | |
| | | palletCode: "æçç¼å·", |
| | | stockStatus: "åºåç¶æ", |
| | | locationCode: "è´§ä½ç¼å·", |
| | | locationId: "è´§ä½id", |
| | | outboundDate: "åºåºæ¶é´", |
| | | warehouse: "ä»åº", |
| | | creator: "å建人", |
| | |
| | | mesUploadStatus: "", |
| | | stockStatus: "", |
| | | locationCode: "", |
| | | locationDetails: "" |
| | | locationDetails: "", |
| | | locationId: "", |
| | | }); |
| | | |
| | | |
| | |
| | | { field: "palletCode", title: TEXT.palletCode, type: "string" }, |
| | | { field: "stockStatus", title: TEXT.stockStatus, type: "select", dataKey: "stockStatusEmun", data: [] }, |
| | | { field: "locationCode", title: TEXT.locationCode, type: "string" }, |
| | | { field: "locationId", title: TEXT.locationId, type: "string"}, |
| | | ], |
| | | ]); |
| | | |
| | | const searchFormFields = ref({ |
| | | palletCode: "", |
| | | warehouseId: "", |
| | | stockStatus: "", |
| | | locationCode: "", |
| | | }); |
| | |
| | | const searchFormOptions = ref([ |
| | | [ |
| | | { title: TEXT.palletCode, field: "palletCode", type: "like" }, |
| | | { title: TEXT.warehouse, field: "warehouseId", type: "selectList", dataKey: "warehouseEnum", data: [] }, |
| | | { title: TEXT.stockStatus, field: "stockStatus", type: "selectList", dataKey: "stockStatusEmun", data: [] }, |
| | | { title: TEXT.locationCode, field: "locationCode", type: "like" }, |
| | | ], |
| | |
| | | using Microsoft.AspNetCore.Mvc;
|
| | | using SqlSugar;
|
| | | using WIDESEA_Common.LocationEnum;
|
| | | using WIDESEA_Common.StockEnum;
|
| | | using WIDESEA_Core;
|
| | | using WIDESEA_Model.Models;
|
| | |
|
| | |
| | | /// æå¹´æç»è®¡å
¥ç«ååºç«ä»»å¡æ°é
|
| | | /// </remarks>
|
| | | [HttpGet("MonthlyStats"), AllowAnonymous]
|
| | | public async Task<WebResponseContent> MonthlyStats([FromQuery] int months = 12, string Roadway = null)
|
| | | public async Task<WebResponseContent> MonthlyStats(int months, string roadway)
|
| | | {
|
| | | try
|
| | | {
|
| | |
| | | // ä»åºåç§°æ å°
|
| | | var roadwayNames = new Dictionary<string, string>
|
| | | {
|
| | | { "FJSC1", "è´æå·1å·ä»åº" },
|
| | | { "ZJSC1", "æ£æå·1å·ä»åº" },
|
| | |
|
| | | { "GWSC1", "髿¸©1å·ä»åº" },
|
| | | { "CWSC1", "常温1å·ä»åº" },
|
| | | { "HCSC1", "å容1å·ä»åº" }
|
| | | { "HCSC1", "å容1å·ä»åº" },
|
| | | { "FJSC1", "è´æå·1å·ä»åº" },
|
| | | { "ZJSC1", "æ£æå·1å·ä»åº" },
|
| | | };
|
| | |
|
| | | // æå»ºæ¥è¯¢
|
| | |
| | | .Where(t => t.InsertTime >= startDate);
|
| | |
|
| | | // 妿æå®äºéè·¯ï¼æ·»å éè·¯è¿æ»¤æ¡ä»¶
|
| | | if (!string.IsNullOrEmpty(Roadway))
|
| | | if (!string.IsNullOrEmpty(roadway))
|
| | | {
|
| | | query = query.Where(t => t.Roadway == Roadway);
|
| | | query = query.Where(t => t.Roadway == roadway);
|
| | | }
|
| | |
|
| | | var monthlyStats = await query
|
| | |
| | | Month = monthKey,
|
| | | Inbound = stat.Inbound,
|
| | | Outbound = stat.Outbound,
|
| | | Roadway = Roadway,
|
| | | RoadwayName = !string.IsNullOrEmpty(Roadway) && roadwayNames.ContainsKey(Roadway)
|
| | | ? roadwayNames[Roadway]
|
| | | Roadway = roadway,
|
| | | RoadwayName = !string.IsNullOrEmpty(roadway) && roadwayNames.ContainsKey(roadway)
|
| | | ? roadwayNames[roadway]
|
| | | : null
|
| | | });
|
| | | }
|
| | |
| | | Month = monthKey,
|
| | | Inbound = 0,
|
| | | Outbound = 0,
|
| | | Roadway = Roadway,
|
| | | RoadwayName = !string.IsNullOrEmpty(Roadway) && roadwayNames.ContainsKey(Roadway)
|
| | | ? roadwayNames[Roadway]
|
| | | Roadway = roadway,
|
| | | RoadwayName = !string.IsNullOrEmpty(roadway) && roadwayNames.ContainsKey(roadway)
|
| | | ? roadwayNames[roadway]
|
| | | : null
|
| | | });
|
| | | }
|
| | |
| | | return WebResponseContent.Instance.Error($"åä»åºåºååå¸è·å失败: {ex.Message}");
|
| | | }
|
| | | }
|
| | | /// <summary>
|
| | | /// æ¥è¯¢åä»åºçµæ± /æè´§æ°éå空æçæ°é
|
| | | /// </summary>
|
| | | /// <remarks>
|
| | | /// ä»åºIDè§åï¼1=髿¸©åº, 2=常温åº, 3=åæåº, 6/7=æå·åº
|
| | | /// <br/>
|
| | | /// ç»è®¡è§åï¼
|
| | | /// <br/>
|
| | | /// - 髿¸©/常温/åæåºï¼ç»è®¡ çµæ± æ°é(StockStatus=6) å 空æçæ°é(StockStatus=22)
|
| | | /// <br/>
|
| | | /// - æå·åº(6/7)ï¼ç»è®¡ æè´§æ°é(StockStatusâ 22) å 空æçæ°é(StockStatus=22)
|
| | | /// <br/>
|
| | | /// éè¿è¿åæ°æ®ä¸ç StockStatus å Count å¯ä»¥è¿ä¸æ¥æ¥è¯¢æç»çµæ± ã
|
| | | /// </remarks>
|
| | | [HttpGet("StockAndTrayCount"), AllowAnonymous]
|
| | | public async Task<WebResponseContent> StockAndTrayCount()
|
| | | {
|
| | | try
|
| | | {
|
| | | var warehouseIds = new[] { 1, 2, 3, 6, 7 };
|
| | |
|
| | | var warehouseNames = new Dictionary<int, string>
|
| | | {
|
| | | { 1, "髿¸©åº" },
|
| | | { 2, "常温åº" },
|
| | | { 3, "åæåº" },
|
| | | { 6, "æå·åº" },
|
| | | { 7, "æå·åº" }
|
| | | };
|
| | |
|
| | | var result = new List<object>();
|
| | |
|
| | | foreach (var warehouseId in warehouseIds)
|
| | | {
|
| | | var warehouseName = warehouseNames.GetValueOrDefault(warehouseId, $"ä»åº{warehouseId}");
|
| | |
|
| | | if (warehouseId == 6 || warehouseId == 7)
|
| | | {
|
| | | var totalCount = await _db.Queryable<Dt_StockInfo>()
|
| | | .Where(s => s.WarehouseId == warehouseId)
|
| | | .CountAsync();
|
| | |
|
| | | var emptyTrayCount = await _db.Queryable<Dt_StockInfo>()
|
| | | .Where(s => s.WarehouseId == warehouseId && s.StockStatus == (int)StockStatusEmun.空æçåºå)
|
| | | .CountAsync();
|
| | |
|
| | | result.Add(new
|
| | | {
|
| | | WarehouseId = warehouseId,
|
| | | WarehouseName = warehouseName,
|
| | | HasGoodsCount = totalCount - emptyTrayCount,
|
| | | EmptyTrayCount = emptyTrayCount,
|
| | | });
|
| | | }
|
| | | else
|
| | | {
|
| | | var batteryCount = await _db.Queryable<Dt_StockInfo>()
|
| | | .Where(s => s.WarehouseId == warehouseId && s.StockStatus == (int)StockStatusEmun.å
¥åºå®æ)
|
| | | .LeftJoin<Dt_StockInfoDetail>((s, d) => s.Id == d.StockId)
|
| | | .CountAsync();
|
| | |
|
| | | var emptyTrayCount = await _db.Queryable<Dt_StockInfo>()
|
| | | .Where(s => s.WarehouseId == warehouseId && s.StockStatus == (int)StockStatusEmun.空æçåºå)
|
| | | .CountAsync();
|
| | |
|
| | | result.Add(new
|
| | | {
|
| | | WarehouseId = warehouseId,
|
| | | WarehouseName = warehouseName,
|
| | | BatteryCount = batteryCount,
|
| | | EmptyTrayCount = emptyTrayCount,
|
| | | });
|
| | | }
|
| | | }
|
| | |
|
| | | return WebResponseContent.Instance.OK(null, result);
|
| | | }
|
| | | catch (Exception ex)
|
| | | {
|
| | | return WebResponseContent.Instance.Error($"çµæ± å空æçæ°éæ¥è¯¢å¤±è´¥: {ex.Message}");
|
| | | }
|
| | | }
|
| | | }
|
| | | } |
| | |
| | | "PDAVersion": "4", |
| | | "WebSocketPort": 9296, |
| | | "AutoOutboundTask": { |
| | | "Enable": true, /// æ¯å¦å¯ç¨èªå¨åºåºä»»å¡ |
| | | "Enable": false, /// æ¯å¦å¯ç¨èªå¨åºåºä»»å¡ |
| | | "CheckIntervalSeconds": 300, /// æ£æ¥é´éï¼ç§ï¼ |
| | | "TargetAddresses": { /// æå··éåç¼é
ç½®ç®æ å°åï¼æ¯æå¤åºåºå£ï¼ |
| | | "GW": [ "11001", "11010", "11068" ], |