用React给XXL-JOB开发一个新皮肤(四):实现用户管理模块
目录
- 一. 简述
- 二. 模块规划
- 2.1. 页面规划
- 2.2. 模型实体定义
- 三. 模块实现
- 3.1. 用户分页搜索
- 3.2. Modal 配置
- 3.3. 创建用户表单
- 3.4. 修改用户表单
- 3.5. 删除
- 四. 结束语
一. 简述
上一篇文章我们实现登录页面和管理页面的 Layout 骨架,并对接登录和登出接口。这篇文章我们将实现用户管理的模块和相应的接口。最后效果如下:

二. 模块规划
在开发之前我们需要对 xxl-job管理系统的用户模块进行规划。
2.1. 页面规划
一般我们都是从前端页面需要使用什么组件;后端接口需要哪些?

前端使用的组件:表格、分页、下拉框、输入框和按钮,就是一个很普通的 CRUD 管理页面,比较简单;接口也是围绕这些功能的:分页查询接口、创建用户接口、编辑用户接口和删除接口。
2.2. 模型实体定义
接着我们需要定义下前后端交互会使用的到的请求和响应实体的定义。
首先是用户分页查询接口的请求和响应:
// UserPageQueryProp 用户分页查询请求参数定义
export interface UserPageQueryProp {page: number; // 页码size: number; // 页大小role: number; // 角色 IDusername?: string; // 用户名称
}// UserTableProp 用户分页查询返回参数定义
export interface UserTableProp {id: number; // 用户IDusername: string; // 用户名称role: number; // 角色permission: string; // 权限
}
这里需要注意的是虽然我们表格中只有用户名和角色名两个显示属性,但是考虑到在编辑的时候需要根据角色显示权限信息,这里在分页查询中返回用户的权限数据。但是如果在一些复杂的分页表格中,不建议这样操作!
接着是用户创建和编辑的请求的定义:
// UserTableProp 用户创建表单属性
export interface UserCreateFormProp {username: string; // 用户名称password: string; // 密码role: number; // 角色permission: string[]; // 权限
}// UserUpdateFormProp 用户创建表单属性
export interface UserUpdateFormProp extends UserCreateFormProp{id: number; // 用户ID
}
三. 模块实现
从这个模块我们可以分为两个大部分和三个小组件组成。

其中功能部分我们可以使用 antd 的Space 中嵌套表单组件实现;表格可以使用 Table 组件(这个组件自带分页功能)实现;最后创建和编辑按钮我们使用 Modal 组件中嵌套 Form 表单组件实现就可以了。下面我们按功能一个个实现这个用户模块。
这里我们在使用
TS这个Buff的使用,大部分使用需要申明类型,尤其在使用不熟悉的UI组件库的时候,大家需要多读文章,多看组件定义文件或者源码。
3.1. 用户分页搜索
上面我们分析我们要使用组件,这里就不赘述了,直接上代码:
import {Button, Divider, Input, Select, Space, Table, Tag} from "antd";
import React, {useEffect, useState} from "react";
import {User} from "@/types";
import {ColumnsType} from "antd/es/table";
import {useRequest} from "ahooks";
import UserApi from "@/api/user.ts";
import {ClearOutlined, PlusOutlined, SearchOutlined} from "@ant-design/icons";const UserPage = () => {// 定义列信息const columns: ColumnsType<User.UserTableProp> = [{title: '账号',key: 'username',dataIndex: 'username',align: 'center'},{title: '角色',key: 'role',dataIndex: 'role',align: 'center',render: (_, record) => record.role == 1 ? <Tag color="#f50">管理员</Tag> : <Tag color="#2db7f5">普通用户</Tag>},{title: '操作',key: 'active',align: 'center',width: 200,render: (_, record) => <Space><Button type="primary" onClick={() => openEdit(record.id)}>编辑</Button><Button type="primary" danger onClick={() => deleteUser(record.id)}>删除</Button></Space>,},]// 总条数const [total, setTotal] = useState<number>(0);const [selectedRowKeys, setSelectedRowKeys] = useState<number[]>([]);// 用户数据const [datasource, setDatasource] = useState<User.UserTableProp[]>([]);// 分页查询属性const [pageQuery, setPageQuery] = useState<User.UserPageQueryProp>(defaultUserPageQuery());return <div><Space><Button type="primary" icon={<PlusOutlined />}>增加用户</Button><Divider type="vertical"/><div>角色:</div><SelectonChange={e => setPageQuery({...pageQuery, role: e})}placeholder="选择状态"defaultValue={-1}style={{width: 100}}options={[{value: -1, label: '全部'},{value: 1, label: '管理员'},{value: 0, label: '普通用户'}]}/><div style={{marginLeft: 20}}>用户名称:</div><InputallowClearplaceholder="请输入搜索的用户名称"value={pageQuery.username}onChange={e => setPageQuery({...pageQuery, username: e.target.value})} /><Button danger type='primary' icon={<ClearOutlined />} onClick={clearSearch}>清空</Button><Button type='primary' icon={<SearchOutlined />} onClick={() => loadUser.run(pageQuery)}>搜索</Button></Space><Tableborderedsize={'small'}columns={columns}loading={loadUser.loading}dataSource={datasource}style={{ marginTop: 10 }}rowKey={(record) => record.id}pagination={{onShowSizeChange: (current, size) => loadUser.run({...pageQuery, page: current, size: size}),onChange: (page, pageSize) => loadUser.run({...pageQuery, page: page, size: pageSize}),showTotal: () => `共 ${total} 个`,showQuickJumper: true,showSizeChanger: true,pageSize: pageQuery.size,current: pageQuery.page,size: 'default',total: total,}}rowSelection={{type: 'checkbox',selectedRowKeys: selectedRowKeys,onChange: (selectedRowKeys: React.Key[]) => {setSelectedRowKeys([...selectedRowKeys.map(item => item as number)])}}}/></div>
}export default UserPage;
这里我们需要注意一下几点:
- 表格每一个行都需要一个
Key,默认是React.Key,但是如果我们需要自定义的时候,可以使用rowKey={(record) => record.id}定义自己的rowKey,这里的record就是定义表格属性模型:User.UserTableProp - 关于分页属性我们可以通过
pagination属性进行设置,可以设置属性和方法可以在分页组件文章中看到 - 最后一点就是关于表格行选中可以通过
rowSelection属性设置;
接下来我们就需要对接分页查询的接口了,首先我们在 api/user.ts 中添加用户分页接口 api 定义:
/*** 用户分页* @param param* @constructor*/
export const UserPage = (param: User.UserPageQueryProp): Promise<PageData<User.UserTableProp>> => {return https.request({url: '/user/pageList',method: 'post',data: param})
}
接着我们看一下如何使用这个api,并且了解下ahooks 中的useRequest中非常好用的地方。
// 加载用户列表
const loadUser = useRequest(UserApi.UserPage, {manual: true, // 手动调用onSuccess: ({records, total}) => { // 成功之后执行的操作setTotal(total);setDatasource(records);}
});
最后我们配合 useEffect使用,加载用户列表的接口会在加载用户管理页面的时候调用这个接口。
useEffect(() => {loadUser.run(pageQuery)
}, [])
这里我们介绍 ahooks 中的 useRequest这个工具 hooks。

支持的功能很多,这里我们现使用这里的 loading 返回值。在我们请求接口的时候如果遇到网络抖动之类的加载缓慢的情况,让表格出现一个加载状态的图标是非常友好了,不然用户也很懵逼。在上面antd 提供了加载属性loading={loadUser.loading}我们只需要将这个值的变化交给 useRequest 就可以,完全不需要我们手动控制。
接下来我们实现上面搜索的功能。

这里一个是下拉框一个是输入框,我们直接使用的是 antd 的组件,我们仅需要实现清空输入和搜索两个按钮事件就可以了。对于清空搜索的点击事件,我们只需要将下拉选项设置为默认值,输入框清空就可以了,代码如下 :
// 清空搜索
const clearSearch = () => {setPageQuery({...pageQuery, role: -1, username: ""})
}
对于搜索我们仅需要手动调用分页接口就可以了,代码如下:
<Button type='primary' icon={<SearchOutlined />} onClick={() => loadUser.run(pageQuery)}
>搜索</Button>
3.2. Modal 配置
这个用户管理的部分需要用到创建用户和编辑用户两个功能,在xxl-job中都是都通过打开弹窗进行操的,我们这里也是使用相同的逻辑。这里我们使用 antd 的 Modal 组件。在使用这个组件的时候我们需要对 Modal 组件的打开和关闭进行一个统一的控制。
// UserCreateModelProp 创建用户弹窗属性
export interface UserCreateModalProp {visible: boolean;close: (isLoad: boolean) => void; // 关闭模态框
}// UserUpdateFormProp 用户更新表单属性
export interface UserUpdateFormProp {id: number; // 用户IDpassword: string; // 密码role: number; // 角色permission: string[]; // 权限
}// 定义模态框的类型
export type ModalType = "create" | "update";// UserModelProp 用户模态框汇总属性
export interface UserModalProp {createVisible: boolean; // 创建用户模态框打开标识updateVisible: boolean; // 编辑用户模态框打开标识userData?: UserTableProp; // 编辑是存放被编辑用户信息
}
接着我们分别定义打开和关闭模态框的事件:
// 关闭模态框
const closeModal = (isLoad: boolean) => {// 在全局只能有一个弹窗打开,所以在关闭的时候把标识变量都设为 false 就可以了setUserModelProp({createVisible: false, updateVisible: false, userData: undefined})if(isLoad) {// 如果创建和编辑成功,我们需要重新加载表格数据显示最新的数据loadUser.run(pageQuery)}
}// 打开模态框
const openModal = (types: User.ModalType, data?: User.UserTableProp) => {switch (types) {case "create":setUserModalProp({createVisible: true, updateVisible: false});break;case "update":setUserModalProp({updateVisible: true, createVisible: false, userData: data});break;default:break}
}
最后我们在创建和编辑按钮上使用这些事件就可以了:
<Button type="primary" icon={<PlusOutlined />} onClick={() => openModal('create')}>增加用户</Button><Button type="primary" onClick={() => openModal('update', record)}>编辑</Button>
接着我们定一个模态框组件,在当前目录下创建 create.tsx和 update.tsx 文件,这两个文件分别是创建用户和编辑用户模态框组件(子组件)。
import {Modal} from "antd";
import React from "react";
import {User} from "@/types";const CreateUserModal: React.FC<User.UserCreateModalProp> = ({visible, close}) => {const submitForm = () => {close(true)}return <Modaltitle="创建用户"open={visible}onOk={submitForm}onCancel={() => close(false)}><h1>创建用户</h1></Modal>
}export default CreateUserModal;
编辑类似不做展示了
这两个子组件设置组件之间的传值问题,我们在User.UserCreateModalProp定义了创建用户模态框组件需要的参数:visible变量和 close函数。最后我们在 index.tsx 中使用这个子组件就可以了。
// 存放模态框状态值
const [userModalProp, setUserModalProp] = useState<User.UserModalProp>({createVisible: false, updateVisible: false});<CreateUserModalkey="create"close={closeModal} // 模态框关闭事件visible={userModalProp.createVisible} // 创建用户模态框打开状态标识变量
/>
效果如下:

3.3. 创建用户表单
这里我们接着实现创建用户表单和表单提交的相关部分,直接上代码:
推荐先看看
antd的Form组件的文章。
import {Checkbox, Divider, Empty, Form, Input, message, Modal, Radio, Row, Spin, Tag} from "antd";
import React, {useEffect, useState} from "react";
import {Group, User} from "@/types";
import {useRequest} from "ahooks";
import {GroupApi, UserApi} from "@/api/index.ts";
import styled from "@emotion/styled";const CreateUserModal: React.FC<User.UserCreateModalProp> = ({visible, close}) => {// 表单const [form] = Form.useForm<User.UserCreateFormProp>();// 监听表单 role 的 valueconst roleValue = Form.useWatch('role', form);// 执行器列表const [groups, setGroups] = useState<Group.JobGroupListProp[]>([]);// 执行器请求const groupLoader = useRequest(GroupApi.GroupLists, {manual: true, onSuccess: (data) => {setGroups(data);}})// 创建用户请求const createLoader = useRequest(UserApi.CreateUser, {manual: true, onSuccess: () => {message.success('创建用户成功')close(true)}});const submitForm = () => {form.validateFields().then(value => {// console.log("submit => ", value)if (value.role == 1) {value.permission = []}createLoader.run(value);})}// 监听 visible 打开关闭标识useEffect(() => {if (visible) { // 当创建用户模态框打开,请求执行器列表接口并设置角色默认值为普通用户groupLoader.run();form.setFieldValue('role', 0)} else {// 关闭模态框的时候,将表单置为空并将执行器列表设置为空数组form.resetFields();setGroups([]);}}, [visible])return <Controllertitle="创建用户"maskClosablewidth={500}open={visible}onOk={submitForm}onCancel={() => close(false)}><Spin tip="加载中......" spinning={createLoader.loading}><Form form={form} layout="vertical" name="form_create_modal"><Form.Item name="username" label="账号" rules={[{ required: true, message: '请输入账号' }]}><Input placeholder="请输入账号" /></Form.Item><Form.Item name="password" label="密码" rules={[{ required: true, message: '请输入密码' }]}><Input.Password placeholder="请输入密码" /></Form.Item><Form.Item name="role" label="角色"><Radio.Group><Radio value={0}>普通用户</Radio><Radio value={1}>管理员</Radio></Radio.Group></Form.Item>{roleValue === 0 && <Form.Item name="permission" label="权限">{groups.length > 0 ? <Checkbox.Group className="xxl-job-list">{groups.map(item =><Row key={item.id}><Checkbox value={item.appName}>{item.title}<Divider type="vertical" /><Tag color="lime">{item.appName}</Tag></Checkbox></Row>)}</Checkbox.Group> : <Empty />}</Form.Item>}</Form></Spin></Controller>
}const Controller = styled(Modal)`.ant-modal-body {padding-top: 24px;.xxl-job-list {flex-direction: column;}}
`export default CreateUserModal;
这里我们通过 Modal 包裹表单组件,使用 useEffect监听 visible属性,当前模态框打开的时候,需要请求执行器列表,并设置角色默认值。
还需要注意的一个点是,当角色是管理员的时候,是不需要选择执行器的,所有在切换角色为管理员的时候,需要将之前选中的执行器清空;所以在最后提交用户数据的时候,设置下执行器就可以了。
const submitForm = () => {form.validateFields().then(value => {if (value.role == 1) { // 当角色是管理员的时候,将执行器权限设置为空数据value.permission = []}createLoader.run(value);})
}
此外我们还通过 styled 修改了 Modal 组件的样式,主要是为了将多选框flex 布局从 row 改为 column。
// 使用 styled 包裹 Modal 组件
const Controller = styled(Modal)`.ant-modal-body {padding-top: 24px;.xxl-job-list {flex-direction: column;}}
`
3.4. 修改用户表单
有了上面创建用户表单部分,我们在修改用户信息的时候,仅需要了解表单初始化的问题了;这里我们也是用使用Form.setFieldsValue方法进行初始化表单,代码代码:
useEffect(() => {if (visible && data) {groupLoader.run();form.setFieldsValue({id: data.id, username: data.username, role: data.role, permission: data.permission})} else {form.resetFields();setGroups([]);}
}, [visible])
这里还有一个不一样的地方是我们会设置一个隐藏的用户主键,方便我们后面执行更新的时候确定要被更新用户信息:
<Controllertitle="更新用户"maskClosablewidth={500}open={visible}onOk={submitForm}onCancel={() => close(false)}><Spin tip="加载中......" spinning={updateLoader.loading}><Form form={form} layout="vertical" name="form_update_modal">// 不显示主键,在我们提交数据的时候会反给form.validateFields().then(value => {})中<Form.Item name="id" label="主键" style={{display: 'none'}}><Input /></Form.Item><Form.Item name="username" label="账号"><Input placeholder="请输入账号" readOnly /></Form.Item><Form.Item name="password" label="密码"><Input.Password placeholder="请输入新密码,为空则不更新密码" /></Form.Item><Form.Item name="role" label="角色"><Radio.Group><Radio value={0}>普通用户</Radio><Radio value={1}>管理员</Radio></Radio.Group></Form.Item>{roleValue === 0 && <Form.Item name="permission" label="权限">{groups.length > 0 ? <Checkbox.Group className="xxl-job-list">{groups.map(item =><Row key={item.id}><Checkbox value={item.appName}>{item.title}<Divider type="vertical" /><Tag color="lime">{item.appName}</Tag></Checkbox></Row>)}</Checkbox.Group> : <Empty />}</Form.Item>}</Form></Spin></Controller>
3.5. 删除
终于快要搞完了,现在我们就剩删除用户这个功能了。针对我们删除来说,一般我都需要弹出一个提示,询问用户是否确定删除这条数据。这里我们可以使用 antd 中的 删除Modal或者气泡提示就可以了。

这里功能简单,只需要调用组件,在其回调方法中调用删除接口就可以了。代码如下:
// 移除用户
const loadRemoveUser = useRequest(UserApi.RemoveUser, {manual: true,onSuccess: () => {loadUser.run(pageQuery);message.success('移除用户成功');}
})// 删除用户
const deleteUser = (id: number) => {Modal.confirm({title: '你确认删除当前用户吗?',icon: <ExclamationCircleFilled />,content: '删除用户会导致无法登录和操作任务',okText: '确认',okType: 'danger',cancelText: '取消',onOk() {loadRemoveUser.run(id)},onCancel() {},});
}
最后在给删除按钮添加点击事件,并将用户的 ID 传给接口。
<Button type="link" danger onClick={() => deleteUser(record.id)}>删除</Button>
四. 结束语
这篇文章我们介绍了如何利用 antd 提供的组件,快速开发一个 CRUD 功能的管理模块,相信大家可以从中收获很多东西了;下一篇文章我们将介绍执行器管理的模块开发。
相关文章:
用React给XXL-JOB开发一个新皮肤(四):实现用户管理模块
目录 一. 简述二. 模块规划 2.1. 页面规划2.2. 模型实体定义 三. 模块实现 3.1. 用户分页搜索3.2. Modal 配置3.3. 创建用户表单3.4. 修改用户表单3.5. 删除 四. 结束语 一. 简述 上一篇文章我们实现登录页面和管理页面的 Layout 骨架,并对接登录和登出接口。这篇…...
某赛通电子文档安全管理系统 hiddenWatermark/uploadFile 文件上传漏洞复现
0x01 产品简介 某赛通电子文档安全管理系统(简称:CDG)是一款电子文档安全加密软件,该系统利用驱动层透明加密技术,通过对电子文档的加密保护,防止内部员工泄密和外部人员非法窃取企业核心重要数据资产,对电子文档进行全生命周期防护,系统具有透明加密、主动加密、智能…...
Redis五种数据类型及应用场景
1、数据类型 String(字符串,整数,浮点数):做简单的键值对缓存 List(列表):储存一些列表类型的数据结构 Hash(哈希):包含键值对的无序散列表,结构化的数据 Set(无序集合):交集,并集…...
测试环境搭建整套大数据系统(一:基础配置,修改hostname,hosts,免密)
一:使用服务器配置。 二:修改服务器名称hostname,hosts。 在 Linux 系统中,hostname 和 /etc/hosts 文件分别用于管理主机名和主机名解析。 在三台服务器上,分别执行以下命令。 vim /etc/hostnamexdso-hadoop-test-0…...
maven helper 解决jar包冲突方法
一 概要说明 1.1 说明 首先,解决idea中jar包冲突,使用maven的插件:maven helper插件,它能够给我们罗列出来同一个jar包的不同版本,以及他们的来源,但是对不同jar包中同名的类没有办法。 1.2 依赖顺序 …...
AppSrv-文件共享(23国赛真题)
2023全国职业院校技能大赛网络系统管理赛项–模块B:服务部署(WindowServer2022) 文章目录 AppSrv-文件共享题目配置步骤创建用户主目录共享文件夹:本地目录为d:\share\users\,允许所有域用户可读可写。在本目录下为所有用户添加一个以名称命名的文件夹,该文件夹将设置为所…...
AsyncLocal是如何实现在Thread直接传值的?
一:背景 1. 讲故事 这个问题的由来是在.NET高级调试训练营第十期分享ThreadStatic底层玩法的时候,有朋友提出了AsyncLocal是如何实现的,虽然做了口头上的表述,但总还是会不具体,所以觉得有必要用文字图表的方式来系统…...
Flask 入门1:一个简单的 Web 程序
1. 关于 Flask Flask诞生于2010年, Armin Ronacher的一个愚人节玩笑。不过现在已经是一个用python语言基于Werkzeug工具箱编写的轻量级web开发框架,它主要面向需求简单,项目周期短的小应用。 Flask本身相当于一个内核,其他几乎所…...
维护管理Harbor,docker容器的重启策略
维护管理Harbor 通过HarborWeb创建项目 在 Harbor 仓库中,任何镜像在被 push 到 regsitry 之前都必须有一个自己所属的项目。 单击“项目”,填写项目名称,项目级别若设置为"私有",则不勾选。如果设置为公共仓库&#…...
Qt6入门教程 14:QToolButton
目录 一.简介 二.常用接口 1.void setMenu(QMenu * menu) 2.void setPopupMode(ToolButtonPopupMode mode) 3.void setToolButtonStyle(Qt::ToolButtonStyle style) 4.void setArrowType(Qt::ArrowType type) 5.void setDefaultAction(QAction * action) 三.实战演练 1…...
3D数据转换器HOOPS Exchange如何获取模型的几何数据? 干货预警!
一、概述 前面讲解过模型在内存中的结构,现在回顾一下,当模型导入成功后,整个模型数据会以原生结构的 PRC 组装树形式存放到内存中。(申请 HOOPS Exchange 试用) PRC结构的主要类型包含四种,分别是…...
Coremail启动鸿蒙原生应用开发,打造全场景邮件办公新体验
1月18日,华为在深圳举行鸿蒙生态千帆启航仪式,Coremail出席仪式并与华为签署鸿蒙合作协议,宣布正式启动鸿蒙原生应用开发。作为首批拥抱鸿蒙的邮件领域伙伴,Coremail的加入标志着鸿蒙生态版图进一步完善。 Coremail是国内自建邮件…...
基于CVITEK_CV1821+SOI_Q03P的IPC方案
方案概述: 该方案基于主控平台CVITEK_CV1821和sensor SOI_Q03P,运用于智能监控IP摄像头,可用于户外或室内。采用了2304x1296的分辨率,30的帧率,支持HDR。作为3M的监控摄像头,通过ISP图像调校技术ÿ…...
chromedriver安装和环境变量配置
chromedriver 1、安装2、【重点】环境变量配置(1)包的复制:(2)系统环境变量配置 3、验证 1、安装 网上随便搜一篇chromedriver的安装文档即可。这里是一个快速链接 特别提醒:截止2024.1.30,chr…...
Linux浅学笔记03
目录 有关root的命令 用户和用户组 用户组管理:(以下需要root用户执行) 创建用户组: 删除用户组: 用户管理:(以下需要root用户执行) 创建用户: 删除用户: 查看用…...
【vue】图片加载骨架
一、前言 在网速较低或者网站的服务器宽带只有几MB的情况下,网页中的图片加载时,要么空白,要么像打印机一样一行一行地“扫描”出来,为了提升用户体验,可以给图片标签外加一层骨架。 无骨架 有骨架 二、详细设计 每张…...
leetcode59. 螺旋矩阵 II
leetcode59. 螺旋矩阵 II 题目 思路 螺旋数组,一次螺旋4个方向(上行从左到右、右列从上到下、下行从右到左、左列从下到上),共执行(n//2)次螺旋。且对于n为奇数时,额外填充中心点nums[mid][mid] n 每一次螺旋圈下来…...
bash 5.2中文修订5
Grouping Commands 命令分组 Bash 提供两种方法将要执行的命令列表分组为一个单元。当命令被分组时,重定向可以应用于整个命令列表。例如,列表中所有命令的输出可以被重定向到单个流。 () 圆括号命令分组 ( list ) 将命令列表放在括号之间会强制 she…...
5GNR解调分析手持式频谱分析仪
2024年已经是5G网络全面普及的一年,手机也基本都升级了5G版本,那么同样的,5G的网络运行也是需要维护的。 我们知道,5G是新型的网络传输技术,如果一般的频谱分析仪是没有办法单独针对5G NR进行解析的。这个时候你就需要…...
互联网加竞赛 基于深度学习的人脸表情识别
文章目录 0 前言1 技术介绍1.1 技术概括1.2 目前表情识别实现技术 2 实现效果3 深度学习表情识别实现过程3.1 网络架构3.2 数据3.3 实现流程3.4 部分实现代码 4 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 基于深度学习的人脸表情识别 该项目较…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...
Caliper 配置文件解析:fisco-bcos.json
config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...
C语言中提供的第三方库之哈希表实现
一. 简介 前面一篇文章简单学习了C语言中第三方库(uthash库)提供对哈希表的操作,文章如下: C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...
Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...
