xw_admin/src/views/order/dataConfirm/index.vue
2024-08-29 23:40:46 +08:00

784 lines
25 KiB
Vue

<template>
<el-container class="mainBox">
<el-aside width="340px">
<el-container>
<el-header>
<span class="emailTitle">邮件通知</span>
<span class="statusBox">
<span class="item complete">已确认</span>
<span class="item notStarted">未确认</span>
<span class="item part">部分确认</span>
</span>
<emailSync @updateSync="refreshDom" :show="refreshShow" :text="syncText">
<span class="refreshEmail" v-auth="'mailSyncManual'" @click="manualClick"><el-icon size="16px" :class="refreshShow?'refreshEmailIcon':''"><sc-icon-Refresh/></el-icon></span>
</emailSync>
</el-header>
<el-main class="nopadding" v-loading="listLoading" element-loading-text="加载中...">
<el-scrollbar height="100%" ref="scrollbar" @scroll="onScroll">
<div class="emailMain" ref="emailMain">
<div class="itemBox" :class="[item.is_confirm==2?'part':item.is_confirm==1?'complete':'notStarted', emailId == item.id?'itemTrue':'']" v-for="item in confirmList" :key="item" @click="()=>{this.emailChange(item,true);}">
<div class="name text">{{item.from && item.from.email}}</div>
<div class="title text">{{item.subject}}</div>
<div class="msg text">{{item.text}}</div>
<div class="date">{{item.sent_at}}</div>
<div class="total">
<el-badge class="badgeItem" :value="item.total_count" :max="99" color="#eeeeee"></el-badge>
</div>
<div class="deleteBtn" v-auth="'mailDataDelete'" @click.stop="deleteEmail(item)"><el-icon style="font-size: 32px"><sc-icon-JbDelete/></el-icon></div>
</div>
</div>
</el-scrollbar>
</el-main>
</el-container>
</el-aside>
<el-container class="mainHeaderNoBorderPadding" v-loading="loading" element-loading-text="加载中...">
<el-main class="nopadding emailMiddle">
<div class="emailContent">
<div class="title">【邮件名称】{{emailParams.subject}}</div>
<div class="fromPeople itemText"><span class="text">发件人:</span>{{emailParams.from && emailParams.from.email}} {{emailParams.from && emailParams.from.name?'('+emailParams.from.name+')':''}}</div>
<div class="receivingPeople itemText"><span class="text">收件人:</span>{{emailParams.source_email}}</div>
<div class="theme itemText">
<span class="text">摘&nbsp;&nbsp;&nbsp;要:</span><span v-html="emailParams.text"></span>
</div>
<div class="rightBtnMain">
<div class="date">{{emailParams.sent_at}}</div>
<div class="btnItem">
<el-button type="danger" v-auth="'repairDelete'" :disabled="selection.length>0?false:true" plain icon="el-icon-delete" :size="size" @click="deleteEmailDetail"></el-button>
<el-button type="primary" v-auth="'mailBodyInfo'" plain :size="size" @click="seeEmail">查看原邮件</el-button>
<el-dropdown placement="bottom-start">
<el-button type="primary" v-auth="'repairConfirm'" :size="size">确认维保 <el-icon class="el-icon--right"><el-icon-ArrowDown/></el-icon></el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="allDefend('all')">全部入保</el-dropdown-item>
<el-dropdown-item @click="allDefend">部分入保</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
</div>
<div class="emailBody">
<div class="searchMain " style="padding-left: 10px;">
<scSearch ref="scSearch" :searchList="searchList" @fetchSelectData="getSelectData"></scSearch>
<div class="searchItem searchBtn">
<el-button :size="size" :icon="searchShow?'el-icon-ArrowUpBold':'el-icon-ArrowDownBold'" @click="searchShowClick">{{searchShow?'收起':'更多'}}</el-button>
<el-button :size="size" type="primary" icon="el-icon-search" @click="upSearch">查询</el-button>
<el-button :size="size" type="info" icon="el-icon-RefreshRight" @click="reset">重置</el-button>
</div>
</div>
<el-table class="scTable" :header-cell-class-name="setClassName" :data="emailData.rows" ref="table" :row-key="rowKey" :key="toggleIndex" :header-cell-style="{'background': '#F5F7FA','color':'#606266'}" @selection-change="selectionChange" :size="config.size" :border="config.config.border" :stripe="config.config.stripe">
<el-table-column type="selection" align="center" width="45" :selectable="selectable"></el-table-column>
<el-table-column label="序号" align="center" type="index" :index="customIndexMethod"></el-table-column>
<template v-for="(item, index) in userColumn" :key="index">
<template v-if="item.prop == 'description'">
<el-table-column v-if="!item.hide" :column-key="item.prop" :label="item.label" :prop="item.prop" :width="item.width" :sortable="item.sortable" :fixed="item.fixed" :filters="item.filters">
<template #default="scope">
<slot :name="item.prop" v-bind="scope">
<el-popover
placement="bottom-start"
title=""
:width="400"
trigger="hover"
:content="scope.row[item.prop]"
>
<template #reference>
<span style="width: 100%;display: inline-block;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;">{{scope.row[item.prop]}}</span>
</template>
</el-popover>
</slot>
</template>
</el-table-column>
</template>
<template v-else>
<el-table-column v-if="!item.hide" :column-key="item.prop" :label="item.label" :prop="item.prop" :width="item.width" :sortable="item.sortable" :fixed="item.fixed" :filters="item.filters" show-overflow-tooltip>
<template #default="scope">
<slot :name="item.prop" v-bind="scope">
<span v-if="item.prop == 'is_confirm'" :class="{'success':scope.row[item.prop],'danger':!scope.row[item.prop]}">
{{scope.row[item.prop]?'已确认':'未确认'}}
</span>
<span v-else>{{ scope.row[item.prop] }}</span>
</slot>
</template>
</el-table-column>
</template>
</template>
<el-table-column min-width="1"></el-table-column>
<template #empty>
<el-empty :description="emptyText" :image-size="100"></el-empty>
</template>
</el-table>
</div>
<div class="annex">
<div class="annexMain" v-if="emailParams.file_path && emailParams.file_path.length>0">
<div class="title">
{{emailParams.file_path && emailParams.file_path.length}} 个附件
</div>
<div class="itemBox">
<div class="leftBox">
<el-icon style="font-size: 26px;"><sc-icon-Excel/></el-icon>
</div>
<div class="rightBox" @click="downFile(emailParams)">
<div class="name">{{emailParams.file_name && emailParams.file_name.file}}</div>
<div class="size">
{{emailParams.file_name && emailParams.file_name.size}}
<span class="down">下载</span>
</div>
</div>
</div>
</div>
<div class="scTable-page">
<div class="scTable-pagination">
<el-pagination background :small="true" :layout="paginationLayout" :total="total" :page-size="scPageSize" :page-sizes="pageSizes" v-model:currentPage="currentPage" @current-change="paginationChange" @update:page-size="pageSizeChange"></el-pagination>
</div>
<div class="scTable-do">
<el-button @click="reset" icon="el-icon-refresh" circle style="margin-left:15px"></el-button>
<el-popover placement="top" title="列设置" :width="500" trigger="click" :hide-after="0" @show="customColumnShow=true" @after-leave="customColumnShow=false">
<template #reference>
<el-button icon="el-icon-set-up" circle style="margin-left:15px"></el-button>
</template>
<columnSetting v-if="customColumnShow" ref="columnSetting" @userChange="columnSettingChange" @save="columnSettingSave" @back="columnSettingBack" :column="userColumn"></columnSetting>
</el-popover>
<el-popover placement="top" title="表格设置" :width="400" trigger="click" :hide-after="0">
<template #reference>
<el-button icon="el-icon-setting" circle style="margin-left:15px"></el-button>
</template>
<el-form label-width="80px" label-position="left">
<el-form-item label="表格尺寸">
<el-radio-group v-model="config.size" size="small" @change="configSizeChange">
<el-radio-button label="large">大</el-radio-button>
<el-radio-button label="default">正常</el-radio-button>
<el-radio-button label="small">小</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="样式">
<el-checkbox v-model="config.config.border" label="纵向边框" @change="configSizeChange"></el-checkbox>
<el-checkbox v-model="config.config.stripe" label="斑马纹" @change="configSizeChange"></el-checkbox>
</el-form-item>
</el-form>
</el-popover>
</div>
</div>
</div>
</el-main>
</el-container>
</el-container>
</template>
<script>
import columnSetting from '@/components/scTable/columnSetting'
import emailSync from './emailSync'
import config from "@/config/table";
import {eventBus} from "@/utils/eventBus"
export default {
components: {
columnSetting,
emailSync
},
data() {
return {
size:'small',
dialog: {
save: false,
show: false,
},
confirmList:[],
listMore:false,
listLoading:false,
listParams:{
page:1,
pageSize:30,
},
threshold:100,
refreshShow:false,
syncText:"",
emailId:'',
searchShow:false,
searchData:{},
searchList:[
{name:'是否确认',type:'select',code:['is_confirm'],data:[],placeholder:"请选择",isOpen:true,show:false},
{name:'单号',type:'text',code:['sn'],placeholder:"请输入单号",isOpen:true,show:false},
{name:'SN号',type:'text',code:['serial_number'],placeholder:"请输入SN号",isOpen:true,show:false},
{name:'Aliid',type:'text',code:['aliid'],placeholder:"请输入Aliid",isOpen:true,show:false},
{name:'PE确认日期',type:'date',code:'pe_confirmation_time',show:true},
{name:'故障类型',type:'select',code:['fault_type'],data:[],placeholder:"请选择故障类型",isOpen:true,show:false},
{name:'近期维修',type:'select',code:['recent_repair'],data:[],placeholder:"请输入近期维修",isOpen:true,show:false},
{name:'机架',type:'select',code:['rack'],data:[],placeholder:"请选择机架",isOpen:true,show:false},
{name:'机型',type:'select',code:['model'],data:[],placeholder:"请选择机型",isOpen:true,show:false},
{name:'阿里机型',type:'select',code:['ali_model'],data:[],placeholder:"请选择阿里机型",isOpen:true,show:false},
{name:'通知时间',type:'date',code:['notification_time'],show:true},
{name:'描述',type:'text',code:['description'],placeholder:"请输入描述",isOpen:true,show:false},
{name:'维修分类',type:'select',code:['maintenance_category'],data:[],placeholder:"请选择维修分类",isOpen:true,show:false},
{name:'预约时间',type:'date',code:['scheduled_time'],show:true},
{name:'过保时间',type:'date',code:['warranty_expiry_time'],show:true},
{name:'4BD SLA 截止时间',type:'date',code:['4bd_sla_expiry_time'],isOpen:true,show:false},
{name:'15BD SLA 截止时间',type:'date',code:['15bd_sla_expiry_time'],isOpen:true,show:false},
{name:'序列号',type:'text',code:['manufacturer_serial_number'],placeholder:"请输入序列号",isOpen:true,show:false},
{name:'厂商',type:'select',code:['manufacturer'],data:[],placeholder:"请选择厂商",isOpen:true,show:false},
{name:'型号',type:'select',code:['product_model'],data:[],placeholder:"请选择型号",isOpen:true,show:false},
{name:'槽位号',type:'text',code:['slot_number'],placeholder:"请输入槽位号",isOpen:true,show:false},
{name:'固件版本号',type:'text',code:['firmware_version'],placeholder:"请输入固件版本号",isOpen:true,show:false},
{name:'大小',type:'select',code:['size'],data:[],placeholder:"请输入大小",isOpen:true,show:false},
{name:'物料编号',type:'text',code:['material_number'],placeholder:"请输入物料编号",isOpen:true,show:false},
{name:'速率',type:'select',code:['speed'],data:[],placeholder:"请输入速率",isOpen:true,show:false},
{name:'类型',type:'select',code:['type'],data:[],placeholder:"请输选择类型",isOpen:true,show:false},
{name:'创建时间',type:'date',code:['created_at'],isOpen:true,show:false},
],
emailParams: {},
toggleIndex: 0,
rowKey:"",
paginationLayout:config.paginationLayout,
scPageSize:config.pageSize,
pageSizes:config.pageSizes,
currentPage: 1,
total:0,
loading:false,
customColumnShow: false,
config: {
size: 'small',
config:{
border: false,
stripe: false
},
},
selection:[],
userColumn:[],
emailData:{
list:[],
column:[],
rows:[]
},
emptyText: "暂无数据",
}
},
computed: {
isAllDisabled() {
let isDis = false;
if(this.emailData && this.emailData.rows.length>0){
isDis = this.emailData.rows.every((el) => el.is_confirm == true)
}
return isDis
},
},
mounted() {
this.getData();
},
methods: {
customIndexMethod(index){
const start = (this.currentPage - 1) * this.scPageSize + 1;
return start + index
},
setClassName({ column }) {
if (column.type == 'selection' && this.isAllDisabled) {
return 'all-disabled'
}
},
async getData() {
this.listLoading = true;
const res = await this.$API.orders.order.mail.list.get(this.listParams);
this.listLoading = false;
if(res.code == 200){
if(res.data.rows && res.data.rows.length>0){
res.data.rows.forEach(item=>{
item.text = this.stripHtmlTags(item.summary)
})
}
if(res.data.rows && res.data.rows.length < this.listParams.pageSize){
this.listMore = true;
}else{
this.listMore = false;
}
if(this.listParams.page == 1){
this.confirmList = res.data.rows;
await this.emailChange(res.data.rows[0])
}else{
this.confirmList = this.confirmList.concat(res.data.rows);
}
}
},
stripHtmlTags(html) {
const div = document.createElement('div');
div.innerHTML = html;
return div.textContent || div.innerText || '';
},
// 删除邮件
async deleteEmail(item) {
let params = {
ids:[item.id]
}
const res = await this.$API.orders.order.mail.emailDelete.post(params);
if(res.code == 200){
this.emailId = "";
await this.getData();
}
},
// 滚动分页
onScroll(event){
this.$nextTick(()=>{
const scrollbar = this.$refs.scrollbar;
const emailHeight = this.$refs.emailMain;
const remainingDistance = scrollbar.$el.scrollHeight + event.scrollTop + 100;
if (remainingDistance > emailHeight.clientHeight) {
this.loadMore();
}
})
},
loadMore(){
if(this.listLoading || this.listMore){
return
}
this.listParams.page ++;
this.getData();
},
emailChange(item,isChange) {
this.emailId = isChange?item.id:this.emailId>0?this.emailId:item.id;
this.searchData = {};
if(this.$refs.scSearch){
this.$refs.scSearch.reload();
}
this.getEmailData();
},
async getEmailData() {
let params = Object.assign({},{
mail_data_id: this.emailId,
pageSize:this.scPageSize,
page:this.currentPage
},this.searchData);
this.loading = true;
const res = await this.$API.orders.order.mail.detail.post(params);
if (res.code == 200) {
this.total = res.data.total;
this.emailData = res.data;
this.userColumn = res.data.columnConfig;
if(res.data.mail_info && res.data.mail_info.length>0){
res.data.mail_info[0].text = this.stripHtmlTags(res.data.mail_info[0].summary)
this.emailParams = res.data.mail_info[0];
}
if(res.data.tableConfig && res.data.tableConfig.size){
this.config = res.data.tableConfig;
}
}
this.loading = false;
},
async getDetailIds() {
let ids = new Array();
let params = {
mail_data_id:this.emailId
}
const res = await this.$API.orders.order.mail.detailIds.post(params);
if(res.code == 200){
ids = res.data;
}
return ids;
},
async allDefend(type) {
let res = {};
if(type == "all"){
const ids = await this.getDetailIds();
if(ids){
let params = {
mail_data_id:this.emailId,
ids:ids
};
res = await this.$API.orders.order.mail.confirm.post(params);
}
}else{
let params = {
mail_data_id:this.emailId,
ids:this.selection.map(em=> em.id)
};
res = await this.$API.orders.order.mail.confirm.post(params);
}
if(res.code == 200){
this.listParams.page = 1;
await this.getData();
}
},
async manualClick() {
if(this.refreshShow){
return
}
const res = await this.$API.orders.order.mail.manual.post();
if(res.code == 200){
this.$message.success('开始检查是否有需要同步的邮件');
}
},
refreshDom(params){
if(params.type == 16){
this.refreshShow = params.current != params.limit && params.status ==0?true:false;
this.syncText = params.msg;
if(params.status == 1){
this.$message.success(params.msg);
this.getData();
}
}
},
// 删除邮件明细
async deleteEmailDetail() {
let params = {
mail_data_id:this.emailId,
ids:this.selection.map(em=> em.id)
};
const res = await this.$API.orders.order.mail.delete.post(params);
if(res.code == 200){
await this.getData();
}
},
seeEmail(){
eventBus.$emit('tagClose','/order/view-mail',{id:this.emailId});
},
async getSelectData(item) {
let {data, params} = item;
this.searchData = params;
let searchParams = this.$TOOL.objCopy(params);
searchParams.mail_data_id = this.emailId;
searchParams.field = ""
if(typeof data.code === 'string'){
searchParams.field = data.code;
}else{
searchParams.field = data.code[0];
}
if(data.type == 'select'){
const res = await this.$API.orders.order.mail.selectField.post(searchParams);
if(res.code == 200){
if(res.data && res.data.length>0){
res.data.forEach(item=>{
item.label = item[data.code];
})
}
this.searchList.forEach(item=>{
if(item.code == data.code){
item.data = res.data;
}
})
}
}
},
searchShowClick(){
this.searchShow = !this.searchShow;
this.searchList.forEach(item=>{
if(item.isOpen){
item.show = this.searchShow
}
})
},
upSearch(){
this.getEmailData();
},
reset(){
this.searchData = {};
this.$refs.scSearch.reload();
this.getEmailData();
},
downFile(info){
if(info.file_path && info.file_path.length>0){
info.file_path.forEach(em=>{
const link = document.createElement('a');
link.href = em;
link.setAttribute('download', '');
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
})
}
},
// 选择数据
selectionChange(selection){
this.selection = selection;
},
selectable(row){
if(row.is_confirm){
return false;
}else {
return true;
}
},
//分页点击
paginationChange(){
this.getEmailData();
},
//条数变化
pageSizeChange(size){
this.scPageSize = size
this.getEmailData();
},
//自定义变化事件
columnSettingChange(userColumn){
this.userColumn = userColumn;
this.toggleIndex += 1;
},
//自定义列保存
async columnSettingSave(userColumn){
this.$refs.columnSetting.isSave = true
try {
let apiObj = this.$API.orders.order.mail.detail;
await config.columnSettingSave('', userColumn, apiObj, {mail_data_id:this.emailId});
this.$message.success('保存成功')
}catch(error){
this.$message.error('保存失败')
this.$refs.columnSetting.isSave = false
}
this.$refs.columnSetting.isSave = false
},
//自定义列重置
async columnSettingBack(userColumn){
this.$refs.columnSetting.isSave = true
try {
let apiObj = this.$API.orders.order.mail.detail;
const column = await config.columnSettingReset('', userColumn, apiObj, {mail_data_id:this.emailId})
if(column){
this.userColumn = column
this.$refs.columnSetting.usercolumn = JSON.parse(JSON.stringify(this.userColumn||[]))
}
}catch(error){
this.$message.error('重置失败')
this.$refs.columnSetting.isSave = false
}
this.$refs.columnSetting.isSave = false
},
async configSizeChange() {
try {
let apiObj = this.$API.orders.order.mail.detail;
await config.columnSettingConfigSave('', this.config, apiObj, {mail_data_id:this.emailId});
this.$message.success('保存成功')
} catch (error) {
this.$message.error('保存失败')
}
},
}
}
</script>
<style lang="scss" scoped>
::v-deep .all-disabled .el-checkbox__input .el-checkbox__inner {
background-color: #edf2fc;
border-color: #dcdfe6;
cursor: not-allowed;
}
.emailTitle{font-size: 14px;font-weight: 600;}
.statusBox{
display: flex;align-items: center;justify-content: flex-end;
.item{
position: relative;
margin-left: 18px;
}
.item:after{
content: '';
position: absolute;
left: -12px;
top: 5px;
width: 6px;
height: 6px;
border-radius: 50%;
}
}
.refreshEmail{
display: flex;align-items: center;color: var(--el-color-primary);
cursor: pointer;
}
.refreshEmailIcon{
animation: rotate 0.6s infinite linear;
}
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.refreshBox{
padding: 10px;
}
.complete:after{
background: var(--el-color-success);
}
.notStarted:after{
background: var(--el-color-danger);
}
.part:after{
background: var(--el-color-warning);
}
.emailMain{
padding: 5px 0;
.itemBox{
position: relative;
padding: 12px 0 12px 15px;
cursor: pointer;
.text{text-overflow: ellipsis;white-space: nowrap;overflow: hidden;width: calc(100% - 10px);}
.name{margin-bottom: 10px;font-size: 14px;font-weight: 600;color: var(--el-color-dark);}
.title{margin-bottom: 6px;color: var(--el-text-color-regular)}
.msg{color: var(--el-text-color-placeholder);width: calc(100% - 40px);}
.date{
position: absolute;right: 12px;top: 14px;z-index: 10;
color: var(--el-text-color-regular);
width: 90px;
overflow: hidden;text-overflow: ellipsis;white-space: nowrap;
}
.total{
position: absolute;right: 12px;bottom: 8px;z-index: 10;
.badgeItem ::v-deep .el-badge__content{
background: #EBEBEB;
border-color: #EBEBEB;
color: #555555;
}
}
.deleteBtn{
position: absolute;
bottom: -4px;
right: 0;
align-items: flex-end;
justify-content: center;
display: none;
}
}
.itemBox:hover{
padding-right: 10px;
cursor: pointer;
}
.itemBox:hover .total{
right: 20px;
}
.itemBox:hover .deleteBtn{
display: flex;
cursor: pointer;
}
.itemBox:after{
content: "";
position: absolute;
top: 16px;
left: 2px;
z-index: 20;
width: 4px;
height: calc(100% - 32px);
border-radius: 4px;
}
.itemTrue{
background: #EFF5FF;
border-top-left-radius: 2px;
border-bottom-left-radius: 2px;
}
.itemBox:last-child{
box-shadow: none;
}
}
.emailMiddle{
display: flex;flex-direction: column;
.emailContent{
box-shadow: 0 1px 1px rgba(0,0,0,0.06);
padding: 10px 5px 10px 10px;
color: var(--el-color-dark);
position: relative;
.title{
font-weight: 600;
font-size: 14px;
padding: 10px 0;
margin-bottom: 8px;
}
.fromPeople{
margin-bottom: 6px;
}
.date{
margin-bottom: 6px;
}
.receivingPeople{
margin-bottom: 6px;
}
.itemText{
padding: 0 0 0 10px;
.text{
color: var(--el-text-color-regular)
}
}
.theme{
line-height: 20px;
}
.rightBtnMain{
position: absolute;
right: 10px;
top: 10px;
.date{
text-align: right;
margin-bottom: 10px;
color: var(--el-text-color-placeholder);
}
}
}
.emailBody{
flex: 1;
overflow: hidden;
display: flex;flex-direction: column;
}
.annex{
padding: 10px;
overflow: hidden;
display: flex;flex-direction: column;justify-content: space-between;
.annexMain{
width: 320px;
margin-bottom: 10px;
.itemBox{
margin-top: 8px;
border-radius: 4px;
padding: 10px;
background: #f6f6f6;
display: flex;align-items: center;
cursor: pointer;
.leftBox{flex-basis: 40px;display: flex;align-items: center;justify-content: flex-start;}
.rightBox{
flex: 1;overflow: hidden;
.name{
width: 100%;
white-space: nowrap;text-overflow: ellipsis;overflow: hidden;
margin-bottom: 4px;
}
.size{
position: relative;
.down{
color: var(--el-color-primary);
cursor: pointer;
margin-left: 10px;
}
}
}
}
}
.scTable-page{
flex: 1;
display: flex;flex-direction: row;justify-content: space-between;align-items: flex-end;
}
}
}
.scTable{
flex: 1;
overflow: hidden;
.success{
color: var(--el-color-success);
}
.danger{
color: var(--el-color-danger);
}
}
.scTable ::v-deep .el-table__header .cell{
white-space: nowrap;text-overflow: ellipsis;overflow: hidden;
}
</style>