Merge remote-tracking branch 'origin/main'

This commit is contained in:
wangyilin 2024-11-08 16:24:35 +08:00
commit 5da1ce3539
102 changed files with 4436 additions and 98 deletions

View File

@ -58,7 +58,8 @@
"@tarojs/taro": "3.6.26",
"dayjs": "^1.11.13",
"pinia": "^2.2.2",
"vue": "^3.0.0"
"vue": "^3.0.0",
"vuex": "^4.0.2"
},
"devDependencies": {
"@babel/core": "^7.8.0",

View File

@ -17,14 +17,24 @@ export default defineAppConfig({
'myProject/projectDetails/projectDetails',
'securityUserForm/securityUserForm',
]
}, {
},
{
root: "subPages/police",
pages: [
'dailyInspection/dailyInspection',
'myEnterprisesUnit/myEnterprisesUnit',
'myEnterprisesUnit/projectDetails/projectDetails'
]
}
},
{
root: "subPages/select",
pages: [
'dailyLife/dailyLife',
'signature/signature'
]
},
],
window: {
backgroundTextStyle: 'light',
navigationBarBackgroundColor: '#4e87ff',

View File

@ -4,15 +4,13 @@
<nut-swiper ref="swiperRef" pagination-visible pagination-color="#e53e31" :auto-play="3000" :init-page="0">
<nut-swiper-item v-for="(item, index) in list" :key="index" style="height: 180px">
<image :src="item" alt="" style="height: 100%; width: 100%" draggable="false" />
<view>1123</view>
</nut-swiper-item>
</nut-swiper>
</view>
<view class="nameTitle">
<view class="itemSchool">
<text>单位数量</text>
<text
style=" white-space: nowrap;overflow: hidden;text-overflow: ellipsis;width: 80px;text-align: center">{{numberStatistics.enterprisesUnitCount}}</text>
<text style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis; width: 80px; text-align: center">{{ numberStatistics.enterprisesUnitCount }}</text>
</view>
<view class="itemSchool">
<text>服务项目</text>
@ -36,8 +34,7 @@
<!--九宫格-->
<view class="Module">
<view class="subModule">
<view class="subModuleItem" v-for="item in subModuleList" :key="item.id"
@click="subNavigation(item.url)">
<view class="subModuleItem" v-for="item in subModuleList" :key="item.id" @click="subNavigation(item.url)">
<view class="subModuleIndex">
<image :src="item.icon"></image>
</view>
@ -46,12 +43,11 @@
</view>
</view>
<view style="background-color: #e9eef4; height: 15rpx"></view>
</view>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import Taro from "@tarojs/taro";
import Taro from '@tarojs/taro'
import icon from '@/assets/images/project.png'
import icon01 from '@/assets/images/回单.jpg'
import icon02 from '@/assets/images/工单.jpg'
@ -59,8 +55,8 @@ import icon03 from '@/assets/images/排名.jpg'
import icon04 from '@/assets/images/法制宣传.jpg'
import icon06 from '@/assets/images/警保风采.jpg'
import './index.scss'
import api from "@/request";
import {DataStatisticsRes} from "@/types/pages/police";
import api from '@/request'
import { DataStatisticsRes } from '@/types/pages/police'
const list = ref([process.env.TARO_APP_MINIO_URL + '/police-security/2024/11/5/dunpai.jpg'])
const swiperRef = ref() //
const subModuleList = ref([
@ -68,45 +64,45 @@ const subModuleList = ref([
id: 0,
icon: icon,
name: '项目管理',
url: '/subPages/police/myEnterprisesUnit/myEnterprisesUnit'
url: '/subPages/police/myEnterprisesUnit/myEnterprisesUnit',
},
{
id: 1,
icon: icon02,
name: '整改工单',
url: ''
name: '监督考核',
url: '/subPages/police/dailyInspection/dailyInspection',
},
{
id: 2,
icon: icon03,
name: '考核排名',
url: ''
url: '',
},
{
id: 3,
icon: icon06,
name: '警保风采',
url: ''
url: '',
},
{
id: 4,
icon: icon04,
name: '法制宣传',
url: ''
url: '',
},
{
id: 5,
icon: icon01,
name: '整改回单',
url: ''
}
url: '',
},
])
const numberStatistics = ref<DataStatisticsRes>({
enterprisesUnitCount: 0,
serviceProjectCount: 0,
securityUserCount: 0,
noCardSecurityUserCount:0
noCardSecurityUserCount: 0,
})
const dataStatistics = async () => {
const resp = await api.get<DataStatisticsRes>('/policeIndex/dataStatistics')
@ -117,5 +113,4 @@ onMounted(async()=>{
})
const subNavigation = async (url: string) => Taro.navigateTo({ url })
</script>

View File

@ -0,0 +1,41 @@
import { defineStore } from 'pinia'
export const useDailyStore = defineStore('daily', {
state: () => ({
userdailyinspection: [],
base64_1: '',
base64_2: '',
}),
actions: {
dailyinspectionList(data) {
this.userdailyinspection = [...data]
},
change_base64_1(data) {
// console.log("🚀 ~ change_base64_1 ~ data:", data)
this.base64_1 = data
},
change_base64_2(data) {
this.base64_2 = data
},
cleardailtcolour() {
this.userdailyinspection = {
...this.userdailyinspection,
markColor: this.userdailyinspection.markColor,
markColor1: this.userdailyinspection.markColor,
comment: ''
}
}
},
getters: {
getdailyinspection(state) {
return state.userdailyinspection
},
get_base64_1(state) {
return state.base64_1
},
get_base64_2(state) {
return state.base64_2
}
}
})

View File

@ -0,0 +1,40 @@
// page {
// background-color: #e9eef4;
// }
// .container {
// background-color: #e9eef4;
// }
.picker {
padding: 30rpx 30rpx;
display: flex;
justify-content: space-between;
}
.exit {
height: 100rpx;
line-height: 40px;
border-bottom: solid 0.5px #ebebf7;
box-sizing: border-box;
display: flex;
justify-content: space-between;
align-items: center;
.exitItem {
display: flex;
align-items: center;
}
.iconoscope {
z-index: 9999;
width: 8px;
height: 8px;
display: inline-block;
border: solid 2px #c2c2c2;
margin-left: 10px;
transform: rotate(45deg);
border-bottom: white;
border-left: white;
}
}

View File

@ -0,0 +1,3 @@
export default definePageConfig({
navigationBarTitleText: '监督考核',
})

View File

@ -0,0 +1,324 @@
<template>
<view class="container">
<!-- picker -->
<picker mode="selector" :range="selector" rangeKey="label" @change="onChange">
<view class="picker">
考核单位
<view style="display: flex; align-items: center">
<view v-if="selectorChecked.length === 0" style="color: #606266">请选择考核单位</view>
<view> {{ selectorChecked }}</view>
<IconFont name="arrow-right"></IconFont>
</view>
</view>
</picker>
<!-- picker -->
<!-- 如果 selectorType undefined null?.length 会返回 undefined然后通过 ?? 运算符将其替换为 0确保条件判断不会出错 -->
<picker v-if="(selectorType?.length ?? 0) > 0" mode="selector" :range="selectorType" rangeKey="label" @change="onChangeType">
<view class="picker">
当前考核项目
<view style="display: flex; align-items: center">
<view v-if="selectorCheckedType.length === 0" style="color: #606266">请选择考核项目</view>
<view> {{ selectorCheckedType }}</view>
<IconFont name="arrow-right"></IconFont>
</view>
</view>
</picker>
<!-- 选择题 -->
<view class="exit" v-for="item in starRating" :key="item.snowFlakeId" @click="Onrating(item.name, item.snowFlakeId)">
<view class="exitItem">
<text style="margin-left: 30rpx; font-size: 16px">
<text>{{ item.name }}{{ item.totalScore }} </text>
</text>
</view>
<view style="margin-right: 30rpx; display: flex; align-items: center">
<view v-if="item.currentScore > 0" style="color: #ff0000"> -{{ item.currentScore }}</view>
<IconFont name="arrow-right"></IconFont>
</view>
</view>
<nut-form>
<nut-form-item label-width="50" label="备注">
<nut-input v-model="_form.remark" placeholder="请输入备注" type="text" />
</nut-form-item>
</nut-form>
<!-- 签字 -->
<view>
<nut-form labelWidth="320rpx" labelAlign="left">
<nut-form-item label="考核人员签字:">
<navigator :url="`/subPages/select/signature/signature?index=${1}`" hover-class="navigator-hover">
<nut-button style="height: 50rpx" shape="square" type="info">考核人员签字</nut-button>
</navigator>
</nut-form-item>
<nut-form-item v-if="mydailycolors">
<view style="padding: 0">
<image :src="mydailycolors"></image>
</view>
</nut-form-item>
<nut-form-item label="被考评学校签名:">
<navigator :url="`/subPages/select/signature/signature?index=${2}`" hover-class="navigator-hover">
<nut-button style="height: 50rpx" shape="square" type="info">被考评学校负责人</nut-button>
</navigator>
</nut-form-item>
<nut-form-item v-if="mydailycolorschools">
<view style="padding: 0">
<image :src="mydailycolorschools"></image>
</view>
</nut-form-item>
<nut-form-item label="确认:">
<nut-button style="height: 50rpx" shape="square" type="info" @click="onSubmit">确认提交</nut-button>
</nut-form-item>
<view style="height: 20px"></view>
</nut-form>
</view>
</view>
</template>
<script setup lang="ts">
import { IconFont } from '@nutui/icons-vue-taro'
import Taro, { useLoad } from '@tarojs/taro'
import './dailyInspection.scss'
import { ref, computed, reactive, watch } from 'vue'
import api from '@/request/index'
import { useDailyStore } from '@/store/daily'
const store = useDailyStore()
const daily = computed(() => store.getdailyinspection)
const base64_1 = computed(() => store.get_base64_1)
const base64_2 = computed(() => store.get_base64_2)
const submitData = ref<Item[]>([])
// watch(
// daily,
// (newData) => {
// console.log('watch_______________', newData)
// if (newData.length > 0) starRating.value = newData
// submitData.value = newData
// },
// { immediate: true }
// )
const _form = reactive({
enterprisesUnitId: '', //id
ckProjectId: '', //
assessmentUserSignature: '', //
byAssessmentEnterprisesUnitUserSignature: '', //
remark: '', //
})
watch(
[daily, base64_1, base64_2],
([newDaily, newBase64_1, newBase64_2]) => {
_form.assessmentUserSignature = newBase64_1
_form.byAssessmentEnterprisesUnitUserSignature = newBase64_2
console.log('watch_______________', _form)
if (newDaily.length > 0) {
starRating.value = newDaily
}
submitData.value = newDaily
},
{ immediate: true }
)
const mydailycolors = ref('')
const mydailycolorschools = ref('')
useLoad(async () => {
await getUnitEnterprisesUnitList()
})
const starRating = ref<any[]>([])
const Onrating = function (name: string, snowFlakeId: string) {
let index = starRating.value.findIndex((item) => item.snowFlakeId === snowFlakeId)
Taro.navigateTo({
url: `/subPages/select/dailyLife/dailyLife?name=${name}&index=${index}`,
// url: `/subPages/select/dailyLife/dailyLife`,
// success: function (res) {
// try {
// if (process.env.TARO_ENV === 'weapp') {
// res.eventChannel.emit('starRating', { data: selectedItemList })
// }
// } catch (error) {
// }
// },
})
}
interface UnitEnterprisesUnitList {
label: string
value: string
extData: {
type: {
label: string
value: string
}
}
}
interface CkProjectListByType {
label: string
value: string
extData: {
createTime: string
remark: string
totalScore: number
type: {
label: string
value: string
}
}
}
/**
* @assessmentCriteriaRulesByCkProjectId 获取考核规则
*/
const assessmentCriteriaRulesByCkProjectId = async function (ckProjectId) {
Taro.showLoading({
title: '加载中...',
mask: true,
})
const res = await api.get<any[]>(`/assessmentCriteria/assessmentCriteriaRulesByCkProjectId`, { ckProjectId })
//
res.data?.forEach((item) => {
item.currentScore = 0
item.itemList.forEach((element) => {
// element.selectedID = element.standardList[0].snowFlakeId
element.standardList.unshift({
ckItemId: 'null',
deductionPoints: 0,
name: '达标',
snowFlakeId: 'null',
})
element.selectedID = element.standardList[0].snowFlakeId
element.selected_points = 0 // 0
//
if (element.type.value === 'multiple') {
element.selectedGroup = [element.selectedID]
}
})
})
starRating.value = res.data ?? [] // res.data undefined使
store.dailyinspectionList(starRating.value)
Taro.hideLoading()
}
/**
* @ckProjectListByType 根据类型获取考核标准列表
*/
const selectorCheckedType = ref<string>('')
const selectorType = ref<CkProjectListByType[]>()
const ckProjectListByType = async function (type) {
const res = await api.get<CkProjectListByType[]>(`/assessmentCriteria/ckProjectListByType`, { type })
selectorType.value = res.data
}
const onChangeType = function (e: any) {
let index = Number(e.detail.value)
selectorCheckedType.value = selectorType.value?.[index].label as string
let ckProjectId = selectorType.value?.[index].value
assessmentCriteriaRulesByCkProjectId(ckProjectId)
_form.ckProjectId = selectorType.value?.[index].value as string
}
const selector = ref<UnitEnterprisesUnitList[]>()
const selectorChecked = ref<string>('')
const onChange = function (e: any) {
let index = Number(e.detail.value)
selectorChecked.value = selector.value?.[index].label as string
let type = selector.value?.[index].extData.type.value
ckProjectListByType(type)
_form.enterprisesUnitId = selector.value?.[index].value as string
}
const getUnitEnterprisesUnitList = async function () {
const res = await api.get<UnitEnterprisesUnitList[]>(`/policeIndex/getUnitEnterprisesUnitList`)
selector.value = res.data
}
const _showToast = function (title) {
Taro.showToast({
title,
icon: 'none',
duration: 1500,
mask: true,
})
}
/**
* @onSubmit 提交
*/
/**
* @assessmentRecordDetails 选择后的数据用于提交
*/
interface Item {
itemList: any[] //
}
const assessmentRecordDetails = ref<any[]>([])
const onSubmit = async function () {
if (_form.enterprisesUnitId === '') {
_showToast('请选择企事业单位')
return
}
if (_form.ckProjectId === '') {
_showToast('请选择考核项目')
return
}
if (_form.assessmentUserSignature === '') {
_showToast('请考核人员签字')
return
}
if (_form.byAssessmentEnterprisesUnitUserSignature === '') {
_showToast('请被考核单位人员签字')
return
}
Taro.showLoading({
title: '加载中...',
mask: true,
})
submitData.value.forEach((element) => {
element?.itemList.forEach((item) => {
item.standardList.forEach((ele) => {
if (ele.snowFlakeId === item.selectedID && !item.hasOwnProperty('selectedGroup') && item.selectedID != 'null') {
assessmentRecordDetails.value.push({
ckGroupId: item.snowFlakeId, //Id
ckItemId: ele.ckItemId, //ID
ckStandardId: item.selectedID, //ID
})
}
})
if (item.hasOwnProperty('selectedGroup')) {
item.selectedGroup.forEach((selectedItem) => {
console.log(selectedItem)
if (selectedItem != 'null') {
assessmentRecordDetails.value.push({
ckGroupId: item.snowFlakeId, //Id
ckItemId: item.snowFlakeId, //ID
ckStandardId: selectedItem, //ID
})
}
})
}
})
})
const assessmentRecordParams = {
assessmentRecordDetails: [] as any[],
}
Object.assign(assessmentRecordParams, _form)
assessmentRecordParams.assessmentRecordDetails = [...assessmentRecordDetails.value]
console.log('🚀 ~ onSubmit ~ assessmentRecordParams:', assessmentRecordParams)
const result = await api.post('/assessmentCriteria/submitAssessmentRecord', assessmentRecordParams)
console.log('🚀 ~ onSubmit ~ result:', result)
Taro.hideLoading()
if (result.code === 200) {
Taro.showToast({
title: result.message,
icon: 'success',
duration: 1500,
mask: true,
})
} else {
_showToast(result.message)
}
}
// useDidShow(() => {
// // pinia
// console.log('onShow_______________ pinia ', submitData.value)
// })
</script>

View File

@ -0,0 +1,26 @@
.userinform {
height: 100%;
width: 100%;
}
.userItem {
color: #7b7b7b;
font-size: 14px;
margin-bottom: 8px;
.textIndex {
margin-left: 20rpx;
}
}
.text {
width: 96%;
}
.singleChoice {
width: 90%;
}
.label {
margin: 0 20px;
}

View File

@ -0,0 +1,3 @@
export default definePageConfig({
navigationBarTitleText: '',
})

View File

@ -0,0 +1,124 @@
<template>
<view class="userinform">
<view class="userItem">
<!-- v-model="item.snowFlakeId" 展开所有 -->
<nut-collapse v-model="item.snowFlakeId" accordion v-for="(item, index) in starRating[findIndex].itemList" :key="item.snowFlakeId">
<nut-collapse-item :name="item.snowFlakeId" :title="item.name">
<view class="singleChoice">
<!-- v-model="form[item.name]" -->
<nut-radio-group v-if="item.type.value === 'radio'" v-model="item.selectedID" @change="(modelValue) => onChange(modelValue, item.name)">
<nut-radio v-for="(items, indexs) in item.standardList" size="40" :label="items.snowFlakeId" :key="indexs"> {{ items.name }}</nut-radio>
</nut-radio-group>
<nut-checkbox-group v-else v-model="item.selectedGroup" @change="(arr) => checkboxGroupChange(arr, index)" style="display: flex; flex-direction: column">
<nut-checkbox
@change="(state, label) => checkboxChange(state, label)"
v-for="(items, i) in item.standardList"
size="40"
:label="items.snowFlakeId"
:key="i"
style="margin-bottom: 20rpx"
shape="button"
>{{ items.name }}</nut-checkbox
>
</nut-checkbox-group>
</view>
</nut-collapse-item>
</nut-collapse>
</view>
</view>
</template>
<script setup>
import Taro, { useLoad, useUnload } from '@tarojs/taro'
import { ref, computed, watch } from 'vue'
import { useDailyStore } from '@/store/daily.ts'
const store = useDailyStore()
const starRating = ref([])
const findIndex = ref(0)
const airdefenceEnumdata = ref([])
useLoad((options) => {
Taro.setNavigationBarTitle({
title: options.name,
})
findIndex.value = options.index
// console.log('starRating.value_______________', starRating.value)
// if (process.env.TARO_ENV === 'weapp') {
// const instance = Taro.getCurrentInstance()
// const eventChannel = instance.page.getOpenerEventChannel()
// eventChannel.on('starRating', function (data) {
// Taro.setNavigationBarTitle({
// title: data.data.name,
// })
// airdefenceEnumdata.value = [...data.data.itemList]
// })
// }
})
const daily = computed(() => store.getdailyinspection)
watch(
daily,
(newData) => {
starRating.value = newData
},
{ immediate: true }
)
/**
* @assessmentRecordDetails 选择后的数据用于提交
*/
const assessmentRecordDetails = ref([])
const onChange = (modelValue, name) => {
starRating.value[findIndex.value].itemList.forEach((element) => {
if (name === element.name) {
element.selectedID = modelValue
element.standardList.forEach((item) => {
// console.log('item.snowFlakeId, modelValue_________________', item.snowFlakeId, modelValue)
if (item.snowFlakeId == modelValue) {
element.selectedName = item.name // selectedName 便
element.selected_points = item.deductionPoints //
}
})
}
})
}
const checkboxGroupChange = function (arr, index) {
// console.log('🚀 ~ checkboxGroupChange ~ arr:', arr)
// console.log(index)
// console.log(starRating.value[findIndex.value].itemList[index])
let points = 0
starRating.value[findIndex.value].itemList.forEach((element, i) => {
if (i === index) {
element.selectedGroup.forEach((selectedId) => {
element.standardList.forEach((standardItem) => {
if (selectedId === standardItem.snowFlakeId) {
points += standardItem.deductionPoints
}
})
})
}
})
starRating.value[findIndex.value].itemList[index].selected_points = points
// console.log(points)
// console.log(starRating.value[findIndex.value].itemList[index].selected_points)
}
const checkboxChange = function (state, label) {
// console.log('🚀 ~ checkboxChange ~ state, label:', state, label)
}
useUnload(() => {
let points = 0
starRating.value[findIndex.value].itemList.forEach((element) => {
points += element.selected_points
})
starRating.value[findIndex.value].currentScore = points
store.dailyinspectionList([...starRating.value])
})
</script>

View File

@ -0,0 +1,3 @@
export default definePageConfig({
navigationBarTitleText: '签名',
})

View File

@ -0,0 +1,53 @@
<template>
<nut-signature @confirm="confirm" @clear="clear"></nut-signature>
<img v-if="imgData" :src="imgData" class="imgData" style="width: 100%" />
</template>
<script setup lang="ts">
import { useDailyStore } from '@/store/daily'
const store = useDailyStore()
import Taro, { useLoad } from '@tarojs/taro'
import { ref } from 'vue'
const _index = ref(0)
useLoad((options) => {
console.log(options)
_index.value = Number(options.index)
})
const imgData = ref('')
const convertToBase64 = (imgUrl: string): Promise<string> => {
return new Promise((resolve, reject) => {
const fs = Taro.getFileSystemManager()
fs.readFile({
filePath: imgUrl, //
encoding: 'base64',
success(res) {
resolve('data:image/png;base64,' + res.data) // image img
},
fail(err) {
reject(err)
},
})
})
}
const confirm = async (canvas: any, data: string) => {
if (data) {
imgData.value = data
console.log('imgData', canvas, data)
try {
const base64Image = await convertToBase64(data)
if (_index.value === 1) {
store.change_base64_1(base64Image)
} else {
store.change_base64_2(base64Image)
}
// console.log('Base64 Image:', base64Image)
} catch (error) {
console.error('Failed to convert image to Base64:', error)
}
}
}
const clear = () => {
imgData.value = ''
console.log('clear')
}
</script>

View File

@ -23,6 +23,7 @@
<easyexcel.version>3.3.4</easyexcel.version>
<mysql.driver.version>8.0.32</mysql.driver.version>
<mybatis.plus.version>3.5.7</mybatis.plus.version>
<geotools.version>25.2</geotools.version>
<druid.version>1.2.20</druid.version>
<minio.version>8.4.3</minio.version>
<okhttp.version>4.8.1</okhttp.version>
@ -190,6 +191,17 @@
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>${mybatis.plus.version}</version>
</dependency>
<!-- 处理地理空间数据的读取、写入、转换、分析以及可视化 geotools-->
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-main</artifactId>
<version>${geotools.version}</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-geojson</artifactId>
<version>${geotools.version}</version>
</dependency>
<!-- minio对象存储 https://www.minio.org.cn/ -->
<dependency>
<groupId>io.minio</groupId>

View File

@ -23,5 +23,5 @@ public @interface CheckUserType {
/**
* 需要的客户端类型
*/
UserType[] userTypes();
UserType[] userTypes() default {};
}

View File

@ -0,0 +1,25 @@
package com.changhu.common.db.enums;
import com.baomidou.mybatisplus.annotation.IEnum;
import com.changhu.common.db.BaseEnum;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author 20252
* @createTime 2024/11/5 下午4:22
* @desc EnterprisesUnitType...
*/
@Getter
@AllArgsConstructor
public enum EnterprisesUnitType implements BaseEnum<String>, IEnum<String> {
school("school", "学校"),
hospital("hospital", "医院"),
community("community", "社区/小区"),
bank("bank", "银行"),
;
private final String value;
private final String label;
}

View File

@ -0,0 +1,25 @@
package com.changhu.common.db.enums;
import com.baomidou.mybatisplus.annotation.IEnum;
import com.changhu.common.db.BaseEnum;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* author: luozhun
* desc: 单选或多选
* createTime: 2023/8/16 17:39
*/
@Getter
@AllArgsConstructor
public enum SelectType implements BaseEnum<String>, IEnum<String> {
RADIO("radio", "单选"),
MULTIPLE("multiple", "多选"),
;
private final String value;
private final String label;
}

View File

@ -0,0 +1,428 @@
package com.changhu.common.utils;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.changhu.common.exception.MessageException;
import lombok.extern.slf4j.Slf4j;
import org.geotools.geojson.geom.GeometryJSON;
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.CRS;
import org.geotools.referencing.GeodeticCalculator;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKBReader;
import org.locationtech.jts.io.WKTReader;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import java.awt.geom.Point2D;
import java.io.IOException;
import java.io.StringReader;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.List;
import java.util.Objects;
/**
* author: luozhun
* desc: GeometryUtil
* createTime: 2023/8/25 18:03
*/
@Slf4j
public class GeometryUtil {
/**
* - WGS 84srid=4326用于全球地理坐标系统的标准参考坐标系
* - 美国地理参考系统srid=4269用于美国本土的地图和地理数据
* - 欧洲地理参考系统srid=4258用于欧洲地图和地理数据
* - 中国国家大地坐标系srid=4490用于中国的地图和地理数据
*/
public static final int SRID = 4326;
public static final String ST_GeomFromText = StrUtil.format("ST_GeomFromText({},{},{})", "?", SRID, "'axis-order=long-lat'");
private static final GeometryFactory GEOMETRY_FACTORY = new GeometryFactory(new PrecisionModel(), SRID);
private static final GeometryFactory LOCATION_TECH_GEOMETRY_FACTORY = new GeometryFactory(new PrecisionModel(), SRID);
/**
* 空对象因为简历空间索引不能为空 Mysql 不支持创建 Empty 的数据 这里自定义一个类型 标识为null
*/
public static Point emptyPoint() {
return createPoint("POINT(0 0)");
}
public static Polygon emptyPolygon() {
return createPolygon("POLYGON((0 0, 0 0, 0 0, 0 0))");
}
public static LineString emptyLineString() {
return createLineString("LINESTRING(0 0, 0 0)");
}
public static MultiPoint emptyMultiPoint() {
return createMultiPoint("MULTIPOINT((0 0))");
}
public static MultiPolygon emptyMultiPolygon() {
return createMultiPolygon("MULTIPOLYGON(((0 0, 0 0, 0 0, 0 0)))");
}
public static MultiLineString emptyMultiLineString() {
return createMultiLineString("MULTILINESTRING(((0 0, 0 0)))");
}
public static boolean equals(Geometry geometry1, Geometry geometry2) {
return StrUtil.equals(geometry1.toText(), geometry2.toText());
}
//** **\\
/**
* 创建点对象
*/
public static Point createPoint(List<BigDecimal> param) {
if (param == null) {
return null;
}
BigDecimal longitude = param.get(0);
BigDecimal latitude = param.get(1);
if (longitude == null || latitude == null) {
return null;
}
Coordinate coordinate = new Coordinate(longitude.doubleValue(), latitude.doubleValue());
return GEOMETRY_FACTORY.createPoint(coordinate);
}
public static Point createPoint(double longitude, double latitude) {
Coordinate coordinate = new Coordinate(longitude, latitude);
return GEOMETRY_FACTORY.createPoint(coordinate);
}
/**
* 从WKT创建点对象
*
* @param wkt 注WKT类似 POINT(109.013388 32.715519)
*/
public static Point createPoint(String wkt) {
return createGeometryFromWkt(wkt, Point.class);
}
/**
* 从WKT创建点对象
*
* @param bytes 数据库二进制数据
*/
public static Point createPoint(byte[] bytes) {
return createGeometryFromBytes(bytes, Point.class);
}
//** 多边形 **\\
/**
* 创建多边形对象
* <p>
* 后面可能考虑兼容折线类型如果是折线类型那么需要规范首尾结点要相同才能构成 polygon 否则构成 polyline
* 目前暂时没有做这方面的规划用代码兼容了首尾不相等的情况构成polygon
*/
public static Polygon createPolygon(List<List<BigDecimal>> params) {
if (params == null || params.size() < 4) {
throw new MessageException("构成多边形至少需要三个有效坐标,并且保证尾部坐标和首部坐标相同");
}
// 检测首尾是否相等不相等则补充尾坐标
List<BigDecimal> startPoint = params.get(0);
List<BigDecimal> entPoint = params.get(params.size() - 1);
if (!Objects.equals(startPoint.get(0), entPoint.get(0))
|| !Objects.equals(startPoint.get(1), entPoint.get(1))) {
params.add(params.get(0));
}
Coordinate[] coordinates = convertBigDecimalList2CoordinateArray(params);
return GEOMETRY_FACTORY.createPolygon(coordinates);
}
public static Polygon createPolygonWithDouble(List<List<Double>> params) {
if (params == null || params.size() < 4) {
throw new MessageException("构成多边形至少需要三个有效坐标,并且保证尾部坐标和首部坐标相同");
}
// 检测首尾是否相等不相等则补充尾坐标
List<Double> startPoint = params.get(0);
List<Double> entPoint = params.get(params.size() - 1);
if (!Objects.equals(startPoint.get(0), entPoint.get(0))
|| !Objects.equals(startPoint.get(1), entPoint.get(1))) {
params.add(params.get(0));
}
Coordinate[] coordinates = convertDoubleList2CoordinateArray(params);
return GEOMETRY_FACTORY.createPolygon(coordinates);
}
/**
* 从WKT创建多边形对象
*
* @param wkt 注WKT类似POLYGON((20 10, 30 0, 40 10, 30 20, 20 10))
*/
public static Polygon createPolygon(String wkt) {
return createGeometryFromWkt(wkt, Polygon.class);
}
/**
* 创建多边形对象
*
* @param bytes 数据库二进制数据
*/
public static Polygon createPolygon(byte[] bytes) {
return createGeometryFromBytes(bytes, Polygon.class);
}
//** 折线 **\\
/**
* 创建折线对象
*/
public static LineString createLineString(List<List<BigDecimal>> params) {
if (params == null || params.size() < 2) {
throw new MessageException("构成折线至少需要两个有效坐标");
}
Coordinate[] coordinates = convertBigDecimalList2CoordinateArray(params);
return GEOMETRY_FACTORY.createLineString(coordinates);
}
/**
* wkt 创建折线对象
*/
public static LineString createLineString(String wkt) {
return createGeometryFromWkt(wkt, LineString.class);
}
/**
* bytes 创建折线对象
*/
public static LineString createLineString(byte[] bytes) {
return createGeometryFromBytes(bytes, LineString.class);
}
//** 多点 **\\
/**
* 创建多点对象
*/
public static MultiPoint createMultiPoint(List<List<BigDecimal>> multiParam) {
int size = multiParam.size();
Point[] points = new Point[size];
for (int i = 0; i < size; i++) {
points[i] = createPoint(multiParam.get(i));
}
return GEOMETRY_FACTORY.createMultiPoint(points);
}
/**
* wkt 创建多点对象
*/
public static MultiPoint createMultiPoint(String wkt) {
return createGeometryFromWkt(wkt, MultiPoint.class);
}
/**
* bytes 创建多点对象
*/
public static MultiPoint createMultiPoint(byte[] bytes) {
return createGeometryFromBytes(bytes, MultiPoint.class);
}
//** 多折线 **\\
/**
* 创建多折线对象
*/
public static MultiLineString createMultiLineString(List<List<List<BigDecimal>>> multiParams) {
int size = multiParams.size();
LineString[] lineStrings = new LineString[size];
for (int i = 0; i < size; i++) {
lineStrings[i] = createLineString(multiParams.get(i));
}
return GEOMETRY_FACTORY.createMultiLineString(lineStrings);
}
/**
* wkt 创建多折线对象
*/
public static MultiLineString createMultiLineString(String wkt) {
return createGeometryFromWkt(wkt, MultiLineString.class);
}
/**
* wkt 创建多折线对象
*/
public static MultiLineString createMultiLineString(byte[] bytes) {
return createGeometryFromBytes(bytes, MultiLineString.class);
}
//** 多多边形 **\\
/**
* 创建多多边形
*/
public static MultiPolygon createMultiPolygon(List<List<List<BigDecimal>>> multiParams) {
int size = multiParams.size();
Polygon[] polygons = new Polygon[size];
for (int i = 0; i < size; i++) {
polygons[i] = createPolygon(multiParams.get(i));
}
return GEOMETRY_FACTORY.createMultiPolygon(polygons);
}
/**
* wkt 创建多多边形
*/
public static MultiPolygon createMultiPolygon(String wkt) {
return createGeometryFromWkt(wkt, MultiPolygon.class);
}
/**
* bytes 创建多多边形
*/
public static MultiPolygon createMultiPolygon(byte[] bytes) {
return createGeometryFromBytes(bytes, MultiPolygon.class);
}
//** 通用工具 **\\
/**
* bytes 创建空间对象
*
* @param bytes 数据库的二进制数据
*/
public static <T extends Geometry> T createGeometryFromBytes(byte[] bytes, Class<T> clazz) {
if (bytes == null) {
return null;
}
try {
WKBReader wkbReader = new WKBReader(GEOMETRY_FACTORY);
byte[] geomBytes = ByteBuffer.allocate(bytes.length - 4).order(ByteOrder.LITTLE_ENDIAN)
.put(bytes, 4, bytes.length - 4).array();
Geometry geometry = wkbReader.read(geomBytes);
return Convert.convert(clazz, geometry);
} catch (Exception e) {
throw new MessageException("从 Bytes 创建空间对象 {} 时出现错误:{}", clazz.getSimpleName(), e.getMessage());
}
}
/**
* wkt 创建空间对象
*
* @param wkt 类似POLYGON((20 10, 30 0, 40 10, 30 20, 20 10)) POINT(109.013388 32.715519)
* @param clazz 继承
*/
public static <T extends Geometry> T createGeometryFromWkt(String wkt, Class<T> clazz) {
if (wkt == null || StrUtil.isBlank(wkt)) {
return null;
}
try {
WKTReader reader = new WKTReader(GEOMETRY_FACTORY);
Geometry geometry = reader.read(wkt);
return Convert.convert(clazz, geometry);
} catch (ParseException e) {
throw new MessageException("从WKT创建空间对象 {} 时出现错误。wkt{}", clazz.getSimpleName(), wkt);
}
}
/**
* GeoJson 创建空间对象
*/
public static <T extends Geometry> T createGeometryFromGeoJson(String geoJson, Class<T> clazz) {
try {
GeometryJSON geometryJson = new GeometryJSON(20);
Geometry read = geometryJson.read(new StringReader(geoJson));
return createGeometryFromWkt(read.toString(), clazz);
} catch (IOException e) {
log.error("从 GeoJson 创建空间对象出错:{}", e.getMessage());
}
return null;
}
/**
* List<LngLatParam> 转化为 Coordinate[]
*/
private static Coordinate[] convertBigDecimalList2CoordinateArray(List<List<BigDecimal>> params) {
int size = params.size();
Coordinate[] coordinates = new Coordinate[size];
for (int i = 0; i < params.size(); i++) {
List<BigDecimal> param = params.get(i);
Coordinate coordinate = new Coordinate(param.get(0).doubleValue(), param.get(1).doubleValue());
coordinates[i] = coordinate;
}
return coordinates;
}
private static Coordinate[] convertDoubleList2CoordinateArray(List<List<Double>> params) {
int size = params.size();
Coordinate[] coordinates = new Coordinate[size];
for (int i = 0; i < params.size(); i++) {
List<Double> param = params.get(i);
Coordinate coordinate = new Coordinate(param.get(0), param.get(1));
coordinates[i] = coordinate;
}
return coordinates;
}
/**
* 计算面积 平方米
* 28155 .195928.042862
*/
public static BigDecimal getApproximateArea(Geometry geometry) {
try {
String wkt = geometry.toText();
WKTReader wktReader = new WKTReader(LOCATION_TECH_GEOMETRY_FACTORY);
Geometry geom = wktReader.read(wkt);
// WGS84(一般项目中常用的是CSR:84和EPSG:4326)
CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:4326");
// Pseudo-Mercator(墨卡托投影)
CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:4490");
MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, true);
Geometry geometryMercator = JTS.transform(geom, transform);
// 面积周长
return BigDecimal.valueOf(geometryMercator.getArea());
} catch (FactoryException | TransformException | ParseException e) {
log.error("计算面积出错:{}", e.getMessage());
}
return null;
}
/**
* 当前数据库的数据来源都是高德数据源 坐标系为GCJ02 如果来源是其他的地图的需要根据规则转换成GCJ02
* 同理如果需要转换到其他的数据源的坐标系也需要进行转换
*/
public static <T extends Geometry> T convertWgs84ToGcj02(T geometry) {
log.info("原始数据:{}", geometry.toText());
Coordinate[] coordinates = geometry.getCoordinates();
for (Coordinate coordinate : coordinates) {
double lon = coordinate.x;
double lat = coordinate.y;
double[] doubles = GpsConvertUtil.wgs84ToGcj02(lon, lat);
coordinate.x = doubles[0];
coordinate.y = doubles[1];
}
log.info("转后数据:{}", geometry.toText());
return geometry;
}
public static double distance(Point p0, Point p1) {
GeodeticCalculator calculator = new GeodeticCalculator();
calculator.setStartingGeographicPoint(p0.getX(), p0.getY());
calculator.setDestinationGeographicPoint(p1.getX(), p1.getY());
return calculator.getOrthodromicDistance();
}
public static Point2D calculateEndingGlobalCoordinates(double longitude, double latitude, double azi, double dis) {
GeodeticCalculator calculator = new GeodeticCalculator();
calculator.setStartingGeographicPoint(longitude, latitude);
calculator.setDirection(azi, dis);
return calculator.getDestinationGeographicPoint();
}
}

View File

@ -0,0 +1,135 @@
package com.changhu.common.utils;
/**
* author: luozhun
* desc: 坐标系转换
* createTime: 2023/8/25 18:18
*/
public class GpsConvertUtil {
public static final double pi = 3.1415926535897932384626;
public static final double xpi = 3.14159265358979324 * 3000.0 / 180.0;
public static final double a = 6378245.0;
public static final double ee = 0.00669342162296594323;
public static double transformLat(double x, double y) {
double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y
+ 0.2 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
return ret;
}
public static double transformLon(double x, double y) {
double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1
* Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0
* pi)) * 2.0 / 3.0;
return ret;
}
public static double[] transform(double lon, double lat) {
if (outOfChina(lon, lat)) {
return new double[]{lon, lat};
}
double dLat = transformLat(lon - 105.0, lat - 35.0);
double dLon = transformLon(lon - 105.0, lat - 35.0);
double radLat = lat / 180.0 * pi;
double magic = Math.sin(radLat);
magic = 1 - ee * magic * magic;
double sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
double mgLat = lat + dLat;
double mgLon = lon + dLon;
return new double[]{mgLon, mgLat};
}
public static boolean outOfChina(double lon, double lat) {
if (lon < 72.004 || lon > 137.8347)
return true;
return lat < 0.8293 || lat > 55.8271;
}
/**
* 84 to 火星坐标系 (GCJ-02) World Geodetic System ==> Mars Geodetic System
*/
public static double[] wgs84ToGcj02(double lon, double lat) {
if (outOfChina(lon, lat)) {
return new double[]{lon, lat};
}
double dLat = transformLat(lon - 105.0, lat - 35.0);
double dLon = transformLon(lon - 105.0, lat - 35.0);
double radLat = lat / 180.0 * pi;
double magic = Math.sin(radLat);
magic = 1 - ee * magic * magic;
double sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
double mgLat = lat + dLat;
double mgLon = lon + dLon;
return new double[]{mgLon, mgLat};
}
/**
* * 火星坐标系 (GCJ-02) to 84 * * @param lon * @param lat * @return
*/
public static double[] gcj02ToWgs84(double lon, double lat) {
double[] gps = transform(lon, lat);
double longitude = lon * 2 - gps[0];
double latitude = lat * 2 - gps[1];
return new double[]{longitude, latitude};
}
/**
* 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 GCJ-02 坐标转换成 BD-09 坐标
*/
public static double[] gcj02ToBd09(double lon, double lat) {
double z = Math.sqrt(lon * lon + lat * lat) + 0.00002 * Math.sin(lat * xpi);
double theta = Math.atan2(lat, lon) + 0.000003 * Math.cos(lon * xpi);
double tempLon = z * Math.cos(theta) + 0.0065;
double tempLat = z * Math.sin(theta) + 0.006;
return new double[]{tempLon, tempLat};
}
/**
* * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 * * BD-09 坐标转换成GCJ-02 坐标 * * @param
* bdlat * @param bdlon * @return
*/
public static double[] bd09ToGcj02(double lon, double lat) {
double x = lon - 0.0065, y = lat - 0.006;
double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * xpi);
double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * xpi);
double tempLon = z * Math.cos(theta);
double tempLat = z * Math.sin(theta);
return new double[]{tempLon, tempLat};
}
/**
* 将wgs84转为bd09
*/
public static double[] wgs84ToBd09(double lon, double lat) {
double[] gcj02 = wgs84ToGcj02(lon, lat);
return gcj02ToBd09(gcj02[0], gcj02[1]);
}
public static double[] bd09ToWgs84(double lon, double lat) {
double[] gcj02 = bd09ToGcj02(lon, lat);
double[] wgs84 = gcj02ToWgs84(gcj02[0], gcj02[1]);
// 保留小数点后六位
wgs84[1] = retain6(wgs84[1]);
wgs84[0] = retain6(wgs84[0]);
return wgs84;
}
/**
* 保留小数点后六位
*/
private static double retain6(double num) {
String result = String.format("%.6f", num);
return Double.parseDouble(result);
}
}

View File

@ -42,7 +42,7 @@ public class ManagementSecurityUnitLogin extends AbstractLoginHandler {
.or()
.eq(ManagementSecurityUnitUser::getTelephone, accountOrTelephone)
.oneOpt()
.orElseThrow(() -> new MessageException(ResultCode.ERROR));
.orElseThrow(() -> new MessageException(ResultCode.USER_NOT_FOUND));
//判断用户是否禁用
if (managementSecurityUnitUser.getIsEnable().equals(IsEnable.FALSE)) {

View File

@ -0,0 +1,134 @@
package com.changhu.module.assessmentCriteria.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.changhu.common.annotation.CheckUserType;
import com.changhu.common.annotation.JsonBody;
import com.changhu.common.annotation.UserType;
import com.changhu.common.db.enums.EnterprisesUnitType;
import com.changhu.common.exception.MessageException;
import com.changhu.common.pojo.vo.SelectNodeVo;
import com.changhu.module.assessmentCriteria.pojo.entity.CkGroup;
import com.changhu.module.assessmentCriteria.pojo.entity.CkItem;
import com.changhu.module.assessmentCriteria.pojo.entity.CkStandard;
import com.changhu.module.assessmentCriteria.pojo.params.*;
import com.changhu.module.assessmentCriteria.pojo.queryParams.CkProjectPagerQueryParams;
import com.changhu.module.assessmentCriteria.pojo.vo.AssessmentCriteriaRuleVo;
import com.changhu.module.assessmentCriteria.pojo.vo.CkProjectDetailTableVo;
import com.changhu.module.assessmentCriteria.pojo.vo.CkProjectPagerVo;
import com.changhu.module.assessmentCriteria.service.AssessmentCriteriaService;
import com.changhu.support.mybatisplus.pojo.params.PageParams;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @author 20252
* @createTime 2024/11/6 上午10:02
* @desc AssessmentCriteriaController...
*/
@Tag(name = "考核标准")
@JsonBody
@RequestMapping("/assessmentCriteria")
@CheckUserType(userTypes = UserType.MANAGEMENT_SUPER)
public class AssessmentCriteriaController {
@Autowired
private AssessmentCriteriaService assessmentCriteriaService;
@Operation(summary = "根据类型获取考核项目列表")
@GetMapping("/ckProjectListByType")
@CheckUserType(value = false)
public List<SelectNodeVo<Long>> ckProjectListByType(@RequestParam EnterprisesUnitType type) {
return assessmentCriteriaService.assessmentCriteriaListByType(type);
}
@Operation(summary = "根据考核项目获取考核规则")
@GetMapping("/assessmentCriteriaRulesByCkProjectId")
@CheckUserType(value = false)
public List<AssessmentCriteriaRuleVo> assessmentCriteriaRulesByCkProjectId(@RequestParam Long ckProjectId) {
return assessmentCriteriaService.assessmentCriteriaRulesByCkProjectId(ckProjectId);
}
@Operation(summary = "提交考核记录")
@PostMapping("/submitAssessmentRecord")
@CheckUserType(value = false)
public void submitAssessmentRecord(@Validated @RequestBody AssessmentRecordParams params) {
assessmentCriteriaService.submitAssessmentRecord(params);
}
@Operation(summary = "考核项目分页查询")
@PostMapping("/ckProjectPagerVoPager")
public Page<CkProjectPagerVo> ckProjectPagerVoPager(@RequestBody PageParams<CkProjectPagerQueryParams, CkProjectPagerVo> queryParams) {
return assessmentCriteriaService.ckProjectPagerVoPager(queryParams);
}
@Operation(summary = "新增或修改考核项目")
@PostMapping("/saveOrUpdateCkProject")
public void saveOrUpdateCkProject(@Valid @RequestBody CkProjectSaveOrUpdateParams params) {
assessmentCriteriaService.saveOrUpdateCkProject(params);
}
@Operation(summary = "删除考核项目")
@DeleteMapping("/deleteCkProjectById")
public void deleteCkProjectById(@RequestParam Long ckProjectId) {
assessmentCriteriaService.deleteCkProjectById(ckProjectId);
}
@Operation(summary = "考核项目详情")
@GetMapping("/ckProjectDetail")
public List<CkProjectDetailTableVo> ckProjectDetail(@RequestParam Long ckProjectId) {
return assessmentCriteriaService.ckProjectDetail(ckProjectId);
}
@Operation(summary = "新增或修改考核分组")
@PostMapping("/saveOrUpdateCkGroup")
public void saveOrUpdateCkGroup(@Valid @RequestBody CkGroupSaveOrUpdateParams params) {
assessmentCriteriaService.saveOrUpdateCkGroup(params);
}
@Operation(summary = "新增或修改考核项")
@PostMapping("/saveOrUpdateCkItem")
public void saveOrUpdateCkItem(@Valid @RequestBody CkItemSaveOrUpdateParams params) {
assessmentCriteriaService.saveOrUpdateCkItem(params);
}
@Operation(summary = "新增或修改考核标准")
@PostMapping("/saveOrUpdateCkStandard")
public void saveOrUpdateCkStandard(@Valid @RequestBody CkStandardSaveOrUpdateParams params) {
assessmentCriteriaService.saveOrUpdateCkStandard(params);
}
@Operation(summary = "删除考核分组")
@DeleteMapping("/deleteCkGroupById")
public void deleteCkGroupById(@RequestParam Long ckGroupId) {
boolean b = Db.removeById(ckGroupId, CkGroup.class);
if (!b) {
throw new MessageException();
}
}
@Operation(summary = "删除考核项")
@DeleteMapping("/deleteCkItemById")
public void deleteCkItemById(@RequestParam Long ckItemId) {
boolean b = Db.removeById(ckItemId, CkItem.class);
if (!b) {
throw new MessageException();
}
}
@Operation(summary = "删除考核标准")
@DeleteMapping("/deleteCkStandardById")
public void deleteCkStandardById(@RequestParam Long ckStandardId) {
boolean b = Db.removeById(ckStandardId, CkStandard.class);
if (!b) {
throw new MessageException();
}
}
}

View File

@ -0,0 +1,15 @@
package com.changhu.module.assessmentCriteria.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.changhu.module.assessmentCriteria.pojo.entity.CkAssessmentRecordDetails;
import org.apache.ibatis.annotations.Mapper;
/**
* ck_assessment_record_details (考核记录明细) 固化类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Mapper
public interface CkAssessmentRecordDetailsMapper extends BaseMapper<CkAssessmentRecordDetails> {
}

View File

@ -0,0 +1,15 @@
package com.changhu.module.assessmentCriteria.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.changhu.module.assessmentCriteria.pojo.entity.CkAssessmentRecord;
import org.apache.ibatis.annotations.Mapper;
/**
* ck_assessment_record (考核记录) 固化类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Mapper
public interface CkAssessmentRecordMapper extends BaseMapper<CkAssessmentRecord> {
}

View File

@ -0,0 +1,15 @@
package com.changhu.module.assessmentCriteria.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.changhu.module.assessmentCriteria.pojo.entity.CkGroup;
import org.apache.ibatis.annotations.Mapper;
/**
* ck_group (考核组) 固化类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Mapper
public interface CkGroupMapper extends BaseMapper<CkGroup> {
}

View File

@ -0,0 +1,15 @@
package com.changhu.module.assessmentCriteria.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.changhu.module.assessmentCriteria.pojo.entity.CkItem;
import org.apache.ibatis.annotations.Mapper;
/**
* ck_item (分组内的考核项) 固化类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Mapper
public interface CkItemMapper extends BaseMapper<CkItem>{
}

View File

@ -0,0 +1,39 @@
package com.changhu.module.assessmentCriteria.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.changhu.module.assessmentCriteria.pojo.entity.CkProject;
import com.changhu.module.assessmentCriteria.pojo.queryParams.CkProjectPagerQueryParams;
import com.changhu.module.assessmentCriteria.pojo.vo.CkProjectDetailTableVo;
import com.changhu.module.assessmentCriteria.pojo.vo.CkProjectPagerVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* ck_project (考核项目) 固化类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Mapper
public interface CkProjectMapper extends BaseMapper<CkProject> {
/**
* 分页查询
*
* @param page 分页参数
* @param params 查询参数
* @return 分页数据
*/
Page<CkProjectPagerVo> pager(@Param("page") Page<CkProjectPagerVo> page,
@Param("params") CkProjectPagerQueryParams params);
/**
* 考核项目详情
*
* @param ckProjectId 考核项目id
* @return 详情
*/
List<CkProjectDetailTableVo> ckProjectDetail(@Param("ckProjectId") Long ckProjectId);
}

View File

@ -0,0 +1,15 @@
package com.changhu.module.assessmentCriteria.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.changhu.module.assessmentCriteria.pojo.entity.CkStandard;
import org.apache.ibatis.annotations.Mapper;
/**
* ck_standard (扣分标准) 固化类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Mapper
public interface CkStandardMapper extends BaseMapper<CkStandard>{
}

View File

@ -0,0 +1,57 @@
package com.changhu.module.assessmentCriteria.pojo.entity;
import java.io.Serial;
import java.io.Serializable;
import com.changhu.support.mybatisplus.pojo.entity.BaseEntity;
import lombok.Data;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import lombok.EqualsAndHashCode;
import com.baomidou.mybatisplus.annotation.TableName;
/**
* 考核记录 实体类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
@EqualsAndHashCode(callSuper = true)
@TableName(autoResultMap = true)
public class CkAssessmentRecord extends BaseEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 企事业单位id
*/
private Long enterprisesUnitId;
/**
* 考核项目id
*/
private Long ckProjectId;
/**
* 考核人员签字
*/
private String assessmentUserSignature;
/**
* 被考核单位人员签字
*/
private String byAssessmentEnterprisesUnitUserSignature;
/**
* 考核备注
*/
private String remark;
}

View File

@ -0,0 +1,57 @@
package com.changhu.module.assessmentCriteria.pojo.entity;
import java.io.Serial;
import java.io.Serializable;
import com.changhu.support.mybatisplus.pojo.entity.BaseEntity;
import lombok.Data;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import lombok.EqualsAndHashCode;
import com.baomidou.mybatisplus.annotation.TableName;
/**
* 考核记录明细 实体类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
@EqualsAndHashCode(callSuper = true)
@TableName(autoResultMap = true)
public class CkAssessmentRecordDetails extends BaseEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 考核记录id
*/
private Long ckAssessmentRecordId;
/**
* 考核项目id
*/
private Long ckProjectId;
/**
* 考核分组id
*/
private Long ckGroupId;
/**
* 考核项id
*/
private Long ckItemId;
/**
* 考核标准id
*/
private Long ckStandardId;
}

View File

@ -0,0 +1,52 @@
package com.changhu.module.assessmentCriteria.pojo.entity;
import java.io.Serial;
import java.io.Serializable;
import com.changhu.support.mybatisplus.pojo.entity.BaseEntity;
import lombok.Data;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import lombok.EqualsAndHashCode;
import com.baomidou.mybatisplus.annotation.TableName;
/**
* 考核组 实体类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
@EqualsAndHashCode(callSuper = true)
@TableName(autoResultMap = true)
public class CkGroup extends BaseEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 考核项目id
*/
private Long ckProjectId;
/**
* 考核组名称
*/
private String name;
/**
* 总分
*/
private Integer totalScore;
/**
* 备注信息
*/
private String remark;
}

View File

@ -0,0 +1,53 @@
package com.changhu.module.assessmentCriteria.pojo.entity;
import java.io.Serial;
import java.io.Serializable;
import com.changhu.common.db.enums.SelectType;
import com.changhu.support.mybatisplus.pojo.entity.BaseEntity;
import lombok.Data;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import lombok.EqualsAndHashCode;
import com.baomidou.mybatisplus.annotation.TableName;
/**
* 分组内的考核项 实体类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
@EqualsAndHashCode(callSuper = true)
@TableName(autoResultMap = true)
public class CkItem extends BaseEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 考核组id
*/
private Long ckGroupId;
/**
* 考核项名称
*/
private String name;
/**
* 单选或多选
*/
private SelectType type;
/**
* 备注信息
*/
private String remark;
}

View File

@ -0,0 +1,53 @@
package com.changhu.module.assessmentCriteria.pojo.entity;
import java.io.Serial;
import java.io.Serializable;
import com.changhu.common.db.enums.EnterprisesUnitType;
import com.changhu.support.mybatisplus.pojo.entity.BaseEntity;
import lombok.Data;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import lombok.EqualsAndHashCode;
import com.baomidou.mybatisplus.annotation.TableName;
/**
* 考核项目 实体类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
@EqualsAndHashCode(callSuper = true)
@TableName(autoResultMap = true)
public class CkProject extends BaseEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 考核项目名字
*/
private String name;
/**
* 类型(对应企事业单位类型)
*/
private EnterprisesUnitType type;
/**
* 总分
*/
private Integer totalScore;
/**
* 备注信息
*/
private String remark;
}

View File

@ -0,0 +1,47 @@
package com.changhu.module.assessmentCriteria.pojo.entity;
import java.io.Serial;
import java.io.Serializable;
import com.changhu.common.db.enums.SelectType;
import com.changhu.support.mybatisplus.pojo.entity.BaseEntity;
import lombok.Data;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import lombok.EqualsAndHashCode;
import com.baomidou.mybatisplus.annotation.TableName;
/**
* 扣分标准 实体类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
@EqualsAndHashCode(callSuper = true)
@TableName(autoResultMap = true)
public class CkStandard extends BaseEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 考核项id
*/
private Long ckItemId;
/**
* 条件
*/
private String name;
/**
* 扣多少分
*/
private Double deductionPoints;
}

View File

@ -0,0 +1,54 @@
package com.changhu.module.assessmentCriteria.pojo.params;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.util.List;
/**
* @author 20252
* @createTime 2024/11/7 上午11:15
* @desc AssessmentRecordParams...
*/
@Data
public class AssessmentRecordParams {
@Schema(description = "企事业单位id")
@NotNull(message = "被考核单位不能为空")
private Long enterprisesUnitId;
@Schema(description = "考核项目")
@NotNull(message = "考核项目不能为空")
private Long ckProjectId;
@Schema(description = "考核人员签字")
@NotEmpty(message = "考核人员需签字")
private String assessmentUserSignature;
@Schema(description = "被考核单位人员签字")
@NotEmpty(message = "被考核单位需人员签字")
private String byAssessmentEnterprisesUnitUserSignature;
@Schema(description = "考核备注")
private String remark;
@Valid
@Schema(description = "考核记录详情")
private List<RecordDetailParams> assessmentRecordDetails;
@Data
public static class RecordDetailParams {
@NotNull(message = "考核分组不能为空")
@Schema(description = "考核分组id")
private Long ckGroupId;
@NotNull(message = "考核项不能为空")
@Schema(description = "考核项id")
private Long ckItemId;
@NotNull(message = "考核标准不能为空")
@Schema(description = "考核标准id")
private Long ckStandardId;
}
}

View File

@ -0,0 +1,33 @@
package com.changhu.module.assessmentCriteria.pojo.params;
import com.changhu.common.db.enums.EnterprisesUnitType;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* @author 20252
* @createTime 2024/11/6 上午10:31
* @desc CkProjectSaveOrUpdateParams...
*/
@Data
public class CkGroupSaveOrUpdateParams {
@Schema(description = "考核分组id")
private Long snowFlakeId;
@Schema(description = "考核项目id")
@NotNull(message = "所属考核项目不能为空")
private Long ckProjectId;
@NotBlank(message = "考核组名不能为空")
@Schema(description = "考核组名称")
private String name;
@NotNull(message = "考核组分数不能为空")
@Schema(description = "考核组总分")
private Integer totalScore;
@Schema(description = "备注")
private String remark;
}

View File

@ -0,0 +1,33 @@
package com.changhu.module.assessmentCriteria.pojo.params;
import com.changhu.common.db.enums.SelectType;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* @author 20252
* @createTime 2024/11/6 上午11:51
* @desc CkItemSaveOrUpdateParams...
*/
@Data
public class CkItemSaveOrUpdateParams {
@Schema(description = "id")
private Long snowFlakeId;
@NotNull(message = "考核组不能为空")
@Schema(description = "考核组id")
private Long ckGroupId;
@NotBlank(message = "考核项名称不能为空")
@Schema(description = "考核项名称")
private String name;
@NotNull(message = "组件类型不能为空")
@Schema(description = "组件类型")
private SelectType type;
@Schema(description = "备注")
private String remark;
}

View File

@ -0,0 +1,35 @@
package com.changhu.module.assessmentCriteria.pojo.params;
import com.changhu.common.db.enums.EnterprisesUnitType;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.time.LocalDateTime;
/**
* @author 20252
* @createTime 2024/11/6 上午10:31
* @desc CkProjectSaveOrUpdateParams...
*/
@Data
public class CkProjectSaveOrUpdateParams {
@Schema(description = "考核项目id")
private Long snowFlakeId;
@NotBlank(message = "考核项目名不能为空")
@Schema(description = "考核项目名称")
private String name;
@NotNull(message = "单位类型不能为空")
@Schema(description = "对应企事业单位类型")
private EnterprisesUnitType type;
@NotNull(message = "考核分数不能为空")
@Schema(description = "考核总分")
private Integer totalScore;
@Schema(description = "备注")
private String remark;
}

View File

@ -0,0 +1,31 @@
package com.changhu.module.assessmentCriteria.pojo.params;
import com.changhu.common.db.enums.SelectType;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* @author 20252
* @createTime 2024/11/6 下午2:50
* @desc CkStandardSaveOrUpdateParams...
*/
@Data
public class CkStandardSaveOrUpdateParams {
@Schema(description = "考核标准id")
private Long snowFlakeId;
@NotNull
@Schema(description = "考核项id")
private Long ckItemId;
@NotBlank(message = "标准名不能为空")
@Schema(description = "标准名")
private String name;
@NotNull(message = "扣分值不能为空")
@Schema(description = "扣分值")
private Double deductionPoints;
}

View File

@ -0,0 +1,15 @@
package com.changhu.module.assessmentCriteria.pojo.queryParams;
import com.changhu.common.db.enums.EnterprisesUnitType;
import lombok.Data;
/**
* @author 20252
* @createTime 2024/11/6 上午10:09
* @desc CkProjectPagerQueryParams...
*/
@Data
public class CkProjectPagerQueryParams {
private String name;
private EnterprisesUnitType type;
}

View File

@ -0,0 +1,57 @@
package com.changhu.module.assessmentCriteria.pojo.vo;
import com.changhu.common.db.enums.SelectType;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
/**
* @author 20252
* @createTime 2024/11/7 上午10:00
* @desc 考核标准规则
*/
@Data
public class AssessmentCriteriaRuleVo {
@Schema(description = "考核组id")
private Long snowFlakeId;
@Schema(description = "考核组名称")
private String name;
@Schema(description = "考核组总成绩")
private Integer totalScore;
@Schema(description = "考核组备注")
private String remark;
@Schema(description = "考核项")
private List<Item> itemList;
@Data
public static class Item {
@Schema(description = "考核项id")
private Long snowFlakeId;
@Schema(description = "考核分组id")
private Long ckGroupId;
@Schema(description = "考核项名称")
private String name;
@Schema(description = "考核项组件类型")
private SelectType type;
@Schema(description = "考核项备注")
private String remark;
@Schema(description = "考核标准")
private List<Standard> standardList;
}
@Data
public static class Standard {
@Schema(description = "考核标准id")
private Long snowFlakeId;
@Schema(description = "考核项id")
private Long ckItemId;
@Schema(description = "考核标准名字")
private String name;
@Schema(description = "扣分值")
private Double deductionPoints;
}
}

View File

@ -0,0 +1,39 @@
package com.changhu.module.assessmentCriteria.pojo.vo;
import com.changhu.common.db.enums.SelectType;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* @author 20252
* @createTime 2024/11/6 上午11:03
* @desc CkProjectDetailTableVo...
*/
@Data
public class CkProjectDetailTableVo {
@Schema(description = "考核分组id")
private Long ckGroupId;
@Schema(description = "考核分组名字")
private String groupName;
@Schema(description = "考核分组总分")
private Integer groupTotalScore;
@Schema(description = "考核分组备注")
private String groupRemark;
@Schema(description = "考核项id")
private Long ckItemId;
@Schema(description = "考核项名字")
private String itemName;
@Schema(description = "组件类型")
private SelectType type;
@Schema(description = "考核项备注")
private String itemRemark;
@Schema(description = "考核标准id")
private Long ckStandardId;
@Schema(description = "考核标准")
private String standardName;
@Schema(description = "扣分数")
private Double deductionPoints;
}

View File

@ -0,0 +1,31 @@
package com.changhu.module.assessmentCriteria.pojo.vo;
import com.changhu.common.db.enums.EnterprisesUnitType;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
/**
* @author 20252
* @createTime 2024/11/6 上午10:05
* @desc CkProjectPagerVo...
*/
@Data
public class CkProjectPagerVo {
@Schema(description = "考核项目id")
private Long snowFlakeId;
@Schema(description = "考核项目名称")
private String name;
@Schema(description = "对应企事业单位类型")
private EnterprisesUnitType type;
@Schema(description = "考核总分")
private Integer totalScore;
@Schema(description = "备注")
private String remark;
@Schema(description = "创建时间")
private LocalDateTime createTime;
@Schema(description = "创建人名字")
private String createUserName;
}

View File

@ -0,0 +1,95 @@
package com.changhu.module.assessmentCriteria.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.changhu.common.db.enums.EnterprisesUnitType;
import com.changhu.common.pojo.vo.SelectNodeVo;
import com.changhu.module.assessmentCriteria.pojo.params.*;
import com.changhu.module.assessmentCriteria.pojo.queryParams.CkProjectPagerQueryParams;
import com.changhu.module.assessmentCriteria.pojo.vo.AssessmentCriteriaRuleVo;
import com.changhu.module.assessmentCriteria.pojo.vo.CkProjectDetailTableVo;
import com.changhu.module.assessmentCriteria.pojo.vo.CkProjectPagerVo;
import com.changhu.support.mybatisplus.pojo.params.PageParams;
import java.util.List;
/**
* @author 20252
* @createTime 2024/11/6 上午10:07
* @desc AssessmentCriteriaService...
*/
public interface AssessmentCriteriaService {
/**
* 根据类型获取考核标准列表
*
* @param type 类型
* @return 结果
*/
List<SelectNodeVo<Long>> assessmentCriteriaListByType(EnterprisesUnitType type);
/**
* 根据考核项目获取考核规则
*
* @param ckProjectId 考核项目id
* @return 结果
*/
List<AssessmentCriteriaRuleVo> assessmentCriteriaRulesByCkProjectId(Long ckProjectId);
/**
* 考核项目分页查询
*
* @param queryParams 查询参数
* @return 查询结果
*/
Page<CkProjectPagerVo> ckProjectPagerVoPager(PageParams<CkProjectPagerQueryParams, CkProjectPagerVo> queryParams);
/**
* 新增或修改考核项目
*
* @param params 参数
*/
void saveOrUpdateCkProject(CkProjectSaveOrUpdateParams params);
/**
* 删除考核项目
*
* @param ckProjectId 考核项目id
*/
void deleteCkProjectById(Long ckProjectId);
/**
* 考核项目详情
*
* @param ckProjectId 考核项目id
* @return 结果
*/
List<CkProjectDetailTableVo> ckProjectDetail(Long ckProjectId);
/**
* 新增或修改考核分组
*
* @param params 参数
*/
void saveOrUpdateCkGroup(CkGroupSaveOrUpdateParams params);
/**
* 新增或修改考核项
*
* @param params 参数
*/
void saveOrUpdateCkItem(CkItemSaveOrUpdateParams params);
/**
* 新增或修改考核标准
*
* @param params 参数
*/
void saveOrUpdateCkStandard(CkStandardSaveOrUpdateParams params);
/**
* 提交考核记录
*
* @param params 参数
*/
void submitAssessmentRecord(AssessmentRecordParams params);
}

View File

@ -0,0 +1,13 @@
package com.changhu.module.assessmentCriteria.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.changhu.module.assessmentCriteria.pojo.entity.CkAssessmentRecordDetails;
/**
* ck_assessment_record_details (考核记录明细) 服务类
* author: luozhun
* desc 由groovy脚本自动生成
*/
public interface CkAssessmentRecordDetailsService extends IService<CkAssessmentRecordDetails> {
}

View File

@ -0,0 +1,13 @@
package com.changhu.module.assessmentCriteria.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.changhu.module.assessmentCriteria.pojo.entity.CkAssessmentRecord;
/**
* ck_assessment_record (考核记录) 服务类
* author: luozhun
* desc 由groovy脚本自动生成
*/
public interface CkAssessmentRecordService extends IService<CkAssessmentRecord> {
}

View File

@ -0,0 +1,13 @@
package com.changhu.module.assessmentCriteria.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.changhu.module.assessmentCriteria.pojo.entity.CkGroup;
/**
* ck_group (考核组) 服务类
* author: luozhun
* desc 由groovy脚本自动生成
*/
public interface CkGroupService extends IService<CkGroup>{
}

View File

@ -0,0 +1,13 @@
package com.changhu.module.assessmentCriteria.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.changhu.module.assessmentCriteria.pojo.entity.CkItem;
/**
* ck_item (分组内的考核项) 服务类
* author: luozhun
* desc 由groovy脚本自动生成
*/
public interface CkItemService extends IService<CkItem> {
}

View File

@ -0,0 +1,13 @@
package com.changhu.module.assessmentCriteria.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.changhu.module.assessmentCriteria.pojo.entity.CkProject;
/**
* ck_project (考核项目) 服务类
* author: luozhun
* desc 由groovy脚本自动生成
*/
public interface CkProjectService extends IService<CkProject>{
}

View File

@ -0,0 +1,13 @@
package com.changhu.module.assessmentCriteria.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.changhu.module.assessmentCriteria.pojo.entity.CkStandard;
/**
* ck_standard (扣分标准) 服务类
* author: luozhun
* desc 由groovy脚本自动生成
*/
public interface CkStandardService extends IService<CkStandard> {
}

View File

@ -0,0 +1,215 @@
package com.changhu.module.assessmentCriteria.service.impl;
import com.changhu.common.db.enums.SelectType;
import com.changhu.common.utils.SnowFlakeIdUtil;
import com.changhu.module.assessmentCriteria.pojo.entity.*;
import com.changhu.module.assessmentCriteria.pojo.params.*;
import com.google.common.collect.Lists;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.lang.func.LambdaUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.changhu.common.db.enums.EnterprisesUnitType;
import com.changhu.common.exception.MessageException;
import com.changhu.common.pojo.vo.SelectNodeVo;
import com.changhu.module.assessmentCriteria.mapper.CkProjectMapper;
import com.changhu.module.assessmentCriteria.pojo.queryParams.CkProjectPagerQueryParams;
import com.changhu.module.assessmentCriteria.pojo.vo.AssessmentCriteriaRuleVo;
import com.changhu.module.assessmentCriteria.pojo.vo.CkProjectDetailTableVo;
import com.changhu.module.assessmentCriteria.pojo.vo.CkProjectPagerVo;
import com.changhu.module.assessmentCriteria.service.AssessmentCriteriaService;
import com.changhu.support.mybatisplus.pojo.entity.BaseEntity;
import com.changhu.support.mybatisplus.pojo.params.PageParams;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author 20252
* @createTime 2024/11/6 上午10:08
* @desc AssessmentCriteriaServiceImpl...
*/
@Service
public class AssessmentCriteriaServiceImpl implements AssessmentCriteriaService {
@Autowired
private CkProjectMapper ckProjectMapper;
@Override
public List<SelectNodeVo<Long>> assessmentCriteriaListByType(EnterprisesUnitType type) {
return Db.lambdaQuery(CkProject.class).eq(CkProject::getType, type).list()
.stream()
.map(e -> SelectNodeVo.<Long>builder()
.value(e.getSnowFlakeId())
.label(e.getName())
.extData(Dict.create()
.set(LambdaUtil.getFieldName(CkProject::getRemark), e.getRemark())
.set(LambdaUtil.getFieldName(CkProject::getTotalScore), e.getTotalScore())
.set(LambdaUtil.getFieldName(CkProject::getType), e.getType())
.set(LambdaUtil.getFieldName(CkProject::getCreateTime), e.getCreateTime())
)
.build())
.toList();
}
@Override
public List<AssessmentCriteriaRuleVo> assessmentCriteriaRulesByCkProjectId(Long ckProjectId) {
//根据考核项目拿到考核分组
List<AssessmentCriteriaRuleVo> groupList = Db.lambdaQuery(CkGroup.class)
.eq(CkGroup::getCkProjectId, ckProjectId)
.orderByAsc(BaseEntity::getCreateTime)
.list()
.stream()
.map(e -> {
AssessmentCriteriaRuleVo assessmentCriteriaRuleVo = new AssessmentCriteriaRuleVo();
assessmentCriteriaRuleVo.setSnowFlakeId(e.getSnowFlakeId());
assessmentCriteriaRuleVo.setName(e.getName());
assessmentCriteriaRuleVo.setTotalScore(e.getTotalScore());
assessmentCriteriaRuleVo.setRemark(e.getRemark());
return assessmentCriteriaRuleVo;
}).toList();
if (groupList.isEmpty()) {
throw new MessageException("该考核项目内暂未制定规则");
}
//根据考核分组拿到考核项
List<AssessmentCriteriaRuleVo.Item> itemList = Db.lambdaQuery(CkItem.class)
.in(CkItem::getCkGroupId, groupList.stream().map(AssessmentCriteriaRuleVo::getSnowFlakeId).toList())
.orderByAsc(BaseEntity::getCreateTime)
.list()
.stream()
.map(e -> {
AssessmentCriteriaRuleVo.Item item = new AssessmentCriteriaRuleVo.Item();
item.setSnowFlakeId(e.getSnowFlakeId());
item.setCkGroupId(e.getCkGroupId());
item.setName(e.getName());
item.setType(e.getType());
item.setRemark(e.getRemark());
return item;
}).toList();
if (itemList.isEmpty()) {
throw new MessageException("该考核项目内未制定考核项");
}
//根据考核项拿到考核标准
List<AssessmentCriteriaRuleVo.Standard> standardList = Db.lambdaQuery(CkStandard.class)
.in(CkStandard::getCkItemId, itemList.stream().map(AssessmentCriteriaRuleVo.Item::getSnowFlakeId).toList())
.orderByAsc(BaseEntity::getCreateTime)
.list().stream()
.map(e -> {
AssessmentCriteriaRuleVo.Standard standard = new AssessmentCriteriaRuleVo.Standard();
standard.setSnowFlakeId(e.getSnowFlakeId());
standard.setCkItemId(e.getCkItemId());
standard.setName(e.getName());
standard.setDeductionPoints(e.getDeductionPoints());
return standard;
}).toList();
if (standardList.isEmpty()) {
throw new MessageException("该考核项目内未制定考核标准");
}
//先将考核标准塞到考核项内
Map<Long, List<AssessmentCriteriaRuleVo.Standard>> standardMap = standardList.stream().collect(Collectors.groupingBy(AssessmentCriteriaRuleVo.Standard::getCkItemId));
itemList.forEach(e -> e.setStandardList(standardMap.get(e.getSnowFlakeId())));
//将考核项塞到考核分组内
Map<Long, List<AssessmentCriteriaRuleVo.Item>> itemMap = itemList.stream().collect(Collectors.groupingBy(AssessmentCriteriaRuleVo.Item::getCkGroupId));
groupList.forEach(e -> e.setItemList(itemMap.get(e.getSnowFlakeId())));
return groupList;
}
@Override
public Page<CkProjectPagerVo> ckProjectPagerVoPager(PageParams<CkProjectPagerQueryParams, CkProjectPagerVo> queryParams) {
return ckProjectMapper.pager(queryParams.getPage(), queryParams.getParams());
}
@Transactional(rollbackFor = Exception.class)
@Override
public void saveOrUpdateCkProject(CkProjectSaveOrUpdateParams params) {
boolean b = Db.saveOrUpdate(BeanUtil.copyProperties(params, CkProject.class));
if (!b) {
throw new MessageException();
}
}
@Transactional(rollbackFor = Exception.class)
@Override
public void deleteCkProjectById(Long ckProjectId) {
boolean b = Db.removeById(ckProjectId, CkProject.class);
if (!b) {
throw new MessageException();
}
}
@Override
public List<CkProjectDetailTableVo> ckProjectDetail(Long ckProjectId) {
return ckProjectMapper.ckProjectDetail(ckProjectId);
}
@Transactional(rollbackFor = Exception.class)
@Override
public void saveOrUpdateCkGroup(CkGroupSaveOrUpdateParams params) {
boolean b = Db.saveOrUpdate(BeanUtil.copyProperties(params, CkGroup.class));
if (!b) {
throw new MessageException();
}
}
@Transactional(rollbackFor = Exception.class)
@Override
public void saveOrUpdateCkItem(CkItemSaveOrUpdateParams params) {
boolean b = Db.saveOrUpdate(BeanUtil.copyProperties(params, CkItem.class));
if (!b) {
throw new MessageException();
}
}
@Transactional(rollbackFor = Exception.class)
@Override
public void saveOrUpdateCkStandard(CkStandardSaveOrUpdateParams params) {
boolean b = Db.saveOrUpdate(BeanUtil.copyProperties(params, CkStandard.class));
if (!b) {
throw new MessageException();
}
}
@Transactional(rollbackFor = Exception.class)
@Override
public void submitAssessmentRecord(AssessmentRecordParams params) {
CkAssessmentRecord ckAssessmentRecord = CkAssessmentRecord.builder()
.snowFlakeId(SnowFlakeIdUtil.snowflakeId())
.enterprisesUnitId(params.getEnterprisesUnitId())
.ckProjectId(params.getCkProjectId())
.assessmentUserSignature(params.getAssessmentUserSignature())
.byAssessmentEnterprisesUnitUserSignature(params.getByAssessmentEnterprisesUnitUserSignature())
.remark(params.getRemark())
.build();
//保存考核记录
boolean save = Db.save(ckAssessmentRecord);
if (!save) {
throw new MessageException();
}
List<AssessmentRecordParams.RecordDetailParams> assessmentRecordDetails = params.getAssessmentRecordDetails();
if (CollUtil.isEmpty(assessmentRecordDetails)) {
return;
}
//保存考核明细
boolean b = Db.saveBatch(assessmentRecordDetails.stream()
.map(e -> CkAssessmentRecordDetails.builder()
.ckAssessmentRecordId(ckAssessmentRecord.getSnowFlakeId())
.ckProjectId(ckAssessmentRecord.getCkProjectId())
.ckGroupId(e.getCkGroupId())
.ckItemId(e.getCkItemId())
.ckStandardId(e.getCkStandardId())
.build())
.toList());
if (!b) {
throw new MessageException();
}
}
}

View File

@ -0,0 +1,17 @@
package com.changhu.module.assessmentCriteria.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.changhu.module.assessmentCriteria.mapper.CkAssessmentRecordDetailsMapper;
import com.changhu.module.assessmentCriteria.pojo.entity.CkAssessmentRecordDetails;
import com.changhu.module.assessmentCriteria.service.CkAssessmentRecordDetailsService;
import org.springframework.stereotype.Service;
/**
* ck_assessment_record_details (考核记录明细) 服务实现类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Service
public class CkAssessmentRecordDetailsServiceImpl extends ServiceImpl<CkAssessmentRecordDetailsMapper, CkAssessmentRecordDetails> implements CkAssessmentRecordDetailsService {
}

View File

@ -0,0 +1,17 @@
package com.changhu.module.assessmentCriteria.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.changhu.module.assessmentCriteria.mapper.CkAssessmentRecordMapper;
import com.changhu.module.assessmentCriteria.pojo.entity.CkAssessmentRecord;
import com.changhu.module.assessmentCriteria.service.CkAssessmentRecordService;
import org.springframework.stereotype.Service;
/**
* ck_assessment_record (考核记录) 服务实现类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Service
public class CkAssessmentRecordServiceImpl extends ServiceImpl<CkAssessmentRecordMapper, CkAssessmentRecord> implements CkAssessmentRecordService {
}

View File

@ -0,0 +1,17 @@
package com.changhu.module.assessmentCriteria.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.changhu.module.assessmentCriteria.mapper.CkGroupMapper;
import com.changhu.module.assessmentCriteria.pojo.entity.CkGroup;
import com.changhu.module.assessmentCriteria.service.CkGroupService;
import org.springframework.stereotype.Service;
/**
* ck_group (考核组) 服务实现类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Service
public class CkGroupServiceImpl extends ServiceImpl<CkGroupMapper, CkGroup> implements CkGroupService {
}

View File

@ -0,0 +1,17 @@
package com.changhu.module.assessmentCriteria.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.changhu.module.assessmentCriteria.mapper.CkItemMapper;
import com.changhu.module.assessmentCriteria.pojo.entity.CkItem;
import com.changhu.module.assessmentCriteria.service.CkItemService;
import org.springframework.stereotype.Service;
/**
* ck_item (分组内的考核项) 服务实现类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Service
public class CkItemServiceImpl extends ServiceImpl<CkItemMapper, CkItem> implements CkItemService {
}

View File

@ -0,0 +1,17 @@
package com.changhu.module.assessmentCriteria.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.changhu.module.assessmentCriteria.mapper.CkProjectMapper;
import com.changhu.module.assessmentCriteria.pojo.entity.CkProject;
import com.changhu.module.assessmentCriteria.service.CkProjectService;
import org.springframework.stereotype.Service;
/**
* ck_project (考核项目) 服务实现类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Service
public class CkProjectServiceImpl extends ServiceImpl<CkProjectMapper, CkProject> implements CkProjectService {
}

View File

@ -0,0 +1,17 @@
package com.changhu.module.assessmentCriteria.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.changhu.module.assessmentCriteria.mapper.CkStandardMapper;
import com.changhu.module.assessmentCriteria.pojo.entity.CkStandard;
import com.changhu.module.assessmentCriteria.service.CkStandardService;
import org.springframework.stereotype.Service;
/**
* ck_standard (扣分标准) 服务实现类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Service
public class CkStandardServiceImpl extends ServiceImpl<CkStandardMapper, CkStandard> implements CkStandardService {
}

View File

@ -3,6 +3,7 @@ package com.changhu.module.management.pojo.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.Fastjson2TypeHandler;
import com.changhu.common.db.enums.EnterprisesUnitType;
import com.changhu.module.management.pojo.model.ContactPersonInfo;
import com.changhu.support.mybatisplus.pojo.entity.BaseEntity;
import lombok.AllArgsConstructor;
@ -10,6 +11,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import org.locationtech.jts.geom.Point;
import java.io.Serial;
import java.io.Serializable;
@ -41,6 +43,12 @@ public class EnterprisesUnit extends BaseEntity implements Serializable {
*/
private String name;
/**
* 企事业单位类型
*/
private EnterprisesUnitType type;
/**
*
*/
@ -66,6 +74,11 @@ public class EnterprisesUnit extends BaseEntity implements Serializable {
*/
private String address;
/**
* 坐标
*/
private Point point;
/**
* 联系人
*/

View File

@ -1,11 +1,13 @@
package com.changhu.module.management.pojo.params;
import com.changhu.common.db.enums.EnterprisesUnitType;
import com.changhu.module.management.pojo.model.ContactPersonInfo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.locationtech.jts.geom.Point;
import java.util.List;
@ -28,6 +30,10 @@ public class EnterprisesUnitSaveOrUpdateParams {
@NotBlank(message = "名称不能为空")
private String name;
@Schema(description = "类型")
@NotNull(message = "类型不能为空")
private EnterprisesUnitType type;
@Schema(description = "行政区划编码")
@NotEmpty(message = "行政区划不能为空")
private List<String> administrativeDivisionCodes;
@ -35,6 +41,9 @@ public class EnterprisesUnitSaveOrUpdateParams {
@Schema(description = "详细地址")
private String address;
@Schema(description = "坐标")
private Point point;
@Schema(description = "联系人")
private ContactPersonInfo contactPersonInfo;

View File

@ -1,8 +1,10 @@
package com.changhu.module.management.pojo.vo;
import com.changhu.common.db.enums.EnterprisesUnitType;
import com.changhu.module.management.pojo.model.ContactPersonInfo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.locationtech.jts.geom.Point;
/**
* @author 20252
@ -16,6 +18,9 @@ public class EnterprisesUnitPagerVo {
@Schema(description = "名字")
private String name;
@Schema(description = "类型")
private EnterprisesUnitType type;
@Schema(description = "公安单位id")
private Long policeUnitId;
@ -42,6 +47,9 @@ public class EnterprisesUnitPagerVo {
@Schema(description = "地址")
private String address;
@Schema(description = "坐标")
private Point point;
@Schema(description = "联系方式")
private ContactPersonInfo contactPersonInfo;

View File

@ -3,6 +3,8 @@ package com.changhu.module.miniProgram.controller;
import com.changhu.common.annotation.CheckUserType;
import com.changhu.common.annotation.JsonBody;
import com.changhu.common.annotation.UserType;
import com.changhu.common.pojo.vo.SelectNodeVo;
import com.changhu.module.miniProgram.pojo.vo.IndexDataStatisticsVo;
import com.changhu.module.miniProgram.pojo.vo.IndexServiceProjectListVo;
import com.changhu.module.miniProgram.service.MPoliceService;
import io.swagger.v3.oas.annotations.Operation;
@ -26,10 +28,24 @@ public class PoliceIndexController {
@Autowired
private MPoliceService policeIndexService;
@Operation(summary = "首页数据统计")
@GetMapping("/dataStatistics")
@CheckUserType(userTypes = UserType.MINI_PROGRAM_POLICE)
public IndexDataStatisticsVo dataStatistics() {
return policeIndexService.dataStatistics();
}
@Operation(summary = "获取单位内的服务项目")
@GetMapping("/getUnitServiceProjectList")
@CheckUserType(userTypes = UserType.MINI_PROGRAM_POLICE)
public List<IndexServiceProjectListVo> getUnitServiceProjectList() {
return policeIndexService.getUnitServiceProjectList();
}
@Operation(summary = "获取单位内的企事业单位列表")
@GetMapping("/getUnitEnterprisesUnitList")
@CheckUserType(userTypes = UserType.MINI_PROGRAM_POLICE)
public List<SelectNodeVo<Long>> getUnitEnterprisesUnitList() {
return policeIndexService.getUnitEnterprisesUnitList();
}
}

View File

@ -0,0 +1,21 @@
package com.changhu.module.miniProgram.pojo.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* @author 20252
* @createTime 2024/11/7 下午2:23
* @desc IndexDataStatisticsVo...
*/
@Data
public class IndexDataStatisticsVo {
@Schema(description = "企事业单位数量")
private Integer enterprisesUnitCount = 0;
@Schema(description = "服务项目数量")
private Integer serviceProjectCount = 0;
@Schema(description = "保安人员数量")
private Integer securityUserCount = 0;
@Schema(description = "无证保安人员数量")
private Integer noCardSecurityUserCount = 0;
}

View File

@ -1,6 +1,7 @@
package com.changhu.module.miniProgram.pojo.vo;
import cn.hutool.core.lang.Dict;
import com.changhu.common.db.enums.EnterprisesUnitType;
import com.changhu.common.db.enums.IsOrNot;
import com.changhu.common.db.enums.ServiceProjectType;
import com.changhu.module.management.pojo.model.ContactPersonInfo;
@ -21,6 +22,8 @@ public class IndexServiceProjectListVo {
private Long snowFlakeId;
@Schema(description = "企事业单位名称")
private String name;
@Schema(description = "单位类型")
private EnterprisesUnitType type;
@Schema(description = "省编码")
private String province;
@ -53,10 +56,15 @@ public class IndexServiceProjectListVo {
static class ServiceProjectVo {
@Schema(description = "服务项目id")
private Long snowFlakeId;
@Schema(description = "保安单位id")
private Long securityUnitId;
@Schema(description = "保安单位名字")
private String securityUnitName;
@Schema(description = "项目经理信息")
private Dict projectManagerMiniProgramUserInfo;
@Schema(description = "服务项目名称")
private String name;
@Schema(description = "服务项目类型")

View File

@ -1,5 +1,7 @@
package com.changhu.module.miniProgram.service;
import com.changhu.common.pojo.vo.SelectNodeVo;
import com.changhu.module.miniProgram.pojo.vo.IndexDataStatisticsVo;
import com.changhu.module.miniProgram.pojo.vo.IndexServiceProjectListVo;
import java.util.List;
@ -10,10 +12,26 @@ import java.util.List;
* @desc MPoliceService...
*/
public interface MPoliceService {
/**
* 首页数据统计
*
* @return 首页数据统计
*/
IndexDataStatisticsVo dataStatistics();
/**
* 获取单位内的服务项目
*
* @return 服务项目
*/
List<IndexServiceProjectListVo> getUnitServiceProjectList();
/**
* 获取单位内的企事业单位列表
*
* @return 企事业单位列表
*/
List<SelectNodeVo<Long>> getUnitEnterprisesUnitList();
}

View File

@ -1,9 +1,18 @@
package com.changhu.module.miniProgram.service.impl;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.lang.func.LambdaUtil;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.changhu.common.pojo.vo.SelectNodeVo;
import com.changhu.common.utils.UserUtil;
import com.changhu.module.management.mapper.ServiceProjectMapper;
import com.changhu.module.management.pojo.entity.EnterprisesUnit;
import com.changhu.module.management.pojo.entity.ServiceProject;
import com.changhu.module.miniProgram.pojo.entity.SecurityUser;
import com.changhu.module.miniProgram.pojo.vo.IndexDataStatisticsVo;
import com.changhu.module.miniProgram.pojo.vo.IndexServiceProjectListVo;
import com.changhu.module.miniProgram.service.MPoliceService;
import com.changhu.support.mybatisplus.pojo.entity.BaseEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -20,8 +29,61 @@ public class MPoliceServiceImpl implements MPoliceService {
@Autowired
private ServiceProjectMapper serviceProjectMapper;
@Override
public IndexDataStatisticsVo dataStatistics() {
Long unitId = UserUtil.getUnitId();
IndexDataStatisticsVo indexDataStatisticsVo = new IndexDataStatisticsVo();
List<Long> enterprisesUnitIds = Db.lambdaQuery(EnterprisesUnit.class)
.eq(EnterprisesUnit::getPoliceUnitId, unitId)
.list()
.stream().map(BaseEntity::getSnowFlakeId)
.toList();
if (enterprisesUnitIds.isEmpty()) {
return indexDataStatisticsVo;
}
indexDataStatisticsVo.setEnterprisesUnitCount(enterprisesUnitIds.size());
List<Long> serviceProjectIds = Db.lambdaQuery(ServiceProject.class)
.in(ServiceProject::getEnterprisesUnitId, enterprisesUnitIds)
.list()
.stream()
.map(BaseEntity::getSnowFlakeId)
.toList();
if (serviceProjectIds.isEmpty()) {
return indexDataStatisticsVo;
}
indexDataStatisticsVo.setServiceProjectCount(serviceProjectIds.size());
Long securityUserCount = Db.lambdaQuery(SecurityUser.class)
.in(SecurityUser::getServiceProjectId, serviceProjectIds)
.count();
indexDataStatisticsVo.setSecurityUserCount(securityUserCount.intValue());
Long noCardSecurityUserCount = Db.lambdaQuery(SecurityUser.class)
.in(SecurityUser::getServiceProjectId, serviceProjectIds)
.isNull(SecurityUser::getSecurityNumber)
.count();
indexDataStatisticsVo.setNoCardSecurityUserCount(noCardSecurityUserCount.intValue());
return indexDataStatisticsVo;
}
@Override
public List<IndexServiceProjectListVo> getUnitServiceProjectList() {
return serviceProjectMapper.getServiceProjectList(UserUtil.getUnitId(), null);
}
@Override
public List<SelectNodeVo<Long>> getUnitEnterprisesUnitList() {
return Db.lambdaQuery(EnterprisesUnit.class)
.eq(EnterprisesUnit::getPoliceUnitId, UserUtil.getUnitId())
.list()
.stream()
.map(item -> SelectNodeVo.<Long>builder()
.value(item.getSnowFlakeId())
.label(item.getName())
.extData(Dict.of(LambdaUtil.getFieldName(EnterprisesUnit::getType), item.getType()))
.build())
.toList();
}
}

View File

@ -8,9 +8,18 @@ import com.alibaba.fastjson2.support.spring6.http.converter.FastJsonHttpMessageC
import com.changhu.common.db.BaseEnum;
import com.changhu.common.properties.Fastjson2Properties;
import com.changhu.support.fastjson2.deserialze.DbEnumDeserializer;
import com.changhu.support.fastjson2.deserialze.LatitudeDeserializer;
import com.changhu.support.fastjson2.deserialze.LongitudeDeserializer;
import com.changhu.support.fastjson2.deserialze.PointDeserializer;
import com.changhu.support.fastjson2.filter.DesensitizedFilter;
import com.changhu.support.fastjson2.serializer.DbEnumSerializer;
import com.changhu.support.fastjson2.serializer.LatitudeSerializer;
import com.changhu.support.fastjson2.serializer.LongitudeSerializer;
import com.changhu.support.fastjson2.serializer.PointSerializer;
import lombok.extern.slf4j.Slf4j;
import org.geotools.measure.Latitude;
import org.geotools.measure.Longitude;
import org.locationtech.jts.geom.Point;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
@ -47,9 +56,17 @@ public class FastJson2Config {
JSON.register(clazz, DbEnumDeserializer.instance);
});
JSON.config(JSONWriter.Feature.WriteLongAsString);
JSON.register(Latitude.class, LatitudeSerializer.instance);
JSON.register(Longitude.class, LongitudeSerializer.instance);
JSON.register(Point.class, PointSerializer.instance);
//反序列化配置
JSON.register(Latitude.class, LatitudeDeserializer.instance);
JSON.register(Longitude.class, LongitudeDeserializer.instance);
JSON.register(Point.class, PointDeserializer.instance);
JSON.config(JSONWriter.Feature.WriteLongAsString);
}
@Bean

View File

@ -0,0 +1,31 @@
package com.changhu.support.fastjson2.deserialze;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.reader.ObjectReader;
import org.geotools.measure.Latitude;
import java.lang.reflect.Type;
import java.math.BigDecimal;
/**
* author: luozhun
* desc: LatitudeDeserializer
* createTime: 2023/8/26 16:10
*/
public class LatitudeDeserializer implements ObjectReader<Latitude> {
public static final LatitudeDeserializer instance = new LatitudeDeserializer();
private LatitudeDeserializer() {
}
@Override
public Latitude readObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
//读取为BigDecimal来确保精度和避免浮点数的舍入误差
BigDecimal value = jsonReader.readBigDecimal();
if (value == null) {
return null;
}
return new Latitude(value.doubleValue());
}
}

View File

@ -0,0 +1,31 @@
package com.changhu.support.fastjson2.deserialze;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.reader.ObjectReader;
import org.geotools.measure.Longitude;
import java.lang.reflect.Type;
import java.math.BigDecimal;
/**
* author: luozhun
* desc: LongitudeDeserializer
* createTime: 2023/8/26 16:15
*/
public class LongitudeDeserializer implements ObjectReader<Longitude> {
public static final LongitudeDeserializer instance = new LongitudeDeserializer();
private LongitudeDeserializer() {
}
@Override
public Longitude readObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
//读取为BigDecimal来确保精度和避免浮点数的舍入误差
BigDecimal value = jsonReader.readBigDecimal();
if (value == null) {
return null;
}
return new Longitude(value.doubleValue());
}
}

View File

@ -0,0 +1,35 @@
package com.changhu.support.fastjson2.deserialze;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.reader.ObjectReader;
import com.changhu.common.utils.GeometryUtil;
import org.locationtech.jts.geom.Point;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
* author: luozhun
* desc: PointDeserializer
* createTime: 2023/8/26 16:28
*/
public class PointDeserializer implements ObjectReader<Point> {
public static final PointDeserializer instance = new PointDeserializer();
private PointDeserializer() {
}
@Override
public Point readObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
List<BigDecimal> list = new ArrayList<>();
jsonReader.readArray(list, BigDecimal.class);
if (CollUtil.isEmpty(list)) {
return null;
}
return GeometryUtil.createPoint(list);
}
}

View File

@ -0,0 +1,30 @@
package com.changhu.support.fastjson2.serializer;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.writer.ObjectWriter;
import org.geotools.measure.Latitude;
import java.lang.reflect.Type;
/**
* author: luozhun
* desc: LatitudeSerializer
* createTime: 2023/8/26 15:44
*/
public class LatitudeSerializer implements ObjectWriter<Latitude> {
public static final LatitudeSerializer instance = new LatitudeSerializer();
private LatitudeSerializer() {
}
@Override
public void write(JSONWriter jsonWriter, Object object, Object fieldName, Type fieldType, long features) {
if (object == null) {
jsonWriter.writeNull();
return;
}
jsonWriter.writeDouble(((Latitude) object).degrees());
}
}

View File

@ -0,0 +1,30 @@
package com.changhu.support.fastjson2.serializer;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.writer.ObjectWriter;
import org.geotools.measure.Longitude;
import java.lang.reflect.Type;
/**
* author: luozhun
* desc: LongitudeSerializer
* createTime: 2023/8/26 15:46
*/
public class LongitudeSerializer implements ObjectWriter<Longitude> {
public static final LongitudeSerializer instance = new LongitudeSerializer();
private LongitudeSerializer() {
}
@Override
public void write(JSONWriter jsonWriter, Object object, Object fieldName, Type fieldType, long features) {
if (object == null) {
jsonWriter.writeNull();
return;
}
jsonWriter.writeDouble(((Longitude) object).degrees());
}
}

View File

@ -0,0 +1,45 @@
package com.changhu.support.fastjson2.serializer;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.writer.ObjectWriter;
import com.changhu.common.utils.GeometryUtil;
import org.geotools.measure.Latitude;
import org.geotools.measure.Longitude;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Point;
import java.lang.reflect.Type;
import java.util.Arrays;
/**
* author: luozhun
* desc: PointSerializer
* createTime: 2023/8/26 15:59
*/
public class PointSerializer implements ObjectWriter<Point> {
public static final PointSerializer instance = new PointSerializer();
private PointSerializer() {
}
@Override
public void write(JSONWriter jsonWriter, Object object, Object fieldName, Type fieldType, long features) {
if (object == null) {
jsonWriter.writeNull();
return;
}
Point point = (Point) object;
if (GeometryUtil.equals(GeometryUtil.emptyPoint(), point)) {
jsonWriter.writeNull();
return;
}
jsonWriter.writeAny(
Arrays.asList(
new Longitude(point.getCoordinate().getOrdinate(Coordinate.X)).degrees(),
new Latitude(point.getCoordinate().getOrdinate(Coordinate.Y)).degrees()
)
);
}
}

View File

@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionIntercepto
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.changhu.support.mybatisplus.interceptor.CustomDataPermissionHandler;
import com.changhu.support.mybatisplus.interceptor.GeometryInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -30,6 +31,8 @@ public class CustomMybatisPlusConfig {
interceptor.addInnerInterceptor(paginationInterceptor(DbType.MYSQL));
// sql性能规范
// interceptor.addInnerInterceptor(new IllegalSQLInnerInterceptor());
// 地理位置支持 配合
interceptor.addInnerInterceptor(new GeometryInnerInterceptor());
interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
//乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());

View File

@ -0,0 +1,13 @@
package com.changhu.support.mybatisplus.handler.global.geo;
import org.apache.ibatis.type.BaseTypeHandler;
import org.locationtech.jts.geom.Geometry;
/**
* author: luozhun
* desc: GeometryTypeHandler
* createTime: 2023/8/25 17:59
*/
public abstract class AbstractGeometryTypeHandler<T extends Geometry> extends BaseTypeHandler<T> {
}

View File

@ -0,0 +1,55 @@
package com.changhu.support.mybatisplus.handler.global.geo;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.changhu.common.utils.GeometryUtil;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.locationtech.jts.geom.Point;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* author: luozhun
* desc: PointTypeHandler
* createTime: 2023/8/26 13:17
*/
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(Point.class)
public class PointTypeHandler extends AbstractGeometryTypeHandler<Point> {
@Override
public void setNonNullParameter(PreparedStatement preparedStatement, int i, Point point, JdbcType jdbcType) throws SQLException {
preparedStatement.setString(i, point.toText());
}
@Override
public Point getNullableResult(ResultSet resultSet, String s) throws SQLException {
return createPoint(resultSet.getString(s), resultSet.getBytes(s));
}
@Override
public Point getNullableResult(ResultSet resultSet, int i) throws SQLException {
return createPoint(resultSet.getString(i), resultSet.getBytes(i));
}
@Override
public Point getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
return createPoint(callableStatement.getString(i), callableStatement.getBytes(i));
}
public Point createPoint(String pointStr, byte[] pointBytes) {
if (JSONUtil.isTypeJSON(pointStr)) {
return GeometryUtil.createGeometryFromGeoJson(pointStr, Point.class);
}
if (StrUtil.startWithIgnoreCase(pointStr, ClassUtil.getClassName(Point.class, true))) {
return GeometryUtil.createGeometryFromWkt(pointStr, Point.class);
}
return GeometryUtil.createPoint(pointBytes);
}
}

View File

@ -0,0 +1,133 @@
package com.changhu.support.mybatisplus.interceptor;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.locationtech.jts.geom.*;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static com.changhu.common.utils.GeometryUtil.ST_GeomFromText;
/**
* @author 20252
* @createTime 2024/6/6 下午4:32
* @desc 注意!!!此拦截器只针对mp提供的基本构造方法管用 可以进行参数对象拦截 如果是xml请自行添加ST_GeomFromText函数
*/
@Slf4j
public class GeometryInnerInterceptor extends JsqlParserSupport implements InnerInterceptor {
public static final List<Class<? extends Geometry>> GEOMETRY_CLASS_LIST = CollUtil.newArrayList(
Point.class,
MultiPoint.class,
Polygon.class,
MultiPolygon.class,
LineString.class,
MultiLineString.class
);
public GeometryInnerInterceptor() {
}
@Override
public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh);
MappedStatement ms = mpSh.mappedStatement();
//sql类型INSERT UPDATE DELETE
SqlCommandType sct = ms.getSqlCommandType();
//mp参数
Object parameter = mpSh.parameterHandler().getParameterObject();
//参数对象
Object object = null;
//获取参数的属性
switch (sct) {
case UPDATE:
try {
object = BeanUtil.beanToMap(parameter).get(Constants.ENTITY);
} catch (Exception ignored) {
}
break;
case INSERT:
object = parameter;
break;
}
//如果没有参数 就不进行sql修改
if (object == null) {
return;
}
//获取 parameter 对象 中有关 geometry 的属性名对应
List<String> geoFields = this.getGeoFields(object);
//如果没有geometry字段 就不进行sql修改
if (geoFields.isEmpty()) {
return;
}
//获取原始sql
BoundSql boundSql = ms.getBoundSql(parameter);
//UPDATE geo_test SET update_by=?,update_time=?,delete_flag=1 WHERE id=? AND delete_flag=0
String originalSql = StrUtil.removeAllLineBreaks(boundSql.getSql());
switch (sct) {
case UPDATE:
for (String geometryField : geoFields) {
String regex = geometryField + "\\s*=\\s*\\?";
originalSql = ReUtil.replaceAll(originalSql, regex, StrUtil.format("{}={}", geometryField, ST_GeomFromText));
}
break;
case INSERT:
for (String geometryField : geoFields) {
originalSql = this.replaceFindGeo(originalSql, geometryField);
}
break;
}
PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql();
//修改sql
mpBs.sql(originalSql);
}
private String replaceFindGeo(String originalSql, String geometryField) {
List<String> split = StrUtil.split(originalSql, geometryField);
//找出geo字段在sql中的位置
int geometryFieldIndex = StrUtil.count(split.get(0), ",");
StringBuilder stringBuffer = new StringBuilder();
Matcher matcher = Pattern.compile("\\?").matcher(originalSql);
int count = 0;
while (matcher.find()) {
if (count == geometryFieldIndex) {
matcher.appendReplacement(stringBuffer, ST_GeomFromText);
break;
}
count++;
}
matcher.appendTail(stringBuffer);
return stringBuffer.toString();
}
/**
* 获取对象中的geo字段
*/
private List<String> getGeoFields(Object object) {
return Arrays.stream(ReflectUtil.getFields(object.getClass()))
.filter(field -> GEOMETRY_CLASS_LIST.contains(field.getType()))
.map(Field::getName)
.collect(Collectors.toList());
}
}

View File

@ -131,6 +131,9 @@
<logger name="com.changhu.module.miniProgram.mapper">
<appender-ref ref="MpConsole"/>
</logger>
<logger name="com.changhu.module.assessmentCriteria.mapper">
<appender-ref ref="MpConsole"/>
</logger>
<!--spring日志-->
<logger name="org.springframework" level="DEBUG"/>
<!--建立一个默认的root的logger -->

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.changhu.module.assessmentCriteria.mapper.CkProjectMapper">
<select id="pager" resultType="com.changhu.module.assessmentCriteria.pojo.vo.CkProjectPagerVo">
select cp.*, msu.name as 'createUserName'
from ck_project cp
left join management_super_user msu on cp.create_by = msu.snow_flake_id
where cp.delete_flag = 0
<if test="params.name != null and params.name != ''">
and cp.name like concat('%',#{params.name},'%')
</if>
<if test="params.type != null">
and cp.type = #{params.type.value}
</if>
order by cp.create_time desc
</select>
<select id="ckProjectDetail"
resultType="com.changhu.module.assessmentCriteria.pojo.vo.CkProjectDetailTableVo">
select cg.snow_flake_id as 'ckGroupId',
cg.name as 'groupName',
cg.total_score as 'groupTotalScore',
cg.remark as 'groupRemark',
ci.snow_flake_id as 'ckItemId',
ci.name as 'itemName',
ci.type,
ci.remark as 'itemRemark',
cs.snow_flake_id as 'ckStandardId',
cs.`name` as 'standardName',
cs.deduction_points
from ck_project cp
left join ck_group cg on cp.snow_flake_id = cg.ck_project_id and cg.delete_flag = 0
left join ck_item ci on cg.snow_flake_id = ci.ck_group_id and ci.delete_flag = 0
left join ck_standard cs on ci.snow_flake_id = cs.ck_item_id and cs.delete_flag = 0
where cp.delete_flag = 0
and cp.snow_flake_id = #{ckProjectId}
</select>
</mapper>

View File

@ -49,6 +49,7 @@
JSON_ARRAYAGG(JSON_OBJECT(
'snowFlakeId', sp.snow_flake_id,
'securityUnitId',sp.security_unit_id,
'securityUnitName',su.name,
'name', sp.name,
'type', sp.type,
'isRecruitSecurity', sp.is_recruit_security,
@ -65,6 +66,7 @@
'remark', sp.remark)) as 'service_project_list'
from enterprises_unit eu
join service_project sp on eu.snow_flake_id = sp.enterprises_unit_id and sp.delete_flag = 0
left join security_unit su on sp.security_unit_id = su.snow_flake_id and su.delete_flag = 0
left join mini_program_user mpu on sp.project_manager_mini_program_user_id = mpu.snow_flake_id and mpu.delete_flag = 0
left join administrative_division ad1 on eu.province = ad1.code and ad1.delete_flag = 0
left join administrative_division ad2 on eu.city = ad2.code and ad2.delete_flag = 0

View File

@ -14,3 +14,8 @@ VITE_APP_RSA_PUBLIC_KEY=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJps/EXxxSpEM1Ix4R
# minio
VITE_APP_MINIO_URL=http://118.253.177.137:9000
VITE_APP_MINIO_BUCKET=police-security-dev
# 高德
VITE_APP_GAODE_KEY=f379a3f860a68d7438526275d6a94b05
VITE_APP_GAODE_VERSION=2.0
VITE_APP_SECURITY_JS_CODE=432125a0f8d8cad2dac38b77d6f6728f

View File

@ -14,3 +14,8 @@ VITE_APP_RSA_PUBLIC_KEY=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpu1C3JHZ+Ng/eVVCZ
# minio
VITE_APP_MINIO_URL=https://www.hnjinglian.cn:9002
VITE_APP_MINIO_BUCKET=police-security
# 高德
VITE_APP_GAODE_KEY=f379a3f860a68d7438526275d6a94b05
VITE_APP_GAODE_VERSION=2.0
VITE_APP_SECURITY_JS_CODE=432125a0f8d8cad2dac38b77d6f6728f

View File

@ -10,6 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
"@amap/amap-jsapi-loader": "^1.0.1",
"@vueuse/core": "^11.0.3",
"ant-design-vue": "^4.2.3",
"axios": "^1.7.5",
@ -24,6 +25,7 @@
"vue-uuid": "^3.0.0"
},
"devDependencies": {
"@amap/amap-jsapi-types": "^0.0.15",
"@types/lodash-es": "^4.17.8",
"@types/node": "^22.5.1",
"@vitejs/plugin-vue": "^5.1.2",

View File

@ -0,0 +1,57 @@
<template>
<div :id="mapId" class="mapContainer">
<slot></slot>
</div>
</template>
<script setup lang="ts">
import {onMounted, onUnmounted, shallowRef} from "vue";
import {initMap} from "@/utils/aMapUtil";
const props = withDefaults(defineProps<{
plugins?: string[],
initCallback?: (map: AMap.Map) => void,
mapOptions?: AMap.MapOptions
}>(), {
plugins: () => {
return []
},
mapOptions: () => {
return {
// 3D
viewMode: "3D",
//
zoom: 11,
mapStyle: 'amap://styles/darkblue'
}
}
})
const mapId = "mapContainer"
const map = shallowRef<AMap.Map>(null);
defineExpose({
mapInstance: map
})
onMounted(() => {
initMap(props.plugins).then(AMap => {
map.value = new AMap.Map(mapId, props.mapOptions)
props.initCallback && props.initCallback(map.value)
})
})
onUnmounted(() => {
map.value?.destroy()
})
</script>
<style scoped lang="scss">
#mapContainer {
padding: 0;
margin: 0;
width: 100%;
height: 100%;
}
</style>

View File

@ -19,7 +19,6 @@
>
<template #icon>
<icon-font :font-class="item.icon"/>
<!-- <icon-font font-class="icon-guanlianbaoan" type="class" size="10"/>-->
</template>
<span class="margin-left-xs">{{ item.title }}</span>
</a-menu-item>

View File

@ -1,11 +1,9 @@
<template>
<a-cascader
v-model:value="modelValue"
:placeholder="placeholder"
:change-on-select="changeOnSelect"
:options="administrativeDivisionTree"
:load-data="loadData"
:allow-clear="allowClear"
v-bind="props"
/>
</template>
@ -14,18 +12,14 @@ import api from "@/axios";
import {onMounted, ref} from "vue";
import {CascaderProps} from "ant-design-vue";
import {isEmpty} from "lodash-es";
import {AdministrativeDivisionTreeProps} from "@/types/components/tree";
withDefaults(defineProps<{
placeholder?: string,
changeOnSelect?: boolean
allowClear?: boolean
}>(), {
const props = withDefaults(defineProps<AdministrativeDivisionTreeProps>(), {
placeholder: '请选择行政区划',
changeOnSelect: true,
allowClear: true
allowClear: true,
})
const modelValue = defineModel('value', {
default: []
})

View File

@ -8,6 +8,8 @@ type DictType =
| 'Sex'
| 'ServiceProjectType'
| 'MiniProgramUserIdentity'
| 'EnterprisesUnitType'
| 'SelectType'
export const initDict = () => {
api.get<Record<DictType, SelectNodeVo<any>[]>>('/common/enums').then(resp => {

View File

@ -21,13 +21,23 @@ export const SYSTEM_MENUS: SystemMenu[] = [
type: 'dir',
children: [
{
title: '公安单位',
name: 'policeUnit',
path: '/policeUnit',
title: '公安',
name: 'police',
path: '/police',
type: 'dir',
children: [{
title: '单位管理',
name: 'policeUnitManage',
path: '/police/unitManage',
type: 'menu',
// icon: 'icon-policeman-full',
// size: '16',
component: () => import('@/views/unitManage/policeUnit/index.vue')
component: () => import('@/views/unitManage/police/unitManage/index.vue')
}, {
title: '考核标准',
name: 'policeAssessmentCriteria',
path: '/police/assessmentCriteria',
type: 'menu',
component: () => import('@/views/unitManage/police/assessmentCriteria/index.vue')
}]
}, {
title: '保安单位',
name: 'securityUnit',
@ -36,5 +46,12 @@ export const SYSTEM_MENUS: SystemMenu[] = [
component: () => import('@/views/unitManage/securityUnit/index.vue')
}
]
}, {
title: '数据总览',
name: 'dataOverview',
path: '/dataOverview',
type: 'menu',
isFull: true,
component: () => import('@/views/data/dataOverview.vue')
}
]

View File

@ -13,6 +13,8 @@ import router from "@/router";
// pinia stores
import pinia from "@/stores";
import {initDict} from "@/config/dict.ts";
//高德类型声明文件
import "@amap/amap-jsapi-types";
initDict();

View File

@ -2,17 +2,31 @@ import {RouteRecordRaw} from "vue-router";
import {SYSTEM_MENUS} from "@/config";
import {SystemMenu} from "@/types/config";
const routerClassify: Record<'layout' | 'full', RouteRecordRaw[]> = {
layout: [],
full: []
}
/**
*
*/
const extractMenuToRouter = (): RouteRecordRaw[] => {
const result: RouteRecordRaw[] = []
const extractMenuToRouter = () => {
const traverse = (data: SystemMenu[]) => {
data.forEach(item => {
if (item.type === 'dir' && item.children && item.children.length > 0) {
traverse(item.children)
} else {
result.push({
if (!item.isFull) {
routerClassify.layout.push({
path: item.path,
name: item.name,
meta: {
title: item.title
},
component: item.component
} as RouteRecordRaw)
} else {
routerClassify.full.push({
path: item.path,
name: item.name,
meta: {
@ -21,14 +35,14 @@ const extractMenuToRouter = (): RouteRecordRaw[] => {
component: item.component
} as RouteRecordRaw)
}
}
})
}
traverse(SYSTEM_MENUS)
return result;
}
extractMenuToRouter()
export const staticRouter: RouteRecordRaw[] = [
{
path: '/login',
@ -45,8 +59,10 @@ export const staticRouter: RouteRecordRaw[] = [
name: 'layout',
redirect: '/index',
component: () => import("@/components/layout/Layout.vue"),
children: extractMenuToRouter()
}, {
children: routerClassify.layout
},
...routerClassify.full,
{
path: '/test',
name: 'test',
component: () => import("@/views/test.vue"),

View File

@ -0,0 +1,7 @@
export interface AdministrativeDivisionTreeProps {
placeholder?: string,
changeOnSelect?: boolean
allowClear?: boolean
onChange?: (value: (string | number[]), selectedOptions: TreeNodeVo<string | number>[]) => void
displayRender?: (opt: { labels: string[], selectedOptions: TreeNodeVo<string | number>[] }) => string
}

View File

@ -4,6 +4,7 @@ export interface SystemMenu {
type: 'dir' | 'menu';
title: string;
path: string;
isFull?: boolean;
name: string;
icon?: string;

View File

@ -0,0 +1,90 @@
import {BaseTableRowRecord} from "@/types/components/table";
export interface CkProjectPagerVo extends BaseTableRowRecord {
name: string;
type: BaseEnum<string>
totalScore: number
remark: string;
}
export interface CkProjectPagerQueryParams {
name: string;
type: string
}
export interface SaveOrUpdateCkProjectParams {
/*考核项目id */
snowFlakeId?: string;
/*考核项目名称 */
name: string;
/*对应企事业单位类型,可用值:school,hospital,community,bank */
type: string;
/*考核总分 */
totalScore: number;
/*备注 */
remark?: string;
}
export interface SaveOrUpdateCkGroupParams {
/*考核分组id */
snowFlakeId?: string;
/*考核项目id */
ckProjectId?: string;
/*考核组名称 */
name: string;
/*考核组总分 */
totalScore: number;
/*备注 */
remark?: string;
}
export interface SaveOrUpdateCkItemParams {
/*id */
snowFlakeId?: string;
/*考核组id */
ckGroupId: string;
/*考核项名称 */
name: string;
/*组件类型,可用值:RADIO,MULTIPLE */
type: string;
/*备注 */
remark?: string;
}
export interface SaveOrUpdateCkStandardParams {
/*考核标准id */
snowFlakeId?: string;
/*考核项id */
ckItemId: string;
/*标准名 */
name: string;
/*扣分值 */
deductionPoints: number;
}
export interface CkProjectDetailRes {
/*考核分组id */
ckGroupId: string;
groupRowSpan: number;
/*考核分组名字 */
groupName: string;
/*考核分组总分 */
groupTotalScore: number;
/*考核分组备注 */
groupRemark: string;
/*考核项id */
ckItemId: string;
itemRowSpan: number;
/*考核项名字 */
itemName: string;
/*考核项备注 */
itemRemark: string;
/*考核标准id */
ckStandardId: string;
/*考核标准条件 */
standardName: string;
/*扣分数 */
deductionPoints: number;
/*选择类型,可用值:RADIO,MULTIPLE */
type: BaseEnum<string>;
}

View File

@ -55,6 +55,7 @@ export interface EnterprisesUnitPagerQueryParams {
export interface EnterprisesUnitPagerVo extends BaseTableRowRecord {
/** 名字 **/
name?: string;
type: BaseEnum<string>
/** 公安单位id **/
policeUnitId: string;
/** 省编码 **/
@ -75,6 +76,7 @@ export interface EnterprisesUnitPagerVo extends BaseTableRowRecord {
streetName?: string;
/** 地址 **/
address?: string;
point: [number, number]
/** 联系方式 **/
contactPersonInfo?: {
name: string;
@ -91,10 +93,13 @@ export interface EnterprisesUnitSaveOrUpdateParams {
policeUnitId: string;
/** 名称 **/
name: string;
/** 类型 **/
type: string;
/** 行政区划编码 **/
administrativeDivisionCodes: string[];
/** 详细地址 **/
address?: string;
point?: [number, number]
/** 联系人 **/
contactPersonInfo?: {
name: string;

View File

@ -0,0 +1,18 @@
import AMapLoader from "@amap/amap-jsapi-loader";
type Amap = typeof AMap;
export const initMap = (plugins?: string[]): Promise<Amap> => new Promise((resolve, reject) => {
//@ts-ignore
window._AMapSecurityConfig = {
securityJsCode: __APP_ENV.VITE_APP_SECURITY_JS_CODE
}
AMapLoader.load({
key: __APP_ENV.VITE_APP_GAODE_KEY,
version: __APP_ENV.VITE_APP_GAODE_VERSION,
plugins
}).then((AMap: Amap) => {
resolve(AMap)
}).catch(err => {
reject(err)
})
})

View File

@ -0,0 +1,13 @@
<template>
<div style="width: 100vw;height: 100vh">
<map-container/>
</div>
</template>
<script setup lang="ts">
import MapContainer from "@/components/aMap/MapContainer.vue";
</script>
<style scoped lang="scss">
</style>

View File

@ -1,13 +1,4 @@
<template>
<administrative-division-tree style="width: 500px" :value='[ "430000"]'/>
</template>
<script setup lang="ts">
import AdministrativeDivisionTree from "@/components/tree/AdministrativeDivisionTree.vue";
const objUrl = "/police-security/2024/10/30/55f99091b88c4c80ab90036d2b4914c6.jpg";
<script lang="ts" setup>
</script>
<style scoped lang="scss">
</style>

View File

@ -0,0 +1,188 @@
import {
CkProjectDetailRes,
SaveOrUpdateCkGroupParams,
SaveOrUpdateCkItemParams, SaveOrUpdateCkProjectParams, SaveOrUpdateCkStandardParams
} from "@/types/views/unitManage/police/assessmentCriteria.ts";
import {deleteDataModal, submitSimpleFormModal} from "@/components/tsx/ModalPro.tsx";
import api from "@/axios";
import {message} from "ant-design-vue";
import {dictSelectNodes} from "@/config/dict.ts";
export const saveOrUpdateCkProject = (params: SaveOrUpdateCkProjectParams = {
name: '',
totalScore: 100,
remark: '',
type: 'school'
}, callback: Function) => {
submitSimpleFormModal<SaveOrUpdateCkProjectParams>({
title: params.snowFlakeId ? `编辑【${params.name}` : '添加考核项目',
formParams: params,
formOptions: {
name: {
type: 'input',
label: '考核项目名称',
required: true
},
type: {
type: 'select',
label: '考核类型',
required: true,
options: dictSelectNodes('EnterprisesUnitType')
},
totalScore: {
type: 'inputNumber',
label: '总分',
required: true,
componentsProps: {
precision: 0
}
},
remark: {
type: 'inputTextArea',
label: '备注'
}
},
submit: async (params) => {
const resp = await api.post('/assessmentCriteria/saveOrUpdateCkProject', params)
message.success(resp.message)
callback && callback()
}
})
}
export const deleteCkProjectById = (name: string, ckProjectId: string, callback: Function) => {
deleteDataModal(name, async () => {
const resp = await api.delete('/assessmentCriteria/deleteCkProjectById', {
ckProjectId
})
message.success(resp.message)
callback && callback();
})
}
export const ckProjectDetail = async (ckProjectId: string): Promise<CkProjectDetailRes[]> => {
const {data} = await api.get<CkProjectDetailRes[]>('/assessmentCriteria/ckProjectDetail', {ckProjectId})
const groupRowSpan: Record<string, { firstIndex: number, count: number }> = {}
const itemRowSpan: Record<string, { firstIndex: number, count: number }> = {}
data.forEach((item, index) => {
//如果第一次没有值
if (item.ckGroupId) {
if (!groupRowSpan[item.ckGroupId]) {
groupRowSpan[item.ckGroupId] = {count: 1, firstIndex: index}
} else {
groupRowSpan[item.ckGroupId].count++;
data[index].groupRowSpan = 0
}
}
if (item.ckItemId) {
if (!itemRowSpan[item.ckItemId]) {
itemRowSpan[item.ckItemId] = {count: 1, firstIndex: index}
} else {
itemRowSpan[item.ckItemId].count++;
data[index].itemRowSpan = 0
}
}
})
Object.values(groupRowSpan).forEach(({count, firstIndex}) => {
data[firstIndex].groupRowSpan = count;
})
Object.values(itemRowSpan).forEach(({count, firstIndex}) => {
data[firstIndex].itemRowSpan = count;
})
return data
}
export const saveOrUpdateCkGroup = (params: SaveOrUpdateCkGroupParams, callback: Function) => {
submitSimpleFormModal<SaveOrUpdateCkGroupParams>({
title: params.snowFlakeId ? `编辑【${params.name}` : '添加考核分组',
formParams: params,
formOptions: {
name: {
type: 'input',
label: '分组名字',
required: true
},
totalScore: {
type: 'inputNumber',
label: '分组总分',
required: true,
componentsProps: {
precision: 0
}
},
remark: {
type: 'inputTextArea',
label: '备注'
}
},
submit: async (params) => {
const resp = await api.post('/assessmentCriteria/saveOrUpdateCkGroup', params)
message.success(resp.message)
callback && callback()
}
})
}
export const saveOrUpdateCkItem = (params: SaveOrUpdateCkItemParams, callback: Function) => {
submitSimpleFormModal<SaveOrUpdateCkItemParams>({
title: params.snowFlakeId ? `编辑【${params.name}` : '添加考核项',
formParams: params,
formOptions: {
name: {
type: 'input',
label: '考核项',
required: true
},
type: {
type: 'radioGroup',
label: '控件类型',
required: true,
options: dictSelectNodes('SelectType')
},
remark: {
type: 'inputTextArea',
label: '备注'
}
},
submit: async (params) => {
const resp = await api.post('/assessmentCriteria/saveOrUpdateCkItem', params)
message.success(resp.message)
callback && callback()
}
})
}
export const saveOrUpdateCkStandard = (params: SaveOrUpdateCkStandardParams, callback: Function) => {
submitSimpleFormModal<SaveOrUpdateCkStandardParams>({
title: params.snowFlakeId ? `编辑【${params.name}` : '添加考核标准',
formParams: params,
formOptions: {
name: {
type: 'input',
label: '标准',
required: true
},
deductionPoints: {
type: 'inputNumber',
label: '扣分值',
required: true,
componentsProps: {
precision: 1
}
}
},
submit: async (params) => {
const resp = await api.post('/assessmentCriteria/saveOrUpdateCkStandard', params)
message.success(resp.message)
callback && callback()
}
})
}

View File

@ -0,0 +1,284 @@
<template>
<div>
<TableProMax
ref="ckProjectTableRef"
:request-api="ckProjectPagerVoPager"
:search-form-options="ckProjectTableSearchOptions"
:columns="ckProjectTableColumns"
>
<template #tableHeader>
<a-space>
<a-button class="btn-success"
@click="saveOrUpdateCkProject(undefined,ckProjectTableRef?.requestGetTableData)">添加考核项目
</a-button>
</a-space>
</template>
</TableProMax>
</div>
</template>
<script setup lang="tsx">
import {TableProMaxProps} from "@/types/components/table";
import {
CkProjectDetailRes,
CkProjectPagerQueryParams,
CkProjectPagerVo
} from "@/types/views/unitManage/police/assessmentCriteria.ts";
import TableProMax from "@/components/table/TableProMax.vue";
import api from "@/axios";
import {ref} from "vue";
import {ComponentExposed} from "vue-component-type-helpers";
import {dictSelectNodes} from "@/config/dict.ts";
import {deleteDataModal} from "@/components/tsx/ModalPro.tsx";
import {message, Modal} from "ant-design-vue";
import {ColumnsType} from "ant-design-vue/es/table";
import {
ckProjectDetail,
deleteCkProjectById,
saveOrUpdateCkGroup,
saveOrUpdateCkItem,
saveOrUpdateCkProject,
saveOrUpdateCkStandard
} from "@/views/unitManage/police/assessmentCriteria/index.ts";
type CkProjectTableProps = TableProMaxProps<CkProjectPagerVo, CkProjectPagerQueryParams>
const ckProjectTableRef = ref<ComponentExposed<typeof TableProMax>>(null)
const ckProjectPagerVoPager: CkProjectTableProps['requestApi'] = (params) => {
return api.post('/assessmentCriteria/ckProjectPagerVoPager', params)
}
const ckProjectTableSearchOptions: CkProjectTableProps['searchFormOptions'] = {
name: {
type: 'input',
label: '名字'
},
type: {
type: 'select',
label: '类型',
options: [{
value: null,
label: '全部'
}, ...dictSelectNodes('EnterprisesUnitType')]
}
}
const ckProjectTableColumns: CkProjectTableProps['columns'] = [
{
dataIndex: 'name',
title: '考核项目'
}, {
dataIndex: 'type',
title: '类型',
customRender: ({text}) => text?.label
}, {
dataIndex: 'totalScore',
title: '考核总分'
}, {
dataIndex: 'remark',
title: '备注'
}, {
dataIndex: 'createUserName',
title: '创建人'
}, {
dataIndex: 'createTime',
title: '创建时间'
}, {
dataIndex: 'opt',
title: '操作',
customRender: ({record}) => {
return <a-space>
<a-button class="btn-warn" onClick={() => saveOrUpdateCkProject({
snowFlakeId: record.snowFlakeId,
name: record.name,
totalScore: record.totalScore,
remark: record.remark,
type: record.type.value
}, ckProjectTableRef.value?.requestGetTableData)}>编辑
</a-button>
<a-button class="btn-danger"
onClick={() => deleteCkProjectById(record.name, record.snowFlakeId, ckProjectTableRef.value?.requestGetTableData)}>删除
</a-button>
<a-button class="btn-purple" onClick={() => {
const dataSource = ref<CkProjectDetailRes[]>([])
const initData = async () => dataSource.value = await ckProjectDetail(record.snowFlakeId);
const ckProjectDetailTableColumns: ColumnsType<CkProjectDetailRes> = [
{
dataIndex: 'groupName',
title: '考核分组',
customCell: (_record) => {
return {
rowspan: _record.groupRowSpan
}
},
customRender: ({record: _record}) => {
return <div class={'flex-justify-between'}>
<div>
<p>{_record.groupName}({_record.groupTotalScore})</p>
<p>{_record.groupRemark}</p>
</div>
<div class="flex-column-center">
<a-dropdown trigger={['click']} v-slots={{
overlay: () => <a-menu>
<a-menu-item key="0">
<a-button type="text" style={{color: 'green'}} onClick={() => saveOrUpdateCkItem({
ckGroupId: _record.ckGroupId,
name: "",
type: 'radio'
}, initData)}>添加考核项
</a-button>
</a-menu-item>
<a-menu-item key="1">
<a-button type="text" style={'color:rgb(251, 177, 27)'} onClick={() => saveOrUpdateCkGroup({
snowFlakeId: _record.ckGroupId,
ckProjectId: record.snowFlakeId,
name: _record.groupName,
totalScore: _record.groupTotalScore,
remark: _record.groupRemark
}, initData)}>编辑
</a-button>
</a-menu-item>
<a-menu-item key="3">
<a-button type="text" style={'color:red'}
onClick={() => deleteDataModal(_record.groupName, async () => {
const resp = await api.delete('/assessmentCriteria/deleteCkGroupById', {ckGroupId: _record.ckGroupId}, {loading: true})
message.success(resp.message)
await initData()
})}>删除
</a-button>
</a-menu-item>
</a-menu>
}}>
<a class="ant-dropdown-link">
操作
</a>
</a-dropdown>
</div>
</div>
}
}, {
dataIndex: 'itemName',
title: '考核项',
customCell: (_record) => {
return {
rowspan: _record.itemRowSpan
}
},
customRender: ({record: _record}) => {
if (!_record.ckItemId) {
return '/'
}
return <div class="flex-justify-between">
<p>{_record.itemName}({_record.type?.label})
</p>
<a-dropdown trigger={['click']} v-slots={{
overlay: () => <a-menu>
<a-menu-item key="0">
<a-button type="text" style={{color: 'green'}} onClick={() => saveOrUpdateCkStandard({
ckItemId: _record.ckItemId,
name: '',
deductionPoints: 0
}, initData)}>
添加考核标准
</a-button>
</a-menu-item>
<a-menu-item key="1">
<a-button type="text" style={'color:rgb(251, 177, 27)'} onClick={() => saveOrUpdateCkItem({
snowFlakeId: _record.ckItemId,
ckGroupId: _record.ckGroupId,
name: _record.itemName,
type: _record.type.value,
remark: _record.itemRemark
}, initData)}>编辑
</a-button>
</a-menu-item>
<a-menu-item key="3">
<a-button type="text" style={'color:red'}
onClick={() => deleteDataModal(_record.itemName, async () => {
const resp = await api.delete('/assessmentCriteria/deleteCkItemById', {ckItemId: _record.ckItemId}, {loading: true})
message.success(resp.message)
await initData()
})}>删除
</a-button>
</a-menu-item>
</a-menu>
}}>
<a class="ant-dropdown-link">
操作
</a>
</a-dropdown>
</div>
}
}, {
dataIndex: 'standardName',
title: '标准',
customRender: ({record: _record}) => {
if (!_record.ckStandardId) {
return '/'
}
return <div class="flex-justify-between">
<p>{_record.standardName}{_record.deductionPoints}</p>
<a-dropdown trigger={['click']} v-slots={{
overlay: () => <a-menu>
<a-menu-item key="1">
<a-button type="text" style={'color:rgb(251, 177, 27)'} onClick={() => saveOrUpdateCkStandard({
snowFlakeId: _record.ckStandardId,
ckItemId: _record.ckItemId,
name: _record.standardName,
deductionPoints: _record.deductionPoints
}, initData)}>编辑
</a-button>
</a-menu-item>
<a-menu-item key="3">
<a-button type="text" style={'color:red'}
onClick={() => deleteDataModal(_record.itemName, async () => {
const resp = await api.delete('/assessmentCriteria/deleteCkStandardById', {ckStandardId: _record.ckStandardId}, {loading: true})
message.success(resp.message)
await initData()
})}>删除
</a-button>
</a-menu-item>
</a-menu>
}}>
<a class="ant-dropdown-link">
操作
</a>
</a-dropdown>
</div>
}
}
]
initData();
Modal.info({
title: `${record.name}】详情`,
icon: ' ',
width: '80%',
centered: true,
content: () => <div style={{height: '80vh', overflow: 'auto'}}>
<a-space>
<a-button class="btn-success" onClick={() => saveOrUpdateCkGroup({
ckProjectId: record.snowFlakeId,
name: '',
totalScore: 0
}, initData)}>添加考核分组
</a-button>
</a-space>
<a-table
bordered
pagination={false}
class="margin-top-xs"
columns={ckProjectDetailTableColumns}
data-source={dataSource.value}
></a-table>
</div>
})
}}>考核详情
</a-button>
</a-space>
}
}
]
</script>
<style scoped lang="scss">
</style>

View File

@ -0,0 +1,236 @@
import {TableProMaxProps, TableProMaxSlots} from "@/types/components/table";
import {
EnterprisesUnitPagerQueryParams,
EnterprisesUnitPagerVo, EnterprisesUnitSaveOrUpdateParams,
PoliceUnitPagerVo
} from "@/types/views/unitManage/police/policeUnit.ts";
import {ref} from "vue";
import {FormExpose} from "ant-design-vue/es/form/Form";
import {ComponentExposed} from "vue-component-type-helpers";
import MapContainer from "@/components/aMap/MapContainer.vue";
import {FormProMaxItemOptions} from "@/types/components/form";
import {dictSelectNodes} from "@/config/dict.ts";
import {Button, message, Modal, Space} from "ant-design-vue";
import api from "@/axios";
import TableProMax from "@/components/table/TableProMax.vue";
import {deleteDataModal} from "@/components/tsx/ModalPro.tsx";
import {PageParams} from "@/types/hooks/useTableProMax.ts";
import FormProMax from "@/components/form/FormProMax.vue";
type _TableProps = TableProMaxProps<EnterprisesUnitPagerVo, EnterprisesUnitPagerQueryParams>;
type _FormType = EnterprisesUnitSaveOrUpdateParams & {
contactPersonInfoName?: string;
contactPersonInfoTelephone?: string
}
const saveOrUpdateEnterprisesUnit = (params: _FormType, callback: Function) => {
const _formRef = ref<FormExpose>(null)
const _mapRef = ref<ComponentExposed<typeof MapContainer>>(null)
const _formParams = ref<_FormType>({...params})
let city = '';
const initMarker = (map: AMap.Map) => {
//添加maker点 设置point
const maker = new AMap.Marker({
position: _formParams.value.point,
draggable: true
})
maker.on("dragend", ({lnglat}) => {
_formParams.value.point = lnglat
})
map.clearMap()
map.add(maker)
map.setFitView()
console.log(123);
}
const _formOptions = ref<FormProMaxItemOptions<_FormType>>({
name: {
type: 'input',
label: '单位名称',
required: true,
},
type: {
type: 'select',
label: '单位类型',
required: true,
options: dictSelectNodes('EnterprisesUnitType')
},
administrativeDivisionCodes: {
type: 'administrativeDivisionTree',
label: '行政区划',
required: true,
componentsProps: {
displayRender: ({labels}): string => {
city = labels[0]
return labels.join(' / ');
}
}
},
address: {
type: 'inputTextArea',
label: '详细地址',
},
map: {
type: 'custom',
label: '经纬度',
customRender: () => <MapContainer
ref={_mapRef}
style={{width: '100%', height: '300px', position: 'relative'}}
initCallback={(map) => {
AMap.plugin(['AMap.AutoComplete'], () => {
//@ts-ignore
const auto = new AMap.AutoComplete({
city,
input: "tipinput"
});
//注册监听,当选中某条记录时会触发
auto.on("select", (e) => {
//有些点位可能没有经纬度信息
if (!e.poi.location) {
message.error('所选点位没有经纬度信息 建议选则附近的手动移动!');
return
}
_formParams.value.point = e.poi.location
initMarker(map)
});
})
if (_formParams.value.point) {
initMarker(map)
}
}}
>
<div style={{position: 'absolute', left: '10px', top: '10px', zIndex: 9999}}>
<input id={'tipinput'}
placeholder={'请输入详细地址'}
autocomplete="off"
/>
</div>
</MapContainer>
},
contactPersonInfoName: {
type: 'input',
label: '联系人名称'
},
contactPersonInfoTelephone: {
type: 'input',
label: '联系人电话'
},
remark: {
type: 'inputTextArea',
label: '备注'
}
})
Modal.confirm({
title: params.snowFlakeId ? `${params.name}】 信息编辑` : '新增企事业单位',
width: 600,
icon: ' ',
centered: true,
content: () => <FormProMax
ref={_formRef}
v-model:value={_formParams.value}
formItemOptions={_formOptions.value}/>,
onOk: async () => {
await _formRef.value?.validate()
const resp = await api.post('/enterprisesUnit/saveOrUpdate', {
..._formParams.value,
contactPersonInfo: {
name: _formParams.value.contactPersonInfoName,
telephone: _formParams.value.contactPersonInfoTelephone
}
})
message.success(resp.message)
callback && callback()
}
})
}
export const showEnterprisesUnit = (policeUnitPagerVo: PoliceUnitPagerVo) => {
const _tableRef = ref<ComponentExposed<typeof TableProMax>>(null)
const _columns: _TableProps['columns'] = [
{
dataIndex: 'name',
title: '名称'
}, {
dataIndex: 'type',
title: '类型',
customRender: ({text}) => text?.label
}, {
dataIndex: 'contactPersonInfo',
title: '联系人',
customRender: ({text}) => text?.name + "/" + text.telephone
}, {
dataIndex: 'province',
title: '行政区划',
customRender: ({record}) => [record.provinceName, record.cityName, record.districtsName, record.streetName].filter(Boolean).join("/")
}, {
dataIndex: 'address',
title: '详细地址'
}, {
dataIndex: 'remark',
title: '备注'
}, {
dataIndex: 'createTime',
title: '创建时间'
}, {
dataIndex: 'opt',
title: '操作',
customRender: ({record}) => <Space>
<Button
class="btn-warn"
onClick={() => saveOrUpdateEnterprisesUnit({
snowFlakeId: record.snowFlakeId,
policeUnitId: record.policeUnitId,
name: record.name,
type: record.type.value,
administrativeDivisionCodes: [record.province, record.city, record.districts, record.street].filter(Boolean),
address: record.address,
point: record.point,
contactPersonInfoName: record.contactPersonInfo?.name,
contactPersonInfoTelephone: record.contactPersonInfo?.telephone,
remark: record.remark
}, _tableRef.value?.requestGetTableData)}
>
</Button>
<Button class="btn-danger" onClick={() => deleteDataModal(record.name, async () => {
const resp = await api.delete('/enterprisesUnit/deleteById', {
enterprisesUnitId: record.snowFlakeId
})
message.success(resp.message)
await _tableRef.value?.requestGetTableData()
})}>
</Button>
</Space>
}
]
const _reqApi: _TableProps["requestApi"] = (params) => {
(params as PageParams<EnterprisesUnitPagerQueryParams>).params.policeUnitId = policeUnitPagerVo.snowFlakeId
return api.post('/enterprisesUnit/pager', params)
}
Modal.info({
title: `${policeUnitPagerVo.name}】 管辖企事业单位`,
width: '80%',
content: () => <TableProMax
ref={_tableRef}
columns={_columns}
requestApi={_reqApi}
v-slots={{
tableHeader: (_) => {
return <Space>
<Button
class="btn-success"
onClick={() => saveOrUpdateEnterprisesUnit({
name: undefined,
type: 'school',
policeUnitId: policeUnitPagerVo.snowFlakeId,
administrativeDivisionCodes: [policeUnitPagerVo.province, policeUnitPagerVo.city, policeUnitPagerVo.districts, policeUnitPagerVo.street].filter(Boolean)
}, _tableRef.value?.requestGetTableData)}
>
</Button>
<Button disabled></Button>
</Space>
}
} as TableProMaxSlots<PoliceUnitPagerVo>}
/>
})
}

View File

@ -0,0 +1,159 @@
<template>
<TableProMax
ref="tableRef"
:request-api="reqApi"
:columns="columns"
:searchFormOptions="searchFormOptions"
>
</TableProMax>
</template>
<script setup lang="tsx">
import TableProMax from "@/components/table/TableProMax.vue";
import {ref} from "vue";
import {ComponentExposed} from "vue-component-type-helpers";
import {TableProMaxProps} from "@/types/components/table";
import {
PoliceUnitPagerQueryParams,
PoliceUnitPagerVo
} from "@/types/views/unitManage/police/policeUnit.ts";
import api from "@/axios";
import {dictSelectNodes} from "@/config/dict.ts";
import {message} from "ant-design-vue";
import {UNIT_TYPE} from "@/config";
import {showEnterprisesUnit} from "@/views/unitManage/police/unitManage/index.tsx";
type TableProps = TableProMaxProps<PoliceUnitPagerVo, PoliceUnitPagerQueryParams>
const tableRef = ref<ComponentExposed<typeof TableProMax>>(null!)
const reqApi: TableProps['requestApi'] = (params) => api.post('/management/super/policeUnit/pager', params)
const columns: TableProps['columns'] = [
{
dataIndex: 'name',
title: '名称'
}, {
dataIndex: 'code',
title: '代码'
}, {
dataIndex: 'contactPersonInfo',
title: '联系人',
customRender({record}) {
return record.contactPersonInfo?.name + "/" + record.contactPersonInfo?.telephone
},
}, {
dataIndex: 'provinceName',
title: '行政区划',
customRender: ({record}) => [record.provinceName, record.cityName, record.districtsName, record.streetName].filter(Boolean).join('/')
}, {
dataIndex: 'isEnable',
title: '是否启用',
customRender: ({text}) => <a-tag color={text?.extData?.color}>{text?.label}</a-tag>,
}, {
dataIndex: 'checkStatus',
title: '审核状态',
customRender: ({text}) => <a-tag color={text?.extData?.color}>{text?.label}</a-tag>,
}, {
dataIndex: 'createTime',
title: '创建时间'
}, {
dataIndex: 'opt',
title: '操作',
customRender({record}) {
if (record.checkStatus.value === 1) {
return <a-space>
<a-popconfirm
title="确认审核通过嘛?"
onConfirm={async () => {
const resp = await api.post('/management/checkPass', {
checkDataId: record.snowFlakeId,
unitOptType: UNIT_TYPE.police
})
message.success(resp.message)
await tableRef.value?.requestGetTableData()
}}>
<a-button type="primary">审核通过
</a-button>
</a-popconfirm>
</a-space>
}
return <a-space>
<a-button
class="btn-success"
onClick={() => showEnterprisesUnit(record)}
>企事业单位
</a-button>
<a-button
class={record.isEnable.value === 0 ? 'btn-danger' : 'btn-success'}
onClick={async () => {
const resp = await api.post('/management/disableOrEnable', {
dataId: record.snowFlakeId,
unitOptType: UNIT_TYPE.police
})
message.success(resp.message)
await tableRef.value?.requestGetTableData()
}}
>{record.isEnable.value === 0 ? '禁用' : '启用'}</a-button>
</a-space>
},
}
]
const searchFormOptions = ref<TableProps["searchFormOptions"]>({
name: {
type: 'input',
label: '名称'
}, code: {
type: 'input',
label: '代码'
}, administrativeDivisionCodes: {
type: 'administrativeDivisionTree',
label: '行政区划',
}, isEnable: {
type: 'select',
label: '是否启用',
options: [
{
value: null,
label: '全部'
}, ...dictSelectNodes('IsEnable')
]
}, checkStatus: {
type: 'select',
label: '审核状态',
options: [
{
value: null,
label: '全部'
}, ...dictSelectNodes('CheckStatus')
]
}
})
const a = {
groupId1: {
itemId1: {
standardId: 123123,
deductionPoints: 2
},
itemId2: {
standardId: 345345,
deductionPoints: 4
}
},
groupId2: {
itemId1: {
standardId: 456456,
deductionPoints: 2
},
itemId2: {
standardId: 567567,
deductionPoints: 4
}
}
}
</script>
<style scoped lang="scss">
</style>

Some files were not shown because too many files have changed in this diff Show More