瀏覽代碼

menu list

libf 2 年之前
父節點
當前提交
78e374a1ca

+ 117 - 47
src/App.vue

@@ -1,86 +1,156 @@
 <template>
   <div class="m3" v-if="auth && auth.signedUser">
-    <Header :auth="auth.signedUser" class="header" v-if="control.header.show"></Header>
+    <Header
+      :auth="auth.signedUser"
+      class="header"
+      v-if="control.header.show"
+    ></Header>
     <div class="main">
-      <SideBar class="sidebar" :auth="auth.signedUser" :global="global"  v-if="control.sidebar.show"></SideBar>
-      <div class="mainview" style="width:100vw;height:100vh;display:flex;flex-flow:column nowrap;align-items:center;justify-content:center;">
-         <Calendar style="flex: 1 1 auto; margin:10px;" :attendees="attendees"></Calendar>
+      <SideBar
+        class="sidebar"
+        :auth="auth.signedUser"
+        :global="global"
+        v-if="control.sidebar.show"
+      >
+      </SideBar>
+      <div
+        class="mainview"
+        style="
+          width: 100vw;
+          height: 100vh;
+          display: flex;
+          flex-flow: column nowrap;
+          align-items: center;
+          justify-content: center;
+        "
+      >
+        <HLTBox>
+          <div style="height: calc(100% - 50px); overflow: auto">
+            <CalList
+              style="flex: 0 0 200px; margin: 10px"
+              :indextitles="indextitles"
+              @select="menuselect"
+            ></CalList>
+          </div>
+          <div style="height: 100%; overflow: auto">
+            <Calendar
+              style="flex: 1 1 auto; margin: 10px"
+              :events="selectedevents"
+              @update="updateEvent"
+              @delete="deleteEvent"
+            ></Calendar>
+          </div>
+        </HLTBox>
       </div>
     </div>
-    <Footer :auth="auth.signedUser" class="footer" v-if="control.footer.show"></Footer>
+    <Footer
+      :auth="auth.signedUser"
+      class="footer"
+      v-if="control.footer.show"
+    ></Footer>
   </div>
 </template>
 
 <script>
+import Header from "./components/layout/Header";
+import Footer from "./components/layout/Footer";
+import SideBar from "./components/layout/SideBar";
+import HLTBox from "./components/box/HLTBox";
+import Calendar from "./components/calendar/Calendar.vue";
+import CalList from "./components/calendar/CalList.vue";
 
-import Header from './components/layout/Header';
-import Footer from './components/layout/Footer';
-import SideBar from './components/layout/SideBar';
-import Calendar from './components/calendar/Calendar.vue';
+import {
+  events,
+  onCalendarEventsLoaded,
+  updateEvent,
+  deleteEvent,
+} from "./components/calendar/CalendarData";
 
 export default {
-  name: 'app',
+  name: "app",
   components: {
     Header,
     Footer,
     SideBar,
+    HLTBox,
     Calendar,
+    CalList,
   },
-  data(){
+  data() {
     return {
       global: null,
       auth: null,
-      control:{
-        header:{
+      control: {
+        header: {
           show: true,
         },
-        sidebar:{
-          show: false,
+        sidebar: {
+          show: true,
         },
-        footer:{
+        footer: {
           show: true,
-        }
+        },
       },
-      attendees: ["ids from app","ids from app","ids from app","ids from app","ids from app","ids from app","ids from app"],
-    }
+      key: "ALL",
+      indexcals: events,
+      indextitles: {},
+      selectedevents: events["ALL"].events,
+    };
   },
-  created(){
+  created() {
     this.global = window.m3.global;
     this.auth = window.m3.auth;
   },
+  mounted() {
+    onCalendarEventsLoaded((events, titles) => {
+      this.indexcals = events;
+      this.indextitles = titles;
+      this.selectedevents = this.indexcals[this.key].events;
+    });
+  },
   methods: {
-    open_calendar() {
-      Calendar.show();
-    }
+    // 更新一个日历事件
+    updateEvent(event) {
+      updateEvent(event);
+    },
+    // 删除一个日历事件
+    deleteEvent(event) {
+      deleteEvent(event);
+    },
+    // 从菜单选择一项日历
+    menuselect(key) {
+      this.key = key;
+      this.selectedevents = this.indexcals[this.key].events;
+    },
   },
-}
+};
 </script>
 
 <style>
-  body{
-    font-size: 12px;
-    font-family: "PingFang SC",Arial,"Microsoft YaHei",sans-serif;
-    margin: 0px;
-    padding: 0px;
-    overflow: hidden;
-  }
-  
-  .el-input__inner{
-    padding: 0 5px!important;
-  }
+body {
+  font-size: 12px;
+  font-family: "PingFang SC", Arial, "Microsoft YaHei", sans-serif;
+  margin: 0px;
+  padding: 0px;
+  overflow: hidden;
+}
 
-  .el-menu .svg-icon{
-    width: 1.2em!important;
-    height: 1.2em!important;
-    padding: 0px 5px 0 0;
-  }
+.el-input__inner {
+  padding: 0 5px !important;
+}
 
-  .main{
-    padding-top: 50px;
-    display: flex;
-  }
+.el-menu .svg-icon {
+  width: 1.2em !important;
+  height: 1.2em !important;
+  padding: 0px 5px 0 0;
+}
 
-  .container{
-    overflow: hidden;
-  }
+.main {
+  padding-top: 50px;
+  display: flex;
+}
+
+.container {
+  overflow: hidden;
+}
 </style>

+ 32 - 0
src/components/calendar/CalList.vue

@@ -0,0 +1,32 @@
+<template>
+    <el-menu mode="vertical"
+        :default-active="activeindex"
+        @select="menuselect">
+        <el-menu-item v-for="item in indextitles"
+              :key="item.id" :index="item.id">{{item.name}}</el-menu-item>
+    </el-menu>
+</template>
+<script>
+
+export default {
+    name: "CalList",
+    props: {
+        indextitles: {},
+    },
+    data: () => {
+        return {
+            activeindex: "ALL",
+        };
+    },
+    mounted() {
+    },
+    methods: {
+        menuselect(key) {
+            this.activeindex = key;
+            this.$emit("select", key);
+        },
+    }
+}
+</script>
+<style scoped>
+</style>

+ 52 - 52
src/components/calendar/Calendar.vue

@@ -1,6 +1,7 @@
 <template>
   <div>
     <div
+      ref="caldiv"
       style="
         border: 1px solid #cccccc;
         padding: 0px 0px 0px 0px;
@@ -10,7 +11,7 @@
       "
     >
       <span style="margin-left: 10px; margin-right: 10px">📅</span>
-      <select v-model="selectedView" class="view-select">
+      <!-- <select v-model="selectedView" class="view-select">
         <option
           v-for="view in viewOptions"
           :key="view.value"
@@ -18,7 +19,7 @@
         >
           {{ view.title }}
         </option>
-      </select>
+      </select> -->
       <div class="buttons">
         <el-button type="text" @click="onClickTodayButton"> 今天 </el-button>
         <el-button
@@ -67,7 +68,7 @@
         @clickTimezonesCollapseBtn="onClickTimezonesCollapseBtn"
       />
     </div>
-    <EventForm ref="eventform" style="visibility:hidden;"></EventForm>
+    <EventForm ref="eventform" style="display:none;"></EventForm>
   </div>
 </template>
 
@@ -78,7 +79,7 @@ import "./tuical/toastui-calendar.css";
 import "tui-date-picker/dist/tui-date-picker.min.css";
 import "tui-time-picker/dist/tui-time-picker.min.css";
 
-import { events, calendars } from "./mock-data";
+import { events, calendars } from "./CalendarData";
 import { theme } from "./theme";
 import "./calendar.css";
 
@@ -91,9 +92,13 @@ export default {
     EventForm,
   },
   props: {
+    key: "",
+    events: {
+      type: Array,
+    },
     attendees: {
       type: Array,
-      default: () => ["*"],
+      default: () => ["ids from app"],
     },
   },
   data() {
@@ -109,7 +114,6 @@ export default {
           name: "notice2",
         },
       ],
-      events,
       zones: [
         {
           timezoneName: "Asia/Shanghai",
@@ -172,29 +176,29 @@ export default {
     },
   },
   mounted() {
-    m3.callFS("/matrix/calendar/load.js")
-      .then((res) => {
-        //console.log(res)
-        if (
-          res.status == "ok" &&
-          res.message &&
-          res.message.data &&
-          res.message.data.length > 0
-        ) {
-          var cals = [];
-          for (var i in calendars) {
-            cals.push(calendars[i]);
-          }
-          for (var i in res.message.calendars) {
-            cals.push(res.message.calendars[i]);
-          }
-          this.calendarInstance.setCalendars(cals);
-        }
-      })
-      .catch((err) => {
-        console.error(err);
-      });
-
+    // m3.callFS("/matrix/calendar/load.js")
+    //   .then((res) => {
+    //     //console.log(res)
+    //     if (
+    //       res.status == "ok" &&
+    //       res.message &&
+    //       res.message.data &&
+    //       res.message.data.length > 0
+    //     ) {
+    //       var cals = [];
+    //       for (var i in calendars) {
+    //         cals.push(calendars[i]);
+    //       }
+    //       for (var i in res.message.calendars) {
+    //         cals.push(res.message.calendars[i]);
+    //       }
+    //       this.calendarInstance.setCalendars(cals);
+    //       // this.events = events;
+    //     }
+    //   })
+    //   .catch((err) => {
+    //     console.error(err);
+    //   });
     this.setDateRangeText();
   },
   methods: {
@@ -235,26 +239,35 @@ export default {
     onCustomFormPopup(eventData) {
       eventData.CustomEventForm = true;
       
+      var l = this.$refs["caldiv"].offsetLeft+1;
+      var t = this.$refs["caldiv"].offsetTop+1;
+      var w = this.$refs["caldiv"].clientWidth;
+      var h = this.$refs["caldiv"].clientHeight-1;
+      this.$refs["eventform"].$el.style.position = "absolute";
+      this.$refs["eventform"].$el.style.left = l + "px";
+      this.$refs["eventform"].$el.style.top = t + "px";
+      this.$refs["eventform"].$el.style.width = w + "px";
+      this.$refs["eventform"].$el.style.height = h + "px";
+
       const event = {
-        calendarId: eventData.calendarId || "",
+        calendarId: eventData.calendarId || "work",
         id: eventData.id || String(Math.random()),
         title: eventData.title,
         isAllday: eventData.isAllday,
         start: eventData.start,
         end: eventData.end,
-        category: eventData.category,
+        repeattype: eventData.repeattype || "",
+        category: eventData.category || "time",
         dueDateClass: "",
         location: eventData.location,
         state: eventData.state,
         isPrivate: eventData.isPrivate,
         body: eventData.body,
-        attendees: eventData.attendees,
+        attendees: this.attendees,
       };
 
       this.$refs["eventform"].event = event;
-      this.$refs["eventform"].show();
-
-      eventData.Submit = event;
+      this.$refs["eventform"].show(eventData.submit);
     },
     onSelectDateTime({ start, end }) {
       console.group("onSelectDateTime");
@@ -262,23 +275,8 @@ export default {
       console.groupEnd();
     },
     onBeforeCreateEvent(eventData) {
-      const event = {
-        calendarId: eventData.calendarId || "",
-        id: String(Math.random()),
-        title: eventData.title,
-        isAllday: eventData.isAllday,
-        start: eventData.start,
-        end: eventData.end,
-        category: eventData.category,
-        dueDateClass: "",
-        location: eventData.location,
-        state: eventData.state,
-        isPrivate: eventData.isPrivate,
-        body: eventData.body,
-        attendees: this.attendees,
-      };
-
-      this.calendarInstance.createEvents([event]);
+      this.calendarInstance.createEvents([eventData]);
+      this.$emit("update", {target: null, change: eventData});
     },
     onBeforeUpdateEvent(updateData) {
       console.group("onBeforeUpdateEvent");
@@ -293,6 +291,7 @@ export default {
         targetEvent.calendarId,
         changes
       );
+      this.$emit("update", {target: targetEvent, change: changes});
     },
 
     onBeforeDeleteEvent({ title, id, calendarId }) {
@@ -301,6 +300,7 @@ export default {
       console.groupEnd();
 
       this.calendarInstance.deleteEvent(id, calendarId);
+      this.$emit("delete", {target: {id, calendarId}});
     },
     onAfterRenderEvent({ title }) {
       console.group("onAfterRenderEvent");

+ 275 - 0
src/components/calendar/CalendarData.js

@@ -0,0 +1,275 @@
+import { TZDate } from './tuical/toastui-calendar';
+
+import { addDate, addHours, diffDays, subDate, subtractDate } from './utils';
+
+const today = new TZDate();
+
+/*
+* @property {string} [id] - Event id.
+* @property {string} [calendarId] - Calendar id.
+* @property {string} [title] - Event title.
+* @property {string} [body] - Body content of the event.
+* @property {string} [isAllday] - Whether the event is all day or not.
+* @property {string|number|Date|TZDate} [start] - Start time of the event.
+* @property {string|number|Date|TZDate} [end] - End time of the event.
+* @property {number} [goingDuration] - Travel time which is taken to go in minutes.
+* @property {number} [comingDuration] - Travel time which is taken to come back in minutes.
+* @property {string} [location] - Location of the event.
+* @property {Array.<string>} [attendees] - Attendees of the event.
+* @property {string} [category] - Category of the event. Available categories are 'milestone', 'task', 'time' and 'allday'.
+* @property {string} [dueDateClass] - Classification of work events. (before work, before lunch, before work)
+* @property {string} [recurrenceRule] - Recurrence rule of the event.
+* @property {string} [state] - State of the event. Available states are 'Busy', 'Free'.
+* @property {boolean} [isVisible] - Whether the event is visible or not.
+* @property {boolean} [isPending] - Whether the event is pending or not.
+* @property {boolean} [isFocused] - Whether the event is focused or not.
+* @property {boolean} [isReadOnly] - Whether the event is read only or not.
+* @property {boolean} [isPrivate] - Whether the event is private or not.
+*/
+
+var allevents = [
+  {
+    id: '444',
+    calendarId: 'work',
+    title: '国产化设备投产',
+    category: 'allday',
+    start: addDate(today, 5),
+    end: addDate(today, 15),
+  },
+  {
+    id: '555',
+    calendarId: 'work',
+    title: '网银服务变更',
+    category: 'time',
+    start: addHours(today, 24),
+    end: addHours(today, 27),
+  },
+  {
+    id: '666',
+    calendarId: 'work',
+    title: '本地网络升级',
+    category: 'time',
+    start: addHours(today, 24),
+    end: addHours(today, 27),
+  },
+  {
+    id: '777',
+    calendarId: 'work',
+    title: '离中考还有 ' + diffDays(new TZDate('2023-06-18'), today) + " 天",
+    category: 'milestone',
+    start: today,
+    end: today,
+    isReadOnly: true,
+  },
+  {
+    id: '991',
+    calendarId: 'work',
+    title: '测试吐司日历',
+    category: 'time',
+    start: addHours(today, 24),
+    end: addHours(today, 27),
+  },
+  {
+    id: '992',
+    calendarId: 'rest',
+    title: '测试完成',
+    category: 'milestone',
+    start: addDate(today, 5),
+    end: addDate(today, 5),
+  },
+  {
+    id: '993',
+    calendarId: 'maintain',
+    title: '全天维护',
+    category: 'allday',
+    start: subtractDate(today, 2),
+    end: subtractDate(today, 1),
+  },
+  {
+    id: '994',
+    calendarId: 'work',
+    title: '报表开发',
+    category: 'task',
+    start: addHours(today, 48),
+    end: addHours(today, 51),
+  },
+];
+
+var calendars = [
+  {
+    id: 'work',
+    name: '工作日',
+    backgroundColor: '#9e5fff',
+    borderColor: '#9e5fff',
+    dragBackgroundColor: '#9e5fff',
+  },
+  {
+    id: 'rest',
+    name: '休息日',
+    backgroundColor: '#00a9ff',
+    borderColor: '#00a9ff',
+    dragBackgroundColor: '#00a9ff',
+  },
+  {
+    id: 'maintain',
+    name: '维护期',
+    backgroundColor: '#55a9ff',
+    borderColor: '#55a9ff',
+    dragBackgroundColor: '#55a9ff',
+  },
+];
+
+var indexcalendars = {};
+var indexevents = { "ALL": { name: "所有日历", events: allevents } };
+var titleidmap = {};
+var maxtitleid = 1;
+
+function getTitleID(title) {
+  if (titleidmap[title]) {
+    return titleidmap[title];
+  }
+  titleidmap[title] = "T" + maxtitleid;
+  maxtitleid++;
+  return titleidmap[title];
+}
+
+let param = encodeURIComponent(JSON.stringify({ start: '', end: '' }));
+m3.callFS("/matrix/calendar/load.js", param).then((res) => {
+  //console.log(res)
+  for (var i in calendars) {
+    indexcalendars[calendars[i].id] = calendars[i];
+  }
+  if (res.status == "ok" && res.message && res.message.data && res.message.data.length > 0) {
+    for (var i in res.message.data) {
+      var dat = res.message.data[i];
+      dat.id = allevents.length;
+      // console.log(dat);
+      allevents.push(dat);
+      for (var i in res.message.calendars) {
+        if (indexcalendars[res.message.calendars[i].id]) {
+          indexcalendars[res.message.calendars[i].id] = res.message.calendars[i];
+          for (var ni = 0; ni < calendars.length; ni++) {
+            calendars[ni] = res.message.calendars[i];
+          }
+        } else {
+          calendars.push(res.message.calendars[i]);
+          indexcalendars[res.message.calendars[i].id] = res.message.calendars[i];
+        }
+      }
+    }
+    for (var i = 0; i < allevents.length; i++) {
+      var event = allevents[i];
+      if (!indexevents[event.calendarId]) {
+        var cal = indexcalendars[event.calendarId];
+        if (cal && cal.name) {
+          indexevents[event.calendarId] = { name: "所有" + cal.name, events: [] };
+        } else {
+          indexevents[event.calendarId] = { name: "all " + event.calendarId, events: [] };
+        }
+      }
+      var tid = getTitleID(event.title);
+      if (!indexevents[tid]) {
+        indexevents[tid] = { name: event.title, events: [] };
+      }
+      indexevents[event.calendarId].events.push(event);
+      indexevents[tid].events.push(event);
+    }
+    indexevents["ALL"].events.push(event);
+    updateproc();
+  }
+}).catch((err) => {
+  console.error(err);
+});
+
+var calendarEventsLoadedProc;
+var onCalendarEventsLoaded = function (fp) {
+  calendarEventsLoadedProc = fp;
+}
+
+var updateproc = function() {
+  var indextitles = [];
+  for(var k in indexevents) {
+    indextitles.push({id: k, name: indexevents[k].name});
+  }
+  if (calendarEventsLoadedProc) {
+    calendarEventsLoadedProc(indexevents, indextitles);
+  }
+} 
+
+
+var updateEvent = function (event) {
+  var newdata = {};
+  var target = {};
+  if (!event.target) {
+    newdata = event.change;
+    target = newdata;
+  } else {
+    for (var k in event.target) {
+      newdata[k] = event.target[k];
+    }
+    for (var k in event.change) {
+      newdata[k] = event.change[k];
+    }
+  }
+  var tid = getTitleID(target.title);
+  if (!indexevents[tid]) {
+    indexevents[tid] = { name: target.title, events: [] };
+  }
+  var isnew = true;
+  for (var i = 0; i < indexevents["ALL"].events.length; i++) {
+    if (indexevents["ALL"].events[i].id == target.id) {
+      indexevents["ALL"].events[i] = newdata;
+      isnew = false;
+      break;
+    }
+  }
+  if (isnew) {
+    indexevents["ALL"].events.push(newdata);
+    indexevents[newdata.calendarId].events.push(newdata);
+    indexevents[tid].events.push(newdata);
+  } else {
+    for (var i = 0; i < indexevents[target.calendarId].events.length; i++) {
+      if (indexevents[target.calendarId].events[i].id == target.id) {
+        indexevents[newdata.calendarId].events[i] = newdata;
+        break;
+      }
+    }
+    for (var i = 0; i < indexevents[tid].events.length; i++) {
+      if (indexevents[tid].events[i].id == target.id) {
+        indexevents[tid].events[i] = newdata;
+        break;
+      }
+    }
+  }
+  updateproc();
+  return indexevents;
+}
+
+var deleteEvent = function (event) {
+  for (var i = 0; i < indexevents["ALL"].events.length; i++) {
+    if (indexevents["ALL"].events[i].id == event.target.id) {
+      indexevents["ALL"].events.splice(i, 1);
+      break;
+    }
+  }
+  for (var i = 0; i < indexevents[event.target.calendarId].events.length; i++) {
+    if (indexevents[event.target.calendarId].events[i].id == event.target.id) {
+      indexevents[event.target.calendarId].events.splice(i, 1);
+      break;
+    }
+  }
+  var tid = getTitleID(event.target.title);
+  for (var i = 0; i < indexevents[tid].events.length; i++) {
+    if (indexevents[tid].events[i].id == event.target.id) {
+      indexevents[tid].events.splice(i, 1);
+      break;
+    }
+  }
+  if (indexevents[tid].length == 0) {
+    delete (indexevents, tid);
+  }
+  updateproc();
+  return indexevents;
+}
+
+export var events = indexevents, calendars = calendars, onCalendarEventsLoaded = onCalendarEventsLoaded, updateEvent = updateEvent, deleteEvent = deleteEvent;

+ 241 - 17
src/components/calendar/EventForm.vue

@@ -1,30 +1,254 @@
 <template>
-  <div>
-    <div class="test">ooooooooooooooooooooo</div>
-    <div class="test">ooooooooooooooooooooo</div>
-    <div class="test">ooooooooooooooooooooo</div>
-  </div>
+  <el-container style="display: none; position: absolute; background: #ffffff">
+    <el-main>
+      <el-form ref="form" label-width="150px" size="small">
+        <el-form-item label="名称">
+          <el-input placeholder="名称" v-model="event.title"></el-input>
+        </el-form-item>
+
+        <el-form-item label="日历标签">
+          <el-select v-model="event.calendarId" placeholder="日历标签">
+            <el-option
+              :label="item.name"
+              :value="item.id"
+              v-for="item in calendar.calendarId.list"
+              :key="item.id"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="日历分类">
+          <el-select v-model="event.category" placeholder="日历分类">
+            <el-option
+              :label="item.name"
+              :value="item.id"
+              v-for="item in calendar.categories.list"
+              :key="item.id"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="起止时间">
+          <el-date-picker
+            v-model="event.start"
+            :editable="true"
+            :clearable="true"
+            type="datetime"
+            format="yyyy-MM-dd HH:mm:ss"
+          ></el-date-picker>
+          -
+          <el-date-picker
+            v-model="event.end"
+            :editable="true"
+            :clearable="true"
+            type="datetime"
+            format="yyyy-MM-dd HH:mm:ss"
+          ></el-date-picker>
+        </el-form-item>
+
+        <el-form-item label="重复周期">
+          每
+          <el-select v-model="event.repeatcount" class="count-selector">
+            <el-option
+              :label="item.name"
+              :value="item.id"
+              v-for="item in calendar.repeatcount.list"
+              :key="item.id"
+            ></el-option>
+          </el-select>
+          <el-select v-model="event.repeattype" class="count-selector">
+            <el-option
+              :label="item.name"
+              :value="item.id"
+              v-for="item in calendar.repeattype.list"
+              :key="item.id"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="每周期起始时间点">
+          第
+          <el-select v-model="event.periodstartmonth" class="count-selector">
+            <el-option
+              :label="item.name"
+              :value="item.id"
+              v-for="item in calendar.repeatcount.list"
+              :key="item.id"
+            ></el-option>
+          </el-select>
+          月 第
+          <el-select v-model="event.periodstartweek" class="count-selector">
+            <el-option
+              :label="item.name"
+              :value="item.id"
+              v-for="item in calendar.repeatcount.list"
+              :key="item.id"
+            ></el-option>
+          </el-select>
+          周 第
+          <el-select v-model="event.periodstartday" class="count-selector">
+            <el-option
+              :label="item.name"
+              :value="item.id"
+              v-for="item in calendar.repeatcount.list"
+              :key="item.id"
+            ></el-option>
+          </el-select>
+          天
+          <el-select v-model="event.periodstarthour" class="count-selector">
+            <el-option
+              :label="item.name"
+              :value="item.id"
+              v-for="item in calendar.repeathour.list"
+              :key="item.id"
+            ></el-option>
+          </el-select>
+          时:
+          <el-select v-model="event.periodstartminute" class="count-selector">
+            <el-option
+              :label="item.name"
+              :value="item.id"
+              v-for="item in calendar.repeatminute.list"
+              :key="item.id"
+            ></el-option>
+          </el-select>
+          分
+        </el-form-item>
+
+        <el-form-item label="每周期持续时间">
+          <el-select v-model="event.perioddays" class="count-selector">
+            <el-option
+              :label="item.name"
+              :value="item.id"
+              v-for="item in calendar.repeatcount.list"
+              :key="item.id"
+            ></el-option>
+          </el-select>
+          天
+          <el-select v-model="event.periodhours" class="count-selector">
+            <el-option
+              :label="item.name"
+              :value="item.id"
+              v-for="item in calendar.repeathour.list"
+              :key="item.id"
+            ></el-option>
+          </el-select>
+          时:
+          <el-select v-model="event.periodminutes" class="count-selector">
+            <el-option
+              :label="item.name"
+              :value="item.id"
+              v-for="item in calendar.repeatminute.list"
+              :key="item.id"
+            ></el-option>
+          </el-select>
+          分
+        </el-form-item>
+
+        <el-form-item label="相关ID">
+          <el-input placeholder="相关ID" v-model="event.attendees">
+            <el-button
+              slot="append"
+              class="el-icon-search"
+              type="success"
+            ></el-button>
+          </el-input>
+        </el-form-item>
+
+        <el-form-item label="备注">
+          <el-input type="textarea" placeholder="备注" v-model="event.body">
+          </el-input>
+        </el-form-item>
+
+        <el-form-item>
+          <el-button @click="hide()">取消</el-button>
+          <el-button type="success" @click="save()">保存</el-button>
+        </el-form-item>
+      </el-form>
+    </el-main>
+  </el-container>
 </template>
 
 <script>
-
 export default Vue.component("EventForm", {
-    name: "EventForm",
-    props: {
-      event: {},
-    },
-    mounted() {
+  name: "EventForm",
+  props: {
+    event: {
+      type: Object,
+      default: () => {
+        return {};
+      },
     },
-    methods: {
-      show() {
-        
-        alert(JSON.stringify(this.event));
+    submit: {},
+  },
+  data() {
+    var countlist = function (m, n) {
+      var cl = [];
+      for (var i = m; i <= n; i++) {
+        cl.push({ id: i, name: "" + i });
       }
+      return cl;
+    };
+    return {
+      submitfunc: function(){},
+      calendar: {
+        calendarId: {
+          list: [
+            { id: "work", name: "工作日" },
+            { id: "rest", name: "非工作日" },
+            { id: "maintain", name: "维护期" },
+          ],
+        },
+        categories: {
+          list: [
+            { id: "task", name: "工作任务" },
+            { id: "milestone", name: "里程碑" },
+            { id: "allday", name: "全天事件" },
+            { id: "time", name: "日程安排" },
+          ],
+        },
+        repeatcount: {
+          list: countlist(1, 999),
+        },
+        repeathour: {
+          list: countlist(0, 23),
+        },
+        repeatminute: {
+          list: countlist(0, 59),
+        },
+        repeattype: {
+          list: [
+            { id: "", name: "不重复" },
+            { id: "d", name: "天" },
+            { id: "w", name: "周" },
+            { id: "m", name: "月" },
+            { id: "y", name: "年" },
+          ],
+        },
+      },
+    };
+  },
+  mounted() {},
+  methods: {
+    show(submitfunc) {
+      this.$el.style.display = "block";
+      this.submitfunc = submitfunc;
     },
+    save() {
+      this.submitfunc(this.event);
+      this.hide();
+    },
+    hide() {
+      this.$el.style.display = "none";
+    },
+  },
 });
 </script>
 <style scoped>
-.test {
-    color: red;
+.input {
+  width: 200px;
+}
+.count-selector {
+  width: 80px;
 }
 </style>

+ 51 - 0
src/components/calendar/QuerySelector.vue

@@ -0,0 +1,51 @@
+<template>
+  <div
+    style="display: none; position: absolute; background: #ffffff;"
+  >
+    <div>
+      关键字:
+      <el-input
+        placeholder=""
+        v-model="event.title">
+      </el-input>
+      <el-button>查询</el-button>
+    </div> 
+    <div>
+      全选:
+      <el-input
+        placeholder=""
+        v-model="event.title">
+      </el-input>
+    </div> 
+    <div><el-button @click="hide()">取消</el-button><el-button @click="save()">选择</el-button></div>
+  </div>
+</template>
+
+<script>
+export default Vue.component("EventForm", {
+  name: "EventForm",
+  props: {
+    event: {
+      type: Object,
+      default: () => {
+        return {};
+      },
+    },
+  },
+  mounted() {},
+  methods: {
+    show() {
+      this.$el.style.display = "block"; 
+    },
+    save() {
+      this.event.submit(this.event);
+      this.hide();
+    },
+    hide() {
+      this.$el.style.display = "none";
+    },
+  },
+});
+</script>
+<style scoped>
+</style>

+ 0 - 113
src/components/calendar/mock-data.js

@@ -1,113 +0,0 @@
-import { TZDate } from './tuical/toastui-calendar';
-
-import { addDate, addHours, diffDays, subDate, subtractDate } from './utils';
-
-const today = new TZDate();
-
-/*
-* @property {string} [id] - Event id.
-* @property {string} [calendarId] - Calendar id.
-* @property {string} [title] - Event title.
-* @property {string} [body] - Body content of the event.
-* @property {string} [isAllday] - Whether the event is all day or not.
-* @property {string|number|Date|TZDate} [start] - Start time of the event.
-* @property {string|number|Date|TZDate} [end] - End time of the event.
-* @property {number} [goingDuration] - Travel time which is taken to go in minutes.
-* @property {number} [comingDuration] - Travel time which is taken to come back in minutes.
-* @property {string} [location] - Location of the event.
-* @property {Array.<string>} [attendees] - Attendees of the event.
-* @property {string} [category] - Category of the event. Available categories are 'milestone', 'task', 'time' and 'allday'.
-* @property {string} [dueDateClass] - Classification of work events. (before work, before lunch, before work)
-* @property {string} [recurrenceRule] - Recurrence rule of the event.
-* @property {string} [state] - State of the event. Available states are 'Busy', 'Free'.
-* @property {boolean} [isVisible] - Whether the event is visible or not.
-* @property {boolean} [isPending] - Whether the event is pending or not.
-* @property {boolean} [isFocused] - Whether the event is focused or not.
-* @property {boolean} [isReadOnly] - Whether the event is read only or not.
-* @property {boolean} [isPrivate] - Whether the event is private or not.
-*/
-
-var events = [
-  {
-    id: '777',
-    calendarId: 'work',
-    title: '离中考还有 '+diffDays(new TZDate('2023-06-18'), today)+" 天",
-    category: 'milestone',
-    start: today,
-    end: today,
-    isReadOnly: true,
-  },
-  {
-    id: '991',
-    calendarId: 'work',
-    title: '测试吐司日历',
-    category: 'time',
-    start: addHours(today, 24),
-    end: addHours(today, 27),
-  },
-  {
-    id: '992',
-    calendarId: 'rest',
-    title: '测试完成',
-    category: 'milestone',
-    start: addDate(today, 5),
-    end: addDate(today, 5),
-  },
-  {
-    id: '993',
-    calendarId: 'maintain',
-    title: '全天维护',
-    category: 'allday',
-    start: subtractDate(today, 2),
-    end: subtractDate(today, 1),
-  },
-  {
-    id: '994',
-    calendarId: 'work',
-    title: '报表开发',
-    category: 'task',
-    start: addHours(today, 48),
-    end: addHours(today, 51),
-  },
-];
-
-var calendars = [
-  {
-    id: 'work',
-    name: '工作日',
-    backgroundColor: '#9e5fff',
-    borderColor: '#9e5fff',
-    dragBackgroundColor: '#9e5fff',
-  },
-  {
-    id: 'rest',
-    name: '休息日',
-    backgroundColor: '#00a9ff',
-    borderColor: '#00a9ff',
-    dragBackgroundColor: '#00a9ff',
-  },
-  {
-    id: 'maintain',
-    name: '维护期',
-    backgroundColor: '#55a9ff',
-    borderColor: '#55a9ff',
-    dragBackgroundColor: '#55a9ff',
-  },
-];
-
-let param = encodeURIComponent(JSON.stringify({start:'', end:''}));
-m3.callFS("/matrix/calendar/load.js", param).then( (res)=>{
-  //console.log(res)
-  if(res.status == "ok" && res.message && res.message.data && res.message.data.length > 0) {
-    for(var i in res.message.data) {
-      var dat = res.message.data[i];
-      dat.id = events.length;
-      // console.log(dat);
-      events.push(dat);
-    }
-  }
-}).catch( (err)=>{
-  console.error(err);
-} );
-
-export var events = events, calendars = calendars;

+ 10 - 10
src/components/calendar/tuical/toastui-calendar.mjs

@@ -6194,13 +6194,13 @@ function useGridSelection({
           isAllday: type !== "timeGrid",
           isPrivate: false,
           popupArrowPointPosition,
-          close: clearAll
+          close: clearAll,
+          submit: (eventData) => {
+            eventBus.fire("beforeCreateEvent", eventData);
+          },
         };
         eventBus.fire("customFormPopup", eventData);
         if (eventData.CustomEventForm) {
-          if (eventData.Submit) {
-            eventBus.fire("beforeCreateEvent", eventData.Submit);
-          }
           clearGridSelection();
         } else {
           showFormPopup(eventData);
@@ -6652,14 +6652,14 @@ function EventDetailPopup() {
         eventState: state,
         eventCategory: category,
         body,
-        popupArrowPointPosition
+        popupArrowPointPosition,
+        submit: (eventData) => {
+          const changes = getChanges(event, eventData);
+          eventBus.fire("beforeUpdateEvent", { event: event.toEventObject(), changes });
+        },
       };
       eventBus.fire("customFormPopup", eventData);
       if (eventData.CustomEventForm) {
-        if (eventData.Submit) {
-          const changes = getChanges(event, eventData.Submit);
-          eventBus.fire("beforeUpdateEvent", { event: event.toEventObject(), changes });
-        }
         hideAllPopup();
       } else {
         showFormPopup(eventData);
@@ -7326,7 +7326,7 @@ function EventFormPopup() {
       eventBus.fire("beforeCreateEvent", eventData);
     } else if (event) {
       const changes = getChanges(event, eventData);
-      eventBus.fire("beforeUpdateEvent", { event: event.toEventObject(), changes });
+      eventBus.fire("beforeUpdateEvent", { event: event.toEventObject(), newdata: eventData, changes });
     }
     hideAllPopup();
   };

+ 2 - 0
src/main.js

@@ -7,6 +7,8 @@ import zhLocale from 'element-ui/lib/locale/lang/zh-CN'
 // 开始动态加载依赖组件
 window.state && window.state("正在加载依赖组件...")
 
+Vue.use(ElementUI, { zhLocale })
+
 // 动态加载模块依赖关系
 // auth,global,Vue... 为 m3 内部加载的模块, 这里的定义只为标明依赖关系时引用, 初始化时会自动替换为m3内部定义
 let mods = {auth:{}, global:{}, Vue:{}}