当前位置: 首页 > article >正文

vue-ts-demo

 npm i -g @vue/cli

PS D:\kwai\vue3\project> vue create vue3-te-demo

element-plus

一个 Vue 3 UI 框架 | Element Plus

https://element-plus.org/zh-CN/guide/installation.html

安装:

npm install element-plus --save

完整引入使用:

使用:

按需引入使用

首先你需要安装unplugin-vue-components 和 unplugin-auto-import这两款插件

shell

npm install -D unplugin-vue-components unplugin-auto-import

修改vue.config.js中的内容为:

const { defineConfig } = require('@vue/cli-service')
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')

module.exports = defineConfig({
  transpileDependencies: true,
  configureWebpack:{
    plugins: [
      AutoImport({
        resolvers: [ElementPlusResolver()],
      }),
      Components({
        resolvers: [ElementPlusResolver()],
      }),
    ],
  }
})

如果报错:RROR  TypeError: AutoImport is not a function TypeError,则需要降版本:

ERROR TypeError: AutoImport is not a function TypeError: AutoImport is not a-CSDN博客

使用:

重启项目

快速生成模版快捷键

登录页面

表单:

解决外边距塌陷:

css解决外边距塌陷的7种方法_css外边距塌陷-CSDN博客

 内容:

<template>
    <div class="login-box">
        <el-form
        ref="ruleFormRef"
        :model="ruleForm"
        status-icon
        :rules="rules"
        label-width="80px"
        class="demo-ruleForm"
        >
            <h2>后台管理系统</h2>
            <el-form-item label="姓名" prop="name">
            <el-input v-model="ruleForm.name"  type="name" autocomplete="off" />
            </el-form-item>
            <el-form-item label="密码" prop="pass">
            <el-input v-model="ruleForm.pass"  type="password" autocomplete="off" />
            </el-form-item>

            <el-form-item>
            <el-button  class="login-btn" type="primary" @click="submitForm(ruleFormRef)"
                >登录</el-button
            >
            <el-button class="login-btn" @click="resetForm(ruleFormRef)">重置</el-button>
            </el-form-item>
        </el-form>
    </div>
</template>

<script setup lang="ts">
import { reactive, ref } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'

const ruleFormRef = ref<FormInstance>()

const rules = reactive<FormRules>({
  name: [
    {
      required: true,
      trigger: 'blur',
    },
    {
      min: 3,
      max: 5,
      message: 'Length should be 3 to 5',
      trigger: 'blur',
    },
  ],
  pass: [
    {
      required: true,
      trigger: 'blur',
    },
    {
      min: 3,
      max: 5,
      message: 'Length should be 6 to 8',
      trigger: 'blur',
    },
  ]
});



const ruleForm = reactive({
  pass: '',
  name: '',
})


const submitForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return
  formEl.validate((valid) => {
    if (valid) {
      console.log('submit!')
    } else {
      console.log('error submit!')
      return false
    }
  })
}

const resetForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return
  formEl.resetFields()
}
</script>

<style scoped  lang="scss">
    .login-box{
        width: 100%;
        height: 100%;
        background:url("../assets/bg.png");
        padding: 1px;
        text-align: center;
        .demo-ruleForm{
            width: 500px;
            background-color: white;
            margin:100px auto;
            padding: 20px;
            border-radius: 20px;
        }

        .login-btn{
            width: 40%;

        }

        h2{
            margin-bottom: 16px;
        }
    }
</style>

使用ts对数据类型进行限制

新建一个文件夹type用于数据存放

export interface LoginForm{
    pass:string,
    name:string,
}

export class LoginData{
    ruleForm:LoginForm={pass:"",name:""}
}

在之前对pass name的数据定义中,并没有规范类型

在定义类型之后:双向绑定

登录请求

axios中文网|axios API 中文文档 | axios

 npm install axios --save-dev  

新建 request/index.ts    使用index.ts的好处

https://juejin.cn/post/7221004205271646245

index.ts

import axios from "axios";

const mockType = 'cbzMock'  // fastMock
const baseURL = mockType === 'cbzMock' ? 'https://mock.presstime.cn/mock/63569fbbbee0a00099ca48a1/api/vue-ts-mall-demo' : 'https://www.fastmock.site/mock/bf1fcb3c2e2945669c2c8d0ecb8009b8/api'
//创建axios实例
const service = axios.create({
    baseURL: baseURL,
    timeout: 5000,
    headers: {
        "Content-type" : "application/json;charset=utf-8"
    }
})

//请求拦截
service.interceptors.request.use((config) => {
    config.headers = config.headers || {}
    if(localStorage.getItem("token")){
        config.headers.token = localStorage.getItem("token") || ""
    }
    return config
})

//响应拦截
service.interceptors.response.use(({ data }) => {
    const code : number = data.data.code
    if(code != 200){
        return Promise.reject(data)
    }
    return data
},(err) => {
    console.log(err)
})

export default service

api.ts

import service from "@/request/index";
import {LoginData} from "@/type/login";

// 登录接口
export function login(data: LoginData) {
    return service({
        url: "/login",
        method: "POST",
        data
    })
}

// 商品列表接口
export function getGoodsList(){
    return service({
        url: "/getGoodsList",
        method: "GET"
    })
}

// 用户列表接口
export function getUserList(){
    return service({
        url: "/getUserList",
        method: "GET"
    })
}

// 角色列表接口
export function getRoleList(){
    return service({
        url: "/getRoleList",
        method: "GET"
    })
}

// 权限列表接口
export function getAuthorityList(){
    return service({
        url: "/getAuthorityList",
        method: "GET"
    })
}

登录操作

const submitForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return
  formEl.validate((valid) => {
    if (valid) {
      console.log('submit!')
      //假装成功!
      login(ruleForm).then( (res)=>console.log(res) ).catch( (err)=>{ 
        console.log(err)
        //登录成功,切换到主页面
        router.replace({ name:'mainview'});
    }
    
    );
    } else {
      console.log('error submit!')
      return false
    }
  })
}

主页面


 

布局容器

https://element-plus.org/zh-CN/component/container.html

header 

<template>

    <div>
        main view
    </div>
    <div class="common-layout">
    <el-container>
      <el-header>
        <el-row :gutter="20">
            <el-col :span="4">   <img src="../assets/logo.png" alt="" class="icon-logo">  <div class="grid-content ep-bg-purple" /></el-col>
            <el-col :span="16"> <h2 class="title">后台管理系统</h2> <div class="grid-content ep-bg-purple" /></el-col>
            <el-col :span="4"> <span class="quit">退出登录</span>  <div class="grid-content ep-bg-purple" /></el-col>
        </el-row>

      </el-header>
      <el-container>
        <el-aside width="200px">Aside</el-aside>
        <el-main>Main</el-main>
      </el-container>
    </el-container>
  </div>

</template>

<script setup lang="ts">

</script>

<style scoped  lang="scss">
.el-header{
    height: 80px;
    background: #666;
    .icon-logo{
        height: 80px;
    }
    .title ,.quit{
        text-align: center;
        height: 80px;
        line-height: 80px;
    }

}
</style>

 height 和line-height 的设置https://www.cnblogs.com/pwindy/p/13026176.html

实现上下居中的对齐,如果不设置line-height ,。则会居上

Aside

如何实现侧边栏一直到底部:

<template>

    <div>
        main view
    </div>
    <div class="common-layout">
    <el-container>
      <el-header>
        <el-row :gutter="20">
            <el-col :span="4">   <img src="../assets/logo.png" alt="" class="icon-logo">  <div class="grid-content ep-bg-purple" /></el-col>
            <el-col :span="16"> <h2 class="title">后台管理系统</h2> <div class="grid-content ep-bg-purple" /></el-col>
            <el-col :span="4"> <span class="quit">退出登录</span>  <div class="grid-content ep-bg-purple" /></el-col>
        </el-row>

      </el-header>
      <el-container>
        <el-aside width="200px">
            <el-col :span="120">
                <el-menu
                    active-text-color="#ffd04b"
                    background-color="#545c64"
                    class="el-menu-vertical-demo"
                    default-active="2"
                    text-color="#fff"
                >
                    <el-menu-item index="2">
                    <el-icon><icon-menu /></el-icon>
                    <span>商品列表</span>
                    </el-menu-item>
                </el-menu>
            </el-col>
        </el-aside>
        <el-main>Main</el-main>
      </el-container>
    </el-container>
  </div>

</template>

<script setup lang="ts">
import {
  Menu as IconMenu,
  Setting,
} from '@element-plus/icons-vue'
const handleOpen = (key: string, keyPath: string[]) => {
  console.log(key, keyPath)
}
const handleClose = (key: string, keyPath: string[]) => {
  console.log(key, keyPath)
}
</script>

<style scoped  lang="scss">
.el-header{
    height: 80px;
    background: #666;
    .icon-logo{
        height: 80px;
    }
    .title ,.quit{
        text-align: center;
        height: 80px;
        line-height: 80px;
    }
}

.el-aside{
    .el-menu{

        height: calc(100vh - 80px);
    }

}
</style>

可以通过计算:100vh即 100%的垂直视口 - header高度80px

.el-aside{
    .el-menu{

        height: calc(100vh - 80px);
    }

}

动态路由

<template>
    <div class="common-layout">
    <el-container>
      <el-header>
        <el-row :gutter="20">
            <el-col :span="4">   <img src="../assets/logo.png" alt="" class="icon-logo">  <div class="grid-content ep-bg-purple" /></el-col>
            <el-col :span="16"> <h2 class="title">后台管理系统</h2> <div class="grid-content ep-bg-purple" /></el-col>
            <el-col :span="4"> <span class="quit">退出登录</span>  <div class="grid-content ep-bg-purple" /></el-col>
        </el-row>

      </el-header>
      <el-container>
        <el-aside width="120px">
                <el-menu
                    active-text-color="#ffd04b"
                    background-color="#545c64"
                    class="el-menu-vertical-demo"
                    default-active="2"
                    text-color="#fff"
                    router
                >
                <!--router开启路由模式 可以通过标签的index 进行跳转-->
                    <el-menu-item :index="item.path"    v-for="item in subRouterList" :key="item.path">
                    <span>{{item.meta.title}}</span>
                    </el-menu-item>
                </el-menu>
        </el-aside>
        <!--设置路由出口-->
        <el-main>  
            <router-view></router-view>
        </el-main>
      </el-container>
    </el-container>
  </div>

</template>

<script setup lang="ts">
import {
} from '@element-plus/icons-vue'

import { useRouter } from 'vue-router';
const router = useRouter();
const subRouterList = router.getRoutes().filter( v=>
v.meta.isShow)
console.log(subRouterList)

</script>

<style scoped  lang="scss">
.el-header{
    height: 80px;
    background: #666;
    .icon-logo{
        height: 80px;
    }
    .title ,.quit{
        text-align: center;
        height: 80px;
        line-height: 80px;
    }
}

.el-aside{
    .el-menu{
        height: calc(100vh - 80px);
    }
}

</style>

子路由设置:children

import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import GoodsView from '@/views/GoodsView.vue'
import LoginView from '../views/LoginView.vue'
import MainView from '../views/MainView.vue'
import UserView from '@/views/UserView.vue'
const routes: Array<RouteRecordRaw> = [
  {
    path: '/mainview',
    name: 'mainview',
    component: MainView,
    children:[
      {
        path:'goods',
        name:'goods',
        meta:{
          isShow:true,
          title:"商品列表"
        },
        component:GoodsView
      },
      {
        path:'user',
        name:'user',
        meta:{
          isShow:true,
          title:"用户列表"
        },
        component:UserView
      }
    ]
  },
 {
    path: '/login',
    name: 'login',
    component:LoginView
  }
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

export default router

商品页面

搜索

列表

分页展示

列表数据的获取:

数据定义:

export interface Goods{
    id:number,
    userId:number,
    title:string,
    introduce:string,
}

interface SelectData{
    id:number,
    userId:number,
    title:string,
    introduce:string,
    curPage:number,
    count:number,
    pageSize:number,
}

export class GoodsPages{
  // 被选择的数据, 查询时用
  selected_data:SelectData ={        
    userId: 0,
    id: 0,
    title: "",
    introduce: "",
    curPage: 1,
    count: 0,
    pageSize: 10};
  // 展示的商品数据
  goods_list: Goods[] = []
}

数据获取:

<script setup lang="ts">
import { computed, onMounted } from 'vue';
import { getGoodsList } from '@/request/api';
import {GoodsPages } from '@/type/goods';
import { reactive } from 'vue'

//定义数据
const goods_data = reactive(new GoodsPages())

//当前页数据
const curPagaData = reactive(  {
    comList:computed( ()=>{
        return goods_data.goods_list.slice((goods_data.selected_data.curPage-1)*10,goods_data.selected_data.curPage*10);
    })

} )
    
onMounted(  ()=>{
    console.log('onMounted');
     //请求数据
    getGoodsList()
        .then( (res)=>{   
            goods_data.goods_list = res.data.data;
            console.log('goodsList',goods_data.goods_list)     
        })
        .catch( (err)=>{
            console.log(err) 
        })
    }
)


</script>

分页展示逻辑:

<div>
          curPagaData.comList 是列表当前页展示的数据
        <el-table :data=curPagaData.comList border style="width: 100%">
            <el-table-column prop="id" label="id" width="180" />   使用列表中的字段与  每一列标题 
            <el-table-column prop="title" label="title" width="180" />
            <el-table-column prop="introduce" label="introduce" />
        </el-table>

         分页展示
        <el-pagination layout="prev, pager, next" 
        v-model:page-size=goods_data.selected_data.pageSize      页面的大小:设置为10
        v-model:current-page=goods_data.selected_data.curPage     当前是第几页
        :total=goods_data.goods_list.length />   总页数:是请求到的列表的总数
    </div>

查询逻辑

    <div class="select-box">
        <el-form :inline="true" :model="goods_data.selected_data" class="demo-form-inline">
           <el-form-item label="用户Title">
            <el-input v-model="goods_data.selected_data.title" placeholder="用户Title" clearable />
            </el-form-item>  
            <el-form-item>
            <el-button type="primary" @click="onSubmit">查询</el-button>
            </el-form-item>
        </el-form>

    </div>


//查询数据
const onSubmit = () => {
  console.log('submit! suc',goods_data.selected_data.title)
   //如果是空的,则使用原来的数据
   if (goods_data.selected_data.title === ''){
    goods_data.goods_list = last_data;
    goods_data.selected_data.curPage=1;
    return;
   }

  //过滤数据
  let filterArry:Goods[]=[];
  //过滤数据
  filterArry = goods_data.goods_list.filter( (value)=>{
    return value.title.indexOf(goods_data.selected_data.title) !== -1
  } );


  goods_data.goods_list = filterArry;
  goods_data.selected_data.curPage=1;
}



onMounted(  ()=>{
    getGoodsList()
        .then( (res)=>{   
            goods_data.goods_list = res.data.data;
            //记录当前的数据,用于恢复
            last_data = goods_data.goods_list;
            console.log('goodsList',goods_data.goods_list)     
        })
        .catch( (err)=>{
            console.log(err) 
        })
    }
)

用户列表

展示

自定义列模版:展示用户角色

 <template #default="scope">
                <el-text class="mx-1"   v-for="item in scope.row.role"  :key="item.role"> {{item.roleName +" "}}</el-text>         

选择器 

数据定义:

/*
获取用户列表接口 GET  /getUserList
请求报文:无
响应报文:
{
    "data": {
        "code": 200,
        "data": [
            {
                "id": 1,
                "nickName": "小明",
                "userName": "小明",
                "role": [
                    {
                        "role": 1,
                        "roleName": "管理员"
                    },
                    {
                        "role": 2,
                        "roleName": "普通用户"
                    }
                ]
            },
            {
                "id": 2,
                "nickName": "红红",
                "userName": "红红",
                "role": [
                    {
                        "role": 1,
                        "roleName": "管理员"
                    }
                ]
            },
            {
                "id": 3,
                "nickName": "绿绿",
                "userName": "绿绿",
                "role": [
                    {
                        "role": 2,
                        "roleName": "普通用户"
                    }
                ]
            }
        ]
    }
}

获取角色列表接口 GET  /getRoleList
请求报文:无
响应报文:
{
    "data": {
        "code": 200,
        "data": [
            {
                "roleName": "管理员",
                "roleId": 1,
                "authority": [
                    1,
                    2,
                    4,
                    5,
                    6,
                    7,
                    8,
                    9,
                    11,
                    13,
                    14,
                    15,
                    16
                ]
            },
            {
                "roleName": "普通用户",
                "roleId": 2,
                "authority": [
                    1,
                    3,
                    4,
                    6,
                    7,
                    8,
                    9,
                    11,
                    12,
                    13
                ]
            }
        ]
    }
}

*/

interface RoloInfo{
    role:number,
    roleName:string,
}

interface UserInfo{
    id:number,
    nickName:string,
    userName:string
    role:RoloInfo[],
}

interface RoleType{
    roleName:string,
    roleId:number,
    authority:Array<number>[],
}


interface QueryUser{
    nickName: string,  // 用户别名
    role: number  // 角色编号
}

export class UserPage{
    roleList:RoleType[]=[];
    userList:UserInfo[]=[];
    selectedData:QueryUser={nickName:'',role:0}
}

vue:

<template>
    <div class="select-box">
        <el-form :inline="true" :model="userPage.selectedData" class="demo-form-inline">
           <el-form-item label="用户Title">
            <el-input v-model="userPage.selectedData.nickName" placeholder="用户nickName" clearable />
            </el-form-item> 
            <el-form-item label="用户roleid">
                <el-select v-model="userPage.selectedData.role" placeholder="全部" style="width: 240px">
                    <el-option
                        :key="0"
                        label="全部"
                        :value="0"
                    />
                    <el-option
                        v-for="item in userPage.roleList"
                        :key="item.roleId"
                        :label="item.roleName"
                        :value="item.roleId"
                    />
                </el-select>
            </el-form-item>           
            <el-form-item>
            <el-button type="primary" @click="onSubmit">查询</el-button>
            </el-form-item>
        </el-form>

    </div>

    <div>
        <el-table :data=userPage.userList border style="width: 100%">
            <el-table-column prop="id" label="编号" width="180" />
            <el-table-column prop="nickName" label="用户昵称" width="180" />
            <el-table-column prop="role" label="用户角色" >
                <template #default="scope">
                <el-text class="mx-1"   v-for="item in scope.row.role"  :key="item.role"> {{item.roleName +" "}}</el-text>             
 
                </template>
            </el-table-column>
        </el-table>

    </div>
</template>

<script setup lang="ts">
import { getRoleList, getUserList } from '@/request/api';
import { UserInfo, UserPage } from '@/type/userinfo';
import { onMounted, reactive } from 'vue';

const userPage = reactive(new UserPage())
let lastUserList:UserInfo[]=[];

onMounted(()=>{
    getUserList().then(

    (res)=>{
        userPage.userList = res.data.data;
        lastUserList =userPage.userList;
        console.log("userList",userPage.userList);
    }
    )

    getRoleList().then(
        (res)=>{
            userPage.roleList =res.data.data;
            console.log("roleList",userPage.roleList);
        }
    )
})


const onSubmit=()=>{
    console.log('onsubmit',userPage.selectedData.role,userPage.selectedData.nickName);
    if (userPage.selectedData.role===0&& userPage.selectedData.nickName===''){

        userPage.userList = lastUserList;
        return;
    }

    let list:UserInfo[]= userPage.userList.filter(
    (value)=>{
        let found = false;

        if (userPage.selectedData.role===0){
            return value.nickName.indexOf(userPage.selectedData.nickName)!=-1;

        }

        if (userPage.selectedData.nickName===''){
            for(let i=0;i<value.role.length;++i){
                if (value.role[i].role === userPage.selectedData.role){
                    return true;
                }

            }
        }

        if (value.nickName.indexOf(userPage.selectedData.nickName)!=-1){
            for(let i=0;i<value.role.length;++i){
                if (value.role[i].role === userPage.selectedData.role){
                    return true;
                }

            }

        }
        return found;
    }

    );


    userPage.userList = list;
}

</script>

<style scoped>

</style>

编辑

编辑按钮

           <el-table-column prop="role" label="操作" >
                <template #default="scope">
                    <el-button type="primary"  @click="handleEditUser(scope.row)">编辑</el-button>
                </template> 
            </el-table-column>

弹出编辑框


    <!-- 编辑用户的弹出窗-->
  <el-dialog v-model="userPage.editShow" title="编辑用户信息">
    <el-form :model="userPage.editUser">
      <el-form-item label="用户昵称" label-width="120px">
        <el-input v-model="userPage.editUser.nickName" autocomplete="off" />
      </el-form-item>

      <el-form-item label="用户角色" label-width="120px">
        <el-select multiple v-model="userPage.editUser.role" class="m-2" size="large" placeholder="请选择角色">
          <el-option
              v-for="item in userPage.roleList"
              :key="item.roleId"
              :label="item.roleName"
              :value="item.roleId"
          />
        </el-select>
      </el-form-item>

    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="userPage.editShow = false">取消</el-button>
        <el-button type="primary" @click="ensureEditUser">修改</el-button>
      </span>
    </template>
  </el-dialog>

数据结构

// 用户编辑接口
export interface UserEdit {
    id: number,  // 用户id
    nickName: string,  // 用户昵称
    role: number[],   // 用户角色
    userName: string  // 用户名
}


export class UserPage{
    roleList:RoleType[]=[];
    userList:UserInfo[]=[];
    selectedData:QueryUser={nickName:'',role:0}

    editShow = false  // 是否显示编辑用户弹出窗
    // 编辑用户时用到的对象
    editUser: UserEdit = {
        id: 0,
        nickName: "",
        role: [],
        userName: ""
    }
}

// 编辑用户弹窗
const handleEditUser = (row: UserInfo) => {
    userPage.editShow = true
    userPage.editUser = {
        id: row.id,
        nickName: row.nickName,
        role: row.role.map((value) => value.role),
        userName: ""
      }
}

const ensureEditUser = () => {
    console.log(userPage.editUser)
    userPage.editShow = false;
    let obj= userPage.userList.find( (value)=>{ value.id === userPage.editUser.id})


    for(let i=0;i<userPage.userList.length;++i){
        if (userPage.editUser.id === userPage.userList[i].id){
            userPage.userList[i].nickName= userPage.editUser.nickName;
            userPage.userList[i].role =[];
            for(let item of userPage.roleList){
                if (userPage.editUser.role.find( (value)=>( value === item.roleId) )){
                    userPage.userList[i].role.push({
                        role:item.roleId,
                        roleName:item.roleName
                    })
                }
            }
        }
    }

 
   console.log(userPage.userList)  
}

查询

let lastUserList:UserInfo[]=[];
const onSubmit=()=>{
    console.log('onsubmit',userPage.selectedData.role,userPage.selectedData.nickName);
    if (userPage.selectedData.role===0&& userPage.selectedData.nickName===''){

        userPage.userList = lastUserList;
        return;
    }

    let list:UserInfo[]= userPage.userList.filter(
    (value)=>{
        let found = false;

        if (userPage.selectedData.role===0){
            return value.nickName.indexOf(userPage.selectedData.nickName)!=-1;

        }

        if (userPage.selectedData.nickName===''){
            for(let i=0;i<value.role.length;++i){
                if (value.role[i].role === userPage.selectedData.role){
                    return true;
                }

            }
        }

        if (value.nickName.indexOf(userPage.selectedData.nickName)!=-1){
            for(let i=0;i<value.role.length;++i){
                if (value.role[i].role === userPage.selectedData.role){
                    return true;
                }

            }

        }
        return found;
    }

    );


    userPage.userList = list;
}

代码

通过百度网盘分享的文件:src.zip
链接:https://pan.baidu.com/s/1p9YR2W0-DuIZs1_UJwDh6g?pwd=kdhs 
提取码:kdhs


http://www.kler.cn/a/310060.html

相关文章:

  • Linux——基础指令2 + 权限
  • [SWPUCTF 2022 新生赛]Power! 反序列化详细题解
  • 数据分析那些事儿——关于A/B实验
  • 分布式----Ceph部署(上)
  • 鸿蒙next打包流程
  • 解耦与模块化:鸿蒙平台上的服务注册与查找机制
  • 【C-项目】网盘(一期,无限进程版)
  • 什么是数据治理?如何保障数据质量安全
  • 大舍传媒:尼日利亚传统新闻媒体宣传助力新兴行业蓬勃发展
  • 百收SEO蜘蛛池
  • Spring Boot 项目的 pom.xml 中,groupId、artifactId 等信息要如何定义?——定义规则及案例
  • 渗透测试综合靶场 DC-1 通关详解
  • (PySpark)RDD实验实战——求商品销量排行
  • 教师薪酬管理系统的设计与实现
  • Springboot与minio:
  • 《C++魔法:零开销实现抽象工厂模式》
  • LeetCode 滑动窗口 滑动子数组的美丽值
  • Java迭代器Iterator和Iterable有什么区别?
  • 2024 ccpc 网络赛题解
  • SEO之页面优化(一-页面标题2)
  • Java操作数栈分析
  • 【JAVA基础】实现Tomcat基本功能
  • PyQt5-QCheckBox-开关按钮
  • Maven详细介绍
  • 【postgres】笔记
  • 重修设计模式-结构型-适配器模式