|
@@ -1,25 +1,36 @@
|
|
|
<script setup lang="ts">
|
|
|
-import { onMounted, ref, reactive, computed } from 'vue'
|
|
|
-import { initLoadResouce } from '@/utils/resource'
|
|
|
import type { DropdownInstance } from 'element-plus'
|
|
|
import type { IconDropdownItem } from '@/types/dataAnalysis'
|
|
|
|
|
|
+import { onMounted, ref, reactive, watch } from 'vue'
|
|
|
+import { initLoadResouce } from '@/utils/resource'
|
|
|
+import { useCommonStore } from '@/stores/useCommon'
|
|
|
+
|
|
|
+const { selectInfo, tempMultipleChioce, saveSelectInfo, saveTempMultipleChioce } = useCommonStore()
|
|
|
+
|
|
|
interface DropdownInfo {
|
|
|
- isRadio?: boolean
|
|
|
+ isRadio?: boolean // 是否是单选
|
|
|
slectInfo: Array<IconDropdownItem>
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * @description: 最大选择数
|
|
|
- * @return {*}
|
|
|
- */
|
|
|
-const maxSelect = 1
|
|
|
-
|
|
|
// props
|
|
|
const props = withDefaults(defineProps<DropdownInfo>(), {
|
|
|
isRadio: true
|
|
|
})
|
|
|
|
|
|
+/**
|
|
|
+ * @description: 初始化选择信息
|
|
|
+ * @return {*}
|
|
|
+ */
|
|
|
+const selectBaseInfo = reactive<Array<IconDropdownItem>>(
|
|
|
+ JSON.parse(JSON.stringify(props.slectInfo))
|
|
|
+)
|
|
|
+
|
|
|
+// 判断是不是通过确认框关闭的。主要服务于多选的情况
|
|
|
+// 原理是因为点击确认关闭的话,确认事件会先触发,然后再触发关闭事件
|
|
|
+// 由此来去判断是否需要把多选框的信息恢复
|
|
|
+const isConfimClose = ref<Boolean>(false)
|
|
|
+
|
|
|
// emits
|
|
|
const emits = defineEmits(['changePf'])
|
|
|
|
|
@@ -27,7 +38,7 @@ const emits = defineEmits(['changePf'])
|
|
|
const dropDownRef = ref<DropdownInstance>()
|
|
|
|
|
|
// 资源的加载路径
|
|
|
-const resourceInfo: Record<string, string> = props.slectInfo.reduce(
|
|
|
+const resourceInfo: Record<string, string> = selectBaseInfo.reduce(
|
|
|
(acc, item) => {
|
|
|
acc[item.value] = item.icon
|
|
|
return acc
|
|
@@ -43,15 +54,20 @@ const backupInfo = reactive<Array<IconDropdownItem>>([])
|
|
|
|
|
|
/**
|
|
|
* @description: 确认选择
|
|
|
+ * 这里主要用于多选的情况使用,对于单选,即使点击确认按钮也不会有二次请求,因为seleinfo没有改变
|
|
|
* @return {*}
|
|
|
*/
|
|
|
const confirmSelect = () => {
|
|
|
- Object.assign(backupInfo, JSON.parse(JSON.stringify(props.slectInfo)))
|
|
|
+ isConfimClose.value = true // 通过确认事件关闭
|
|
|
+ Object.assign(backupInfo, JSON.parse(JSON.stringify(selectBaseInfo)))
|
|
|
dropDownRef.value?.handleClose()
|
|
|
- emits(
|
|
|
- 'changePf',
|
|
|
- props.slectInfo.filter((item) => item.isSelected).map((item) => item.value)
|
|
|
- )
|
|
|
+
|
|
|
+ if (props.isRadio) return
|
|
|
+
|
|
|
+ // 去把state的数据更新一下
|
|
|
+ tempMultipleChioce.pf = selectBaseInfo.filter((item) => item.isSelected).map((item) => item.value)
|
|
|
+
|
|
|
+ saveTempMultipleChioce() // 保存到本地
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -60,7 +76,7 @@ const confirmSelect = () => {
|
|
|
*/
|
|
|
const cancleSelect = () => {
|
|
|
dropDownRef.value?.handleClose()
|
|
|
- Object.assign(props.slectInfo, backupInfo)
|
|
|
+ Object.assign(selectBaseInfo, backupInfo)
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -70,31 +86,98 @@ const cancleSelect = () => {
|
|
|
*/
|
|
|
const dropdownVis = (state: boolean) => {
|
|
|
if (state) {
|
|
|
- Object.assign(backupInfo, JSON.parse(JSON.stringify(props.slectInfo)))
|
|
|
+ // 打开的时候,需要备份一下当前选择
|
|
|
+ Object.assign(backupInfo, JSON.parse(JSON.stringify(selectBaseInfo)))
|
|
|
} else {
|
|
|
- Object.assign(props.slectInfo, backupInfo)
|
|
|
+ // 关闭的时候,如果一个都没有选中,那么就需要把备份的信息恢复回去
|
|
|
+ // 这里只针对于多选情况,因为单选的逻辑中不存在一个都没有选中的情况,因为无法取消已经选中
|
|
|
+ // 而多选的情况下,因为即使可以取消,也不会立即改变selectInfo中的信息,只有点击了确认按钮才会改变,所以这里只需要恢复props的selectinfo就行了
|
|
|
+
|
|
|
+ // 不是点击确认按钮关闭的多选框,且是多选按钮,也需要恢复
|
|
|
+ if (!selectBaseInfo.find((item) => item.isSelected) || (!isConfimClose.value && !props.isRadio))
|
|
|
+ Object.assign(selectBaseInfo, backupInfo)
|
|
|
+ if (isConfimClose.value) isConfimClose.value = false // 把状态重置
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * @description: 用于限制最多的选择个数
|
|
|
- * @return {*}
|
|
|
- */
|
|
|
-const canSelect = computed(() => {
|
|
|
- return props.slectInfo.filter((item) => item.isSelected).length < maxSelect
|
|
|
-})
|
|
|
-
|
|
|
-/**
|
|
|
* @description: 选择事件,当目前可以选择或者是这个选项已经被选中的时候,就允许改变他的状态
|
|
|
* @param {*} item 当前的选项信息
|
|
|
* @return {*}
|
|
|
*/
|
|
|
const selectPf = (item: any) => {
|
|
|
- if (canSelect.value || item.isSelected) {
|
|
|
+ if (props.isRadio) {
|
|
|
+ selectInfo.pf = []
|
|
|
+ selectInfo.pf.push(item.value)
|
|
|
+
|
|
|
+ saveSelectInfo() // 选择之后保存到本地一次
|
|
|
+ } else {
|
|
|
+ // 多选就取反就行
|
|
|
item.isSelected = !item.isSelected
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * @description: 同步selectinfo的信息到页面上
|
|
|
+ * @return {*}
|
|
|
+ */
|
|
|
+const syncSelectInfo = () => {
|
|
|
+ selectBaseInfo.forEach((item) => {
|
|
|
+ item.isSelected = selectInfo.pf.includes(item.value)
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @description: 同步tempMultipleChioce的信息到页面上
|
|
|
+ * @return {*}
|
|
|
+ */
|
|
|
+const syncTempMultipleChioce = () => {
|
|
|
+ selectBaseInfo.forEach((item) => {
|
|
|
+ item.isSelected = tempMultipleChioce.pf.includes(item.value)
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @description: 监听selectinfo的变化,然后同步到页面上
|
|
|
+ * @return {*}
|
|
|
+ */
|
|
|
+const watchSelectPf = watch(
|
|
|
+ () => selectInfo.pf,
|
|
|
+ () => {
|
|
|
+ syncSelectInfo()
|
|
|
+ },
|
|
|
+ { deep: true }
|
|
|
+)
|
|
|
+
|
|
|
+/**
|
|
|
+ * @description: 监听tempMultipleChioce的变化,然后同步到页面上
|
|
|
+ * @return {*}
|
|
|
+ */
|
|
|
+const watchTempMultipleChioce = watch(
|
|
|
+ () => tempMultipleChioce.pf,
|
|
|
+ () => {
|
|
|
+ syncTempMultipleChioce()
|
|
|
+ },
|
|
|
+ { deep: true }
|
|
|
+)
|
|
|
+
|
|
|
+/**
|
|
|
+ * @description: 根据本地保存的方案信息,去初始化selectinfo的信息
|
|
|
+ * @return {*}
|
|
|
+ */
|
|
|
+const initSelectInfo = () => {
|
|
|
+ if (props.isRadio) {
|
|
|
+ watchTempMultipleChioce() // 如果是单选进来的,在这儿把多选的事件取消掉
|
|
|
+ syncSelectInfo() // 同步一下数据
|
|
|
+ } else {
|
|
|
+ watchSelectPf() // 与上面同理
|
|
|
+ syncTempMultipleChioce() // 同理
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 去加载一下本地的信息
|
|
|
+initSelectInfo()
|
|
|
+
|
|
|
onMounted(() => {
|
|
|
// 去加载所有需要的资源
|
|
|
|
|
@@ -109,12 +192,12 @@ onMounted(() => {
|
|
|
<el-dropdown
|
|
|
trigger="click"
|
|
|
@visible-change="dropdownVis"
|
|
|
- :hide-on-click="false"
|
|
|
+ :hide-on-click="props.isRadio"
|
|
|
ref="dropDownRef"
|
|
|
>
|
|
|
<span class="displayBox">
|
|
|
<div class="displayIcon">
|
|
|
- <span class="iconItem" v-for="item in props.slectInfo">
|
|
|
+ <span class="iconItem" v-for="item in selectBaseInfo">
|
|
|
<el-image
|
|
|
v-if="item.isSelected"
|
|
|
style="width: 20px; height: 20px; margin-right: 5px"
|
|
@@ -131,11 +214,10 @@ onMounted(() => {
|
|
|
<template #dropdown>
|
|
|
<el-dropdown-menu>
|
|
|
<el-dropdown-item
|
|
|
- v-for="item in props.slectInfo"
|
|
|
+ v-for="item in selectBaseInfo"
|
|
|
:key="item.value"
|
|
|
:value="item.value"
|
|
|
@click="selectPf(item)"
|
|
|
- :disabled="!canSelect && !item.isSelected"
|
|
|
>
|
|
|
<el-image
|
|
|
style="width: 20px; height: 20px; margin-right: 5px"
|
|
@@ -143,12 +225,7 @@ onMounted(() => {
|
|
|
:fit="'cover'"
|
|
|
/>
|
|
|
<!-- 禁用掉原生的点击事件,自己实现点击 -->
|
|
|
- <el-checkbox
|
|
|
- :disabled="!canSelect && !item.isSelected"
|
|
|
- v-model="item.isSelected"
|
|
|
- size="small"
|
|
|
- @click.native.prevent="return"
|
|
|
- />
|
|
|
+ <el-checkbox v-model="item.isSelected" size="small" @click.native.prevent="return" />
|
|
|
</el-dropdown-item>
|
|
|
</el-dropdown-menu>
|
|
|
<span class="btnGroup">
|