我是使用sharedb 作为后端 ,然后前端使用的elementUI样式,编写的一个值班小工具。接下来,让我们先来了解一下sharedb是什么吧?

  • sharedb工具

  github地址:https://github.com/share/sharedb.git

  官方概念:ShareDB是基于JSON文档的操作转换(OT)实时数据库后端它是DerbyJS Web应用程序框架的实时后端

  特征:

    1. 实时同步任何JSON文档
    2. 并发多用户协作
    3. 具有异步最终一致性的同步编辑API
    4. 实时查询订阅
    5. 与任何数据库轻松集成-MongoDBPostgresQL(实验性)
    6. 通过发布/订阅集成可水平扩展
    7. 从文档和操作中选择所需字段的投影
    8. 用于实现访问控制和自定义扩展的中间件
    9. 非常适合在浏览器或服务器上使用
    10. 重新连接后脱机更改同步
    11. 用于单元测试的数据库和pub / sub的内存中实现

   在这里,我只列出sharedb的概念以及特征,其中的其他特性(包括中间件等等),大家可以自行去github上去看。

   对于我来说,我是把github上的代码克隆下来,然后选择了其中的counter作为例子模板,去编写工具代码,首先对其中的server.js进行更改.

在server.js中,我只改了 doc.create({ name1: [], date: [] }, callback);这一行代码,在sharedb文档中doc.create(data[, type][, options][, function(err) {...}]) 在本地创建文档,然后将创建操作发送到服务器。因为对于我的需求,就是要将名字,以及对应名字所选的日期发送到服务器上,所以在这里我创建了这个对象。

  server.js

var http = require('http');
var express = require('express');
var ShareDB = require('sharedb');
var WebSocket = require('ws');
var WebSocketJSONStream = require('websocket-json-stream');

var backend = new ShareDB();
createDoc(startServer);
// Create initial document then fire callback
function createDoc(callback) {
  var connection = backend.connect();
  var doc = connection.get('examples', 'counter');
  doc.fetch(function (err) {
    if (err) throw err;
    if (doc.type === null) {
      doc.create({ name1: [], date: [] }, callback);
      return;
    };
    callback();
  });
}
function startServer() {
  // Create a web server to serve files and listen to WebSocket connections
  var app = express();
  app.use(express.static('static'));
  var server = http.createServer(app);
  // Connect any incoming WebSocket connection to ShareDB
  var wss = new WebSocket.Server({ server: server });
  wss.on('connection', function (ws, req) {
    var stream = new WebSocketJSONStream(ws);
    backend.listen(stream);
  });

  server.listen(8080);
  console.log('Listening on http://localhost:8080');
}

  client.js代码:

var sharedb = require('sharedb/lib/client');

// Open WebSocket connection to ShareDB server
var socket = new WebSocket('ws://' + window.location.host);
var connection = new sharedb.Connection(socket);

// Create local Doc instance mapped to 'examples' collection document with id 'counter'
var doc = connection.get('examples', 'counter');

// 获取文档的初始值并订阅更改
doc.subscribe(showNames);
doc.subscribe(dateRanges);
// 当文档更改时(由此客户端或任何其他客户端或服务器),
// 更新页面上的名字以及日期范围
doc.on('op', showNames);
doc.on('op', dateRanges);

function dateRanges() {
  app.$data.items = doc.data.date[0];
};
function showNames() {
  app.$data.messages1 = doc.data.name1[0] ? doc.data.name1[0] : [];
};
// 当点击提交名字的时候,更改本地的名字,并将同步更改服务器和其它链接的客户端//提交日期
function submite() {
  doc.submitOp([{ p: ['date', 0], li: app.$data.items }]);
};
//提交名字
function display() {
  doc.submitOp([{ p: ['name1', 0], li: app.$data.messages1 }]);
};
// Expose to index.html
global.display = display;
global.submite = submite;

html代码

这个代码就没什么好说的啦,主要功能 就是可以先输入名字,然后再选择想要进行值班的日期。而输入的名字不可以有重复的,主要是靠一个复选框实现的,以及日期选择器,感兴趣的同学可以看看哦!,大家也可以看到这里面引用的js是bundle.js,所以我们要把写在client.js中的代码,复制到bundle.js中才可以实现哦。

<!DOCTYPE html>
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<link rel="icon" href="1.ico">
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<title>值班小工具</title>

<body>
  <div id="app" >
    <router-view> </router-view>
  </div>
</body>
<script src="dist/bundle.js"></script>
<script>
  const inputName = {
    template: `<div>
                 <el-header>
                  <el-input id="date" placeholder="请输入用户名" name="date" v-model="message"></el-input>
                  <el-button v-on:click="display1" type="primary">提交 名字</el-button> 
                  </el-header> 
                  <el-main>
                      <span class="date">日 期</span>
                      <span class="name">姓 名</span>
                  <el-checkbox-group  v-model="checked"  >
                      <li v-for="(item,index) in $root.items" :key="item.checked">
                         <el-checkbox 
                              v-on:change="checked1(index,checked)" 
                              :label="item"
                              name="item"
                              >
                              {{item}}
                              <span class="messages">{{[$root.messages1[index]].join("|")}}</span>
                         </el-checkbox>
                      </li>
                  </el-checkbox-group>
                  </el-main>
              </div>` ,
    data() {
      name: inputName;
      return {
        message: '',
        messages1: [],
        checked: []
      }
    },
    methods: {
      checked1: function () {
      },
      display1: function (index, checked) {
        var a = document.getElementsByName('item');
        this.messages1 = this.$root.messages1;
        var cashName = document.getElementById("date").value;
        var result = cashName.match(/[\s`~!@#¥$%^&*()_+<>?:"{},.\/;'[\]\w]/im);
        for (var i = 0; i < a.length; i++) {
          if (result !== null) {
            this.$message({
              message: '请输入正确的名字哦!',
              type: 'warning'
            });
            break
          }
          if (a[i].checked && this.messages1[i] == null) {
            this.messages1[i] = new Array;
          }
          if (a[i].checked && this.messages1[i] !== null && this.messages1[i][0] !== this.message) {
            this.messages1[i].push(this.message);
          }
          if (a[i].checked && this.messages1[i] !== null && this.messages1[i].length > 2) {
            this.messages1[i].pop(this.message);
            this.$message({
              message: '前面已经有两人选择了哦,请选择其它日期吧!',
              type: 'warning'
            });
          }
        }
        display()
      }
    }
  };
  const inputDate = {
    template: `<div>
                 <el-header>
                  <el-date-picker
                      v-model="value"
                      type="daterange"
                      range-separator=""
                      start-placeholder="开始日期"
                      end-placeholder="结束日期"
                      format="yyyy年M月d日"
                      value-format="yyyy-MM-dd"
                      v-on:change="change1"
                    >
                  </el-date-picker>
                  <el-button onclick="submite()" type="primary">提交 日期</el-button>
                  </el-header>
                   <el-main>
                      <span class="date">日 期</span>
                      <span class="name">姓 名</span>
                      <li v-for="(item,index) in $root.items" :key="item.index">
                            {{item}}
                            <span class="messages1">{{[$root.messages1[index]].join('&')}}</span>
                      </li>
                  </el-main>
              </div>`,
    data() {
      name: inputDate;
      return {
        items: [],
        value: '',
      }
    },
    methods: {
      change1(value) {
        var begin = value[0];
        var end = value[1];
        var item = new Array();
        app.$data.items = item;
        var ab = begin.split("-");
        var ae = end.split("-");
        var db = new Date();
        db.setUTCFullYear(ab[0], ab[1] - 1, ab[2]);
        var de = new Date();
        de.setUTCFullYear(ae[0], ae[1] - 1, ae[2]);
        var unixDb = db.getTime();
        var unixDe = de.getTime();
        for (var k = unixDb; k <= unixDe;) {
          item.push(new Date(parseInt(k)).format().toString());
          k = k + 24 * 60 * 60 * 1000;
        }
      }
    }
  };
  const routes = [
    { path: '/inputDate', component: inputDate },
    { path: '/inputName', component: inputName }
  ];
  const router = new VueRouter({
    routes
  });
  Date.prototype.format = function () {
    var s = "";
    s += this.getFullYear() + "-";
    s += this.getMonth() + 1 + "-";
    s += this.getDate();
    return s;
  };
  var app = new Vue({
    router,
    data() {
      return {
        value6: '',
        items: [],
        checked: [],
        message: '',
        messages1: [],
        checked: []
      }
    }
  }).$mount('#app');
</script>
<style scoped>
  #app {
    /* width: 1200px;
    height: 848px; */
    background-position: center;
    padding-top: 0%;
  }

  body {
    margin: 0%;
  }

  .el-checkbox__label {
    display: inline-block;
    padding-left: 10px;
    line-height: 19px;
    font-size: 14px;
    width: 100%;
  }

  .el-date-picker {
    width: 30%;
  }

  h3 {
    margin: 40px 0 0;
  }

  a {
    color: #42b983;
  }

  .el-header {
   
    color: #333;
    text-align: center;
    line-height: 88px;
  }

  li {
    padding-top: 2%;
    list-style-image: url('./4.ico');
  }

  p {
    font-size: 20px;
    font-family: 'Segoe UI', Tahoma, Verdana, sans-serif
  }

  .date {
    padding-left: 10%;
  }

  .name {
    padding-left: 40%;
  }

  .el-main {
    padding-top: 1%;
    padding-left: 35%;
    width: 70%;
    height: 550px;
  }

  .el-input {
    width: 30%;
  }

  .messages1 {
    float: right;
    padding-right: 27%;
    text-decoration: underline;
  }

  .messages {
    float: right;
    padding-right: 24%;
    text-decoration: underline;
  }

  .el-checkbox {
    width: 80%;
    color: black;

  }
</style>

第一次写博客,可能有些地方写的不是很完整,欢迎大家提出意见!

posted on 2020-05-27 15:32  小名香菜~  阅读(1739)  评论(0编辑  收藏  举报