前端vue3——實現二次元人物拼圖校驗

文章目錄

    • ?前言
    • ?vue3拖拽實現拼圖
      • 💖 思路分解
      • 💖 布局結構
      • 💖 拖拽函數
      • 💖 校驗函數
      • 💖 inscode整體代碼
    • ?運行效果
      • 💖 隨機順序
      • 💖 拖拽中
      • 💖 校驗失敗
      • 💖 校驗通過
    • ?總結
    • ?結束

yma16-logo

?前言

大家好,我是yma16,本文分享關于 前端vue3——實現二次元人物拼圖校驗。
vue3系列相關文章:
vue3 + fastapi 實現選擇目錄所有文件自定義上傳到服務器
前端vue2、vue3去掉url路由“ # ”號——nginx配置
csdn新星計劃vue3+ts+antd賽道——利用inscode搭建vue3(ts)+antd前端模板
認識vite_vue3 初始化項目到打包
python_selenuim獲取csdn新星賽道選手所在城市用echarts地圖顯示
讓大模型分析csdn文章質量 —— 提取csdn博客評論在文心一言分析評論區內容
前端vue3——html2canvas給網站截圖生成宣傳海報
拖拽相關文章
前端——html拖拽原理

前端html拖拽原理
HTML 拖拽的基本原理是通過鼠標事件和 DOM 操作來實現的。

一般來說,拖拽操作包括三個階段:

  1. 鼠標按下事件:當用戶按下鼠標左鍵時,觸發鼠標按下事件。在該事件處理函數中,首先需要記錄下被拖拽元素的相關信息,比如該元素的位置、大小和初始鼠標點擊位置等。

  2. 鼠標移動事件:當用戶按下鼠標左鍵時并拖動鼠標時,觸發鼠標移動事件。在該事件處理函數中,需要根據鼠標當前位置和拖拽元素的初始位置,計算出該元素要被移動的距離,并在 DOM 中更新該元素的位置。

  3. 鼠標松開事件:當用戶松開鼠標左鍵時,觸發鼠標松開事件。在該事件處理函數中,需要清除拖拽元素的相關信息,比如初始鼠標點擊位置等。

在以上三個階段中,需要使用的 DOM 操作包括:

  1. 獲取 DOM 元素:可以使用 document.getElementById() 或 document.querySelector() 等方法來獲取需要拖拽的元素。

  2. 更新元素位置:可以使用元素的 style 屬性來修改元素的位置,比如設置元素的 left 和 top 屬性。

  3. 創建新元素:可以使用 document.createElement() 方法來創建新的 DOM 元素。

通過以上鼠標事件和 DOM 操作的組合,可以實現基本的 HTML 拖拽功能。

?vue3拖拽實現拼圖

使用vue3和原生的html drag 實現片的拖拽

💖 思路分解

  1. 拆分圖片為4宮格樣式
  2. 定義拖拽的樣式div對應圖片的4宮格
  3. 定義拖拽的div元素,背景圖片使用圖片拆分的素材
  4. 給元素定義序號
  5. 校驗最終的元素序號,判斷是否拼圖成功

拆分圖片
split-image

💖 布局結構

才有左右布局
左側:拖拽來源區域
右側:拖拽放入區域
template布局

<template><div class="container-drag"><div style="width: 100%;text-align:center;margin: 10px;"><a-button type="primary" class="random-button" @click="randomDragOrder">隨機順序</a-button></div><div class="container-drag-box"><div class="container-drag-left"><!-- <> --><div v-for="item in state.dragConfig.sourceArray" :key="item.id" class="drag-item-box":id="state.dragConfig.sourceDomPrefix + '-' + item.id"><div class="drag-item" draggable="true" :id="state.dragConfig.dragDomPrefix + '-' + item.id"><!-- 拖拽對象 data-order 校驗排序用 --><img :src="item.src" width="280" height="280" :data-order="item.id" /></div></div></div><div class="container-drag-right" id="target-box-id"><!-- 目標對象 data-order 校驗排序用--><div v-for="item in state.dragConfig.sourceArray" :key="item" class="target-item-box dropzone":id="state.dragConfig.targetDomPrefix + '-' + item.id" :data-order="item.id"></div></div></div><div style="width: 100%;text-align:center"><a-button type="primary" @click="confirmImg">確定</a-button></div></div>
</template>

css配置

<style>
.container-drag {min-width: 800px;
}.random-button {margin: 5px;cursor: pointer;
}.container-drag-box {display: flex;justify-content: space-between;
}.container-drag-left {width: 800px;}.container-drag-right {width: 600px;height: 600px;margin: 0;
}.drag-item-box {display: inline-block;margin: 2px;padding: 0;width: 280px;height: 280px;border: 1px solid rgb(24, 144, 255);overflow: hidden;}.target-item-box {display: inline-block;width: 280px;height: 280px;border: 1px solid rgb(255, 255, 255);box-sizing: border-box;overflow: hidden;margin-right: 5px;margin-bottom: 0;margin-top: 0;
}/* 拖拽對象 */
.drag-item {margin: 0;text-align: center;cursor: pointer;
}/* 拖拽中 */
.dragging {opacity: .5;
}/* 懸浮上方 */
.dragover {background: rgba(0,255,0,.5);
}
</style>

布局效果
box-left

💖 拖拽函數

拖拽對象配置方法drag,dragstart,dragend
放入區域配置方法drop,dragover,dragleave,dragenter

// 拖拽對象
const drag = (event) => {console.log("dragging", event);
}const dragStart = (event) => {// 保存被拖動元素的引用state.dragConfig.dragTarget = event.target;// 設置為半透明event.target.classList.add("dragging");
}const dragEnd = (event) => {// 拖動結束,重置透明度event.target.classList.remove("dragging");
}// 目標對象const dragOver = (event) => {// 阻止默認行為以允許放置event.preventDefault();
}const dragLeave = (event) => {// 在可拖動元素離開潛在放置目標元素時重置該目標的背景if (event.target.classList.contains("dropzone")) {event.target.classList.remove("dragover");}
}const dragEnter = (event) => {// 在可拖動元素進入潛在的放置目標時高亮顯示該目標if (event.target.classList.contains("dropzone")) {event.target.classList.add("dragover");}
}const drop = (event) => {// 阻止默認行為(會作為某些元素的鏈接打開)event.preventDefault();// 將被拖動元素移動到選定的目標元素中if (event.target.classList.contains("dropzone")) {event.target.classList.remove("dragover");// 刪除自身state.dragConfig.dragTarget.parentNode.removeChild(state.dragConfig.dragTarget);// 添加元素event.target.appendChild(state.dragConfig.dragTarget);}
}const initDragAction = (sourceElement) => {if (!sourceElement) {return}/* 在放置拖拽對象上觸發的事件 */sourceElement.addEventListener("drag", drag);sourceElement.addEventListener("dragstart", dragStart);sourceElement.addEventListener("dragend", dragEnd);
}const initTargetAction = (targetElement) => {if (!targetElement) {return}/* 在放置目標對象上觸發的事件 */targetElement.addEventListener("dragover",dragOver,false,);targetElement.addEventListener("dragenter", dragEnter);targetElement.addEventListener("dragleave", dragLeave);targetElement.addEventListener("drop", drop);
}

💖 校驗函數

遍歷dom節點獲取自定義的data-order屬性進行校驗

// 校驗
const confirmImg = () => {const rightDom = document.getElementById('target-box-id')console.log('rightDom', rightDom)const rightDomChildNodes = rightDom.childNodesconsole.log('rightDomChildNodes', rightDomChildNodes)if (rightDomChildNodes.length) {// childNodes會出現空文本節點for (let i = 0, length = rightDomChildNodes.length; i < length; ++i) {console.log('childNodes', rightDomChildNodes[i])if (rightDomChildNodes[i].nodeType !== 1) {// 跳過文本節點continue}else if (rightDomChildNodes[i].hasChildNodes) {console.log('childNodes attr', rightDomChildNodes[i])const currentDataOrder = rightDomChildNodes[i].getAttribute('data-order')const imgDataOrder = rightDomChildNodes[i].getElementsByTagName('img')[0].getAttribute('data-order')console.log('currentDataOrder', currentDataOrder)console.log('imgDataOrder', imgDataOrder)if (currentDataOrder !== imgDataOrder) {return message.warn('拼圖位置錯誤:\t第' + currentDataOrder+'張圖片')}}else {return message.warn('沒有完成拼圖,請拖拽圖片')}}}else {return message.warn('沒有完成拼圖,請拖拽圖片')}return '恭喜你完成拼圖'
}

💖 inscode整體代碼

完整的vue代碼

<template><div class="container-drag"><div style="width: 100%;text-align:center;margin: 10px;"><a-button type="primary" class="random-button" @click="randomDragOrder">隨機順序</a-button></div><div class="container-drag-box"><div class="container-drag-left"><!-- <> --><div v-for="item in state.dragConfig.sourceArray" :key="item.id" class="drag-item-box":id="state.dragConfig.sourceDomPrefix + '-' + item.id"><div class="drag-item" draggable="true" :id="state.dragConfig.dragDomPrefix + '-' + item.id"><!-- 拖拽對象 data-order 校驗排序用 --><img :src="item.src" width="280" height="280" :data-order="item.id" /></div></div></div><div class="container-drag-right" id="target-box-id"><!-- 目標對象 data-order 校驗排序用--><div v-for="item in state.dragConfig.sourceArray" :key="item" class="target-item-box dropzone":id="state.dragConfig.targetDomPrefix + '-' + item.id" :data-order="item.id"></div></div></div><div style="width: 100%;text-align:center"><a-button type="primary" @click="confirmImg">確定</a-button></div></div>
</template><script setup>
import { reactive, onMounted } from 'vue'
import { message } from 'ant-design-vue'
const state = reactive({dragConfig: {sourceDomPrefix: 'source-item',targetDomPrefix: 'target-item',dragDomPrefix: 'drag-item',dragTarget: null,sourceImg: '/img/imageSource.png',sourceArray: [{id: 1,src: '/img/image1.png'},{id: 2,src: '/img/image2.png'},{id: 3,src: '/img/image3.png'},{id: 4,src: '/img/image4.png'},]}
})
// 數組隨機順序
const randomDragOrder = () => {const sourceArray = [...state.dragConfig.sourceArray]sourceArray.sort(() => Math.random() - 0.5);state.dragConfig.sourceArray = sourceArray
}// 拖拽對象
const drag = (event) => {console.log("dragging", event);
}const dragStart = (event) => {// 保存被拖動元素的引用state.dragConfig.dragTarget = event.target;// 設置為半透明event.target.classList.add("dragging");
}const dragEnd = (event) => {// 拖動結束,重置透明度event.target.classList.remove("dragging");
}// 目標對象const dragOver = (event) => {// 阻止默認行為以允許放置event.preventDefault();
}const dragLeave = (event) => {// 在可拖動元素離開潛在放置目標元素時重置該目標的背景if (event.target.classList.contains("dropzone")) {event.target.classList.remove("dragover");}
}const dragEnter = (event) => {// 在可拖動元素進入潛在的放置目標時高亮顯示該目標if (event.target.classList.contains("dropzone")) {event.target.classList.add("dragover");}
}const drop = (event) => {// 阻止默認行為(會作為某些元素的鏈接打開)event.preventDefault();// 將被拖動元素移動到選定的目標元素中if (event.target.classList.contains("dropzone")) {event.target.classList.remove("dragover");// 刪除自身state.dragConfig.dragTarget.parentNode.removeChild(state.dragConfig.dragTarget);// 添加元素event.target.appendChild(state.dragConfig.dragTarget);}
}const initDragAction = (sourceElement) => {if (!sourceElement) {return}/* 在放置拖拽對象上觸發的事件 */sourceElement.addEventListener("drag", drag);sourceElement.addEventListener("dragstart", dragStart);sourceElement.addEventListener("dragend", dragEnd);
}const initTargetAction = (targetElement) => {if (!targetElement) {return}/* 在放置目標對象上觸發的事件 */targetElement.addEventListener("dragover",dragOver,false,);targetElement.addEventListener("dragenter", dragEnter);targetElement.addEventListener("dragleave", dragLeave);targetElement.addEventListener("drop", drop);
}// 校驗
const confirmImg = () => {const rightDom = document.getElementById('target-box-id')console.log('rightDom', rightDom)const rightDomChildNodes = rightDom.childNodesconsole.log('rightDomChildNodes', rightDomChildNodes)if (rightDomChildNodes.length) {// childNodes會出現空文本節點for (let i = 0, length = rightDomChildNodes.length; i < length; ++i) {console.log('childNodes', rightDomChildNodes[i])if (rightDomChildNodes[i].nodeType !== 1) {// 跳過文本節點continue}else if (rightDomChildNodes[i].hasChildNodes) {console.log('childNodes attr', rightDomChildNodes[i])const currentDataOrder = rightDomChildNodes[i].getAttribute('data-order')const imgDataOrder = rightDomChildNodes[i].getElementsByTagName('img')[0].getAttribute('data-order')console.log('currentDataOrder', currentDataOrder)console.log('imgDataOrder', imgDataOrder)if (currentDataOrder !== imgDataOrder) {return message.warn('拼圖位置錯誤:\t第' + currentDataOrder+'張圖片')}}else {return message.warn('沒有完成拼圖,請拖拽圖片')}}}else {return message.warn('沒有完成拼圖,請拖拽圖片')}return '恭喜你完成拼圖'
}// 生命周期
onMounted(() => {// 拖拽對象const dragArr = state.dragConfig.sourceArray.map(item => {return state.dragConfig.dragDomPrefix + '-' + item.id})dragArr.forEach(id => {initDragAction(document.getElementById(id))})// 目標對象const sourceArr = state.dragConfig.sourceArray.map(item => {return state.dragConfig.sourceDomPrefix + '-' + item.id})sourceArr.forEach(id => {initTargetAction(document.getElementById(id))})const targetArr = state.dragConfig.sourceArray.map(item => {return state.dragConfig.targetDomPrefix + '-' + item.id})targetArr.forEach(id => {initTargetAction(document.getElementById(id))})
})</script><style>
.container-drag {min-width: 800px;
}.random-button {margin: 5px;cursor: pointer;
}.container-drag-box {display: flex;justify-content: space-between;
}.container-drag-left {width: 800px;}.container-drag-right {width: 600px;height: 600px;margin: 0;
}.drag-item-box {display: inline-block;margin: 2px;padding: 0;width: 280px;height: 280px;border: 1px solid rgb(255, 255, 255);overflow: hidden;}.target-item-box {display: inline-block;width: 280px;height: 280px;border: 1px solid rgb(255, 255, 255);box-sizing: border-box;overflow: hidden;margin-right: 5px;margin-bottom: 0;margin-top: 0;
}/* 拖拽對象 */
.drag-item {margin: 0;text-align: center;cursor: pointer;
}/* 拖拽中 */
.dragging {opacity: .5;
}/* 懸浮上方 */
.dragover {background: rgba(0,255,0,.5);
}
</style>

代碼放在inscode vue3項目在線運行

?運行效果

💖 隨機順序

random

💖 拖拽中

draging

💖 校驗失敗

verrify-error

💖 校驗通過

verrify-success
拖拽過程截圖

drag-process

?總結

拼圖校驗總結:

1.校驗的順序可以用元素的attribute傳遞位置順序進行標記
2.拖拽對象的函數使用 拖拽對象配置方法drag,dragstart,dragend 放入區域配置方法drop,dragover,dragleave,dragenter

拖拽總結:

在HTML中,拖放(drag and
drop)是一種用戶界面交互的特定形式,其中用戶可以拖動元素或數據并將其放置在另一個位置。以下是HTML拖放的一些總結:

  1. 拖放可用于各種用途,例如重新排序列表,將文本或文件拖動到另一個應用程序中,或從文件資源管理器將文件拖動到Web頁面中。
  2. 在HTML中,拖放API由一些事件組成,包括dragstart、dragenter、dragover、dragleave、drop和dragend。
  3. 通過使用HTML data屬性,可以將數據附加到拖動事件,并在放置事件中訪問它們。
  4. 通過使用CSS,可以為用戶拖動時顯示的元素創建自定義外觀。
  5. 在JavaScript中,可以使用dragEvent對象來訪問有關拖動和放置事件的詳細信息,例如拖動元素的位置和放置元素的位置。
  6. 可以使用HTML5的拖放API創建復雜的拖放交互,例如可拖動的圖形和對象,將元素沿路徑拖動等。

?結束

本文分享到這結束,如有錯誤或者不足之處歡迎指出!
cute-img

👍 點贊,是我創作的動力!
?? 收藏,是我努力的方向!
?? 評論,是我進步的財富!
💖 感謝你的閱讀!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/210279.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/210279.shtml
英文地址,請注明出處:http://en.pswp.cn/news/210279.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

IDEA中.java .class .jar的含義與聯系

當使用IntelliJ IDEA這樣的集成開發環境進行Java編程時&#xff0c;通常涉及.java源代碼文件、.class編譯后的字節碼文件以及.jar可執行的Java存檔文件。 1. .java 文件&#xff1a; 1.這些文件包含了Java源代碼&#xff0c;以文本形式編寫。它們通常位于項目中的源代碼目錄中…

蒼穹外賣項目筆記(8)— 緩存商品、購物車功能

前言 代碼鏈接&#xff1a; Echo0701/take-out? (github.com) 1 緩存菜品 1.1 問題說明 【注】很多時候系統性能的瓶頸就在于數據庫這端 1.2 實現思路 通過 Redis 來緩存數據&#xff0c;減少數據庫查詢操作 【注】Redis 基于內存來保存數據的&#xff0c;訪問 Redis 數據…

LeetCode208.實現Trie(前綴樹)

我一開始想題目叫前綴樹&#xff0c;是要用樹嗎&#xff1f;但是不知道用樹怎么寫&#xff0c;然后我就花了10多分鐘&#xff0c;用了HashMap解了。map的key是word&#xff0c;value是一個放了word的所有前綴的set&#xff0c;這樣search方法就非常簡單了&#xff0c;只要看has…

Leetcode—2048.下一個更大的數值平衡數【中等】

2023每日刷題&#xff08;五十四&#xff09; Leetcode—2048.下一個更大的數值平衡數 實現代碼 class Solution { public:int nextBeautifulNumber(int n) {for(int x n 1; ; x) {vector<int> cnt(10, 0);for(int y x; y > 0; y / 10) {cnt[y%10];}bool ok tru…

C++ Div3、Sqrt 函數高性能實現(帶匯編指令集)

均采用魔法數字&#xff08;Magic Number&#xff09;實現&#xff0c;一個是經典求平方根函數所使用的魔法數字&#xff1a;0x5f375a86、0x5f3759df。 float Sqrt(float x) noexcept { /* 0x5f3759df */float xhalf 0.5f * x;int32_t i *(int32_t*)&x;i 0x5f375a86 - …

TP5上傳圖片壓縮尺寸

圖片上傳&#xff0c;最簡單的就是&#xff0c; 方法一&#xff1a; 修改上傳限制&#xff0c;不讓上傳大于多少多少的圖片 改一下size即可&#xff0c;默認單位是B換算成M還需要除以兩次1024 方法二&#xff1a; 對上傳的圖片進行縮放&#xff0c;此辦法網上找了不少的代碼…

如何在 Azure Cosmos DB 中使用緩存

Cosmos DB 是微軟在 Azure 云中發布的新 NoSQL 數據庫。與關系數據庫不同&#xff0c;Cosmos DB 是一種托管數據庫服務&#xff0c;因此具有可擴展性&#xff0c;因此在高事務性 .NET 和 .NET Core 應用程序中很受歡迎。 但是&#xff0c;使用 Cosmos DB 時&#xff0c;您需要…

pytorch 鉤子函數hook 詳解及實戰

文章目錄 1. 介紹1.1 pytorch hook 函數種類1.2 pytorch hook 種類1.3 hook的執行順序2. torch.Tensor.register_hook()2.1 功能2.2 語法2.3 案例3. nn.Module.register_forward_pre_hook3.1 功能3.2 語法3.3 案例4. nn

連通分量提取

圖像形態學操作中的提取連通分量是一種用于分離圖像中相互連接的像素區域的技術。這些像素區域通常代表著圖像中的不同物體、目標或者區域。連通分量提取通常用于圖像分割、對象識別、特征提取等領域。 原理&#xff1a; ??連通分量提取基于圖像中像素的連接性。在這個過程中…

ECharts標題字體大小自適應變化

我們在做自適應Echarts的時候,字體大小在配置項里是如下配置的, title 標題組件,包含主標題和副標題。 以下是常用的對標題的設置: title:{//設置圖表的標題text:"主標題",link:"baidu.com", //設置標題超鏈接target:"self",

HCIP —— BGP 基礎 (下)

BGP 的狀態機 --- 建立對等體之間的TCP會話&#xff1a;指定建立對等體的對象 六種狀態機 Idle狀態 Idle 等待狀態&#xff08;相當于OSPF的down狀態&#xff09;--- 采用TCP單播建鄰 Idle 狀態下&#xff0c;啟動BGP協議后必須指定建立對等體的目標之后&#xff0c;才能進入…

yaml工作常用語法總結

文章目錄 yaml中的| 符號 和 > 符號yaml中的 - 符號工作中常遇到的問題- 命令行中有冒號加空格&#xff0c;導致yaml解析報錯 yaml中的| 符號 和 > 符號 在 YAML 中&#xff0c;| 符號表示標量塊&#xff08;Scalar Block&#xff09;的開始。它用于表示長文本塊或保持多…

代碼隨想錄算法訓練營第四十六天| 139 單詞拆分

目錄 139 單詞拆分 139 單詞拆分 class Solution { public:bool wordBreak(string s, vector<string>& wordDict) {vector<bool>dp(s.size() 1);//長度為i的字符串時能否成功拆分unordered_set<string>set(wordDict.begin(),wordDict.end());dp[0] t…

數據結構 | 查漏補缺之哈希表、最短路徑、二叉樹與森林的轉換

哈希表是什么&#xff1f; 或者說 設圖采用鄰接表的存儲結構&#xff0c;寫對圖的刪除頂點和刪除邊的算法步驟 刪除邊 刪除點 最短路徑問題 參考博文 迪杰斯特拉(Dijkstra)算法_dijkstra算法-CSDN博客 Dijkstra(迪杰斯特拉&#xff09;算法 定義一個點為源點&#xff0c;算源…

5G+AI開花結果,助力智慧安檢落地

“請帶包的乘客過機安檢&#xff01;”&#xff0c;深圳地鐵、騰訊共同打造的5GAI智慧安檢輔助系統亮相福田樞紐站&#xff0c;進一步解放了人力&#xff0c;提高安檢效率&#xff0c;為交通安全保駕護航&#xff0c;讓智慧出行成為現實。 傳統的安檢設備均為人工肉眼辨識&…

java面試題匯總-目錄

堅持記錄和總結一些面試過程中遇到的面試題&#xff0c;以及總結出自己的回答技巧。不用死記硬背也能完整的回答出來。會持續更新&#xff0c;歡迎提出問題和疑問&#xff0c;大家一起總結經驗。 1.Hashmap、Hashtable、ConcurrentHashMap原理 2.談談sql優化-mysql 3.ArrayList…

2023年9月13日 Go生態洞察:WASI支持在Go中的實現

&#x1f337;&#x1f341; 博主貓頭虎&#xff08;&#x1f405;&#x1f43e;&#xff09;帶您 Go to New World?&#x1f341; &#x1f984; 博客首頁——&#x1f405;&#x1f43e;貓頭虎的博客&#x1f390; &#x1f433; 《面試題大全專欄》 &#x1f995; 文章圖文…

21、命令執行

文章目錄 一、命令執行概述1.1 基本定義1.2 原理1.3 兩個條件1.4 命令執行漏洞產生的原因1.5 管道符號和通用命令符 二、遠程命令執行2.1 遠程命令執行相關函數2.2 遠程命令執行漏洞的利用 三、系統命令執行3.1 相關函數3.2 系統命令執行漏洞利用 四、命令執行漏洞防御 一、命令…

Vue筆記(三)深入組件

組件注冊 組件注冊有兩種方式&#xff1a; 全局注冊 可以使用Vue應用實例的.component()方法&#xff0c;讓組件在當前Vue應用中全局可用&#xff0c;.component()方法可以被鏈式調用。全局注冊的組件可以在此應用的任意組件的模版中使用。import { createApp } from vue imp…

阿里云生態離線數倉

1. 大數據開發治理平臺 DataWorks 功能齊全&#xff1a;10多年大數據建設沉淀完整的平臺&#xff0c;覆蓋數據開發治理的全生命周期 簡單易用&#xff1a;全圖形化界面&#xff0c;SQL為主的數據開發方式 安全穩定&#xff1a;雙11日千萬級任務穩定調度&#x…