Merge remote-tracking branch 'origin/0.9X' into 0.9X

This commit is contained in:
2026-07-11 17:54:04 +08:00
6 changed files with 150 additions and 27 deletions

View File

@@ -1,11 +1,12 @@
import request from '@/utils/request'
// 查询参数列表
export function listConfig(query) {
export function listConfig(query, requestOptions = {}) {
return request({
url: '/system/config/list',
method: 'get',
params: query
params: query,
...requestOptions
})
}
@@ -18,28 +19,31 @@ export function getConfig(configId) {
}
// 根据参数键名查询参数值
export function getConfigKey(configKey) {
export function getConfigKey(configKey, requestOptions = {}) {
return request({
url: '/system/config/configKey/' + configKey,
method: 'get'
method: 'get',
...requestOptions
})
}
// 新增参数配置
export function addConfig(data) {
export function addConfig(data, requestOptions = {}) {
return request({
url: '/system/config',
method: 'post',
data: data
data: data,
...requestOptions
})
}
// 修改参数配置
export function updateConfig(data) {
export function updateConfig(data, requestOptions = {}) {
return request({
url: '/system/config',
method: 'put',
data: data
data: data,
...requestOptions
})
}

View File

@@ -802,6 +802,8 @@ export default {
pageNum: 1,
pageSize: 10,
configKey,
}, {
silentError: true,
})
const rows = (res && res.rows) || []
const hit = rows.find(item => item && item.configKey === configKey)
@@ -839,7 +841,6 @@ export default {
this.debugLog('saveConfig-payload-too-long', { payloadLength: payload.length, persistPayload })
if (this.$cache) this.$cache.local.setJSON(storageKey, persistPayload)
this.configVisible = false
if (this.$modal) this.$modal.msgWarning(`配置内容过多后端参数长度上限为500当前为${payload.length},已使用本地保存`)
return
}
try {
@@ -848,6 +849,8 @@ export default {
const updateRes = await updateConfig({
...existsConfig,
configValue: payload,
}, {
silentError: true,
})
this.debugLog('saveConfig-updateConfig-success', { storageKey, updateRes, existsConfig })
} else {
@@ -859,6 +862,8 @@ export default {
configValue: payload,
configType: 'Y',
remark: `工作台快捷入口配置(${label}`,
}, {
silentError: true,
})
this.debugLog('saveConfig-addConfig-success', { storageKey, addRes })
}
@@ -869,7 +874,6 @@ export default {
this.debugLog('saveConfig-upsert-error', e)
if (this.$cache) this.$cache.local.setJSON(storageKey, persistPayload)
this.configVisible = false
if (this.$modal) this.$modal.msgWarning('保存失败,已使用本地保存')
}
},
/**

View File

@@ -102,6 +102,7 @@ service.interceptors.response.use(res => {
const code = res.data.code || 200;
// 获取错误信息
const msg = errorCode[code] || res.data.msg || errorCode['default']
const silentError = !!(res.config && res.config.silentError)
// 二进制数据则直接返回
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
return res.data
@@ -120,13 +121,19 @@ service.interceptors.response.use(res => {
}
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 500) {
if (!silentError) {
Message({ message: msg, type: 'error' })
}
return Promise.reject(new Error(msg))
} else if (code === 601) {
if (!silentError) {
Message({ message: msg, type: 'warning' })
}
return Promise.reject('error')
} else if (code !== 200) {
if (!silentError) {
Notification.error({ title: msg })
}
return Promise.reject('error')
} else {
return res.data
@@ -142,7 +149,9 @@ service.interceptors.response.use(res => {
} else if (message.includes("Request failed with status code")) {
message = "系统接口" + message.substr(message.length - 3) + "异常";
}
if (!(error.config && error.config.silentError)) {
Message({ message: message, type: 'error', duration: 5 * 1000 })
}
return Promise.reject(error)
}
)

View File

@@ -337,12 +337,38 @@
<AnomalyAnalysis :visible.sync="anomalyOpen" :reportId="activeReport ? activeReport.reportId : null" :allItems="allItems" :gridRows="gridRows" :allCols="allCols" @anomaly-found="onAnomalyFound" />
<!-- Line chart -->
<el-dialog title="折线图统计" :visible.sync="chartOpen" width="100%" top="0" append-to-body :close-on-click-modal="false" custom-class="chart-fullscreen" @opened="renderCharts" @closed="disposeCharts">
<div class="chart-grid" v-if="chartDataCols.length">
<div v-for="(col, idx) in chartDataCols" :key="idx" class="chart-item">
<el-dialog title="折线图统计" :visible.sync="chartOpen" width="100%" top="0" append-to-body :close-on-click-modal="false" custom-class="chart-fullscreen" @opened="onChartOpen" @closed="disposeCharts">
<div class="chart-tag-bar" v-if="chartDataCols.length">
<div class="chart-tag-row" v-if="chartActiveCols.length">
<span class="chart-tag-label">已选</span>
<el-tag v-for="(col, idx) in chartActiveCols" :key="getColKey(col)"
type="primary" effect="dark" size="small"
draggable="true"
:class="{ 'is-dragging': _chartTagDragIdx === idx, 'drag-over': _chartTagDragOverIdx === idx }"
closable
@close="removeChartCol(getColKey(col))"
@dragstart.native="onChartTagDragStart($event, idx)"
@dragenter.native="onChartTagDragEnter(idx)"
@dragleave.native="onChartTagDragLeave"
@dragover.native.prevent
@drop.native="onChartTagDrop(idx)"
@dragend.native="onChartTagDragEnd"
>{{ col.itemName || col.metricName || '' }}</el-tag>
</div>
<div class="chart-tag-row" v-if="chartUnselectedCols.length">
<span class="chart-tag-label">待选</span>
<el-tag v-for="col in chartUnselectedCols" :key="getColKey(col)"
type="info" effect="plain" size="small"
@click="addChartCol(getColKey(col))"
>{{ col.itemName || col.metricName || '' }}</el-tag>
</div>
</div>
<div class="chart-grid" v-if="chartActiveCols.length">
<div v-for="(col, idx) in chartActiveCols" :key="'c'+idx" class="chart-item">
<div :ref="'chart_'+idx" style="width:100%;height:280px"></div>
</div>
</div>
<el-empty v-else-if="chartDataCols.length" description="请在上方「待选」中点击添加列" />
<el-empty v-else description="暂无数据" />
</el-dialog>
</template>
@@ -498,7 +524,10 @@ export default {
backfilling: false,
progressOpen: false, progressTitle: '', progressTasks: [],
anomalyOpen: false, anomalyMap: {},
chartOpen: false, _chartInstances: []
chartOpen: false, _chartInstances: [],
chartSelectedKeys: [],
_chartTagDragIdx: -1,
_chartTagDragOverIdx: -1
}
},
computed: {
@@ -599,6 +628,15 @@ export default {
const key = 'mv' + col.mIdx
return this.gridRows.some(r => r[key] != null)
})
},
chartActiveCols() {
return this.chartSelectedKeys
.map(key => this.chartDataCols.find(c => this.getColKey(c) === key))
.filter(Boolean)
},
chartUnselectedCols() {
const set = new Set(this.chartSelectedKeys)
return this.chartDataCols.filter(c => !set.has(this.getColKey(c)))
}
},
watch: { configOpen(v) { if (!v) this.rpOpen = false } },
@@ -1266,11 +1304,69 @@ export default {
}
return makeOption(label, [{ type: 'line', data: rows.map(r => { const v = parseFloat(r['mv'+col.mIdx]); return isNaN(v) ? 0 : v }), smooth: true }])
},
getColKey(col) {
if (col.$type === 'detail') return 'd-' + col.itemId
return 'm-' + (col.metricId != null ? col.metricId : 'idx' + col.mIdx)
},
loadChartSelection() {
if (!this.activeReport) return
const key = 'cost_chart_cols_' + this.activeReport.reportId
const allKeys = this.chartDataCols.map(c => this.getColKey(c))
let selected = []
try {
const saved = localStorage.getItem(key)
if (saved) {
const parsed = JSON.parse(saved)
selected = (parsed.selected || []).filter(k => allKeys.includes(k))
}
} catch (e) { /* ignore */ }
this.chartSelectedKeys = selected
},
saveChartSelection() {
if (!this.activeReport) return
const key = 'cost_chart_cols_' + this.activeReport.reportId
localStorage.setItem(key, JSON.stringify({
selected: this.chartSelectedKeys
}))
},
addChartCol(key) {
this.chartSelectedKeys.push(key)
this.saveChartSelection()
this.renderCharts()
},
removeChartCol(key) {
const idx = this.chartSelectedKeys.indexOf(key)
if (idx >= 0) this.chartSelectedKeys.splice(idx, 1)
this.saveChartSelection()
this.renderCharts()
},
onChartTagDragStart(e, idx) {
this._chartTagDragIdx = idx
this._chartTagDragOverIdx = -1
if (e.dataTransfer) e.dataTransfer.effectAllowed = 'move'
},
onChartTagDragEnter(idx) { this._chartTagDragOverIdx = idx },
onChartTagDragLeave() { this._chartTagDragOverIdx = -1 },
onChartTagDragEnd() { this._chartTagDragIdx = -1; this._chartTagDragOverIdx = -1 },
onChartTagDrop(targetIdx) {
if (this._chartTagDragIdx < 0 || this._chartTagDragIdx === targetIdx) { this._chartTagDragIdx = -1; this._chartTagDragOverIdx = -1; return }
const [item] = this.chartSelectedKeys.splice(this._chartTagDragIdx, 1)
const insertAt = this._chartTagDragIdx < targetIdx ? targetIdx - 1 : targetIdx
this.chartSelectedKeys.splice(insertAt, 0, item)
this._chartTagDragIdx = -1
this._chartTagDragOverIdx = -1
this.saveChartSelection()
this.renderCharts()
},
onChartOpen() {
this.loadChartSelection()
this.renderCharts()
},
renderCharts() {
this.disposeCharts()
this.$nextTick(() => {
this._chartInstances = []
this.chartDataCols.forEach((col, idx) => {
this.chartActiveCols.forEach((col, idx) => {
const el = this.$refs['chart_'+idx]
if (!el || !el[0]) return
const chart = echarts.init(el[0])
@@ -1344,9 +1440,16 @@ export default {
/deep/ .summary-row td .cell { color: #303133; }
.summary-label { font-weight: bold; color: #303133; padding: 0 5px; }
.summary-val { font-weight: bold; color: #303133; }
/deep/ .chart-fullscreen { width: 100% !important; max-width: 100% !important; height: 100vh !important; margin: 0 !important; }
/deep/ .chart-fullscreen .el-dialog__body { height: calc(100vh - 90px); overflow: auto; padding: 16px 20px; }
/deep/ .chart-fullscreen { width: 100% !important; max-width: 100% !important; margin: 0 !important; }
/deep/ .chart-fullscreen .el-dialog__body { max-height: calc(100vh - 90px); overflow: auto; padding: 16px 20px; }
/deep/ .chart-fullscreen .el-dialog__header { padding: 12px 20px; }
.chart-tag-bar { padding: 0 4px 8px; }
.chart-tag-row { display: flex; flex-wrap: wrap; align-items: center; margin-bottom: 4px; }
.chart-tag-row:last-child { margin-bottom: 0; }
.chart-tag-label { font-size: 12px; color: #909399; margin-right: 4px; flex-shrink: 0; }
/deep/ .chart-tag-row .el-tag { transition: transform 0.15s, opacity 0.15s; user-select: none; margin: 1px 4px 1px 0; }
/deep/ .chart-tag-row .el-tag.is-dragging { opacity: 0.3; transform: scale(0.92); }
/deep/ .chart-tag-row .el-tag.drag-over { transform: translateY(-2px); border-color: #409eff !important; }
.chart-grid { display: flex; flex-wrap: wrap; }
.chart-item { width: 33.33%; padding: 6px; box-sizing: border-box; }
</style>

View File

@@ -2298,6 +2298,7 @@ export default {
});
},
handleExportCoil(row) {
this.$modal.confirm('是否确认将钢卷"' + row.currentCoilNo + '"进行发货?').then(() => {
exportCoil(row.coilId).then(response => {
this.$modal.msgSuccess("发货成功");
// 2. 插入一条已完成的待操作记录
@@ -2318,6 +2319,8 @@ export default {
}).catch(error => {
this.$modal.msgError("发货失败");
});
}).catch(() => {
});
},
async handleNewExport(row) {
this.loading = true

View File

@@ -530,8 +530,8 @@ export default {
}
return {
start: `${startDate} 00:00:00`,
end: `${endDate} 23:59:59`
start: `${startDate} 07:00:00`,
end: `${endDate} 07:00:00`
};
};
@@ -812,8 +812,8 @@ export default {
// all 类型:年视图日期变更
handleYearDateChange() {
if (this.yearDate) {
this.queryParams.startTime = `${this.yearDate}-01-01 00:00:00`;
this.queryParams.endTime = `${this.yearDate}-12-31 23:59:59`;
this.queryParams.startTime = `${this.yearDate}-01-01 07:00:00`;
this.queryParams.endTime = `${this.yearDate}-12-31 07:00:00`;
this.handleQuery();
}
},