Merge branch 'build' of http://git.sinoecare.com/sinoecare/digital_village_v2/dvcp_v2_webapp into build
This commit is contained in:
4
.env.biaopin
Normal file
4
.env.biaopin
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
VUE_APP_SCOPE=biaopin
|
||||||
|
#VUE_APP_API=https://web.fdfengshou.cn/
|
||||||
|
VUE_APP_API=http://192.168.1.87:9000/
|
||||||
|
#VUE_APP_API=http://test87web.cunwuyun.cn/
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
"build": "vue-cli-service build",
|
"build": "vue-cli-service build",
|
||||||
"dev:ai": "vue-cli-service serve examples/main.js --mode ai",
|
"dev:ai": "vue-cli-service serve examples/main.js --mode ai",
|
||||||
"dev:oms": "vue-cli-service serve examples/main.js --mode oms",
|
"dev:oms": "vue-cli-service serve examples/main.js --mode oms",
|
||||||
|
"dev:biaopin": "vue-cli-service serve examples/main.js --mode biaopin",
|
||||||
"dev:dv": "vue-cli-service serve examples/main.js --mode dv",
|
"dev:dv": "vue-cli-service serve examples/main.js --mode dv",
|
||||||
"dev:fengdu": "vue-cli-service serve examples/main.js --mode fengdu",
|
"dev:fengdu": "vue-cli-service serve examples/main.js --mode fengdu",
|
||||||
"lib": "npm publish||(npm unpublish -f&&npm publish)",
|
"lib": "npm publish||(npm unpublish -f&&npm publish)",
|
||||||
|
|||||||
@@ -15,14 +15,15 @@ export default {
|
|||||||
currentPage() {
|
currentPage() {
|
||||||
let {hash} = this.$route
|
let {hash} = this.$route
|
||||||
return hash == "#add" ? Add : List
|
return hash == "#add" ? Add : List
|
||||||
}
|
},
|
||||||
|
appName: v => v.menuName || v.$options.label
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section class="AppCopilotConfig">
|
<section class="AppCopilotConfig">
|
||||||
<component :is="currentPage" v-bind="$props"/>
|
<component :is="currentPage" v-bind="$props" :appName="appName"/>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ export default {
|
|||||||
colConfigs: [
|
colConfigs: [
|
||||||
{prop: "appId", label: "应用编号"},
|
{prop: "appId", label: "应用编号"},
|
||||||
{prop: "appName", label: "应用名称", width: 200},
|
{prop: "appName", label: "应用名称", width: 200},
|
||||||
|
{prop: "status", label: "状态", width: 100, dict: "assessmentStartStatus"},
|
||||||
],
|
],
|
||||||
dialog: false,
|
dialog: false,
|
||||||
form: {}
|
form: {}
|
||||||
@@ -39,7 +40,8 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
handleAdd(row = {}) {
|
handleAdd(row = {}) {
|
||||||
this.form = this.$copy(row)
|
const {appIconUrl: url, fileId} = row
|
||||||
|
this.form = this.$copy({...row, appIconUrl: url ? [{url, fileId}] : []})
|
||||||
this.dialog = true
|
this.dialog = true
|
||||||
// this.$router.push({hash: "#add", query: {id}})
|
// this.$router.push({hash: "#add", query: {id}})
|
||||||
},
|
},
|
||||||
@@ -71,7 +73,8 @@ export default {
|
|||||||
},
|
},
|
||||||
submit() {
|
submit() {
|
||||||
this.$refs.form.validate().then(() => {
|
this.$refs.form.validate().then(() => {
|
||||||
this.instance.post("/app/appaiconfiginfo/addOrUpdate", this.form).then(res => {
|
const {appIconUrl} = this.form, {url, id:fileId} = appIconUrl.at(0) || {}
|
||||||
|
this.instance.post("/app/appaiconfiginfo/addOrUpdate", {...this.form, appIconUrl: url, fileId}).then(res => {
|
||||||
if (res?.code == '0') {
|
if (res?.code == '0') {
|
||||||
this.$message.success("提交成功!")
|
this.$message.success("提交成功!")
|
||||||
this.getTableData()
|
this.getTableData()
|
||||||
@@ -82,7 +85,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.$dict.load("copilotAbility")
|
this.$dict.load("copilotAbility", "assessmentStartStatus")
|
||||||
this.getTableData()
|
this.getTableData()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -91,14 +94,14 @@ export default {
|
|||||||
<template>
|
<template>
|
||||||
<section class="ccList">
|
<section class="ccList">
|
||||||
<ai-list>
|
<ai-list>
|
||||||
<ai-title slot="title" title="定制方案" isShowBottomBorder/>
|
<ai-title slot="title" :title="$attrs.appName" isShowBottomBorder/>
|
||||||
<template #content>
|
<template #content>
|
||||||
<ai-search-bar>
|
<ai-search-bar>
|
||||||
<template #left>
|
<template #left>
|
||||||
<el-button type="primary" icon="iconfont iconAdd" @click="handleAdd()">添加</el-button>
|
<el-button type="primary" icon="iconfont iconAdd" @click="handleAdd()">添加</el-button>
|
||||||
</template>
|
</template>
|
||||||
<template #right>
|
<template #right>
|
||||||
<el-input size="small" placeholder="搜索" v-model="search.appName" clearable
|
<el-input size="small" placeholder="请输入应用名称" v-model="search.appName" clearable
|
||||||
@change="page.current=1,getTableData()"/>
|
@change="page.current=1,getTableData()"/>
|
||||||
</template>
|
</template>
|
||||||
</ai-search-bar>
|
</ai-search-bar>
|
||||||
@@ -129,7 +132,7 @@ export default {
|
|||||||
<ai-select v-model="form.ability" dict="copilotAbility"/>
|
<ai-select v-model="form.ability" dict="copilotAbility"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="应用图标" prop="appIconUrl">
|
<el-form-item label="应用图标" prop="appIconUrl">
|
||||||
<ai-uploader v-model="form.appIconUrl" :instance="instance" :limit="1" valueIsUrl/>
|
<ai-uploader v-model="form.appIconUrl" :instance="instance" :limit="1"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</ai-dialog>
|
</ai-dialog>
|
||||||
|
|||||||
@@ -86,35 +86,36 @@ export default {
|
|||||||
this.component = config.custom
|
this.component = config.custom
|
||||||
this.meta = config?.meta || {}
|
this.meta = config?.meta || {}
|
||||||
} else {
|
} else {
|
||||||
this.componentList = JSON.parse(res.data.config).config
|
const layers = JSON.parse(res.data.config).config
|
||||||
this.dashboard = JSON.parse(res.data.config).dashboard
|
this.dashboard = JSON.parse(res.data.config).dashboard
|
||||||
|
Promise.all(layers.map(item => Promise.resolve().then(() => {
|
||||||
this.componentList.forEach((item, index) => {
|
|
||||||
if (item.dataType !== 'staticData' && ((item.type.indexOf('Chart') > -1) || ['display', 'table', 'map', 'summary', 'AiRanking', 'AiDvTable'].includes(item.type))) {
|
if (item.dataType !== 'staticData' && ((item.type.indexOf('Chart') > -1) || ['display', 'table', 'map', 'summary', 'AiRanking', 'AiDvTable'].includes(item.type))) {
|
||||||
this.getSourceData(item, index)
|
return this.getSourceData(item)
|
||||||
}
|
}
|
||||||
if (item.type === 'monitor' && item.monitorType === 'cmcc') {
|
if (item.type === 'monitor' && item.monitorType === 'cmcc') {
|
||||||
this.instance.post(`${this.urlPrefix}/appzyvideoequipment/getWebSdkUrl?deviceId=${item.moniterId}`).then(res => {
|
return item.moniterId && this.instance.post(`${this.urlPrefix}/appzyvideoequipment/getWebSdkUrl?deviceId=${item.moniterId}`).then(res => {
|
||||||
if (res.code == 0) {
|
if (res.code == 0) {
|
||||||
this.$set(this.componentList[index], 'src', JSON.parse(res.data).url)
|
return item.src = JSON.parse(res.data).url
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (item.type === 'monitor' && item.monitorType === 'slw') {
|
if (item.type === 'monitor' && item.monitorType === 'slw') {
|
||||||
this.instance.post(`${this.urlPrefix}/appzyvideoequipment/getWebSdkUrl?deviceId=${item.moniterId}`).then(res => {
|
return item.moniterId && this.instance.post(`${this.urlPrefix}/appzyvideoequipment/getWebSdkUrl?deviceId=${item.moniterId}`).then(res => {
|
||||||
if (res.code == 0) {
|
if (res.code == 0) {
|
||||||
this.$set(this.componentList[index], 'src', res.data)
|
return item.src = res.data
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}))).then(() => {
|
||||||
|
this.componentList = layers
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
getSourceData(item, index) {
|
getSourceData(item) {
|
||||||
const api = item.dataType === 'apiData' ? item.api : `${this.urlPrefix}/appdiylargescreen/statisticsByLsid?id=${item.sourceDataId}`
|
const api = item.dataType === 'apiData' ? item.api : `${this.urlPrefix}/appdiylargescreen/statisticsByLsid?id=${item.sourceDataId}`
|
||||||
this.instance.post(api).then(res => {
|
return this.instance.post(api).then(res => {
|
||||||
if (res?.data) {
|
if (res?.data) {
|
||||||
if (res.data.length) {
|
if (res.data.length) {
|
||||||
const keys = Object.keys(res.data[0])
|
const keys = Object.keys(res.data[0])
|
||||||
@@ -166,9 +167,9 @@ export default {
|
|||||||
dynamicData = res.data
|
dynamicData = res.data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.$set(this.componentList[index], item.dataType, dynamicData)
|
item[item.dataType] = dynamicData
|
||||||
} else {
|
} else {
|
||||||
this.$set(this.componentList[index], item.dataType, [])
|
item[item.dataType] = []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -192,7 +193,7 @@ export default {
|
|||||||
const item = tableData[k.substring(1) || 0] || {}
|
const item = tableData[k.substring(1) || 0] || {}
|
||||||
item[prop] = v
|
item[prop] = v
|
||||||
tableData[k.substring(1) || 0] = item
|
tableData[k.substring(1) || 0] = item
|
||||||
}else if (k != columnProp) {
|
} else if (k != columnProp) {
|
||||||
const index = columns.findIndex(e => k == e)
|
const index = columns.findIndex(e => k == e)
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
const item = tableData[index] || {}
|
const item = tableData[index] || {}
|
||||||
|
|||||||
@@ -39,11 +39,11 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
getCmccURL() {
|
getCmccURL() {
|
||||||
const {did} = this.$attrs
|
const {did} = this.$attrs
|
||||||
request.post(`/app/appzyvideoequipment/getWebSdkUrl?deviceId=${did}`).then(res => {
|
did ? request.post(`/app/appzyvideoequipment/getWebSdkUrl?deviceId=${did}`).then(res => {
|
||||||
if (res.code == 0) {
|
if (res.code == 0) {
|
||||||
this.cmccUrl = JSON.parse(res.data).url
|
this.cmccUrl = JSON.parse(res.data).url
|
||||||
}
|
}
|
||||||
}).finally(() => this.cmccUrl = this.cmccUrl || this.src)
|
}) : this.cmccUrl = this.src
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
|||||||
@@ -322,6 +322,10 @@ div[flex], .flex {
|
|||||||
&.normal {
|
&.normal {
|
||||||
align-items: unset;
|
align-items: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.end {
|
||||||
|
align-items: flex-end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.fill {
|
.fill {
|
||||||
|
|||||||
@@ -16,16 +16,11 @@ export default {
|
|||||||
loading: false,
|
loading: false,
|
||||||
prompt: "",
|
prompt: "",
|
||||||
history: [],
|
history: [],
|
||||||
apps: [
|
apps: [],
|
||||||
{label: "日常助理", icon: "https://cdn.sinoecare.com/i/2024/07/04/66864da37fc2b.png"},
|
|
||||||
{label: "文本助理", icon: "https://cdn.sinoecare.com/i/2024/07/04/66864da1684ad.png"},
|
|
||||||
],
|
|
||||||
filter: "",
|
filter: "",
|
||||||
conversations: [
|
conversations: [],
|
||||||
{content: "请对“city不city”一词进行深入分析"},
|
currentConversation: null,
|
||||||
{content: "请对“city不city”一词进行深入分析"},
|
app: {}
|
||||||
{content: "请对“city不city”一词进行深入分析"},
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -38,19 +33,38 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
rowBtns: () => [
|
rowBtns: v => [
|
||||||
{icon: "https://cdn.sinoecare.com/i/2024/07/04/66866edc2910a.png", click: row => 0},
|
{icon: "https://cdn.sinoecare.com/i/2024/07/04/66866edc2910a.png", label: "置顶", click: row => 0},
|
||||||
{icon: "https://cdn.sinoecare.com/i/2024/07/04/66866ed734540.png", click: row => 0},
|
{icon: "https://cdn.sinoecare.com/i/2024/07/04/66866ed734540.png", label: "编辑", click: row => 0},
|
||||||
{icon: "https://cdn.sinoecare.com/i/2024/07/04/66866eda99e4d.png", click: row => 0},
|
{icon: "https://cdn.sinoecare.com/i/2024/07/04/66866eda99e4d.png", label: "删除", click: row => v.handleDeleteConversation(row.conversationId)},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
components: {ThinkingBar, ChatContent},
|
components: {ThinkingBar, ChatContent},
|
||||||
methods: {
|
methods: {
|
||||||
getHistory(cb) {
|
getHistory(params) {
|
||||||
this.http.post("/app/appaicopilotinfo/list").then(res => {
|
this.http.post("/app/appaicopilotinfo/list", null, {params}).then(res => {
|
||||||
if (res?.data) {
|
if (res?.data) {
|
||||||
if (cb) cb(res.data.records)
|
this.history = res.data.records
|
||||||
else this.history = res.data.records
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getApps() {
|
||||||
|
return this.http.post("/app/appaiconfiginfo/list", null, {
|
||||||
|
params: {
|
||||||
|
status: 1, size: 999
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
if (res?.data) {
|
||||||
|
return this.apps = res.data.records
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getConversations() {
|
||||||
|
return this.http.post("/app/appaicopilotinfo/listHistory", null, {
|
||||||
|
params: {content: this.filter}
|
||||||
|
}).then(res => {
|
||||||
|
if (res?.data) {
|
||||||
|
return this.conversations = res.data.records || []
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -61,12 +75,13 @@ export default {
|
|||||||
},
|
},
|
||||||
handleSend() {
|
handleSend() {
|
||||||
if (!this.prompt.trim()) return this.$message.error("无法发送空白信息")
|
if (!this.prompt.trim()) return this.$message.error("无法发送空白信息")
|
||||||
const concatenateStr = (content, i = 0) => {
|
const concatenateStr = (content, i = 0, target = this.history.at(-1)) => {
|
||||||
this.history.at(-1).content += content.slice(i, i + 1)
|
target.content += content.slice(i, i + 1)
|
||||||
if (++i < content.length) setTimeout(() => concatenateStr(content, i), 50)
|
if (++i < content.length) setTimeout(() => concatenateStr(content, i, target), 50)
|
||||||
}
|
}
|
||||||
this.$debounce(() => {
|
this.$debounce(() => {
|
||||||
const message = {appType: "2", userType: 0, content: this.prompt}
|
const {currentConversation: conversationId, app, prompt: content} = this.$data
|
||||||
|
const message = {appType: "2", userType: 0, content, conversationId, ...app}
|
||||||
this.history.push(message)
|
this.history.push(message)
|
||||||
this.loading = true
|
this.loading = true
|
||||||
this.prompt = ""
|
this.prompt = ""
|
||||||
@@ -78,13 +93,48 @@ export default {
|
|||||||
}
|
}
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
|
this.getConversations()
|
||||||
})
|
})
|
||||||
}, 100)
|
}, 100)
|
||||||
|
},
|
||||||
|
handleDeleteConversation(conversationId) {
|
||||||
|
this.$confirm("是否要删除该会话历史?").then(() => {
|
||||||
|
this.http.post("/app/appaicopilotinfo/deleteConversation", null, {params: {conversationId}}).then(res => {
|
||||||
|
if (res?.code == '0') {
|
||||||
|
this.$message.success("删除成功!")
|
||||||
|
this.getConversations()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}).catch(() => 0)
|
||||||
|
},
|
||||||
|
handleChangeApp(item) {
|
||||||
|
const {appId, id: aiConfigId} = item
|
||||||
|
this.handleChangeConversation({appId, aiConfigId})
|
||||||
|
this.history = [{userType: 2, content: `当前应用已切换至【${item.appName}】`}]
|
||||||
|
},
|
||||||
|
handleChangeConversation({conversationId, appId, aiConfigId} = {}) {
|
||||||
|
this.currentConversation = conversationId
|
||||||
|
this.app = {appId, aiConfigId}
|
||||||
|
},
|
||||||
|
getIcon(item = {}) {
|
||||||
|
const icon = item.appIconUrl || "https://cdn.sinoecare.com/i/2024/07/04/66864da1684ad.png"
|
||||||
|
return {
|
||||||
|
backgroundImage: `url(${icon})`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
currentConversation(v) {
|
||||||
|
v && this.getHistory({conversationId: v})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.getHistory()
|
Promise.all([this.getApps(), this.getConversations()]).then(() => {
|
||||||
|
const {appId, id: aiConfigId} = this.apps.at(0)
|
||||||
|
this.handleChangeConversation(this.conversations.at(0) || {appId, aiConfigId})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -98,20 +148,21 @@ export default {
|
|||||||
</div>
|
</div>
|
||||||
<thinking-bar v-show="loading"/>
|
<thinking-bar v-show="loading"/>
|
||||||
<div class="flex content">
|
<div class="flex content">
|
||||||
<div class="left" :class="{expand}">
|
<div class="left" :class="{expand}" v-loading="loading" element-loading-text="小助手正在思考中.."
|
||||||
|
element-loading-spinner="el-icon-loading" element-loading-background="rgba(255,255,255,0.8)">
|
||||||
<div class="profile">
|
<div class="profile">
|
||||||
<div v-text="profile.name"/>
|
<div v-text="profile.name"/>
|
||||||
<span v-text="profile.girdName"/>
|
<span v-text="profile.girdName"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="apps flex">
|
<div class="apps">
|
||||||
<div v-for="(item,i) in apps" :key="i" class="app pointer" :style="{backgroundImage: `url(${item.icon})`}" v-text="item.label"/>
|
<div v-for="(item,i) in apps" :key="i" class="app pointer" :class="{current:item.id==app.aiConfigId}" :style="getIcon(item)" v-text="item.appName" @click="handleChangeApp(item)"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="conversation">
|
<div class="conversation">
|
||||||
<el-input class="search" v-model="filter" placeholder="搜索历史对话记录" size="small" suffix-icon="el-icon-search" clearable/>
|
<el-input class="search" v-model="filter" placeholder="搜索历史对话记录" size="small" suffix-icon="el-icon-search" clearable @change="getConversations"/>
|
||||||
<div class="item pointer" v-for="item in conversations" :key="item.id">
|
<div class="item pointer" v-for="item in conversations" :key="item.id" @click="currentConversation=item.conversationId" :class="{current:item.conversationId==currentConversation}">
|
||||||
{{ item.content }}
|
{{ item.content }}
|
||||||
<div class="operation flex">
|
<div class="operation flex">
|
||||||
<div v-for="(btn,i) in rowBtns" :key="i" class="pointer" :style="{backgroundImage: `url(${btn.icon})`}"/>
|
<div v-for="(btn,i) in rowBtns" :key="i" class="pointer" :style="{backgroundImage: `url(${btn.icon})`}" @click.stop="btn.click(item)"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -123,7 +174,7 @@ export default {
|
|||||||
<div v-for="(btn,i) in btns" :key="i" class="btn pointer" :style="{backgroundImage: `url(${btn.icon})`}" v-text="btn.label" @click="btn.click"/>
|
<div v-for="(btn,i) in btns" :key="i" class="btn pointer" :style="{backgroundImage: `url(${btn.icon})`}" v-text="btn.label" @click="btn.click"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex end">
|
<div class="flex end">
|
||||||
<el-input type="textarea" class="fill input" autosize resize="none" v-model="prompt" placeholder="请输入..." :rows="2"
|
<el-input type="textarea" class="fill input" autosize resize="none" v-model="prompt" placeholder="请输入..." :rows="5"
|
||||||
@keydown.native="handleHotkey" :disabled="loading" :placeholder="loading?'正在思考中...':'请输入'"/>
|
@keydown.native="handleHotkey" :disabled="loading" :placeholder="loading?'正在思考中...':'请输入'"/>
|
||||||
<div class="sendBtn" @click="handleSend"/>
|
<div class="sendBtn" @click="handleSend"/>
|
||||||
</div>
|
</div>
|
||||||
@@ -143,7 +194,7 @@ export default {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
gap: 18px;
|
gap: 18px;
|
||||||
z-index: 202406171636;
|
z-index: 1888;
|
||||||
|
|
||||||
.copilot {
|
.copilot {
|
||||||
border-radius: 0 0 8px 8px;
|
border-radius: 0 0 8px 8px;
|
||||||
@@ -156,6 +207,7 @@ export default {
|
|||||||
background-image: linear-gradient(90deg, #3577FD 0%, #216AFD 100%);
|
background-image: linear-gradient(90deg, #3577FD 0%, #216AFD 100%);
|
||||||
box-shadow: 0 2px 6px 0 #0a255c14;
|
box-shadow: 0 2px 6px 0 #0a255c14;
|
||||||
border-radius: 8px 8px 0 0;
|
border-radius: 8px 8px 0 0;
|
||||||
|
overflow: hidden;
|
||||||
padding: 0 8px 0 14px;
|
padding: 0 8px 0 14px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
@@ -192,17 +244,19 @@ export default {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
transition: width 1s;
|
transition: width 1s;
|
||||||
padding: 14px 0;
|
padding: 14px 0;
|
||||||
overflow: hidden;
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
& > * {
|
& > * {
|
||||||
margin: 0 14px;
|
margin: 0 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.expand {
|
&.expand {
|
||||||
width: 260px;
|
width: 306px;
|
||||||
|
|
||||||
& + .right {
|
& + .right {
|
||||||
border-left-color: #ddd;
|
border-left-color: #ddd;
|
||||||
|
width: 660px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +264,7 @@ export default {
|
|||||||
padding: 18px 14px;
|
padding: 18px 14px;
|
||||||
height: 88px;
|
height: 88px;
|
||||||
background: url("https://cdn.sinoecare.com/i/2024/06/04/665ed2bc580fa.png") no-repeat;
|
background: url("https://cdn.sinoecare.com/i/2024/06/04/665ed2bc580fa.png") no-repeat;
|
||||||
background-size: 100%;
|
background-size: 100% 100%;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #222222;
|
color: #222222;
|
||||||
letter-spacing: 0;
|
letter-spacing: 0;
|
||||||
@@ -229,6 +283,9 @@ export default {
|
|||||||
margin-top: 18px;
|
margin-top: 18px;
|
||||||
padding-top: 29px;
|
padding-top: 29px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
content: "常用功能";
|
content: "常用功能";
|
||||||
@@ -251,7 +308,7 @@ export default {
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
|
||||||
|
|
||||||
&:hover {
|
&:hover, &.current {
|
||||||
background-color: #286ffd14;
|
background-color: #286ffd14;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -304,7 +361,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover, &.current {
|
||||||
background: #2b71fd24;
|
background: #2b71fd24;
|
||||||
|
|
||||||
.operation {
|
.operation {
|
||||||
@@ -316,11 +373,12 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.right {
|
.right {
|
||||||
width: 420px;
|
width: 468px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 14px 0 14px 14px;
|
padding: 14px 0 14px 14px;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
border-left: 1px solid transparent;
|
border-left: 1px solid transparent;
|
||||||
|
transition: width 1s;
|
||||||
|
|
||||||
.sendBtn {
|
.sendBtn {
|
||||||
width: 36px;
|
width: 36px;
|
||||||
@@ -346,9 +404,10 @@ export default {
|
|||||||
|
|
||||||
.topBar {
|
.topBar {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 25px;
|
height: 28px;
|
||||||
border-bottom: 1px solid #E0E0E0;
|
border-bottom: 1px solid #E0E0E0;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@@ -371,6 +430,7 @@ export default {
|
|||||||
border: none;
|
border: none;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
|
min-height: 73px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-scrollbar class="chatContent">
|
<el-scrollbar class="chatContent">
|
||||||
<div class="chat-wrapper" v-for="item in list" :key="item.id">
|
<div class="chat-wrapper" v-for="item in list" :key="item.id">
|
||||||
<div class="chat-text" :class="{right:item.userType == '0'}">
|
<div class="chat-text" :class="{right:item.userType == '0',system:item.userType == '2'}">
|
||||||
<img class="avatar" :src="avatar(item)" alt=""/>
|
<img v-if="item.userType!=2" class="avatar" :src="avatar(item)" alt=""/>
|
||||||
<div class="content" v-text="item.content"/>
|
<div class="content" v-text="item.content"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -11,6 +11,9 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* userType: 0-用户 1-机器人 2-系统
|
||||||
|
*/
|
||||||
export default {
|
export default {
|
||||||
name: "chatContent",
|
name: "chatContent",
|
||||||
props: {
|
props: {
|
||||||
@@ -58,7 +61,7 @@ export default {
|
|||||||
|
|
||||||
.content {
|
.content {
|
||||||
position: relative;
|
position: relative;
|
||||||
max-width: 220px;
|
max-width: max(calc(100% - 140px), 220px);
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: #F3F5F7;
|
background: #F3F5F7;
|
||||||
@@ -91,6 +94,24 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.system {
|
||||||
|
padding-right: 0;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.content {
|
||||||
|
font-size: 12px;
|
||||||
|
background: #F0F0F0;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #888;
|
||||||
|
padding: 3px 6px;
|
||||||
|
width: fit-content;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar {
|
.avatar {
|
||||||
|
|||||||
Reference in New Issue
Block a user