• 基于VC++的WEB浏览器的实现


    目 录
    摘 要 2
    1设计题目与要求 2
    2系统设计 2
    2.1总体设计 2
    2.2详细设计 2
    2.2.1用户界面设计 3
    2.2.2多标签模块设计 6
    2.2.3浏览模块设计 6
    2.2.4操作按钮模块设计 9
    2.2.5页面缩放模块设计 10
    2.2.6状态栏模块设计 11
    2.2.7收藏夹模块设计 13
    2.2.8窗体关闭模块设计 13
    2.3系统平台、语言和工具 14
    3调试过程及操作说明 14
    3.1启动 Web 浏览器 14
    3.2浏览网页 14
    3.3修改界面样式及查看帮助 16
    3.4退出程序 16
    4开发中遇到的问题及解决方案 18
    4.1无法获取到正确的网页标题 18
    4.2多文档模式开发中获取活动窗口的问题 18
    4.3页面缩放的问题 19
    5目前未解决的问题 19
    5.1浏览器状态无法正常显示 19
    5.2标签切换时地址栏内容未切换 19
    5.3标签切换时网页标题丢失 20
    6自我评价与总结 20
    参考文献 21
    本科毕业论文评分表 22
    1设计题目与要求

    设计题目:基于VC++的WEB浏览器的实现设计要求:①能实现浏览器外观界面的设计
    ②能实现网页的浏览、后退、前进、刷新等基本功能
    ③实现其它附加功能(不在要求范围之内)
    ④界面良好,功能完善

    2系统设计

    2.1总体设计

    本次毕业设计所实现的 Web 浏览器首先要实现设计要求中的功能,要有友好的界面,能正常的浏览网页,能实现后退、前进、刷新等基本功能。
    此外,在要求的功能之上,对 Web 浏览器的功能进行了扩充,能实现网页保存、打印网页、在网页上查找、选中全部内容、标签式多窗口浏览、关闭浏览器提示、页面缩放、网页加载进度显示、浏览器状态以及界面样式更换等功能。

    2.2详细设计

    本 Web 浏览器具有较多的功能,因而采用了模块化的设计思想,将每个功能做成了相应的模块,便于开发。另外由于 Web 浏览器的自身性质,本次开发采用了 MFC 的多文档(MDI) 模式,使用 App—MainFrame—ChildFrame—View 的模式开发。

    // MainFrm.cpp : CMainFrame 类的实现
    //
    
    #include "stdafx.h"
    #include "WebBrowser.h"
    #include "ChildFrm.h"
    #include "MainFrm.h"
    #include "CloseDlg.h"
    
    #define WM_NEWURL WM_USER+104
    #define ID_STATUSBAR_PROGRESS 9999
    
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #endif
    
    // CMainFrame
    
    IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWndEx)
    
    BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWndEx)
    	ON_WM_CREATE()
    	// 全局帮助命令
    	ON_COMMAND(ID_HELP_FINDER, &CMDIFrameWndEx::OnHelpFinder)
    	ON_COMMAND(ID_HELP, &CMDIFrameWndEx::OnHelp)
    	ON_COMMAND(ID_CONTEXT_HELP, &CMDIFrameWndEx::OnContextHelp)
    	ON_COMMAND(ID_DEFAULT_HELP, &CMDIFrameWndEx::OnHelpFinder)
    	ON_COMMAND(ID_WINDOW_MANAGER, &CMainFrame::OnWindowManager)
    	ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnApplicationLook)
    	ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnUpdateApplicationLook)
        ON_UPDATE_COMMAND_UI(ID_EDIT_BACK,&CMainFrame::ButtonEnable)
        ON_UPDATE_COMMAND_UI(ID_EDIT_FORWARD,&CMainFrame::ButtonEnable)
        ON_UPDATE_COMMAND_UI(ID_STATUSBAR_PANE1,&CMainFrame::ButtonEnable)
    	ON_COMMAND(ID_VIEW_CAPTION_BAR, &CMainFrame::OnViewCaptionBar)
    	ON_UPDATE_COMMAND_UI(ID_VIEW_CAPTION_BAR, &CMainFrame::OnUpdateViewCaptionBar)
    	ON_COMMAND(ID_TOOLS_OPTIONS, &CMainFrame::OnOptions)
        ON_COMMAND(ID_ADDR, &CMainFrame::OnAddr)
        ON_MESSAGE(WM_NEWURL, &CMainFrame::OnNewUrl)
        ON_COMMAND(ID_BUTTON18, &CMainFrame::OnZoom)
        ON_WM_CLOSE()
        ON_COMMAND(ID_BUTTON_SYSTEM, &CMainFrame::OnButtonSystem)
    END_MESSAGE_MAP()
    
    // CMainFrame 构造/析构
    
    CMainFrame::CMainFrame()
    {
    	// TODO: 在此添加成员初始化代码
    	theApp.m_nAppLook = theApp.GetInt(_T("ApplicationLook"), ID_VIEW_APPLOOK_OFF_2007_BLUE);
        isBack=isForward=FALSE;
    }
    
    CMainFrame::~CMainFrame()
    {
    }
    
    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
    	if (CMDIFrameWndEx::OnCreate(lpCreateStruct) == -1)
    		return -1;
    
    	BOOL bNameValid;
    	// 基于持久值设置视觉管理器和样式
    	OnApplicationLook(theApp.m_nAppLook);
    
    	CMDITabInfo mdiTabParams;
    	mdiTabParams.m_style = CMFCTabCtrl::STYLE_3D_ONENOTE; // 其他可用样式...
    	mdiTabParams.m_bActiveTabCloseButton = TRUE;      // 设置为 FALSE 会将关闭按钮放置在选项卡区域的右侧
    	mdiTabParams.m_bTabIcons = TRUE;    // 设置为 TRUE 将在 MDI 选项卡上启用文档图标
    	mdiTabParams.m_bAutoColor = TRUE;    // 设置为 FALSE 将禁用 MDI 选项卡的自动着色
    	mdiTabParams.m_bDocumentMenu = TRUE; // 在选项卡区域的右边缘启用文档菜单
        mdiTabParams.m_bEnableTabSwap = TRUE;
    	EnableMDITabbedGroups(TRUE, mdiTabParams);
    
    	m_wndRibbonBar.Create(this);
    	m_wndRibbonBar.LoadFromResource(IDR_RIBBON);
    	if (!m_wndStatusBar.Create(this))
    	{
    		TRACE0("未能创建状态栏\n");
    		return -1;      // 未能创建
    	}
    	CString strTitlePane1;
    	CString strTitlePane2;
    	bNameValid = strTitlePane1.LoadString(IDS_STATUS_PANE1);
        ASSERT(bNameValid);
    	bNameValid = strTitlePane2.LoadString(IDS_STATUS_PANE2);
    	ASSERT(bNameValid);
        StatusBar=new CMFCRibbonLabel(strTitlePane1,FALSE);
        ProgressBar=new CMFCRibbonProgressBar(ID_STATUSBAR_PROGRESS,160);
    	m_wndStatusBar.AddDynamicElement(StatusBar);
        m_wndStatusBar.AddExtendedElement(ProgressBar,L"进度");
        m_wndStatusBar.AddSeparator();
    	m_wndStatusBar.AddExtendedElement(new CMFCRibbonStatusBarPane(ID_STATUSBAR_PANE2, strTitlePane2, TRUE), strTitlePane2);
    	// 启用 Visual Studio 2005 样式停靠窗口行为
    	CDockingManager::SetDockingMode(DT_SMART);
    	// 启用 Visual Studio 2005 样式停靠窗口自动隐藏行为
    	EnableAutoHidePanes(CBRS_ALIGN_ANY);
    
    	// 创建标题栏:
    	if (!CreateCaptionBar())
    	{
    		TRACE0("未能创建标题栏\n");
    		return -1;      // 未能创建
    	}
    
    	// 启用增强的窗口管理对话框
    	EnableWindowsDialog(ID_WINDOW_MANAGER, ID_WINDOW_MANAGER, TRUE);
    
    	// 将文档名和应用程序名称在窗口标题栏上的顺序进行交换。这
    	// 将改进任务栏的可用性,因为显示的文档名带有缩略图。
    	ModifyStyle(0, FWS_PREFIXTITLE);
    
    	return 0;
    }
    
    BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
    {
    	if( !CMDIFrameWndEx::PreCreateWindow(cs) )
    		return FALSE;
    	// TODO: 在此处通过修改
    	//  CREATESTRUCT cs 来修改窗口类或样式
    
    	return TRUE;
    }
    
    BOOL CMainFrame::CreateCaptionBar()
    {
    	if (!m_wndCaptionBar.Create(WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS, this, ID_VIEW_CAPTION_BAR, -1, TRUE))
    	{
    		TRACE0("未能创建标题栏\n");
    		return FALSE;
    	}
    
    	BOOL bNameValid;
    
    	CString strTemp, strTemp2;
    	bNameValid = strTemp.LoadString(IDS_CAPTION_BUTTON);
    	ASSERT(bNameValid);
    	m_wndCaptionBar.SetButton(strTemp, ID_TOOLS_OPTIONS, CMFCCaptionBar::ALIGN_LEFT, FALSE);
    	bNameValid = strTemp.LoadString(IDS_CAPTION_BUTTON_TIP);
    	ASSERT(bNameValid);
    	m_wndCaptionBar.SetButtonToolTip(strTemp);
    
    	bNameValid = strTemp.LoadString(IDS_CAPTION_TEXT);
    	ASSERT(bNameValid);
    	m_wndCaptionBar.SetText(strTemp, CMFCCaptionBar::ALIGN_LEFT);
    
    	m_wndCaptionBar.SetBitmap(IDB_INFO, RGB(255, 255, 255), FALSE, CMFCCaptionBar::ALIGN_LEFT);
    	bNameValid = strTemp.LoadString(IDS_CAPTION_IMAGE_TIP);
    	ASSERT(bNameValid);
    	bNameValid = strTemp2.LoadString(IDS_CAPTION_IMAGE_TEXT);
    	ASSERT(bNameValid);
    	m_wndCaptionBar.SetImageToolTip(strTemp, strTemp2);
    
    	return TRUE;
    }
    
    // CMainFrame 诊断
    
    #ifdef _DEBUG
    void CMainFrame::AssertValid() const
    {
    	CMDIFrameWndEx::AssertValid();
    }
    
    void CMainFrame::Dump(CDumpContext& dc) const
    {
    	CMDIFrameWndEx::Dump(dc);
    }
    #endif //_DEBUG
    
    
    // CMainFrame 消息处理程序
    
    void CMainFrame::OnWindowManager()
    {
    	ShowWindowsDialog();
    }
    
    void CMainFrame::OnApplicationLook(UINT id)
    {
    	CWaitCursor wait;
    	theApp.m_nAppLook = id;
    	switch (theApp.m_nAppLook)
    	{
    	case ID_VIEW_APPLOOK_WIN_2000:
    		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManager));
    		m_wndRibbonBar.SetWindows7Look(FALSE);
    		break;
    	case ID_VIEW_APPLOOK_OFF_XP:
    		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOfficeXP));
    		m_wndRibbonBar.SetWindows7Look(FALSE);
    		break;
    	case ID_VIEW_APPLOOK_WIN_XP:
    		CMFCVisualManagerWindows::m_b3DTabsXPTheme = TRUE;
    		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
    		m_wndRibbonBar.SetWindows7Look(FALSE);
    		break;
    	case ID_VIEW_APPLOOK_OFF_2003:
    		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2003));
    		CDockingManager::SetDockingMode(DT_SMART);
    		m_wndRibbonBar.SetWindows7Look(FALSE);
    		break;
    	case ID_VIEW_APPLOOK_VS_2005:
    		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2005));
    		CDockingManager::SetDockingMode(DT_SMART);
    		m_wndRibbonBar.SetWindows7Look(FALSE);
    		break;
    	case ID_VIEW_APPLOOK_VS_2008:
    		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2008));
    		CDockingManager::SetDockingMode(DT_SMART);
    		m_wndRibbonBar.SetWindows7Look(FALSE);
    		break;
    	case ID_VIEW_APPLOOK_WINDOWS_7:
    		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows7));
    		CDockingManager::SetDockingMode(DT_SMART);
    		m_wndRibbonBar.SetWindows7Look(TRUE);
    		break;
    	default:
    		switch (theApp.m_nAppLook)
    		{
    		case ID_VIEW_APPLOOK_OFF_2007_BLUE:
    			CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_LunaBlue);
    			break;
    		case ID_VIEW_APPLOOK_OFF_2007_BLACK:
    			CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_ObsidianBlack);
    			break;
    		case ID_VIEW_APPLOOK_OFF_2007_SILVER:
    			CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Silver);
    			break;
    		case ID_VIEW_APPLOOK_OFF_2007_AQUA:
    			CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Aqua);
    			break;
    		}
    		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2007));
    		CDockingManager::SetDockingMode(DT_SMART);
    		m_wndRibbonBar.SetWindows7Look(FALSE);
    	}
    	RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_UPDATENOW | RDW_FRAME | RDW_ERASE);
    	theApp.WriteInt(_T("ApplicationLook"), theApp.m_nAppLook);
    }
    
    void CMainFrame::OnUpdateApplicationLook(CCmdUI* pCmdUI)
    {
    	pCmdUI->SetRadio(theApp.m_nAppLook == pCmdUI->m_nID);
    }
    
    void CMainFrame::OnViewCaptionBar()
    {
    	m_wndCaptionBar.ShowWindow(m_wndCaptionBar.IsVisible() ? SW_HIDE : SW_SHOW);
    	RecalcLayout(FALSE);
    }
    
    void CMainFrame::OnUpdateViewCaptionBar(CCmdUI* pCmdUI)
    {
    	pCmdUI->SetCheck(m_wndCaptionBar.IsVisible());
    }
    
    void CMainFrame::OnOptions()
    {
    	CMFCRibbonCustomizeDialog *pOptionsDlg = new CMFCRibbonCustomizeDialog(this, &m_wndRibbonBar);
    	ASSERT(pOptionsDlg != NULL);
    	pOptionsDlg->DoModal();
    	delete pOptionsDlg;
    }
    
    void CMainFrame::OnAddr()
    {
        CMFCRibbonEdit *pEdit=DYNAMIC_DOWNCAST(CMFCRibbonEdit, m_wndRibbonBar.FindByID(ID_ADDR));  //获取地址输入框
        CString strUrl=pEdit->GetEditText();  //获取地址框文本
        if(strUrl=="")  //数据合法性判断
            MessageBox(L"请输入要访问的网址!",L"提示",MB_ICONWARNING);
        else
        {
            CChildFrame *pChildFrame=(CChildFrame*)GetActiveFrame();
            CHtmlView *pBrowser=(CHtmlView*)pChildFrame->GetActiveView();
            if(pBrowser->GetLocationURL()!=strUrl) pBrowser->Navigate(strUrl);
        }
    }
    
    void CMainFrame::ChangeAddr(CString str)
    {  //修改地址输入框文本
        CMFCRibbonEdit *pEdit=DYNAMIC_DOWNCAST(CMFCRibbonEdit, m_wndRibbonBar.FindByID(ID_ADDR));
        pEdit->SetEditText(str);
    }
    
    double CMainFrame::GetZoom()
    {   //获取滑块的值
        CMFCRibbonSlider *pSlider=DYNAMIC_DOWNCAST(CMFCRibbonSlider, m_wndRibbonBar.FindByID(ID_SLIDER2));
        return (pSlider->GetPos())/10.0;
    }
    
    void CMainFrame::SetStatusText(LPCTSTR str)
    {  //设置状态栏文本(有Bug)
        CString tmp=str;
        static BOOL isFinish=TRUE;
        if(StatusBar&&!tmp.IsEmpty()&&isFinish) StatusBar->SetText(str);
        isFinish=tmp.Find(L"完成",0);
    }
    
    void CMainFrame::SetProgress(long value,long max)
    {  //设置进度条
        if(ProgressBar)
        {
            ProgressBar->SetRange(0,max);
            ProgressBar->SetPos(value);
        }
    }
    
    afx_msg LRESULT CMainFrame::OnNewUrl(WPARAM wParam, LPARAM lParam)
    {  //CHtmlView类打开了新窗口
        LPDISPATCH* ppDispatch=(LPDISPATCH*)wParam;
        SendMessage(WM_COMMAND, ID_FILE_NEW, 0);
        CChildFrame* pChildFrame = (CChildFrame*)GetActiveFrame();
        *ppDispatch=((CHtmlView*)pChildFrame->GetActiveView())->GetApplication();
        return 0;
    }
    
    void CMainFrame::OnZoom()
    {
    }
    
    void CMainFrame::OnClose()
    {  //处理WM_CLOSE
        CCloseDlg closeDlg;
        UINT r=closeDlg.DoModal();  //打开关闭对话框
        if(r==IDALL) CMDIFrameWndEx::OnClose();
        else if(r==IDCUR) GetActiveFrame()->DestroyWindow();
    }
    
    void CMainFrame::SetButtonState(BOOL sForward,BOOL sBack)
    {  //接收后退、前进按钮状态
        isBack=sBack;
        isForward=sForward;
    }
    
    void CMainFrame::ButtonEnable(CCmdUI *pCmdUI)
    {  //设置按钮可用
        if(pCmdUI->m_nID==ID_EDIT_FORWARD) pCmdUI->Enable(isForward);
        else if(pCmdUI->m_nID==ID_EDIT_BACK) pCmdUI->Enable(isBack);
        else pCmdUI->Enable(TRUE);
    }
    
    void CMainFrame::OnButtonSystem()
    {  //打开系统信息
        ShellAbout(this->m_hWnd,L"Crazy Urus 浏览器",L"Crazy Urus 浏览器\n\r作者:廖星(Crazy Urus)",AfxGetApp()->LoadIcon(IDR_MAINFRAME));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347

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

  • 相关阅读:
    UDS02-根据标识符读取数据服务【ServiceID = 0x22】
    获取Windows正在运行的窗口进程
    STM32:GPIO功能描述和工作方式
    在window11上安装sshd
    [vue]vuex
    Linux——信号量(定义、示例、信号量接口)
    [计算机入门] Windows附件程序介绍(影音类)
    基于微调技术打造自己的私有LLM大模型
    2023年【四川省安全员B证】报名考试及四川省安全员B证考试内容
    JAVA面试技巧之自我介绍
  • 原文地址:https://blog.csdn.net/sheziqiong/article/details/126814327