فهرست منبع

fix: 添加排床

fan 2 سال پیش
والد
کامیت
aaf78a5be7
2فایلهای تغییر یافته به همراه614 افزوده شده و 3 حذف شده
  1. 92 0
      src/views/biz/bed/near/data.ts
  2. 522 3
      src/views/biz/bed/near/index.vue

+ 92 - 0
src/views/biz/bed/near/data.ts

@@ -0,0 +1,92 @@
+import dayjs from 'dayjs';
+import { nanoid } from 'nanoid';
+import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
+dayjs.extend(isSameOrBefore);
+const WEEKINFO = {
+  Mo: '星期一',
+  Tu: '星期二',
+  We: '星期三',
+  Th: '星期四',
+  Fr: '星期五',
+  Sa: '星期六',
+};
+
+export const COUNT = ['空班', '第一班', '第二班', '第三班', '第四班'];
+// 默认头部
+export function defaultHead() {
+  const res = [];
+  for (let i = 1; i < 7; i++) {
+    const date = dayjs().day(i).format('YYYY-MM-DD');
+    res.push({
+      monthDay: dayjs(date).format('MM-DD'),
+      week: WEEKINFO[dayjs(date).format('dd')],
+      current: dayjs().isSame(date, 'day'),
+      // 班次
+      count: ['第一班', '第二班', '第三班'],
+    });
+  }
+  return res;
+}
+const defaultBedCount = 5;
+// 默认床位
+export function defaultBed() {
+  const res = [];
+  for (let i = 0; i < defaultBedCount; i++) {
+    res.push({
+      bed: i < 10 ? '0' + i : '' + i,
+      regionName: 'A区',
+      regionCode: 'A',
+      robot: '4008s',
+      // 双机位
+      double: i % 2 == 0 ? true : false,
+    });
+  }
+  return res;
+}
+
+// 默认数据
+export function defaultData() {
+  const res = [];
+  for (let i = 0; i < defaultBedCount; i++) {
+    const obj = {
+      id: nanoid(5),
+      bed: i < 10 ? '0' + i : '' + i,
+      regionCode: 'A',
+      sailings: [],
+    };
+
+    for (let w = 1; w < 7; w++) {
+      const week = [];
+      const date = dayjs().day(w).format('YYYY-MM-DD');
+      // console.log(dayjs().isAfter(date, 'day'));
+      // console.log('date', date);
+      for (let s = 0; s < 3; s++) {
+        const bool = Math.round(Math.random() * 100) > 50;
+        week.push({
+          id: nanoid(5),
+          key: nanoid(8),
+          name: bool ? '刘' + nanoid(3) : '',
+          date: date,
+          old: dayjs().isSame(date, 'day') ? false : dayjs().isAfter(date, 'day'),
+          show: true,
+          empty: !bool,
+          edit: false,
+          error: false,
+          selected: false,
+          actived: false,
+          disabled: false,
+          // 横坐标
+          x: i,
+          // 纵坐标
+          y: w,
+          // 具体班次
+          z: s,
+        });
+        debugger;
+      }
+      obj.sailings.push(week);
+    }
+    res.push(obj);
+  }
+  return res;
+}

+ 522 - 3
src/views/biz/bed/near/index.vue

@@ -1,7 +1,526 @@
 <template>
-  <div> 占位符 </div>
+  <div class="mx-2 my-4 wrap">
+    <div>
+      <div class="my-4 filter">
+        <div>
+          <XTForm :form-data="formData" @change="callFilter" />
+        </div>
+      </div>
+      <div class="detail">
+        <div class="aside">
+          <div class="aside-item aside-item--tit">床位</div>
+          <div class="mb-2 aside-item" v-for="b in bed" :key="b.bed">
+            <div class="aside-item_bed">{{ b.bed }}</div>
+            <div class="aside-item_robot">
+              <i class="iconfont icon-xt-dual-pump_default" v-if="b.double" />
+              <span>{{ b.robot }}</span>
+            </div>
+          </div>
+        </div>
+        <div class="container">
+          <Affix :offset-top="100" @change="changeAffix">
+            <div class="mb-2 container-head">
+              <div class="head-item" v-for="h in head" :key="h.monthDay">
+                <div :class="['head-item_time', h.current ? 'head-item_time--current' : '']">
+                  <span class="head-item_time-week">{{ h.week }}</span>
+                  <span class="head-item_time-day">({{ h.monthDay }})</span>
+                </div>
+                <div class="head-item_sailings">
+                  <div
+                    :class="[
+                      'head-item_sailings-item',
+                      filter.sailings ? 'head-item_sailings-item--only' : '',
+                    ]"
+                    v-for="c in h.count"
+                    :key="c"
+                  >
+                    {{ c }}
+                  </div>
+                </div>
+              </div>
+            </div>
+          </Affix>
+
+          <div class="container-body">
+            <div class="flex mb-2" v-for="(c, cIdx) in cnt" :key="c.id">
+              <div class="flex items-center" v-if="c.bed == bed[cIdx].bed">
+                <div
+                  class="body-list animate__animated animate__slideInLeft"
+                  v-for="(sa, idx) in c.sailings"
+                  :key="idx"
+                >
+                  <div
+                    v-for="person in sa"
+                    :key="person.key"
+                    :class="[
+                      'body-list_item',
+                      person.show ? '' : 'body-list_item--hidden',
+                      filter.sailings && person.show ? 'body-list_item--only' : '',
+                      setClass(person),
+                    ]"
+                    @click="handlePerson(person)"
+                    @dblclick="handleDbPerson(person)"
+                  >
+                    <!-- <div>testt</div> -->
+                    <div>{{ person.name }} </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="edit">
+      <div class="edit-not">
+        <div>未排床</div>
+        <div
+          v-for="item in bedNot"
+          :key="item.id"
+          :class="['edit-item', item.id == notBedId ? 'edit-item--not' : '']"
+          @click="handleNotBed(item)"
+        >
+          {{ item.name }}
+        </div>
+      </div>
+      <div class="edit-has">
+        <div>已排床</div>
+        <div
+          v-for="item in bedHas"
+          :key="item.id"
+          :class="['edit-item', item.id == hasBedId ? 'edit-item--has' : '']"
+          @click="handleHasBed(item)"
+        >
+          {{ item.name }}
+        </div>
+      </div>
+    </div>
+  </div>
 </template>
 
-<script setup lang="ts"></script>
+<script setup lang="ts">
+  import { ref } from 'vue';
+  import dayjs from 'dayjs';
+  import { Affix } from 'ant-design-vue';
+  import { defaultHead, defaultBed, defaultData } from './data';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { XTForm } from '/@/components/XTForm';
+  import _ from 'lodash-es';
+  console.log('🚀 ~ file: index.vue:51 ~ defaultHead:', defaultHead());
+  console.log('🚀 ~ file: index.vue:51 ~ defaultBed:', defaultBed());
+  console.log('🚀 ~ file: index.vue:51 ~ defaultData:', defaultData());
+  console.log('🚀 ~ file: index.vue:51 ~ dayjs:', dayjs().day());
+  console.log('🚀 ~ file: index.vue:51 ~ dayjs:', defaultHead());
+  console.log('🚀 ~ file: index.vue:51 ~ dayjs:', dayjs().day(1).format('MM-DD'));
+  const { createMessage } = useMessage();
+  const head = ref(defaultHead());
+  const bed = defaultBed();
+  const cnt = ref(defaultData());
+  const notBedId = ref('');
+  const hasBedId = ref('');
+  const filter = ref({}) as any;
+  const bedNot = [
+    {
+      id: 'n123123',
+      name: '测试123123',
+    },
+    {
+      id: 'n456456',
+      name: '测试456456',
+    },
+  ];
+  const bedHas = [
+    {
+      id: 'h123123',
+      name: '测试123123',
+    },
+    {
+      id: 'h456456',
+      name: '测试456456',
+    },
+  ];
+  // formdata
+  const formData = [
+    {
+      name: 'text',
+      // label: '全部',
+      componentType: 'Select',
+      placeholder: '请选择',
+      width: 120,
+      defaultValue: '0',
+      dicts: [
+        { label: '空床优先', value: '0' },
+        { label: '未称量', value: '1' },
+      ],
+    },
+    {
+      name: 'text233',
+      componentType: 'DatePicker',
+      placeholder: '请输入',
+      format: 'YYYY-MM-DD',
+      valueFormat: 'YYYY-MM-DD',
+    },
+    {
+      name: 'sailings',
+      componentType: 'Select',
+      placeholder: '请选择',
+      width: 120,
+      defaultValue: 0,
+      // label: '班次',
+      dicts: [
+        { label: '全部班次', value: 0 },
+        { label: '第一班', value: 1 },
+        { label: '第二班', value: 2 },
+        { label: '第三班', value: 3 },
+      ],
+    },
+  ];
+  function handleNotBed(data) {
+    notBedId.value = data.id;
+    hasBedId.value = null;
+    console.log('🚀 ~ file: index.vue:97 ~ handleNotBed ~ cnt.value :', cnt.value);
+    setCnt();
+  }
+  function handleHasBed(data) {
+    hasBedId.value = data.id;
+    notBedId.value = null;
+    console.log('🚀 ~ file: index.vue:97 ~ handleNotBed ~ cnt.value :', cnt.value);
+    setCnt();
+  }
+  function callFilter(data) {
+    console.log('🚀 ~ file: index.vue:173 ~ callFilter ~ data:', data);
+    if (data.sailings || data.sailings == 0) {
+      console.log('修改班次', data.sailings);
+      filter.value.sailings = data.sailings;
+      setCnt(1);
+      head.value = head.value.map(ele => {
+        const count = ['第一班', '第二班', '第三班'];
+        ele.count = data.sailings == 0 ? count : _.slice(count, data.sailings - 1, data.sailings);
+        return ele;
+      });
+      console.log(
+        '🚀 ~ file: index.vue:97 ~ handleNotBed ~ cnt.value :',
+        cnt.value[0]['sailings'][0],
+      );
+    }
+  }
+  // 设置数据
+  function setCnt(type?: number) {
+    if (type == 1) {
+      cnt.value = cnt.value.map(ele => {
+        ele.sailings = ele.sailings.map(cele => {
+          return cele.map((sele, idx) => {
+            if (filter.value.sailings == 0) {
+              sele.show = true;
+              return sele;
+            }
+            if (filter.value.sailings != 0 && filter.value.sailings - 1 == idx) {
+              sele.show = true;
+              return sele;
+            } else {
+              sele.show = false;
+              return sele;
+            }
+          });
+        });
+        return ele;
+      });
+    } else {
+      cnt.value = cnt.value.map(ele => {
+        ele.sailings = ele.sailings.map(cele => {
+          return cele.map(sele => {
+            sele.edit = true;
+            if (sele.old) {
+              sele.disabled = true;
+            } else {
+              sele.disabled = sele.name && !sele.empty ? true : false;
+            }
+            return sele;
+          });
+        });
+        return ele;
+      });
+    }
+  }
+  function changeAffix(affixed) {
+    console.log('🚀 ~ file: index.vue:70 ~ changeAffix ~ affixed:', affixed);
+  }
+  // 设置 class
+  function setClass(data) {
+    if (data.disabled) {
+      return 'body-list_item--disabled';
+    } else if (data.empty && data.selected && data.edit) {
+      return 'body-list_item--selected';
+    } else if (data.empty && data.actived && data.edit) {
+      return 'body-list_item--actived';
+    } else if (!data.disabled && data.empty && data.edit) {
+      return 'body-list_item--select';
+    } else if (data.old) {
+      return 'body-list_item--old';
+    } else if (data.empty && data.actived) {
+      return 'body-list_item--actived';
+    } else if (!data.name && data.empty) {
+      return 'body-list_item--empty';
+    }
+  }
+  // 双击事件
+  function handleDbPerson(data) {
+    console.log('🚀 ~ file: index.vue:136 ~ data:', data);
+    if (notBedId.value) {
+      cnt.value[data.x]['sailings'][data.y - 1][data.z]['selected'] = true;
+    }
+    if (hasBedId.value) {
+      cnt.value[data.x]['sailings'][data.y - 1][data.z]['actived'] = true;
+    }
+    console.log('cnt.value', cnt.value);
+  }
+  function handlePerson(data) {
+    console.log('🚀 ~ file: index.vue:336 ~ handlePerson ~ data:', data);
+    createMessage.info(
+      `横坐标: ${data.x}, 纵坐标: ${data.y}, 班次: ${data.z + 1}, ${
+        data.empty ? '空床' : data.name
+      }${notBedId.value ? ', 未排床: ' + notBedId.value : ''}`,
+    );
+  }
+</script>
+
+<style lang="less" scoped>
+  .wrap {
+    display: flex;
+  }
+
+  .detail {
+    display: flex;
+  }
+
+  .aside {
+    &-item {
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      align-items: center;
+      width: 82px;
+      height: 54px;
+      border-radius: 4px 0 0 4px;
+
+      &--tit {
+        text-align: center;
+        font-size: 14px;
+        font-weight: 400;
+        color: #818694;
+        margin-bottom: 0;
+      }
+
+      &_bed {
+        font-size: 14px;
+        font-weight: 600;
+        color: #000a18;
+      }
+
+      &_robot {
+        font-size: 12px;
+        font-weight: 400;
+        color: #818694;
+        line-height: 18px;
+      }
+    }
+  }
+
+  .container {
+    display: flex;
+    flex-direction: column;
+
+    &-head {
+      display: flex;
+      background-color: #f0f2f5;
+    }
+
+    &-body {
+      display: flex;
+      flex-direction: column;
+      overflow: auto;
+    }
+  }
+
+  .body {
+    &-list {
+      display: flex;
+
+      &_item {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        font-size: 14px;
+        padding: 0 10px;
+        width: 82px;
+        height: 54px;
+        text-align: center;
+        background: #fff;
+        margin-right: 1px;
+        cursor: pointer;
+        color: #000a18;
+        transition: all 0.3s ease-in-out;
+
+        &:last-child {
+          margin-right: 10px;
+          border-radius: 0 4px 4px 0;
+        }
+
+        &:first-child {
+          border-radius: 4px 0 0 4px;
+        }
+
+        &:hover {
+          transform: scale(1.1);
+          background: #fff;
+          box-shadow: 0 0 20px 0 rgb(0 37 74 / 12%);
+          border-radius: 4px;
+        }
+
+        &--empty {
+          background-color: #eaedf3;
+
+          &:hover {
+            background-color: #eaedf3;
+          }
+        }
+
+        &--only {
+          border-radius: 4px;
+          width: 246px;
+          margin-right: 10px;
+
+          &:hover {
+            background-color: #eaedf3;
+          }
+        }
+
+        &--old {
+          color: #c3cdd8;
+        }
+
+        &--selected {
+          background-color: rgb(239 255 251 / 100%);
+          border: 1px dashed rgb(68 215 182 / 100%);
+
+          &:hover {
+            background-color: rgb(239 255 251 / 100%);
+          }
+        }
+
+        &--actived {
+          background-color: rgb(233 246 255 / 100%);
+          border: 1px dashed rgb(0 109 255 / 100%);
+
+          &:hover {
+            background-color: rgb(233 246 255 / 100%);
+          }
+        }
+
+        &--disabled {
+          color: #c3cdd8;
+          background: #eaedf3;
+          cursor: not-allowed;
+
+          &:hover {
+            transform: scale(1);
+            color: #c3cdd8;
+            background: #eaedf3;
+          }
+        }
+
+        &--select {
+          background: #fff;
+        }
+
+        &--hidden {
+          display: none;
+        }
+      }
+    }
+  }
+
+  .head {
+    &-item {
+      margin-right: 10px;
+
+      &:last-child {
+        margin-right: 0;
+      }
+
+      &_time {
+        text-align: center;
+        color: #000a18;
+        margin-bottom: 6px;
+
+        &-week {
+          font-size: 14px;
+          font-weight: 600;
+          margin-right: 6px;
+        }
+
+        &-day {
+          font-size: 12px;
+          font-weight: 400;
+          color: #818694;
+        }
+
+        &--current {
+          color: #0075ff;
+
+          .head-item_time-day {
+            color: #0075ff;
+          }
+        }
+      }
+
+      &_sailings {
+        display: flex;
+
+        &-item {
+          width: 82px;
+          font-size: 12px;
+          font-weight: 400;
+          color: #818694;
+          text-align: center;
+          margin-right: 1px;
+          // background-color: #ccc;
+          &:last-child {
+            margin-right: 0;
+          }
+
+          &--only {
+            width: 246px;
+          }
+        }
+      }
+    }
+  }
+
+  .edit {
+    min-width: 250px;
+    min-height: 800px;
+    background-color: #fff;
+    border-radius: 4px;
+
+    &-item {
+      width: 210px;
+      height: 40px;
+      line-height: 40px;
+      background: #f4f6f9;
+      border-radius: 4px;
+      margin-bottom: 10px;
+      cursor: pointer;
+
+      &--not {
+        background: #effffb;
+        border: 1px dashed #44d7b6;
+      }
 
-<style lang="less" scoped></style>
+      &--has {
+        background: #e9f6ff;
+        border: 1px dashed #006dff;
+      }
+    }
+  }
+</style>