| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="ordered-checkbox-container"> |
| | | <!-- 横åæåçå¤éæ¡ç» --> |
| | | <el-checkbox-group |
| | | v-model="checkedValues" |
| | | class="horizontal-checkbox-group" |
| | | > |
| | | <el-checkbox |
| | | v-for="option in options" |
| | | :key="getValue(option)" |
| | | :label="getValue(option)" |
| | | > |
| | | {{ getLabel(option) }} |
| | | </el-checkbox> |
| | | </el-checkbox-group> |
| | | |
| | | <!-- éä¸é¡ºåºå±ç¤ºåºå --> |
| | | <div v-if="selectedOrder.length > 0" class="selection-order-display"> |
| | | <span class="order-label">æå¡æ§è¡é¡ºåºï¼</span> |
| | | <span |
| | | v-for="(item, index) in selectedOrder" |
| | | :key="item.value" |
| | | class="order-item" |
| | | > |
| | | {{ getSelectedIndex(index) }}.{{ getLabelByValue(item.value) }} |
| | | <el-tooltip content="è®¾ç½®è¡¥å¿æ¶é´" placement="top"> |
| | | <el-input-number |
| | | v-model="item.compensateTime" |
| | | :min="0" |
| | | :max="60" |
| | | size="mini" |
| | | controls-position="right" |
| | | class="compensate-time-input" |
| | | @change="handleCompensateTimeChange(item.value, $event)" |
| | | /> |
| | | </el-tooltip> |
| | | <span v-if="index < selectedOrder.length - 1">ã</span> |
| | | </span> |
| | | </div> |
| | | <div v-else class="selection-order-display"> |
| | | <span class="order-label">ææ éä¸é¡¹</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: "OrderedCheckboxGroup", |
| | | props: { |
| | | options: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | value: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | initialselectedOrder: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | valueKey: { |
| | | type: String, |
| | | default: "value", |
| | | }, |
| | | labelKey: { |
| | | type: String, |
| | | default: "label", |
| | | }, |
| | | // æ°å¢ï¼é»è®¤è¡¥å¿æ¶é´ |
| | | defaultCompensateTime: { |
| | | type: Number, |
| | | default: 0, |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | checkedValues: [], |
| | | selectedOrder: [], // ç°å¨æ ¼å¼ä¸º [{value, compensateTime}] |
| | | }; |
| | | }, |
| | | watch: { |
| | | value: { |
| | | immediate: true, |
| | | handler(newVal) { |
| | | if ( |
| | | Array.isArray(newVal) && |
| | | newVal.length > 0 && |
| | | typeof newVal[0] === "object" |
| | | ) { |
| | | console.log(this.selectedOrder, "111"); |
| | | |
| | | // 1. ä¼ å
¥çæ¯å¯¹è±¡æ°ç» [{ sort, preachform, compensateTime }] |
| | | this.checkedValues = newVal.map((item) => item.preachform); // æå preachform ç»æéä¸å¼æ°ç» |
| | | // æå»º selectedOrderï¼ä¼å
使ç¨ä¼ å
¥ç compensateTimeï¼å¦åç¨é»è®¤å¼ |
| | | this.selectedOrder = newVal.map((item) => ({ |
| | | value: item.preachform, |
| | | compensateTime: item.hasOwnProperty("compensateTime") |
| | | ? item.compensateTime |
| | | : this.defaultCompensateTime, |
| | | })); |
| | | } else { |
| | | // 2. ä¼ å
¥çæ¯å符串æ°ç» (å¦ ["1", "3", "4"]ï¼å
¼å®¹ä¹åçç¨æ³) |
| | | if (JSON.stringify(newVal) !== JSON.stringify(this.checkedValues)) { |
| | | this.checkedValues = [...newVal]; |
| | | console.log(this.selectedOrder, "222"); |
| | | console.log(this.newVal, "22"); |
| | | // æå»ºææ´æ° selectedOrderï¼ä¿çå·²æç compensateTime |
| | | const newOrder = []; |
| | | newVal.forEach((value) => { |
| | | const existingItem = this.selectedOrder.find( |
| | | (item) => item.value === value |
| | | ); |
| | | if (existingItem) { |
| | | newOrder.push(existingItem); |
| | | } else { |
| | | newOrder.push({ |
| | | value, |
| | | compensateTime: this.hasOwnProperty(value) |
| | | ? this.hasOwnProperty(value) |
| | | : this.defaultCompensateTime, |
| | | }); |
| | | } |
| | | }); |
| | | this.selectedOrder = newOrder; |
| | | } |
| | | } |
| | | }, |
| | | deep: true, // 建议添å deep: true 以确ä¿å¯¹è±¡æ°ç»å
çååè½è¢«æè· |
| | | }, |
| | | checkedValues(newVal, oldVal) { |
| | | console.log(this.selectedOrder, "333"); |
| | | // å¤çéä¸é¡¹çåå |
| | | const added = newVal.filter((item) => !oldVal.includes(item)); |
| | | const removed = oldVal.filter((item) => !newVal.includes(item)); |
| | | |
| | | added.forEach((value) => { |
| | | if (!this.selectedOrder.find((item) => item.value === value)) { |
| | | this.selectedOrder.push({ |
| | | value, |
| | | compensateTime: this.defaultCompensateTime, |
| | | }); |
| | | } |
| | | }); |
| | | |
| | | removed.forEach((value) => { |
| | | const index = this.selectedOrder.findIndex( |
| | | (item) => item.value === value |
| | | ); |
| | | if (index > -1) { |
| | | this.selectedOrder.splice(index, 1); |
| | | } |
| | | }); |
| | | |
| | | // æ´æ°ç¶ç»ä»¶ç v-model ç»å®å¼ï¼éä¸å¼æ°ç»ï¼ |
| | | this.$emit("input", [...newVal]); |
| | | // 触å change äºä»¶ï¼ä¼ é宿´çä¸å¡æ°æ® |
| | | this.emitChangeEvent(); |
| | | }, |
| | | }, |
| | | methods: { |
| | | getValue(option) { |
| | | return typeof option === "object" ? option[this.valueKey] : option; |
| | | }, |
| | | getLabel(option) { |
| | | return typeof option === "object" ? option[this.labelKey] : option; |
| | | }, |
| | | getLabelByValue(value) { |
| | | const option = this.options.find((opt) => this.getValue(opt) === value); |
| | | return option ? this.getLabel(option) : value; |
| | | }, |
| | | getSelectedIndex(index) { |
| | | if (index < 20) { |
| | | return String.fromCharCode(0x2460 + index); |
| | | } else { |
| | | return `(${index + 1})`; |
| | | } |
| | | }, |
| | | // å¤çè¡¥å¿æ¶é´åå |
| | | handleCompensateTimeChange(value, newTime) { |
| | | const item = this.selectedOrder.find((item) => item.value === value); |
| | | if (item) { |
| | | item.compensateTime = newTime; |
| | | // è¡¥å¿æ¶é´ååæ¶ï¼åªè§¦å change äºä»¶ï¼ä¸è§¦å¨ v-model |
| | | this.emitChangeEvent(); |
| | | } |
| | | }, |
| | | hasOwnProperty(patfrom) { |
| | | console.log(patfrom); |
| | | console.log(this.initialselectedOrder); |
| | | // 使ç¨findæ¹æ³æ¥æ¾å¹é
ç对象 |
| | | const foundObject = this.initialselectedOrder.find( |
| | | (item) => item.preachform === patfrom |
| | | ); |
| | | |
| | | // 妿æ¾å°å¯¹è±¡ï¼è¿åå
¶compensateTimeï¼å¦åè¿åfalse |
| | | return foundObject ? foundObject.compensateTime : false; |
| | | }, |
| | | // åå°ååäºä»¶ |
| | | emitChangeEvent() { |
| | | // è½¬æ¢æ°æ®æ ¼å¼ä¸ºç¶ç»ä»¶éè¦çæ ¼å¼ |
| | | const outputData = this.selectedOrder.map((item, index) => ({ |
| | | sort: index + 1, |
| | | preachform: item.value, |
| | | compensateTime: item.compensateTime, |
| | | })); |
| | | this.$emit("change", outputData); // åå° change äºä»¶ï¼ä¼ é宿´æ°æ® |
| | | }, |
| | | // è·åå½åéæ©é¡ºåºåè¡¥å¿æ¶é´ |
| | | getSelectionOrder() { |
| | | return this.selectedOrder.map((item, index) => ({ |
| | | sort: index + 1, |
| | | preachform: item.value, |
| | | compensateTime: item.compensateTime, |
| | | })); |
| | | }, |
| | | // è®¾ç½®éæ©é¡ºåºåè¡¥å¿æ¶é´ |
| | | setSelectionOrder(orderedValues) { |
| | | this.selectedOrder = orderedValues.map((item) => ({ |
| | | value: item.preachform, |
| | | compensateTime: item.compensateTime || this.defaultCompensateTime, |
| | | })); |
| | | |
| | | this.checkedValues = orderedValues.map((item) => item.preachform); |
| | | this.emitChangeEvent(); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .ordered-checkbox-container { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 16px; |
| | | } |
| | | |
| | | .horizontal-checkbox-group { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 20px; |
| | | } |
| | | |
| | | .selection-order-display { |
| | | padding: 12px; |
| | | background-color: #f5f7fa; |
| | | border-radius: 4px; |
| | | border: 1px solid #ebeef5; |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | align-items: center; |
| | | } |
| | | |
| | | .order-label { |
| | | font-weight: bold; |
| | | color: #606266; |
| | | margin-right: 8px; |
| | | } |
| | | |
| | | .order-item { |
| | | color: #409eff; |
| | | font-weight: 500; |
| | | display: inline-flex; |
| | | align-items: center; |
| | | margin-right: 8px; |
| | | } |
| | | |
| | | .compensate-time-input { |
| | | width: 90px; |
| | | margin-left: 8px; |
| | | } |
| | | |
| | | /* ååºå¼è®¾è®¡ï¼å°å±å¹æ¶æ¢è¡ */ |
| | | @media (max-width: 768px) { |
| | | .horizontal-checkbox-group { |
| | | gap: 12px; |
| | | } |
| | | |
| | | .selection-order-display { |
| | | padding: 8px; |
| | | flex-direction: column; |
| | | align-items: flex-start; |
| | | } |
| | | |
| | | .order-item { |
| | | margin-bottom: 8px; |
| | | } |
| | | } |
| | | </style> |