<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      什么!你還不會寫Vue組件,編寫《數據級權限》匹配公式組件

      說明

          該文章是屬于OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。

          該系統文章,我會盡量說的非常詳細,做到不管新手、老手都能看懂。

          說明:OverallAuth2.0 是一個簡單、易懂、功能強大的權限+可視化流程管理系統。

      友情提醒:本篇文章是屬于系列文章,看該文章前,建議先看之前文章,可以更好理解項目結構。

      qq群:801913255,進群有什么不懂的盡管問,群主都會耐心解答。

      有興趣的朋友,請關注我吧(*^▽^*)。

      關注我,學不會你來打我

      前言

      該篇文章是實現【數據級權限】的開篇文章,其主要實現內容如下圖↓

      該圖為功能級權限匹配插件

      創建模型和數據源

      在實現組件前,先要使用TS把模型和數據源創建好

      我的文檔目錄如:Src->model->match->index.ts    依托于開源項目OverallAuth2.0統一權限分發中心的系統架構

      創建匹配條件的關系

      //組條件
      export const matchingGroup = [
          {
              label: '',
              value: 'And',
              disabled: false
          },
          {
              label: '',
              value: 'Or',
              disabled: false
          }
      ]
      View Code

      創建匹配組件模型

      //公式匹配模型
      export interface matchingData {
      
          id: string;
          // 父級id
          pid: string;
          //匹配組(and,or) 
          matchGroup: string;
          //層級
          level: number;
          //匹配條件
          matchingWhere: matchingWhereData[];
          //子集
          children: matchingData[];
      }
      
      //匹配條件模型
      export interface matchingWhereData {
          //主鍵
          id: string;
          //字段key(選中的字段)
          fieldKey: string;
          //等式符號key(選中的符號)
          matchEquationKey: string;
          //匹配數據key(選中的匹配值)
          matchDataKey: string;
      }
      View Code

      創建生成隨機id的方法

      /* 生成隨機不重復id */
      export const randamId = function () {
          let n = 1;
          let arr = [];
          for (let i = 0; i < n; i++) {
              arr[i] = parseInt((Math.random() * 10000000000).toString());
          }
          for (let i = 0; i < n; i++) {
              for (let j = i + 1; j < n; j++) {
                  if (arr[i] === arr[j]) {
                      randamId();
                      return false;
                  }
              }
          }
          return ("Item-" + arr).toString();
      };
      View Code

      編寫組件

      我的頁面目錄:Src->views->match->index.vue      Src->views->match->match.vue

      編寫match.vue頁面代碼

      <template>
        <div class="plandiv">
          <div v-for="item in data" :key="item.id" class="forDiv">
            <div class="groupDiv">
              <div class="groupBackColor">
                <div style="width: 20%">
                  <el-select
                    v-model="item.matchGroup"
                    placeholder="請選擇"
                    style="
                      float: left;
                      margin-right: 10px;
                      margin-left: 10px;
                      min-width: 100px;
                    "
                  >
                    <el-option
                      v-for="group in matchingGroup"
                      :key="group.value"
                      :label="group.label"
                      :value="group.value"
                    />
                  </el-select>
                </div>
                <div style="width: 80%">
                  <div class="buttonStyle">這里放操作按鈕</div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </template>
      <script  lang="ts" >
      import {
        matchingData,
        matchingGroup,
        matchingWhere,
        matchingEquation,
        positionList,
      } from "@/model/match";
      import { defineComponent, PropType } from "vue";
      
      export default defineComponent({
        name: "xc-match",
        props: {
          data: {
            type: Object as PropType<matchingData[]>,
            required: true,
          },
        },
        setup() {
          return {
            matchingGroup,
            matchingWhere,
            matchingEquation,
            positionList,
          };
        },
        components: {},
      });
      </script>
      
      <style  scoped>
      /* 最外層樣式 */
      .plandiv {
        background-color: white;
        height: auto;
      }
      /* 循環層樣式 */
      .forDiv {
        overflow-y: auto;
      }
      /* 分組樣式 */
      .groupDiv {
        border: 1px solid #919aa3;
        width: auto;
        height: auto;
        margin-top: 5px;
        margin-right: 20px;
        margin-bottom: 10px;
        margin-left: 20px;
      }
      /* 組條件背景色 */
      .groupBackColor {
        background-color: #919aa3;
        height: 50px;
        line-height: 50px;
        display: flex;
        width: 100%;
        justify-content: center;
        align-items: center;
      }
      
      /* 按鈕樣式 */
      .buttonStyle {
        text-align: left;
        margin-left: 20px;
      }
      </style>
      View Code

      編寫index.vue頁面代碼

      <template>
          <match :data="pageList"></match>
      </template>
      <script lang="ts" setup>
      import { matchingData, randamId } from "@/model/match";
      import { ref } from "vue";
      import match from "../match/match.vue";
      const pageList = ref<matchingData[]>([
        {
          id: "Group-1",
          pid: "0",
          matchGroup: "And",
          level: 1,
          matchingWhere: [
            {
              id: randamId().toString(),
              fieldKey: "",
              matchEquationKey: "",
              matchDataKey: "",
            },
          ],
          children: [],
        },
      ]);
      </script>
      View Code

      index.vue頁面中,我們添加了一條分組的默認值。查看下效果

      添加分組按鈕

      在class='buttonStyle' div中添加如下代碼

       

      <el-button icon="CirclePlus" plain @click="addGroup(item)"
                      >新增分組</el-button
                    >
                    <el-button icon="Plus" plain @click="addItem(item)"
                      >新增條件</el-button
                    >
                    <el-button
                      v-if="item.level !== 1"
                      type="danger"
                      icon="Delete"
                      @click="deleteGroup(item)"
                      >刪除分組</el-button
                    >

       

      添加按鈕事件

      添加前,我們必須先安裝一個插件:npm install number-precision

      在setup(props)中添加如下代碼,并retrun事件

      //最多組
          const maxGroup = ref<number>(5);
          //最多層級
          const maxLevel = ref<number>(3);
          //最多條件
          const maxWhere = ref<number>(10);
      
          // 添加組事件
          const addGroup = function (item: matchingData) {
            //獲取當前組的長度
            var listGroupLength = item.children.length;
      
            //添加前驗證最多添加多少層級
            if (item.level >= maxLevel.value) {
              ElMessage({
                message: "最多添加" + maxLevel.value + "",
                type: "warning",
              });
              return;
            }
      
            //添加前驗證能添加多少組
            if (listGroupLength >= maxGroup.value) {
              ElMessage({
                message: "每層下最多添加" + maxGroup.value + "個組",
                type: "warning",
              });
              return;
            }
      
            //當前組必須要有條件才能添加下級組
            if (item.matchingWhere.length == 0) {
              ElMessage({
                message: "當前組下無任何條件,不能添加分組!",
                type: "warning",
              });
              return;
            }
      
            //組織要添加節點的數據
            var groupId = item.id + "-" + (listGroupLength + 1);
            var groupPid = item.id;
            var groupLevel = item.level + 1;
      
            //找到對應的下標
            const index = props.data.findIndex((s) => {
              if (s.id === item.id) {
                return true;
              }
            });
      
            //精確插入當前節點及插入位置
            var indexLength = listGroupLength + 1;
            item.children.splice(plus(...[index, indexLength]), 0, {
              id: groupId,
              pid: groupPid,
              matchGroup: "Or",
              level: groupLevel,
              matchingWhere: [],
              children: [],
            });
          };
          
          // 刪除組
          const deleteGroup = function (item: matchingData) {
            GetGroupSpliceIndex(item.id, props.data);
          };
      
          //遞歸刪除組
          const GetGroupSpliceIndex = (id: string, list: matchingData[]) => {
            //找到刪除數據下標
            const index = list.findIndex((p: { id: string }) => {
              if (p.id === id) {
                return true;
              }
            });
            if (index === -1) GetGroupSpliceIndex(id, list[0].children);
            list.forEach((f: { id: string }) => {
              if (f.id == id) {
                list.splice(index, 1);
              }
            });
          };
      View Code

      這個時候,我們點擊按鈕,不會出現下級。因為遞歸的重要一步,并沒有完成。

      在match.vue 頁面中找到有class="groupDiv" 的div,在div中的末尾添加如下代碼

         <xc-match
                v-if="item.children && item.children.length"
                :data="item.children"
              />

      以上代碼是實現遞歸的關鍵,位置一定要準。

      說明一點xc-match一定要和頁面導出的名稱一樣。

      看效果圖

      添加條件及條件按鈕

      添加條件項

      在match.vue頁面xc-match元素前,添加如下代碼

       <div
                class="itemBackColor"
                v-for="whereItem in item.matchingWhere"
                :key="whereItem.id"
              >
                <!-- 匹配條件 -->
                <el-select
                  v-model="whereItem.fieldKey"
                  placeholder="請選擇匹配條件"
                  style="width: 240px"
                >
                  <el-option
                    v-for="where in matchingWhere"
                    :key="where.value"
                    :label="where.label"
                    :value="where.value"
                  />
                </el-select>
                <!-- 匹配等式 -->
                <el-select
                  v-model="whereItem.matchEquationKey"
                  placeholder="請選擇等式"
                  style="width: 240px"
                >
                  <el-option
                    v-for="equation in matchingEquation"
                    :key="equation.value"
                    :label="equation.label"
                    :value="equation.value"
                  />
                </el-select>
                <!-- 匹配值 -->
                <el-input-number
                  v-model="whereItem.matchDataKey"
                  :step="1"
                  min="1"
                  max="200"
                  step-strictly
                  style="width: 240px"
                  v-if="whereItem.fieldKey === 'Age'"
                />
                <el-select
                  v-else-if="whereItem.fieldKey === 'Position'"
                  v-model="whereItem.matchDataKey"
                  placeholder="請選擇職位"
                  style="width: 240px"
                >
                  <el-option
                    v-for="position in positionList"
                    :key="position.value"
                    :label="position.label"
                    :value="position.value"
                  />
                </el-select>
                <el-date-picker
                  v-else-if="whereItem.fieldKey === 'CreateTime'"
                  v-model="whereItem.matchDataKey"
                  type="date"
                  style="width: 240px"
                  placeholder="請選擇時間"
                />
                <el-input
                  v-else
                  v-model="whereItem.matchDataKey"
                  style="width: 240px"
                  placeholder="請輸入"
                  clearable
                />
                <el-button
                  type="danger"
                  icon="Delete"
                  plain
                  size="small"
                  style="margin-left: 10px"
                  @click="deleteItem(whereItem, item)"
                  >刪除條件</el-button
                >
                <!-- 當前項id:{{ whereItem.id }} -->
              </div>
      View Code

      css如下

      /* 項背景色 */
      .itemBackColor {
        height: 46px;
        display: -webkit-box;
        margin-left: 20px;
        margin-right: 20px;
        display: flex;
        align-items: center;
      }
      .itemBackColor > *:not(:first-child) {
        margin-left: 10px;
      }

      添加條件按鈕事件

       //添加項事件
          const addItem = function (item: matchingData) {
            if (item.matchingWhere.length > maxWhere.value) {
              ElMessage({
                message: "每層下最多添加" + maxWhere.value + "組條件",
                type: "warning",
              });
              return;
            }
            item.matchingWhere.push({
              id: randamId().toString(),
              fieldKey: "",
              matchEquationKey: "",
              matchDataKey: "",
            });
          };
      
          // 刪除項
          const deleteItem = function (item: matchingWhereData, data: matchingData) {
            GetItemSpliceIndex(item.id, data);
          };
      
          //遞歸刪除項
          const GetItemSpliceIndex = (id: string, list: any) => {
            //找到刪除數據下標
            const index = list.matchingWhere.findIndex((p: { id: string }) => {
              if (p.id === id) {
                return true;
              }
            });
            if (index === -1) GetItemSpliceIndex(id, list.children);
            list.matchingWhere.forEach((f: { id: string }) => {
              if (f.id == id) {
                //刪除當前項
                list.matchingWhere.splice(index, 1);
                if (list.matchingWhere.length == 0) {
                  var parentGroup = props.data.filter((s) => s.id == list.pid);
                  //當前組下無任何項并且層級不等于1,刪除當前組
                  if (parentGroup.length == 0 && list.level !== 1) {
                    GetGroupSpliceIndex(list.id, props.data);
                  }
                }
              }
            });
          };
      View Code

      查看效果,如下圖↓

      驗證條件是否完整

      編寫驗證方法

       //驗證條件是否為空
          const VerifyWhereEmpty = function () {
            const isTrueArray = ref<boolean[]>([]);
            VerifyFunction(props.data, isTrueArray.value);
            const trueArray = isTrueArray.value?.filter((f) => f === true);
            if (trueArray.length === 0) {
              ElMessage({
                message: "成功",
                type: "warning",
              });
            } else {
              ElMessage({
                message: "匹配條件未填寫完整",
                type: "warning",
              });
            }
          };
          //遞歸驗證
          const VerifyFunction = function (
            list: matchingData[],
            isTrueArray: boolean[]
          ) {
            list.forEach((element) => {
              element.matchingWhere.forEach((w) => {
                if (
                  w.matchEquationKey.length == 0 ||
                  w.matchDataKey.length == 0 ||
                  w.fieldKey.length == 0
                ) {
                  isTrueArray.push(true);
                  return;
                }
              });
              if (element.children.length > 0) {
                VerifyFunction(element.children, isTrueArray);
              }
            });
          };
      View Code

      在index.vue 頁面調用

      <template>
        <div>
          <el-button type="success" icon="Check" @click="submitForm">
            保存
          </el-button>
          <match :data="pageList" ref="childRef"></match>
        </div>
      </template>
      <script lang="ts" setup>
      import { matchingData, randamId } from "@/model/match";
      import { ref } from "vue";
      import match from "../match/match.vue";
      //樣式
      const emit = defineEmits(["validate"]);
      const pageList = ref<matchingData[]>([
        {
          id: "Group-1",
          pid: "0",
          matchGroup: "And",
          level: 1,
          matchingWhere: [
            {
              id: randamId().toString(),
              fieldKey: "",
              matchEquationKey: "",
              matchDataKey: "",
            },
          ],
          children: [],
        },
      ]);
      //保存
      const childRef = ref();
      const submitForm = function () {
        if (childRef.value != null) {
          childRef.value.VerifyWhereEmpty();
        }
      };
      </script>
      View Code

      做完這些就能達到最終效果

       

      需要源碼的,關注公眾號,發送【權限】獲取源碼

      以上就是本篇文章的全部內容,感謝耐心觀看

      后端WebApi 預覽地址:http://139.155.137.144:8880/swagger/index.html

      前端vue 預覽地址:http://139.155.137.144:8881

      關注公眾號:發送【權限】,獲取源碼

      有興趣的朋友,請關注我微信公眾號吧(*^▽^*)。

      關注我:一個全棧多端的寶藏博主,定時分享技術文章,不定時分享開源項目。關注我,帶你認識不一樣的程序世界

       

       

       

       

       

       

      posted @ 2025-03-19 14:50  陳逸子風  閱讀(744)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产精品夫妇激情啪发布| 国产精品久久久久影院色| 国产超高清麻豆精品传媒麻豆精品 | 无码av天天av天天爽| 91精品乱码一区二区三区| 在线观看无码不卡av| 青青青爽在线视频观看| 高中女无套中出17p| 免费高清特级毛片A片| 波多野结衣一区二区三区高清| 2020国产欧洲精品网站| 蜜臀一区二区三区精品免费| 无码人妻一区二区三区AV| 亚洲春色在线视频| 久久精品第九区免费观看| 日本免费一区二区三区| 国产自产视频一区二区三区| 2019亚洲午夜无码天堂| 国产精品视频一区不卡| 国产视频一区二区三区四区视频| 成人精品视频一区二区三区尤物 | 国产久9视频这里只有精品| 亚洲高清有码中文字| 亚洲精品一区久久久久一品av| 久久国产精品老女人| 男女一边摸一边做爽爽| 久久亚洲精品中文字幕无| 国产高清一区二区不卡| 最新国产AV最新国产在钱| 午夜精品极品粉嫩国产尤物| 蜜臀av黑人亚洲精品| 一本高清码二区三区不卡| 沧州市| 肉大捧一进一出免费视频| 无码中文字幕av免费放| 精品久久久中文字幕人妻| 色欲AV无码一区二区人妻| 久久91精品牛牛| 国产精品美女一区二三区| 2021亚洲爆乳无码专区| 久久香蕉国产线看观看怡红院妓院|