<template>
  <a-drawer
    :visible="visible"
    :width="isMobile ? screenWidth : screenWidth * 0.85"
    placement="right"
    title="工单详情"
    @close="onClose"
  >
    <!--  移交工单对话框  -->
    <a-modal
      :visible="transVisible"
      :zIndex="1001"
      title="移交工单"
      @cancel="handleTransferCancel"
      @ok="handleTransferOk"
    >
      <a-form-model ref="transmitFormRef" :label-col="{ span: 4 }" :model="transmitForm" :rules="{ transferTo: { required: true, message: '移交人必填' }, note: { required: true, message: '备注不能为空' } }" :wrapper-col="{ span: 16 }">
        <a-form-model-item label="移交给" prop="transferTo">
          <a-select
            v-model="transmitForm.transferTo"
            :filter-option="false"
            :not-found-content="null"
            :options="nameOptionsFiltered"
            :show-arrow="false"
            placeholder="请输入移交人"
            show-search
            style="width: 150px"
            @search="employeeNameSearch" />
        </a-form-model-item>
        <a-form-model-item label="留言" prop="note">
          <a-textarea v-model="transmitForm.note" :rows="3" placeholder="请输入移交留言" />
        </a-form-model-item>
        <a-form-model-item label="上传图片">
          <div class="clearfix">
            <a-upload
              :before-upload="beforeUpload"
              :file-list="fileList"
              :remove="remove"
              action="/api/af-oa/file/upload"
              list-type="picture-card"
              name="avatar"
              @change="handleChange"
              @preview="handlePreview"
            >
              <div v-if="fileList.length < 5">
                <a-icon type="plus" />
                <div class="ant-upload-text">点击上传</div>
              </div>
            </a-upload>
          </div>
        </a-form-model-item>
      </a-form-model>
    </a-modal>
    <!-- 图片预览弹框 -->
    <a-modal
      :dialog-style="{ top: '30px' }"
      :footer="null"
      :visible="previewVisible"
      :z-index="1001"
      width="90%"
      @cancel="handleCancel"
    >
      <img :src="previewImage" alt="上传图片" style="width: 100%"/>
    </a-modal>
    <!--  关闭工单确认框  -->
    <a-modal
      :visible="closeVisible"
      :zIndex="1002"
      title="关闭工单"
      @cancel="handleCloseCancel"
      @ok="handleCloseOk"
    >
      <p>是否确认手动关闭工单？</p>
      <p style="color: red">（该操作不可撤销，请谨慎操作！）</p>
    </a-modal>
    <!--  信息主体  -->
    <a-spin :spinning="loadTicketDetails">
      <a-page-header :title="'订单：' + this.details.serial_number">
        <div class="row">
          <div class="content">
            <a-descriptions :column="isMobile ? 1 : 2" size="small">
              <a-descriptions-item label="优先级">
                <a-alert
                  :message="showPriority()"
                  :show-icon="true"
                  :type="showPriorityColorControl()"/>
              </a-descriptions-item>
              <a-descriptions-item label="发起人">{{ details.uploader }}</a-descriptions-item>
              <a-descriptions-item label="问题类型">{{ details.category }}</a-descriptions-item>
              <a-descriptions-item label="发起人联系方式">{{ details.uploader_phone }}</a-descriptions-item>
            </a-descriptions>
          </div>
        </div>
        <!-- 按钮 -->
        <template #extra>
          <a-button-group style="margin-right: 4px;">
            <a-popover placement="bottomLeft" title="开始处理">
              <template slot="content">
                <p>开始处理当前工单</p>
              </template>
              <a-button :disabled="handlerBtnDisable()" type="primary" @click="confirmTicketBtn()">开始处理</a-button>
            </a-popover>
            <a-popover placement="bottomLeft" title="移交他人">
              <template slot="content">
                <p>将工单转交他人处理</p>
              </template>
              <a-button :disabled="transferBtnDisable()" type="primary" @click="transferBtn()">移交他人</a-button>
            </a-popover>
            <a-popover placement="bottomLeft" title="关闭工单">
              <template slot="content">
                <p>强制关闭当前工单</p>
                <p style="color: red">此操作不可撤销，请谨慎使用</p>
              </template>
              <a-button :disabled="closeBtnDisable()" type="danger" @click="closeBtn()">关闭工单</a-button>
            </a-popover>
          </a-button-group>
          <a-button-group style="margin-right: 4px;">
            <a-button :loading="showSpin" type="dashed" @click="initView">刷新({{ btnCountdownText }})</a-button>
          </a-button-group>
        </template>
        <!-- 进度条 -->
        <a-card :bordered="false" style="margin-top: 40px">
          <a-steps :current="step" :direction="'horizontal'">
            <a-step>
              <template #title><span>待处理</span></template>
              <template #description>
                <div>工单已提交，等待处理<div>{{ format(details.created_time,'yyyy-MM-dd hh:mm:ss') }}</div></div>
              </template>
            </a-step>
            <a-step>
              <template #title><span>处理中</span></template>
              <template #description>
                <div v-if="step >= 1"><strong>{{ details.name }}</strong> 处理中...<div>{{ format(details.confirm_time,'yyyy-MM-dd hh:mm:ss') }}</div></div>
              </template>
            </a-step>
            <a-step>
              <template #title><span>{{ getStatus() }}</span></template>
              <template #description>
                <div v-if="step >= 2">{{ format(details.finished_time,'yyyy-MM-dd hh:mm:ss') }}</div>
              </template>
            </a-step>
          </a-steps>
        </a-card>
        <!--    切换栏    -->
        <a-tabs style="margin-top: 50px;">
          <!--    问题描述    -->
          <a-tab-pane :key="1" tab="问题详细描述">
            <a-card :loading="descriptionLoading" style="width: 100%">
              <div v-for="(item,index) in addOnDescription" v-if="addOnDescription.length > 0" :key="index">
                <span style="font-size: 2em;margin-right: 20px;margin-top: 20px">{{ details.uploader }}</span>
                <span>{{ format(item.time,'yyyy年MM月dd日 hh:mm:ss') }}</span>
                <p style="text-indent: 2em;font-size: 20px;margin: 20px">{{ item.description }}</p>
                <img
                  v-for="(pic,m) in item.images"
                  :key="'is' + m"
                  :class="changePhotoClassForSmall(pic.id)"
                  :src="'data:image/png;base64,' + pic.url"
                  alt=""
                  @click="changePhotoClass(pic.id)">
                <div style="height: 1px;background: -webkit-linear-gradient(left, #fff -4%,#6b6c72 50%,#fff 100%);"></div>
              </div>
              <span style="font-size: 2em;margin-right: 20px">{{ details.uploader }}</span>
              <span>{{ format(details.created_time,'yyyy年MM月dd日 hh:mm:ss') }}</span>
              <p style="text-indent: 2em;font-size: 20px;margin: 10px">{{ details.description }}</p>
              <img
                v-for="(originalPic,n) in originalImages"
                :key="'os' + n"
                :class="changePhotoClassForSmall(originalPic.id)"
                :src="'data:image/png;base64,' + originalPic.url"
                style="margin-bottom: 10px"
                @click="changePhotoClass(originalPic.id)"
                alt="">
            </a-card>
          </a-tab-pane>
          <!--     工单流转历史     -->
          <a-tab-pane :key="2" tab="工单流转历史">
            <ticket-details-flow
              v-if="details.id"
              :id="details.id"
              :disableCloseBtn="disableCloseBtn"
              :ticketId="ticketId"
              @imageClick="flowImageClick"/>
          </a-tab-pane>
        </a-tabs>
      </a-page-header>
    </a-spin>
    <audio ref="audio" controls="controls" hidden src="@vue2-client/assets/sound/newNote.mp3"></audio>
    <!--  放大后图片  -->
    <div v-if="selectedImageShow" class="imgBackground" @click="changePhotoClass(selectedImage.id)">
      <img
        :src="'data:image/png;base64,' + selectedImage.url"
        class="img_xl"
        alt="">
    </div>
  </a-drawer>
</template>

<script>
  import JsonViewer from 'vue-json-viewer'
  import { formatDate } from '@vue2-client/utils/util'
  import { TicketDetailsViewApi, post } from '@vue2-client/services/api'
  import XTable from '@vue2-client/base-client/components/common/XTable/XTable'
  import { mapState } from 'vuex'
  import TicketDetailsFlow from './part/TicketDetailsFlow'
  import moment from 'moment'
  import XFormItem from '@vue2-client/base-client/components/common/XForm/XFormItem'

  function getBase64 (file) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader()
      reader.readAsDataURL(file)
      reader.onload = () => resolve(reader.result)
      reader.onerror = error => reject(error)
    })
  }

  export default {
    name: 'TicketDetailsView',
    components: {
      XFormItem,
      TicketDetailsFlow,
      JsonViewer,
      XTable
    },
    data () {
      return {
        moment,
        // 页面宽度
        screenWidth: document.documentElement.clientWidth,
        // 控制成功页面显示
        successVisible: false,
        // 控制预览显示
        previewVisible: false,
        // 图片真实地址
        previewImage: '',
        // 图片列表
        fileList: [],
        // 工单详情
        details: {
          // 当前负责人ID
          id: undefined,
          name: '',
          uploader: '',
          status: undefined,
          priority: undefined,
          description: '',
          created_time: '',
          confirm_time: '',
          finished_time: '',
          category: '',
          serial_number: '',
          uploader_phone: ''
        },
        images: [],
        selectedImage: null,
        selectedImageShow: false,
        // 当前步骤
        step: 0,
        // 移交工单窗口可见性
        transVisible: false,
        // 移交表单
        transmitForm: {
          transferTo: undefined,
          note: ''
        },
        // 控制关闭订单按钮可用性
        disableCloseBtn: false,
        // 控制关闭工单确认框显示
        closeVisible: false,
        // 控制加载过程
        loadTicketDetails: false,
        // 附加描述
        addOnDescription: [],
        // 上传工单时自带照片
        originalImages: [],
        // 定时刷新定时器
        timer: undefined,
        // 所有员工姓名
        nameOptions: [],
        // 结果筛选的员工信息
        nameOptionsFiltered: [],
        // 工单流转抽屉可见性
        workFlowVisible: false,
        // 控制小加载指示物显示
        showSpin: true,
        // 原始描述长度
        addOnDescriptionOriginal: undefined,
        // 描述加载控制
        descriptionLoading: false,
        // 用于刷新按钮倒计时显示
        btnCountdownText: 5,
      }
    },
    mounted () {
      this.initView()
    },
    computed: {
      ...mapState('account', { currUser: 'user' }),
      ...mapState('setting', ['isMobile'])
    },
    props: {
      ticketId: {
        type: String,
        required: true
      },
      visible: {
        type: Boolean,
        default: false
      }
    },
    beforeDestroy () {
      this.stopTimer()
    },
    methods: {
      employeeNameSearch (input) {
        if (!input) {
          this.nameOptionsFiltered = []
          return
        }
        this.nameOptionsFiltered = this.nameOptions.filter(item => item.name.includes(input)).map(item => ({ label: item.name, value: item.id }))
      },
      // 获取所有员工名，供输入框备选
      getAllEmpNames () {
        return post(TicketDetailsViewApi.getAllEmployeeName, null)
          .then(res => {
            this.nameOptions = res
          }, err => {
            console.log(err)
          })
      },
      // 图像修改检测
      handleChange ({ fileList }) {
        this.fileList = fileList.filter((item) => {
          return item.status === 'done' || item.status === 'uploading'
        })
      },
      // 在上传页面，点击图片上的垃圾桶，撤销上传
      remove (file) {
        return post(TicketDetailsViewApi.revocationImage, {
          file: file
        })
          .then(res => {
            if (res.data === 'success') {
              this.$message.success('删除成功')
            }
            this.fileList = this.fileList.filter((item) => {
              return item.response.name !== file.response.name
            })
          }, err => {
            console.log(err)
          })
      },
      // 上传头像前校验
      beforeUpload (file) {
        const isJpgOrPng =
          file.type === 'image/jpeg' ||
          file.type === 'image/jpg' ||
          file.type === 'image/png'
        const Lt2M = file.size / 1024 / 1024 < 2
        if (!Lt2M) {
          this.$message.error('图片不得大于2MB!')
        }
        if (!isJpgOrPng) {
          this.$message.error('只能上传jpg/png格式的图片')
        }
        return isJpgOrPng && Lt2M
      },
      handleCancel () {
        this.previewVisible = false
      },
      // 处理预览图像
      async handlePreview (file) {
        if (!file.url && !file.preview) {
          file.preview = await getBase64(file.originFileObj)
        }
        this.previewImage = file.url || file.preview
        this.previewVisible = true
      },
      // 开启定时器
      setTimer () {
        if (this.timer === undefined) {
          this.timer = setInterval(() => {
            if (this.btnCountdownText > 0) {
              this.btnCountdownText--
              if (this.btnCountdownText === 0) {
                this.initView()
                this.btnCountdownText = 5
              }
            }
          }, 1000)
        }
      },
      // 初始化组件
      initView () {
        this.showSpin = true
        this.descriptionLoading = true
        // 获取所有员工名
        this.getAllEmpNames()
        // 获取工单的基本详情
        this.getTicketDetail(this.ticketId)
        // 获取工单的附加信息
        this.handleOtherData()
      },
      // 图像点击切换放大缩小
      changePhotoClass (id) {
        for (let i = 0; i < this.images.length; i++) {
          if (id === this.images[i].id) {
            this.images[i].isLarge = !this.images[i].isLarge
            this.selectedImage = this.images[i]
          }
        }
        this.selectedImageShow = !this.selectedImageShow
      },
      // 控制未放大图像变暗
      changePhotoClassForSmall (id) {
        for (let i = 0; i < this.images.length; i++) {
          if (id === this.images[i].id) {
            if (this.images[i].isLarge === true) {
              return 'img_sm_dark'
            } else {
              return 'img_sm'
            }
          }
        }
      },
      // 获取当前相关联的照片
      getPhoto () {
        return post(TicketDetailsViewApi.getTicketImages, {
          ticketId: this.ticketId
        })
          .then(res => {
            this.images = res
            for (let i = 0; i < this.images.length; i++) {
              this.images[i].isLarge = false
            }
            this.mergeAddImage()
          }, err => {
            console.log(err)
          })
      },
      // 将同一次上传的图片，与描述放在一起
      mergeAddImage () {
        this.originalImages = []
        for (let i = 0; i < this.addOnDescription.length; i++) {
          this.addOnDescription[i].images = []
        }
        for (let i = 0; i < this.images.length; i++) {
          if (this.images[i].did === 0) {
            this.originalImages.push(this.images[i])
            continue
          }
          for (let j = 0; j < this.addOnDescription.length; j++) {
            if (this.images[i].did === this.addOnDescription[j].id) {
              this.addOnDescription[j].images.push(this.images[i])
            }
          }
        }
        this.initDone()
      },
      initDone () {
        // 初始化信息
        this.showSpin = false
        this.descriptionLoading = false
        if (this.step !== 3) {
          this.setTimer()
        }
        this.addOnDescriptionOriginal = 1
      },
      // 关闭工单确认后业务逻辑
      handleCloseOk () {
        return post(TicketDetailsViewApi.manualCloseTicket, {
          ticketId: this.ticketId,
          time: this.format(new Date(), 'yyyy-MM-dd hh:mm:ss')
        })
          .then(res => {
            if (res.data !== 0) {
              this.$message.success(
                '操作成功',
                5
              )
              this.initView()
              this.closeVisible = false
            } else {
              this.$message.error(
                '操作失败',
                5
              )
            }
          }, err => {
            console.error(err)
          })
      },
      // 关闭工单取消后业务逻辑
      handleCloseCancel () {
        this.closeVisible = false
      },
      // 确认工单按钮业务逻辑
      confirmTicketBtn () {
        return post(TicketDetailsViewApi.confirmTicket, {
          ticketId: this.ticketId,
          time: this.format(new Date(), 'yyyy-MM-dd hh:mm:ss'),
          empId: this.currUser.id
        })
          .then(res => {
            if (res.data !== 0) {
              this.$message.success('操作成功', 5)
            } else {
              this.$message.error('工单已被他人处理或关闭，请刷新再试', 5)
            }
            this.initView()
          }, err => {
            console.error(err)
            this.$message.error('工单已被他人处理，请刷新再试', 5)
            this.initView()
          })
      },
      // 转移工单按钮业务逻辑
      transferBtn () {
        this.transVisible = true
      },
      // 获取工单状态撤销or关闭
      getStatus () {
        if (this.details.status === 2) {
          return '已撤销'
        } else {
          return '已关闭'
        }
      },
      // 关闭工单按钮业务逻辑
      closeBtn () {
        this.closeVisible = true
      },
      // 转移工单确认后逻辑
      handleTransferOk () {
        this.$refs.transmitFormRef.validate().then(() => {
          post(TicketDetailsViewApi.transferTicketToOthers, {
            ticketId: this.ticketId,
            endTime: this.format(new Date(), 'yyyy-MM-dd hh:mm:ss'),
            ...this.transmitForm,
            images: this.fileList
          })
            .then(res => {
              const result = res
              this.transVisible = false
              if (result.data === 1) {
                this.$message.success(
                  '操作成功',
                  5
                )
                this.fileList = []
                this.$refs.transmitFormRef.resetFields()
              } else {
                this.$message.error('工单已被他人处理或关闭，请刷新再试', 5)
              }
              this.handleCancel()
              this.initView()
            }, err => {
              console.error(err)
              this.transVisible = false
            })
        })
      },
      // 转移工单取消后逻辑
      handleTransferCancel () {
        this.transVisible = false
        this.$refs.transmitFormRef.resetFields()
      },
      // 关闭抽屉时回调
      onClose () {
        this.stopTimer()
        this.addOnDescription = []
        this.disableCloseBtn = false
        this.$emit('update:visible', false)
        this.originalImages = []
        this.images = []
        this.addOnDescriptionOriginal = undefined
      },
      // 对其他信息进行初始化，包括附加描述，图片
      handleOtherData () {
        const beforeLength = this.addOnDescription.length
        return post(TicketDetailsViewApi.getAddonDescription, {
          ticketId: this.ticketId
        })
          .then(res => {
            this.addOnDescription = res
            this.getPhoto()
            if (this.addOnDescription.length > beforeLength && this.addOnDescriptionOriginal !== undefined) {
              this.addOnDescriptionOriginal = 1
              this.$refs.audio.currentTime = 0
              this.$refs.audio.play()
              this.$notification.open({
                message: '最新通知',
                description:
                  '客户追加了问题描述，请及时查看！',
                onClick: () => {
                }
              })
            }
          }, err => {
            console.log(err)
          })
      },
      // 获取工单详情信息
      getTicketDetail (num) {
        this.showSpin = true
        return post(TicketDetailsViewApi.getTicketDetails, {
          ticketId: num
        }).then(res => {
            this.details = res[0]
            this.step = res[0].status
            if (this.details.status === 3) {
              this.disableCloseBtn = true
            }
            const categoryValue = this.details.category
            this.$appdata.getDictByKeyAsync('ticketCategoryMap').then(
              res => {
                this.details.category = res[categoryValue].label
              },
            )
          }, err => {
            console.error(err)
          })
      },
      // 日期格式化
      format (date, format) {
        return formatDate(date, format)
      },
      // 转换JSON
      toJSON (value) {
        try {
          return JSON.parse(value)
        } catch (e) {
          return value
        }
      },
      // 控制开始处理按钮可用状态
      handlerBtnDisable () {
        return this.step !== 0
      },
      // 控制移交他人按钮可用状态
      transferBtnDisable () {
        return this.step === 0 || this.step === 3
      },
      // 控制关闭工单按钮可用状态
      closeBtnDisable () {
        return this.step === 0 || this.disableCloseBtn || this.details.name !== this.currUser.ename
      },
      // 优先级文字显示
      showPriority () {
        if (this.details.priority === 2) {
          return '一般'
        } else if (this.details.priority === 1) {
          return '紧急'
        } else {
          return '非常紧急'
        }
      },
      // 优先度颜色控制
      showPriorityColorControl () {
        if (this.details.priority === 2) {
          return 'info'
        } else if (this.details.priority === 1) {
          return 'warning'
        } else {
          return 'error'
        }
      },
      // 单击工单流转历史图片
      flowImageClick (image) {
        this.selectedImage = image
        this.selectedImageShow = !this.selectedImageShow
      },
      // 停止定时器
      stopTimer () {
        if (this.timer) {
          clearInterval(this.timer)
          this.timer = undefined
        }
      },
    },
    watch: {
      'visible' (val) {
        if (val) {
          this.initView()
        }
      },
      'step' (newVal) {
        if (newVal === 3) {
          this.stopTimer()
        }
      }
    }
  }
</script>

<style lang="less" scoped>
.high-priority{
  background-color: rgba(163, 30, 30, 0.66);
  border: red solid 1px;
  font-size: large;
  padding: 5px;
  color: white;
  border-radius: 10px;
}

.detail-layout {
  margin-left: 44px;
}
.text {
  color: rgba(0, 0, 0, .45);
}

.heading {
  color: rgba(0, 0, 0, .85);
  font-size: 20px;
}

.no-data {
  color: rgba(0, 0, 0, .25);
  text-align: center;
  line-height: 64px;
  font-size: 16px;

  i {
    font-size: 24px;
    margin-right: 16px;
    position: relative;
    top: 3px;
  }
}

.mobile {
  .detail-layout {
    margin-left: unset;
  }
  .text {

  }
  .status-list {
    text-align: left;
  }
}

.row {
  display: flex;

  .content {
    -webkit-box-flex: 1;
    flex: auto;
    -ms-flex: auto;
  }

  .extra {
    flex: 0 1 auto;
    -webkit-box-flex: 0;
    -ms-flex: 0 1 auto;
    min-width: 242px;
    margin-left: 88px;
    text-align: right;
  }
}

.img_sm {
  border: rgba(84, 84, 84, 0.2) solid 1.5px;
  border-radius: 5px;
  padding: 10px;
  width: 160px;
  height: 120px;
  margin-bottom: 20px;
  margin-left: 20px;
}
.img_xl {
  position: absolute;
  top:0;bottom:0;left:0;right:0;
  margin: auto;
  width: 60%;
  max-width: 1000px;
  cursor: zoom-out;
  z-index: 9999;
  animation: imgZoomIn 0.4s;
  -webkit-animation: imgZoomIn 0.4s;
}
@keyframes imgZoomIn
{
  from {width: 160px;}
  to {width: 60%;}
}
.img_sm:hover {
  opacity: 0.6;
  cursor: zoom-in;
}
.img_sm_dark{
  filter: grayscale(100%);
  opacity: 0.6;
  border: rgba(84, 84, 84, 0.2) solid 1.5px;
  border-radius: 5px;
  padding: 10px;
  width: 160px;
  height: 120px;
  margin-bottom: 20px;
  margin-left: 20px;
}
.imgBackground {
  position: absolute;
  top:0;bottom:0;left:0;right:0;
  width: 100%;
  height: 100%;
  z-index: 9998;
  background-color: rgba(0,0,0,0.7);
}
</style>
