使用WPF製作視頻監控多畫面切換

来源:https://www.cnblogs.com/jared-an/archive/2018/12/01/10049662.html
-Advertisement-
Play Games

前言 曾有做過一個產品,有一個功能是視頻監控模塊,視頻監控首先想到的是視頻多畫面切換功能,由於前端是用WPF開發的,所以當時就做了一個多畫面切換組件,效果如下: 功能設計前提: 由於要使用海康大華天地偉業等視頻廠家的視頻,對接的方式是通過各個廠家提供的SDK(官網下載),由於播放視頻的時候需要傳遞控 ...


  前言

      曾有做過一個產品,有一個功能是視頻監控模塊,視頻監控首先想到的是視頻多畫面切換功能,由於前端是用WPF開發的,所以當時就做了一個多畫面切換組件,效果如下:

  功能設計前提:

  由於要使用海康大華天地偉業等視頻廠家的視頻,對接的方式是通過各個廠家提供的SDK(官網下載),由於播放視頻的時候需要傳遞控制項的句柄(Handle),所以要在WPF中使用System.Windows.Forms下的控制項Panel

  具體實現:

  1、  實現多畫面類MultiView,主要提供頁面初始化、設置當前畫面等功能

  public static class MultiView
    {
        public static int CurrentModel = 0;
        public static Dictionary<int, CellPanel> DictPanel = null;
        private static Grid OriginalGrid = null;
        private static Grid TempGrid1 = new Grid();
        private static Grid TempGrid2 = new Grid();
        private static int MaxCellNums = 0;

        /// <summary>
        /// 初始化頁面
        /// </summary>
        /// <param name="grid">主體</param>
        /// <param name="cellNums">最大畫面數</param>
        public static void InitGrid(Grid grid, int cellNums)
        {
            MultiView.OriginalGrid = grid;
            MultiView.MaxCellNums = cellNums;

            MultiView.DictPanel = new Dictionary<int, CellPanel>();
            for (int index = 1; index <= MultiView.MaxCellNums; index++)
            {
                CellPanel cellPanel = new CellPanel();
                cellPanel.Index = index;
                MultiView.DictPanel.Add(index, cellPanel);
            }
        }

        /// <summary>
        /// 設置當前畫面數
        /// </summary>
        /// <param name="model"></param>
        public static void SetCurrentModel(int model)
        {
            switch (model)
            {
                case 1:
                    MultiView.SetModelByColumnAndRow(1, 1);
                    break;
                case 3:
                    MultiView.SetModel3();
                    break;
                case 4:
                    MultiView.SetModelByColumnAndRow(2, 2);
                    break;
                case 6:
                    MultiView.SetModel6();
                    break;
                case 8:
                    MultiView.SetModel8();
                    break;
                case 9:
                    MultiView.SetModelByColumnAndRow(3, 3);
                    break;
                case 10:
                    MultiView.SetModel10();
                    break;
                case 16:
                    MultiView.SetModelByColumnAndRow(4, 4);
                    break;
                case 25:
                    MultiView.SetModelByColumnAndRow(5, 5);
                    break;
            }

            MultiView.CurrentModel = model;
        }
        /// <summary>
        /// 獲取當前畫面
        /// </summary>
        /// <returns></returns>
        public static CellPanel CurrentCellPanel()
        {
            for (int index = 1; index <= MultiView.MaxCellNums; index++)
            {
                if (MultiView.DictPanel[index].Selected)
                {
                    return MultiView.DictPanel[index];
                }
            }
            return null;
        }

        /// <summary>
        /// 通過行列數設置畫面分割
        /// </summary>
        /// <param name="column"></param>
        /// <param name="row"></param>
        public static void SetModelByColumnAndRow(int column, int row)
        {
            MultiView.Clear();
            MultiView.CreateColumnAndRow(MultiView.OriginalGrid, row, column);
            
            int num = 1;
            for (int rowIndex = 0; rowIndex < row; rowIndex++)
            {
                for (int columnIndex = 0; columnIndex < column; columnIndex++)
                {
                    CellPanel cellPanel = MultiView.DictPanel[num];
                    Grid.SetColumn(cellPanel, columnIndex);
                    Grid.SetRow(cellPanel, rowIndex);
                    MultiView.OriginalGrid.Children.Add(cellPanel);
                    num++;
                }
            }
        }
        /// <summary>
        /// 三畫面
        /// </summary>
        public static void SetModel3()
        {
            MultiView.Clear();
            ColumnDefinition columnDefinition1 = new ColumnDefinition();
            ColumnDefinition columnDefinition2 = new ColumnDefinition();
            columnDefinition1.Width = new GridLength(0.618, GridUnitType.Star);
            columnDefinition2.Width = new GridLength(0.382, GridUnitType.Star);
            MultiView.OriginalGrid.ColumnDefinitions.Add(columnDefinition1);
            MultiView.OriginalGrid.ColumnDefinitions.Add(columnDefinition2);
            CellPanel cellPanel = MultiView.DictPanel[1];
            Grid.SetColumn(cellPanel, 0);
            MultiView.OriginalGrid.Children.Add(cellPanel);

            for (int index1 = 0; index1 < 2; ++index1)
            {
                cellPanel = MultiView.DictPanel[index1 + 2];
                MultiView.TempGrid1.RowDefinitions.Add(new RowDefinition());
                Grid.SetRow(cellPanel, index1);
                MultiView.TempGrid1.Children.Add(cellPanel);
            }

            Grid.SetColumn(MultiView.TempGrid1, 1);
            MultiView.OriginalGrid.Children.Add(MultiView.TempGrid1);
        }
        /// <summary>
        /// 六畫面
        /// </summary>
        public static void SetModel6()
        {
            MultiView.Clear();
            MultiView.CreateColumnAndRow(MultiView.OriginalGrid, 2, 2);
            MultiView.OriginalGrid.ColumnDefinitions[0].Width = new GridLength(0.66, GridUnitType.Star);
            MultiView.OriginalGrid.ColumnDefinitions[1].Width = new GridLength(0.34, GridUnitType.Star);
            MultiView.OriginalGrid.RowDefinitions[0].Height = new GridLength(0.67, GridUnitType.Star);
            MultiView.OriginalGrid.RowDefinitions[1].Height = new GridLength(0.33, GridUnitType.Star);

            CellPanel cellPanel = MultiView.DictPanel[1];
            Grid.SetColumn(cellPanel, 0);
            Grid.SetRow(cellPanel, 0);
            MultiView.OriginalGrid.Children.Add(cellPanel);

            //p2,p3 畫面
            Grid.SetColumn(MultiView.TempGrid1, 1);
            Grid.SetRow(MultiView.TempGrid1, 0);

            for (int index = 0; index < 2; ++index)
            {
                cellPanel = MultiView.DictPanel[index + 2];
                MultiView.TempGrid1.RowDefinitions.Add(new RowDefinition());
                Grid.SetRow(cellPanel, index);
                MultiView.TempGrid1.Children.Add(cellPanel);
            }
            MultiView.OriginalGrid.Children.Add(MultiView.TempGrid1);
            //p4,p5 畫面
            Grid.SetColumn(MultiView.TempGrid2, 0);
            Grid.SetRow(MultiView.TempGrid2, 1);

            for (int index = 0; index < 2; ++index)
            {
                cellPanel = MultiView.DictPanel[index + 4];

                MultiView.TempGrid2.ColumnDefinitions.Add(new ColumnDefinition());
                Grid.SetColumn(cellPanel, index);
                MultiView.TempGrid2.Children.Add(cellPanel);
            }
            MultiView.OriginalGrid.Children.Add(MultiView.TempGrid2);

            cellPanel = MultiView.DictPanel[6];
            Grid.SetRow(cellPanel, 1);
            Grid.SetColumn(cellPanel, 1);
            MultiView.OriginalGrid.Children.Add(cellPanel);
        }
        /// <summary>
        /// 八畫面
        /// </summary>
        public static void SetModel8()
        {
            MultiView.Clear();
            MultiView.CreateColumnAndRow(MultiView.OriginalGrid, 2, 2);
            MultiView.OriginalGrid.ColumnDefinitions[0].Width = new GridLength(0.75, GridUnitType.Star);
            MultiView.OriginalGrid.ColumnDefinitions[1].Width = new GridLength(0.25, GridUnitType.Star);
            MultiView.OriginalGrid.RowDefinitions[0].Height = new GridLength(0.75, GridUnitType.Star);
            MultiView.OriginalGrid.RowDefinitions[1].Height = new GridLength(0.25, GridUnitType.Star);

            CellPanel cellPanel = MultiView.DictPanel[1];
            Grid.SetColumn(cellPanel, 0);
            Grid.SetRow(cellPanel, 0);
            MultiView.OriginalGrid.Children.Add(cellPanel);

            //p2,p3,p4 畫面
            Grid.SetColumn(MultiView.TempGrid1, 1);
            Grid.SetRow(MultiView.TempGrid1, 0);

            for (int index = 0; index < 3; ++index)
            {
                cellPanel = MultiView.DictPanel[index + 2];

                MultiView.TempGrid1.RowDefinitions.Add(new RowDefinition());
                Grid.SetRow(cellPanel, index);
                MultiView.TempGrid1.Children.Add(cellPanel);
            }
            MultiView.OriginalGrid.Children.Add(MultiView.TempGrid1);
            //p5,p6,p7 畫面
            Grid.SetColumn(MultiView.TempGrid2, 0);
            Grid.SetRow(MultiView.TempGrid2, 1);

            for (int index = 0; index < 3; ++index)
            {
                cellPanel = MultiView.DictPanel[index + 5];

                MultiView.TempGrid2.ColumnDefinitions.Add(new ColumnDefinition());
                Grid.SetColumn(cellPanel, index);
                MultiView.TempGrid2.Children.Add(cellPanel);
            }
            MultiView.OriginalGrid.Children.Add(MultiView.TempGrid2);

            cellPanel = MultiView.DictPanel[8];
            Grid.SetRow(cellPanel, 1);
            Grid.SetColumn(cellPanel, 1);
            MultiView.OriginalGrid.Children.Add(cellPanel);
        }
        /// <summary>
        /// 十畫面
        /// </summary>
        public static void SetModel10()
        {
            MultiView.Clear();
            MultiView.CreateColumnAndRow(MultiView.OriginalGrid, 2, 2);
            MultiView.OriginalGrid.ColumnDefinitions[0].Width = new GridLength(0.77, GridUnitType.Star);
            MultiView.OriginalGrid.ColumnDefinitions[1].Width = new GridLength(0.23, GridUnitType.Star);
            MultiView.OriginalGrid.RowDefinitions[0].Height = new GridLength(0.8, GridUnitType.Star);
            MultiView.OriginalGrid.RowDefinitions[1].Height = new GridLength(0.2, GridUnitType.Star);

            CellPanel cellPanel = MultiView.DictPanel[1];
            Grid.SetColumn(cellPanel, 0);
            Grid.SetRow(cellPanel, 0);
            MultiView.OriginalGrid.Children.Add(cellPanel);

            //p2,p3,p4,p5 畫面
            Grid.SetColumn(MultiView.TempGrid1, 1);
            Grid.SetRow(MultiView.TempGrid1, 0);

            for (int index = 0; index < 4; ++index)
            {
                cellPanel = MultiView.DictPanel[index + 2];

                MultiView.TempGrid1.RowDefinitions.Add(new RowDefinition());
                Grid.SetRow(cellPanel, index);
                MultiView.TempGrid1.Children.Add(cellPanel);
            }
            MultiView.OriginalGrid.Children.Add(MultiView.TempGrid1);
            //p6,p7,p8,p9 畫面
            Grid.SetColumn(MultiView.TempGrid2, 0);
            Grid.SetRow(MultiView.TempGrid2, 1);

            for (int index = 0; index < 4; ++index)
            {
                cellPanel = MultiView.DictPanel[index + 6];

                MultiView.TempGrid2.ColumnDefinitions.Add(new ColumnDefinition());
                Grid.SetColumn(cellPanel, index);
                MultiView.TempGrid2.Children.Add(cellPanel);
            }
            MultiView.OriginalGrid.Children.Add(MultiView.TempGrid2);

            cellPanel = MultiView.DictPanel[10];
            Grid.SetRow(cellPanel, 1);
            Grid.SetColumn(cellPanel, 1);
            MultiView.OriginalGrid.Children.Add(cellPanel);
        }
        /// <summary>
        /// 索引畫面全屏
        /// </summary>
        /// <param name="index">畫面索引</param>
        public static void SetFullScreen(int index)
        {
            MultiView.Clear();
            CellPanel cellPanel = MultiView.DictPanel[index];
            Grid.SetColumn(cellPanel, 0);
            Grid.SetRow(cellPanel, 0);
            MultiView.OriginalGrid.Children.Add(cellPanel);
        }

        private static void Clear()
        {
            MultiView.OriginalGrid.RowDefinitions.Clear();
            MultiView.OriginalGrid.ColumnDefinitions.Clear();
            MultiView.OriginalGrid.Children.Clear();
            MultiView.TempGrid1.Children.Clear();
            MultiView.TempGrid1.RowDefinitions.Clear();
            MultiView.TempGrid1.ColumnDefinitions.Clear();
            MultiView.TempGrid2.Children.Clear();
            MultiView.TempGrid2.RowDefinitions.Clear();
            MultiView.TempGrid2.ColumnDefinitions.Clear();

        }

        private static void CreateColumnAndRow(Grid grid, int row, int column)
        {
            for (int index = 0; index < row; ++index)
            {
                grid.RowDefinitions.Add(new RowDefinition());
            }
                
            for (int index = 0; index < column; ++index)
            {
                grid.ColumnDefinitions.Add(new ColumnDefinition());
            }      
        }
    }

 

       2、 實現單通道畫面控制項CellPanel

        1) 前臺頁面

<UserControl x:Class="MultiviewControl.CellPanel"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
             xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
             BorderThickness="1" BorderBrush="Silver">
    <Grid Background="Black">
        <wfi:WindowsFormsHost >
            <wf:Panel x:Name="panel" AutoSize="true" Dock="Fill"/>
        </wfi:WindowsFormsHost>
    </Grid>
</UserControl>

 

        2) 後臺實現

 1  public partial class CellPanel : System.Windows.Controls.UserControl
 2     {
 3         public int Index;
 4         public bool Selected;
 5 
 6         private bool isFull = false;
 7         private SolidColorBrush SelectedColor = new SolidColorBrush(Colors.YellowGreen);
 8         private SolidColorBrush MouseEnterColor = new SolidColorBrush(Colors.Red);
 9         private SolidColorBrush NormalColor = new SolidColorBrush(Colors.Silver);
10 
11         public CellPanel()
12         {
13             this.InitializeComponent();
14             this.panel.Click += new EventHandler(this.panel_Click);
15             this.panel.DoubleClick += new EventHandler(this.panel_DoubleClick);
16             this.panel.MouseEnter += new EventHandler(this.panel_MouseEnter);
17             this.panel.MouseLeave += new EventHandler(this.panel_MouseLeave);
18             this.panel.SizeChanged += new EventHandler(this.panel_SizeChange);
19             this.Selected = false;
20         }
21 
22         public void panel_Click(object sender, EventArgs e)
23         {
24             foreach (CellPanel cellPanel in MultiView.DictPanel.Values)
25             {
26                 cellPanel.Selected = false;
27                 cellPanel.BorderBrush = NormalColor;
28             }
29             this.Selected = true;
30             this.BorderBrush = SelectedColor;
31         }
32         public void panel_DoubleClick(object sender, EventArgs e)
33         {
34             if (this.isFull)
35             {
36                 MultiView.SetCurrentModel(MultiView.CurrentModel);
37             }
38             else
39             {
40                 MultiView.SetFullScreen(this.Index);
41             }
42             
43             this.isFull = !this.isFull;
44         }
45         private void panel_MouseEnter(object sender, EventArgs e)
46         {
47             if (!this.Selected)
48             {
49                 this.BorderBrush = MouseEnterColor;
50             }
51         }
52 
53         private void panel_MouseLeave(object sender, EventArgs e)
54         {
55             if (!this.Selected)
56             {
57                 this.BorderBrush = NormalColor;
58             }
59         }
60         private void panel_SizeChange(object sender, EventArgs e)
61         {
62             this.panel.Size = new System.Drawing.Size((int)this.Width - 2, (int)this.Height - 2);
63         }
64 
65     }

 

  3、新建一個窗體MainWindow,調用MutiView類

     1) 前臺頁面

 1 <Window x:Class="MultiviewControl.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         Title="MainWindow" Height="350" Width="525">
 5     <Grid>
 6         <Grid.RowDefinitions>
 7             <RowDefinition Height="*" />
 8             <RowDefinition Height="40" />
 9         </Grid.RowDefinitions>
10         <Grid x:Name="grid" />
11         <StackPanel Orientation="Horizontal" Grid.Row="1">
12             <Button Content="1畫 面" Tag="1" Click="btn_Click" Margin="6" Width="60"/>
13             <Button Content="3畫 面" Tag="3" Click="btn_Click" Margin="6" Width="60"/>
14             <Button Content="4畫 面" Tag="4" Click="btn_Click" Margin="6" Width="60"/>
15             <Button Content="6畫 面" Tag="6" Click="btn_Click" Margin="6" Width="60"/>
16             <Button Content="8畫 面" Tag="8" Click="btn_Click" Margin="6" Width="60"/>
17             <Button Content="9畫 面" Tag="9" Click="btn_Click" Margin="6" Width="60"/>
18             <Button Content="10畫 面" Tag="10" Click="btn_Click" Margin="6" Width="60"/>
19         </StackPanel>
20     </Grid>
21 </Window>

 

         2) 後臺實現    

 1  public partial class MainWindow : Window
 2     {
 3         public MainWindow()
 4         {
 5             InitializeComponent();
 6             MultiView.InitGrid(this.grid, 64);
 7             MultiView.SetCurrentModel(4);
 8         }
 9 
10         private void btn_Click(object sender, RoutedEventArgs e)
11         {
12             Button btn = sender as Button;
13             int index = 0;
14             if(btn.Tag != null)
15             {
16                 MultiView.SetCurrentModel(Convert.ToInt32( btn.Tag));
17             }
18            
19         }
20 
21     }

 

 

          多畫面切換就OK了!希望能對大家有用!

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 破解步驟 1、下載補丁 2、修改配置文件 3、輸入激活碼 4、激活成功 下載補丁 下載地址(如發現下載鏈接失效,請聯繫我的QQ郵箱,謝謝~): 適用版本(沒有測試向下相容性): |補丁文件名|適合Idea版本| |: |: | |JetbrainsCrack 3.4 release enc.jar| ...
  • public class TestSuShu { public static void main(String[] args) { for(int i=2;i<=100;i++) { boolean isSushu = true; for(int j=2;j<i;j++) { if(i%j==0) ...
  • 題意 "題目鏈接" Sol 記得NJU有個特別強的ACM隊叫拉格朗,總感覺少了什麼。。 不說了直接扔公式 $$f(x) = \sum_{i = 1}^n y_i \prod_{j \not = i} \frac{k x[j]}{x[i] x[j]}$$ 複雜度$O(n^2)$ 如果$x$的取值是連續 ...
  • 1.常見參數 tcpdump -i eth0 -nn -s0 -v port 80 -i 選擇監控的網卡 -nn 不解析主機名和埠號,捕獲大量數據,名稱解析會降低解析速度 -s0 捕獲長度無限制 -v 增加輸出中顯示的詳細信息量 port 80 埠過濾器,只捕獲80埠的流量,通常是HTTP 2... ...
  • 爬蟲的定義 什麼是爬蟲? 爬蟲(又被稱為網頁蜘蛛,網路機器人)就是模擬客戶端發送網路請求,接收請求響應,一種按照一定的規則,自動地抓取互聯網信息的程式。 原則上,只要是瀏覽器(客戶端)能做的事情,爬蟲都能夠做。 爬蟲的分類和爬蟲的流程 爬蟲的分類 爬蟲的分類 根據被爬網站的數量不同,我們把爬蟲分為 ...
  • 1、if語句if 語句基本用法: 其中,表達式可以是一個單純的布爾值或變數,也可以是比較表達式或邏輯表達式,如果表達式為真,則執行“語句塊”;如果表達式的值為假,就跳 過“語句塊”,繼續執行後面的語句。 2、if…else語句if…else 語句基本用法: 使用 if…else 語句時,表達式可以是 ...
  • 總體原則:命名一定要體現其在程式中的作用; Camel命名法:第一個單詞的首字母小寫,其餘每個單詞的首字母大寫;多用給變數或者欄位命名;給欄位命名必須以下劃線開始; Pascal命名法:每個單詞的首字母都大寫,其餘字母小寫;適用於方法名、類名、屬性名等; ...
  • 一. 起始 去年.NetCore2.0的發佈,公司決定新項目採用.NetCore開發,當作試驗。但是問題在於當前公司內部使用的RPC服務為Thrift v0.9 + zookeeper版本,經過個性化定製,支持了非同步,但也因為如此,這麼多年來一直沒有去升級,導致遷移工作很複雜(歷史遺留項目太多,有各 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...