写在前面

本例使用js,jquery等方法实现虚拟餐厅的运行、烹饪、结账、发工资、扩大店面等功能,效果大体如下:

↓↓末尾可以进入demo↓↓


整体功能如下:

  1. 使用构造函数创建餐厅、服务员、厨师、雇员、顾客、菜品等,其中服务员和厨师继承于雇员。

  2. 各个类添加功能,如餐厅的hire()和fire(),雇员、服务员、厨师的work()等等方法。

  3. 使用svg创建图形。

  4. 在每个人的工作中,使用迭代来完成人物位置的改变。

    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
    function moveout(p){
    if(p.name){
    p.moving = true;
    }
    //因为顾客和服务员都会调用moveout,所以加了个判定判断实参是否是服务员。
    var src = p.position,
    dest = [];
    var svg1 = document.createElementNS('http://www.w3.org/2000/svg',"svg")
    svg1.setAttribute("width",760)
    svg1.setAttribute("height",506)
    var cir = document.createElementNS('http://www.w3.org/2000/svg',"circle")
    cir.setAttribute("cx",p.position[0])
    cir.setAttribute("cy",p.position[1])
    cir.setAttribute("r",10)
    if(p.name){
    dest = [80,10]
    cir.setAttribute("fill","rgb(99, 0, 0)")
    if(document.getElementById(p.name)){
    document.getElementById(p.name).remove();
    }
    var tex = document.createElementNS('http://www.w3.org/2000/svg',"text")
    tex.setAttribute("x", p.position[0] - 45)
    tex.setAttribute("y", p.position[1] + 5)
    tex.style = "font-size:16;fill:black"
    tex.innerHTML = p.name
    svg1.append(tex)
    }
    else{
    dest = [770,10]
    cir.setAttribute("fill","rgb(170, 170, 255)")
    if(document.getElementById(p.seat)){
    document.getElementById(p.seat).remove();
    }
    }
    if(src[1] > dest[1]){
    src[1] -= 10;
    setTimeout(function(){
    moveout(p)
    },20)
    }
    else if(src[1] < dest[1]){
    src[1] += 10;
    setTimeout(function(){
    moveout(p)
    },20)
    }
    else if(src[0] > dest[0]){
    src[0] -= 10;
    setTimeout(function(){
    moveout(p)
    },20)
    }
    else if(src[0] < dest[0]){
    src[0] += 10;
    setTimeout(function(){
    moveout(p)
    },20)
    }
    else{

    if(!p.slary){
    return;
    }
    else{
    p.working = false;
    p.moving = false;
    }
    }
    svg1.append(cir)
    svg1.id = p.name || p.seat
    document.getElementById("person").append(svg1)
    return;
    }
  5. 添加锁来锁定需要工作的类型的工作状态,使得任何人不能同时执行多件工作。

  6. 统计每天的盈利、支出情况。通过函数判定,当时间进入新的一天时,发工资,并更新统计数据。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    if(nowHour == 0 && newday == 0){
    newday = 1;
    //此处判断进入新的一天,并将flag设置为1。
    days++;
    expend += totleSlary;
    x.money -= totleSlary;
    InfoUpdate("今天支出了 " + totleSlary + " 工资");
    //InfoUpdate是更新所有工作内容的方法。
    receipts = 0;
    expend = 0;
    //重置收入和支出,以便统计每日收支情况。
    }
    if(nowHour == 1 && newday == 1){
    //此处将flag恢复为0。
    newday = 0;
    }
  7. 每完成一件工作,及时更新工作内容、效果在一个

  8. 条目上限20,自上而下更新的div中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    function InfoUpdate(str,checkOut){
    checkOut = checkOut || null;
    //此处根据实参判断是否是结账信息,是的话需要加粗~
    var info = document.getElementById("InfoList")
    if(info.childNodes.length > 20){
    info.childNodes[19].remove()
    }
    var li = document.createElement("li")
    if(checkOut){
    li.innerHTML = "<strong>" + str + "</strong>"
    }
    else{
    li.innerHTML = str
    }
    info.insertBefore(li,info.childNodes[0])
    return;
    }

期间遇到的问题:

  1. 在锁的使用中,遇到了已经锁定了的人物被选中的问题。经过分析,最后发现,我在调用人物的时候,是在函数中部将人物的锁给锁定。也许电脑会很快的计算出来,也许这个过程只需要0.001毫秒。但是即使是0.001毫秒,也有可能导致该人物在同一时间被不同工作选中。而解决的办法就是当人物一进入函数,立马将人物锁定。

  2. 在使用setTimeout做函数迭代的过程中发现,假设setTimeout函数之后还有一段代码,则js在编码的时候会先跳过setTimeout去执行下一段代码,而在settimeout的时间到了之后再跳回执行setTimeout中的代码。如:

    1
    2
    3
    4
    5
    6
    7
    8
    function(){
    setTimeout(function(){
    alert("1")
    return;
    },1000)
    alert("2")
    }
    //会先弹出2,再弹出1
  3. 闭包函数过多引起的内存泄露。因为各种调用关系比较复杂,导致很多函数有进无出,引起内存泄露。统一再编码整合之后,该问题得到很好的改善。


DEMO

来亲自体验吧~