Compare commits

...

17 Commits

Author SHA1 Message Date
zzq 4478b93089 案件审核汇总核验页面开发接口对接 2024-04-25 17:13:16 +08:00
zzq d46c63777a Merge branch 'main' of http://123.132.248.154:10000/HC_YFZX/ShiJiTianKongDiPingTai into zzq 2024-04-24 16:47:33 +08:00
石超 456dca2ef7 地图操作图标修改 2024-04-24 15:41:42 +08:00
zzq 9954a1cecf Merge branch 'main' of http://123.132.248.154:10000/HC_YFZX/ShiJiTianKongDiPingTai into zzq 2024-04-24 15:23:48 +08:00
石超 b4ee18d2e8 Merge branch 'main' of http://123.132.248.154:10000/HC_YFZX/ShiJiTianKongDiPingTai 2024-04-24 15:04:31 +08:00
石超 9b701b8913 地图图标按钮位置 2024-04-24 15:04:28 +08:00
刘妍 27ab99c336 Merge branch 'main' of http://123.132.248.154:10000/HC_YFZX/ShiJiTianKongDiPingTai 2024-04-24 14:50:12 +08:00
刘妍 e5e7667b37 Merge branch 'ly' 2024-04-24 14:49:49 +08:00
刘妍 1f63f1446b 案件详情接口对接 2024-04-24 14:49:04 +08:00
zzq b8a2252cbb Merge branch 'main' of http://123.132.248.154:10000/HC_YFZX/ShiJiTianKongDiPingTai into zzq 2024-04-24 14:20:34 +08:00
石超 bd7dc16b23 更换名称、logo、icon 2024-04-24 14:11:48 +08:00
石超 c6695f3676 1. vite降级 2.修改打包配置 2024-04-24 14:01:10 +08:00
石超 d3484f2f55 1. 添加图斑绘制;2. 更换图标 3.删除消息通知 4. 删除更换api和文档地址 2024-04-24 13:35:43 +08:00
刘妍 20499f6127 Merge branch 'main' of http://123.132.248.154:10000/HC_YFZX/ShiJiTianKongDiPingTai 2024-04-23 17:11:11 +08:00
刘妍 c6274021fc 案件列表接口对接,案件详情处理流程各个组件封装 2024-04-23 17:10:06 +08:00
石超 0ccb63b47e 引入mapbox-utils 安装:pnpm install mapbox-gl-utils 添加矢量瓦片加载案例 2024-04-23 15:42:35 +08:00
石超 71797a2bb9 1.添加mapbox-gl 2.添加地图组件 3. 修改从vue引入插件提示错误的问题 4. 安装了mapbox-gl插件和@types/node插件 2024-04-23 08:46:40 +08:00
55 changed files with 3937 additions and 440 deletions

2
.env
View File

@ -1,2 +1,2 @@
# 标题
VITE_GLOB_APP_TITLE = 费县智慧林业防灭火平台
VITE_GLOB_APP_TITLE = 临沂市天空地数字执法

7
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,7 @@
{
"i18n-ally.localesPaths": [
"src/locales",
"src/locales/lang",
"public/resource/tinymce/langs"
]
}

View File

@ -73,6 +73,7 @@
"@iconify/iconify": "^3.1.1",
"@logicflow/core": "^1.2.18",
"@logicflow/extension": "^1.2.19",
"@turf/turf": "^6.5.0",
"@vben/hooks": "workspace:*",
"@vue/shared": "^3.4.5",
"@vueuse/core": "^10.7.1",
@ -92,11 +93,13 @@
"element-plus": "^2.6.0",
"exceljs": "^4.4.0",
"highlight.js": "^11.9.0",
"js-md5": "^0.8.3",
"kml-geojson": "^1.2.2",
"localforage": "^1.10.0",
"js-md5": "^0.8.3",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"mapbox-gl": "^3.3.0",
"mapbox-gl-utils": "^0.44.0",
"mars3d": "^3.7.0",
"mars3d-cesium": "^1.113.0",
"min-dash": "^4.2.1",
@ -139,6 +142,7 @@
"@types/crypto-js": "^4.2.1",
"@types/lodash-es": "^4.17.12",
"@types/mockjs": "^1.0.10",
"@types/node": "^20.10.6",
"@types/nprogress": "^0.2.3",
"@types/qrcode": "^1.5.5",
"@types/qs": "^6.9.11",
@ -162,7 +166,7 @@
"turbo": "^1.11.3",
"typescript": "^5.3.3",
"unbuild": "^2.0.0",
"vite": "^5.0.10",
"vite": "^4.2.0",
"vite-plugin-mars3d": "^3.1.3",
"vite-plugin-mock": "^2.9.6",
"vue-tsc": "^1.8.27"

BIN
public/del.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 894 B

After

Width:  |  Height:  |  Size: 15 KiB

BIN
public/line.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 184 KiB

BIN
public/point.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
public/polygon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -5,25 +5,48 @@ import {
TabDataItem,
CaseCollectionItem,
GetBaseItem,
CaseCollectionDelItem,
GetBaseIdItem,
GetBaseUidItem,
GetCaseDealItem,
CaseBackItem,
} from './model/index';
enum Api {
GETORG_List = '/api/Orgs/OrgList', //组织机构字典
GETTABLEDATA_LIST = '/api/DroneCaseinfo/LoadWaitToVerifyCaseList', //表格列表数据
ADDCASE_COLLECTION = '/api/DroneCaseinfo/AddCaseFavorite', //收藏案件
ADDCASE_COLLECTION = '/api/DroneCaseinfo/AddCaseFavorite', //添加收藏案件
DELCASE_COLLECTION = '/api/DroneCaseinfo/DeleteFavoriteCases', //移除收藏
GETCOLLECTION_LIST = '/api/DroneCaseinfo/LoadFavoriteCases', //收藏列表
GETUSERINFO = '/api/DroneCaseinfo/GetCurrentUser', //获取当前用户信息
GETCASE_DETAIL = '/api/DroneCaseinfo/GetCaseInfo', //获取案件详情
GETCASELIST = '/api/DroneCaseinfo/FavoriteCaseList', //全部收藏案件数据
GETCASEDEAL = '/api/DroneCaseinfo/GetDroneCaseDeal', //审核详情
CASE_AUDITING = '/api/DroneCaseinfo/VerfiyCaseData', //案件通过审核
CASE_BACK = '/api/DroneCaseinfo/DrawbackCase', //案件退回
}
/**
* @description: Get sample options value
*/
export const getUserOrg = (params?: OrgItemList) =>
defHttp.get<DemoOptionsItem[]>({ url: Api.GETORG_List, params });
export const getUserInfoData = (params?: OrgItemList) =>
defHttp.get<DemoOptionsItem[]>({ url: Api.GETUSERINFO, params });
export const getTableDataList = (params?: TabDataItem) =>
defHttp.get<DemoOptionsItem[]>({ url: Api.GETTABLEDATA_LIST, params });
export const addCaseCollection = (params?: CaseCollectionItem) =>
defHttp.post<DemoOptionsItem[]>({ url: Api.ADDCASE_COLLECTION, params });
export const delCaseCollection = (params?: CaseCollectionItem) =>
export const delCaseCollection = (params?: CaseCollectionDelItem) =>
defHttp.post<DemoOptionsItem[]>({ url: Api.DELCASE_COLLECTION, params });
export const getCollectionCaseList = (params?: GetBaseItem) =>
defHttp.get<DemoOptionsItem[]>({ url: Api.GETCOLLECTION_LIST, params });
export const getCaseDataDetail = (params?: GetBaseIdItem) =>
defHttp.get<DemoOptionsItem[]>({ url: Api.GETCASE_DETAIL, params });
export const getCaseList = (params?: GetBaseUidItem) =>
defHttp.get<DemoOptionsItem[]>({ url: Api.GETCASELIST, params });
export const getCaseDealDetail = (params?: GetCaseDealItem) =>
defHttp.get<DemoOptionsItem[]>({ url: Api.GETCASEDEAL, params });
export const caseAudiSteps = (params?: GetBaseIdItem) =>
defHttp.get<DemoOptionsItem[]>({ url: Api.CASE_AUDITING, params });
export const caseBackSteps = (params?: CaseBackItem) =>
defHttp.get<DemoOptionsItem[]>({ url: Api.CASE_BACK, params });

View File

@ -1,8 +1,29 @@
import { BasicFetchResult } from '@/api/model/baseModel';
export interface BasicFetchResult<T> {
moduleIds?: any;
formScheme?: any;
elementIds?: any;
items: T[];
total: number;
user: any;
pics: any;
video_list: any;
is_illegal: any;
info: any;
pic_info_list: any;
after_pic_list: any;
evidence_file_list: any;
punish_pic_list: any;
payment_pic_list: any;
agree_checkout_pic_list: any;
checkout_pic_list: any;
boundary_pic_list: any;
}
export interface DemoOptionsItem {
items: any;
total: any;
user: any;
pics: any;
}
export interface OrgItemList {
@ -26,16 +47,28 @@ export interface TabDataItem {
is_illegal: any;
}
export interface CaseCollectionItem {
id: any;
caseNo: any;
favoriteUserId: any;
}
export interface CaseCollectionDelItem {}
export interface GetBaseItem {
page: any;
limit: any;
key: any;
}
export interface GetBaseIdItem {
id: any;
}
export interface GetBaseUidItem {
uid: any;
}
export interface GetCaseDealItem {
caseid: any;
}
export interface CaseBackItem {
id: any;
drawbackReason: any;
}
/**
* @description: Request list return value
*/

50
src/api/monitor/index.ts Normal file
View File

@ -0,0 +1,50 @@
// WFProcess 流程模版基本信息
import { defHttp } from '@/utils/http/axios';
import { caseFlowLogParams , flowLogModel , droneCaseDealModel ,droneCaseDealParams} from './model/index'
enum Api {
// 获取案件详情步骤条
GetCaseFlowLog = '/api/DroneCaseinfo/GetCaseFlowLog',
// 获取案件处理详情
GetDroneCaseDeal = '/api/DroneCaseinfo/GetDroneCaseDeal',
// 获取案件详情
GetCaseInfo = '/api/DroneCaseinfo/GetCaseInfo',
// 案件列表
LoadCaseInfoList = '/api/DroneCaseinfo/LoadCaseInfoList',
// 获取GeoJson图层
GetDroneGeoJson='/api/DroneCaseinfo/GetDroneGeoJson'
}
/**
* @description: getCaseFlowLog
*/
export function getCaseFlowLog(params?: caseFlowLogParams) {
return defHttp.get<flowLogModel>({ url: Api.GetCaseFlowLog, params });
}
/**
* @description: getCaseFlowLog
*/
export function getDroneCaseDeal(params?: droneCaseDealParams) {
return defHttp.get<droneCaseDealModel>({ url: Api.GetDroneCaseDeal, params });
}
/**
* @description: getCaseFlowLog
*/
export function getCaseInfo(params?: caseFlowLogParams) {
return defHttp.get<flowLogModel>({ url: Api.GetCaseInfo, params });
}
/**
* @description: getCaseFlowLog
*/
export function getCaseInfoList(params?: caseFlowLogParams) {
return defHttp.get<flowLogModel>({ url: Api.LoadCaseInfoList, params });
}
/**
* @description: getCaseFlowLog
*/
export function getDroneGeoJson(params?: caseFlowLogParams) {
return defHttp.get<flowLogModel>({ url: Api.GetDroneGeoJson, params });
}

View File

@ -0,0 +1,34 @@
export interface caseFlowLogParams {
id?: string;
}
export interface droneCaseDealParams{
caseid?:string;
}
export interface flowLog {
name: string;
time: string;
user_name: string;
status: number;
state?:string;
}
export type flowLogModel = flowLog[];
export interface fileList{
filePath?:string | undefined;
s_filePath?:string;
}
export type fileListModel = fileList[];
export type droneCaseDealModel = {
video_list?: any;
pic_info_list?: any;
after_pic_list?: any;
remove_video_list?: any;
evidence_file_list?: any;
boundary_pic_list?: any;
punish_pic_list?: any;
payment_pic_list?: any;
agree_checkout_pic_list?: any;
checkout_pic_list?: any;
}

View File

@ -0,0 +1,17 @@
import { defHttp } from '@/utils/http/axios';
import { DemoOptionsItem, OrgItemList, CaseCollectionDelItem, CaseBackItem } from './model/index';
enum Api {
GETORG_List = '/api/DroneCaseinfo/LoadCaseInfoList', //表格列表
PASS_VERIFICAT = '/api/DroneCaseinfo/VerificatCase', //核验
BACK_VERIFICAT = '/api/DroneCaseinfo/DrawbackCase', //退回
}
/**
* @description: Get sample options value
*/
export const getTableListData = (params?: OrgItemList) =>
defHttp.get<DemoOptionsItem[]>({ url: Api.GETORG_List, params });
export const passVerificatCase = (params?: CaseCollectionDelItem) =>
defHttp.post<DemoOptionsItem[]>({ url: Api.PASS_VERIFICAT, params });
export const backVerificcatCase = (params?: CaseBackItem) =>
defHttp.get<DemoOptionsItem[]>({ url: Api.BACK_VERIFICAT, params });

View File

@ -0,0 +1,73 @@
export interface BasicFetchResult<T> {
moduleIds?: any;
formScheme?: any;
elementIds?: any;
items: T[];
total: number;
user: any;
pics: any;
video_list: any;
is_illegal: any;
info: any;
pic_info_list: any;
after_pic_list: any;
evidence_file_list: any;
punish_pic_list: any;
payment_pic_list: any;
agree_checkout_pic_list: any;
checkout_pic_list: any;
boundary_pic_list: any;
}
export interface DemoOptionsItem {
items: any;
total: any;
user: any;
pics: any;
}
export interface OrgItemList {}
export interface TabDataItem {
is_intact: any;
page: any;
limit: any;
key: any;
appId: any;
reportTime: any;
violationStatus: any;
handle_status_id: any;
identification_user: any;
countyid: any;
streetid: any;
communityid: any;
case_no: any;
is_illegal: any;
}
export interface CaseCollectionItem {
caseNo: any;
favoriteUserId: any;
}
export interface CaseCollectionDelItem {}
export interface GetBaseItem {
page: any;
limit: any;
key: any;
}
export interface GetBaseIdItem {
id: any;
}
export interface GetBaseUidItem {
uid: any;
}
export interface GetCaseDealItem {
caseid: any;
}
export interface CaseBackItem {
id: any;
drawbackReason: any;
}
/**
* @description: Request list return value
*/
export type DemoOptionsGetResultModel = BasicFetchResult<DemoOptionsItem>;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

View File

@ -4,7 +4,7 @@
-->
<template>
<div class="anticon" :class="getAppLogoClass" @click="goHome">
<img src="../../../assets/images/logo.png" />
<img src="/logo.png" />
<div class="ml-2 truncate md:opacity-100" :class="getTitleClass" v-show="showTitle">
{{ title }}
</div>

View File

@ -0,0 +1,85 @@
<template>
<div class="map-container">
<div id="mapContainer" class="map-box"></div>
<div class="map-control">
<img @click="drawPoint" src="/point.png" alt="image1" />
<img @click="drawLine" src="/line.png" alt="image1" />
<img @click="drawPolygon" src="/polygon.png" alt="image1" />
<img @click="unDrawPolygon" src="/del.png" alt="image1" />
</div>
</div>
</template>
<script lang="ts" setup>
import { onMounted, onUnmounted, defineProps } from 'vue';
import mapboxgl, { Map } from 'mapbox-gl';
import U from 'mapbox-gl-utils';
import 'mapbox-gl/dist/mapbox-gl.css';
import './src/index.less';
import { MapboxConfig, MapboxDefaultStyle } from './src/config';
import { MP } from './src/MP';
// map
interface MapboxOptionsInterface {
mapOptions: mapboxgl.MapboxOptions;
}
const props = defineProps<MapboxOptionsInterface>();
//
let map: Map;
let mp: any = null;
// emit
//
const emit = defineEmits(['mapOnLoad', 'mapDraw']);
onMounted(() => {
mapboxgl.accessToken = MapboxConfig.ACCESS_TOKEN;
map = initMap();
map.on('load', () => {
//mapbox-gl-utils
U.init(map);
mp = new MP(map);
emit('mapOnLoad', map);
});
});
//
//
onUnmounted(() => {
map ? map.remove() : null;
});
//
//
const initMap = () => {
return new mapboxgl.Map({
container: 'mapContainer',
language: 'zh-cmn',
projection: 'equirectangular', // wgs84
style: MapboxDefaultStyle,
...props.mapOptions,
});
};
//
const drawPoint = () => {
mp.draw('Point');
mp.on('Point', function (e) {
emit('mapDraw', 'Point', e);
});
};
//线
const drawLine = () => {
mp.draw('LineString');
mp.on('LineString', function (e) {
emit('mapDraw', 'LineString', e);
});
};
//
const drawPolygon = () => {
mp.draw('Polygon');
mp.on('Polygon', function (e) {
emit('mapDraw', 'Polygon', e);
});
};
//
const unDrawPolygon = () => {
mp.deleteDraw();
emit('mapDraw', 'cancel');
};
</script>

View File

@ -0,0 +1,7 @@
# Map.U 的用法
## 参考文档
```
https://stevage.github.io/map-gl-utils/
```

View File

@ -0,0 +1,540 @@
import U from 'mapbox-gl-utils';
import * as turf from '@turf/turf';
type EventType = 'Point' | 'LineString' | 'Polygon';
interface GenerateGeoJSONDataInterface {
lng: number;
lat: number;
}
interface FeatureCollection {
type: string;
features: Array<any>;
}
const CIRCLE_STYLE = {
'circle-color': '#6495ED',
'circle-radius': 8,
'circle-stroke-width': 2,
'circle-stroke-color': '#ffffff',
};
const LINE_STYLE = {
'line-color': '#6495ED',
'line-width': 3,
};
const LINE_IS_DRAW_STYLE = {
'line-dasharray': [2, 2],
'line-color': '#00FA9A',
'line-width': 3,
};
const POLYGON_STYLE = {
'fill-color': '#FAFAD2',
'fill-opacity': 0.3,
};
function typeOf(obj: any): any {
const toString: any = Object.prototype.toString;
const map: any = {
'[object Boolean]': 'boolean',
'[object Number]': 'number',
'[object String]': 'string',
'[object Function]': 'function',
'[object Array]': 'array',
'[object Date]': 'date',
'[object RegExp]': 'regExp',
'[object Undefined]': 'undefined',
'[object Null]': 'null',
'[object Object]': 'object',
};
return map[toString.call(obj)];
}
function deepClone(data: any): any {
// 获取传入拷贝函数的数据类型
const type = typeOf(data);
// 定义一个返回any类型的数据
let reData: any;
// 递归遍历一个array类型数据
if (type === 'array') {
reData = [];
for (let i = 0; i < data.length; i++) {
reData.push(deepClone(data[i]));
}
} else if (type === 'object') {
//递归遍历一个object类型数据
reData = {};
for (const i in data) {
reData[i] = deepClone(data[i]);
}
} else {
// 返回基本数据类型
return data;
}
// 将any类型的数据return出去作为deepClone的结果
return reData;
}
class BaseMP {
map: any;
listeners: {};
constructor(map: any) {
this.map = map;
// 初始化mapbox工具类
U.init(this.map);
this.listeners = {};
}
//监听
on(event: EventType, callback: void) {
console.log('on', event);
this.listeners[event] = callback;
}
off(event: EventType) {
console.log('off', event);
if (this.listeners[event]) {
delete this.listeners[event];
}
}
emit(event: EventType, data: any) {
if (this.listeners[event]) {
this.listeners[event](data);
}
}
//防抖函数
debounce = (func: Function, delay: number) => {
let timer: any = null;
return (...args: any) => {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, args);
}, delay);
};
};
//切换鼠标样式
_changeMouseCursor = (cursor: string = 'pointer') => {
this.map.getCanvas().style.cursor = cursor;
};
//生成geoJson
_generateGeoJSON(data: GenerateGeoJSONDataInterface[], geometryType: EventType) {
/**
* // 生成点类型的GeoJSON
* var data = [{lng: -122.4194, lat: 37.7749}, {lng: -122.408, lat: 37.791}, {lng: -122.431, lat: 37.769}];
* var geoJSON = generateGeoJSON(data, "Point");
*
* // 生成线类型的GeoJSON
* var data = [{lng: -122.4194, lat: 37.7749}, {lng: -122.408, lat: 37.791}, {lng: -122.431, lat: 37.769}];
* var geoJSON = generateGeoJSON(data, "LineString");
*
* // 生成面类型的GeoJSON
* var data = [{lng: -122.4194, lat: 37.7749}, {lng: -122.408, lat: 37.791}, {lng: -122.431, lat: 37.769}];
* var geoJSON = generateGeoJSON(data, "Polygon");
* **/
const featureCollection: FeatureCollection = {
type: 'FeatureCollection',
features: [],
};
switch (geometryType) {
case 'Point':
for (let i = 0; i < data.length; i++) {
const feature = {
type: 'Feature',
geometry: {
type: geometryType,
coordinates: [data[i].lng, data[i].lat],
},
properties: {},
};
featureCollection.features.push(feature);
}
break;
case 'LineString':
const lineFeature = {
type: 'Feature',
geometry: {
type: geometryType,
coordinates: [],
},
properties: {},
};
for (let i = 0; i < data.length; i++) {
lineFeature['geometry']['coordinates'].push([data[i].lng, data[i].lat]);
}
featureCollection.features.push(lineFeature);
break;
case 'Polygon':
const polygonFeature = {
type: 'Feature',
geometry: {
type: geometryType,
coordinates: [[]],
},
properties: {},
};
for (let i = 0; i < data.length; i++) {
polygonFeature['geometry']['coordinates'][0].push([data[i].lng, data[i].lat]);
}
featureCollection.features.push(polygonFeature);
break;
}
return featureCollection;
}
}
export class MP extends BaseMP {
drawModelChoose: { LineString: string; Point: string; Polygon: string; DEFAULT: string };
drawModel: string;
drawLocal: never[];
drawCurrentId: {
point: string; //点
line: string; //线
lastLine: string; //鼠标位置的点
polygon: string;
};
currentMouseLocation: null;
correctionMouseLocation: null;
clickCount: number;
clickTimeout: null;
constructor(map) {
super(map);
this.drawModelChoose = {
LineString: 'LineString',
Point: 'Point',
Polygon: 'Polygon',
DEFAULT: 'default',
};
this.drawModel = this.drawModelChoose.DEFAULT;
this.drawLocal = [];
this.drawCurrentId = {
point: 'current-draw-point', //点
line: 'current-draw-line', //线
lastLine: 'current-draw-last-line', //鼠标位置的点
polygon: 'current-draw-polygon',
};
this.currentMouseLocation = null; //当前鼠标位置
this.correctionMouseLocation = null; //校正后的鼠标位置
this.clickCount = 0; // 定义一个计数器
this.clickTimeout = null; // 定义一个超时变量
}
//添加或更新source
_addOrUpdateSource = (gS, id) => {
if (this.map.getSource(id)) {
this.map.getSource(id).setData(gS);
} else {
this.map.U.addGeoJSON(id, gS);
}
};
// 添加layer有则不操作
_addLayer = (layerId, sourceId, type, style) => {
// 如果图层不存在,添加图层。如果存在,不做操作
if (!this.map.getLayer(sourceId)) {
switch (type) {
case this.drawModelChoose.Point:
//addCircleLayer
this.map.U.addCircleLayer(layerId, sourceId, style);
break;
case this.drawModelChoose.LineString:
//addLineLayer
this.map.U.addLineLayer(layerId, sourceId, style);
break;
case this.drawModelChoose.Polygon:
//addPolygonLayer
this.map.U.addFillLayer(layerId, sourceId, style);
break;
default:
console.log('layer类型错误');
}
}
};
_currentDrawSource = () => {
// currentGSP 点 currentGSL 线 currentGSPL 面
const currentGSP = this._generateGeoJSON(this.drawLocal, 'Point');
this._addOrUpdateSource(currentGSP, this.drawCurrentId.point);
if (
this.drawModel === this.drawModelChoose.LineString ||
this.drawModel === this.drawModelChoose.Polygon
) {
const currentGSL = this._generateGeoJSON(this.drawLocal, 'LineString');
this._addOrUpdateSource(currentGSL, this.drawCurrentId.line);
}
if (this.drawModel === this.drawModelChoose.Polygon) {
const lastGSPL = this._generateGeoJSON(this.drawLocal, 'Polygon');
this._addOrUpdateSource(lastGSPL, this.drawCurrentId.polygon);
}
};
_currentDrawLayer = () => {
this._addLayer(this.drawCurrentId.point, this.drawCurrentId.point, 'Point', CIRCLE_STYLE);
if (
this.drawModel === this.drawModelChoose.LineString ||
this.drawModel === this.drawModelChoose.Polygon
) {
this._addLayer(this.drawCurrentId.line, this.drawCurrentId.line, 'LineString', LINE_STYLE);
}
if (this.drawModel === this.drawModelChoose.Polygon) {
this._addLayer(
this.drawCurrentId.polygon,
this.drawCurrentId.polygon,
'Polygon',
POLYGON_STYLE,
);
}
};
//最后动态的一笔
_currentDrawLastLine = () => {
if (
this.drawModel === this.drawModelChoose.LineString ||
this.drawModel === this.drawModelChoose.Polygon
) {
if (!this.drawLocal.length) {
this.map.U.removeLayer(this.drawCurrentId.lastLine);
this.map.U.removeSource(this.drawCurrentId.lastLine);
return false;
}
const startPoint = this.drawLocal[this.drawLocal.length - 1];
const endPoint = this.getDrawEndPoint();
// 添加动态线
const lastGSL = this._generateGeoJSON([startPoint, endPoint], 'LineString');
this.crossesLine(this.drawLocal, [startPoint, endPoint]);
this._addOrUpdateSource(lastGSL, this.drawCurrentId.lastLine);
this._addLayer(
this.drawCurrentId.lastLine,
this.drawCurrentId.lastLine,
'LineString',
LINE_IS_DRAW_STYLE,
);
}
if (this.drawModel === this.drawModelChoose.Polygon) {
this._currentDrawLastPolygon();
}
};
//获取矫正的最后点
getDrawEndPoint = () => {
let endPoint = null;
if (this.nearlyClientDistant()) {
endPoint = this.correctionMouseLocation;
} else {
endPoint = this.currentMouseLocation;
}
return endPoint;
};
//最后动态的一笔,跟随面生成
_currentDrawLastPolygon = () => {
// 添加动态面
const endPoint = this.getDrawEndPoint();
const drawLocalCopy = deepClone(this.drawLocal);
drawLocalCopy.push(endPoint);
drawLocalCopy.push(drawLocalCopy[0]);
const lastGSPL = this._generateGeoJSON(drawLocalCopy, 'Polygon');
this._addOrUpdateSource(lastGSPL, this.drawCurrentId.polygon);
this._addLayer(
this.drawCurrentId.polygon,
this.drawCurrentId.polygon,
'Polygon',
POLYGON_STYLE,
);
};
//鼠标点击
clickHandler = (e) => {
const _this = this;
this.clickCount++; // 每次单击事件计数器加1
if (this.clickCount === 1) {
// 如果是第一次单击
this.clickTimeout = setTimeout(function () {
// 启动超时变量
// 单击事件
_this.clickCount = 0; // 计数器清零
if (_this.nearlyClientDistant()) {
_this.drawLocal.push(_this.correctionMouseLocation);
// 如果是第一个点,那么就结束绘制
// todo 画面第一点后结束
if (
_this.drawModel === _this.drawModelChoose.Polygon &&
_this.correctionMouseLocation === _this.drawLocal[0]
) {
_this._currentDrawSource();
_this._currentDrawLayer();
_this.emit(_this.drawModel, _this.drawLocal);
_this.finishDraw();
return false;
} else {
_this.drawLocal.pop();
}
} else {
_this.drawLocal.push(e.lngLat);
}
_this._currentDrawSource();
_this._currentDrawLayer();
if (_this.drawModel === _this.drawModelChoose.Point) {
_this.drawIsFinish();
}
}, 200); // 设置超时时间为300毫秒
} else {
// 如果不是第一次单击
clearTimeout(this.clickTimeout); // 清除超时变量
this.clickCount = 0; // 计数器清零
// 在这里编写双击事件的操作
console.log('在这里编写双击事件的操作');
if (this.drawModel === this.drawModelChoose.LineString) {
this.drawIsFinish();
}
}
};
//右键点击
contextmenuHandler = (e) => {
if (this.drawLocal.length < 1) {
return false;
}
this.drawLocal.pop();
this._currentDrawSource();
this._currentDrawLayer();
this._currentDrawLastLine();
};
// 鼠标移动
mousemoveHandler = this.debounce((e) => {
this.currentMouseLocation = e.lngLat;
this._currentDrawLastLine();
}, 5);
// 判断是否吸附距离12像素
nearlyClientDistant = () => {
// 判断屏幕距离,鼠标吸附
let _this = this;
let mousePoint = [this.currentMouseLocation.lng, this.currentMouseLocation.lat];
let closestFeature = null;
let closestDistance = Infinity;
let threshold = 10; // 阈值,单位为像素
// 遍历所有特征,找到距离最近的特征
let clientPosition = _this.map.project(mousePoint);
this.drawLocal.forEach(function (feature) {
_this.map.project([feature.lng, feature.lat]);
let featurePosition = _this.map.project([feature.lng, feature.lat]);
// 计算两个点在屏幕上的像素距离
let distance = Math.sqrt(
Math.pow(clientPosition.x - featurePosition.x, 2) +
Math.pow(clientPosition.y - featurePosition.y, 2),
);
if (distance < closestDistance && distance < threshold) {
closestFeature = feature;
closestDistance = distance;
}
});
// 如果距离小于阈值,则将标注吸附到特征上
if (closestFeature) {
this._changeMouseCursor('pointer');
this.correctionMouseLocation = closestFeature;
return true;
} else {
// console.log('范围外')
this._changeMouseCursor('crosshair');
return false;
}
};
// 判断是否相交 true 相交 false 不相交
crossesLine = (line1, line2) => {
let _this = this;
if (this.drawLocal.length >= 3) {
let _line1 = line1.map((e) => {
return [e.lng, e.lat];
});
_line1.pop();
let _line2 = line2.map((e) => {
return [e.lng, e.lat];
});
//判断是否有交叉
let intersect = turf.lineIntersect(turf.lineString(_line1), turf.lineString(_line2));
if (intersect.features.length > 0) {
let coordinates = intersect.features[0].geometry.coordinates;
//判断是否交叉在点上
const isExist = _line1.some(
(item) => item[0] === coordinates[0] && item[1] === coordinates[1],
);
if (isExist) {
// console.log('no cross,穿过了交点')
_this.map.U.setProperty(this.drawCurrentId.lastLine, 'line-color', '#00FA9A');
_this.map.on('click', this.clickHandler);
} else {
// console.log('cross')
_this.map.U.setProperty(this.drawCurrentId.lastLine, 'line-color', '#DC143C');
_this._changeMouseCursor('no-drop');
_this.map.off('click', this.clickHandler);
}
} else {
// console.log('no cross,不沾边')
_this.map.U.setProperty(this.drawCurrentId.lastLine, 'line-color', '#00FA9A');
_this.map.on('click', this.clickHandler);
}
} else {
return false;
}
};
drawStart = () => {
//每次绘制都要初始化数据
this.drawLocal = [];
this.deleteDraw();
//禁用鼠标双击放大事件
this.map.doubleClickZoom.disable();
this._changeMouseCursor('crosshair');
this.map.on('click', this.clickHandler);
this.map.on('contextmenu', this.contextmenuHandler);
this.map.on('mousemove', this.mousemoveHandler);
};
draw = (shape) => {
if (this.drawModelChoose[shape]) {
this.drawModel = this.drawModelChoose[shape];
this.drawStart();
} else {
console.log(`暂无${shape}类型`);
}
};
drawIsFinish = () => {
let _this = this;
this.emit(this.drawModel, this.drawLocal);
this.finishDraw();
//恢复双击放大功能
setTimeout(() => {
_this.map.doubleClickZoom.enable();
}, 10);
};
// 结束绘制线和面
finishDraw = () => {
this.map.U.removeSource(this.drawCurrentId.lastLine);
this.map.U.removeLayer(this.drawCurrentId.lastLine);
this.drawModel = this.drawModelChoose.DEFAULT;
this.unDraw();
};
unDraw = () => {
// console.log('推出绘制模式');
this.map.off('click', this.clickHandler);
this.map.off('contextmenu', this.contextmenuHandler);
this.map.off('mousemove', this.mousemoveHandler);
this._changeMouseCursor('pointer');
this.drawLocal = [];
};
//删除绘制的内容
deleteDraw = () => {
this.map.U.removeSource([
this.drawCurrentId.line,
this.drawCurrentId.point,
this.drawCurrentId.lastLine,
this.drawCurrentId.polygon,
]);
this.map.U.removeLayer([
this.drawCurrentId.line,
this.drawCurrentId.point,
this.drawCurrentId.lastLine,
this.drawCurrentId.polygon,
]);
this.unDraw();
};
}

View File

@ -0,0 +1,27 @@
export enum MapboxConfig {
ACCESS_TOKEN = 'pk.eyJ1Ijoic2hpY2hhbzEyMyIsImEiOiJja3FobnI1aDEwNGF6Mm9vOXVhNnBzZmFhIn0.2fZKiMqCQHxVY74QShMEGQ',
TDT_TOKEN = 'b6585bc41ee16251dbe6b1af64f375d9',
// add more config options here
}
export const MapboxDefaultStyle = {
glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf',
version: 8,
sources: {
'raster-tiles': {
type: 'raster',
tiles: [
`https://t0.tianditu.gov.cn/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=${MapboxConfig.TDT_TOKEN}`,
],
tileSize: 256,
},
},
layers: [
{
id: 'tdt-img-tiles',
type: 'raster',
source: 'raster-tiles',
minzoom: 0,
maxzoom: 22,
},
],
};

View File

@ -0,0 +1,24 @@
.mapboxgl-ctrl-logo {
display: none !important;
}
.map-container{
position: relative;
}
.map-box,
.map-container {
width: 100%;
height: 100%;
}
.map-control {
position: absolute;
right: 10px;
top: 10px;
display: flex;
img {
width: 40px;
height: 40px;
cursor: pointer;
}
}

View File

@ -34,9 +34,9 @@
});
// perf .env.xxx, key--mode XXX
const addresses = ref({
development: 'http://www.a.com',
test: 'http://www.b.com',
prod: 'http://www.c.com',
development: 'http://localhost',
test: 'http://localhost',
prod: 'http://localhost',
});
const radioStyle = ref({
display: 'flex',

View File

@ -25,169 +25,16 @@ export const tabListData: TabItem[] = [
{
key: '1',
name: '通知',
list: [
{
id: '000000001',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png',
title: '你收到了 14 份新周报',
description: '',
datetime: '2017-08-09',
type: '1',
},
{
id: '000000002',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png',
title: '你推荐的 曲妮妮 已通过第三轮面试',
description: '',
datetime: '2017-08-08',
type: '1',
},
{
id: '000000003',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/kISTdvpyTAhtGxpovNWd.png',
title: '这种模板可以区分多种通知类型',
description: '',
datetime: '2017-08-07',
// read: true,
type: '1',
},
{
id: '000000004',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png',
title: '左侧图标用于区分不同的类型',
description: '',
datetime: '2017-08-07',
type: '1',
},
{
id: '000000005',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png',
title:
'标题可以设置自动显示省略号本例中标题行数已设为1行如果内容超过1行将自动截断并支持tooltip显示完整标题。',
description: '',
datetime: '2017-08-07',
type: '1',
},
{
id: '000000006',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png',
title: '左侧图标用于区分不同的类型',
description: '',
datetime: '2017-08-07',
type: '1',
},
{
id: '000000007',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png',
title: '左侧图标用于区分不同的类型',
description: '',
datetime: '2017-08-07',
type: '1',
},
{
id: '000000008',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png',
title: '左侧图标用于区分不同的类型',
description: '',
datetime: '2017-08-07',
type: '1',
},
{
id: '000000009',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png',
title: '左侧图标用于区分不同的类型',
description: '',
datetime: '2017-08-07',
type: '1',
},
{
id: '000000010',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png',
title: '左侧图标用于区分不同的类型',
description: '',
datetime: '2017-08-07',
type: '1',
},
],
list: [],
},
{
key: '2',
name: '消息',
list: [
{
id: '000000006',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg',
title: '曲丽丽 评论了你',
description: '描述信息描述信息描述信息',
datetime: '2017-08-07',
type: '2',
clickClose: true,
},
{
id: '000000007',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg',
title: '朱偏右 回复了你',
description: '这种模板用于提醒谁与你发生了互动',
datetime: '2017-08-07',
type: '2',
clickClose: true,
},
{
id: '000000008',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg',
title: '标题',
description:
'请将鼠标移动到此处以便测试超长的消息在此处将如何处理。本例中设置的描述最大行数为2超过2行的描述内容将被省略并且可以通过tooltip查看完整内容',
datetime: '2017-08-07',
type: '2',
clickClose: true,
},
],
list: [],
},
{
key: '3',
name: '待办',
list: [
{
id: '000000009',
avatar: '',
title: '任务名称',
description: '任务需要在 2017-01-12 20:00 前启动',
datetime: '',
extra: '未开始',
color: '',
type: '3',
},
{
id: '000000010',
avatar: '',
title: '第三方紧急代码变更',
description: '冠霖 需在 2017-01-07 前完成代码变更任务',
datetime: '',
extra: '马上到期',
color: 'red',
type: '3',
},
{
id: '000000011',
avatar: '',
title: '信息安全考试',
description: '指派竹尔于 2017-01-09 前完成更新并发布',
datetime: '',
extra: '已耗时 8 天',
color: 'gold',
type: '3',
},
{
id: '000000012',
avatar: '',
title: 'ABCD 版本发布',
description: '指派竹尔于 2017-01-09 前完成更新并发布',
datetime: '',
extra: '进行中',
color: 'blue',
type: '3',
},
],
list: [],
},
];

View File

@ -11,19 +11,19 @@
<template #overlay>
<Menu @click="handleMenuClick">
<MenuItem
<!-- <MenuItem
key="doc"
:text="t('layout.header.dropdownItemDoc')"
icon="ion:document-text-outline"
v-if="getShowDoc"
/>
/> -->
<Menu.Divider v-if="getShowDoc" />
<MenuItem
<!-- <MenuItem
v-if="getShowApi"
key="api"
:text="t('layout.header.dropdownChangeApi')"
icon="ant-design:swap-outlined"
/>
/> -->
<MenuItem
v-if="getUseLockPage"
key="lock"

View File

@ -65,7 +65,7 @@
"qrSignInFormTitle": "二维码登录",
"signUpFormTitle": "注册",
"forgetFormTitle": "重置密码",
"signInTitle": "费县智慧林业防灭火平台",
"signInTitle": "临沂市天空地数字执法",
"signInDesc": "",
"policy": "我同意xxx隐私政策",
"scanSign": "扫码后点击\"确认\",即可完成登录",

View File

@ -17,7 +17,7 @@ const dashboard: AppRouteModule = {
{
path: '/dashboard/analysis',
name: 'Analysis',
component: () => import('@/views/demo/caseauditing/index.vue'),
component: () => import('@/views/dashboard/analysis/index.vue'),
meta: {
// affix: true,
title: t('routes.dashboard.analysis'),

View File

@ -1,17 +1,32 @@
<template>
<div class="p-4">
<div class="md:flex enter-y">
<VisitSource class="md:w-1/3 !md:mx-4 !md:my-0 !my-4 w-full" :loading="loading" />
</div>
<div class="w-full" style="height: 100%">
<MapboxMaps :mapOptions="mapOptions" @map-on-load="mapOnLoad" @map-draw="handlerMapDraw" />
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import VisitSource from './components/VisitSource.vue';
import MapboxMaps from '@/components/MapboxMaps/index.vue';
const loading = ref(true);
setTimeout(() => {
loading.value = false;
}, 1500);
const mapOptions = {
center: [116.404, 39.905],
zoom: 8,
};
const mapOnLoad = (map) => {
// map
console.log('map::: ', map);
// mapU
console.log('map.U::: ', map.U);
//
const testSource =
'http://123.132.248.154:9205/geoserver/gwc/service/tms/1.0.0/TEST_WORK_SPACE%3Alindi@EPSG:900913@pbf/{z}/{x}/{y}.pbf';
//
map.U.addVector('sourceId', testSource).addLineLayer('layerId', {
source: 'sourceId',
'source-layer': 'lindi', // source-layer
});
};
//
const handlerMapDraw = (type: string, data: any) => {
console.log('data::: ', data);
console.log('type::: ', type);
};
</script>

View File

@ -18,14 +18,41 @@
</a-radio-group>
</a-form-item>
<a-form-item label="现场照片:">
<div v-for="(item, num) in imageList" :key="num">
<a-image :width="85" :src="item.s_filePath" />
<div
v-for="(item, num) in imageList"
:key="num"
style="
position: relative;
width: 125px;
height: 112px;
overflow: hidden;
float: left;
background: #f9f9f9;
margin-left: 6px;
margin-bottom: 6px;
"
>
<a-image :width="125" :src="item.s_filePath" />
</div>
</a-form-item>
<a-form-item label="现场视频:">
<a-input v-model:value="caseHandlingData.username" />
<div
style="margin-top: 10px; width: 240px; height: 150px"
v-for="(item, index) in videoList"
:key="index"
>
<video width="100%" height="100%" controls>
<source :src="item" type="video/mp4" />
您的浏览器不支持Video标签
</video>
</div>
<a-empty v-show="videoList.length <= 0">
<template #description>
<span>暂无视频</span>
</template>
</a-empty>
</a-form-item>
<a-form-item label="处理措施: " v-if="illegal == 1">
<a-form-item label="处理措施: " v-if="illegal == '1'">
<a-select
v-model:value="caseHandlingData.measure_name"
placeholder="请选择处理措施"
@ -33,7 +60,7 @@
/>
</a-form-item>
<a-col :span="24" v-if="illegal == 0">
<a-col :span="24" v-if="illegal == '0'">
<a-form-item label="项目名称: ">
<a-input v-model:value="caseHandlingData.result_name" />
</a-form-item>
@ -64,13 +91,13 @@
<a-input v-model:value="caseHandlingData.evidence_file_indate" />
</a-form-item>
<a-form-item label="合法批准文件: " v-if="illegal == 0">
<a-form-item label="合法批准文件: " v-if="illegal == '0'">
<div
v-for="(item, num) in evidenceFileList"
:key="num"
style="
position: relative;
width: 85px;
width: 125px;
height: 112px;
overflow: hidden;
float: left;
@ -79,7 +106,7 @@
margin-bottom: 6px;
"
>
<a-image :width="85" :src="item.s_filePath" />
<a-image :width="125" :src="item.s_filePath" />
</div>
<a-empty v-if="evidenceFileList.length <= 0">
<template #description>
@ -88,13 +115,13 @@
</a-empty>
</a-form-item>
<a-form-item label="勘测定界图: " v-if="illegal == 0">
<a-form-item label="勘测定界图: " v-if="illegal == '0'">
<div
v-for="(item, num) in boundaryImageList"
:key="num"
style="
position: relative;
width: 85px;
width: 125px;
height: 112px;
overflow: hidden;
float: left;
@ -103,7 +130,7 @@
margin-bottom: 6px;
"
>
<a-image :width="85" :src="item.s_filePath" />
<a-image :width="125" :src="item.s_filePath" />
</div>
<a-empty v-if="boundaryImageList.length <= 0">
<template #description>
@ -114,15 +141,15 @@
<a-form-item label="是否超范围: ">
<a-radio-group v-model:value="caseHandlingData.is_out_boundary">
<a-radio :label="1"></a-radio>
<a-radio :label="0"></a-radio>
<a-radio :value="1"></a-radio>
<a-radio :value="0"></a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="是否超层: ">
<a-radio-group v-model:value="caseHandlingData.is_over_floor">
<a-radio :label="1"></a-radio>
<a-radio :label="0"></a-radio>
<a-radio :value="1"></a-radio>
<a-radio :value="0"></a-radio>
</a-radio-group>
</a-form-item>
@ -134,7 +161,7 @@
</a-form-item>
</a-col>
<a-col :span="24" v-if="illegal == 1 && caseHandlingData.measure_name == '拟拆除'">
<a-col :span="24" v-if="illegal == '1' && caseHandlingData.measure_name == '拟拆除'">
<a-form-item label="实际用途: ">
<a-input v-model:value="caseHandlingData.actual_use_to" />
</a-form-item>
@ -146,8 +173,8 @@
</a-form-item>
<a-form-item label="建设情况: ">
<a-radio-group v-model:value="caseHandlingData.is_build_complete">
<a-radio :label="1">已建成</a-radio>
<a-radio :label="0">建设中</a-radio>
<a-radio :value="1">已建成</a-radio>
<a-radio :value="0">建设中</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="建筑结构: ">
@ -160,7 +187,7 @@
:key="num"
style="
position: relative;
width: 85px;
width: 125px;
height: 112px;
overflow: hidden;
float: left;
@ -169,7 +196,7 @@
margin-bottom: 6px;
"
>
<a-image :width="85" :src="item.s_filePath" />
<a-image :width="125" :src="item.s_filePath" />
</div>
<a-empty v-if="afterImageList.length <= 0">
<template #description>
@ -185,7 +212,7 @@
</a-form-item>
</a-col>
<a-col :span="24" v-if="illegal == 1 && caseHandlingData.measure_name == '查处'">
<a-col :span="24" v-if="illegal == '1' && caseHandlingData.measure_name == '查处'">
<a-form-item label="实际用途: ">
<a-input v-model:value="caseHandlingData.actual_use_to" />
</a-form-item>
@ -200,8 +227,8 @@
</a-form-item>
<a-form-item label="违法类型: ">
<a-radio-group v-model:value="caseHandlingData.illegal_type">
<a-radio label="违法建筑类">违法建筑类</a-radio>
<a-radio label="非法采矿类">非法采矿类</a-radio>
<a-radio value="违法建筑类">违法建筑类</a-radio>
<a-radio value="非法采矿类">非法采矿类</a-radio>
</a-radio-group>
</a-form-item>
<a-divider orientation="left">案件办理信息-查处</a-divider>
@ -222,7 +249,7 @@
:key="num"
style="
position: relative;
width: 85px;
width: 125px;
height: 112px;
overflow: hidden;
float: left;
@ -231,7 +258,7 @@
margin-bottom: 6px;
"
>
<a-image :width="85" :src="item.s_filePath" />
<a-image :width="125" :src="item.s_filePath" />
</div>
<a-empty v-if="punishImageList.length <= 0">
<template #description>
@ -245,7 +272,7 @@
:key="num"
style="
position: relative;
width: 85px;
width: 125px;
height: 112px;
overflow: hidden;
float: left;
@ -254,7 +281,7 @@
margin-bottom: 6px;
"
>
<a-image :width="85" :src="item.s_filePath" />
<a-image :width="125" :src="item.s_filePath" />
</div>
<a-empty v-if="paymentImagesList.length <= 0">
<template #description>
@ -271,7 +298,7 @@
</a-form-item>
</a-col>
<a-col :span="24" v-if="illegal == 1 && caseHandlingData.measure_name == '拟完善手续'">
<a-col :span="24" v-if="illegal == '1' && caseHandlingData.measure_name == '拟完善手续'">
<a-form-item label="实际用途: ">
<a-input v-model:value="caseHandlingData.actual_use_to" />
</a-form-item>
@ -286,8 +313,8 @@
</a-form-item>
<a-form-item label="完善手续条件: ">
<a-radio-group v-model:value="caseHandlingData.is_have_checkout_condition">
<a-radio :label="1"></a-radio>
<a-radio :label="0"></a-radio>
<a-radio :value="1"></a-radio>
<a-radio :value="0"></a-radio>
</a-radio-group>
</a-form-item>
<a-divider orientation="left">案件办理信息-完善手续</a-divider>
@ -298,7 +325,7 @@
:key="num"
style="
position: relative;
width: 85px;
width: 125px;
height: 112px;
overflow: hidden;
float: left;
@ -307,7 +334,7 @@
margin-bottom: 6px;
"
>
<a-image :width="85" :src="item.s_filePath" />
<a-image :width="125" :src="item.s_filePath" />
</div>
<a-empty v-if="agreeImageList.length <= 0">
<template #description>
@ -321,7 +348,7 @@
:key="num"
style="
position: relative;
width: 85px;
width: 125px;
height: 112px;
overflow: hidden;
float: left;
@ -330,7 +357,7 @@
margin-bottom: 6px;
"
>
<a-image :width="85" :src="item.s_filePath" />
<a-image :width="124" :src="item.s_filePath" />
</div>
<a-empty v-if="checkoutImageList.length <= 0">
<template #description>
@ -344,7 +371,7 @@
:key="num"
style="
position: relative;
width: 85px;
width: 125px;
height: 112px;
overflow: hidden;
float: left;
@ -353,7 +380,7 @@
margin-bottom: 6px;
"
>
<a-image :width="85" :src="item.s_filePath" />
<a-image :width="125" :src="item.s_filePath" />
</div>
<a-empty v-if="boundaryImageList.length <= 0">
<template #description>
@ -372,7 +399,7 @@
</a-form-item>
</a-col>
<a-col :span="24" v-if="illegal == 2">
<a-col :span="24" v-if="illegal == '2'">
<a-form-item label="伪变化原因: ">
<a-input v-model:value="caseHandlingData.pseudo_change_reason" />
</a-form-item>
@ -385,14 +412,14 @@
<a-form-item label="是否有建筑物: ">
<!-- <a-input v-model:value="caseHandlingData.is_have_build" /> -->
<a-radio-group v-model:value="caseHandlingData.is_have_build">
<a-radio :label="1"></a-radio>
<a-radio :label="0"></a-radio>
<a-radio :value="1"></a-radio>
<a-radio :value="0"></a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="是否永久性建筑: " v-if="caseHandlingData.is_have_build == 1">
<a-radio-group v-model:value="caseHandlingData.is_forever_build">
<a-radio :label="1"></a-radio>
<a-radio :label="0"></a-radio>
<a-radio :value="1"></a-radio>
<a-radio :value="0"></a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="办理人: ">
@ -406,8 +433,24 @@
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { onMounted, ref, defineProps, watch } from 'vue';
import { getUserInfoData, getCaseDealDetail } from '@/api/caseauditing/index';
const caseId: any = ref();
const props = defineProps({
id: {
default: null,
type: String,
},
});
watch(
() => props.id,
(newValue) => {
caseId.value = newValue;
getCaseHandlingDetail();
},
{ immediate: true, deep: true },
);
const caseHandlingData: any = ref({
id: '',
measure_name: '',
@ -419,7 +462,7 @@
illegal_contact_phone: null, //
actual_scene_case: null, //
});
const illegal: any = ref('0');
const illegal: any = ref();
const dealMeasuresList: any = ref([]);
const evidenceFileList: any = ref([]);
const boundaryImageList: any = ref([]);
@ -429,4 +472,81 @@
const agreeImageList: any = ref([]);
const checkoutImageList: any = ref([]);
const imageList: any = ref([]);
const videoList: any = ref([]);
function getUserInfo() {
getUserInfoData().then((res) => {
caseHandlingData.value.createusername = res.user.Name;
});
}
function getCaseHandlingDetail() {
getCaseDealDetail({ caseid: caseId.value }).then((res) => {
illegal.value = JSON.stringify(res.is_illegal);
caseHandlingData.value = res.info;
imageList.value = [];
if (res.pic_info_list.length > 0) {
res.pic_info_list.forEach((item) => {
item.s_filePath = 'http://60.213.14.14:6070/' + '/S_' + item.filePath;
item.filePath = 'http://60.213.14.14:6070/' + '/' + item.filePath;
imageList.value.push(item);
});
}
afterImageList.value = [];
if (res.after_pic_list.length > 0) {
res.after_pic_list.forEach((item) => {
item.s_filePath = 'http://60.213.14.14:6070/' + '/S_' + item.filePath;
item.filePath = 'http://60.213.14.14:6070/' + '/' + item.filePath;
afterImageList.value.push(item);
});
}
//
evidenceFileList.value = [];
if (res.evidence_file_list.length > 0) {
res.evidence_file_list.forEach((item) => {
item.s_filePath = 'http://60.213.14.14:6070/' + '/S_' + item.filePath;
item.filePath = 'http://60.213.14.14:6070/' + '/' + item.filePath;
evidenceFileList.value.push(item);
});
}
//
if (res.punish_pic_list.length > 0) {
punishImageList.value = handleImageArray(res.punish_pic_list);
}
//
if (res.payment_pic_list.length > 0) {
paymentImagesList.value = handleImageArray(res.payment_pic_list);
}
//
if (res.agree_checkout_pic_list.length > 0) {
agreeImageList.value = handleImageArray(res.agree_checkout_pic_list);
}
//
if (res.checkout_pic_list.length > 0) {
checkoutImageList.value = handleImageArray(res.checkout_pic_list);
}
//
if (res.boundary_pic_list.length > 0) {
boundaryImageList.value = handleImageArray(res.boundary_pic_list);
}
if (res.video_list) {
res.video_list.forEach((item) => {
videoList.value.push('http://60.213.14.14:6070/' + item);
});
}
});
}
function handleImageArray(imageArr) {
let returnArray: any = ref([]);
imageArr.forEach((item) => {
let obj = {
s_filePath: 'http://60.213.14.14:6070/' + '/S_' + item,
filePath: 'http://60.213.14.14:6070/' + '/' + item,
};
returnArray.value.push(obj);
});
return returnArray.value;
}
onMounted(() => {
getUserInfo();
});
</script>

View File

@ -33,14 +33,14 @@ export const columns: BasicColumn[] = [
customRender: ({ record }) => {
const status = record.is_illegal;
if (status == 1) {
const text = '合法';
return text;
} else if (status == 2) {
const text = '违法';
return text;
} else {
} else if (status == 2) {
const text = '伪变化';
return text;
} else {
const text = '合法';
return text;
}
},
},
@ -66,7 +66,7 @@ export const formSchema: FormSchema[] = [
dynamicDisabled: true,
},
{
field: 'countyname',
field: 'homeAddress',
label: '案件地址:',
component: 'Input',
dynamicDisabled: true,
@ -90,7 +90,7 @@ export const formSchema: FormSchema[] = [
dynamicDisabled: true,
},
{
field: 'lng',
field: 'lngLat',
label: '经纬度:',
component: 'Input',
dynamicDisabled: true,
@ -106,13 +106,13 @@ export const formSchema: FormSchema[] = [
slot: 'videoSlot',
},
{
field: 'name',
field: 'identification_user',
label: '上报人:',
component: 'Input',
dynamicDisabled: true,
},
{
field: 'name',
field: 'identification_time',
label: '上报时间:',
component: 'Input',
dynamicDisabled: true,

View File

@ -8,32 +8,50 @@
</a-button>
</div>
<div class="flex">
<a-select
ref="select"
<a-tree-select
v-if="selectOptions1.length > 0"
v-model:value="selectValues1"
:options="selectOptions1"
style="width: 200px"
class="ml-3"
show-search
style="width: 230px"
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
placeholder="查询地区"
allow-clear
:tree-data="selectOptions1"
:field-names="{
children: 'children',
value: 'id',
label: 'name',
}"
tree-node-filter-prop="name"
@change="areaChange"
/>
<a-select
ref="select"
v-model:value="selectValues2"
v-model:value="is_illegal"
style="width: 150px"
class="ml-3"
allowClear
:options="selectOptions2"
placeholder="现场状况"
@change="reload1"
/>
<a-select
ref="select"
v-model:value="selectValues3"
v-model:value="is_drawback"
:options="selectOptions3"
style="width: 150px"
class="ml-3"
allowClear
placeholder="新增退回"
@change="reload1"
/>
<a-input style="width: 150px" class="ml-3" v-model:value="value" placeholder="请输入" />
<a-button class="ml-3" :icon="h(SearchOutlined)">搜索</a-button>
<a-input
style="width: 150px"
class="ml-3"
v-model:value="searchKey"
placeholder="请输入"
/>
<a-button class="ml-3" :icon="h(SearchOutlined)" @click="reload1"></a-button>
<a-button type="success" class="ml-3" :icon="h(DownloadOutlined)">导出</a-button>
</div>
</div>
@ -47,10 +65,9 @@
:actions="[
{
label: '收藏',
type: 'link',
color: 'warning',
onClick: () => {
handleEdit(record);
handleCollention(record);
},
},
{
@ -84,7 +101,7 @@
type: 'link',
color: 'warning',
onClick: () => {
handleEdit(record);
handleRemoveCollention(record);
},
},
{
@ -119,15 +136,15 @@
/></div>
</div>
<div :class="`${prefixCls}-content-tabbox-right-content`">
<BasicForm ref="formRef" @register="registerForm" v-if="tabsActiveIndex == 0">
<template #imgSlot="{ model, field }">
<BasicForm ref="formRef" @register="registerForm" v-show="tabsActiveIndex == 0">
<template #imgSlot>
<div
v-for="(item, num) in fileList"
:key="num"
style="
position: relative;
width: 85px;
height: 112px;
width: 125px;
height: 90px;
overflow: hidden;
float: left;
background: #f9f9f9;
@ -135,26 +152,44 @@
margin-bottom: 6px;
"
>
<a-image :width="85" :src="item.url" />
<a-image :width="125" :src="item.url" />
</div>
<a-empty v-if="fileList.length <= 0">
<a-empty v-show="fileList.length <= 0">
<template #description>
<span>暂无图片</span>
</template>
</a-empty>
</template>
<template #videoSlot="{ model, field }"></template>
<template #videoSlot>
<div
style="margin-top: 10px; width: 240px; height: 150px"
v-for="(item, index) in videoList"
:key="index"
>
<video width="100%" height="100%" controls>
<source :src="item" type="video/mp4" />
您的浏览器不支持Video标签
</video>
</div>
<a-empty v-show="videoList.length <= 0">
<template #description>
<span>暂无视频</span>
</template>
</a-empty>
</template>
</BasicForm>
<HandleCase v-if="tabsActiveIndex == 1" />
<HandleCase :id="selectRowDetail.id" v-show="tabsActiveIndex == 1" />
</div>
<div :class="`${prefixCls}-content-tabbox-right-footer`">
<a-input class="ml-3" v-model:value="value" placeholder="案件退回原因" />
<a-button type="error" class="ml-3"> 退回 </a-button>
<a-button type="primary" class="ml-3"> 通过 </a-button>
<a-input class="ml-3" v-model:value="caseBackReason" placeholder="案件退回原因" />
<a-button type="error" class="ml-3" @click="handleCaseBack"> 退 </a-button>
<a-button type="primary" class="ml-3" @click="handlePassForm"> </a-button>
</div>
</div>
</div>
<div :class="`${prefixCls}-content-mapbox`"></div>
<div :class="`${prefixCls}-content-mapbox`">
<MapDetail :ruleForm="selectRowDetail"></MapDetail>
</div>
</div>
</div>
</PageWrapper>
@ -166,7 +201,6 @@
StarOutlined,
DownloadOutlined,
CloseOutlined,
PlusOutlined,
} from '@ant-design/icons-vue';
import HandleCase from '@/views/demo/caseauditing/HandleCase.vue';
import { BasicTable, useTable, TableAction } from '@/components/Table';
@ -174,73 +208,49 @@
import { PageWrapper } from '@/components/Page';
import {
getTableDataList,
getUserOrg,
addCaseCollection,
delCaseCollection,
getCollectionCaseList,
getUserInfoData,
getCaseDataDetail,
getCaseList,
caseAudiSteps,
caseBackSteps,
} from '@/api/caseauditing/index';
import { getDeptList } from '@/api/demo/system';
import { columns, formSchema } from './index.data';
// import { useMessage } from '@/hooks/web/useMessage';
import { useMessage } from '@/hooks/web/useMessage';
import MapDetail from '@/views/demo/summaryverification/mapDetail.vue';
// const { createConfirm, createMessage } = useMessage();
const { createMessage } = useMessage();
const favoriteNum: any = ref();
const tabsActiveIndex: any = ref('0');
const tabsArr: any = ref(['案件信息', '核查办理']);
const auditingVisible: any = ref(true);
const auditingVisible: any = ref(false);
const collenctionVisible: any = ref(false);
const collenctionList: any = ref([]);
const selectRowDetail: any = ref({});
const caseBackReason: any = ref();
const selectValues1: any = ref();
const selectOptions1: any = ref([]);
// const playerOptions: any = ref([]);
const selectValues2: any = ref();
const videoList: any = ref([]);
const searchKey: any = ref();
const countyid: any = ref();
const streetid: any = ref();
const communityid: any = ref();
const is_illegal: any = ref();
const selectOptions2: any = ref([
{ label: '合法', value: 0 },
{ label: '违法', value: 1 },
{ label: '伪变化', value: 2 },
]);
const selectValues3: any = ref();
const is_drawback: any = ref();
const selectOptions3: any = ref([
{ label: '新增', value: 0 },
{ label: '退回', value: 1 },
]);
const fileList = ref([
{
uid: '-1',
name: 'image.png',
status: 'done',
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
},
{
uid: '-2',
name: 'image.png',
status: 'done',
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
},
]);
const previewVisible = ref(false);
const previewImage = ref('');
const previewTitle = ref('');
function getBase64(file: File) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = (error) => reject(error);
});
}
const handleCancel = () => {
previewVisible.value = false;
previewTitle.value = '';
};
const handlePreview = async (file: UploadProps['fileList'][number]) => {
if (!file.url && !file.preview) {
file.preview = (await getBase64(file.originFileObj)) as string;
}
previewImage.value = file.url || file.preview;
previewVisible.value = true;
previewTitle.value = file.name || file.url.substring(file.url.lastIndexOf('/') + 1);
};
const fileList: any = ref([]);
const [registerTable, { reload: reload1 }] = useTable({
title: '',
@ -261,6 +271,19 @@
title: '操作',
dataIndex: 'action',
},
beforeFetch: (data) => {
let temp = {
page: data.page,
limit: data.limit,
is_illegal: is_illegal.value,
is_drawback: is_drawback.value,
countyid: countyid.value,
streetid: streetid.value,
communityid: communityid.value,
key: searchKey.value,
};
return temp;
},
handleSearchInfoFn(info) {
return info;
},
@ -295,10 +318,109 @@
showActionButtonGroup: false,
baseColProps: { lg: 24, md: 24 },
});
function areaChange(items) {
countyid.value = null;
streetid.value = null;
communityid.value = null;
if (items && JSON.stringify(items).length == 6) {
countyid.value = items;
}
if (items && JSON.stringify(items).length == 9) {
streetid.value = items;
}
if (items && JSON.stringify(items).length == 12) {
communityid.value = items;
}
reload1();
}
function handlePassForm() {
const param = {
id: selectRowDetail.value.id,
};
caseAudiSteps(param).then((res) => {
if (res) {
createMessage.success('审核成功');
reload1();
reload2();
}
});
}
function handleCaseBack() {
if (!caseBackReason.value) {
createMessage.error('退回原因不能为空');
return;
}
const param = {
id: selectRowDetail.value.id,
drawbackReason: caseBackReason.value,
};
caseBackSteps(param).then((res) => {
if (res) {
createMessage.success('操作成功');
} else {
createMessage.error('此案件未办理,无需退回。');
}
});
}
function handleAuditing(record) {
const formData = record;
caseBackReason.value = null;
formData.homeAddress =
record.countyname + record.streetname + record.communityname + record.address;
formData.lngLat = record.lng + ' , ' + record.lat;
selectRowDetail.value = formData;
auditingVisible.value = true;
setFieldsValue(record);
setTimeout(() => {
setFieldsValue(formData);
}, 100);
const param = {
id: record.id,
};
getCaseDataDetail(param).then((res) => {
fileList.value = [];
videoList.value = [];
if (res.pics) {
res.pics.forEach((item) => {
fileList.value.push({
url: 'http://60.213.14.14:6070/' + item.path,
id: item.id,
});
});
}
if (res.video_list) {
res.video_list.forEach((item) => {
videoList.value.push('http://60.213.14.14:6070/' + item);
});
}
});
}
function handleCollention(row) {
getUserInfoData().then((res) => {
let param = {
caseNo: row.case_no,
favoriteUserId: res.user.Id,
};
addCaseCollection(param).then((rel) => {
if (rel) {
createMessage.success('收藏成功');
getCollentionLength();
}
});
});
}
function handleRemoveCollention(row) {
const arr = collenctionList.value.filter((item) => {
return item.caseNo == row.case_no;
});
let param = [arr[0].id];
delCaseCollection(param).then((res) => {
if (res) {
createMessage.success('已从收藏夹中移除');
getCollentionLength();
reload2();
}
});
}
function openCollenction() {
collenctionVisible.value = true;
@ -315,12 +437,29 @@
}
function getCollentionLength() {
getCollectionCaseList().then((res) => {
console.log('ree', res);
favoriteNum.value = res.total;
});
}
function getOrgList() {
getDeptList().then((res) => {
res.forEach((item) => {
if (item.id == '371300') {
selectOptions1.value = item.children;
}
});
});
}
function getCaseCollList() {
getUserInfoData().then((res) => {
getCaseList({ uid: res.user.Id }).then((rel) => {
collenctionList.value = rel;
});
});
}
onMounted(() => {
getCollentionLength();
getCaseCollList();
getOrgList();
});
const prefixCls = 'form-box';
</script>
@ -358,6 +497,7 @@
&-collenction {
display: flex;
flex-direction: column;
height: 100%;
&-header {
padding: 0 10px;

View File

@ -0,0 +1,95 @@
<template>
<div>
<BasicTable @register="registerTable" :searchInfo="searchInfo">
<template #toolbar>
<PermissionBtn @btn-event="onBtnClicked" />
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction
:actions="[
{
label: '详情',
onClick: viewDetail.bind(null, record),
},
]"
/>
</template>
</template>
</BasicTable>
<BasicModal
v-bind="$attrs"
@register="registerModal"
title="案件详情"
:canFullscreen="false"
:defaultFullscreen="true"
:showCancelBtn="false"
:showOkBtn="false"
:draggable="false"
>
<CaseView :caseId="caseId"></CaseView>
</BasicModal>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue';
import { BasicTable, useTable, TableAction, BasicColumn } from '@/components/Table';
import { getCaseInfoList } from '@/api/monitor/index';
import { useMessage } from '@/hooks/web/useMessage';
import { PermissionBtn } from '@/components/PermissionBtn/index';
import { searchFormSchema, columns } from './list.data';
import { BasicModal, useModal } from '@/components/Modal';
import { CaseView } from '@/views/demo/monitor/index';
const { createConfirm, createMessage } = useMessage();
const searchInfo = reactive<Recordable>({});
const [registerTable, { reload, getSelectRows, clearSelectedRowKeys }] = useTable({
title: '案件列表',
api: getCaseInfoList,
columns,
rowKey: 'id',
formConfig: {
labelWidth: 120,
schemas: searchFormSchema,
},
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
rowSelection: {
type: 'checkbox',
},
handleSearchInfoFn(info) {
return info;
},
actionColumn: {
width: 80,
title: '操作',
dataIndex: 'action',
},
});
const [registerModal, { openModal, setModalProps }] = useModal();
const caseId = ref('');
function onBtnClicked(domId) {
switch (domId) {
case 'btnAdd':
break;
default:
break;
}
}
function viewDetail(record) {
console.log(record);
caseId.value = record.id;
openModal();
}
</script>
<style lang="less" scoped>
// ::v-deep .ant-row .ant-col{
// margin-right: 2px;
// }
// ::v-deep .ant-row .ant-col.ant-col-2 {
// margin-right: 10px;
// }
</style>

View File

@ -0,0 +1,204 @@
import { BasicColumn, FormSchema } from '@/components/Table';
export const columns: BasicColumn[] = [
{
dataIndex: 'case_no',
title: '案件编号',
},
{
dataIndex: 'countyname',
title: '县区',
defaultHidden: true,
},
{
dataIndex: 'streetname',
title: '乡镇',
},
{
dataIndex: 'communityname',
title: '村/社区',
},
{
dataIndex: 'address',
title: '详细地址',
defaultHidden: true,
},
{
dataIndex: 'lng',
title: '经度',
defaultHidden: true,
},
{
dataIndex: 'lat',
title: '纬度',
defaultHidden: true,
},
{
dataIndex: 'area',
title: '占地面积',
defaultHidden: true,
},
{
dataIndex: 'case_description',
title: '案件描述',
},
{
dataIndex: 'typename',
title: '案件类型',
},
{
dataIndex: 'handle_status_name',
title: '案件状态',
},
{
dataIndex: 'deal_username',
title: '处理人',
defaultHidden: true,
},
{
dataIndex: 'deal_time',
title: '处理时间',
defaultHidden: true,
},
{
dataIndex: 'identification_user',
title: '判读人',
defaultHidden: true,
},
{
dataIndex: 'verifystatusname',
title: '审核流程',
defaultHidden: true,
},
{
dataIndex: 'createusername',
title: '上报人',
defaultHidden: true,
},
{
dataIndex: 'createtime',
title: '上报时间',
defaultHidden: true,
},
{
dataIndex: 'verifytime',
title: '审核时间',
defaultHidden: true,
},
{
dataIndex: 'verifyuser',
title: '审核人',
defaultHidden: true,
},
];
export const searchFormSchema: FormSchema[] = [
{
field: 'is_drawback',
component: 'Select',
label: '新增退回',
colProps: { span: 4 },
componentProps: {
placeholder: '新增退回',
options: [
{ label: '新增', value: 0, key: '0' },
{ label: '退回', value: 1, key: '1' },
],
},
},
{
field: 'handle_status_id',
component: 'Select',
label: '办理状态',
colProps: { span: 4 },
componentProps: {
placeholder: '办理状态',
options: [
{ value: 0, label: '未办理' },
{ value: 1, label: '待审核' },
{ value: 2, label: '已办结' },
],
},
},
{
field: 'typeid',
component: 'Select',
label: '案件类型',
colProps: { span: 4 },
componentProps: {
placeholder: '案件类型',
// 接口获取/categorys/load
},
},
{
// countyid streetid communityid
field: 'countyid',
component: 'TreeSelect',
colProps: { span: 4 },
label: '查询地区',
componentProps: {
placeholder: '查询地区',
// 接口获取/Orgs/OrgList
},
},
{
field: 'is_illegal',
component: 'Select',
colProps: { span: 4 },
label: '现场状况',
componentProps: {
placeholder: '现场状况',
options: [
{ value: 0, label: '合法' },
{ value: 1, label: '违法' },
{ value: 2, label: '伪变化' },
],
},
},
{
field: 'case_no',
component: 'Input',
label: '案件编号',
colProps: { span: 4 },
componentProps: {
placeholder: '案件编号',
},
},
{
field: 'key',
component: 'Input',
label: '关键字',
colProps: { span: 4 },
componentProps: {
placeholder: '请输入关键字',
},
},
{
field: 'identification_user',
label: '判读人姓名',
component: 'Input',
colProps: { span: 4 },
componentProps: {
placeholder: '判读人姓名',
},
},
{
field: 'deal_username',
component: 'Input',
label: '处理人姓名',
colProps: { span: 4 },
componentProps: {
placeholder: '处理人姓名',
},
},
{
field: '[report_start_time, report_end_time]',
component: 'RangePicker',
label: '日期范围',
componentProps: {
format: 'YYYY-MM-DD',
placeholder: ['开始日期', '结束日期'],
},
colProps: { span: 8 },
},
];

View File

@ -0,0 +1,440 @@
<template>
<div class="case-view">
<div class="case-view_step">
<a-steps
v-model:current="current"
type="navigation"
size="small"
:style="stepStyle"
>
<a-step
v-for="(item, index) in flowLog"
:key="index"
:title="item.name"
:status="item.state"
:disabled="item.status == 0 ? true : false"
/>
</a-steps>
</div>
<div class="case-view_content">
<div class="file-box w-1/2 xl:w-1/2" v-if="caseHandleInfo">
<CollapseContainer
title="【案件下发信息】"
:canExpan="false"
v-if="current == 0 || current == 4"
>
<Issue :data="detailData"></Issue>
</CollapseContainer>
<CollapseContainer
title="【案件核查信息】"
:canExpan="false"
v-if="current == 1 || current == 4"
>
<Inspect
:data="caseHandleInfo"
:playerOptions="playerOptions"
:threadImageList="threadImageList"
></Inspect>
</CollapseContainer>
<CollapseContainer
title="【案件办理信息-合法举证】"
:canExpan="false"
v-if="
(caseHandleInfo.is_illegal == '合法' && current == 2) ||
(caseHandleInfo.is_illegal == '合法' && current == 4)
"
>
<Evidence
:data="caseHandleInfo"
:evidenceFileList="evidenceFileList"
:boundaryImageList="boundaryImageList"
></Evidence>
</CollapseContainer>
<CollapseContainer
title="【案件办理信息-伪变化】"
:canExpan="false"
v-if="
(caseHandleInfo.is_illegal == '伪变化' && current == 2) ||
(caseHandleInfo.is_illegal == '伪变化' && current == 4)
"
>
<div> 伪变化没有案件办理信息 </div>
</CollapseContainer>
<CollapseContainer
title="【案件办理信息-违法-拟拆除】"
:canExpan="false"
v-if="
(caseHandleInfo.is_illegal == '违法' &&
caseHandleInfo.info.measure_name == '拟拆除' &&
current == 2) ||
(caseHandleInfo.is_illegal == '违法' &&
caseHandleInfo.info.measure_name == '拟拆除' &&
current == 4)
"
>
<Dismantle :data="caseHandleInfo" :videoOptions="videoOptions"></Dismantle>
</CollapseContainer>
<CollapseContainer
title="【案件办理信息-违法-查处】"
:canExpan="false"
v-if="
(caseHandleInfo.is_illegal == '违法' &&
caseHandleInfo.info.measure_name == '查处' &&
current == 2) ||
(caseHandleInfo.is_illegal == '违法' &&
caseHandleInfo.info.measure_name == '查处' &&
current == 4)
"
>
<Investigate
:data="caseHandleInfo"
:paymentImageList="paymentImageList"
:punishImageList="punishImageList"
></Investigate>
</CollapseContainer>
<CollapseContainer
title="【案件办理信息-违法-拟完善手续】"
:canExpan="false"
v-if="
(caseHandleInfo.is_illegal == '违法' &&
caseHandleInfo.info.measure_name == '拟完善手续' &&
current == 2) ||
(caseHandleInfo.is_illegal == '违法' &&
caseHandleInfo.info.measure_name == '拟完善手续' &&
current == 4)
"
>
<Procedure
:data="caseHandleInfo"
:agreeImageList="agreeImageList"
:checkoutImageList="checkoutImageList"
:boundaryImageList="boundaryImageList"
></Procedure>
</CollapseContainer>
<CollapseContainer
title="【案件审核信息】"
:canExpan="false"
v-if="current == 3 || current == 4"
>
<Audit :data="flowLog[3]"></Audit>
</CollapseContainer>
<CollapseContainer
title="【案件退回描述】"
:canExpan="false"
v-if="detailData.is_drawback == 1"
>
<a-descriptions bordered :column="2" size="small" :labelStyle="labelStyle">
<a-descriptions-item label="退回描述">
{{ detailData.drawback_description }}
</a-descriptions-item>
</a-descriptions>
</CollapseContainer>
</div>
<CollapseContainer title="地图位置" :canExpan="false" class="map-box ml-1 w-1/2 xl:w-1/2">
<MapDetail :ruleForm="detailData" :isOnce="true"></MapDetail>
</CollapseContainer>
</div>
</div>
</template>
<script lang="ts" setup>
// 202205020912205393
// 202404181541067344
import { ref, onMounted, reactive, watch } from 'vue';
import { getCaseFlowLog, getCaseInfo, getDroneCaseDeal } from '@/api/monitor/index';
import { fileListModel, fileList } from '@/api/monitor/model/index';
import { CollapseContainer } from '@/components/Container';
import {
Issue,
Inspect,
Audit,
Dismantle,
MapDetail,
Evidence,
Investigate,
Procedure,
} from '../index';
const BASE_IMAGE_URL = ref('http://192.168.104:9011');
const current = ref<number>(0);
const stepStyle = ref({
marginBottom: '60px',
boxShadow: '0px -1px 0 0 #e8e8e8 inset',
});
const labelStyle = ref({
width: '100px',
});
const props = defineProps({
caseId: String,
});
console.log(props);
watch(
() => props.caseId,
(newVal, oldVal) => {
console.log(newVal);
getCaseFlowLogData();
loadDetailCaseInfo();
getCaseHandleInfo();
},
);
const detailData = ref();
const caseHandleInfo = ref();
const playerOptions = ref();
//
const threadImageList = ref<fileListModel>([]);
//
const threadAfterImageList = ref<any>([]);
//
const videoOptions = ref();
//
const evidenceFileList = ref<fileListModel>([]);
//
const boundaryImageList = ref<fileListModel>([]);
//
const punishImageList = ref<fileListModel>([]);
//
const paymentImageList = ref<fileListModel>([]);
//
const agreeImageList = ref<fileListModel>([]);
//
const checkoutImageList = ref<fileListModel>([]);
const flowLog = ref();
//
async function getCaseFlowLogData() {
current.value = 0;
const data = await getCaseFlowLog({ id: props.caseId });
flowLog.value = data;
if (flowLog.value.length == 4 && flowLog.value[1].status == 1) {
let obj = {
name: '伪变化',
status: 1,
time: '',
state: 'finish',
user_name: '',
};
flowLog.value.splice(2, 0, obj);
}
current.value = 0;
flowLog.value.forEach((item, index) => {
current.value = current.value + item.status;
if (flowLog.value[index].status == 1) {
flowLog.value[index].state = 'finish';
} else {
flowLog.value[index].state = 'wait';
}
});
if (current.value != 0) {
current.value--;
}
}
//
async function loadDetailCaseInfo() {
const data = await getCaseInfo({ id: props.caseId });
console.log(data);
detailData.value = data;
}
//
async function getCaseHandleInfo() {
const data = await getDroneCaseDeal({ caseid: props.caseId });
console.log(data);
caseHandleInfo.value = data;
if (caseHandleInfo.value.is_illegal == 0) {
caseHandleInfo.value.is_illegal = '合法';
} else if (caseHandleInfo.value.is_illegal == 1) {
caseHandleInfo.value.is_illegal = '违法';
} else if (caseHandleInfo.value.is_illegal == 2) {
caseHandleInfo.value.is_illegal = '伪变化';
}
//
playerOptions.value = [];
if (data.video_list.length > 0) {
data.video_list.forEach((item, index) => {
let options = {
playbackRates: [0.5, 1.0, 1.5, 2.0], //
autoplay: false, //true,
muted: false, //
loop: false, //
preload: 'auto', // <video>auto,
language: 'zh-CN',
aspectRatio: '16:9', // 使 - "16:9""4:3"
fluid: true, // trueVideo.js player
sources: [
{
type: '',
src: BASE_IMAGE_URL + '/' + item, //url
},
],
poster: '', //
// width: document.documentElement.clientWidth,
notSupportedMessage: '此视频暂无法播放,请稍后再试', //Video.js
controlBar: {
timeDivider: true, //
durationDisplay: true, //
remainingTimeDisplay: false, //
fullscreenToggle: true, //
},
};
playerOptions.value.push(options);
});
}
//
if (data.pic_info_list.length > 0) {
data.pic_info_list.forEach((item) => {
threadImageList.value.push(item.filePath);
});
for (let i = 0; i < threadImageList.value.length; i++) {
let obj = {
filePath: BASE_IMAGE_URL + '/' + threadImageList.value[i],
s_filePath: BASE_IMAGE_URL + '/S_' + threadImageList.value[i],
};
threadImageList.value[i] = obj;
}
}
//
if (data.after_pic_list.length > 0) {
threadAfterImageList.value = [];
data.after_pic_list.forEach((item: fileList) => {
threadAfterImageList.value.push(BASE_IMAGE_URL + '/S_' + item.filePath);
});
}
//
videoOptions.value = [];
if (data.remove_video_list.length > 0) {
videoOptions.value = [];
data.remove_video_list.forEach((item, index) => {
let options = {
playbackRates: [0.5, 1.0, 1.5, 2.0], //
autoplay: false, //true,
muted: false, //
loop: false, //
preload: 'auto', // <video>auto,
language: 'zh-CN',
aspectRatio: '16:9', // 使 - "16:9""4:3"
fluid: true, // trueVideo.js player
sources: [
{
type: '',
src: BASE_IMAGE_URL + '/' + item, //url
},
],
poster: '', //
// width: document.documentElement.clientWidth,
notSupportedMessage: '此视频暂无法播放,请稍后再试', //Video.js
controlBar: {
timeDivider: true, //
durationDisplay: true, //
remainingTimeDisplay: false, //
fullscreenToggle: true, //
},
};
videoOptions.value.push(options);
});
}
// - evidence_file_list
if (data.evidence_file_list.length > 0) {
evidenceFileList.value = [];
data.evidence_file_list.forEach((item: fileList) => {
let obj = {
filePath: BASE_IMAGE_URL + '/' + item.filePath,
s_filePath: BASE_IMAGE_URL + '/' + item.filePath,
};
evidenceFileList.value.push(obj);
});
}
if (data.boundary_pic_list.length > 0) {
boundaryImageList.value = [];
data.boundary_pic_list.forEach((item) => {
let obj = {
filePath: BASE_IMAGE_URL + '/' + item,
s_filePath: BASE_IMAGE_URL + '/' + item,
};
boundaryImageList.value.push(obj);
});
}
// - punish_pic_list
if (data.punish_pic_list.length > 0) {
punishImageList.value = [];
data.punish_pic_list.forEach((item) => {
let obj = {
filePath: BASE_IMAGE_URL + '/' + item,
s_filePath: BASE_IMAGE_URL + '/S_' + item,
};
punishImageList.value.push(obj);
});
}
// - payment_pic_list
if (data.payment_pic_list.length > 0) {
paymentImageList.value = [];
data.payment_pic_list.forEach((item) => {
let obj = {
filePath: BASE_IMAGE_URL + '/' + item,
s_filePath: BASE_IMAGE_URL + '/S_' + item,
};
paymentImageList.value.push(obj);
});
}
// - agree_checkout_pic_list
if (data.agree_checkout_pic_list.length > 0) {
agreeImageList.value = [];
data.agree_checkout_pic_list.forEach((item) => {
let obj = {
filePath: BASE_IMAGE_URL + '/' + item,
s_filePath: BASE_IMAGE_URL + '/S_' + item,
};
agreeImageList.value.push(obj);
});
}
// - checkout_pic_list
if (data.checkout_pic_list.length > 0) {
checkoutImageList.value = [];
data.checkout_pic_list.forEach((item) => {
let obj = {
filePath: BASE_IMAGE_URL + '/' + item,
s_filePath: BASE_IMAGE_URL + '/S_' + item,
};
checkoutImageList.value.push(obj);
});
}
}
onMounted(() => {
getCaseFlowLogData();
loadDetailCaseInfo();
getCaseHandleInfo();
});
</script>
<style lang="less" scoped>
.case-view {
padding: 20px 32px;
background-color: @component-background;
&__step {
padding: 24px 40px;
background-color: @app-content-background;
}
&_content {
display: flex;
height: 65vh;
.file-box {
overflow: auto;
}
}
}
.map-box {
height: 100%;
}
</style>

View File

@ -0,0 +1,51 @@
export interface caseDetailObj {
case_no?: string;
identification_user?: string;
identification_time?: string;
handle_status_id?: number;
handle_status_name?: string;
countyname?: string;
streetname?: string;
communityname?: string;
address?: string;
lng?: number;
lat?: number;
area?: number;
typename?: string;
remark?: string;
case_description?: string;
}
export interface infoObj{
createusername?: string;
createtime?:string;
verifystatusname?:string;
measure_name?:string;
result_name?: string;
contacts_people?: string;
contacts_phone?: string;
actual_scene_case?: string;
actual_use_to?: string;
pseudo_change_reason?: string;
actual_area?: string;
is_have_build?: number;
is_forever_build?: number;
illegal_contact?: string;
is_build_complete?: number;
is_have_checkout_condition?: number;
illegal_contact_phone?: string;
build_structure?: string;
illegal_type?: string;
remark?: string;
transactor_name?: string;
transact_time?: string;
evidence_file_name?: string;
evidence_file_number?: string;
evidence_file_indate?: string;
illegal_contact_idcard?: string;
registr_number?: string;
procedure_indate?:string;
}
export interface caseHandleInfoObj {
info:infoObj
is_illegal?: string;
}

View File

@ -0,0 +1,39 @@
<template>
<a-descriptions bordered :column="2" size="small" :labelStyle="labelStyle">
<a-descriptions-item label="审核人">
{{ auditData.user_name }}
</a-descriptions-item>
<a-descriptions-item label="审核时间">
{{ auditData.time }}
</a-descriptions-item>
</a-descriptions>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue';
const labelStyle = ref({
width: '100px',
});
const auditData: any = ref({});
const props = defineProps({
data: {
type: Object,
default: () => {
return {};
},
},
});
console.log(props.data);
auditData.value = props.data;
watch(
() => props.data,
(newVal, oldVal) => {
auditData.value = newVal;
},
);
</script>
<style lang="less" scoped>
::v-deep .ant-image .ant-image-img {
width: 85px;
margin-bottom: 10px;
}
</style>

View File

@ -0,0 +1,85 @@
<template>
<a-descriptions bordered :column="2" size="small" :labelStyle="labelStyle">
<a-descriptions-item label="办理人">{{
caseHandleInfo.info.transactor_name
}}</a-descriptions-item>
<a-descriptions-item label="办理时间">
{{ caseHandleInfo.info.transact_time }}
</a-descriptions-item>
<a-descriptions-item label="拟拆除后照片">
<div>
<ImagePreview :imageList="imgList" />
</div>
</a-descriptions-item>
<a-descriptions-item label="视频">
<div v-if="videoOptions.length > 0">
<video-player
class="video-player vjs-custom-skin"
v-for="(item, index) in videoOptions"
:key="index"
ref="videoPlayer"
:playsinline="true"
:options="item"
style="width: 200px"
></video-player>
</div>
</a-descriptions-item>
</a-descriptions>
</template>
<script lang="ts" setup>
import { reactive, watch, ref } from 'vue';
import { ImagePreview } from '@/components/Preview';
import { caseHandleInfoObj } from '../model';
const labelStyle = ref({
width: '100px',
});
const caseHandleInfo = ref<caseHandleInfoObj>({
info: {},
});
const videoOptions: any = ref([]);
const threadAfterImageList: any = ref([]);
const props = defineProps({
data: {
type: Object,
default: () => {
return {};
},
},
videoOptions: {
type: Object,
default: () => {
return {};
},
},
threadAfterImageList: {
type: Object,
default: () => {
return {};
},
},
});
caseHandleInfo.value = props.data;
videoOptions.value = props.videoOptions;
threadAfterImageList.value = props.threadImageList;
const imgList = ref([
'https://picsum.photos/id/66/346/216',
'https://picsum.photos/id/67/346/216',
'https://picsum.photos/id/68/346/216',
]);
watch(
() => props.data,
(newVal, oldVal) => {
caseHandleInfo.value = newVal;
videoOptions.value = props.videoOptions;
threadImageList.value = props.threadImageList;
},
);
</script>
<style lang="less" scoped>
::v-deep .ant-image .ant-image-img {
width: 85px;
margin-bottom: 10px;
}
</style>

View File

@ -0,0 +1,97 @@
<template>
<a-descriptions bordered :column="2" size="small" :labelStyle="labelStyle">
<a-descriptions-item label="办理人">{{
caseHandleInfo.info.transactor_name
}}</a-descriptions-item>
<a-descriptions-item label="办理时间">
{{ caseHandleInfo.info.transact_time }}
</a-descriptions-item>
<a-descriptions-item label="批准文件名称">
{{ caseHandleInfo.info.evidence_file_name }}
</a-descriptions-item>
<a-descriptions-item label="批准文件编号">
{{ caseHandleInfo.info.evidence_file_number }}
</a-descriptions-item>
<a-descriptions-item label="批文有效日期">
{{ caseHandleInfo.info.evidence_file_indate }}
</a-descriptions-item>
<a-descriptions-item label="合法举证材料">
<div>
<ImagePreview :imageList="evidenceFileList" />
</div>
</a-descriptions-item>
<a-descriptions-item label="勘测定界图">
<div>
<ImagePreview :imageList="boundaryImageList" />
</div>
</a-descriptions-item>
</a-descriptions>
</template>
<script lang="ts" setup>
import { watch, ref } from 'vue';
import { ImagePreview } from '@/components/Preview';
import { caseHandleInfoObj } from '../model';
const labelStyle = ref({
width: '100px',
});
const caseHandleInfo = ref<caseHandleInfoObj>({
info: {},
});
const playerOptions: any = ref([]);
const boundaryImageList: any = ref([]);
const evidenceFileList: any = ref([]);
const props = defineProps({
data: {
type: Object,
default: () => {
return {};
},
},
playerOptions: {
type: Object,
default: () => {
return {};
},
},
boundaryImageList: {
type: Object,
default: () => {
return {};
},
},
evidenceFileList: {
type: Object,
default: () => {
return {};
},
},
});
caseHandleInfo.value = props.data;
playerOptions.value = props.playerOptions;
boundaryImageList.value = props.boundaryImageList;
evidenceFileList.value = props.boundaryImageList;
const imgList = ref([
'https://picsum.photos/id/66/346/216',
'https://picsum.photos/id/67/346/216',
'https://picsum.photos/id/68/346/216',
]);
watch(
() => props.data,
(newVal, oldVal) => {
caseHandleInfo.value = newVal;
playerOptions.value = props.playerOptions;
boundaryImageList.value = props.boundaryImageList;
evidenceFileList.value = props.boundaryImageList;
},
);
</script>
<style lang="less" scoped>
::v-deep .ant-image .ant-image-img {
width: 85px;
margin-bottom: 10px;
}
</style>

View File

@ -0,0 +1,247 @@
<template>
<a-descriptions bordered :column="2" size="small" :labelStyle="labelStyle">
<a-descriptions-item label="核查人">{{
caseHandleInfo.info.createusername
}}</a-descriptions-item>
<a-descriptions-item label="核查时间">
{{ caseHandleInfo.info.createtime }}
</a-descriptions-item>
<a-descriptions-item label="处理进度">
{{ caseHandleInfo.info.verifystatusname }}
</a-descriptions-item>
<a-descriptions-item label="是否违法">
{{ caseHandleInfo.is_illegal }}
</a-descriptions-item>
<a-descriptions-item label="处理措施" v-if="caseHandleInfo.is_illegal == '是'">
{{ caseHandleInfo.info.measure_name }}
</a-descriptions-item>
<!-- 合法 -->
<a-descriptions-item label="项目名称" v-if="caseHandleInfo.is_illegal == '合法'">
{{ caseHandleInfo.info.result_name }}
</a-descriptions-item>
<a-descriptions-item label="当事人" v-if="caseHandleInfo.is_illegal == '合法'">
{{ caseHandleInfo.info.contacts_people }}
</a-descriptions-item>
<a-descriptions-item label="联系电话" v-if="caseHandleInfo.is_illegal == '合法'">
{{ caseHandleInfo.info.contacts_phone }}
</a-descriptions-item>
<a-descriptions-item label="建设情况" v-if="caseHandleInfo.is_illegal == '合法'">
{{ caseHandleInfo.info.actual_scene_case }}
</a-descriptions-item>
<a-descriptions-item label="实际用途" v-if="caseHandleInfo.is_illegal == '合法'">
{{ caseHandleInfo.info.actual_use_to }}
</a-descriptions-item>
<!-- 伪变化 -->
<a-descriptions-item label="伪变化原因" v-if="caseHandleInfo.is_illegal == '伪变化'">
{{ caseHandleInfo.info.pseudo_change_reason }}
</a-descriptions-item>
<a-descriptions-item label="实际用途" v-if="caseHandleInfo.is_illegal == '伪变化'">
{{ caseHandleInfo.info.actual_use_to }}
</a-descriptions-item>
<a-descriptions-item label="实际面积" v-if="caseHandleInfo.is_illegal == '伪变化'">
{{ caseHandleInfo.info.actual_area }}
</a-descriptions-item>
<a-descriptions-item label="是否有建筑物" v-if="caseHandleInfo.is_illegal == '伪变化'">
{{ caseHandleInfo.info.is_have_build == 1 ? '是' : '否' }}
</a-descriptions-item>
<a-descriptions-item label="是否永久性建筑" v-if="caseHandleInfo.is_illegal == '伪变化'">
{{ caseHandleInfo.info.is_forever_build == 1 ? '是' : '否' }}
</a-descriptions-item>
<!-- 案件违法 - 拆除 -->
<a-descriptions-item
label="处理办法"
v-if="caseHandleInfo.is_illegal == '违法' && caseHandleInfo.info.measure_name == '拟拆除'"
>
{{ caseHandleInfo.info.measure_name }}
</a-descriptions-item>
<a-descriptions-item
label="实际用途"
v-if="caseHandleInfo.is_illegal == '违法' && caseHandleInfo.info.measure_name == '拟拆除'"
>
{{ caseHandleInfo.info.actual_use_to }}
</a-descriptions-item>
<a-descriptions-item
label="当事人"
v-if="caseHandleInfo.is_illegal == '违法' && caseHandleInfo.info.measure_name == '拟拆除'"
>
{{ caseHandleInfo.info.illegal_contact }}
</a-descriptions-item>
<a-descriptions-item
label="联系电话"
v-if="caseHandleInfo.is_illegal == '违法' && caseHandleInfo.info.measure_name == '拟拆除'"
>
{{ caseHandleInfo.info.illegal_contact_phone }}
</a-descriptions-item>
<a-descriptions-item
label="建设情况"
v-if="caseHandleInfo.is_illegal == '违法' && caseHandleInfo.info.measure_name == '拟拆除'"
>
{{ caseHandleInfo.info.is_build_complete == 1 ? '已建成' : '建设中' }}
</a-descriptions-item>
<a-descriptions-item
label="建筑结构"
v-if="caseHandleInfo.is_illegal == '违法' && caseHandleInfo.info.measure_name == '拟拆除'"
>
{{ caseHandleInfo.info.build_structure }}
</a-descriptions-item>
<!-- 案件违法 查处 -->
<a-descriptions-item
label="处理办法"
v-if="caseHandleInfo.is_illegal == '违法' && caseHandleInfo.info.measure_name == '查处'"
>
{{ caseHandleInfo.info.measure_name }}
</a-descriptions-item>
<a-descriptions-item
label="实际用途"
v-if="caseHandleInfo.is_illegal == '违法' && caseHandleInfo.info.measure_name == '查处'"
>
{{ caseHandleInfo.info.actual_use_to }}
</a-descriptions-item>
<a-descriptions-item
label="当事人"
v-if="caseHandleInfo.is_illegal == '违法' && caseHandleInfo.info.measure_name == '查处'"
>
{{ caseHandleInfo.info.illegal_contact }}
</a-descriptions-item>
<a-descriptions-item
label="联系电话"
v-if="caseHandleInfo.is_illegal == '违法' && caseHandleInfo.info.measure_name == '查处'"
>
{{ caseHandleInfo.info.illegal_contact_phone }}
</a-descriptions-item>
<a-descriptions-item
label="建筑结构"
v-if="caseHandleInfo.is_illegal == '违法' && caseHandleInfo.info.measure_name == '查处'"
>
{{ caseHandleInfo.info.build_structure }}
</a-descriptions-item>
<a-descriptions-item
label="违法类型"
v-if="caseHandleInfo.is_illegal == '违法' && caseHandleInfo.info.measure_name == '查处'"
>
{{ caseHandleInfo.info.illegal_type }}
</a-descriptions-item>
<!-- 案件违法 完善手续 -->
<a-descriptions-item
label="处理办法"
v-if="caseHandleInfo.is_illegal == '违法' && caseHandleInfo.info.measure_name == '拟完善手续'"
>
{{ caseHandleInfo.info.measure_name }}
</a-descriptions-item>
<a-descriptions-item
label="实际用途"
v-if="caseHandleInfo.is_illegal == '违法' && caseHandleInfo.info.measure_name == '拟完善手续'"
>
{{ caseHandleInfo.info.actual_use_to }}
</a-descriptions-item>
<a-descriptions-item
label="当事人"
v-if="caseHandleInfo.is_illegal == '违法' && caseHandleInfo.info.measure_name == '拟完善手续'"
>
{{ caseHandleInfo.info.illegal_contact }}
</a-descriptions-item>
<a-descriptions-item
label="联系电话"
v-if="caseHandleInfo.is_illegal == '违法' && caseHandleInfo.info.measure_name == '拟完善手续'"
>
{{ caseHandleInfo.info.illegal_contact_phone }}
</a-descriptions-item>
<a-descriptions-item
label="拟完善手续名称"
v-if="caseHandleInfo.is_illegal == '违法' && caseHandleInfo.info.measure_name == '拟完善手续'"
>
{{ caseHandleInfo.info.result_name }}
</a-descriptions-item>
<a-descriptions-item
label="是否具备完善手续条件"
v-if="caseHandleInfo.is_illegal == '违法' && caseHandleInfo.info.measure_name == '拟完善手续'"
>
{{ caseHandleInfo.info.is_have_checkout_condition == 1 ? '是' : '否' }}
</a-descriptions-item>
<a-descriptions-item label="备注">
{{ caseHandleInfo.info.remark }}
</a-descriptions-item>
<a-descriptions-item label="现场照片">
<div>
<ImagePreview :imageList="imgList" />
</div>
</a-descriptions-item>
<a-descriptions-item label="现场视频">
<div v-if="playerOptions.length > 0">
<video-player
class="video-player vjs-custom-skin"
v-for="(item, index) in playerOptions"
:key="index"
ref="videoPlayer"
:playsinline="true"
:options="item"
style="width: 200px"
></video-player>
</div>
</a-descriptions-item>
</a-descriptions>
</template>
<script lang="ts" setup>
import { reactive, watch, ref } from 'vue';
import { ImagePreview } from '@/components/Preview';
import { caseHandleInfoObj } from '../model';
const labelStyle = ref({
width: '100px',
});
const caseHandleInfo = ref<caseHandleInfoObj>({
info: {},
});
const playerOptions: any = ref([]);
const threadImageList: any = ref([]);
const props = defineProps({
data: {
type: Object,
default: () => {
return {};
},
},
playerOptions: {
type: Object,
default: () => {
return {};
},
},
threadImageList: {
type: Object,
default: () => {
return {};
},
},
});
console.log(props)
caseHandleInfo.value = props.data;
playerOptions.value = props.playerOptions;
threadImageList.value = props.threadImageList;
const imgList = ref([
'https://picsum.photos/id/66/346/216',
'https://picsum.photos/id/67/346/216',
'https://picsum.photos/id/68/346/216',
]);
watch(
() => props.data,
(newVal, oldVal) => {
caseHandleInfo.value = newVal;
playerOptions.value = props.playerOptions;
threadImageList.value = props.threadImageList;
},
);
</script>
<style lang="less" scoped>
::v-deep .ant-image .ant-image-img {
width: 85px;
margin-bottom: 10px;
}
</style>

View File

@ -0,0 +1,100 @@
<template>
<a-descriptions bordered :column="2" size="small" :labelStyle="labelStyle">
<a-descriptions-item label="办理人">{{
caseHandleInfo.info.transactor_name
}}</a-descriptions-item>
<a-descriptions-item label="办理时间">
{{ caseHandleInfo.info.transact_time }}
</a-descriptions-item>
<a-descriptions-item label="立案号">
{{ caseHandleInfo.info.registr_number }}
</a-descriptions-item>
<a-descriptions-item label="当事人姓名">
{{ caseHandleInfo.info.illegal_contact }}
</a-descriptions-item>
<a-descriptions-item label="身份证号码">
{{ caseHandleInfo.info.illegal_contact_idcard }}
</a-descriptions-item>
<a-descriptions-item label="违法类型">
{{ caseHandleInfo.info.illegal_type }}
</a-descriptions-item>
<a-descriptions-item label="处罚通知书">
<div>
<ImagePreview :imageList="punishImageList" />
</div>
</a-descriptions-item>
<a-descriptions-item label="交款通知单">
<div>
<ImagePreview :imageList="paymentImageList" />
</div>
</a-descriptions-item>
</a-descriptions>
</template>
<script lang="ts" setup>
import { watch, ref } from 'vue';
import { ImagePreview } from '@/components/Preview';
import { caseHandleInfoObj } from '../model';
const labelStyle = ref({
width: '100px',
});
const caseHandleInfo = ref<caseHandleInfoObj>({
info: {},
});
const playerOptions: any = ref([]);
const paymentImageList: any = ref([]);
const punishImageList: any = ref([]);
const props = defineProps({
data: {
type: Object,
default: () => {
return {};
},
},
playerOptions: {
type: Object,
default: () => {
return {};
},
},
paymentImageList: {
type: Object,
default: () => {
return {};
},
},
punishImageList: {
type: Object,
default: () => {
return {};
},
},
});
caseHandleInfo.value = props.data;
playerOptions.value = props.playerOptions;
paymentImageList.value = props.paymentImageList;
punishImageList.value = props.paymentImageList;
const imgList = ref([
'https://picsum.photos/id/66/346/216',
'https://picsum.photos/id/67/346/216',
'https://picsum.photos/id/68/346/216',
]);
watch(
() => props.data,
(newVal, oldVal) => {
caseHandleInfo.value = newVal;
playerOptions.value = props.playerOptions;
paymentImageList.value = props.paymentImageList;
punishImageList.value = props.paymentImageList;
},
);
</script>
<style lang="less" scoped>
::v-deep .ant-image .ant-image-img {
width: 85px;
margin-bottom: 10px;
}
</style>

View File

@ -0,0 +1,77 @@
<template>
<a-descriptions bordered :column="2" size="small" :labelStyle="labelStyle">
<a-descriptions-item label="案件编号">{{ caseDetail.case_no }}</a-descriptions-item>
<a-descriptions-item label="上报人">
{{ caseDetail.identification_user }}
</a-descriptions-item>
<a-descriptions-item label="上报时间">
{{ caseDetail.identification_time }}
</a-descriptions-item>
<a-descriptions-item label="案件状态">
<a-tag color="warning" v-if="caseDetail.handle_status_id == 0">
{{ caseDetail.handle_status_name }}
</a-tag>
<a-tag color="processing" v-else-if="caseDetail.handle_status_id == 1">
{{ caseDetail.handle_status_name }}
</a-tag>
<a-tag color="success" v-else>{{ caseDetail.handle_status_name }}</a-tag>
</a-descriptions-item>
<a-descriptions-item label="行政区划">
/&nbsp;{{ caseDetail.countyname }}&nbsp;/&nbsp;{{ caseDetail.streetname }}&nbsp; / &nbsp;{{
caseDetail.communityname
}}
</a-descriptions-item>
<a-descriptions-item label="案件地址">{{ caseDetail.address }}</a-descriptions-item>
<a-descriptions-item label="经纬度"
>{{ caseDetail.lng }} , {{ caseDetail.lat }}</a-descriptions-item
>
<a-descriptions-item label="案件地址">{{ caseDetail.area }}&nbsp;()</a-descriptions-item>
<a-descriptions-item label="案件类型">{{ caseDetail.typename }}</a-descriptions-item>
<a-descriptions-item label="案件备注">{{ caseDetail.remark }}</a-descriptions-item>
<a-descriptions-item label="案件描述">{{ caseDetail.case_description }}</a-descriptions-item>
<a-descriptions-item label="案件图片">
<div>
<ImagePreview :imageList="imgList" />
</div>
</a-descriptions-item>
</a-descriptions>
</template>
<script lang="ts" setup>
import { reactive, watch, ref } from 'vue';
import { ImagePreview } from '@/components/Preview';
import { DetailModel, caseDetailObj } from '../model';
const labelStyle = ref({
width: '100px',
});
const caseDetail = ref<caseDetailObj>({});
const props = defineProps({
data: {
type: Object,
default: () => {
return {};
},
},
});
if(Object.keys(props.data).length != 0){
caseDetail.value = props.data.info;
}
const imgList = ref([
'https://picsum.photos/id/66/346/216',
'https://picsum.photos/id/67/346/216',
'https://picsum.photos/id/68/346/216',
]);
watch(
() => props.data,
(newVal, oldVal) => {
caseDetail.value = newVal.info;
},
);
</script>
<style lang="less" scoped>
::v-deep .ant-image .ant-image-img {
width: 85px;
margin-bottom: 10px;
}
</style>

View File

@ -0,0 +1,205 @@
<template>
<div class="w-full">
<MapboxMaps :mapOptions="mapOptions" @map-on-load="mapOnLoad" />
</div>
</template>
<script lang="ts" setup>
import rodeImg from '@/assets/images/icon_fly2.png';
import { ref, watch } from 'vue';
import MapboxMaps from '@/components/MapboxMaps/index.vue';
import { getDroneGeoJson } from '@/api/monitor/index';
const detailMap = ref();
const props = defineProps({
ruleForm: {
type: Object,
default: () => {
return {};
},
},
});
const geojson = ref();
const droneMarker = ref();
const mapBox = ref();
const mapOptions = {
center: [117.84714891969796, 35.22152309532066],
zoom: 10,
};
watch(
() => props.ruleForm,
(newVal, oldVal) => {
console.log(newVal);
loadCaseGeoJson();
detailMap.value.flyTo({
center: [newVal.lng, newVal.lat], //
zoom: 18, //
pitch: 0, //
});
loadDroneMarker(newVal.lng, newVal.lat);
},
);
const mapOnLoad = (map) => {
mapBox.value = map;
//
const testSource =
'http://123.132.248.154:9205/geoserver/gwc/service/tms/1.0.0/TEST_WORK_SPACE%3Alindi@EPSG:900913@pbf/{z}/{x}/{y}.pbf';
map.U.addVector('name', testSource);
map.U.addLineLayer('ffff', {
source: 'name',
'source-layer': 'lindi',
});
detailMap.value = map;
loadImageLayer();
loadStreetBorderLayer();
loadCaseGeoJson();
};
//
function loadImageLayer() {
detailMap.value.addLayer({
id: 'wms-test-layer',
type: 'raster',
source: {
type: 'raster',
tiles: [
'http://175.27.168.120:8080/geoserver/feixian/wms?service=WMS&version=1.1.0&request=GetMap&layers=feixian:yingxiang&styles=&bbox={bbox-epsg-3857}&width=256&height=256&srs=EPSG:3857&format=image/png&TRANSPARENT=TRUE',
],
tileSize: 256,
},
paint: {},
});
}
//
function loadStreetBorderLayer() {
detailMap.value.addLayer({
id: 'street-border',
type: 'raster',
source: {
type: 'raster',
tiles: [
'http://175.27.168.120:8080/geoserver/feixian/wms?service=WMS&version=1.1.0&request=GetMap&layers=feixian:zhenjie&styles=&bbox={bbox-epsg-3857}&width=256&height=256&srs=EPSG:3857&format=image/png&TRANSPARENT=TRUE',
],
tileSize: 256,
},
paint: {},
layout: {
visibility: 'visible',
},
});
detailMap.value.resize();
}
// GeoJSON
async function loadCaseGeoJson() {
const data = await getDroneGeoJson({ id: props.ruleForm.info.id });
console.log(data);
geojson.value = data;
if (geojson.value.features.length == 0) {
detailMap.value.addLayer({
id: 'points',
type: 'symbol',
source: {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [props.ruleForm.info.lng, props.ruleForm.info.lng],
},
properties: {
title: 'Mapbox DC',
icon: 'monument',
},
},
],
},
},
layout: {},
});
}
// There is already a source with ID "geojsonfill"
if (detailMap.value.getLayer('geojsonfill')) {
detailMap.value.removeLayer('geojsonfill');
detailMap.value.removeSource('geojsonfill');
}
if (detailMap.value.getLayer('geojsonline')) {
detailMap.value.removeLayer('geojsonline');
detailMap.value.removeSource('geojsonline');
}
detailMap.value.addLayer({
id: 'geojsonfill',
type: 'fill',
source: {
type: 'geojson',
data: geojson.value,
},
paint: {
'fill-color': '#FE9003',
'fill-opacity': 0.2,
'fill-outline-color': '#FE9003',
},
});
detailMap.value.addLayer({
id: 'geojsonline',
type: 'line',
source: {
type: 'geojson',
data: geojson.value,
},
layout: {
'line-join': 'round',
'line-cap': 'round',
},
paint: {
'line-color': '#FE9003',
'line-width': 4,
},
});
}
//
function loadDroneMarker(lng, lat) {
if (detailMap.value.getLayer('cat-on-building')) {
detailMap.value.removeLayer('cat-on-building');
detailMap.value.removeSource('cat-on-building');
detailMap.value.removeImage('cat');
}
detailMap.value.loadImage(rodeImg, (error, image) => {
detailMap.value.addImage('cat', image);
detailMap.value.addLayer({
id: 'cat-on-building',
source: {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [lng, lat],
},
},
],
},
},
slot: 'top',
type: 'symbol',
layout: {
'icon-image': 'cat',
'icon-size': 0.05,
'symbol-placement': 'point',
'symbol-z-elevate': true,
},
});
});
}
</script>
<style scoped lang="less">
.w-full {
width: 100%;
height: 50vh;
}
</style>

View File

@ -0,0 +1,111 @@
<template>
<a-descriptions bordered :column="2" size="small" :labelStyle="labelStyle">
<a-descriptions-item label="办理人">{{
caseHandleInfo.info.transactor_name
}}</a-descriptions-item>
<a-descriptions-item label="办理时间">
{{ caseHandleInfo.info.transact_time }}
</a-descriptions-item>
<a-descriptions-item label="政府统一完善手续证明">
<div>
<ImagePreview :imageList="agreeImageList" />
</div>
</a-descriptions-item>
<a-descriptions-item label="办理手续照片">
<div>
<ImagePreview :imageList="checkoutImageList" />
</div>
</a-descriptions-item>
<a-descriptions-item label="手续有效期">
{{ caseHandleInfo.info.procedure_indate }}
</a-descriptions-item>
<a-descriptions-item label="批准文件编号">
{{ caseHandleInfo.info.evidence_file_number }}
</a-descriptions-item>
<a-descriptions-item label="批文有效日期">
{{ caseHandleInfo.info.evidence_file_indate }}
</a-descriptions-item>
<a-descriptions-item label="勘测定界图">
<div>
<ImagePreview :imageList="boundaryImageList" />
</div>
</a-descriptions-item>
</a-descriptions>
</template>
<script lang="ts" setup>
import { watch, ref } from 'vue';
import { ImagePreview } from '@/components/Preview';
import { caseHandleInfoObj } from '../model';
const labelStyle = ref({
width: '100px',
});
const caseHandleInfo = ref<caseHandleInfoObj>({
info: {},
});
const playerOptions: any = ref([]);
const checkoutImageList: any = ref([]);
const boundaryImageList: any = ref([]);
const agreeImageList: any = ref([]);
const props = defineProps({
data: {
type: Object,
default: () => {
return {};
},
},
playerOptions: {
type: Object,
default: () => {
return {};
},
},
checkoutImageList: {
type: Object,
default: () => {
return {};
},
},
boundaryImageList: {
type: Object,
default: () => {
return {};
},
},
agreeImageList: {
type: Object,
default: () => {
return {};
},
},
});
caseHandleInfo.value = props.data;
playerOptions.value = props.playerOptions;
boundaryImageList.value = props.checkoutImageList;
checkoutImageList.value = props.checkoutImageList;
agreeImageList.value = props.checkoutImageList;
const imgList = ref([
'https://picsum.photos/id/66/346/216',
'https://picsum.photos/id/67/346/216',
'https://picsum.photos/id/68/346/216',
]);
watch(
() => props.data,
(newVal, oldVal) => {
caseHandleInfo.value = newVal;
playerOptions.value = props.playerOptions;
boundaryImageList.value = props.checkoutImageList;
checkoutImageList.value = props.checkoutImageList;
agreeImageList.value = props.checkoutImageList;
},
);
</script>
<style lang="less" scoped>
::v-deep .ant-image .ant-image-img {
width: 85px;
margin-bottom: 10px;
}
</style>

View File

@ -0,0 +1,22 @@
// 案件详情首页
export { default as CaseView } from './caseview/index.vue';
// 【案件下发信息】
export { default as Issue } from './caseview/src/issue.vue';
// 【案件核查信息】
export { default as Inspect } from './caseview/src/inspect.vue';
// 【案件审核信息】
export { default as Audit } from './caseview/src/audit.vue';
// 【案件办理信息-违法-拟拆除】
export { default as Dismantle } from './caseview/src/dismantle.vue';
// 地图位置
export { default as MapDetail } from './caseview/src/mapDetail.vue';
// 案件办理信息-合法举证
export { default as Evidence } from './caseview/src/evidence.vue';
// 【案件办理信息-违法-查处】
export { default as Investigate } from './caseview/src/investigate.vue';
// 【案件办理信息-违法-拟完善手续】
export { default as Procedure } from './caseview/src/procedure.vue';

View File

@ -0,0 +1,34 @@
<template>
<BasicTable @register="registerTable">
<template #form-custom> custom-slot </template>
<template #toolbar>
<a-button type="primary" @click="getFormValues"></a-button>
</template>
</BasicTable>
</template>
<script lang="ts" setup>
import { BasicTable, useTable } from '@/components/Table';
import { getBasicColumns, getFormConfig } from './list.data';
import { getAccountList } from '@/api/demo/system';
const [registerTable, { getForm }] = useTable({
title: '开启搜索区域',
api: getAccountList,
columns: getBasicColumns(),
useSearchForm: true,
formConfig: getFormConfig(),
showTableSetting: true,
tableSetting: { fullScreen: true },
showIndexColumn: false,
rowKey: 'id',
rowSelection: {
type: 'checkbox',
},
showSelectionBar: true, //
});
function getFormValues() {
console.log(getForm().getFieldsValue());
}
</script>

View File

@ -0,0 +1,63 @@
import { FormProps, BasicColumn } from '@/components/Table';
export function getBasicColumns(): BasicColumn[] {
return [
{
title: 'ID',
dataIndex: 'id',
fixed: 'left',
width: 200,
},
{
title: '姓名',
dataIndex: 'name',
width: 150,
filters: [
{ text: 'Male', value: 'male' },
{ text: 'Female', value: 'female' },
],
},
{
title: '地址',
dataIndex: 'address',
},
{
title: '编号',
dataIndex: 'no',
width: 150,
sorter: true,
defaultHidden: true,
},
{
title: '开始时间',
width: 150,
sorter: true,
dataIndex: 'beginTime',
},
{
title: '结束时间',
width: 150,
sorter: true,
dataIndex: 'endTime',
},
];
}
export function getFormConfig(): Partial<FormProps> {
return {
labelWidth: 100,
schemas: [
...getAdvanceSchema(5),
{
field: `field11`,
label: `Slot示例`,
// component: 'Select',
slot: 'custom',
colProps: {
xl: 12,
xxl: 8,
},
},
],
};
}

View File

View File

@ -0,0 +1,36 @@
import { BasicColumn } from '@/components/Table';
export const columns: BasicColumn[] = [
{
title: '案件编号',
dataIndex: 'case_no',
},
{
title: '上报时间',
dataIndex: 'createtime',
},
{
title: '地点',
dataIndex: 'address',
customRender: ({ record }) => {
const text = record.countyname + record.streetname + record.communityname;
return text;
},
},
{
title: '案件描述',
dataIndex: 'case_description',
},
{
title: '占用耕地面积',
dataIndex: 'area',
},
{
title: '处理时间',
dataIndex: 'deal_time',
},
{
title: '案件处理人',
dataIndex: 'deal_username',
},
];

View File

@ -0,0 +1,330 @@
<template>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<div :class="`${prefixCls}`">
<div :class="`${prefixCls}-header`">
<div></div>
<div class="flex">
<a-tree-select
v-if="selectOptions1.length > 0"
v-model:value="selectValues1"
show-search
style="width: 230px"
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
placeholder="查询地区"
allow-clear
:tree-data="selectOptions1"
:field-names="{
children: 'children',
value: 'id',
label: 'name',
}"
tree-node-filter-prop="name"
@change="areaChange"
/>
<a-select
ref="select"
v-model:value="is_illegal"
style="width: 150px"
class="ml-3"
allowClear
:options="selectOptions2"
placeholder="现场状况"
@change="reload1"
/>
<a-select
ref="select"
v-model:value="is_drawback"
:options="selectOptions3"
style="width: 150px"
class="ml-3"
allowClear
placeholder="新增退回"
@change="reload1"
/>
<a-input
style="width: 150px"
class="ml-3"
v-model:value="searchCaseNo"
placeholder="案件编号"
/>
<a-input
style="width: 150px"
class="ml-3"
v-model:value="searchKey"
placeholder="请输入"
/>
<a-button class="ml-3" :icon="h(SearchOutlined)" @click="reload1"></a-button>
<a-button type="success" class="ml-3" :icon="h(DownloadOutlined)">导出</a-button>
</div>
</div>
<div :class="`${prefixCls}-content`">
<div :class="`${prefixCls}-content-tabbox`">
<div :class="`${prefixCls}-content-tabbox-left`">
<BasicTable @register="registerTable" v-if="!caseDetailVisible">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction
:actions="[
{
label: '核验',
onClick: () => {
handleAuditing(record);
},
},
]"
/>
</template>
</template>
</BasicTable>
<div :class="`${prefixCls}-content-tabbox-left-collenction`" v-if="caseDetailVisible">
<div :class="`${prefixCls}-content-tabbox-left-collenction-header`">
<div>案件详情</div>
<div
:class="`${prefixCls}-content-tabbox-left-collenction-header-close`"
@click="closeCaseDetail"
><CloseOutlined
/></div>
</div>
<div :class="`${prefixCls}-content-tabbox-left-collenction-box`">
<CaseView :caseId="selectRowDetail.id" :mapShow="false"></CaseView>
</div>
<div :class="`${prefixCls}-content-tabbox-left-collenction-footer`">
<a-input
size="mini"
class="ml-3"
v-model:value="caseBackReason"
placeholder="退回原因"
/>
<a-button type="error" class="ml-3" @click="handleCaseBack"> 退 </a-button>
<a-button type="primary" class="ml-3" @click="handlePassForm"> </a-button>
</div>
</div>
</div>
</div>
<div :class="`${prefixCls}-content-mapbox`">
<MapDetail :ruleForm="selectRowDetail"></MapDetail>
</div>
</div>
</div>
</PageWrapper>
</template>
<script lang="ts" setup>
import { onMounted, ref, h } from 'vue';
import { SearchOutlined, DownloadOutlined, CloseOutlined } from '@ant-design/icons-vue';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import {
getTableListData,
passVerificatCase,
backVerificcatCase,
} from '@/api/summaryverification/index';
import { getDeptList } from '@/api/demo/system';
import { columns } from './index.data';
import { useMessage } from '@/hooks/web/useMessage';
import { CaseView } from '@/views/demo/monitor/index';
import MapDetail from './mapDetail.vue';
const { createMessage } = useMessage();
const caseBackReason: any = ref();
const caseDetailVisible: any = ref(false);
const selectRowDetail: any = ref({});
const selectValues1: any = ref();
const selectOptions1: any = ref([]);
const searchKey: any = ref();
const searchCaseNo: any = ref();
const countyid: any = ref();
const streetid: any = ref();
const communityid: any = ref();
const is_illegal: any = ref();
const selectOptions2: any = ref([
{ label: '合法', value: 0 },
{ label: '违法', value: 1 },
{ label: '伪变化', value: 2 },
]);
const is_drawback: any = ref();
const selectOptions3: any = ref([
{ label: '新增', value: 0 },
{ label: '退回', value: 1 },
]);
const [registerTable, { reload: reload1 }] = useTable({
title: '',
api: getTableListData,
columns,
rowKey: 'id',
formConfig: {
labelWidth: 120,
},
// rowSelection: {
// type: 'checkbox',
// },
useSearchForm: false,
showTableSetting: false,
bordered: true,
actionColumn: {
width: 100,
title: '操作',
dataIndex: 'action',
},
beforeFetch: (data) => {
let temp = {
page: data.page,
limit: data.limit,
is_illegal: is_illegal.value,
is_drawback: is_drawback.value,
countyid: countyid.value,
streetid: streetid.value,
communityid: communityid.value,
case_no: searchCaseNo.value,
key: searchKey.value,
};
return temp;
},
handleSearchInfoFn(info) {
return info;
},
});
function closeCaseDetail() {
caseDetailVisible.value = false;
}
function handleCaseBack() {
if (!caseBackReason.value) {
createMessage.error('退回原因不能为空');
return;
}
const param = {
id: selectRowDetail.value.id,
drawbackReason: caseBackReason.value,
};
backVerificcatCase(param).then((res) => {
if (res) {
createMessage.success('操作成功');
reload1();
caseDetailVisible.value = false;
} else {
createMessage.error('此案件未办理,无需退回。');
}
});
}
function handlePassForm() {
passVerificatCase([selectRowDetail.value.id]).then((res) => {
if (res) {
caseDetailVisible.value = false;
createMessage.success('操作成功');
} else {
createMessage.error('操作失败');
}
});
}
function areaChange(items) {
countyid.value = null;
streetid.value = null;
communityid.value = null;
if (items && JSON.stringify(items).length == 6) {
countyid.value = items;
}
if (items && JSON.stringify(items).length == 9) {
streetid.value = items;
}
if (items && JSON.stringify(items).length == 12) {
communityid.value = items;
}
reload1();
}
function handleAuditing(record) {
console.log('record', record);
const formData = record;
formData.homeAddress =
record.countyname + record.streetname + record.communityname + record.address;
formData.lngLat = record.lng + ' , ' + record.lat;
selectRowDetail.value = record;
caseDetailVisible.value = true;
}
function getOrgList() {
getDeptList().then((res) => {
res.forEach((item) => {
if (item.id == '371300') {
selectOptions1.value = item.children;
}
});
});
}
onMounted(() => {
getOrgList();
});
const prefixCls = 'form-box';
</script>
<style lang="less" scoped>
.form-box {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
&-header {
width: 100%;
padding: 0 10px;
height: 60px;
background: #f8f8f8;
display: flex;
justify-content: space-between;
align-items: center;
}
&-content {
width: 100%;
height: calc(100% - 60px);
display: flex;
&-tabbox {
width: 70%;
display: flex;
justify-content: space-between;
&-left {
flex: 1;
border: 1px solid #eee;
&-collenction {
display: flex;
flex-direction: column;
height: 100%;
&-box {
height: calc(100% - 110px);
overflow: auto;
}
&-footer {
height: 60px;
background: #fff;
display: flex;
align-items: center;
}
&-header {
padding: 0 10px;
height: 50px;
overflow: auto;
border-bottom: 1px solid #eee;
display: flex;
background: #fff;
align-items: center;
justify-content: space-between;
&-close {
cursor: pointer;
}
}
}
}
}
&-mapbox {
width: calc(30% - 20px);
margin: 0 15px 15px 15px;
border: 1px solid red;
}
}
}
</style>

View File

@ -0,0 +1,206 @@
<template>
<div class="w-full">
<MapboxMaps :mapOptions="mapOptions" @map-on-load="mapOnLoad" />
</div>
</template>
<script lang="ts" setup>
import rodeImg from '@/assets/images/icon_fly2.png';
import { ref, watch } from 'vue';
import MapboxMaps from '@/components/MapboxMaps/index.vue';
import { getDroneGeoJson } from '@/api/monitor/index';
const detailMap = ref();
const props = defineProps({
ruleForm: {
type: Object,
default: () => {
return {};
},
},
});
const geojson = ref();
const droneMarker = ref();
const mapBox = ref();
const mapOptions = {
center: [117.84714891969796, 35.22152309532066],
zoom: 10,
};
watch(
() => props.ruleForm,
(newVal, oldVal) => {
loadCaseGeoJson();
detailMap.value.flyTo({
center: [newVal.lng, newVal.lat], //
zoom: 18, //
pitch: 0, //
});
loadDroneMarker(newVal.lng, newVal.lat);
},
);
const mapOnLoad = (map) => {
mapBox.value = map;
//
const testSource =
'http://123.132.248.154:9205/geoserver/gwc/service/tms/1.0.0/TEST_WORK_SPACE%3Alindi@EPSG:900913@pbf/{z}/{x}/{y}.pbf';
map.U.addVector('name', testSource);
map.U.addLineLayer('ffff', {
source: 'name',
'source-layer': 'lindi',
});
detailMap.value = map;
loadImageLayer();
loadStreetBorderLayer();
if (props.ruleForm && props.ruleForm.id) {
loadCaseGeoJson();
}
};
//
function loadImageLayer() {
detailMap.value.addLayer({
id: 'wms-test-layer',
type: 'raster',
source: {
type: 'raster',
tiles: [
'http://175.27.168.120:8080/geoserver/feixian/wms?service=WMS&version=1.1.0&request=GetMap&layers=feixian:yingxiang&styles=&bbox={bbox-epsg-3857}&width=256&height=256&srs=EPSG:3857&format=image/png&TRANSPARENT=TRUE',
],
tileSize: 256,
},
paint: {},
});
}
//
function loadStreetBorderLayer() {
detailMap.value.addLayer({
id: 'street-border',
type: 'raster',
source: {
type: 'raster',
tiles: [
'http://175.27.168.120:8080/geoserver/feixian/wms?service=WMS&version=1.1.0&request=GetMap&layers=feixian:zhenjie&styles=&bbox={bbox-epsg-3857}&width=256&height=256&srs=EPSG:3857&format=image/png&TRANSPARENT=TRUE',
],
tileSize: 256,
},
paint: {},
layout: {
visibility: 'visible',
},
});
detailMap.value.resize();
}
// GeoJSON
async function loadCaseGeoJson() {
const data = await getDroneGeoJson({ id: props.ruleForm.id });
console.log(data);
geojson.value = data;
if (geojson.value.features.length == 0) {
detailMap.value.addLayer({
id: 'points',
type: 'symbol',
source: {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [props.ruleForm.lng, props.ruleForm.lng],
},
properties: {
title: 'Mapbox DC',
icon: 'monument',
},
},
],
},
},
layout: {},
});
}
// There is already a source with ID "geojsonfill"
if (detailMap.value.getLayer('geojsonfill')) {
detailMap.value.removeLayer('geojsonfill');
detailMap.value.removeSource('geojsonfill');
}
if (detailMap.value.getLayer('geojsonline')) {
detailMap.value.removeLayer('geojsonline');
detailMap.value.removeSource('geojsonline');
}
detailMap.value.addLayer({
id: 'geojsonfill',
type: 'fill',
source: {
type: 'geojson',
data: geojson.value,
},
paint: {
'fill-color': '#FE9003',
'fill-opacity': 0.2,
'fill-outline-color': '#FE9003',
},
});
detailMap.value.addLayer({
id: 'geojsonline',
type: 'line',
source: {
type: 'geojson',
data: geojson.value,
},
layout: {
'line-join': 'round',
'line-cap': 'round',
},
paint: {
'line-color': '#FE9003',
'line-width': 4,
},
});
}
//
function loadDroneMarker(lng, lat) {
if (detailMap.value.getLayer('cat-on-building')) {
detailMap.value.removeLayer('cat-on-building');
detailMap.value.removeSource('cat-on-building');
detailMap.value.removeImage('cat');
}
detailMap.value.loadImage(rodeImg, (error, image) => {
detailMap.value.addImage('cat', image);
detailMap.value.addLayer({
id: 'cat-on-building',
source: {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [lng, lat],
},
},
],
},
},
slot: 'top',
type: 'symbol',
layout: {
'icon-image': 'cat',
'icon-size': 0.05,
'symbol-placement': 'point',
'symbol-z-elevate': true,
},
});
});
}
</script>
<style scoped lang="less">
.w-full {
width: 100%;
height: 100%;
}
</style>

View File

@ -1,105 +1,113 @@
<template>
<l-layout :bottom="46">
<template #bottom >
<el-form style="padding-right:16px;" v-if="selectItem.f_IsNotPassword == 1" :model="formData" :rules="rules" size="mini" ref="form" label-width="64px" >
<el-col :span="24">
<el-form-item label="密码" prop="f_Password">
<el-input type="password" v-model="formData.f_Password"></el-input>
</el-form-item>
</el-col>
</el-form>
</template>
<div class="sign-type-list" >
<div @click="handleChange(item)" :class="['sign-type-list--item',{'checked':selectValue == item.f_StampId }]" v-for="(item,index) in signList" :key="index" >
<div class="sign-type-list--imgdiv" >
<img class="sign-type-list--img" :src="`${apiUrl}system/annexesfile/${item.f_ImgFile}?token=${token}`" >
<div class="sign-type-list--checked" v-if="selectValue == item.f_StampId" >
<i class="el-icon-check" ></i>
</div>
</div>
<p class="sign-type-list--label" >{{$t(item.f_StampName)}}</p>
</div>
<l-layout :bottom="46">
<template #bottom>
<el-form
style="padding-right: 16px"
v-if="selectItem.f_IsNotPassword == 1"
:model="formData"
:rules="rules"
size="mini"
ref="form"
label-width="64px"
>
<el-col :span="24">
<el-form-item label="密码" prop="f_Password">
<el-input type="password" v-model="formData.f_Password"></el-input>
</el-form-item>
</el-col>
</el-form>
</template>
<div class="sign-type-list">
<div
@click="handleChange(item)"
:class="['sign-type-list--item', { checked: selectValue == item.f_StampId }]"
v-for="(item, index) in signList"
:key="index"
>
<div class="sign-type-list--imgdiv">
<img
class="sign-type-list--img"
:src="`${apiUrl}system/annexesfile/${item.f_ImgFile}?token=${token}`"
/>
<div class="sign-type-list--checked" v-if="selectValue == item.f_StampId">
<i class="el-icon-check"></i>
</div>
</div>
</l-layout>
<p class="sign-type-list--label">{{ $t(item.f_StampName) }}</p>
</div>
</div>
</l-layout>
</template>
<script>
export default {
data(){
return {
signList:[],
selectValue:'',
selectItem:{},
export default {
data() {
return {
signList: [],
selectValue: '',
selectItem: {},
formData:{
f_Password:''
},
rules: {
f_Password: [
{ required: true, message: '请填写密码',trigger: 'blur' }
]
},
}
},
created () {
},
computed:{
},
methods:{
resetForm(){
this.selectValue = ''
this.selectItem = {}
this.signList = []
this.$refs.form && this.$refs.form.resetFields()
formData: {
f_Password: '',
},
async validateForm(){
if(this.selectValue){
if(this.selectItem.f_IsNotPassword == 1){
if(await this.$refs.form.validate()){
if(this.selectItem.f_Password == this.$md5(this.formData.f_Password)){
return true
}
else{
this.$message({
type: 'error',
message: this.$t('密码错误!')
})
}
}
}
else{
return true
}
}
else{
rules: {
f_Password: [{ required: true, message: '请填写密码', trigger: 'blur' }],
},
};
},
created() {},
computed: {},
methods: {
resetForm() {
this.selectValue = '';
this.selectItem = {};
this.signList = [];
this.$refs.form && this.$refs.form.resetFields();
},
async validateForm() {
if (this.selectValue) {
if (this.selectItem.f_IsNotPassword == 1) {
if (await this.$refs.form.validate()) {
if (this.selectItem.f_Password == this.$md5(this.formData.f_Password)) {
return true;
} else {
this.$message({
type: 'error',
message: this.$t('请选择签章!')
})
type: 'error',
message: this.$t('密码错误!'),
});
}
}
return false
},
handleChange(item){
this.selectItem = item
this.selectValue = item.f_StampId
},
setForm(data){
this.signList = this.$deepClone(data)
if(this.signList.length == 1){
this.selectItem = this.signList[0]
this.selectValue = this.signList[0].f_StampId
}
},
getForm(){
return this.selectItem
} else {
return true;
}
} else {
this.$message({
type: 'error',
message: this.$t('请选择签章!'),
});
}
}
}
return false;
},
handleChange(item) {
this.selectItem = item;
this.selectValue = item.f_StampId;
},
setForm(data) {
this.signList = this.$deepClone(data);
if (this.signList.length == 1) {
this.selectItem = this.signList[0];
this.selectValue = this.signList[0].f_StampId;
}
},
getForm() {
return this.selectItem;
},
},
};
</script>
<style lang="scss" scoped>
.sign-type-list{
.sign-type-list {
display: flex;
flex-wrap: wrap;
padding-top: 16px;
@ -109,52 +117,52 @@ export default {
position: relative;
box-sizing: border-box;
&--item{
width: 144px;
margin:0 0 16px 16px;
&--item {
width: 144px;
margin: 0 0 16px 16px;
}
&--imgdiv{
width: 144px;
height: 144px;
border-radius: 2px;
overflow: hidden;
cursor: pointer;
position: relative;
border: 1px solid #f1f2f5;
padding: 4px;
&--imgdiv {
width: 144px;
height: 144px;
border-radius: 2px;
overflow: hidden;
cursor: pointer;
position: relative;
border: 1px solid #f1f2f5;
padding: 4px;
}
&--item.checked &--imgdiv{
border: 1px solid #409eff;
&--item.checked &--imgdiv {
border: 1px solid #409eff;
}
&--img{
width: 100%;
&--img {
width: 100%;
}
&--label{
font-size: 12px;
color: #606266;
margin-top: 8px;
text-align: center;
&--label {
font-size: 12px;
color: #606266;
margin-top: 8px;
text-align: center;
}
&--checked{
border: 12px solid #409eff;
border-left: 12px solid transparent;
border-bottom: 12px solid transparent;
border-top-right-radius: 2px;
&--checked {
border: 12px solid #409eff;
border-left: 12px solid transparent;
border-bottom: 12px solid transparent;
border-top-right-radius: 2px;
position: absolute;
right: 3px;
top: 3px;
.el-icon-check {
position: absolute;
right: 3px;
top: 3px;
.el-icon-check{
position: absolute;
top: -10px;
left: -2px;
font-size: 12px;
color: #fff;
}
top: -10px;
left: -2px;
font-size: 12px;
color: #fff;
}
}
}
</style>
}
</style>

View File

@ -4,10 +4,10 @@
"compilerOptions": {
"baseUrl": ".",
"declaration": false,
"types": ["vite/client"],
"types": ["vite/client","node"],
"paths": {
"@/*": ["src/*"],
"#/*": ["types/*"],
"#/*": ["types/*"]
},
"module": "ES2022",
"moduleResolution": "node"

View File

@ -14,15 +14,16 @@ export default defineApplicationConfig({
'@iconify/iconify',
'ant-design-vue/es/locale/zh_CN',
'ant-design-vue/es/locale/en_US',
'@/../lib/vform/designer.umd.js'
'@/../lib/vform/designer.umd.js',
],
},
build: {
/* 其他build生产打包配置省略 */
//...
target: 'esnext',
commonjsOptions: {
include: /node_modules|lib/ //这里记得把lib目录加进来否则生产打包会报错
}
include: /node_modules|lib/, //这里记得把lib目录加进来否则生产打包会报错
},
},
server: {
proxy: {