diff --git a/.umirc.ts b/.umirc.ts index 7bbbab3ec418c387371db8473bbae8ea50764379..5b63a786a761d714a7e86d22230043f081f364d3 100644 --- a/.umirc.ts +++ b/.umirc.ts @@ -14,5 +14,12 @@ export default defineConfig({ /** 开启全局数据流 */ model: {}, request: {}, + proxy: { + "/apis/": { + target: "http://172.23.0.171:9300/", + changeOrigin: true, + pathRewrite: { "^/apis": "" }, + }, + }, npmClient: "yarn", }); diff --git a/src/api/config.ts b/src/api/config.ts index 29d12b631ea937d983c0df277a235b64f2a2e89d..70723886d719f1343bdcd4bd7d0b5c81396a4f61 100644 --- a/src/api/config.ts +++ b/src/api/config.ts @@ -9,6 +9,8 @@ const devConfig = { openApiUrl: "https://api-tfrm-dev.thecover.cn/openApi/gn", /** 当前部署的地址 */ devAppUrl: "http://171.217.92.33:58101/main", + /** */ + dev: "http://172.23.0.171:9300", }; const config = devConfig; diff --git a/src/api/index.tsx b/src/api/index.tsx index 66532d7de559c836d65e1ee485c021c7919ba991..dbbfbde353c445f4d975e223c67a24daffffceb8 100644 --- a/src/api/index.tsx +++ b/src/api/index.tsx @@ -1,5 +1,6 @@ import { request } from "umi"; import config from "./config"; +import { RespResult } from "./core/model/ReqData"; /** * 获取token * @param code @@ -32,3 +33,78 @@ export function getUserinfo(open_id: number, token: string) { }, }); } + +/** + * 上传文件 + * @param formData + * @returns + */ +export function uploadFile(formData: FormData) { + return request<RespResult<{ path: string; name: string }>>( + `/apis/public/api/uploadMedia`, + { + data: formData, + requestType: "form", + method: "post", + } + ); +} +/** + * 上传表单 + * @param form 表单数据 + * @returns + */ +export function submitForm(form: { + address: string; + telphone: number; + problemDesc: string; + reporter: string; + longitude: number; + latitude: number; + belongArea: number; + belongAreaName: string; + fileNames: string; + filePaths: string; +}) { + return request<RespResult<string>>(`/apis/public/api/report`, { + data: form, + method: "post", + requestType: "form", + }); +} + +/** + * 获取报告列表 + * @param phone + * @param pageSize + * @returns + * + * */ +export function getReportList( + phone: string, + pageSize: number, + pageNum: number +) { + return request<RespResult<any[]>>("/apis/public/api/pageMyReportProblems", { + method: "get", + params: { + telphone: phone, + pageSize, + pageNo: pageNum, + }, + }); +} + +/** + * + * @param id 报告id + * @returns + */ +export function getReportDetail(id: string) { + return request<RespResult<any>>("/apis/public/api/queryProblemById", { + method: "get", + params: { + id, + }, + }); +} diff --git a/src/app.ts b/src/app.ts index c7b2b187022224ee96441bd63fa6c7f85872bd15..7cddaee381ba7d13f074cd6b1f0f97dbec07edeb 100644 --- a/src/app.ts +++ b/src/app.ts @@ -2,5 +2,5 @@ import "./global.css"; import { useModel, type RequestConfig } from "umi"; export const request: RequestConfig = { - timeout: 1000, + timeout: 5000, }; diff --git a/src/models/global.ts b/src/models/global.ts index f079e018af027b74f8145e727d3f4316a395c89c..e0df7981a6550ab6563cd8ff956389fc8965532a 100644 --- a/src/models/global.ts +++ b/src/models/global.ts @@ -1,5 +1,6 @@ // 全局共享数据 import { useState } from "react"; +import { UploaderValueItem } from "react-vant"; const useGlobal = () => { const [matterAddress, setMatterAddress] = useState<any>({}); @@ -11,7 +12,9 @@ const useGlobal = () => { * 登录信息 */ const [loginInfo, setLoginInfo] = useState<any>(); - + const [area, setArea] = useState(0); + const [problemDesc, setProblemDesc] = useState(""); + const [fileList, setFileList] = useState<UploaderValueItem[]>([]); return { matterAddress, setMatterAddress, @@ -19,6 +22,12 @@ const useGlobal = () => { setLoginInfo, user, setUser, + area, + setArea, + problemDesc, + setProblemDesc, + fileList, + setFileList, }; }; diff --git a/src/pages/historyDetail.tsx b/src/pages/historyDetail.tsx index fae324681eb8c12cbb6428b4f36a4792e2103e20..7766d053ffa6ec04659421a9e97278b52b99adaa 100644 --- a/src/pages/historyDetail.tsx +++ b/src/pages/historyDetail.tsx @@ -6,46 +6,92 @@ import { Input, Uploader, Button, + Skeleton, + Loading, + Space, } from "react-vant"; import styles from "./historyList.less"; -import { history } from "umi"; +import { history, useLocation } from "umi"; +import { useEffect, useState } from "react"; +import { getReportDetail } from "@/api"; const src = "https://img.yzcdn.cn/vant/cat.jpeg"; const historyDetail = () => { + const location = useLocation(); + + const { id } = location.state as any; + + const [dataSource, setDataSource] = useState<any>(); + const [loading, setLoading] = useState(true); + useEffect(() => { + setLoading(true); + getReportDetail(id).then((res) => { + if (res.data) { + setDataSource(res.data); + setTimeout(() => { + setLoading(false); + }, 200); + } + }); + }, [id]); return ( <div className={styles.container}> - {/* <NavBar - title="问题详情" - onClickLeft={() => history.back()} - leftText="返回" - /> */} - <div className={styles.content}> - <div className={styles.item_title}> - <div> - <div className={styles.item_title_name}>陈平安</div> - <div className={styles.item_title_address}>温江区林泉南街</div> - </div> - <div className={styles.item_time}>2023-03-06 09:16</div> + {loading ? ( + <div className={styles.loadingBox}> + <Loading type="spinner" color="#3f45ff"> + 加载中... + </Loading> </div> - <div className={styles.item_content}> - <p>涌泉街道共和路402号违法宣传标语</p> - <Image width="100" height="100" src={src} /> - <Steps direction="vertical" active={0} style={{ marginTop: 16 }}> - <Steps.Item> - <div>2016-07-12 12:40</div> - <p>尊敬的市民,您所反映的问题已上报</p> - </Steps.Item> - <Steps.Item> - <div>2016-07-12 12:40</div> - <p>尊敬的市民,您所反映的问题已上报</p> - </Steps.Item> - <Steps.Item> - <div>2016-07-12 12:40</div> - <p>尊敬的市民,您所反映的问题已上报</p> - </Steps.Item> - </Steps> + ) : ( + <div className={styles.content}> + <div className={styles.item_title}> + <div className={styles.item_title_name}> + 案件编号:{dataSource?.caseinfo?.MISSION_NUM} + </div> + + <div className={styles.item_time}> + {dataSource?.caseinfo?.INFORM_TIME} + </div> + <div className={styles.item_title_address}> + {dataSource?.caseinfo?.ADDR} + </div> + </div> + <div className={styles.item_content}> + <p>{dataSource?.caseinfo?.PROBLEM_DESC}</p> + <Space> + {dataSource?.attachment?.map((v: any) => { + return ( + <Image + width="100" + height="100" + src={v.CASE_ATTACHMENT_PATH} + /> + ); + })} + </Space> + + <Steps + direction="vertical" + active={dataSource?.process.length - 1} + style={{ marginTop: 16 }} + > + {dataSource?.process?.map((v) => { + return ( + <Steps.Item> + <div>2016-07-12 12:40</div> + <p> + {v?.OPERATION_DESC ?? + "尊敬的市民,您所反映的问题正在处理中"} + </p> + <p>案件状态:{v?.ACTION_NAME}</p> + <p>处理人:{v?.OPERATOR_NAME}</p> + </Steps.Item> + ); + })} + </Steps> + </div> </div> - </div> + )} </div> ); }; diff --git a/src/pages/historyList.less b/src/pages/historyList.less index 61a09b6377883a817e8923351501088523dace74..0e722dbb8208db6370869801547ed8dfa4522b0d 100644 --- a/src/pages/historyList.less +++ b/src/pages/historyList.less @@ -21,11 +21,17 @@ } .item_title { - display: flex; - justify-content: space-between; - align-items: center; + > :first-child { + display: flex; + justify-content: space-between; + align-items: center; + } +} +.item_content { + .item_content_desc { + margin: 8px 0; + } } - .item_time { font-size: 14px; color: #999; @@ -41,3 +47,10 @@ font-size: 14px; color: #999; } + +.loadingBox { + height: 100%; + display: flex; + align-items: center; + justify-content: center; +} diff --git a/src/pages/historyList.tsx b/src/pages/historyList.tsx index a795b005eb1c5b0baf5629837c19f798f54289ce..2c987adef3a0603cccd5bb54d9e09d4bd7c4bfe2 100644 --- a/src/pages/historyList.tsx +++ b/src/pages/historyList.tsx @@ -6,52 +6,103 @@ import { Input, Uploader, Button, + Loading, } from "react-vant"; import styles from "./historyList.less"; import { history } from "umi"; +import { useEffect, useState } from "react"; +import { getReportList } from "@/api"; const src = "https://img.yzcdn.cn/vant/cat.jpeg"; -const Item = (props: any) => { +const Item = ({ data }: { data: any }) => { return ( <div className={styles.item} onClick={() => { - history.push("/historyDetail"); + history.push("/historyDetail", { id: data.CASE_INFO_ID }); }} > <div className={styles.item_title}> - <div> - <div className={styles.item_title_name}>陈平安</div> - <div className={styles.item_title_address}>温江区林泉南街</div> + <div className={styles.item_title_name}> + 案件编号:{data.MISSION_NUM} </div> - <div className={styles.item_time}>2023-03-06 09:16</div> + + <div className={styles.item_time}>{data.INFORM_TIME}</div> + <div className={styles.item_title_address}>{data.ADDR}</div> </div> <div className={styles.item_content}> - <p>涌泉街道共和路402号违法宣传标语</p> - <Image width="100" height="100" src={src} /> - <Steps active={1}> - <Steps.Item>已上报</Steps.Item> - <Steps.Item>未受理</Steps.Item> - <Steps.Item>已立案</Steps.Item> - <Steps.Item>已结束</Steps.Item> - </Steps> + <div className={styles.item_content_desc}>{data.PROBLEM_DESC}</div> + <div style={{ color: "green" }}>{data.rec_status}</div> </div> </div> ); }; const historyList = () => { + const [pagination, setPagination] = useState({ + current: 1, + pageSize: 10, + end: false, + }); + const [dataSource, setDataSource] = useState<any[]>([]); + useEffect(() => { + initData(); + }, []); + const initData = () => { + if (pagination.end) { + return; + } + if (pagination.current === 1) { + setLoading(true); + } + getReportList("123", pagination.pageSize, pagination.current).then( + (res) => { + if (res.data.length === pagination.pageSize) { + setPagination({ + ...pagination, + current: pagination.current + 1, + }); + if (res.data.length < pagination.pageSize) { + setPagination({ + ...pagination, + end: true, + }); + } + } + setDataSource([...dataSource, ...res.data]); + setTimeout(() => { + setLoading(false); + }, 200); + } + ); + }; + const [loading, setLoading] = useState(true); + + const onScroll = (e: React.UIEvent<HTMLDivElement, UIEvent>) => { + /** 判断滚动到底部 */ + if ( + e.currentTarget.scrollTop + e.currentTarget.clientHeight >= + e.currentTarget.scrollHeight - 30 + ) { + if (!pagination.end) { + initData(); + } + } + }; return ( <div className={styles.container}> - {/* <NavBar - title="我的上报" - onClickLeft={() => history.back()} - leftText="返回" - /> */} - <div className={styles.content}> - <Item></Item> - <Item></Item> - <Item></Item> - </div> + {loading ? ( + <div className={styles.loadingBox}> + <Loading type="spinner" color="#3f45ff"> + 加载中... + </Loading> + </div> + ) : ( + <div className={styles.content} onScroll={onScroll}> + {dataSource.map((v) => { + return <Item key={v.CASE_INFO_ID} data={v}></Item>; + })} + </div> + )} </div> ); }; diff --git a/src/pages/locationSearch.tsx b/src/pages/locationSearch.tsx index 33d1e20678b40e9050432b5d631494c5af4a4294..06c5b1dc951e4cf21e5055116b02933f631a6f2a 100644 --- a/src/pages/locationSearch.tsx +++ b/src/pages/locationSearch.tsx @@ -24,6 +24,7 @@ const LocationSearch = () => { location: string; }[] >(); + /** * 获取当前位置 */ @@ -189,87 +190,6 @@ const LocationSearch = () => { </Card> </div> </div> - // <Box flex={1}> - // <Box - // position={'absolute'} - // w={'100%'} - // zIndex={100} - // top={4} - // justifyContent={'center'} - // alignItems={'center'} - // > - // <Input - // w={'80%'} - // bg={'#fff'} - // _focus={{ - // bg: '#fff', - // }} - // value={inputStr} - // onChangeText={setInputStr} - // h={12} - // variant="rounded" - // placeholder="输入位置搜索" - // /> - - // {searchList && searchList.length > 0 ? ( - // <Box w={'100%'} maxH={48}> - // <ScrollView - // w={'100%'} - // contentContainerStyle={{ - // alignItems: 'center', - // }} - // > - // {searchList?.map((v) => { - // return ( - // <TouchableOpacity - // onPress={() => { - // console.log('点击'); - // onSelect(v); - // }} - // style={{ width: '100%', alignItems: 'center' }} - // > - // <Box - // px={2} - // borderBottomWidth={1} - // justifyContent={'center'} - // borderBottomColor={'gray.300'} - // bg={'#fff'} - // minH={12} - // w={'80%'} - // > - // <TextComp numberOfLines={1}> {v.address}</TextComp> - // </Box> - // </TouchableOpacity> - // ); - // })} - // </ScrollView> - // </Box> - // ) : undefined} - // </Box> - - // <Box flex={1} minH={12}> - // <MapView - // compassEnabled={false} - // ref={mapRef} - // initialCameraPosition={{ - // zoom: 18, - // }} - // onPress={(e) => { - // setSearchList([]); - // setCurLocation(e.nativeEvent); - // }} - // onCameraIdle={() => { - // setSearchList([]); - // }} - // onLoad={() => { - // getUserLocation(); - // }} - // > - // <Marker position={curLocation} /> - // </MapView> - // </Box> - - // </Box> ); }; diff --git a/src/pages/main.tsx b/src/pages/main.tsx index dad77249f2ca35b173244014958153bb58dd2629..53e7aff464cd523a58466318078a531c6ec6ede1 100644 --- a/src/pages/main.tsx +++ b/src/pages/main.tsx @@ -13,24 +13,28 @@ const Main = () => { const { loginInfo, user, setUser, setLoginInfo } = useModel("global"); useEffect(() => { - /** 不存在先直接跳转 */ - if (!loginInfo?.token && !window.location.search) { - window.location.href = `${config.thirdPartyFrontEndPageUrl}/authorizedLogin.html?client_id=OM90JPKW&response_type=code&redirect_uri=${config.devAppUrl}`; - return; - } + try { + /** 不存在先直接跳转 */ + if (!loginInfo?.token && !window.location.search) { + window.location.href = `${config.thirdPartyFrontEndPageUrl}/authorizedLogin.html?client_id=OM90JPKW&response_type=code&redirect_uri=${config.devAppUrl}`; + return; + } - if (!loginInfo?.token && window.location.search) { - const params = new URLSearchParams(window.location.search); + if (!loginInfo?.token && window.location.search) { + const params = new URLSearchParams(window.location.search); - if (params.get("code")) { - getToken(params.get("code") as string) - .then((res) => { - setLoginInfo(res.data); - }) - .catch((err) => { - alert(JSON.stringify(err)); - }); + if (params.get("code")) { + getToken(params.get("code") as string) + .then((res) => { + setLoginInfo(res.data); + }) + .catch((err) => { + alert(JSON.stringify(err)); + }); + } } + } catch (error) { + alert(error); } }, []); @@ -38,6 +42,7 @@ const Main = () => { if (!user && loginInfo?.token) { getUserinfo(loginInfo?.openId, loginInfo?.token) .then((res) => { + alert(JSON.stringify(res.data)); setUser(res.data); }) .catch((err) => { diff --git a/src/pages/report.tsx b/src/pages/report.tsx index 7aae55011404d002ffee09f436e0186d4418dbd3..08bdf3e8b9fbd08953c6df8935d9f14de861e79b 100644 --- a/src/pages/report.tsx +++ b/src/pages/report.tsx @@ -9,17 +9,30 @@ import { Picker, Uploader, Button, + UploaderValueItem, + Notify, } from "react-vant"; import { history, useModel } from "umi"; +import { submitForm, uploadFile } from "@/api"; /** * 上报页 * @returns */ const Report = () => { - const { matterAddress } = useModel("global"); + const { + matterAddress, + setMatterAddress, + loginInfo, + user, + area, + setArea, + problemDesc, + setProblemDesc, + fileList, + setFileList, + } = useModel("global"); const [areaVisible, setAreaVisible] = React.useState(false); - const [area, setArea] = useState(0); - console.log(matterAddress); + const columns = [ { text: "广安市城南", value: 511600 }, { text: "广安市城北", value: 511602 }, @@ -34,19 +47,58 @@ const Report = () => { const findName = (id: number) => { return columns.find((v) => v.value == id)?.text; }; + + const handleSubmit = async () => { + /** 校验 */ + if (problemDesc.length === 0) { + Notify.show({ type: "warning", message: "请您描述您的问题" }); + return; + } + if (fileList.length === 0) { + Notify.show({ type: "warning", message: "请您上传问题图片" }); + return; + } + if (area === 0) { + Notify.show({ type: "warning", message: "请您选择所属地区" }); + return; + } + console.log(matterAddress); + if (!matterAddress?.addres || matterAddress?.addres === 0) { + Notify.show({ type: "warning", message: "请您选择事发位置" }); + return; + } + const uploadReq = fileList.map((v) => { + const formData = new FormData(); + + formData.append("file", v.file as File); + + return uploadFile(formData); + }); + + const imgList = (await Promise.all(uploadReq)).map((v) => v.data); + console.log(matterAddress); + const form = { + address: matterAddress.addres, + telphone: 123, + problemDesc: problemDesc, + reporter: "sadsa", + longitude: matterAddress.location.lng, + latitude: matterAddress.location.lat, + belongArea: area, + belongAreaName: findName(area) as string, + fileNames: imgList.map((v) => v.name).join(","), + filePaths: imgList.map((v) => v.path).join(","), + }; + + submitForm(form).then((res) => { + if (res.code === 200) { + Notify.show({ type: "success", message: "上报成功!" }); + } + }); + }; return ( <div className={styles.report_container}> - {/* <NavBar - title="我要上报" - onClickLeft={() => history.back()} - leftText="返回" - /> */} - <Popup - visible={areaVisible} - style={{ height: "40%" }} - position="bottom" - // onClose={onClose} - > + <Popup visible={areaVisible} style={{ height: "40%" }} position="bottom"> <Picker title="选择地区" columns={columns} @@ -69,6 +121,10 @@ const Report = () => { placeholder="输入问题描述,详细描述问题情况有助于我们及时解决上报的问哦,不低于5个字。。。。" style={{ backgroundColor: "#f3f3f3" }} autoSize={{ minHeight: 120, maxHeight: 160 }} + defaultValue={problemDesc} + onChange={(val) => { + setProblemDesc(val); + }} /> </Card.Body> </Card> @@ -115,7 +171,13 @@ const Report = () => { <Card style={{ borderRadius: 10, marginTop: 16 }}> <Card.Header>上传照片</Card.Header> <Card.Body> - <Uploader accept="*" onChange={(v) => console.log(v)} /> + <Uploader + accept="*" + defaultValue={fileList} + onChange={(v) => { + setFileList(v); + }} + /> </Card.Body> </Card> @@ -132,7 +194,7 @@ const Report = () => { </div> <div style={{ marginTop: 16 }}> - <Button type="primary" block round> + <Button type="primary" block round onClick={handleSubmit}> 上报 </Button> </div>