网点管理功能完善
diff --git a/backend/src/main/java/com/supwisdom/dlpay/portal/dao/impl/FeedbackRepositoryImpl.java b/backend/src/main/java/com/supwisdom/dlpay/portal/dao/impl/FeedbackRepositoryImpl.java
index 0487f6c..e53a9ae 100644
--- a/backend/src/main/java/com/supwisdom/dlpay/portal/dao/impl/FeedbackRepositoryImpl.java
+++ b/backend/src/main/java/com/supwisdom/dlpay/portal/dao/impl/FeedbackRepositoryImpl.java
@@ -7,6 +7,7 @@
import com.supwisdom.dlpay.portal.bean.FeedbackSearchBean;
import com.supwisdom.dlpay.portal.dao.FeedbackRepository;
import com.supwisdom.dlpay.portal.domain.TBFeedback;
+import com.supwisdom.dlpay.portal.util.PortalConstant;
import org.hibernate.transform.Transformers;
import org.jetbrains.annotations.NotNull;
@@ -19,7 +20,7 @@
String title = bean.getTitle();
String startdate = bean.getStartdate();
String enddate = bean.getEnddate();
- String replystatus = bean.getReplystatus();
+ String status = bean.getStatus();
String mobileid = bean.getMobileid();
int pageno = bean.getPageno();
int pagesize = bean.getPagesize();
@@ -35,8 +36,12 @@
if (!StringUtil.isEmpty(enddate)) {
sql.append(" and f.fbtime <= :enddate");
}
- if (!StringUtil.isEmpty(replystatus)) {
- sql.append(" and f.replystatus = :replystatus");
+ if (!StringUtil.isEmpty(status)) {
+ if (PortalConstant.FEEDBACK_STATUS_DELETE.equals(status)) {
+ sql.append(" and f.isdelete = :status");
+ } else {
+ sql.append(" and f.replystatus = :status and f.isdelete ='0'");
+ }
}
if (!StringUtil.isEmpty(mobileid)) {
sql.append(" and f.mobileid = :mobileid");
@@ -55,8 +60,14 @@
if (!StringUtil.isEmpty(enddate)) {
f.setParameter("enddate", enddate + "235959");
}
- if (!StringUtil.isEmpty(replystatus)) {
- f.setParameter("replystatus", replystatus);
+ if (!StringUtil.isEmpty(status)) {
+ if (PortalConstant.FEEDBACK_STATUS_DELETE.equals(status)) {
+ f.setParameter("status", PortalConstant.YES);
+ } else if (PortalConstant.FEEDBACK_STATUS_TOREPLY.equals(status)) {
+ f.setParameter("status", PortalConstant.NO);
+ } else {
+ f.setParameter("status", PortalConstant.YES);
+ }
}
if (!StringUtil.isEmpty(mobileid)) {
f.setParameter("mobileid", mobileid);
diff --git a/backend/src/main/java/com/supwisdom/dlpay/portal/domain/TBFeedback.java b/backend/src/main/java/com/supwisdom/dlpay/portal/domain/TBFeedback.java
index 3372084..4fb003c 100644
--- a/backend/src/main/java/com/supwisdom/dlpay/portal/domain/TBFeedback.java
+++ b/backend/src/main/java/com/supwisdom/dlpay/portal/domain/TBFeedback.java
@@ -30,6 +30,8 @@
private String fbip;
@Column(name = "replystatus", length = 1)
private String replystatus;
+ @Column(name = "isdelete", length = 1)
+ private String isdelete;
@Transient
private String username;
@Transient
@@ -126,4 +128,12 @@
public void setReply(TBReply reply) {
this.reply = reply;
}
+
+ public String getIsdelete() {
+ return isdelete;
+ }
+
+ public void setIsdelete(String isdelete) {
+ this.isdelete = isdelete;
+ }
}
diff --git a/backend/src/main/java/com/supwisdom/dlpay/portal/util/PortalConstant.java b/backend/src/main/java/com/supwisdom/dlpay/portal/util/PortalConstant.java
index c6c7129..0e2d14f 100644
--- a/backend/src/main/java/com/supwisdom/dlpay/portal/util/PortalConstant.java
+++ b/backend/src/main/java/com/supwisdom/dlpay/portal/util/PortalConstant.java
@@ -23,4 +23,7 @@
public static final String POINTTASK_STATUS_UNDONE = "undone";
public static final String POINTTASK_STATUS_DONE = "done";
public static final String POINTTASK_STATUS_RECEIVED = "received";
+
+ public static final String FEEDBACK_STATUS_DELETE = "delete";
+ public static final String FEEDBACK_STATUS_TOREPLY = "toreply";
}
diff --git a/backend/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt b/backend/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt
index 8f0983b..bef3e3c 100644
--- a/backend/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt
+++ b/backend/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt
@@ -1282,6 +1282,19 @@
}
/**
+ * 删除留言
+ */
+ @RequestMapping(value = ["/feedback/delete/{fbid}"], method = [RequestMethod.POST])
+ fun deleteFeedback(@PathVariable fbid:String): JsonResult? {
+ val p = SecurityContextHolder.getContext().authentication
+ val user = (mobileApiService.findUserById(p.name)
+ ?: return JsonResult.error("用户不存在,请注册"))
+ val errorMsg = feedbackService.deleteFeedback(fbid, user.uid)
+ ?: return JsonResult.ok()
+ return JsonResult.error(errorMsg)
+ }
+
+ /**
* 查询用户总积分
*/
@Suppress("UNCHECKED_CAST")
diff --git a/backend/src/main/kotlin/com/supwisdom/dlpay/portal/bean/FeedbackSearchBean.kt b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/bean/FeedbackSearchBean.kt
index 07826b9..87c2da1 100644
--- a/backend/src/main/kotlin/com/supwisdom/dlpay/portal/bean/FeedbackSearchBean.kt
+++ b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/bean/FeedbackSearchBean.kt
@@ -5,7 +5,7 @@
var title: String = ""
var startdate: String = ""
var enddate: String = ""
- var replystatus: String = ""
+ var status: String = ""
var pageno: Int = 0
var pagesize: Int = 10
var mobileid: String = ""
diff --git a/backend/src/main/kotlin/com/supwisdom/dlpay/portal/dao/FeedbackDao.kt b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/dao/FeedbackDao.kt
index 58d4d5f..94d9799 100644
--- a/backend/src/main/kotlin/com/supwisdom/dlpay/portal/dao/FeedbackDao.kt
+++ b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/dao/FeedbackDao.kt
@@ -6,5 +6,5 @@
@Repository
interface FeedbackDao : JpaRepository<TBFeedback, String>, FeedbackRepository {
- fun getByFbidAndMobileid(fbid: String, mobileid: String):TBFeedback?
+ fun getByFbidAndMobileidAndIsdelete(fbid: String, mobileid: String, isdelete: String): TBFeedback?
}
\ No newline at end of file
diff --git a/backend/src/main/kotlin/com/supwisdom/dlpay/portal/service/FeedbackService.kt b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/service/FeedbackService.kt
index 5a22ae8..e2f4ea7 100644
--- a/backend/src/main/kotlin/com/supwisdom/dlpay/portal/service/FeedbackService.kt
+++ b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/service/FeedbackService.kt
@@ -23,4 +23,7 @@
@Transactional
fun getFeedbackDetail(fbid: String, mobileid: String): TBFeedback?
+
+ @Transactional
+ fun deleteFeedback(fbid: String, mobileid: String): String?
}
\ No newline at end of file
diff --git a/backend/src/main/kotlin/com/supwisdom/dlpay/portal/service/Impl/FeedbackServiceImpl.kt b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/service/Impl/FeedbackServiceImpl.kt
index b4f5e70..1718ca3 100644
--- a/backend/src/main/kotlin/com/supwisdom/dlpay/portal/service/Impl/FeedbackServiceImpl.kt
+++ b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/service/Impl/FeedbackServiceImpl.kt
@@ -2,10 +2,7 @@
import com.supwisdom.dlpay.framework.jpa.page.Pagination
import com.supwisdom.dlpay.framework.service.SystemUtilService
-import com.supwisdom.dlpay.framework.util.StringUtil
-import com.supwisdom.dlpay.mobile.bean.FeedbackBean
import com.supwisdom.dlpay.mobile.bean.PictureBean
-import com.supwisdom.dlpay.mobile.service.MobileUserService
import com.supwisdom.dlpay.portal.bean.FeedbackSearchBean
import com.supwisdom.dlpay.portal.dao.AnnexDao
import com.supwisdom.dlpay.portal.dao.FeedbackDao
@@ -27,8 +24,6 @@
@Autowired
lateinit var systemUtilService: SystemUtilService
@Autowired
- lateinit var mobileUserService: MobileUserService
- @Autowired
lateinit var annexDao: AnnexDao
@Suppress("UNCHECKED_CAST")
@@ -50,6 +45,9 @@
val optional = feedbackDao.findById(reply.fbid)
return if (optional.isPresent) {
val feedback = optional.get()
+ if (feedback.isdelete == PortalConstant.YES) {
+ return "不能回复用户已删除的留言"
+ }
reply.updatetime = systemUtilService.sysdatetime.hostdatetime
replyDao.save(reply)
feedback.replystatus = PortalConstant.YES
@@ -64,6 +62,7 @@
feedback.apply {
this.fbtime = systemUtilService.sysdatetime.hostdatetime
this.replystatus = PortalConstant.NO
+ this.isdelete = PortalConstant.NO
}
val saved = feedbackDao.save(feedback)
if (pictures.isNotEmpty()) {
@@ -81,7 +80,7 @@
}
override fun getFeedbackDetail(fbid: String, mobileid: String): TBFeedback? {
- val feedback = feedbackDao.getByFbidAndMobileid(fbid,mobileid)
+ val feedback = feedbackDao.getByFbidAndMobileidAndIsdelete(fbid,mobileid,PortalConstant.NO)
?:return null
if (feedback.replystatus == PortalConstant.YES) {
val replayList = replyDao.getAllByFbid(fbid)
@@ -91,4 +90,12 @@
}
return feedback
}
+
+ override fun deleteFeedback(fbid: String, mobileid: String): String? {
+ val feedback = feedbackDao.getByFbidAndMobileidAndIsdelete(fbid,mobileid,PortalConstant.NO)
+ ?:return "该留言不存在"
+ feedback.isdelete = PortalConstant.YES
+ feedbackDao.save(feedback)
+ return null
+ }
}
\ No newline at end of file
diff --git a/frontend/src/components/Home.vue b/frontend/src/components/Home.vue
new file mode 100644
index 0000000..0277ea9
--- /dev/null
+++ b/frontend/src/components/Home.vue
@@ -0,0 +1,111 @@
+<template>
+ <div class="m-map">
+ <div v-if="placeSearch" class="search">
+ <input v-model="searchKey" type="text" placeholder="请输入关键字">
+ <button type="button" @click="handleSearch">搜索</button>
+ <div v-show="searchKey" id="js-result" class="result" />
+ </div>
+ <div id="js-container" class="map" />
+ </div>
+</template>
+
+<script>
+import remoteLoad from '@/utils/remoteLoad.js'
+import { MapKey, MapCityName } from '@/utils/remoteLoad.js'
+export default {
+ props: ['lat', 'lng'],
+ data() {
+ return {
+ searchKey: '',
+ placeSearch: null,
+ dragStatus: false,
+ AMapUI: null,
+ AMap: null
+ }
+ },
+ watch: {
+ searchKey() {
+ if (this.searchKey === '') {
+ this.placeSearch.clear()
+ }
+ }
+ },
+ async created() {
+ // 已载入高德地图API,则直接初始化地图
+ if (window.AMap && window.AMapUI) {
+ this.initMap()
+ // 未载入高德地图API,则先载入API再初始化
+ } else {
+ await remoteLoad(`http://webapi.amap.com/maps?v=1.4.15&key=${MapKey}`)
+ await remoteLoad('http://webapi.amap.com/ui/1.0/main.js')
+ this.initMap()
+ }
+ },
+ methods: {
+ // 搜索
+ handleSearch() {
+ if (this.searchKey) {
+ this.placeSearch.search(this.searchKey)
+ }
+ },
+ // 实例化地图
+ initMap() {
+ // 加载PositionPicker,loadUI的路径参数为模块名中 'ui/' 之后的部分
+ const AMapUI = this.AMapUI = window.AMapUI
+ const AMap = this.AMap = window.AMap
+ AMapUI.loadUI(['misc/PositionPicker'], PositionPicker => {
+ const mapConfig = {
+ zoom: 16,
+ cityName: MapCityName
+ }
+ if (this.lat && this.lng) {
+ mapConfig.center = [this.lng, this.lat]
+ }
+ const map = new AMap.Map('js-container', mapConfig)
+ // 加载地图搜索插件
+ AMap.service('AMap.PlaceSearch', () => {
+ this.placeSearch = new AMap.PlaceSearch({
+ pageSize: 5,
+ pageIndex: 1,
+ citylimit: true,
+ city: MapCityName,
+ map: map,
+ panel: 'js-result'
+ })
+ })
+ // 启用工具条
+ AMap.plugin(['AMap.ToolBar'], function() {
+ map.addControl(new AMap.ToolBar({
+ position: 'RB'
+ }))
+ })
+ // 创建地图拖拽
+ const positionPicker = new PositionPicker({
+ mode: 'dragMap', // 设定为拖拽地图模式,可选'dragMap'、'dragMarker',默认为'dragMap'
+ map: map // 依赖地图对象
+ })
+ // 拖拽完成发送自定义 drag 事件
+ positionPicker.on('success', positionResult => {
+ // 过滤掉初始化地图后的第一次默认拖放
+ if (!this.dragStatus) {
+ this.dragStatus = true
+ } else {
+ this.$emit('drag', positionResult)
+ }
+ })
+ // 启动拖放
+ positionPicker.start()
+ })
+ }
+ }
+}
+</script>
+
+<style lang="css">
+.m-map{ min-width: 500px; min-height: 300px; position: relative; }
+.m-map .map{ width: 100%; height: 100%; }
+.m-map .search{ position: absolute; top: 10px; left: 10px; width: 285px; z-index: 1; }
+.m-map .search input{ width: 180px; border: 1px solid #ccc; line-height: 20px; padding: 5px; outline: none; }
+.m-map .search button{ line-height: 26px; background: #fff; border: 1px solid #ccc; width: 50px; text-align: center; }
+.m-map .result{ max-height: 300px; overflow: auto; margin-top: 10px; }
+</style>
diff --git a/frontend/src/utils/remoteLoad.js b/frontend/src/utils/remoteLoad.js
new file mode 100644
index 0000000..2b798c8
--- /dev/null
+++ b/frontend/src/utils/remoteLoad.js
@@ -0,0 +1,52 @@
+export default function remoteLoad(url, hasCallback) {
+ return createScript(url)
+ /**
+ * 创建script
+ * @param url
+ * @returns {Promise}
+ */
+ function createScript(url) {
+ var scriptElement = document.createElement('script')
+ document.body.appendChild(scriptElement)
+ var promise = new Promise((resolve, reject) => {
+ scriptElement.addEventListener('load', e => {
+ removeScript(scriptElement)
+ if (!hasCallback) {
+ resolve(e)
+ }
+ }, false)
+
+ scriptElement.addEventListener('error', e => {
+ removeScript(scriptElement)
+ reject(e)
+ }, false)
+
+ if (hasCallback) {
+ window.____callback____ = function() {
+ resolve()
+ window.____callback____ = null
+ }
+ }
+ })
+
+ if (hasCallback) {
+ url += '&callback=____callback____'
+ }
+
+ scriptElement.src = url
+
+ return promise
+ }
+
+ /**
+ * 移除script标签
+ * @param scriptElement script dom
+ */
+ function removeScript(scriptElement) {
+ document.body.removeChild(scriptElement)
+ }
+}
+// 高德地图 key
+export const MapKey = 'd69cdfdc1711fc7c318eb7e1a0664976'
+// 地图限定城市
+export const MapCityName = '大理'
diff --git a/frontend/src/views/feedback/index.vue b/frontend/src/views/feedback/index.vue
index eb0723b..95b0835 100644
--- a/frontend/src/views/feedback/index.vue
+++ b/frontend/src/views/feedback/index.vue
@@ -32,7 +32,7 @@
/>
<div class="filter-item" style="margin-right:15px">留言状态</div>
<el-select
- v-model="formData.replystatus"
+ v-model="formData.status"
style="width:200px;margin-right:100px"
>
<el-option
@@ -75,7 +75,8 @@
</el-table-column>
<el-table-column label="状态" align="center" width="100">
<template slot-scope="{row}">
- <el-tag v-if="row.replystatus==='0'" size="medium">待回复</el-tag>
+ <el-tag v-if="row.isdelete==='1'" type="danger" size="medium">已删除</el-tag>
+ <el-tag v-else-if="row.replystatus==='0'" size="medium">待回复</el-tag>
<el-tag v-else type="success" size="medium">已回复</el-tag>
</template>
</el-table-column>
@@ -89,7 +90,7 @@
<el-tooltip class="item" effect="dark" content="查看详情" placement="bottom">
<el-button icon="el-icon-search" circle size="mini" @click="openDetailDialog(row)" />
</el-tooltip>
- <el-tooltip class="item" effect="dark" content="回复" placement="bottom">
+ <el-tooltip v-if="row.isdelete==='0'" class="item" effect="dark" content="回复" placement="bottom">
<el-button type="primary" icon="el-icon-edit" circle size="mini" @click="openReplyDialog(row)" />
</el-tooltip>
</template>
@@ -122,7 +123,8 @@
<el-table-column align="center">
<template slot="header" slot-scope="{}">
<span>当前留言状态:
- <span v-if="currentFeedback.replystatus === '0'" style="color:#409EFF">待回复</span>
+ <span v-if="currentFeedback.isdelete === '1'" style="color:#F56C6C">已删除</span>
+ <span v-else-if="currentFeedback.replystatus === '0'" style="color:#409EFF">待回复</span>
<span v-else style="color:#67C23A">已回复</span>
</span>
</template>
@@ -250,7 +252,7 @@
formData: {
phone: '',
title: '',
- replystatus: '',
+ status: '',
startdate: '',
enddate: '',
pageno: 1,
@@ -264,11 +266,14 @@
label: '所有'
},
{
- value: '0',
+ value: 'toreply',
label: '待回复'
}, {
- value: '1',
+ value: 'replyed',
label: '已回复'
+ }, {
+ value: 'delete',
+ label: '已删除'
}],
pickerOptions: {
shortcuts: [{
@@ -337,7 +342,7 @@
clearFilter() {
this.formData.phone = ''
this.formData.title = ''
- this.formData.replystatus = ''
+ this.formData.status = ''
this.queryDate = null
},
dateFormat(date) {
@@ -381,7 +386,6 @@
if (response.list) {
reply = response.list[0]
}
- console.log(reply.replycontent)
const replyContent = {
title: '回复内容',
content: reply.replycontent,
diff --git a/frontend/src/views/outlets/index.vue b/frontend/src/views/outlets/index.vue
index 60f3401..4814982 100644
--- a/frontend/src/views/outlets/index.vue
+++ b/frontend/src/views/outlets/index.vue
@@ -34,7 +34,7 @@
>
<div>
<el-form ref="outletsForm" :model="outletsForm" :rules="rules" label-width="100px">
- <el-form-item label="网点名称" prop="title" class="form-input-item">
+ <el-form-item label="网点名称" prop="name" class="form-input-item">
<el-input
v-model="outletsForm.name"
maxlength="30"
@@ -50,17 +50,42 @@
style="width:80%"
/>
</el-form-item>
- <el-form-item label="问答内容" prop="content">
+ <el-form-item label="业务范围" prop="businescope" class="form-input-item">
<el-input
- v-model="outletsForm.content"
- type="textarea"
- maxlength="230"
- :rows="8"
- placeholder=""
+ v-model="outletsForm.businescope"
+ maxlength="50"
show-word-limit
style="width:80%"
/>
</el-form-item>
+ <el-form-item label="联系电话" prop="tel" class="form-input-item">
+ <el-input
+ v-model="outletsForm.tel"
+ maxlength="30"
+ show-word-limit
+ style="width:80%"
+ />
+ </el-form-item>
+ <el-form-item label="营业时间" prop="businessTime" class="form-input-item">
+ <el-time-picker
+ v-model="businessTime"
+ is-range
+ format="HH:mm"
+ range-separator="至"
+ start-placeholder="开始时间"
+ end-placeholder="结束时间"
+ placeholder="选择时间范围"
+ />
+ </el-form-item>
+ <el-card style="width:550px">
+ <i style="position: absolute;font-size:50px;z-index: 999999;margin-left:81% " class="el-icon-circle-close close-map-btn" />
+ <div class="g-wraper">
+ <div class="m-part">
+ <mapDrag class="mapbox" @drag="dragMap" />
+ </div>
+ </div>
+ </el-card>
+
</el-form>
</div>
<div style="text-align:center">
@@ -75,10 +100,22 @@
</div>
</template>
<script>
+import mapDrag from '@/components/Home.vue'
export default {
name: 'Outlets',
+ components: {
+ mapDrag
+ },
data() {
return {
+ dragData: {
+ lng: null,
+ lat: null,
+ address: null,
+ nearestJunction: null,
+ nearestRoad: null,
+ nearestPOI: null
+ },
outletsDialogVisible: false,
formData: {
name: '',
@@ -86,6 +123,7 @@
pageno: 1,
pagesize: 10
},
+ businessTime: null,
listLoading: false,
tableKey: 0,
list: null,
@@ -98,16 +136,30 @@
ordernum: 1
},
rules: {
- title: [
+ name: [
{ required: true, message: '请输入问答标题', trigger: 'blur' }
],
content: [
{ required: true, message: '请输入问答内容', trigger: 'blur' }
+ ],
+ address: [
+ { required: true, message: '请输入问答内容', trigger: 'blur' }
]
}
}
},
methods: {
+ dragMap(data) {
+ console.log(data)
+ this.dragData = {
+ lng: data.position.lng,
+ lat: data.position.lat,
+ address: data.address,
+ nearestJunction: data.nearestJunction,
+ nearestRoad: data.nearestRoad,
+ nearestPOI: data.nearestPOI
+ }
+ },
addOutlets() {
this.title = '录入网点'
this.resetForm('outletsForm')
@@ -127,3 +179,28 @@
}
}
</script>
+<style>
+body{ margin: 0; }
+.page-header{
+ color: #fff; text-align: center; background: #159957;
+ background-image: -webkit-linear-gradient(330deg,#155799,#159957);
+ background-image: linear-gradient(120deg,#155799,#159957);
+ padding: 3rem 4rem; margin-bottom: 30px;
+}
+.page-header h1{ margin: 0; font-size: 40px; }
+.page-header p{ color: #ccc; margin: 0; margin-bottom: 30px; }
+.page-header a{ display: inline-block; border: 1px solid #fff; margin-right: 10px; line-height: 40px; padding: 0 20px; border-radius: 4px; color: #fff; text-decoration: none; transition: all .3s; }
+.page-header a:hover{ background: #fff; color: #333; }
+.g-wraper{ width: 1000px; margin: 0 auto; color: #666; font-size: 16px; line-height: 30px; }
+.m-part::after{ content: ''; display: block; clear: both; }
+.m-part .title{ font-size: 30px; line-height: 60px; margin-bottom: 10px; color: #333; }
+.m-part .mapbox{ width: 550px; height: 400px;float: left; }
+.m-part .info{ margin: 0; padding: 0; list-style: none; line-height: 30px; margin-left: 620px; }
+.m-part .info span{ display: block; color: #999; }
+.m-part ol{ line-height: 40px; margin-left: 0; padding-left: 0; }
+.m-part pre{ padding: 10px 20px; line-height: 30px; border-radius: 3px; box-shadow: 0 0 15px rgba(0,0,0,.5); }
+.m-footer{ background: #eee; line-height: 60px; text-align: center; color: #999; font-size: 12px; }
+.m-footer a{ margin: 0 5px; color: #999; text-decoration: none; }
+.el-card__body {padding:0 !important}
+.close-map-btn {color: #f7f7fc;}
+</style>
diff --git a/frontend/vue.config.js b/frontend/vue.config.js
index 19b8cb8..db6370a 100644
--- a/frontend/vue.config.js
+++ b/frontend/vue.config.js
@@ -54,6 +54,9 @@
configureWebpack: {
// provide the app's title in webpack's name field, so that
// it can be accessed in index.html to inject the correct title.
+ externals: {
+ AMap: 'window.AMap'
+ },
name: name,
resolve: {
alias: {