From b5f23e89d8536a4af882789010b76459c0283433 Mon Sep 17 00:00:00 2001 From: wangjy <1595161655@qq.com> Date: Thu, 10 Oct 2024 17:57:26 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E6=8E=A5=E5=8F=A3=E8=B0=83?= =?UTF-8?q?=E8=AF=95=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.development | 8 +- .env.test | 2 +- src/components/table.vue | 33 +++ src/router/routes.js | 2 +- src/stores/user.js | 26 +- src/utils/api.js | 28 ++- src/utils/request.js | 8 +- src/views/Login/Login.vue | 26 +- src/views/project/detail.vue | 474 ++++++++++++++++++++++++++--------- src/views/project/list.vue | 156 +++++++++--- vite.config.js | 11 - 11 files changed, 553 insertions(+), 221 deletions(-) diff --git a/.env.development b/.env.development index a4cb9d2..710fb84 100644 --- a/.env.development +++ b/.env.development @@ -1,6 +1,6 @@ VITE_BASE_URL = "./" -VITE_BASE_NAME = "external" -VITE_APP_PROXYURL = 'http://183.230.174.15:8088/external' -VITE_APP_REQUESTURL = '/external' -VITE_APP_ROUTERURL = '/external/' +VITE_BASE_NAME = "pms-front-test" +VITE_APP_PROXYURL = 'http://192.168.124.202:8080' +VITE_APP_REQUESTURL = '/pms-front-test' +VITE_APP_ROUTERURL = '/pms-front-test/' diff --git a/.env.test b/.env.test index 9013e48..707e773 100644 --- a/.env.test +++ b/.env.test @@ -1,5 +1,5 @@ VITE_BASE_URL = '/pms-front-test' VITE_BASE_NAME = "pms-front-test" -VITE_APP_PROXYURL = 'http://183.230.174.15:8093/aiops-external' +VITE_APP_PROXYURL = 'http://192.168.124.202:8080' VITE_APP_REQUESTURL = '/pms-front-test' VITE_APP_ROUTERURL = '/pms-front-test/' \ No newline at end of file diff --git a/src/components/table.vue b/src/components/table.vue index cf38883..32f8316 100644 --- a/src/components/table.vue +++ b/src/components/table.vue @@ -27,6 +27,13 @@ + @@ -160,4 +167,30 @@ onUnmounted(() => { display: flex; justify-content: flex-end; } +:deep(.el-scrollbar__wrap--hidden-default){ + min-height: 100px; +} + :deep(.el-table) { + --el-table-text-align: center; +} + + :deep(.el-table th) { + text-align: center; +} + + :deep(.el-table .cell) { + text-align: center; +} + +/* 如果操作列需要特殊处理,可以添加以下样式 */ + :deep(.operation-column .cell) { + text-align: center; + display: flex; + justify-content: center; +} +:deep(.el-table__inner-wrapper::before){ + + display: none; + +} diff --git a/src/router/routes.js b/src/router/routes.js index 6eaf732..27cc19a 100644 --- a/src/router/routes.js +++ b/src/router/routes.js @@ -108,7 +108,7 @@ export const asyncRoutes = [ name: 'worklogList', authKey: 'Workorder', meta: { - title: '日志列表', + title: '工作日志', }, component: () => import('@/views/workLog/list.vue'), }, diff --git a/src/stores/user.js b/src/stores/user.js index e466a69..6002ddb 100644 --- a/src/stores/user.js +++ b/src/stores/user.js @@ -25,22 +25,10 @@ export const useUserStore = defineStore('user', { async login(params) { try { const res = await loginApi.login(params) - const roleType = res.data.user.roles - .filter(item => item.roleType) - .map(per => per.roleType) - .join(',') - // setPerssionsTabbar(roleType) - const roleKey = res.data.user.roles - .filter(item => item.roleKey) - .map(per => per.roleKey) - .join(',') - sessionStorage.setItem('roleType', $utils.encryptByDES.CBC(roleType)) - sessionStorage.setItem('roleKey', $utils.encryptByDES.CBC(roleKey)) - const token = $utils.encryptByMD5(`123456`) - setToken(token) - await this.updateUserInfo(res.data) + setToken(res.token) + await this.updateUserInfo() ElMessage.success({ message: '登录成功' }) - const permissions = [...res.data.resourceKeys] + const permissions = [...this.userInfo.permissions] // , 'WorkOrderError', 'workOrderDestroy', 'workOrderReserver' sessionStorage.setItem('permissions', $utils.encryptByDES.CBC(JSON.stringify(permissions))) this.updateAsyncRoutes() @@ -56,8 +44,8 @@ export const useUserStore = defineStore('user', { removeToken() router.push('/') }, - async updateUserInfo(data) { - const userInfo = data.user + async updateUserInfo() { + const userInfo = await loginApi.getUserInfo() sessionStorage.setItem('userInfo', $utils.encryptByDES.CBC(JSON.stringify(userInfo))) this.userInfo = userInfo }, @@ -67,8 +55,8 @@ export const useUserStore = defineStore('user', { updateAsyncRoutes() { // 权限时处理异步路由 let sessionPermissions = JSON.parse($utils.decryptByDES.CBC(sessionStorage.getItem('permissions'))) - // console.log(asyncRoutes, sessionPermissions, 'asyncRoutes, sessionPermissions') - let result = filterAsyncRoutes(asyncRoutes, sessionPermissions) + // let result = filterAsyncRoutes(asyncRoutes, sessionPermissions) + let result = asyncRoutes result = editRedirect(result) // console.log(result, 'result') diff --git a/src/utils/api.js b/src/utils/api.js index 7e431b9..791e77e 100644 --- a/src/utils/api.js +++ b/src/utils/api.js @@ -1,14 +1,37 @@ import request from '@/utils/request' - //登录板块api export const loginApi = { // 登录 - login: data => request('/login', 'post', data), + login: data => request('/login', 'json', data), // 退出登录 loginOut: () => request('/aiops-api/logout', 'get'), //修改密码 editPassword: data => request('/aiops-api/auth/user/updatePwd', 'post', data), + // 获取验证码 + getCode: () => request('/captchaImage', 'captchaImage', {}, { + SHOW_LOADING: false, headers: { + 'Content-Type': 'application/json' + } + }), + getUserInfo: () => request('/getInfo', 'get'), } + +// 项目板块 +export const projectApi = { + // 查询项目列表 + listProject: query => request('/business/project/list', 'get', query), + deleteProject: id => request(`/business/project/${id}`, 'delete'), + addProject: data => request('/business/project/add', 'json', data), + updateProject: data => request('/business/project/update', 'json', data), + getProjectCode: () => request('/business/project/getCode', 'get'), + getProjectDetail: id => request(`/business/project/info/${id}`, 'get'), + // 项目成员 + getProjectUser: id => request(`/business/project/${id}`, 'get'), + updateProjectUser: data => request('/business/project/team', 'json', data), + deleteProjectUser: id => request(`/business/project/team/${id}`, 'delete'), +} + +// 用户板块 export const useUserApi = () => { @@ -16,6 +39,7 @@ export const useUserApi = () => { // 系统板块 export const systemApi = { getUserList: data => request('/aiops-api/auth/user/list', 'post', data), + getDictData: dictCode => request('/system/dict/data/type/' + dictCode, 'get'), } // 系统定时任务 export const systemJobApi = { diff --git a/src/utils/request.js b/src/utils/request.js index e11bf35..bee06db 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -17,7 +17,7 @@ const service = axios.create({ service.interceptors.request.use( config => { if (getToken()) { - config.headers['token'] = getToken() + config.headers['Authorization'] = 'Bearer ' + getToken() } return config }, @@ -105,6 +105,9 @@ const doRequest = (url, method = 'GET', params, opts, callback) => { method = 'POST' opts.headers['Content-Type'] = 'application/json' opts.responseType = 'blob' + }else if (/captchaImage/i.test(method)) { + method = 'get' + opts.headers['Content-Type'] = 'application/json' } service({ url: url, @@ -156,7 +159,7 @@ const doRequest = (url, method = 'GET', params, opts, callback) => { opts.SHOW_LOADING && loadingInstance && loadingInstance.close() return } - if (res.code === 0) { + if (res.code === 200) { resolve(res) // // resolve(res.data) } else if (res.code === 401) { @@ -175,7 +178,6 @@ const doRequest = (url, method = 'GET', params, opts, callback) => { opts.SHOW_LOADING && loadingInstance && loadingInstance.close() }) .catch(err => { - console.log('ssss') opts.SHOW_LOADING && loadingInstance && loadingInstance.close() if (err.code === 'ERR_CANCELED') return ElMessage.error({ diff --git a/src/views/Login/Login.vue b/src/views/Login/Login.vue index 44f16d2..56df71d 100644 --- a/src/views/Login/Login.vue +++ b/src/views/Login/Login.vue @@ -73,6 +73,7 @@ import { ElMessage } from 'element-plus' import { reactive, ref } from 'vue' import { useRouter } from 'vue-router' +import { loginApi } from '@/utils/api' import { useUserStore } from '@/stores/user' import { storeToRefs } from 'pinia' const userStore = useUserStore() @@ -82,23 +83,14 @@ const login = reactive({ pwd: '', validateCode: '', }) -const codeSrc = ref( - process.env.NODE_ENV === 'production' - ? `${window.location.origin}${ - import.meta.env.VITE_APP_REQUESTURL - }/captcha/captchaImage?type=math&&t=${Math.random()}` - : `${import.meta.env.VITE_APP_REQUESTURL}/captcha/captchaImage?type=math`, -) //${window.location.origin} +const codeSrc = ref() +const uuid = ref() const updateCode = async () => { - codeSrc.value = - process.env.NODE_ENV === 'production' - ? `${window.location.origin}${ - import.meta.env.VITE_APP_REQUESTURL - }/captcha/captchaImage?type=math&&t=${Math.random()}` - : `${import.meta.env.VITE_APP_REQUESTURL}/captcha/captchaImage?type=math&&t=${Math.random()}` //char math + const res = await loginApi.getCode() + codeSrc.value = 'data:image/png;base64,' + res.img + uuid.value = res.uuid } -// getCode() const confirmLogin = async () => { if (!login.account) { ElMessage.error({ message: `用户名不能为空!` }) @@ -113,9 +105,10 @@ const confirmLogin = async () => { return } const params = { - password: $utils.encryptByMD5(`${login.account}${login.pwd}`), + password: login.pwd, username: login.account, - validateCode: login.validateCode, + code: login.validateCode, + uuid: uuid.value, } try { await userStore.login(params) @@ -127,6 +120,7 @@ const confirmLogin = async () => { const usershadow = ref(false) const shadow = ref(false) const codeShadow = ref(false) +updateCode() \ No newline at end of file + diff --git a/src/views/project/list.vue b/src/views/project/list.vue index daa1547..e34e0c5 100644 --- a/src/views/project/list.vue +++ b/src/views/project/list.vue @@ -6,16 +6,19 @@ - - - - + + - - - - + + + + @@ -64,6 +67,15 @@ + + + @@ -71,26 +83,68 @@ import { ref, reactive, onMounted } from 'vue' import { useRouter } from 'vue-router' import CustomTable from '@/components/table.vue' +import SelectUser from '@/components/selectUser.vue' import { WarningFilled } from '@element-plus/icons-vue' +import { projectApi } from '@/utils/api' const router = useRouter() const searchForm = reactive({ projectName: '', - manager: '', - status: '', + projectLeaderName: '', + projectLeader: '', + projectState: '', }) const columns = [ { prop: 'projectName', label: '项目名称' }, { prop: 'projectCode', label: '项目编号' }, - { prop: 'manager', label: '负责人' }, - { prop: 'budgetDays', label: '预计工时(天)' }, - { prop: 'startDate', label: '开始时间' }, - { prop: 'endDate', label: '结束时间' }, - { prop: 'status', label: '项目状态' }, - { prop: 'memberCount', label: '参与项目人数' }, - { prop: 'createdBy', label: '项目创建人' }, + { prop: 'projectLeaderName', label: '负责人' }, + { prop: 'budgetDate', label: '预计工时(天)' }, + { + prop: 'startDate', + label: '开始时间', + type: 'status', + callback: (data, row) => { + return data.split(' ')[0] + }, + }, + { + prop: 'endDate', + label: '结束时间', + type: 'status', + callback: (data, row) => { + return data.split(' ')[0] + }, + }, + { + prop: 'projectState', + label: '项目状态', + type: 'status', + callback: (value, row) => { + let status = '未知' + let color = '' + + switch (value) { + case '0': + status = '未启动' + color = '#909399' // 灰色 + break + case '1': + status = '进行中' + color = '#409EFF' // 蓝色 + break + case '2': + status = '已完成' + color = '#67C23A' // 绿色 + break + } + + return `${status}` + }, + }, + { prop: 'teamNum', label: '参与项目人数' }, + { prop: 'createByName', label: '项目创建人' }, { prop: 'operation', label: '操作', @@ -105,6 +159,35 @@ const total = ref(0) const deleteDialogVisible = ref(false) const currentDeleteItem = ref(null) +const pageNum = ref(1) +const pageSize = ref(10) + +// 用户选择相关 +const userSelectDialogVisible = ref(false) +const currentSelectedUser = ref([]) + +const openUserSelectDialog = () => { + userSelectDialogVisible.value = true +} + +const handleUserSelectClose = () => { + userSelectDialogVisible.value = false +} + +const handleUserConfirm = (selectedUsers) => { + if (selectedUsers.length > 0) { + const selectedUser = selectedUsers[0] + searchForm.projectLeaderName = selectedUser.name + searchForm.projectLeader = selectedUser.id + currentSelectedUser.value = [selectedUser] + } else { + searchForm.projectLeaderName = '' + searchForm.projectLeader = '' + currentSelectedUser.value = [] + } + userSelectDialogVisible.value = false +} + const onSearch = () => { // 实现搜索逻辑 console.log('Search with:', searchForm) @@ -125,7 +208,7 @@ const addProject = () => { const handleEdit = row => { router.push({ path: '/project/detail', - query: { id: row.id }, + query: { id: row.projectId }, state: { projectData: row }, }) } @@ -140,42 +223,35 @@ const handleCloseDeleteDialog = () => { currentDeleteItem.value = null } -const confirmDelete = () => { +const confirmDelete = async () => { // 实现删除逻辑 - console.log('Delete project:', currentDeleteItem.value) + await projectApi.deleteProject(currentDeleteItem.value.projectId) deleteDialogVisible.value = false currentDeleteItem.value = null + ElMessage.success('删除成功') fetchProjectList() } const handleSizeChange = val => { - console.log(`每页 ${val} 条`) + pageSize.value = val + pageNum.value = 1 // 重置为第一页 fetchProjectList() } const handleCurrentChange = val => { - console.log(`当前页: ${val}`) + pageNum.value = val fetchProjectList() } -const fetchProjectList = () => { +const fetchProjectList = async () => { // 这里使用假数据,实际应该调用API - const fakeData = Array(20) - .fill(null) - .map((_, index) => ({ - id: index + 1, - projectName: `项目${index + 1}`, - projectCode: `XM00${index + 1}`, - manager: ['张三', '李四', '王五'][index % 3], - budgetDays: Math.floor(Math.random() * 100) + 10, - startDate: '2024-08-31', - endDate: '2024-09-15', - status: ['待启动', '进行中', '已完成'][index % 3], - memberCount: Math.floor(Math.random() * 10) + 3, - createdBy: '张三', - })) - tableData.value = fakeData - total.value = fakeData.length + const res = await projectApi.listProject({ + ...searchForm, + pageNum: pageNum.value, + pageSize: pageSize.value, + }) + tableData.value = res.rows + total.value = res.total } onMounted(() => { @@ -278,4 +354,4 @@ onMounted(() => { left: 50%; transform: translate(-50%, -50%); } - + \ No newline at end of file diff --git a/vite.config.js b/vite.config.js index b5f9299..376fca1 100644 --- a/vite.config.js +++ b/vite.config.js @@ -60,17 +60,6 @@ export default ({ mode }) => { }, // 设置代理 proxy: { - '/upload': { - target: 'http://111.10.228.245:8088/external', - changeOrigin: true, - secure: false, - rewrite: path => path.replace('/upload/', '/upload/'), - }, - '/aiopsfile': { - target: 'http://111.10.228.245:8088/external', - changeOrigin: true, - secure: false, - }, [env.VITE_APP_REQUESTURL]: { target: env.VITE_APP_PROXYURL,