feat(geolocation): 完善工作地点获取功能

- 新增高德地图逆地理编码接口,支持根据浏览器定位自动获取工作地点。
- 在项目报工页面中实现工作地点的自动更新,用户可通过按钮重新获取定位。
- 添加加载状态和错误提示,提升用户体验。
- 优化相关方法以处理地理位置获取的异步操作。
This commit is contained in:
2026-04-17 13:57:27 +08:00
parent edca68136c
commit 0400398361
4 changed files with 215 additions and 19 deletions

View File

@@ -87,7 +87,19 @@
</el-alert>
<el-form ref="form" :model="form" :rules="rules" label-width="96px">
<el-form-item label="工作地点" prop="workPlace">
<el-input v-model="form.workPlace" placeholder="请输入工作地点" />
<el-input
v-model="form.workPlace"
readonly
:placeholder="workPlaceLoading ? '正在获取定位…' : '请点击「重新获取定位」获取工作地点(不可手动输入)'"
>
<el-button
slot="append"
icon="el-icon-location-outline"
:loading="workPlaceLoading"
@click="refreshWorkPlace"
>重新获取定位</el-button>
</el-input>
<div v-if="workPlaceLocateError" class="work-place-error">{{ workPlaceLocateError }}</div>
</el-form-item>
<el-form-item label="是否出差" prop="isTrip">
<el-radio-group v-model="form.isTrip">
@@ -148,12 +160,19 @@ import { listDept } from "@/api/system/dept";
import { listUser } from "@/api/system/user";
import ProjectSelect from "@/components/fad-service/ProjectSelect";
import ProjectReportDetail from "@/views/oa/project/report/components/ProjectReportDetail.vue";
import {
EMPTY_GEOCODE,
geolocationUserMessage,
resolveWorkPlaceFromBrowser
} from "@/utils/geolocationWorkPlace";
export default {
name: "ProjectReport",
components: { ProjectReportDetail, ProjectSelect },
data () {
return {
workPlaceLoading: false,
workPlaceLocateError: "",
// 按钮loading
buttonLoading: false,
detailVisible: false,
@@ -230,6 +249,50 @@ export default {
this.getUserList();
},
methods: {
/**
* @param {{ silent?: boolean, force?: boolean }} options
*/
async syncWorkPlaceFromGeolocation (options = {}) {
const silent = !!options.silent;
const force = !!options.force;
if (!force && this.form && this.form.reportId) {
return;
}
this.workPlaceLoading = true;
this.workPlaceLocateError = "";
try {
const text = await resolveWorkPlaceFromBrowser();
this.$set(this.form, "workPlace", text);
if (!silent) {
this.$modal.msgSuccess("已根据定位更新工作地点");
}
} catch (e) {
console.error("[projectReport] 工作地点定位失败", e);
const msg = geolocationUserMessage(e);
this.workPlaceLocateError = msg;
this.$set(this.form, "workPlace", undefined);
const isBrowserGeoError =
e &&
(e.code === 1 ||
e.code === 2 ||
e.code === 3 ||
e.message === "BROWSER_UNSUPPORTED" ||
e.message === EMPTY_GEOCODE);
if (isBrowserGeoError) {
this.$modal.msgWarning(msg);
}
} finally {
this.workPlaceLoading = false;
this.$nextTick(() => {
if (this.$refs.form) {
this.$refs.form.validateField("workPlace");
}
});
}
},
refreshWorkPlace () {
this.syncWorkPlaceFromGeolocation({ silent: false, force: true });
},
/** 格式化日期为 yyyy-MM-dd 格式 */
formatDate (date) {
const year = date.getFullYear();
@@ -258,26 +321,31 @@ export default {
this.reset();
this.open = true;
this.title = "补录项目报工";
this.$nextTick(() => {
this.syncWorkPlaceFromGeolocation({ silent: true, force: false });
});
},
/** 检查今日报工 */
/** 检查今日报工(须返回 Promise供新增时 .finally 打开弹窗) */
checkTodayReport () {
getTodayProjectReport().then(response => {
if (response.data && response.data.reportId) {
this.hasTodayReport = true;
this.todayReportId = response.data.reportId;
this.form = {
...this.form,
...response.data
};
} else {
return getTodayProjectReport()
.then(response => {
if (response.data && response.data.reportId) {
this.hasTodayReport = true;
this.todayReportId = response.data.reportId;
this.form = {
...this.form,
...response.data
};
} else {
this.hasTodayReport = false;
this.todayReportId = null;
}
})
.catch(() => {
this.hasTodayReport = false;
this.todayReportId = null;
}
}).catch(() => {
this.hasTodayReport = false;
this.todayReportId = null;
});
});
},
getDeptList () {
@@ -313,6 +381,8 @@ export default {
},
// 表单重置
reset () {
this.workPlaceLoading = false;
this.workPlaceLocateError = "";
this.form = {
reportId: undefined,
handler: undefined,
@@ -359,9 +429,15 @@ export default {
handleAdd () {
this.reset();
this.suppVisible = false;
this.checkTodayReport();
this.open = true;
this.title = "添加项目报工";
this.checkTodayReport().finally(() => {
this.open = true;
this.$nextTick(() => {
if (!this.form.reportId) {
this.syncWorkPlaceFromGeolocation({ silent: true, force: false });
}
});
});
},
/** 修改按钮操作 */
handleUpdate (row) {
@@ -473,4 +549,11 @@ export default {
display: block;
margin-top: 2px;
}
.work-place-error {
color: #f56c6c;
font-size: 12px;
line-height: 1.5;
margin-top: 4px;
}
</style>