| | |
| | | # ff-ai-ep-underway-vue |
| | | # ff-ai-ep-underway-vuegit |
| | | |
| | | This template should help get you started developing with Vue 3 in Vite. |
| | | |
| | |
| | | <meta charset="UTF-8"> |
| | | <link rel="icon" href="/favicon.ico"> |
| | | <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| | | <title>Vite App</title> |
| | | <title>ç½æ ¼ä¸ä½å</title> |
| | | </head> |
| | | <body> |
| | | <div id="app"></div> |
| | |
| | | |
| | | export default { |
| | | /** |
| | | * æ¥è¯¢å·²ä¸åç线索æ¸
å |
| | | * æ¥è¯¢çº¿ç´¢æ¸
å |
| | | * @param {object} param0 |
| | | * @returns |
| | | */ |
| | | getClues(time) { |
| | | return $clue.get(`feedback/queryYxfList?updateTime=${time}`); |
| | | }, |
| | | |
| | | getClue({ sTime, eTime, pageNum = 1, pageSize = 30 }) { |
| | | return $clue.get( |
| | | `clue/fetch?sTime=${sTime}&eTime=${eTime}&pageNum=${pageNum}&pageSize=${pageSize}` |
| | | ); |
| | | }, |
| | | |
| | | /** |
| | | * ä»ç¬¬ä¸æ¹è¿ç¨æå线索æ¸
å |
| | | * @param {string} updateTime æ´æ°æ¶é´ï¼è·å该æ¶é´ä¹åç线索 |
| | | * @returns |
| | | */ |
| | | fetchRemoteClue(updateTime) { |
| | | return $clue.get(`clue/fetch/remote?updateTime=${updateTime}`); |
| | | } |
| | |
| | | |
| | | export default { |
| | | /** |
| | | * |
| | | * è·å线索ç»è®º |
| | | * @param {string} clueId 线索id |
| | | */ |
| | | getConclusion(clueId) { |
| | | return $clue.get(`clue/conclusion/fetch?clueId=${clueId}`); |
| | | }, |
| | | |
| | | /** |
| | | * æäº¤çº¿ç´¢ç»è®º |
| | | * @param {object} conclusion 线索 |
| | | * @returns |
| | | */ |
| | | uploadConclusion(conclusion) { |
| | | return $clue.post(`clue/conclusion/upload`, conclusion); |
| | | }, |
| | | |
| | | /** |
| | | * æ¨é线索ç»è®ºè³ç¬¬ä¸æ¹ |
| | | * @param {Array} conclusionIdList 线索idéå |
| | | * @returns |
| | | */ |
| | | pushConclusion(conclusionIdList) { |
| | | return $clue.post(`clue/conclusion/push`, conclusionIdList); |
| | | } |
| | |
| | | import { $clue } from './index'; |
| | | import { getClueQuestionList } from '@/model/clueQuestion'; |
| | | |
| | | export default { |
| | | /** |
| | | * |
| | | * è·åå·²æäº¤ç线索é®é¢ |
| | | * @param {string} clueId 线索id |
| | | */ |
| | | getQuestion(clueId) { |
| | | return $clue.get(`clue/question/fetch?clueId=${clueId}`); |
| | | return $clue |
| | | .get(`clue/question/fetch?clueId=${clueId}`) |
| | | .then((res) => { |
| | | return getClueQuestionList(res); |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * ä¸ä¼ 线索é®é¢ |
| | | * @param {object} question é®é¢æè¿° |
| | | * @param {*} files é®é¢å¾ç |
| | | * @returns |
| | | */ |
| | | uploadQuestion(question, files) { |
| | | const formData = {}; |
| | | const formData = new FormData(); |
| | | formData.append('question', JSON.stringify(question)); |
| | | files.forEach((e) => { |
| | | formData.append('images', e); |
| | | }); |
| | | return $clue.post(`clue/question/upload`, formData); |
| | | }, |
| | | |
| | | uploadQuestionUrl() { |
| | | return `${$clue.defaults.baseURL}clue/question/upload`; |
| | | }, |
| | | |
| | | /** |
| | | * æ¨é线索é®é¢è³ç¬¬ä¸æ¹ |
| | | * @param {Array} questionIdList é®é¢idéå |
| | | * @returns |
| | | */ |
| | | pushQuestion(questionIdList) { |
| | | return $clue.post(`clue/question/push`, questionIdList); |
| | | } |
| | |
| | | import md5 from 'md5'; |
| | | import { ElMessage } from 'element-plus'; |
| | | |
| | | // const ip = 'http://101.230.224.80:8082/'; |
| | | const ip = 'http://192.168.0.138:8080/'; |
| | | const url = 'http://47.100.191.150:9030/'; |
| | | // const url = 'http://192.168.1.9:8080/'; |
| | | const imgUrl = url + 'images/'; |
| | | |
| | | //é£ç¾½ç管 |
| | | const $clue = axios.create({ |
| | | baseURL: ip, |
| | | timeout: 10000, |
| | | baseURL: url, |
| | | timeout: 10000 |
| | | // headers: addHeaders() |
| | | }); |
| | | // console.log($clue); |
| | | |
| | | function addHeaders(headers) { |
| | | function getHeaders() { |
| | | const token = 'e6dc8bb9e1ff0ce973fb92b4af2e4c3f'; |
| | | |
| | | const date = new Date(); |
| | |
| | | console.log('==>请æ±ç»æ'); |
| | | if (response.status == 200) { |
| | | if ( |
| | | response.data.code != undefined && |
| | | response.data.code != null |
| | | response.data.success != undefined && |
| | | response.data.success != null |
| | | ) { |
| | | if (response.data.code == 20000) { |
| | | if (response.data.success == true) { |
| | | return response.data.data; |
| | | } else { |
| | | return Promise.reject( |
| | | response.data.code + ', ' + response.data.message |
| | | ); |
| | | ElMessage({ |
| | | message: response.data.message, |
| | | type: 'error' |
| | | }); |
| | | return Promise.reject(response.data.message); |
| | | } |
| | | } else { |
| | | return response; |
| | |
| | | ); |
| | | }); |
| | | |
| | | export { $clue }; |
| | | export { $clue, imgUrl }; |
| | |
| | | --screen-min-height: 900px; |
| | | min-height: var(--screen-min-height); |
| | | min-width: var(--screen-min-width); |
| | | /* overflow: scroll; */ |
| | | color: var(--color-text); |
| | | background: var(--color-background); |
| | | transition: color 0.5s, background-color 0.5s; |
¶Ô±ÈÐÂÎļþ |
| | |
| | | .fy-dashed-border { |
| | | border: 1px dashed var(--el-border-color); |
| | | border-radius: var(--el-border-radius-base); |
| | | } |
| | |
| | | @import './base.css'; |
| | | @import './border.css'; |
| | | @import './text.css'; |
| | | |
| | | #app { |
| | | margin: 0 auto; |
| | | |
| | | font-weight: normal; |
| | | } |
| | | |
| | |
| | | grid-template-columns: 1fr 1fr; |
| | | padding: 0 2rem; |
| | | } */ |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | .fy-h1 { |
| | | padding: 8px 8px 8px 8px; |
| | | font-size: var(--el-font-size-large); |
| | | } |
| | | |
| | | .fy-h2 { |
| | | padding: 16px 0 8px 0; |
| | | font-size: var(--el-font-size-medium); |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | |
| | | .fy-p1 { |
| | | |
| | | } |
| | | |
| | | .fy-p2 { |
| | | |
| | | } |
| | | |
| | | .fy-tip-red { |
| | | font-size: var(--el-font-size-small); |
| | | color: var(--el-color-danger); |
| | | } |
| | |
| | | export interface GlobalComponents { |
| | | BaseMap: typeof import('./components/map/BaseMap.vue')['default'] |
| | | ElButton: typeof import('element-plus/es')['ElButton'] |
| | | ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup'] |
| | | ElCol: typeof import('element-plus/es')['ElCol'] |
| | | ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider'] |
| | | ElDatePicker: typeof import('element-plus/es')['ElDatePicker'] |
| | | ElDescriptions: typeof import('element-plus/es')['ElDescriptions'] |
| | | ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem'] |
| | | ElDescrrptions: typeof import('element-plus/es')['ElDescrrptions'] |
| | | ElDescrrptionsItem: typeof import('element-plus/es')['ElDescrrptionsItem'] |
| | | ElDiag: typeof import('element-plus/es')['ElDiag'] |
| | | ElDialog: typeof import('element-plus/es')['ElDialog'] |
| | | ElDivider: typeof import('element-plus/es')['ElDivider'] |
| | | ElEmpty: typeof import('element-plus/es')['ElEmpty'] |
| | | ElForm: typeof import('element-plus/es')['ElForm'] |
| | | ElFormItem: typeof import('element-plus/es')['ElFormItem'] |
| | | ElIcon: typeof import('element-plus/es')['ElIcon'] |
| | |
| | | ElRow: typeof import('element-plus/es')['ElRow'] |
| | | ElScrollbar: typeof import('element-plus/es')['ElScrollbar'] |
| | | ElSelect: typeof import('element-plus/es')['ElSelect'] |
| | | ElTag: typeof import('element-plus/es')['ElTag'] |
| | | ElUpload: typeof import('element-plus/es')['ElUpload'] |
| | | MapSearch: typeof import('./components/map/MapSearch.vue')['default'] |
| | | OptionTime: typeof import('./components/search-option/OptionTime.vue')['default'] |
| | | RouterLink: typeof import('vue-router')['RouterLink'] |
| | | RouterView: typeof import('vue-router')['RouterView'] |
| | |
| | | |
| | | <script setup> |
| | | import { onMounted } from 'vue'; |
| | | import { map, AMap } from './baseMap'; |
| | | |
| | | // window._AMapSecurityConfig = { |
| | | // securityJsCode: 'ãæ¨ç³è¯·çå®å
¨å¯é¥ã' |
| | |
| | | // map.add(marker); //æ·»å å°å°å¾ |
| | | }); |
| | | </script> |
| | | <style> |
| | | <style scoped> |
| | | #container { |
| | | position: relative; |
| | | width: 100%; |
| | | height: 100vh; |
| | | min-height: 900px; |
| | | min-width: 1440px; |
| | | min-height: var(--screen-min-height); |
| | | min-width: var(--screen-min-width); |
| | | z-index: 0px; |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-dialog v-model="dialogShow" width="70%" destroy-on-close> |
| | | <template #header> |
| | | <div> åæ æ¾å</div> |
| | | </template> |
| | | <div class="fy-tip-red">å·¦é®ç¹å»å°å¾éååæ ç¹ï¼æè
æ ¹æ®å
³é®åæç´¢å°ç¹</div> |
| | | <el-row> |
| | | <el-col :span="10"> |
| | | <el-form |
| | | :inline="true" |
| | | label-width="50px" |
| | | label-position="left" |
| | | :model="formObj" |
| | | ref="formRef" |
| | | destroy-on-close |
| | | > |
| | | <el-form-item label="å°å" prop="address"> |
| | | <el-input |
| | | v-model="formObj.address" |
| | | placeholder="请è¾å
¥å°åæç´¢" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <!-- <el-form-item label="ç»åº¦" prop="lon"> |
| | | <el-input |
| | | v-model="formObj.lon" |
| | | style="width: 100px" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="纬度" prop="lat"> |
| | | <el-input |
| | | v-model="formObj.lat" |
| | | style="width: 100px" |
| | | ></el-input> |
| | | </el-form-item> --> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="searchKeyword" |
| | | >æç´¢</el-button |
| | | > |
| | | </el-form-item> |
| | | </el-form> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div v-if="searchResult.address"> |
| | | <span>éæ©å°åï¼</span> |
| | | <span>{{ searchResult.address }}</span> |
| | | <div> |
| | | <span>{{ |
| | | searchResult.lon + ', ' + searchResult.lat |
| | | }}</span> |
| | | <el-divider direction="vertical" /> |
| | | <span>{{ |
| | | searchResult.gpsLon + ', ' + searchResult.gpsLat |
| | | }}</span> |
| | | </div> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="2"> |
| | | <el-button |
| | | :disabled="searchResult.gpsLon == undefined" |
| | | type="success" |
| | | @click="submit" |
| | | >éæ©</el-button |
| | | > |
| | | </el-col> |
| | | </el-row> |
| | | <div id="mapContainer"></div> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | import { shallowRef } from 'vue'; |
| | | import AMapLoader from '@amap/amap-jsapi-loader'; |
| | | // import { AMap, onMapMounted } from './baseMap'; |
| | | import baseMapUtil from './baseMapUtil.js'; |
| | | |
| | | // var map; |
| | | var AMap; |
| | | var geocoder; |
| | | var inited = false; |
| | | // onMapMounted(() => { |
| | | // AMap.plugin('AMap.Geocoder', function () { |
| | | // geocoder = new AMap.Geocoder({ |
| | | // city: '䏿µ·' // city æå®è¿è¡ç¼ç æ¥è¯¢çåå¸ï¼æ¯æä¼ å
¥åå¸åãadcode å citycode |
| | | // }); |
| | | |
| | | // // 使ç¨geocoderåå°ç/éå°çç¼ç |
| | | // }); |
| | | // }); |
| | | export default { |
| | | setup() { |
| | | const map = shallowRef(null); |
| | | return { |
| | | map |
| | | }; |
| | | }, |
| | | props: { |
| | | show: Boolean |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogShow: false, |
| | | formObj: {}, |
| | | searchResult: {} |
| | | }; |
| | | }, |
| | | emits: ['update:show', 'onSubmit'], |
| | | watch: { |
| | | show(val) { |
| | | this.dialogShow = val; |
| | | }, |
| | | dialogShow(val) { |
| | | if (val) { |
| | | this.mapInit(); |
| | | } else { |
| | | this.formObj = {}; |
| | | this.searchResult = {}; |
| | | this.map.destroy(); |
| | | } |
| | | this.$emit('update:show', val); |
| | | } |
| | | }, |
| | | methods: { |
| | | mapInit() { |
| | | // if (!inited) { |
| | | AMapLoader.load({ |
| | | key: 'c55f27799afbfa69dc5a3fad90cafe51', // ç³è¯·å¥½çWeb端å¼åè
Keyï¼é¦æ¬¡è°ç¨ load æ¶å¿
å¡« |
| | | version: '2.0', // æå®è¦å è½½ç JS API ççæ¬ï¼ç¼ºçæ¶é»è®¤ä¸º 1.4.15 |
| | | plugins: ['AMap.Geocoder'] // éè¦ä½¿ç¨ççæä»¶å表ï¼å¦æ¯ä¾å°º'AMap.Scale'ç |
| | | }).then((_AMap) => { |
| | | AMap = _AMap; |
| | | this.map = new AMap.Map('mapContainer', { |
| | | rotateEnable: true, |
| | | pitchEnable: true, |
| | | alwaysRender: false, |
| | | showLabel: true, |
| | | showBuildingBlock: true, |
| | | // mapStyle: 'amap://styles/e1e78509de64ddcd2efb4cb34c6fae2a', |
| | | // features: ['bg', 'road'], |
| | | pitch: 0, // å°å¾ä¿¯ä»°è§åº¦ï¼ææèå´ 0 度- 83 度 |
| | | viewMode: '2D', // å°å¾æ¨¡å¼ |
| | | resizeEnable: true, |
| | | center: [121.6039283, 31.25295567], |
| | | zooms: [3, 18], |
| | | zoom: 14 |
| | | }); |
| | | geocoder = new AMap.Geocoder({ |
| | | city: '䏿µ·' // city æå®è¿è¡ç¼ç æ¥è¯¢çåå¸ï¼æ¯æä¼ å
¥åå¸åãadcode å citycode |
| | | }); |
| | | this.map.on('click', (ev) => { |
| | | // this.formObj.lon = ev.lnglat.getLng(); |
| | | // this.formObj.lat = ev.lnglat.getLat(); |
| | | this.map.clearMap(); |
| | | const marker = new AMap.Marker({ |
| | | position: ev.lnglat |
| | | }); |
| | | this.map.add(marker); |
| | | |
| | | geocoder.getAddress(ev.lnglat, (status, result) => { |
| | | if (status === 'complete' && result.info === 'OK') { |
| | | this.searchResult.address = |
| | | result.regeocode.formattedAddress; |
| | | this.searchResult.lon = ev.lnglat.getLng(); |
| | | this.searchResult.lat = ev.lnglat.getLat(); |
| | | const [gpsLon, gpsLat] = baseMapUtil.gcj02towgs84( |
| | | this.searchResult.lon, |
| | | this.searchResult.lat |
| | | ); |
| | | this.searchResult.gpsLon = gpsLon; |
| | | this.searchResult.gpsLat = gpsLat; |
| | | } |
| | | }); |
| | | }); |
| | | }); |
| | | // inited = true; |
| | | // } |
| | | }, |
| | | searchKeyword() { |
| | | const keyWord = this.formObj.address; |
| | | this.map.clearMap(); |
| | | geocoder.getLocation(keyWord, (status, result) => { |
| | | if (status === 'complete' && result.info === 'OK') { |
| | | const geocode = result.geocodes[0]; |
| | | this.searchResult.address = geocode.formattedAddress; |
| | | |
| | | this.searchResult.lon = geocode.location.getLng(); |
| | | this.searchResult.lat = geocode.location.getLat(); |
| | | const [gpsLon, gpsLat] = baseMapUtil.gcj02towgs84( |
| | | this.searchResult.lon, |
| | | this.searchResult.lat |
| | | ); |
| | | this.searchResult.gpsLon = gpsLon; |
| | | this.searchResult.gpsLat = gpsLat; |
| | | |
| | | const marker = new AMap.Marker({ |
| | | position: geocode.location |
| | | }); |
| | | this.map.add(marker); |
| | | this.map.setFitView(marker); |
| | | } |
| | | }); |
| | | }, |
| | | submit() { |
| | | this.$emit('onSubmit', this.searchResult); |
| | | this.dialogShow = false; |
| | | } |
| | | } |
| | | // updated() { |
| | | // this.mapInit(); |
| | | // } |
| | | }; |
| | | </script> |
| | | <style> |
| | | #mapContainer { |
| | | position: relative; |
| | | width: 100%; |
| | | height: 60vh; |
| | | z-index: 0px; |
| | | border-radius: var(--el-border-radius-round); |
| | | box-shadow: var(--el-box-shadow); |
| | | } |
| | | </style> |
| | |
| | | satellite.hide(); |
| | | map.add([satellite]); |
| | | |
| | | const rPx = 100; |
| | | const tPx = 110; |
| | | // const rPx = 100; |
| | | // const tPx = 110; |
| | | // æ·»å å°å¾æ§å¶å·¥å
· |
| | | map.addControl( |
| | | new AMap.ControlBar({ |
| | | position: { |
| | | right: rPx + 'px', |
| | | top: tPx + 'px' |
| | | } |
| | | }) |
| | | ); |
| | | map.addControl( |
| | | new AMap.ToolBar({ |
| | | position: { |
| | | right: rPx + 30 + 'px', |
| | | top: tPx + 90 + 'px' |
| | | } |
| | | }) |
| | | ); |
| | | // map.addControl( |
| | | // new AMap.ControlBar({ |
| | | // position: { |
| | | // right: rPx + 'px', |
| | | // top: tPx + 'px' |
| | | // } |
| | | // }) |
| | | // ); |
| | | // map.addControl( |
| | | // new AMap.ToolBar({ |
| | | // position: { |
| | | // right: rPx + 30 + 'px', |
| | | // top: tPx + 90 + 'px' |
| | | // } |
| | | // }) |
| | | // ); |
| | | |
| | | // |
| | | mouseTool = new AMap.MouseTool(map); |
| | |
| | | import { map, AMap } from './baseMap'; |
| | | import { toRaw } from 'vue'; |
| | | |
| | | //å®ä¹ä¸äºå¸¸é |
| | | const PI = 3.1415926535897932384626; |
| | | const a = 6378245.0; //é¿åè½´ |
| | | const ee = 0.00669342162296594323; //æç/*** GCJ02 转æ¢ä¸º WGS84* @param lng* @param lat* @returns {*[]}*/ |
| | | |
| | | function transformlat(lng, lat) { |
| | | // lat = +lat lng = +lng |
| | | let ret = |
| | | -100.0 + |
| | | 2.0 * lng + |
| | | 3.0 * lat + |
| | | 0.2 * lat * lat + |
| | | 0.1 * lng * lat + |
| | | 0.2 * Math.sqrt(Math.abs(lng)); |
| | | ret += |
| | | ((20.0 * Math.sin(6.0 * lng * PI) + |
| | | 20.0 * Math.sin(2.0 * lng * PI)) * |
| | | 2.0) / |
| | | 3.0; |
| | | ret += |
| | | ((20.0 * Math.sin(lat * PI) + 40.0 * Math.sin((lat / 3.0) * PI)) * |
| | | 2.0) / |
| | | 3.0; |
| | | ret += |
| | | ((160.0 * Math.sin((lat / 12.0) * PI) + |
| | | 320 * Math.sin((lat * PI) / 30.0)) * |
| | | 2.0) / |
| | | 3.0; |
| | | return ret; |
| | | } |
| | | |
| | | function transformlng(lng, lat) { |
| | | // lat = +latlng = +lng |
| | | let ret = |
| | | 300.0 + |
| | | lng + |
| | | 2.0 * lat + |
| | | 0.1 * lng * lng + |
| | | 0.1 * lng * lat + |
| | | 0.1 * Math.sqrt(Math.abs(lng)); |
| | | ret += |
| | | ((20.0 * Math.sin(6.0 * lng * PI) + |
| | | 20.0 * Math.sin(2.0 * lng * PI)) * |
| | | 2.0) / |
| | | 3.0; |
| | | ret += |
| | | ((20.0 * Math.sin(lng * PI) + 40.0 * Math.sin((lng / 3.0) * PI)) * |
| | | 2.0) / |
| | | 3.0; |
| | | ret += |
| | | ((150.0 * Math.sin((lng / 12.0) * PI) + |
| | | 300.0 * Math.sin((lng / 30.0) * PI)) * |
| | | 2.0) / |
| | | 3.0; |
| | | return ret; |
| | | } |
| | | |
| | | /** |
| | | * 夿æ¯å¦å¨å½å
ï¼ä¸å¨å½å
åä¸ååç§» |
| | | * @param lng |
| | | * @param lat |
| | | * @returns {boolean} |
| | | */ |
| | | function out_of_china(lng, lat) { |
| | | // 纬度3.86~53.55,ç»åº¦73.66~135.05 |
| | | return !(lng > 73.66 && lng < 135.05 && lat > 3.86 && lat < 53.55); |
| | | } |
| | | |
| | | export default { |
| | | /** |
| | | * å°æ°ç»è¡¨ç¤ºçåæ ç¹ï¼è½¬æ¢ä¸ºAMap.LngLat对象 |
| | |
| | | if (map == undefined) return; |
| | | map.clearMap(); |
| | | }, |
| | | |
| | | /** |
| | | * é«å¾·å°å¾åæ 转GPSåæ ç®æ³ |
| | | */ |
| | | gcj02towgs84(lng, lat) { |
| | | // lat = +latlng = +lng |
| | | if (out_of_china(lng, lat)) { |
| | | return [lng, lat]; |
| | | } else { |
| | | let dlat = transformlat(lng - 105.0, lat - 35.0); |
| | | let dlng = transformlng(lng - 105.0, lat - 35.0); |
| | | let radlat = (lat / 180.0) * PI; |
| | | let magic = Math.sin(radlat); |
| | | magic = 1 - ee * magic * magic; |
| | | let sqrtmagic = Math.sqrt(magic); |
| | | dlat = |
| | | (dlat * 180.0) / |
| | | (((a * (1 - ee)) / (magic * sqrtmagic)) * PI); |
| | | dlng = |
| | | (dlng * 180.0) / ((a / sqrtmagic) * Math.cos(radlat) * PI); |
| | | let mglat = Math.round((lat * 2 - lat - dlat) * 1000000) / 1000000; |
| | | let mglng = Math.round((lng * 2 - lng - dlng) * 1000000) / 1000000; |
| | | return [mglng, mglat]; |
| | | } |
| | | }, |
| | | /** |
| | | * WGS84 转æ¢ä¸º GCJ02 |
| | | * @param lng |
| | | * @param lat |
| | | * @returns {*[]} |
| | | */ |
| | | wgs84togcj02(lng, lat) { |
| | | // lat = +latlng = +lng |
| | | if (out_of_china(lng, lat)) { |
| | | return [lng, lat]; |
| | | } else { |
| | | let dlat = transformlat(lng - 105.0, lat - 35.0); |
| | | let dlng = transformlng(lng - 105.0, lat - 35.0); |
| | | let radlat = (lat / 180.0) * PI; |
| | | let magic = Math.sin(radlat); |
| | | magic = 1 - ee * magic * magic; |
| | | let sqrtmagic = Math.sqrt(magic); |
| | | dlat = |
| | | (dlat * 180.0) / |
| | | (((a * (1 - ee)) / (magic * sqrtmagic)) * PI); |
| | | dlng = |
| | | (dlng * 180.0) / ((a / sqrtmagic) * Math.cos(radlat) * PI); |
| | | let mglat = Math.round((lat + dlat) * 1000000) / 1000000; |
| | | let mglng = Math.round((lng + dlng) * 1000000) / 1000000; |
| | | return [mglng, mglat]; |
| | | } |
| | | } |
| | | }; |
| | |
| | | // 表åç确认ååæ¶ |
| | | import { onActivated, onDeactivated, ref, watch } from 'vue'; |
| | | import { useCloned } from '@vueuse/core'; |
| | | // import { useCloned } from '@vueuse/core'; |
| | | import { useMessageBoxTip, useMessageBox } from './messageBox'; |
| | | |
| | | export function useFormConfirm({ |
| | |
| | | // manual: true |
| | | // }).cloned.value; |
| | | formRef.value.clearValidate(); |
| | | formRef.value.resetFields(); |
| | | }; |
| | | |
| | | // æ¸
空表å |
| | | const clear = function () { |
| | | edit.value = false; |
| | | isReset = true; |
| | | formRef.value.resetFields(); |
| | | formObj.value = {} |
| | | }; |
| | | |
| | | // æäº¤æåå |
| | |
| | | } |
| | | }; |
| | | |
| | | return { formObj, formRef, edit, active, onSubmit, onCancel, onReset }; |
| | | return { formObj, formRef, edit, active, onSubmit, onCancel, onReset, clear }; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | export const streets = [ |
| | | { label: '大å®è·¯è¡é', value: ['310106019', '大å®è·¯è¡é'] }, |
| | | { label: '彿µ¦æ°æè¡é', value: ['310106020', '彿µ¦æ°æè¡é'] }, |
| | | { label: '临汾路è¡é', value: ['310106021', '临汾路è¡é'] }, |
| | | { label: 'è·æ±è¥¿è·¯è¡é', value: ['310106022', 'è·æ±è¥¿è·¯è¡é'] }, |
| | | { label: '彿µ¦é', value: ['310106101', '彿µ¦é'] }, |
| | | { label: 'æ±å®è·¯è¡é', value: ['310106006', 'æ±å®è·¯è¡é'] }, |
| | | { label: 'ç³é¨äºè·¯è¡é', value: ['310106011', 'ç³é¨äºè·¯è¡é'] }, |
| | | { label: 'å京西路è¡é', value: ['310106012', 'å京西路è¡é'] }, |
| | | { label: 'éå®å¯ºè¡é', value: ['310106013', 'éå®å¯ºè¡é'] }, |
| | | { label: 'æ¹å®¶æ¸¡è¡é', value: ['310106014', 'æ¹å®¶æ¸¡è¡é'] }, |
| | | { label: '天ç®è¥¿è·¯è¡é', value: ['310106015', '天ç®è¥¿è·¯è¡é'] }, |
| | | { label: 'åç«è¡é', value: ['310106016', 'åç«è¡é'] }, |
| | | { label: 'å®å±±è·¯è¡é', value: ['310106017', 'å®å±±è·¯è¡é'] }, |
| | | { label: 'å
±åæ°è·¯è¡é', value: ['310106018', 'å
±åæ°è·¯è¡é'] } |
| | | ]; |
¶Ô±ÈÐÂÎļþ |
| | |
| | | import { imgUrl } from '@/api/clue/index'; |
| | | |
| | | function getClueQuestion(data) { |
| | | data.cqFilePath = data.cqFilePath.split(';').map((val) => { |
| | | return imgUrl + val; |
| | | }); |
| | | return data; |
| | | } |
| | | |
| | | function getClueQuestionList(dataList) { |
| | | return dataList.map((v) => { |
| | | return getClueQuestion(v); |
| | | }); |
| | | } |
| | | |
| | | export { getClueQuestion, getClueQuestionList }; |
| | |
| | | .overlay-container { |
| | | background: transparent; |
| | | position: absolute; |
| | | width: 100%; |
| | | min-height: var(--screen-min-height); |
| | | min-width: var(--screen-min-width); |
| | | width: 100vw; |
| | | height: 100vh; |
| | | top: 0; |
| | | left: 0; |
| | |
| | | <template> |
| | | <el-row class="container"> |
| | | <el-row class="container" justify="space-between"> |
| | | <el-col :span="6" class="grid-content bg-content"> |
| | | <div class="title">ä¸å线索æ¸
å</div> |
| | | <div class="fy-h1">线索æ¸
å</div> |
| | | <div class="search-wrap"> |
| | | <span>æ¶é´</span> |
| | | <el-date-picker |
| | |
| | | placeholder="éæ©æ¥æåæ¶é´" |
| | | /> |
| | | <el-button type="primary" @click="getClues">æ¥è¯¢</el-button> |
| | | <el-button type="primary" @click="fetchRemoteClue" |
| | | >æå线索</el-button |
| | | > |
| | | </div> |
| | | <ClueList |
| | | :dataList="clueList" |
| | |
| | | ></ClueList> |
| | | </el-col> |
| | | <el-col :span="6" class="grid-content bg-content-1"> |
| | | <ClueReport></ClueReport> |
| | | <div class="fy-h1">线索åé¦</div> |
| | | <el-scrollbar height="80vh" class="bg-fill"> |
| | | <ClueReport :clueData="selectedClue"></ClueReport> |
| | | </el-scrollbar> |
| | | </el-col> |
| | | </el-row> |
| | | </template> |
| | |
| | | const updateTime = ref(new Date()); |
| | | // 线索æ¸
å |
| | | const clueList = ref([]); |
| | | const selectedClue = ref(); |
| | | |
| | | /** |
| | | * æ¥è¯¢å·²ä¸åç线索æ¸
å |
| | |
| | | const getClues = function () { |
| | | const now = moment(updateTime.value); |
| | | const sTime = now.format('YYYY-MM-DD HH:mm:ss'); |
| | | const eTime = now.add(1, 'month'); |
| | | const eTime = now.add(1, 'month').format('YYYY-MM-DD HH:mm:ss'); |
| | | onMapMounted(() => { |
| | | clueApi.getClue({ sTime, eTime }).then((res) => { |
| | | clueList.value = res; |
| | |
| | | }); |
| | | }; |
| | | |
| | | function fetchRemoteClue() { |
| | | const time = moment(updateTime.value).format('YYYY-MM-DD HH:mm:ss'); |
| | | onMapMounted(() => { |
| | | clueApi.fetchRemoteClue(time).then((res) => { |
| | | clueList.value = res; |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * éæ©çº¿ç´¢äºä»¶ |
| | | */ |
| | | const selectClue = function (clue) { |
| | | |
| | | selectedClue.value = clue; |
| | | }; |
| | | </script> |
| | | |
| | |
| | | |
| | | .grid-content { |
| | | /* min-width: 180px; */ |
| | | border-radius: 4px; |
| | | border-radius: var(--el-border-radius-round); |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 16px; |
| | | padding: 8px 8px; |
| | | /* padding: 8px 8px; */ |
| | | pointer-events: auto; |
| | | box-shadow: var(--el-box-shadow-dark); |
| | | } |
| | | |
| | | .bg-content { |
| | |
| | | } |
| | | |
| | | .search-wrap { |
| | | padding: 0 8px; |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 4px; |
| | | } |
| | | |
| | | .bg-fill { |
| | | /* background: var(--el-fill-color-extra-light); */ |
| | | padding: 0 8px; |
| | | } |
| | | </style> |
| | |
| | | (item.selected ? 'list-item__selected' : '') |
| | | " |
| | | @click="selectItem(item)" |
| | | @mouseover="item.show = true" |
| | | @mouseleave="item.show = false" |
| | | v-if="!item.delete" |
| | | > |
| | | <div style="display: flex; gap: 8px"> |
| | | <div>{{ item.id }}</div> |
| | | <div>{{ item.clueName }}</div> |
| | | <div>{{ item.cid }}</div> |
| | | <div>{{ item.cclueName }}</div> |
| | | </div> |
| | | </li> |
| | | </template> |
| | |
| | | methods: { |
| | | // åè¡¨éæ© |
| | | selectItem(item) { |
| | | this.clearSelect(); |
| | | item.selected = true; |
| | | this.$emit('itemSelected', item); |
| | | }, |
| | | clearSelect() {} |
| | | clearSelect() { |
| | | this.dataList.forEach((e) => { |
| | | e.selected = false; |
| | | }); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | |
| | | overflow: auto; |
| | | overflow-x: hidden; |
| | | border: var(--el-border); |
| | | font-size: var(--el-font-size-small); |
| | | } |
| | | |
| | | .list-item { |
| | |
| | | <template> |
| | | <!-- æ¸
å详æ
--> |
| | | <el-descriptions |
| | | class="margin-top" |
| | | title="With border" |
| | | :column="3" |
| | | :size="size" |
| | | class="" |
| | | title="线索æ¸
å详æ
" |
| | | :column="1" |
| | | size="small" |
| | | border |
| | | > |
| | | <template #extra> |
| | | <el-button type="primary">Operation</el-button> |
| | | <el-button |
| | | type="primary" |
| | | text |
| | | size="small" |
| | | @click="openPDF" |
| | | >æ¥çPDF</el-button |
| | | > |
| | | </template> |
| | | <el-descriptions-item> |
| | | <template #label> |
| | | <div class="cell-item"> |
| | | <el-icon :style="iconStyle"> |
| | | <user /> |
| | | </el-icon> |
| | | Username |
| | | </div> |
| | | <div class="cell-item">线索ç¼å·</div> |
| | | </template> |
| | | kooriookami |
| | | {{ clueData.cid }} |
| | | </el-descriptions-item> |
| | | |
| | | <el-descriptions-item> |
| | | <el-descriptions-item width="65px" min-width="50px"> |
| | | <template #label> |
| | | <div class="cell-item"> |
| | | <el-icon :style="iconStyle"> |
| | | <iphone /> |
| | | </el-icon> |
| | | Telephone |
| | | </div> |
| | | <div class="cell-item">线索åç§°</div> |
| | | </template> |
| | | 18100000000 |
| | | {{ clueData.cclueName }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item> |
| | | <!-- <el-descriptions-item> |
| | | <template #label> |
| | | <div class="cell-item"> |
| | | <el-icon :style="iconStyle"> |
| | | <location /> |
| | | </el-icon> |
| | | Place |
| | | </div> |
| | | <div class="cell-item">å建æ¶é´</div> |
| | | </template> |
| | | Suzhou |
| | | </el-descriptions-item> |
| | | <el-descriptions-item> |
| | | <template #label> |
| | | <div class="cell-item"> |
| | | <el-icon :style="iconStyle"> |
| | | <tickets /> |
| | | </el-icon> |
| | | Remarks |
| | | </div> |
| | | </template> |
| | | <el-tag size="small">School</el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item> |
| | | <template #label> |
| | | <div class="cell-item"> |
| | | <el-icon :style="iconStyle"> |
| | | <office-building /> |
| | | </el-icon> |
| | | Address |
| | | </div> |
| | | </template> |
| | | No.1188, Wuzhong Avenue, Wuzhong District, Suzhou, Jiangsu Province |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | | |
| | | <!-- æ¸
å详æ
--> |
| | | <el-descriptions |
| | | class="" |
| | | title="线索æ¸
å详æ
" |
| | | :column="1" |
| | | :size="size" |
| | | border |
| | | > |
| | | <!-- <el-descriptions-item class="inventory-descriptions-item" v-for="item in 10" :key="item" > |
| | | <template #label> |
| | | <span>{{ item }}</span> |
| | | </template> |
| | | {{ item }} |
| | | {{ clueData.ccreateTime }} |
| | | </el-descriptions-item> --> |
| | | <el-descriptions-item> |
| | | <template #label> |
| | | <div class="cell-item"> |
| | | ä¸»é® |
| | | </div> |
| | | <div class="cell-item">ä¸åæ¶é´</div> |
| | | </template> |
| | | {{ clueData.id }} |
| | | {{ clueData.creleaseTime }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item> |
| | | <template #label> |
| | | <div class="cell-item"> |
| | | 线索åç§° |
| | | </div> |
| | | <div class="cell-item">æ¥è¦ç«ç¹</div> |
| | | </template> |
| | | {{ clueData.clueName }} |
| | | {{ clueData.csiteName }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item> |
| | | <template #label> |
| | | <div class="cell-item"> |
| | | 线索ç»è®º |
| | | </div> |
| | | <div class="cell-item">ç«ç¹ç±»å</div> |
| | | </template> |
| | | {{ clueData.conclusion }} |
| | | {{ clueData.csiteType }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item> |
| | | <template #label> |
| | | <div class="cell-item"> |
| | | å建æ¶é´ |
| | | </div> |
| | | <div class="cell-item">线索ç»è®º</div> |
| | | </template> |
| | | {{ clueData.createTime }} |
| | | {{ clueData.cconclusion }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item> |
| | | <!-- <el-descriptions-item> |
| | | <template #label> |
| | | <div class="cell-item"> |
| | | æ¥è¦ç«ç¹åç§° |
| | | </div> |
| | | <div class="cell-item">ç«ç¹ç±»åé项</div> |
| | | </template> |
| | | {{ clueData.siteName }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item> |
| | | <template #label> |
| | | <div class="cell-item"> |
| | | ç«ç¹ç±»å |
| | | </div> |
| | | </template> |
| | | {{ clueData.sitetype }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item> |
| | | <template #label> |
| | | <div class="cell-item"> |
| | | ä¸åæ¶é´ |
| | | </div> |
| | | </template> |
| | | {{ clueData.xfsj }} |
| | | </el-descriptions-item> |
| | | |
| | | <el-descriptions-item> |
| | | <template #label> |
| | | <div class="cell-item"> |
| | | ç«ç¹ç±»å |
| | | </div> |
| | | </template> |
| | | {{ clueData.airCheckedOptions }} |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | | <el-button type="primary" @click="reportButton">åé¦ä¸æ¥</el-button> |
| | | <el-dialog v-if="!this.isClueHave" v-model="isShow" width="50%" :before-close="handleClose"> |
| | | <template #title> |
| | | <span> åé¦ä¸æ¥</span> |
| | | </template> |
| | | <el-form label-width="120px" label-position="left"> |
| | | <el-form-item label="é®é¢ç±»å" > |
| | | <el-radio-group v-model="form.radio"> |
| | | <el-radio label="æé®é¢">æé®é¢</el-radio> |
| | | <el-radio label="æ é®é¢">æ é®é¢</el-radio> |
| | | <el-radio label="已解å³">已解å³</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | <el-form-item label="线索id"> |
| | | <el-input v-model.number="form.id"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="线索ç»è®º"> |
| | | <el-input v-model="form.conclusion"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="è¯¦ç»æè¿°"> |
| | | <el-input v-model="form.details" type="textarea" placeholder="请è¾å
¥è¯¦æ
"></el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button type="" @click="isShow=false">åæ¶</el-button> |
| | | <el-button @click="report">ç¡®å®</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | <el-button type="primary" @click="reportPhoto">å¾çä¸ä¼ </el-button> |
| | | <el-dialog v-model="isShowReportPhoto"> |
| | | <el-form> |
| | | <el-form-item label="线索id"> |
| | | <el-input v-model=""></el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | </el-dialog> |
| | | {{ clueData.cairCheckedOptions }} |
| | | </el-descriptions-item> --> |
| | | </el-descriptions> |
| | | <ClueReportConclusion :clueId="clueData.cid"></ClueReportConclusion> |
| | | <ClueReportQuestion :clueId="clueData.cid"></ClueReportQuestion> |
| | | </template> |
| | | |
| | | |
| | | <script> |
| | | import axios from 'axios' |
| | | import ClueReportConclusion from './ClueReportConclusion.vue'; |
| | | import ClueReportQuestion from './ClueReportQuestion.vue'; |
| | | export default { |
| | | // å¸å°ç±»å æ§å¶åé¦ä¸æ¥çæ ·å¼ |
| | | // fasleä»£è¡¨æ æ°æ® trueä»£è¡¨ææ°æ® |
| | | props:{ |
| | | isClueHave:{ |
| | | type:Boolean, |
| | | default:false |
| | | components: { ClueReportConclusion, ClueReportQuestion }, |
| | | props: { |
| | | clueData: { |
| | | type: Object, |
| | | default: () => { |
| | | return {}; |
| | | } |
| | | } |
| | | }, |
| | | name: 'HomePage', |
| | | data(){ |
| | | return{ |
| | | // ä¿åä¸å线索æ¥è¯¢åè¿åçæ°ç»æ°æ® |
| | | // æè
æ¯ç¹å»çå±ç¤ºç»æå¯¹åºçå¯¹è±¡æ°æ® |
| | | clueData:{}, |
| | | // 䏿¥å¼¹åºæ¡ |
| | | isShow:false, |
| | | data() { |
| | | return { |
| | | // å¾çä¸ä¼ çå¼¹åºæ¡ |
| | | isShowReportPhoto:false, |
| | | // 表åä¸ |
| | | form:{ |
| | | // é®é¢ç±»å åéæé®çå¼ |
| | | radio:'', |
| | | // 线索id |
| | | id:0, |
| | | // 线索ç»è®º |
| | | conclusion:'', |
| | | // è¯¦ç»æè¿° |
| | | details:'', |
| | | // ä¿åæäº¤åçè¿åç»æ |
| | | result:'' |
| | | }, |
| | | photoForm:{ |
| | | clueId:0, |
| | | questionDescription:'', |
| | | |
| | | isShowReportPhoto: false, |
| | | photoForm: { |
| | | clueId: 0, |
| | | questionDescription: '' |
| | | } |
| | | } |
| | | }; |
| | | }, |
| | | methods:{ |
| | | // ç¹å»ä¸æ¥æé® |
| | | reportButton(){ |
| | | // å½è¯¥çº¿ç´¢idå·²ç»æç»è®ºäº |
| | | if(this.isClueHave === true){ |
| | | alert('è¯¥çº¿ç´¢å·²ç»æç»è®ºäºï¼ä¸å¯éå¤ä¸æ¥') |
| | | } |
| | | else if(this.isClueHave === false){ |
| | | this.isShow = !this.isShow |
| | | } |
| | | }, |
| | | // ç¹å»åé¦ä¸æ¥æ¶ |
| | | report(){ |
| | | //ååºè¯·æ± |
| | | axios.post('').then(response =>{ |
| | | // è·åç»æ |
| | | this.result = response.data.data |
| | | if(this.result =='䏿¥æå'){ |
| | | ElMessage.success(this.result); |
| | | // åªæä¸ä¼ æåæ¶æå
³éå¯¹è¯æ¡ |
| | | this.isShow = false |
| | | } |
| | | else if(this.result =='䏿¥å¤±è´¥'){ |
| | | ElMessage.error(this.result); |
| | | // å¦åææ¶ä¸å
³éå¯¹è¯æ¡ |
| | | } |
| | | }) |
| | | |
| | | }, |
| | | reportPhoto(){ |
| | | |
| | | } |
| | | methods: { |
| | | openPDF() { |
| | | |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style> |
| | | |
| | | </style> |
| | | <style></style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="fy-h2"> |
| | | 线索ç»è®º |
| | | <el-button |
| | | v-if="conclusion" |
| | | type="warning" |
| | | size="small" |
| | | plain |
| | | icon="Upload" |
| | | @click="pushConclusion" |
| | | :disabled="pushing ? true : conclusion.ccUploaded" |
| | | >{{ pushing ? 'æ¨éä¸' : pushText }}</el-button |
| | | > |
| | | </div> |
| | | <el-descriptions v-if="conclusion" :column="1" size="small" border> |
| | | <el-descriptions-item width="1px" min-width="30px"> |
| | | <template #label> |
| | | <div class="descriptions-item">é®é¢ç±»å</div> |
| | | </template> |
| | | {{ conclusion.ccQuestionType }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="线索ç»è®º"> |
| | | {{ conclusion.ccConclusion }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="è¯¦ç»æè¿°"> |
| | | {{ conclusion.ccDetails }} |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | <div v-else class="fy-dashed-border"> |
| | | <el-empty :image-size="50" description="线索ç»è®ºæªä¸ä¼ "> |
| | | <el-button type="primary" @click="openDialog" |
| | | >åé¦ä¸æ¥</el-button |
| | | > |
| | | </el-empty> |
| | | </div> |
| | | <el-dialog |
| | | v-model="dialogShow" |
| | | width="50%" |
| | | :close-on-click-modal="false" |
| | | :close-on-press-escape="false" |
| | | > |
| | | <template #header> |
| | | <span> åé¦ç»è®º</span> |
| | | </template> |
| | | <el-form |
| | | label-width="120px" |
| | | label-position="left" |
| | | :rules="rules" |
| | | :model="formObj" |
| | | ref="formRef" |
| | | > |
| | | <el-form-item label="é®é¢ç±»å" prop="ccQuestionType"> |
| | | <el-radio-group v-model="formObj.ccQuestionType"> |
| | | <el-radio label="æé®é¢">æé®é¢</el-radio> |
| | | <el-radio label="æ é®é¢">æ é®é¢</el-radio> |
| | | <el-radio label="已解å³">已解å³</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | <el-form-item label="线索ç»è®º" prop="ccConclusion"> |
| | | <el-input v-model="formObj.ccConclusion"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="è¯¦ç»æè¿°" prop="ccDetails"> |
| | | <el-input |
| | | v-model="formObj.ccDetails" |
| | | type="textarea" |
| | | placeholder="请è¾å
¥è¯¦æ
" |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="onCancel">åæ¶</el-button> |
| | | <el-button type="primary" :loading="loading" @click="onSubmit" |
| | | >ç¡®å®</el-button |
| | | > |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { reactive, ref, watch, computed } from 'vue'; |
| | | import { useFormConfirm } from '@/composables/formConfirm'; |
| | | import clueConclusionApi from '@/api/clue/clueConclusionApi'; |
| | | |
| | | const props = defineProps({ |
| | | clueId: Number |
| | | }); |
| | | |
| | | watch( |
| | | () => props.clueId, |
| | | () => { |
| | | getConclusion(); |
| | | } |
| | | ); |
| | | |
| | | // æ¨éç¶æ |
| | | const pushing = ref(false); |
| | | |
| | | // 线索ç»è®º |
| | | const conclusion = ref({}); |
| | | |
| | | // 䏿¥å¼¹åºæ¡ |
| | | const dialogShow = ref(false); |
| | | const { formObj, formRef, onSubmit, onCancel, clear } = |
| | | useFormConfirm({ |
| | | submit: { |
| | | do: submit |
| | | }, |
| | | cancel: { |
| | | do: cancel |
| | | } |
| | | }); |
| | | const loading = ref(false); |
| | | // è¡¨åæ£æ¥è§å |
| | | const rules = reactive({ |
| | | ccQuestionType: [ |
| | | { |
| | | required: true, |
| | | message: 'é®é¢ç±»åä¸è½ä¸ºç©º', |
| | | trigger: 'change' |
| | | } |
| | | ], |
| | | ccConclusion: [ |
| | | { |
| | | required: true, |
| | | message: '线索ç»è®ºä¸è½ä¸ºç©º', |
| | | trigger: 'blur' |
| | | } |
| | | ], |
| | | ccDetails: [ |
| | | { |
| | | required: true, |
| | | message: 'è¯¦ç»æè¿°ä¸è½ä¸ºç©º', |
| | | trigger: 'blur' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | // æå¼ä¸æ¥åé¦å¯¹è¯æ¡ |
| | | function openDialog() { |
| | | dialogShow.value = true; |
| | | } |
| | | |
| | | function submit() { |
| | | formObj.value.cid = props.clueId; |
| | | return uploadConclusion(); |
| | | } |
| | | function cancel() { |
| | | dialogShow.value = false; |
| | | } |
| | | |
| | | /** |
| | | * ä¸ä¼ 线索ç»è®º |
| | | */ |
| | | function uploadConclusion() { |
| | | loading.value = true; |
| | | return clueConclusionApi |
| | | .uploadConclusion(formObj.value) |
| | | .then(() => { |
| | | dialogShow.value = false; |
| | | clear(); |
| | | getConclusion(); |
| | | }) |
| | | .finally(() => { |
| | | loading.value = false; |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * è·å线索ç»è®º |
| | | */ |
| | | function getConclusion() { |
| | | clueConclusionApi.getConclusion(props.clueId).then((res) => { |
| | | conclusion.value = res; |
| | | }); |
| | | } |
| | | |
| | | function pushConclusion() { |
| | | clueConclusionApi |
| | | .pushConclusion([conclusion.value.ccId]) |
| | | .then(() => { |
| | | pushing.value = true; |
| | | }); |
| | | } |
| | | |
| | | const pushText = computed(() => { |
| | | return conclusion.value.ccUploaded ? 'å·²æ¨é' : 'æ¨éé®é¢'; |
| | | }); |
| | | </script> |
| | | <style scoped> |
| | | .descriptions-item { |
| | | /* background: aqua; */ |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="fy-h2">线索é®é¢</div> |
| | | <template v-if="questionList.length > 0"> |
| | | <el-descriptions |
| | | v-for="(item, index) in questionList" |
| | | :title="'é®é¢ ' + item.cqUid" |
| | | :key="index" |
| | | :column="2" |
| | | size="small" |
| | | border |
| | | > |
| | | <template #extra> |
| | | <el-button-group> |
| | | <el-button |
| | | type="warning" |
| | | size="small" |
| | | plain |
| | | icon="Upload" |
| | | @click="pushQuestion(item)" |
| | | :disabled="item.pushing ? true : item.cqUploaded" |
| | | >{{ |
| | | item.cqUploaded |
| | | ? 'å·²æ¨é' |
| | | : item.pushing |
| | | ? 'æ¨éä¸' |
| | | : 'æ¨éé®é¢' |
| | | }}</el-button |
| | | > |
| | | <el-button |
| | | type="primary" |
| | | size="small" |
| | | @click="checkQuestion(item)" |
| | | >é®é¢è¯¦æ
</el-button |
| | | > |
| | | </el-button-group> |
| | | </template> |
| | | <el-descriptions-item |
| | | width="1px" |
| | | min-width="70px" |
| | | label="é®é¢ç¼å·" |
| | | > |
| | | {{ item.cqUid }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="æå¨è¡é"> |
| | | {{ item.cqStreet }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="é®é¢æè¿°"> |
| | | {{ item.cqDescription }} |
| | | </el-descriptions-item> |
| | | <!-- <el-descriptions-item label="详ç»å°å"> |
| | | {{ item.cqAddress }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="ç»åº¦"> |
| | | {{ item.cqLongitude }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="纬度"> |
| | | {{ item.cqLatitude }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="å建æ¶é´"> |
| | | {{ item.cqCreateTime }} |
| | | </el-descriptions-item> --> |
| | | </el-descriptions> |
| | | <div class="btn-wrap"> |
| | | <el-button type="primary" @click="openDialog" |
| | | >æ·»å é®é¢</el-button |
| | | > |
| | | </div> |
| | | </template> |
| | | <div v-else class="fy-dashed-border"> |
| | | <el-empty :image-size="50" description="æ 线索é®é¢"> |
| | | <el-button type="primary" @click="openDialog" |
| | | >åé¦ä¸æ¥</el-button |
| | | > |
| | | </el-empty> |
| | | </div> |
| | | <QuestionDetail |
| | | :clueId="clueId" |
| | | v-model:show="dialogShow" |
| | | :question="selectedQuestion" |
| | | @on-submit="getQuestion" |
| | | ></QuestionDetail> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, watch, computed } from 'vue'; |
| | | import clueQuestionApi from '@/api/clue/clueQuestionApi'; |
| | | import QuestionDetail from './QuestionDetail.vue'; |
| | | |
| | | const props = defineProps({ |
| | | clueId: Number |
| | | }); |
| | | |
| | | // 线索ç»è®º |
| | | const questionList = ref([]); |
| | | // 䏿¥å¼¹åºæ¡ |
| | | const dialogShow = ref(false); |
| | | const selectedQuestion = ref(); |
| | | |
| | | watch( |
| | | () => props.clueId, |
| | | () => { |
| | | getQuestion(); |
| | | } |
| | | ); |
| | | |
| | | // æå¼ä¸æ¥åé¦å¯¹è¯æ¡ |
| | | function openDialog() { |
| | | selectedQuestion.value = undefined; |
| | | dialogShow.value = true; |
| | | } |
| | | |
| | | // æ¥çé®é¢è¯¦æ
|
| | | function checkQuestion(item) { |
| | | selectedQuestion.value = item; |
| | | dialogShow.value = true; |
| | | } |
| | | /** |
| | | * è·å线索ç»è®º |
| | | */ |
| | | function getQuestion() { |
| | | clueQuestionApi.getQuestion(props.clueId).then((res) => { |
| | | questionList.value = res; |
| | | }); |
| | | } |
| | | |
| | | function pushQuestion(item) { |
| | | clueQuestionApi.pushQuestion([item.cqId]).then(() => { |
| | | item.pushing = true; |
| | | }); |
| | | } |
| | | |
| | | </script> |
| | | <style scoped> |
| | | .btn-wrap { |
| | | display: flex; |
| | | justify-content: center; |
| | | padding: 16px; |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-dialog |
| | | v-model="dialogShow" |
| | | width="50%" |
| | | :close-on-click-modal="false" |
| | | :close-on-press-escape="false" |
| | | destroy-on-close |
| | | > |
| | | <template #header> |
| | | <span> åé¦é®é¢</span> |
| | | </template> |
| | | <el-form |
| | | label-width="90px" |
| | | label-position="left" |
| | | :rules="rules" |
| | | :model="formObj" |
| | | ref="formRef" |
| | | > |
| | | <el-form-item label="é®é¢æè¿°" prop="cqDescription"> |
| | | <el-input |
| | | v-model="formObj.cqDescription" |
| | | type="textarea" |
| | | placeholder="请è¾å
¥è¯¦æ
" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="æå¨è¡é" prop="cqStreet"> |
| | | <el-select v-model="formObj.cqStreet" placeholder="æå¨è¡é"> |
| | | <el-option |
| | | v-for="s in streets" |
| | | :key="s.value" |
| | | :label="s.label" |
| | | :value="s.label" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="详ç»å°å" prop="cqAddress"> |
| | | <el-input v-model="formObj.cqAddress"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="åæ " prop="coordinate"> |
| | | <el-input |
| | | style="width: 300px; margin-right: 8px" |
| | | v-model="formObj.coordinate" |
| | | placeholder="ç»çº¬åº¦åæ ï¼æ ¼å¼ä¸º121.123452,31.231235" |
| | | ></el-input> |
| | | <el-button plain type="primary" @click="openMapDialog" |
| | | >åæ æ¾å</el-button |
| | | > |
| | | </el-form-item> |
| | | <el-form-item label="é®é¢å¾ç" prop="files"> |
| | | <el-upload |
| | | ref="uploadRef" |
| | | :file-list="fileList" |
| | | action="" |
| | | :auto-upload="false" |
| | | list-type="picture-card" |
| | | name="images" |
| | | accept="image/png, image/jpeg" |
| | | :limit="3" |
| | | multiple |
| | | :on-remove="handleFileRemove" |
| | | :on-change="handleFileChange" |
| | | > |
| | | <el-icon><Plus /></el-icon> |
| | | <template #tip> |
| | | <div class="el-upload__tip"> |
| | | è¯·éæ©å°äº500kbçjpg/pngå¾çï¼æå¤3å¼ |
| | | </div> |
| | | </template> |
| | | </el-upload> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="onCancel">åæ¶</el-button> |
| | | <el-button |
| | | :disabled="!edit" |
| | | type="primary" |
| | | :loading="loading" |
| | | @click="onSubmit" |
| | | >ç¡®å®</el-button |
| | | > |
| | | </template> |
| | | </el-dialog> |
| | | <MapSearch |
| | | v-model:show="mapDialogShow" |
| | | @on-submit="selectAddress" |
| | | ></MapSearch> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { reactive, ref, watch, computed } from 'vue'; |
| | | import { useFormConfirm } from '@/composables/formConfirm'; |
| | | import { streets } from '@/constant/street'; |
| | | import clueQuestionApi from '@/api/clue/clueQuestionApi'; |
| | | import MapSearch from '@/components/map/MapSearch.vue'; |
| | | |
| | | const props = defineProps({ |
| | | clueId: Number, |
| | | show: Boolean, |
| | | question: Object |
| | | }); |
| | | |
| | | const emit = defineEmits(['update:show', 'onSubmit'], ['onClose']); |
| | | |
| | | // 䏿¥å¼¹åºæ¡ |
| | | const dialogShow = ref(false); |
| | | const mapDialogShow = ref(false); |
| | | const uploadRef = ref(); |
| | | const fileList = ref([]); |
| | | |
| | | function handleFileRemove(file, fileList) { |
| | | formObj.value.files = fileList; |
| | | } |
| | | |
| | | function handleFileChange(file, fileList) { |
| | | formObj.value.files = fileList; |
| | | } |
| | | |
| | | const { formObj, formRef, edit, onSubmit, onCancel, clear } = |
| | | useFormConfirm({ |
| | | submit: { |
| | | do: submit |
| | | }, |
| | | cancel: { |
| | | do: cancel |
| | | } |
| | | }); |
| | | const loading = ref(false); |
| | | // è¡¨åæ£æ¥è§å |
| | | const rules = reactive({ |
| | | cqDescription: [ |
| | | { |
| | | required: true, |
| | | message: 'é®é¢æè¿°ä¸è½ä¸ºç©º', |
| | | trigger: 'blur' |
| | | } |
| | | ], |
| | | cqStreet: [ |
| | | { |
| | | required: true, |
| | | message: 'æå¨è¡éä¸è½ä¸ºç©º', |
| | | trigger: 'change' |
| | | } |
| | | ], |
| | | cqAddress: [ |
| | | { |
| | | required: true, |
| | | message: '详ç»å°åä¸è½ä¸ºç©º', |
| | | trigger: 'blur' |
| | | } |
| | | ], |
| | | coordinate: [ |
| | | { |
| | | required: true, |
| | | message: 'åæ ä¸è½ä¸ºç©º', |
| | | trigger: 'blur' |
| | | } |
| | | ], |
| | | // cqLongitude: [ |
| | | // { |
| | | // required: true, |
| | | // message: 'ç»åº¦ä¸è½ä¸ºç©º', |
| | | // trigger: 'blur' |
| | | // } |
| | | // ], |
| | | // cqLatitude: [ |
| | | // { |
| | | // required: true, |
| | | // message: '维度ä¸è½ä¸ºç©º', |
| | | // trigger: 'blur' |
| | | // } |
| | | // ], |
| | | files: [ |
| | | { |
| | | required: true, |
| | | message: 'å¾çä¸è½ä¸ºç©º', |
| | | trigger: 'change' |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | function submit() { |
| | | const coor = formObj.value.coordinate.split(','); |
| | | const q = { |
| | | cId: parseInt(props.clueId), |
| | | cqDescription: formObj.value.cqDescription, |
| | | cqStreet: formObj.value.cqStreet, |
| | | cqAddress: formObj.value.cqAddress, |
| | | cqLongitude: parseFloat(coor[0]), |
| | | cqLatitude: parseFloat(coor[1]) |
| | | }; |
| | | const files = []; |
| | | formObj.value.files.forEach((f) => { |
| | | files.push(f.raw); |
| | | }); |
| | | return uploadQuestion(q, files); |
| | | } |
| | | |
| | | function cancel() { |
| | | // clear(); |
| | | dialogShow.value = false; |
| | | } |
| | | |
| | | function openMapDialog() { |
| | | mapDialogShow.value = true; |
| | | } |
| | | |
| | | function selectAddress(result) { |
| | | formObj.value.cqAddress = result.address; |
| | | formObj.value.coordinate = result.gpsLon + ',' + result.gpsLat; |
| | | } |
| | | |
| | | /** |
| | | * ä¸ä¼ 线索ç»è®º |
| | | */ |
| | | function uploadQuestion(question, files) { |
| | | loading.value = true; |
| | | |
| | | return clueQuestionApi |
| | | .uploadQuestion(question, files) |
| | | .then(() => { |
| | | dialogShow.value = false; |
| | | clear(); |
| | | uploadRef.value.clearFiles(); |
| | | emit('onSubmit'); |
| | | }) |
| | | .finally(() => { |
| | | loading.value = false; |
| | | }); |
| | | } |
| | | |
| | | function parseFormObj(question) { |
| | | question.coordinate = |
| | | question.cqLongitude + ',' + question.cqLatitude; |
| | | fileList.value = []; |
| | | question.cqFilePath.forEach((f, index) => { |
| | | fileList.value.push({ |
| | | name: `${index}`, |
| | | url: f |
| | | }); |
| | | }); |
| | | return question; |
| | | } |
| | | |
| | | watch( |
| | | () => props.show, |
| | | (val) => { |
| | | dialogShow.value = val; |
| | | } |
| | | ); |
| | | watch( |
| | | () => props.question, |
| | | (val) => { |
| | | fileList.value = []; |
| | | if (val) { |
| | | formObj.value = parseFormObj(val); |
| | | } else { |
| | | formObj.value = {}; |
| | | } |
| | | } |
| | | ); |
| | | watch(dialogShow, (val) => { |
| | | emit('update:show', val); |
| | | }); |
| | | </script> |