RT
烦死了,我就想查个天气需要位置信息,怎么找个省市区的信息怎么费事,一万个api一万个付费,要么就是返回数据一坨看都不想看,乱七八糟的东西,而且响应速度还巨慢无比。 我找这个破api找的心里非常难受,这么基础的东西都付费,还每天100次,不知道开发商怎么想的。 100次,再来个级联查询,每天查50次是吧,前端调试都不够。 这是我在天气api里的调用次数统计,如果算上省市区,因为要搜索两次,会是180次+(编译器每次失焦都会保存编译页面重新运行,api-2)> > 自己动手丰衣足食。
最终效果gif
采用SpringBoot作为后端
依赖jackson,lombok,hutool,需要自己加,这里给出jackson的maven,gradle的有需要自己去maven里找就行了,lombok这里不再补充.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.13.2</version>
</dependency>
省市区数据源(非最新版)
相信我,在绝大部分情况下,够用了。
https://raw.githubusercontent.com/JasonBoy/china-location/master/dist/location.json
前端需求
单机下拉框,看到所有省,点省,看到市,然后用市信息调用api查询天气,所以这里的代码只有两级查询,如有需要可以自行改代码进行最高三级查询到区级。 eg. 安徽省->阜阳市
后端实现
Controller
import com.fasterxml.jackson.core.JsonProcessingException;
import com.orisland.bs.entities.CommonResult;
import com.orisland.bs.service.location;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
@RestController
@Slf4j
@CrossOrigin
public class ApiController {
@GetMapping("/privince")
public CommonResult getPrivince() throws JsonProcessingException {
return new CommonResult(200, "success", location.getPrivince());
}
@GetMapping("/city/{code}")
public CommonResult getCity(@PathVariable("code") String city) throws JsonProcessingException {
return new CommonResult(200, "success", location.getCity(city));
}
}
location
Tool.JsonTool 这个东西只是为了省去jackson的mapper,不再贴代码。
import cn.hutool.core.io.resource.ResourceUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.orisland.bs.Tool.JsonTool;
import java.util.*;
public class location {
public static List<Object> getPrivince() throws JsonProcessingException {
String s = ResourceUtil.readUtf8Str("location.json");
JsonNode jsonNode = JsonTool.mapper.readTree(s);
Iterator<Map.Entry<String, JsonNode>> fields = jsonNode.fields();
List<Object> res = new ArrayList<>();
while (fields.hasNext()){
JsonNode jsonNode1 = jsonNode.get(fields.next().getKey());
String name = jsonNode1.get("name").toString();
String code = jsonNode1.get("code").toString();
Map<String, String> item = new HashMap<>();
item.put("name", privinceName.substring(1, name.length() - 1));
item.put("code", privinceCode.substring(1, code.length() - 1));
res.add(item);
}
return res;
}
public static List<Object> getCity(String cityCode) throws JsonProcessingException {
String s = ResourceUtil.readUtf8Str("location.json");
JsonNode jsonNode = JsonTool.mapper.readTree(s);
JsonNode jsonNode1 = jsonNode.get(cityCode).get("cities");
Iterator<Map.Entry<String, JsonNode>> fields = jsonNode1.fields();
List<Object> res = new ArrayList<>();
while (fields.hasNext()){
JsonNode jsonNode2 = jsonNode1.get(fields.next().getKey());
Map<String, Object> item = new HashMap<>();
String code = jsonNode2.get("code").toString();
String name = jsonNode2.get("name").toString();
item.put("code", code.substring(1,code.length()-1));
item.put("name", name.substring(1,name.length()-1));
res.add(item);
}
return res;
}
}
CommonResult
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T>{
private Integer code;
private String message;
private T data;
public CommonResult(Integer code, String message){
this(code, message, null);
}
}
查询逻辑
前端为react,使用antd作为组件,本文采用函数式组件不使用类式组件。
<Cascader options={privince} loadData={choose} onChange={onChange} changeOnSelect />
对应方法
const [privince, setPrivince] = useState([]);
const [loading, setLoading] = useState(false);
const location = useRef({});
const city = useRef("");
const getPrivince = useCallback(() => {
request.get("http://localhost:2006/privince")
.then(({data}) => {
if (data.code === 200){
let list= []
data.data.map((item) => {
list = [...list, {
id:item.code,
label:item.name,
value:item.name,
isLeaf:false
}]
})
setPrivince(list)
}
}).catch((err) => {
console.log(err)
}).finally(() => {
})
const choose = useCallback((selectedOptions) => {
const targetOption = selectedOptions[selectedOptions.length - 1];
targetOption.loading = loading;
request.get("http://localhost:2006/city/"+targetOption.id)
.then(({data}) => {
if (data.code === 200){
let list= []
data.data.map((item) => {
list = [...list, {
id:item.code,
label:item.name,
value:item.name,
}]
})
targetOption.children = list
setLoading(false)
setPrivince([...privince])
}
}).catch((err) => {
console.log(err)
}).finally(() => {
})
})
查询天气效果(非常简陋的demo展示)
天气api
免费的(额度很大),放心用。
https://dev.qweather.com/docs/api/
后记
因为在气头上写的代码,所以基本没花什么时间,bug在所难免,结构也没调整和优化,如有需要可以根据自己的需要优化代码。
开发商你的良心不会痛吗? 2022年4月21日19:17:30
|