zdppy + vue3 + antd 实现一个表格编辑行,批量删除功能

编辑单元格和多选的功能

首先是编辑单元格的功能,点击编辑按钮,可以直接在表格中队内容进行编辑,点击保存以后能够同步到数据库。
在这里插入图片描述

其次是多选的功能,点击每行前面的多选框按钮,我们可以选中多行。
在这里插入图片描述
完整后端代码:

import api
import upload
import time
import amcomment
import env
import mcrud
import amuserdetail

save_dir = "uploads"
env.load(".env")
db = mcrud.new_env()

app = api.Api(
    routes=[
        *amcomment.get_routes(db),
        *amuserdetail.get_routes(db),
        upload.download("/download/{filename}", save_dir),
    ],
    middleware=[api.middleware.cors()]
)

if __name__ == "__main__":
    app.run(port=8889)

完整前端代码:

<script setup>
import {cloneDeep} from 'lodash-es';
import {computed, onMounted, reactive, ref} from 'vue';
import axios from "axios";

const columns = [
  {
    name: '姓名',
    dataIndex: 'name',
    id: 'name',
  },
  {
    name: '性别',
    dataIndex: 'gender',
    id: 'gender',
  },
  {
    title: '年龄',
    dataIndex: 'age',
    id: 'age',
  },
  {
    title: '电话',
    dataIndex: 'phone',
    id: 'phone',
  },
  {
    title: '邮箱',
    id: 'email',
    dataIndex: 'email',
  },
  {
    title: '薪资',
    id: 'salary',
    dataIndex: 'salary',
  },
  {
    title: '操作',
    id: 'action',
  },
];

const dataSource = ref([]);

const editableData = reactive({});

const edit = id => {
  editableData[id] = cloneDeep(dataSource.value.filter(item => id === item.id)[0]);
};

const save = id => {

  // backend update
  axios({
    method: "put",
    url: "http://127.0.0.1:8889/zdppy_amuserdetail/" + id,
    contentType: "application/json",
    data: editableData[id],
  }).then(resp => {
    console.log("update", resp.data);
  })

  // frontend update
  Object.assign(dataSource.value.filter(item => id === item.id)[0], editableData[id]);
  delete editableData[id];
};

const cancel = id => {
  delete editableData[id];
};

// handle multi selected
const state = reactive({
  selectedRowKeys: [],
  // Check here to configure the default column
  loading: false,
});

const hasSelected = computed(() => state.selectedRowKeys.length > 0);
const start = () => {
  state.loading = true;
  // ajax request after empty completing
  setTimeout(() => {
    state.loading = false;
    state.selectedRowKeys = [];
  }, 1000);
};

const onSelectChange = selectedRowKeys => {
  console.log('selectedRowKeys changed: ', selectedRowKeys);
  state.selectedRowKeys = selectedRowKeys;
};

onMounted(() => {
  axios({
    method: "get",
    url: "http://127.0.0.1:8889/zdppy_amuserdetail",
  }).then((response) => {
    console.log("response.data", response.data);
    const responseData = response.data.data
    console.log("responseData=", responseData)
    dataSource.value = responseData.results;
  })
})
</script>

<template>
  <div style="margin-bottom: 16px">
    <a-button type="primary" :disabled="!hasSelected" :loading="state.loading" @click="start">
      Reload
    </a-button>
    <span style="margin-left: 8px">
        <template v-if="hasSelected">
          {{ `Selected ${state.selectedRowKeys.length} items` }}
        </template>
      </span>
  </div>


  <a-table
      :columns="columns"
      :data-source="dataSource"
      :row-selection="{ selectedRowKeys: state.selectedRowKeys, onChange: onSelectChange }"
      :row-key="record => record.id"
      bordered>
    <template #headerCell="{ column }">
      <template v-if="column.id === 'name'">
        <span>
          {{ column.name }}
        </span>
      </template>
      <template v-else-if="column.id === 'gender'">
        <span>
          {{ column.name }}
        </span>
      </template>
    </template>

    <template #bodyCell="{ column, text, record }">
      <template v-if="['name', 'age', 'address'].includes(column.dataIndex)">
        <div>
          <a-input
              v-if="editableData[record.id]"
              v-model:value="editableData[record.id][column.dataIndex]"
              style="margin: -5px 0"
          />
          <template v-else>
            {{ text }}
          </template>
        </div>
      </template>

      <template v-else-if="column.id === 'action'">
        <div class="editable-row-operations">
          <span v-if="editableData[record.id]">
            <a-typography-link @click="save(record.id)">保存</a-typography-link>
            <a-popconfirm title="Sure to cancel?" @confirm="cancel(record.id)">
              <a>取消</a>
            </a-popconfirm>
          </span>

          <span v-else>
            <a @click="edit(record.id)">编辑</a>
          </span>
        </div>
      </template>
    </template>
  </a-table>
</template>

<style scoped>
.editable-row-operations a {
  margin-right: 8px;
}
</style>

不过目前有个问题,那就是没有实现批量删除的功能。我们可以在多选以后,点击批量删除按钮,同时删除被选中的数据。

实现前端批量删除的功能

如图:
在这里插入图片描述

选中任意两条数据以后,点击批量删除按钮,这时会弹出确认信息。
点击确认以后会触发一个方法,会在控制台输出需要被删除的数据的ID,是一个数组,用于执行批量删除的操作。

此时的完整前端代码如下:

<script setup>
import {cloneDeep} from 'lodash-es';
import {computed, onMounted, reactive, ref} from 'vue';
import axios from "axios";

const columns = [
  {
    name: '姓名',
    dataIndex: 'name',
    id: 'name',
  },
  {
    name: '性别',
    dataIndex: 'gender',
    id: 'gender',
  },
  {
    title: '年龄',
    dataIndex: 'age',
    id: 'age',
  },
  {
    title: '电话',
    dataIndex: 'phone',
    id: 'phone',
  },
  {
    title: '邮箱',
    id: 'email',
    dataIndex: 'email',
  },
  {
    title: '薪资',
    id: 'salary',
    dataIndex: 'salary',
  },
  {
    title: '操作',
    id: 'action',
  },
];

const dataSource = ref([]);

const editableData = reactive({});

const edit = id => {
  editableData[id] = cloneDeep(dataSource.value.filter(item => id === item.id)[0]);
};

const save = id => {

  // backend update
  axios({
    method: "put",
    url: "http://127.0.0.1:8889/zdppy_amuserdetail/" + id,
    contentType: "application/json",
    data: editableData[id],
  }).then(resp => {
    console.log("update", resp.data);
  })

  // frontend update
  Object.assign(dataSource.value.filter(item => id === item.id)[0], editableData[id]);
  delete editableData[id];
};

const cancel = id => {
  delete editableData[id];
};

// handle multi selected
const state = reactive({
  selectedRowKeys: [],
  // Check here to configure the default column
  loading: false,
});

const hasSelected = computed(() => state.selectedRowKeys.length > 0);
const start = () => {
  state.loading = true;
  // ajax request after empty completing
  setTimeout(() => {
    state.loading = false;
    state.selectedRowKeys = [];
  }, 1000);
};

const onSelectChange = selectedRowKeys => {
  console.log('selectedRowKeys changed: ', selectedRowKeys);
  state.selectedRowKeys = selectedRowKeys;
};

// delete selected data
const onDeleteSelectedClick = () => {
  console.log("onDeleteSelectedClick", state.selectedRowKeys);
}
onMounted(() => {
  axios({
    method: "get",
    url: "http://127.0.0.1:8889/zdppy_amuserdetail",
  }).then((response) => {
    console.log("response.data", response.data);
    const responseData = response.data.data
    console.log("responseData=", responseData)
    dataSource.value = responseData.results;
  })
})
</script>

<template>
  <div class="flex space-x-3 py-3">
    <a-button type="primary" :disabled="!hasSelected" :loading="state.loading" @click="start">
      Reload
    </a-button>
    <a-popconfirm title="您确认要删除选中的数据吗?" @confirm="onDeleteSelectedClick">
      <a-button type="primary" :disabled="!hasSelected" danger>
        批量删除
      </a-button>
    </a-popconfirm>
  </div>


  <a-table
      :columns="columns"
      :data-source="dataSource"
      :row-selection="{ selectedRowKeys: state.selectedRowKeys, onChange: onSelectChange }"
      :row-key="record => record.id"
      bordered>
    <template #headerCell="{ column }">
      <template v-if="column.id === 'name'">
        <span>
          {{ column.name }}
        </span>
      </template>
      <template v-else-if="column.id === 'gender'">
        <span>
          {{ column.name }}
        </span>
      </template>
    </template>

    <template #bodyCell="{ column, text, record }">
      <template v-if="['name', 'age', 'address'].includes(column.dataIndex)">
        <div>
          <a-input
              v-if="editableData[record.id]"
              v-model:value="editableData[record.id][column.dataIndex]"
              style="margin: -5px 0"
          />
          <template v-else>
            {{ text }}
          </template>
        </div>
      </template>

      <template v-else-if="column.id === 'action'">
        <div class="editable-row-operations">
          <span v-if="editableData[record.id]">
            <a-typography-link @click="save(record.id)">保存</a-typography-link>
            <a-popconfirm title="Sure to cancel?" @confirm="cancel(record.id)">
              <a>取消</a>
            </a-popconfirm>
          </span>

          <span v-else>
            <a @click="edit(record.id)">编辑</a>
          </span>
        </div>
      </template>
    </template>
  </a-table>
</template>

<style scoped>
.editable-row-operations a {
  margin-right: 8px;
}
</style>

修改确认提示文本

修改之前:是OK和Cancel
在这里插入图片描述

修改之后:是确认和取消
在这里插入图片描述

核心代码如下:

<a-popconfirm
        title="您确认要删除选中的数据吗?"
        ok-text="确认"
        cancel-text="取消"
        @confirm="onDeleteSelectedClick">
      <a-button type="primary" :disabled="!hasSelected" danger>
        批量删除
      </a-button>
    </a-popconfirm>
```

此时前端的完整代码如下:
```html
<script setup>
import {cloneDeep} from 'lodash-es';
import {computed, onMounted, reactive, ref} from 'vue';
import axios from "axios";

const columns = [
  {
    name: '姓名',
    dataIndex: 'name',
    id: 'name',
  },
  {
    name: '性别',
    dataIndex: 'gender',
    id: 'gender',
  },
  {
    title: '年龄',
    dataIndex: 'age',
    id: 'age',
  },
  {
    title: '电话',
    dataIndex: 'phone',
    id: 'phone',
  },
  {
    title: '邮箱',
    id: 'email',
    dataIndex: 'email',
  },
  {
    title: '薪资',
    id: 'salary',
    dataIndex: 'salary',
  },
  {
    title: '操作',
    id: 'action',
  },
];

const dataSource = ref([]);

const editableData = reactive({});

const edit = id => {
  editableData[id] = cloneDeep(dataSource.value.filter(item => id === item.id)[0]);
};

const save = id => {

  // backend update
  axios({
    method: "put",
    url: "http://127.0.0.1:8889/zdppy_amuserdetail/" + id,
    contentType: "application/json",
    data: editableData[id],
  }).then(resp => {
    console.log("update", resp.data);
  })

  // frontend update
  Object.assign(dataSource.value.filter(item => id === item.id)[0], editableData[id]);
  delete editableData[id];
};

const cancel = id => {
  delete editableData[id];
};

// handle multi selected
const state = reactive({
  selectedRowKeys: [],
  // Check here to configure the default column
  loading: false,
});

const hasSelected = computed(() => state.selectedRowKeys.length > 0);
const start = () => {
  state.loading = true;
  // ajax request after empty completing
  setTimeout(() => {
    state.loading = false;
    state.selectedRowKeys = [];
  }, 1000);
};

const onSelectChange = selectedRowKeys => {
  console.log('selectedRowKeys changed: ', selectedRowKeys);
  state.selectedRowKeys = selectedRowKeys;
};

// delete selected data
const onDeleteSelectedClick = () => {
  console.log("onDeleteSelectedClick", state.selectedRowKeys);
}
onMounted(() => {
  axios({
    method: "get",
    url: "http://127.0.0.1:8889/zdppy_amuserdetail",
  }).then((response) => {
    console.log("response.data", response.data);
    const responseData = response.data.data
    console.log("responseData=", responseData)
    dataSource.value = responseData.results;
  })
})
</script>

<template>
  <div class="flex space-x-3 py-3">
    <a-button type="primary" :disabled="!hasSelected" :loading="state.loading" @click="start">
      Reload
    </a-button>
    <a-popconfirm
        title="您确认要删除选中的数据吗?"
        ok-text="确认"
        cancel-text="取消"
        @confirm="onDeleteSelectedClick">
      <a-button type="primary" :disabled="!hasSelected" danger>
        批量删除
      </a-button>
    </a-popconfirm>
  </div>


  <a-table
      :columns="columns"
      :data-source="dataSource"
      :row-selection="{ selectedRowKeys: state.selectedRowKeys, onChange: onSelectChange }"
      :row-key="record => record.id"
      bordered>
    <template #headerCell="{ column }">
      <template v-if="column.id === 'name'">
        <span>
          {{ column.name }}
        </span>
      </template>
      <template v-else-if="column.id === 'gender'">
        <span>
          {{ column.name }}
        </span>
      </template>
    </template>

    <template #bodyCell="{ column, text, record }">
      <template v-if="['name', 'age', 'address'].includes(column.dataIndex)">
        <div>
          <a-input
              v-if="editableData[record.id]"
              v-model:value="editableData[record.id][column.dataIndex]"
              style="margin: -5px 0"
          />
          <template v-else>
            {{ text }}
          </template>
        </div>
      </template>

      <template v-else-if="column.id === 'action'">
        <div class="editable-row-operations">
          <span v-if="editableData[record.id]">
            <a-typography-link @click="save(record.id)">保存</a-typography-link>
            <a-popconfirm title="Sure to cancel?" @confirm="cancel(record.id)">
              <a>取消</a>
            </a-popconfirm>
          </span>

          <span v-else>
            <a @click="edit(record.id)">编辑</a>
          </span>
        </div>
      </template>
    </template>
  </a-table>
</template>

<style scoped>
.editable-row-operations a {
  margin-right: 8px;
}
</style>

```


## 实现批量删除的功能
后端本身已经有这个接口了,我们只需要在前端调用即可。

核心代码如下:
```js

// delete selected data
const onDeleteSelectedClick = () => {
  console.log("onDeleteSelectedClick", state.selectedRowKeys);
  state.loading = true
  axios({
    method: "delete",
    url: "http://127.0.0.1:8889/zdppy_amuserdetail_ids",
    contentType: "application/json",
    data: {
      ids: state.selectedRowKeys,
    }
  }).finally(() => {
    state.loading = false;
    loadTableData()
  })
}

const loadTableData = () => {
  axios({
    method: "get",
    url: "http://127.0.0.1:8889/zdppy_amuserdetail",
  }).then((response) => {
    console.log("response.data", response.data);
    const responseData = response.data.data
    console.log("responseData=", responseData)
    dataSource.value = responseData.results;
  })
}
onMounted(() => {
  loadTableData()
})
```


此时完整的前端代码如下:
```html
<script setup>
import {cloneDeep} from 'lodash-es';
import {computed, onMounted, reactive, ref} from 'vue';
import axios from "axios";

const columns = [
  {
    name: '姓名',
    dataIndex: 'name',
    id: 'name',
  },
  {
    name: '性别',
    dataIndex: 'gender',
    id: 'gender',
  },
  {
    title: '年龄',
    dataIndex: 'age',
    id: 'age',
  },
  {
    title: '电话',
    dataIndex: 'phone',
    id: 'phone',
  },
  {
    title: '邮箱',
    id: 'email',
    dataIndex: 'email',
  },
  {
    title: '薪资',
    id: 'salary',
    dataIndex: 'salary',
  },
  {
    title: '操作',
    id: 'action',
  },
];

const dataSource = ref([]);

const editableData = reactive({});

const edit = id => {
  editableData[id] = cloneDeep(dataSource.value.filter(item => id === item.id)[0]);
};

const save = id => {

  // backend update
  axios({
    method: "put",
    url: "http://127.0.0.1:8889/zdppy_amuserdetail/" + id,
    contentType: "application/json",
    data: editableData[id],
  }).then(resp => {
    console.log("update", resp.data);
  })

  // frontend update
  Object.assign(dataSource.value.filter(item => id === item.id)[0], editableData[id]);
  delete editableData[id];
};

const cancel = id => {
  delete editableData[id];
};

// handle multi selected
const state = reactive({
  selectedRowKeys: [],
  // Check here to configure the default column
  loading: false,
});

const hasSelected = computed(() => state.selectedRowKeys.length > 0);
const start = () => {
  state.loading = true;
  // ajax request after empty completing
  setTimeout(() => {
    state.loading = false;
    state.selectedRowKeys = [];
  }, 1000);
};

const onSelectChange = selectedRowKeys => {
  console.log('selectedRowKeys changed: ', selectedRowKeys);
  state.selectedRowKeys = selectedRowKeys;
};

// delete selected data
const onDeleteSelectedClick = () => {
  console.log("onDeleteSelectedClick", state.selectedRowKeys);
  state.loading = true
  axios({
    method: "delete",
    url: "http://127.0.0.1:8889/zdppy_amuserdetail_ids",
    contentType: "application/json",
    data: {
      ids: state.selectedRowKeys,
    }
  }).finally(() => {
    state.loading = false;
    loadTableData()
  })
}

const loadTableData = () => {
  axios({
    method: "get",
    url: "http://127.0.0.1:8889/zdppy_amuserdetail",
  }).then((response) => {
    console.log("response.data", response.data);
    const responseData = response.data.data
    console.log("responseData=", responseData)
    dataSource.value = responseData.results;
  })
}
onMounted(() => {
  loadTableData()
})
</script>

<template>
  <div class="flex space-x-3 py-3">
    <a-button type="primary" :disabled="!hasSelected" :loading="state.loading" @click="start">
      Reload
    </a-button>
    <a-popconfirm
        title="您确认要删除选中的数据吗?"
        ok-text="确认"
        cancel-text="取消"
        @confirm="onDeleteSelectedClick">
      <a-button type="primary" :disabled="!hasSelected" danger>
        批量删除
      </a-button>
    </a-popconfirm>
  </div>


  <a-table
      :columns="columns"
      :data-source="dataSource"
      :row-selection="{ selectedRowKeys: state.selectedRowKeys, onChange: onSelectChange }"
      :row-key="record => record.id"
      bordered>
    <template #headerCell="{ column }">
      <template v-if="column.id === 'name'">
        <span>
          {{ column.name }}
        </span>
      </template>
      <template v-else-if="column.id === 'gender'">
        <span>
          {{ column.name }}
        </span>
      </template>
    </template>

    <template #bodyCell="{ column, text, record }">
      <template v-if="['name', 'age', 'address'].includes(column.dataIndex)">
        <div>
          <a-input
              v-if="editableData[record.id]"
              v-model:value="editableData[record.id][column.dataIndex]"
              style="margin: -5px 0"
          />
          <template v-else>
            {{ text }}
          </template>
        </div>
      </template>

      <template v-else-if="column.id === 'action'">
        <div class="editable-row-operations">
          <span v-if="editableData[record.id]">
            <a-typography-link @click="save(record.id)">保存</a-typography-link>
            <a-popconfirm title="Sure to cancel?" @confirm="cancel(record.id)">
              <a>取消</a>
            </a-popconfirm>
          </span>

          <span v-else>
            <a @click="edit(record.id)">编辑</a>
          </span>
        </div>
      </template>
    </template>
  </a-table>
</template>

<style scoped>
.editable-row-operations a {
  margin-right: 8px;
}
</style>

```

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

axios和Mybatis

除了get和post方法还有其他的方法&#xff1a; 发送 PUT 请求 发送 PUT 请求通常用于更新服务器上的资源。 const updateData {title: foo updated,body: bar updated,userId: 1 };axios.put(https://jsonplaceholder.typicode.com/posts/1, updateData).then(function (res…

Camera Raw:编辑 - 配置文件

Camera Raw “编辑”模块中的配置文件 Profile面板为照片编辑提供了一个坚实的基础&#xff0c;能够显著改善照片的初始外观&#xff0c;使编辑过程更加高效和灵活。 使用配置文件&#xff0c;可以控制如何呈现照片中的颜色和色调。配置文件旨在作为照片编辑的起点和基础。 ◆ …

数列结构(3.9)——队列应用

树的层次遍历 树的层次遍历&#xff0c;也称为树的广度优先遍历&#xff0c;是一种按照树的层次顺序&#xff0c;从上到下、从左到右遍历树中所有节点的算法。在二叉树中&#xff0c;这种遍历方式通常使用队列来实现。下面是层次遍历的基本步骤&#xff1a; 创建一个空队列&a…

qemu模拟orangepi

前言 由于qemu目前只支持orange pipc单板&#xff0c;也就是H3型号&#xff0c;故我们就拿这个型号做测试 环境搭建 linux主机环境 我这里采用win10 WSL&#xff0c;且环境用的是openeuler的&#xff0c;在选择服务器类型可以按照自己喜好选择&#xff0c;也就是包安装方式…

【ARMv8/v9 GIC 系列 1.7 -- GIC PPI | SPI | SGI | LPI 中断使能配置介绍】

请阅读【ARM GICv3/v4 实战学习 】 文章目录 GIC 各种中断使能配置PPIs(每个处理器私有中断)SPIs(共享外设中断)SGIs(软件生成的中断)LPIs(局部中断)GIC 各种中断使能配置 在ARM GICv3和GICv4架构中,不同类型的中断(如PPIs、SPIs、SGIs和LPIs)可以通过不同的方式进…

SUSAN

1995年英国牛津大学的S.M.Smith提出了一种新的图像边缘检测算法SUSAN算法,不同于以前经典边缘检测算法,SUSAN算法基于灰度相似性比较,采用圆形模板,对图像进行灰度差统计,无需计算方向导数,而且具备积分特性,它简单而且有效,适用于图像中边缘和角点的检测,可以去除图像…

【Unity】简单举例UI合批,优化draw call

1. UGUI-Editor 首先引入UGUI-Editor插件 链接: https://pan.baidu.com/s/1PpxStvgRCDi9xjUr6j6nCQ?pwdm5ju 提取码: m5ju 或者直接去Github搜索UGUI-Editor 2. 没有UI时 3. 放几个UI看看效果 4. 选中Canvas&#xff0c;右键优化Batch 发现减少了3个&#xff0c;这是因为&…

玉石风能否接棒黏土风?一探AI绘画新风尚

在数字艺术的浪潮中,AI绘画平台以其独特的创造力和便捷性,正在逐步改变我们对艺术的传统认知。从黏土风的温暖质感到琉璃玉石的细腻光泽,每一次风格的转变都引领着新的潮流。今天,我们将聚焦玉石风,探讨它是否能成为下一个流行的艺术滤镜,并提供一种在线体验的方式,让你…

昇思25天学习打卡营第13天 | ShuffleNet图像分类

ShuffleNet网络介绍 ShuffleNetV1是旷视科技提出的一种计算高效的CNN模型&#xff0c;和MobileNet, SqueezeNet等一样主要应用在移动端&#xff0c;所以模型的设计目标就是利用有限的计算资源来达到最好的模型精度。ShuffleNetV1的设计核心是引入了两种操作&#xff1a;Pointw…

Spring AOP实现操作日志记录示例

1. 准备工作 项目环境&#xff1a;jdk8springboot2.6.13mysql8 1.1 MySQL表 /*Navicat Premium Data TransferSource Server : localhostSource Server Type : MySQLSource Server Version : 50730Source Host : 127.0.0.1:3306Source Schema …

通过IDEA生成webapp及web.xml配置文件

1、选择File->Project Structure 2、选择Modules-> + -> Web 有的springboot工程选择是war工程,这个web可能已经存在了。 如果不存在,就手动创建,创建后,需要修改pom.xml中的配置 <packaging>war</packaging> 3、创建webapp根目录 这步重点就是创建…

ARM架构以及程序运行解析

文章目录 1. ARM架构 2. ARM处理器程序运行的过程 3. 示例 3. 基于ARM架构的STM32单片机 1. 运行模式 2. 寄存器组 3. STM32的基本结构 4. STM32的运行模式 4. 寄存器组详解 1. 未备份寄存器 2. 备份寄存器 3. 程序计数器 4. 程序状态寄存器 5. CPSR和SPSR寄存器…

运维Tips | Ubuntu 24.04 安装配置 xrdp 远程桌面服务

[ 知识是人生的灯塔&#xff0c;只有不断学习&#xff0c;才能照亮前行的道路 ] Ubuntu 24.04 Desktop 安装配置 xrdp 远程桌面服务 描述&#xff1a;Xrdp是一个微软远程桌面协议&#xff08;RDP&#xff09;的开源实现&#xff0c;它允许我们通过图形界面控制远程系统。这里使…

Banana Pi BPI-M5 Pro 低调 SBC 采用 Rockchip RK3576 八核 Cortex-A72/A53 AIoT SoC

Banana Pi BPI-M5 Pro&#xff0c;也称为 Armsom Sige5&#xff0c;是一款面向 AIoT 市场的低调单板计算机 (SBC)&#xff0c;由 Rockchip RK3576 八核 Cortex-A72/A53 SoC 驱动&#xff0c;提供Rockchip RK3588和RK3399 SoC 之间的中档产品。 该主板默认配备 16GB LPDDR4X 和…

学习笔记——动态路由——OSPF(特殊区域)

十、OSPF特殊区域 1、技术背景 早期路由器靠CPU计算转发&#xff0c;由于硬件技术限制问题&#xff0c;因此资源不是特别充足&#xff0c;因此是要节省资源使用&#xff0c;规划是非常必要的。 OSPF路由器需要同时维护域内路由、域间路由、外部路由信息数据库。当网络规模不…

NAT:地址转换技术

为什么会引入NAT&#xff1f; NAT&#xff08;网络地址转换&#xff09;的引入主要是为了解决两个问题 IPv4地址短缺&#xff1a;互联网快速发展&#xff0c;可用的公网IP地址越来越少。网络安全&#xff1a;需要一种方法来保护内部网络不被直接暴露在互联网上。 IPv4 &…

人脸检测(Python)

目录 环境&#xff1a; 初始化摄像头&#xff1a; 初始化FaceDetector对象&#xff1a; 获取摄像头帧&#xff1a; 获取数据&#xff1a; 绘制数据&#xff1a; 显示图像&#xff1a; 完整代码&#xff1a; 环境&#xff1a; cvzone库&#xff1a;cvzone是一个基于…

RAG实践:ES混合搜索BM25+kNN(cosine)

1 缘起 最近在研究与应用混合搜索&#xff0c; 存储介质为ES&#xff0c;ES作为大佬牌数据库&#xff0c; 非常友好地支持关键词检索和向量检索&#xff0c; 当然&#xff0c;支持混合检索&#xff08;关键词检索向量检索&#xff09;&#xff0c; 是提升LLM响应质量RAG(Retri…

spring boot(学习笔记第十二课)

spring boot(学习笔记第十二课) Spring Security内存认证&#xff0c;自定义认证表单 学习内容&#xff1a; Spring Security内存认证自定义认证表单 1. Spring Security内存认证 首先开始最简单的模式&#xff0c;内存认证。 加入spring security的依赖。<dependency>…

【TB作品】51单片机 Proteus仿真 MAX7219点阵驱动数码管驱动

1、8乘8点阵模块&#xff08;爱心&#xff09; 数码管测试程序与仿真 实验报告: MAX7219 数码管驱动测试 一、实验目的 通过对 MAX7219 芯片的编程与控制&#xff0c;了解如何使用单片机驱动数码管显示数字&#xff0c;并掌握 SPI 通信协议的基本应用。 二、实验器材 51…