代码调试

This commit is contained in:
BianLzhaoMin 2025-12-26 10:15:18 +08:00
parent c9093f203c
commit e49f216474
6 changed files with 281 additions and 201 deletions

View File

@ -1,5 +1,6 @@
<template>
<el-select
filterable
:style="style"
:size="size"
v-bind="$attrs"

View File

@ -95,7 +95,7 @@ export const constantRoutes = [
component: () => import('@/views/planMange/monthlyPlan/edit.vue'),
name: 'MonthlyPlanEdit',
meta: {
title: '月计划填报',
title: '月计划',
activeMenu: '/plan/monthlyPlan', // 保持左侧高亮在列表菜单
},
},
@ -111,7 +111,7 @@ export const constantRoutes = [
component: () => import('@/views/planMange/dailyPlan/edit.vue'),
name: 'DailyPlanEdit',
meta: {
title: '日计划填报',
title: '日计划',
activeMenu: '/plan/dailyPlan', // 保持左侧高亮在列表菜单
},
},

View File

@ -1,5 +1,5 @@
import axios from 'axios'
import { ElNotification , ElMessageBox, ElMessage, ElLoading } from 'element-plus'
import { ElNotification, ElMessageBox, ElMessage, ElLoading } from 'element-plus'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { tansParams, blobValidate } from '@/utils/ruoyi'
@ -14,139 +14,167 @@ export let isRelogin = { show: false }
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const service = axios.create({
// axios中请求配置有baseURL选项表示请求URL公共部分
baseURL: import.meta.env.VITE_APP_BASE_API,
// 超时
timeout: 10000
// axios中请求配置有baseURL选项表示请求URL公共部分
baseURL: import.meta.env.VITE_APP_BASE_API,
// 超时
timeout: 10000,
})
// request拦截器
service.interceptors.request.use(config => {
// 是否需要设置 token
const isToken = (config.headers || {}).isToken === false
// 是否需要防止数据重复提交
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
if (getToken() && !isToken) {
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
}
// get请求映射params参数
if (config.method === 'get' && config.params) {
let url = config.url + '?' + tansParams(config.params)
url = url.slice(0, -1)
config.params = {}
config.url = url
}
if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
const requestObj = {
url: config.url,
data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
time: new Date().getTime()
}
const requestSize = Object.keys(JSON.stringify(requestObj)).length // 请求数据大小
const limitSize = 5 * 1024 * 1024 // 限制存放数据5M
if (requestSize >= limitSize) {
console.warn(`[${config.url}]: ` + '请求数据大小超出允许的5M限制无法进行防重复提交验证。')
return config
}
const sessionObj = cache.session.getJSON('sessionObj')
if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
cache.session.setJSON('sessionObj', requestObj)
} else {
const s_url = sessionObj.url // 请求地址
const s_data = sessionObj.data // 请求数据
const s_time = sessionObj.time // 请求时间
const interval = 1000 // 间隔时间(ms),小于此时间视为重复提交
if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
const message = '数据正在处理,请勿重复提交'
console.warn(`[${s_url}]: ` + message)
return Promise.reject(new Error(message))
} else {
cache.session.setJSON('sessionObj', requestObj)
}
}
}
return config
}, error => {
console.log(error)
Promise.reject(error)
})
service.interceptors.request.use(
(config) => {
// 是否需要设置 token
const isToken = (config.headers || {}).isToken === false
// 是否需要防止数据重复提交
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
if (getToken() && !isToken) {
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
}
// get请求映射params参数
if (config.method === 'get' && config.params) {
let url = config.url + '?' + tansParams(config.params)
url = url.slice(0, -1)
config.params = {}
config.url = url
}
if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
const requestObj = {
url: config.url,
data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
time: new Date().getTime(),
}
const requestSize = Object.keys(JSON.stringify(requestObj)).length // 请求数据大小
const limitSize = 5 * 1024 * 1024 // 限制存放数据5M
if (requestSize >= limitSize) {
console.warn(
`[${config.url}]: ` + '请求数据大小超出允许的5M限制无法进行防重复提交验证。',
)
return config
}
const sessionObj = cache.session.getJSON('sessionObj')
if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
cache.session.setJSON('sessionObj', requestObj)
} else {
const s_url = sessionObj.url // 请求地址
const s_data = sessionObj.data // 请求数据
const s_time = sessionObj.time // 请求时间
const interval = 1000 // 间隔时间(ms),小于此时间视为重复提交
if (
s_data === requestObj.data &&
requestObj.time - s_time < interval &&
s_url === requestObj.url
) {
const message = '数据正在处理,请勿重复提交'
console.warn(`[${s_url}]: ` + message)
return Promise.reject(new Error(message))
} else {
cache.session.setJSON('sessionObj', requestObj)
}
}
}
return config
},
(error) => {
console.log(error)
Promise.reject(error)
},
)
// 响应拦截器
service.interceptors.response.use(res => {
// 未设置状态码则默认成功状态
const code = res.data.code || 200
// 获取错误信息
const msg = errorCode[code] || res.data.msg || errorCode['default']
// 二进制数据则直接返回
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
return res.data
}
if (code === 401) {
if (!isRelogin.show) {
isRelogin.show = true
ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
isRelogin.show = false
useUserStore().logOut().then(() => {
location.href = '/index'
})
}).catch(() => {
isRelogin.show = false
})
}
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 500) {
ElMessage({ message: msg, type: 'error' })
return Promise.reject(new Error(msg))
} else if (code === 601) {
ElMessage({ message: msg, type: 'warning' })
return Promise.reject(new Error(msg))
} else if (code !== 200) {
ElNotification.error({ title: msg })
return Promise.reject('error')
} else {
return Promise.resolve(res.data)
}
},
error => {
console.log('err' + error)
let { message } = error
if (message == "Network Error") {
message = "后端接口连接异常"
} else if (message.includes("timeout")) {
message = "系统接口请求超时"
} else if (message.includes("Request failed with status code")) {
message = "系统接口" + message.substr(message.length - 3) + "异常"
}
ElMessage({ message: message, type: 'error', duration: 5 * 1000 })
return Promise.reject(error)
}
service.interceptors.response.use(
(res) => {
// 未设置状态码则默认成功状态
const code = res.data.code || 200
// 获取错误信息
const msg = errorCode[code] || res.data.msg || errorCode['default']
// 二进制数据则直接返回
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
return res.data
}
if (code === 401) {
if (!isRelogin.show) {
isRelogin.show = true
ElMessageBox.confirm(
'登录状态已过期,您可以继续留在该页面,或者重新登录',
'系统提示',
{ confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' },
)
.then(() => {
isRelogin.show = false
useUserStore()
.logOut()
.then(() => {
location.href = '/index'
})
})
.catch(() => {
isRelogin.show = false
})
}
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 500) {
ElMessage({ message: msg, type: 'error' })
return Promise.reject(new Error(msg))
} else if (code === 601) {
ElMessage({ message: msg, type: 'warning' })
return Promise.reject(new Error(msg))
} else if (code !== 200) {
ElNotification.error({ title: msg })
return Promise.reject('error')
} else {
return Promise.resolve(res.data)
}
},
(error) => {
console.log('err' + error)
let { message } = error
if (message == 'Network Error') {
message = '后端接口连接异常'
} else if (message.includes('timeout')) {
message = '系统接口请求超时'
} else if (message.includes('Request failed with status code')) {
message = '系统接口' + message.substr(message.length - 3) + '异常'
}
ElMessage({ message: message, type: 'error', duration: 5 * 1000 })
return Promise.reject(error)
},
)
// 通用下载方法
export function download(url, params, filename, config) {
downloadLoadingInstance = ElLoading.service({ text: "正在下载数据,请稍候", background: "rgba(0, 0, 0, 0.7)", })
return service.post(url, params, {
transformRequest: [(params) => { return tansParams(params) }],
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
responseType: 'blob',
...config
}).then(async (data) => {
const isBlob = blobValidate(data)
if (isBlob) {
const blob = new Blob([data])
saveAs(blob, filename)
} else {
const resText = await data.text()
const rspObj = JSON.parse(resText)
const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
ElMessage.error(errMsg)
}
downloadLoadingInstance.close()
}).catch((r) => {
console.error(r)
ElMessage.error('下载文件出现错误,请联系管理员!')
downloadLoadingInstance.close()
})
downloadLoadingInstance = ElLoading.service({
text: '正在下载数据,请稍候',
background: 'rgba(0, 0, 0, 0.7)',
})
return service
.post(url, params, {
transformRequest: [
(params) => {
return tansParams(params)
},
],
headers: { ...config?.headers, 'Content-Type': 'application/x-www-form-urlencoded' },
responseType: 'blob',
...config,
})
.then(async (data) => {
const isBlob = blobValidate(data)
if (isBlob) {
const blob = new Blob([data])
saveAs(blob, filename)
} else {
const resText = await data.text()
const rspObj = JSON.parse(resText)
const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
ElMessage.error(errMsg)
}
downloadLoadingInstance.close()
})
.catch((r) => {
console.error(r)
ElMessage.error('下载文件出现错误,请联系管理员!')
downloadLoadingInstance.close()
})
}
export default service

View File

@ -1,57 +1,49 @@
import { reactive } from 'vue'
import dayjs from 'dayjs'
// 静态选项(可后续替换为接口下拉)
const stationOptions = [
{ label: '昆明运检站', value: 1 },
{ label: '大理运检站', value: 2 },
]
const majorOptions = [
{ label: '输电专业', value: 1 },
{ label: '变电专业', value: 2 },
]
const businessTypeOptions = [
{ label: '日常巡视', value: 1 },
{ label: '缺陷处理', value: 2 },
]
const riskLevelOptions = [
{ label: '低风险', value: 1 },
{ label: '中风险', value: 2 },
{ label: '高风险', value: 3 },
]
// 月计划列表搜索表单配置
export const buildFormColumns = () => [
export const buildFormColumns = (
inspectionStationOptions,
majorOptions,
businessTypeOptions,
riskLevelOptions,
) => [
{
type: 'month',
prop: 'month',
prop: 'monthlyPlan',
placeholder: '请选择月份',
},
{
type: 'select',
prop: 'stationId',
prop: 'inspectionStationId',
placeholder: '请选择运检站',
options: stationOptions,
options: inspectionStationOptions.map((item) => ({
label: item.value,
value: item.id,
})),
},
{
type: 'input',
prop: 'keyword',
prop: 'keyWord',
placeholder: '请输入关键字',
},
{
type: 'select',
prop: 'majorId',
prop: 'planMajorId',
placeholder: '请选择专业',
options: majorOptions,
options: majorOptions.map((item) => ({
label: item.planMajorName,
value: item.planMajorId,
})),
},
{
type: 'select',
prop: 'businessTypeId',
placeholder: '请选择业务类型',
options: businessTypeOptions,
options: businessTypeOptions.map((item) => ({
label: item.planMajorName,
value: item.planMajorId,
})),
},
{
type: 'select',

View File

@ -208,7 +208,7 @@
@click="onOpenPersonPicker"
v-model="selectedManagerNames"
>
<template #suffix>
<template #suffix v-if="!isDetail">
<el-icon
class="clickable-suffix"
@click.stop="onOpenPersonPicker"
@ -306,7 +306,7 @@
<div class="card-header">人员排班</div>
</template>
<div class="schedule-wrapper">
<div class="schedule-tip">
<div class="schedule-tip" v-if="!isDetail">
<span class="schedule-tip-extra">
仅在计划开始时间 ~
计划结束时间范围内可排班表单中的计划投入管理人员只是模板不会被日历上的增删影响
@ -350,10 +350,10 @@
</template>
<div class="popover-list">
<el-tag
v-for="person in day.managers"
:key="person.id"
size="small"
closable
:key="person.id"
:closable="!isDetail"
v-for="person in day.managers"
@close.stop="onRemovePersonFromDay(day.date, person)"
>
{{ person.name }}
@ -364,9 +364,9 @@
<div class="person-tags">
<el-tag
size="small"
v-for="person in day.managers"
:key="person.id"
closable
:closable="!isDetail"
v-for="person in day.managers"
@close.stop="onRemovePersonFromDay(day.date, person)"
>
{{ person.name }}
@ -483,8 +483,8 @@
<div class="selected-list">
<div>
<el-tag
closable
:key="item.id"
:closable="!isDetail"
class="selected-tag"
@close="onRemoveManager(item)"
v-for="item in managerDialog.selected"
@ -512,7 +512,7 @@
</template>
<script setup name="MonthlyPlanEdit">
import { ref, reactive, computed, getCurrentInstance, nextTick } from 'vue'
import { ref, reactive, computed, getCurrentInstance, nextTick, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { updatePlanAPI } from '@/api/planMange/plan.js'
import {
@ -630,23 +630,6 @@ const getInitFormData = () => ({
const formData = ref(getInitFormData())
//
const stationOptions = [
{ label: '昆明运检站', value: 1 },
{ label: '大理运检站', value: 2 },
]
const businessTypeOptions = [
{ label: '日常巡视', value: 1 },
{ label: '缺陷处理', value: 2 },
]
const riskLevelOptions = [
{ label: '低风险', value: 1 },
{ label: '中风险', value: 2 },
{ label: '高风险', value: 3 },
]
const rules = {
planMajorId: [{ required: true, message: '请选择专业', trigger: 'change' }],
businessTypeId: [{ required: true, message: '请选择业务类型', trigger: 'change' }],
@ -674,8 +657,8 @@ const rules = {
}
const onBack = () => {
// router.back()
router.push({
//
proxy.$tab.closeOpenPage({
path: '/plan/monthlyPlan',
})
}

View File

@ -61,27 +61,60 @@
<script setup name="MonthlyPlan">
import { ref, computed, getCurrentInstance } from 'vue'
import { useRouter } from 'vue-router'
import { useOptions } from '@/hooks/useOptions'
import {
listMonthlyPlanAPI,
addMonthlyPlanAPI,
delMonthlyPlanAPI,
} from '@/api/planMange/monthlyPlan.js'
import { getInspectionStationSelectAPI, getMajorTypeCategorySelectAPI } from '@/api/common.js'
import config from './config'
import ComTable from '@/components/ComTable/index.vue'
import ComButton from '@/components/ComButton/index.vue'
import ComDialog from '@/components/ComDialog/index.vue'
import AddForm from './addForm.vue'
const router = useRouter()
const { proxy } = getCurrentInstance()
const { plan_risk_level } = proxy.useDict('plan_risk_level')
const router = useRouter()
const { tableColumns, dialogConfig, buildFormColumns } = config
const comTableRef = ref(null)
const addFormRef = ref(null)
//
const { options: inspectionStationOptions } = useOptions(
'inspectionStationOptions',
getInspectionStationSelectAPI,
{ category: 0 },
)
//
const { options: majorTypeCategoryOptions } = useOptions(
'majorTypeCategoryOptions',
getMajorTypeCategorySelectAPI,
{
category: 0,
},
)
//
const { options: planBusinessTypeOptions } = useOptions(
'planBusinessTypeOptions',
getMajorTypeCategorySelectAPI,
{
category: 1,
},
)
// 使
const formColumns = computed(() => buildFormColumns())
const formColumns = computed(() =>
buildFormColumns(
inspectionStationOptions.value,
majorTypeCategoryOptions.value,
planBusinessTypeOptions.value,
plan_risk_level.value,
),
)
//
const actionColumns = [
@ -90,9 +123,25 @@ const actionColumns = [
type: 'primary',
link: true,
handler: (row) => {
const {
monthlyPlanId,
inspectionStationName,
projectName,
workContent,
plannedStartTime,
plannedEndTime,
} = row
router.push({
path: '/plan/monthlyPlanEdit/index',
query: { id: row.planId, mode: 'detail' },
query: {
projectName,
workContent,
monthlyPlanId,
mode: 'detail',
plannedEndTime,
plannedStartTime,
inspectionStationName,
},
})
},
},
@ -112,12 +161,12 @@ const actionColumns = [
router.push({
path: '/plan/monthlyPlanEdit/index',
query: {
monthlyPlanId,
inspectionStationName,
projectName,
workContent,
plannedStartTime,
monthlyPlanId,
plannedEndTime,
plannedStartTime,
inspectionStationName,
},
})
},
@ -180,23 +229,50 @@ const onCloseDialogOuter = (visible) => {
//
const onExportPersonArrange = (queryParams) => {
console.log('queryParams', queryParams)
// proxy.download(
// 'xxx/xxx',
// {
// ...queryParams.value,
// },
// `job_${new Date().getTime()}.xlsx`,
// )
proxy.download(
'/monthlyPlan/export',
{
...queryParams,
},
`人员安排表.xlsx`,
{
headers: {
'Content-Type': 'application/json',
},
},
)
}
//
const onExportOverallSummary = (queryParams) => {
console.log('queryParams', queryParams)
proxy.download(
'/monthlyPlan/exportResourceSummary',
{
...queryParams,
},
`整体汇总表.xlsx`,
{
headers: {
'Content-Type': 'application/json',
},
},
)
}
//
const onExportWorkloadSummary = (queryParams) => {
console.log('queryParams', queryParams)
proxy.download(
'/monthlyPlan/exportWorkloadSummary',
{
...queryParams,
},
`工作量汇总表.xlsx`,
{
headers: {
'Content-Type': 'application/json',
},
},
)
}
</script>