欢迎来到三一办公! | 帮助中心 三一办公31ppt.com(应用文档模板下载平台)
三一办公
全部分类
  • 办公文档>
  • PPT模板>
  • 建筑/施工/环境>
  • 毕业设计>
  • 工程图纸>
  • 教育教学>
  • 素材源码>
  • 生活休闲>
  • 临时分类>
  • ImageVerifierCode 换一换
    首页 三一办公 > 资源分类 > DOC文档下载  

    毕业设计(论文)基于Android手机电子书阅读器的设计与实现.doc

    • 资源ID:3978459       资源大小:5.71MB        全文页数:48页
    • 资源格式: DOC        下载积分:8金币
    快捷下载 游客一键下载
    会员登录下载
    三方登录下载: 微信开放平台登录 QQ登录  
    下载资源需要8金币
    邮箱/手机:
    温馨提示:
    用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP免费专享
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    毕业设计(论文)基于Android手机电子书阅读器的设计与实现.doc

    郑州大学毕业设计(项目报告)题 目: 手机电子书阅读器的设计与实现 指导教师: 职称: 讲师 学生姓名: 学号: 20117740444 专 业: 计算机科学与技术(软件测试) 院(系): 软件学院 完成时间: 2014年12月 2014年 12月 29日目录摘要11项目开发目标11.1项目来源11.2开发目标12项目总体设计22.1技术框架设计22.2数据库设计22.3功能框架设计53项目功能描述83.1软件欢迎界面模块功能描述83.2主界面功能描述103.3书籍管理模块功能描述123.4文件浏览模块功能描述163.5阅读管理模块功能描述203.5.1 章节管理模块功能描述243.5.2 书签管理模块功能描述273.5.3 搜索管理模块功能描述283.6设置管理模块功能描述293.7 使用帮助模块功能描述353.8 关于模块功能描述364项目技术总结384.1技术创新及特点384.2个人收获与体会444.3致谢44摘要在这个快节奏的时代,人们的空余时间越来越零碎,而且人们对智能手机的依赖越来越重,所以,一个拥有丰富功能且能随时进行电子书阅读的电子书阅读器的出现,则是我们刻不容缓的事情。此软件是在Android平台上进行设计开发,此软件的开发是通过了客户需求分析阶段以及技术可行性分析阶段,然后进行总体设计阶段和详细设计编码等阶段。此软件不仅具有基本的电子书阅读功能,而且还拥有丰富的实用功能设计,例如目录自动生成以及阅读界面设置、阅读休息提醒等。经过不断的测试与完善,电子书阅读器功能稳定,并且在真机上对其进行了测试与验证,基本上达到了用户的需求标准。关键字:电子书阅读器, Android,文件浏览,书架 1项目开发目标1.1项目来源此次开发的项目是手机电子书阅读器,属于自选项目。随着社会的发展,人们的生活节奏也越来越快空闲时间也越来越零碎,人们没有了大段的时间来进行书籍的阅读,所以一款能利用零碎时间进行随时阅读的软件成为了我们的需求。而一款能在人们随身携带的手机上运行的阅读软件成为了大家的选择。以前我们看看杂志,小说都要去图书馆借阅,而且时间有限,很不方便;而在电脑上看杂志,看小说,文档也是很不方便的。以此看来,一个好的手机阅读器软件的开发是相当有必要的。1.2开发目标手机电子书阅读器的开发目标就是让用户可以把零碎的空余时间有效的利用到书籍的阅读上,而且用户在没有网路的情况下也可以正常的进行书籍的阅读,让用户摆脱书籍的笨重携带不方便等确定,给予阅读者更大的便利性更好的舒适性。此软件是在Android平台上进行设计开发,它的界面丰富简洁但是却不简单,它包含了书架界面、文件查看界面、软件设置界面、书籍阅读界面等界面,它的功能全面。其优越性表现在:自动扫描手机里的所有书籍、手动从文件夹中选择添加书籍、自动为书籍生成章节目录、添加查看书签、全文关键词搜索、阅读主题选择、阅读字体大小设置等功能。此外,给用户更清晰方便的界面,也是本软件的出发点之一。2项目总体设计2.1技术框架设计手机电子书阅读器采用了常见的三层架构,分别为UI层、业务逻辑层和数据层。UI层:数据展示与管理、用户交互、绘制、Adapter。业务逻辑层:数据加式(数据层的数据有时候需要进行加工成UI层需要的数据)、数据变化的通知机制数据层:数据访问(SQLite、文件等)、缓存(图片、文件等)、配置文件(shared perference)此软件的开发环境:Windows7 + Eclipse4.2.0 + SDK。UI ViewsData AdapterUIBLData ObserverBLFileSQLiteData ProviderMemory CacheLocal DataUtil/ConfigData图1 软件框架结构2.2数据库设计E-R 图是直观表示概念模型的工具,它有四个基本成分:矩形框,表示实体类型。菱形框,表示联系类型。椭圆形框,表示实体类型和联系类型的属性。对于关键码的属性,在属性名下划一横线。直线,联系类型与其涉及的试题类型之间以直线连接。图2 ER图数据库使用了2个实体,分别为书籍、书签。书籍与书签的对应关系为1:n。在数据库的设计方面,为了实现数据库的完整性与一致性,我们使用了触发器,在数据库的选用上,选择了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎的SQLite数据库,数据库名称为eBook.db,共2个实体表,分别为书籍表、书签表。与书籍(books)实体类的属性信息对应的字段信息表如表1所示:字段名类型说明book_idINTEGER书籍编号book_nameTEXT书籍名称book_pathTEXT书籍路径file_sizeTEXT书籍大小last_readDATETIME阅读时间book_shelfINTEGER所属书籍read_percentageDOUBLE已读比例posINTEGER阅读位置表1 书籍表书籍表(books)创建的SQL语句:CREATE TABLE books (book_id INTEGER PRIMARY KEY,book_name TEXT NOT NULL, book_path TEXT NOT NULL UNIQUE, file_size TEXT,last_read DATETIME DEFAULT(datetime(CURRENT_TIMESTAMP,'localtime'),book_shelf INTEGER,read_percentage DOUBLE DEFAULT 0,pos INTEGER DEFAULT 0 ); 与书签(bookMarks)实体类的属性信息对应的字段信息表如表2所示:字段名类型说明idINTEGER书签编号book_idINTEGER书籍编号percentDOUBLE位置比例contentTEXT书签内容posINTEGER书签位置timeDATETIME添加时间表2 书签表书签表(bookMarks)创建的SQL语句: CREATE TABLE bookMarks ( id INTEGER PRIMARY KEY AUTOINCREMENT,"book_id INTEGER,"percent DOUBLE,content TEXT, pos INTEGER, time DATETIME DEFAULT ( datetime( CURRENT_TIMESTAMP, 'localtime' ); 触发器(fk_Delete)创建SQL语句:CREATE TRIGGER fk_Delete BEFORE DELETE ON booksFOR EACH ROWBEGINDELETEFROM bookMarksWHERE book_id = old.book_id;END2.3功能框架设计图3 功能模块图手机电子书阅读器软件主要分为8个功能大模块如图3所示,分别是欢迎模块、软件主界面、书籍管理、阅读管理、文件浏览、系统管理、使用帮助、关于。其中书籍模块中还要文件扫描模块,阅读管理中有章节管理、书签管理、搜索管理。系统设置中有密码设置。其各个模块的详细设计如下:1.软件欢迎模块。该模块主要实现的功能是,通过Handler来实现一个2秒的缓冲界面,然后通过SharedPreferences读取配置文件,判断是否有密码。如果有密码则跳转至密码验证界面;如果没有密码则判断是否为第一次使用此软件,如果是第一次使用则跳转至引导页面。2.软件主界面模块。该模块是一个通过TabHost标签组件来实现的一个分类管理功能。本界面的标签在屏幕的最下方,分别是:文件管理、我的书架、我的设置。点击不同的标签则显示不同的界面,默认显示标签为“我的书架”,打开选项中会出现对应的视图。实现了将本程序关联成手机默认打开程序中,即从外部打开文本文件时选择查看方式中会出现本软件图标供用户选择以本软件打开。3.书籍管理。该模块是以书架的模式来展现书籍,并可以对书籍进行一些操作,本模块共有3个书架分别为:“最近阅读”、“历史阅读”、“收藏阅读”,默认显示是“最近阅读”书架。本模块有导航按钮和书籍选择按钮。当弹出导航栏时,则把书籍从每行显示三本书籍调整到每行显示两本书籍。导航栏中与三大项:分类排序、添加书籍、清空书籍。每项里面又有子菜单。当点击导航里的按钮时会显示子功能导航,当再点击其它按钮时,会收起前面的子功能导航,展开当前的子功能。当单击书籍选择按钮时会弹出书籍选择窗口,选择里面的书架则进入相应的书架界面,同时还可以通过左右滑动来切换书架界面。当单击书籍时会打开相应的书籍阅读界面,长按某书籍时会弹出书籍操作窗口。4.文件浏览。该模块使用ListView组件显示文件目录,不同的文件类型显示不同的图标。最上面标题栏有导航按钮,当点击导航按钮时会从左侧弹出导航栏,导航栏中有标记文件按钮、分类排序按钮和添加到书架按钮,点击标记文件按钮或长按某文件或目录时则切换到多选模式,其中有多选按钮、反选按钮和取消按钮;点击分类排序则弹出子菜单,其中有按名称排序、按大小排序、按时间排序和按类型排序;点击添加到书架时如果为选择文件则自动进入多选模式让用户进行文件选择,如果用户未选择则提示“请选择书籍”,进行选择是用户可选择文件或目录,系统会自动进行扫描,把符合要求的文件添加到“最近书架”中,并弹出提示信息,其中有失败个数、已存在个数和成功个数。在多选模式下点击返回按钮或点击标记文件会取消多选模式。非多选模式下,用户点击文件时本软件会根据文件扩展名来判断打开文件方式,如果是文本文件则直接用本软件打开,并把其添加到“最近书架”中,其它格式则调用对应的软件打开,如果是未识别的类型则提示“没有打开此文件的应用”。5.阅读管理。该模块通过自定义一个View视图来显示书页,通过自定义类来读取文本内容并通过onDraw()方法把文件名、文本内容、电量信息、时间信息和已读百分比进行绘制成图片,并通过View来把绘制的图片显示出来。第一次进入阅读页面是会有显示引导页面来指导用户如何读本页面进行操作。本页面操作包括点击事件和滑动事件,点击左侧屏幕进行向上翻页,点击右侧屏幕进行向下翻页,点击屏幕中间画出菜单选项。此菜单是使用PopupWindow组件实现,菜单分上下两部分,上面的菜单有返回按钮、屏幕亮度调节按钮和添加书签按钮;下面的菜单有主题选择按钮、搜索按钮、书签按钮、目录按钮、字体大小调节按钮、翻页方式按钮、夜间模式切换按钮和退出软件按钮。6.系统设置。系统设置模块包括阅读设置和系统设置。阅读设置中有连续阅读模式、阅读完成时自动归类、阅读休息提醒和阅读空闲退出。连续阅读模式:下次启动直接进入上次阅读的界面进行继续阅读;阅读完成时自动归类:当书籍阅读到最后一页后对此书籍自动移至“历史阅读”书架中;阅读休息提醒:设置一个时间,当用户在阅读页面停留至这个时间时会弹出个提示框来提醒用户进行休息;阅读空闲退出:设置一个时间,当用户停留在阅读界面并且为对其未进行任何操作至这个时间时,系统会自动关闭本软件。系统设置中有显示隐藏文件、使用软件密码、退出确认、使用帮助和关于。显示隐藏文件:当用户选择此设置后会在下次启动本软件时在文件浏览中显示隐藏文件;使用软件密码:用户可以对此软件进行密码设置;退出时确认:当选择此设置后,退出软件时会显示一个确认框进行退出确认,未选择此设置时则会直接退出本软件;使用帮助:显示本软件的帮助信息;关于:显示关于本软件的信息。本软件的设置信息全部使用SharedPreferences存储。7.使用帮助。该模块通过读取帮助文件在TextView中显示,并且为TextView添加滚动条。文件中含有本软件的特点、功能介绍、操作说明等,。8.关于。该模块的主要功能是通过一个简单的弹出窗口来显示本软件的版本信息、联系方式。3项目功能描述3.1软件欢迎界面模块功能描述图4所示为欢迎界面模块,此模块作用是为了使软件的进入更连贯自然,让用户不感觉界面的出现突兀。两秒后跳入其它页面,如果有密码跳入密码验证页面如图6所示,如果是第一次启动跳入引导页面如图5所示。 图4 欢迎界面图5 引导界面 图6 密码验证界面关于欢迎页面启动的代码如下:new Handler().postDelayed(new Runnable() Overridepublic void run() Intent intent=null;initSaveData();/判断是否有密码if(share.getString("mi_ma", "").equals("")/判断是否为第一次启动if(share.getBoolean("first", true) edit.putBoolean("first", false);mit();intent = new Intent(WelcomeActivity.this,GuideMain.class);elseintent = new Intent(WelcomeActivity.this,ActivityMain.class);elseintent = new Intent(WelcomeActivity.this, GestureVerifyActivity.class);intent.putExtra("from_activity", 0);startActivity(intent);finish();, 2000);关于引导界面滑动事件代码:Overridepublic boolean onTouch(View v, MotionEvent event) switch (event.getAction() case MotionEvent.ACTION_DOWN: / 手指按下的X坐标downX = event.getX();break;case MotionEvent.ACTION_UP: float lastX = event.getX();/ 抬起的时候的X坐标大于按下的时候就显示上一张图片if (lastX > downX) if (currentPosition > 0) / 设置动画,mImageSwitcher.setInAnimation(AnimationUtils.loadAnimation( getApplication(), R.anim.left_in);mImageSwitcher.setOutAnimation(AnimationUtils.loadAnimation( getApplication(), R.anim.right_out);currentPosition-;mImageSwitcher.setImageResource(imgIdscurrentPosition% imgIds.length);setImageBackground(currentPosition); else Toast.makeText(getApplication(), "向右滑动", Toast.LENGTH_SHORT).show();if (lastX < downX) if (currentPosition < imgIds.length - 1) mImageSwitcher.setInAnimation(AnimationUtils.loadAnimation(getApplication(), R.anim.right_in);mImageSwitcher.setOutAnimation(AnimationUtils.loadAnimation(getApplication(), R.anim.left_out);currentPosition+;mImageSwitcher.setImageResource(imgIdscurrentPosition);setImageBackground(currentPosition); else Intent intent = new Intent(GuideMain.this, ActivityMain.class);startActivity(intent);finish();break;return true;通过xml设置引导页面动画,代码如下(以向左滑动为例):<?xml version="1.0" encoding="utf-8"?><set xmlns:android=" <translate android:fromXDelta="-100%p" android:toXDelta="0" android:duration="500"/> </set>3.2主界面功能描述图7所示是软件的主页面,这是一个通过TabHost标签组件来实现的一个分类管理功能。本界面的标签在屏幕的最下方,分别是文件管理、我的书架、我的设置。点击不同的标签则显示不同的界面,默认显示标签为我的书架,打开选项中会出现对应的视图。实现了将本程序关联成手机默认打开程序中,即从外部打开文本文件时选择查看方式中会出现本软件图标供用户选择以本软件打开。图7 软件主界面初始化选项卡代码如下:private void initTabs() myTabHost = (TabHost) findViewById(R.id.TabHost1);myTabHost.setup(this.getLocalActivityManager();/添加文件管理选项myTabHost.addTab(myTabHost.newTabSpec("tab_file").setIndicator(composeLayout("文件管理", R.drawable.folders).setContent(new Intent(this, FileExplorerActivity.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);/添加我的书架选项myTabHost.addTab(myTabHost.newTabSpec("tab_books").setIndicator(composeLayout("我的书架", R.drawable.books).setContent(new Intent(this, BookShelf.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);/添加我的设置选项myTabHost.addTab(myTabHost.newTabSpec("tab_setting").setIndicator(composeLayout("我的设置", R.drawable.setting).setContent(new Intent(this, MySetting.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);myTabHost.setCurrentTab(1);myTabHost.setOnTabChangedListener(new OnTabChangedListener();updateTab(myTabHost);将程序关联成Android系统默认打开程序代码:<activity android:name="com.zzu.ebookreader.ActivityMain"><intent-filter><action android:name="android.intent.action.VIEW"></action><category android:name="android.intent.category.DEFAULT"></category><data android:mimeType="text/plain"></data></intent-filter> </activity>接收从外部传来的参数并处理的代码:Intent intent = getIntent();String action = intent.getAction();if (intent.ACTION_VIEW.equals(action) String res_path = ""try res_path = URLDecoder.decode(intent.getDataString(), "utf8"); catch (UnsupportedEncodingException e) e.printStackTrace();3.3书籍管理模块功能描述图8所示是书籍管理主页面,最上面标题栏有导航按钮和书籍选择按钮。当点击导航按钮时会从左侧弹出导航栏如图9所示,并把书籍从每行显示三个调整到每行显示两个。当点击导航里的按钮时会显示子功能导航,当再点击其它按钮时,会收起前面的子功能导航,展开当前的子功能。当单击书籍选择按钮时会弹出书籍选择窗口,选择里面的书架则进入相应的书架界面,同时还可以通过左右滑动来切换书架界面。当单击书籍时会打开相应的书籍阅读界面,长按某书籍时会弹出书籍操作窗口如图10所示,书籍操作窗口中有删除阅读记录、删除阅读记录和文件、移动到历史书架、移动到收藏书籍、查看书籍详情和分享本书,不同书架中的操作项略有不同。 图8 书架效果页面图9 导航栏页面 图10 书籍操作窗口初始化ViewPager的核心代码如下:private void InitViewPager() mPager = (ViewPager) findViewById(R.id.vPager);listViews = new ArrayList<View>();Intent intent = new Intent(BookShelf.this, BookShelfActivity.class);intent.putExtra("book_shelf", MyConstant.BOOKS_RECENTLY);listViews.add(getView("BookShelfRecently", intent);Intent intent2=new Intent(BookShelf.this, BookShelfActivity.class);intent2.putExtra("book_shelf", MyConstant.BOOKS_HISTORY);listViews.add(getView("BookShelfHistory", intent2);Intent intent3=new Intent(BookShelf.this, BookShelfActivity.class);intent3.putExtra("book_shelf", MyConstant.BOOKS_COLLECT);listViews.add(getView("BookShelfCollect", intent3);adapter = new MyPagerAdapter(listViews);mPager.setAdapter(adapter);mPager.setCurrentItem(0);mPager.setOnPageChangeListener(new MyOnPageChangeListener();单击书籍跳转至阅读页面进行阅读代码如下:private void goReadActivity(BookInfo tem) if(new File(tem.bookPath).exists() Intent intent = new Intent(BookShelfActivity.this, ReaderActivity.class);bundle = new Bundle(); bundle.putInt("id", tem.bookId); bundle.putString("name", tem.bookName); bundle.putString("path", tem.bookPath); bundle.putInt("pos", tem.pos); bundle.putDouble("percentage", tem.readPercentage); intent.putExtras(bundle); startActivity(intent); elsebooksTableOperate.delete(tem.bookId);adapter.notifyDataSetChanged();Toast.makeText(BookShelfActivity.this, "书籍文件不存在,移除记录", Toast.LENGTH_SHORT).show();书籍排序的核心代码(以按时间排序为例):SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");try long time1 = format.parse(book1.lastRead).getTime();long time2 = format.parse(book2.lastRead).getTime();if (time1 < time2) return 1; else if (time1 > time2) return -1; else return book1.bookNpareToIgnoreCase(book2.bookName); catch (ParseException e) e.printStackTrace();分享本书的代码如下:Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); sendIntent.putExtra(Intent.EXTRA_TEXT, ""+selectBook.bookName+""+"这本书还不错,分享给大家看看!"); sendIntent.setType("text/plain"); startActivity(sendIntent);点击添加书籍中的快速扫描按钮,进入此界面开始扫描,通过自定义文件名过滤类来进行搜索并显示正在扫描界面,其中有扫描到的文件数目如图11所示。扫描完成后使用ListView组件显示扫描结果,最上面标题栏有返回按钮、我的书籍标题、重新扫描按钮。当长按某文件时则切换到多选模式如图12所示,最上面标题栏改变为标记全部按钮、选中的文件数目显示、加入书架按钮、取消按钮。多选模式下可以点击文件进行逐个选择,也可进行全选和取消全选操作。当用户选择是标题栏上会有对应的已选文件个数显示。选好之后点击加入书架将会把选中的文件加入最近书架中,也可以点击取消则取消多选模式。图11 正在扫描图12 多选模式时时显示扫描到的文件个数部分代码:Handler handler = new Handler() public void handleMessage(Message msg) if (msg.what != -1) numText.setText("" + msg.what); else listData = listTem;ll.setVisibility(View.GONE);super.handleMessage(msg);class UpdataBooks extends Thread Overridepublic void run() handler.sendEmptyMessage(1);getAllFiles(file);handler.sendEmptyMessage(-1);扫描文本文件部分代码:public void getAllFiles(File root) File files = root.listFiles(new MyFileFilter(false,"txt");if (files != null) for (File f : files) if (f.isDirectory() getAllFiles(f); else if ( f.length() > 1024 * 100) Map<String, String> tem = new HashMap<String, String>();tem.put("fileName", f.getName();tem.put("filePath", f.getAbsolutePath();tem.put("fileSize", getFileSize(f.length();num+;handler.sendEmptyMessage(num);listTem.add(tem);isSelect.add(false);3.4文件浏览模块功能描述下面是文件浏览模块主页面,使用ListView组件显示文件目录,不同的文件类型显示不同的图标如图13所示。最上面标题栏有导航按钮,当点击导航按钮时会从左侧弹出导航栏如图14所示,导航栏中有标记文件按钮、分类排序按钮和添加到书架按钮,点击标记文件按钮或长按某文件或目录时则切换到多选模式,其中有多选按钮、反选按钮和取消按钮;点击分类排序则弹出子菜单,其中有按名称排序、按大小排序、按时间排序和按类型排序;点击添加到书架时如果为选择文件则自动进入多选模式让用户进行文件选择,如果用户未选择则提示“请选择书籍”,进行选择是用户可选择文件或目录,系统会自动进行扫描,把符合要求的文件添加到“最近书架”中,并弹出提示信息,其中有失败个数、已存在个数和成功个数。在多选模式下点击返回按钮或点击标记文件会取消多选模式。非多选模式下,用户点击文件时本软件会根据文件扩展名来判断打开文件方式如图15所示,如果是文本文件则直接用本软件打开,并把其添加到“最近书架”中,其它格式则调用对应的软件打开,如果是未识别的类型则提示“没有打开此文件的应用”。 图13 文件浏览页面图14 文件浏览导航栏图15 打开视频文件文件路径导航实现代码:public void navigationBar() String strPath = null;try strPath = currentParent.getCanonicalPath().split("/"); catch (IOException e1) e1.printStackTrace();tvpath.removeAllViews();for (int i = 1; i < strPath.length; i+) final FrameLayout frameLayout = new FrameLayout(FileExplorerActivity.this);final LinearLayout linyou = new LinearLayout(FileExplorerActivity

    注意事项

    本文(毕业设计(论文)基于Android手机电子书阅读器的设计与实现.doc)为本站会员(laozhun)主动上传,三一办公仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知三一办公(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    备案号:宁ICP备20000045号-2

    经营许可证:宁B2-20210002

    宁公网安备 64010402000987号

    三一办公
    收起
    展开