自定义拖拽列表

news2024/11/29 22:45:12

 效果图

 DataAnalysis.vue

<template>
  <div class="app-container">
    <div class="operate">
      <el-select class="t_select" v-model="templateName" clearable placeholder="模版" size="default" @clear="clearTemplateData" @change="templateData">
        <el-option v-for="item in templateList" :key="item.id" :label="item.templateName" :value="item.id"/>
      </el-select>
      <el-button @click="setTemplate" type="primary" size="default">保存模版</el-button>
      <el-button @click="excelExport" type="primary" size="default">Excel导出</el-button>
    </div>

    <main>
      <!-- 所有属性 -->
      <Draggable
          class="item-container item-container1"
          group="drag"
          v-model:list="allProps"
          item-key="label"
      >
        <template #item="{ element }">
          <div class="item">{{ element.label }}</div>
        </template>
      </Draggable>

      <!-- 多级表头子属性:基础表头① -->
      <Draggable
          class="item-container item-container2"
          group="drag"
          v-model:list="baseProps"
          item-key="label"
      >
        <template #item="{ element }">
          <div class="item">{{ element.label }}</div>
        </template>
      </Draggable>

      <!-- 多级表头:③  -->
      <Draggable
          class="item-container item-container3"
          group="drag"
          v-model:list="multiLevelProps"
          item-key="label"
      >
        <template #item="{ element }">
          <div class="item">{{ element.label }}</div>
        </template>
      </Draggable>

      <!-- 分组属性:② -->
      <Draggable
          class="item-container item-container4"
          group="drag"
          v-model:list="groupProps"
          item-key="label"
      >
        <template #item="{ element }">
          <div class="item">{{ element.label }}</div>
        </template>
      </Draggable>

      <!-- 表格展示数据     -->
      <el-table :data="brr" border :span-method="objectSpanMethod">
        <el-table-column
            v-for="item in groupProps"
            :prop="item.prop"
            :label="item.label"/>
        <MultiHeaders
            :multiHeaders="multiHeaderValues"
            :baseProps="baseProps"
            v-if="multiLevelProps && multiLevelProps.length"/>
        <el-table-column
            v-for="item in baseProps"
            :prop="item.prop"
            :label="item.label"
            v-else/>
      </el-table>

    </main>

    <el-dialog v-model="isShowTemplate" title="设置模版" width="30%">
      <el-form label-width="100px" :model="tForm" style="max-width: 460px">
        <el-form-item label="模版名称">
          <el-input v-model="tForm.templateName"/>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="isShowTemplate = false">取消</el-button>
          <el-button type="primary" @click="saveTemplate">保存</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import {ref,onMounted, computed,watch,getCurrentInstance} from "vue"
import Draggable from "vuedraggable"
import MultiHeaders from "./MultiHeaders.vue"
import {useRoute} from "vue-router";
import {useStore} from "vuex";
import {useStorage} from "@vueuse/core";
import {parseTime} from "@/utils/ruoyi";
import {getAnalysisTemplate,saveAnalysisTemplate} from "@/api/common/dataAnalysis";

const route = useRoute()
document.title = '数据分析'
const store = useStore()
const {proxy} = getCurrentInstance()
//全部表头属性
const allProps = ref([
  {
    label: "项目编码",
    prop: "businessNo",
  },
  {
    label: "箱号",
    prop: "caseNum",
  },
  {
    label: "客户",
    prop: "customerName",
  },
  {
    label: "费用类型",
    prop: "feeCodeName",
  },
  {
    label: "提单号",
    prop: "mblNo",
  },
  {
    label: "币种",
    prop: "currencyName",
  },
  {
    label: "数量",
    prop: "num",
  },
  {
    label: "金额",
    prop: "shouldReceipt",
  },
])
//基础表头属性①
const baseProps = ref([])
//多级表头属性③
const multiLevelProps = ref([])
//分组表头属性②
const groupProps = ref([])
//需要分组的数据
const data = ref([])

const multiHeaderValues = computed(() => {
  //获取去重后的multiLevelProps的值
  return multiLevelProps.value.map((item) => {
    return findGroup(item.prop)
  })
})
//选中的模版
const template = ref([])

onMounted(() => {
  queryData()
  getTemplate()
})

let index = ref(0)

watch([()=>groupProps.value,()=>baseProps.value,()=>multiLevelProps.value,()=>template.value],()=>{
  addGroup()
  index.value = 0
},{
  deep:true
})

function addGroup(){
  //获取brr和arr
  getBrr()
  //排序
  // arr.value.forEach(item=>{
  //   data.value.sort(comprisonFunction(item))
  // })
  data.value.sort(comprisonFunction(arr.value[0]))
  brr.value.sort(comprisonFunction(arr.value[0]))

  //对brr去重
  goWeight()

  //分层级合并列
  setTabelRowSpan(brr.value, arr.value);

  //合并baseProps中字段
  mergeValue()
  // console.log(brr.value)
  // console.log(results.value)
  // console.log(baseProps.value)
  // console.log(groupProps.value)
  // console.log(multiHeaderValues.value)
  // console.log(multiLevelProps.value)
  // console.table(brr.value)
}

const brr = ref([])//分组列去重后的数据(groupProps中值的k:v)
const arr = ref([])//要分组的Table属性(groupProps中值的key)
function getBrr(){
  brr.value = []
  arr.value = []
  data.value.forEach((item) => {
    let obj={}
    for (let i = 0; i < groupProps.value.length; i++) {
      let tempObj = {}
      tempObj[groupProps.value[i].prop] = item[groupProps.value[i].prop]
      obj = {...obj,...tempObj}
      if ( arr.value.length < groupProps.value.length){
        arr.value.push(groupProps.value[i].prop)
      }
    }
    brr.value.push(obj)
  })
}

function goWeight(){
  let obj = {};
  let tempArr=brr.value
  brr.value = tempArr.reduce((curr, next) => {
    let str=''
    arr.value.forEach(item=>{
      str+=next[item]
    })
    obj[str] ? '' : obj[str]=curr.push(next);
    return curr;
  }, []);
}

function setTabelRowSpan(tableData, fieldArr){
  let lastItem = {};
  fieldArr.forEach((field, index) => {
    tableData.forEach(item => {
      item.mergeCell = fieldArr;
      const rowSpan = `rowspan_${field}`
      //判断是否合并到上个单元格。
      if(fieldArr.slice(0, index + 1).every(e => lastItem[e] === item[e])){
        //是:合并行
        item[rowSpan] = 0;
        lastItem[rowSpan] += 1;
      }else{
        //否:完成一次同类合并。lastItem重新赋值,进入下一次合并计算。
        item[rowSpan] = 1;
        lastItem = item;
      }
    })
  })
}

function objectSpanMethod({ row, column, rowIndex, columnIndex }) {
  //判断当前单元格是否需要合并
  if (row.mergeCell.includes(column.property)) {
    const rowspan = row[`rowspan_${column.property}`]
    if (rowspan) {
      return {rowspan: rowspan, colspan: 1};
    } else {
      return {rowspan: 0, colspan: 0};
    }
  }
}

function mergeValue(){
  if(multiHeaderValues.value.length>0){
    butes()
  }
  brr.value.forEach(item=>{
    data.value.forEach(temp=>{
      let isTrue = true
      arr.value.forEach(arrTmp=>{
        if (temp[arrTmp]!==item[arrTmp]){
          isTrue = false
        }
      })

      let m_level = ''
      multiLevelProps.value.forEach(mpItem=>{
        m_level = m_level === '' ? temp[mpItem.prop] : m_level+'_'+temp[mpItem.prop]
      })
      if (isTrue){//data中每个元素(即对象)的groupProps属性值相等才会合并
        baseProps.value.forEach(bpItem=>{
          if ((typeof (temp[bpItem.prop])==='number')){//数据类型累加
            if(multiLevelProps.value.length!==0){
              results.value.forEach(rItem=>{

                if(m_level === rItem){
                  if (temp[bpItem.prop]!==''&&temp[bpItem.prop]!==null){
                    if (item[bpItem.prop+"_"+rItem]===undefined){
                      item[bpItem.prop+"_"+rItem]=temp[bpItem.prop]
                    }else {
                      item[bpItem.prop+"_"+rItem]=item[bpItem.prop+"_"+rItem] + temp[bpItem.prop]
                    }
                  }
                }
              })

            }else{
              if (temp[bpItem.prop]!==''&&temp[bpItem.prop]!==null){
                if (item[bpItem.prop]===undefined){
                  item[bpItem.prop]=temp[bpItem.prop]
                }else {
                  item[bpItem.prop]=item[bpItem.prop] + temp[bpItem.prop]
                }
              }
            }
            return
          }
          //字符串类型拼接
          if (temp[bpItem.prop]!==''&&temp[bpItem.prop]!==null){
            if(multiLevelProps.value.length!==0){

              results.value.forEach(rItem=>{

                if(m_level === rItem){
                  if (temp[bpItem.prop]!==''&&temp[bpItem.prop]!==null){
                    if (item[bpItem.prop+"_"+rItem]===undefined){
                      item[bpItem.prop+"_"+rItem]=temp[bpItem.prop]
                    }else {
                      if (!item[bpItem.prop+"_"+rItem].includes(temp[bpItem.prop]))
                        item[bpItem.prop+"_"+rItem]=item[bpItem.prop+"_"+rItem] +','+ temp[bpItem.prop]
                    }
                  }
                }
              })

            }else {
              if (temp[bpItem.prop] !== '' && temp[bpItem.prop] !== null) {
                if (item[bpItem.prop] === undefined) {
                  item[bpItem.prop] = temp[bpItem.prop]
                } else {
                  if (!item[bpItem.prop].includes(temp[bpItem.prop]))
                    item[bpItem.prop] = item[bpItem.prop] + ',' + temp[bpItem.prop]
                }
              }
            }
          }
        })
      }
    })
  })
}

//递归循环数据
let results = ref([])
function butes(){
  const m_len = multiHeaderValues.value.length
  if(m_len>0){
    if(m_len >= 2){
      results.value = recurse(multiHeaderValues.value[index.value],multiHeaderValues.value[++index.value],m_len,multiHeaderValues.value)
    }else{
      results.value = multiHeaderValues.value[0]
    }
    return results.value
  }
}

function recurse(arr1,arr2,len,arr){
  let newArr = []
  arr1.forEach(item=>{
    arr2.forEach(item2=>{
      newArr.push(item+'_'+item2)
    })
  })
  index.value++
  if(index.value < len){
    return recurse(newArr,arr[index.value],len,arr)
  }else{
    return newArr
  }
}

function comprisonFunction (propName) {
  return function (object1, object2) {
    let value1 = object1[propName];
    let value2 = object2[propName];
    if (value1 > value2 ) {
      return -1;
    } else if(value1 < value2) {
      return 1;
    } else {
      return 0;
    }
  }

}

// const obj = ref({})
// const groupArr = ref([])
// function getGroupVal() {
//   obj.value = {}
//   groupArr.value = []
//   for (let i = 0; i < groupProps.value.length; i++) {
//     obj.value[groupProps.value[i].prop + 'Arr'] = [];
//     groupArr.value[i] = []
//     data.value.forEach(item => {
//       if (!obj.value[groupProps.value[i].prop + 'Arr'].includes(item[groupProps.value[i].prop])) {
//         obj.value[groupProps.value[i].prop + 'Arr'].push(item[groupProps.value[i].prop]);
//         let abc = {}
//         abc[groupProps.value[i].prop] = item[groupProps.value[i].prop]
//         // console.log(abc)
//         groupArr.value[i].push(abc)
//       }
//     })
//   }
// }

function findGroup(prop) {
  const set = new Set()
  data.value.forEach(item => {
    set.add(item[prop])
  })
  //去重后再转换成数组
  return Array.from(set)
}

//导出excel时数据表头
function excelHeader(){
  const newArr = []
  results.value.forEach(rItem=>{
    baseProps.value.forEach(item=>{
      let arr = []
      arr.push(item.prop+"_"+rItem)
      newArr.push(arr)
    })
  })
  return newArr
}

function generateArray() {
  const rows = [] //多重表头例如[[1,2,3][4,5]]
  const ranges = [] //合并单元格
  const mainLength = groupProps.value.length
  //所有多重表头(包括最后一行)
  const headers = multiHeaderValues.value.concat([baseProps.value])
  //数据表头
  const mHeader = excelHeader()
  //所有多重表头长度乘积
  const allCols = headers.reduce((res, cur) => {
    return res * cur.length
  }, 1)
  let colspan = allCols // 4 总共需要的单元格
  for (let i = 0; i < headers.length; i++) {
    const curRow = headers[i]
    //需要合并的单元格数量
    colspan = colspan / curRow.length
    //需要重复的次数
    const cycleTime = allCols / colspan / curRow.length
    let row = new Array(mainLength).fill('')
    if (i === headers.length - 1) {
      row = [...groupProps.value]
    }
    for (let k = 0; k < cycleTime; k++) {
      curRow.forEach((val, index) => {
        const C = index * colspan + k * curRow.length * colspan + mainLength
        const range = {s: {r: i, c: C}, e: {r: i, c: C + colspan - 1}}
        if (colspan > 1) ranges.push(range)
        row.push(val)
        for (let j = 1; j < colspan; j++) {
          row.push("")
        }
      })

    }
    rows.push(row)
  }
  // for(let m=0;m<mainLength;m++){
  //   ranges.push(
  //     {
  //       s:{
  //         r:headers.length-1,
  //         c:m
  //       },
  //       e:{
  //         r:0,
  //         c:m
  //       }
  //     }
  //   )
  // }
  return {
    ranges,
    rows,
    mHeader
  }
}

//报表导出
function excelExport() {
  import("@/utils/Export2Excel").then((excel) => {
    // const tHeader = groupProps.value.map((item)=>item.name)
    // const filterVal = groupProps.value.map((item)=>item.prop)
    const {ranges, rows,mHeader} = generateArray()
    const tHeader = rows[rows.length - 1].map((item) => item.label)
    // const filterVal = rows[rows.length - 1].map((item) => item.prop)
    const multiHeader = rows.slice(0, -1)
    const gHeader = groupProps.value.map((item)=>item.prop)
    const filterVal = gHeader.concat(mHeader.map((item)=>item[0]))
    const TData = formatJson(filterVal, brr.value)

    excel.export_json_to_excel({
      header: tHeader,
      multiHeader: multiHeader,
      data: TData,
      filename: "数据分析",
      merges: ranges,
      autoWidth: true,
      bookType: "xlsx",
    })
  })
}

function formatJson(filterVal, jsonData) {
  return jsonData.map((v) =>
      filterVal.map((j) => {
        return v[j]
      })
  )
}
const myOrigin = window.location.origin
function queryData(){
  window.addEventListener('message',function (e) {
    if (e.origin === myOrigin) {
      document.title = e.data.title+'-数据分析'
      if (e.data.isPush) {
        data.value = JSON.parse(e.data.data)
        allProps.value = JSON.parse(e.data.allProps)
        data.value.forEach(item=>{
          //业务类型
          if(item.businessType === 0){
            item.businessType = '海运出口'
          } else if(item.businessType === 1){
            item.businessType = '空运出口'
          } else if(item.businessType === 2){
            item.businessType = '海运进口'
          }
          //单据日期
          if(item.glMarineSpecialOutDTO.id){
            item.expectSailingStartDate = parseTime(item.glMarineSpecialOutDTO.expectSailingStartDate, "{y}-{m}-{d}")
          } else if(item.glMarineImportOutDTO.id){
            item.expectSailingStartDate = parseTime(item.glMarineImportOutDTO.expectSailingStartDate, "{y}-{m}-{d}")
          } else if(item.glAirExportOutDTO.id){
            item.expectSailingStartDate = parseTime(item.glAirExportOutDTO.expectSailingStartDate, "{y}-{m}-{d}")
          }
          //装运日期
          if(item.glMarineSpecialOutDTO.shipmentDate){
            item.shipmentDate = parseTime(item.glMarineSpecialOutDTO.shipmentDate, "{y}-{m}-{d}")
          }
          //送达日期
          if(item.glMarineSpecialOutDTO.deliveryDate){
            item.deliveryDate = parseTime(item.glMarineSpecialOutDTO.deliveryDate, "{y}-{m}-{d}")
          }
          //预计到港日期
          if(item.glMarineSpecialOutDTO.expectSailingArrivalDate){
            item.expectSailingArrivalDate = parseTime(item.glMarineSpecialOutDTO.expectSailingArrivalDate, "{y}-{m}-{d}")
          } else if(item.glMarineImportOutDTO.id){
            item.expectSailingArrivalDate = parseTime(item.glMarineImportOutDTO.expectSailingArrivalDate, "{y}-{m}-{d}")
          } else if(item.glAirExportOutDTO.id){
            item.expectSailingArrivalDate = parseTime(item.glAirExportOutDTO.expectSailingArrivalDate, "{y}-{m}-{d}")
          }
          //预计开航日期
          if(item.glMarineSpecialOutDTO.expectSailingStartDate){
            item.expectSailingStartDate = parseTime(item.glMarineSpecialOutDTO.expectSailingStartDate, "{y}-{m}-{d}")
          } else if(item.glMarineImportOutDTO.id){
            item.expectSailingStartDate = parseTime(item.glMarineImportOutDTO.expectSailingStartDate, "{y}-{m}-{d}")
          } else if(item.glAirExportOutDTO.id){
            item.expectSailingStartDate = parseTime(item.glAirExportOutDTO.expectSailingStartDate, "{y}-{m}-{d}")
          }
        })
        let obj = {
          data:data.value,
          allProps:allProps.value
        }
        useStorage(e.data.tableName,JSON.stringify(obj))
      } else {
        let arr = JSON.parse(useStorage(e.data.tableName).value)
        data.value = arr.data
        allProps.value = arr.allProps
      }
    }
  })
}

//保存模版
//被选中的模版
const templateName = ref('')
const isShowTemplate = ref(false)
const tForm = ref({
  templateName:''
})

//模版弹窗
function setTemplate(){
  isShowTemplate.value = true
}

//所有的模版
const templateList = ref([])

//从数据库中获取当前用户的所有模版数据
function getTemplate(){
  getAnalysisTemplate({
    employeeId: store.state.user.info.id,
    pageNum:1,
    pageSize:100
  }).then(res => {
    templateList.value = res.data.records
  })
}

//将模版数据保存数据库
function saveTemplate(){
  let params = {
    "employeeId": store.state.user.info.id,
    "templateName": tForm.value.templateName,
    "data":JSON.stringify({
      "baseProps":JSON.stringify(baseProps.value),
      "groupProps": JSON.stringify(groupProps.value),
      "multiLevelProps": JSON.stringify(multiLevelProps.value),
      "multiHeaderValues": JSON.stringify(multiHeaderValues.value)
    })
  }
  saveAnalysisTemplate(params).then(response => {
    isShowTemplate.value = false
    getTemplate()
    proxy.$modal.msgSuccess("保存成功");
  })
}

//根据模版获取数据生成数据报表
function templateData(val){
  if(val !== undefined){
    templateList.value.forEach(item=>{
      if(item.id === val){
        template.value = JSON.parse(item.data)
      }
    })
    if(template.value.hasOwnProperty("baseProps")){
      baseProps.value = JSON.parse(template.value.baseProps)
      groupProps.value = JSON.parse(template.value.groupProps)
      multiLevelProps.value = JSON.parse(template.value.multiLevelProps)
      multiHeaderValues.value = JSON.parse(template.value.multiHeaderValues)
    }
  }
}

function clearTemplateData(){
  template.value =[]
  baseProps.value = []
  groupProps.value = []
  multiLevelProps.value = []
  multiHeaderValues.value = []
}

</script>

<style lang="scss" scoped>
.item {
  background: #333;
  padding: 5px;
}

.item-container {
  background: #eee;
  padding: 10px;
  display: flex;
  min-height: 51px;
  align-self: flex-start;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 10px;
  cursor: move;
  color: #ccc;
}

.item-container1 {
  grid-column: 1/3;
}

main {
  display: grid;
  gap: 10px;
  // margin-top: 10px;
  grid-template-columns: 200px 1fr;
}
.operate{
  margin-bottom: 5px;
  .t_select{
    margin-right: 12px;
  }
}
</style>

MultiHeaders.vue

<template>
<!--  <el-table-column v-for="(item,index) in headers" :label="item" >-->
<!--    <MultiHeaders  v-for="item2 in subHeaders"  :multiHeaders="subHeaders" v-if="subHeaders&&subHeaders.length" :baseProps="baseProps" :resultsProps="resultsProps" ></MultiHeaders>-->
<!--    <el-table-column v-else v-for="items in baseProps" :label="items.prop" :prop="items.prop"></el-table-column>-->
<!--  </el-table-column>-->
    <el-table-column v-for="item in headers"  :label="item.name">
      <template v-if="item.child.length>0">
        <multi-header v-if="item.child.length>0" :child="item.child" :baseProps="baseProps" :upProp="item.prop"></multi-header>
      </template>
      <el-table-column v-else v-for="bItem in baseProps" :label="bItem.label" :prop="bItem.prop+'_'+item.prop" ></el-table-column>
    </el-table-column>
</template>

<script setup>
import {computed, watch} from "vue"
import MultiHeader from "@/views/configTable/MultiHeader.vue";
const props = defineProps({
  multiHeaders: { //右边款字段的值=table表头
    typeof: Array,
    default: [],
  },
  baseProps: { // 左上框数据
    typeof: Array,
    default: [],
  },
  upProp: {
    typeof: String,
    default: '',
  },
})
function childData(list,i){
  const arr = []
  //最后一个数组
  if(i<list.length){
    list[i].forEach(item=>{
      const obj = {
        name:'',
        prop:'',
        child:[]
      }
      obj['name'] = item
      obj['prop'] = item
      obj['child'] = []
      arr.push(obj)
    })
  }

  return arr
}
function transListDataToTreeData(list,i) {
  //共3条数据
  const arr = list[i] // 第一层数组 1
  if(arr){
    const news = []
    arr.forEach(item=>{
      let obj = {
        name:item,
        prop:item,
        child:[]
      }
      const child = childData(list,i+1)
      if(child.length > 0){
        obj.child = transListDataToTreeData(list,i+1)

      }else{
        obj.child = child
      }
      news.push(obj)
    })
    return news
  }else{
    return []
  }
}

function sliceArr(arr,size){
  const res = []
  for (let i=0;i<Math.ceil(arr.length/size);i++){
    let start = i*size
    let end = start + size
    res.push(arr.slice(start,end))
  }
  return res
}

const headers = computed(() => {
  // return props.multiHeaders[0]
  return transListDataToTreeData(props.multiHeaders,0)
})
const subHeaders = computed(() => {
  return props.multiHeaders.slice(1)
})
watch(
    () => headers.value,
  (value) => {
    console.log(value)
  }
)
</script>

<style lang="scss" scoped></style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1176535.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电脑监控软件安装教程(30秒钟教会你快速安装)

在现代化办公中&#xff0c;如果有需要安装电脑监控软件的可以参考下面这篇文章&#xff1a; 一、准备阶段 可以自行到官网获取安装包&#xff0c;比如去域之盾官网&#xff0c;即可通过客服获取试用包。 二、操作阶段 1、这个就是安装包&#xff0c;点击运行。 2、这个是正…

Postgresql数据类型-数字类型

PostgreSQL支持的数字类型有整数类型、用户指定精度类型、浮点类型、serial类型。 PostgreSQL支持的数字类型如表所示 smallint、integer、bigint都是整数类型&#xff0c;存储一定范围的整数&#xff0c;超出范围将会报错。smallint存储2字节整数&#xff0c;字段定义时可写成…

大模型使用技巧

目录 1、文心一言&#xff1a;https://yiyan.baidu.com/ 2、智谱清言 ChatGLM&#xff1a;https://chatglm.cn/ 3、百川智能&#xff1a;https://www.baichuan-ai.com/ 4、科大讯飞星火大模型&#xff1a;https://xinghuo.xfyun.cn 5、字节跳动 AI 豆包 https://www.do…

idea2023 PoJie以后无法修改内存无效,heap内存设置

1. 打开电脑环境变量 2. 找到对应pojie文件 vmoptions目录 3. 修改这个文件 添加或者修改配置 -Xms128m -Xmx8192m4. 重启idea 修改成功

史上最全,从初级测试到高级测试开发面试题汇总,冲击大厂年50w+

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 接口测试面试相关…

考研408-计算机网络 第一章-计算机网络体系结构学习笔记及习题

第一章 计算机网络体系结构 一 计算机网络概述 1.1 概念及功能 1.1.1 计算机网络的概念 计算机网络就是互连的、自治的计算机系统的集合 互连&#xff1a;通过通信链路互联互通 自治&#xff1a;各个节点之间无主从关系&#xff0c;高度自治的 1.1.2 计算机网络的功能 功…

通过51单片机控制SG90舵机按角度正反转转动

一、前言 本文介绍如何通过51单片机控制SG90舵机实现角度的正反转转动。SG90舵机是一种常用的微型舵机&#xff0c;具有体积小、重量轻、结构简单等特点&#xff0c;被广泛应用于机器人、遥控模型和各种自动控制系统中。 使用51单片机&#xff08;STC89C52&#xff09;作为控…

公开IP属地信息如何保护用户的隐私?

公开IP属地信息通常涉及与用户或组织的隐私有关&#xff0c;因此在公开此类信息时需要非常小心&#xff0c;以避免侵犯他人的隐私权。以下是触碰底线的几种情况以及如何保护网络安全和用户隐私&#xff1a; 个人隐私保护&#xff1a; 公开IP属地信息可能泄露用户的物理位置&…

5虚拟局域网构建

前面简单介绍了使用交换机连接不同的服务器&#xff0c;这次我们看看怎么搞虚拟局域网。 虚拟局域网&#xff0c;也被称为VLAN&#xff08;Virtual Local Area Network&#xff09;&#xff0c;是一个网络的划分概念&#xff0c;使得一组网络设备可以表现得像在同一个物理网络…

大家都在用的数据安全运维管理系统是哪家?有什么功能?

随着数字化大力发展&#xff0c;越来越多的企业开始重视数据安全&#xff0c;开始采购数据安全运维管理系统。但面对市面上多个品牌的数据安全运维管理系统&#xff0c;企业采购时候往往是蒙圈的。因此不少负责人在问&#xff0c;大家都在用的数据安全运维管理系统是哪家&#…

时间序列预测模型实战案例(八)(Informer)个人数据集、详细参数、代码实战讲解

论文地址->Informer论文地址PDF点击即可阅读 代码地址-> 论文官方代码地址点击即可跳转下载GIthub链接 本文介绍 本篇博客带大家看的是Informer模型进行时间序列预测的实战案例&#xff0c;它是在2019年被提出并在ICLR 2020上被评为Best Paper&#xff0c;可以说Inform…

麒麟操作系统登录双因素认证方案 安当加密

麒麟操作系统安全登录方案可以采取以下几种方式&#xff1a; 账户密码认证&#xff1a;用户登录时需要输入正确的账户和密码&#xff0c;账户和密码是用户登录系统的必要条件。为了保证账户和密码的安全性&#xff0c;可以采用加密算法对密码进行加密存储&#xff0c;并且限制…

CTF工具音频隐写神器MP3stego安装和详细使用方法

音频隐写MP3stego安装和详细使用方法 1.MP3stego介绍&#xff1a;2.MP3stego下载安装&#xff1a;3.MP3stego使用教程&#xff1a;4.MP3stego使用案例&#xff1a;5.MP3stego总结&#xff1a; 1.MP3stego介绍&#xff1a; MP3stego是一个在通用的MP3音频文件中隐写的软件&…

1. Collection,List, Map, Queue

1. java集合框架体系结构图 2. Collection派生的子接口 其中最重要的子接口是&#xff1a; 1&#xff09;List 表示有序可重复列表&#xff0c;重要的实现类有&#xff1a;ArrayList, LinkedList ArrayList特点&#xff1a;底层数组实现&#xff0c;随机查找快&#xff0c;增删…

【FastCAE源码阅读4】VTK OrientationMarkerWidget方向标记组件的使用

FastCAE前处理窗口有个方向指示的组件&#xff0c;会跟踪场景进行旋转&#xff0c;这种设计在很多三维软件都有类似的设计&#xff0c;效果如下图&#xff1a; FastCAE采用的是VTK自带的vtkOrientationMarkerWidget实现的&#xff0c;具体代码如下&#xff1a; void Graph3D…

Springboot在线考试系统 毕业设计-附源码82626

Springboot在线考试系统 摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对在线考试等问题&am…

基于Pytorch框架的LSTM算法(一)——单维度单步滚动预测(2)

#项目说明&#xff1a; 说明&#xff1a;1time_steps滚动预测代码 y_norm scaler.fit_transform(y.reshape(-1, 1)) y_norm torch.FloatTensor(y_norm).view(-1)# 重新预测 window_size 12 future 12 L len(y)首先对模型进行训练&#xff1b; 然后选择所有数据的后wind…

“利用义乌购API揭秘跨境贸易商机:一键获取海量优质商品列表!“

义乌购API可以根据关键词取商品列表。通过调用义乌购API的item_search接口&#xff0c;传入关键词参数&#xff0c;可以获取到符合该关键词的商品列表。 以下是使用义乌购API根据关键词取商品列表的步骤&#xff1a; 注册义乌购开发者账号并获取授权码和密钥。在代码中导入义…

SAP-MM-定义计量单位组

业务场景&#xff1a; 有些物料的计量单位是相同的&#xff0c;为了快速维护物料的计量单位的转换关系&#xff0c;可以创建计量单位组&#xff0c;输入转换关系时&#xff0c;输入组就可以直接转换&#xff0c;不需要单个维护 SPRO-后勤常规-物料主数据-设置关键字段-定义计…

享搭低代码平台:快速构建符合需求的进销存管理系统应用

本文介绍了享搭低代码平台如何赋予用户快速构建进销存管理系统应用的能力。通过在应用商店安装费用进销存管理模板&#xff0c;并通过拖拽方式对模板进行自定义扩充&#xff0c;用户可以快速搭建符合自身需求的进销存管理系统&#xff0c;从而提高管理效率和优化运营。 介绍低代…