Browse Source

席位管理

CzRger 1 year ago
parent
commit
ce70f81ec6

+ 0 - 1
.gitignore

@@ -8,7 +8,6 @@ pnpm-debug.log*
 lerna-debug.log*
 
 node_modules
-seat*
 *.local
 
 # Editor directories and files

+ 5 - 2
src/components/cus/CusTable.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="cus-table" :class="{'cus-table-normal': !otherStyle, 'cus-table-full': full !== false}">
-    <div class="cus-table-main" ref="ref_tableMain">
+    <div class="cus-table-main" ref="ref_tableMain" :class="{'cus-tab-main-no-page': noPage !== false}">
       <el-table
           v-bind="$attrs"
           class="ct-table"
@@ -113,7 +113,7 @@ import {
         required: true
       },
       total: {
-        required: true
+        required: false
       },
       page: {},
       pageSize: {},
@@ -252,6 +252,9 @@ import {
     :deep(.ct-table) {
       height: 100%;
     }
+    &.cus-tab-main-no-page {
+      height: 100% !important;
+    }
   }
   :deep(.ct-page) {
     height: $cus-page-height;

+ 3 - 0
src/style/cus.scss

@@ -220,6 +220,9 @@
           .__cus-dialog-content {
             flex: 1;
             overflow-y: auto;
+            .el-form-item__label {
+              font-size: 14px;
+            }
           }
           .__cus-dialog-foot {
             width: 100%;

BIN
src/views/system/seat-manage/add.png


+ 525 - 0
src/views/system/seat-manage/index.vue

@@ -0,0 +1,525 @@
+<template>
+  <div class="__normal-page">
+    <div class="__normal-content">
+      <div class="seat">
+        <div class="seat-filter">
+          <CusForm>
+            <CusFormColumn
+                :span="8"
+                label="值班厅领导"
+                link="select"
+                static
+                v-model:param="queryForm.shipId"
+                labelKey="label"
+                valueKey="value"
+                :clearable="false"
+                :options="[
+                    {label: '类型一', value: '1'},
+                    {label: '类型二', value: '2'},
+                    {label: '类型三', value: '3'},
+                ]"/>
+            <CusFormColumn
+                :span="8"
+                label="总值班"
+                link="select"
+                static
+                v-model:param="queryForm.shipId"
+                labelKey="label"
+                valueKey="value"
+                :clearable="false"
+                :options="[
+                  {label: '类型一', value: '1'},
+                  {label: '类型二', value: '2'},
+                  {label: '类型三', value: '3'},
+              ]"/>
+            <CusFormColumn
+                :span="8"
+                label="带班领导"
+                link="select"
+                static
+                v-model:param="queryForm.shipId"
+                labelKey="label"
+                valueKey="value"
+                :clearable="false"
+                :options="[
+                  {label: '类型一', value: '1'},
+                  {label: '类型二', value: '2'},
+                  {label: '类型三', value: '3'},
+              ]"/>
+            <CusFormColumn
+                :span="24"
+                label="值班员"
+                link="select"
+                static
+                v-model:param="queryForm.shipId2"
+                labelKey="label"
+                valueKey="value"
+                multiple
+                :clearable="false"
+                :filterable="false"
+                :options="[
+                  {label: '类型一', value: '1'},
+                  {label: '类型二', value: '2'},
+                  {label: '类型三', value: '3'},
+              ]"/>
+          </CusForm>
+        </div>
+        <div class="seat-position">
+          <template v-for="item in seatList">
+            <div class="seat-item __hover" :class="{no: !item.deptName, active: currentSeat.index === item.index}" @click="currentSeat = item">
+              <div class="index">{{item.index}}</div>
+              <div class="name">{{item.deptName ? item.deptName : '无单位'}}</div>
+            </div>
+          </template>
+        </div>
+      </div>
+      <div class="dept" v-if="currentSeat?.index">
+        <template v-if="isEdit">
+          <div class="dept-edit-buttons">
+            <div class="reset __hover">清空</div>
+            <div class="save __hover">保存</div>
+            <div class="cancel __hover" @click="onEditCancel">取消</div>
+          </div>
+          <div class="dept-edit-form">
+            <CusForm labelWidth="86px" ref="ref_form">
+              <CusFormColumn
+                  :span="24"
+                  :disabled="true"
+                  label="席位编号:"
+                  v-model:param="editDutyInfo.deptForm.index"/>
+              <CusFormColumn
+                  :span="24"
+                  required
+                  label="单位名称:"
+                  link="dept"
+                  v-model:param="editDutyInfo.deptForm.p2"/>
+              <CusFormColumn
+                  :span="24"
+                  label="单位简称:"
+                  v-model:param="editDutyInfo.deptForm.p2"/>
+              <CusFormColumn
+                  :span="24"
+                  label="简介:"
+                  type="textarea"
+                  :rows="4"
+                  show-word-limit
+                  :maxlength="100"
+                  v-model:param="editDutyInfo.deptForm.p3"/>
+            </CusForm>
+          </div>
+          <div class="dept-duty-total">
+            值班人员列表({{editDutyInfo.tableData.length}})
+            <div class="people-add __hover" @click="addPeople">
+              <img src="./add.png"/>新增
+            </div>
+          </div>
+          <div class="dept-duty-table">
+            <CusTable
+                :tableData="editDutyInfo.tableData"
+                :tableHead="editDutyInfo.tableHead"
+                noPage
+            >
+            </CusTable>
+          </div>
+        </template>
+        <template v-else>
+          <div class="dept-title">
+            <div class="dept-title-index">{{currentSeat.index}}</div>
+            <div class="dept-title-name">{{currentSeat.deptName ? currentSeat.deptName : '无单位'}}</div>
+            <div class="dept-title-button __hover" @click="onEdit">编辑</div>
+          </div>
+          <div class="dept-info">
+            <div class="item">
+              <div class="label">单位简称:</div>
+              <div class="value">{{currentSeat.deptName}}</div>
+            </div>
+            <div class="item">
+              <div class="label">单位简介:</div>
+              <div class="value">{{currentSeat.remark}}</div>
+            </div>
+          </div>
+          <div class="dept-duty-total">
+            值班人员列表({{dutyInfo.total}})
+          </div>
+          <div class="dept-duty-table">
+            <CusTable
+                v-loading="dutyInfo.loading"
+                ref="ref_cusTable"
+                :tableData="dutyInfo.tableData"
+                :tableHead="dutyInfo.tableHead"
+                :total="dutyInfo.total"
+                :page="dutyInfo.pageNum"
+                :pageSize="dutyInfo.pageSize"
+                @handlePage="handlePage"
+            >
+            </CusTable>
+          </div>
+        </template>
+      </div>
+    </div>
+    <PeopleCom v-model:show="showPeople" :transfer="transfer"/>
+  </div>
+</template>
+
+<script lang="ts">
+import {
+  defineComponent,
+  computed,
+  onMounted,
+  ref,
+  reactive,
+  watch,
+  getCurrentInstance,
+  ComponentInternalInstance,
+  toRefs,
+  nextTick
+} from 'vue'
+import {useStore} from 'vuex'
+import {useRouter, useRoute} from 'vue-router'
+import PeopleCom from './people.vue'
+
+export default defineComponent({
+  name: '',
+  components: {
+    PeopleCom
+  },
+  setup(props, {emit}) {
+    const store = useStore();
+    const router = useRouter();
+    const route = useRoute();
+    const that = (getCurrentInstance() as ComponentInternalInstance).appContext.config.globalProperties
+    const state = reactive({
+      queryForm: {},
+      seatList: [],
+      currentSeat: {},
+      dutyInfo: {
+        tableData: [],
+        pageNum: 1,
+        pageSize: 10,
+        total: 10,
+        loading: false,
+        tableHead: [
+          {value: "p1", label: "姓名", show: true},
+          {value: "p1", label: "联系电话", show: true},
+          {value: "p1", label: "更新时间", show: true},
+        ],
+      },
+      editDutyInfo: {
+        tableData: [],
+        tableHead: [
+          {value: "p1", label: "姓名", show: true},
+          {value: "p1", label: "联系电话", show: true},
+          {value: "p1", label: "更新时间", show: true},
+          {value: "do", label: "操作", show: true},
+        ],
+        deptForm: {}
+      },
+      isEdit: false,
+      showPeople: false,
+      transfer: {}
+    })
+    const handlePage = ({page, pageSize}: any) => {
+      state.dutyInfo.pageNum = page
+      state.dutyInfo.pageSize = pageSize
+      handleSearch(page, pageSize)
+    }
+    //  查询方法
+    const handleSearch = (page = 1, pageSize = 10) => {
+      //  添加分页参数
+      const queryParams: any = {
+        pageNum: page,
+        pageSize: pageSize,
+      }
+      state.dutyInfo.loading = true
+      // mock
+      const arr: any = []
+      for (let i = 0; i < 77; i++) {
+        arr.push({
+          p1: '阿三顶顶顶顶顶顶顶顶顶顶顶顶顶' + i,
+          fileList: [
+            { "url": "http://8.140.240.182:18085/profile/upload/2023/10/23/6b7bf3b4-592a-4e2f-ba92-11923671ce3b.doc", "name": "迁移案例.doc"},
+          ],
+        })
+      }
+      state.dutyInfo.tableData = arr
+      state.dutyInfo.total = arr.length
+      state.dutyInfo.loading = false
+    }
+    onMounted(() => {
+      for (let i = 0; i< 48; i++) {
+        const obj = {index: i + 1}
+        if (i === 0) {
+          obj.deptId = '111'
+          obj.deptName = '广海局'
+          obj.remark = '中华人民共和国海南海事局,是交通运输部派驻海南的海事行政管理机关,隶属中华人民共和国海事局中华人民共和国海南海事局,是交通运输部派驻海南的海事行政管理机关,隶属中华人民共和国海事局'
+        }
+        if (i === 1) {
+          obj.deptId = '222'
+          obj.deptName = '海事局'
+        }
+        if (i === 26) {
+          obj.deptId = '333'
+          obj.deptName = '太极'
+        }
+        state.seatList.push(obj)
+      }
+    })
+    const onEdit = () => {
+      state.editDutyInfo.deptForm = JSON.parse(JSON.stringify(state.currentSeat))
+      state.editDutyInfo.tableData = JSON.parse(JSON.stringify(state.dutyInfo.tableData))
+      state.isEdit = true
+    }
+    const onEditCancel = () => {
+      state.editDutyInfo.deptForm = {}
+      state.editDutyInfo.tableData = []
+      state.isEdit = false
+    }
+    const addPeople = () => {
+      state.transfer = JSON.parse(JSON.stringify(state.currentSeat))
+      state.showPeople = true
+    }
+    onMounted(() => {
+      handleSearch()
+    })
+    return {
+      ...toRefs(state),
+      handlePage,
+      onEdit,
+      onEditCancel,
+      addPeople
+    }
+  },
+})
+</script>
+
+<style scoped lang="scss">
+.__normal-content {
+  display: flex;
+  justify-content: space-between;
+  padding-top: 40px;
+  padding-right: 30px;
+  .seat {
+    width: 925px;
+    height: 100%;
+    margin-right: 36px;
+    display: flex;
+    flex-direction: column;
+    padding-bottom: 40px;
+    box-sizing: border-box;
+    .seat-position {
+      flex: 1;
+      margin-top: 22px;
+      overflow: hidden;
+      display: grid;
+      grid-template-columns: repeat(8, 1fr);
+      grid-template-rows: repeat(6, 1fr);
+      column-gap: 15px;
+      row-gap: 24px;
+      .seat-item {
+        background-color: rgba(0,108,255,0.25);
+        box-shadow: inset 0px 0px 10px 0px rgba(0,210,255,0.25);
+        border-radius: 8px;
+        font-size: 16px;
+        font-family: PingFang SC-Medium, PingFang SC;
+        font-weight: 500;
+        color: #FFFFFF;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        position: relative;
+        .index {
+          position: absolute;
+          top: 4px;
+          left: 6px;
+          font-size: 14px;
+          font-family: PingFang SC-Regular, PingFang SC;
+          font-weight: 400;
+          color: rgba(255,255,255,0.6);
+        }
+        &.no {
+          opacity: 0.4;
+        }
+        &.active {
+          background-color: rgba(0,108,255,0.4);
+          border: 4px solid;
+          border-radius: 0;
+          border-image: linear-gradient(90deg, rgba(79, 172, 254, 1), rgba(0, 242, 254, 1)) 2 2;
+          clip-path: inset(0px round 6px);
+          opacity: 1;
+          .index {
+            top: 0px;
+            left: 2px;
+          }
+        }
+      }
+    }
+  }
+  .dept {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    .dept-title {
+      height: 48px;
+      background: rgba(0,163,255,0.1) linear-gradient(45deg, #09456f 0%, #0b2e4b 100%);
+      border-radius: 0px 0px 0px 0px;
+      border-image: linear-gradient(90deg, rgba(0, 163, 255, 1), rgba(0, 255, 255, 0)) 1 1;
+      display: flex;
+      align-items: center;
+      position: relative;
+      line-height: 1;
+      &:before {
+        position: absolute;
+        content: '';
+        width: 80%;
+        height: 1px;
+        background: linear-gradient(90deg, rgba(0, 163, 255, 1), rgba(0, 255, 255, 0));
+        left: 0;
+        top: 0;
+      }
+      &:after {
+        position: absolute;
+        content: '';
+        width: 80%;
+        height: 1px;
+        background: linear-gradient(90deg, rgba(0, 163, 255, 1), rgba(0, 255, 255, 0));
+        left: 0;
+        bottom: 0;
+      }
+      .dept-title-index {
+        margin-left: 10px;
+        font-size: 24px;
+        font-family: PangMenZhengDao;
+        font-weight: 400;
+        color: #00FFFF;
+        text-shadow: 0px 1px 1px rgba(0,0,0,0.2);
+        background: linear-gradient(88deg, #FFFFFF 0%, #1FFFFF 100%);
+        -webkit-background-clip: text;
+        -webkit-text-fill-color: transparent;
+      }
+      .dept-title-name {
+        margin-left: 10px;
+        font-size: 24px;
+        font-family: Microsoft YaHei-Bold, Microsoft YaHei;
+        font-weight: bold;
+        color: #00FFFF;
+        text-shadow: 0px 1px 1px rgba(0,0,0,0.2);
+        background: linear-gradient(88deg, #FFFFFF 0%, #1FFFFF 100%);
+        -webkit-background-clip: text;
+        -webkit-text-fill-color: transparent;
+      }
+      .dept-title-button {
+        margin-left: auto;
+        margin-right: 10px;
+        width: 52px;
+        height: 30px;
+        border-radius: 4px;
+        border: 1px solid rgba(0, 133, 247, 0.5);
+        background-color: rgba(0, 133, 247, 0.2);
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        font-size: 16px;
+        font-family: PingFang SC-Regular, PingFang SC;
+        font-weight: 400;
+        color: #FFFFFF;
+      }
+    }
+    .dept-info {
+      display: flex;
+      flex-direction: column;
+      .item {
+        display: flex;
+        margin-top: 16px;
+        .label {
+          width: 80px;
+          font-size: 16px;
+          font-family: PingFang SC-Medium, PingFang SC;
+          font-weight: 500;
+          color: #02FFF1;
+        }
+        .value {
+          flex: 1;
+          font-size: 16px;
+          font-family: PingFang SC-Regular, PingFang SC;
+          font-weight: 400;
+          color: rgba(255,255,255,0.7);
+        }
+      }
+    }
+    .dept-edit-buttons {
+      display: flex;
+      align-items: center;
+      justify-content: flex-end;
+      >div {
+        width: 52px;
+        height: 30px;
+        border-radius: 4px;
+        border: 1px solid rgba(0, 133, 247, 0.5);
+        font-size: 16px;
+        font-family: PingFang SC-Regular, PingFang SC;
+        font-weight: 400;
+        color: #FFFFFF;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        box-sizing: border-box;
+      }
+      .reset, .cancel {
+        background-color: rgba(0, 133, 247, 0.2);
+      }
+      .save {
+        background-color: rgba(0, 133, 247, 1);
+        margin: 0 10px;
+      }
+    }
+    :deep(.dept-edit-form) {
+      margin-top: 24px;
+      .el-form-item__label {
+        font-size: 14px;
+      }
+    }
+    .dept-duty-total {
+      margin-top: 16px;
+      font-size: 16px;
+      font-family: PingFang SC-Medium, PingFang SC;
+      font-weight: 500;
+      color: #02FFF1;
+      display: flex;
+      align-items: center;
+      .people-add {
+        margin-left: auto;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        >img {
+          margin-right: 4px;
+        }
+      }
+    }
+    .dept-duty-table {
+      margin-top: 10px;
+      flex: 1;
+      :deep(.cus-table) {
+        .el-table__header-wrapper, .el-table__fixed-right, .el-table__fixed {
+          .el-table__header {
+            tr {
+              >th {
+                height: 40px;
+              }
+            }
+          }
+        }
+        .el-table__body-wrapper, .el-table__fixed-body-wrapper {
+          .el-table__body {
+            .el-table__row {
+              >td {
+                height: 40px;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+</style>

+ 91 - 0
src/views/system/seat-manage/people.vue

@@ -0,0 +1,91 @@
+<template>
+  <CusDialog
+      title="新增人员"
+      :show="show"
+      @close="$emit('update:show', false)"
+      @submit="onSubmit"
+      width="400px"
+      height="226px"
+      footAlign="right"
+  >
+    <div class="__normal-form">
+      <CusForm labelWidth="100px" ref="ref_form">
+        <CusFormColumn
+            :span="24"
+            required
+            label="单位:"
+            link="dept"
+            :disabled="true"
+            v-model:param="cusDetail.p1"/>
+        <CusFormColumn
+            :span="24"
+            required
+            label="新增值班人员:"
+            v-model:param="cusDetail.p2"
+            link="select"
+            static
+            labelKey="label"
+            valueKey="value"
+            :options="[
+                {label: '类型一', value: '1'},
+                {label: '类型二', value: '2'},
+                {label: '类型三', value: '3'},
+            ]"/>
+      </CusForm>
+    </div>
+  </CusDialog>
+</template>
+
+<script lang="ts">
+import {
+  defineComponent,
+  computed,
+  onMounted,
+  ref,
+  reactive,
+  watch,
+  getCurrentInstance,
+  ComponentInternalInstance,
+  toRefs,
+  nextTick
+} from 'vue'
+import {useStore} from 'vuex'
+import {useRouter, useRoute} from 'vue-router'
+
+export default defineComponent({
+  name: '',
+  components: {},
+  props: {
+    show: {},
+    transfer: <any>{}
+  },
+  setup(props, {emit}) {
+    const store = useStore();
+    const router = useRouter();
+    const route = useRoute();
+    const that = (getCurrentInstance() as ComponentInternalInstance).appContext.config.globalProperties
+    const state = reactive({
+      cusDetail: {}
+    })
+    watch(() => props.show, (n) => {
+      if (n) {
+        state.cusDetail = {}
+        nextTick(() => {
+          ref_form.value.reset()
+        })
+      }
+    })
+    const ref_form = ref()
+    const onSubmit = () => {
+    }
+    return {
+      ...toRefs(state),
+      onSubmit,
+      ref_form
+    }
+  },
+})
+</script>
+
+<style scoped lang="scss">
+</style>