Compare commits

..

2 Commits

13 changed files with 663 additions and 40 deletions

View File

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

View File

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