vue3项目 基于vuedraggable插件实现拖拽上下移动

// 父页面
<template>
  <div class="main_body">
    <blockTitle title="事件详情" />
    <a-form
      ref="formRef"
      :model="formValue"
      style="width: 100%"
      class="form_box"
      :layout="'inline'"
      :labelAlign="'right'"
      autocomplete="off"
    >
      <draggable :list="formValue.orderEventVOs" :force-fallbacl="true" animation="500" item-key="index">
        <template #item="{ element: item, index }">
          <FromItem
            :formItemData="item"
            :index="index"
            :length="formValue.orderEventVOs.length"
            :showDelBtn="route.query?.type === 'add' ? true : false"
            @handlerIcon="handlerIcon"
            @handlerMoveIcon="handlerMoveIcon"
            :userList="userList"
          />
        </template>
      </draggable>
    </a-form>
    <div v-if="route.query?.type === 'add'">
      <a-button type="primary" @click="handlerIcon('add', null)">添加事件</a-button>
    </div>
    <div class="save-btn">
      <a-button type="primary" @click="closePage">关闭页面</a-button>
      <a-button type="primary" @click="saveFrom">保存信息</a-button>
    </div>
  </div>
</template>

<script setup>
import blockTitle from '@/components/blockTitle.vue'
import FromItem from './components/FromItem.vue'
import { getItemEventByOrderId, getItemEventByEventId, addEvent, editEvent } from '@/api/eventManage'
import draggable from 'vuedraggable'
import { getUserList } from '@/api/common'
const route = useRoute()
const router = useRouter()
const formRef = ref()
const obj = {
  id: '',
  eventName: '',
  orderSort: '',
  executorDept: undefined,
  executor: undefined,
  planStartTime: null,
  planStopTime: null,
  totalWorkHours: '',
  remark: ''
}
const userList = ref([])
if (route.query?.type === 'add') {
  obj.templateId = route.query?.id
} else {
  obj.productionOrderId = route.query?.id
}
const formValue = ref({
  orderEventVOs: []
})
const handlerIcon = (type, index) => {
  if (type === 'add') {
    formValue.value.orderEventVOs.push({ ...obj })
  } else {
    formValue.value.orderEventVOs.splice(index, 1)
  }
}
const handlerMove = (arr, indexOne, indexTwo) => {
  arr[indexOne] = arr.splice(indexTwo, 1, arr[indexOne])[0]
  return arr
}
const handlerMoveIcon = (type, index) => {
  if (type === 'top') {
    if (index === 0) return
    handlerMove(formValue.value.orderEventVOs, index - 1, index)
  } else {
    if (index === formValue.value.orderEventVOs.length - 1) return
    handlerMove(formValue.value.orderEventVOs, index, index + 1)
  }
}
const saveFrom = () => {
  formValue.value.orderEventVOs.forEach((item, index) => {
    item.orderSort = index
  })
  formRef.value.validate().then(() => {
    // 发送请求
    if (route.query?.type === 'add') {
      addEvent(formValue.value.orderEventVOs).then(() => {
        window.$message.success('操作成功')
        getEventByEventId(route.query?.id)
      })
    } else {
      editEvent(formValue.value.orderEventVOs).then(() => {
        window.$message.success('操作成功')
        getEventByOrderId(route.query?.id)
      })
    }
  })
}
const closePage = () => {
  router.go(-1)
}
const getEventByEventId = (val) => {
  getItemEventByEventId(val).then((res) => {
    if (res && res.length) {
      formValue.value.orderEventVOs = res
    } else {
      formValue.value.orderEventVOs.push({ ...obj })
    }
  })
}
const getEventByOrderId = (val) => {
  getItemEventByOrderId(val).then((res) => {
    if (res && res.length) {
      formValue.value.orderEventVOs = res
    } else {
      formValue.value.orderEventVOs.push({ ...obj })
    }
  })
}
onMounted(() => {
  getUserList().then((res) => {
    userList.value = res?.rows || []
  })
})
watch(
  () => route.query?.id,
  (val) => {
    // 发送请求 如果为空  默认添加一组
    if (val) {
      if (route.query?.type === 'add') {
        getEventByEventId(val)
      } else {
        getEventByOrderId(val)
      }
    }
  },
  {
    immediate: true
  }
)
</script>

<style lang="scss" scoped>
.form_box {
  :deep(.ant-form-item-label) {
    min-width: 120px;
    max-width: 120px;
  }
}
.save-btn {
  margin-top: 50px;
  display: flex;
  justify-content: center;
}
</style>

// 子页面
<template>
  <div class="box">
    <a-row wrap style="width: 90%; margin: 0 auto">
      <a-col :span="11" v-if="formItemData.id">
        <a-form-item label="事件id" :name="['orderEventVOs', index, 'id']" :rules="getRules('id')">
          <span>{{ formItemData.id }}</span>
        </a-form-item>
      </a-col>
      <a-col :span="11">
        <a-form-item label="事件名称" :name="['orderEventVOs', index, 'eventName']" :rules="getRules('eventName')">
          <a-input
            placeholder="请输入事件名称"
            v-model:value="formItemData.eventName"
            :maxlength="20"
            v-if="!formItemData.id"
          />
          <span v-else>{{ formItemData.eventName }}</span>
        </a-form-item>
      </a-col>
      <!-- <a-col :span="11">
        <a-form-item label="事件顺序" :name="['orderEventVOs', index, 'orderSort']" :rules="getRules('orderSort')">
          <a-input-number
            placeholder="请输入事件顺序"
            v-model:value="formItemData.orderSort"
            :min="0"
            disabled
            style="width: 100%"
          />
        </a-form-item>
      </a-col> -->
      <a-col :span="11">
        <a-form-item
          label="执行部门"
          :name="['orderEventVOs', index, 'executorDept']"
          :rules="getRules('executorDept')"
        >
          <a-select placeholder="请选择执行部门" v-model:value="formItemData.executorDept">
            <a-select-option v-for="item in ['生产平台', '资源服务平台']" :key="item">
              {{ item }}
            </a-select-option>
          </a-select>
        </a-form-item>
      </a-col>
      <a-col :span="11">
        <a-form-item label="执行人" :name="['orderEventVOs', index, 'executor']" :rules="getRules('executor')">
          <a-select placeholder="请选择执行人" v-model:value="formItemData.executor">
            <a-select-option v-for="item in userList" :key="item.id">
              {{ item.personName }}
            </a-select-option>
          </a-select>
        </a-form-item>
      </a-col>
      <a-col :span="11">
        <a-form-item label="期望开始时间" :name="['orderEventVOs', index, 'planStartTime']">
          <a-date-picker
            v-model:value="formItemData.planStartTime"
            style="width: 100%"
            valueFormat="YYYY-MM-DD"
            @change="changeStartTime"
          />
        </a-form-item>
      </a-col>
      <a-col :span="11">
        <a-form-item
          label="期望完成时间"
          :name="['orderEventVOs', index, 'planStopTime']"
          :rules="getRules('planStopTime')"
        >
          <a-date-picker
            v-model:value="formItemData.planStopTime"
            style="width: 100%"
            valueFormat="YYYY-MM-DD"
            :disabled-date="disabledDate"
          />
        </a-form-item>
      </a-col>
      <a-col span="11">
        <a-form-item
          label="预计工时"
          :name="['orderEventVOs', index, 'totalWorkHours']"
          :rules="getRules('totalWorkHours')"
        >
          <a-input-number
            placeholder="请输入预计工时"
            v-model:value="formItemData.totalWorkHours"
            :min="0"
            style="width: 100%"
          />
        </a-form-item>
      </a-col>
      <a-col :span="22">
        <a-form-item label="事件备注" :name="['orderEventVOs', index, 'remark']">
          <a-textarea
            placeholder="请输入事件备注"
            v-model:value="formItemData.remark"
            :auto-size="{ minRows: 3, maxRows: 3 }"
          />
        </a-form-item>
      </a-col>
    </a-row>
    <div class="btn-box">
      <a-tooltip placement="right">
        <template #title>上移</template>
        <a-button type="primary" shape="circle" @click="move('top', props.index)" v-if="length > 1 && showDelBtn">
          <template #icon><ArrowUpOutlined /></template>
        </a-button>
      </a-tooltip>
      <a-tooltip placement="right">
        <template #title>下移</template>
        <a-button type="primary" shape="circle" @click="move('down', props.index)" v-if="length > 1 && showDelBtn">
          <template #icon><ArrowDownOutlined /></template>
        </a-button>
      </a-tooltip>
      <a-tooltip placement="right">
        <template #title>删除</template>
        <a-button type="primary" shape="circle" @click="add('del', props.index)" v-if="length > 1 && showDelBtn">
          <template #icon><DeleteOutlined /></template>
        </a-button>
      </a-tooltip>
    </div>
  </div>
</template>
<script setup>
import dayjs from 'dayjs'
import { getRules } from '../index'
import { DeleteOutlined, ArrowUpOutlined, ArrowDownOutlined } from '@ant-design/icons-vue'
const emit = defineEmits(['handlerIcon', 'handlerMoveIcon'])
const props = defineProps({
  formItemData: {
    type: Object,
    default: () => ({})
  },
  index: {
    type: Number,
    default: 0
  },
  length: {
    type: Number,
    default: 0
  },
  showDelBtn: {
    type: Boolean,
    default: false
  },
  userList: {
    type: Array,
    default: () => []
  }
})
const { index, formItemData, length, showDelBtn } = toRefs(props)
const changeStartTime = () => {
  formItemData.value.planStopTime = null
}
const disabledDate = (current) => {
  if (formItemData.value.planStartTime) {
    return current && current < dayjs(formItemData.value.planStartTime)
  }
}
const add = (type) => {
  emit('handlerIcon', type, props.index)
}
const move = (type) => {
  emit('handlerMoveIcon', type, props.index)
}
</script>
<style lang="scss" scoped>
.box {
  position: relative;
  .btn-box {
    position: absolute;
    right: 10%;
    top: 0;
    height: 140px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    .ant-btn {
      margin: 0;
      padding: 0;
    }
  }
}
</style>

posted @ 2023-09-14 15:25  Life_countdown  阅读(1542)  评论(0)    收藏  举报