Merge remote-tracking branch 'origin/main'
This commit is contained in:
@@ -170,6 +170,8 @@ security:
|
|||||||
- /oa/attendanceRecord/**
|
- /oa/attendanceRecord/**
|
||||||
- /oa/oaWarehouse/**
|
- /oa/oaWarehouse/**
|
||||||
- /oa/oaWarehouseMaster/**
|
- /oa/oaWarehouseMaster/**
|
||||||
|
# 高德逆地理(经纬度转城市等,供前端/H5 调用)
|
||||||
|
- /oa/amap/**
|
||||||
|
|
||||||
# MyBatisPlus配置
|
# MyBatisPlus配置
|
||||||
# https://baomidou.com/config/
|
# https://baomidou.com/config/
|
||||||
|
|||||||
@@ -2,13 +2,20 @@ package com.ruoyi.framework.config;
|
|||||||
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class RestTemplateConfig {
|
public class RestTemplateConfig {
|
||||||
|
|
||||||
|
private static final int CONNECT_TIMEOUT_MS = 5_000;
|
||||||
|
private static final int READ_TIMEOUT_MS = 15_000;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public RestTemplate restTemplate() {
|
public RestTemplate restTemplate() {
|
||||||
return new RestTemplate();
|
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
|
||||||
|
factory.setConnectTimeout(CONNECT_TIMEOUT_MS);
|
||||||
|
factory.setReadTimeout(READ_TIMEOUT_MS);
|
||||||
|
return new RestTemplate(factory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package com.ruoyi.oa.controller;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.R;
|
||||||
|
import com.ruoyi.oa.domain.vo.AmapCityNameVo;
|
||||||
|
import com.ruoyi.oa.service.IOaAmapGeocodeService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.validation.constraints.DecimalMax;
|
||||||
|
import javax.validation.constraints.DecimalMin;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 高德地图:经纬度逆地理编码(城市名等)
|
||||||
|
*/
|
||||||
|
@Validated
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/oa/amap")
|
||||||
|
public class OaAmapController extends BaseController {
|
||||||
|
|
||||||
|
private final IOaAmapGeocodeService oaAmapGeocodeService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据经纬度获取城市名称(高德逆地理编码)
|
||||||
|
*/
|
||||||
|
@GetMapping("/city")
|
||||||
|
public R<AmapCityNameVo> cityByLocation(
|
||||||
|
@NotNull(message = "经度不能为空")
|
||||||
|
@DecimalMin(value = "-180.0", message = "经度范围无效")
|
||||||
|
@DecimalMax(value = "180.0", message = "经度范围无效")
|
||||||
|
@RequestParam Double longitude,
|
||||||
|
@NotNull(message = "纬度不能为空")
|
||||||
|
@DecimalMin(value = "-90.0", message = "纬度范围无效")
|
||||||
|
@DecimalMax(value = "90.0", message = "纬度范围无效")
|
||||||
|
@RequestParam Double latitude
|
||||||
|
) {
|
||||||
|
AmapCityNameVo vo = oaAmapGeocodeService.reverseGeocodeCity(longitude, latitude);
|
||||||
|
return R.ok(vo);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.ruoyi.oa.domain.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 高德逆地理编码:城市名称(及可选行政区信息,便于展示/调试)
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class AmapCityNameVo implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 城市名(直辖市、省直辖等场景可能为省名或区名,与高德 addressComponent 一致) */
|
||||||
|
private String cityName;
|
||||||
|
|
||||||
|
/** 省 */
|
||||||
|
private String province;
|
||||||
|
|
||||||
|
/** 区/县 */
|
||||||
|
private String district;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.ruoyi.oa.service;
|
||||||
|
|
||||||
|
import com.ruoyi.oa.domain.vo.AmapCityNameVo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 高德地图逆地理编码(经纬度 → 城市等)
|
||||||
|
*/
|
||||||
|
public interface IOaAmapGeocodeService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据经纬度解析城市名称等信息
|
||||||
|
*
|
||||||
|
* @param longitude 经度
|
||||||
|
* @param latitude 纬度
|
||||||
|
* @return 非 null;解析失败时 cityName 等可能为空
|
||||||
|
*/
|
||||||
|
AmapCityNameVo reverseGeocodeCity(Double longitude, Double latitude);
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
package com.ruoyi.oa.service.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.ruoyi.oa.domain.vo.AmapCityNameVo;
|
||||||
|
import com.ruoyi.oa.service.IOaAmapGeocodeService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 高德逆地理编码:restapi.amap.com/v3/geocode/regeo
|
||||||
|
* <p>
|
||||||
|
* 配置项:{@code fad.amap.key}(与 {@code application.yml} 中一致)
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class OaAmapGeocodeServiceImpl implements IOaAmapGeocodeService {
|
||||||
|
|
||||||
|
private static final String AMAP_REGEO_URL = "https://restapi.amap.com/v3/geocode/regeo";
|
||||||
|
|
||||||
|
private final RestTemplate restTemplate;
|
||||||
|
|
||||||
|
@Value("${fad.amap.key:}")
|
||||||
|
private String amapKey;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AmapCityNameVo reverseGeocodeCity(Double longitude, Double latitude) {
|
||||||
|
AmapCityNameVo vo = new AmapCityNameVo();
|
||||||
|
if (longitude == null || latitude == null) {
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
if (!StringUtils.hasText(amapKey)) {
|
||||||
|
log.warn("fad.amap.key 未配置,无法调用高德逆地理编码");
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 高德要求:location = 经度,纬度
|
||||||
|
String location = longitude + "," + latitude;
|
||||||
|
String url = UriComponentsBuilder.fromHttpUrl(AMAP_REGEO_URL)
|
||||||
|
.queryParam("key", amapKey)
|
||||||
|
.queryParam("location", location)
|
||||||
|
.queryParam("extensions", "base")
|
||||||
|
.queryParam("batch", "false")
|
||||||
|
.queryParam("output", "JSON")
|
||||||
|
.build(true)
|
||||||
|
.toUriString();
|
||||||
|
|
||||||
|
String body = restTemplate.getForObject(url, String.class);
|
||||||
|
if (!StringUtils.hasText(body)) {
|
||||||
|
log.warn("高德逆地理编码响应为空, location={}", location);
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
JSONObject response = JSONObject.parseObject(body);
|
||||||
|
if (response == null) {
|
||||||
|
log.warn("高德逆地理编码 JSON 解析失败, location={}", location);
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
if (!"1".equals(response.getString("status"))) {
|
||||||
|
String info = response.getString("info");
|
||||||
|
log.warn("高德逆地理编码失败: status={}, info={}, infocode={}",
|
||||||
|
response.getString("status"), info, response.getString("infocode"));
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject regeocode = response.getJSONObject("regeocode");
|
||||||
|
if (regeocode == null) {
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
JSONObject addressComponent = regeocode.getJSONObject("addressComponent");
|
||||||
|
if (addressComponent == null) {
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
String province = nullToEmpty(addressComponent.getString("province"));
|
||||||
|
String district = nullToEmpty(addressComponent.getString("district"));
|
||||||
|
vo.setProvince(province);
|
||||||
|
vo.setDistrict(district);
|
||||||
|
|
||||||
|
String cityName = resolveCityName(addressComponent, province);
|
||||||
|
vo.setCityName(cityName);
|
||||||
|
return vo;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("高德逆地理编码异常, longitude={}, latitude={}, err={}",
|
||||||
|
longitude, latitude, e.getMessage(), e);
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 城市字段:普通城市为字符串;部分省直辖为 [];直辖市可能用省名表示
|
||||||
|
*/
|
||||||
|
private static String resolveCityName(JSONObject addressComponent, String province) {
|
||||||
|
Object cityRaw = addressComponent.get("city");
|
||||||
|
if (cityRaw instanceof JSONArray) {
|
||||||
|
JSONArray arr = (JSONArray) cityRaw;
|
||||||
|
if (!arr.isEmpty()) {
|
||||||
|
return nullToEmpty(arr.getString(0));
|
||||||
|
}
|
||||||
|
return province;
|
||||||
|
}
|
||||||
|
String city = addressComponent.getString("city");
|
||||||
|
if (StringUtils.hasText(city) && !"[]".equals(city)) {
|
||||||
|
return city.trim();
|
||||||
|
}
|
||||||
|
return province;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String nullToEmpty(String s) {
|
||||||
|
return s == null ? "" : s.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
15
ruoyi-ui/src/api/oa/amap.js
Normal file
15
ruoyi-ui/src/api/oa/amap.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据经纬度逆地理编码获取城市等信息(后端转发高德)
|
||||||
|
* @param {number} longitude 经度
|
||||||
|
* @param {number} latitude 纬度
|
||||||
|
*/
|
||||||
|
export function getCityByLocation (longitude, latitude) {
|
||||||
|
return request({
|
||||||
|
url: '/oa/amap/city',
|
||||||
|
method: 'get',
|
||||||
|
params: { longitude, latitude },
|
||||||
|
timeout: 15000
|
||||||
|
})
|
||||||
|
}
|
||||||
98
ruoyi-ui/src/utils/geolocationWorkPlace.js
Normal file
98
ruoyi-ui/src/utils/geolocationWorkPlace.js
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
import { getCityByLocation } from '@/api/oa/amap'
|
||||||
|
|
||||||
|
const GEO_OPTIONS = {
|
||||||
|
enableHighAccuracy: false,
|
||||||
|
timeout: 20000,
|
||||||
|
maximumAge: 120000
|
||||||
|
}
|
||||||
|
|
||||||
|
export const EMPTY_GEOCODE = 'EMPTY_GEOCODE'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 AmapCityNameVo 格式化为展示用工作地点字符串
|
||||||
|
*/
|
||||||
|
export function formatWorkPlaceFromAmap (vo) {
|
||||||
|
if (!vo) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
const province = (vo.province || '').trim()
|
||||||
|
const cityName = (vo.cityName || '').trim()
|
||||||
|
const district = (vo.district || '').trim()
|
||||||
|
const parts = []
|
||||||
|
if (province) {
|
||||||
|
parts.push(province)
|
||||||
|
}
|
||||||
|
if (cityName && cityName !== province) {
|
||||||
|
parts.push(cityName)
|
||||||
|
}
|
||||||
|
if (district) {
|
||||||
|
parts.push(district)
|
||||||
|
}
|
||||||
|
const joined = parts.join(' ').trim()
|
||||||
|
return joined || cityName || province || ''
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCurrentPositionAsync () {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (typeof navigator === 'undefined' || !navigator.geolocation) {
|
||||||
|
reject(new Error('BROWSER_UNSUPPORTED'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
navigator.geolocation.getCurrentPosition(
|
||||||
|
position => resolve(position),
|
||||||
|
err => reject(err),
|
||||||
|
GEO_OPTIONS
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 浏览器定位 + 后端逆地理 → 工作地点字符串
|
||||||
|
* @returns {Promise<string>}
|
||||||
|
*/
|
||||||
|
export async function resolveWorkPlaceFromBrowser () {
|
||||||
|
const position = await getCurrentPositionAsync()
|
||||||
|
const { longitude, latitude } = position.coords
|
||||||
|
const res = await getCityByLocation(longitude, latitude)
|
||||||
|
const vo = res && res.data
|
||||||
|
const text = formatWorkPlaceFromAmap(vo)
|
||||||
|
if (!text) {
|
||||||
|
const err = new Error(EMPTY_GEOCODE)
|
||||||
|
console.warn('[workPlace] 逆地理结果为空', { longitude, latitude, vo })
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将定位/逆地理错误转换为用户可读文案
|
||||||
|
*/
|
||||||
|
export function geolocationUserMessage (err) {
|
||||||
|
if (!err) {
|
||||||
|
return '获取工作地点失败'
|
||||||
|
}
|
||||||
|
if (err.message === 'BROWSER_UNSUPPORTED') {
|
||||||
|
return '当前浏览器不支持定位,请更换浏览器或使用 HTTPS 访问后重试'
|
||||||
|
}
|
||||||
|
if (err.message === EMPTY_GEOCODE) {
|
||||||
|
return '无法根据当前位置解析城市,请稍后重试;若持续失败请联系管理员检查高德地图配置(fad.amap.key)'
|
||||||
|
}
|
||||||
|
const code = err.code
|
||||||
|
if (code === 1) {
|
||||||
|
return '您已拒绝定位权限,请在浏览器设置中允许本站点定位后点击「重新获取定位」'
|
||||||
|
}
|
||||||
|
if (code === 2) {
|
||||||
|
return '暂时无法获取位置信息,请到信号较好处点击「重新获取定位」重试'
|
||||||
|
}
|
||||||
|
if (code === 3) {
|
||||||
|
return '定位请求超时,请检查网络后点击「重新获取定位」重试'
|
||||||
|
}
|
||||||
|
const msg = err.message || ''
|
||||||
|
if (msg.includes('timeout') || msg.includes('超时')) {
|
||||||
|
return '接口请求超时,请稍后点击「重新获取定位」重试'
|
||||||
|
}
|
||||||
|
if (msg.includes('Network Error') || msg.includes('网络')) {
|
||||||
|
return '网络异常,请检查连接后点击「重新获取定位」重试'
|
||||||
|
}
|
||||||
|
return '获取工作地点失败,请点击「重新获取定位」重试'
|
||||||
|
}
|
||||||
@@ -87,7 +87,19 @@
|
|||||||
</el-alert>
|
</el-alert>
|
||||||
<el-form ref="form" :model="form" :rules="rules" label-width="96px">
|
<el-form ref="form" :model="form" :rules="rules" label-width="96px">
|
||||||
<el-form-item label="工作地点" prop="workPlace">
|
<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>
|
||||||
<el-form-item label="是否出差" prop="isTrip">
|
<el-form-item label="是否出差" prop="isTrip">
|
||||||
<el-radio-group v-model="form.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 { listUser } from "@/api/system/user";
|
||||||
import ProjectSelect from "@/components/fad-service/ProjectSelect";
|
import ProjectSelect from "@/components/fad-service/ProjectSelect";
|
||||||
import ProjectReportDetail from "@/views/oa/project/report/components/ProjectReportDetail.vue";
|
import ProjectReportDetail from "@/views/oa/project/report/components/ProjectReportDetail.vue";
|
||||||
|
import {
|
||||||
|
EMPTY_GEOCODE,
|
||||||
|
geolocationUserMessage,
|
||||||
|
resolveWorkPlaceFromBrowser
|
||||||
|
} from "@/utils/geolocationWorkPlace";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "ProjectReport",
|
name: "ProjectReport",
|
||||||
components: { ProjectReportDetail, ProjectSelect },
|
components: { ProjectReportDetail, ProjectSelect },
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
workPlaceLoading: false,
|
||||||
|
workPlaceLocateError: "",
|
||||||
// 按钮loading
|
// 按钮loading
|
||||||
buttonLoading: false,
|
buttonLoading: false,
|
||||||
detailVisible: false,
|
detailVisible: false,
|
||||||
@@ -230,6 +249,50 @@ export default {
|
|||||||
this.getUserList();
|
this.getUserList();
|
||||||
},
|
},
|
||||||
methods: {
|
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 格式 */
|
/** 格式化日期为 yyyy-MM-dd 格式 */
|
||||||
formatDate (date) {
|
formatDate (date) {
|
||||||
const year = date.getFullYear();
|
const year = date.getFullYear();
|
||||||
@@ -258,11 +321,15 @@ export default {
|
|||||||
this.reset();
|
this.reset();
|
||||||
this.open = true;
|
this.open = true;
|
||||||
this.title = "补录项目报工";
|
this.title = "补录项目报工";
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.syncWorkPlaceFromGeolocation({ silent: true, force: false });
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/** 检查今日报工 */
|
/** 检查今日报工(须返回 Promise,供新增时 .finally 打开弹窗) */
|
||||||
checkTodayReport () {
|
checkTodayReport () {
|
||||||
getTodayProjectReport().then(response => {
|
return getTodayProjectReport()
|
||||||
|
.then(response => {
|
||||||
if (response.data && response.data.reportId) {
|
if (response.data && response.data.reportId) {
|
||||||
this.hasTodayReport = true;
|
this.hasTodayReport = true;
|
||||||
this.todayReportId = response.data.reportId;
|
this.todayReportId = response.data.reportId;
|
||||||
@@ -274,7 +341,8 @@ export default {
|
|||||||
this.hasTodayReport = false;
|
this.hasTodayReport = false;
|
||||||
this.todayReportId = null;
|
this.todayReportId = null;
|
||||||
}
|
}
|
||||||
}).catch(() => {
|
})
|
||||||
|
.catch(() => {
|
||||||
this.hasTodayReport = false;
|
this.hasTodayReport = false;
|
||||||
this.todayReportId = null;
|
this.todayReportId = null;
|
||||||
});
|
});
|
||||||
@@ -313,6 +381,8 @@ export default {
|
|||||||
},
|
},
|
||||||
// 表单重置
|
// 表单重置
|
||||||
reset () {
|
reset () {
|
||||||
|
this.workPlaceLoading = false;
|
||||||
|
this.workPlaceLocateError = "";
|
||||||
this.form = {
|
this.form = {
|
||||||
reportId: undefined,
|
reportId: undefined,
|
||||||
handler: undefined,
|
handler: undefined,
|
||||||
@@ -359,9 +429,15 @@ export default {
|
|||||||
handleAdd () {
|
handleAdd () {
|
||||||
this.reset();
|
this.reset();
|
||||||
this.suppVisible = false;
|
this.suppVisible = false;
|
||||||
this.checkTodayReport();
|
|
||||||
this.open = true;
|
|
||||||
this.title = "添加项目报工";
|
this.title = "添加项目报工";
|
||||||
|
this.checkTodayReport().finally(() => {
|
||||||
|
this.open = true;
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (!this.form.reportId) {
|
||||||
|
this.syncWorkPlaceFromGeolocation({ silent: true, force: false });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
handleUpdate (row) {
|
handleUpdate (row) {
|
||||||
@@ -473,4 +549,11 @@ export default {
|
|||||||
display: block;
|
display: block;
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.work-place-error {
|
||||||
|
color: #f56c6c;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.5;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
Reference in New Issue
Block a user