Merge pull request 'dd' (#133) from dd into master

Reviewed-on: http://git.feashow.cn/feashow/SmartOpsWeb/pulls/133
This commit is contained in:
2024-10-06 11:26:18 +00:00
8 changed files with 171 additions and 130 deletions

View File

@@ -20,9 +20,9 @@ steps:
- npm -v - npm -v
- mkdir -p ./node_modules - mkdir -p ./node_modules
- export NODE_MODULES_PATH=`pwd`/node_modules - export NODE_MODULES_PATH=`pwd`/node_modules
# - npm config set registry https://registry.npmmirror.com # - npm config set registry https://registry.npmmirror.com
- set NODE_OPTIONS=--openssl-legacy-provider # - set NODE_OPTIONS=--openssl-legacy-provider
# - npm install # - npm install
- npm run build - npm run build
- echo $NODE_MODULES_PATH - echo $NODE_MODULES_PATH
- cp -r dist /app/build/$DRONE_REPO_NAME - cp -r dist /app/build/$DRONE_REPO_NAME

View File

@@ -12,5 +12,5 @@ docker rmi smartopsweb:latest
echo '----build image start----' echo '----build image start----'
docker build -t smartopsweb:latest . docker build -t smartopsweb:latest .
echo '----build image success----' echo '----build image success----'
docker run --name smartopsweb -d -p 28081:80 smartopsweb:latest docker run --name smartopsweb --restart=always -d -p 28081:80 smartopsweb:latest

View File

@@ -1,11 +1,16 @@
<script setup> <script setup>
import LiveCallItem from '@/components/liveCall/LiveCallItem.vue' import LiveCallItem from '@/components/liveCall/LiveCallItem.vue'
import {getHistoryCallContent} from '@/api/workbench'; import {getHistoryCallContent} from '@/api/workbench';
import {ElMessage} from "element-plus";
const dialogVisible = ref(false); const dialogVisible = ref(false);
const recordLeftRef = ref(null); const recordLeftRef = ref(null);
const emit = defineEmits(['update:value'])
const props = defineProps({ const props = defineProps({
rowData: String value: {
type:String,
default:''
}
}) })
const open = (row) => { const open = (row) => {
@@ -13,14 +18,20 @@ const open = (row) => {
}; };
const leftHeadData = ref({ const leftHeadData = ref({
username: '张三', // username: '张三',
phone: '13546812315', // phone: '13546812315',
orderName: '张三工单', // orderName: '张三工单',
})
const detailLoading=ref(false)
const recordLeftObj = ref({});
const _value = computed({
get() {
return props.value;
},
set(val) {
emit("update:value", val);
}
}) })
const recordLeftObj = ref({
content: []
});
const convertArrayToMap=(array)=> { const convertArrayToMap=(array)=> {
const map = new Map(); const map = new Map();
array.forEach(item => { array.forEach(item => {
@@ -35,22 +46,33 @@ const convertArrayToMap=(array)=> {
return map; return map;
} }
watch(() => props.rowData, async (newVal) => { watch(() => props.value, async (newVal) => {
recordLeftObj.value.content = [] if(newVal){
// let map1 = new Map()
await getHistoryCallContent(newVal).then(res => { getHistoryDetail(newVal)
res.data?.forEach(item => { }
item.textVoList = convertArrayToMap(item.textVoList);
})
recordLeftObj.value = res.data
// console.info("🚀 ~method:res.data -----", res.data)
if (res.data && res.data.length > 0) {
leftHeadData.value.username = res.data[0].callIdNumber || '--';
leftHeadData.value.phone = res.data[0].callPhone || '--';
leftHeadData.value.orderName = res.data[0].orderName || '--';
}
})
}) })
const getHistoryDetail=(newVal)=>{
detailLoading.value=true
getHistoryCallContent(newVal).then(res => {
if (res.code === 1000) {
detailLoading.value=false
res.data?.forEach(item => {
if( item.textVoList&& item.textVoList.length>0){
item.textVoList = convertArrayToMap(item.textVoList);
}
})
recordLeftObj.value = res.data
if (res.data && res.data.length > 0) {
leftHeadData.value.username = res.data[0].callIdNumber || '--';
leftHeadData.value.phone = res.data[0].callPhone || '--';
leftHeadData.value.orderName = res.data[0].orderName || '--';
}
} else {
ElMessage.error(res.msg);
}
})
}
const scrollToBottom = (scrollbarRef) => { const scrollToBottom = (scrollbarRef) => {
if (scrollbarRef) { if (scrollbarRef) {
@@ -68,8 +90,8 @@ defineExpose({
</script> </script>
<template> <template>
<el-dialog v-model="dialogVisible" title="历史通话记录" width="600" class="box"> <el-dialog v-model="dialogVisible" title="历史通话记录" width="700" class="box">
<LiveCallItem ref="recordLeftRef" :recordArray="recordLeftObj" :headData="leftHeadData" style="width: 100%;"/> <LiveCallItem ref="recordLeftRef" :recordArray="recordLeftObj" :headData="leftHeadData" style="width: 100%;" :detailLoading="detailLoading"/>
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
<el-button type="primary" @click="dialogVisible = false"> <el-button type="primary" @click="dialogVisible = false">
@@ -82,6 +104,6 @@ defineExpose({
<style> <style>
.box { .box {
height: 68vh; /*height: 68vh;*/
} }
</style> </style>

View File

@@ -1,11 +1,13 @@
<template> <template>
<div class="live-call"> <div class="live-call" v-loading="detailLoading">
<div class="header"> <div class="header">
<div> <div>
<span style="margin-right: 20px">{{ headData.username }}</span> <span style="margin-right: 20px">{{ headData.username }}</span>
<span>电话号码{{ headData.phone }}</span>
</div> </div>
<div><span>工单名称{{ headData.orderName }}</span></div> <div>
<span>电话号码{{ headData.phone ||'--'}}</span>
</div>
<div><span>工单名称{{ headData.orderName ||'--'}}</span></div>
</div> </div>
<el-scrollbar ref="scrollbarRef" class="scrollbar"> <el-scrollbar ref="scrollbarRef" class="scrollbar">
<div class="chat-content" ref="innerRef"> <div class="chat-content" ref="innerRef">
@@ -31,8 +33,10 @@
</div> </div>
</div> </div>
</div> </div>
<el-divider border-style="dotted" v-if="item">一轮通话结束~~</el-divider> <el-divider border-style="dotted" v-if="item.textVoList&&item.textVoList.length>0">一轮通话结束~~</el-divider>
</div> </div>
<!-- <el-empty description="暂无通话记录~" v-if="recordArray"/>-->
</div> </div>
</el-scrollbar> </el-scrollbar>
</div> </div>
@@ -51,10 +55,17 @@ const props = defineProps({
type: Object, type: Object,
default: {} default: {}
}, },
detailLoading: {
type: Boolean,
default: false
},
}) })
const getScrollbarRef = () => { const getScrollbarRef = () => {
return scrollbarRef.value return scrollbarRef.value
} }
watch(() => props.detailLoading, (newVal) => {
props.detailLoading=newVal
})
defineExpose({ defineExpose({
getScrollbarRef getScrollbarRef
}) })
@@ -62,7 +73,7 @@ defineExpose({
<style lang="scss" scoped> <style lang="scss" scoped>
.live-call { .live-call {
width: 48%; width: 50%;
height: 47vh; height: 47vh;
margin-bottom: 20px; margin-bottom: 20px;
overflow: hidden; overflow: hidden;

View File

@@ -2,10 +2,11 @@
<div class="live-call"> <div class="live-call">
<div class="header"> <div class="header">
<div> <div>
<span style="margin-right: 20px">{{ headData.username }}</span> <span style="margin-right: 20px">姓名{{ recordObj.name ||'--'}}</span>
<span>{{ headData.phone }}</span> <span>电话号码{{ recordObj.phone ||'--'}}</span>
</div> </div>
<div><span>工单名称{{ headData.orderName }}</span></div> <div><span>工单名称{{ recordObj.orderName||'--' }}</span></div>
<div><span>{{ recordObj.type=='1'?'线路一':recordObj.type=='2'?'线路二':'' }}</span></div>
</div> </div>
<el-scrollbar ref="scrollbarRef" class="scrollbar"> <el-scrollbar ref="scrollbarRef" class="scrollbar">
<div class="chat-content" ref="innerRef"> <div class="chat-content" ref="innerRef">
@@ -14,7 +15,8 @@
<!-- 我的 --> <!-- 我的 -->
<div v-if="item.speaker==0" class="word-my"> <div v-if="item.speaker==0" class="word-my">
<div class="info"> <div class="info">
<p class="name">{{ item.speaker==0?headData.username:'AI助手' }} </p> <!-- <p class="name">{{ item.speaker==0?recordObj.name:'AI助手' }} </p>-->
<p class="name">{{ item.speaker==0?item.callIdNumber:'AI助手' }} </p>
<div class="info-content">{{ item.message }}</div> <div class="info-content">{{ item.message }}</div>
</div> </div>
<el-avatar text="我"/> <el-avatar text="我"/>
@@ -23,11 +25,15 @@
<div v-else class="word"> <div v-else class="word">
<el-avatar text="对方"/> <el-avatar text="对方"/>
<div class="info"> <div class="info">
<p class="name">{{ item.speaker==0?headData.username:'AI助手' }} </p> <p class="name">{{ item.speaker==0?item.callIdNumber:'AI助手' }} </p>
<div class="info-content">{{ item.message }}</div> <div class="info-content">{{ item.message }}</div>
</div> </div>
</div> </div>
</div> </div>
<!-- <el-divider border-style="dotted" v-if="handleShowDeadLine(recordObj)">一轮通话结束~~</el-divider>-->
<!-- <el-empty description="暂无通话记录~" v-else/>-->
</div> </div>
</el-scrollbar> </el-scrollbar>
</div> </div>
@@ -46,9 +52,28 @@ const props = defineProps({
default: {} default: {}
}, },
}) })
const getScrollbarRef=()=>{ const getScrollbarRef=()=>{
return scrollbarRef.value return scrollbarRef.value
} }
const handleShowDeadLine=(recordObj)=>{
console.info("🚀 ~method:'recordObj' -----", recordObj)
let flag=false
if(recordObj.content&&recordObj.content.length>1){
let indices = recordObj.content.reduce(function (r, v, i) {
return r.concat(v === 'a' ? i : []);
}, []);
console.log(indices);
recordObj.content.forEach((item,index)=>{
console.info("🚀 ~method:.callIdNumber -----",recordObj.content.findIndex(item=>item.callIdNumber), item.callIdNumber)
flag=recordObj.content[recordObj.content.length-2]?.callIdNumber!=recordObj.content[recordObj.content.length-1].callIdNumber
})
}
return flag;
}
defineExpose({ defineExpose({
getScrollbarRef getScrollbarRef
}) })

View File

@@ -17,71 +17,21 @@ const authStore = useAuthStore()
const recordLeftRef = ref(null); const recordLeftRef = ref(null);
const recordRightRef = ref(null); const recordRightRef = ref(null);
const leftHeadData = ref({ const leftHeadData = ref({
username: '张三', // username: '张三',
phone: '13546812315', // phone: '13546812315',
orderName: '张三工单', // orderName: '张三工单',
}) })
const rightHeadData = ref({ const rightHeadData = ref({
username: '李四', // username: '李四',
phone: '18246812546', // phone: '18246812546',
orderName: '李四工单', // orderName: '李四工单',
}) })
const recordLeftObj = ref({ const recordLeftObj = ref({
content: [] content: []
} })
// {
// "callIdNumber": "17260625724565",
// "content": [{
// "callIdNumber": "17260625724565",
// "conversationId": 0,
// "conversationTimestamp": "2024-09-15 12:10",
// "createTime": "2024-09-16",
// "message": "你好11",
// "speaker": "1"
// },
// {
// "callIdNumber": "17260625724565",
// "conversationId": 0,
// "conversationTimestamp": "2024-09-15 16:10",
// "createTime": "2024-09-16",
// "message": "你好好11!",
// "speaker": "0"
// }
// ],
// "name": "",
// "phone": "",
// "timestamp": "1726416597958",
// "type": "1"
// }
)
const recordRightObj = ref({ const recordRightObj = ref({
content: [] content: []
} })
// {
// "callIdNumber": "17260625724123",
// "content": [{
// "callIdNumber": "17260625724123",
// "conversationId": 0,
// "conversationTimestamp": "2024-09-15 12:10",
// "createTime": "2024-09-16",
// "message": "你好22",
// "speaker": "1"
// },
// {
// "callIdNumber": "17260625724123",
// "conversationId": 0,
// "conversationTimestamp": "2024-09-15 16:10",
// "createTime": "2024-09-16",
// "message": "你好好222!",
// "speaker": "0"
// }
// ],
// "name": "",
// "phone": "",
// "timestamp": "1726416597958",
// "type": "2"
// }
)
let socket = reactive(""); let socket = reactive("");
let token = getToken(); let token = getToken();
let send = { let send = {
@@ -139,12 +89,20 @@ const initWebSocket = () => {
} }
console.log("服务器返回的信息: ", data); console.log("服务器返回的信息: ", data);
if (data.type == '1') { if (data.type == '1') {
recordLeftObj.value.name=data.name
recordLeftObj.value.phone=data.phone
recordLeftObj.value.type=data.type
recordLeftObj.value.orderName=data.orderName
recordLeftObj.value.content.push(data.content) recordLeftObj.value.content.push(data.content)
// console.info("🚀 ~method:onmessage -----", recordLeftObj.value) // console.info("🚀 ~method:onmessage -----", recordLeftObj.value)
nextTick(() => { nextTick(() => {
scrollToBottom(recordLeftRef.value) scrollToBottom(recordLeftRef.value)
}) })
} else { } else {
recordRightObj.value.name=data.name
recordRightObj.value.phone=data.phone
recordRightObj.value.type=data.type
recordRightObj.value.orderName=data.orderName
recordRightObj.value.content.push(data.content) recordRightObj.value.content.push(data.content)
// console.info("🚀 ~method:onmessage -----", recordRightObj.value) // console.info("🚀 ~method:onmessage -----", recordRightObj.value)
nextTick(() => { nextTick(() => {

View File

@@ -8,7 +8,7 @@
<h3>历史通话记录</h3> <h3>历史通话记录</h3>
<fvTable ref="tableIns" :tableConfig="tableConfig"></fvTable> <fvTable ref="tableIns" :tableConfig="tableConfig"></fvTable>
<voice ref="voiceRef" title="语音详情" :rowUrl="rowUrl" /> <voice ref="voiceRef" title="语音详情" :rowUrl="rowUrl" />
<infoLiveCall ref="infoLiveCallRef" :rowData="rowData" /> <infoLiveCall ref="infoLiveCallRef" v-model:value="orderNumber" />
</div> </div>
</div> </div>
</template> </template>
@@ -17,7 +17,7 @@
import LiveCall from '@/components/liveCall/index.vue' import LiveCall from '@/components/liveCall/index.vue'
import Voice from '@/components/voice/index.vue' import Voice from '@/components/voice/index.vue'
import InfoLiveCall from '@/components/infoLiveCall/index.vue' import InfoLiveCall from '@/components/infoLiveCall/index.vue'
const rowData = ref() const orderNumber = ref('')
const rowUrl = ref() const rowUrl = ref()
const infoLiveCallRef = ref() const infoLiveCallRef = ref()
const voiceRef = ref() const voiceRef = ref()
@@ -121,7 +121,6 @@ const tableConfig = reactive({
], ],
api: '/order/list', api: '/order/list',
params: { params: {
orderState: '2'
} }
}) })
const handleVoice = (row) => { const handleVoice = (row) => {
@@ -137,10 +136,9 @@ const handleVoice = (row) => {
} }
const handleInfo = (row) => { const handleInfo = (row) => {
console.log(row); console.log('fefe',row.orderNumber);
orderNumber.value = row.orderNumber
infoLiveCallRef.value.open(true) infoLiveCallRef.value.open()
rowData.value = row.orderNumber
} }
</script> </script>

View File

@@ -1,7 +1,9 @@
<template> <template>
<fvSearchForm :searchConfig="searchConfig" @search="search"></fvSearchForm> <fvSearchForm :searchConfig="searchConfig" @search="search"></fvSearchForm>
<fvTable ref="tableIns" :tableConfig="tableConfig" @headBtnClick="headBtnClick"></fvTable> <fvTable ref="tableIns" :tableConfig="tableConfig" @headBtnClick="headBtnClick"></fvTable>
<fvFormDialog v-if="showAddOrEditUserDialog" ref="formDialogRef" :title="dialogTitle" :form-schema="formSchema" :form-rules="formRules" @dialogCancel="handleCancel" @dialogSubmit="handleSubmit"></fvFormDialog> <fvFormDialog ref="formDialogRef" :title="dialogTitle" :dialogType="dialogType"
:form-schema="formSchema" :form-rules="formRules"
@dialogSubmit="handleSubmitAddressBook"></fvFormDialog>
</template> </template>
<script setup> <script setup>
@@ -11,6 +13,7 @@ import {useCacheStore} from "@/stores/cache.js";
const tableIns = ref() const tableIns = ref()
const formDialogRef = ref() const formDialogRef = ref()
const dialogType = ref("");
const showAddOrEditUserDialog = ref(false) const showAddOrEditUserDialog = ref(false)
const dialogTitle = ref(""); const dialogTitle = ref("");
const searchConfig = reactive([ const searchConfig = reactive([
@@ -68,7 +71,7 @@ const tableConfig = reactive({
api: '/user', api: '/user',
params: {}, params: {},
btns: [ btns: [
{name: '导入', key: 'add', type: 'primary'}, {name: '新增', key: 'add', type: 'primary'},
] ]
}) })
const formRules = reactive({ const formRules = reactive({
@@ -179,36 +182,60 @@ const headBtnClick = (key) => {
} }
//新增用户 //新增用户
const handleAdd = () => { const handleAdd = () => {
// showAddOrEditUserDialog.value = true showAddOrEditUserDialog.value = true
// formRules.value.password[0].required = true // formRules.value.password[0].required = true
// restForm(); // restForm();
// dialogTitle.value = "新增用户"; dialogTitle.value = "新增用户";
// nextTick(()=>{ dialogType.value = "add";
// // 清空校验 nextTick(() => {
// formDialogRef.value.getFormInstance().clearValidate() // formDialogRef.value.getFormInstance().setValues({})
// formDialogRef.value.getFormInstance().resetFields() // 清空校验
// }) formDialogRef.value.getFormInstance().clearValidate()
formDialogRef.value.getFormInstance().resetFields()
})
}; };
const handleEdit = (row) => {
formDialogRef.value.openOrCloseDialog(true)
getDetail(row)
dialogTitle.value = "编辑用户";
dialogType.value = "edit";
}
const getDetail = (row) => {
getUserDetail(row.userId).then(res => {
if (res.code === 1000) {
ElMessage.success(res.msg)
nextTick(() => {
formDialogRef.value.getFormInstance().setValues(res.data)
// 清空校验
formDialogRef.value.getFormInstance().clearValidate()
})
} else {
}
})
}
//取消 //取消
const handleCancel = () => { const handleCancel = () => {
showAddOrEditUserDialog.value = false; showAddOrEditUserDialog.value = false;
}; };
//提交 //提交
const handleSubmit = async (formInstance) => { const handleSubmit = async (formInstance) => {
if (!formInstance) return; if (!formInstance) return;
formInstance.validate(async (valid) => { let validate = await formInstance.validate()
if (!valid) return; if (!validate.isValidate) return;
// if (title.value === "新增用户") { if (dialogType.value === "add") {
// addUser(userForm.value).then(res => { addUser(formInstance.getValues()).then(res => {
// if (res.code === 1000) { if (res.code === 1000) {
// ElMessage.success(res.msg); ElMessage.success(res.msg);
// isVisited.value = false; tableIns.value.refresh()
// } else { formDialogRef.value.openOrCloseDialog(false)
// ElMessage.error(res.msg); } else {
// } ElMessage.error(res.msg);
// }); }
// } });
}) }
// editUser
} }
</script> </script>