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

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

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

      《vue3-實現蛇形單向流程圖》

      最終展示效果:

      點擊node節點,顯示其詳情:

      話不多說,上代碼

      父組件引用及其傳參:

      <flowchart ref="flowchartRef"  :chartData="hierarchicalArray" :Index="5" />

      proxy.$refs.flowchartRef.initWidth(hierarchicalArray.value)

      流程圖組件:

      <template>
        <!-- 蛇形流程圖-->
        <div class="snakeFlowchart" >
          <div style="width: 100%; display: flex; position: relative; margin-top: 20px" v-if="experienceData && experienceData.length > 0">
            <!--左側曲線-->
            <div :style="`width:${sideWidth}vw ; margin-left: 30px`">
              <div>
                <span  :style="`margin-top:${ItemHeight/2}px ; opacity: 0`" class="headerRadio"></span>
                <div v-if="experienceData.length > Index">
                              <span
                    v-for="(num, index) in leftRows"
                    :key="index"
                    class="hingelisHeard"
                    :style="`height:${ItemHeight}px ; margin-top:${ItemHeight}px; ;border: ${LineWidth}px ${LineType} ${LineColor};`"
                  ></span>
                </div>
              </div>
            </div>
            <!--中間流程項-->
            <div style="width: 96%">
              <div
                style="display: flex"
                v-for="(item, index) in experienceData"
                :key="index"
                :style="{ 'justify-content':(index + 1) % 2 !== 0?'flex-start':'flex-end'}"
              >
              <!-- 單數行 -->
                <div style="display: flex ;justify-content: flex-start;" v-if="(index + 1) % 2 !== 0">
                  <div
                    class="timeline"
                    v-for="(item, i) in DisplayProcessing(experienceData, index + 1)"
                    :key="i"
                    :style="(i + 1) % Index !== 0 ? `width:${ItemWidth}vw ; height:${ItemHeight}px` : `width: ${IconWidth}vw;height:${ItemHeight}px`"
                  >
                    <el-popover placement="bottom" :width="600" trigger="click">
                      <template #reference>
                        <div class="Nodes" @click="onNodeClick(item)"  :style="{ backgroundColor: item === selectedNode ? '#cce3dd' : '#FFF' }">
                          <span v-if="item.keyFlag == 'Y'" class="star-box">
                            <el-icon class="star-icon"><StarFilled /></el-icon>
                          </span>
                          <div class="NodesItem">
                            <div class="labelContent">
                              <el-icon v-if="item.checkPreProcess && item.checkPreProcess.length>0" style="color:green"><Grid /></el-icon>
                              {{ item.processName }}
                            </div>
                          </div>
                        </div>
                      </template>
                      <el-card shadow="never">
                        <template #header>
                          <div class="card-header">
                            <span class="title">{{ item.processName }} </span>
                            <el-tag
                              :type="item.enableFlag == 'Y' ? 'success' : 'danger'"
                              size="small"
                              style="margin-left:8px;"
                              >{{ item.enableFlag == 'Y' ? '啟用' : '停用' }}</el-tag
                            >
                          </div>
                        </template>
                        <el-descriptions title="" :column="2" size="small">
                          <el-descriptions-item label="工序編碼 :">
                            {{ item.processCode }}
                          </el-descriptions-item>
                          <el-descriptions-item label="是否關鍵工序 :">{{
                            item.keyFlag == 'Y'?'是':'否'
                          }}</el-descriptions-item>
                          <el-descriptions-item label="工序類型 :">{{ item.processType == '1'?'報工':'報工&測試' }}</el-descriptions-item>
                          <el-descriptions-item label="能否外協 :">{{ item.outSourcing == true?'能':'否' }}</el-descriptions-item>
                          <el-descriptions-item label="查前工序 :">{{ item.checkPreProcessNames }} </el-descriptions-item>
                          <el-descriptions-item label="備注 :">{{ item.remark }}</el-descriptions-item>
                        </el-descriptions>
                      </el-card>
                    </el-popover>
                    
                    <div
                      class="border"
                      v-if="
                                          (i + 1) % Index != 0 &&
                                          i != DisplayProcessing(experienceData, index + 1).length - 1
                                      "
                    >
                      <div class="borderTime " :style="`border-bottom:${LineWidth}px ${LineType} ${LineColor}`"></div>
                    </div>
                  </div>
                </div>
                <!-- 雙數行 -->
                <div style="display: flex ;justify-content: flex-end;" v-else>
                  <div
                    class="timeline2"
                    v-for="(itemDouble, i) in DisplayProcessing(experienceData, index + 1)"
                    :key="i"
                    :style="
                                      i + 1 === 1 &&
                                      DisplayProcessing(experienceData, index + 1).length !== 1
                                          ? `width: ${IconWidth}vw;height:${ItemHeight}px`
                                          : `width:${ItemWidth}vw;height:${ItemHeight}px`
                                  "
                  >
                    <el-popover placement="bottom" :width="600" trigger="click">
                      <template #reference>
                        <div class="Nodes" @click="onNodeClick(itemDouble)"  :style="{ backgroundColor: itemDouble === selectedNode ? '#cce3dd' : '#FFF' }">
                          <span v-if="itemDouble.keyFlag == 'Y'" class="star-box">
                            <el-icon class="star-icon"><StarFilled /></el-icon>
                          </span>
                          <div class="NodesItem">
                            <div class="labelContent">
                              <el-icon v-if="itemDouble.checkPreProcess && itemDouble.checkPreProcess.length>0" style="color:green"><Grid /></el-icon>
                              {{ itemDouble.processName }}
                            </div>
                          </div>
                        </div>
                      </template>
                      <el-card shadow="never">
                        <template #header>
                          <div class="card-header">
                            <span class="title">{{ itemDouble.processName }} </span>
                            <el-tag
                              :type="itemDouble.enableFlag == 'Y' ? 'success' : 'danger'"
                              size="small"
                              >{{ itemDouble.enableFlag == 'Y' ? '啟用' : '停用' }}</el-tag
                            >
                          </div>
                        </template>
                        <el-descriptions title="" :column="2" size="small">
                          <el-descriptions-item label="工序編碼 :">
                            {{ itemDouble.processCode }}
                          </el-descriptions-item>
                          <el-descriptions-item label="是否關鍵工序 :">{{
                            itemDouble.keyFlag == 'Y'?'是':'否'
                          }}</el-descriptions-item>
                          <el-descriptions-item label="工序類型 :">{{ itemDouble.processType == '1'?'報工':'報工&測試' }}</el-descriptions-item>
                          <el-descriptions-item label="能否外協 :">{{ itemDouble.outSourcing == true?'能':'否' }}</el-descriptions-item>
                          <el-descriptions-item label="查前工序 :">{{ itemDouble.checkPreProcessNames }} </el-descriptions-item>
                          <el-descriptions-item label="備注 :">{{ itemDouble.remark }}</el-descriptions-item>
                        </el-descriptions>
                      </el-card>
                    </el-popover>
                    <div class="border" v-if="i !== 0">
                      <div class="borderTime" :style="`border-bottom:${LineWidth}px ${LineType} ${LineColor}`"></div>
                    </div>
       
                    
                  </div>
                </div>
              </div>
            </div>
            <!--右側曲線-->
            <div :style="`width:${sideWidth}vw ; margin-right: 30px`">
              <div>
                <span class="hingelis" :style="`margin-top: ${ItemHeight/2}px;height:${ItemHeight}px; border: ${LineWidth}px ${LineType} ${LineColor};`" v-if="experienceData.length > Index"></span>
                <div v-if="experienceData.length > Index * 2">
                              <span
                    class="hingelis"
                    v-for="(num, index) in rightRows"
                    :key="index"
                      :style="`height:${ItemHeight}px ; margin-top:${ItemHeight}px; border: ${LineWidth}px ${LineType} ${LineColor};`"
                  ></span>
                </div>
              </div>
            </div>
          </div>
          <el-empty v-else description="暫無數據" />
        </div>
      </template>
      <script setup name="Flowchart">
      import { Plus } from '@element-plus/icons-vue'
      import { onMounted, ref, watch } from 'vue'
      import { nextTick } from 'vue'
      const { proxy } = getCurrentInstance()
      
      
      const props = defineProps({
        // 流程數據
        chartData: {
          type: Array,
          default: () => {
            return [];
          },
        },
        //每行幾條數據
        Index: {
          type: Number,
          default: 5,
        },
        // 行高
        ItemHeight: {
          type: String,
          default: '80',
        },
        // 線寬度
        LineWidth:{
          type: Number,
          default: 1
        },
        // 線樣式(實線/虛線)
        LineType:{
          type: String,
          default: 'solid',
        },
        // 線顏色
        LineColor:{
          type: String,
          default: '#ddd',
        },
        //已完成流程顏色
        DoneItemColor: {
          type: String,
          default: '#a0a0a5',
        },
        // 當前流程顏色
        CurrentItemColor:{
          type: String,
          default: '#10bc28',
        },
        //小球大小
        IconWidth:{
          type: String,
          default: '0.85',
        }
      })
      
       // 流程數據
      const  experienceData =ref([])
      const  leftRows=ref(0)
      const  rightRows = ref(0)
      const  leftShow = ref(false)
      const  rightShow = ref(false)
      // 寬度
      const  ItemWidth =ref(19.4)
      // 拐彎位置寬度
      const  sideWidth =ref('')
      
      /** 初始化寬度 */
      function  initWidth(data){
        experienceData.value = data;
        let p  = document.querySelector(".snakeFlowchart").parentNode;
        // 1VW寬度
        let VW = window.innerWidth/100
        // 中間流程部分占8成,算出每一段長度
        ItemWidth.value= ((Number(p.clientWidth))*0.70/VW)/(props.Index-1)
        // console.log(this.ItemWidth)
        // 兩邊拐彎部分共占2成
        sideWidth.value = ((Number(p.clientWidth))*0.30/VW)/2
      }
      /** 計算數據排列 */
      function DisplayProcessing(Arg, Num) {
        //數據循環處理
        let arr = Arg.slice(props.Index * (Num - 1), props.Index * Num);
        arr = Num % 2 === 0 ? arr.reverse() : arr;
        return arr;
      }
      
      const selectedNode = ref(null)
      function onNodeClick(itemData) {
        selectedNode.value = itemData
      }
      
      // 監聽 props.chartData 的變化
      watch(
        () => props.chartData, (newVal) => {
          experienceData.value = newVal
          // console.log("experienceData===",experienceData.value)
          let rows = Math.ceil(newVal.length / props.Index);
          leftRows.value = rows === 2 ? 0 : rows % 2 === 0 ? parseInt(rows / 2) - 1 : parseInt(rows / 2);
          rightRows.value = rows === 4 ? 1 : rows % 2 === 0 ? parseInt(rows / 2) % 2 === 0 ? parseInt(rows / 2) >= 4
                    ? parseInt(rows / 2) - 1
                    : parseInt(rows / 2)
                  : parseInt(rows / 2) - 1
                : parseInt(rows / 2) - 1;
          leftShow.value = rows % 2 === 0;
          rightShow.value = rows === 1 ? false : rows % 2 === 1;
          
        },
        { deep: true }
      )
      
      
      defineExpose({
        initWidth
      })
      </script>
      <style scoped lang="scss">
      .timeline {
        width: 21.4vw;
        display: flex;
        align-items: center;
      }
      .timeline2 {
        width: 21.4vw;;
        display: flex;
        align-items: center;
        justify-content: flex-end;
      }
      .border {
        width: 100%;
        justify-content: center;
        align-items: center;
        display: flex;
        .borderTime {
          width: 100%;
        }
      }
       
      
      .Nodes {
        position: absolute;
        min-width:90px;
        padding: 8px;
        height:auto;
        background-color: #fff;
        border-radius: 4px;
        box-shadow: 0 1px 5px rgba(30, 145, 121, 0.5);
        border: 1px solid #1e9179;
        cursor: pointer;
        .star-box{ 
          z-index:98; 
          position: absolute; 
          top: 0; left: 0; width: 0; height: 0; 
          border-top: 20px solid #027357; 
          border-right: 20px solid transparent; 
          .star-icon{ 
            z-index:99; 
            color: white; 
            position: absolute; 
            top: -20px; left: 0px; 
            font-size: 12px; 
          } 
        } 
        .NodesItem{
          justify-content: center;
          align-items: center;
          display: flex;
          width: 100%;
          .labelContent{
            max-width: 140px; 
            position: relative; 
            font-size: 14px; 
            text-align: left; /* 內容從左向右展示 */ 
            word-wrap: break-word; /* 允許長單詞或 URL 地址換行 */ 
            overflow-wrap: break-word; /* 同 word-wrap,增加兼容性 */ 
            white-space: normal; /* 允許文本換行 */ 
          }
        }
      }
      .hingelis {
        content: "";
        display: block;
        width: 100%;
        border-radius: 0 15px 15px 0px;
        border-left: 0px !important;
      }
      .hingelisHeard {
        content: "";
        display: block;
        width: 100%;
        border-radius: 15px 0px 0px 15px;
        border-right: 0px !important;
      }
       
      .headerRadio {
        display: block;
        width: 100%;
        border-bottom: 1px solid #cccccc;
        position: relative;
      }
      
      </style>

       

      posted @ 2025-07-17 10:22  愛聽書的程序猿  閱讀(110)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲日韩av无码一区二区三区| 精品国产av无码一区二区三区| 72种姿势欧美久久久久大黄蕉| 在线 | 国产精品99传媒a | 亚洲另类激情专区小说婷婷久| 色欧美片视频在线观看| 欧美 亚洲 另类 丝袜 自拍 动漫 久久久久久久久毛片精品 | 国产a在视频线精品视频下载| 国产精品va在线观看无码不卡| 亚洲精品成人区在线观看 | 九九热在线观看精品视频| 亚洲综合精品一区二区三区| 无遮挡高潮国产免费观看| 人成午夜免费视频在线观看| 成人午夜在线观看刺激| 双乳奶水饱满少妇呻吟免费看| 人妻中文字幕亚洲一区| 国产国语毛片在线看国产| 四虎国产精品成人免费久久| 四虎永久免费精品视频| 麻豆一区二区中文字幕| 潮安县| 国产精品自拍一二三四区| 亚洲日韩精品无码一区二区三区 | 精品午夜福利在线视在亚洲| 熟女视频一区二区在线观看| 视频一区视频二区在线视频| 少妇被黑人到高潮喷出白浆| 四虎成人精品永久网站| 日本九州不卡久久精品一区| 亚洲国产性夜夜综合| 真实单亲乱l仑对白视频| 国产精品成人va在线播放| 国产一区二区不卡91| 亚洲国产欧美在线人成AAAA| 精品人妻无码中文字幕在线| h无码精品动漫在线观看| 成人一区二区不卡国产| 亚洲成a人v欧美综合天堂下载 | 五月综合激情婷婷六月| 亚洲精品无码久久久影院相关影片 |