代码提交

This commit is contained in:
lixiaobang 2026-02-02 10:14:00 +08:00
parent 476b9f79cb
commit 7959a0bd7d
13 changed files with 1180 additions and 184 deletions

View File

@ -1,3 +1,4 @@
export * from './modules/auth'
export * from './modules/user'
export * from './modules/workTicket'
export * from './modules/workTicket'
export * from './modules/projectImplementation'

View File

@ -0,0 +1,33 @@
import { get } from '../request'
/**
* 查询项目实施列表
* @param {Object} params - 查询参数
* @param {Number} params.pageNum - 页码可选
* @param {Number} params.pageSize - 每页数量可选
* @param {String} params.status - 状态可选
* @param {String} params.projectName - 项目名称可选模糊查询
* @param {Number} params.projectId - 项目ID可选
* @returns {Promise} 返回项目实施列表 { total: number, rows: array }
*/
export function getProjectImplementationList(params = {}) {
return get('/manage/contractor/projectImplementation/list', params)
}
/**
* 查询项目详情
* @param {Number} projectId - 项目ID
* @returns {Promise} 返回项目详情数据
*/
export function getProjectImplementationDetail(projectId) {
return get(`/manage/contractor/projectImplementation/${projectId}`)
}
/**
* 查询当天合格数量和检查项总数
* @param {Number} projectId - 项目ID
* @returns {Promise} 返回当天检查项汇总数据 { qualifiedCount: number, totalCount: number, submissionDate: string, submitted: boolean }
*/
export function getTodayInspectionSummary(projectId) {
return get('/manage/contractor/dailyInspection/todaySummary', { projectId })
}

View File

@ -92,6 +92,15 @@ export function submitWorkPlan(projectId) {
return put(`/manage/contractor/workPlan/submit/${projectId}`)
}
/**
* 撤回工作计划
* @param {Number|String} projectId - 项目ID必填
* @returns {Promise}
*/
export function withdrawWorkPlan(projectId) {
return put(`/manage/contractor/workPlan/withdraw/${projectId}`)
}
/**
* 上传文件
* @param {String} filePath - 文件路径本地临时文件路径
@ -196,4 +205,56 @@ export function submitImplementation(projectId) {
return put(`/manage/contractor/projectImplementation/submitImplementation?projectId=${projectId}`)
}
/**
* 修改工作计划
* @param {Object} data - 工作计划数据
* @param {Number|String} data.id - 工作计划ID必填
* @returns {Promise}
*/
export function updateWorkPlan(data) {
return put('/manage/contractor/workPlan', data)
}
/**
* 获取出入证详情根据项目ID
* @param {Number|String} projectId - 项目ID必填
* @returns {Promise} 返回出入证详情
*/
export function getAccessPermitDetail(projectId) {
return get(`/manage/contractor/accessPermit/project/${projectId}`)
}
/**
* 修改出入证申请
* @param {Object} data - 出入证申请数据
* @param {Number|String} data.id - 出入证申请ID必填
* @returns {Promise}
*/
export function updateAccessPermit(data) {
return put('/manage/contractor/accessPermit', data)
}
/**
* 修改工作票申请
* @param {Object} data - 工作票数据
* @param {Number|String} data.id - 工作票ID必填
* @param {Number} data.projectId - 所属项目ID必填
* @param {String} data.workLocation - 作业地点
* @param {Number} data.supervisorId - 作业负责人ID
* @param {String} data.supervisorName - 作业负责人姓名
* @param {String} data.supervisorPosition - 作业负责人职位
* @param {String} data.workContent - 作业内容
* @param {String} data.riskType - 风险类型高风险中风险低风险
* @param {String} data.workStartTime - 作业开始时间格式yyyy-MM-dd HH:mm:ss
* @param {String} data.workEndTime - 作业结束时间格式yyyy-MM-dd HH:mm:ss
* @param {Array<String>} data.safetyMeasuresList - 安全措施列表
* @param {Array<Object>} data.qualificationList - 作业班成员资质列表
* @param {String} data.needMonitoringCamera - 是否需申领移动监控球机"0""1"
* @param {Number} data.cameraApplicationId - 监控球机申请ID如果需要监控球机时填写
* @param {String} data.remark - 备注
* @returns {Promise}
*/
export function updateWorkTicket(data) {
return put('/manage/contractor/workTicket', data)
}

View File

@ -2,14 +2,14 @@
<template>
<view class="MainBox">
<view class="labebBox">申请单位</view>
<view class="fw-600">{{ progectInfo.applyUnit }}</view>
<view class="fw-600">{{ applyUnit }}</view>
<view class="labebBox">施工单位</view>
<view class="fw-600">{{ progectInfo.constructUnit }}</view>
<view class="fw-600">{{ constructUnit }}</view>
<view class="labebBox">施工地点</view>
<view class="fw-600">{{ progectInfo.site }}</view>
<view class="fw-600">{{ site }}</view>
<view class="labebBox">附件资料</view>
<view class="ListBox">
<u-virtual-list :list-data="dataSource" :item-height="80" height="100%">
<u-virtual-list v-if="dataSource.length > 0" :list-data="dataSource" :item-height="80" height="100%">
<template #default="{ item, index }">
<view class="CardBox" :key="item.id">
<view class="FlexBox">
@ -22,45 +22,78 @@
</view>
</template>
</u-virtual-list>
<view v-else class="empty-tip">暂无附件资料</view>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue'
const progectInfo = ref({
Id: 1,
applyUnit: '北京CBD改造项目管理有限公司',
constructUnit: '北京CBD改造项目施工有限公司',
site: '北京市海淀区',
})
const dataSource = ref([
{
id: 1,
name: '项目合同.pdf'
},
{
id: 2,
name: '项目进度表.xlsx'
},
{
id: 3,
name: '项目成本表.xlsx'
},
{
id: 4,
name: '项目风险卡.xlsx'
},
{
id: 5,
name: '项目整改记录.xlsx'
},
{
id: 6,
name: '项目风险管控类型.xlsx'
import { ref, computed } from 'vue'
const props = defineProps({
projectData: {
type: Object,
default: () => null
}
})
//
const applyUnit = computed(() => {
return props.projectData?.constructionUnitName || '未设置'
})
//
const constructUnit = computed(() => {
return props.projectData?.constructionUnitName || '未设置'
})
//
const site = computed(() => {
const location = props.projectData?.workLocation || ''
const detail = props.projectData?.workLocationDetail || ''
if (location && detail) {
return `${location} ${detail}`
}
return location || detail || '未设置'
})
// projectData
const dataSource = ref([
//
//
])
//
const getProjectStatusText = (status) => {
const statusMap = {
'0': '未开始',
'1': '进行中',
'2': '已完成',
'3': '已暂停',
'4': '已取消'
}
return statusMap[status] || '未知状态'
}
//
const getImplementationStatusText = (status) => {
const statusMap = {
'1': '实施中',
'2': '已完工',
'3': '整改中',
'4': '待完工确认'
}
return statusMap[status] || '未知状态'
}
//
const getApprovalStatusText = (status) => {
const statusMap = {
'0': '待审批',
'1': '已审批',
'2': '已拒绝'
}
return statusMap[status] || '未知状态'
}
</script>
<style lang="scss" scoped>
.labebBox {
@ -97,6 +130,13 @@ const dataSource = ref([
margin-top: 20rpx;
height: calc(100% - 384rpx);
padding: 20rpx;
.empty-tip {
text-align: center;
color: #999;
font-size: 28rpx;
padding: 40rpx 0;
}
.CardBox {
width: 100%;

View File

@ -5,7 +5,7 @@
<u-row>
<u-col :span="6">
<view>今日检查项完成度</view>
<view class="blcakFont">5/6</view>
<view class="blcakFont">{{ completedCount }}/{{ totalCheckItems }}</view>
</u-col>
<u-col :span="6">
<view>待整改问题数</view>
@ -43,7 +43,34 @@
</view>
</template>
<script setup>
import { ref } from 'vue'
import { ref, computed } from 'vue'
const props = defineProps({
projectData: {
type: Object,
default: () => null
},
todaySummary: {
type: Object,
default: () => ({
qualifiedCount: 0,
totalCount: 0,
submissionDate: '',
submitted: false
})
}
})
// 使
const totalCheckItems = computed(() => {
return props.todaySummary?.totalCount || 0
})
// 使
const completedCount = computed(() => {
return props.todaySummary?.qualifiedCount || 0
})
const dataSource = ref([
{ id: 1, name: 'AI返现安全帽佩戴不规范', time: '2023-08-01 10:00:00' },
{ id: 2, name: 'AI返现安全帽佩戴不规范', time: '2023-08-02 10:00:00' },
@ -55,8 +82,17 @@ const dataSource = ref([
])
//
const submitCheck = () => {
// ID
const projectId = props.projectData?.projectId
if (!projectId) {
uni.showToast({
title: '项目ID不存在',
icon: 'none'
})
return
}
uni.navigateTo({
url: '/pages/TodayExamine/index',
url: `/pages/TodayExamine/index?projectId=${projectId}`,
})
}
//

View File

@ -44,16 +44,16 @@
<up-tabs :list="list1" @click="click"></up-tabs>
</view>
<view class="displayCase">
<ControlView v-if="currentTab === 1"></ControlView>
<BasicView v-if="currentTab === 2" ></BasicView>
<RecordView v-if="currentTab === 3"></RecordView>
<ControlView v-if="currentTab === 1" :project-data="progectInfo.detailData" :today-summary="todayInspectionSummary"></ControlView>
<BasicView v-if="currentTab === 2" :project-data="progectInfo.detailData"></BasicView>
<RecordView v-if="currentTab === 3" :project-data="progectInfo.detailData"></RecordView>
</view>
</view>
<view class="FootBox">
<u-button type="primary">项目完工确认</u-button>
<u-button type="primary" :disabled="progectInfo.detailData?.implementationStatus !== '4'">项目完工确认</u-button>
<view class="FootTxt">
<view>复核进度</view>
<view class="yellow">监理复核中</view>
<view class="yellow">{{ getReviewStatusText() }}</view>
</view>
</view>
</view>
@ -62,16 +62,29 @@
import ControlView from './components/ControlView.vue'
import BasicView from './components/BasicView.vue'
import RecordView from './components/RecordView.vue'
import { ref } from 'vue'
import { ref, onMounted } from 'vue'
import { getProjectImplementationDetail, getTodayInspectionSummary } from '@/api'
const progectInfo = ref({
Id: 1,
name: '北京CBD改造项目',
code: '20230801001',
leader: '张三',
period: '2023.8.1-2023.12.31',
riskControlType: '动火作业风险卡',
percentage: 30
Id: null,
name: '',
code: '',
leader: '',
period: '',
riskControlType: '',
percentage: 0,
//
detailData: null
})
//
const todayInspectionSummary = ref({
qualifiedCount: 0,
totalCount: 0,
submissionDate: '',
submitted: false
})
// tabs
const currentTab = ref(1)
// tabs
@ -95,10 +108,127 @@ const click = (e) => {
}
//
const goBack = () => {
uni.switchTab({
url: '/pages/ProgectList/index'
})
uni.navigateBack()
}
//
const formatDate = (dateStr) => {
if (!dateStr) return ''
const date = new Date(dateStr)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
return `${year}.${month}.${day}`
}
//
const fetchProjectDetail = async (projectId) => {
try {
const data = await getProjectImplementationDetail(projectId)
if (data) {
//
progectInfo.value.detailData = data
//
progectInfo.value.Id = data.projectId
progectInfo.value.name = data.projectName || '未命名项目'
progectInfo.value.code = data.projectCode || ''
//
progectInfo.value.leader = data.supervisorName || '未设置'
//
const startTime = formatDate(data.workStartTime)
const endTime = formatDate(data.workEndTime)
progectInfo.value.period = startTime && endTime ? `${startTime}-${endTime}` : '未设置'
//
progectInfo.value.percentage = data.currentProgress || 0
// riskControlCard.templateName
progectInfo.value.riskControlType = data.riskControlCard?.templateName || '未设置'
}
} catch (error) {
console.error('获取项目详情失败:', error)
uni.showToast({
title: '获取项目详情失败',
icon: 'none'
})
}
}
//
const fetchTodayInspectionSummary = async (projectId) => {
try {
const data = await getTodayInspectionSummary(projectId)
if (data) {
todayInspectionSummary.value = {
qualifiedCount: data.qualifiedCount || 0,
totalCount: data.totalCount || 0,
submissionDate: data.submissionDate || '',
submitted: data.submitted || false
}
}
} catch (error) {
console.error('获取今日检查项汇总失败:', error)
// 使
todayInspectionSummary.value = {
qualifiedCount: 0,
totalCount: 0,
submissionDate: '',
submitted: false
}
}
}
//
const getReviewStatusText = () => {
const data = progectInfo.value.detailData
if (!data) return '未知状态'
//
if (data.supervisionReviewStatus) {
const statusMap = {
'0': '待监理复核',
'1': '监理复核中',
'2': '监理复核通过',
'3': '监理复核拒绝'
}
return statusMap[data.supervisionReviewStatus] || '未知状态'
}
//
if (data.propertyReviewStatus) {
const statusMap = {
'0': '待物业复核',
'1': '物业复核中',
'2': '物业复核通过',
'3': '物业复核拒绝'
}
return statusMap[data.propertyReviewStatus] || '未知状态'
}
return '未开始复核'
}
//
onMounted(() => {
// URLID
const pages = getCurrentPages()
const currentPage = pages[pages.length - 1]
const options = currentPage.options || {}
const projectId = options.id || options.projectId
if (projectId) {
fetchProjectDetail(projectId)
fetchTodayInspectionSummary(projectId)
} else {
uni.showToast({
title: '缺少项目ID参数',
icon: 'none'
})
}
})
</script>
<style lang="scss" scoped>
.FlexBox {

View File

@ -4,7 +4,7 @@
<view class="FlexBox TopBox">
<view class="SelectBox">
<u-select :current="TypeValue" :options="TypeList" placeholder="请选择工单类型" size="large" showOptionsLabel
@update:current="TypeValue = $event"></u-select>
@update:current="handleTypeChange($event)"></u-select>
</view>
@ -34,7 +34,10 @@
</view>
</template>
<script setup>
import { ref } from 'vue'
import { ref, onMounted } from 'vue'
import { onPullDownRefresh } from '@dcloudio/uni-app'
import { getProjectImplementationList } from '@/api'
const TypeValue = ref('1') //
//
const TypeList = ref([
@ -44,15 +47,96 @@ const TypeList = ref([
{ name: '待完工确认', id: '4' },
])
const dataSource = ref([
{ id: 1, name: '北京CBD写字楼改造项目', remainingTime: '1', site: '北京市朝阳区建国路88号', status: '实施中' },
{ id: 2, name: '工单2', remainingTime: '2', site: '北京市朝阳区建国路88号', status: '整改中' },
{ id: 3, name: '工单3', remainingTime: '3', site: '北京市朝阳区建国路88号', status: '待完工确认' },
{ id: 4, name: '工单4', remainingTime: '5', site: '北京市朝阳区建国路88号', status: '实施中' },
{ id: 5, name: '工单5', remainingTime: '3', site: '北京市朝阳区建国路88号', status: '待完工确认' },
{ id: 6, name: '工单6', remainingTime: '2', site: '北京市朝阳区建国路88号', status: '已完工' },
{ id: 7, name: '工单7', remainingTime: '4', site: '北京市朝阳区建国路88号', status: '已完工' },
])
const dataSource = ref([])
const total = ref(0) //
//
const fetchProjectImplementationList = async () => {
try {
const params = {
pageNum: 1,
pageSize: 1000
}
//
if (TypeValue.value === '2') {
// -
params.myProject = true
} else if (TypeValue.value === '3') {
//
params.status = '整改中'
} else if (TypeValue.value === '4') {
//
params.status = '待完工确认'
} else {
//
params.status = '实施中'
}
const result = await getProjectImplementationList(params)
// { total, rows, code, msg }
if (result && result.rows && Array.isArray(result.rows)) {
dataSource.value = result.rows.map(item => {
//
let remainingDays = 0
if (item.workEndTime) {
const endTime = new Date(item.workEndTime)
const now = new Date()
const diffTime = endTime - now
remainingDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
remainingDays = remainingDays > 0 ? remainingDays : 0
}
//
let statusText = '未知状态'
if (item.implementationStatus === '1') {
statusText = '实施中'
} else if (item.implementationStatus === '2') {
statusText = '已完工'
} else if (item.implementationStatus === '3') {
statusText = '整改中'
} else if (item.implementationStatus === '4') {
statusText = '待完工确认'
}
return {
id: item.projectId,
name: item.projectName || '未命名项目',
remainingTime: remainingDays,
site: item.workLocation || item.workLocationDetail || '未设置地址',
status: statusText,
// 便使
rawData: item
}
})
total.value = result.total || 0
} else {
dataSource.value = []
total.value = 0
}
} catch (error) {
console.error('查询项目实施列表失败:', error)
dataSource.value = []
total.value = 0
}
}
//
const handleTypeChange = (value) => {
TypeValue.value = value
fetchProjectImplementationList()
}
//
onMounted(() => {
fetchProjectImplementationList()
})
//
onPullDownRefresh(() => {
fetchProjectImplementationList().finally(() => {
uni.stopPullDownRefresh()
})
})
//
const GoDetail = (id) => {

View File

@ -18,8 +18,8 @@
<view class="LabelBox">{{ item.checkItemName }}</view>
<view class="ValueBox">
<u-radio-group v-model="item.value" @change="change(item)">
<u-radio label="合格" :border-color="item.value === '' ? '#ff9900' : '#c5d5d6'"></u-radio>
<u-radio label="不合格" :border-color="item.value === '' ? '#ff9900' : '#c5d5d6'"></u-radio>
<u-radio label="合格" :name="'合格'" :border-color="item.value === '合格' ? '#ff9900' : '#c5d5d6'"></u-radio>
<u-radio label="不合格" :name="'不合格'" :border-color="item.value === '不合格' ? '#ff9900' : '#c5d5d6'"></u-radio>
</u-radio-group>
</view>
</view>
@ -32,31 +32,75 @@
</view>
</template>
<script setup>
import { ref } from 'vue'
import { ref, onMounted } from 'vue'
import { getProjectImplementationDetail } from '@/api'
//
const checkItemList = ref([
{
id: 1,
checkItemName: '作业人员是否持证上岗',
value: '是'
},
{
id: 2,
checkItemName: '作业人员是否有安全装备',
value: '是'
},
{
id: 3,
checkItemName: '作业人员是否有安全工具',
value: '是'
}
])
const checkItemList = ref([])
//
const goBack = () => {
uni.navigateBack({
delta: 1
})
}
//
const fetchCheckItems = async (projectId) => {
try {
const data = await getProjectImplementationDetail(projectId)
if (data && data.riskControlCard && data.riskControlCard.checkItems && data.riskControlCard.checkItems.length > 0) {
// checkItemssortOrder
checkItemList.value = data.riskControlCard.checkItems
.map(item => ({
id: item.checkItemId,
checkItemName: item.itemDescription,
value: item.checkResult === '合格' ? '合格' : (item.checkResult || ''),
checkItemId: item.checkItemId,
templateItemId: item.templateItemId,
sortOrder: item.sortOrder || 0,
originalData: item // 便
}))
.sort((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0))
} else {
uni.showToast({
title: '暂无检查项数据',
icon: 'none'
})
checkItemList.value = []
}
} catch (error) {
console.error('获取检查项数据失败:', error)
uni.showToast({
title: '获取检查项数据失败',
icon: 'none'
})
checkItemList.value = []
}
}
//
const change = (item) => {
console.log('检查项选择改变:', item)
}
//
onMounted(() => {
// URLID
const pages = getCurrentPages()
const currentPage = pages[pages.length - 1]
const options = currentPage.options || {}
const projectId = options.projectId || options.id
if (projectId) {
fetchCheckItems(projectId)
} else {
uni.showToast({
title: '缺少项目ID参数',
icon: 'none'
})
}
})
</script>
<style lang="scss" scoped>

View File

@ -26,8 +26,8 @@
<u-tag :text="item.draftStatusText" shape="circle"></u-tag>
</view>
<view class="BtnList">
<u-button text="修改" plain color="#2979ff" size="small"></u-button>
<u-button text="撤回" plain color="#ff9900" size="small"></u-button>
<u-button text="修改" plain color="#2979ff" size="small" @click="handleEdit(item)"></u-button>
<u-button text="撤回" plain color="#ff9900" size="small" @click="handleWithdraw(item, index)"></u-button>
<u-button text="删除" plain color="#fa3534" size="small" @click="handleDelete(item, index)"></u-button>
</view>
</view>
@ -36,7 +36,7 @@
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { getWorkPlanList, deleteWorkPlan } from '@/api/modules/workTicket'
import { getWorkPlanList, deleteWorkPlan, withdrawWorkPlan } from '@/api/modules/workTicket'
const TypeValue = ref('1') //
//
@ -142,6 +142,30 @@ const HandleNewAdd = () => {
})
}
//
const handleEdit = (item) => {
const projectId = item.projectId || item.id
if (!projectId) {
uni.showToast({
title: '项目ID不存在',
icon: 'none'
})
return
}
// ID ticketIds ticketId
const ticketId = item.ticketIds || item.ticketId
// URL edit=1
let url = `/pages/WorkOrderEdit/index?projectId=${projectId}&edit=1`
if (ticketId) {
// ticketIds 使
const ticketIdValue = Array.isArray(ticketId) ? ticketId[0] : ticketId
url += `&workTicketId=${ticketIdValue}`
}
uni.navigateTo({
url: url
})
}
//
const handleDetail = (item) => {
const projectId = item.projectId || item.id
@ -166,6 +190,55 @@ const handleDetail = (item) => {
})
}
//
const handleWithdraw = async (item, index) => {
try {
//
const res = await new Promise((resolve) => {
uni.showModal({
title: '提示',
content: `确定要撤回项目"${item.projectName || '未命名项目'}"吗?`,
confirmText: '撤回',
confirmColor: '#ff9900',
success: (result) => {
resolve(result.confirm)
},
fail: () => {
resolve(false)
}
})
})
if (!res) {
return
}
// ID使 projectId使 id
const projectId = item.projectId || item.id
if (!projectId) {
uni.showToast({
title: '项目ID不存在',
icon: 'none'
})
return
}
//
await withdrawWorkPlan(projectId)
uni.showToast({
title: '撤回成功',
icon: 'success'
})
//
await fetchWorkPlanList()
} catch (error) {
console.error('撤回失败:', error)
// request.js
}
}
//
const handleDelete = async (item, index) => {
try {

View File

@ -137,13 +137,19 @@ const restoreFormData = (data) => {
}
if (data.period && Array.isArray(data.period) && data.period.length >= 2) {
if (data.period[0]) {
startDateText.value = data.period[0];
startDate.value = dayjs(data.period[0]).valueOf();
// "2020-01-01 00:00:00"
const startDateStr = String(data.period[0]).split(' ')[0];
startDateText.value = startDateStr;
startDate.value = dayjs(startDateStr).isValid() ? dayjs(startDateStr).valueOf() : null;
}
if (data.period[1]) {
endDateText.value = data.period[1];
endDate.value = dayjs(data.period[1]).valueOf();
// "2020-01-01 00:00:00"
const endDateStr = String(data.period[1]).split(' ')[0];
endDateText.value = endDateStr;
endDate.value = dayjs(endDateStr).isValid() ? dayjs(endDateStr).valueOf() : null;
}
// formData.period
UpdatePeriod();
}
};

View File

@ -296,10 +296,10 @@ const restoreFormData = (data) => {
formData.value.CarList = [...data.CarList];
}
if (data.remark) formData.value.remark = data.remark;
// data
// if (data.fileList && Array.isArray(data.fileList)) {
// fileList1.value = [...data.fileList];
// }
//
if (data.fileList && Array.isArray(data.fileList)) {
fileList1.value = [...data.fileList];
}
};
// allData.GatePassInfo
@ -358,7 +358,11 @@ defineExpose({
return typeof id === 'string' ? parseInt(id) || id : id;
});
// ID
const accessPermitId = props.allData?.GatePassInfo?.id || null;
return {
permitId: accessPermitId, // ID使permitId
projectId,
workLocation,
sysUserIds,

File diff suppressed because it is too large Load Diff

View File

@ -75,8 +75,6 @@ async function handleLogin() {
password: formData.password,
role: formData.role
})
console.log(response);
// token
if (response) {
userStore.setUserInfo(response)