iT邦幫忙

0

Vue 遞迴階層勾選框問題

  • 分享至 

  • xImage

目前用Vue+quasar 寫了一個階層的勾選框
現在可以在子層勾選後,將父層的也一起勾選
目前遇到兩個問題
1 如果子層的全部勾選取消,我要如何判斷,並且取消勾選父層
2 如果有三層以上,我目前的方式沒辦法勾選全部的父層,只能勾選到上一層

謝謝

<template>
  <div class="row" v-if="menu.id != 0">
    <div class="col-2 menu-title" :style="levelCss">
      <label class="label-text">{{ $t(menu.title) }}</label>
      <q-icon
        v-if="hasChildren"
        name="keyboard_arrow_down"
        @click="openMenu()"
      ></q-icon>
    </div>
    <div class="col-10">
      <div class="row">
        <div class="col-2 toggle">
          <q-toggle
            checked-icon="check"
            color="green"
            unchecked-icon="clear"
            v-model="readEnabled"
            :true-value="1"
            :false-value="0"
            :onUpdate:modelValue="permissionValues"
            :data-menu="menu.id"
          />
        </div>
        <div class="col-1 toggle">
          <q-toggle
            checked-icon="check"
            color="green"
            unchecked-icon="clear"
            v-model="creatEnabled"
            :true-value="2"
            :false-value="0"
            :onUpdate:modelValue="permissionValues"
          />
        </div>
        <div class="col-1 toggle">
          <q-toggle
            checked-icon="check"
            color="blue"
            unchecked-icon="clear"
            v-model="creatDisplay"
            :true-value="4"
            :false-value="0"
            :onUpdate:modelValue="permissionValues"
          />
        </div>
        <div class="col-1 toggle">
          <q-toggle
            checked-icon="check"
            color="green"
            unchecked-icon="clear"
            v-model="updateEnabled"
            :true-value="8"
            :false-value="0"
            :onUpdate:modelValue="permissionValues"
          />
        </div>
        <div class="col-1 toggle">
          <q-toggle
            checked-icon="check"
            color="blue"
            unchecked-icon="clear"
            v-model="updateDisplay"
            :true-value="16"
            :false-value="0"
            :onUpdate:modelValue="permissionValues"
          />
        </div>
        <div class="col-1 toggle">
          <q-toggle
            checked-icon="check"
            color="green"
            unchecked-icon="clear"
            v-model="deleteEnabled"
            :true-value="32"
            :false-value="0"
            :onUpdate:modelValue="permissionValues"
          />
        </div>
        <div class="col-1 toggle">
          <q-toggle
            checked-icon="check"
            color="blue"
            unchecked-icon="clear"
            v-model="deleteDisplay"
            :true-value="64"
            :false-value="0"
            :onUpdate:modelValue="permissionValues"
          />
        </div>
        <div class="col-1 toggle">
          <q-toggle
            checked-icon="check"
            color="green"
            unchecked-icon="clear"
            v-model="saveEnabled"
            :true-value="128"
            :false-value="0"
            :onUpdate:modelValue="permissionValues"
          />
        </div>
        <div class="col-1 toggle">
          <q-toggle
            checked-icon="check"
            color="blue"
            unchecked-icon="clear"
            v-model="saveDisplay"
            :true-value="256"
            :false-value="0"
            :onUpdate:modelValue="permissionValues"
          />
        </div>
        <div class="col-1 toggle">
          <q-toggle
            checked-icon="check"
            color="green"
            unchecked-icon="clear"
            v-model="exportEnabled"
            :true-value="512"
            :false-value="0"
            :onUpdate:modelValue="permissionValues"
          />
        </div>
        <div class="col-1 toggle">
          <q-toggle
            checked-icon="check"
            color="blue"
            unchecked-icon="clear"
            v-model="exportDisplay"
            :true-value="1024"
            :false-value="0"
            :onUpdate:modelValue="permissionValues"
          />
        </div>
      </div>
    </div>
  </div>
  <div v-show="isOpen">
    <tree-menu
      @check-parent="checkParent"
      v-for="list in menu.children"
      :menuList="list"
      :key="list.id"
    />
  </div>
</template>

<script setup>
import utils from "src/boot/utils";

const permissStore = utils.usePermissStore();
const loginStore = utils.useLoginStore();
const props = defineProps({
  menuList: Object,
});

const menu = props.menuList;
const hasChildren = menu.children.length !== 0;
const emit = defineEmits(["check-parent"]);

const level = (menu.id.match(/\./g) || []).length * 12;
const levelCss = "padding-left:" + level + "px";

const readEnabled = utils.ref(0);
const creatEnabled = utils.ref(0);
const creatDisplay = utils.ref(0);
const updateEnabled = utils.ref(0);
const updateDisplay = utils.ref(0);
const deleteEnabled = utils.ref(0);
const deleteDisplay = utils.ref(0);
const saveEnabled = utils.ref(0);
const saveDisplay = utils.ref(0);
const exportEnabled = utils.ref(0);
const exportDisplay = utils.ref(0);

const isOpen = utils.ref(false);

const permissionValues = (v) => {
  countPerValue();
  emit("check-parent", v);
};

const openMenu = () => {
  isOpen.value = !isOpen.value;
};

const countPerValue = () => {
  let id = menu.id;
  let obj = {};
  obj[id] =
    readEnabled.value +
    creatEnabled.value +
    creatDisplay.value +
    updateEnabled.value +
    updateDisplay.value +
    deleteEnabled.value +
    deleteDisplay.value +
    saveEnabled.value +
    saveDisplay.value +
    exportEnabled.value +
    exportDisplay.value;
  permissStore.appendPermission(obj);
};

const checkParent = (v) => {
  countPerValue();
  let storeValue = permissStore.getPermissions[menu.id];
  if ((storeValue & v) == 0) storeValue += v;

  readEnabled.value = storeValue & 1 ? 1 : 0;
  creatEnabled.value = storeValue & 2 ? 2 : 0;
  creatDisplay.value = storeValue & 4 ? 4 : 0;
  updateEnabled.value = storeValue & 8 ? 8 : 0;
  updateDisplay.value = storeValue & 16 ? 16 : 0;
  deleteEnabled.value = storeValue & 32 ? 32 : 0;
  deleteDisplay.value = storeValue & 64 ? 64 : 0;
  saveEnabled.value = storeValue & 128 ? 128 : 0;
  saveDisplay.value = storeValue & 256 ? 256 : 0;
  exportEnabled.value = storeValue & 512 ? 512 : 0;
  exportDisplay.value = storeValue & 1024 ? 1024 : 0;
};
</script>

<style scoped>
.menu-title {
  display: flex;
  align-items: center;
  padding-left: v-bind(levelCss);
}
.toggle {
  display: flex;
  justify-content: center;
}
.label-text {
  font-size: 14px;
  padding-top: 5px;
}
</style>

froce iT邦大師 1 級 ‧ 2024-06-17 11:33:49 檢舉
懶得寫code,你自己去參考下面的去改。
用遞迴寫會比較簡單

https://michael-verschoof.medium.com/recursive-components-in-vue-3-e897643df82
https://github.com/michaelverschoof/medium-examples/blob/recursive-component/src/views/HomeView.vue
https://github.com/michaelverschoof/medium-examples/blob/recursive-component/src/components/RecursiveComponent.vue
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友回答

立即登入回答