我正在参加创作者训练营第5期,****点击了解活动概况

声明

本课程于2020年8月6日仿自北京易成星光科技开发的Worktile,相关材料版权归属于原网站,本课程作为仿站习作,仅做教育用,不得用作商业用途,商业合作请拜访源站。

课程开发前试用了市面上简直一切企业协作工作渠道,选中Worktile是觉得它是其时最优秀的,也喜爱它的UI风格,引荐有需求的朋友选购。

本课程意图是演示一个杂乱的协同类OA的SaaS运用软件,依据众触这样一个专业的低代码运用渠道,怎么开发一个杂乱的功用完整的SaaS运用。Worktile是专为企业工作场景规划的项目协作办理系统,事务概念多,联系错综杂乱;虽然大家很或许不需求做到这种杂乱度的运用,但学习里边用到的思维和用法是十分有价值的。

源站跟着时刻的推移或许会不断迭代演化,而课程作品并不会一同跟着改变,所以作品跟你现在看到的源站不同是正常的。

本课程有十分翔实的视频解说每个功用模块,都是是从空白页面开端一步步完成的:总览、安排架构、网盘、即时音讯、项目办理、批阅。

账号

为了演示公司的安排架构,虚拟了以下人员:

  1. CEO:戴国强 13845678901 办理员

  2. 总经办经理:赵敏 13845678911 办理员

  3. 人事总监:陈颖 13845678902 办理员

  4. 财务总监:付媛 13845678906 办理员

  5. 项目一组组长:曾辉 13845678312

  6. 项目一组开发:黄鸿亮 13845678909

  7. 项目一组开发:黄姚谦 13845678223

  8. 技术总监:谢林华 13845678907

  9. 项目组经理:孙荣浩 13845678905

  10. 渠道组组长:葛传富 13845678910

  11. 测验组组长:王伯祥 13845678908

  12. 尚未分配部分:黄飞凯 13845678102

这些人物和手机都是瞎编的,头像来自我来笔记。

本课程运用作为供学习者克隆的模板,数据不能太乱,没有提供演示账号也没开放注册,所以即便克隆了本运用也还不能直接登录。克隆以后到登录页面(/z/login),它运用的是账号登录办理插件,右键选中插件,在右边面板激活“注册”后保存再刷新页面即可注册了,注册后自己有账号能够登录了但仍是没有暗码以上面这些人员的账号登录,能够先在”后端安全“中注释掉$user.toggleRole里的限制,再在”成员办理“中点击某个成员的”设置“,在”修正成员账号“标签页中修正此成员的暗码后就有暗码以此人身份登录了。详细指导请移步教育视频。

预备深入研究的同学请注册登录众触官网后,点击克隆按钮,把整个运用仿制一份随意调试更改吧。

大局$V.s

大局可持久化状况,sstatus首字母。运用开端时从localStorage读取,运用结束时(onbeforeunload)存回localStorage,这样能够当即恢复回上次脱离时的状况。

  1. $V.s.左导航:最新点开的左边导航栏标签

  2. $V.s.音讯:最新点开的私聊联系人或群组的_id

  3. $V.s.未读:各私聊或群组的最新未读音讯的个数

  4. $V.s.已读:各私聊或群组的最新已读音讯的时刻

  5. $V.s.折叠:各种被折叠的菜单

  6. $V.s.项目:最新点开的项目_id及其组件下标和视图下标

  7. $V.s.使命栏:以项目为单位固定到使命栏的使命列表

大局事情

  1. click:当有弹窗$v.pop时封闭弹窗,但keep为真时点击弹窗内部或许zpage以外(confirm或alert)不封闭。

  2. keydown:当有弹窗或模态窗时按下退出键Escape可封闭弹窗或模态窗。

安排架构

公司的安排架构是其他功用的根底。 能够以树状结构办理各部分及其成员,也能够从通讯录里检查搭档正在经手的使命状况。

  1. 职位列表
    可增加、修正、上移、下移、删去。

  2. 用户登录时(c.exp.onLogin)拉取公司全职工信息和公司安排架构,即c.exp.onLogin)拉取公司全职工信息和公司安排架构,即c.exp.部分。

  3. 对职工和安排架构整合到大局变量中,便利运用的很多当地运用。
    $V.部分是安排架构的克隆,除了增加了个”未分配部分“
    $V.部分成员是把安排架构拍平后把各部分成员加进去
    $V.部分总成员是在$V.部分成员根底上再把一切子孙部分成员都加进去

  4. 成员办理
    基本信息设置,修正成员账号,角色设置

  5. 调整部分
    能够选中成员(单选或全选)后可批量调整他们的部分

  6. 成员查找(过滤)

关键、难点:

  1. 移动便是交换方位,常用原生函数arr.splice(新下标, 0, arr.splice(旧下标, 1)[0]),先从旧下标删去一个元素,删去得到的是数组,所以后面加个[0]获得元素自身,再把被删去元素刺进到新下标中。
    也就简略理解l.arr.splice(l.arr.splice(index – 1, 0, l.arr.splice(l.arr.splice(index, 1)[0])是上移,l.arr.splice(l.arr.splice(index + 1, 0, l.arr.splice(l.arr.splice(index, 1)[0])是下移了。
    等学习了后面课程把握了怎么运用Sortable.js,回过头来把这儿的上移和下移按钮改成拖动排序将使操作更简略和直观。

  2. 在数据库中删去数组的某个元素常用**pull∗∗,即从数组中∗∗拉走∗∗某个元素:pull**,即从数组中**拉走**某个元素:
    xtk.modify(“公司”, “职位”, {pull: {“x.arr”: x}})

  3. 数据结构
    部分是以树形结构存储的,部分有称号、主管,zchildren数组放子部分。
    数据组件的数据源包括zchildren时会递归烘托成树形结构。

  4. 子部分缩进
    为了体现部分层次结构在动态款式里依据层次深度($indexes)核算左缩进(paddingLeft)

  5. 部分调整或成员更新后通过$v.F5让挂载组件获取最新数据从头烘托

  6. 删去成员的部分用的是$unset。留心“未分配部分”这个特别部分。

  7. 删去子部分用的是$pull,从数组中“拉走”。

通讯录

  1. 搭档列表

  2. 搭档概况

  3. 搭档使命列表及状况数

  4. 发音讯

  5. 常用联系人

  6. 收藏

  7. 按部分查找搭档

网盘

相似百度网盘、阿里网盘,以虚拟文件夹的方法分层分类来办理云端存储的文件,可批量上传整个文件夹。

网盘展现

  1. 读取文件夹及文件信息。

  2. 文件夹树

  3. 文件途径

  4. 查找

  5. 排序

关键、难点:

  1. 树形数据结构
    文件夹仅仅存储于product表中的简略记载,包括称号色彩(即父文件夹)信息,而非直接的树形结构,但咱们要依据“父”结构出相似于上节课的树形安排架构来,作为数据组件的数据源。
    文件夹能够有十分深的层次结构,不像安排架构那么单一稳固,不能一次性把一切的文件夹都读取出来。咱们在onReady先读取顶层文件和顶层文件夹(其父文件夹是”无”),并顺次读取各自直接子文件夹(依据有无子文件夹决议是否显现“展开”小三角图标)。
    读取文件或文件夹的一个关键是把父文件夹_id传入履行环境:{ 父: _id }
    文件是上传到对象存储服务器的普通资源,并不无文件结构树信息,所以咱们每次上传完文件后要给资源表增加当时文件夹作为其父文件夹:
    $resource.modify(_id, { “x.类型”: “网盘”, “x.父”: 当时文件夹_id })

  2. 几个关键变量
    $v.根是文件夹结构树的根(称号唤作“网盘”吧,文件途径的第一个节点),是最大的一棵树。它的“zchildren”包括上面读取顶层文件夹,”文件“包括顶层文件。特别地,它的_id为”无“。
    $v.树是以父文件夹_id作为key的各级文件夹起始的大大小小的树。所以$v.树.无也即$v.根
    $v.途径是树根到当时文件夹各级文件夹树的数组
    $v.文件夹是当时文件夹_id。用户点击时(不管是左边文件结构树仍是主体文件夹列表)会以它作为父文件夹读取它里边的文件夹和文件信息。别的,点击”展开“小三角图标时只需读写孙辈文件夹信息,一方面树里不展现文件信息,另一方体面文件夹现已读取,孙辈文件夹信息是为了决议是否展现子文件夹的小三角。

  3. 文件夹(自界说组件)
    动态色彩

  4. 从头烘托
    $v.F5改变时有三个挂载组件会从头拼装数据并再次烘托。
    A. 左边文件结构树里的挂载组件便是用来拼装$v.树的,从根节点开端向下递归遍历一切现已查找出来的文件夹:一方面把文件夹直接挂载$v.树上,另一方面把它推入父文件夹的zchildren数组中。
    B. 顶部的文件途径里的挂载组件便是用来拼装$v.途径的,从当时文件夹开端向上递归直至根节点,把每层文件夹推入途径数组头部(unshift)。
    C. 主体文件列表里的挂载组件便是用来拼装当时文件夹里的文件列表的。

  5. 查找、排序
    咱们总是先展现文件夹列表,然后才是文件列表,是分隔查找分隔排序的,再把两种拼接起来:
    (v.查找.文件夹∣∣v.查找.文件夹 || v.树[v.文件夹\].zchildren || \[\]).**sort**(v.sort.key, v.sort.incr).∗∗concat∗∗((v.sort.incr).**concat**((v.查找.文件 || v.树\[v.树\[v.文件夹].文件 || []).sort(v.sort.key,v.sort.key, v.sort.incr))

网盘上传

  1. 新建文件夹

  2. 上传文件(可多选)

  3. 上传文件夹(坚持文件结构)

  4. 上传列表,上传进展和状况

关键、难点:

  1. 上传文件
    按钮触发的是躲藏在里边的input元素:el.firstElementChild.click()。把上传成功后才要用到的‘el.firstElementChild.click()。
    把上传成功后才要用到的`
    l.U`在刚开端挑选文件(onChange时)就设置了是为了防止上传过程中遭到用户点击了其他文件夹导致v.文件夹发生改变的影响,而刷新用户当时文件列表(v.文件夹发生改变的影响,而刷新用户当时文件列表(v.exp.文件.exc({父: $v.文件夹}))则没有这个忧虑。

  2. 上传文件夹
    为了防止受v.文件夹改变的影响先赋值给暂时变量:v.文件夹改变的影响先赋值给暂时变量:l.文件夹 = v.文件夹把整个文件夹递归上传的关键是每个待上传文件有个相对途径‘webkitRelativePath‘,循环每个途径节点,创立未创立的文件夹节点,直到最里层的文件夹赋给v.文件夹
    把整个文件夹递归上传的关键是每个待上传文件有个相对途径`webkitRelativePath`,循环每个途径节点,创立未创立的文件夹节点,直到最里层的文件夹赋给
    l.当时文件夹,上传完成后把它作为父文件夹。

  3. 上传列表
    文件上传前把信息推入$v.上传数组,标识为”正在上传“,假如是图片或视频给它创立一个缩略图:URL.createObjectURL(file),上传过程中及时改变它的进展款式,上传完成后删去”正在上传“标识。

网盘办理

  1. 重命名

  2. 移动

  3. 删去

  4. 修正色彩

  5. 发送到谈天

  6. 回收站

关键、难点:

  1. 咱们删去文件夹或文件是让它脱离原来的方位,但随后有还原操作,所以还要保留原来方位的信息。
    咱们通过把父文件夹改成原父文件夹的方法来完成
    rename: {“x.父”: “x.原父”}
    这样没有父文件夹的资源便是被逻辑删去的。
    “x.原父”: {
    exists: true}

即时音讯

相似企业微信/飞书/钉钉的即时音讯,支撑私聊、群聊、前史音讯、置顶,能够发送表情、图片、网盘文件、项目和批阅到会话,还能够收藏文件、固定音讯。 是学习衔接的好课程。

音讯初始化

  1. 获取私有群(群成员包括我)和公开群的列表信息,并把它们的_id组成列表$V.音讯.群ID

  2. 翻开衔接$socket.open()
    群组_id列表作为channels,这样可收到相关群组的音讯;
    saveToDB设为true,把信息都保存到数据库,这样通过$socket.hist()能够检查前史音讯,即时不在线是他人发送的未读音讯也能收到;
    allowMultiLogin设为true,这样翻开的多个设备/浏览器都能够一起收到音讯。

  3. onConnect 已连上
    通过$socket.hist()获取一切私聊的前史音讯。
    通过$socket.hist($V.音讯.群ID)获取一切私有群和公开群的前史音讯。
    给各音讯增加发送音讯日期,为了便利在音讯列表中显现切割用的日期和星期。
    获取置顶会话的_id列表。
    依据私聊对象_id或群聊_id:
    把各音讯列表放入$V.音讯.chat中;
    把各更多音讯的列表放入$V.音讯.more中,每逢谈天窗口滚到顶部时就从中拿出一个_id去获取更早的前史音讯;
    把各音讯_id放入$V.音讯.histID中,删去前史音讯时用;
    把各音讯的发送时刻大于其已读时刻$V.s.已读的音讯条数放入其$V.s.未读中;

  4. onData 收到新音讯
    依据谈天对象(私聊对象_id或群聊_id)把音讯放入对应的音讯列表$V.音讯.chat中。
    假如此音讯是当时正在翻开的谈天会话中,则烘托后把新音讯滚入视图,否则给其未读音讯数加 1。
    假如此音讯包括@我的信息,弹出一个告诉窗口notification(如未被阻挠)。

音讯会话

  1. 创立群组/群组设置

  2. 加入群组

  3. 建议私聊

  4. 会话列表。不管置顶会话是否有音讯都悉数先展现出来,然后展现除去置顶的有音讯的会话:
    V.音讯.置顶.concat(V.音讯.置顶.concat(V.音讯.chat.keys().filter(‘!V.音讯.置顶.includes(V.音讯.置顶.includes(x)’))

  5. 会话过滤:
    .filter(‘f.search.kw?(f.search.kw ? (c.user[x\].x.名字 || c.xdb[x\].x.name).includes(f.search.kw) : 1′)

  6. 未读音讯,包括前史未读和即时未读新音讯。
    未读总数:V.s.未读.values().reduce(′V.s.未读.values().reduce(‘acc + $x’, 0)

  7. 点击会话时
    把会话ID赋给$V.s.音讯,烘托音讯列表后滚到最新一条音讯
    假如未读音讯数小于6时把一切音讯设为已读(清空未读并记载最新音讯的发送时刻)

  8. 删去会话
    A. 删去相关会话的文件列表
    B. 删去文件列表中的文件自身
    C. 删去相关会话的固定音讯列表
    D. 删去整个音讯前史。

即时音讯

  1. 音讯列表
    V.音讯.chat\[V.音讯.chat\[V.s.音讯]

  2. 当跟前一个音讯不是同一地利展现日期切割。
    date !== array\[array\[index – 1].date

  3. 把自己发送的音讯向右对齐,以差异于他人发送的音讯
    $c.me._id === from ? ” message-item–me” : “”

  4. 音讯弹出框
    固定音讯,删去自己发送的音讯

  5. HTML组件烘托音讯体

  6. 穿插调查器
    假如还有更多音讯未读取出来时(V.音讯.more\[V.音讯.more\[V.s.音讯].length),当滚到音讯框顶部是会触发穿插调查器从$V.音讯.more里拿出一项交给socket.more()来获取更多音讯,并放入音讯列表头部,烘托后滚到第一个音讯但穿插调查器却在窗口外的方位,这样防止接连触发,而是等用户再往上滚的时分又会触发一次。一个留意点是引进暂时变量socket.more()来获取更多音讯,并放入音讯列表头部,烘托后滚到第一个音讯但穿插调查器却在窗口外的方位,这样防止接连触发,而是等用户再往上滚的时分又会触发一次。
    一个留意点是引进暂时变量
    v.l.more来阻挠每次新烘托穿插调查器时导致的初次履行,由于此刻并不是由有户自动往上滚引起的。

  7. 未读音讯
    展现未读音讯数,点击时往上滚到上次的已读音讯或许音讯框顶部以触发获取更多音讯的穿插调查器,然后触发“悉数标记为已读”

  8. 发送文本音讯
    [表情文本]替换成对应的img:.replace(c.reg.表情,c.reg.表情, c.fun.表情);
    @某人:在群组会话中按下@时(即Shift + 2,2的keyCode是50)弹出扫除自己的群组成员列表,但在已弹窗时按下非Shift键(keyCode为16)则封闭弹窗;
    @24位的某人_id替换成对应的名字:.replace(c.reg.提及,c.reg.提及, c.fun.提及);点击时还有成员弹窗是由于增加了onClick事情:window.提及click();
    socket.send(socket.send(V.s.音讯, “text”, $f.音讯.txt);

  9. 发送图片/文件音讯
    点击文件图标是弹出上传对话框,挑选一个或多个文件后上传至服务器;
    然后依据不同的文件类型转化成对应的HTML文本:i为图片,直接显现图片缩略图;v为视频,显现对应的视频截图;f为其它文件类型,会依据其文件后缀format来显现不同的图标);
    音讯发送后把文件信息增加到此会话的文件列表中。
    值得留意的是音讯发送完了并没有当即操作数据库而是先把内容放在变量v.待保存文件音讯中,等候音讯回来后在v.待保存文件音讯中,等候音讯回来后在c.exp.onData再履行,由于考虑到以后删去文件时也要把它从音讯前史中删去,删去时要用到音讯发送时刻d:$socket.pull(_id, from, d),而这个时刻是在服务器端生成的,只要收到音讯后才知道。

  10. 发送项目使命/批阅/网盘音讯

其它

  1. 文件列表
    从网盘发送到谈天的文件不在此列表中
    删去一个文件要:
    A. 删去文件自身
    B. 从相关会话的文件列表中移除
    C. 音讯前史中移除对应音讯。

  2. 固定音讯列表
    删去时从相关会话的固定音讯列表中移除

  3. 点击成员图标
    群组时显现群组成员,可进一步显现成员材料或移除成员
    私聊时显现成员材料

  4. 点击设置图标
    置顶会话和吊销置顶会话
    群组设置
    退出群组
    删去群组

项目办理

项目协作办理是Worktile的中心功用,用来方案、安排和跟进一些具有清晰意图且相互相关的使命。 支撑高度灵活的个性化装备以习惯各种场景的项目需求。

Worktile以项目化的方法方案、管控和跟进多种工作领域和场景中的使命。

项目办理概念

项目

使命调集中心,用来方案、安排和跟进一些具有清晰意图且相互相关的使命。项目能够是长时刻的也能够是短期的。

组件

使命的展现方法,将使命信息以不同的视觉方法出现给用户,有多种组件类型:看板、列表、表格、甘特图、日历、报表。

视图

组件能够有多种视图来对使命进行分组、挑选、排序。

使命类型

承载不搭档务场景的模型,由高度结构化的使命特点构成,可规则使命类型之间的联系和状况流通方法,然后形成信息寄存和团队协作的规范。

特点:使命类型能够指定此类型的使命可包括哪些自界说信息,有多种特点类型:文本、富文本、数字、日期、成员、多个成员、下拉单选、下拉多选、承继。

使命

某种使命类型的实例。每个使命都有标题、状况,还有担任人、参加人、起止时刻、谈论等,主体部分是使命类型里界说的各种特点。

建议大家克隆本课程后尝试扩展更多特点类型,乃至扩展组件类型。

数据模型

项目:

{
    称号: String,
    使命类型: [ID],
    描述: String,
    色彩: String,
    置顶: Boolean,
    参加人: [ID],
    组件: [{
        类型: String,
        称号: String,
        使命类型: ID,
        PC显现: [String],
        视图: [{
            称号: String,
            分组: String,
            挑选: String,
            排序: String
        }]
    }]
}

使命类型:

{
    称号: String,
    项目: ID,
    父使命类型: ID,
    图标: String,
    描述: String,
    状况: [{
        称号: String,
        色彩: String,
        类型: Number,
        默许: Boolean
    }],
    状况流: {},
    特点: [{
        字段: String,
        类型: String,
        选项: [],
        新建: Boolean,
        必填: Boolean
    }]
}

使命:

{
    标题: String,
    项目: ID,
    使命类型: ID,
    父使命: ID,
    相关使命: [ID],
    担任人: ID,
    开端时刻: Number,
    截止时刻: Number,
    谈论: [{
        txt: String,
        auth: ID,
        d: Date
    }],
    状况: {
        称号: String,
        色彩: String,
        类型: Number
    },
    特点: { ... } // 比如如下
}

其中使命特点是存储它所属使命类型特点指定的详细数据,比方招聘使命的特点:

{
    职位: String,
    部分: String,
    薪资规模: String,
    需求人数: Number,
    在职人数: Number,
    JD描述: String,
    参加人: [ID]
}

安装数据库办理插件能够更直观地理解数据模型。

初始化

加载项目

  1. 加载我参加的私有项目

  2. 加载公开项目

  3. 把以上两种项目兼并后抽取简要信息组成$v.项目.菜单列表

  4. $v.项目.菜单过滤出$v.项目.置顶列表

  5. 假如有$V.s.项目._id就持续加载此项目信息

  6. 加载此项意图使命类型

  7. 加载此项意图一切使命

  8. 恢复此项意图使命栏数组

使命收拾

把上面加载的原始数据收拾到$v.使命

  1. 假如使命类型里有指定父使命类型,就把它增加到其父使命类型的$v.使命.子使命类型

  2. 把各使命类型里自界说的特点赋给对应的$v.使命.特点列表中

  3. 为了便利读取,持续把上述特点列表依据它里边的字段赋给对应的$v.使命.字段对象中

  4. 不更改原c常量,克隆一切使命数据赋给‘c常量,克隆一切使命数据赋给`v.使命.arr数组,并依据其\_id组成$v.使命.O`对象

  5. 假如一个使命有父使命,那就把该使命依据使命类型增加到其父使命的子使命数组x.子使命里,此外递归往上寻觅父使命链条组成使命链数组x.父使命arr,作为导航栏展现在使命弹窗顶部

  6. 对于使命类型里界说的承继类型的特点,给其下一切使命里的此特点增加承继字段

分组收拾

把上面加载的原始数据收拾到$v.分组

  1. 把当时活泼的项目组件(即V.s.项目.组件)赋给‘V.s.项目.组件)赋给`v.分组.组件`

  2. 把当时活泼组件的使命类型下的使命,通过当时活泼视图挑选要求过滤后,依据当时活泼视图规则的分组字段进行分组,把每个使命增加到$v.分组.O[分组特点]数组中,不同的分组特点组成$v.分组.arr数组

  3. 依据使命状况核算各分组下的使命数,并算计分组总数

  4. 依据当时活泼视图的排序要求给各分组里的使命列表进行排序

  5. 把当时使命类型的$v.使命.字段赋给$v.分组.字段

  6. 对甘特图组件做额外处理

使命活动

把使命活动封装成函数,以便利在多个当地使命发生改变时调用:把传入的事情参数增加上改变人和改变时刻后刺进到使命对应的xtk数组头里。

使命弹窗

从其他页面跳转过来带有“使命”参数时($query.使命)弹出使命模态框。

onResize

当窗体不足以容纳一切组件时把后面的组件/视图收到“更多”里边。 $v.项目.显现表明能够容纳的组件数。

项目

  1. 项目列表、查找

  2. 置顶、吊销置顶

  3. 检查归档使命、激活归档使命

  4. 逻辑删去项目

  5. 置顶列表

  6. 回收站

  7. 创立项目

  8. 抽屉
    抽屉把手.drawer-handler点击时会切换$V.s.折叠.左菜单的状况然后切换.drawer-wrap的类名drawer-wrap-collapse。

  9. 组件列表
    只展现特定个数:组件.slice(0, $v.项目.显现)

  10. 更多组件
    组件.slice(v.项目.显现,组件.length)选中更多列表里的组件时显现组件称号:v.项目.显现, 组件.length)
    选中更多列表里的组件时显现组件称号:
    V.s.项目.组件 >= v.项目.显现?组件\[v.项目.显现 ? 组件\[V.s.项目.组件].称号 : “更多”

  11. 视图和更多视图

使命类型

  1. 新建使命类型与修正使命类型

  2. 特点装备
    特点是保存到数据库中的关于使命的字段。
    预界说特点:当时状况、担任人、开端时刻、截止时刻

  3. 增加自界说特点
    “特点类型”决议了特点的展现方法,选定后不可更改。
    如有“父使命类型”则增加“承继”特点,有专属的“源特点称号”下拉框以挑选可承继特点,包括父使命类型的预界说特点和自界说特点,承继可递归/追溯到尖端祖宗使命。

  4. 界说自界说特点
    选中一个自界说特点后装备其特点。
    “特点称号”是展现和保存到数据库的字段名,下拉框有选项列表,翻开“展现在新建页上”开关会在“新建使命”弹窗中展现,并出现“必填”选项,“必填”开关会在特点名前增加赤色星号,并在入库前检查是否已填。

  5. 排序与删去自界说特点

  6. 状况装备
    状况列表决议了一个使命的一切或许的状况。
    状况有称号、色彩、类型和备注。
    状况有3中类型:未开端、进行中、已完成,决议了使命分组中的进展条的3种色彩。
    初始状况是新建使命的默许状况,所以只或许有一个初始状况。

  7. 状况流
    状况流是指特定状况可改变成哪种几种状况,未勾选或已铲除状况流则一个状况能够改变成任何一种状况。

  8. 增加、修改、移除、保存状况

组件

  1. 增加、修改、删去、排序组件
    每种使命类型能够增加多种不同方法的组件
    但报表组件与使命类型无关,一个项目也只需求一个报表组件

  2. 组件视图
    每个组件能够有各种不同视图,界说其分组、挑选、排序的方法。
    修改、增加、删去

  3. PC显现
    界说在PC端显现使命列表时应该显现哪些特点
    增加、删去、排序要显现的特点

  4. 看板
    看板的首要特点是能够拖拽分组或排序
    拖拽一个使命到另一个分组时要修正其分组的字段到新组名
    拖动这个分组以排序会把组名列表存入到视图的”组名arr“数组里
    当翻开右下角的”拖拽排序“开关时会触发旁边的挂载组件里的表达式,加载并装备SmoothDnD库。

  5. 表格、列表
    两者相似,差异在于表格用table出现,把字段名展现在表格头,列表用div出现,字段名和它的值放在一同展现。

  6. 日历
    日历用的是FullCalendar插件,在挂载组件里的表达式里加载并装备。

  7. 甘特图
    下面专节解说

  8. 报表
    有个挂载组件加载highcharts插件并初始化$v.使命.状况$v.使命.使命类型
    每个图表都是直接烘托在各自的挂载组件$el上面,在$obj.option里界说其动态选项,在挂载事情里增加动态数据。
    点击每个数量都会弹窗展现其使命列表。

甘特图

  1. 挂载时初始化$v.甘特
    move函数:每调用一次都会在时刻轴增加一周,传入负值时就把时刻轴往左延伸,轴 – 7,正值便往右,轴 + 7,在队首或队尾推入新增的一周(包括年月日信息)。
    日期核算比月份杂乱点,咱们以当周的星期几为基点,前面的日期推入队首(unshift),后面的日期推入队尾(push)。值得留意的是延伸过程中日期有或许是小于0或许大于本月最大天数,那就意味着日期跨月份了,小了就要加上上月天数,大了要减去本月天数。
    月:也包括年份,用来烘托年月轴
    日:用来烘托日期轴
    首日:用来核算使命条和今日线(gantt-today-line)的left款式

  2. 延伸时刻轴
    挂载时预先以今日为中心向前后各延伸了10周,一起在年月轴两边各放置了一个穿插调查器,当用户滚到它那里时自动持续延伸4周。$v.甘特.inited用来防止还未初始化就触发翻滚。

  3. hover
    鼠标挪到左边固定栏的使命上时(onMouseOver)会把对应的使命条滚入可视规模(scrollIntoViewIfNeeded)。
    鼠标挪到使命条上时展现使命概要信息和前后拖拽手柄。

  4. 拖拽
    拖动使命条本体和前后拖拽手柄都能够更改使命的开端时刻和(或)截止时刻,一起动态显现拖拽层(gantt-drag-mask)的可视化作用。
    鼠标按下时开端监听鼠标移动事情,鼠标松开时依据移动距离/偏移量修正开端时刻和(或)截止时刻。
    拖拽使命条本体时假如未发生位移应该以为是点击动作然后弹窗展现使命概况

使命

  1. 新建使命
    A. 在看板、表格、列表类型的组件的右上角都有个“新建”按钮用来新建无预设使命
    B. 每个分组都有个加号按钮用来增加同组新使命:在$f.创立使命的挂载事情中将把$v.modal.分组赋给用来分组的字段中,假如该字段是状况则进一步过滤出或许的状况选项,有父使命类型时也同理;
    C. 在使命弹窗中,假如允许有子使命类型,则能够在其某个子使命标签栏里新建子使命,此刻预设了父使命。

  2. 本组使命进展占比
    每组使命上方都有个进展条,分别表明本组已完成、进行中、未开端的使命数及其占比。

  3. 使命弹窗顶部
    由项目名、使命类型、父使命arr数组、当时使命标题及各自图标和色彩组成。
    每节父使命可点击展现其概况。

  4. 分享到谈天

  5. 固定到使命栏
    $v.使命栏是当时项目固定的使命列表,可展开缩短,可移除可点击弹出概况。

  6. 归档使命

  7. 删去使命
    一起也要删去其相关的一个使命活动和多个资源。
    把一切相关资源查找出来,把回来来的arr克隆一下再顺次删去:
    r.arr.clone().forEach(′r.arr.clone().forEach(‘resource.delete($x._id)’)

  8. 标题
    点击切换到修改形式并聚集,失掉焦点或按下回车时保存修正并切换回展现形式。

  9. 当时状况
    展现称号、图标和色彩
    点击弹出当时状况下一个可流通的状况选项

  10. 担任人、开端时刻、截止时刻

  11. 基本信息
    展现的是当时使命类型的自界说特点及其在此使命中的值。
    分别依据各自的特点类型来展现,一般分3列展现,但富文本和多行文本独占一行。

  12. 子使命标签栏及其列表
    可点击展现,可免除相关、删去使命,可改变担任人和到日期

  13. 相关使命
    相关又非直接子使命

  14. 附件
    使命弹窗的顶层是个挂载组件,会把相关资源查找出来,虽然一开端不展现附件列表但也是要展现附件数量的。
    增加,重命名,删去
    附件图标或许是上去前的本地文件预览图thumb,也或许是资源上传后的缩略图,还或许是依据其文件类型预设的文件图标。

  15. 谈论

  16. 活动
    由于用户点击的时分才展现,所以能够推迟加载,单独寄存于相关xtk中,没必要像谈论相同存于使命中。

日期挑选器

日期挑选器是比较常用的功用,也有点小杂乱,本来能够选一个开源的js库直接运用的,刚开端的时分为了验证表达式的能力就直接写了。

  1. 弹出日期挑选器前先初始化$v.pop
    keep:为坚持点击弹框自身不关框,参阅c.exp.onLogin里增加的一个大局click事情date:当时已设日期/时刻,假如没有就会是今日time:是否需求设置时刻,假如上面的date里包括了分钟/秒钟则默许为真F5:意图是再次触发日期挑选器里的挂载事情然后从头初始化‘c.exp.onLogin里增加的一个大局click事情
    date:当时已设日期/时刻,假如没有就会是今日
    time:是否需求设置时刻,假如上面的date里包括了分钟/秒钟则默许为真
    F5:意图是再次触发日期挑选器里的挂载事情然后从头初始化`
    v.日期`
    cb:选中/铲除日期是调用的回调函数,它会做“截止时刻不能早于开端时刻”的验证后保存/铲除对应日期。

  2. 日期挑选器顶层是个挂载组件用以结构$v.日期
    F5函数:依据v.日期里的年和月结构那个月份的日期数组v.日期里的年和月结构那个月份的日期数组v.日期.arr,每次挂载或年份、月份发生改变时都要调用。
    日期数要比一个月的天数多,用的是6周,也即6 * 7的二维数组,所以有前头有部分日期是上个月的,后头有部分是下个月的。咱们以本月第一个星期几作为起点,小于它的是上个月的,月份 – 1,日期 + 上月天数;大于本月天数的是下个月的,月份 + 1,日期 – 本月天数。
    别的13月份是明年的1月,0月份是去年12月。

  3. 回来日期
    假如需求设置时刻则有必关键“确认”按钮才回来由年月日时分结构的date,点选日期仅仅更新$v.日期里的月和日。
    假如不需求设置时刻点选日期则会当即回来由选中年月日结构的date。

  4. 铲除
    假如需求设置时刻“铲除”按钮仅仅封闭时刻设置表单
    假如不需求设置时刻则会当即回来空以便调用者铲除此日期

  5. 快速输入时刻
    除了直接在输入框直接输入小时分钟数外能够点击输入框上方或下方的箭头进行加减,乃至直接按键盘上的上下箭头键进行快速加减。为提高功率,分钟数是以5为单位进行加减的。
    留意在加减过程中小时分钟数超出规模时的特别处理。

  6. 加减年份/月份
    顶部有双箭头加减年份,单箭头图标可加减月份。留意月份或许会翻到去年或明年时的检查。

  7. 快速挑选跨度大的年份/月份
    当需求挑选较远的年份时用上面的箭头一步步加减有点慢,比方挑选一个老人的出世年月日,此刻点击顶部中心的年月能够直接挑选月份,再点击顶部中心的年份能够以20年为单位快速定位年份。

批阅

规划批阅表单、分条件设置流程、实时核算明细核算和批阅人、批阅流程展现、赞同/回绝/转交/吊销批阅、谈论和查阅记载、即时音讯告诉批阅人、发送到谈天。

表单规划

  1. 分组办理

  2. 模板办理

  3. 批阅表单规划
    表单规划器是个拖拉拽的可视化修改器,自身便是个简易版的零代码运用开发工具,包括三部分:可选控件、表单主体及表单和控件特点设置。
    特点包括:特点类型,特点名,提示文字,是否必填等。
    单选框、复选框、下拉列表有选项列表。
    明细是个特别控件容器,可包括其他控件。明细里边的数字类型的控件还能够有“是否参加明细核算”,“是否条件流程因素项”两项特点。

关键、难点:

  1. 拖拽运用的是Sortable.js。
    列表之间拖拽的关键有相同的组名(group name),可选控件列表的组的拉取选项(group pull)用的是clone,表明被拽出列表时是克隆一份给表单主体而不是被拽离走了,一起组不可增加新控件(put: false)。group: { name: “group”, pull: “clone”, put: false }。
    嵌套列表引荐装备:{ fallbackOnBody: true, swapThreshold: 0.65 }。
    onSort函数要分是表单主体里控件间排序仍是从可选控件里拉进来一个控件,拉进来时参数里有个pullMode是clone(对应前面的拉取选项clone),

  2. 把控件从一个方位拖到新的方位时,是先把它从原来的方位(oldIndex)移除,在刺进到新方位(newIndex)
    f.x.特点.splice(f.x.特点.splice(l.e.newIndex, 0, f.x.特点.splice(f.x.特点.splice(l.e.oldIndex, 1)[0])

  3. 单击选中一个表单控件时装备控件特点途径:v.批阅表单.特点=”特点.”+v.批阅表单.特点 = “特点.” + index;而明细里的控件特点途径则是:v.批阅表单.特点=”特点.”+v.批阅表单.特点 = “特点.” + parent.index+”.特点.”+index + “.特点.” + index,它们是被嵌套在明细控件内的,为了不触发外层事情用$event.stopPropagation()阻挠事情传播
    修改控件各特点时增加onChange事情,即便是空事情也会跟着输入或勾选而实时更新/(烘托)表单主体对应控件然后有更好的修改体会。

  4. 控件有多种类型,每种类型的表现方法和特点都不同,所以要依据不同的类型用烘托条件来操控显现哪种类型的控件。大家可依据实践需求进一步丰富控件列表。

  5. 从头烘托
    表单主体是用一个挂载组件包装的,当增加新控件或控件排序时给$v.F5特点一个新值使表单从头烘托。
    明细里的特点列表也如此,但运用另一个变量$v.F5明细仅从头烘托明细的特点。

界说批阅流程

不同类型批阅,批阅流程及每个流程的批阅人不同

  1. 自由流程
    提交人能够自由挑选批阅由几步组成,每个阶段需求谁来批阅,灵活性比较强,适合杂乱程度不高且批阅流程不定的批阅,但不利于批阅流程的规范性。

  2. 固定流程
    不管请求条件怎么,批阅流程都是固定,适合杂乱程度不高但流程固定的批阅。

  3. 分条件设置流程
    最常用的批阅流程,当请求条件不一起,需求不同的批阅流程和批阅人,如:报销金额低于5000时只需求1级主管批阅即可,报销金额在5000至10000时,需求增加2级主管批阅,大于10000时则需求在增加boss批阅。

  4. 批阅知会人
    批阅中不需求某些成员参加批阅流程,但需求让TA知晓这个批阅。

关键、难点:

  1. 部分栏是公司的安排架构,可按部分分级增加一个或多个批阅人。“部分主管”是个未确认的变量,会在建议批阅时得到替换成详细人员。

  2. 分条件设置流程中可通过表达式界说某种条件下的批阅流,如招聘人数或报销金额越多需求参加批阅的人也越多层级越高。留意条件的接连性,不要留下空挡。

建议批阅

  1. 填写请求表单

  2. 实时核算明细核算

  3. 实时核算批阅人
    获取部分主管

  4. 提交批阅
    验证表单必填项。
    生成批阅编号

关键、难点:

  1. 明细核算分为算计与总计
    算计是某个待核算字段之和,总计是各待核算字段算计之和。
    累加用:reduce(“acc+acc + x”, 0)

  2. 条件流程中依据前面编好的条件表达式(x.条件)从批阅流程列表中找到契合条件的流程。一个关键是履行条件表达式是要把请求表单内容(x.条件)从批阅流程列表中找到契合条件的流程。一个关键是履行条件表达式是要把请求表单内容(f.请求)传进去作为履行环境;另一个关键是找到流程的批阅人列表需求克隆一下赋给请求表单的待批阅人,由于接下来的批阅改成会更改此待批阅人(如替换部分主管,转交批阅人)而咱们并不想影响到原流程中的批阅人。
    f.请求.待批阅人=批阅流程.find(′exc(f.请求.待批阅人 = 批阅流程.find(‘exc(x.条件, $f.请求)’).批阅人.clone()

  3. 页面onReady里界说了“找部分主管”函数,请求表单挂载时履行,条件流程中输入数字时也会履行。
    难点是递归调用“$exp.部分主管”,部分从上往下一级级递归寻觅直到到达请求人所在部分时被stopIf()停止。每次递归都把当时部分传给表达式履行环境。

  4. 批阅编号是请求年月日+4位数的序列号。序列号是每天从1开端的唯一数,每次请求都从数据库增加($inc)1得到。

  5. 提交批阅时从待批阅人列表把第一个批阅人移出来作为当时批阅人,并发送即时音讯给TA。

批阅展现

  1. 当时状况

  2. 请求人

  3. 批阅概况
    各类型数据展现
    明细及其算计、总计

  4. 批阅流程

  5. 知会人

  6. 谈论

  7. 查阅记载

关键、难点:

  1. 分类报销能够把批阅概况较全面地展现,它外层的是个table元素的数据组件,里边由4个tbody,但它操控的是第二个用来展现明细的数据组件,第一个tbody是空的,用来占位,第三个用来展现特点列表,第四个放在最下面用来显现总计。
    值得玩味的是第二个用来展现明细的数据组件没有装备HTML元素,即它自身并不会烘托成HTML元素,而是为了操控它第一个子元素的烘托,即循环展现明细列表(第二个子元素用来展现算计),而每个明细又有多项特点,再次运用数据组件,而明细里还有数组型特点要用到数据组件(比方上传多个附件)。
    这是个嵌套运用数据组件极致展现杂乱数据的比如。

  2. 批阅流程中的数据组件操控的是第二个li,由批阅流、当时批阅人、待批阅人兼并得来,第一个li固定放请求人,不受数据组件操控。
    这儿的【批阅流】是现已参加批阅动作的人,或许包括吊销人(请求人自己)和被转交人。每次动作都往批阅流中推入相关信息:push: { “x.批阅流”: { 谁: c.me._id, 时刻: date(), 动作, 意见 } }

  3. 谈论的input并不是用来输入的,而是点击时(onFocus时让v.modal.谈论=true)弹出含有textarea的谈论表单,点击其他当地能回收谈论表单是由于在更高层的当地(modal−detail−main)把v.modal.谈论 = true)弹出含有textarea的谈论表单,点击其他当地能回收谈论表单是由于在更高层的当地(modal-detail-main)把v.modal.谈论置空。

  4. 批阅模态窗里有个挂载组件,非请求人每次翻开批阅模态窗时都往【批阅查阅】增加一条查阅记载,

  5. 为了减少批阅的信息量,把批阅谈论和批阅查阅都保存到相关xtk表中,以批阅._id作为key。在各类批阅列表场景中都不读取谈论和批阅查阅,翻开批阅模态窗时在上面的挂载组件里默许读取谈论,但依旧不读取批阅查阅。

批阅流程

  1. 赞同批阅

  2. 回绝批阅

  3. 转交批阅

  4. 吊销批阅

  5. 谈论批阅

  6. 查阅批阅

批阅告诉

  1. 我请求的

  2. 我批阅的

  3. 知会我的

  4. 即时音讯告诉

  5. 发送到谈天

关键、难点:

  1. 获取最新数据/从头烘托
    待审在不同的人之间流通,信息改变快速。除了期望等候“我”批阅的请求用即时音讯告诉到“我“以外,还期望在批阅页面时能收到跟“我”相关的【待批阅】请求。
    待批阅数:在根节点有个挂载组件,用$v.F5作为key表达式,每逢v.F5改变时(提交、吊销、赞同、回绝、转交批阅)都会从头拉取“我”相关的待批阅数量批阅列表:批阅列表的table用一个以‘v.F5改变时(提交、吊销、赞同、回绝、转交批阅)都会从头拉取“我”相关的待批阅数量
    批阅列表:批阅列表的table用一个以`
    v.tab + $v.F6`为key表达式挂载组件包装。当在左边导航栏(我请求的、我批阅的,知会我的)或右上角标签栏(待批阅、已批阅)切换时都会从头拉取最新批阅列表。