初始化

This commit is contained in:
2025-07-28 14:57:35 +08:00
commit 8fcffec73d
412 changed files with 73935 additions and 0 deletions

194
pages/work/index.vue Normal file
View File

@@ -0,0 +1,194 @@
<template>
<view class="work-container">
<!-- 轮播图 -->
<uni-swiper-dot class="uni-swiper-dot-box" :info="swiperImgData" :current="current" field="content">
<swiper class="swiper-box" :current="swiperDotIndex" @change="changeSwiper">
<swiper-item v-for="(item, index) in swiperImgData" :key="index">
<view class="swiper-item" @click="clickBannerItem(item)">
<image :src="item.image" mode="aspectFill" :draggable="false" />
</view>
</swiper-item>
</swiper>
</uni-swiper-dot>
<!-- 宫格组件 -->
<view class="grid-body">
<uni-grid :column="4" :showBorder="false" @change="changeGrid">
<uni-grid-item v-for="(item, index) in uniGridList" v-if="item.ifData" :index="index+1" :key="index">
<view class="grid-item-box">
<uni-icons :type="item.type" :size="30" />
<text class="text">{{item.text}}</text>
</view>
</uni-grid-item>
</uni-grid>
</view>
</view>
</template>
<script>
// 获取路由
import {
getRouters
} from '@/api/login'
import {
checkPermi,
checkRole
} from "@/utils/permission"; // 权限判断函数
export default {
data() {
return {
current: 0,
swiperDotIndex: 0,
swiperImgData: [{
image: '/static/images/banner/banner01.jpg'
},
{
image: '/static/images/banner/banner02.jpg'
},
{
image: '/static/images/banner/banner03.jpg'
}
],
uniGridList: [{
text: '打卡记录',
type: "calendar-filled",
ifData: "checkRole(['admin'])"
},
{
text: '异常巡检',
type: "info-filled",
ifData: "checkRole(['admin'])"
},
{
text: '隐患申报',
type: "navigate-filled",
ifData: "checkRole(['admin',common])"
},
// {
// text: '申报记录',
// type: "list",
// ifData: "checkRole(['admin'])"
// },
]
}
},
created() {
this.getUserRouters()
},
methods: {
//获取路由
getUserRouters() {
let params = {
menuUseful: 1
}
getRouters(params).then(res => {
// this.iconBoxList=res.data[0].children;
console.log(res.data[0]);
});
},
checkPermi(res) {
console.log(res);
},
checkRole(res) {
console.log(res);
},
clickBannerItem(item) {
console.info(item)
},
changeSwiper(e) {
this.current = e.detail.current
},
changeGrid(e) {
let {
index
} = e.detail
if (index == 1) {
this.$tab.navigateTo("/pages/work/inspection/checkInRecord/index");
} else if (index == 2) {
this.$tab.navigateTo("/pages/work/inspection/inspectionEx/index");
} else if (index == 3) {
this.$tab.navigateTo("/pages/work/sidebar/safetyDeclaratio/index");
} else if (index == 4) {
this.$tab.navigateTo("/pages/work/sidebar/filingLog/index");
}
}
}
}
</script>
<style lang="scss">
/* #ifndef APP-NVUE */
page {
display: flex;
flex-direction: column;
box-sizing: border-box;
background-color: #fff;
min-height: 100%;
height: auto;
}
view {
font-size: 14px;
line-height: inherit;
}
/* #endif */
.text {
text-align: center;
font-size: 26rpx;
margin-top: 10rpx;
}
.grid-item-box {
flex: 1;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
align-items: center;
justify-content: center;
padding: 15px 0;
}
.uni-margin-wrap {
width: 690rpx;
width: 100%;
;
}
.swiper {
height: 300rpx;
}
.swiper-box {
height: 150px;
}
.swiper-item {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
align-items: center;
color: #fff;
height: 300rpx;
line-height: 300rpx;
}
@media screen and (min-width: 500px) {
.uni-swiper-dot-box {
width: 400px;
/* #ifndef APP-NVUE */
margin: 0 auto;
/* #endif */
margin-top: 8px;
}
.image {
width: 100%;
}
}
</style>

View File

@@ -0,0 +1,309 @@
<template>
<view class="charts-box">
<uni-section class="mb-10" title="打卡数据" signIn="info">
<template v-slot:right>
<uni-data-select style="width:70px;" :clear=false v-model="queryform.month" :localdata="monthList"
@change="monthSelectChange"></uni-data-select>
</template>
</uni-section>
<qiun-data-charts type="ring" :opts="opts" :chartData="chartData" :errorShow="false" :tapLegend="false" />
<uni-section class="mb-10" title="打卡列表" List="info">
<template v-slot:right>
<uni-data-select style="width:70px;" :clear=false v-model="queryform.weekType" :localdata="weekList"
@change="weekTypeSelectChange"></uni-data-select>
</template>
</uni-section>
<uni-card v-for="item of cardList" :title="item.inspectionPoint" :thumbnail="avatar">
<uni-row class="demo-uni-row" :width="nvueWidth">
<uni-col :span="20">
<view>
<text class="uni-body">
打卡时间{{item.inspectionTime}}
</text>
</view>
</uni-col>
<uni-col :span="4">
<view class="tag-view">
<uni-tag :inverted="true" :circle="true" text="已打卡" size="small" />
</view>
</uni-col>
</uni-row>
</uni-card>
<uni-load-more :status="status" />
</uni-section>
</view>
</template>
<script>
import {
listRecordView
} from '@/api/inspection/record.js'
export default {
data() {
return {
status: 'noMore',
// 分栏
nvueWidth: 730,
// 数据可视化
inspectionRecordViewTable: [],
cardList: [],
weekList: [{
text: "全部",
value: 0
}, {
text: "第一周",
value: 1
},
{
text: "第二周",
value: 2
},
{
text: "第三周",
value: 3
},
{
text: "第四周",
value: 4
}
],
monthList: [{
text: " 一月",
value: 1
},
{
text: " 二月",
value: 2
},
{
text: " 三月",
value: 3
},
{
text: " 四月",
value: 4
},
{
text: " 五月",
value: 5
},
{
text: " 六月",
value: 6
},
{
text: " 七月",
value: 7
},
{
text: " 八月",
value: 8
},
{
text: " 九月",
value: 9
},
{
text: " 十月",
value: 10
},
{
text: "十一月",
value: 11
},
{
text: "十二月",
value: 12
}
],
queryform: {
month: 9,
weekType: 0,
inspectorUser: this.$store.state.user.nickName
},
avatar: '/static/images/signIn.png',
chartData: {},
//这里的 opts 是图表类型 type="ring" 的全部配置参数,您可以将此配置复制到 config-ucharts.js 文件中下标为 ['ring'] 的节点中来覆盖全局默认参数。实际应用过程中 opts 只需传入与全局默认参数中不一致的【某一个属性】即可实现同类型的图表显示不同的样式,达到页面简洁的需求。
opts: {
timing: "easeOut",
duration: 1000,
rotate: false,
rotateLock: false,
color: ["#1890FF", "#91CB74", "#FAC858", "#EE6666", "#73C0DE", "#3CA272", "#FC8452", "#9A60B4", "#ea7ccc"],
padding: [5, 5, 5, 5],
fontSize: 13,
fontColor: "#666666",
dataLabel: false,
dataPointShape: false,
dataPointShapeType: "hollow",
touchMoveLimit: 60,
enableScroll: false,
enableMarkLine: false,
legend: {
show: true,
position: "bottom",
lineHeight: 25,
float: "center",
padding: 5,
margin: 5,
backgroundColor: "rgba(0,0,0,0)",
borderColor: "rgba(0,0,0,0)",
borderWidth: 0,
fontSize: 13,
fontColor: "#666666",
hiddenColor: "#CECECE",
itemGap: 10
},
title: {
name: "已打卡",
fontSize: 15,
color: "#666666",
offsetX: 0,
offsetY: 0
},
subtitle: {
name: "30",
fontSize: 25,
color: "#fbbd08",
offsetX: 0,
offsetY: 0
},
extra: {
ring: {
ringWidth: 30,
activeOpacity: 0.5,
activeRadius: 10,
offsetAngle: 0,
labelWidth: 15,
border: false,
borderWidth: 3,
borderColor: "#FFFFFF",
centerColor: "#FFFFFF",
customRadius: 0,
linearType: "none"
},
tooltip: {
showBox: true,
showArrow: true,
showCategory: false,
borderWidth: 0,
borderRadius: 0,
borderColor: "#000000",
borderOpacity: 0.7,
bgColor: "#000000",
bgOpacity: 0.7,
gridType: "solid",
dashLength: 4,
gridColor: "#CCCCCC",
boxPadding: 3,
fontSize: 13,
lineHeight: 20,
fontColor: "#FFFFFF",
legendShow: true,
legendShape: "auto",
splitLine: true,
horizentalLine: false,
xAxisLabel: false,
yAxisLabel: false,
labelBgColor: "#FFFFFF",
labelBgOpacity: 0.7,
labelFontColor: "#666666"
}
}
}
};
},
methods: {
getList() {
const currentDate = new Date();
const currentMonth = currentDate.getMonth() + 1; // getMonth() 返回 0-11所以需要加 1
this.queryform.month = currentMonth;
listRecordView(this.queryform).then(res => {
let data = res.data
if (data.clockIn != 0) {
let obj = [{
"name": data.clockState,
"value": data.clockIn + ""
}]
this.inspectionRecordViewTable = obj
} else {
this.inspectionRecordViewTable = []
}
this.cardList = data.inspectionRecordTables
})
this.getServerData()
},
//周选择框事件
weekTypeSelectChange(e) {
this.queryform.weekType = e
this.getList()
},
// 月选择框事件
monthSelectChange(e) {
this.queryform.month = e
this.getList()
},
// 初始化月份
getmonth() {
const now = new Date();
this.queryform.month = (now.getMonth() + 1);
},
onClick(e) {
console.log(e)
},
getServerData() {
//模拟从服务器获取数据时的延时
setTimeout(() => {
//模拟服务器返回数据,如果数据格式和标准格式不同,需自行按下面的格式拼接
let res = {
series: [{
data: [],
}]
};
// //卡片数据
console.log(this.inspectionRecordViewTable);
if (this.inspectionRecordViewTable.length > 0) {
console.log(true);
res.series[0].data = this.inspectionRecordViewTable
this.opts.title.name = "本月总打卡"
this.opts.subtitle.name = this.inspectionRecordViewTable[0].value + ""
} else {
this.opts.title.name = "暂无该月份数据"
this.opts.subtitle.name = "0"
res.series[0].data = []
}
this.chartData = JSON.parse(JSON.stringify(res));
}, 1000);
},
},
created() {
this.getList()
}
};
</script>
<style lang="scss" scoped>
/* #ifndef APP-NVUE */
page {
display: flex;
flex-direction: column;
box-sizing: border-box;
background-color: #fff;
min-height: 100%;
height: auto;
}
view {
font-size: 14px;
line-height: inherit;
}
/* 请根据实际需求修改父元素尺寸,组件自动识别宽高 */
.charts-box {
width: 100%;
height: 300px;
}
</style>

View File

@@ -0,0 +1,273 @@
<template>
<view class="container">
<view class="example">
<uni-forms ref="dynamicForm" :model="form" label-width="80px" :rules="rules">
<uni-forms-item label="巡检点" name="inspectionPoint" required>
<uni-easyinput v-model="form.inspectionPoint" placeholder="请输入巡检点"></uni-easyinput>
</uni-forms-item>
<uni-forms-item label="巡检类型" name="inspectionType" required>
<uni-data-select v-model="form.inspectionType" :localdata="selectList"></uni-data-select>
</uni-forms-item>
<uni-forms-item label="备注" name="remark">
<uni-easyinput type="textarea" v-model="form.remark" placeholder="请输入备注"></uni-easyinput>
</uni-forms-item>
<uni-forms-item label="图片上传">
<view class="example-body">
<uni-file-picker limit="3" :sourceType="sourceType" :value="img" title="最多选择3张图片" file-mediatype="image"
@delete="deleteImg" @select="upload" :auto-upload="false"></uni-file-picker>
</view>
</uni-forms-item>
</uni-forms>
<view class="button-group">
<button type="primary" size="mini" @click="cancel()">取消</button>
<button type="primary" size="mini" @click="submit()">提交</button>
</view>
</view>
</view>
</template>
<script>
import {
uploadImg
} from "@/api/system/user"
import {
listData
} from '@/api/system/dict/data.js'
import {
addRecord
} from "@/api/inspection/record.js"
import { addWatermarkToImage } from "@/utils/watermark.js"
export default {
// vue
data() {
return {
// 选择框数据
selectList: [],
form: {
inspectionType: null, //默认常规巡检
inspectorId: this.$store.state.user.nickName, //巡检人
inspectionPoint: "",// 巡检点
remark: "",
inspectionImg: "",
ImgUrl: []
},
img: [],
sourceType: ['camera'],
//存图片文件
imgFiles: "",
rules: {
inspectionPoint: {
// name 字段的校验规则
rules: [
// 校验 name 不能为空
{
required: true,
errorMessage: '请填写巡检点',
}
],
},
inspectionType: {
// name 字段的校验规则
rules: [
// 校验 name 不能为空
{
required: true,
errorMessage: '请填选择巡检类型',
}
],
},
remark: {
// name 字段的校验规则
rules: [
// 校验 name 不能为空
{
required: true,
errorMessage: '请填写备注',
}
],
},
}
}
},
methods: {
// 初始化字典
async initDictType() {
const typeData = await listData({
dictType: "inspection_type"
});
typeData.rows.forEach(item => {
let data = {
value: 0,
text: ""
}
data.value = item.dictValue
data.text = item.dictLabel
this.selectList.push(data)
})
},
// 提交
submit() {
this.$refs.dynamicForm.validate().then(res => {
this.form.inspectionImg = this.joinList()
console.log("this.form",this.form);
addRecord(this.form).then(res => {
console.log(res);
if (res.code==200) {
uni.showToast({
title: '提交成功',
icon: 'success', // 成功图标
duration: 1000 // 持续时间为2000ms
});
setTimeout(() => {
this.$tab.navigateBack(); // 假设这是正确的页面跳转方法,具体方法可能因框架而异
}, 1000);
}
})
})
},
// 图片删除
deleteImg(e) {
//const index = this.img.findIndex(f => f.uuid === e.tempFile.uuid); // 假设文件通过 url 唯一标识
const index = this.img.findIndex(f => f.path === e.tempFile.path); // 通过图片路径表示来删除数组中的指定数据
if (index !== -1) {
this.form.ImgUrl.splice(index, 1)
this.img.splice(index,1)
}
},
// 上传图片
upload(e) {
console.log(e);
// this.img.push(e.tempFiles[0])
// e.tempFilePaths.forEach(item => {
// uploadImg({
// filePath: item
// }).then(res => {
// this.form.ImgUrl.push(res.fileName)
// })
// })
this.handleImageUpload(e.tempFiles[0]);
},
// 取消
cancel() {
uni.reLaunch({
url: '/pages/work/index'
})
uni.showToast({
title: '打卡失败',
icon: 'error', // 成功图标
duration: 1000 // 持续时间为2000ms
});
},
// 定义一个方法用于将list拼接成字符串
joinList() {
// 使用数组的join方法以逗号分隔元素
return this.form.ImgUrl.join(',');
},
/** 处理图片上传 --知无涯 */
async handleImageUpload(file) {
const that = this;
try {
if (!file) {
throw new Error('无效的文件对象');
}
// 生成水印文字:巡检地点 + 巡检时间
const times = this.getCurrentDate();
const watermarkText = `${this.form.inspectionPoint || '未命名地点'} \n${times || '未设置时间'}`;
// 添加水印 - 水印配置
const watermarkedFile = await addWatermarkToImage(file.file, watermarkText);
// 创建预览URL
const previewUrl = URL.createObjectURL(watermarkedFile);
// 更新表单数据
that.imgFiles = {
raw: watermarkedFile,
name: watermarkedFile.name,
url: previewUrl
};
//上传图片,获取图片路径
that.img.push(that.imgFiles)
uploadImg({
filePath: previewUrl
}).then(res => {
that.form.ImgUrl.push(res.fileName)
console.log(res);
})
} catch (error) {
console.error("水印处理失败:", error);
proxy.$modal.msgError("图片处理失败: " + error.message);
}
},
// 获取当前时间
getCurrentDate() {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
},
},
created() {
this.initDictType()
}
}
</script>
<style lang="scss">
page {
display: flex;
flex-direction: column;
box-sizing: border-box;
background-color: #fff;
height: 90vh;
/* 使页面高度占满整个视口 */
}
.container {
flex: 1;
/* 让 container 占满剩余空间 */
display: flex;
flex-direction: column;
/* 设置为列方向 */
}
.example {
flex: 1;
/* 让 example 占满 container 的剩余空间 */
display: flex;
flex-direction: column;
/* 设置为列方向,确保子元素垂直排列 */
padding: 15px;
background-color: #fff;
}
// 样式沉底
.button-group {
position: fixed;
bottom: 20px;
left: 0;
/* 使用 margin-top: auto 来将按钮组推到 example 容器的底部 */
display: flex;
width: 100%;
justify-content: space-around;
}
.button-group button {
flex: 1;
background: #fff;
color: #000;
/* 使按钮平分可用空间 */
/* 可能还需要设置一些其他的样式来确保按钮看起来正确,比如 text-align, padding 等 */
}
</style>

View File

@@ -0,0 +1,279 @@
<template>
<view class="container">
<view class="example">
<uni-forms ref="dynamicForm" :model="form" label-width="80px">
<uni-forms-item label="巡检点" name="inspectionPoint">
<uni-easyinput disabled :value="form.inspectionPoint" placeholder="请输入巡检点"></uni-easyinput>
</uni-forms-item>
<uni-forms-item label="巡检要求" name="inspectionRequirements">
<uni-easyinput type="textarea" disabled :value="form.inspectionRequirements" placeholder="请输入巡检要求"></uni-easyinput>
</uni-forms-item>
<uni-forms-item label="图片上传">
<view class="example-body">
<uni-file-picker limit="3" :sourceType="sourceType" :value="img" title="最多选择3张图片"
file-mediatype="image" @delete="deleteImg" @select="upload"
:auto-upload="false"></uni-file-picker>
</view>
</uni-forms-item>
<!-- 备注 -->
<uni-forms-item label="备注" name="remark">
<uni-easyinput type="textarea" v-model="form.remark" placeholder="请输入备注"></uni-easyinput>
</uni-forms-item>
</uni-forms>
<view class="button-group">
<button class="btn btn-primary" @click="submit()">提交</button>
<button class="btn btn-cancel" @click="cancel()">取消</button>
</view>
</view>
<!-- 消息提示框 -->
<view>
<uni-popup ref="alertDialog" type="dialog">
<uni-popup-dialog :type="msgType" title="消息" :content="messageText" @confirm="dialogConfirm"
showClose="false"></uni-popup-dialog>
</uni-popup>
</view>
</view>
</template>
<script>
import {
uploadImg
} from "@/api/system/user"
import {
addRecord
} from "@/api/inspection/record.js"
import {
addWatermarkToImage
} from "@/utils/watermark.js"
export default {
// vue
data() {
return {
form: {
inspectionType: 0, //默认常规巡检
inspectorId: this.$store.state.user.nickName, //巡检人
// 巡检点
inspectionPoint: "",
// 巡检要求
inspectionRequirements: "",
inspectionImg: "",
ImgUrl: []
},
img: [],
sourceType: ['camera'],
//存图片文件
imgFiles: "",
// 消息提示框
msgType: '',
messageText: '',
isUploading: false, // 上传中标志
}
},
methods: {
// 提交
submit() {
if (this.isUploading) {
this.msgType = 'warning'
this.messageText = '图片正在上传中,请稍等'
this.$refs.alertDialog.open()
return;
}
if (!Array.isArray(this.form.ImgUrl) || this.form.ImgUrl.length === 0) {
this.msgType = 'error'
this.messageText = `请选择要上传的图片`
this.$refs.alertDialog.open()
return;
}
this.form.inspectionImg = this.joinList()
addRecord(this.form).then(res => {
if (res.code === 200) {
// console.log("sdfsadfsdfsdfsdfsdf");
this.msgType = 'success'
this.messageText = `打卡成功`
this.$refs.alertDialog.open()
} else {
this.msgType = 'error'
this.messageText = `打卡失败`
this.$refs.alertDialog.open()
}
})
},
// 图片删除
deleteImg(e) {
//const index = this.img.findIndex(f => f.uuid === e.tempFile.uuid); // 假设文件通过 url 唯一标识
const index = this.img.findIndex(f => f.path === e.tempFile.path); // 假设文件通过 url 唯一标识
if (index !== -1) {
this.form.ImgUrl.splice(index, 1)
this.img.splice(index, 1)
}
},
// 上传图片
upload(e) {
console.log(e);
// this.img.push(e.tempFiles[0])
// e.tempFilePaths.forEach(item => {
// uploadImg({
// filePath: item
// }).then(res => {
// this.form.ImgUrl.push(res.fileName)
// })
// })
this.handleImageUpload(e.tempFiles[0]);
},
// 取消
cancel() {
uni.reLaunch({
url: '/pages/work/index'
})
uni.showToast({
title: '打卡失败',
icon: 'error', // 成功图标
duration: 1000 // 持续时间为2000ms
});
},
// 定义一个方法用于将list拼接成字符串
joinList() {
// 使用数组的join方法以逗号分隔元素
return this.form.ImgUrl.join(',');
},
/** 处理图片上传 --知无涯 */
async handleImageUpload(file) {
this.isUploading = true; // 开始上传
const that = this;
try {
if (!file) {
throw new Error('无效的文件对象');
}
// 生成水印文字:巡检地点 + 巡检时间
const times = this.getCurrentDate();
const watermarkText = `${this.form.inspectionPoint || '未命名地点'} \n${times || '未设置时间'}`;
// 添加水印 - 水印配置
// const watermarkedFile = await addWatermarkToImage(file.file, watermarkText, {
// font: 'bold 20px Arial', // 加大字号并加粗
// color: 'rgba(0, 0, 0, 0.7)' // 黑色70%不透明度
// });
const watermarkedFile = await addWatermarkToImage(file.file, watermarkText);
// 创建预览URL
const previewUrl = URL.createObjectURL(watermarkedFile);
// 更新表单数据
that.imgFiles = {
raw: watermarkedFile,
name: watermarkedFile.name,
url: previewUrl
};
//上传图片,获取图片路径
that.img.push(that.imgFiles)
await uploadImg({
filePath: previewUrl
}).then(res => {
that.form.ImgUrl.push(res.fileName)
// console.log(res);
})
} catch (error) {
console.error("水印处理失败:", error);
proxy.$modal.msgError("图片处理失败: " + error.message);
} finally {
this.isUploading = false; // 上传完毕
}
},
// 获取当前时间
getCurrentDate() {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
},
//对话框确定按钮
dialogConfirm() {
if (this.msgType == 'success') {
uni.reLaunch({
url: '/pages/work/index'
})
return;
} else {
return;
}
},
},
// uniapp
//uniapp方法在最开始的时候拿到传值过来的值
onLoad(option) {
const _this = this
// console.log('传递的值',option)
_this.form.inspectionPoint = option.inspectionPoint
_this.form.inspectionRequirements = option.inspectionRequirements
_this.form.inspectionPointId = option.inspectionPointId
},
created() {
// console.log("this.$store.state.user",this.$store.state.user);
}
}
</script>
<style lang="scss">
page {
display: flex;
flex-direction: column;
box-sizing: border-box;
background-color: #fff;
height: 90vh;
/* 使页面高度占满整个视口 */
}
.container {
flex: 1;
/* 让 container 占满剩余空间 */
display: flex;
flex-direction: column;
/* 设置为列方向 */
}
.example {
flex: 1;
/* 让 example 占满 container 的剩余空间 */
display: flex;
flex-direction: column;
/* 设置为列方向,确保子元素垂直排列 */
padding: 15px;
background-color: #fff;
}
// 样式沉底
.button-group {
position: fixed;
bottom: 20px;
left: 0;
/* 使用 margin-top: auto 来将按钮组推到 example 容器的底部 */
display: flex;
width: 100%;
justify-content: space-around;
}
.button-group button {
flex: 1;
background: #fff;
color: #000;
/* 使按钮平分可用空间 */
/* 可能还需要设置一些其他的样式来确保按钮看起来正确,比如 text-align, padding 等 */
}
</style>

View File

@@ -0,0 +1,79 @@
<script>
import {
getInspectionManage
} from '@/api/inspection/inspectionManage.js'
export default {
created() {
this.requestCameraAuth()
},
methods: {
requestCameraAuth() {
const _this = this
uni.authorize({
scope: 'scope.camera', // 请求相机权限
success: (res) => {
_this.scanQRCode();
},
fail: (err) => {
// 用户拒绝授权
uni.showToast({
title: '您拒绝了授权',
icon: 'none'
});
}
});
},
scanQRCode() {
const _this = this
uni.scanCode({
onlyFromCamera: true,
scanType: ['qrCode'],
success(res) {
if (res.result) {
// 扫描成功,处理二维码内容
getInspectionManage(res.result).then(res => {
if (res.data.inspectionStatus === "1") {
let inspectionPoint = res.data.inspectionPoint
let inspectionRequirements = res.data.inspectionRequirements
// _this.$tab.redirectTo(
// `/pages/work/inspection/scanSign/index?inspectionPoint=${inspectionPoint}&inspectionRequirements=${inspectionRequirements}`
// )
uni.reLaunch({
url: `/pages/work/inspection/scanSign/index?inspectionPoint=${inspectionPoint}&inspectionRequirements=${inspectionRequirements}`
})
} else {
uni.reLaunch({
url: '/pages/work/index'
}).then(()=>{
// 扫描失败
uni.showToast({
title: '验证码已失效!!!',
icon: 'none'
});
})
}
});
} else {
// 扫描失败
uni.showToast({
title: '扫描失败',
icon: 'none'
});
}
},
fail(res) {
uni.showToast({
title: '调用相机失败',
icon: 'none'
});
}
});
}
}
}
</script>
<style>
</style>

View File

@@ -0,0 +1,145 @@
<template>
<view class="container">
<button type="default" @click="scanCode">扫码</button>
<!-- <view>
扫码结果{{qrCodeRes}}
</view>
<image :src="qc"></image> -->
</view>
</template>
<script>
let Qrcode = require('../../../../utils/reqrcode.js')
import {
getInspectionManage
} from '@/api/inspection/inspectionManage.js'
export default {
data() {
return {
qrCodeRes: '',
qc: ''
}
},
methods: {
// 扫码
scanCode() {
// #ifdef APP-PLUS
this.scanCodeAPP()
// #endif
// #ifdef H5
this.scanCodeH5()
// #endif
},
// APP直接调用 uni.scanCode 接口
scanCodeAPP() {
uni.scanCode({
scanType: ['qrCode'],
success: (res) => {
this.qrCodeRes = res.result
}
})
},
// H5通过拉起相机拍照来识别二维码
scanCodeH5() {
let that = this;
uni.chooseImage({
count: 1,
sourceType: ['camera'],
success: imgRes => {
that.qc = imgRes.tempFiles[0].path; // 预览图片
const tempFile = imgRes.tempFiles[0];
const reader = new FileReader();
reader.onload = function(event) {
const base64 = event.target.result;
try {
Qrcode.qrcode.decode(base64);
Qrcode.qrcode.callback = (codeRes) => {
if (codeRes.indexOf('error') >= 0) {
that.qrCodeRes = '不合法二维码:' + codeRes;
uni.showToast({
title: '二维码识别失败!',
icon: 'none'
});
} else {
let r = that.decodeStr(codeRes);
that.qrCodeRes = r;
getInspectionManage(that.qrCodeRes)
.then(res => {
if (res.data.inspectionStatus === "1") {
console.log(res)
let inspectionPoint = res.data.inspectionPoint;
let inspectionRequirements = res.data
.inspectionRequirements;
let inspectionPointId = res.data.id
uni.reLaunch({
url: `/pages/work/inspection/scanSign/index?inspectionPoint=${inspectionPoint}&inspectionRequirements=${inspectionRequirements}&inspectionPointId=${inspectionPointId}`
});
} else {
uni.showToast({
title: '验证码已失效!',
icon: 'none'
});
uni.reLaunch({
url: '/pages/work/index'
});
}
})
.catch(err => {
console.log("请求错误", err);
uni.showToast({
title: '服务器错误',
icon: 'none'
});
});
}
};
} catch (error) {
console.log("解析失败", error);
uni.showToast({
title: '二维码解析失败',
icon: 'none'
});
}
};
reader.readAsDataURL(tempFile);
},
fail: (err) => {
console.log("图片选择失败", err);
uni.showToast({
title: '拍照失败,请重试',
icon: 'none'
});
}
});
},
// 获取文件地址函数
getObjectURL(file) {
if (window.URL && window.URL.createObjectURL) {
return window.URL.createObjectURL(file);
} else {
console.warn("当前浏览器不支持 createObjectURL 方法");
return null;
}
},
// 解码,输出:中文
decodeStr(str) {
try {
return decodeURIComponent(escape(str));
} catch (e) {
console.warn("解码失败,返回原字符串:", str);
return str;
}
},
}
}
</script>
<style>
.container {
padding: 10px;
}
</style>

View File

@@ -0,0 +1,33 @@
<!-- HTML -->
<mumu-get-qrcode @success='qrcodeSucess' @error="qrcodeError"></mumu-get-qrcode>
<script>
// js
import mumuGetQrcode from '@/uni_modules/mumu-camera/components/mumu-camera/mumu-camera.vue'
// 嫌路径长的话可以单独复制出来
export default {
components: {
mumuGetQrcode
},
methods: {
qrcodeSucess(data) {
uni.showModal({
title: '成功',
content: data,
success: () => {
uni.navigateBack({})
}
})
},
qrcodeError(err) {
console.log(err)
uni.showModal({
title: '摄像头授权失败',
content: '摄像头授权失败,请检测当前浏览器是否有摄像头权限。',
success: () => {
uni.navigateBack({})
}
})
}
}
}
</script>

View File

@@ -0,0 +1,150 @@
<template>
<view class="work-container">
<uni-card v-for="(item,index) of dataList" class="parent">
<template v-slot:title>
<h3 class="title">{{item.declarationLabel}}</h3>
</template>
<h3>{{item.requirementDescription}}</h3>
<h3>{{item.occurTime}}</h3>
<view class="card-actions-item" @click="actionsClick(item.id)">
<button size="mini">详情</button>
</view>
</uni-card>
<uni-load-more status="已经没有更多数据了"></uni-load-more>
</uni-section>
</view>
</template>
<script>
import {
listData
} from '@/api/system/dict/data.js'
import {
listSafetyDeclaration
} from "@/api/sidebar/sidebar.js"
import formatTime from '@/utils/formatTime.js'
export default {
name: "FilingLog",
data() {
return {
dataList: [],
queryParams: {
pageNum: 1, // 初始页码设为1
pageSize: 10
},
isLoading: false, // 添加一个标志位,用于防止重复请求
typeDataList: [],
total: 0
}
},
methods: {
actionsClick(e) {
uni.navigateTo({
url: `/pages/work/sidebar/safetyDeclaratio/index?id=` + e
})
},
async getList() {
if (this.isLoading) return; // 如果已经在加载中,则不执行
this.isLoading = true;
const res = await listSafetyDeclaration(this.queryParams);
if (this.typeDataList.length == 0) {
this.typeDataList = await listData({
dictType: "hs_declaration_type"
});
}
this.total = res.total
let processedDataList = res.rows.map(item => {
const matchedType = this.typeDataList.rows.find(type => type.dictValue == item.declarationType);
const time = formatTime(item.occurTime);
return {
...item,
occurTime: time,
declarationLabel: matchedType ? matchedType.dictLabel : "未知类型"
};
});
// 合并新旧数据
this.dataList = [...this.dataList, ...processedDataList];
},
onLoad(options) {
this.getList();
},
},
onReachBottom() {
this.isLoading = false;
//上拉到底时触发onReachBottom函数跟生命周期同级
let allTotal = this.queryParams.pageNum * this.queryParams.pageSize
console.log("allTotal",allTotal);
console.log("this.total",this.total);
if (allTotal < this.total) {
this.queryParams.pageNum++;
// this.queryParams.page++//当前条数小于总条数 则增加请求页数
this.getList() //调用加载数据方法
setTimeout(() => {
//结束下拉刷新
uni.stopPullDownRefresh();
}, 1000);
} else {
console.log('已加载全部数据')
}
},
onPullDownRefresh() {
this.queryParams.pageNum=1;
this.isLoading = false;
//下拉刷新触发onPullDownRefresh函数跟生命周期同级
this.dataList = []
this.getList().then(res=>{
setTimeout(() => {
//结束下拉刷新
uni.stopPullDownRefresh();
}, 1000);
})
}
}
</script>
<style lang="scss">
page {
display: flex;
flex-direction: column;
box-sizing: border-box;
background-color: #fff;
min-height: 100%;
height: auto;
}
.work-container {
margin-left: 4px
}
.parent {
position: relative;
h3 {
margin-bottom: 5px;
font-weight:600;
color: rgb(153, 153, 153);
}
.title {
font-weight:bold;
padding: 3rpx;
color: black;
}
}
.card-actions-item {
display: inline-block;
flex-direction: row;
align-items: center;
position: absolute;
bottom: 5px;
right: 30px;
button {
border-radius: 10px;
}
}
</style>

View File

@@ -0,0 +1,255 @@
<template>
<view class="container">
<view class="example">
<!-- 基础用法不包含校验规则 -->
<uni-forms ref="SafetyDeclarationTable" :rules="customRules" :modelValue="SafetyDeclarationTable"
label-width="80px">
<uni-forms-item label="隐患类别" name="declarationType" required>
<uni-data-select :disabled="id!=null" v-model="SafetyDeclarationTable.declarationType"
:localdata="selectList"></uni-data-select>
</uni-forms-item>
<uni-forms-item label="隐患内容" name="requirementDescription" required>
<uni-easyinput :disabled="id!=null" v-model="SafetyDeclarationTable.requirementDescription"
placeholder="请输入申报内容" />
</uni-forms-item>
<!-- <uni-forms-item label="隐患时间" name="occurTime" required>
<uni-datetime-picker :disabled="id!=null" type="datetime" v-model="SafetyDeclarationTable.occurTime" />
</uni-forms-item> -->
<uni-forms-item label="备注" name="remark">
<uni-easyinput :disabled="id!=null" type="textarea" v-model="SafetyDeclarationTable.remark"
placeholder="请输入备注" />
</uni-forms-item>
<uni-forms-item label="图片上传">
<view class="example-body">
<uni-file-picker :readonly="id!=null" limit="9" :value="img" title="最多选择9张图片" file-mediatype="image"
@delete="deleteImg" @select="upload" :auto-upload="false"></uni-file-picker>
</view>
</uni-forms-item>
</uni-forms>
<view class="button-group">
<button type="primary" size="mini" flex="1" v-if="!id" @click="cancellation()">取消</button>
<button type="primary" size="mini" flex="1" v-if="!id" @click="submit('SafetyDeclarationTable')">提交</button>
</view>
</view>
</view>
</template>
<script>
import { checkRole,checkPermi } from "@/utils/permission"; // 权限判断函数
import config from '@/config'
const baseUrl = config.baseUrl
import store from "@/store"
import {
listData
} from '@/api/system/dict/data.js'
import {
uploadImg
} from "@/api/system/user"
import {
addSafetyDeclaration,
getSafetyDeclaration
} from "@/api/sidebar/sidebar.js"
export default {
data() {
return {
id: null,
msgType: "",
messageText: "",
// 选择框数据
selectList: [],
img: [],
SafetyDeclarationTable: {
declarationType: 0,
requirementDescription: "",
occurTime: "",
declarationImg: "",
remark: "",
ImgUrl: []
},
selectedImg: "",
customRules: {
declarationType: {
rules: [{
required: true,
errorMessage: '请选择申报类型'
}]
},
requirementDescription: {
rules: [{
required: true,
errorMessage: '申报内容不能为空'
}]
},
// occurTime: {
// rules: [{
// required: true,
// errorMessage: '申报时间不能为空'
// }]
// }
}
}
},
mounted() {
// 需要在onReady中设置规则
this.$refs.SafetyDeclarationTable.setRules(this.customRules)
},
onLoad(option) {
if (option.id) {
this.id = option.id
this.getData();
}
},
methods: {
// 注册
checkPermi,
checkRole,
getData() {
getSafetyDeclaration(this.id).then(res => {
this.SafetyDeclarationTable.declarationType = res.data.declarationType * 1.
this.SafetyDeclarationTable = res.data
if (res.data.declarationImg != "") {
let filePathArray = res.data.declarationImg.split(",");
filePathArray.forEach(item => {
this.img.push({
url: baseUrl + item
})
console.log(this.img);
console.log(baseUrl);
})
// console.log("filePathArray",filePathArray);
}
})
},
deleteImg(e) {
console.log("deleteImg", e.tempFile.uuid);
// console.log("deleteImg",this.SafetyDeclarationTable.ImgUrl);
const index = this.img.findIndex(f => f.uuid === e.tempFile.uuid); // 假设文件通过 url 唯一标识
console.log(index);
if (index !== -1) {
// 移除文件
this.selectList.splice(index, 1);
this.SafetyDeclarationTable.ImgUrl.splice(index, 1)
// console.log();
}
},
submit(ref) {
this.$refs[ref].validate().then(res => {
this.SafetyDeclarationTable.declarationImg = this.joinList()
console.log("提交成功");
console.log("this.SafetyDeclarationTable", this.SafetyDeclarationTable);
addSafetyDeclaration(this.SafetyDeclarationTable).then(res => {
uni.showToast({
title: '提交成功',
icon: 'success', // 成功图标
duration: 1000 // 持续时间为2000ms
});
// 延时执行,确保弹窗有足够的时间显示
setTimeout(() => {
this.$tab.navigateBack(); // 假设这是正确的页面跳转方法,具体方法可能因框架而异
}, 1000);
})
}).catch(err => {
console.log('err', err);
})
},
cancellation() {
this.$tab.navigateBack();
},
// 上传图片
upload(e) {
console.log(e);
this.img.push(e.tempFiles[0])
e.tempFilePaths.forEach(item => {
uploadImg({
filePath: item
}).then(res => {
console.log(res);
this.SafetyDeclarationTable.ImgUrl.push(res.fileName)
})
})
},
// 初始化字典
async initDictType() {
const typeData = await listData({
dictType: "hs_declaration_type"
});
typeData.rows.forEach(item => {
let data = {
value: 0,
text: ""
}
data.value = item.dictValue
data.text = item.dictLabel
this.selectList.push(data)
// console.log(this.selectList);
})
},
// 定义一个方法用于将list拼接成字符串
joinList() {
// 使用数组的join方法以逗号分隔元素
return this.SafetyDeclarationTable.ImgUrl.join(',');
}
},
created() {
this.initDictType();
}
}
</script>
<style lang="scss">
page {
display: flex;
flex-direction: column;
box-sizing: border-box;
background-color: #fff;
height: 90vh;
/* 使页面高度占满整个视口 */
}
.container {
flex: 1;
/* 让 container 占满剩余空间 */
display: flex;
flex-direction: column;
/* 设置为列方向 */
}
.example {
flex: 1;
/* 让 example 占满 container 的剩余空间 */
display: flex;
flex-direction: column;
/* 设置为列方向,确保子元素垂直排列 */
padding: 15px;
background-color: #fff;
}
.segmented-control {
margin-bottom: 15px;
}
.form-item {
display: flex;
align-items: center;
}
// 样式沉底
.button-group {
position: fixed;
bottom: 20px;
left: 0;
/* 使用 margin-top: auto 来将按钮组推到 example 容器的底部 */
display: flex;
width: 100%;
justify-content: space-around;
}
.button-group button {
flex: 1;
background: #fff;
color: #000;
/* 使按钮平分可用空间 */
/* 可能还需要设置一些其他的样式来确保按钮看起来正确,比如 text-align, padding 等 */
}
</style>