0802api設計和實戰-網絡ajax請求1-react-仿低代碼平臺項目

文章目錄

    • 1 API設計
      • 1.1 用戶功能
        • 1.1.1 獲取用戶信息
        • 1.1.2 注冊
        • 1.1.3 登錄
      • 1.2 問卷功能
        • 1.2.1 獲取單個問卷
        • 1.2.2 獲取問卷列表
        • 1.2.3 創建問卷
        • 1.2.4 更新問卷
        • 1.2.5 批量徹底刪除問卷
        • 1.2.6 復制問卷
      • 1.3 小結
    • 2 實戰
      • 2.1配置axios
      • 2.2 封裝API和測試
      • 2.3 新建問卷
      • 2.4 自定義hooks封裝獲取問卷信息
      • 2.5 使用useRequest重構Ajax請求-統一處理
      • 2.6 開發問卷列表
      • 2.7 第三方hook抽離搜索功能
      • 2.8 開發星標和回收站
    • 結語

1 API設計

1.1 用戶功能

1.1.1 獲取用戶信息
  • method: get
  • path: /api/user/info
  • response:
    • 成功:{errno: 0, data{...}}
    • 失敗:{errno: 10001, mes: 'xxx'}
1.1.2 注冊
  • method: post

  • path: /api/user/register

  • request body: {username, password, nickname}

  • response: {errno: 0}

1.1.3 登錄
  • method: post
  • path: /api/user/login
  • request body: {username, password}
  • response: {errno: 0, token}
    • Token令牌:使用jwt

1.2 問卷功能

1.2.1 獲取單個問卷
  • method: get
  • path: /api/question/:id
  • response: {errno: 0, data: {id, title,...}}
1.2.2 獲取問卷列表
  • method: get
  • path: /api/question/
  • response: {errno: 0, data:{list:[{...}}
1.2.3 創建問卷
  • method: post
  • path: /api/question
  • request body: 暫無
  • response: {errno: 0, data: {id}}
1.2.4 更新問卷
  • method: patch
  • path: /api/question/:id
  • response: {errno: 0}

tips:刪除是“假刪除”,實際 是更新isDeleted屬性

1.2.5 批量徹底刪除問卷
  • method: delete
  • path: /api/question
  • request body: {ids: [...]}
  • response: {errno: 0}
1.2.6 復制問卷
  • method: post
  • path: `/api/question/duplicate/:id``
  • response: {errno: 0, data: {id}}

1.3 小結

  • 使用Restful API
  • 用戶驗證使用JWT
  • 統一返回格式:{errno, data, msg}

2 實戰

2.1配置axios

src/services/request.ts基礎代碼如下:

import axios from "axios";const request = axios.create({timeout: 5000,
});export default request;

添加返回類型和統一錯誤出來,request.ts代碼如下:

import axios from "axios";
import { message } from "antd";const request = axios.create({timeout: 5000,
});// response 攔截:統一處理errno和msg
request.interceptors.response.use(res => {const resData = (res.data || {}) as ResTypeconst {errno, data, msg} = resDataif (errno !== 0) {// 錯誤提示if (msg) {message.error(msg)}throw new Error(msg);}return data as any}
)
export default request;export type ResDataType = {[key: string]: any;
};export type ResType = {errno: number;data?: ResDataType;msg?: string;
};

2.2 封裝API和測試

獲取問卷信息API,src/api/question.ts代碼如下:

import request, { ResDataType } from "../services/request";export async function getQuestionApi(id: string): Promise<ResDataType> {const url = `/api/question/${id}`;const data = (await request.get(url)) as ResDataType;return data;
}

src/pages/quesiton/Edit/index.tsx代碼如下:

import { FC, useEffect} from "react";
import { useParams } from "react-router-dom";
import { getQuestionApi } from "@/api/question";const Edit: FC = () => {const { id = "" } = useParams();// 獲取問卷信息useEffect(()=> {async function fn() {const resData = await getQuestionApi(id)console.log(resData);}fn()}, [])return <div>Edit {id}</div>;
};export default Edit;

測試結果如下圖所示:在這里插入圖片描述

2.3 新建問卷

封裝新建問卷API,question.ts代碼如下:

import request, { ResDataType } from "../services/request";.../*** 新建問卷* @returns 問卷id*/
export async function createQuestionApi() {const url = `/api/question`;const data = (await request.post(url)) as ResDataType;return data;
}

ManageLayout.tsx中調用新建問卷,src/layouts/MangeLayout.tsx代碼如下:

import { FC, useState } from "react";
import { Outlet, useNavigate, useLocation } from "react-router-dom";
import {PlusOutlined,BarsOutlined,StarOutlined,DeleteOutlined,
} from "@ant-design/icons";
import { Button, Space, Divider, message } from "antd";import { createQuestionApi } from "@/api/question";
import styles from "./ManageLayout.module.scss";const ManageLayout: FC = () => {const nav = useNavigate();const { pathname } = useLocation();const [loading, setLoading] = useState(false)// 點擊創建問卷async function handleCreateClick() {setLoading(true)const data = await  createQuestionApi()const {id} = data || {}if (id) {nav(`/question/edit/${id}`)message.success("創建成功")}setLoading(false)}return (<div className={styles.container}><div className={styles.left}><Space direction="vertical"><Buttontype="primary"size="large"icon={<PlusOutlined />}onClick={handleCreateClick}disabled={loading}>新建問卷</Button>...);
};export default ManageLayout;

tips:接口請求有延遲,防止用戶連續點擊按鈕,觸發重復操作,這里添加loading控制按鈕,后續可以用封裝好的“防抖”操作替換。

2.4 自定義hooks封裝獲取問卷信息

在編輯頁和統計頁都需要獲取帶加載狀態的問卷信息,這里我們通過自定義hooks抽取公共部分,src/hooks/useLoadQuestionData.ts代碼如下:

import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";import { getQuestionApi } from "@/api/question";/*** 獲取帶加載狀態的問卷信息* @returns loading狀態,問卷信息*/
function useLoadQuestionData() {const { id = "" } = useParams();const [loading, setLoading] = useState(true);const [questionData, setQuestionData] = useState({});useEffect(() => {async function fn() {const data = await getQuestionApi(id);setQuestionData(data);setLoading(false);}fn();}, []);return { loading, questionData };
}export default useLoadQuestionData;

編輯頁src/pages/question/Edit/index.tsx代碼改造如下:

import { FC } from "react";
import useLoadQuestionData from "@/hooks/useLoadQuestionData";const Edit: FC = () => {// 獲取問卷信息const { loading, questionData } = useLoadQuestionData();return (<div><p>Edit page</p><div>{loading ? <p>loading</p> : <p>{JSON.stringify(questionData)}</p>}</div></div>);
};export default Edit;

2.5 使用useRequest重構Ajax請求-統一處理

第三方ahooks-useRequst 當前功能有:

  • 自動/手動請求
  • 輪詢
  • 防抖
  • 節流
  • 窗口聚焦刷新
  • 錯誤重試
  • 加載延遲
  • SWR(stale-while-revalidate)
  • 緩存

由于接口請求,每次都需要定義loading,data,使用useEffect執行函數,很繁瑣,這里我們使用第三方ahooks提供的useRequest簡化。

改造自定義hook-useLoadQuestionData,useLoadQuestionData.ts代碼如下:

import { useParams } from "react-router-dom";
import { useRequest } from "ahooks";
import { getQuestionApi } from "@/api/question";/*** 獲取帶加載狀態的問卷信息* @returns loading狀態,問卷信息*/
function useLoadQuestionData() {const { id = "" } = useParams();async function load() {const data = await getQuestionApi(id);return data;}const { loading, data, error } = useRequest(load);return { loading, data, error };
}export default useLoadQuestionData;

改造創建問卷,ManageLayout.tsx代碼如下:

import { FC, useState } from "react";
import { Outlet, useNavigate, useLocation } from "react-router-dom";
import {PlusOutlined,BarsOutlined,StarOutlined,DeleteOutlined,
} from "@ant-design/icons";
import { Button, Space, Divider, message } from "antd";import { createQuestionApi } from "@/api/question";
import styles from "./ManageLayout.module.scss";
import { useRequest } from "ahooks";const ManageLayout: FC = () => {const nav = useNavigate();const { pathname } = useLocation();// 點擊創建問卷const {loading,// error,run: handleCreateClick,} = useRequest(createQuestionApi, {manual: true,onSuccess: (res) => {nav(`/question/edit/${res.id}`);message.success("創建成功");},});return (<div className={styles.container}><div className={styles.left}><Space direction="vertical"><Buttontype="primary"size="large"icon={<PlusOutlined />}onClick={handleCreateClick}disabled={loading}>新建問卷</Button>
...
};export default ManageLayout;

2.6 開發問卷列表

獲取問卷列表mock接口 getQuestionList.js代碼如下:

const Mock = require('mockjs');
const Random = Mock.Random;function getQuestionList(len = 10, isDeleted = false) {const list = [];for (let i = 0; i < len; i++) {list.push({_id: Random.id(),title: Random.ctitle(),isPublished: Random.boolean(),isStar: Random.boolean(),answerCount: Random.natural(50, 100),createdAt: Random.datetime(),isDeleted})}return list;
}module.exports = getQuestionList;

question.js代碼如下:

const Mock = require('mockjs')const getQuestionList = require("./data/getQuestionList")const Random = Mock.Randommodule.exports = [
...{// 獲取問卷列表url: '/api/question',method: 'get',response() {return {errno: 0,data: {list: getQuestionList(),total: 100}}}},
]

question.ts api代碼如下所示:

/*** 獲取問卷列表* @returns 問卷列表數據*/
export async function getQuestionListApi() {const url = `/api/question`;const data = (await request.get(url)) as ResDataType;return data;
}

List.tsx調用接口代碼如下所示:

import { FC } from "react";
// import { useSearchParams } from "react-router-dom";
import { useRequest, useTitle } from "ahooks";
import { Typography, Spin, Divider } from "antd";import QuestionCard from "@/components/QuestionCard";
import ListSearch from "@/components/ListSearch";
import { getQuestionListApi } from "@/api/question";
import styles from "./common.module.scss";const { Title } = Typography;const List: FC = () => {useTitle("調查問卷-我的問卷");// const [searchParams] = useSearchParams();// console.log("keyword", searchParams.get("keyword"));//問卷列表數據const { data = {}, loading } = useRequest(getQuestionListApi);const { list = [], total = 0 } = data;return (<><div className={styles.header}><div className={styles.left}><Title level={3}>我的問卷</Title></div><div className={styles.right}><ListSearch /></div></div><div className={styles.content}>{loading && (<div style={{ textAlign: "center" }}><Spin /></div>)}{!loading &&list.length > 0 &&list.map((q: any) => {const { _id } = q;return <QuestionCard key={_id} {...q} />;})}</div><div className={styles.footer}>loadingMore 上劃加載更多</div></>);
};export default List;

2.7 第三方hook抽離搜索功能

在我的問卷、星標問卷和回收站都有搜索功能,有相同的邏輯,這里我們通過自定義hook抽離公共邏輯。自定義搜索hook-useLoadQuestionListData.ts代碼如下所示:

import { useSearchParams } from "react-router-dom";
import { useRequest } from "ahooks";
import { getQuestionListApi } from "@/api/question";import { LIST_SEARCH_PARAM_KEY } from "@/constant";/*** 獲取問卷列表* @returns 問卷列表*/
function useLoadQuestionListData() {const [searchParams] = useSearchParams();const keyword = searchParams.get(LIST_SEARCH_PARAM_KEY) || "";async function load() {const data = await getQuestionListApi({ keyword });return data;}const { loading, data, error } = useRequest(load, {refreshDeps: [searchParams],});return { loading, data, error };
}export default useLoadQuestionListData;

getQuestionListApi.ts如下所示:

import request, { ResDataType } from "../services/request";type SearchOption = {keyword: string;
};.../*** 獲取問卷列表* @param opt 請求參數* @returns 問卷列表數據*/
export async function getQuestionListApi(opt: Partial<SearchOption>
): Promise<ResDataType> {const url = `/api/question`;const data = (await request.get(url, {params: opt})) as ResDataType;return data;
}

說明

  • refreshDeps: useRequest 刷新依賴項,根據數組里面的變量重新執行useRequest
  • request.get(url, {params: opt})),params axios get請求傳遞參數,形式:url?a=b&b=1…

2.8 開發星標和回收站

星標問卷查詢的數據 isStar=true;回收站查詢的問卷列表isDeleted=true,我們需要擴展api接口參數。

useLoadQuestionListData.ts代碼改造如下:

import { useSearchParams } from "react-router-dom";
import { useRequest } from "ahooks";
import { getQuestionListApi } from "@/api/question";import { LIST_SEARCH_PARAM_KEY } from "@/constant";type OptionType = {isStar: boolean;isDeleted: boolean;
};/*** 獲取問卷列表* @returns 問卷列表*/
function useLoadQuestionListData(opt: Partial<OptionType>) {const { isStar, isDeleted } = opt;const [searchParams] = useSearchParams();const keyword = searchParams.get(LIST_SEARCH_PARAM_KEY) || "";async function load() {const data = await getQuestionListApi({ keyword, isStar, isDeleted });return data;}const { loading, data, error } = useRequest(load, {refreshDeps: [searchParams],});return { loading, data, error };
}export default useLoadQuestionListData;

星標問卷-Star.tsx代碼如下所示:

import { FC } from "react";
import { useTitle } from "ahooks";
import { Typography, Empty, Spin } from "antd";import QuestionCard from "@/components/QuestionCard";
import ListSearch from "@/components/ListSearch";
import styles from "./common.module.scss";
import useLoadQuestionListData from "@/hooks/useLoadQuestionListData";const { Title } = Typography;const List: FC = () => {useTitle("調查問卷-星標問卷");//問卷列表數據const { data = {}, loading } = useLoadQuestionListData({ isStar: true });const { list = [], total = 0 } = data;return (<><div className={styles.header}><div className={styles.left}><Title level={3}>星標問卷</Title></div><div className={styles.right}><ListSearch /></div></div><div className={styles.content}>{loading && (<div style={{ textAlign: "center" }}><Spin /></div>)}{!loading && list.length === 0 && <Empty description="暫無數據" />}{!loading &&list.length > 0 &&list.map((q: any) => {const { _id } = q;return <QuestionCard key={_id} {...q} />;})}</div><div className={styles.footer}>分頁</div></>);
};export default List;

回收站-Trash.tsx代碼如下所示;

import { FC, useState } from "react";
import { useTitle } from "ahooks";
import {Typography,Empty,Table,Tag,Space,Button,Modal,message,Spin,
} from "antd";import { ExclamationCircleOutlined } from "@ant-design/icons";
import ListSearch from "../../components/ListSearch";
import styles from "./common.module.scss";
import useLoadQuestionListData from "@/hooks/useLoadQuestionListData";const { Title } = Typography;
const { confirm } = Modal;const List: FC = () => {useTitle("調查問卷-回收站");//問卷列表數據const { data = {}, loading } = useLoadQuestionListData({ isDeleted: true });const { list = [], total = 0 } = data;const columns = [{title: "標題",dataIndex: "title",},{title: "是否發布",dataIndex: "isPublished",render: (isPublished: boolean) =>isPublished ? <Tag color="processing">已發布</Tag> : <Tag>未發布</Tag>,},{title: "答卷",dataIndex: "answerCount",},{title: "創建時間",dataIndex: "createdAt",},];// 選擇ids集合const [selectedIds, setSelectedIds] = useState<string[]>([]);function del() {confirm({title: "您確定要刪除嗎?",okText: "確定",cancelText: "取消",content: "刪除以后不可找回!",icon: <ExclamationCircleOutlined />,onOk: () => message.success("刪除成功"),});}const TableEle = (<><div style={{ marginBottom: "10px" }}><Space><Button type="primary" disabled={selectedIds.length === 0}>恢復</Button><Button danger disabled={selectedIds.length === 0} onClick={del}>徹底刪除</Button></Space></div><TabledataSource={list}columns={columns}pagination={false}rowKey={(q: any) => q._id}rowSelection={{type: "checkbox",onChange: (selectRowKeys) => {setSelectedIds(selectRowKeys as string[]);},}}></Table></>);return (<><div className={styles.header}><div className={styles.left}><Title level={3}>回收站</Title></div><div className={styles.right}><ListSearch /></div></div><div className={styles.content}>{loading && (<div style={{ textAlign: "center" }}><Spin /></div>)}{!loading && list.length === 0 && <Empty description="暫無數據" />}{TableEle}</div><div className={styles.footer}>分頁</div></>);
};export default List;

服務端星標問卷查詢返回的isStar=true;回收站返回的isDeleted=true

index.js代碼如下所示:

...async function getRes(fn, ctx) {return new Promise(resolve => {setTimeout(() => {const res = fn(ctx)resolve(res)}, 500);})
}// 注冊mock路由
mockList.forEach(item => {const {url, method, response} = itemrouter[method](url, async ctx => {const res = await getRes(response, ctx)ctx.body = res})
})...

question.js代碼如下:

...{// 獲取問卷列表url: '/api/question',method: 'get',response(ctx) {const { url = '' } = ctxconst isStar = url.indexOf('isStar=true') >= 0const isDeleted = url.indexOf('isDeleted=true') >= 0return {errno: 0,data: {list: getQuestionList({isStar, isDeleted}),total: 100}}}},
]

getQuestionList.js如下所示:

const Mock = require('mockjs');
const Random = Mock.Random;function getQuestionList(opt = {}) {const { len = 10, isStar, isDeleted } = optconst list = [];for (let i = 0; i < len; i++) {list.push({_id: Random.id(),title: Random.ctitle(),isPublished: Random.boolean(),isStar: isStar || Random.boolean(),answerCount: Random.natural(50, 100),createdAt: Random.datetime(),isDeleted: isDeleted || Random.boolean()})}return list;
}module.exports = getQuestionList;

說明

  • 數據展示有3種狀態:根據不同的狀態有不同展示
    • 加載中:
    • 加載完成,數據為空
    • 加載完成,有數據
  • rowKey={(q: any) => q._id}:ts不設置any類型,程序不報錯,但是ts檢查錯誤

結語

?QQ:806797785

??倉庫地址:https://gitee.com/gaogzhen

??倉庫地址:https://github.com/gaogzhen

[1]ahook官網[CP/OL].

[2]mock文檔[CP/OL].

[3]Ant Design官網[CP/OL].

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

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

相關文章

Android Kotlin AIDL 完整實現與優化指南

本文將詳細介紹如何在Android中使用Kotlin實現AIDL&#xff08;Android Interface Definition Language&#xff09;&#xff0c;并提供多種優化方案。 一、基礎實現 1. 創建AIDL文件 在src/main/aidl/com/example/myapplication/目錄下創建&#xff1a; IMyAidlInterface.…

【數據結構】_棧和隊列相關面試題

&#x1f525; 數據結構修煉場 &#x1f525; &#x1f4a5; 棧與隊列 終極試煉 &#x1f4a5; &#x1f680; 理論已加載完畢&#xff0c;代碼之魂覺醒時刻&#xff01; ?? 是時候用實戰點燃你的算法之力了—— 「題目風暴&#xff0c;來襲&#xff01;」 &#xff08;握…

精益數據分析(8/126):從Airbnb案例看精益創業與數據驅動增長

精益數據分析&#xff08;8/126&#xff09;&#xff1a;從Airbnb案例看精益創業與數據驅動增長 大家好&#xff01;一直以來&#xff0c;我都堅信在創業和技術的領域里&#xff0c;持續學習與分享是不斷進步的關鍵。今天&#xff0c;咱們繼續深入學習《精益數據分析》&#x…

專題二十:路由策略與策略路由

一、路由策略 1.1 路由策略的概念 路由策略是通過修改路由表的路由條目來控制數據流量的可達性。即對接受和發布的路由進過濾。這種方式稱為路由策略 路由策略功能相關作用控制路由的發布可通過路由策略對所要發布的路由信息進行過濾&#xff0c;只允許發布滿足條件的路由信…

VSCode 擴展離線下載方法

學習自該文章&#xff0c;感謝作者&#xff01; 2025 年 VSCode 插件離線下載攻略&#xff1a;官方渠道一鍵獲取 - 知乎 獲取擴展關鍵信息 方法一&#xff1a;官網獲取 打開 VSCode 擴展官方網站 搜索要下載的擴展&#xff0c;以 CodeGeeX 為例&#xff0c;網址為&#xf…

一 、環境的安裝 Anaconda + Pycharm + PaddlePaddle

《從零到一實踐&#xff1a;系統性學習生成式 AI(NLP)》 一 、環境的安裝 Anaconda Pycharm PaddlePaddle 1. Anaconda 軟件安裝 Anaconda 軟件安裝有大量的教程&#xff0c;此處不在說明&#xff0c;安裝完成之后界面如下&#xff1a; 2. 創建 Anaconda 虛擬環境 Paddl…

軟考教材重點內容 信息安全工程師 第23章 云計算安全需求分析與安全保護工程

23.1.云計算基本概念 云計算就是在這樣的需求驅動下而產生的一種計算模式。云計算通過虛擬化及網絡通信技術&#xff0c;提供一種按需服務、彈性化的 IT 資源池服務平臺。云計算的主要特征如下。 1. IT 資源以服務的形式提供 IT 資源以一種服務產品的形式提供&#xff0c;滿…

藍橋杯 19. 最大比例

最大比例 原題目鏈接 題目描述 X 星球的某個大獎賽設了 M 級獎勵。每個級別的獎金是一個正整數。 并且&#xff0c;相鄰兩個級別間的比例是一個固定值&#xff0c;也就是說&#xff1a;所有級別的獎金構成一個等比數列。 例如&#xff1a; 獎金數列為 16, 24, 36, 54&…

基于 Python 的自然語言處理系列(82):Transformer Reinforcement Learning

&#x1f517; 本文所用工具&#xff1a;trl、transformers、peft、bitsandbytes &#x1f4d8; 官方文檔參考&#xff1a;https://huggingface.co/docs/trl 一、引言&#xff1a;從有監督微調到 RLHF 全流程 隨著語言大模型的發展&#xff0c;如何在大規模預訓練模型基礎上更精…

JAVA猜數小游戲

import java.util.Random; import java.util.Scanner;public class HelloWorld {public static void main(String[] args) {Random rnew Random();int luck_number r.nextInt(100)1;while (true){System.out.println("輸入猜數字");Scanner sc new Scanner(System…

GPU渲染階段介紹+Shader基礎結構實現

GPU是什么 &#xff08;CPU&#xff09;Center Processing Unit:邏輯編程 &#xff08;GPU&#xff09;Graphics Processing Unit&#xff1a;圖形處理&#xff08;矩陣運算&#xff0c;數據公式運算&#xff0c;光柵化&#xff09; 渲染管線 渲染管線也稱為渲染流水線&#x…

Spring Boot + MyBatis 動態字段更新方法

在Spring Boot和MyBatis中&#xff0c;實現動態更新不固定字段的步驟如下&#xff1a; 方法一&#xff1a;使用MyBatis動態SQL&#xff08;適合字段允許為null的場景&#xff09; 定義實體類 包含所有可能被更新的字段。 Mapper接口 定義更新方法&#xff0c;參數為實體對象&…

單例模式:確保唯一實例的設計模式

單例模式&#xff1a;確保唯一實例的設計模式 一、模式核心&#xff1a;保證類僅有一個實例并提供全局訪問點 在軟件開發中&#xff0c;有些類需要確保只有一個實例&#xff08;如系統配置類、日志管理器&#xff09;&#xff0c;避免因多個實例導致狀態混亂或資源浪費。 單…

UnoCSS原子CSS引擎-前端福音

UnoCSS是一款原子化的即時按需 CSS 引擎&#xff0c;其中沒有核心實用程序&#xff0c;所有功能都是通過預設提供的。默認情況下UnoCSS應用通過預設來實現相關功能。 UnoCSS中文文檔&#xff1a; https://www.unocss.com.cn 前有很多種原子化的框架&#xff0c;例如 Tailwind…

【Qwen2.5-VL 踩坑記錄】本地 + 海外賬號和國內賬號的 API 調用區別(阿里云百煉平臺)

API 調用 阿里云百煉平臺的海內外 API 的區別&#xff1a; 海外版&#xff1a;需要進行 API 基礎 URL 設置國內版&#xff1a;無需設置。 本人的服務器在香港&#xff0c;采用海外版的 API 時&#xff0c;需要進行如下API端點配置 / API基礎URL設置 / API客戶端配置&#xf…

C語言筆記(鵬哥)上課板書+課件匯總(結構體)-----數據結構常用

結構體 目錄&#xff1a; 1、結構體類型聲明 2、結構體變量的創建和初始化 3、結構體成員訪問操作符 4、結構體內存對齊*****&#xff08;重要指數五顆星&#xff09; 5、結構體傳參 6、結構體實現位段 一、結構體類型聲明 其實在指針中我們已經講解了一些結構體內容了&…

UV: Python包和項目管理器(從入門到不放棄教程)

目錄 UV: Python包和項目管理器&#xff08;從入門到不放棄教程&#xff09;1. 為什么用uv&#xff0c;而不是conda或者pip2. 安裝uv&#xff08;Windows&#xff09;2.1 powershell下載2.2 winget下載2.3 直接下載安裝包 3. uv教程3.1 創建虛擬環境 (uv venv) 4. uvx5. 此pip非…

網絡開發基礎(游戲方向)之 概念名詞

前言 1、一款網絡游戲分為客戶端和服務端兩個部分&#xff0c;客戶端程序運行在用戶的電腦或手機上&#xff0c;服務端程序運行在游戲運營商的服務器上。 2、客戶端和服務端之間&#xff0c;服務端和服務端之間一般都是使用TCP網絡通信。客戶端和客戶端之間通過服務端的消息轉…

java將pdf轉換成word

1、jar包準備 在項目中新增lib目錄&#xff0c;并將如下兩個文件放入lib目錄下 aspose-words-15.8.0-jdk16.jar aspose-pdf-22.9.jar 2、pom.xml配置 <dependency><groupId>com.aspose</groupId><artifactId>aspose-pdf</artifactId><versi…

【C/C++】插件機制:基于工廠函數的動態插件加載

本文介紹了如何通過 C 的 工廠函數、動態庫&#xff08;.so 文件&#xff09;和 dlopen / dlsym 實現插件機制。這個機制允許程序在運行時動態加載和調用插件&#xff0c;而無需在編譯時知道插件的具體類型。 一、 動態插件機制 在現代 C 中&#xff0c;插件機制廣泛應用于需要…