缘起
2016年8月,自己利用闲暇时间开发了一个基于PHP+jQ的小论坛。后来接触前端以后,又基于Vue重构了一番。直到2017年的某一天,不经意间被老板瞄到,提倡用于公司内部的内网论坛并奖励了一辆车(小米卡丁车)。借此机会,一点一点的更新迭代,基本也是利用业余时间弄的。毕竟用于公司文化、水贴,整体还是以业务为主的。
最开始想做的是轻论坛,为此还研究了很多开源论坛(discuz,dedecms,phpwind...知道的现在都不年轻了吧),甚至还想改一版17年的小米论坛,因为当时它的整体体验比较轻。最后都放弃了, 原因是当时预估PC会越来越弱,功能齐全未必是主流,小屏兼容,轻量级才是未来。
当时自己想的广告语:
有时候你喜欢看,不喜欢说?
你总是已读,但不愿意回复?
你总是笑而不语,且不主动参与?
你总是想在日报写些东西,想说些话,但又删除了,觉得不太合适?;
这时候你可以来这里发现频道的圈子,这里是家庭晚会,是文化一角,是咖啡聊天室;
产品定位
像小米论坛一样轻,像微信一样简单,像圈子一样好玩够用就行。
当然随着这些年,自己搞全栈,产品体验肯定也有所提升。随着一版一版的更新迭代,现在的它也不能落后。
产品功能规划:
一览图:
仅限内网使用,外观酷似第一版掘金沸点~
技术栈
- 产品,搞前端的一般不会去画原型,因为画的功夫就写好了。按照自己喜欢的风格抄就行了。
- UI, 以前学过PS,除了复杂的蒙版、调光调色以外,基本的logo、图标、素材组合都能做。
- 前端,Vue+Element,基本圈子的组件都是自己重新封装的,只用了一些提示和按钮。
- 后端,所有接口都是自己写的,去年还特意升级到了TP6🤭,懂的都懂哈。
- 测试, 所有玩帖子的小伙伴都是我的测试同学。
技术亮点
发布模块
- 自定义表情包,里面那个是我们自己设计的
- 图片+视频,视频是自动识别的
- 链接支持爬取标题
- 话题功能
<div
class="inputor"
ref="ucominput"
@click="handleInputClick"
@compositionend="handleCompositionEnd"
@compositionstart="handleCompositionStart"
@keyup="handleInputClick"
v-html="innerText"
:contenteditable="true"
@focus="handleFocus"
@blur="handleBlur"
spellcheck="false"
placeholder="告诉你个小秘密,发沸点时添加话题会被更多小伙伴看见呦~"
@input="handleInput"
:class="{ 'rich-input': true, 'empty': isEmpty }"
></div>
<!-- 剩余字数 -->
<div :class="{ 'input-num': true, 'input-num-reduce': (1000 - richBoxLen) < 0 }">{{ 1000 - richBoxLen }}</div>
function richBoxLen() {
let str = this.value;
let num = 0;
let reg = /<img(.*?)>/g;
// 过滤掉图标
let left = str.replace(reg, () => {
num++;
return "";
});
let space = 0;
// 过滤掉换行
left = left.replace(/<div><br><\/div>/g, () => {
space++;
return "";
});
return num * 2 + left.length + space;
}
...
- 文本过滤,这块我前端转义后再后端加固了一下htmlspecialchars,另外再调用一下百度AI的文本审核,里面可以识别谩骂、涉黄、灌水等;前端可以使用js-xss库来过滤,或者设置CSP的等级
浏览板块
- 图文浏览,这里增加了OSS缩略图来缓解首次打开加载问题。
cur: curUrl + "?x-oss-process=image/resize,m_fill,w_200",
small: curUrl + "?x-oss-process=image/resize,m_fill,h_40,w_40",
curW: result.width,
curH: result.height,
curP: (result.height / result.width) * 100 + "%",
singleW: result.width > 200 ? "200px" : result.width + "px",
single: true,
- 头像优化,头像读取钉钉,也支持自定义,还支持随机生成(解决头像为空或死链问题)
//默认头像,取自一个开源头像项目,支持本地部署,
return `https://api.multiavatar.com/${username}.svg`
//也支持类似uuid的唯一码
const getRanNum = function () {
var result = [];
for (var i = 0; i < 4; i++) {
var ranNum = Math.ceil(Math.random() * 25);
result.push(String.fromCharCode(65 + ranNum));
}
return result.join('');
}
-
打赏插件,这个插件比较有意思,可以在内网任意地方调起,让你随时随地打赏,这个没啥难度就不提了。
-
评论插件,评论太复杂了,最开始用的畅言,后来还是自己撸了一个。多重回复,谩骂、涉黄、贴图、防注入、@人等等,小小的评论做起来挺费事的,直接搞了个插件,有时间用ts重构一下发出来。后面文化君还想加评论的点赞和打赏,想想都头大呀。
-
视频热区域加载,网上也看过大牛的,不过感觉有些复杂,于是实现了一个丐版,还挺好用。主要是
IntersectionObserver这个方法。
// 检测视频,进入窗口自动播放
observeVideo(){
let $referenceBox = document.querySelector('.wrap'),
$targets = document.querySelectorAll('.uchat_video');
//实例化观察器
this.observer = new IntersectionObserver(this.reserveCallback, {
root: $referenceBox,
rootMargin: '0px',
threshold: [0.7, 0.8, 0.9, 1]
});
this.addObserver($targets);
},
//开始监听
addObserver ($targets) {
for(let i = 0, len = $targets.length; i < len; i ++) {
this.observer.observe($targets[i]);
}
},
// 回调
reserveCallback (entries) {
let ratio = entries[0].intersectionRatio,
$target = entries[0].target;
if(1 - ratio <= 0.03) {
if(this.curVideo) this.onPause(this.curVideo);
this.onPlay($target);
this.curVideo = $target;
return;
}
this.onPause($target)
},
-
时间插件,有一个比较好玩的插件推荐个大家
dayjs,可快速分析距离当前和以往的间隔//返回距离当前时间 getToNow(date) { return dayjs().to(dayjs(date)) }, -
悬赏任务,为了刺激各部门积极参与优化计划,还特意开发了一个任务悬赏模块。我负责发布任务,大家愿意用业余时间做的可以领取任务,交付且上线以后,可以领取对应的金币。太卷了,不过也确实是两全其美的法,公司出钱鼓励大家创作。UI、产品、研发、运营都可以领取任务。
更新往事
更新文档一般涉及了很多其他优化功能,摘出来几个给大家过过眼,建议大家做功能养成做版本更新记录,方便存档。
💥我是懂点技术的的「扫地盲僧」,希望我的分享能够给你带来帮助~
关注我,你的点赞直接取决于我是否有勇气写下一篇分享😂