完善客户端问题单及维护期限

This commit is contained in:
龙运模 2024-11-29 20:40:32 +08:00
parent 1c6d8e34c9
commit 5bb07240f4
14 changed files with 955 additions and 222 deletions

View File

@ -90,7 +90,7 @@ export default {
orderList:{
url: `${config.API_URL}/customer.work.order.list`,
name: "问题工单列表",
post: async function(data){
get: async function(data){
return await http.post(this.url, data);
}
},
@ -104,7 +104,7 @@ export default {
orderMyList:{
url: `${config.API_URL}/customer.work.order.my.list`,
name: "我的问题工单",
post: async function(data){
get: async function(data){
return await http.post(this.url, data);
}
},
@ -114,6 +114,47 @@ export default {
post: async function(data){
return await http.post(this.url, data);
}
},
queryRecordList:{
url: `${config.API_URL}/service.query.record.list`,
name: "查询历史记录",
get: async function(data){
return await http.post(this.url, data);
}
},
periodQuery:{
url: `${config.API_URL}/customer.maintenance.period.query`,
name: "维保期限查询",
get: async function(data){
return await http.post(this.url, data);
}
},
periodQueryStatusList:{
url: `${config.API_URL}/customer.order.business.status.list`,
name: "维保期限业务状态列表",
post: async function(data){
return await http.post(this.url, data);
}
},
customerMyQuery:{
url: `${config.API_URL}/customer.my.query`,
name: "我的记录查询(查询所有记录)",
post: async function(data){
return await http.post(this.url, data);
}
},
customerRecentlyQuery:{
url: `${config.API_URL}/customer.recently.query`,
name: "我的最近查询查询前10条",
post: async function(data){
return await http.post(this.url, data);
}
},
recommendation:{
url: `${config.API_URL}/customer.random.recommendation`,
name: "随机推荐",
post: async function(data){
return await http.post(this.url, data);
}
}
}

View File

@ -1,7 +1,6 @@
<template>
<el-container class="mainBox mainHeaderNoBorderPadding">
<el-header>
<!--v-auths="['addCost','deleteCost','costFlowImport','costFlowExport']"-->
<div class="left-panel">
<el-button type="primary" v-auth="'addCost'" :size="size" icon="el-icon-plus" @click="add">新增</el-button>
<el-button type="danger" plain v-auth="'deleteCost'" :disabled="selection.length>0?false:true" :size="size" icon="el-icon-delete" @click="all_del"></el-button>
@ -80,7 +79,7 @@
</el-main>
</el-container>
<!-- <save-dialog v-if="dialog.save" ref="saveDialog" @success="handleSuccess" @closed="dialog.save=false"></save-dialog>-->
<save-dialog v-if="dialog.save" ref="saveDialog" @success="handleSuccess" @closed="dialog.save=false"></save-dialog>
</template>
<script>

View File

@ -27,7 +27,7 @@
<div class="history">
<div class="title">搜索历史</div>
<div class="mainView">
<div class="viewItem" v-for="(item,index) in historyList" :key="index">{{item.name}}</div>
<div class="viewItem" v-for="(item,index) in historyList" :key="index">{{item.content}}</div>
</div>
</div>
<footerPage></footerPage>
@ -49,52 +49,8 @@ export default {
{name:"咨询与联系方式",icon:"sc-icon-SeekAdviceFrom",url:''},
{name:"其他",icon:"sc-icon-OtherServe",url:''},
],
recommendList:[
{name:'维保期限查询',color:'#436FFF'},
{name:'主控部件查询',color:'#FF8543'},
{name:'智能客服',color:'#22D3F6'},
{name:'我的产品',color:'#0FCA44'},
{name:'订单号查询',color:'#FBCA0A'},
{name:'主控部件查询',color:'#FF8543'},
{name:'我的产品',color:'#32af40'},
{name:'主控部件查询',color:'#FF8543'},
{name:'问题单',color:'#FF4B51'},
{name:'主控部件查询',color:'#FF8543'},
{name:'我的产品',color:'#0FCA44'},
{name:'问题单',color:'#FF4B51'},
{name:'维保期限查询',color:'#436FFF'},
{name:'订单号查询',color:'#FBCA0A'},
{name:'我的产品',color:'#0FCA44'},
{name:'订单号查询',color:'#FBCA0A'},
{name:'主控部件查询',color:'#94471d'},
{name:'我的产品',color:'#FF8543'},
{name:'主控部件查询',color:'#3d7a80'},
{name:'问题单',color:'#FF4B51'},
{name:'主控部件查询',color:'#FF8543'},
],
historyList:[
{name:'搜索历史文案占位……'},
{name:'搜索历史文案占位……'},
{name:'搜索历史文案占位……'},
{name:'维保工单'},
{name:'维保工单'},
{name:'维保工单'},
{name:'维保工单'},
{name:'维保工单'},
{name:'维保工单'},
{name:'维保工单'},
{name:'维保工单'},
{name:'维保工单'},
{name:'维保工单'},
{name:'维保工单'},
{name:'维保工单'},
{name:'维保工单'},
{name:'维保工单'},
{name:'维保工单'},
{name:'维保工单'},
{name:'维保工单'},
{name:'维保工单'},
]
recommendList:[],
historyList:[]
}
},
activated() {
@ -104,10 +60,8 @@ export default {
},
mounted() {
for (let i = 0; i < this.recommendList.length; i++) {
const bubble = this.getCreateBubble(this.recommendList[i]);
this.$refs.bubble.appendChild(bubble);
}
this.getRecommendation();
this.getRecentlyQuery();
},
beforeUnmount() {
@ -128,10 +82,36 @@ export default {
bubble.style.top = `${y}px`;
bubble.style.maxWidth = '160px';
bubble.style.maxHeight = '38px';
bubble.style.background = `${item.color}`;
bubble.innerText =`${item.name}`;
bubble.style.background = this.getRandomColor();
bubble.innerText =`${item.description}`;
return bubble
},
getRandomColor() {
const letters = '0123456789ABCDEF';
let color = '#';
for (let i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
},
async getRecommendation() {
const res = await this.$API.customer.recommendation.post();
if(res.code === 200){
for (let i = 0; i < res.data.length; i++) {
const bubble = this.getCreateBubble(res.data[i]);
this.$refs.bubble.appendChild(bubble);
}
}
},
async getRecentlyQuery() {
const res = await this.$API.customer.customerRecentlyQuery.post();
if (res.code === 200) {
this.historyList = res.data;
}
}
}
}
</script>
@ -141,7 +121,6 @@ export default {
display: flex;
flex-direction: column;
padding: 0 20px;
//min-height: 800px;
.rowView{
height: 240px;
padding: 20px 0;
@ -235,7 +214,7 @@ export default {
justify-content: flex-start;
flex-wrap: wrap;
position: relative;
height: 300px;
height: 280px;
::v-deep .bubble{
display: flex;
align-items: center;
@ -264,7 +243,7 @@ export default {
font-size: 22px;
}
.mainView{
padding: 20px 0 80px 0;
padding: 20px 0 30px 0;
max-width: 1200px;
margin: 0 auto;
display: flex;
@ -273,6 +252,9 @@ export default {
width: 33%;
padding: 10px 0;
font-size: 16px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
}

View File

@ -0,0 +1,345 @@
<template>
<el-container class="mainView">
<el-scrollbar style="width: 100%">
<el-main>
<el-form ref="form" :size="size" :rules="rules" label-width="95px" :model="form">
<div class="boxMain">
<div class="title">工单时间</div>
<div class="boxCom">
<el-row>
<el-col :span="8" :lg="6">
<el-form-item label="报修客户" prop="customer">
<el-select class="input" v-model="form.customer_id" @visible-change="getCustomerSelect('customer')" placeholder="请选择报修客户">
<el-option v-for="(item,index) in setMap['customer']" :key="index" :value="item.id" :label="item.customer_name"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8" :lg="6">
<el-form-item label="标准机型" prop="standard_model">
<el-input class="input" type="text" v-model="form.standard_model" placeholder="请输入标准机型"></el-input>
</el-form-item>
</el-col>
<el-col :span="8" :lg="6">
<el-form-item label="报修日期">
<el-date-picker class="input" type="date" value-format="YYYY-MM-DD" placeholder="请选择报修日期"></el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="8" :lg="6">
<el-form-item label="PE确认时间" prop="pe_confirmation_time">
<el-date-picker class="input" v-model="form.pe_confirmation_time" type="date" value-format="YYYY-MM-DD" placeholder="请选择PE确认时间"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="8" :lg="6">
<el-form-item label="过保时间" prop="warranty_end_date">
<el-date-picker class="input" v-model="form.warranty_end_date" type="date" value-format="YYYY-MM-DD" placeholder="请选择过保时间"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="8" :lg="6">
<el-form-item label="SLA截止时间" prop="sla_expiration">
<el-date-picker class="input" v-model="form.sla_expiration" type="date" value-format="YYYY-MM-DD" placeholder="请选择SLA截止时间" style="width: 100%"></el-date-picker>
</el-form-item>
</el-col>
</el-row>
</div>
</div>
<div class="boxMain">
<div class="title">维保工单信息</div>
<div class="boxCom">
<el-row>
<el-col :span="8" :lg="6">
<el-form-item label="维修单等级" prop="maintenance_grade">
<el-input class="input" v-model="form.maintenance_grade" type="text" placeholder="请输入维修等级"></el-input>
</el-form-item>
</el-col>
<el-col :span="8" :lg="6">
<el-form-item label="维修分类" prop="maintenance_level">
<el-select class="input" v-model="form.maintenance_level" @visible-change="getSelect('maintenance_level',2)" placeholder="请选择维修分类">
<el-option v-for="(item,index) in setMap['maintenance_level']" :key="index" :value="item.id" :label="item.item_name"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8" :lg="6">
<el-form-item label="故障内容" prop="fault_description">
<el-input class="input" v-model="form.fault_description" type="text" placeholder="请输入维修单号"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="8" :lg="6">
<el-form-item label="故障类型" prop="fault_type">
<el-select class="input" v-model="form.fault_type" @visible-change="getSelect('fault_type',1)" placeholder="请选择故障类型">
<el-option v-for="(item,index) in setMap['fault_type']" :key="index" :value="item.id" :label="item.item_name"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8" :lg="6">
<el-form-item label="维保等级" prop="maintenance_plan">
<el-input class="input" v-model="form.maintenance_plan" placeholder="维保等级">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8" :lg="6">
<el-form-item label="是否关机" prop="requires_shutdown">
<el-select class="input" v-model="form.requires_shutdown" placeholder="请选择是否关机">
<el-option label="是" :value="1"></el-option>
<el-option label="否" :value="0"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="8" :lg="6">
<el-form-item label="机房城市" prop="city">
<el-input class="input" v-model="form.city" placeholder="机房城市">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8" :lg="6">
<el-form-item label="园区" prop="park_name">
<el-input class="input" v-model="form.park_name" placeholder="园区">
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="8" :lg="6">
<el-form-item label="机房/IDC" prop="data_center_name">
<el-input class="input" v-model="form.data_center_name" placeholder="机房/IDC">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8" :lg="6">
<el-form-item label="机架位" prop="rack_position">
<el-input class="input" v-model="form.rack_position" type="text" placeholder="请输入机架位"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="8" :lg="6">
<el-form-item label="整机SN/Se" prop="device_sn">
<el-input class="input" v-model="form.device_sn" placeholder="整机SN/Se">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8" :lg="6">
<el-form-item label="整机厂商" prop="device_manufacturer">
<el-input class="input" v-model="form.device_manufacturer" type="text" placeholder="请输入整机厂商"></el-input>
</el-form-item>
</el-col>
<el-col :span="8" :lg="6">
<el-form-item label="整机型号" prop="device_model">
<el-input class="input" v-model="form.device_model" type="text" placeholder="请输入整机型号"></el-input>
</el-form-item>
</el-col>
</el-row>
</div>
</div>
<div class="boxMain boxMainNoBorder">
<div class="title titleFlex">
<span class="name">维保部件信息</span>
<el-button type="primary" plain :size="size" icon="el-icon-Plus" @click="addOrder">添加部件信息</el-button>
</div>
<div class="boxCom">
<el-row>
<el-col :span="25" :lg="24">
<el-form-item label="验证ERP库存" prop="is_verify_erp_inventory">
<el-radio-group v-model="form.is_verify_erp_inventory">
<el-radio :value="true"></el-radio>
<el-radio :value="false"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<sc-table ref="table" :data="form.component_info" style="width: 100%;" :hidePagination="true" :hideDo="true" :hideEmpty="true" :size="size">
<sc-table-column type="index" label="序号" width="65"></sc-table-column>
<sc-table-column prop="component_serial_no" label="部件SN/Sp" :show-overflow-tooltip="true" width="160"></sc-table-column>
<sc-table-column prop="component_manufacturer" label="部件厂商" :show-overflow-tooltip="true" width="130"></sc-table-column>
<sc-table-column prop="component_model" label="部件型号" :show-overflow-tooltip="true" width="160"></sc-table-column>
<sc-table-column prop="component_pn" label="部件PN/Sp" :show-overflow-tooltip="true" width="150"></sc-table-column>
<sc-table-column prop="bd_backup_count" label="甚于BD数" :show-overflow-tooltip="true" width="120"></sc-table-column>
<sc-table-column label="操作" fixed="right" width="120">
<template #default="scope">
<el-button link type="danger" :size="size" @click="deleteOrder(scope.row,scope.$index)">删除</el-button>
</template>
</sc-table-column>
</sc-table>
</div>
</div>
<div class="btnBox">
<el-button type="primary" :size="size" @click="save" :loading="isSave">确认保存</el-button>
</div>
</el-form>
</el-main>
</el-scrollbar>
</el-container>
<info-save-dialog ref="saveDialog" v-if="dialog.save" @success="handleSaveSuccess" @closed="dialog.save=false"></info-save-dialog>
</template>
<script>
import infoSaveDialog from "@/views/order/components/infoSave";
export default {
name: "order-edit",
components:{
infoSaveDialog
},
data(){
return{
size:"small",
isSave:false,
setMap:{
maintenance_level:[],
fault_type:[],
},
form:{
customer_id:"", //
standard_model:"", //
repair_order_no:"",
maintenance_grade:"", //
maintenance_level: "", //
fault_type: "", //
fault_description: "", //
requires_shutdown: "", //
city: "", //
park_name: "", //
data_center_name: "", // /IDC
rack_position: "", //
device_sn: "", // SN
device_manufacturer: "", //
device_model: "", //
component_serial_no: "", //
component_manufacturer: "", //
component_model: "", //
component_pn: "", // PN
sla_expiration: "", // SLA
bd_backup_count: "", // BD
pe_confirmation_time: "", // PE
warranty_end_date: "", //
maintenance_plan: '', // 1-
is_verify_erp_inventory:true,
component_info:[]
},
rules:{
fault_description:[{required:true,trigger:"blur",message:"故障描述不能为空"}],
fault_type:[{required:true,trigger:"change",message:"故障类型不能为空"}],
city:[{required:true,trigger:"blur",message:"机房城市不能为空"}],
device_sn:[{required:true,trigger:"blur",message:"整机SN/Se不能为空"}],
device_manufacturer:[{required:true,trigger:"blur",message:"整机厂商不能为空"}],
device_model:[{required:true,trigger:"blur",message:"整机型号不能为空"}],
sla_expiration:[{required:true,trigger:"change",message:"SLA截止时间不能为空"}],
bd_backup_count:[{required:true,trigger:"blur",message:"剩余BD数不能为空"}],
},
dialog: {
save: false,
},
}
},
mounted() {
},
methods:{
async getSelect(name,num) {
const res = await this.$API.orders.order.maintenance.optionList.post({const_type:num});
if(res.code == 200){
this.setMap[name] = res.data;
}
},
async getCustomerSelect(name){
let params = {
field:"customer_name",
id:{
operator:"in",
value:""
}
}
const res = await this.$API.setup.customer.select.post(params);
if(res.code == 200){
this.setMap[name] = res.data;
}
},
addOrder(){
this.dialog.save = true;
this.$nextTick(() => {
this.$refs.saveDialog.open()
})
},
handleSaveSuccess(data,mode){
if(mode == 'add'){
this.form.component_info.push(data);
}
if(mode == 'edit'){
if(this.info.component_info.length>0){
this.info.component_info.forEach((item,index)=>{
if(index == data.num || (data.id && item.id == data.id)){
item.num = index;
item.component_manufacturer = data.component_manufacturer;
item.component_model = data.component_model;
item.component_pn = data.component_pn;
item.component_serial_no = data.component_serial_no;
}
})
}else{
this.info.component_info.push(data);
}
}
},
deleteOrder(row,num){
this.form.component_info.forEach((em,index)=>{
if(index === num){
this.form.component_info.splice(index,1);
}
});
},
save(){
this.$refs.form.validate(async (valid) => {
if (valid) {
this.isSave = true;
const res = await this.$API.orders.order.maintenance.add.post(this.form);
this.isSave = false;
if(res.code == 200){
this.$message.success("操作成功");
}
}
})
}
}
}
</script>
<style scoped lang="scss">
.mainView{
background: var(--el-color-white);
}
.boxMain{
border-bottom: 1px solid #f2f2f2;
padding: 10px 0 5px 0;
.title{
margin-bottom: 10px;
}
.titleFlex{
display: flex;align-items: stretch;justify-content: space-between;
}
.boxCom{
.el-row{
.el-col{
padding: 0 10px;
::v-deep .input{
width: 100%;
}
}
}
}
}
.boxMainNoBorder{
border-bottom: 0;
}
.btnBox{
margin-top: 15px;
text-align: left;
padding: 0 10px;
}
</style>

View File

@ -232,7 +232,7 @@ export default {
//
table_edit(row){
eventBus.$emit('tagClose','/order/create-order',{id:row.id});
eventBus.$emit('tagClose','/order/order-edit',{id:row.id});
},
//
table_show(row){

View File

@ -9,7 +9,7 @@
</div>
</el-header>
<el-main class="serveMain" v-if="routerText===1">
<scTable v-loading="tableLoading" element-loading-text="加载中..." height="100%" ref="table" :data="list.data" :size="size" hideDo>
<scTable v-loading="tableLoading" element-loading-text="加载中..." height="100%" ref="table" :apiObj="list.apiObj" :column="list.column" :size="size" hideDo>
<el-table-column type="index" label="序号"></el-table-column>
<template v-for="(item,index) in list.column" :key="index">
<el-table-column :label="item.label" :prop="item.prop" :width="item.width" show-overflow-tooltip>
@ -37,7 +37,9 @@
</scTable>
</el-main>
<el-main class="serveMain" v-if="routerText===2">
<feedbackDetail></feedbackDetail>
<el-scrollbar>
<feedbackDetail ref="infoDetail"></feedbackDetail>
</el-scrollbar>
</el-main>
</el-container>
</template>
@ -62,6 +64,7 @@ export default {
},
tableLoading:false,
list:{
apiObj:this.$API.customer.orderMyList,
column:[
{label:'创建时间',prop:'created_at',width:160,show: true},
{label:'机器序列号',prop:'serial_number',width:200,show: true},
@ -71,7 +74,6 @@ export default {
{label:'提交账号',prop:'creator_name',width:160,show: true},
{label:'备注',prop:'remark',show: true},
],
data:[]
},
routerParams:{}
@ -79,7 +81,7 @@ export default {
},
mounted() {
this.getTypeList();
this.getMyList();
// this.getMyList();
},
methods:{
async getTypeList() {
@ -100,6 +102,7 @@ export default {
this.routerText = item.value;
const result = this.title.slice(0,this.title.findIndex(em=> em.value === item.value)+1);
this.title = result;
},
table_show(row){
this.routerParams = row;
@ -108,6 +111,10 @@ export default {
if(valueS.indexOf(2) ===-1){
this.title.push({name:"反馈详情",value:2})
}
this.$nextTick(()=>{
this.$refs.infoDetail.setInfoParams(row);
})
},
table_del(row){
let params = {

View File

@ -1,69 +1,125 @@
<template>
<div class="serveMain">
<div class="serveMain" v-loading="loading" element-loading-text="加载中...">
<div class="feedHeader">
<span class="name">问题描述</span>
<span class="date">2024-10-23 11:02:44</span>
<span class="date">{{info.created_at}}</span>
</div>
<div class="describe">这是一个问题描述这是一个问题描述这是一个问题描述</div>
<div class="describe">{{info.remark}}</div>
<div class="attachment">
<span class="imgView">
<el-image class="img" src="https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"></el-image>
</span>
<span class="imgView">
<el-image class="img" src="https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"></el-image>
<span class="imgView" v-for="(item,index) in info.attachment" :key="index">
<el-image class="img" preview-teleported :preview-src-list="[item]" :src="item"></el-image>
</span>
</div>
<div v-for="(item,index) in info.reply_item" :key="index">
<div class="intelligenceCustomer formInputText">
<div class="title">问题回复</div>
<div class="cardView">
<div class="avatar">
<el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"></el-avatar>
<el-avatar :src="item.user_info && item.user_info.avatar"></el-avatar>
</div>
<div class="rightView">
<div class="userHeader">
<span class="name">AA工程师</span>
<span class="time">2024-10-23 11:02:44</span>
<span class="name">{{item.user_info && item.user_info.name===''?'匿名':item.user_info.name}}</span>
<span class="time">{{item.created_at}}</span>
</div>
<div class="text">问题回复一次问题回复一次已为您分配工程师问题回复一次</div>
<div class="text" v-html="item.remark"></div>
</div>
</div>
<div class="fileList">
<div class="imgListSpam" v-for="(em,ind) in item.attachment" :key="ind">
<span class="imgSpan" v-if="['png','jpg','jpeg','gif'].indexOf(em.type) !==-1">
<el-image class="img" :src="em.url" preview-teleported :preview-src-list="[em.url]"></el-image>
</span>
</div>
</div>
<div class="fileList fileListMargin">
<div class="fileListSpam" v-for="(em,ind) in item.attachment" :key="ind">
<span class="fileSpan" v-if="['png','jpg','jpeg','gif'].indexOf(em.type) ===-1" @click="linkFile(em)">
<fileType size="22px" :fileType="em.type" />
<span class="name">{{em.name}}</span>
</span>
</div>
</div>
</div>
<div class="operateView">
</div>
<div class="operateView" v-if="saveShow">
<div class="uploadList">
<uploadListFile></uploadListFile>
<uploadListFile :list="submitParams.attachment" @uploadFileSuccess="uploadFileSuccess"></uploadListFile>
</div>
<el-input class="formInputText" type="textarea" :rows="3" placeholder="请描述您的问题"></el-input>
<el-input class="formInputText" v-model="submitParams.remark" type="textarea" :rows="4" resize="none" placeholder="请描述您的问题"></el-input>
</div>
<div class="saveView">
<el-button :size="size" type="primary">{{saveShow?'提交':'继续提问'}}</el-button>
<el-button :size="size" type="primary" @click="saveShow=true" v-if="!saveShow">继续提问</el-button>
<el-button :size="size" type="primary" @click="save" v-else> </el-button>
</div>
</div>
</template>
<script>
import fileType from "@/views/docsManager/fileType"
import uploadListFile from "@/views/personalCenter/components/uploadListFile";
export default {
name: "feedbackDetail",
components:{
uploadListFile
uploadListFile,
fileType
},
data(){
return{
size:"small",
loading:false,
params:{},
saveShow:false,
info:{},
submitParams:{
work_order_id:"",
attachment:[],
remark:"",
}
}
},
mounted() {
},
methods:{
setInfoParams(params){
this.params = params;
this.submitParams.work_order_id = params.id;
this.getInfo();
},
async getInfo() {
let params = {
work_order_id:this.params.id
}
this.loading = true;
const res = await this.$API.customer.workOrderInfo.post(params);
this.loading = false;
if(res.code == 200){
this.info = res.data;
}
},
uploadFileSuccess(fileList){
this.submitParams.attachment = fileList;
},
linkFile(em){
window.location.href = em.url;
},
async save() {
const res = await this.$API.customer.replyOrder.post(this.submitParams);
if(res.code == 200){
this.submitParams.attachment = [];
this.submitParams.remark = "";
await this.getInfo();
}
}
}
}
</script>
<style scoped lang="scss">
.serveMain{
min-height: 100%;
.feedHeader{
display: flex;
align-items: center;
@ -75,14 +131,16 @@ export default {
}
.attachment{
.imgView{
.img{width: 80px;height: 80px;border-radius: 4px;margin: 0 4px 4px 0;}
.img{width: 80px;height: 80px;border-radius: 4px;margin: 0 6px 6px 0;}
}
}
.backShow{
background: #f5f5f5;
}
.intelligenceCustomer{
background: #f5f5f5;
border-radius: 4px;
padding: 10px;
margin: 10px 0;
border-bottom: 1px solid #f5f5f5;
.title{color: #333;font-weight: 500;margin-bottom: 10px;}
.cardView{
display: flex;
@ -93,8 +151,32 @@ export default {
margin-bottom: 5px;font-size: 12px;color: #888;
.time{margin-left: 5px;}
}
.text{line-height: 20px;}
}
}
.fileList{
margin-top: 10px;
margin-left: 50px;
display: flex;
align-items: center;
.imgFloat{
float: left;
}
.imgSpan{
.img{
width: 60px;height: 60px;border-radius: 4px;margin: 0 6px 6px 0;
}
}
.fileSpan{
display: flex;align-items: center;margin:0 10px 8px 0;
background: #F6F6F6;
padding: 4px 30px 4px 10px;
cursor: pointer;
}
}
.fileListMargin{
margin-top: 0;
}
}
.operateView{
margin-top: 15px;

View File

@ -20,7 +20,7 @@
<div class="fileItem" v-for="(item,index) in imageList" :key="index">
<fileType size="22px" :fileType="item.type" />
{{item.name}}
<span class="btnView" @click="deleteClick(item)"><el-icon size="14"><el-icon-Close/></el-icon></span>
<span class="btnView" @click="deleteClick(index)"><el-icon size="14"><el-icon-Close/></el-icon></span>
</div>
</div>
</div>
@ -43,17 +43,19 @@ export default {
type:Number,
}
},
watch:{
list:{
handler(val){
this.imageList = val;
},
deep:true,
immediate:true
}
},
data(){
return{
size:'small',
imageList:[
{name:'测试文件.png',type:'png'},
{name:'测试文件.doc',type:'png'},
{name:'测试文件.doc',type:'png'},
{name:'测试文件.doc',type:'doc'},
{name:'测试文件.doc',type:'doc'},
{name:'测试文件.doc',type:'doc'},
],
imageList:[],
oss:{
host:''
},
@ -101,16 +103,20 @@ export default {
name:fileName,
type:fileType
};
console.log(imageUrl,799)
this.imageList.push(imageUrl)
this.imageList.push(imageUrl);
this.$emit('uploadFileSuccess',this.imageList);
},
//
handleError(){
this.$message.warning('上传失败请重新上传');
},
deleteClick(item){
console.log(item,233)
deleteClick(num){
this.imageList.forEach((item,index)=>{
if(index == num){
this.imageList.splice(index,1);
}
})
this.$emit('uploadFileSuccess',this.imageList);
}
}
}

View File

@ -4,17 +4,26 @@
<el-main class="serveMain">
<div class="searchMain searchMainNoTop">
<div class="searchItem">
<div class="name">序列号</div> <el-input type="text" :size="size" placeholder="请输入序列号"></el-input>
<div class="name">序列号</div> <el-input type="text" v-model="params.serial_number.value" :size="size" clearable placeholder="请输入序列号"></el-input>
</div>
<div class="searchItem searchBtn">
<el-button :size="size" type="primary" icon="el-icon-search" @click="upSearch">查询</el-button>
</div>
</div>
<div class="mainTable">
<scTable height="100%" class="serveTable" ref="serveTable" :data="list.data" :column="list.column" stripe :size="size">
<scTable class="serveTable" ref="table" :apiObj="list.apiObj" :column="list.column" :params="params" stripe :size="size">
<el-table-column type="index" label="序号"></el-table-column>
<template v-for="(item,index) in list.column" :key="index">
<el-table-column :label="item.label" :prop="item.prop" :width="item.width" show-overflow-tooltip></el-table-column>
<el-table-column :label="item.label" :prop="item.prop" :width="item.width" show-overflow-tooltip>
<template #default="scope">
<span v-if="item.prop === 'business_status'">
<span v-for="(em,index) in setMap.statusList" :key="index">
<span :style="{color:em.value==1?`var(--el-order-color-1)`:em.value==2?`var(--el-order-color-2)`:em.value==3?`var(--el-order-color-3)`:em.value==4?`var(--el-order-color-4)`:`var(--el-order-color-100)`}" v-if="em.value === scope.row[item.prop]">{{em.label}}</span>
</span>
</span>
<span v-else>{{scope.row[item.prop]}}</span>
</template>
</el-table-column>
</template>
</scTable>
</div>
@ -28,50 +37,44 @@ export default {
data(){
return{
size:'small',
setMap:{
statusList:[]
},
list:{
data:[
{created_at:'2024-11-23 10:34:56',number:"XW1.5-1U-PWR-XW-01",name:"F62.32.C"},
{created_at:'2024-11-23 10:34:56',number:"XW1.5-1U-PWR-XW-01",name:"F62.32.C"},
{created_at:'2024-11-23 10:34:56',number:"XW1.5-1U-PWR-XW-01",name:"F62.32.C"},
{created_at:'2024-11-23 10:34:56',number:"XW1.5-1U-PWR-XW-01",name:"F62.32.C"},
{created_at:'2024-11-23 10:34:56',number:"XW1.5-1U-PWR-XW-01",name:"F62.32.C"},
{created_at:'2024-11-23 10:34:56',number:"XW1.5-1U-PWR-XW-01",name:"F62.32.C"},
{created_at:'2024-11-23 10:34:56',number:"XW1.5-1U-PWR-XW-01",name:"F62.32.C"},
{created_at:'2024-11-23 10:34:56',number:"XW1.5-1U-PWR-XW-01",name:"F62.32.C"},
{created_at:'2024-11-23 10:34:56',number:"XW1.5-1U-PWR-XW-01",name:"F62.32.C"},
{created_at:'2024-11-23 10:34:56',number:"XW1.5-1U-PWR-XW-01",name:"F62.32.C"},
{created_at:'2024-11-23 10:34:56',number:"XW1.5-1U-PWR-XW-01",name:"F62.32.C"},
{created_at:'2024-11-23 10:34:56',number:"XW1.5-1U-PWR-XW-01",name:"F62.32.C"},
{created_at:'2024-11-23 10:34:56',number:"XW1.5-1U-PWR-XW-01",name:"F62.32.C"},
{created_at:'2024-11-23 10:34:56',number:"XW1.5-1U-PWR-XW-01",name:"F62.32.C"},
{created_at:'2024-11-23 10:34:56',number:"XW1.5-1U-PWR-XW-01",name:"F62.32.C"},
{created_at:'2024-11-23 10:34:56',number:"XW1.5-1U-PWR-XW-01",name:"F62.32.C"},
{created_at:'2024-11-23 10:34:56',number:"XW1.5-1U-PWR-XW-01",name:"F62.32.C"},
{created_at:'2024-11-23 10:34:56',number:"XW1.5-1U-PWR-XW-01",name:"F62.32.C"},
{created_at:'2024-11-23 10:34:56',number:"XW1.5-1U-PWR-XW-01",name:"F62.32.C"},
{created_at:'2024-11-23 10:34:56',number:"XW1.5-1U-PWR-XW-01",name:"F62.32.C"},
],
apiObj: this.$API.customer.periodQuery,
column:[
{label:'创建时间',prop:'created_at',width:160,show: true},
{label:'序列号',prop:'number',width:300,show: true},
{label:'部件名称',prop:'name',show: true},
]
{label:'序列号',prop:'serial_number',width:160,hide: false},
{label:'工单号',prop:'repair_order_no',width:200,hide: false},
{label:'业务状态',prop:'business_status',width:120,hide: false},
{label:'维保到期日期',prop:'warranty_end_date',width:200,hide: false},
{label:'客户名称',prop:'customer_name',hide: false},
],
},
params:{
serial_number:{
operator:"like",
value:""
}
}
}
},
mounted() {
this.getStatusList();
},
methods:{
upSearch(){
this.$refs.table.upData(this.params);
},
async getStatusList() {
const res = await this.$API.customer.periodQueryStatusList.post();
if(res.code === 200){
this.setMap.statusList = res.data;
}
}
}
}
</script>
<style scoped lang="scss">
//.serveTable{
// height: 100%;
//}
</style>

View File

@ -0,0 +1,226 @@
<template>
<el-container class="mainBox mainHeaderNoBorderPadding">
<div class="header">问题详情</div>
<div class="content">
<el-main class="nopadding" v-loading="loading" element-loading-text="加载中...">
<el-scrollbar>
<div class="faqMain">
<div class="mainBack">
<div class="describe">
<span class="name">机器序列号</span>
<span class="text">{{info.serial_number}}</span>
</div>
<div class="describe">
<span class="name"> </span>
<span class="text">{{info.purchase_time}}</span>
</div>
<div class="describe">
<span class="name"> </span>
<span class="text">{{info.remark}}</span>
</div>
<div class="imgList">
<el-image class="img" v-for="(em,index) in info.attachment" :key="index" preview-teleported :preview-src-list="[em]" :src="em" fit="cover"></el-image>
</div>
</div>
<div class="faqCardBox" v-for="(item,index) in info.reply_item" :key="index">
<div class="leftView avatar">
<el-avatar :size="36" :src="item.user_info && item.user_info.avatar" fit="contain">
<img src="https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png"/>
</el-avatar>
</div>
<div class="rightView">
<div class="msgTitle">
{{item.user_info && item.user_info.name?item.user_info.name:'匿名'}}
<span class="time">{{item.created_at}}</span>
</div>
<div class="textCom">
<div v-html="item.remark"></div>
</div>
<div class="fileList">
<div class="imgListSpam" v-for="(em,ind) in item.attachment" :key="ind">
<span class="imgSpan" v-if="['png','jpg','jpeg','gif'].indexOf(em.type) !==-1">
<el-image class="img" :src="em.url" preview-teleported :preview-src-list="[em.url]"></el-image>
</span>
</div>
</div>
<div class="fileList fileListMargin">
<div class="fileListSpam" v-for="(em,ind) in item.attachment" :key="ind">
<span class="fileSpan" v-if="['png','jpg','jpeg','gif'].indexOf(em.type) ===-1" @click="linkFile(em)">
<fileType size="22px" :fileType="em.type" />
<span class="name">{{em.name}}</span>
</span>
</div>
</div>
</div>
</div>
<div class="saveView">
<div class="operateView">
<div class="uploadList">
<uploadListFile :list="submitParams.attachment" @uploadFileSuccess="uploadFileSuccess"></uploadListFile>
</div>
<el-input class="formInputText" v-model="submitParams.remark" type="textarea" :rows="4" resize="none" placeholder="请描述您的问题"></el-input>
</div>
<div class="saveBtn">
<el-button :size="size" type="primary" @click="save"> </el-button>
</div>
</div>
</div>
</el-scrollbar>
</el-main>
</div>
</el-container>
</template>
<script>
import fileType from "@/views/docsManager/fileType"
import uploadListFile from "@/views/personalCenter/components/uploadListFile";
export default {
name: "faq-info",
components:{
fileType,
uploadListFile
},
data(){
return{
size:"small",
loading:false,
id: this.$route.query.id,
info:{},
submitParams:{
work_order_id:this.$route.query.id,
attachment:[],
remark:"",
}
}
},
mounted() {
this.getInfo();
},
methods:{
async getInfo() {
let params = {
work_order_id:Number(this.id)
}
this.loading = true;
const res = await this.$API.customer.workOrderInfo.post(params);
this.loading = false;
if(res.code == 200){
this.info = res.data;
}
},
uploadFileSuccess(fileList){
this.submitParams.attachment = fileList;
},
linkFile(em){
window.location.href = em.url;
},
async save() {
const res = await this.$API.customer.replyOrder.post(this.submitParams);
if (res.code == 200) {
this.submitParams.attachment = [];
this.submitParams.remark = "";
await this.getInfo();
}
}
}
}
</script>
<style scoped lang="scss">
.mainBox{
display: flex;flex-direction: column;
.header{
flex-basis: 48px;
display: flex;align-items: center;justify-content: flex-start;
font-size: 14px;font-weight: bold;
border-bottom: 1px solid #f4f4f4;
margin: 0 -10px;
padding: 0 10px;
}
.content{
flex: 1;
overflow: hidden;
padding: 10px 0;
}
}
.faqMain{
.mainBack{
background: #f6f6f6;
padding: 10px;
border-radius: 6px;
position: relative;
.describe{
margin-bottom: 10px;
.name{
color: #222;
margin-right: 15px;
}
.text{
color: #222;font-weight: 500;
}
.time{
color: #888888;
margin-left: 10px;
}
}
.imgList{
display: flex;align-items: center;flex-wrap: wrap;
.img{
width: 88px;
height: 88px;
border-radius: 4px;
margin-right: 10px;
}
}
}
.faqCardBox{
border-bottom: 1px solid #f4f4f4;
padding: 15px 0;
display: flex;align-items: flex-start;
.avatar{
margin-right: 8px;
}
.rightView{
.msgTitle{
color: #555;
.time{
margin-left: 8px;
}
}
.textCom{
margin-top: 4px;
}
.fileList{
margin-top: 10px;
display: flex;
align-items: center;
.imgFloat{
float: left;
}
.imgSpan{
.img{
width: 60px;height: 60px;border-radius: 4px;margin: 0 6px 6px 0;
}
}
.fileSpan{
display: flex;align-items: center;margin:0 10px 8px 0;
background: #F6F6F6;
padding: 4px 30px 4px 10px;
cursor: pointer;
}
}
.fileListMargin{
margin-top: 0;
}
}
}
}
.saveView{
width: 800px;
margin-top: 20px;
.saveBtn{
margin-top: 20px;
}
}
</style>

View File

@ -2,38 +2,36 @@
<el-container class="mainBox mainHeaderNoBorderPadding">
<div class="header">问题反馈</div>
<div class="content">
<el-main class="nopadding">
<div class="faqMain">
<div class="mainBack">
<div class="describe">
<span class="name">问题描述</span>
<span class="text">这是一个问题描述这是一个问题描述这是一个问题描述</span>
</div>
<div class="imgList">
<el-image class="img" v-for="(em,index) in imgList" :key="index" preview-teleported :preview-src-list="[em.url]" :src="em.url" fit="cover"></el-image>
</div>
<div class="btnBox">
<el-button :size="size" type="primary">回复</el-button>
</div>
</div>
<div class="faqCardBox" v-for="(item,index) in cardList" :key="index">
<div class="leftView avatar">
<el-avatar :size="36" :src="item.avatar" fit="contain">
<img src="https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png"/>
</el-avatar>
</div>
<div class="rightView">
<div class="msgTitle">
{{item.name}}
<span class="time">{{item.time}}</span>
</div>
<div class="textCom">
<div v-html="item.message"></div>
</div>
</div>
</div>
</div>
</el-main>
<scTable ref="table" :apiObj="list.apiObj" :column="list.column" row-key="id" :size="size" hideDo>
<el-table-column type="index" label="序号"></el-table-column>
<template v-for="(item,index) in list.column" :key="index">
<el-table-column :label="item.label" :prop="item.prop" :width="item.width" show-overflow-tooltip>
<template #default="scope">
<span v-if="item.prop === 'type'">
<span v-for="(em,ind) in setMap.typeList" :key="ind">
<span v-if="em.value === scope.row[item.prop]">{{em.label}}</span>
</span>
</span>
<span v-else-if="item.prop === 'attachment'">
<span v-for="(em,ind) in scope.row[item.prop]" :key="ind">
<el-image class="tableImages" :src="em" preview-teleported :preview-src-list="[em]" style="width: 22px;height: 22px;margin: 0 4px;border-radius: 3px;">
<template #error>
<el-icon size="18"><el-icon-Picture/></el-icon>
</template>
</el-image>
</span>
</span>
<span v-else>{{scope.row[item.prop]}}</span>
</template>
</el-table-column>
</template>
<el-table-column label="操作" fixed="right" align="center" width="150">
<template #default="scope">
<el-button type="primary" link @click="table_show(scope.row, 'see')" :size="size">查看</el-button>
<el-button type="danger" link @click="table_del(scope.row, 'delete')" :size="size">删除</el-button>
</template>
</el-table-column>
</scTable>
</div>
</el-container>
</template>
@ -47,48 +45,21 @@ export default {
data(){
return{
size:"small",
imgList:[
{url:'https://dm-auto.oss-cn-shanghai.aliyuncs.com/xw_cloud/8bcb8f0a-878d-437f-b583-d574261fbff1.jpg'},
{url:'https://dm-auto.oss-cn-shanghai.aliyuncs.com/xw_cloud/fca9e7f6-0cb4-434f-9c88-50b8fe2e6580.jpg'}
setMap:{
typeList:[],
},
list: {
apiObj: this.$API.customer.orderList,
column: [
{label:'创建时间',prop:'created_at',width:160,show: true},
{label:'机器序列号',prop:'serial_number',width:200,show: true},
{label:'问题类型',prop:'type',width:180,show: true},
{label:'购买时间',prop:'purchase_time',width:160,show: true},
{label:'附件',prop:'attachment',width:120,show: true},
{label:'提交账号',prop:'creator_name',width:160,show: true},
{label:'备注',prop:'remark',show: true},
],
cardList:[
{
avatar:'https://dm-auto.oss-cn-shanghai.aliyuncs.com/xw_cloud/67b071a4e2a5430ef06fce968332c86fd596a1ec.jpg',
name:"智能客服",
time:"11月11号 13:24",
message:"工程师将为您处理"
},
{
avatar:'https://dm-auto.oss-cn-shanghai.aliyuncs.com/xw_cloud/0535000066601D782037570F58C33857.jpeg',
name:"售后客服",
time:"06月21号 13:24",
message:"马上为您处理"
},
{
avatar:'https://dm-auto.oss-cn-shanghai.aliyuncs.com/xw_cloud/67b071a4e2a5430ef06fce968332c86fd596a1ec.jpg',
name:"智能客服",
time:"11月11号 13:24",
message:"工程师将为您处理"
},
{
avatar:'https://dm-auto.oss-cn-shanghai.aliyuncs.com/xw_cloud/0535000066601D782037570F58C33857.jpeg',
name:"售后客服",
time:"06月21号 13:24",
message:"马上为您处理"
},
{
avatar:'https://dm-auto.oss-cn-shanghai.aliyuncs.com/xw_cloud/67b071a4e2a5430ef06fce968332c86fd596a1ec.jpg',
name:"智能客服",
time:"11月11号 13:24",
message:"工程师将为您处理"
},
{
avatar:'https://dm-auto.oss-cn-shanghai.aliyuncs.com/xw_cloud/0535000066601D782037570F58C33857.jpeg',
name:"售后客服",
time:"06月21号 13:24",
message:"马上为您处理"
}
]
}
},
created() {
@ -98,7 +69,29 @@ export default {
},
methods:{
table_show(row){
this.$router.push({
path: '/service/faq-info',
query: {
id: row.id,
name:row.name
}
})
},
table_del(row){
let params = {
ids:[row.id]
}
this.$confirm(`确定删除序列号 ${row.serial_number} 吗?`, '提示', {
type: 'warning'
}).then(async () => {
const res = await this.$API.customer.orderDelete.post(params);
if(res.code == 200){
this.$message.success("删除成功");
this.$refs.table.refresh();
}
}).catch(()=>{})
}
}
}
</script>
@ -172,4 +165,7 @@ export default {
}
}
}
.tableImages{
margin-top: 4px;
}
</style>

View File

@ -407,7 +407,6 @@ export default {
linkFile(em){
window.location.href = em.file;
},
handleScroll(event){
const { scrollTop } = event;
if(scrollTop === 0 && this.msgList.length>0 && this.page >1){

View File

@ -1,7 +1,18 @@
<template>
<el-container class="mainNoBack userBox">
<el-main>
查询记录
<el-container class="mainBox mainBoxHeaderNoBorder">
<el-main class="nopadding">
<div class="searchMain">
<scSearch ref="scSearch" :searchList="searchList" @fetchSelectData="getSelectData"></scSearch>
<div class="searchItem searchBtn">
<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>
<scTable ref="table" :apiObj="list.apiObj" :column="list.column" row-key="id" stripe :size="size" @selection-change="selectionChange">
<el-table-column type="selection" align="center" width="40"></el-table-column>
<sc-table-column label="序号" align="center" type="index"></sc-table-column>
</scTable>
</el-main>
</el-container>
</template>
@ -11,14 +22,50 @@ export default {
name: "queryRecord",
data(){
return{
size:'small',
dialog: {
save: false,
show: false,
},
list: {
apiObj: this.$API.customer.queryRecordList,
column: [],
},
selection: [],
exportShow:false,
searchShow:false,
searchList:[
{name:'查询时间',type:'date',code:'created_at',show: true},
{name:'查询类型',type:'select',data:[],code:'updated_at',show: true},
{name:'用户名',type:'text',code:'bom_version',placeholder:"请输入用户名",show:true},
{name:'关键字',type:'text',code:['bom_abbreviation'],keyword:true,show:true},
],
params: {},
}
},
mounted() {
},
methods:{
//
selectionChange(selection){
this.selection = selection;
},
getSelectData(item){
let {params} = item;
this.params = params;
},
upSearch(){
this.$refs.table.upData(this.params);
},
reset(){
this.params = {};
this.$refs.scSearch.reload();
this.$refs.table.reload();
},
handleSaveSuccess(){
this.$refs.table.refresh();
},
}
}
</script>

View File

@ -79,7 +79,7 @@ export default {
}
},
mounted() {
console.log(32423)
},
methods: {
searchShowClick(){