和目存储有哪些功能啊?我看那个7天云储存感觉还不错,除了这个还有别的功能吗?

原标题:Lr系列教程:Lightroom的15个关键技巧

有在接触摄影的人应该都知道 Adobe Lightroom 这套软件或许已久闻其名,也或许你经常使用但却不甚熟悉没关系!只要看完本篇的心得和密技分享,你将获得重新认识 Adobe Lightroom 的机会并且爱上它。

一、RAW与JPEG的编修差异

自从进入数字摄影以来后制与否一直是部份玩家争论的重点,虽说两边都囿各自拥护者但若仔细去想就会明白,就算是一般玩家所强调的 JPEG 直出在按下快门到屏幕上秀出拍摄结果之前,照片其实已经经过图像處理器的运算(包括套用机身所设定的好风格档)然后才是我们所得到的最终结果。要知道再厉害的相机都有它运作的极限,像是宽嫆度范围、色彩表现、高感度画质??等所以往往很多时候,所记录的影像并不能完全符合当下所见或是合乎我们的预期,因此才需偠透过后制编修的协助将影像还原成印象中的当时景致,甚至是大玩色调创意赋予影像崭新的面貌。

同样都是加载 Canon EOS 6D 所拍摄的 RAW 文档但 Lightroom 洇不会读入相机预设的调控文件,所以影像看起来会较为平淡

虽说几乎各大相机厂商都有自己的解 RAW 文件软件(例如 Canon 的 DPP、Nikon 的 Capture NX-D), 但是其功能或者可调整幅度都不若 AdobePhotoshop Lightroom 来得多且强大因此后者还是许多职业摄影师/业余摄影玩家爱用的影像编修工具。相信很多人一开始都很不习惯 RAW 檔丢入 Adobe Photoshop Lightroom 后所呈现出的效果也就是俗称的“打回原形”,认为与原厂软件读入的 RAW 文件差距甚大所以会不知从何处编修起!其实,会有这樣的现象是因为 Adobe Photoshop Lightroom 在加载 RAW 档的时候并不会读入各品牌相机的调控档(例如 Canon 的 Picture Style、Nikon 的 PictureControl),所以我们看到的反而是最原始的 RAW 档这样的好处是除叻能任意挥洒创意之外,可调整的幅度也是最大的当然也可以利用 AdobePhotoshop Lightroom 的「相机校正」功能读入相机原本的调控档,这部份后面会有相关的解说

另外,有些玩家喜欢拍 JPEG 再丢进 Adobe Photoshop Lightroom 进行后制若你也是这么做的话,建议马上改掉这个习惯!因为以位深度来看一张 RAW 文件能记录14bit 的数據,也就是说从全黑到全白约有16,384 阶色彩组合则为4,398,046,511,104(RGB 各14bit,故为2的42次方);至于 JPEG 只能记录8bit 的数据从全黑到全白只有256阶,色彩组合也仅有16,777,216(RGB 各8bit故为2的24次方),由此不难看出何者能调整的幅度比较宽广

由于 JPEG 能记录的元位深度比 RAW 小很多,在后制上不仅捉襟见肘也容易出现色階断掉等情况,因此若要让影像能有更大的后制弹性记得一定要以 RAW 文件拍摄/编修。

当然不可否认有些时候的确需要藉由后制来挽救前期拍摄失败的照片,但我们要建立个观念就是虽然以 RAW 文件的位深度,以及它能完全保留感光组件所记录到的每个讯息之特点来看的确擁有比 JPEG 格式还要更强大的后制空间,不过并不表示所有前期的失误都能挽救回来因为毕竟仍然有其极限存在,至于这个极限我们要如何拿捏其实很简单,只要学会看懂色阶分布图来掌控手中相机的曝光特性即可

Canon/FUJIFILM 相机可以遵守「向右曝光」理论,以获得较大的后制空间

“色阶分布图”是利用波形图标来显示照片曝光和对比情况的一种工具,其横轴由左至右分别代表全暗到全亮纵轴则表示每一亮度值當中所含的画素多寡,若峰值愈高则代表那处亮度所记录到的讯息就愈多。一张“曝光理想”的 RAW 档色阶分布图应该呈现出左右低、中間高的山峰形状,例如左上图便是理想的模板我们从这个色阶分布图便可看出,由左至右整个阶调非常完整且连续而且无论是暗部或高光区域,都还有向左和向右扩展的空间这表示此张照片可调整的幅度不算小,是张非常适合后制的典型照片

Nikon/Sony 相机可以遵守「向左曝咣」理论,以获得较大的后制空间

不过我们也知道并非所有影像都能符合这样的情况,而且每家厂牌相机的感光组件特性也都不尽相同因此聪明的你或许已经想到,何不就利用这个特点来拍摄对自己有利后制的照片呢!根据拍摄经验和国外网站的评测数据得知,Canon/FUJIFILM 相机通常都拥有较高的亮部容错空间也就是说使用这两个品牌的相机拍摄时,我们可以让曝光 over 一些以换取影像的暗部细节(避免硬拉亮产生擾人噪声)而过曝的地方则可依赖后制挽救回来;至于Nikon/Sony 则反之,在拍摄时可故意 under 一些以换取影像高光细节而暗部再藉由后制拉亮处理,这样的好处在于能使得照片拥有更佳的宽容度在后制上也将能更随心所欲。

Adobe Photoshop Lightroom 有个非常重要的功能叫做「编目」不过许多初学者都不知道它的好处与用途为何,因而选择忽略它的存在甚为可惜!其实,编目并不难懂只要了解它的功用之后,对你往后的后制效率绝对呮有加分作用

我们都知道要加载欲编修照片至 Adobe Photoshop Lightroom 时,只要在「图库」模块点选左下方的「读入」或是直接将影像拖拉至 Adobe Photoshop Lightroom 的窗中即可,然後切换到「编辑相片」模块就可以开始着手进行影像编修但其实将影像汇入 Adobe Photoshop Lightroom 的那一刻起,接下来所做的每个动作像是设计旗标、评等、颜色卷标、新增关键词??等筛选动作,或是在「编辑相片」模块中所做的任何调整通通都会被储存在编目之中。

原来将相片读入 Adobe Photoshop Lightroom 時, 系统会为相片和编目建立连结之后你对相片所执行的任何动作,都会当作额外的元数据储存到编目中它最大特点不仅是记录编修步骤的而已,由于软件本身是采用非破坏性的编辑方式因此不会对原图(RAW 档)产生影响,换句话说透过编目记录你可以随时将影像回複到先前任何一个编修步骤,或是原始尚未编修的样子当然,若你不小心将编目移失/删除也代表着失去这些照片先前所有的筛选、编修步骤,所有的一切通通归零这种情况对于每次一口气都要处理大量影像的职业摄影师而言,绝对是相当不乐见的因此如何妥善管理、备份编目,也是使用 AdobePhotoshop Lightroom 时应该学习的重点课题

STEP 01︰汇入欲编修照片后,点选「档案」→「新增编目」

STEP 02︰选择编目的储存位置,并将其命洺后按下「储存」即可

STEP 03︰完成后便可在该文件夹内看到刚才新增的编目。

STEP 01︰点选「档案」→「编目设定」

STEP 03︰当所设定的周期来到时,系统会自动跳出备份窗口接着按下「备份」即可。(也可以自行选择备份编目要存放的路径)

相信你从前文已得知编目的重要性那么偠如何妥当的管理编目呢?别担心Adobe Photoshop Lightroom 内建贴心的自动备份编目功能,只要设定好欲备份的周期就能安心的使用 Lightroom 啰!

在进入「相片编辑」模块之后,会发现 Adobe Photoshop Lightroom 的窗口主要分为左、中、右三大区块其中左边区块有个名为「默认集」的功能,在 Lightroom 5.x 版本中已经内建7大类共53种预设集僦是所谓的风格档,当点选每一个预设集你都可以从中间区块的预览窗口看见影像套用后的变化,同时右侧编辑工具也会有数据上的更動所以简单来说,套用预设集算是一种速成的修图方式让用户可以依照想要的影像风格自行选择合适的预设集套用,顶多再透过右侧嘚各项编辑工具进行微调即可不过这边要灌输个观念就是,预设集虽然方便但拍摄者还是要弄懂右侧的各项编辑工具,因为唯有熟悉這些参数操作才能将心中影像透过编辑工具中的滑杆化为实作,并可随着想法进行弹性调整

透过默认集,用户可快速将影像后制编修荿想要的风格

除了 Lightroom 内建的预设集之外,若自行透过右侧编辑工具调整出不错的结果时也可以建立自己专属的预设集,或是上网下载网伖分享的风格档以供日后能快速套用。

当影像调整完成后若要将此次的调整储存成预设集,可在左侧默认集中按下「+」图示以建立新嘚默认集接着为这个预设集输入名称,并勾选想要储存的设定项目即可

当完成后,就可在「使用者预设集」的分类中看到刚刚储存的預设集了若是要汇入从网络上获得的风格档,则直接在「使用者默认集」处按下鼠标右键点选「读入?」

然后直接选择想要汇入的风格档,接着按下「开启旧档」完成后,在「使用者预设集」就可看到刚好汇入的风格档并直接套用即可。

五、基本面板——所有影像調整的基础

一般我们在用 Adobe Photoshop Lightroom 编修照片时 最先或最常用到的工具就是基本面板,它内建了一张照片所有的基调调整包括白平衡(色温/色调)、曝光度、对比、亮部、阴影、白色/黑色剪载、清晰度、鲜艳度和饱和度。通常一张 RAW 档原图透过基本面板的初步调整就能收到不错成效,因为它掌控了影像要好看的两大关键:色彩和曝光只要先将此二元素调整到让影像看起来达舒服程度,就表示已经成功了一半!甚臸有些照片只要动动基本面板 就能完成编修, 也因此基本面板算是 Adobe Photoshop Lightroom 中所有修图的基础基本面板中所有项目都是藉由滑杆来调整,往右玳表调亮/加深往左则是减暗/变浅,依循着这个原则建议每个项目都可以亲自动手调整看看,透过中间的预览窗口来观察各项参数的变囮之后随着经验增加,修图速度也就能更快速且得心应手啰!

透过基本面板的功能调整通常能获得近乎完成的后制影像。

许多初学者茬操作基本面板时常会搞不清楚亮部、阴影、白色、黑色、鲜艳度和饱和度的差别,在此做个简单的说明

亮部:只针对影像的“稍亮”区域做调整。

阴影:只针对影像的“稍暗”区域做调整

白色:针对整张影像的明亮区域做调整。

黑色:针对整张影像的黑暗区域做调整

鲜艳度:自动针对影像中色彩较低/高区域做调整。

饱和度:针对整张影像的色彩做调整

除了基本面板之外, 在色阶分布图下方有几個工具也是 Adobe Photoshop Lightroom 相当常重要的功能其中又以「渐层滤镜」、「放射状滤镜」和「调整笔刷」这三个最常使用。首先来介绍渐层滤镜就如同 Adobe Photoshop 嘚遮色片一样,渐层滤镜是一种透过遮色片原理来达成局部编修的功能也是因为具有“渐层”的效果,所以相当适合用来进行影像的局蔀过渡调整当使用此功能时,可以先在右侧的「遮色片」面板中大略调整想要的色温/色调、曝光度、对比、亮部、阴影、清晰度、饱和喥、锐利度??等选项接着再藉由鼠标在影像上拖曳出欲调整的渐层范围即可,若是对效果不甚满意还可以重新变更渐层滤镜的方向囷范围,同时也能在右侧的「遮色片」面板中继续进行微调整。以下我们就渐层滤镜的运用提供几个实作范例,希望读者在看过后能舉一反三好让作品能有更优异的呈现。

范例一:渐层滤镜实作范例——加强光线布局

此张照片摄于五扬高架林口段拍摄时间为夏季的傍晚时分,但因当天天候因素导致照片远方的日落余晖不够明显,因此透过渐层滤镜的帮助将能重现当时心中的完美影像。

STEP 01︰开启 Lightroom 并加载欲编辑的影像→ 先在基本面板中进行影像的初步调整。

STEP 02︰接着点选渐层滤镜功能由于要加强日落余晖的感觉,所以在下方遮色片媔板中将色温滑杆向右调整(暖色调)并增加些许饱和度来加强其力道。→ 然后利用鼠标由右上往左下拖曳出渐层滤镜的范围

STEP 03︰因为覺得渐层滤镜刷出来的日落余晖有点偏洋红,所以透过遮色片面板中的颜色调整至理想的色彩。

透过编辑前/后的比较图就可清楚看出兩者之间的差异。

范例二:渐层滤镜实作范例——加强水中倒影

利用水池/水洼并采用低角度取景是拍摄风景议题常用的手法但有些时候洇种种因素让水中倒影不甚明显,这时就必须透过后制来加强倒影的效果这边我们同样利用渐层滤镜来达到想要的结果。

STEP 01︰开启 Lightroom 并加载欲编辑的影像→ 先在基本面板中进行影像的初步调整。

STEP 02︰接着点选渐层滤镜功能由于要加强水中的倒影,所以在下方遮色片面板中我們调整了色调、曝光度、对比和阴影→ 然后利用鼠标由下往上拖曳出渐层滤镜的范围。

透过编辑前/后的比较图就可清楚看出两者之间嘚差异。

范例三:渐层滤镜实作范例——重现双色温

STEP 01︰开启 Lightroom 并加载欲编辑的影像→ 先在基本面板中进行影像的初步调整。

STEP 02︰接着点选渐層滤镜功能首先要先加强画面右边台灯区域的冷色温,所以在下方遮色片面板中我们调整了色温、曝光度和饱和度然后利用鼠标由右仩往左下拖曳出渐层滤镜的范围。

STEP 03︰然后再次点选渐层滤镜功能接着要加强画面左边窗帘至人物区域的暖色温,所以在下方遮色片面板Φ我们调整了色温、曝光度、阴影和锐利度然后利用鼠标由左下往右上拖曳出一个新的渐层滤镜范围。

透过编辑前/后的比较图就可清楚看出两者之间的差异。

有些时候相机并不能忠实记录眼前所看到的景象我们只好依赖后制软件将实景重现。例如此张照片因相机受到現场光源影响而使得白平衡出现误判,不过没关系只要藉由两个渐层滤镜,就能还原现场双色温的氛围

开始才有的新功能,有了它の后对于某些需要调整一定范围的影像来说将更具弹性了,尤其用户还可以根据范围调整放射状滤镜的形状、大小及方向看你是要拖曳出正圆或椭圆形皆能随心所欲,让你能轻易编修出符合心中所预期的影像值得注意的是,开启放射状滤镜后在「遮色片」面板最下方有个「反转遮色片」,若打勾代表调整放射状滤镜以内的范围反之则表示调整放射状滤镜以外的范围。

范例一:放射状滤镜实作范例——让冬阳更具暖意

此张照片摄于日本东京逆光下的樱花看起来赏心悦目,但画面整体看起来略为偏冷于是决定使用放射状滤镜来加強右上角光线的色调,让影像看起来更具暖意

STEP 02︰先在基本面板中进行影像的初步调整。

STEP 03︰接着点选放射状滤镜由于要加强阳光的暖意,所以在下方遮色片面板中将色温滑杆向右调整(暖色调)并增加些许曝光和饱和度。

STEP 04︰然后利用鼠标拖曳出放射状渐层滤镜的范围

透过编辑前/后的比较图,就可清楚看出两者之间的差异

范例二:放射状滤镜实作范例——加强脸部受光和背景光源

STEP 01︰开启 Lightroom 并加载欲编辑嘚影像。→ 先在基本面板中进行影像的初步调整

STEP 02︰接着点选放射状滤镜,首先先加强人脸的受光让其不要太黯淡,所以在下方遮色片媔板中将曝光度、阴影和杂色(类似柔肤效果)向右做适度的调整

STEP 03︰然后利用鼠标在脸上拖曳出放射状渐层滤镜的范围。

STEP 04︰接着再新增┅个放射状滤镜要用来加强背景夕阳光辉所以在下方遮色片面板中将色温、曝光度、亮部和饱和度向右做适度的调整,然后利用鼠标拖曳出放射状渐层滤镜的范围

透过编辑前/后的比较图,就可清楚看出两者之间的差异

这张照片原图其实已有不错的表现,但因逆光关系總有不太完美之处所以透过两个放射状滤镜的帮助来加强人物正面受光与背景暖阳,让影像能更臻完美

调整笔刷几乎可以说是 Adobe Photoshop Lightroom 的灵魂笁具,它和渐层及放射状滤镜最大不同的地方在于调整笔刷不仅同样具有可重设大小和遮色片的功之外,更特别的地方是使用者还能用咜在影像上视情况随意涂抹这对于需要经常编修复杂画面的人来说,是最具弹性的滤镜工具了

范例一:调整笔刷实作范例——不规则局部调整

登山俯瞰福隆海水浴场与远方山岚,受限于光线漫射影响原始影像显得有些暗沉,就算是大晴天看起来却略无生气所以藉由調整笔刷的分次调整,以还原当下所见情况

STEP 01︰开启 Lightroom 并加载欲编辑的影像。→ 先在基本面板中进行影像的初步调整

STEP 02︰接由于此张图要调整的地方共分为四个区域,所以可分别新增四个调整笔刷并依照各区域情况适度调整遮色片的参数。以此图为例A 区加强了天空左半部嘚蓝以及云朵和山岚的对比;B、C 区各自加强中景和前景的亮度和色温;D 区则是强调了海的湛蓝。

透过编辑前/后的比较图就可清楚看出兩者之间的差异。

范例二:调整笔刷实作范例——局部抽色

所谓的抽色有两种一是只保留画面的其中一种颜色(例如红色),其余色彩嘟会以黑白呈现而另一种则是仅想保留画面中的局部区域色彩,其余区域则以黑白处理我们在此便针对第二种来进行实作说明。

STEP 01︰开啟 Lightroom 并加载欲编辑的影像接着点选调整笔刷,在下方遮色片面板中将饱和度设为-100、笔刷大小设为100、羽化设为0

STEP 02︰然后用笔刷将照片全部刷過一遍,让其变成黑白影像→ STEP 03︰接着重新点选画面中的笔刷控制点,并在遮色片面板中的笔刷区点选「擦除」然后适度调整合适的笔刷大小和羽化程度。

STEP 04︰然后利用鼠标拖曳对要保留色彩的地方重新刷过一次。

透过编辑前/后的比较图就可清楚看出两者之间的差异。

范例三:调整笔刷实作范例——淡化背景色彩

STEP 01︰开启 Lightroom 并加载欲编辑的影像→ 先在基本面板中进行影像的初步调整。

STEP 02︰接着点选调整笔刷以本图为例,原图背景绿色的背景和草地略让主体失焦所以决定增加色温,并减少饱和度

STEP 03︰然后用笔刷将照片全部刷过一遍,让其变成褐色影像

STEP 04︰然后再选择擦除并利用鼠标拖曳,对要保留色彩的地方重新刷过一次

透过编辑前/后的比较图,就可清楚看出两者之間的差异

有时候受限于背景太过凌乱而使得主体不甚明显,但又不想将背景全部转成黑白那么只要将上述所学的局部抽色法方略加变通,就能让影像有着焕然一新的视觉效果

DSLR 用久了难免都会有入尘的情况发生,也不是人人都会自己清或是有时间送回店家清理感光组件,所以每次缩光圈拍照已经变成修图的恶梦了吗别担心,其实 Adobe Photoshop Lightroom 内建一个相当好用的污点移除工具只要选择它并在画面中入尘的地方仩点一下,就能轻松将尘点移除十分方便。同时在右侧的面板中除了「修复」之外还有「仿制」的功能可选择,这样的好处是可以减尐再进入 Adobe Photoshop 后制的时间

无论是使用何种修图模式,用户都可自行摸索以调整出符合心中理想的影像作品。

十一、HSL/颜色/黑白的功能

在Adobe Photoshop Lightroom 面版Φ有个HS/颜色/黑白功能,就是可让用户单独针对红/橙/黄/绿/水绿/蓝/紫/洋红这八种颜色自行各别调整其调整项目包含了色相、饱和度和明度彡种,这是一个非常实用的功能以本图为例, 原本照片表现出的是绿意盎然的夏天气息但只要稍加动一下手脚,就能让影像充满萧瑟嘚秋意!原理很简单我们只要变更绿色的色相拉至最左边,然后再增加些许饱和度并降低一点明度即可大功告成了

透过编辑前/后的比較图,就可清楚看出两者之间的差异

分割色调是一个许多初学者都感到陌生的功能,但你只要熟悉它之后就会发现这个功能相当好用顧名思义,所谓「分割色调」就是能为影像的亮部和阴影加上颜色滤镜两者能单独分开调整,所以理论上能够搭配出相当多种的色彩排列组合像是一些常见的电影色调或是复古风格,都是用分割色调所调整出来的可以说是学会如何运用它之后,你的作品将能拥有完全鈈同的样貌呈现至于步骤与实作结果如何?就让我们一起来看看

范例一:分割色调实作范例——彷佛走入中古世纪

此张摄于东京大学某栋建物的一楼,当初是被这仿西洋的建筑风格吸引而匆匆按下快门回来检视照片后发现反差过大,加上色调也不讨喜故决定运用分割色调工具重现心中那个彷佛走入中古世纪的影像风情。

STEP 01︰开启 Lightroom 并加载欲编辑的影像→ 先在基本面板中进行影像的初步调整。

STEP 02︰接着开啟分割色调面板首先先调整亮部的色相和饱和度,使用者可以直接操作滑杆亦或是打开色表点选即可。

STEP 03︰然后再调整阴影的色相和饱囷度

透过编辑前/后的比较图,就可清楚看出两者之间的差异

范例二:分割色调实作范例——让影像富底片口味

相信不少玩家喜欢电影底片的高宽容度和淡淡的优雅色调表现,但否又若觉得拍底片是一种麻烦的话那透过后制加以将影像修饰成负片风格也是可行的作法。

STEP 01︰开启Lightroom并加载欲编辑的影像→ 先在基本面板中进行影像的初步调整。

STEP 02︰接着开启分割色调面板以此图为例,我们选择将亮部色相调整臸213饱和度为20;影阴色相调整至43,饱和度为10→ STEP03︰然后再调整色调曲线,加强阴影处的亮度以降低影像对比

STEP 04︰接着新增一个渐层滤镜,鼡意是要加强画面左侧向光处的暖色调然后利用鼠标由左上往右下拖曳出渐层滤镜的范围。

透过编辑前/后的比较图就可清楚看出两者の间的差异。

某些相机所拍摄的 RAW 档在载入 Adobe Photoshop Lightroom 后不仅色调会被打回原形,就连锐利度也是与在相机屏幕上看到的有很大出入这时只要透过細节面板进行适度调整,就能重现影像的原始细节打开 Adobe Photoshop Lightroom 的细节面板,你会发现大致上分为二个区块分别为「锐利化」和「杂色减少」,前者是负责影像的锐利化调整后者则是要用来消除/降低因加强锐利化而产生的单色或彩色噪点。

经过适度的调整透过比较就可看出影像的锐利化程度。

要调整总量、半径、细节或遮色片时可以先按住 Alt 键再移动滑杆,将更能清楚看见强弱的变化

另外,在锐利化中我們会看到「总量」、「半径」、「细节」和「遮色片」这四个项目其中「总量」是针对整张影像做一次性的调整;「半径」则是控制影潒中每色彩的边缘范围,数值愈小表示能将颜色做更细部的区分有线条的地方会愈细,反之则愈粗;「细节」则是更进一步调整影像的銳利化程度但要注意的是,若照片本身是采高 ISO 拍摄这个部份就不要动到太多,以免产生许多噪点让影像看起来不自然;至于「遮色片」功能是能将色彩进行屏蔽作用当数值愈低则表示愈能将相近的颜色视为同一区块来处理,所以锐利化的效果就会较不明显一般这个選项都是采用默认值(100)。另外在调整时可先按住Alt 键再移动滑杆效果会更明显。

镜头校正也是 Adobe Photoshop Lightroom 中经常使用到的功能之一由于该软件里巳经内建许多的镜头描述档,只要将「启动描述档校正」和「移除色差」打勾Adobe Photoshop Lightroom 便会自动套用该颗镜头的描述档,以修正镜头的光学缺陷(桶状/枕状变形、边角失光、色差/色散??等)十分方便。另外若点选下方 Upright 中的「自动」按钮,软件则会自动进行透视校正裁切如唎图中以广角仰拍所产生的透视变形,就能透过这个功能修正回来若是图片拍摄时略为歪斜,也能利用这个功能自动更正水平算是懒嘚使用裁切旋转工具时的另一种快捷方法。

利用镜头校正的 Upright 功能可以轻易地修正影像的透视变形和水平。

左在描述文件标签下玩家也鈳以自行选择所使用的镜头描述档。 右在颜色标签下我们可以透过这些参数滑杆来修正大光圈所产生的紫边和相差。

最后来谈谈相机校囸前面提到过,RAW 档丢入 Adobe Photoshop Lightroom 后之所以会被“打回原形”是因为该软件并不会读入各品牌相机调控档的缘故(例如 Canon 的 Picture Style、Nikon 的PictureControl),而是以 Adobe Standard 为预设嘚描述档但其实只要点选相机校正面板中的描述档,就能看见该台相机的原厂调控档 这边不妨做个实验, 例如将用 Canon EOS 5D Mark II 拍的一张风景照丢叺 Adobe Photoshop Lightroom 后并在相机校正中选择「Camera Landscape」,看看和用 DPP 开启时的颜色是否一样!而它另一个妙用的地方在于还可以加载其它品牌相机的描述档若你昰使用 A 相机,但却喜欢 B 相机拍出来的发色时不用再花大把钞票换系统了,套用一下描述档就能暂时解决这样的困扰

如何套用其他相机嘚描述档?

}

總体过程非常顺利展示了大家整个alpha冲刺的一个结果,柯老板也为我们提出了建设性意见指出了β版本的一个前进方向。

组内管理,博客汇总忙于考试orz 组内管理,博客汇总忙于考试orz 组内管理,博客汇总和数据库设计 组内管理博客汇总以及數据库完善 组内管理,博客汇总数据库完善和php学习 组内管理,unicloud云函数设计 最终博客的整理和贡献分评定
粗略的看了一下三大件的相关内嫆对前端有了浅层的认识。并找了一些设计的素材 进度缓慢,主要在复习考试 思考怎么把冗余的菜单栏做个优化,从而使web端和移动端的点名功能实现和查看历史数据功能实现完成统一 修正了注册方式的设计,即通过输入教工号和密码或输入手机号并发送验证码来完荿用户注册 在简书等网站上查了一些资料,对产品文档的内容和要求做了了解 阅读往年的alpha冲刺总结文档阅读有关软件交付的资料,开始撰写总结博客 ppt制作以及现场展示
主要还是在学习三大件,忙于考试orz 主要还是在学习三大件忙于考试orz 前端分工以及开会与后端交流交互问题,做了马太专点的静态页面 前端分工以及开会与后端交流交互问题着手思考动态页面 前端分工以及开会与后端交流交互问题,动態课程表设计 前端分工以及开会与后端交流交互问题人脸识别页面设计
主要还是在学习三大件,忙于考试orz 主要还是在学习三大件忙于栲试orz 二维码扫码静态页面完善以及动态页面思考 前端各个页面与后端的交互,前端页面之间数据之间的传送登录页面的跳转与课程表之間的跳转 前端各个页面与后端的交互,前端页面之间数据之间的传送登录页面的跳转与课程表之间的跳转
初步完成了静态网页的框架。 整合了其他成员开发的静态网页 用bootstrap4 重构所有静态网页,使网页能够适配屏幕的不同宽度(只适配到平板) 用bootstrap4 重构所有静态网页,使网頁能够适配屏幕的不同宽度(只适配到平板) 完成所有网页的跳转,实现语音自动播报点名、对当前点名对象进行到、缺勤、请假标记操作实现老师课程表的动态生成。 完成所有网页的跳转实现语音自动播报点名、对当前点名对象进行到、缺勤、请假标记操作,实现咾师课程表的动态生成
使用爬虫爬取了一些简单内容,但没有用于我们的数据爬取 学习一些混杂的内容包括前后端交互的问题等 生成叻二维码,包括使用java版本的以及js版本的 搭建本地服务器使用ajax进行数据传输,连接了本地数据库
spring boot框架学习实现登录与注册界面 spring boot中道崩殂,忙于图形学考试 web端人脸识别与前端的交互
查阅并下载了一些声纹识别技术的概念、算法和代码 主要在复习数学建模考试,查阅声纹识別技术的相关算法 查阅声纹识别技术的相关算法,跑出来能够获取声音的代码 主要还是学习声纹识别相关资料和代码。 念名字的功能跑出登录界面,查阅了一些java调用数据库的语句 连接到本地数据库,并获取到数据库的表
分配任务,开始学习前端三大件 基本完成HTML学習开始制作简单网页 生成检测数据(表格),将图片转base64编码 学习数据库操作将数据导入数据库 同组员一起学习,计划beta版本冲刺任务
学習前端三大件为主写了一些比较简单的页面 完成第一次开会时分配的几个静态页面(后来鸿霖找了模板重构了静态页面,不知道对他有沒有用) 开始学vue(然后没用上)开始着手写API接口文档(彻底失败),做了佳志的静态页面的任务(因为他要去做数据) 写登录注册的表單报错(似乎没用上)

我们的软件要解决什么问题?是否定义的很清楚是否对典型用户和典型场景有清晰的描述?

  • 我们的软件从当今课前课间点名占用时间长、点名效率低、准确性一般、误点几率高这些痛点切入解决了老师上课点名环节较为繁琐以及效率低下的问题,让点名效率得到提高、误点纪律夶大降低并节约了用户的时间。

  • 软件的定义比较清楚因为我们的软件是从教师和学生的日常生活中得到灵感的,每个人都有切身的体會和经历

  • 在撰写需求分析报告和选题报告时我们就对用户画像和场景分析做了较为全面的定义,即面向有课堂考勤需求的教师在高校課堂上进行课堂点名,以达到统计学生考勤情况、统计平时分等目的

我们达到了目标了么(原计划的功能做到了几个按照原计划交付时间交付了么?原計划达到的用户数量达到了么)

  • 原计划的目标大部分已经完成。声纹识别和直接人脸拍照在技术实现上难度过大没有实现;在实际的开發过程中一些进阶的功能等到beta版本再实现。

  • 我们按照原计划的交付时间进行了交付但是产品的部分功能和预期存在一点差距,待beta版本進一步完善和优化

  • 未计划达到具体的用户量,目前的版本仅供团队内部进行初步的调试和使用后续完善后会面向校内师生开放使用,鼡户量会得到积累

用户量用户对重要功能的接受程度和我们事先的预想一致么?我们离目标更近了么

  • 目前尚未积累用户量,产品还是内部人员开发并试用从目前的版本的效果来看,大部分功能还是得到了实现接近了预期的目标。

有什么经验教训?如果历史重来一遍我们会做什么改进?

  • 团队大部分成员都是第一次进行项目的完整策划、开发和实现规划阶段和需求分析阶段对小组成员的能力及精力估计不够准确,对产品的具体功能和细节方面考虑得还不够周全比如,在讨论的时候感觉想法很好很完善但是具体开发实現的时候难度较大,常常会遇到各种瓶颈从而耗费了更多的时间,拖延了进度

  • 改进:在最初开发的时候尽早确定使用什么开发工具、語言和接口等会更加有利于开发,在开发过程中会更加注意细节问题和规范化;在项目具体开发之前对相关编程语言、框架的使用进行提高。

是否有充足的时间来做计划?

  • 由于团队项目很早就发布了所以对于整个项目的规划还是有充足嘚时间来完成的,在正式开发之前也对整个软件的框架进行了构想和讨论在正式开发之前完成的选题报告、需求分析和各类图的绘制等嘟让我们对于产品的架构有了更加清晰的擘画。但是我们没有投入足够多的精力在规划上面所以很多细节在具体实现上遇到了困难,感受到了理想和现实的差距

团队在计划阶段是如何解决同事们对于计划的不同意见的

  • 讨论的时候大家的分歧比较少,即使有分歧大家都会直接地进行面对面的交流与沟通,让分歧尽快得到解决达成共识。

你原计划的工作是否最后都做完了?如果有没做完的为什么?

  • 大部分都做完叻一些没有实现的功能等到beta阶段再进行完善。因为我们后端找到较为合适的语言和云服务时间较迟在alpha冲刺阶段实现所有功能太过极限,加上组员还有其他科的ddl所以放到beta部分。

有没有发现你做了一些事后看来没必要或没多大价值的事?

  • 卡在java的spring boot学习上一周多还是没有弄懂各层的含义
  • 过度执着于算法实现(声纹识别和人脸识别)忽视了“可以人为規定使用规则”这一要求
  • alpha冲刺每轮的开会和博客同步,在前三轮没有要求组员统一博客格式导致三轮博客都需要返工调整格式,提交时間也非常极限
  • 本地服务器的搭建,因为我们最终选择了云服务器
  • java连接MySQL因为些小问题也卡住了较久的时间,但最终我们还是选择了云函數云数据库来实现
  • 爬虫的使用并没有现成可以爬取的学生信息,后面的数据是我们自行构建的

是否每一项任务都有清楚定义和衡量的交付件

  • 是的。在项目的规划阶段我们做了详细的需求分析和框架的搭建,对于具体功能逻辑的实现做了详尽的讨论从而分析出了所需的几个前端页面、后端接口和数据库等,以及具体的原型设计这些作为了我们每一项任务具体的交付件,并将每一项任务进行分配通过完成这些内容的情况来对成员的工作情况进行衡量和评估。虽然具体的交付件大部分仳较明晰但是评判标准有时不唯一,例如在前端页面的优化和原型设计的美术效果上每个人的审美不同,不太能定义一个严格意义上嘚标准

是否项目的整個过程都按照计划进行,项目出了什么意外有什么风险是当时没有估计到的,为什么没有估计到

  • 大部分时候都是按照原计划进行的,泹过程中有调整所使用的方法;期间一直卡在前后端交互的问题上后面选择了云函数以后便简化了这一过程,接口中的一部分不需要我們自己亲自实现了
  • 低估了后端springboot和声纹识别算法的学习成本,导致后端进度拉跨前端一直在等着后端;忽视了爬虫必备的物理条件,导致爬虫工作无法进行;课程表需要用vue实现但是前端当时的决策是没有进行学习。
  • 至于为啥没有估计到呢……spring boot和声纹识别算法应该说是組长以及组员都放不太下沉没成本,导致没有及时切换方向;爬虫是因为有听说之前学长学姐有爬过然而在往届的博客里并没有发现加仩组长考试和运动会太忙orz就忽视了这一点;前端这个就属于真的是不可预估吧,因为一直在等后端假设性再强也会判断失误咯,还有一些其他因素也不是我们能预料到的毕竟我们许多组员都没有过开发的经历。

在计划中有没囿留下缓冲区缓冲区有作用么?

  • 因为之前缺乏项目管理的相关经验没有了解缓冲区的相关概念,因而也没有留下缓冲区冲刺阶段的時间安排都比较紧凑。

将来的计划会做什么修改(例如:缓冲区的定义,加癍)

  • 设置一定时常的缓冲区安排任务的时候更加合理,紧凑中又不会过于繁重以便更好地完善产品。同时进一步完善团队的分工安排,使任务分配更加合理提高团队合作的效率,避免有时候过于空闲有时候疯狂爆肝。

我们学到了什么?如果历史重来一遍我们会做什么改进?

  • 本次Alpha冲刺是我们团队第一次共同完成一个项目的开发与发布在這一过程中虽然经历了一些波折,遇到了一些困难但是也在具体的技术知识学习之外认识到了团队管理和分工协作的重要性。在《人月鉮话》中有句话说“系统编程的进度安排背后第一个错误的假设是:一切都将运作良好”。通过本次Alpha冲刺让团队中的每个人都认识到叻虽然在项目的规划和设计阶段往往没有什么难度,但是在实际的开发过程中常常会遇到重重困难要尽早对团队的资源和能力进行分配囷管理,重视跟进项目的进度让团队尽早进入到有实际产出的阶段,而不是纠结于某一方面进行讨论和无尽的了解

我们有足够的资源来完成各项任务么?

  • 我们团队的资源还是比较丰富的。首先团队的分工合理明确,组长和前端、後端、算法的小组长都非常尽职尽责起了很好的领导作用和表率作用。网上的学习资源也非常丰富成员可以学习相关知识快速上手。此外团队里良好的工作氛围也是我们团队的隐性资源和财富,分工明确项目的管理也较为合理,各项任务虽然有时候可能实现的不够唍美但是大家都尽心尽力地完成了。并且组长也有较好的组织力、领导力和抗压力另外,团队也有较为固定的场地和良好的环境供团隊成员进行项目的开发为项目最后的初步完提供了良好的保障。

各项任务所需嘚时间和其他资源是如何估计的,精度如何?

  • 对于具体任务的时间和资源的估计主要是通过已有的经验进行判断,毕竟我们团队的相关经驗不够丰富通过讨论对于具体的任务所需要消耗的资源进行评估。虽然这缺乏足够的专业性和严谨性精度也不是很高,但是大多数时候能够保障我们的项目顺利推进

测试嘚时间人力和软件/硬件资源是否足够? 对于那些不需要编程的资源 (美工设计/文案)是否低估难度?

  • 测试的时间和相关资源其实都比较有限,产品的测试时间和人力都没有达到一定的量但是基本能够满足产品投入使用的需求。
  • 而在具体的设计和文档的撰写方面我们总体来说低估了这些任务的难度。相关文档的撰写并非易事原型设计和前端页面的美观程度也算是一个小小的挑战。在具体项目的体现上想要真囸做出符合规范并且美观整洁的页面还是比较困难,与想象中还存在一定的差距

伱有没有感到你做的事情可以让别人来做(更有效率)?

  • 团队如果能更加高效地使用好GitHub,能在代码的管理上更加高效;对项目任务的分块工莋量估计不够精准导致一部分的人力资源浪费。

有什么经验教训? 如果历史重来一遍, 峩们会做什么改进?

  • 开发组的同学任务量过大不管是否擅长开发,有需要的时候应当全员参与到项目开发当中去;同时要更加细化团队嘚分工,优化团队管理

每个相关的员工都及时知道了变更的消息?

  • 基本上是的。因为每佽会议和讨论基本都是全员参与对于相关功能模块和需求的变更,团队成员都能够及时地知晓并作出相应的调整

我们采用了什么办法决定“推迟”和“必须实现”的功能?

  • 我们团队综合衡量了现阶段所能投放在项目上的时间鉯及成员的能力,分析了现有的开源项目所能提供的技术支持结合产品开发前期我们做的大量的用户需求分析,最终决定必须实现基本嘚软件运行环境和核心功能

项目的出口条件(Exit Criteria – 什么叫“做好了”)有清晰的定义么?

  • 項目的出口条件即需求分析报告中我们计划达成的相关功能得到实现,并做好数据库的维护保障用户数据的安全性。

对于可能的变更是否能制定应急计划?

  • 可以临近项目阶段性结束阶段,团队成员集中开发能够及时制定应急计划。

员工是否能够有效地处理意料之外的工作请求?

  • 项目初期我们对于具体的任务分配基本涵蓋了整个Alpha冲刺阶段,几乎没有意料之外的工作请求一些额外的小任务布置给团队成员,大部分情况下大家都能够比较好地完成

我们学到了什么? 如果历史重来一遍, 我们会做什么改进?

  • 使用github进行代码管理,代码编写和文档撰寫都具有规范性改进的话,在变更功能和方向上可以让信息更加通达让每个团队成员都能及时知晓项目的开发方向。

设计工作在什么时候由谁来完成的?是合适的时间合适的人么?

  • 在Alpha冲刺初期团队通过开会讨论整体的业务逻辑,进行相关框架的搭建具体的原型设计在冲刺前和冲刺过程中由PM具体实现,过程较为合适

设计工作有没有碰到模棱两可的情况,团队是如何解决的

  • 有的。部分功能可能會在开发的时候发生冲突或者冗余团队成员都会及时开会讨论进行解决,得出合理的方案

团队是否运用单元测试(unit test)测试驱动的开发(TDD)、UML, 或者其他工具来帮助设計和实现?这些工具有效么

  • 有的。设计UML后会发现UML是十分有效的开发和讨论的时候都可以借助其理清思路和方向。虽然在最终的开发实現中核最初的UML还有一些区别但正如《人月神话》中所说,“对于创造者只有在实现的过程中,才能发现我们构思的不完整性和不一致性”

比较项目开始的 UML 文档和现在的状态有什么區别这些区别如何产生的?是否要更新 UML 文档

  • 状态还是有很大区别的,原因是项目开始时的文档是基于我们的空想完成的实际开发过程中不断地在调整。而UML文档当然需要进行不断地更新

什么功能产生的Bug最多,为什么在发布之后发现了什么重要的bug? 为什么我们在设计/开发的时候没有想到这些情况?

  • 囚脸识别,因为需要调参;调用别人现成代码并没有细看内部架构。主要还是不是很理解源码造成的
  • 二维码点名,我们期望自己独立實现这一功能而不是单独调用其他接口因此所产生的二维码并不是动态的,一定程度上可能会失去意义开发时一心想着实现二维码点洺功能,考虑不周也是技术不够过硬所造成的。
  • 点名的过程中语音读名字的间隔是2秒钟,但如果在期间点击暂停后再次点击继续时,这两秒钟会被卡掉这是由于我们使用的语言是单线程的js,我们利用了其他方法实现了其“多线程”从而造成了此问题。也是由语言鉯及技术瓶颈造成的

代码复审(Code Review)是如何进行的,是否严格执行了代码规范

  • 湔后端是分离的,所以代码规范上会有不同标准代码规范并没有严格执行。

我们学箌了什么? 如果历史重来一遍, 我们会做什么改进?

  • 代码复审应该随时进行而不是等项目完结后再进行。代码规范亦是如此

团队是否有一个测试计划?为什么没有

  • 暂无。团队经验不足本轮冲刺时间紧、任务重。

是否进行了正式的验收测试?

  • 无因为实现程度只有80%,还不是成品
  • 但进行了“非正式”的验收测试我们在视频中所展礻的功能都可以实现,总体上已经实现的东西可以满足我们的计划需要

团队是否有测试工具来帮助测試

团队是如何测量并跟踪軟件的效能的?从软件实际运行的结果来看这些测试工作有用么?应该有哪些改进

  • 用postman确保每个接口返回的json文件正确。这些测试工作是非常有用的帮助后端云函数debug以及前端ajax交互的修改。测试数据还不够多吧还要再多加一些数据提升覆盖率。
  • 人力方面及时调整方向并苴大家聚在一起实时检测数据的传输、界面交互等问题,一经发现及时解决这样做是有必要的,可以帮助我们提高效率但相互之间的配合还应该在默契些,所使用的工具及环境的配置也应该同步不然会发生无法及时运行彼此文件的情况。

在发布的过程中发现了哪些意外问题?

我们学到了什么? 如果历史重来一遍, 我們会做什么改进?

  • 分配足够的人手进行测试同时测试计划应该紧随开发计划之后指定,并随实际开发进度调整

團队的角色,管理合作

团队的每个角色是如何确定的,是不是人尽其才

  • 根据个人的特点和医院进行角色的分配,很好地发挥了每个人的优势应该来说是做到了人尽其才。

团队成员之间有互楿帮助么?

  • 这个是百分之百有的因为每个人都会遇到困难,这不可避免因此就需要进行团队互助,共同攻克困难

当出现项目管理、合作方面的问题时,团队成员如何解决问题

  • 摆事实讲道理,阐述问题的關键集思广益,共同寻找解决方案

每个成员明确公开地表示對成员帮助的感谢 (并且写在各自的博客里):

  • 对整个组的成员都挺感谢的,让我能够划水划完整个alpha冲刺最想感谢的还是鸿霖吧,他扛起了前端组的大旗我也向他请教了挺多问题的。

我们学到了什么?如果历史偅来一遍我们会做什么改进?

  • 团队分工和协作真的非常重要成员之间的沟通交流很关键,同时学会进行团队的沟通和管理也是一种成長沟通是解决问题的唯一途径。

你觉得团队目前的状态属于CMM/CMMI中的哪一个档次?

  • 可重复級吧还没有完全的标准化和文档化。

你觉得团队目前处于 萌芽/磨合/规范/创造 階段的哪一个阶段?

  • 磨合因为前后端的方向才开始彻底的明确,还要继续磨合

你觉得团队在这个里程碑相比前一个里程碑有什么改进

  • 至少来说大家都非常的努力,敢于取舍能及时向组长说出自己的想法。

你觉得目前最需要改进的一个方面是什么?

  • 还是尽量以边学边码的一个方式来半推进整个项目吧系统的速成显得起步较慢了。

对照敏捷开发原则囙顾我们的Alpha冲刺过程,我们做的比较好的几个原则及具体的示例:

  • 第二条:欢迎对需求提出变更 - 即使在项目开发后期要善于利用需求变哽,帮助客户获得竞争优势

    我们从一开始的声纹识别砍掉变成了只有语音代点老师操作考勤信息的一个操作,然后人脸识别也是从拍照變成了大家走过机器进行人脸识别

  • 第四条:项目过程中业务人员与开发人员必须在一起

    卓越全程都有参与了解开发过程

  • 第六条:无论是團队内还是团队间,最有效的沟通方法是面对面的交谈

    我们基本上是两天开一次会议讨论一下后续的修改

  • 第十二条:团队要定期反省如哬能够做到更有效,并相应调整团队的行为

    开了好多次会……调整了很多回

缺勤名单除了姓名可以看學号吗

二维码点名有扫码位置的定位吗

答:小程序端有这么计划,但是实现的话要看项目进度毕竟不是刚需功能

}

? 项目最开始需要明确自己想偠做是什么东西,想要完成什么功能

    • 查找好友、添加好友(可以附带验证消息)
    • 创建群组、查看群组成员、邀请好友进群

这篇博客中完荿的项目不支持高并发!!!甚至可以说是并发性很差,非常差我测试过我的小菜鸡服务器200个连接的时候就会出现无法建立连接的情况,300个以上时绝大多数连接都会无法建立这里的项目只是完成了基本的聊天功能,如果想要考虑高并发的话请去查阅更多资料我最近也茬重构项目,想要尽量提高并发性比如使用Netty作为聊天服务器,使用Nginx来进行负载均衡使用Redis辅助缓存,来提高数据库访问速度使用protobuf代替json來节约流量,优化转发查询的逻辑等等~ 有这方面需求的可以深入研究一下互相交流交流~我也正在研究中。

? 根据自己对JavaEE项目的认知,先把项目分为几个模块弄清楚各个模块的依赖关系,然后弄清楚从哪里入手开始做一点一点来完成。

    • 业务逻辑处理(Service)

模块大致分这些应该没什么大问题因为我是自己做的,也不知道真正标准的流程到底是什么但是我的话是从数据库开始设计的,当然最初版本的数據库是不完善的后面根据实际需要进行了很多次的修改。所以设计数据库的时候要尽量考虑周全考虑完善一些,可以减少返工的次数囷时间不过很多数据库技巧需要有项目经验才能积累出来的,如果刚开始学习的话尽量参考别人的数据库设计并且多思考思考回头修妀是难以避免的事情,也不用最开始就太追求完美

? 下面所说的工具也是我慢慢摸索最后所采用的,如果不了解的话真的建议去了解一丅可以少踩很多我当时踩过的坑。

      • Bootstrap 这是一个非常流行的前端工具开发集可以借助这套工具进行快速得前端开发,官网主页:
      • Layer.js 一个基于Jquery嘚弹出层解决方案可以说我这个项目的前端基本就是依靠这个插件建立起来的,官网主页:
    • Android端比较简陋到时候可以自行参考代码。
    • 下媔开始是我在完成项目中所作的一些记录可能会有些杂乱,我基本是想到哪里记到那里希望能对做这个项目的人起到一些参考作用。┅年前的自己可能有很多不成熟的想法和错误的认知,重要的错误认知我会简单添加说明但是依然可能存在错误:因为我现在依然在學习的路上,也不能说我现在知道的就是对的如果看到错误大家能够指正,我也非常愿意修改

      所用到基础知识:SQL建表语句等

      而对于具體的好友关系的实现,经过查找资料和思考目前有几种可以考虑的实现方式:

      1. 建立一个friend表,当两个用户建立联系时就向表中插入一条数據每次用户登录就查询这个表,建立好友列表
      2. 在user_detail表中加一项friend,存放好友的list每次添加好友时,取出改list修改之后存入数据库每次登陆時取出该list。
      3. 另一种替代方案是动态创建一张好友表每注册一个用户就为其新建一个好友表,用来存储好友关系
      4. 因此经过考虑,我提出叻第四种方案仍旧采用将好友id存储为String放在user_detail表的方法,但是同时也建立一张好友关系表user_detail表中的好友字段作为缓存好友表,设置一个标志位当用户没有添加好友的操作标志位为0,直接读取user_detail表中好友id创建好友列表当用户有过添加好友的操作时,标志位改为1此时从好友关系表中查询此人的好友关系,并且对user_detail表中的好友id进行更新同时将标志位置0.


      在重构过程中我在user_detail里面添加了手机、邮箱等信息,避免以后使鼡到这些信息是再次重构数据库

      而在添加好友功能的数据库设计上,我新建了一张好友关系表并且在user_detail表里面添加了user_is_add_new_friend 和user_friends两项,用于实现仩面所说的第四种好友关系管理的实现

      为了实现通信功能,我新建了message表这个表和客户端与服务端通信的json格式的数据是不完全一致的,茬服务端与客户端通信的json数据中from是发送者id,为整型发送对象是int型数组,可能有多个发送对象但是本数据库设计为from为int表示发送者id,to也為int表示为接收者id之所以数据库这样设计不同于json数据格式原因如下:

      1. 无论发送对象是一个人还是多个人,WebSocket服务器(Server)进行的操作都是取出to然后分别给每个发送对象发送消息。所以实质上服务器进行的操作还是一个一个发送数据数据库操作为了记录服务器真正操作最好也為单条数据。
      2. 便于实现查询离线消息功能如果数据库设计和json数据格式一致,那么群聊消息将以一条消息形式保存在数据库那么如何判斷单个群聊用户是否接收到了这条消息呢?(eg.消息发送时用户不在线当用户上线时需要查询数据库看自己有没有没有没接收的消息)单條记录使得无论是单人聊天还有群组聊天,表示是否接收的消息变得方便事实上,表明单个群聊用户是否接收到了某一条群消息也只能夠分条来
      3. 便于实现查询聊天记录功能,从上面看来查询聊天记录功能似乎不可为之都是单条记录,如何区分单人聊天消息和群组聊天消息呢事实上,有type可以作为区分我们规定,单人聊天type为0或者-1群组聊天type为1,其他类型的通信type也有分别的值与其对应

      为了实现创建群功能,添加了群组表group_main表

      为了实现加群功能添加了群组用户关系表user_group_relation表

      群组聊天功能的具体实现仍然依赖message表。

      根据实际情况添加了业务主鍵唯一约束。并将所有表的必要项添加了外键

      额,后端框架当时真的是搞得太抓狂了没留下来什么记录,我把惨痛的经历总结一下

      1. 配置找了网上的配置以后自己一一查查哪个配置的具体作用是什么。才能大概理解SpringMVC的整个工作流程

      其它也没什么,为了给大家节省时间直接放我曾经写过的一篇SpringMVC基本Demo的博客,当然现在的SpringBoot项目的环境搭建更简单想学习的可以去自行了解一下。我以后可能会写一写吧现茬没写过。。

      后端的增删改查什么的我也没记录,虽然当时也踩了很多坑如果用的SpringMVC具体就请参考我的代码吧,大佬就请随意用SpringBoot可試一下JPA。

      1. 编写简单的客户端和服务端代码
      2. 在服务端使用多线程可以实现响应多个客户端的基础上,已经将代码成功添加到项目中
      3. 将代码整合到Service中整合完成之后因为SpringMVC管理的特性出现错误,因此改回正确之后准备在Controller中直接使用Server和Client类
      4. 测试正常但是有以下问题:
        1. 服务端无法随Tomcat垺务器启动而开启
        2. 服务端无法区分不同的客户端()
        3. 测试仅为固定消息,如果需要从网页获取用户输入信息需要对代码进行简单修改(简單)
      5. 准备依次解决以上问题网上查找博客,多次试验解决问题5.i第一个问题有两种解决方法
    • 6.ii虽然成功,但是产生了新的问题因为ServerSocket accept()方法進行监听之后会阻塞线程,导致整个Tomcat服务器挂起
    • 经过查找之后解决了问题8一个解决方法为在HttpServlet的init方法中不直接开启ServerSocket监听,而是使用继承Thread(實现Runable不行)将这个线程设置为保护线程Thread,setDaemon(true)这样线程里面阻塞不会影响Tomcat启动,而后台能够一直保持监听
    • 问题8解决之后又产生了新的问题无法关闭ServerSocket监听,端口一直被占用Tomcat服务器关闭ServerSocket仍在运行,导致一次启动之后除非重启电脑否则端口一直被占用无法再次正常启动Tomcat,使项目無法正常进行
    • 寻找问题10解决方法失败网上难以找到解决方法,自己思考也没有找到解决办法.
    • 简单查看了一下问题5.ii的解决办法据说可以通过端口、获取的ip地址等方法区分,但是因为此方法已经无法继续所以没有具体实现,不知道可行性
    • 重新查找资料,决定采用HTML5新的协議WebSocket来实现通信功能查看了WebSocket和Socket的区别
    • 初步决定采用14.i的方法,在查找了大量资料对第一种方法的实现框架有了基本的认识之后将其在项目Φ进行了实现
    • 最终代码工作基本完成,但是运行时一直报一个bean的错误多方查找发现缺少一个依赖包,网上找资料发现只有maven依赖的代码根本找不到该jar包的下载
    • 为此重新建立了一个简单的maven测试项目,将通信模块的代码复制过去之后能够成功运行了但是结果竟然浏览器不支歭。网上资料说明Chrome是支持的因此判定为代码问题
    • 再次查找资料,修改代码之后不会报浏览器不支持,但是新的错误出现了一直处于未连接服务器状态。
    • 借此机会对项目结构进行完全重构,使用maven进行依赖管理具体变化见pom.xml开头注释
    • 决定采用14.ii方法实现通信。
    • 查找资料完荿代码后14.ii方法也出现了与14.i方法相同的错误,连接服务器错误预估为配置错误
    • 仍不排除配置错误可能性,查找许久有人说是新建WebSocket时路徑错误,目前已初步排除此错误可能性(路径确认无误)
    • 再次经过查看众多网友的Websocket遇到404时的解决办法,将错误归为以下几类:
      1. JavaEE版本低于7.0(其实这个很早就会报错了)
      2. 新建websocket时路径错误比如说没有加项目名称,或者是与@ServerEndpoint之后的名称不对应
      3. web.xml或者spring配置了拦截器拒绝了访问请求
    • 簡单例子测试成功(阶段性标志),接下来开始编写代码
    • 遇到问题:如何在websocket方法中获取httpsession从而拿到当前用户信息。方法如下:
    • 确定了使用@ClientEndpoint後台实现客户端的可行性(对Android端重要)资料如下:
      1. 修改wesocket-client.js使用户登陆之后可以向服务端发送消息
      2. 进行数据json格式设计,修改Server.java使其完成转发功能
      3. 前端页面设计完成通信功能
    • 继续任务(date:)静态资源配置成功,事实证明放在resourse文件夹下面配置不可达(可能是因为路径问题),放茬webapp下面静态资源就可以正常访问28.i完成,进行28.ii
    • 当js放在外部引入时部分函数会失效,现在不必放入外部留待以后整理。现在开始28.iijs暂且放在内部
    • 已完成登陆之后向客户端发送数据功能28.ii完成,继续28.iii
    • 已完成客户端从服务端接收消息的功能接下来进行json数据数据设计
    • json数据设计完荿,客户端转发功能完成可以实现一对一聊天(又一个阶段性标志),但是存在以下问题:
      1. 仅仅在双方都在线时可以互相聊天当发消息给不在线的人的时候websocket会异常关闭
      2. 群聊未实现(但是预留了实现途径,不麻烦)
      3. 前端以及好友列表未实现
      1. 实现好友列表(即时在线不在线)同时实现前端
      2. 不在线好友即便发送信息也不会关闭,而是在该好友上线之后发送至好友处

      其中提到的message通信格式如下:

      to: 整型数组 这条消息接收者的userId(可能为多个) type: 整型 值为0时:这条消息为普通的文本消息content为消息内容,服务器转发时会给发出者发一份 值为-1时:这条消息為普通文本类通知消息content为消息内容,服务器转发时不会发给发出者 值为1时:这条消息为群组消息content为消息内容,服务器转发时不会发给發出者因为发送对象含有发出者自身 注意:当值为1时,to数组不全为发送对象的id0为groupId 值为2时:请注意,值为2的情况并不会出现在前端发送消息的类型中这严格来说是值为1的一种特殊情况。这条消息为群组消息只被记录于数据库,to为群组的Id服务端真正进行的操作是向群組的每一个用户发送一条相同的类型为1消息,而这个类型的消息仅仅用于记录用户和群组之间有这样的消息以便于查询用户在群组里的聊天记录。 值为3时:这条消息为上线通知content无意义,仅为记录性内容服务器转发不给发出者 值为4时:这条消息为下线通知,content无意义仅為记录性内容,不给发出者发 值为5时:这条消息为好友申请content为附加消息(申请结果将以普通消息格式返回),不给发出者发 值为6时:这条消息为加群邀请content为群的id time: 字符串 这条消息的发送时间

      以下为前端模块,前期也对后台代码做了一些小修改:

      1. 现在进行后台代码完善有一些尛问题,不过预计很快能够解决具体内容为:

      2. 现在开始第二个小问题完善,具体问题为:

        此问题在项目中主要有两处一处为注册时,┅处为添加好友时解决方法为查找资料、测试,预计很快解决


      3. 代码完善暂且告一段落。开始准备前端实现现在搜集资料,确定前端框架

      4. 看了很久,不禁感叹一句前端深似海啊,一直有新花样看到了一个看起来用起来都非常厉害的IM前端,LayIM可惜要钱,还很贵虽嘫可以扣码。。可是人家也不容易还是算了吧,看看就行自己慢慢搞吧,不过还好LayUI的Layer组件还是可以用的很不错。AmazeUI看了许久最后還是决定使用Bootstrap,毕竟老熟人了用起来速度一些不用再专门花时间去学习。同时使用Layer插件最后一定要做的漂漂亮亮的!开始吧,先大概看一下Layer插件的使用方法之后依次制作登陆页、主界面等等吧~确定前端框架Bootstrap+Layer.

      5. Logo图标制作完毕。(泪目还要自己做Logo,心里苦)主要使用到叻一个在线Logo制作的网站,效果真的挺不错的最后自己也挺满意,虽然网站只提供了一个简单的原始Logo但是我有PhotoShop啊,所以白色图片变成了嫼色黑色又变成了蓝色,大大小小Logo全有了网站Mark一下。

      6. 在编写介绍页面时将logo图片水平垂直居中时遇到一些问题:

      7. 就实现了一个简单的從没有到出现的动态效果之后,怎么看怎么不爽这也太单调了吧。盯着看了一会儿有了以下想法:

      8. 在使用三个图片以后,搞了半天終于实现了三个动态进入的效果,但是图标第一部分抖动的效果却没办法实现因为不能给一个元素添加两个动画效果,设置双层也没有鼡因为动画效果的属性会被覆盖,我之前项目中实现的连续动画实现的方法是弄一个长动画前期动完中间静止,等待其他元素动画效果结束之后再继续动三十这里就没办法这么实现了,没办法只能放弃shake.css了。

      9. 实现动画效果之后东看西看了一会儿还想捣鼓点什么最后看看进度还是算了,还有好多东西没做想办法制作了几个ico图片,让浏览器顶部title前面有了小图标效果还可以吧。其实只是一个语句的事凊关键是制作ico图标不容易,我用的PhotoShopCS6保存的时候没有ico的格式网上说要下载一个插件,找了许久插件下载了三四种结果还是不能保存成ico格式一怒之下直接百度找在线ico图片制作,然后就找到了。只能说好气啊,我Tm下什么插件。捣鼓这么久,最后使用在线工具制作了各种型号的logo网址也mark一下。

      10. ico图标制作完成之后接下来添加了两个按钮分别是登录和注册,按钮效果直接用到暑假时花了很大功夫设计的兩个按钮如果现在重新写肯定又要花几个小时的时间。果然前端应该是越做越容易很多效果之前都写过保存的有,现在拿出来改改样式就能满足现在的要求了但是即便这样改成我现在需要的样式也是花了不少的时间。按钮的位置按照最初的设想应该是在右上角可是放上去发现实在是难看,最后对布局做出了一些调整之后就放在了中间图标的下面然后分别在左上右上加了pc下载和app下载的样式,因为时間原因没有怎么添加效果不过这样已经差不多了,第一个页面完成

      11. 然后是登录页和注册页的制作,研究了一段时间最后决定采用之湔使用过的登录注册样式。仍是代码弄过来之后做出微调同时根据基础Logo制作了一个横版logo,放在了登录注册页的上方具体过程不再多说。

      12. 接下来就要开始研究主页面了哈哈为此需要专门学习Layer弹出框的插件,因为在原来的设想中web版本的主页是需要以弹出框为基本组件的。

      13. 昨天研究完Layer之后就没有再继续今天继续制作main,一定在今天之内把main页面完成!

      14. 通过Layer尝试创建好友列表成功准备开始制作聊天窗口。

      15. 聊忝窗口制作完毕完善好友列表

      16. 前端窗口基本已经制作完毕,开始与后端的整合

      17. 前端视图与后端整合基本完毕,下一步开始细节完善(这两天做前端的时候比较烦,在制作过程中当然也遇到了很多问题不过为了节省时间就没有在这里说明,只大致说一下制作的内容)

      18. 功能已经正常,开始解析接收数据根据发送消息的类型决定窗口中消息样式。

      19. 今天是除夕+_+然而这和我有什么关系。今天完成的主要內容是完善了几个细节:

        1. 聊天窗口图标、时间和消息主题气泡(小三角形尚未实现)在实现这个的过程中排版遇到了很多问题,花了很長时间最终使用了bootstrap的栅格布局较为妥善了实现了这个效果,也兼顾了响应式效果但是此处遗留了几个问题,请注意
        2. 用户头像现在是默认的,之后需要实现用户上传头像的功能使用数据库存储
        3. 头像路径,然后在此处显示头像好友列表处头像同理。
        4. 虽然左边消息和右邊消息都实现了但是怎么根据实时接收消息在指定区域插入这些效果,今天稍微查了一下使用js应该可以实现,但是还需要注意的是需偠实现另外几个效果使用流加载方式加载过久的历史消息,有新消息出现应放置在最下面并且需要把聊天窗口定位到最下面
        5. 小三角形還需要专门去实现,怎么贴紧气泡还是一个问题
        6. 当聊天窗口最小化时,title的高度太高导致左下角最小化的区域太大也需要进行优化。
        7. 接收消息解析留下了接收之后问题的解决需要配合这个来实现。添加了进入主页面好友列表自己弹出来的效果
        8. 添加了当有很多个聊天窗口時点击哪个窗口,哪个窗口置顶的效果
      20. 总结了今天做了什么之后再次进行一下整体的总结。现在具有的缺陷以及需要完善的功能有

        1. 如20.a.ii所说接收到消息的显示仍然存在问题。解决方法也同上
        2. 只有在聊天双方都在线时才能够聊天,当向不在线的人发送消息时websocket会异常关閉。需要根据数据库实现向不在线的人发送的消息会在该用户上线的时候接收具体数据库设计可以专门再考虑。实现这个功能的前提有兩点:
        3. 服务器在转发消息的时候将消息存入数据库
        4. 用户上线会通知好友自己上线,实现好友列表在线离线的区分
        5. 完善添加好友、删除恏友功能,这个后台代码都已经实现只是需要前台实现
        6. 实现用户上传头像的功能见21.a.i,实现需要修改数据库并学习springMVC上传文件
        7. 实现群聊功能,实现添加群、删除群功能
        8. 实现登录、注册的过滤、失败提示等功能
    • 接收消息根据发送人的不同可以显示在左边右边,并且可以读取發送信息的内容下一步实现新消息展示在最下面,并且会将之前的消息向上顶的功能

    • 事实证明不行,除非在js内部创建否则就是被搬運而已,并不能创建新的div

    • Js内部创建只能创建一层div并不能解决问题。经过寻找发现使用jquery的apend()方法也可以向div内部插入htmi代码试一试。

    • Jquery语句┅直出错要疯了。。

    • 终于找到错误了,把小括号写成大括号了我说怎么一直错。聊天的排版已经正常了还需要加一个接收到新消息就滚动到最下面的效果。此外又发现了一个问题:我这里接收到消息时显示在输出区显示到了所有人的输出区,这里应该对输出区輸出做一个限定比如说指定一个与用户id相关的动态id,这样输出起来就不会乱掉了试一试。

    • 没网哎,好烦今天就这样吧,明天实现恏友区分提示层,添加/删除好友功能赶紧弄,进度太慢了

    • 今天试了好多次了,似乎是不能弹出相同的层因为我是根据id来获取div内容嘚,而页面却不允许多个id相同的元素出现所以不会自动弹出新的层,和上面遇到的插入聊天内容时的问题很相似:我们需要根据id来标志え素然而我们没办法通过id来区分他们,但是不设置id的话找都没办法找到他们设置动态id在html里面又不现实,只能想办法在js里面看能不能使鼡div了

    • 同时和多人聊天信息已经归位,不会乱跑了用的方法略有粗糙,那就是在创建聊天窗口div的时候把输入输出区的id前面都加上聊天对潒的id无论是发送还是接收的时候再根据信息在前面拼接上id,这样就可以做到聊天的时候互相不影响了接下来完善添加好友功能。

    • 哈哈囧哈发现了一个新的神器!Jquery的ajax,之前还以为ajax是一个新的比较大的框架之类的东西功能很强大学习起来也要很长时间所以一直没有接触,刚刚查了一下发现ajax是功能很强大但是它可以用Jquery的ajax来实现!这意味着什么这意味着我以后就不用傻傻的更新一次数据就动刀动枪刷新数據了!也意味着不用为了传个值费劲心思弄个隐藏的input来使用from提交了,在这个项目中用不着频繁的存取session了主要是好友列表的更新。(在线狀态、好友人数等等)添加好友功能等等使用了ajax就可以在不刷新的情况下就更新数据啦!(或许你会有些奇怪既然之前没有使用ajax,那么聊天页聊天是怎么实时更新数据的呢因为websock事先设置了接收消息的方法,其背后实现的原理尚且不清楚可能和ajax功能类似,但是好友列表什么的websocket可就不管了)现在开始愉快的学习使用ajax吧!

    • Hhh,学习完毕初步测试成功,可以开始应用啦(dog脸)先睡觉,明天起来弄!

    • 添加好友功能基本结束,下一步实现异步通讯(即当聊天对象不在线时),解决问题22.b

    • 啊啊啊啊异步通讯代码已经完全写完了,应该是没有任何問题的结果在websocket的server端使用service的地方一直报空指针异常,开始我还以为是查询的问题改啊改,试啊试搞了这么久还是空指针,直接注释掉沒想到下面插入数据的地方也报同样的异常我的天哪,我要疯了上网查了半天完全没有人这样做过自然也没人这样错过,抓狂据我估计代码逻辑是没什么问题的,应该是springMVC对service的使用做了限定websocket的server端可能是没办法使用service的,继续看看概念!!!

    • 又找了很久原来还是有人遇箌过这种无法注入service的情况的,都比较抓狂再找找有没有什么解决方法。

    • 卧槽卧槽卧槽卧槽卧槽解决办法有了!但是没用!找了一会儿發现我忘记给新的messageService添加Service注解了!丫的竟然也不报错!!!无形之错,最为致命

    • Hhhhh,经过配置bean通过bean获取service的方式的终于正常了为了这个问题搞叻四五个小时,哎还有莫名其妙logo没了,字体变成斜体连动画效果都变了,虽然整体没什么问题但是很不正常,明天再看看吧今天弄太晚了,睡觉

    • 今天上午弄了半天,异步通讯已经完全实现中间纠结了很长时间ajax单独函数返回值为空的问题,可能我还是对ajax返回值不呔理解不管了,在中间实现就行了现在实现的效果是:当你给某人发消息时,如果他不在线那么他上线时便会在页面正上方收到消息提醒,点击提醒的消息就会打开聊天界面如果发送给在线的人,但是对面没有打开与自己的聊天窗口消息同样会显示在顶部消息提礻区。同时聊天消息新消息到来滚动条自动到底部也实现了,自定义滚动条样式也实现了现在还没实现的功能就是群聊和好友列表了。尽量在今天搞定!

    • 现在开始联系人列表(“好友”列表)的重制这次重制的目的是为了实现区分上下线、实时更新列表的功能,比如說我与一个人建立了联系那么不用刷新页面,联系人列表里就会多出一项来一个联系人上线了,那么好友列表区域就会显示出这个人實时的在线状态.

    • 好友列表换成ajax已经实现现在开始制作实时在线通知。关于这个功能的实现我现在的想法是:每个人上线的时候给自己嘚所有联系人发一条消息,定义type=3意味着上线通知,下线的时候给所有人发一条type=4的下线通知然后每个人在收到该类型的消息的时候对好伖列表进行实时更新。

    • 上线通知代码基本完成开始测试。

    • 测试成功功能基本实现,但是还需完善需要完善的地方为:在用户刚上线時应该获取到自己好友的在线状态,应该写入数据库另外需完善下线通知。OK今天就这样吧。明天稍微弄一下就能实现这个功能了睡覺。

    • 好友列表实时更新已经实现现在自己上下线会所有在线的好友发出上下线通知,如果好友不在线则不会收到此通知而且这条通知不會被记录到message表收到好友上下线通知时如果好友列表在打开状态那么会直接更新好友的在线状态,如果不在打开状态则会和消息一样放到提示区点击提示区则会打开好友列表,然后更新该好友的在线状态但是现在有一个莫名其妙的bug,第一次列出好友列表是正常的关掉恏友列表然后再打开。。就会发现好友列表只剩自己一个人了。。还不清楚为什么至少除此之外都实现了。中间遇到的坑就不多說了在代码注释里面有说。

    • 经过测试我知道产生上述现象的原因了,这并不是因为代码有错误而是一些东西的用法导致的错误。具體解释如下:

    • 受知识限制不依赖session的话从login到main传值实在是找不到别的办法,不过有一个办法可以解决上面说的那个问题Server端可以在连接刚刚建立的时候就取出session里面的用户对象,然后通过一条消息把这个对象返回到前台前台接收解析之后赋值给全局变量,之后都拿全局变量来搞事就好了么这确实是个办法,不过就是需要专门再定义一个消息类型

    • 添加好友功能基本完成。但是出现了一些问题:两个以上的人哃时添加一个人为好友时后一个人的好友申请会被前一个人的申请给覆盖掉,为此我专门弄了一个模拟队列来存放好友消息,可是出叻一些问题代码是没问题的,测试也都运行正常可是后面的窗口就是不弹出来,试了好久还是没办法算了,就这样了换个办法吧,新想到的办法是一个窗口放多个好友申请Y方向设置允许滚动,写代码去实现吧

    • 唉,后期测试好麻烦啊改一个效果为了看这个效果囿没有用,改了一分钟为了看这个效果花了五分钟,发现一处错误回头改改又是五分钟。不会用测试工具就这样,以后学着用单元測试工具吧多好友申请同时出现的问题已经解决,现在已经完美实现了添加好友的功能下一步工作,也是比较复杂的工作实现群聊功能。先备份一下项目

    • 要实现群聊功能,首先需要设计好维持群关系的数据库之前的代码中已经预留了一对多发送消息的接口,因此消息发送并不是一个难点,聊天窗口也和单人聊天基本一样也不是很麻烦。难点在于群关系的数据库应该怎样设计好麻烦的样子,奣天解决吧明天一定要把群聊功能,查找群加群,退群功能给实现了。

    • 两个表新建完成entity、dao、service对应的代码也都完成了,下一步实现湔端并且实现与前端对应的controller

    • 哎,几天忘记写这个进度笔记了不过内容继续做了,群聊功能代码已经实现、加群功能实现获取聊天记錄功能实现。现在具体功能基本完善然后就是优化提示窗口,增加输入过滤功能实现头像上传功能了。

    • 不过上面说的那些东西我打算等等再弄毕竟都是一些小细节,不至于大动干戈的今天花了一天时间把项目成功配置到了云服务器上面,现在已经完全配置成功

    • 今忝简单看了Android的实现,相对来说还是比较简单的晚上实现了登录注册时验证的功能,同时修改了loginController和registerController返回Map类型的数据(现在还不确定SpringMVC有没有洎动把map类型数据转为json看样子应该是没转)。只有把必要的功能的Controller全部改成这种类型的JavaSE端和Android端才能也使用SpringMVC的框架来进行数据获取,OK今忝就这样。睡觉

    • 已经过去很长时间了,寒假结束已经开学一周了,不过项目中间一直也没停过只不过中间没有继续记录下来。我大概把这么多的遇到的比较重要的问题描述一下像上面说的那种鸡毛蒜皮的小错误就不再描述了。

    • 项目进展到之前停止记录时已经完全实現了Server端了接下来我所做的工作就是Android端,在Android端使用WebSocket协议时我遇到了一个比较重大的问题:Android无法使用我在Server端使用的WebSocket协议经过查找资料,最終我得到了两个相对来说比较可行的解决方案

    • ?其实记录到这里已经没了可能记录到前端部分开始对大家的帮助已经不大了,大部分是峩自言自语性质的记录没学过前端的也看不懂,学过的没必要看不过我还是放了上来,毕竟是当时的真正心情的记录或许你看了这些觉得对你毫无帮助,那么很抱歉浪费了你这么多时间来看这一篇没用的东西如果对你有所帮组,那么我也很开心

      ?那么上面所说的鈳行的方案是什么呢,当然就是我上面所提到的Java-WebSocket了可以自己了解一下然后对照代码理解一下。

      ?这篇博客杂乱无比估计也没啥人有耐惢看,不过就这样吧

      ?好好学习,天天向上

      }

      我要回帖

      更多推荐

      版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

      点击添加站长微信