|
@@ -6,20 +6,18 @@
|
|
|
<el-slider
|
|
<el-slider
|
|
|
v-model="dim.currentValue"
|
|
v-model="dim.currentValue"
|
|
|
:min="0"
|
|
:min="0"
|
|
|
- :max="getMaxForDim(dim.code)"
|
|
|
|
|
- :disabled="dim.currentValue === 0 && getRemaining() === 0"
|
|
|
|
|
|
|
+ :max="100"
|
|
|
class="dim-slider"
|
|
class="dim-slider"
|
|
|
- @change="onWeightChange"
|
|
|
|
|
|
|
+ @change="onWeightChange(dim.code)"
|
|
|
/>
|
|
/>
|
|
|
<el-input-number
|
|
<el-input-number
|
|
|
v-model="dim.currentValue"
|
|
v-model="dim.currentValue"
|
|
|
:min="0"
|
|
:min="0"
|
|
|
- :max="getMaxForDim(dim.code)"
|
|
|
|
|
- :disabled="dim.currentValue === 0 && getRemaining() === 0"
|
|
|
|
|
|
|
+ :max="100"
|
|
|
:controls="false"
|
|
:controls="false"
|
|
|
size="mini"
|
|
size="mini"
|
|
|
class="dim-input"
|
|
class="dim-input"
|
|
|
- @change="onWeightChange"
|
|
|
|
|
|
|
+ @change="onWeightChange(dim.code)"
|
|
|
/>
|
|
/>
|
|
|
<span class="dim-unit">%</span>
|
|
<span class="dim-unit">%</span>
|
|
|
</div>
|
|
</div>
|
|
@@ -92,25 +90,62 @@ export default {
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
methods: {
|
|
methods: {
|
|
|
- getMaxForDim(code) {
|
|
|
|
|
- const otherTotal = this.dimensions
|
|
|
|
|
- .filter(d => d.code !== code && (d.currentValue || 0) > 0)
|
|
|
|
|
- .reduce((s, d) => s + (d.currentValue || 0), 0)
|
|
|
|
|
- return Math.max(0, 100 - otherTotal)
|
|
|
|
|
- },
|
|
|
|
|
- getRemaining() {
|
|
|
|
|
- return 100 - this.sum
|
|
|
|
|
- },
|
|
|
|
|
- onWeightChange() {
|
|
|
|
|
- this.dimensions.forEach(d => {
|
|
|
|
|
- const max = this.getMaxForDim(d.code)
|
|
|
|
|
- if (d.currentValue > max) {
|
|
|
|
|
- d.currentValue = max
|
|
|
|
|
|
|
+ onWeightChange(changedCode) {
|
|
|
|
|
+ // 1. Clamp the changed dimension
|
|
|
|
|
+ const changed = this.dimensions.find(function(d) { return d.code === changedCode })
|
|
|
|
|
+ if (changed) {
|
|
|
|
|
+ changed.currentValue = Math.max(0, Math.min(100, changed.currentValue))
|
|
|
|
|
+ }
|
|
|
|
|
+ var remaining = 100 - this.sum
|
|
|
|
|
+ if (remaining === 0) {
|
|
|
|
|
+ this.emitValue()
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ var others = this.dimensions.filter(function(d) { return d.code !== changedCode })
|
|
|
|
|
+ if (remaining > 0) {
|
|
|
|
|
+ // 需要把剩余分配到其他维度
|
|
|
|
|
+ var otherTotal = others.reduce(function(s, d) { return s + (d.currentValue || 0) }, 0)
|
|
|
|
|
+ if (otherTotal === 0) {
|
|
|
|
|
+ // 所有其他维度为 0,平分剩余
|
|
|
|
|
+ var rest = remaining
|
|
|
|
|
+ others.forEach(function(d, i) {
|
|
|
|
|
+ d.currentValue = (i === others.length - 1) ? rest : Math.floor(remaining / others.length)
|
|
|
|
|
+ if (i < others.length - 1) rest = remaining - d.currentValue
|
|
|
|
|
+ })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ var distSum = 0
|
|
|
|
|
+ others.forEach(function(d, i) {
|
|
|
|
|
+ if (i === others.length - 1) {
|
|
|
|
|
+ d.currentValue = Math.max(0, remaining - distSum)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ var share = Math.max(0, Math.round((d.currentValue / otherTotal) * remaining))
|
|
|
|
|
+ d.currentValue = share
|
|
|
|
|
+ distSum += share
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
}
|
|
}
|
|
|
- if (d.currentValue < 0) {
|
|
|
|
|
- d.currentValue = 0
|
|
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 超过 100,需要从其他维度扣除
|
|
|
|
|
+ var excess = -remaining
|
|
|
|
|
+ var otherTotal2 = others.reduce(function(s, d) { return s + (d.currentValue || 0) }, 0)
|
|
|
|
|
+ if (otherTotal2 > 0) {
|
|
|
|
|
+ var cutSum = 0
|
|
|
|
|
+ others.forEach(function(d, i) {
|
|
|
|
|
+ if (i === others.length - 1) {
|
|
|
|
|
+ d.currentValue = Math.max(0, (d.currentValue || 0) - (excess - cutSum))
|
|
|
|
|
+ } else {
|
|
|
|
|
+ var cut = Math.min(d.currentValue || 0, Math.round((d.currentValue / otherTotal2) * excess))
|
|
|
|
|
+ d.currentValue = Math.max(0, (d.currentValue || 0) - cut)
|
|
|
|
|
+ cutSum += cut
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
}
|
|
}
|
|
|
- })
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ // 最后修正浮点误差
|
|
|
|
|
+ var finalSum = this.dimensions.reduce(function(s, d) { return s + (d.currentValue || 0) }, 0)
|
|
|
|
|
+ if (finalSum !== 100 && others.length > 0) {
|
|
|
|
|
+ others[0].currentValue += 100 - finalSum
|
|
|
|
|
+ }
|
|
|
this.emitValue()
|
|
this.emitValue()
|
|
|
},
|
|
},
|
|
|
emitValue() {
|
|
emitValue() {
|
|
@@ -122,10 +157,10 @@ export default {
|
|
|
this.$emit('input', weights)
|
|
this.$emit('input', weights)
|
|
|
},
|
|
},
|
|
|
applyPreset(preset) {
|
|
applyPreset(preset) {
|
|
|
- this.dimensions.forEach(d => {
|
|
|
|
|
|
|
+ this.dimensions.forEach(function(d) {
|
|
|
d.currentValue = preset.weights[d.code] || 0
|
|
d.currentValue = preset.weights[d.code] || 0
|
|
|
})
|
|
})
|
|
|
- this.onWeightChange()
|
|
|
|
|
|
|
+ this.emitValue()
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|