代码调试

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> <template>
<el-select <el-select
filterable
:style="style" :style="style"
:size="size" :size="size"
v-bind="$attrs" v-bind="$attrs"

View File

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

View File

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

View File

@ -1,57 +1,49 @@
import { reactive } from 'vue' import { reactive } from 'vue'
import dayjs from 'dayjs' 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', type: 'month',
prop: 'month', prop: 'monthlyPlan',
placeholder: '请选择月份', placeholder: '请选择月份',
}, },
{ {
type: 'select', type: 'select',
prop: 'stationId', prop: 'inspectionStationId',
placeholder: '请选择运检站', placeholder: '请选择运检站',
options: stationOptions, options: inspectionStationOptions.map((item) => ({
label: item.value,
value: item.id,
})),
}, },
{ {
type: 'input', type: 'input',
prop: 'keyword', prop: 'keyWord',
placeholder: '请输入关键字', placeholder: '请输入关键字',
}, },
{ {
type: 'select', type: 'select',
prop: 'majorId', prop: 'planMajorId',
placeholder: '请选择专业', placeholder: '请选择专业',
options: majorOptions, options: majorOptions.map((item) => ({
label: item.planMajorName,
value: item.planMajorId,
})),
}, },
{ {
type: 'select', type: 'select',
prop: 'businessTypeId', prop: 'businessTypeId',
placeholder: '请选择业务类型', placeholder: '请选择业务类型',
options: businessTypeOptions, options: businessTypeOptions.map((item) => ({
label: item.planMajorName,
value: item.planMajorId,
})),
}, },
{ {
type: 'select', type: 'select',

View File

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

View File

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