|
@@ -1,303 +0,0 @@
|
|
|
-<template>
|
|
|
|
|
- <div class="dimension-weight-picker">
|
|
|
|
|
- <div class="dimension-rows">
|
|
|
|
|
- <div
|
|
|
|
|
- v-for="dim in dimensions"
|
|
|
|
|
- :key="dim.value"
|
|
|
|
|
- class="dimension-row"
|
|
|
|
|
- :class="{ 'is-enabled': rowEnabled[dim.value] }"
|
|
|
|
|
- >
|
|
|
|
|
- <el-checkbox
|
|
|
|
|
- v-model="rowEnabled[dim.value]"
|
|
|
|
|
- @change="onToggle(dim.value)"
|
|
|
|
|
- class="dim-check"
|
|
|
|
|
- >
|
|
|
|
|
- <span class="dim-label" :style="{ color: dim.color }">{{ dim.label }}</span>
|
|
|
|
|
- </el-checkbox>
|
|
|
|
|
-
|
|
|
|
|
- <div class="dim-slider" :class="{ 'is-locked': !rowEnabled[dim.value] }">
|
|
|
|
|
- <el-slider
|
|
|
|
|
- v-model="rowValues[dim.value]"
|
|
|
|
|
- :disabled="!rowEnabled[dim.value]"
|
|
|
|
|
- :min="0"
|
|
|
|
|
- :max="100"
|
|
|
|
|
- :step="5"
|
|
|
|
|
- :show-tooltip="true"
|
|
|
|
|
- @change="onSliderChange(dim.value)"
|
|
|
|
|
- />
|
|
|
|
|
- </div>
|
|
|
|
|
-
|
|
|
|
|
- <el-input-number
|
|
|
|
|
- v-model="rowValues[dim.value]"
|
|
|
|
|
- :disabled="!rowEnabled[dim.value]"
|
|
|
|
|
- :min="0"
|
|
|
|
|
- :max="100"
|
|
|
|
|
- :step="5"
|
|
|
|
|
- size="small"
|
|
|
|
|
- class="dim-num"
|
|
|
|
|
- controls-position="right"
|
|
|
|
|
- @change="onSliderChange(dim.value)"
|
|
|
|
|
- />
|
|
|
|
|
- <span class="dim-unit">%</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
-
|
|
|
|
|
- <div class="sum-bar">
|
|
|
|
|
- <span class="sum-label">已分配:</span>
|
|
|
|
|
- <div class="sum-track">
|
|
|
|
|
- <div class="sum-fill" :class="sumClass" :style="{ width: totalSum + '%' }"></div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <span class="sum-value" :class="sumClass">{{ totalSum }}%</span>
|
|
|
|
|
- <span v-if="totalSum !== 100 && totalSum !== 0" class="sum-tip">(启用项合计应等于100%)</span>
|
|
|
|
|
- <span v-if="totalSum === 100" class="sum-tip sum-ok">✓ 分配合理</span>
|
|
|
|
|
- </div>
|
|
|
|
|
-
|
|
|
|
|
- <div v-if="showPresets" class="preset-btns">
|
|
|
|
|
- <el-button size="mini" @click="applyPreset('single', 'body')">100%身</el-button>
|
|
|
|
|
- <el-button size="mini" @click="applyPreset('single', 'mind')">100%智</el-button>
|
|
|
|
|
- <el-button size="mini" @click="applyPreset('single', 'action')">100%行</el-button>
|
|
|
|
|
- <el-button size="mini" @click="applyPreset('single', 'wealth')">100%富</el-button>
|
|
|
|
|
- <el-button size="mini" @click="applyPreset('single', 'heart')">100%心</el-button>
|
|
|
|
|
- <el-button size="mini" @click="applyPreset('equal')">均分100%</el-button>
|
|
|
|
|
- <el-button size="mini" type="text" style="margin-left:4px;" @click="clearAll">清空</el-button>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
-</template>
|
|
|
|
|
-
|
|
|
|
|
-<script>
|
|
|
|
|
-export default {
|
|
|
|
|
- name: 'DimensionWeightPicker',
|
|
|
|
|
- props: {
|
|
|
|
|
- // v-model: Array of { dimension: 'body', weight: 40, enabled: true }
|
|
|
|
|
- value: {
|
|
|
|
|
- type: Array,
|
|
|
|
|
- default: function() {
|
|
|
|
|
- return []
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- // 是否显示快捷预设按钮
|
|
|
|
|
- showPresets: {
|
|
|
|
|
- type: Boolean,
|
|
|
|
|
- default: false
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- data() {
|
|
|
|
|
- return {
|
|
|
|
|
- rowEnabled: {
|
|
|
|
|
- body: false,
|
|
|
|
|
- mind: false,
|
|
|
|
|
- action: false,
|
|
|
|
|
- wealth: false,
|
|
|
|
|
- heart: false
|
|
|
|
|
- },
|
|
|
|
|
- rowValues: {
|
|
|
|
|
- body: 0,
|
|
|
|
|
- mind: 0,
|
|
|
|
|
- action: 0,
|
|
|
|
|
- wealth: 0,
|
|
|
|
|
- heart: 0
|
|
|
|
|
- },
|
|
|
|
|
- dimensions: [
|
|
|
|
|
- { value: 'body', label: '身·土', color: '#FF8C42' },
|
|
|
|
|
- { value: 'mind', label: '智·金', color: '#6366F1' },
|
|
|
|
|
- { value: 'action', label: '行·木', color: '#10B981' },
|
|
|
|
|
- { value: 'wealth', label: '富·水', color: '#F59E0B' },
|
|
|
|
|
- { value: 'heart', label: '心·火', color: '#FF6B9D' }
|
|
|
|
|
- ]
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- computed: {
|
|
|
|
|
- totalSum() {
|
|
|
|
|
- let sum = 0
|
|
|
|
|
- for (var key in this.rowEnabled) {
|
|
|
|
|
- if (this.rowEnabled[key]) {
|
|
|
|
|
- sum += this.rowValues[key] || 0
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- return sum
|
|
|
|
|
- },
|
|
|
|
|
- sumClass() {
|
|
|
|
|
- if (this.totalSum === 0) return 'sum-zero'
|
|
|
|
|
- return this.totalSum === 100 ? 'sum-ok' : 'sum-error'
|
|
|
|
|
- },
|
|
|
|
|
- // 用于 v-model 输出的格式
|
|
|
|
|
- outputValue() {
|
|
|
|
|
- const result = []
|
|
|
|
|
- for (var key in this.rowEnabled) {
|
|
|
|
|
- if (this.rowEnabled[key]) {
|
|
|
|
|
- result.push({
|
|
|
|
|
- dimension: key,
|
|
|
|
|
- weight: this.rowValues[key] || 0,
|
|
|
|
|
- enabled: true
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- return result
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- watch: {
|
|
|
|
|
- value: {
|
|
|
|
|
- handler(val) {
|
|
|
|
|
- this.loadFromValue(val || [])
|
|
|
|
|
- },
|
|
|
|
|
- immediate: true,
|
|
|
|
|
- deep: true
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- methods: {
|
|
|
|
|
- loadFromValue(val) {
|
|
|
|
|
- // 重置
|
|
|
|
|
- for (var key in this.rowEnabled) {
|
|
|
|
|
- this.rowEnabled[key] = false
|
|
|
|
|
- this.rowValues[key] = 0
|
|
|
|
|
- }
|
|
|
|
|
- // 加载外部值
|
|
|
|
|
- if (Array.isArray(val)) {
|
|
|
|
|
- for (var i = 0; i < val.length; i++) {
|
|
|
|
|
- var item = val[i]
|
|
|
|
|
- if (item.dimension && this.rowEnabled.hasOwnProperty(item.dimension)) {
|
|
|
|
|
- this.rowEnabled[item.dimension] = true
|
|
|
|
|
- this.rowValues[item.dimension] = item.weight || 0
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- onToggle(dim) {
|
|
|
|
|
- // 如果启用但值为0,默认给一个值
|
|
|
|
|
- if (this.rowEnabled[dim] && this.rowValues[dim] === 0) {
|
|
|
|
|
- this.rowValues[dim] = 100
|
|
|
|
|
- }
|
|
|
|
|
- this.emitInput()
|
|
|
|
|
- },
|
|
|
|
|
- onSliderChange() {
|
|
|
|
|
- this.emitInput()
|
|
|
|
|
- },
|
|
|
|
|
- emitInput() {
|
|
|
|
|
- this.$emit('input', this.outputValue)
|
|
|
|
|
- },
|
|
|
|
|
- applyPreset(type, dim) {
|
|
|
|
|
- // 先清空
|
|
|
|
|
- for (var key in this.rowEnabled) {
|
|
|
|
|
- this.rowEnabled[key] = false
|
|
|
|
|
- this.rowValues[key] = 0
|
|
|
|
|
- }
|
|
|
|
|
- if (type === 'single' && dim) {
|
|
|
|
|
- this.rowEnabled[dim] = true
|
|
|
|
|
- this.rowValues[dim] = 100
|
|
|
|
|
- } else if (type === 'equal') {
|
|
|
|
|
- // 均分给所有5个
|
|
|
|
|
- var each = Math.floor(100 / 5)
|
|
|
|
|
- var remainder = 100 - each * 5
|
|
|
|
|
- for (var i = 0; i < this.dimensions.length; i++) {
|
|
|
|
|
- var d = this.dimensions[i]
|
|
|
|
|
- this.rowEnabled[d.value] = true
|
|
|
|
|
- this.rowValues[d.value] = each + (i < remainder ? 1 : 0)
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- this.emitInput()
|
|
|
|
|
- },
|
|
|
|
|
- clearAll() {
|
|
|
|
|
- for (var key in this.rowEnabled) {
|
|
|
|
|
- this.rowEnabled[key] = false
|
|
|
|
|
- this.rowValues[key] = 0
|
|
|
|
|
- }
|
|
|
|
|
- this.emitInput()
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-</script>
|
|
|
|
|
-
|
|
|
|
|
-<style scoped>
|
|
|
|
|
-.dimension-weight-picker {
|
|
|
|
|
- font-size: 14px;
|
|
|
|
|
-}
|
|
|
|
|
-.dimension-rows {
|
|
|
|
|
- border: 1px solid #dcdfe6;
|
|
|
|
|
- border-radius: 4px;
|
|
|
|
|
- padding: 8px 12px;
|
|
|
|
|
- background: #fafafa;
|
|
|
|
|
-}
|
|
|
|
|
-.dimension-row {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- padding: 6px 0;
|
|
|
|
|
- border-bottom: 1px solid #f0f0f0;
|
|
|
|
|
-}
|
|
|
|
|
-.dimension-row:last-child {
|
|
|
|
|
- border-bottom: none;
|
|
|
|
|
-}
|
|
|
|
|
-.dim-check {
|
|
|
|
|
- width: 90px;
|
|
|
|
|
- min-width: 90px;
|
|
|
|
|
-}
|
|
|
|
|
-.dim-label {
|
|
|
|
|
- font-weight: 600;
|
|
|
|
|
- font-size: 13px;
|
|
|
|
|
-}
|
|
|
|
|
-.dim-slider {
|
|
|
|
|
- flex: 1;
|
|
|
|
|
- margin: 0 12px;
|
|
|
|
|
- opacity: 0.4;
|
|
|
|
|
- pointer-events: none;
|
|
|
|
|
- transition: opacity 0.2s;
|
|
|
|
|
-}
|
|
|
|
|
-.dim-slider.is-locked {
|
|
|
|
|
- opacity: 1;
|
|
|
|
|
- pointer-events: auto;
|
|
|
|
|
-}
|
|
|
|
|
-.dim-num {
|
|
|
|
|
- width: 80px;
|
|
|
|
|
-}
|
|
|
|
|
-.dim-unit {
|
|
|
|
|
- color: #999;
|
|
|
|
|
- margin-left: 4px;
|
|
|
|
|
- font-size: 12px;
|
|
|
|
|
-}
|
|
|
|
|
-.sum-bar {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- margin-top: 10px;
|
|
|
|
|
- gap: 8px;
|
|
|
|
|
-}
|
|
|
|
|
-.sum-label {
|
|
|
|
|
- color: #666;
|
|
|
|
|
- font-size: 13px;
|
|
|
|
|
- min-width: 56px;
|
|
|
|
|
-}
|
|
|
|
|
-.sum-track {
|
|
|
|
|
- flex: 1;
|
|
|
|
|
- height: 8px;
|
|
|
|
|
- background: #e4e7ed;
|
|
|
|
|
- border-radius: 4px;
|
|
|
|
|
- overflow: hidden;
|
|
|
|
|
-}
|
|
|
|
|
-.sum-fill {
|
|
|
|
|
- height: 100%;
|
|
|
|
|
- border-radius: 4px;
|
|
|
|
|
- transition: width 0.3s, background 0.3s;
|
|
|
|
|
-}
|
|
|
|
|
-.sum-zero .sum-fill { background: #e4e7ed; }
|
|
|
|
|
-.sum-ok .sum-fill { background: #67c23a; }
|
|
|
|
|
-.sum-error .sum-fill { background: #f56c6c; }
|
|
|
|
|
-.sum-value {
|
|
|
|
|
- min-width: 40px;
|
|
|
|
|
- font-size: 13px;
|
|
|
|
|
- font-weight: 600;
|
|
|
|
|
-}
|
|
|
|
|
-.sum-zero .sum-value { color: #999; }
|
|
|
|
|
-.sum-ok .sum-value { color: #67c23a; }
|
|
|
|
|
-.sum-error .sum-value { color: #f56c6c; }
|
|
|
|
|
-.sum-tip {
|
|
|
|
|
- font-size: 12px;
|
|
|
|
|
- color: #f56c6c;
|
|
|
|
|
-}
|
|
|
|
|
-.sum-ok .sum-tip {
|
|
|
|
|
- color: #67c23a;
|
|
|
|
|
-}
|
|
|
|
|
-.preset-btns {
|
|
|
|
|
- margin-top: 8px;
|
|
|
|
|
- display: flex;
|
|
|
|
|
- flex-wrap: wrap;
|
|
|
|
|
- gap: 4px;
|
|
|
|
|
-}
|
|
|
|
|
-</style>
|
|
|