|
@@ -806,6 +806,15 @@ export default {
|
|
|
...this.editData,
|
|
|
year: this.editData.year ? this.editData.year.toString() : ''
|
|
|
}
|
|
|
+ // 若编辑入参未包含预测编码,则根据id加载详情以保证回显
|
|
|
+ try {
|
|
|
+ const id = (this.editData && (this.editData.id || this.editData.Id)) || (this.formData && (this.formData.id || this.formData.Id))
|
|
|
+ if (!this.formData.forecastCode && id) {
|
|
|
+ this.loadForecastDetail(id)
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ // 非关键性异常,忽略
|
|
|
+ }
|
|
|
} else {
|
|
|
// 新增模式:使用默认数据,自动填入下个月
|
|
|
const now = new Date()
|
|
@@ -855,19 +864,47 @@ export default {
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
- * 生成预测编码
|
|
|
- * @description 自动生成销售预测编码
|
|
|
- * @returns {void}
|
|
|
- * @this {ForecastFormMixinComponent & Vue}
|
|
|
+ * 收集当前可见表单项的必填与数值规则错误信息(用于控制台打印)
|
|
|
+ * @returns {string[]} 错误消息列表
|
|
|
*/
|
|
|
- generateForecastCode() {
|
|
|
- const now = new Date()
|
|
|
- const year = this.formData.year || now.getFullYear()
|
|
|
- const month = this.formData.month || (now.getMonth() + 1)
|
|
|
- const monthStr = month.toString().padStart(2, '0')
|
|
|
- const random = Math.floor(1000 + Math.random() * 9000) // 生成1000-9999之间的随机数
|
|
|
-
|
|
|
- this.formData.forecastCode = `FC-${year}${monthStr}-${random}`
|
|
|
+ collectValidationErrors() {
|
|
|
+ try {
|
|
|
+ const errors = []
|
|
|
+ const option = this.formOption || {}
|
|
|
+ const groups = Array.isArray(option.group) ? option.group : []
|
|
|
+ const isEmpty = (v) => v === undefined || v === null || v === ''
|
|
|
+
|
|
|
+ groups.forEach(group => {
|
|
|
+ const columns = Array.isArray(group.column) ? group.column : []
|
|
|
+ columns.forEach(field => {
|
|
|
+ if (!field || !field.prop) return
|
|
|
+ // 仅校验可见字段
|
|
|
+ if (field.display === false) return
|
|
|
+ const rules = Array.isArray(field.rules) ? field.rules : []
|
|
|
+ const val = this.formData ? this.formData[field.prop] : undefined
|
|
|
+ // 必填校验
|
|
|
+ const requiredRule = rules.find(r => r && r.required)
|
|
|
+ if (requiredRule && isEmpty(val)) {
|
|
|
+ const label = field.label || field.prop
|
|
|
+ const msg = requiredRule.message || `${label}为必填项`
|
|
|
+ errors.push(`${label}: ${msg}`)
|
|
|
+ }
|
|
|
+ // 数值最小值校验
|
|
|
+ const numberRule = rules.find(r => r && r.type === 'number' && (r.min !== undefined))
|
|
|
+ if (numberRule && !isEmpty(val)) {
|
|
|
+ const num = Number(val)
|
|
|
+ if (!Number.isFinite(num) || num < numberRule.min) {
|
|
|
+ const label = field.label || field.prop
|
|
|
+ const msg = numberRule.message || `${label}必须不小于${numberRule.min}`
|
|
|
+ errors.push(`${label}: ${msg}`)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+ return errors
|
|
|
+ } catch (e) {
|
|
|
+ return []
|
|
|
+ }
|
|
|
},
|
|
|
|
|
|
/**
|
|
@@ -881,10 +918,20 @@ export default {
|
|
|
// 先结束 Avue 内置的按钮loading,避免未调用 done 导致一直loading
|
|
|
if (typeof done === 'function') done()
|
|
|
|
|
|
+ console.log(this.formData)
|
|
|
// 采用旧实现风格:通过 this.$refs.forecastForm.validate 回调进行校验
|
|
|
if (this.$refs && this.$refs.forecastForm && typeof this.$refs.forecastForm.validate === 'function') {
|
|
|
this.$refs.forecastForm.validate((valid) => {
|
|
|
if (!valid) {
|
|
|
+ // 编辑态下,收集并打印具体未通过原因
|
|
|
+ if (this.isEdit && typeof console !== 'undefined') {
|
|
|
+ const errors = this.collectValidationErrors ? this.collectValidationErrors() : []
|
|
|
+ if (errors && errors.length) {
|
|
|
+ console.group && console.group('表单校验未通过')
|
|
|
+ errors.forEach(msg => console.error(msg))
|
|
|
+ console.groupEnd && console.groupEnd()
|
|
|
+ }
|
|
|
+ }
|
|
|
// 校验失败时,如存在 loading 回调(部分版本提供),尝试恢复按钮状态
|
|
|
if (typeof loading === 'function') loading()
|
|
|
// 通知父组件校验失败,便于父侧重置保存按钮loading
|