feat: 添加治理模块功能

mengfanliang-dev-pitfall
mengfanliang 2024-08-08 11:08:55 +08:00
parent 58ce329781
commit 347f8eef3f
95 changed files with 11134 additions and 436 deletions

View File

@ -29,4 +29,5 @@ export default {
@import './styles/theme.scss';
@import './styles/uview.scss';
@import './styles/home_style.scss';
@import './styles/common.scss';
</style>

1778
Mock/responseData.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,34 +1,91 @@
import {post, upload, uploads} from "../utils/request";
import { post, upload, uploads } from "../utils/request";
export const submitLogin = (params) => post("/app/admin/check", params) // 登录
export const getIDCardDeduplication = (params) => post("/app/user/hasCardIdForApp", params) // 身份证去重
export const getUserDeduplication = (params) => post("/app/user/hasUserNameForApp", params) // 用户名去重
export const getPhoneNumberDeduplication = (params) => post("/app/user/hasPhoneForApp", params) // 手机号去重
export const setRegister = (params) => post("/app/admin/register", params) // 注册
export const setForgotPassword = (params) => post("/app/admin/forgetPassword", params) // 忘记密码
export const getElectronicWorkCard = (params) => post("/app/user/getUserDetailInfoByUserIdForApp", params) // 电子工牌
export const getElectronicWorkCardQRCode = (params) => post("/app/user/generateQRCodeImageByUserId", params) // 电子工牌二维码
export const getEmployedBy = (params) => post("/app/employmentApplyManagement/getEmploymentRecordByUserIdOrCorpInfoId", params) // 就职单位列表
export const setResignationApplication = (params) => post("/app/employmentApplyManagement/edit", params) // 离职申请
export const setRelatedPartyScanning = (params) => post("/app/user/updateUserInfoAfterScanQRCode", params) // 相关方扫码
export const getDataDictionary = (params) => post("/app/dictionaries/getLevels", params) // 数据字典
export const setUploadAttachments = (params) => upload("/app/imgFiles/addSingleImg", params) // 上传附件
export const removeUploadAttachments = (params) => post("/app/imgFiles/deleteImg", params) // 删除附件
export const setRelatedPartyRegistration = (params) => post("/app/user/saveUser", params) // 相关方注册
export const setRelatedPartyUpdate = (params) => post("/app/user/editUser", params) // 相关方修改
export const checkRelatedUnitsPersonCount = (params) => post("/app/user/checkUserCountForApp", params) // 检查相关方单位流动人员数和单位总人数
export const getServiceUnitList = (params) => post("/app/user/getRelatedUnitsListByUserId", params) // 服务单位列表
export const getServiceUnitView = (params) => post("/app/user/getRelatedUnitsDetailById", params) // 服务单位查看
export const setFeedbackUpload = (params) => upload("/app/feedback/upload", params) //反馈问题附件
export const setFeedbackAdd = (params) => post("/app/feedback/add", params) //反馈问题提交
export const getVersion = (params) => post("/app/versionmanager/getVersion", params) //版本更新
export const setUpdatePassword = (params) => post("/app/user/editUserPasswordByUserId", params) //修改密码
export const getUserInfo = (params) => post("/app/user/getDetailByUserIdAndCorpInfoId", params) //用户信息
export const setUserInfo = (params) => post("/app/user/edit", params) //修改用户信息
export const getCertificateInformationList = (params) => post("/app/specialUser/list", params) //证书信息列表
export const getCertificateInformationView = (params) => post("/app/specialUser/goEdit", params) //证书信息查看
export const setCertificateInformationAdd = (params) => upload("/app/specialUser/add", params) //证书信息添加
export const setCertificateInformationEdit = (params) => upload("/app/specialUser/edit", params) //证书信息修改
export const setCertificateInformationEditPost = (params) => post("/app/specialUser/edit", params) //证书信息修改
export const getDeptTree = (params) => post("/api/department/listzTree", params) //用户信息
export const getEMPLOYMENTAPPLYMANAGEMENTID = (params) => post("/app/user/getEMPLOYMENTAPPLYMANAGEMENTID",params)//获取EMPLOYMENTAPPLYMANAGEMENTID
export const submitLogin = (params) => post("/app/admin/check", params); // 登录
export const getIDCardDeduplication = (params) =>
post("/app/user/hasCardIdForApp", params); // 身份证去重
export const getUserDeduplication = (params) =>
post("/app/user/hasUserNameForApp", params); // 用户名去重
export const getPhoneNumberDeduplication = (params) =>
post("/app/user/hasPhoneForApp", params); // 手机号去重
export const setRegister = (params) => post("/app/admin/register", params); // 注册
export const setForgotPassword = (params) =>
post("/app/admin/forgetPassword", params); // 忘记密码
export const getElectronicWorkCard = (params) =>
post("/app/user/getUserDetailInfoByUserIdForApp", params); // 电子工牌
export const getElectronicWorkCardQRCode = (params) =>
post("/app/user/generateQRCodeImageByUserId", params); // 电子工牌二维码
export const getEmployedBy = (params) =>
post(
"/app/employmentApplyManagement/getEmploymentRecordByUserIdOrCorpInfoId",
params
); // 就职单位列表
export const setResignationApplication = (params) =>
post("/app/employmentApplyManagement/edit", params); // 离职申请
export const setRelatedPartyScanning = (params) =>
post("/app/user/updateUserInfoAfterScanQRCode", params); // 相关方扫码
export const getDataDictionary = (params) =>
post("/app/dictionaries/getLevels", params); // 数据字典
export const setUploadAttachments = (params) =>
upload("/app/imgFiles/addSingleImg", params); // 上传附件
export const removeUploadAttachments = (params) =>
post("/app/imgFiles/deleteImg", params); // 删除附件
export const setRelatedPartyRegistration = (params) =>
post("/app/user/saveUser", params); // 相关方注册
export const setRelatedPartyUpdate = (params) =>
post("/app/user/editUser", params); // 相关方修改
export const checkRelatedUnitsPersonCount = (params) =>
post("/app/user/checkUserCountForApp", params); // 检查相关方单位流动人员数和单位总人数
export const getServiceUnitList = (params) =>
post("/app/user/getRelatedUnitsListByUserId", params); // 服务单位列表
export const getServiceUnitView = (params) =>
post("/app/user/getRelatedUnitsDetailById", params); // 服务单位查看
export const setFeedbackUpload = (params) =>
upload("/app/feedback/upload", params); //反馈问题附件
export const setFeedbackAdd = (params) => post("/app/feedback/add", params); //反馈问题提交
export const getVersion = (params) =>
post("/app/versionmanager/getVersion", params); //版本更新
export const setUpdatePassword = (params) =>
post("/app/user/editUserPasswordByUserId", params); //修改密码
export const getUserInfo = (params) =>
post("/app/user/getDetailByUserIdAndCorpInfoId", params); //用户信息
export const setUserInfo = (params) => post("/app/user/edit", params); //修改用户信息
export const getCertificateInformationList = (params) =>
post("/app/specialUser/list", params); //证书信息列表
export const getCertificateInformationView = (params) =>
post("/app/specialUser/goEdit", params); //证书信息查看
export const setCertificateInformationAdd = (params) =>
upload("/app/specialUser/add", params); //证书信息添加
export const setCertificateInformationEdit = (params) =>
upload("/app/specialUser/edit", params); //证书信息修改
export const setCertificateInformationEditPost = (params) =>
post("/app/specialUser/edit", params); //证书信息修改
export const getDeptTree = (params) =>
post("/api/department/listzTree", params); //用户信息
export const getEMPLOYMENTAPPLYMANAGEMENTID = (params) =>
post("/app/user/getEMPLOYMENTAPPLYMANAGEMENTID", params); //获取EMPLOYMENTAPPLYMANAGEMENTID
/** 获取隐患信息 */
export const getHiddenInfo = (params) => post("/app/hidden/goEdit", params);
/** 隐患级别树 */
export const getHiddenLevelTree = (params) =>
post("/dictionaries/listSelectTreeByTkiTree", params);
/** 隐患部位树 */
export const getHiddenPositionTree = (params) =>
post("/app/hidden/getTreehiddenRegionListAll", params);
/** 部门树 */
export const getDepartmentTree = (params) => post("/app/sys/listTree", params);
/** 人员 */
export const getPersonnelList = (params) => post("/app/sys/listUser", params);
/** 上传附件 */
export const setUploadFile = (params) => upload("/app/imgfiles/add", params);
/** 获取图片 */
export const getFileList = (params) => post("/app/imgfiles/listImgs", params);
/** 删除图片 */
export const setFileDelete = (params) => post("/app/imgfiles/delete", params);

View File

@ -0,0 +1,87 @@
<template>
<next-tree
ref="nextTreeRef"
check-strictly
func-mode="radio"
select-parent
:if-search="false"
:tree-data="treeData"
theme-color="#3377ff"
page-height="92vh"
:label-key="'name'"
:value-key="'id'"
:children-key="'children'"
@confirm="fnTreeConfirm"
@cancel="fnTreeCancel"
></next-tree>
</template>
<script>
import { getDepartmentTree } from "@/api";
export default {
props: {
value: {
type: String,
default: "",
},
visible: {
type: Boolean,
required: true,
},
},
data() {
return {
treeData: [],
};
},
watch: {
visible: {
handler: function (newVal, oldVal) {
if (newVal) {
this.$nextTick(() => {
if (this.$refs.nextTreeRef) {
this.$refs.nextTreeRef._show();
this.$refs.nextTreeRef.checkedFunc(this.value);
}
});
} else {
this.$nextTick(() => {
if (this.$refs.nextTreeRef) {
this.$refs.nextTreeRef._hide();
}
});
}
},
immediate: true,
},
},
mounted() {
if (this.visible) {
// this.fnGetData(); //
}
},
methods: {
//
fnTreeConfirm(evt) {
this.$emit("confirm", evt);
this.$emit("update:visible", false);
},
//
fnTreeCancel() {
this.$emit("update:visible", false);
},
async fnGetData() {
const resData = await getDepartmentTree({
loading: false,
});
this.treeData = JSON.parse(resData.zTreeNodes);
},
},
};
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,75 @@
<template>
<view>
<u-form-item
:label="label"
:prop="prop"
:required="required"
@click="visible = true"
>
<div class="select_content">
<u-input
:value="name || '请选择'"
border="none"
input-align="right"
readonly
></u-input>
<u-icon name="arrow-right" />
</div>
</u-form-item>
<u-line />
<department :visible.sync="visible" :value="id" @confirm="fnConfirm" />
</view>
</template>
<script>
import Department from "./department.vue";
export default {
components: { Department },
props: {
label: {
type: String,
default: "部门",
},
prop: {
type: String,
default: "",
},
required: {
type: Boolean,
default: true,
},
clearKey: {
type: String,
default: "",
},
},
data() {
return {
name: "",
id: "",
form: {},
visible: false,
};
},
methods: {
fnConfirm(event) {
this.name = event[0].name;
this.id = event[0].id;
if (JSON.stringify(this.form) !== "{}" && this.clearKey) {
const clearKeys = this.clearKey.split(",");
for (let i = 0; i < clearKeys.length; i++) {
this.form[clearKeys[i]] = "";
}
}
this.visible = false;
},
},
};
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,49 @@
<template>
<view class="fab_button" @click="handleClick">
<block v-if="type === 'plus'">
<u-icon name="plus" color="#fff" size="28rpx"></u-icon>
</block>
<block v-if="type === 'search'">
<u-icon name="search" color="#fff" size="28rpx"></u-icon>
</block>
<block v-if="type === 'scan'">
<u-icon
name="/static/images/scan.png"
color="#fff"
size="28rpx"
></u-icon>
</block>
</view>
</template>
<script>
export default {
props: {
type: {
type: String,
default: 'plus'
}
},
methods: {
handleClick() {
this.$emit('click')
}
}
}
</script>
<style lang="scss" scoped>
.fab_button {
position: fixed;
bottom: 100rpx;
right: 30rpx;
background-color: #3377ff;
border-radius: 50%;
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
}
</style>

View File

@ -0,0 +1,88 @@
<template>
<next-tree
ref="nextTreeRef"
func-mode="radio"
:select-parent="false"
:check-strictly="false"
:if-search="false"
:tree-data="treeData"
theme-color="#3377ff"
page-height="92vh"
:label-key="'name'"
:value-key="'id'"
:children-key="'children'"
@confirm="fnTreeConfirm"
@cancel="fnTreeCancel"
/>
</template>
<script>
import { getHiddenPositionTree } from "@/api";
export default {
props: {
value: {
type: String,
default: "",
},
visible: {
type: Boolean,
required: true,
},
},
data() {
return {
treeData: [],
};
},
watch: {
visible: {
handler: function (newVal, oldVal) {
if (newVal) {
this.$nextTick(() => {
if (this.$refs.nextTreeRef) {
this.$refs.nextTreeRef._show();
this.$refs.nextTreeRef.checkedFunc(this.value);
}
});
} else {
this.$nextTick(() => {
if (this.$refs.nextTreeRef) {
this.$refs.nextTreeRef._hide();
}
});
}
},
immediate: true,
},
},
mounted() {
if (this.visible) {
// this.fnGetData(); //
}
},
methods: {
//
fnTreeConfirm(evt) {
this.$emit("confirm", evt);
this.$emit("update:visible", false);
},
//
fnTreeCancel() {
this.$emit("update:visible", false);
},
async fnGetData() {
const responseData = await getHiddenPositionTree({
loading: false,
});
this.treeData = JSON.parse(responseData.zTreeNodes);
},
},
};
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,71 @@
<template>
<view>
<u-form-item
:label="label"
:prop="prop"
:required="required"
@click="visible = true"
>
<view class="select_content">
<u-input
:value="name || '请选择'"
border="none"
input-align="right"
readonly
/>
<u-icon name="arrow-right"></u-icon>
</view>
</u-form-item>
<u-line />
<hidden-position
:value="id"
:visible.sync="visible"
@confirm="fnConfirm"
/>
</view>
</template>
<script>
import HiddenPosition from "./hidden_position.vue";
export default {
components: { HiddenPosition },
props: {
name: {
type: String,
required: true,
},
id: {
type: String,
required: true,
},
label: {
type: String,
default: "隐患部位",
},
prop: {
type: String,
default: "",
},
required: {
type: Boolean,
default: true,
},
},
data() {
return {
visible: false,
};
},
methods: {
fnConfirm(evt) {
this.name = evt[0].name;
this.id = evt[0].id;
this.visible = false;
},
},
};
</script>

View File

@ -0,0 +1,87 @@
<template>
<next-tree
ref="nextTreeRef"
func-mode="radio"
:select-parent="false"
:check-strictly="false"
:if-search="false"
:tree-data="treeData"
theme-color="#3377ff"
page-height="92vh"
:label-key="'name'"
:value-key="'id'"
:children-key="'children'"
@confirm="fnTreeConfirm"
@cancel="fnTreeCancel"
/>
</template>
<script>
import { getHiddenLevelTree } from "@/api";
export default {
props: {
value: {
type: String,
default: "",
},
visible: {
type: Boolean,
required: true,
},
},
data() {
return {
treeData: [],
};
},
watch: {
visible: {
handler: function (newVal, oldVal) {
if (newVal) {
this.$nextTick(() => {
if (this.$refs.nextTreeRef) {
this.$refs.nextTreeRef._show();
this.$refs.nextTreeRef.checkedFunc(this.value);
}
});
} else {
this.$nextTick(() => {
if (this.$refs.nextTreeRef) {
this.$refs.nextTreeRef._hide();
}
});
}
},
immediate: true,
},
},
mounted() {
if (this.visible) {
// this.fnGetData(); //
}
},
methods: {
//
fnTreeConfirm(evt) {
this.$emit("confirm", evt);
this.$emit("update:visible", false);
},
//
fnTreeCancel() {
this.$emit("update:visible", false);
},
async fnGetData() {
const responseData = await getHiddenLevelTree({
DICTIONARIES_ID: "3babc15144444bdc8d763d0af2bdfff6",
loading: false,
});
this.treeData.value = JSON.parse(resData.zTreeNodes);
},
},
};
</script>

View File

@ -0,0 +1,69 @@
<template>
<view>
<u-form-item
:label="label"
:prop="prop"
:required="required"
@click="visible = true"
>
<view class="select_content">
<u-input
:value="name || '请选择'"
border="none"
input-align="right"
readonly
/>
<u-icon name="arrow-right"></u-icon>
</view>
</u-form-item>
<u-line />
<hidden-type :visible.sync="visible" :value="id" @confirm="fnConfirm" />
</view>
</template>
<script>
import HiddenType from "./hidden_type.vue";
export default {
components: { HiddenType },
props: {
name: {
type: String,
required: true,
},
id: {
type: String,
required: true,
},
label: {
type: String,
default: "隐患类型",
},
prop: {
type: String,
default: "",
},
required: {
type: Boolean,
default: true,
},
},
data() {
return {
visible: false,
};
},
methods: {
fnConfirm(evt) {
this.name = evt[0].name;
this.id = evt[0].id;
this.visible = false;
},
},
};
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,462 @@
<template>
<u-cell-group>
<u-cell :title="data.info.HIDDENDESCR" />
<u-cell title="隐患来源" :value="hiddenSource[data.info.SOURCE]" />
<block v-if="data.info.SOURCE === '2'">
<u-cell title="风险点(单元)" :value="data.info.RISK_UNIT" />
<u-cell title="辨识部位" :value="data.info.IDENTIFICATION" />
<u-cell title="存在风险" :value="data.info.RISK_DESCR" />
<u-cell title="风险分级" :value="data.info.LEVEL" />
<u-cell title="检查内容" :value="data.info.CHECK_CONTENT" />
</block>
<u-cell title="隐患上报位置(经纬度)">
<template #label>
<view v-if="data.info.LONGITUDE && data.info.LATITUDE">
<view>经度:{{ data.info.LONGITUDE }}</view>
<view>纬度:{{ data.info.LATITUDE }}</view>
</view>
</template>
</u-cell>
<u-cell
title="隐患部位"
:value="data.info.hregionName || data.info.HIDDENPART"
/>
<u-cell title="隐患位置描述" :value="data.info.POSITIONDESC" />
<u-cell title="隐患类型" :value="data.info.HIDDENTYPENAME" />
<u-cell title="隐患级别" :value="data.info.HIDDENLEVELNAME" />
<u-cell
title="隐患发现人"
:value="data.hiddenFindPeople.map((item) => item.NAME).join('、')"
/>
<u-cell
title="隐患发现时间"
:value="fnFormatTime(data.info.DISCOVERYTIME)"
/>
<u-cell title="整改类型">
<template #value>
<text v-if="data.info.RECTIFICATIONTYPE === '1'"></text>
<text v-else-if="data.info.RECTIFICATIONTYPE === '2'">限期整改</text>
</template>
</u-cell>
<u-cell title="整改负责部门" :value="data.info.editDeptName" />
<u-cell title="整改负责人" :value="data.info.editUserName" />
<block v-if="data.info.RECTIFICATIONTYPE === '2'">
<u-cell title="整改期限" :value="data.info.editRectificationDeadline" />
</block>
<u-cell title="是否相关方">
<template #value>
<text v-if="data.info.ISRELEVANT === '1'"></text>
<text v-else-if="data.info.ISRELEVANT === '2'"></text>
</template>
</u-cell>
<u-cell title="隐患照片">
<template #label>
<view class="mt-10 flex-start">
<view v-for="(item, index) in data.hImgs" :key="index" class="ml-10">
<u-image
show-loading
width="100rpx"
height="100rpx"
:src="item.FILEPATH"
@click="fnPreviewImage(item.FILEPATH, data.hImgs)"
/>
</view>
</view>
</template>
</u-cell>
<block v-if="data.hiddenVideo.length > 0">
<u-cell title="隐患视频">
<template #value>
<u-icon
name="play-circle-fill"
size="24"
@click="fnPreviewVideo(data.hiddenVideo[0].FILEPATH)"
/>
</template>
</u-cell>
</block>
<view v-for="(item, index) in data.hiddenExamineList" :key="index">
<block v-if="item.TYPE === 4">
<u-divider text-position="left" text="隐患确认"></u-divider>
<u-cell title="隐患级别" :value="item.editLevelName" />
<u-cell title="整改负责人部门" :value="item.editDeptName" />
<u-cell title="整改负责人" :value="item.editUserName" />
<u-cell title="整改完成期限" :value="item.spare3" />
<u-cell title="隐患确认人" :value="data.info.conUserName" />
<u-cell title="隐患确认时间" :value="data.info.CONFIRM_TIME" />
</block>
<block v-if="item.TYPE === 2">
<u-divider text-position="left" text="延期信息"></u-divider>
<u-cell title="申请延期日期" :value="item.CREATTIME" />
<u-cell title="延期日期" :value="fnFormatTime(item.DELAY_TIME)" />
<u-cell title="审核人" :value="data.info.conUserName" />
<u-cell title="处置方案" :value="item.DISPOSAL_PLAN" />
<block v-if="item.DISPOSAL_FILE">
<u-cell title="处置方案附件">
<template #value>
<u-button
type="primary"
size="mini"
shape="circle"
:custom-style="{ width: 'auto' }"
@click="fnPreviewFile(item.DISPOSAL_FILE)"
>
下载
</u-button>
</template>
</u-cell>
</block>
<u-cell title="延期审核状态">
<template #value>
<text v-if="item.STATE === -1"></text>
<text v-if="item.STATE === 1"></text>
<text v-if="item.STATE === 2"></text>
</template>
</u-cell>
<block v-if="item.STATE !== -1">
<u-cell title="审核时间" :value="item.OPERATTIME" />
</block>
</block>
<block v-if="item.TYPE === 1">
<u-divider text-position="left" text="特殊处理审核信息"></u-divider>
<u-cell title="无法整改原因" :label="item.EXAMINE" />
<u-cell title="特殊处置审核状态">
<template #value>
<text v-if="item.STATE === -1"></text>
<text v-if="item.STATE === 1"></text>
<text v-if="item.STATE === 2"></text>
</template>
</u-cell>
<block v-if="item.STATE === 1">
<u-cell title="处置方案" :value="item.DISPOSAL_PLAN" />
<block v-if="item.DISPOSAL_FILE">
<u-cell title="处置方案附件">
<template #value>
<up-button
type="primary"
size="mini"
shape="circle"
:custom-style="{ width: 'auto' }"
@click="fnPreviewFile(item.DISPOSAL_FILE)"
>
下载
</up-button>
</template>
</u-cell>
</block>
</block>
<block v-if="item.STATE !== -1">
<u-cell title="审核时间" :value="item.OPERATTIME" />
<u-cell title="审核人" :value="data.info.conUserName" />
</block>
<block v-if="item.STATE === 2">
<u-cell
title="是否更换整改负责人"
:value="item.spare1 === '1' ? '是' : '否'"
/>
<block v-if="item.spare1 === '1'">
<u-cell title="整改负责人" :value="item.editUserName" />
</block>
</block>
</block>
</view>
<block
v-if="
data.info.STATE === '2' ||
data.info.STATE === '4' ||
data.info.STATE === '10'
"
>
<u-divider text-position="left" text="整改信息"></u-divider>
<u-cell title="整改描述" :label="data.info.RECTIFYDESCR" />
<u-cell title="整改部门" :value="data.info.RECTIFICATIONDEPTNAME" />
<u-cell title="整改人" :value="data.info.RECTIFICATIONORNAME" />
<u-cell title="整改时间" :value="data.info.RECTIFICATIONTIME" />
<u-cell title="投入资金" :value="data.info.INVESTMENT_FUNDS + '元'" />
<u-cell title="整改后图片">
<template #label>
<view class="mt-10 flex-start">
<view
v-for="(item, index) in data.rImgs"
:key="index"
class="ml-10"
>
<u-image
show-loading
width="100rpx"
height="100rpx"
:src="item.FILEPATH"
@click="fnPreviewImage(item.FILEPATH, data.rImgs)"
/>
</view>
</view>
</template>
</u-cell>
<u-cell title="整改方案">
<template #value>
<text v-if="data.info.HAVESCHEME === '0'"></text>
<text v-else-if="data.info.HAVESCHEME === '1'"></text>
</template>
</u-cell>
<block v-if="data.info.HAVESCHEME === '1'">
<u-cell
title="排查日期"
:value="data.rectificationPlanInfo.SCREENINGDATE"
/>
<block v-if="data.rectificationPlanInfo.LISTNAME">
<u-cell
title="隐患清单"
:value="data.rectificationPlanInfo.LISTNAME"
/>
</block>
<u-cell
title="治理标准要求"
:value="data.rectificationPlanInfo.GOVERNSTANDARDS"
/>
<u-cell
title="治理方法"
:value="data.rectificationPlanInfo.GOVERNMETHOD"
/>
<u-cell
title="经费和物资的落实"
:value="data.rectificationPlanInfo.EXPENDITURE"
/>
<u-cell
title="负责治理人员"
:value="data.rectificationPlanInfo.PRINCIPAL"
/>
<u-cell
title="工时安排"
:value="data.rectificationPlanInfo.PROGRAMMING"
/>
<u-cell
title="时限要求"
:value="data.rectificationPlanInfo.TIMELIMITFOR"
/>
<u-cell
title="工作要求"
:value="data.rectificationPlanInfo.JOBREQUIREMENT"
/>
<u-cell
title="其他事项"
:value="data.rectificationPlanInfo.OTHERBUSINESS"
/>
<u-cell title="方案图片">
<template #label>
<view class="mt-10 flex-start">
<view
v-for="(item, index) in data.sImgs"
:key="index"
class="ml-10"
>
<u-image
show-loading
width="100rpx"
height="100rpx"
:src="item.FILEPATH"
@click="fnPreviewImage(item.FILEPATH, data.sImgs)"
/>
</view>
</view>
</template>
</u-cell>
</block>
</block>
<block v-if="data.info.STATE === '4'">
<u-divider text-position="left" text="验收信息"></u-divider>
<block v-if="data.info.RECTIFICATIONTYPE === '1'">
<u-cell title="验收人" :value="data.info.CHECKORNAME" />
</block>
<block v-else>
<view v-for="(item, index) in data.checkList" :key="index">
<u-cell title="验收描述" :label="item.CHECKDESCR" />
<u-cell title="是否合格" :value="item.STATUS === 1 ? '是' : '否'" />
<u-cell title="验收部门" :value="item.CHECKDEPTNAME" />
<u-cell title="验收人" :value="item.CHECKORNAME" />
<u-cell title="验收时间" :value="item.CHECK_TIME" />
<u-cell title="验收图片">
<template #label>
<view class="mt-10 flex-start">
<view
v-for="(item1, index1) in item.cImgs"
:key="index1"
class="ml-10"
>
<u-image
show-loading
width="100rpx"
height="100rpx"
:src="item1.FILEPATH"
@click="fnPreviewImage(item1.FILEPATH, item.cImgs)"
/>
</view>
</view>
</template>
</u-cell>
</view>
</block>
</block>
<u-modal
:show="data.videoDialog.visible"
title="视频预览"
:show-confirm-button="false"
show-cancel-button
cancel-text="关闭"
@cancel="fnCloseVideoDialog"
>
<video
v-if="data.videoDialog.src"
:src="data.videoDialog.src"
style="width: 100%; height: 200px; margin: 10px"
autoplay
/>
</u-modal>
</u-cell-group>
</template>
<script>
import { getHiddenInfo } from "@/api";
import { HIDDEN_LEVEL_COlOR, HIDDEN_SOURCE } from "@/utils/constant";
import dayjs from "dayjs";
import { goEditData as resData } from "@/Mock/responseData.js";
export default {
props: {
hiddenId: {
type: String,
reequired: true,
},
},
data() {
return {
data: {
info: {},
hiddenFindPeople: [],
hImgs: [],
hiddenVideo: [],
rImgs: [],
sImgs: [],
hiddenExamineList: [],
checkList: [],
videoDialog: {
visible: false,
src: "",
},
specialDisposalReviewInfo: {},
rectificationPlanInfo: {},
},
};
},
mounted() {
this.fnGetData();
},
computed: {
hiddenLevelColor() {
return HIDDEN_LEVEL_COlOR;
},
hiddenSource() {
return HIDDEN_SOURCE;
},
selfStore() {
return this.$store;
},
},
methods: {
/** 预览图片处理 */
fnPreviewImage(src, srcArr) {
let urls = srcArr.map((sos) => sos.FILEPATH);
uni.previewImage({
urls,
current: src,
});
},
/** 预览视频处理 */
fnPreviewVideo(src) {
this.data.videoDialog.visible = true;
this.data.videoDialog.src = src;
},
/** 预览文件处理 */
fnPreviewFile(src) {
let { filePath } = this.selfStore.state;
uni.downloadFile({
url: filePath + src,
success: (res) => {
const filePath = res.tempFilePath;
uni.openDocument({
filePath,
});
},
});
},
/** 关闭视频弹窗 */
fnCloseVideoDialog() {
this.data.videoDialog.visible = false;
this.data.videoDialog.src = "";
},
/** 时间格式化 */
fnFormatTime(val) {
return dayjs(val).format("YYYY-MM-DD");
},
//
async fnGetData() {
let { filePath } = this.selfStore.state;
// const responseData = await getHiddenInfo({
// HIDDEN_ID: this.hiddenId
// })
// console.log('responseData :>> ', responseData);
for (let i = 0; i < resData.hImgs.length; i++) {
resData.hImgs[i].FILEPATH = filePath + resData.hImgs[i].FILEPATH;
}
for (let i = 0; i < resData.rImgs.length; i++) {
resData.rImgs[i].FILEPATH = filePath + resData.rImgs[i].FILEPATH;
}
for (let i = 0; i < resData.sImgs.length; i++) {
resData.sImgs[i].FILEPATH = filePath + resData.sImgs[i].FILEPATH;
}
for (let i = 0; i < resData.hiddenVideo.length; i++) {
resData.hiddenVideo[i].FILEPATH =
filePath + resData.hiddenVideo[i].FILEPATH;
}
for (let i = 0; i < resData.checkList.length; i++) {
for (let j = 0; j < resData.checkList[i].cImgs.length; j++) {
resData.checkList[i].cImgs[j].FILEPATH =
filePath + resData.checkList[i].cImgs[j].FILEPATH;
}
}
this.data.info = resData.pd;
this.data.rectificationPlanInfo = resData.hs;
this.data.hiddenFindPeople = resData.hiddenFindPeople;
this.data.hImgs = resData.hImgs;
this.data.rImgs = resData.rImgs;
this.data.sImgs = resData.sImgs;
this.data.checkList = resData.checkList;
this.data.hiddenVideo = resData.hiddenVideo;
this.data.hiddenExamineList = resData.hiddenExa;
this.$emit("throw-basic-info", resData);
},
},
};
</script>
<style lang="scss" scoped>
/deep/ .u-cell__body {
padding: 26rpx 30rpx;
}
</style>

View File

@ -0,0 +1,121 @@
<template>
<next-tree
ref="nextTreeRef"
func-mode="radio"
:select-parent="false"
:check-strictly="false"
:if-search="false"
:tree-data="treeData"
theme-color="#3377ff"
page-height="92vh"
:label-key="'name'"
:value-key="'id'"
:children-key="'children'"
@confirm="fnTreeConfirm"
@cancel="fnTreeCancel"
></next-tree>
</template>
<script>
import { getHiddenLevelTree } from "@/api";
export default {
props: {
value: {
type: String,
default: "",
},
isShowNeglect: {
type: Boolean,
default: true,
},
isShowMore: {
type: Boolean,
default: true,
},
isShowMajor: {
type: Boolean,
default: true,
},
visible: {
type: Boolean,
required: false,
},
},
data() {
return {
treeData: [],
};
},
watch: {
visible: {
handler: function (newVal, oldVal) {
if (newVal) {
this.$nextTick(() => {
if (this.$refs.nextTreeRef) {
this.$refs.nextTreeRef._show();
this.$refs.nextTreeRef.checkedFunc(this.value);
}
});
} else {
this.$nextTick(() => {
if (this.$refs.nextTreeRef) {
this.$refs.nextTreeRef._hide();
}
});
}
},
immediate: true,
},
},
mounted() {
if (this.visible) {
// this.fnGetData(); //
}
},
methods: {
//
fnTreeConfirm(event) {
this.$emit("confirm", evt);
this.$emit("update:visible", false);
},
//
fnTreeCancel() {
this.$emit("update:visible", false);
},
async fnGetData() {
const resData = await getHiddenLevelTree({
DICTIONARIES_ID: "5e7cf8620ba54ad89719d0be62133c7a",
loading: false,
});
const data = JSON.parse(resData.zTreeNodes);
for (let i = 0; i < data.length; i++) {
for (let j = 0; j < data[i].children.length; j++) {
if (!this.isShowMore) {
if (data[i].children[j].id === "jdyh001") {
data[i].children.splice(j, 1);
}
}
if (!this.isShowNeglect) {
if (data[i].children[j].id === "hiddenLevel1001") {
data[i].children.splice(j, 1);
}
}
}
if (!this.isShowMajor) {
if (data[i].id === "hiddenLevel0002") {
data.splice(i, 1);
}
}
}
this.treeData = data;
},
},
};
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,88 @@
<template>
<view>
<u-form-item
:label="label"
:prop="prop"
:required="required"
@click="visible = true"
>
<div class="select_content">
<u-input
:value="name || '请选择'"
border="none"
input-align="right"
readonly
></u-input>
<u-icon name="arrow-right" />
</div>
</u-form-item>
<u-line />
<hidden-level
:value="id"
:visible.sync="visible"
:is-show-neglect="isShowNeglect"
:is-show-more="isShowMore"
:is-show-major="isShowMajor"
@confirm="fnConfirm"
/>
</view>
</template>
<script>
import HiddenLevel from "./hidden_level.vue";
export default {
components: { HiddenLevel },
props: {
label: {
type: String,
default: "隐患级别",
},
prop: {
type: String,
default: "",
},
required: {
type: Boolean,
default: true,
},
isShowNeglect: {
type: Boolean,
default: true,
},
isShowMore: {
type: Boolean,
default: true,
},
isShowMajor: {
type: Boolean,
default: true,
},
name: {
type: String,
required: true,
},
id: {
type: String,
required: true,
},
},
data() {
return {
visible: false,
};
},
methods: {
fnConfirm(event) {
this.name = event[0].name;
this.id = event[0].id;
this.visible = false;
},
},
};
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,53 @@
<template>
<u-sticky bgColor="#ffffff">
<view class="card">
<u-search
v-model="localInputSearchValue"
:showAction="true"
actionText="搜索"
:animation="false"
@search="selfHandlerSearch"
@custom="selfHandlerSearch"
@clear="selfHandlerClear"
/>
</view>
<app-line />
</u-sticky>
</template>
<script>
export default {
props: {
inputSearchValue: {
type: String,
required: true,
},
},
data() {
return {
// 使
localInputSearchValue: this.inputSearchValue,
};
},
watch: {
// prop
inputSearchValue(newVal) {
this.localInputSearchValue = newVal;
},
},
methods: {
selfHandlerSearch() {
this.$emit("search", this.localInputSearchValue);
},
selfHandlerClear() {
this.localInputSearchValue = "";
}
},
};
</script>
<style lang="scss" scoped>
.key-word-search-input-box {
margin: 20rpx;
}
</style>

12
components/line/index.vue Normal file
View File

@ -0,0 +1,12 @@
<template>
<view class="line"></view>
</template>
<script></script>
<style scoped lang="scss">
.line {
background-color: #f4f4f4;
height: 10rpx;
}
</style>

View File

37
components/list/list.vue Normal file
View File

@ -0,0 +1,37 @@
<template>
<view v-if="list.length > 0">
<view class="list">
<u-list @scrolltolower="selfScrollToLower">
<u-list-item v-for="(item, index) in list" :key="index" style="border-bottom: none; padding: 0rpx;">
<view class="item">
<slot :item="item" :index="index" />
</view>
</u-list-item>
</u-list>
</view>
</view>
<empty v-else />
</template>
<script>
export default {
props: {
list: {
type: Array,
required: true,
},
},
data() {
return {}
},
methods: {
selfScrollToLower() {
this.$emit("scrollToLower");
},
},
};
</script>
<style scoped lang="scss"></style>

View File

View File

@ -0,0 +1,91 @@
<template>
<view>
<u-form-item :label="label" :required="required">
<u-button
type="primary"
size="mini"
text="定位"
class="custom_btn"
:custom-style="{
width: '100rpx',
margin: 0,
position: 'absolute',
right: 0,
top: 0,
}"
@click="fnLocation"
/>
</u-form-item>
<u-line />
<u-form-item label="经度" :prop="longitudeProp" :required="required">
<u-input v-model="longitude" border="none" readonly input-align="right" />
</u-form-item>
<u-line />
<u-form-item label="纬度" :prop="latitudeProp" :required="required">
<u-input v-model="latitude" border="none" readonly input-align="right" />
</u-form-item>
<u-line />
</view>
</template>
<script>
export default {
props: {
label: {
type: String,
default: "位置",
},
longitudeProp: {
type: String,
default: "",
},
latitudeProp: {
type: String,
default: "",
},
required: {
type: Boolean,
default: true,
},
longitude: {
type: String,
required: true,
},
latitude: {
type: String,
required: true,
},
},
data() {
return {
selfLongitude: "",
selfLatitude: "",
};
},
mounted() {
this.$on("acceptLocationData", this.handleAcceptLocationData);
},
beforeDestroy() {
this.$off("acceptLocationData", this.handleAcceptLocationData);
},
methods: {
fnLocation() {
uni.navigateTo({
url: "/pages/map/index",
});
},
handleAcceptLocationData(event) {
this.longitude = event.longitue.toString();
this.latitude = event.latitude.toString();
},
},
};
</script>
<style scoped lang="scss">
.custom_btn {
transform: translate(-10px, -11px)
}
</style>

View File

@ -0,0 +1,97 @@
<template>
<view>
<u-form-item
:label="label"
:prop="prop"
:required="required"
@click="fnShowPicker"
>
<view class="select_content">
<u-input
:value="name || '请选择'"
border="none"
input-align="right"
readonly
/>
<u-icon name="arrow-right" />
</view>
</u-form-item>
<u-line />
<u-picker
:show="visible"
:columns="[columns]"
key-name="NAME"
:default-index="[defaultIndex]"
@cancel="visible = false"
@confirm="fnConfirm"
/>
</view>
</template>
<script>
import { getPersonnelList } from "@/api";
export default {
props: {
label: {
type: String,
default: "人员",
},
prop: {
type: String,
default: "",
},
required: {
type: Boolean,
default: true,
},
departmentId: {
type: String,
required: true,
},
},
data() {
return {
name: "",
id: "",
visible: false,
columns: [],
defaultIndex: 0,
};
},
watch: {
departmentId(newVal) {
// this.fnGetData(newVal);
},
},
mounted() {
// this.fnGetData(this.departmentId);
},
methods: {
async fnGetData(DEPARTMENT_ID) {
const resData = await getPersonnelList({
DEPARTMENT_ID,
NOMAIN: "1",
});
this.columns = resData.userList;
},
fnShowPicker() {
this.visible = true;
this.defaultIndex = 0;
for (let i = 0; i < this.columns.length; i++) {
if (this.columns[i].USER_ID === this.id) {
this.defaultIndex = i;
break;
}
}
},
fnConfirm(event) {
this.name = event.value[0].NAME;
this.id = event.value[0].USER_ID;
this.visible = false;
},
},
};
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,53 @@
<template>
<view>
<u-popup :show="visible" mode="right" custom-style="width:70vw">
<view class="card">
<slot />
</view>
<view class="footer flex-between">
<view style="flex: 1">
<u-button text="重置" @click="fnReset" />
</view>
<view style="flex: 1">
<u-button type="primary" text="搜索" @click="fnSearch" />
</view>
</view>
</u-popup>
<app-fab-button type="search" @click="visible = true" />
</view>
</template>
<script>
import AppFabButton from '@/components/fabButton/index.vue';
export default {
components: { AppFabButton },
data() {
return {
visible: false
}
},
methods: {
fnReset() {
this.$emit('reset')
this.fnSearch();
},
fnSearch() {
this.$emit('search')
this.visible = false;
}
}
}
</script>
<style lang="scss" scoped>
.footer {
position: absolute;
bottom: 0;
left: 0;
right: 0;
}
</style>

89
components/time/index.vue Normal file
View File

@ -0,0 +1,89 @@
<template>
<view>
<u-form-item
:label="label"
:prop="prop"
:required="required"
:label-position="labelPosition"
@click="fnShowPicker"
>
<view class="select_content">
<u-input
:value="modelValue || '请选择'"
border="none"
input-align="right"
readonly
/>
<u-icon name="arrow-right"></u-icon>
</view>
</u-form-item>
<u-line />
<u-datetime-picker
v-model="value"
:show="visible"
:max-date="maxDate"
:min-date="minDate"
:mode="mode"
@cancel="visible = false"
@confirm="fnConfirm"
/>
</view>
</template>
<script>
import dayjs from "dayjs";
export default {
props: {
label: {
type: String,
default: "时间",
},
prop: {
type: String,
default: "",
},
mode: {
type: String,
default: "datetime",
},
labelPosition: {
type: String,
default: "left",
},
required: {
type: Boolean,
default: true,
},
maxDate: {
type: Number,
default: dayjs().add(10, "year").valueOf(),
},
minDate: {
type: Number,
default: dayjs().subtract(10, "year").valueOf(),
},
modelValue: {
type: String,
required: true,
},
},
data() {
return {
visible: false,
value: new Date().getTime(),
};
},
methods: {
fnShowPicker() {
this.visible = true;
},
fnConfirm({ mode, value }) {
this.$emit("fn-confirm-emit", { mode, value });
this.visible = false;
},
},
};
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,97 @@
<template>
<view>
<u-form-item
:label="label"
:label-position="labelPosition"
:prop="prop"
:required="required"
>
<u-upload
:file-list="modelValue"
:multiple="multiple"
:max-count="maxCount"
width="79"
height="79"
useBeforeRead
:accept="accept"
@afterRead="fnAfterRead"
@delete="fnDelete"
/>
</u-form-item>
<u-line />
</view>
</template>
<script>
import { setFileDelete } from "@/api";
export default {
props: {
label: {
type: String,
default: "图片",
},
labelPosition: {
type: String,
default: "top",
},
prop: {
type: String,
default: "",
},
required: {
type: Boolean,
default: true,
},
multiple: {
type: Boolean,
default: true,
},
maxCount: {
type: Number,
default: 4,
},
accept: {
type: String,
default: "image",
},
modelValue: {
type: Array,
required: true,
},
},
data() {
return {};
},
methods: {
fnAfterRead({ file, index, name }) {
if (this.multiple) {
//
this.modelValue.push(...file);
} else {
//
this.modelValue.push(file);
}
},
async fnDelete({ file, index, name }) {
uni.showModal({
title: "提示",
content: this.accept === "image" ? "是否删除该图片" : "是否删除该视频",
success: async (res) => {
if (res.confirm) {
if (file.IMGFILES_ID) {
await setFileDelete({ IMGFILES_ID: event.file.IMGFILES_ID });
}
this.modelValue.splice(index, 1);
}
},
fail: (err) => reject(err),
});
},
},
};
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,34 @@
import { post, upload, uploads } from '../../utils/request';
/** 获取隐患确认的列表数据 */
export const getHiddenDangerConfirmList = (params) => post('/app/hidden/listGwj', params);
/** 隐患确认提交 */
export const setHiddenConfirmSubmit = (params) =>
post("/app/hidden/confirm", params);
/** 隐患列表 */
export const getHiddenList = (params) => post('/app/hidden/list', params);
/** 特殊处置审核列表 */
export const getHiddenSpecialDisposalReviewList = (params) =>
post("/app/hiddenexamine/list", params);
/** 特殊处置审核提交 */
export const setHiddenSpecialDisposalReviewSubmit = (params) =>
post("/app/hiddenexamine/specialExamine", params);
/** 延期审核提交 */
export const setHiddenDelayReviewSubmit = (params) =>
post("/app/hiddenexamine/delayedExamine", params);
/** 当前人是否能验收当前隐患 */
export const getHiddenAcceptanceCurrentPersonnelIsCheck = (params) =>
post("/app/hidden/isChek", params);
/** 隐患验收提交 */
export const setHiddenAcceptanceSubmit = (params) =>
post("/app/hidden/check", params);
/** 隐患删除 */
export const setHiddenDelete = (params) => post("/app/hidden/delete", params);

View File

@ -0,0 +1,88 @@
<template>
<view class="container">
<view class="card">
<app-hidden-view :hidden-id="hiddenId" />
<view class="card">
<u-form
ref="formRef"
label-position="left"
:model="form"
:rules="rules"
label-width="auto"
>
<u-form-item label="是否通过" prop="POSTPONE_AUDIT" required>
<u-radio-group v-model="form.POSTPONE_AUDIT" direction="horizontal">
<u-radio name="1" label="通过" />
<u-radio name="2" label="不通过" />
</u-radio-group>
</u-form-item>
<u-line />
<view class="mt-10">
<u-button
type="primary"
shape="circle"
text="提交"
:throttle-time="1000"
@click="fnSubmit"
/>
</view>
</u-form>
</view>
</view>
</view>
</template>
<script>
import AppHiddenView from "@/components/hiddenView/index.vue";
import useFormValidate from "@/utils/useFormValidate";
import { setHiddenDelayReviewSubmit } from "../../api";
export default {
components: { AppHiddenView },
onLoad(query) {
this.hiddenId = query.HIDDEN_ID;
this.hiddenExamineId = query.HIDDENEXAMINE_ID;
},
data() {
return {
store: this.$store,
hiddenId: "",
hiddenExamineId: "",
form: {
POSTPONE_AUDIT: "", //
},
rules: {
POSTPONE_AUDIT: {
type: "string",
required: true,
message: "请选择延期审核是否通过",
trigger: ["blur", "change"],
},
},
};
},
methods: {
async fnSubmit() {
await useFormValidate(this.$refs.formRef);
await setHiddenDelayReviewSubmit({
STATE: form.value.POSTPONE_AUDIT,
HIDDENEXAMINE_ID: hiddenExamineId.value,
loginUserId: userInfo.USER_ID,
USERNAME: userInfo.NAME,
});
uni.showToast({
icon: "none",
title: "提交成功",
});
setTimeout(() => {
uni.navigateBack();
}, 1000);
},
},
};
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,170 @@
<!-- 延期审核页面 -->
<template>
<view>
<!-- 吸顶搜索框 start -->
<key-word-search-input
:inputSearchValue="searchForm.HIDDENDESCR"
@search="handleSearch"
/>
<!-- 吸顶搜索框 end -->
<!-- 列表渲染 start -->
<list :list="list" @scroll-to-lower="scrollToLower">
<template #default="{ item }">
<view class="flex-between main-title">
<view class="u-line-1">{{ item.HIDDENDESCR || "暂无" }}</view>
<view :class="hiddenLevelColor[item.HIDDENLEVEL]">
{{ item.HIDDENLEVELNAME }}
</view>
</view>
<view class="flex-between subtitle mt-5">
<view>来源{{ hiddenSource[item.SOURCE] }}</view>
</view>
<view class="flex-between subtitle mt-5">
<view>隐患发现人{{ item.findUserNames || "暂无" }}</view>
<view>
隐患发现时间{{
item.DISCOVERYTIME ? formatTime(item.DISCOVERYTIME) : "暂无"
}}
</view>
</view>
<view class="flex-between subtitle mt-5">
<view>隐患确认人{{ item.confirmUserName || "暂无" }}</view>
<view>
隐患确认时间{{
item.CONFIRM_TIME ? formatTime(item.CONFIRM_TIME) : "暂无"
}}
</view>
</view>
<view class="flex-between subtitle mt-5">
<view>
隐患状态
<text v-if="item.exaSTATE !== -1"></text>
<text v-else></text>
</view>
<view class="flex-between">
<view v-if="item.exaSTATE === -1">
<u-button
type="primary"
size="mini"
shape="circle"
@click="handleClickDeferredAudit(item)"
>
延期审核
</u-button>
</view>
<view class="ml-10">
<u-button
type="primary"
size="mini"
shape="circle"
@click="handleClickView(item)"
>
查看
</u-button>
</view>
</view>
</view>
</template>
</list>
</view>
</template>
<script>
import keyWordSearchInput from "@/components/keyWordSearchInput/index.vue";
import List from "@/components/list/list.vue";
import * as specialDisposalReviewApi from "../../api/index";
import dayjs from "dayjs";
import { HIDDEN_LEVEL_COlOR, HIDDEN_SOURCE } from "@/utils/constant";
import { delay_review_list } from "@/Mock/responseData.js";
export default {
components: { keyWordSearchInput, List },
data() {
return {
store: this.$store, // store
searchForm: {
HIDDENDESCR: "",
},
isRequestEnd: false, //
pagination: {
showCount: 10,
currentPage: 1,
stateConfirm: "0",
total: 0,
},
list: [],
};
},
created() {},
mounted() {},
//
onShow() {
this.getList();
},
computed: {
hiddenLevelColor() {
return HIDDEN_LEVEL_COlOR;
},
hiddenSource() {
return HIDDEN_SOURCE;
},
},
methods: {
/** 获取列表数据 */
getList() {
if (this.isRequestEnd) return null;
uni.showLoading({
title: "加载中",
});
let { USER_ID, CORPINFO_ID, DEPARTMENT_ID } = this.store.state.userInfo;
// specialDisposalReviewApi.getHiddenSpecialDisposalReviewList({
// USER_ID: USER_ID,
// CORPINFO_ID,
// currentPage: this.pagination.currentPage,
// showCount: this.pagination.showCount,
// DISPOSESTATE: 2,
// stateConfirm: this.pagination.stateConfirm,
// USERDEPT: DEPARTMENT_ID,
// SELFUSERID: USER_ID,
// corpinfoId: CORPINFO_ID,
// loginUserId: USER_ID,
// });
// mock
setTimeout(() => {
this.list = delay_review_list;
this.pagination.total = delay_review_list.length;
uni.hideLoading();
}, 400);
},
/** 格式化日期时间 */
formatTime(val) {
return dayjs(val).format("YYYY-MM-DD");
},
/** 处置审核按钮事件 */
handleClickDeferredAudit(ext) {
uni.$u.route(
"/hiddenManageSubPackages/pages/delay_review/delay_review",
{
HIDDEN_ID: ext.HIDDEN_ID,
HIDDENEXAMINE_ID: ext.HIDDENEXAMINE_ID,
}
);
},
/** 查看按钮事件 */
handleClickView(ext) {
uni.$u.route("/hiddenManageSubPackages/pages/delay_review/view", {
HIDDEN_ID: ext.HIDDEN_ID,
HIDDENEXAMINE_ID: ext.HIDDENEXAMINE_ID,
});
},
},
};
</script>

View File

@ -0,0 +1,32 @@
<template>
<view class="container">
<view class="card">
<app-hidden-view :hidden-id="hiddenId" />
</view>
</view>
</template>
<script>
import AppHiddenView from "@/components/hiddenView/index.vue";
export default {
components: { AppHiddenView },
onLoad(query) {
this.hiddenId = query.HIDDEN_ID;
this.hiddenExamineId = query.HIDDENEXAMINE_ID;
},
mounted() { },
data() {
return {
hiddenId: "",
hiddenExamineId: "",
};
},
};
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,195 @@
<template>
<view class="container">
<view class="card">
<!-- 隐患详情查看 -->
<app-hidden-view
:hidden-id="hiddenId"
@throw-basic-info="info = $event.pd"
/>
<!-- 隐患验收 -->
<view v-if="isSubmit === '0'" class="card">
<u-form
ref="formRef"
label-position="left"
:model="form"
:rules="rules"
label-width="auto"
>
<u-divider text-position="left" text="隐患验收"></u-divider>
<u-form-item label="是否合格" prop="ISQUALIFIED" required>
<u-radio-group v-model="form.ISQUALIFIED" direction="horizontal">
<u-radio name="1" label="是" />
<u-radio name="0" label="否" />
</u-radio-group>
</u-form-item>
<u-line />
<block v-if="form.ISQUALIFIED === '1'">
<u-form-item
label="验收描述"
prop="CHECKDESCR"
label-position="top"
required
>
<u-textarea
v-model="form.CHECKDESCR"
placeholder="请输入验收描述"
border="none"
auto-height
/>
</u-form-item>
<u-line />
<app-time
:model-value="form.CHECK_TIME"
label="验收日期"
prop="CHECK_TIME"
mode="date"
@fn-confirm-emit="fnConfirmEmit"
/>
<app-upload
:model-value="form.acceptanceFile"
label="验收图片"
prop="acceptanceFile"
/>
</block>
<view class="mt-10">
<u-button
type="primary"
shape="circle"
text="提交"
:throttle-time="1000"
@click="fnSubmit"
/>
</view>
</u-form>
</view>
</view>
</view>
</template>
<script>
import AppHiddenView from "@/components/hiddenView/index.vue";
import AppTime from "@/components/time/index.vue";
import AppUpload from "@/components/upload/index.vue";
import {
getHiddenAcceptanceCurrentPersonnelIsCheck,
setHiddenAcceptanceSubmit,
} from "../../api";
import dayjs from 'dayjs';
import useFormValidate from "@/utils/useFormValidate";
export default {
components: { AppHiddenView, AppTime, AppUpload },
data() {
return {
store: this.$store,
hiddenId: "",
isSubmit: "",
info: {},
form: {
ISQUALIFIED: "1",
CHECKDESCR: "",
CHECK_TIME: "",
acceptanceFile: [],
},
//
rules: {
ISQUALIFIED: {
type: "string",
required: true,
message: "请选择是否合格",
trigger: ["blur", "change"],
},
CHECKDESCR: {
type: "string",
required: true,
message: "请输入验收描述",
trigger: ["blur", "change"],
},
CHECK_TIME: {
type: "string",
required: true,
message: "请选择验收日期",
trigger: ["blur", "change"],
},
acceptanceFile: {
type: "array",
required: true,
message: "请上传验收图片",
trigger: ["blur", "change"],
},
},
};
},
onLoad(query) {
this.hiddenId = query.HIDDEN_ID;
this.fnGetCurrentPersonnelIsCheck();
},
methods: {
async fnGetCurrentPersonnelIsCheck() {
// const { isTrue } = await getHiddenAcceptanceCurrentPersonnelIsCheck({
// HIDDEN_ID: this.hiddenId,
// CHECKOR: this.store.state.userInfo.USER_ID,
// });
// console.log('isTrue :>> ', isTrue);
// this.isSubmit = isTrue;
this.isSubmit = "success"; // todo,
},
async fnUploadFile(filePath, FOREIGN_KEY, TYPE) {
await setUploadFile({
filePath,
formData: {
FOREIGN_KEY,
TYPE,
},
});
},
async fnSubmit() {
await useFormValidate(this.$refs.formRef);
console.log('this.form :>> ', this.form);
// const { check } = await setHiddenAcceptanceSubmit({
// HIDDEN_ID: this.hiddenId,
// CHECKOR: this.store.state.userInfo.USER_ID,
// USERNAME: this.store.state.userInfo.NAME,
// INSPECTION_ID: this.info.FOREIGN_ID,
// ...this.form,
// });
// for (let i = 0; i < this.form.acceptanceFile.length; i++) {
// await this.fnUploadFile(
// this.form.acceptanceFile[i].url,
// check.HIDDENCHECK_ID,
// 5
// );
// }
uni.showToast({
icon: "none",
title: "提交成功",
});
setTimeout(() => {
uni.navigateBack();
}, 1000);
},
fnConfirmEmit({ mode, value }) {
if (mode === "datetime") {
this.form = {
...this.form,
CHECK_TIME: dayjs(value).format("YYYY-MM-DD HH:mm"),
};
} else if (mode === "date") {
this.form = {
...this.form,
CHECK_TIME: dayjs(value).format("YYYY-MM-DD"),
};
} else if (mode === "year-month") {
this.form = {
...this.form,
CHECK_TIME: dayjs(value).format("YYYY-MM"),
};
}
}
},
};
</script>

View File

@ -0,0 +1,205 @@
<template>
<view>
<!-- 吸顶搜索框 start -->
<key-word-search-input
:inputSearchValue="searchForm.HIDDENDESCR"
@search="handleSearch"
/>
<!-- 吸顶搜索框 end -->
<!-- 列表渲染 start -->
<list :list="list" @scroll-to-lower="scrollToLower">
<template #default="{ item }">
<view class="flex-between main-title">
<view class="u-line-1">{{ item.HIDDENDESCR || "暂无" }}</view>
<view :class="hiddenLevelColor[item.HIDDENLEVEL]">
{{ item.HIDDENLEVELNAME }}
</view>
</view>
<view class="flex-between subtitle mt-5">
<view>来源{{ hiddenSource[item.SOURCE] }}</view>
</view>
<view class="flex-between subtitle mt-5">
<view>整改人{{ item.RECTIFICATIONORNAME || "暂无" }}</view>
<view>
整改时间{{
item.RECTIFICATIONTIME
? formatTime(item.RECTIFICATIONTIME)
: "暂无"
}}
</view>
</view>
<view class="flex-between subtitle mt-5">
<view>隐患发现人{{ item.findUserNames || "暂无" }}</view>
<view>
隐患发现时间{{
item.DISCOVERYTIME ? formatTime(item.DISCOVERYTIME) : "暂无"
}}
</view>
</view>
<view class="flex-between subtitle mt-5">
<view>隐患确认人{{ item.confirmUserName || "暂无" }}</view>
<view>
隐患确认时间{{
item.CONFIRM_TIME ? formatTime(item.CONFIRM_TIME) : "暂无"
}}
</view>
</view>
<view class="flex-between subtitle mt-5">
<view>隐患状态{{ statusList[item.STATE] }}</view>
<view class="flex-between">
<view>
<u-button
type="primary"
size="mini"
shape="circle"
@click="handleClickAcceptance(item)"
>
验收
</u-button>
</view>
<view class="ml-10">
<u-button
type="primary"
size="mini"
shape="circle"
@click="handleClickView(item)"
>
查看
</u-button>
</view>
</view>
</view>
</template>
</list>
<!-- 列表渲染 end -->
</view>
</template>
<script>
import keyWordSearchInput from "@/components/keyWordSearchInput/index.vue";
import List from "@/components/list/list.vue";
import * as HiddenAcceptanceApi from "../../api/index";
import dayjs from "dayjs";
import { HIDDEN_LEVEL_COlOR, HIDDEN_SOURCE } from "@/utils/constant";
import { hidden_acceptance_list } from "@/Mock/responseData.js";
export default {
components: { keyWordSearchInput, List },
onLoad() {},
data() {
return {
store: this.$store, // store
searchForm: {
HIDDENDESCR: "",
},
isRequestEnd: false, //
pagination: {
showCount: 10,
currentPage: 1,
stateConfirm: "0",
total: 0,
},
statusList: {
"-2": "待确认",
"-1": "已过期",
1: "未整改",
2: "已整改",
3: "已复查",
4: "已验收",
5: "已忽略",
6: "重大隐患",
7: "待处理特殊隐患",
8: "特殊处理隐患",
},
list: [],
};
},
//
onShow() {
this.getList();
},
created() {},
computed: {
hiddenLevelColor() {
return HIDDEN_LEVEL_COlOR;
},
hiddenSource() {
return HIDDEN_SOURCE;
},
},
mounted() {},
methods: {
/** 处理搜索事件 */
async handleSearch(val) {
this.pagination = {
...this.pagination,
currentPage: 1,
showCount: 10,
total: 0,
};
await this.getList(val);
},
/** 获取列表数据 */
getList() {
if (this.isRequestEnd) return null;
uni.showLoading({
title: "加载中",
});
let { USER_ID, CORPINFO_ID, DEPARTMENT_ID } = this.store.state.userInfo;
// HiddenAcceptanceApi.getHiddenList({
// USER_ID: USER_ID,
// CORPINFO_ID,
// currentPage: this.pagination.currentPage,
// showCount: this.pagination.showCount,
// DISPOSESTATE: 2,
// stateConfirm: this.pagination.stateConfirm,
// USERDEPT: DEPARTMENT_ID,
// SELFUSERID: USER_ID,
// corpinfoId: CORPINFO_ID,
// loginUserId: USER_ID,
// });
// mock
setTimeout(() => {
this.list = hidden_acceptance_list;
this.pagination.total = hidden_acceptance_list.length;
uni.hideLoading();
}, 400);
},
/** 格式化日期时间 */
formatTime(val) {
return dayjs(val).format("YYYY-MM-DD");
},
/** 向下滚动加载数据 */
async scrollToLower() {
this.pagination.currentPage = this.pagination.currentPage++;
if (this.total >= this.pagination.currentPage) await this.getList();
},
/** 验收按钮点击事件 */
handleClickAcceptance(ext) {
uni.$u.route(
"/hiddenManageSubPackages/pages/hidden_acceptance/acceptance",
{
HIDDEN_ID: ext.HIDDEN_ID,
}
);
},
/** 查看按钮点击事件 */
handleClickView(ext) {
uni.$u.route("/hiddenManageSubPackages/pages/hidden_acceptance/view", {
HIDDEN_ID: ext.HIDDEN_ID,
});
},
},
};
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,27 @@
<template>
<view class="container">
<view class="card">
<app-hidden-view :hidden-id="hiddenId" />
</view>
</view>
</template>
<script setup>
import AppHiddenView from "@/components/hiddenView/index.vue";
export default {
components: { AppHiddenView },
onLoad(query) {
this.hiddenId = query.HIDDEN_ID;
},
data() {
return {
hiddenId: "",
};
},
};
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,214 @@
<template>
<view class="container">
<view class="card">
<!-- 隐患详情查看 -->
<app-hidden-view
:hidden-id="hiddenId"
@throw-basic-info="form = { ...form, ...$event.pd }"
/>
<!-- 隐患确认 -->
<view class="card">
<u-form
ref="formRef"
label-position="left"
:model="form"
:rules="rules"
label-width="auto"
>
<u-divider text-position="left" text="隐患确认"></u-divider>
<app-hidden-level
:id="form.HIDDENLEVEL"
:name="form.HIDDENLEVELNAME"
:is-show-more="false"
:is-show-major="false"
prop="HIDDENLEVELNAME"
label="隐患级别"
/>
<block v-if="form.RECTIFICATIONTYPE === '1'">
<up-form-item label="是否整改完成" prop="isTrue" required>
<up-radio-group v-model="form.isTrue" direction="horizontal">
<up-radio name="1" label="是" />
<up-radio name="2" label="否" />
</up-radio-group>
</up-form-item>
<up-line />
</block>
<block
v-if="
(form.RECTIFICATIONTYPE === '2' &&
form.HIDDENLEVEL !== 'hiddenLevel1001') ||
form.isTrue === '2'
"
>
<app-department
:id="form.RECTIFICATIONDEPT"
:name="form.RECTIFICATIONDEPTNAME"
:form="form"
clear-key="RECTIFICATIONORNAME,RECTIFICATIONOR"
prop="RECTIFICATIONDEPTNAME"
label="整改负责人部门"
/>
<app-personnel
:id="form.RECTIFICATIONOR"
:name="form.RECTIFICATIONORNAME"
:department-id="form.RECTIFICATIONDEPT"
prop="RECTIFICATIONORNAME"
label="整改负责人"
/>
<app-time
:model-value="form.RECTIFICATIONDEADLINE"
label="整改期限"
prop="RECTIFICATIONDEADLINE"
mode="date"
@fn-confirm-emit="fnConfirmEmit"
/>
</block>
<view class="mt-10 flex-between">
<view
v-if="form.SOURCE !== '4' && form.SOURCE !== '5'"
style="flex: 1; margin-right: 2%"
>
<u-button
type="error"
shape="circle"
text="打回"
@click="
route({
url: '/application/pages/hidden_confirm/reject',
params: {
HIDDEN_ID: hiddenId,
},
})
"
/>
</view>
<view style="flex: 1">
<u-button
type="primary"
shape="circle"
text="保存"
:throttle-time="1000"
@click="fnSubmit"
/>
</view>
</view>
</u-form>
</view>
</view>
</view>
</template>
<script>
import AppHiddenView from "@/components/hiddenView/index.vue";
import AppHiddenLevel from "@/components/hidden_level/hidden_level.vue";
import AppDepartment from "@/components/department/index.vue";
import AppPersonnel from "@/components/personnel/index.vue";
import AppTime from "@/components/time/index.vue";
import dayjs from "dayjs";
import useFormValidate from "@/utils/useFormValidate";
import { setHiddenConfirmSubmit } from "@/hiddenManageSubPackages/api";
export default {
components: {
AppHiddenView,
AppHiddenLevel,
AppDepartment,
AppPersonnel,
AppTime,
},
data() {
return {
store: this.$store,
hiddenId: "",
form: {
isTrue: "1",
HIDDENLEVEL: "",
HIDDENLEVELNAME: "",
RECTIFICATIONDEPT: "",
RECTIFICATIONDEPTNAME: "",
RECTIFICATIONOR: "",
RECTIFICATIONORNAME: "",
RECTIFICATIONDEADLINE: "",
},
//
rules: {
HIDDENLEVELNAME: {
type: "string",
required: true,
message: "请选择隐患级别",
trigger: ["blur", "change"],
},
isTrue: {
type: "string",
required: true,
message: "请选择是否整改完成",
trigger: ["blur", "change"],
},
RECTIFICATIONDEPTNAME: {
type: "string",
required: true,
message: "请选择整改负责人部门",
trigger: ["blur", "change"],
},
RECTIFICATIONORNAME: {
type: "string",
required: true,
message: "请选择整改负责人",
trigger: ["blur", "change"],
},
RECTIFICATIONDEADLINE: {
type: "string",
required: true,
message: "请选择整改期限",
trigger: ["blur", "change"],
},
},
};
},
onLoad(query) {
this.hiddenId = query.HIDDEN_ID;
},
mounted() {},
methods: {
async fnSubmit() {
await useFormValidate(this.$refs.formRef);
await setHiddenConfirmSubmit({
USERNAME: this.store.state.userInfo.NAME,
HIDDEN_ID: this.hiddenId,
HIDDENLEVEL: this.form.value.HIDDENLEVEL,
RECTIFICATIONDEPT: this.form.value.RECTIFICATIONDEPT,
RECTIFICATIONDEADLINE: this.form.value.RECTIFICATIONDEADLINE,
RECTIFICATIONOR: this.form.value.RECTIFICATIONOR,
isTrue: this.form.value.isTrue,
});
uni.showToast({
icon: "none",
title: "提交成功",
});
setTimeout(() => {
uni.navigateBack();
}, 1000);
},
fnConfirmEmit({ mode, value }) {
if (mode === "datetime") {
this.form = {
...this.form,
RECTIFICATIONDEADLINE: dayjs(value).format("YYYY-MM-DD HH:mm"),
};
} else if (mode === "date") {
this.form = {
...this.form,
RECTIFICATIONDEADLINE: dayjs(value).format("YYYY-MM-DD"),
};
} else if (mode === "year-month") {
this.form = {
...this.form,
RECTIFICATIONDEADLINE: dayjs(value).format("YYYY-MM"),
};
}
},
},
};
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,192 @@
<!-- 隐患确认组件 -->
<template>
<view>
<!-- 吸顶搜索框 start -->
<key-word-search-input
:inputSearchValue="searchForm.HIDDENDESCR"
@search="handleSearch"
/>
<!-- 吸顶搜索框 end -->
<!-- 列表渲染 start -->
<list :list="list" @scroll-to-lower="scrollToLower">
<template #default="{ item }">
<view class="flex-between main-title">
<view class="u-line-1">{{ item.HIDDENDESCR || "暂无" }}</view>
<view :class="hiddenLevelColor[item.HIDDENLEVEL]">
{{ item.HIDDENLEVELNAME }}
</view>
</view>
<view class="flex-between subtitle mt-5">
<view>来源{{ hiddenSource[item.SOURCE] }}</view>
</view>
<view class="flex-between subtitle mt-5">
<view>隐患发现人{{ item.findUserNames || "暂无" }}</view>
<view>
隐患发现时间{{
item.DISCOVERYTIME ? formatTime(item.DISCOVERYTIME) : "暂无"
}}
</view>
</view>
<view class="flex-between subtitle mt-5">
<view>
隐患确认状态{{
item.STATE === "-2"
? "待确认"
: item.STATE === "16"
? "已打回"
: "已确认"
}}
</view>
<view class="flex-between">
<view
v-if="
item.STATE === '-2' && userInfo.USER_ID === item.CONFIRM_USER
"
>
<u-button
type="primary"
size="mini"
shape="circle"
@click="handleClickConfirm(item)"
>
确认
</u-button>
</view>
<view class="ml-10">
<u-button
type="primary"
size="mini"
shape="circle"
@click="handleClickView(item)"
>
查看
</u-button>
</view>
</view>
</view>
</template>
</list>
<!-- 列表渲染 end -->
</view>
</template>
<script>
import keyWordSearchInput from "@/components/keyWordSearchInput/index.vue";
import List from "@/components/list/list.vue";
import * as HiddenDangerConfirmApi from "../../api/index";
import dayjs from "dayjs";
import { HIDDEN_LEVEL_COlOR, HIDDEN_SOURCE } from "@/utils/constant";
import { listMock } from "@/Mock/responseData.js";
export default {
components: { keyWordSearchInput, List },
data() {
return {
store: this.$store, // store
searchForm: {
HIDDENDESCR: "",
},
isRequestEnd: false, //
pagination: {
showCount: 10,
currentPage: 1,
stateConfirm: "0",
total: 0,
},
list: [],
};
},
created() {},
mounted() {},
//
onShow() {
this.getList();
},
computed: {
hiddenLevelColor() {
return HIDDEN_LEVEL_COlOR;
},
hiddenSource() {
return HIDDEN_SOURCE;
},
userInfo() {
return this.$store.getters.getUserInfo;
},
},
methods: {
/** 处理搜索事件 */
async handleSearch(val) {
this.pagination = {
...this.pagination,
currentPage: 1,
showCount: 10,
total: 0,
};
await this.getList(val);
},
/** 获取列表数据 */
getList() {
if (this.isRequestEnd) return null;
uni.showLoading({
title: "加载中",
});
let { USER_ID, CORPINFO_ID, DEPARTMENT_ID } = this.store.state.userInfo;
// HiddenDangerConfirmApi.getHiddenDangerConfirmList({
// USER_ID: USER_ID,
// CORPINFO_ID,
// currentPage: this.pagination.currentPage,
// showCount: this.pagination.showCount,
// DISPOSESTATE: 2,
// stateConfirm: this.pagination.stateConfirm,
// USERDEPT: DEPARTMENT_ID,
// SELFUSERID: USER_ID,
// corpinfoId: CORPINFO_ID,
// loginUserId: USER_ID,
// });
// mock
setTimeout(() => {
this.list = listMock;
this.pagination.total = listMock.length;
uni.hideLoading();
}, 400);
},
/** 格式化日期时间 */
formatTime(val) {
return dayjs(val).format("YYYY-MM-DD");
},
/** 向下滚动加载数据 */
async scrollToLower() {
this.pagination.currentPage = this.pagination.currentPage++;
if (this.total >= this.pagination.currentPage) await this.getList();
},
/** 处理点击确认按钮事件 */
handleClickConfirm(ext) {
uni.$u.route(
"/hiddenManageSubPackages/pages/hidden_confirm/confirm",
{
HIDDEN_ID: ext.HIDDEN_ID,
}
);
},
/** 处理点击查看按钮事件 */
handleClickView(ext) {
uni.$u.route(
"/hiddenManageSubPackages/pages/hidden_confirm/view",
{
HIDDEN_ID: ext.HIDDEN_ID,
}
)
}
},
};
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,92 @@
<template>
<view class="container">
<view class="card">
<view class="card">
<u-form
ref="formRef"
label-position="top"
:model="form"
:rules="rules"
label-width="auto"
>
<u-form-item label="打回原因" prop="REJECTOPINION" required>
<u-textarea
v-model="form.REJECTOPINION"
placeholder="请输入打回原因"
border="none"
auto-height
/>
</u-form-item>
<u-line />
<view class="mt-10">
<u-button
type="primary"
shape="circle"
text="提交"
:throttle-time="1000"
@click="fnSubmit"
/>
</view>
</u-form>
</view>
</view>
</view>
</template>
<script>
import dayjs from "dayjs";
export default {
props: {
label: {
type: String,
default: "时间",
},
prop: {
type: String,
default: "",
},
mode: {
type: String,
default: "datetime",
},
labelPosition: {
type: String,
default: "left",
},
required: {
type: Boolean,
default: true,
},
maxDate: {
type: Number,
default: dayjs().add(10, "year").valueOf(),
},
minDate: {
type: Number,
default: dayjs().subtract(10, "year").valueOf(),
},
},
data() {
return {
modelValue: "",
visible: false,
value: new Date().getTime(),
};
},
methods: {
fnShowPicker() {
this.visible = true;
},
fnConfirm({ mode, value }) {
if (mode === "datetime")
this.modelValue = dayjs(value).format("YYYY-MM-DD HH:mm");
else if (mode === "date")
this.modelValue = dayjs(value).format("YYYY-MM-DD");
else if (mode === "year-month")
this.modelValue = dayjs(value).format("YYYY-MM");
this.visible = false;
},
},
};
</script>

View File

@ -0,0 +1,27 @@
<template>
<view class="container">
<view class="card">
<app-hidden-view :hidden-id="hiddenId" />
</view>
</view>
</template>
<script>
import AppHiddenView from "@/components/hiddenView/index.vue";
export default {
components: { AppHiddenView },
onLoad(query) {
this.hiddenId = query.HIDDEN_ID;
},
data() {
return {
hiddenId: "",
};
}
};
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,158 @@
<template>
<view>
<!-- 吸顶搜索框 start -->
<key-word-search-input
:inputSearchValue="searchForm.HIDDENDESCR"
@search="handleSearch"
/>
<!-- 吸顶搜索框 end -->
<!-- 列表渲染 start -->
<list :list="list" @scroll-to-lower="scrollToLower">
<template #default="{ item }">
<view class="flex-between main-title">
<view class="u-line-1">{{ item.HIDDENDESCR || "暂无" }}</view>
<view :class="hiddenLevelColor[item.HIDDENLEVEL]">
{{ item.HIDDENLEVELNAME }}
</view>
</view>
<view class="flex-between subtitle mt-5">
<view>来源{{ hiddenSource[item.SOURCE] }}</view>
</view>
<view class="flex-between subtitle mt-5">
<view>隐患发现人{{ item.findUserNames || "暂无" }}</view>
<view>
隐患发现时间{{
item.DISCOVERYTIME
? formatHiddenBaseTime(item.DISCOVERYTIME)
: "暂无"
}}
</view>
</view>
<view class="flex-between subtitle mt-5">
<view>隐患确认人{{ item.confirmUserName || "暂无" }}</view>
<view>
隐患确认时间{{
item.CONFIRM_TIME
? formatHiddenBaseTime(item.CONFIRM_TIME)
: "暂无"
}}
</view>
</view>
<view class="flex-between subtitle mt-5">
<view>隐患状态已忽略</view>
<u-button
type="primary"
size="mini"
shape="circle"
@click="handleClickView(item)"
>
查看
</u-button>
</view>
</template>
</list>
<!-- 列表渲染 end -->
</view>
</template>
<script>
import keyWordSearchInput from "@/components/keyWordSearchInput/index.vue";
import List from "@/components/list/list.vue";
import dayjs from "dayjs";
import { HIDDEN_LEVEL_COlOR, HIDDEN_SOURCE } from "@/utils/constant";
import { hidden_neglect_list } from "@/Mock/responseData.js";
export default {
components: { keyWordSearchInput, List },
data() {
return {
store: this.$store, // store
searchForm: {
HIDDENDESCR: "",
},
isRequestEnd: false, //
pagination: {
showCount: 10,
currentPage: 1,
stateConfirm: "0",
total: 0,
},
list: [],
};
},
created() {},
mounted() {},
//
onShow() {
this.getList();
},
computed: {
hiddenLevelColor() {
return HIDDEN_LEVEL_COlOR;
},
hiddenSource() {
return HIDDEN_SOURCE;
},
userInfo() {
return this.$store.getters.getUserInfo;
},
},
methods: {
/** 处理搜索事件 */
async handleSearch(val) {
this.pagination = {
...this.pagination,
currentPage: 1,
showCount: 10,
total: 0,
};
await this.getList(val);
},
/** 获取列表数据 */
getList() {
if (this.isRequestEnd) return null;
uni.showLoading({
title: "加载中",
});
let { USER_ID, CORPINFO_ID, DEPARTMENT_ID } = this.store.state.userInfo;
// HiddenDangerConfirm.getHiddenDangerConfirmList({
// USER_ID: USER_ID,
// CORPINFO_ID,
// currentPage: this.pagination.currentPage,
// showCount: this.pagination.showCount,
// DISPOSESTATE: 2,
// stateConfirm: this.pagination.stateConfirm,
// USERDEPT: DEPARTMENT_ID,
// SELFUSERID: USER_ID,
// corpinfoId: CORPINFO_ID,
// loginUserId: USER_ID,
// });
setTimeout(() => {
this.list = hidden_neglect_list;
this.pagination.total = hidden_neglect_list.length;
uni.hideLoading();
}, 400);
},
/** 计算隐患发现时间 */
formatHiddenBaseTime(val) {
return dayjs(val).format("YYYY-MM-DD");
},
/** 向下滚动加载数据 */
async scrollToLower() {
this.pagination.currentPage = this.pagination.currentPage++;
if (this.total >= this.pagination.currentPage) await this.getList();
},
/** 处理点击查看按钮事件 */
handleClickView(ext) {
uni.$u.route("/hiddenManageSubPackages/pages/hidden_neglect/view", {
HIDDEN_ID: ext.HIDDEN_ID,
});
},
},
};
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,25 @@
<template>
<view class="container">
<view class="card">
<app-hidden-view :hidden-id="hiddenId" />
</view>
</view>
</template>
<script>
import AppHiddenView from "@/components/hiddenView/index.vue";
export default {
components: { AppHiddenView },
data() {
return {
hiddenId: "",
};
},
onLoad(query) {
this.hiddenId = query.HIDDEN_ID;
},
};
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,114 @@
<template>
<app-search-popup @reset="fnReset" @search="fnSearch">
<u-form label-position="top" label-width="auto" :model="form">
<u-form-item label="隐患级别" prop="HIDDENLEVEL">
<view class="flex-start">
<u-radio-group v-model="form.HIDDENLEVEL">
<u-radio
v-for="(item, index) in hiddenLevelList"
:key="index"
:label="item.name"
:name="item.id"
>
</u-radio>
</u-radio-group>
</view>
</u-form-item>
<u-line />
<app-time
:model-value="form.STARTTIME"
label="开始时间"
prop="STARTTIME"
mode="date"
:required="false"
@fn-confirm-emit="fnConfirmEmit('STARTTIME', $event)"
/>
<app-time
:model-value="form.ENDTIME"
label="结束时间"
prop="ENDTIME"
:required="false"
mode="date"
@fn-confirm-emit="fnConfirmEmit('ENDTIME', $event)"
/>
<u-form-item label="隐患状态" prop="STATE">
<view class="flex-start">
<u-radio-group v-model="form.STATE">
<u-radio
v-for="(item, index) in hiddenStateList"
:key="index"
:label="item.name"
:name="item.id"
>
</u-radio>
</u-radio-group>
</view>
</u-form-item>
<u-line />
</u-form>
</app-search-popup>
</template>
<script>
import AppTime from "@/components/time/index.vue";
import dayjs from "dayjs";
import AppSearchPopup from "@/components/searchPopup/index.vue";
export default {
components: { AppTime, AppSearchPopup },
props: {
form: {
type: Object,
required: true,
},
},
data() {
return {
hiddenLevelList: [
{ id: "hiddenLevel0001", name: "一般隐患" },
{ id: "hiddenLevel0002", name: "重大隐患" },
],
hiddenStateList: [
{ id: "1", name: "未整改" },
{ id: "3", name: "已整改" },
{ id: "4", name: "已验收" },
{ id: "-1", name: "已过期" },
],
};
},
methods: {
fnReset() {
for (let valueKey in this.form) {
this.form[valueKey] = "";
}
},
fnSearch() {
this.$emit("search", this.form);
},
fnConfirmEmit(field, { mode, value }) {
let formattedValue;
if (mode === "datetime") {
formattedValue = dayjs(value).format("YYYY-MM-DD HH:mm");
} else if (mode === "date") {
formattedValue = dayjs(value).format("YYYY-MM-DD");
} else if (mode === "year-month") {
formattedValue = dayjs(value).format("YYYY-MM");
}
this.$emit("update-time", { field, value: formattedValue });
},
},
};
</script>
<style lang="scss" scoped>
.u-radio {
margin: 10rpx 0 10rpx 0;
}
.u-radio-group--row {
flex-flow: row wrap;
}
</style>

View File

@ -0,0 +1,267 @@
<!-- 隐患记录 -->
<template>
<view>
<!-- 吸顶搜索框 start -->
<key-word-search-input
:inputSearchValue="searchForm.HIDDENDESCR"
@search="handleSearch"
/>
<!-- 吸顶搜索框 end -->
<!-- 列表渲染 start -->
<list :list="list" @scroll-to-lower="scrollToLower">
<template #default="{ item }">
<view class="flex-between main-title">
<view class="u-line-1">{{ item.HIDDENDESCR || "暂无" }}</view>
<view :class="hiddenLevelColor[item.HIDDENLEVEL]">
{{ item.HIDDENLEVELNAME }}
</view>
</view>
<view class="flex-between subtitle mt-5">
<view>来源{{ hiddenSource[item.SOURCE] }}</view>
</view>
<view class="flex-between subtitle mt-5">
<view>隐患发现人{{ item.findUserNames || "暂无" }}</view>
<view>
隐患发现时间{{
item.DISCOVERYTIME ? formatTime(item.DISCOVERYTIME) : "暂无"
}}
</view>
</view>
<view class="flex-between subtitle mt-5">
<view>隐患确认人{{ item.confirmUserName || "暂无" }}</view>
<view>
隐患确认时间{{
item.CONFIRM_TIME ? formatTime(item.CONFIRM_TIME) : "暂无"
}}
</view>
</view>
<view class="flex-between subtitle mt-5">
<view>隐患整改人{{ item.RECTIFICATIONORNAME || "暂无" }}</view>
<view>
整改完成时间{{
item.RECTIFICATIONTIME
? formatTime(item.RECTIFICATIONTIME)
: "暂无"
}}
</view>
</view>
<view class="flex-between subtitle mt-5">
<view>隐患整改人{{ item.CHECKNAME || "暂无" }}</view>
<view>
整改完成时间{{
item.RECTIFICATIONTIME
? formatTime(item.RECTIFICATIONTIME)
: "暂无"
}}
</view>
</view>
<view class="flex-between subtitle mt-5">
<view>隐患状态{{ statusList[item.STATE] }}</view>
<view class="flex-between">
<!-- v-if="item.CREATOR === store.state.userInfo.USER_ID && item.STATE === '16'" -->
<block
v-if="
item.CREATOR === store.state.userInfo.USER_ID &&
item.STATE === '16'
"
>
<view>
<u-button
type="primary"
size="mini"
shape="circle"
@click="handleEditClick(item)"
>
修改
</u-button>
</view>
<view class="ml-10">
<u-button
type="primary"
size="mini"
shape="circle"
@click="fnDelete(item.HIDDEN_ID)"
>
删除
</u-button>
</view>
</block>
<view class="ml-10">
<u-button
type="primary"
size="mini"
shape="circle"
@click="handleClickView(item)"
>
查看
</u-button>
</view>
</view>
</view>
</template>
</list>
<!-- 列表渲染 end -->
<search-popup
:form="form"
@search="handleSearch"
@update-time="handleUpdateTime"
/>
</view>
</template>
<script>
import keyWordSearchInput from "@/components/keyWordSearchInput/index.vue";
import List from "@/components/list/list.vue";
import SearchPopup from "./components/search-popup.vue";
import * as HiddenAcceptanceApi from "../../api/index";
import { setHiddenDelete } from "../../api";
import dayjs from "dayjs";
import { HIDDEN_LEVEL_COlOR, HIDDEN_SOURCE } from "@/utils/constant";
import { hidden_record_list } from "@/Mock/responseData.js";
export default {
components: { keyWordSearchInput, List, SearchPopup },
onLoad() {},
data() {
return {
store: this.$store, // store
searchForm: {
HIDDENDESCR: "", //
},
form: {
HIDDENLEVEL: "", //
STARTTIME: "", //
ENDTIME: "", //
STATE: "", //
},
isRequestEnd: false, //
pagination: {
showCount: 10,
currentPage: 1,
stateConfirm: "0",
total: 0,
},
statusList: {
"-2": "待确认",
"-1": "已过期",
1: "未整改",
2: "已整改",
3: "已复查",
4: "已验收",
5: "已忽略",
6: "重大隐患",
7: "待处理特殊隐患",
8: "特殊处理隐患",
},
list: [],
};
},
//
onShow() {
this.getList();
},
created() {},
computed: {
hiddenLevelColor() {
return HIDDEN_LEVEL_COlOR;
},
hiddenSource() {
return HIDDEN_SOURCE;
},
},
mounted() {},
methods: {
/** 处理搜索事件 */
async handleSearch(filterVal) {
console.log('filterVal :>> ', filterVal);
this.pagination = {
...this.pagination,
currentPage: 1,
showCount: 10,
total: 0,
};
await this.getList(filterVal);
},
/** 获取列表数据 */
getList(params) {
console.log('params :>> ', params);
if (this.isRequestEnd) return null;
uni.showLoading({
title: "加载中",
});
let { USER_ID, CORPINFO_ID, DEPARTMENT_ID } = this.store.state.userInfo;
// HiddenAcceptanceApi.getHiddenList({
// USER_ID: USER_ID,
// CORPINFO_ID,
// currentPage: this.pagination.currentPage,
// showCount: this.pagination.showCount,
// DISPOSESTATE: 2,
// stateConfirm: this.pagination.stateConfirm,
// USERDEPT: DEPARTMENT_ID,
// SELFUSERID: USER_ID,
// corpinfoId: CORPINFO_ID,
// loginUserId: USER_ID,
// });
// mock
setTimeout(() => {
this.list = hidden_record_list;
this.pagination.total = hidden_record_list.length;
uni.hideLoading();
}, 400);
},
/** 格式化日期时间 */
formatTime(val) {
return dayjs(val).format("YYYY-MM-DD");
},
/** 向下滚动加载数据 */
async scrollToLower() {
this.pagination.currentPage = this.pagination.currentPage++;
if (this.total >= this.pagination.currentPage) await this.getList();
},
/** 验收按钮点击事件 */
handleEditClick(ext) {
uni.$u.route("/hiddenManageSubPackages/pages/hidden_report/index", {
HIDDEN_ID: ext.HIDDEN_ID,
});
},
/** 删除按钮点击事件 */
async fnDelete() {
await setHiddenDelete({ HIDDEN_ID, loginUserName: userInfo.NAME });
uni.showToast({
icon: "none",
title: "删除成功",
});
handleSearch();
},
/** 查看按钮点击事件 */
handleClickView(ext) {
uni.$u.route("/hiddenManageSubPackages/pages/hidden_record/view", {
HIDDEN_ID: ext.HIDDEN_ID,
});
},
/** 更新 form 表单中开始时间和结束时间两个字段 */
handleUpdateTime({ field, value }) {
this.form = {
...this.form,
[field]: value,
};
},
},
};
</script>
<style scoped lang="scss">
.u-line-1 {
width: 500rpx;
}
</style>

View File

@ -0,0 +1,11 @@
<!-- 隐患记录-查看 -->
<template>
<view>隐患记录-查看</view>
</template>
<script>
export default {}
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,125 @@
<template>
<view class="container">
<view class="card">
<app-hidden-view :hidden-id="hiddenId" />
<view class="card">
<u-form
ref="formRef"
label-position="left"
:model="form"
:rules="rules"
label-width="auto"
>
<app-time
:model-value="form.DELAY_TIME"
label="延期时间"
prop="DELAY_TIME"
:min-date="new Date().getTime()"
@fn-confirm-emit="fnConfirmEmit"
/>
<u-form-item
label="处置方案"
label-position="top"
prop="disposalPlan"
required
>
<u-textarea
v-model="form.disposalPlan"
placeholder="请输入处置方案"
border="none"
auto-height
/>
</u-form-item>
<u-line />
<view class="mt-10">
<u-button
type="primary"
shape="circle"
text="提交"
:throttle-time="1000"
@click="fnSubmit"
/>
</view>
</u-form>
</view>
</view>
</view>
</template>
<script>
import dayjs from "dayjs";
import AppHiddenView from "@/components/hiddenView/index.vue";
import AppTime from "@/components/time/index.vue";
import useFormValidate from "@/utils/useFormValidate";
export default {
components: { AppHiddenView, AppTime },
onLoad(query) {
this.hiddenId = query.HIDDEN_ID;
},
data() {
return {
store: this.$store.state,
hiddenId: "",
form: {
DELAY_TIME: "",
disposalPlan: "",
},
rules: {
DELAY_TIME: {
type: "string",
required: true,
message: "请选择延期时间",
trigger: ["blur", "change"],
},
disposalPlan: {
type: "string",
required: true,
message: "请输入处置方案",
trigger: ["blur", "change"],
},
},
};
},
methods: {
/** 提交按钮点击事件 */
async fnSubmit() {
await useFormValidate(this.$refs.formRef);
// await setHiddenDelaySubmit({
// loginUserId: userInfo.USER_ID,
// USERNAME: userInfo.NAME,
// HIDDEN_ID: hiddenId.value,
// ...form.value,
// });
// uni.showToast({
// icon: "none",
// title: "",
// });
// setTimeout(() => {
// uni.navigateBack();
// }, 1000);
},
fnConfirmEmit({ mode, value }) {
if (mode === "datetime") {
this.form = {
...this.form,
DELAY_TIME: dayjs(value).format("YYYY-MM-DD HH:mm"),
};
} else if (mode === "date") {
this.form = {
...this.form,
DELAY_TIME: dayjs(value).format("YYYY-MM-DD"),
};
} else if (mode === "year-month") {
this.form = {
...this.form,
DELAY_TIME: dayjs(value).format("YYYY-MM"),
};
}
},
},
};
</script>

View File

@ -0,0 +1,191 @@
<!-- 隐患整改组件 -->
<template>
<view class="container">
<!-- 吸顶搜索框 start -->
<key-word-search-input :inputSearchValue="searchForm.HIDDENDESCR" @search="handleSearch" />
<!-- 吸顶搜索框 end -->
<!-- 列表渲染 start -->
<list :list="list" @scroll-to-lower="scrollToLower">
<template #default="{ item }">
<view class="flex-between main-title">
<view class="u-line-1">{{ item.HIDDENDESCR || "暂无" }}</view>
<view :class="hiddenLevelColor[item.HIDDENLEVEL]">
{{ item.HIDDENLEVELNAME }}
</view>
</view>
<view class="flex-between subtitle mt-5">
<view>来源{{ hiddenSource[item.SOURCE] }}</view>
</view>
<view class="flex-between subtitle mt-5">
<view>隐患发现人{{ item.findUserNames || "暂无" }}</view>
<view>
隐患发现时间{{
item.DISCOVERYTIME
? formatTime(item.DISCOVERYTIME)
: "暂无"
}}
</view>
</view>
<view class="flex-between subtitle mt-5">
<view>隐患确认人{{ item.confirmUserName || "暂无" }}</view>
<view>
隐患确认时间{{
item.CONFIRM_TIME
? formatTime(item.CONFIRM_TIME)
: "暂无"
}}
</view>
</view>
<view class="flex-between subtitle mt-5">
<view>隐患确认状态待整改</view>
<view class="flex-between">
<view>
<u-button type="primary" size="mini" shape="circle" @click="handleClickRectify(item)">
整改
</u-button>
</view>
<view v-if="item.exaCount === 0" class="ml-10">
<u-button type="primary" size="mini" shape="circle" @click="handleClickExtensionApplication(item)">
延期申请
</u-button>
</view>
</view>
</view>
</template>
</list>
<!-- 列表渲染 end -->
</view>
</template>
<script>
import keyWordSearchInput from "@/components/keyWordSearchInput/index.vue";
import List from "@/components/list/list.vue";
import * as HiddenRectificationApi from "../../api/index";
import dayjs from "dayjs";
import { HIDDEN_LEVEL_COlOR, HIDDEN_SOURCE } from "@/utils/constant";
import { hidden_rectification_list } from "@/Mock/responseData.js";
export default {
components: { keyWordSearchInput, List },
onShow() {
this.resetPagination()
},
data() {
return {
store: this.$store, // store
searchForm: {
HIDDENDESCR: "",
},
isRequestEnd: false, //
pagination: {
showCount: 10,
currentPage: 1,
stateConfirm: "0",
total: 0,
},
list: [],
}
},
created() { },
mounted() { },
//
onShow() {
this.getList();
},
computed: {
hiddenLevelColor() {
return HIDDEN_LEVEL_COlOR;
},
hiddenSource() {
return HIDDEN_SOURCE;
},
},
methods: {
/** 处理搜索事件 */
async handleSearch(val) {
this.pagination = {
...this.pagination,
currentPage: 1,
showCount: 10,
total: 0,
};
await this.getList(val);
},
async resetPagination(params) {
this.list = [];
this.pagination = {
showCount: 10,
currentPage: 1,
stateConfirm: "0",
total: 0,
};
await this.getList(params);
},
getList() {
if (this.isRequestEnd) return null;
uni.showLoading({
title: "加载中",
});
let { USER_ID, CORPINFO_ID, DEPARTMENT_ID } = this.store.state.userInfo;
// HiddenRectificationApi.getHiddenList({
// USER_ID: USER_ID,
// CORPINFO_ID,
// currentPage: this.pagination.currentPage,
// showCount: this.pagination.showCount,
// DISPOSESTATE: 2,
// stateConfirm: this.pagination.stateConfirm,
// USERDEPT: DEPARTMENT_ID,
// SELFUSERID: USER_ID,
// corpinfoId: CORPINFO_ID,
// loginUserId: USER_ID,
// }).then((response) => {
// console.log('response :>> ', response);
// })
// mock
setTimeout(() => {
this.list = hidden_rectification_list;
this.pagination.total = 0;
uni.hideLoading();
}, 400);
},
/** 格式化日期时间 */
formatTime(val) {
return dayjs(val).format("YYYY-MM-DD");
},
/** 向下滚动加载数据 */
async scrollToLower() {
this.pagination.currentPage = this.pagination.currentPage++;
if (this.total >= this.pagination.currentPage) await this.getList();
},
/** 整改按钮事件 */
handleClickRectify(ext) {
uni.$u.route(
'/hiddenManageSubPackages/pages/hidden_rectification/rectification',
{
HIDDEN_ID: ext.HIDDEN_ID
}
)
},
/** 处理延期申请按钮事件 */
handleClickExtensionApplication(ext) {
uni.$u.route(
'/hiddenManageSubPackages/pages/hidden_rectification/delay',
{
HIDDEN_ID: ext.HIDDEN_ID
}
)
}
}
}
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,464 @@
<!-- 整改详情页 -->
<template>
<view class="container">
<view class="card">
<app-hidden-view
:hidden-id="hiddenId"
@throw-basic-info="info = $event.pd"
/>
<view class="card">
<u-form
ref="formRef"
label-position="left"
:model="form"
:rules="rules"
label-width="auto"
>
<u-form-item label="是否正常整改" prop="IS_NORMAL" required>
<u-radio-group v-model="form.IS_NORMAL" direction="horizontal">
<u-radio name="1" label="是" />
<u-radio name="2" label="否" />
</u-radio-group>
</u-form-item>
<u-line />
<block v-if="form.IS_NORMAL === '2'">
<u-form-item
label="无法整改原因"
label-position="top"
prop="disposalPlan"
required
>
<u-textarea
v-model="form.disposalPlan"
placeholder="请输入无法整改原因"
border="none"
auto-height
/>
</u-form-item>
<u-line />
</block>
<block v-if="form.IS_NORMAL === '1'">
<u-divider text-position="left" text="隐患整改"></u-divider>
<u-form-item
label="隐患整改详细描述"
label-position="top"
prop="RECTIFYDESCR"
required
>
<u-textarea
v-model="form.RECTIFYDESCR"
placeholder="请输入隐患整改详细描述"
border="none"
auto-height
/>
</u-form-item>
<u-line />
<app-time
:model-value="form.RECTIFICATIONTIME"
prop="RECTIFICATIONTIME"
mode="date"
label="整改日期"
@fn-confirm-emit="fnConfirmEmit"
/>
<u-form-item label="投入资金(元)" prop="INVEST_FUNDS" required>
<u-input
v-model="form.INVEST_FUNDS"
placeholder="请输入投入资金"
border="none"
type="number"
input-align="right"
/>
</u-form-item>
<u-line />
<app-upload
v-model="form.AfterRectificationFile"
label="整改后照片"
prop="AfterRectificationFile"
/>
<view>
<view class="mt-10 flex-end">
<u-button
custom-style="width: 100rpx;margin:0"
type="primary"
size="mini"
text="添加"
@click="fnAddAcceptanceList"
/>
</view>
<view
v-for="(item, index) in acceptanceList"
:key="item.id"
style="
position: relative;
border: 1px dashed #ccc;
padding: 20rpx 20rpx 20rpx 40rpx;
"
class="mt-10"
>
<app-department
:id="item.DEPARTMENT_ID"
:name="item.DEPARTMENT_NAME"
:form="acceptanceList[index]"
clear-key="USER_NAME,USER_ID"
label="验收部门"
/>
<app-personnel
:id="item.USER_ID"
:name="item.USER_NAME"
:department-id="item.DEPARTMENT_ID"
label="验收人"
/>
<u-icon
v-if="index !== 0"
name="close-circle-fill"
color="#ff2929"
size="20"
custom-style="position: absolute;right: -20rpx;top: -20rpx"
@click="acceptanceList.splice(index, 1)"
/>
</view>
</view>
<u-form-item label="是否有整改方案" prop="HAVESCHEME" required>
<u-radio-group v-model="form.HAVESCHEME" direction="horizontal">
<u-radio name="1" label="是" />
<u-radio name="0" label="否" />
</u-radio-group>
</u-form-item>
<u-line />
<block v-if="form.HAVESCHEME === '1'">
<u-cell-group :border="false">
<u-cell title="排查日期" :value="info.CREATTIME" />
<u-cell title="隐患清单" :value="info.LIST_NAME" />
</u-cell-group>
<u-form-item
label="治理标准"
label-position="top"
prop="GOVERNSTANDARDS"
required
>
<u-textarea
v-model="form.GOVERNSTANDARDS"
placeholder="请输入治理标准"
border="none"
auto-height
/>
</u-form-item>
<u-line />
<u-form-item
label="治理方法"
label-position="top"
prop="GOVERNMETHOD"
required
>
<u-textarea
v-model="form.GOVERNMETHOD"
placeholder="请输入治理方法"
border="none"
auto-height
/>
</u-form-item>
<u-line />
<u-form-item
label="经费落实"
label-position="top"
prop="EXPENDITURE"
required
>
<u-textarea
v-model="form.EXPENDITURE"
placeholder="请输入经费落实"
border="none"
auto-height
/>
</u-form-item>
<u-line />
<u-form-item
label="负责人员"
label-position="top"
prop="PRINCIPAL"
required
>
<u-textarea
v-model="form.PRINCIPAL"
placeholder="请输入负责人员"
border="none"
auto-height
/>
</u-form-item>
<u-line />
<u-form-item
label="工时安排"
label-position="top"
prop="PROGRAMMING"
required
>
<u-textarea
v-model="form.PROGRAMMING"
placeholder="请输入工时安排"
border="none"
auto-height
/>
</u-form-item>
<u-line />
<u-form-item
label="时限要求"
label-position="top"
prop="TIMELIMITFOR"
required
>
<u-textarea
v-model="form.TIMELIMITFOR"
placeholder="请输入时限要求"
border="none"
auto-height
/>
</u-form-item>
<u-line />
<u-form-item
label="工作要求"
label-position="top"
prop="JOBREQUIREMENT"
required
>
<u-textarea
v-model="form.JOBREQUIREMENT"
placeholder="请输入工作要求"
border="none"
auto-height
/>
</u-form-item>
<u-line />
<u-form-item
label="其它事项"
label-position="top"
prop="OTHERBUSINESS"
required
>
<u-textarea
v-model="form.OTHERBUSINESS"
placeholder="请输入其它事项"
border="none"
auto-height
/>
</u-form-item>
<u-line />
<app-upload
:model-value="form.programmeFile"
label="方案照片"
prop="programmeFile"
/>
</block>
</block>
<view class="mt-10">
<u-button
type="primary"
shape="circle"
text="提交"
:throttle-time="1000"
@click="fnSubmit"
/>
</view>
</u-form>
</view>
</view>
</view>
</template>
<script>
import dayjs from "dayjs";
import AppHiddenView from "@/components/hiddenView/index.vue";
import AppTime from "@/components/time/index.vue";
import AppUpload from "@/components/upload/index.vue";
import useFormValidate from "@/utils/useFormValidate";
import AppDepartment from "@/components/department/index.vue";
import AppPersonnel from "@/components/personnel/index.vue";
export default {
components: {
AppHiddenView,
AppTime,
AppUpload,
AppDepartment,
AppPersonnel,
},
onLoad(query) {
this.hiddenId = query.HIDDEN_ID;
this.fnAddAcceptanceList();
},
data() {
return {
hiddenId: "",
form: {
IS_NORMAL: "1",
disposalPlan: "",
RECTIFYDESCR: "",
RECTIFICATIONTIME: "",
INVEST_FUNDS: "",
AfterRectificationFile: [],
HAVESCHEME: "0",
GOVERNSTANDARDS: "",
GOVERNMETHOD: "",
EXPENDITURE: "",
PRINCIPAL: "",
PROGRAMMING: "",
TIMELIMITFOR: "",
JOBREQUIREMENT: "",
OTHERBUSINESS: "",
programmeFile: [],
},
acceptanceList: [],
rules: {
IS_NORMAL: {
type: "string",
required: true,
message: "请选择是否正常整改",
trigger: ["blur", "change"],
},
disposalPlan: {
type: "string",
required: true,
message: "请输入无法整改原因",
trigger: ["blur", "change"],
},
RECTIFYDESCR: {
type: "string",
required: true,
message: "请输入隐患整改详细描述",
trigger: ["blur", "change"],
},
RECTIFICATIONTIME: {
type: "string",
required: true,
message: "请选择整改日期",
trigger: ["blur", "change"],
},
INVEST_FUNDS: {
type: "number",
required: true,
message: "请输入投入资金",
trigger: ["blur", "change"],
},
AfterRectificationFile: {
type: "array",
required: true,
message: "请上传整改后照片",
trigger: ["blur", "change"],
},
HAVESCHEME: {
type: "string",
required: true,
message: "请选择是否有整改方案",
trigger: ["blur", "change"],
},
GOVERNSTANDARDS: {
type: "string",
required: true,
message: "请输入治理标准",
trigger: ["blur", "change"],
},
GOVERNMETHOD: {
type: "string",
required: true,
message: "请输入治理方法",
trigger: ["blur", "change"],
},
EXPENDITURE: {
type: "string",
required: true,
message: "请输入经费落实",
trigger: ["blur", "change"],
},
PRINCIPAL: {
type: "string",
required: true,
message: "请输入负责人员",
trigger: ["blur", "change"],
},
PROGRAMMING: {
type: "string",
required: true,
message: "请输入工时安排",
trigger: ["blur", "change"],
},
TIMELIMITFOR: {
type: "string",
required: true,
message: "请输入时限要求",
trigger: ["blur", "change"],
},
JOBREQUIREMENT: {
type: "string",
required: true,
message: "请输入工作要求",
trigger: ["blur", "change"],
},
OTHERBUSINESS: {
type: "string",
required: true,
message: "请输入其它事项",
trigger: ["blur", "change"],
},
programmeFile: {
type: "array",
required: true,
message: "请上传方案照片",
trigger: ["blur", "change"],
},
},
};
},
mounted() {},
methods: {
/** 添加验收列表的方法 */
fnAddAcceptanceList() {
this.acceptanceList.push({
DEPARTMENT_NAME: "",
DEPARTMENT_ID: "",
USER_NAME: "",
USER_ID: "",
id: uni.$u.guid(20),
});
},
/** 提交按钮方法 */
async fnSubmit() {
await useFormValidate(this.$refs.formRef);
for (let i = 0; i < this.acceptanceList.length; i++) {
if (
this.acceptanceList[i].DEPARTMENT_NAME ||
this.acceptanceList[i].USER_NAME
) {
uni.showToast({
icon: "none",
title: "请选择部门人员",
});
return;
}
}
},
fnConfirmEmit({ mode, value }) {
if (mode === "datetime") {
this.form = {
...this.form,
RECTIFICATIONTIME: dayjs(value).format("YYYY-MM-DD HH:mm"),
};
} else if (mode === "date") {
this.form = {
...this.form,
RECTIFICATIONTIME: dayjs(value).format("YYYY-MM-DD"),
};
} else if (mode === "year-month") {
this.form = {
...this.form,
RECTIFICATIONTIME: dayjs(value).format("YYYY-MM"),
};
}
},
},
};
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,543 @@
<template>
<view class="container">
<view class="card">
<view class="card">
<u-form
ref="formRef"
label-position="left"
:model="form"
:rules="rules"
label-width="auto"
>
<block v-if="entranceType === 'hidden_troubleshooting_check_item'">
<u-cell title="检查内容">
<template #label>
<view class="mt-5">{{ checkContent }}</view>
</template>
</u-cell>
</block>
<!-- 上传多张图片 -->
<app-upload
:model-value="form.imageFile"
label="隐患照片"
prop="imageFile"
/>
<!-- 上传一个视频资料 -->
<app-upload
:model-value="form.videoFile"
label="隐患视频"
prop="videoFile"
:required="false"
:max-count="1"
:multiple="false"
accept="video"
/>
<u-form-item
label="隐患描述"
label-position="top"
prop="HIDDENDESCR"
required
>
<u-textarea
v-model="form.HIDDENDESCR"
placeholder="请输入隐患描述"
border="none"
auto-height
/>
</u-form-item>
<u-line />
<!-- 隐患部位 -->
<app-hidden-position
:id="form.HIDDENPART"
:name="form.HIDDENPARTNAME"
prop="HIDDENPARTNAME"
/>
<!-- 隐患级别 -->
<app-hidden-level
:id="form.HIDDENLEVEL"
:name="form.HIDDENLEVELNAME"
:is-show-neglect="false"
prop="HIDDENLEVELNAME"
/>
<!-- 隐患类型 -->
<app-hidden-type
:id="form.HIDDENTYPE"
:name="form.HIDDENTYPE1NANEM"
prop="HIDDENTYPE1NANEM"
/>
<u-form-item label="是否立即整改" prop="RECTIFICATIONTYPE" required>
<u-radio-group
v-model="form.RECTIFICATIONTYPE"
direction="horizontal"
>
<block
v-if="
form.HIDDENLEVEL !== 'jdyh001' &&
form.HIDDENLEVEL !== 'hiddenLevel2002'
"
>
<u-radio name="1" label="是" />
</block>
<u-radio name="2" label="否" />
</u-radio-group>
</u-form-item>
<u-line />
<block
v-if="
form.RECTIFICATIONTYPE === '2' &&
form.HIDDENLEVEL !== 'jdyh001' &&
form.HIDDENLEVEL !== 'hiddenLevel2002'
"
>
<!-- 整改责任部门 -->
<app-department
:id="form.RECTIFICATIONDEPT"
:name="form.RECTIFICATIONDEPTNAME"
:form="form"
clear-key="RECTIFICATIONORNAME,RECTIFICATIONOR"
prop="RECTIFICATIONDEPTNAME"
label="整改责任部门"
:required="false"
/>
<!-- 整改责任人 -->
<app-personnel
:id="form.RECTIFICATIONOR"
:name="form.RECTIFICATIONORNAME"
:department-id="form.RECTIFICATIONDEPT"
prop="RECTIFICATIONORNAME"
label="整改责任人"
:required="false"
/>
<!-- 整改期限 -->
<app-time
:model-value="form.RECTIFICATIONDEADLINE"
label="整改期限"
prop="RECTIFICATIONDEADLINE"
mode="date"
:required="false"
@fn-confirm-emit="fnConfirmEmit"
/>
</block>
<block
v-if="
form.HIDDENLEVEL !== 'jdyh001' &&
form.HIDDENLEVEL !== 'hiddenLevel2002'
"
>
<app-personnel
:id="form.CONFIRM_USER"
:name="form.CONFIRM_USER_NAME"
department-id=""
is-hidden-confirm-personnel
prop="CONFIRM_USER_NAME"
label="隐患确认人"
/>
</block>
<app-time
:model-value="form.DISCOVERYTIME"
label="隐患发现时间"
prop="DISCOVERYTIME"
:max-date="new Date().getTime()"
/>
<u-form-item label="是否相关方" prop="ISRELEVANT" required>
<u-radio-group v-model="form.ISRELEVANT" direction="horizontal">
<u-radio name="1" label="是" />
<u-radio name="2" label="否" />
</u-radio-group>
</u-form-item>
<u-line />
<u-form-item
label="隐患位置描述"
label-position="top"
prop="POSITIONDESC"
required
>
<u-textarea
v-model="form.POSITIONDESC"
placeholder="请输入隐患位置描述"
border="none"
auto-height
/>
</u-form-item>
<u-line />
<block v-if="!!hiddenId && entranceType === 'hidden_report'">
<view v-for="(item, index) in repulseCause" :key="index">
<u-cell title="打回意见及时间">
<template #label>
<view class="mt-5">{{ item.REPULSE_CAUSE }}</view>
<view class="mt-5">{{ item.OPERATTIME }}</view>
</template>
</u-cell>
</view>
</block>
<app-location
:longitude="form.LONGITUDE"
:latitude="form.LATITUDE"
longitude-prop="LONGITUDE"
latitude-prop="LATITUDE"
label="隐患上报位置"
/>
<app-department
:id="form.DEPARTMENT_ID"
:name="form.DEPARTMENT_NAME"
:form="form"
clear-key="USER_NAME,USER_ID"
prop="DEPARTMENT_NAME"
label="隐患发现人部门"
/>
<app-personnel
:id="form.USER_ID"
:name="form.USER_NAME"
:department-id="form.DEPARTMENT_ID"
prop="USER_NAME"
label="隐患发现人"
/>
<block v-if="form.RECTIFICATIONTYPE === '1'">
<u-form-item
label="整改描述"
label-position="top"
prop="RECTIFYDESCR"
required
>
<u-textarea
v-model="form.RECTIFYDESCR"
placeholder="请输入整改描述"
border="none"
auto-height
/>
</u-form-item>
<u-line />
<app-upload
v-model="form.AfterRectificationFile"
label="整改后图片"
prop="AfterRectificationFile"
/>
</block>
<view class="mt-10">
<u-button
type="primary"
shape="circle"
text="提交"
:throttle-time="1000"
@click="fnSubmit"
/>
</view>
</u-form>
</view>
</view>
</view>
</template>
<script>
import AppUpload from "@/components/upload/index.vue";
import AppHiddenPosition from "@/components/hiddenPosition/index.vue";
import AppHiddenLevel from "@/components/hidden_level/index.vue";
import AppHiddenType from "@/components/hiddenType/index.vue";
import AppDepartment from "@/components/department/index.vue";
import AppPersonnel from "@/components/personnel/index.vue";
import AppTime from "@/components/time/index.vue";
import AppLocation from "@/components/location/index.vue";
import { getHiddenInfo } from "@/api";
import dayjs from "dayjs";
import useFormValidate from "@/utils/useFormValidate.js";
export default {
components: {
AppUpload,
AppHiddenPosition,
AppHiddenLevel,
AppHiddenType,
AppDepartment,
AppPersonnel,
AppTime,
AppLocation,
},
onLoad(query) {
this.hiddenId = query.HIDDEN_ID;
this.checkContent = query.CHECK_CONTENT;
this.listCheckItemId = query.LISTCHECKITEM_ID;
this.recordItemId = query.RECORDITEM_ID;
this.listManagerId = query.LISTMANAGER_ID;
this.entranceType = query.entranceType || "hidden_report";
this.fnGetData(query.HIDDEN_ID);
},
data() {
return {
store: this.$store,
// form
form: {
imageFile: [],
videoFile: [],
HIDDENDESCR: "",
HIDDENPART: "",
HIDDENPARTNAME: "", //
HIDDENLEVEL: "",
HIDDENLEVELNAME: "",
HIDDENTYPE: "",
HIDDENTYPE1NANEM: "",
RECTIFICATIONTYPE: "2",
RECTIFICATIONDEPT: "",
RECTIFICATIONDEPTNAME: "",
RECTIFICATIONOR: "",
RECTIFICATIONORNAME: "",
RECTIFICATIONDEADLINE: "",
CONFIRM_USER: "",
CONFIRM_USER_NAME: "",
DISCOVERYTIME: dayjs().format("YYYY-MM-DD HH:mm"),
ISRELEVANT: "2",
POSITIONDESC: "",
LONGITUDE: "",
LATITUDE: "",
DEPARTMENT_ID: this.$store.state.userInfo.DEPARTMENT_ID,
DEPARTMENT_NAME: this.$store.state.userInfo.DEPARTMENT_NAME,
USER_ID: this.$store.state.userInfo.USER_ID,
USER_NAME: this.$store.state.userInfo.NAME,
RECTIFYDESCR: "",
AfterRectificationFile: [],
},
rules: {
imageFile: {
type: "array",
required: true,
message: "请上传隐患照片",
trigger: ["blur", "change"],
},
HIDDENDESCR: {
type: "string",
required: true,
message: "请输入隐患描述",
trigger: ["blur", "change"],
},
HIDDENLEVELNAME: {
type: "string",
required: true,
message: "请选择隐患级别",
trigger: ["blur", "change"],
},
HIDDENTYPE1NANEM: {
type: "string",
required: true,
message: "请选择隐患类型",
trigger: ["blur", "change"],
},
RECTIFICATIONTYPE: {
type: "string",
required: true,
message: "请选择是否立即整改",
trigger: ["blur", "change"],
},
CONFIRM_USER_NAME: {
type: "string",
required: true,
message: "请选择隐患确认人",
trigger: ["blur", "change"],
},
DISCOVERYTIME: {
type: "string",
required: true,
message: "请选择隐患发现时间",
trigger: ["blur", "change"],
},
ISRELEVANT: {
type: "string",
required: true,
message: "请选择是否相关方",
trigger: ["blur", "change"],
},
POSITIONDESC: {
type: "string",
required: true,
message: "请输入隐患位置描述",
trigger: ["blur", "change"],
},
HIDDENPARTNAME: {
type: "string",
required: true,
message: "请选择隐患部位",
trigger: ["blur", "change"],
},
LONGITUDE: {
type: "string",
required: true,
message: "请选择经度",
trigger: ["blur", "change"],
},
LATITUDE: {
type: "string",
required: true,
message: "请选择纬度",
trigger: ["blur", "change"],
},
DEPARTMENT_NAME: {
type: "string",
required: true,
message: "请选择隐患发现人部门",
trigger: ["blur", "change"],
},
USER_NAME: {
type: "string",
required: true,
message: "请选择隐患发现人",
trigger: ["blur", "change"],
},
RECTIFYDESCR: {
type: "string",
required: true,
message: "请输入整改描述",
trigger: ["blur", "change"],
},
AfterRectificationFile: {
type: "array",
required: true,
message: "请上传整改后图片",
trigger: ["blur", "change"],
},
},
hiddenId: "",
checkContent: "",
listCheckItemId: "",
recordItemId: "",
listManagerId: "",
entranceType: "",
repulseCause: []
};
},
methods: {
async fnGetData(hidden_id) {
if (!hidden_id) return null;
const responseData = await getHiddenInfo({
hidden_id,
});
for (let i = 0; i < responseData.hImgs.length; i++) {
responseData.hImgs[i].url = filePath + responseData.hImgs[i].FILEPATH;
}
for (let i = 0; i < responseData.rImgs.length; i++) {
responseData.rImgs[i].url = filePath + responseData.rImgs[i].FILEPATH;
}
for (let i = 0; i < responseData.hiddenVideo.length; i++) {
responseData.hiddenVideo[i].url =
filePath + responseData.hiddenVideo[i].FILEPATH;
}
this.form = responseData.pd;
this.form.CONFIRM_USER_NAME = responseData.pd.conUserName;
this.form.HIDDENTYPE1NANEM = responseData.pd.HIDDENTYPENAME;
this.form.HIDDENPARTNAME = responseData.pd.hregionName;
this.form.imageFile = responseData.hImgs;
this.form.videoFile = responseData.hiddenVideo;
this.form.AfterRectificationFile = responseData.rImgs;
this.form.DEPARTMENT_ID = responseData.hiddenFindPeople[0].DEPARTMENT_ID;
this.form.DEPARTMENT_NAME = responseData.hiddenFindPeople[0].deptName;
this.form.USER_ID = responseData.hiddenFindPeople[0].USER_ID;
this.form.USER_NAME = responseData.hiddenFindPeople[0].NAME;
this.repulseCause = responseData.repulsecause;
},
fnConfirmEmit({ mode, value }) {
if (mode === "datetime") {
this.form = {
...this.form,
RECTIFICATIONDEADLINE: dayjs(value).format("YYYY-MM-DD HH:mm"),
};
} else if (mode === "date") {
this.form = {
...this.form,
RECTIFICATIONDEADLINE: dayjs(value).format("YYYY-MM-DD"),
};
} else if (mode === "year-month") {
this.form = {
...this.form,
RECTIFICATIONDEADLINE: dayjs(value).format("YYYY-MM"),
};
}
},
async fnSubmit() {
const { userInfo } = this.store.state;
//
await useFormValidate(this.$refs.formRef);
const other = [
{
DEPARTMENT_ID: this.form.DEPARTMENT_ID,
DEPARTMENT_NAME: this.form.DEPARTMENT_NAME,
USER_ID: this.form.USER_ID,
USER_NAME: this.form.USER_NAME,
},
];
let params = {
...this.form,
HIDDENFINDDEPT: userInfo.DEPARTMENT_ID,
CREATOR: userInfo.USER_ID,
USERNAME: userInfo.NAME,
other: JSON.stringify(other),
};
let currentHiddenId = "";
if (this.entranceType === "hidden_report") {
const { pd } = !hiddenId.value
? await setHiddenAdd(params)
: await setHiddenUpdate(params);
currentHiddenId = pd.HIDDEN_ID;
}
if (
this.entranceType === "hidden_troubleshooting_check_item" ||
this.entranceType === "hidden_troubleshooting_other_hidden"
) {
if (this.entranceType === "hidden_troubleshooting_check_item") {
params = {
...params,
SOURCE: "2",
STATE: "0",
CLEARIMG: "1",
CHECK_CONTENT: this.checkContent,
RECORDITEM_ID: this.recordItemId,
LISTMANAGER_ID: this.listManagerId,
RISKITEM_ID: this.listCheckItemId,
};
}
if (this.entranceType === "hidden_troubleshooting_other_hidden") {
params = {
...params,
SOURCE: "3",
STATE: "0",
LISTMANAGER_ID: this.listManagerId,
};
}
const { pd } = !hiddenId.value
? await setHiddenTroubleshootingCheckItemHiddenAdd(params)
: await setHiddenTroubleshootingCheckItemHiddenUpdate(params);
currentHiddenId = pd.HIDDEN_ID;
}
for (let i = 0; i < this.form.imageFile.length; i++) {
if (!this.form.imageFile[i].FILEPATH)
await fnUploadFile(this.form.imageFile[i].url, currentHiddenId, 3);
}
for (let i = 0; i < this.form.videoFile.length; i++) {
if (!this.form.videoFile[i].FILEPATH)
await fnUploadFile(this.form.videoFile[i].url, currentHiddenId, 102);
}
for (let i = 0; i < this.form.AfterRectificationFile.length; i++) {
if (!this.form.AfterRectificationFile[i].FILEPATH)
await fnUploadFile(
this.form.AfterRectificationFile[i].url,
currentHiddenId,
4
);
}
if (this.entranceType === "hidden_troubleshooting_check_item") {
uni.$emit("hiddenTroubleshootingCheckItemHiddenSaveSuccess", {
hiddenId: currentHiddenId,
});
}
uni.showToast({
icon: "none",
title: "提交成功",
});
setTimeout(() => {
uni.navigateBack();
}, 1000);
},
},
};
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,184 @@
<template>
<view class="container">
<view class="card">
<!-- 隐患详情查看 -->
<app-hidden-view
:hidden-id="hiddenId"
@throw-basic-info="info = $event.pd"
/>
<!-- 处置审核 -->
<view class="card">
<u-form
ref="formRef"
label-position="left"
:model="form"
:rules="rules"
label-width="auto"
>
<u-form-item label="处置审核" prop="DISPOSITION_AUDIT" required>
<u-radio-group
v-model="form.DISPOSITION_AUDIT"
direction="horizontal"
>
<u-radio name="1" label="通过" />
<u-radio name="2" label="不通过" />
</u-radio-group>
</u-form-item>
<u-line />
<block v-if="form.DISPOSITION_AUDIT === '1'">
<u-form-item
label="临时措施"
label-position="top"
prop="TEMPORARY_MEASURES"
required
>
<u-textarea
v-model="form.TEMPORARY_MEASURES"
placeholder="请输入临时措施"
border="none"
auto-height
/>
</u-form-item>
<u-line />
</block>
<block v-if="form.DISPOSITION_AUDIT === '2'">
<u-form-item
label="是否更换整改负责人"
prop="REPLACE_PRINCIPAL"
required
>
<u-radio-group
v-model="form.REPLACE_PRINCIPAL"
direction="horizontal"
>
<u-radio name="1" label="是" />
<u-radio name="2" label="否" />
</u-radio-group>
</u-form-item>
<u-line />
<block v-if="form.REPLACE_PRINCIPAL === '1'">
<app-department
:name="form.PRINCIPAL_DEPARTMENT_NAME"
:id="form.PRINCIPAL_DEPARTMENT_ID"
:form="form"
clear-key="PRINCIPAL_NAME,PRINCIPAL_ID"
prop="PRINCIPAL_DEPARTMENT_NAME"
label="整改负责人部门"
/>
<app-personnel
:id="form.PRINCIPAL_ID"
:name="form.PRINCIPAL_NAME"
:department-id="form.PRINCIPAL_DEPARTMENT_ID"
prop="PRINCIPAL_NAME"
label="整改负责人"
/>
</block>
</block>
<view class="mt-10">
<u-button
type="primary"
shape="circle"
text="提交"
:throttle-time="1000"
@click="fnSubmit"
/>
</view>
</u-form>
</view>
</view>
</view>
</template>
<script>
import AppHiddenView from "@/components/hiddenView/index.vue";
import AppDepartment from "@/components/department/index.vue";
import AppPersonnel from "@/components/personnel/index.vue";
import useFormValidate from "@/utils/useFormValidate";
import { setHiddenSpecialDisposalReviewSubmit } from "../../api";
export default {
components: { AppHiddenView, AppDepartment, AppPersonnel },
onLoad(query) {
this.hiddenId = query.HIDDEN_ID;
this.hiddenExamineId = query.HIDDENEXAMINE_ID;
},
data() {
return {
store: this.$store,
hiddenId: "",
hiddenExamineId: "",
form: {
TEMPORARY_MEASURES: "", //
REPLACE_PRINCIPAL: "", //
PRINCIPAL_DEPARTMENT_NAME: "", //
PRINCIPAL_DEPARTMENT_ID: "", // ID
PRINCIPAL_NAME: "", //
PRINCIPAL_ID: "", // ID
},
//
rules: {
DISPOSITION_AUDIT: {
type: "string",
required: true,
message: "请选择处置审核",
trigger: ["blur", "change"],
},
TEMPORARY_MEASURES: {
type: "string",
required: true,
message: "请输入临时措施",
trigger: ["blur", "change"],
},
REPLACE_PRINCIPAL: {
type: "string",
required: true,
message: "请选择是否更换整改负责人",
trigger: ["blur", "change"],
},
PRINCIPAL_DEPARTMENT_NAME: {
type: "string",
required: true,
message: "请选择整改负责人部门",
trigger: ["blur", "change"],
},
PRINCIPAL_NAME: {
type: "string",
required: true,
message: "请选择整改负责人",
trigger: ["blur", "change"],
},
},
};
},
methods: {
async fnSubmit() {
await useFormValidate(this.$refs.formRef);
await setHiddenSpecialDisposalReviewSubmit({
loginUserId: userInfo.USER_ID,
USERNAME: userInfo.NAME,
HIDDENEXAMINE_ID: hiddenExamineId.value,
TYPE: form.value.DISPOSITION_AUDIT,
disposalPlan: form.value.TEMPORARY_MEASURES,
OLDRECTIFICATIONOR: info.value.RECTIFICATIONOR,
spare2: form.value.PRINCIPAL_ID,
spare1: form.value.REPLACE_PRINCIPAL,
isChange: form.value.REPLACE_PRINCIPAL,
changeUserDepartment: form.value.PRINCIPAL_DEPARTMENT_ID,
changeUser: form.value.PRINCIPAL_ID,
});
uni.showToast({
icon: "none",
title: "提交成功",
});
setTimeout(() => {
uni.navigateBack();
}, 1000);
},
},
};
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,196 @@
<!-- 特殊处置审核组件 -->
<template>
<view>
<!-- 吸顶搜索框 start -->
<key-word-search-input
:inputSearchValue="searchForm.HIDDENDESCR"
@search="handleSearch"
/>
<!-- 吸顶搜索框 end -->
<!-- 列表渲染 start -->
<list :list="list" @scroll-to-lower="scrollToLower">
<template #default="{ item }">
<view class="flex-between main-title">
<view class="u-line-1">{{ item.HIDDENDESCR || "暂无" }}</view>
<view :class="hiddenLevelColor[item.HIDDENLEVEL]">
{{ item.HIDDENLEVELNAME }}
</view>
</view>
<view class="flex-between subtitle mt-5">
<view>来源{{ hiddenSource[item.SOURCE] }}</view>
</view>
<view class="flex-between subtitle mt-5">
<view>隐患发现人{{ item.findUserNames || "暂无" }}</view>
<view>
隐患发现时间{{
item.DISCOVERYTIME ? formatTime(item.DISCOVERYTIME) : "暂无"
}}
</view>
</view>
<view class="flex-between subtitle mt-5">
<view>隐患确认人{{ item.confirmUserName || "暂无" }}</view>
<view>
隐患确认时间{{
item.CONFIRM_TIME ? formatTime(item.CONFIRM_TIME) : "暂无"
}}
</view>
</view>
<view class="flex-between subtitle mt-5">
<view>
隐患状态
<text v-if="item.exaSTATE === '1'"></text>
<text v-else-if="item.exaSTATE === '2'">审核通过</text>
<text v-else></text>
</view>
<view class="flex-between">
<view v-if="item.exaSTATE === -1">
<u-button
type="primary"
size="mini"
shape="circle"
@click="handleClickDisposalReview(item)"
>
处置审核
</u-button>
</view>
<view class="ml-10">
<u-button
type="primary"
size="mini"
shape="circle"
@click="handleClickView(item)"
>
查看
</u-button>
</view>
</view>
</view>
</template>
</list>
<!-- 列表渲染 end -->
</view>
</template>
<script>
import keyWordSearchInput from "@/components/keyWordSearchInput/index.vue";
import List from "@/components/list/list.vue";
import * as specialDisposalReviewApi from "../../api/index";
import dayjs from "dayjs";
import { HIDDEN_LEVEL_COlOR, HIDDEN_SOURCE } from "@/utils/constant";
import { special_disposal_review_lsit } from "@/Mock/responseData.js";
export default {
components: { keyWordSearchInput, List },
data() {
return {
store: this.$store, // store
searchForm: {
HIDDENDESCR: "",
},
isRequestEnd: false, //
pagination: {
showCount: 10,
currentPage: 1,
stateConfirm: "0",
total: 0,
},
list: [],
};
},
created() {},
mounted() {},
//
onShow() {
this.getList();
},
computed: {
hiddenLevelColor() {
return HIDDEN_LEVEL_COlOR;
},
hiddenSource() {
return HIDDEN_SOURCE;
},
},
methods: {
/** 处理搜索事件 */
async handleSearch(val) {
this.pagination = {
...this.pagination,
currentPage: 1,
showCount: 10,
total: 0,
};
await this.getList(val);
},
/** 获取列表数据 */
getList() {
if (this.isRequestEnd) return null;
uni.showLoading({
title: "加载中",
});
let { USER_ID, CORPINFO_ID, DEPARTMENT_ID } = this.store.state.userInfo;
// specialDisposalReviewApi.getHiddenSpecialDisposalReviewList({
// USER_ID: USER_ID,
// CORPINFO_ID,
// currentPage: this.pagination.currentPage,
// showCount: this.pagination.showCount,
// DISPOSESTATE: 2,
// stateConfirm: this.pagination.stateConfirm,
// USERDEPT: DEPARTMENT_ID,
// SELFUSERID: USER_ID,
// corpinfoId: CORPINFO_ID,
// loginUserId: USER_ID,
// });
// mock
setTimeout(() => {
this.list = special_disposal_review_lsit;
this.pagination.total = special_disposal_review_lsit.length;
uni.hideLoading();
}, 400);
},
/** 格式化日期时间 */
formatTime(val) {
return dayjs(val).format("YYYY-MM-DD");
},
/** 向下滚动加载数据 */
async scrollToLower() {
this.pagination.currentPage = this.pagination.currentPage++;
if (this.total >= this.pagination.currentPage) await this.getList();
},
/** 处置审核按钮事件 */
handleClickDisposalReview(ext) {
uni.$u.route(
"/hiddenManageSubPackages/pages/special_disposal_review/disposal_review",
{
HIDDEN_ID: ext.HIDDEN_ID,
HIDDENEXAMINE_ID: ext.HIDDENEXAMINE_ID,
}
);
},
/** 查看按钮事件 */
handleClickView(ext) {
uni.$u.route(
"/hiddenManageSubPackages/pages/special_disposal_review/view",
{
HIDDEN_ID: ext.HIDDEN_ID,
HIDDENEXAMINE_ID: ext.HIDDENEXAMINE_ID,
}
);
},
},
};
</script>
<style lang="scss" scoped>
.u-line-1 {
width: 500rpx;
}
</style>

View File

@ -0,0 +1,31 @@
<template>
<view class="container">
<view class="card">
<app-hidden-view :hidden-id="hiddenId" />
</view>
</view>
</template>
<script>
import AppHiddenView from "@/components/hiddenView/index.vue";
export default {
components: { AppHiddenView },
onLoad(query) {
this.hiddenId = query.HIDDEN_ID;
this.hiddenExamineId = query.HIDDENEXAMINE_ID;
},
mounted() { },
data() {
return {
hiddenId: "",
hiddenExamineId: "",
};
},
};
</script>
<style scoped lang="scss"></style>

54
main.js
View File

@ -1,31 +1,33 @@
import Vue from 'vue'
import store from './store'
import App from './App'
import uView from 'uview-ui'
import Vue from "vue";
import store from "./store";
import App from "./App";
import uView from "uview-ui";
import empty from '@/components/empty/empty.vue'
import uniTable from '@/components/uni-table/uni-table/uni-table.vue'
import uniTbody from '@/components/uni-table/uni-tbody/uni-tbody.vue'
import uniThead from '@/components/uni-table/uni-thead/uni-thead.vue'
import uniTr from '@/components/uni-table/uni-tr/uni-tr.vue'
import uniTh from '@/components/uni-table/uni-th/uni-th.vue'
import uniTd from '@/components/uni-table/uni-td/uni-td.vue'
import empty from "@/components/empty/empty.vue";
import uniTable from "@/components/uni-table/uni-table/uni-table.vue";
import uniTbody from "@/components/uni-table/uni-tbody/uni-tbody.vue";
import uniThead from "@/components/uni-table/uni-thead/uni-thead.vue";
import uniTr from "@/components/uni-table/uni-tr/uni-tr.vue";
import uniTh from "@/components/uni-table/uni-th/uni-th.vue";
import uniTd from "@/components/uni-table/uni-td/uni-td.vue";
import line from '@/components/line/index.vue';
Vue.component('empty',empty)
Vue.component('uni-table',uniTable)
Vue.component('uni-tbody',uniTbody)
Vue.component('uni-thead',uniThead)
Vue.component('uni-tr',uniTr)
Vue.component('uni-th',uniTh)
Vue.component('uni-td',uniTd)
Vue.use(uView)
Vue.config.productionTip = false
Vue.component("empty", empty);
Vue.component("uni-table", uniTable);
Vue.component("uni-tbody", uniTbody);
Vue.component("uni-thead", uniThead);
Vue.component("uni-tr", uniTr);
Vue.component("uni-th", uniTh);
Vue.component("uni-td", uniTd);
Vue.component("AppLine", line);
Vue.use(uView);
Vue.config.productionTip = false;
// Vue.prototype.$filePath = 'https://qgqy.qhdsafety.com/file/'
Vue.prototype.$filePath = 'https://skqhdg.porthebei.com:9004/file/'
Vue.prototype.$filePath = "https://skqhdg.porthebei.com:9004/file/";
App.mpType = 'app'
App.mpType = "app";
const app = new Vue({
...App,
store
})
app.$mount()
...App,
store,
});
app.$mount();

11
package-lock.json generated
View File

@ -9,6 +9,7 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"dayjs": "^1.11.12",
"uview-ui": "^2.0.36",
"vue": "^2.7.14",
"vuex-persistedstate": "^3.2.1"
@ -59,6 +60,11 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
},
"node_modules/dayjs": {
"version": "1.11.12",
"resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.12.tgz",
"integrity": "sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg=="
},
"node_modules/deepmerge": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
@ -215,6 +221,11 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
},
"dayjs": {
"version": "1.11.12",
"resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.12.tgz",
"integrity": "sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg=="
},
"deepmerge": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",

View File

@ -4,6 +4,7 @@
"description": "<p align=\"center\"> <img alt=\"logo\" src=\"https://uviewui.com/common/logo.png\" width=\"120\" height=\"120\" style=\"margin-bottom: 10px;\"> </p> <h3 align=\"center\" style=\"margin: 30px 0 30px;font-weight: bold;font-size:40px;\">uView</h3> <h3 align=\"center\">多平台快速开发的UI框架</h3>",
"main": "main.js",
"dependencies": {
"dayjs": "^1.11.12",
"uview-ui": "^2.0.36",
"vue": "^2.7.14",
"vuex-persistedstate": "^3.2.1"

View File

@ -2,7 +2,8 @@
"easycom": {
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
},
"pages": [{
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationStyle": "custom",
@ -50,7 +51,6 @@
"navigationBarTitleText": "修改信息"
}
},
{
"path": "pages/electronic_work_card/index",
"style": {
@ -63,6 +63,18 @@
"navigationBarTitleText": "服务单位管理"
}
},
{
"path": "pages/hidden_investigation/index",
"style": {
"navigationBarTitleText": "隐患排查"
}
},
{
"path": "pages/hidden_management/index",
"style": {
"navigationBarTitleText": "隐患治理"
}
},
{
"path": "pages/service_unit_management/view",
"style": {
@ -169,6 +181,139 @@
}
}
],
"subPackages": [
{
"root": "hiddenManageSubPackages",
"pages": [
{
"path": "pages/hidden_confirm/index",
"style": {
"navigationBarTitleText": "隐患确认"
}
},
{
"path": "pages/hidden_confirm/confirm",
"style": {
"navigationBarTitleText": "隐患确认"
}
},
{
"path": "pages/hidden_confirm/reject",
"style": {
"navigationBarTitleText": "打回"
}
},
{
"path": "pages/hidden_confirm/view",
"style": {
"navigationBarTitleText": "隐患查看"
}
},
{
"path": "pages/hidden_neglect/index",
"style": {
"navigationBarTitleText": "忽略隐患"
}
},
{
"path": "pages/hidden_neglect/view",
"style": {
"navigationBarTitleText": "忽略隐患"
}
},
{
"path": "pages/hidden_rectification/index",
"style": {
"navigationBarTitleText": "隐患整改"
}
},
{
"path": "pages/hidden_rectification/delay",
"style": {
"navigationBarTitleText": "延期申请"
}
},
{
"path": "pages/hidden_rectification/rectification",
"style": {
"navigationBarTitleText": "整改"
}
},
{
"path": "pages/special_disposal_review/index",
"style": {
"navigationBarTitleText": "特殊处置审核"
}
},
{
"path": "pages/special_disposal_review/view",
"style": {
"navigationBarTitleText": "查看"
}
},
{
"path": "pages/special_disposal_review/disposal_review",
"style": {
"navigationBarTitleText": "特殊处置审核"
}
},
{
"path": "pages/delay_review/index",
"style": {
"navigationBarTitleText": "延期审核"
}
},
{
"path": "pages/delay_review/view",
"style": {
"navigationBarTitleText": "查看"
}
},
{
"path": "pages/delay_review/delay_review",
"style": {
"navigationBarTitleText": "延期审核"
}
},
{
"path": "pages/hidden_acceptance/index",
"style": {
"navigationBarTitleText": "隐患验收"
}
},
{
"path": "pages/hidden_acceptance/view",
"style": {
"navigationBarTitleText": "查看"
}
},
{
"path": "pages/hidden_acceptance/acceptance",
"style": {
"navigationBarTitleText": "隐患验收"
}
},
{
"path": "pages/hidden_report/index",
"style": {
"navigationBarTitleText": "隐患快报"
}
},
{
"path": "pages/hidden_record/index",
"style": {
"navigationBarTitleText": "隐患记录"
}
},
{
"path": "pages/hidden_record/view",
"style": {
"navigationBarTitleText": "查看"
}
}
]
}
],
"globalStyle": {
"navigationBarTextStyle": "white",
"navigationBarTitleText": "uni-app",

View File

@ -0,0 +1,105 @@
<template>
<view class="menu">
<view class="main_title">隐患治理</view>
<view class="navigator_group">
<navigator
class="navigator"
hover-class="none"
url=""
v-if="false"
>
<image src="/static/icon-apps/hidden-investigation-1.png" mode=""></image>
<view class="text">隐患排查</view>
</navigator>
<navigator
class="navigator"
hover-class="none"
url="/hiddenManageSubPackages/pages/hidden_report/index"
>
<image src="/static/icon-apps/hidden-investigation-2.png" mode=""></image>
<view class="text">隐患快报</view>
</navigator>
<navigator
class="navigator"
hover-class="none"
url=""
v-if="false"
>
<image src="/static/icon-apps/hidden-investigation-3.png" mode=""></image>
<view class="text">检查记录</view>
</navigator>
<navigator
class="navigator"
hover-class="none"
url="/hiddenManageSubPackages/pages/hidden_record/index"
>
<image src="/static/icon-apps/hidden-investigation-4.png" mode=""></image>
<view class="text">隐患记录</view>
</navigator>
</view>
</view>
</template>
<script>
export default {
data() {
return {};
},
onLoad() {},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
.menu {
background-color: #fff;
padding: 20rpx;
box-shadow: 0 0 20rpx #cccccc;
margin: 10rpx 10rpx 20rpx 10rpx;
border-radius: 10rpx;
.main_title {
font-weight: bold;
display: flex;
align-items: center;
color: #989898;
font-size: 28rpx;
&::before {
content: "";
display: block;
width: 8rpx;
height: 28rpx;
background-color: #6180f1;
border-radius: 30%;
margin-right: 14rpx;
}
}
.navigator_group {
padding: 30rpx 0 20rpx 0;
display: flex;
gap: 25rpx;
flex-wrap: wrap;
.navigator {
flex-basis: calc(25% - 25rpx);
text-align: center;
position: relative;
image {
width: 52rpx;
height: 52rpx;
}
.text {
font-size: 24rpx;
}
}
}
}
</style>

View File

View File

@ -0,0 +1,135 @@
<template>
<view class="menu">
<view class="main_title">隐患治理</view>
<view class="navigator_group">
<navigator
class="navigator"
hover-class="none"
url="/hiddenManageSubPackages/pages/hidden_confirm/index"
>
<image src="/static/icon-apps/icon-yhzl-1.png" mode=""></image>
<view class="text">隐患确认</view>
</navigator>
<navigator
class="navigator"
hover-class="none"
url="/hiddenManageSubPackages/pages/hidden_neglect/index"
>
<image src="/static/icon-apps/icon-yhzl-2.png" mode=""></image>
<view class="text">忽略隐患</view>
</navigator>
<navigator
class="navigator"
hover-class="none"
url="/hiddenManageSubPackages/pages/hidden_rectification/index"
>
<image src="/static/icon-apps/icon-yhzl-3.png" mode=""></image>
<view class="text">隐患整改</view>
</navigator>
<navigator
class="navigator"
hover-class="none"
url="/hiddenManageSubPackages/pages/special_disposal_review/index"
>
<image src="/static/icon-apps/icon-yhzl-4.png" mode=""></image>
<view class="text">特殊处置审核</view>
</navigator>
<navigator
class="navigator"
hover-class="none"
url="/hiddenManageSubPackages/pages/delay_review/index"
>
<image src="/static/icon-apps/icon-yhzl-5.png" mode=""></image>
<view class="text">延期审核</view>
</navigator>
<navigator
class="navigator"
hover-class="none"
url="/hiddenManageSubPackages/pages/hidden_acceptance/index"
>
<image src="/static/icon-apps/icon-yhzl-6.png" mode=""></image>
<view class="text">隐患验收</view>
</navigator>
<navigator
class="navigator"
hover-class="none"
url="/hiddenManageSubPackages/pages/hidden_report/index"
>
<image src="/static/icon-apps/hidden-investigation-2.png" mode=""></image>
<view class="text">隐患快报</view>
</navigator>
<navigator
class="navigator"
hover-class="none"
url="/hiddenManageSubPackages/pages/hidden_record/index"
>
<image src="/static/icon-apps/hidden-investigation-4.png" mode=""></image>
<view class="text">隐患记录</view>
</navigator>
</view>
</view>
</template>
<script>
export default {
data() {
return {};
},
onLoad() {},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
.menu {
background-color: #fff;
padding: 20rpx;
box-shadow: 0 0 20rpx #cccccc;
margin: 10rpx 10rpx 20rpx 10rpx;
border-radius: 10rpx;
.main_title {
font-weight: bold;
display: flex;
align-items: center;
color: #989898;
font-size: 28rpx;
&::before {
content: "";
display: block;
width: 8rpx;
height: 28rpx;
background-color: #6180f1;
border-radius: 30%;
margin-right: 14rpx;
}
}
.navigator_group {
padding: 30rpx 0 20rpx 0;
display: flex;
gap: 25rpx;
flex-wrap: wrap;
.navigator {
flex-basis: calc(25% - 25rpx);
text-align: center;
position: relative;
image {
width: 52rpx;
height: 52rpx;
}
.text {
font-size: 24rpx;
}
}
}
}
</style>

View File

View File

@ -51,7 +51,7 @@ export default {
},
{
img: require('../../static/icon-apps/app_icons2.png'),
title: '服务单位 管理',
title: '服务单位管理',
url: '/pages/service_unit_management/index'
},
{
@ -69,6 +69,16 @@ export default {
title: '就职单位',
url: '/pages/employed_by/index'
},
// {
// img: require('../../static/icon-apps/app_icons6.png'),
// title: '',
// url: '/pages/hidden_investigation/index'
// },
{
img: require('../../static/icon-apps/app_icons7.png'),
title: '隐患治理',
url: '/pages/hidden_management/index'
}
],
}
},

View File

@ -77,6 +77,7 @@ export default {
resData.PHOTO = this.$filePath + resData.PHOTO
}
await this.$store.dispatch('setUserInfo', resData);
await this.$store.dispatch('setFilePath', 'http://192.168.115.8088');
uni.$u.route({
url: '/pages/index/index',
type: 'reLaunch'

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
static/images/scan.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,43 +1,50 @@
import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedState from 'vuex-persistedstate'
import Vue from "vue";
import Vuex from "vuex";
import createPersistedState from "vuex-persistedstate";
Vue.use(Vuex)
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
userInfo: {
CORPINFO_ID: '',
DEPARTMENT_ID: '',
NAME: "",
ROLEID: "",
ROLE_NAME: "",
USERBZ: "",
USERNAME: "",
USER_ID: "",
state: {
userInfo: {
CORPINFO_ID: "",
DEPARTMENT_ID: "",
NAME: "",
ROLEID: "",
ROLE_NAME: "",
USERBZ: "",
USERNAME: "",
USER_ID: "",
PHOTO: "",
},
},
getters: {
getUserInfo: state => state.userInfo,
},
mutations: {
setUserInfo(state, userInfo) {
state.userInfo = userInfo
}
},
actions: {
setUserInfo({commit}, userInfo) {
commit('setUserInfo', userInfo)
}
},
plugins: [
createPersistedState({
storage: {
getItem: (key) => uni.getStorageSync(key), // 获取
setItem: (key, value) => uni.setStorageSync(key, value), // 存储
removeItem: (key) => uni.removeStorageSync(key) // 删除
}
})
]
})
export default store
},
filePath: "",
},
getters: {
getUserInfo: (state) => state.userInfo,
},
mutations: {
setUserInfo(state, userInfo) {
state.userInfo = userInfo;
},
setFilePath(state, filePath) {
state.filePath = filePath;
},
},
actions: {
setUserInfo({ commit }, userInfo) {
commit("setUserInfo", userInfo);
},
setFilePath({ commit }, filePath) {
commit("setFilePath", filePath);
},
},
plugins: [
createPersistedState({
storage: {
getItem: (key) => uni.getStorageSync(key), // 获取
setItem: (key, value) => uni.setStorageSync(key, value), // 存储
removeItem: (key) => uni.removeStorageSync(key), // 删除
},
}),
],
});
export default store;

139
styles/common.scss Normal file
View File

@ -0,0 +1,139 @@
.text-blue {
color: #3676f2;
}
.text-red {
color: #cb4238;
}
.text-white {
color: #fff;
}
.text-grey {
color: #979799;
}
.text-green {
color: #23b576;
}
.text-yellow {
color: #ffae00;
}
.yellow-bg {
color: #fbbd08;
background-color: #fef2ce;
padding: 10rpx 20rpx;
font-size: 24rpx;
border-radius: 10rpx;
}
.red-bg {
color: #e54d42;
background-color: #fadbd9;
padding: 10rpx 20rpx;
font-size: 24rpx;
border-radius: 10rpx;
}
.mt-10 {
margin-top: 20rpx;
}
.mt-5 {
margin-top: 10rpx;
}
.ml-10 {
margin-left: 20rpx;
}
.ml-5 {
margin-left: 10rpx;
}
.flex-end {
display: flex;
align-items: center;
justify-content: flex-end;
}
.flex-between {
display: flex;
align-items: center;
justify-content: space-between;
}
.flex-start {
display: flex;
align-items: center;
justify-content: flex-start;
}
.main-title {
color: #333333;
font-size: 30rpx;
font-weight: bold;
margin-bottom: 20rpx;
}
.subtitle {
color: #888888;
font-size: 28rpx;
}
.card {
padding: 20rpx;
background-color: #fff;
}
.container {
background-color: #fafafa;
min-height: 100vh;
}
.list {
.item {
background-color: #fff;
padding: 20rpx;
border-bottom: 1px solid #eee;
position: relative;
}
.u-button {
width: max-content !important;
margin: 0;
}
}
.u-form-item__body__right__content__slot {
position: relative;
.u-radio-group--row {
justify-content: flex-end;
gap: 20rpx;
}
.flex-start {
.u-radio-group--row {
justify-content: flex-start;
}
}
.select_content {
flex: 1;
display: flex;
align-items: center;
}
}
.u-form-item__body__right .u-form-item__body__right__content__slot {
justify-content: flex-start;
}
.u-form-item__body__right__message {
margin-bottom: 10rpx;
}

View File

@ -1,21 +1,21 @@
.status_bar {
height: var(--status-bar-height);
width: 100%;
background-color: #0037ff;
height: var(--status-bar-height);
width: 100%;
background-color: #0037ff;
.top_view {
height: var(--status-bar-height);
width: 100%;
position: fixed;
background-color: #0037ff;
top: 0;
z-index: 9999;
height: var(--status-bar-height);
width: 100%;
position: fixed;
background-color: #0037ff;
top: 0;
z-index: 9999;
}
}
.wui_banner{
.wui_banner {
height: 507upx;
position: relative;
overflow: hidden;
.wui-bar{
.wui-bar {
display: flex;
align-items: center;
min-height: 100upx;
@ -23,8 +23,8 @@
z-index: 9999;
position: absolute;
width: 100%;
.search-form{
background: rgba(255,255,255,0.2);
.search-form {
background: rgba(255, 255, 255, 0.2);
border-radius: 100upx;
flex: 1;
height: 60upx;
@ -35,21 +35,21 @@
align-items: center;
margin: 0 30upx;
padding: 0 30upx;
.cuIcon-search{
color: rgba(255,255,255,0.5);
.cuIcon-search {
color: rgba(255, 255, 255, 0.5);
margin-right: 16upx;
font-size: 28upx;
}
input{
color: rgba(255,255,255,0.5);
input {
color: rgba(255, 255, 255, 0.5);
flex: 1;
padding-right: 30upx;
height: 64upx;
line-height: 64upx;
font-size: 26upx;
background-color: transparent;
.phcolor{
color: rgba(255,255,255,0.5);
.phcolor {
color: rgba(255, 255, 255, 0.5);
}
}
}
@ -59,7 +59,7 @@
margin-right: 22upx;
}
}
.banner_img{
.banner_img {
z-index: 1;
width: 100%;
height: 100%;
@ -68,8 +68,6 @@
height: 100%;
}
}
}
.home-apps {
@ -80,7 +78,7 @@
border-radius: 40upx;
margin: 0 30upx;
display: flex;
flex-wrap:wrap;
flex-wrap: wrap;
.home-apps-item {
display: flex;
flex-direction: column;
@ -103,7 +101,7 @@
}
}
}
.home-message{
.home-message {
position: relative;
top: -160upx;
height: 120upx;
@ -113,25 +111,25 @@
padding: 0 30upx;
display: flex;
align-items: center;
.home-title{
.home-title {
width: 54px;
height: 54px;
margin-right: 10upx;
image{
image {
width: 100%;
height: 100%;
}
}
.home-content{
.home-content {
font-size: 28upx;
flex: 1;
}
.home-more{
.home-more {
color: #ccc;
font-size: 26upx;
}
}
.home-letters{
.home-letters {
position: relative;
top: -140upx;
background-color: #fff;
@ -139,48 +137,48 @@
margin: 0 30upx;
padding: 30upx;
.letters-title{
.letters-title {
width: 80px;
height: 21px;
image{
image {
width: 100%;
height: 100%;
}
}
.letters-content{
.letters-item{
.letters-content {
.letters-item {
border-bottom: 1upx solid #e5e5e5;
padding: 20upx 0;
&:last-child{
&:last-child {
border: none;
}
.lable{
.lable {
font-size: 30upx;
white-space: nowrap;
}
.font{
.font {
font-size: 28upx;
color: #666;
}
.letters-title{
.letters-title {
display: flex;
align-items: flex-start;
justify-content: space-between;
width: 100%;
.color-red{
.color-red {
color: #e50d0d;
font-weight:700;
font-weight: 700;
}
.color-org{
.color-org {
color: #ff5806;
font-weight:700;
font-weight: 700;
}
.color-nomal{
.color-nomal {
color: #e5a60d;
font-weight:700;
font-weight: 700;
}
}
.letters-sub-title{
.letters-sub-title {
display: flex;
align-items: flex-start;
justify-content: space-between;
@ -188,31 +186,29 @@
font-size: 30upx;
margin: 10upx 0;
}
.letters-date{
.letters-date {
display: flex;
align-items: center;
width: 100%;
font-size: 30upx;
}
}
}
}
.home-line{
.home-line {
position: relative;
top: -70upx;
text-align: center;
color: #ccc;
}
.sub_grid{
.sub_grid {
display: flex;
flex-wrap: wrap;
.grid_z{
.grid_z {
z-index: 999;
}
.grid_item{
.grid_item {
width: calc(47% - 4upx);
display: block;
padding: 30upx 0;
@ -220,61 +216,63 @@
margin-left: 2%;
margin-top: 2%;
text-align: center;
background-image: linear-gradient(to bottom right, rgba(0,138,255,1), rgba(91,74,255,1));
background-image: linear-gradient(
to bottom right,
rgba(0, 138, 255, 1),
rgba(91, 74, 255, 1)
);
border: 1upx solid #2084d9;
position: relative;
.grid_text{
.grid_text {
display: flex;
padding-left: 30upx;
.grid_tut{
.grid_tut {
width: 85%;
}
}
}
}
.message_list{
.message_list {
padding: 30upx;
.message_item{
.message_item {
position: relative;
.message_flex{
.message_flex {
width: calc(100% - 30upx);
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
.fontstyle{
.fontstyle {
font-size: 32upx;
line-height: 60upx;
}
.font0{
.font0 {
font-size: 30upx;
color: #666;
flex-basis: 72upx;
}
.message_time{
.message_time {
font-size: 26upx;
color: #666;
line-height: 60upx;
}
}
}
}
.message_item.arrow:after {
position: absolute;
top: 0;
right: 0;
bottom: 0;
display: block;
margin: auto;
width: 30upx;
height: 30upx;
color: #b4b4b4;
content: "\e6a3";
text-align: center;
font-size: 34upx;
font-family: cuIcon;
line-height: 30upx
}
position: absolute;
top: 0;
right: 0;
bottom: 0;
display: block;
margin: auto;
width: 30upx;
height: 30upx;
color: #b4b4b4;
content: "\e6a3";
text-align: center;
font-size: 34upx;
font-family: cuIcon;
line-height: 30upx;
}

View File

@ -1,154 +1,156 @@
.ml-10{
margin-left: 20upx !important;
.ml-10 {
margin-left: 20upx !important;
}
.mt-10{
margin-top: 20upx !important;
.mt-10 {
margin-top: 20upx !important;
}
.mb-10{
margin-bottom: 20upx !important;
.mb-10 {
margin-bottom: 20upx !important;
}
.mr-10{
margin-right: 20upx !important;
.mr-10 {
margin-right: 20upx !important;
}
.m-10{
margin: 20upx !important;
.m-10 {
margin: 20upx !important;
}
.p-10{
padding: 20upx !important;
.p-10 {
padding: 20upx !important;
}
.pl-10{
padding-left: 20upx !important;
.pl-10 {
padding-left: 20upx !important;
}
.pr-10{
padding-right: 20upx !important;
.pr-10 {
padding-right: 20upx !important;
}
.pt-10{
padding-top: 20upx !important;
.pt-10 {
padding-top: 20upx !important;
}
.pb-10{
padding-bottom: 20upx !important;
.pb-10 {
padding-bottom: 20upx !important;
}
.w100{
width: 100%;
.w100 {
width: 100%;
}
.flex1{
flex: 1;
.flex1 {
flex: 1;
}
.pr{
position: relative;
.pr {
position: relative;
}
.border{
border: 1px solid #e5e5e5;
.border {
border: 1px solid #e5e5e5;
}
.content {
position: relative;
min-height: 100vh;
background-color: $uni-bg-color-grey;
position: relative;
min-height: 100vh;
background-color: $uni-bg-color-grey;
}
.card{
padding: 20upx;
background-color: #FFFFFF;
.card {
padding: 20upx;
background-color: #ffffff;
}
.search{
border-bottom: 1px solid #ccc;
display: flex;
flex-direction: row;
.u-text{
width: 100upx !important;
flex: none !important;
}
.u-button {
height: 68upx !important;
}
.u-input__content__field-wrapper__field{
height: 42upx !important;
}
.search {
border-bottom: 1px solid #ccc;
display: flex;
flex-direction: row;
.u-text {
width: 100upx !important;
flex: none !important;
}
.u-button {
height: 68upx !important;
}
.u-input__content__field-wrapper__field {
height: 42upx !important;
}
}
.bth-mini{
width: auto !important;
border-radius: 15upx !important;
margin-left: unset;
margin-right: unset;
.bth-mini {
width: auto !important;
border-radius: 15upx !important;
margin-left: unset;
margin-right: unset;
}
.bth{
flex: 1;
border-radius: 15upx !important;
margin-left: unset;
margin-right: unset;
.bth {
flex: 1;
border-radius: 15upx !important;
margin-left: unset;
margin-right: unset;
}
.flex-between{
display: flex;
flex-direction: row;
justify-content: space-between;
.flex-between {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.flex-end{
display: flex;
flex-direction: row;
justify-content: flex-end;
.flex-end {
display: flex;
flex-direction: row;
justify-content: flex-end;
}
.flex-warp{
display: flex;
flex-direction: row;
flex-wrap: wrap;
.flex-warp {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.main-title{
color: #333333;
font-size: 30upx;
.main-title {
color: #333333;
font-size: 30upx;
}
.subtitle{
color: #888888;
font-size: 26upx;
.subtitle {
color: #888888;
font-size: 26upx;
}
.view-title{
border-left: 8upx solid #1d82fe;
.u-text{
padding-left: 10upx;
color: #353535 !important;
}
.view-title {
border-left: 8upx solid #1d82fe;
.u-text {
padding-left: 10upx;
color: #353535 !important;
}
}
.title{
font-weight: bold;
color: #000000;
font-size: 28upx;
.title {
font-weight: bold;
color: #000000;
font-size: 28upx;
}
.title-none{
.u-cell__body__content,.u-cell__title{
display: none !important;
}
.title-none {
.u-cell__body__content,
.u-cell__title {
display: none !important;
}
}
.title-show{
.u-cell__body__content,.u-cell__title{
display: flex !important;
}
.title-show {
.u-cell__body__content,
.u-cell__title {
display: flex !important;
}
}
.flex-none{
display: block;
.u-cell__body{
display: block !important;
}
.flex-none {
display: block;
.u-cell__body {
display: block !important;
}
}
.required{
&:before{
content: '*';
position: absolute;
left: 0;
color: #f56c6c;
font-size: 40upx;
font-weight: normal;
}
}
.form-item-block{
.u-form-item__body{
display: block !important;
.u-form-item__body__left{
width: 100% !important;
}
.u-form-item__body__right{
.u-form-item__body__right__content__slot{
justify-content: flex-start;
position: relative;
margin-left: 20upx;
}
}
.required {
&:before {
content: "*";
position: absolute;
left: 0;
color: #f56c6c;
font-size: 40upx;
font-weight: normal;
}
}
.form-item-block {
.u-form-item__body {
display: block !important;
.u-form-item__body__left {
width: 100% !important;
}
.u-form-item__body__right {
.u-form-item__body__right__content__slot {
justify-content: flex-start;
position: relative;
margin-left: 20upx;
}
}
}
}

View File

@ -5,43 +5,43 @@
border-bottom: 1px solid rgb(214, 215, 217);
}
}
.u-textarea{
.u-textarea {
padding: 18upx;
}
.u-form-item__body__left__content__required{
.u-form-item__body__left__content__required {
position: relative !important;
left: 0 !important;
margin-right: 10upx;
}
.u-form-item__body__left{
.u-form-item__body__left {
//flex: 1 !important;
}
.u-form-item__body__right{
.u-form-item__body__right__content__slot{
.u-form-item__body__right {
.u-form-item__body__right__content__slot {
justify-content: flex-end;
position: relative;
padding-right: 20upx;
}
.u-text{
.u-text {
justify-content: flex-end !important;
}
.u-popup{
.u-popup {
flex: unset !important;
}
}
.u-text__value{
.u-text__value {
font-size: 28upx !important;
}
.u-form-item__body__left__content__label{
.u-form-item__body__left__content__label {
font-size: 28upx !important;
}
.u-tabs__wrapper__nav__item{
.u-tabs__wrapper__nav__item {
flex: 1 !important;
}
.u-upload__deletable{
.u-upload__deletable {
height: 40upx !important;
width: 40upx !important;
.u-icon__icon{
.u-icon__icon {
font-size: 30upx !important;
line-height: 30upx !important;
}

View File

@ -0,0 +1,20 @@
## 1.0.92023-07-06
增加clear时同事发送input事件
## 1.0.82023-06-16
更新修复input事件
## 1.0.72023-06-15
增加输入事件
## 1.0.62023-06-09
增加demo
## 1.0.52023-06-09
更新more插槽的使用说明
## 1.0.42023-06-09
修复mode=more模式下input事件
## 1.0.32023-06-08
更改模式
## 1.0.22023-06-08
更改说明文件模式
## 1.0.12023-06-08
更新说明
## 1.0.02023-06-08
初始化next-search-more

View File

@ -0,0 +1,239 @@
<template>
<view class="next-search-more">
<view class="search" :style="{ backgroundColor: backgroundColor }">
<view class="content" :style="{ 'border-radius': radius + 'px', border: border }">
<view class="content-box" :class="{ center: mode === 'center' }">
<text class="icon icon-search">&#xe66f;</text>
<input class="input" :class="{ center: !active && mode === 'center' }" :focus="isFocus" :placeholder="placeholder" v-model="inputVal" @input="input" @focus="focus" @blur="blur" />
<text v-if="isDelShow" class="icon icon-del" @click="clear">&#xe61c;</text>
</view>
<view v-show="(active && isFixedSearchBtn && button === 'inside') || (isDelShow && button === 'inside')" class="searchBtn" @click="search"></view>
</view>
<template v-if="mode === 'common' || mode ==='center'">
<view v-if="button === 'outside'" class="button" :class="{ active: isFixedSearchBtn || active }" @click="search">
<view class="button-item">{{ !isFixedSearchBtn ? searchName : '搜索' }}</view>
</view>
</template>
<template v-else-if="mode === 'more'">
<view class="button active" @click="selectMore">
<view class="button-item"><text class="icon icon-more">&#xe61a;</text></view>
</view>
</template>
</view>
<view class="more-container-parent">
<view v-if="mode === 'more' && showMore" class="more-container">
<slot name="more"></slot>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
mode: {
type: String,
default: 'common'
},
button: {
type: String,
default: 'outside'
},
isFixedSearchBtn: {
type: Boolean,
default: true
},
radius: {
type: String,
default: '60'
},
placeholder: {
type: String,
default: '请输入搜索内容'
},
backgroundColor: {
type: String,
default: '#fff'
},
showMore: {
type: Boolean,
default: false
},
border: { type: String, default: '1px #f5f5f5 solid' }
},
data() {
return {
active: false,
inputVal: '',
searchName: '取消',
isDelShow: false,
isFocus: false,
timer: 0
};
},
methods: {
focus() {
this.active = true;
},
blur() {
this.isFocus = false;
if (!this.inputVal) {
this.active = false;
}
},
input() {
clearInterval(this.timer)
this.timer = setTimeout(() => {
this.$emit('input', this.inputVal);
}, 500)
},
clear() {
this.inputVal = '';
this.active = false;
this.$emit('input', this.inputVal);
this.$emit('search', '');
},
getFocus() {
this.isFocus = true;
},
search() {
if (!this.inputVal) return;
this.$emit('search', this.inputVal);
},
selectMore() {
this.$emit('moreClick')
}
},
created() {
this.$watch(() => this.inputVal, (newVal) => {
if (newVal) {
this.searchName = '搜索';
this.isDelShow = true;
} else {
this.searchName = '取消';
this.isDelShow = false;
}
})
}
};
</script>
<style lang="scss" scoped>
.next-search-more {
.search {
display: flex;
width: 100%;
border-bottom: 1px #f5f5f5 solid;
box-sizing: border-box;
padding: 15upx;
font-size: $uni-font-size-base;
background: #fff;
.content {
display: flex;
align-items: center;
width: 100%;
height: 60upx;
border: 1px #ccc solid;
background: #fff;
overflow: hidden;
transition: all 0.2s linear;
border-radius: 30px;
.content-box {
width: 100%;
display: flex;
align-items: center;
&.center {
justify-content: center;
}
.icon {
padding: 0 15upx;
&.icon-del {
font-size: 38upx;
}
}
.input {
width: 100%;
max-width: 100%;
line-height: 60upx;
height: 60upx;
transition: all 0.2s linear;
&.center {
width: 200upx;
}
&.sub {
// position: absolute;
width: auto;
color: grey;
}
}
}
.searchBtn {
height: 100%;
flex-shrink: 0;
padding: 0 30upx;
background: $uni-color-success;
line-height: 60upx;
color: #fff;
border-left: 1px #ccc solid;
transition: all 0.3s;
}
}
.button {
display: flex;
align-items: center;
justify-content: center;
position: relative;
flex-shrink: 0;
width: 0;
transition: all 0.2s linear;
white-space: nowrap;
overflow: hidden;
&.active {
padding-left: 15upx;
width: 100upx;
}
.icon-more {
font-size: 48upx;
}
}
}
.more-container-parent {
flex-shrink: 0;
width: 100%;
// position: fixed;
// position: sticky;
z-index: 997;
flex-wrap: nowrap;
display: flex;
flex-direction: row;
position: relative;
flex-direction: column;
.more-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: auto;
background-color: #ffffff;
padding: 20rpx;
border-radius: 0 0 30rpx 30rpx;
box-sizing: border-box;
overflow: hidden;
}
}
}
@font-face {
font-family: 'iconfont';
src: url('https://at.alicdn.com/t/c/font_4110624_nikfg21uyk8.ttf?t=1686190660183') format('truetype');
}
.icon {
font-family: iconfont;
font-size: 32upx;
font-style: normal;
color: #999;
}
</style>

View File

@ -0,0 +1,79 @@
{
"id": "next-search-more",
"displayName": "next-search-more(vue2 vue3多端通用)搜索框组合、搜索下拉框组件全端可用",
"version": "1.0.9",
"description": "搜索下拉框,支持多种展示形式,可以结合第三方组件一起使用,可自定义",
"keywords": [
"远程搜索",
"组合搜索",
"配置搜索",
"自定义搜索",
"搜索下拉框"
],
"repository": "",
"engines": {
"HBuilderX": "^3.1.1"
},
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "插件不采集任何数据",
"permissions": "无"
},
"npmurl": "",
"type": "component-vue"
},
"uni_modules": {
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "n",
"app-nvue": "n"
},
"H5-mobile": {
"Safari": "n",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "n",
"Edge": "n",
"Firefox": "n",
"Safari": "n"
},
"小程序": {
"微信": "y",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u"
},
"快应用": {
"华为": "n",
"联盟": "n"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}

View File

@ -0,0 +1,215 @@
## next-search-more --搜索更多搜索下拉search-more
> 遇到问题或有建议可以加入QQ群(<font color=#f00>455948571</font>)反馈
> 如果觉得组件不错,<font color=#f00>给五星鼓励鼓励</font>咯!
## 使用
>[从uniapp插件市场导入](https://ext.dcloud.net.cn/plugin?name=next-search-more)
```html
<template>
<view class="index">
<view style="padding: 10px 0;background-color:#000000;color: #fff;font-size: 13px;"><text>1. mode=more模式</text></view>
<next-search-more mode="more" :showMore="showMore" @moreClick="moreClick">
<!--以下demo你可以借助第三方的插件实现你想要的任何复杂功能-->
<template #more>
<u--form labelWidth="80" labelAlign="right">
<u-form-item label="radio:">
<u-radio-group v-model="searchForm.radio" placement="row">
<u-radio v-for="(item, index) in optionslist" :key="index" :label="item.name" :name="item.name" />
</u-radio-group>
</u-form-item>
<u-form-item label="checkbox:">
<u-checkbox-group v-model="searchForm.checkbox" placement="row">
<u-checkbox v-for="(item, index) in optionslist" :key="index" :label="item.name" :name="item.name" />
</u-checkbox-group>
</u-form-item>
<u-form-item label="rate:">
<u-rate :count="5" v-model="searchForm.rate" />
</u-form-item>
<u-form-item label="switch:">
<u-switch v-model="searchForm.switch"></u-switch>
</u-form-item>
<u-form-item label="other:">
<next-search-select
:multiple="false"
:list="options"
label-key="projectName"
value-key="id"
placeholder=" 请选择报备项目"
title="选择报备项目"
v-model:value="searchForm.projectId"
@search="searchFunc"
@change="changeCallback"
clearable
></next-search-select>
</u-form-item>
<view class="flex-row">
<u-button @click="cancel" :customStyle="{margin: '10rpx'}" text="取消"></u-button>
<u-button @click="comfirm" :customStyle="{margin: '10rpx'}" type="primary" text="确定"></u-button>
</view>
</u--form>
</template>
</next-search-more>
<view style="padding: 10px 0;background-color:#000000;color: #fff;font-size: 13px;"><text>2. mode=common;button=outside模式</text></view>
<next-search-more mode="common" button="outside" />
<view style="padding: 10px 0;background-color:#000000;color: #fff;font-size: 13px;"><text>3. mode=common;button=inside模式</text></view>
<next-search-more mode="common" button="inside" />
<view style="padding: 10px 0;background-color:#000000;color: #fff;font-size: 13px;"><text>4. mode=center;button=outside模式</text></view>
<next-search-more mode="center" button="outside" />
<view style="padding: 10px 0;background-color:#000000;color: #fff;font-size: 13px;"><text>5. mode=center;button=inside模式</text></view>
<next-search-more mode="center" button="inside" />
<view style="padding: 10px 0;background-color:#000000;color: #fff;font-size: 13px;"><text>6. mode=center;button=inside;isFixedSearchBtn=false模式</text></view>
<next-search-more mode="center" button="inside" :isFixedSearchBtn="false" />
<view class="content-block"><text>全站ICON图标海量下载iconfont图标大全,为你优选-包图网,全站ICON图标海量下载iconfont图标大全,为你优选-包图网</text></view>
</view>
</template>
```
### vue3 + ts 使用
```js
<script lang="ts">
import { ref, nextTick, toRefs, toRaw, unref, reactive } from 'vue'
export default {
setup() {
const showMore = ref(false)
const searchForm = reactive({
radio: '',
checkbox: '',
rate: 3,
switch: false,
projectId: ''
})
let dataLength = 0
const options = ref<any>([])
const optionslist = ref([{
name: '苹果',
disabled: false
},
{
name: '香蕉',
},
{
name: '橙子',
}
])
function cancel () {
showMore.value = false
}
function comfirm () {
showMore.value = false
}
function moreClick () {
showMore.value = !unref(showMore)
}
function searchFunc(val?) {
console.log("搜索的关键字:", val)
uni.showLoading({
title: '请稍后...',
icon: 'none'
})
// 模拟ajax请求
setTimeout(() => {
options.value = []
dataLength = 0
if (dataLength < 40) {
for (let i = 0; i < 40; i++) {
options.value.push({
id: `id-${val ? val + '-' : ''}${dataLength + i}`,
projectName: `项目item-${val ? val + '-' : ''}${dataLength + i}`,
ohterKey: `test-${i}`
})
}
dataLength = unref(options).length
}
uni.hideLoading()
}, 1000)
}
function changeCallback(item) {
console.log("选中的item", item)
}
searchFunc()
return {
showMore,
moreClick,
optionslist,
searchForm,
searchFunc,
options,
changeCallback,
comfirm,
cancel
}
}
}
</script>
<style lang="scss">
.flex-row {
display: flex;
justify-content: space-around;
}
.content-block {
border-radius: 20rpx;
border: 1rpx solid #ccc;
margin: 20rpx;
padding: 20rpx;
}
</style>
<style lang="scss">
page {
background: #ccc;
}
</style>
```
### vue2 同样支持在这里不再写demo
### 组件按需加载
如果不需要组件全局加载而已把组件拷贝到项目的components目录下单独引入进来使用即可达到按需加载的效果
### 预览
***
| 功能预览 | | 项目中应用演示 |
| :--------------------------------------------------------------------------:| | :-----------------------------------------------------------------------------:|
| ![](https://lixueshiaa.github.io/webtest/www/static/next-search-more.gif) | | ![](https://lixueshiaa.github.io/webtest/www/static/next-search-more-demo.gif) |
## 参数
### next-search-more Props
可选参数属性列表
|参数名 |说明 |类型 |是否必填 |默认值 |可选值 |
|---- |---- |---- |---- |---- |---- |
|mode |模式mode支持common模式 center模式 more模式 |String |否 |common |center,more|
|button |搜索按钮的模式支持outside模式 inside模式 |String |否 |outside |inside |
|isFixedSearchBtn |是否固定搜索按钮 |Boolean |否 |true |false |
|radius |搜索控件的radius |String, Number |否 |60 |- |
|placeholder | placeholder |String |否 |请输入搜索内容 |- |
|backgroundColor |搜索控件的背景颜色 |String |否 |#fff |- |
|showMore | mode=more模式下用于控制打开下拉弹层 |Boolean |否 |false |true |
|border| border |String |否 |1px #f5f5f5 solid |- |
# Event 事件
|事件名 |说明 |类型 |回调参数 |
|---- |---- |---- |---- |
|input |搜索框输入事件 |emit |- |
|search|搜索触发的事件 |emit |- |
|moreClick|更多按钮点击触发事件 |emit |- |
## Slot 插槽
|名称 |说明 |参数 |
|---- |---- |---- |
|more |more插槽在mode=more模式下用于存放下拉框内容 |无 |

View File

@ -0,0 +1,177 @@
## 1.9.12024-07-29
更新说明
## 1.9.02024-07-29
更新说明
## 1.8.92024-06-28
完善说明文件
## 1.8.82024-06-21
更新插件
## 1.8.72024-05-08
fix bug
## 1.8.62024-04-07
功能更新
## 1.8.52024-04-07
修复bug
## 1.8.32024-04-06
update
## 1.8.22024-04-06
update
## 1.8.12024-04-06
fix bug
## 1.8.02024-04-03
优化
## 1.7.92024-04-03
优化编辑tree功能
## 1.7.82024-04-02
超集功能上线
## 1.7.72024-03-26
增加expandedMode=singe
## 1.7.62024-02-27
修复特殊字符的处理方法
## 1.7.52024-02-26
增加无子节点的父节点配置
## 1.7.42024-02-05
修复vue2语法使用问题
## 1.7.32024-02-05
修复vue2插槽不显示bug
## 1.7.22024-02-05
优化大数据的性能
## 1.7.12024-01-25
优化功能说明
## 1.7.02024-01-24
增加expandedKeys默认展开项目配置
## 1.6.92024-01-23
增加change事件
## 1.6.82024-01-22
搜索模式下,不再响应展开收起逻辑
## 1.6.72024-01-04
修复异步加载节点搜索展示bug
## 1.6.62023-12-29
修复next-tree异步加载节点关闭bug
## 1.6.52023-12-21
fix bug
## 1.6.42023-12-21
fix bug
## 1.6.32023-12-21
更新vue2版本说明文档
## 1.6.22023-12-21
修复说明文档
## 1.6.12023-12-18
增加empty插槽
## 1.6.02023-12-18
增加empty插槽
## 1.5.92023-12-15
修改说明文件
## 1.5.82023-12-15
修复changeVerify函数单选时返回参数bug
## 1.5.72023-12-14
修复checkStrictlyModel === 'strong'的bug
## 1.5.62023-12-13
代码优化
## 1.5.52023-12-13
优化changeVerify的使用
## 1.5.42023-12-12
修复提示层级问题
## 1.5.32023-12-12
优化uiMode=page模式下的使用
## 1.5.22023-12-11
增加uiMode配置实现页面模式展示
## 1.5.12023-12-06
更新说明
## 1.5.02023-12-06
更新插件使用注意事项
## 1.4.92023-12-01
增加topBar插槽
## 1.4.82023-11-30
增加changeVerify验证函数实现change的各种控制
## 1.4.72023-11-30
增加弹层容器高度可配置
## 1.4.62023-11-28
修复bug
## 1.4.52023-11-28
修复disabled是需要显示灰色不可操作
## 1.4.42023-11-28
增加说明
## 1.4.32023-11-28
增加主题配置
## 1.4.22023-11-28
增加异步加载时,子节点说明
## 1.4.12023-11-27
修复说明bug
## 1.4.02023-11-27
next-tree 全面说明文档
## 1.3.62023-11-27
增加远程加载loadData全面实现全功能覆盖
## 1.3.52023-11-27
增加title的定义
## 1.3.42023-11-27
增加title支持自定义定制
## 1.3.32023-11-21
增加搜索模式searchModel=depHighlight模式从属高亮显示模式
## 1.3.22023-11-20
修复valueKey设置bug
## 1.3.12023-11-17
增加说明文件和demo
## 1.3.02023-11-17
修复clear时不支持关联模式的设置
## 1.2.92023-11-17
增加checkStrictlyModel模式设置强关联和弱关联
## 1.2.82023-11-16
增加next-tree的辅助线模式
## 1.2.72023-11-16
优化next-tree
## 1.2.62023-11-16
修复搜索时,隐藏未打开的数据
## 1.2.52023-11-16
修复搜索无法点击,和级联半选不生效问题
## 1.2.42023-11-16
更新新功能插件使用说明
## 1.2.32023-11-16
增加插槽模式只是高ui要求定制
## 1.2.22023-11-15
修复checkStrictly配置下子关联父的选择状态
## 1.2.12023-11-15
增加半选提示功能配置showHalfCheckedTips
## 1.2.02023-11-14
修复disabled配置状态下父子级联不需要改变disabled设置项的选择状态
## 1.1.92023-11-13
增强大数据量体验交互,增加筛选搜索模式
## 1.1.82023-11-13
增加清除clear和取消cancel事件
## 1.1.72023-11-08
更新next-tree插件功能清单说明
## 1.1.62023-11-07
update说明文档
## 1.1.52023-11-07
update
## 1.1.42023-11-07
更新readme.md说明
## 1.1.32023-11-07
更新说明demo
## 1.1.22023-11-07
增加子节点按需渲染演示demo
## 1.1.12023-11-07
增加清空功能
## 1.1.02023-11-07
增加子孙节点按需渲染,扩展本插件支持大数据量渲染;
## 1.0.92023-10-26
增加文件说明
## 1.0.82023-09-14
增加禁用节点属性配置disabledKey
## 1.0.72023-09-06
增加checkStrictly实现父子节点关联
## 1.0.62023-09-06
更新vue2使用过程视图不更新的技术说明
## 1.0.52023-09-06
修复说明文档
## 1.0.42023-06-19
修改demo
## 1.0.32023-06-19
更新vue2的使用demo
## 1.0.22023-06-19
修复说明文档
## 1.0.12023-05-10
更新说明文件
## 1.0.02023-05-09
初始化项目

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,269 @@
@font-face {
font-family: 'iconfont';
src: url('//at.alicdn.com/t/c/font_4110624_qs48wckazsh.ttf?t=1712479573821') format('truetype');
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.iconfont {
font-family: iconfont;
font-style: normal;
}
.iconfont-loading {
font-family: iconfont;
display: inline-block;
font-style: normal;
animation: spin 1s linear infinite;
}
.next-tree-mask {
position: fixed;
top: 0rpx;
right: 0rpx;
bottom: 0rpx;
left: 0rpx;
z-index: 997;
background-color: rgba(0, 0, 0, 0.6);
opacity: 0;
transition: all 0.3s ease;
visibility: hidden;
}
.next-tree-mask.show {
visibility: visible;
opacity: 1;
}
.next-tree-cnt {
position: fixed;
top: 0rpx;
right: 0rpx;
bottom: 0rpx;
left: 0rpx;
z-index: 997;
top: 360rpx;
transition: all 0.3s ease;
transform: translateY(100%);
}
.next-tree-cnt.next-tree-cnt-page {
transition: none;
}
.next-tree-cnt.show {
transform: translateY(0);
}
.next-tree-bar {
background-color: #fff;
height: 72rpx;
padding-left: 20rpx;
padding-right: 20rpx;
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
border-bottom-width: 1rpx !important;
border-bottom-style: solid;
border-bottom-color: #f5f5f5;
font-size: 32rpx;
color: #757575;
line-height: 1;
}
.next-tree-bar-btns {
display: inline-block;
display: flex;
flex-direction: row;
}
.btn-divid {
display: inline-block;
width: 1px;
margin: 0 10px;
background-color: #ccc;
}
.next-tree-bar-confirm {
color: #f9ae3d;
}
.next-tree-view {
position: absolute;
top: 0rpx;
right: 0rpx;
bottom: 0rpx;
left: 0rpx;
top: 72rpx;
background-color: #fff;
padding-top: 20rpx;
padding-right: 20rpx;
padding-bottom: 20rpx;
padding-left: 20rpx;
}
.next-tree-view-sc {
height: 100%;
overflow: hidden;
}
.next-tree-view-sc .empty {
text-align: center;
color: #757575;
padding: 30rpx;
}
.next-tree-item-block {
}
.next-tree-item {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 26rpx;
color: #757575;
line-height: 1;
height: 0;
opacity: 0;
transition: 0.2s;
position: relative;
overflow: hidden;
}
.next-tree-item .icon-btn {
font-size: 30rpx;
margin-right: 20rpx;
}
.next-tree-item .left-line {
position: relative;
width: 1rpx;
height: 100%;
box-sizing: border-box;
}
.next-tree-item .left-line::before {
position: absolute;
content: "";
width: 1rpx;
height: 100%;
background-color: rgba(204,204,204,0.9);
box-sizing: border-box;
left: -18rpx;
}
.next-tree-item .parent-horizontal-line {
width: 1rpx;
height: 100%;
position: absolute;
top: 0;
left: 0rpx;
box-sizing: border-box;
background-color: rgba(204,204,204,0.9);
}
.next-tree-item .left-line .horizontal-line {
width: 20rpx;
height: 1rpx;
position: absolute;
top: 40rpx;
left: 0rpx;
background-color: rgba(204,204,204,0.9);
box-sizing: border-box;
}
.next-tree-item.show {
height: 80rpx;
opacity: 1;
}
.next-tree-item.showchild:before {
transform: rotate(90deg);
}
.next-tree-item.border {
border-bottom: 1rpx solid rgba(204,204,204,0.2);
}
.next-tree-item.last:before {
opacity: 0;
}
.next-tree-item.disabled {
color: #ccc!important;
}
.next-tree-icon {
width: 26rpx;
height: 26rpx;
margin-right: 8rpx;
}
.next-tree-label {
flex: 1;
display: flex;
align-items: center;
height: 100%;
line-height: 1.2;
}
.next-tree-label .label-input {
border: 1rpx solid #f0f0f0;
border-radius: 10rpx;
width: 100%;
padding: 12rpx 18rpx;
margin-right: 30rpx;
}
.next-tree-check {
width: 40px;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
}
.next-tree-check-yes,
.next-tree-check-no {
width: 20px;
height: 20px;
border-top-left-radius: 20%;
border-top-right-radius: 20%;
border-bottom-right-radius: 20%;
border-bottom-left-radius: 20%;
border-top-width: 1rpx;
border-left-width: 1rpx;
border-bottom-width: 1rpx;
border-right-width: 1rpx;
border-style: solid;
border-color: #f9ae3d;
display: flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
}
.next-tree-check-yes-b {
border-top-left-radius: 20%;
border-top-right-radius: 20%;
border-bottom-right-radius: 20%;
border-bottom-left-radius: 20%;
background-color: #f9ae3d;
color: #fff;
}
.next-tree-check-yes-b .icon-text {
font-size: 14px;
font-weight: normal;
font-family: uicon-iconfont;
display: flex;
flex-direction: row;
align-items: center;
}
.next-tree-check .radio {
border-top-left-radius: 50%;
border-top-right-radius: 50%;
border-bottom-right-radius: 50%;
border-bottom-left-radius: 50%;
}
.next-tree-check .radio .next-tree-check-yes-b {
border-top-left-radius: 50%;
border-top-right-radius: 50%;
border-bottom-right-radius: 50%;
border-bottom-left-radius: 50%;
}
.next-tree-item.disabled .next-tree-check-no {
color: #ccc!important;
}
.next-tree-item.disabled .next-tree-check-yes-b {
background-color: #ccc!important;
}
.hover-c {
opacity: 0.6;
}
.fixed-bottom-bar {
position: fixed;
bottom: 0rpx;
left: 0rpx;
right: 0rpx;
z-index: 998;
}

View File

@ -0,0 +1,84 @@
{
"id": "next-tree",
"displayName": "next-tree超强树选择器、树组件、树插件、无限级联树、单选树、多选树、自定义样式树、树形选择器",
"version": "1.9.1",
"description": "next-tree 弹窗树形选择器,支持多选,支持大数据, 无限级联,单选,父子级级联,远程/ajax加载子节点增量/异步渲染,自定义样式定制,具名插槽等;支持h5/小程序/APP全端通用",
"keywords": [
"树选择",
"tree",
"弹窗树选择器",
"多选树",
"单选树"
],
"engines": {
},
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "修改版本说明",
"permissions": "无"
},
"npmurl": "",
"type": "component-vue"
},
"uni_modules": {
"dependencies": ["next-search-more"],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y",
"alipay": "n"
},
"client": {
"Vue": {
"vue2": "y",
"vue3": "y"
},
"App": {
"app-vue": "y",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "n",
"Edge": "y",
"Firefox": "y",
"Safari": "u"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "u",
"QQ": "y",
"钉钉": "y",
"快手": "u",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

View File

@ -0,0 +1,843 @@
## next-tree --下拉树
> 遇到问题或有建议可以加入QQ群(<font color=#f00>455948571</font>)反馈qQ 455-948-571
> 如果觉得组件不错,<font color=#f00>给五星鼓励鼓励</font>咯!
## 亮点功能说明(打造你不得不用的好插件)
### 本插件自1.5.0版本后支持一下功能
> 1.大数据量渲染本插件智能判断如果子孙集数据量大于50时会响应等待渲染视图
> 2.子节点按需渲染(自动启用,无需配置)
> 3.父子级联选择设置
> 4.单选多选设置
> 5.父节点是否可选设置
> 6.回显默认选中值
> 7.不可选项disabled设置
> 8.增强大数据量体验交互,增加筛选搜索模式
> 9.增强样式定制,提供自定义插槽,实现高要求样式定制
> 10.增加辅助线模式,外观更加精美
> 11.支持动态配置title
> 12.支持搜索模式searchModel=depHighlight模式从属高亮显示模式
> 13.支持异步加载子节点ajax加载子节点
> 14.增加可配置主题,自由定制插件主题颜色
> 15.支持动态校验,可以进行提示控制校验
> 16.支持页面模式/弹层模式,可以进行单页面展示或者弹层展示
> 17.支持半选提示状态显示
> 18.支持展开项expandedKeys配置
> 19.全面支持vue2/vue3
> 20.增加无子节点的父节点配置支持当item[childrenKey]为null时代表无子节点的父节点
> 21.终极支持超数据量使用增加展开模式配置单链路配置使用expandedMode=singe使得ui组件使用进一步不在限制与数据量
> 22.功能模式再次增强支持单选tree多选tree编辑tree展示tree
## 注意
### 作者不介意你对组件源码进行改造使用,为了开源更加高效,谢谢你的配合;为了节省不必要的沟通浪费,以下情况请不要再反馈给作者,请自行解决;
### 在这感各位的理解,我支持开源,但是作者时间有限;谢谢各位的配合;在这里期望我写的小小插件能为你提供便捷;
> 1.如果你对源码进行了修改使用,请不需要对作者做任何的反馈,作者确实没有空陪你做技术分析解答;
> 2.如果你引入插件连插件是否有正常被uniapp框架识别解析都不清楚请你换个插件使用
> 3.如果你引入插件,针对自己项目进行功能改造的,请自行仔细阅读源码并了解其原理,自行改造;这里作者不愿意浪费过多时间进行技术解答;
> 4.如果你不想进行全局加载next-tree需要按需加载next-tree中有相关依赖的组件需要你自行在组件内部单独引入依赖组件可以在package.json中找到
> 5.理论上作者不再解决由于本地开发环境问题所导致的插件使用问题请自行到uniapp官网学习解决
## 使用
### 超集功能即将不对外开源;
>[从uniapp插件市场导入](https://ext.dcloud.net.cn/plugin?name=next-tree)
## 关注作者的动态
[点击进入主页,关注作者](https://ask.dcloud.net.cn/people/ponder_7464)
## 关注作者其他开源
npm开源包[npm](https://www.npmjs.com/~lixueshiaa);
github开源项目[github](https://github.com/lixueshiaa);
```html
<template>
<view style="padding:10px;color: #333;font-weight: 500;">
<view style="padding: 10px 0"><text>1、设置单选和父级不可选</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(false, false)">设置</button>
<view style="padding: 10px 0"><text>2、设置多选和父级不可选</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(true, false)">设置</button>
<view style="padding: 10px 0"><text>3、设置单选和父级可选</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(false, true)">设置</button>
<view style="padding: 10px 0"><text>4、设置多选和父级可选</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(true, true)" >设置</button>
<view style="padding: 10px 0"><text>4、设置多选和父级可选和父级关联子级选择</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(true, true, true)" >设置</button>
<view style="padding: 10px 0"><text>5、设置默认回显(默认选中: '上海-2', '黄埔区-35')</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="echoDefault()" >设置</button>
<!-- 异步加载demo -->
<view style="padding: 10px 0"><text>6、异步加载渲染demo</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="openTree()" >设置</button>
</view>
<!-- 异步加载demo -->
<next-tree :selectParent="false" :checkStrictly="true" funcMode="checkbox" ref="nextTreeAsyncRef" :treeData="asyncTreeData" :loadData="loadData" />
<next-tree :expandedKeys="['3','3-1']" :changeVerify="changeVerify" :title="getTitle" ref="nextTreeRef" :checkStrictly="checkStrictly" :selectParent="selectParent" :funcMode="funcMode" :treeData="treeData" @cancel="oncancel" @confirm="onconfirm">
<!-- label插槽示意代码 -->
<!-- <template #label="{data: {id, label, iconSrc, prev, post}}">
<view class="line-block">
<image class="img" v-if="iconSrc" :src="iconSrc"></image>
<text space="nbsp" v-if="prev">{{prev}}&nbsp;</text><text>{{label}}</text><text space="nbsp" v-if="post">&nbsp;{{post}}</text>
</view>
</template> -->
<!-- <template #topBar>
<view style="color: #666;padding:5px;"><text style="font-size: 12px;">历史记录</text></view>
<view style="display: flex;justify-content: space-between;padding-bottom: 10px;border-bottom: 1rpx solid #f0f0f0;">
<button @click="checkedFunc('1-3-3-4')" :style="'background-color:'+ (activeId === '1-3-3-4' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">北京区-4</button>
<button @click="checkedFunc('3-1-2')" :style="'background-color:'+ (activeId === '3-1-2' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">海珠区-2</button>
<button @click="checkedFunc('3-1-6')" :style="'background-color:'+ (activeId === '3-1-6' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">海珠区-5</button>
</view>
</template> -->
</next-tree>
</template>
```
### vue3 + ts 使用
```ts
<script setup lang="ts">
import { ref, unref } from 'vue'
import nextTree from '@/components/next-tree/next-tree.vue'
const funcMode = ref('radio');
const selectParent = ref(false)
const nextTreeRef = ref()
const nextTreeAsyncRef = ref()
const activeId = ref('')
const localData: any = {
'a1': [{id: 'a1-1', label: 'a1-1'}, {id: 'a1-2', label: 'a1-2',children: [] },{id: 'a1-3', label: 'a1-3'}],
'b1': [{id: 'b1-1', label: 'b1-1',children: []}, {id: 'b1-2', label: 'b1-2'},{id: 'b1-3', label: 'b1-3'}],
'c1': [{id: 'c1-1', label: 'c1-1'}, {id: 'c1-2', label: 'c1-2'},{id: 'c1-3', label: 'c1-3',children: []}],
'a1-2': [{id: 'a1-2-1', label: 'a1-2-1'}, {id: 'a1-2-2', label: 'a1-2-2'}],
'b1-1': [{id: 'b1-1-1', label: 'b1-1-1'}, {id: 'b1-1-2', label: 'b1-1-2'}],
'c1-3': [{id: 'c1-3-1', label: 'c1-3-1'}, {id: 'c1-3-2', label: 'c1-3-2'}]
}
const checkStrictly = ref(false)
const asyncTreeData = ref([{id: 'a1', label: 'a1', children: []},{id: 'b1', label: 'b1', children: []},{id: 'c1', label: 'c1', children: []}])
const treeData = ref([
{id: '1', label: '北京'},
{id: '2', label: '上海', children: [
{id: '2-1', label: '上海-1'},
{id: '2-2', label: '上海-2'},
{id: '2-3', label: '上海-3'},
] },
{id: '3', label: '广州', children: [
{id: '3-1', label: '海珠区', children: [
{id: '3-1-1', label: '海珠区-1'},
{id: '3-1-2', label: '海珠区-2'},
{id: '3-1-4', label: '海珠区-3'},
{id: '3-1-5', label: '海珠区-4'},
{id: '3-1-6', label: '海珠区-5'},
{id: '3-1-7', label: '海珠区-6'},
{id: '3-1-8', label: '海珠区-7'},
{id: '3-1-9', label: '海珠区-8'},
{id: '3-1-10', label: '海珠区-9'},
{id: '3-1-11', label: '海珠区-10'},
]},
{id: '3-2', label: '番禺区', children: [
{id: '3-2-1', label: '番禺区-1'},
{id: '3-2-2', label: '番禺区-2'},
{id: '3-2-4', label: '番禺区-3', children: null}, // 注意: 当childrenKey的值设为null代表无子节点的父节点
{id: '3-2-5', label: '番禺区-4'},
{id: '3-2-6', label: '番禺区-5'},
{id: '3-2-7', label: '番禺区-6'},
{id: '3-2-8', label: '番禺区-7'},
{id: '3-2-9', label: '番禺区-8'},
{id: '3-2-10', label: '番禺区-9'},
{id: '3-2-11', label: '番禺区-10'},
]},
{id: '3-3', label: '黄埔区', children: [
{id: '3-3-1', label: '黄埔区-1'},
{id: '3-3-2', label: '黄埔区-2'},
{id: '3-3-3', label: '黄埔区-3'},
{id: '3-3-4', label: '黄埔区-4'},
{id: '3-3-5', label: '黄埔区-5'},
{id: '3-3-6', label: '黄埔区-6'},
{id: '3-3-7', label: '黄埔区-7'},
{id: '3-3-8', label: '黄埔区-8'},
{id: '3-3-9', label: '黄埔区-9'},
{id: '3-3-10', label: '黄埔区-10'},
{id: '3-3-12', label: '黄埔区-11'},
{id: '3-3-13', label: '黄埔区-12'},
{id: '3-3-13', label: '黄埔区-13'},
{id: '3-3-14', label: '黄埔区-14'},
{id: '3-3-15', label: '黄埔区-15'},
{id: '3-3-16', label: '黄埔区-16'},
{id: '3-3-17', label: '黄埔区-17'},
{id: '3-3-18', label: '黄埔区-18'},
{id: '3-3-19', label: '黄埔区-19'},
{id: '3-3-20', label: '黄埔区-20'},
{id: '3-3-21', label: '黄埔区-21'},
{id: '3-3-22', label: '黄埔区-22'},
{id: '3-3-23', label: '黄埔区-23'},
{id: '3-3-24', label: '黄埔区-24'},
{id: '3-3-25', label: '黄埔区-25'},
{id: '3-3-26', label: '黄埔区-26'},
{id: '3-3-27', label: '黄埔区-27'},
{id: '3-3-28', label: '黄埔区-28'},
{id: '3-3-29', label: '黄埔区-29'},
{id: '3-3-30', label: '黄埔区-30'},
{id: '3-3-31', label: '黄埔区-31'},
{id: '3-3-32', label: '黄埔区-32'},
{id: '3-3-33', label: '黄埔区-33'},
{id: '3-3-34', label: '黄埔区-34'},
{id: '3-3-35', label: '黄埔区-35'},
{id: '3-3-36', label: '黄埔区-36'},
]},
],
}])
function getTitle(checked) {
return `已选:${checked.length}项`
}
function itemclick (_multiple, _selectParent, _checkStrictly = false) {
funcMode.value = _multiple ? 'checkbox' : 'radio';
selectParent.value = _selectParent
checkStrictly.value = _checkStrictly
unref(nextTreeRef).showTree = true
}
function checkedFunc(id) {
if(unref(activeId) === id) {
activeId.value = '';
unref(nextTreeRef).checkedFunc(id, false)
} else {
activeId.value = id;
unref(nextTreeRef).checkedFunc(id)
}
}
function changeVerify(current, chooseList) {
// 注意:返回非空字符串会阻止原有行为,并提示返回的字符串
// 如果函数体不做return返回值即验证通过控件正常处理业务
console.log('当前变化的数据', current)
console.log('已选择的数据', chooseList)
if(chooseList && chooseList.length > 4) {
return '最多可以选择4个节点'
}
}
function openTree() {
unref(nextTreeAsyncRef).showTree = true
}
function echoDefault () {
const selectIds = ['2-1','3-3-35']
checkedTreeData(unref(treeData), selectIds)
console.log('treeData的数据', unref(treeData))
funcMode.value = 'checkbox'
unref(nextTreeRef).showTree = true
}
function loadData(data) {
const type = data.$type; // 加载类型
const source = data.source // 源数据
// 同步实现的代码处理方式
if (type === 'nodeLoad') {
const nodeItem = source;
// 同步实现的代码处理方式
// 如果期望子集节点中还存在孙子节点可以打开,请在初始化数据的时候,初始化个空数组的子节点配置值{[this.childrenKey]: []}
// if(nodeItem && localData[nodeItem.id]) {
// return localData[nodeItem.id]
// } else {
// return []
// }
// 异步的代码实现方式
// 如果期望子集节点中还存在孙子节点可以打开,请在初始化数据的时候,初始化个空数组的子节点配置值{[this.childrenKey]: []}
return new Promise((resolve, reject) => {
setTimeout(() => {
if(nodeItem && localData[nodeItem.id]) {
return resolve(localData[nodeItem.id])
} else {
return resolve([])
}
}, 1000)
})
} else if(type === 'remoteSearch') { // searchModel=remote的时候会在loadData函数中返回type参数供做业务处理
// ...doing
}
}
function checkedTreeData (treeData, selectIds) {
treeData.map(item => {
if (selectIds.indexOf(item.id) !== -1) {
item.checked = true
} else {
item.checked = false
}
if (item.children && item.children.length) {
checkedTreeData(item.children, selectIds)
}
})
}
function oncancel() {
// 清除treeData的选中状态
checkedTreeData(unref(treeData), [])
}
function onconfirm(list) {
console.log('选中项的数量列表list', list)
}
</script>
<style lang="scss">
.line-block {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
.img {
width: 40rpx;
height: 40rpx;
border-radius: 10rpx;
margin: 0 20rpx;
}
}
</style>
```
### vue2 使用
```html
<template>
<view>
<view style="padding:10px;color: #333;font-weight: 500;">
<view style="padding: 10px 0"><text>1、设置单选和父级不可选</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(false, false)">设置</button>
<view style="padding: 10px 0"><text>2、设置多选和父级不可选</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(true, false)">设置</button>
<view style="padding: 10px 0"><text>3、设置单选和父级可选</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(false, true)">设置</button>
<view style="padding: 10px 0"><text>4、设置多选和父级可选</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(true, true)" >设置</button>
<view style="padding: 10px 0"><text>4、设置多选和父级可选和父级关联子级选择</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(true, true, true)" >设置</button>
<view style="padding: 10px 0"><text>5、设置默认回显(默认选中: '上海-2', '黄埔区-35')</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="echoDefault()" >设置</button>
<!-- 异步加载demo -->
<view style="padding: 10px 0"><text>6、异步加载渲染demo</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="openTree()" >设置</button>
</view>
<!-- 异步加载demo -->
<next-tree :selectParent="false" :checkStrictly="true" funcMode="checkbox" ref="nextTreeAsyncRef" :treeData="asyncTreeData" :loadData="loadData" />
<next-tree :expandedKeys="['3','3-1']" :changeVerify="changeVerify" :title="getTitle" ref="nextTreeRef" :checkStrictly="checkStrictly" :selectParent="selectParent" :funcMode="funcMode" :treeData="treeData" @cancel="oncancel" @confirm="onconfirm">
<!-- label插槽示意代码 -->
<!-- <template v-slot:label="{data}">
<view class="line-block">
<image class="img" v-if="data.iconSrc" :src="data.iconSrc"></image>
<text space="nbsp" v-if="data.prev">{{data.prev}}&nbsp;</text><text>{{data.label}}</text><text space="nbsp" v-if="data.post">&nbsp;{{data.post}}</text>
</view>
</template> -->
<!-- <template #topBar>
<view style="color: #666;padding:5px;"><text style="font-size: 12px;">历史记录</text></view>
<view style="display: flex;justify-content: space-between;padding-bottom: 10px;border-bottom: 1rpx solid #f0f0f0;">
<button @click="checkedFunc('1-3-3-4')" :style="'background-color:'+ (activeId === '1-3-3-4' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">北京区-4</button>
<button @click="checkedFunc('3-1-2')" :style="'background-color:'+ (activeId === '3-1-2' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">海珠区-2</button>
<button @click="checkedFunc('3-1-6')" :style="'background-color:'+ (activeId === '3-1-6' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">海珠区-5</button>
</view>
</template> -->
</next-tree>
</view>
</template>
```
```js
<script>
let self = null;
export default {
data () {
return {
funcMode: 'radio',
selectParent: false,
checkStrictly: false,
activeId: '',
localData:{
'a1': [{id: 'a1-1', label: 'a1-1'}, {id: 'a1-2', label: 'a1-2',children: [] },{id: 'a1-3', label: 'a1-3'}],
'b1': [{id: 'b1-1', label: 'b1-1',children: []}, {id: 'b1-2', label: 'b1-2'},{id: 'b1-3', label: 'b1-3'}],
'c1': [{id: 'c1-1', label: 'c1-1'}, {id: 'c1-2', label: 'c1-2'},{id: 'c1-3', label: 'c1-3',children: []}],
'a1-2': [{id: 'a1-2-1', label: 'a1-2-1'}, {id: 'a1-2-2', label: 'a1-2-2'}],
'b1-1': [{id: 'b1-1-1', label: 'b1-1-1'}, {id: 'b1-1-2', label: 'b1-1-2'}],
'c1-3': [{id: 'c1-3-1', label: 'c1-3-1'}, {id: 'c1-3-2', label: 'c1-3-2'}]
},
asyncTreeData: [{id: 'a1', label: 'a1', children: []},{id: 'b1', label: 'b1', children: []},{id: 'c1', label: 'c1', children: []}],
treeData: [
{id: '1', label: '北京', checked: false},
{id: '2', label: '上海', checked: false, children: [
{id: '2-1', label: '上海-1', checked: false},
{id: '2-2', label: '上海-2', checked: false},
{id: '2-3', label: '上海-3', checked: false},
] },
{id: '3', label: '广州', children: [
{id: '3-1', label: '海珠区', checked: false, children: [
{id: '3-1-1', label: '海珠区-1', checked: false, disabled: true},
{id: '3-1-2', label: '海珠区-2', checked: false},
{id: '3-1-4', label: '海珠区-3', checked: false},
{id: '3-1-5', label: '海珠区-4', checked: false},
{id: '3-1-6', label: '海珠区-5', checked: false},
{id: '3-1-7', label: '海珠区-6', checked: false},
{id: '3-1-8', label: '海珠区-7', checked: false},
{id: '3-1-9', label: '海珠区-8', checked: false},
{id: '3-1-10', label: '海珠区-9', checked: false},
{id: '3-1-11', label: '海珠区-10', checked: false},
]},
{id: '3-2', label: '番禺区', checked: false, children: [
{id: '3-2-1', label: '番禺区-1', checked: false},
{id: '3-2-2', label: '番禺区-2', checked: false},
{id: '3-2-4', label: '番禺区-3', checked: false},
{id: '3-2-5', label: '番禺区-4', checked: false},
{id: '3-2-6', label: '番禺区-5', checked: false},
{id: '3-2-7', label: '番禺区-6', checked: false},
{id: '3-2-8', label: '番禺区-7', checked: false},
{id: '3-2-9', label: '番禺区-8', checked: false},
{id: '3-2-10', label: '番禺区-9', checked: false},
{id: '3-2-11', label: '番禺区-10', checked: false},
]},
{id: '3-3', label: '黄埔区', checked: false, children: [
{id: '3-3-1', label: '黄埔区-1', checked: false},
{id: '3-3-2', label: '黄埔区-2', checked: false},
{id: '3-3-3', label: '黄埔区-3', checked: false},
{id: '3-3-4', label: '黄埔区-4', checked: false},
{id: '3-3-5', label: '黄埔区-5', checked: false},
{id: '3-3-6', label: '黄埔区-6', checked: false},
{id: '3-3-7', label: '黄埔区-7', checked: false},
{id: '3-3-8', label: '黄埔区-8', checked: false},
{id: '3-3-9', label: '黄埔区-9', checked: false},
{id: '3-3-10', label: '黄埔区-10', checked: false},
{id: '3-3-12', label: '黄埔区-11', checked: false},
{id: '3-3-13', label: '黄埔区-12', checked: false},
{id: '3-3-13', label: '黄埔区-13', checked: false},
{id: '3-3-14', label: '黄埔区-14', checked: false},
{id: '3-3-15', label: '黄埔区-15', checked: false},
{id: '3-3-16', label: '黄埔区-16', checked: false},
{id: '3-3-17', label: '黄埔区-17', checked: false},
{id: '3-3-18', label: '黄埔区-18', checked: false},
{id: '3-3-19', label: '黄埔区-19', checked: false},
{id: '3-3-20', label: '黄埔区-20', checked: false},
{id: '3-3-21', label: '黄埔区-21', checked: false},
{id: '3-3-22', label: '黄埔区-22', checked: false},
{id: '3-3-23', label: '黄埔区-23', checked: false},
{id: '3-3-24', label: '黄埔区-24', checked: false},
{id: '3-3-25', label: '黄埔区-25', checked: false},
{id: '3-3-26', label: '黄埔区-26', checked: false},
{id: '3-3-27', label: '黄埔区-27', checked: false},
{id: '3-3-28', label: '黄埔区-28', checked: false},
{id: '3-3-29', label: '黄埔区-29', checked: false},
{id: '3-3-30', label: '黄埔区-30', checked: false},
{id: '3-3-31', label: '黄埔区-31', checked: false},
{id: '3-3-32', label: '黄埔区-32', checked: false},
{id: '3-3-33', label: '黄埔区-33', checked: false},
{id: '3-3-34', label: '黄埔区-34', checked: false},
{id: '3-3-35', label: '黄埔区-35', checked: false},
{id: '3-3-36', label: '黄埔区-36', checked: false},
]},
],
}]
}
},
methods: {
openTree: function() {
this.$refs.nextTreeAsyncRef.showTree = true
},
changeVerify: function(current, chooseList) {
// 注意:返回非空字符串会阻止原有行为,并提示返回的字符串
// 如果函数体不做return返回值即验证通过控件正常处理业务
console.log('当前变化的数据', current)
console.log('已选择的数据', chooseList)
if(chooseList && chooseList.length > 4) {
return '最多可以选择4个节点'
}
},
checkedFunc: function(id) {
if(this.activeId === id) {
this.activeId = '';
this.$refs.nextTreeRef.checkedFunc(id, false)
} else {
this.activeId = id;
this.$refs.nextTreeRef.checkedFunc(id)
}
},
function loadData(data) {
const type = data.$type; // 加载类型
const source = data.source // 源数据
// 同步实现的代码处理方式
if (type === 'nodeLoad') {
const nodeItem = source;
// 同步实现的代码处理方式 可以返回单个子节点的集合也可以返回子孙节点的集合
// 如果期望子集节点中还存在孙子节点可以打开,请在初始化数据的时候,初始化个空数组的子节点配置值{[this.childrenKey]: []}
// if(nodeItem && this.localData[nodeItem.id]) {
// return this.localData[nodeItem.id]
// } else {
// return []
// }
// 异步的代码实现方式 可以返回单个子节点的集合也可以返回子孙节点的集合
// 如果期望子集节点中还存在孙子节点可以打开,请在初始化数据的时候,初始化个空数组的子节点配置值{[this.childrenKey]: []}
return new Promise((resolve, reject) => {
setTimeout(() => {
if(nodeItem && self.localData[nodeItem.id]) {
return resolve(self.localData[nodeItem.id])
} else {
return resolve([])
}
}, 1000)
})
} else if(type === 'remoteSearch') { // searchModel=remote的时候会在loadData函数中返回type参数供做业务处理
// ...doing
}
},
getTitle: function(checked) {
return `已选:${checked.length}项`
},
echoDefault: function() {
const selectIds = ['2-1','3-3-35']
this.checkedTreeData(this.treeData, selectIds)
console.log('treeData的数据', this.treeData)
this.funcMode = 'checkbox'
this.$refs.nextTreeRef.showTree = true
},
itemclick: function(_multiple, _selectParent, _checkStrictly = false) {
this.funcMode = _multiple ? 'checkbox' : 'radio'
this.selectParent = _selectParent
this.checkStrictly = _checkStrictly
this.$refs.nextTreeRef.showTree = true
},
checkedTreeData: function(treeData, selectIds) {
// 注意 vue2当数据深嵌套时如果没有在treeData里面初始化checked属性那在改变数据的时候直接将checked属性赋值为true这时候ui界面有可能不会更新
// 这时候建议使用this.$set去更新checked属性值或者在初始化this.treeData的时候初始化checked属性
(treeData || []).map(item => {
if (selectIds.indexOf(item.id) !== -1) {
item.checked = true
} else {
item.checked = false
}
if (item.children && item.children.length) {
this.checkedTreeData(item.children, selectIds)
}
})
},
onconfirm: function(list) {
console.log('选中项的数量列表list', list)
},
oncancel: function() {
// 清除treeData的选中状态
this.checkedTreeData(this.treeData, [])
}
},
created() {
self = this
}
}
</script>
<style lang="scss">
.line-block {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
.img {
width: 40rpx;
height: 40rpx;
border-radius: 10rpx;
margin: 0 20rpx;
}
}
</style>
```
### 个性化自定义样式渲染
如果你的需求对样式需求比较高请使用插槽模式渲染本组件提供label插槽供你自定义定制
```js
<script>
// 提供参考一组自定义渲染数据demotreeData如下
const treeData = [
{id: '1', label: '北京', prev: 'PonderNext-', iconSrc: 'https://img95.699pic.com/xsj/03/fg/hj.jpg%21/fh/300', children: [
{id: '1-3-3-1', label: '北京区-1', prev: '前置-'},
{id: '1-3-3-2', label: '北京区-2', post: '-后置'},
{id: '1-3-3-3', label: '北京区-3', post: '-后置', prev: '前置-'},
{id: '1-3-3-4', label: '北京区-4'},
{id: '1-3-3-5', label: '北京区-5'},
{id: '1-3-3-6', label: '北京区-6'},
{id: '1-3-3-7', label: '北京区-7'},
{id: '1-3-3-8', label: '北京区-8'},
{id: '1-3-3-9', label: '北京区-9'},
{id: '1-3-3-10', label: '北京区-10'},
{id: '1-3-3-12', label: '北京区-11'},
{id: '1-3-3-13', label: '北京区-12'},
{id: '1-3-3-13', label: '北京区-13'},
{id: '1-3-3-14', label: '北京区-14'},
{id: '1-3-3-15', label: '北京区-15'},
{id: '1-3-3-16', label: '北京区-16'},
{id: '1-3-3-17', label: '北京区-17'},
{id: '1-3-3-18', label: '北京区-18'},
{id: '1-3-3-19', label: '北京区-19'},
{id: '1-3-3-20', label: '北京区-20'},
{id: '1-3-3-21', label: '北京区-21'},
{id: '1-3-3-22', label: '北京区-22'},
{id: '1-3-3-23', label: '北京区-23'},
{id: '1-3-3-24', label: '北京区-24'},
{id: '1-3-3-25', label: '北京区-25'},
{id: '1-3-3-26', label: '北京区-26'},
{id: '1-3-3-27', label: '北京区-27'},
{id: '1-3-3-28', label: '北京区-28'},
{id: '1-3-3-29', label: '北京区-29'},
{id: '1-1-3-3-30', label: '北京区-30'},
{id: '1-3-3-31', label: '北京区-31'},
{id: '1-3-3-32', label: '北京区-32'},
{id: '1-3-3-33', label: '北京区-33'},
{id: '1-3-3-34', label: '北京区-34'},
{id: '1-3-3-35', label: '北京区-35'},
{id: '1-3-3-36', label: '北京区-36'},
{id: '1-3-3-37', label: '北京区-37'},
{id: '1-3-3-38', label: '北京区-38'},
{id: '1-3-3-39', label: '北京区-39'},
{id: '1-3-3-40', label: '北京区-40'},
{id: '1-3-3-41', label: '北京区-41'},
{id: '1-3-3-42', label: '北京区-42'},
{id: '1-3-3-43', label: '北京区-43'},
{id: '1-3-3-44', label: '北京区-44'},
{id: '1-3-3-45', label: '北京区-45'},
{id: '1-3-3-46', label: '北京区-46'},
{id: '1-3-3-47', label: '北京区-47'},
{id: '1-3-3-48', label: '北京区-48'},
{id: '1-3-3-49', label: '北京区-49'},
{id: '1-3-3-50', label: '北京区-50'},
{id: '1-3-3-51', label: '北京区-51'},
{id: '1-3-3-52', label: '北京区-52'},
{id: '1-3-3-53', label: '北京区-53'},
{id: '1-3-3-54', label: '北京区-54'},
]},
{id: '2', label: '上海', prev: 'PonderNext-', iconSrc: 'https://img95.699pic.com/xsj/0g/hb/tc.jpg%21/fh/300', children: [
{id: '2-1', label: '上海-1', iconSrc: 'https://img1.baidu.com/it/u=1997340124,765201109&fm=253&fmt=auto&app=120&f=JPEG?w=285&h=285'},
{id: '2-2', label: '上海-2', iconSrc: 'https://img1.baidu.com/it/u=1997340124,765201109&fm=253&fmt=auto&app=120&f=JPEG?w=285&h=285'},
{id: '2-3', label: '上海-3', iconSrc: 'https://img1.baidu.com/it/u=1997340124,765201109&fm=253&fmt=auto&app=120&f=JPEG?w=285&h=285'},
] },
{id: '3', label: '广州', prev: 'PonderNext-', iconSrc: 'https://storage-public.zhaopin.cn/user/avatar/1589350028141684980/d00a1afa-e3ec-40a5-a68e-aef1f684b189.jpg', children: [
{id: '3-1', label: '海珠区', iconSrc: 'https://img95.699pic.com/xsj/0u/f3/5h.jpg%21/fh/300', children: [
{id: '3-1-1', label: '海珠区-1', disabled: true},
{id: '3-1-2', label: '海珠区-2', post: '-后置', prev: '前置-'},
{id: '3-1-4', label: '海珠区-3', post: '-后置',},
{id: '3-1-5', label: '海珠区-4', children: [
{ id: '3-1-5-1', label: '海珠区-4-200号'},
{ id: '3-1-5-2', label: '海珠区-4-201号', children: [
{ id: '3-1-5-1-1', label: '海珠区-4-200号-2'},
{ id: '3-1-5-2-1', label: '海珠区-4-201号-3'},
]},
]},
{id: '3-1-6', label: '海珠区-5'},
{id: '3-1-7', label: '海珠区-6'},
{id: '3-1-8', label: '海珠区-7', post: '-后置',},
{id: '3-1-9', label: '海珠区-8'},
{id: '3-1-10', label: '海珠区-9'},
{id: '3-1-11', label: '海珠区-10'},
{id: '3-1-1', label: '海珠区-11', disabled: true},
{id: '3-1-2', label: '海珠区-12'},
{id: '3-1-4', label: '海珠区-13'},
{id: '3-1-5', label: '海珠区-14'},
{id: '3-1-6', label: '海珠区-15'},
{id: '3-1-7', label: '海珠区-16'},
{id: '3-1-8', label: '海珠区-17'},
{id: '3-1-9', label: '海珠区-18'},
{id: '3-1-10', label: '海珠区-19', prev: '前置-'},
{id: '3-1-11', label: '海珠区-20'},
{id: '3-1-1', label: '海珠区-21', disabled: true},
{id: '3-1-2', label: '海珠区-22'},
{id: '3-1-4', label: '海珠区-23'},
{id: '3-1-5', label: '海珠区-24'},
{id: '3-1-6', label: '海珠区-25'},
{id: '3-1-7', label: '海珠区-26'},
{id: '3-1-8', label: '海珠区-27'},
{id: '3-1-9', label: '海珠区-28'},
{id: '3-1-10', label: '海珠区-29'},
{id: '3-1-11', label: '海珠区-30'},
{id: '3-1-1', label: '海珠区-31', disabled: true},
{id: '3-1-2', label: '海珠区-32'},
{id: '3-1-4', label: '海珠区-33'},
{id: '3-1-5', label: '海珠区-34'},
{id: '3-1-6', label: '海珠区-35'},
{id: '3-1-7', label: '海珠区-36'},
{id: '3-1-8', label: '海珠区-37'},
{id: '3-1-9', label: '海珠区-38'},
{id: '3-1-10', label: '海珠区-39'},
{id: '3-1-11', label: '海珠区-40'},
{id: '3-1-1', label: '海珠区-41', disabled: true},
{id: '3-1-2', label: '海珠区-42'},
{id: '3-1-4', label: '海珠区-43'},
{id: '3-1-5', label: '海珠区-44'},
{id: '3-1-6', label: '海珠区-45'},
{id: '3-1-7', label: '海珠区-46'},
{id: '3-1-8', label: '海珠区-47'},
{id: '3-1-9', label: '海珠区-48'},
{id: '3-1-10', label: '海珠区-49'},
{id: '3-1-11', label: '海珠区-50'},
{id: '3-1-11', label: '海珠区-51'},
]},
{id: '3-2', label: '番禺区', iconSrc: 'https://img1.baidu.com/it/u=931648192,3196263841&fm=253&fmt=auto&app=120&f=JPEG?w=285&h=285', disabled: true, checked: true, children: [
{id: '3-2-1', label: '番禺区-1'},
{id: '3-2-2', label: '番禺区-2'},
{id: '3-2-4', label: '番禺区-3'},
{id: '3-2-5', label: '番禺区-4'},
{id: '3-2-6', label: '番禺区-5'},
{id: '3-2-7', label: '番禺区-6'},
{id: '3-2-8', label: '番禺区-7'},
{id: '3-2-9', label: '番禺区-8'},
{id: '3-2-10', label: '番禺区-9'},
{id: '3-2-11', label: '番禺区-10'},
]},
{id: '3-3', label: '黄埔区', iconSrc: 'https://img.jiaoyubao.cn/43423/20210423113959473-20210423114005024.jpeg', children: [
{id: '3-3-1', label: '黄埔区-1'},
{id: '3-3-2', label: '黄埔区-2'},
{id: '3-3-3', label: '黄埔区-3'},
{id: '3-3-4', label: '黄埔区-4'},
{id: '3-3-5', label: '黄埔区-5'},
{id: '3-3-6', label: '黄埔区-6'},
{id: '3-3-7', label: '黄埔区-7'},
{id: '3-3-8', label: '黄埔区-8'},
{id: '3-3-9', label: '黄埔区-9'},
{id: '3-3-10', label: '黄埔区-10'},
{id: '3-3-12', label: '黄埔区-11'},
{id: '3-3-13', label: '黄埔区-12'},
{id: '3-3-13', label: '黄埔区-13'},
{id: '3-3-14', label: '黄埔区-14'},
{id: '3-3-15', label: '黄埔区-15'},
{id: '3-3-16', label: '黄埔区-16'},
{id: '3-3-17', label: '黄埔区-17'},
{id: '3-3-18', label: '黄埔区-18'},
{id: '3-3-19', label: '黄埔区-19'},
{id: '3-3-20', label: '黄埔区-20'},
{id: '3-3-21', label: '黄埔区-21'},
{id: '3-3-22', label: '黄埔区-22'},
{id: '3-3-23', label: '黄埔区-23'},
{id: '3-3-24', label: '黄埔区-24'},
{id: '3-3-25', label: '黄埔区-25'},
{id: '3-3-26', label: '黄埔区-26'},
{id: '3-3-27', label: '黄埔区-27'},
{id: '3-3-28', label: '黄埔区-28'},
{id: '3-3-29', label: '黄埔区-29'},
{id: '3-3-30', label: '黄埔区-30'},
{id: '3-3-31', label: '黄埔区-31'},
{id: '3-3-32', label: '黄埔区-32'},
{id: '3-3-33', label: '黄埔区-33'},
{id: '3-3-34', label: '黄埔区-34'},
{id: '3-3-35', label: '黄埔区-35'},
{id: '3-3-36', label: '黄埔区-36'},
{id: '3-3-37', label: '黄埔区-37'},
{id: '3-3-38', label: '黄埔区-38'},
{id: '3-3-39', label: '黄埔区-39'},
{id: '3-3-40', label: '黄埔区-40'},
{id: '3-3-41', label: '黄埔区-41'},
{id: '3-3-42', label: '黄埔区-42'},
{id: '3-3-43', label: '黄埔区-43'},
{id: '3-3-44', label: '黄埔区-44'},
{id: '3-3-45', label: '黄埔区-45'},
{id: '3-3-46', label: '黄埔区-46'},
{id: '3-3-47', label: '黄埔区-47'},
{id: '3-3-48', label: '黄埔区-48'},
{id: '3-3-49', label: '黄埔区-49'},
{id: '3-3-50', label: '黄埔区-50'},
{id: '3-3-51', label: '黄埔区-51'},
{id: '3-3-52', label: '黄埔区-52'},
{id: '3-3-53', label: '黄埔区-53'},
{id: '3-3-54', label: '黄埔区-54'},
]},
],
}]
</script>
```
### 预览
###
***
| 功能预览 | 父子级关联演示 | 全面支持大数据量子孙节点ui按需渲染(按需渲染数据) |
| :------------------------------------------------------------------: | :------------------------------------------------------------------: | :------------------------------------------------------------------: |
| ![](https://lixueshiaa.github.io/webtest/www/static/next-tree.gif) | ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-b.gif) | ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-d.gif) |
| 增强控件交互能力增加筛选search模式全面支持大数据量交互 | 超强的样式定制能力,满足你高精美组件的需求 | 打开精美的辅助线模式,让你的控件更加友好 |
| :------------------------------------------------------------------: | :------------------------------------------------------------------: | :------------------------------------------------------------------: |
| ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-e.gif) | ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-f.gif) | ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-u.gif) |
| 增加搜索模式searchModel=depHighlight模式从属高亮显示模式 | 支持异步加载子节点子树集ajax远程加载数据等 | 支持不同主题的切换ui定制更简单 |
| :------------------------------------------------------------------: | :------------------------------------------------------------------: | :------------------------------------------------------------------: |
| ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-p.gif) | ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-k.gif) | ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-n.gif) |
| 增加验证函数和topBar插槽使得更加容易和组件进行交互 | 增加页面模式支持整页ui展示模式 | 增加展开模式expandedMode配置支持单链路展开理论上支持几万数据量 |
| :------------------------------------------------------------------: | :------------------------------------------------------------------: | :------------------------------------------------------------------: |
| ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-cc.gif)| ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-uu.gif)| ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-aab.gif) |
### 超集功能预览(增值功能)
###
| 实现tree的功能模式扩展让你的tree组件实现可编辑态 |
| :--------------------------------------------------------------------: |
| ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-eeee.gif)|
## 参数
可选参数属性列表
|参数名 |说明 |类型 |是否必填 |默认值 |可选值 |
|---- |---- |---- |---- |---- |----------------------- |
|uiMode |ui表现方式popup<弹窗> page<页面>;默认是 popup |String |是 |popup |page |
|funcMode |功能模式配置display<展示模式> edit<编辑模式>checkbox<多选模式> radio<单选模式>;默认是 radio |String |是 |radio |dispaly,edit,checkbox |
|treeData |树源数据列表 |Array |是 |[] |- |
|valueKey |绑定value的键属性(项的唯一key标识) |String |否 |id |- |
|labelKey |用于显示的字段 |String |否 |label |- |
|disabledKey |禁用节点绑定属性 |String |否 |disabled |- |
|childrenKey |子节点绑定属性 (注意当item[childrenKey]的值设为null时代表是无下级数据的父节点即非叶子节点) |String |否 |children |- |
|title | 弹出标题(如果是函数时会返回所选项的值作为回调参数如title: (checked):String => {}) |String, Function |否 |'' |- |
|selectParent |作用于funcMode=display模式下是否可以选父级 |Boolean |否 |false |true |
|foldAll| 折叠时关闭所有已经打开的子集,再次打开时需要一级一级打开 |Boolean |否 |false |true |
|themeColor |主题颜色 |String |否 |#f9ae3d |- |
|cancelColor |取消按钮颜色 |String |否 |#757575 |- |
|titleColor |标题颜色 |String |否 |#757575 |- |
|border |是否有分割线 |Boolean |否 |false |true |
|checkStrictly|作用于funcMode=checkbox模式下 状态下节点选择完全受控(父子节点选中状态不再关联) |Boolean |否 |false |true |
|checkStrictlyModel|作用于funcMode=checkbox模式下父子节点关联模式strong:强关联不再受限节点的disabled控制weak弱关联节点关联受disabled控制 |String |是 |weak |strong |
|showHalfCheckedTips|作用于funcMode=checkbox模式下 checkStrictly为false的状态下生效父子节点选中状态不再关联是否展示半选提示 |Boolean |否 |false |true |
|ifSearch| 筛选search模式 |Boolean |否 |true |false |
|searchModel| 搜索模式配置 depHighlight: 从属高亮显示层级并高亮显示common: 一般remote: 远程 |String |否 |common |depHighlight |
|showAuxiliaryLine| 是否打开辅助线 |Boolean |否 |false |true |
|loadData| 异步加载函数 (node):Promise([childData]) => {} // demo有说明 |Function |否 |- |- |
|height| 只在uiMode=popup时生效弹层容器的高度默认是500 |Number |否 |500 |- |
|changeVerify|作用于funcMode=display模式下 验证函数 (current as any, chooseList as any []):String => {} // 验证函数会把当前控件的选择值作为参数返给函数体demo有说明 |Function |否 |- |- |
|expandedKeys| (Controlled) Specifies the keys of the expanded treeNodes 展开配置项,格式为[valueKey] |Array |否 |[] |- |
|expandedMode| 展开模式配置: common: 一般模式singe: 单一模式; |String |否 |common |singe |
# Event 事件
|事件名 |说明 |类型 |回调参数 |
|---- |---- |---- |---- |
|confirm|菜单收起时返回的筛选结果 |emit |array |
|clear|点击清除按钮时触发 |emit |- |
|cancel|关闭弹层和点击取消时触发 |emit |- |
|change|选项改变时触发 |emit |array |
## Slot 插槽
|名称 |说明 |参数 |
|---- |---- |---- |
|label |label插槽 |data(当前项对于treeData里面的数据) |
|topBar |topBar插槽 |----滚动区域顶部topBar插槽 |
|bottomBar |bottomBar插槽 |----滚动区域底部bottomBar插槽 |
|fixedBottomBar |fixedBottomBar插槽 |----固定在页面的底部使用fixed进行定位 |
|empty |empty插槽 |----数据为空的插槽 |

15
utils/constant.js Normal file
View File

@ -0,0 +1,15 @@
export const HIDDEN_LEVEL_COlOR = {
hiddenLevel1001: "yellow-bg",
hiddenLevel1002: "yellow-bg",
hiddenLevel1004: "yellow-bg",
hiddenLevel2001: "red-bg",
hiddenLevel2002: "red-bg",
};
export const HIDDEN_SOURCE = {
1: "隐患快报",
2: "清单排查",
3: "清单排查",
4: "安全环保检查(监管端)",
5: "安全环保检查(企业端)",
6: "消防检查",
};

View File

@ -1,136 +1,137 @@
let requestPath = "http://192.168.0.115:8088";
// let requestPath = 'http://192.168.0.31:8992/qa-prevention-xgf/'; // 后台请求地址
let requestPath = 'https://skqhdg.porthebei.com:9006/qa-prevention-xgf/'; // 后台请求地址
// let requestPath = 'https://skqhdg.porthebei.com:9006/qa-prevention-xgf/'; // 后台请求地址
// let requestPath = 'https://qgxgf.qhdsafety.com/qa-prevention-xgf/'; // 外网地址
import store from '../store/index'
import store from "../store/index";
function post(url, data) {
return new Promise((resolve, reject) => {
if (data && data.loading !== false) {
uni.showLoading({
title: '加载中'
});
}
uni.request({
url: requestPath + url,
data: {
USER_ID: store.state.userInfo.USER_ID || '',
...data
},
method: 'POST',
header: {
'Content-type': 'application/x-www-form-urlencoded'
},
success: (res) => {
if (res.statusCode != 200){
uni.showToast({
title: '网络错误请重试,' +res.statusCode,
icon: 'error',
duration: 2000
});
reject(err)
return new Promise((resolve, reject) => {
if (data && data.loading !== false) {
uni.showLoading({
title: "加载中",
});
}
uni.request({
url: requestPath + url,
data: {
USER_ID: store.state.userInfo.USER_ID || "",
...data,
},
method: "POST",
header: {
"Content-type": "application/x-www-form-urlencoded",
},
success: (res) => {
if (res.statusCode != 200) {
uni.showToast({
title: "网络错误请重试," + res.statusCode,
icon: "error",
duration: 2000,
});
reject(err);
}
if (data && data.loading !== false) {
uni.hideLoading();
}
if (res.data.result === 'success') {
resolve(res.data)
} else {
uni.showToast({
title: res.data.msg || '系统开小差了',
icon: 'none',
duration: 2000
});
reject(res.data)
}
},
fail: (err) => {
if (data && data.loading !== false) {
uni.hideLoading();
}
uni.showToast({
title: '网络错误请重试',
icon: 'none',
duration: 2000
});
reject(err)
}
});
})
if (data && data.loading !== false) {
uni.hideLoading();
}
if (res.data.result === "success") {
resolve(res.data);
} else {
uni.showToast({
title: res.data.msg || "系统开小差了",
icon: "none",
duration: 2000,
});
reject(res.data);
}
},
fail: (err) => {
if (data && data.loading !== false) {
uni.hideLoading();
}
uni.showToast({
title: "网络错误请重试",
icon: "none",
duration: 2000,
});
reject(err);
},
});
});
}
function upload(url, data) {
return new Promise((resolve, reject) => {
if (data && data.loading !== false) {
uni.showLoading({
title: '加载中'
});
}
uni.uploadFile({
url: requestPath + url,
filePath: data.filePath,
name: data.name || 'file',
formData: data.formData || {},
success: (res) => {
uni.hideLoading();
if (JSON.parse(res.data).result === 'success') {
resolve(JSON.parse(res.data))
} else {
uni.showToast({
title: JSON.parse(res.data).msg || '系统开小差了',
icon: 'none',
duration: 2000
});
reject(JSON.parse(res.data))
}
},
fail: (err) => {
uni.hideLoading();
uni.showToast({
title: '网络错误请重试',
icon: 'none',
duration: 2000
});
reject(err)
}
});
})
return new Promise((resolve, reject) => {
if (data && data.loading !== false) {
uni.showLoading({
title: "加载中",
});
}
uni.uploadFile({
url: requestPath + url,
filePath: data.filePath,
name: data.name || "file",
formData: data.formData || {},
success: (res) => {
uni.hideLoading();
if (JSON.parse(res.data).result === "success") {
resolve(JSON.parse(res.data));
} else {
uni.showToast({
title: JSON.parse(res.data).msg || "系统开小差了",
icon: "none",
duration: 2000,
});
reject(JSON.parse(res.data));
}
},
fail: (err) => {
uni.hideLoading();
uni.showToast({
title: "网络错误请重试",
icon: "none",
duration: 2000,
});
reject(err);
},
});
});
}
function uploads(url, data) {
return new Promise((resolve, reject) => {
if (data && data.loading !== false) {
uni.showLoading({
title: '加载中'
});
}
uni.uploadFile({
url: requestPath + url,
files: data.files,
formData: data.formData || {},
success: (res) => {
uni.hideLoading();
if (JSON.parse(res.data).result === 'success') {
resolve(JSON.parse(res.data))
} else {
uni.showToast({
title: JSON.parse(res.data).msg || '系统开小差了',
icon: 'none',
duration: 2000
});
reject(JSON.parse(res.data))
}
},
fail: (err) => {
uni.hideLoading();
uni.showToast({
title: '网络错误请重试',
icon: 'none',
duration: 2000
});
reject(err)
}
});
})
return new Promise((resolve, reject) => {
if (data && data.loading !== false) {
uni.showLoading({
title: "加载中",
});
}
uni.uploadFile({
url: requestPath + url,
files: data.files,
formData: data.formData || {},
success: (res) => {
uni.hideLoading();
if (JSON.parse(res.data).result === "success") {
resolve(JSON.parse(res.data));
} else {
uni.showToast({
title: JSON.parse(res.data).msg || "系统开小差了",
icon: "none",
duration: 2000,
});
reject(JSON.parse(res.data));
}
},
fail: (err) => {
uni.hideLoading();
uni.showToast({
title: "网络错误请重试",
icon: "none",
duration: 2000,
});
reject(err);
},
});
});
}
export {post, upload, uploads}
export { post, upload, uploads };

16
utils/useFormValidate.js Normal file
View File

@ -0,0 +1,16 @@
const useFormValidate = (ref, message = "请补全必填项!") => {
return new Promise((resolve, reject) => {
ref
.validate()
.then(() => {
resolve(true);
})
.catch(() => {
// eslint-disable-next-line prefer-promise-reject-errors
reject(false);
uni.$u.toast(message);
});
});
};
export default useFormValidate;