定位完成
This commit is contained in:
@@ -2,7 +2,8 @@
|
|||||||
import ChatContent from "./components/chatContent.vue";
|
import ChatContent from "./components/chatContent.vue";
|
||||||
import ThinkingBar from "./components/thinkingBar.vue";
|
import ThinkingBar from "./components/thinkingBar.vue";
|
||||||
import {mapState} from "vuex";
|
import {mapState} from "vuex";
|
||||||
import AiDrag from "../../dv/AiDrag.vue";
|
import AiDrag from "../basic/AiDrag.vue";
|
||||||
|
import AiLocateDialog from "../tools/AiLocateDialog.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "AiCopilot",
|
name: "AiCopilot",
|
||||||
@@ -21,26 +22,34 @@ export default {
|
|||||||
filter: "",
|
filter: "",
|
||||||
conversations: [],
|
conversations: [],
|
||||||
currentConversation: null,
|
currentConversation: null,
|
||||||
app: {}
|
app: {},
|
||||||
|
locate: false,
|
||||||
|
latlng: ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["user"]),
|
...mapState(["user"]),
|
||||||
profile: v => v.user.info || {},
|
profile: v => v.user.info || {},
|
||||||
expandBtn: v => v.expand ? "收起" : "展开",
|
expandBtn: v => v.expand ? "收起" : "展开",
|
||||||
btns: () => [
|
btns: v => [
|
||||||
{
|
{
|
||||||
label: "文件", icon: "https://cdn.sinoecare.com/i/2024/07/04/668663436e46e.png", click: () => {
|
label: "文件", icon: "https://cdn.sinoecare.com/i/2024/07/04/668663436e46e.png", click: () => {
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "位置", icon: "https://cdn.sinoecare.com/i/2024/07/04/668663436e46e.png", click: () => {
|
||||||
|
v.locate = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
rowBtns: v => [
|
rowBtns: v => [
|
||||||
{icon: "https://cdn.sinoecare.com/i/2024/07/04/66866edc2910a.png", label: "置顶", 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", label: "编辑", 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", label: "删除", click: row => v.handleDeleteConversation(row.conversationId)},
|
{icon: "https://cdn.sinoecare.com/i/2024/07/04/66866eda99e4d.png", label: "删除", click: row => v.handleDeleteConversation(row.conversationId)},
|
||||||
]
|
],
|
||||||
|
dialogWidth: v => v.expand ? 960 : 468
|
||||||
},
|
},
|
||||||
components: {AiDrag, ThinkingBar, ChatContent},
|
components: {AiLocateDialog, AiDrag, ThinkingBar, ChatContent},
|
||||||
methods: {
|
methods: {
|
||||||
getHistory(params) {
|
getHistory(params) {
|
||||||
this.http.post("/app/appaicopilotinfo/list", null, {params}).then(res => {
|
this.http.post("/app/appaicopilotinfo/list", null, {params}).then(res => {
|
||||||
@@ -81,8 +90,8 @@ export default {
|
|||||||
if (++i < content.length) setTimeout(() => concatenateStr(content, i, target), 50)
|
if (++i < content.length) setTimeout(() => concatenateStr(content, i, target), 50)
|
||||||
}
|
}
|
||||||
this.$debounce(() => {
|
this.$debounce(() => {
|
||||||
const {currentConversation: conversationId, app, prompt: content} = this.$data
|
const {currentConversation: conversationId, app, prompt: content, latlng} = this.$data
|
||||||
const message = {appType: "2", userType: 0, content, conversationId, ...app}
|
const message = {appType: "2", userType: 0, content, conversationId, ...app, supplementContent: latlng}
|
||||||
this.history.push(message)
|
this.history.push(message)
|
||||||
this.loading = true
|
this.loading = true
|
||||||
this.prompt = ""
|
this.prompt = ""
|
||||||
@@ -122,6 +131,11 @@ export default {
|
|||||||
return {
|
return {
|
||||||
backgroundImage: `url(${icon})`
|
backgroundImage: `url(${icon})`
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
handleLocate(v) {
|
||||||
|
const {lat, lng} = v.location
|
||||||
|
this.latlng = [lat, lng].join(",")
|
||||||
|
this.locate = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -141,7 +155,7 @@ export default {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section class="AiCopilot">
|
<section class="AiCopilot">
|
||||||
<ai-drag class="copilot" v-if="show" :w="468" :h="600" :minHeight="600" :minWidth="468" :x="-480" :y="-542">
|
<ai-drag class="copilot" v-if="show" :w="dialogWidth" :h="600" :minHeight="600" :minWidth="dialogWidth" :x="-dialogWidth-12" :y="-542">
|
||||||
<div class="flex header">
|
<div class="flex header">
|
||||||
<b class="fill" v-text="title"/>
|
<b class="fill" v-text="title"/>
|
||||||
<div class="expandBtn pointer" v-text="expandBtn" @click="expand=!expand"/>
|
<div class="expandBtn pointer" v-text="expandBtn" @click="expand=!expand"/>
|
||||||
@@ -183,6 +197,7 @@ export default {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ai-drag>
|
</ai-drag>
|
||||||
|
<ai-locate-dialog v-model="locate" :ins="http" @confirm="v=>handleLocate(v)" :modal="false"/>
|
||||||
<img class="icon" src="https://cdn.sinoecare.com/i/2024/06/04/665ec6f5ef213.png" @click="show=!show"/>
|
<img class="icon" src="https://cdn.sinoecare.com/i/2024/06/04/665ec6f5ef213.png" @click="show=!show"/>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
@@ -252,14 +267,15 @@ export default {
|
|||||||
|
|
||||||
.content {
|
.content {
|
||||||
height: calc(100% - 50px);
|
height: calc(100% - 50px);
|
||||||
|
float: right;
|
||||||
|
|
||||||
.left {
|
.left {
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
transition: width 1s;
|
|
||||||
padding: 14px 0;
|
padding: 14px 0;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
& > * {
|
& > * {
|
||||||
margin: 0 14px;
|
margin: 0 14px;
|
||||||
@@ -422,6 +438,7 @@ export default {
|
|||||||
border-bottom: 1px solid #E0E0E0;
|
border-bottom: 1px solid #E0E0E0;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|||||||
181
ui/packages/tools/AiLocateDialog.vue
Normal file
181
ui/packages/tools/AiLocateDialog.vue
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
<template>
|
||||||
|
<section class="AiLocateDialog">
|
||||||
|
<ai-dialog :visible.sync="dialog" title="标绘" @closed="$emit('visible',false),selected={}"
|
||||||
|
@opened="$nextTick(()=>initMap())"
|
||||||
|
@onConfirm="handleConfirm" v-bind="$attrs">
|
||||||
|
<div id="amap" v-if="dialog"/>
|
||||||
|
<div class="poi">
|
||||||
|
<el-input ref="poiInput" v-model="search" size="small" clearable @change="handleSearch" placeholder="请输入地点"/>
|
||||||
|
</div>
|
||||||
|
<el-form class="selected" v-if="!!selected.location" id="result" size="mini" label-suffix=":"
|
||||||
|
label-position="left">
|
||||||
|
<div class="header">
|
||||||
|
<i class="iconfont iconLocation"/>
|
||||||
|
<span v-html="[selected.location.lng, selected.location.lat].join(',')"/>
|
||||||
|
</div>
|
||||||
|
<el-form-item label="地点">{{ selected.name || "未知地名" }}</el-form-item>
|
||||||
|
<el-form-item label="类型" v-if="!!selected.type">{{ selected.type }}</el-form-item>
|
||||||
|
<el-form-item label="地址" v-if="!!selected.address">{{ selected.address }}</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</ai-dialog>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import AMapLoader from '@amap/amap-jsapi-loader'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "AiLocateDialog",
|
||||||
|
model: {
|
||||||
|
prop: "visible",
|
||||||
|
event: "visible",
|
||||||
|
},
|
||||||
|
props: ['latlng', 'visible'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dialog: false,
|
||||||
|
search: "",
|
||||||
|
poi: null,
|
||||||
|
map: null,
|
||||||
|
AMap: null,
|
||||||
|
selected: {},
|
||||||
|
geo: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
visible(v) {
|
||||||
|
this.dialog = v
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initMap() {
|
||||||
|
AMapLoader.load({
|
||||||
|
key: "b553334ba34f7ac3cd09df9bc8b539dc",
|
||||||
|
version: '2.0',
|
||||||
|
plugins: ['AMap.PlaceSearch', 'AMap.Marker', 'AMap.Geolocation'],
|
||||||
|
}).then(AMap => {
|
||||||
|
this.AMap = AMap
|
||||||
|
this.map = new AMap.Map('amap', {
|
||||||
|
zoom: 14,
|
||||||
|
center: this.latlng ? [this.latlng.lng, this.latlng.lat] : ''
|
||||||
|
}).on('click', res => {
|
||||||
|
this.map.clearMap()
|
||||||
|
this.selected = {location: res.lnglat}
|
||||||
|
this.poi?.searchNearBy('', res.lnglat, 100)
|
||||||
|
});
|
||||||
|
if (this.latlng) {
|
||||||
|
let marker = new AMap.Marker({
|
||||||
|
position: [this.latlng.lng, this.latlng.lat]
|
||||||
|
})
|
||||||
|
this.map.add(marker)
|
||||||
|
}
|
||||||
|
this.poi = new AMap.PlaceSearch().on('complete', ({poiList}) => {
|
||||||
|
this.map.clearMap()
|
||||||
|
if (poiList?.length > 0) {
|
||||||
|
poiList?.pois?.map(e => {
|
||||||
|
let marker = new AMap.Marker({
|
||||||
|
position: e.location,
|
||||||
|
}).on('click', () => this.selected = e)
|
||||||
|
this.map.add(marker)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
let marker = new AMap.Marker({
|
||||||
|
position: this.selected.location,
|
||||||
|
})
|
||||||
|
this.map.add(marker)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.geo = new AMap.Geolocation({
|
||||||
|
enableHighAccuracy: true,//是否使用高精度定位
|
||||||
|
zoomToAccuracy: true//定位成功后是否自动调整地图视野到定位点
|
||||||
|
})
|
||||||
|
this.map.addControl(this.geo)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleSearch(v) {
|
||||||
|
if (v) {
|
||||||
|
this.poi.searchNearBy(v, this.map.getCenter(), 50000)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleConfirm() {
|
||||||
|
if (this.selected?.location) {
|
||||||
|
this.$emit('confirm', this.selected)
|
||||||
|
} else {
|
||||||
|
this.$message.error('请先选择坐标位置')
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.dialog = this.visible
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.AiLocateDialog {
|
||||||
|
:deep( .el-dialog__body ){
|
||||||
|
padding: 0;
|
||||||
|
height: 480px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.ai-dialog__content--wrapper {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#amap {
|
||||||
|
width: 100%;
|
||||||
|
height: 480px;
|
||||||
|
|
||||||
|
.amap-logo, .amap-copyright {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.amap-marker-label {
|
||||||
|
border-color: transparent;
|
||||||
|
box-shadow: 1px 1px 0 0 rgba(#999, .2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.poi {
|
||||||
|
position: absolute;
|
||||||
|
left: 10px;
|
||||||
|
top: 10px;
|
||||||
|
display: flex;
|
||||||
|
height: 32px;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
div {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected {
|
||||||
|
position: absolute;
|
||||||
|
right: 16px;
|
||||||
|
top: 16px;
|
||||||
|
background: #fff;
|
||||||
|
min-width: 200px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
|
||||||
|
.header {
|
||||||
|
color: #fff;
|
||||||
|
background: #26f;
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
height: 32px;
|
||||||
|
font-size: 14px;
|
||||||
|
gap: 4px;
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-form-item {
|
||||||
|
padding: 0 8px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user