hejianhao
2025-05-08 3a26073dd1aae27cdecb21d096b718c51e680526
接口
12个文件已修改
3个文件已添加
172 ■■■■ 已修改文件
culture/package.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/public/index.html 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/layouts/components/HeaderNav.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/layouts/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/main.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/router/index.js 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/utils/baseurl.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/utils/encryption.js 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/utils/request.js 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/utils/sm4.js 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/login/index.vue 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/login/service.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/projectList/index.vue 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/projectList/service.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/vue.config.js 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/package.json
@@ -17,6 +17,7 @@
    "core-js": "^3.41.0",
    "element-ui": "^2.15.6",
    "moment": "^2.30.1",
    "sm-crypto": "^0.3.13",
    "vue": "^2.7.16",
    "vue-router": "^3.6.5",
    "vuex": "^3.6.2"
culture/public/index.html
@@ -7,7 +7,7 @@
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <link rel="icon" href="<%= BASE_URL %>logo.jpg">
  <!-- <link rel="icon" href="data:,"> -->
  <title>实验室流程</title>
  <title>菌种库</title>
</head>
<body>
culture/src/layouts/components/HeaderNav.vue
@@ -57,7 +57,7 @@
    // 退出登录
    outLogin() {
      sessionStorage.clear()
      this.$router.replace({ path: "/" });
      this.$router.replace({ path: "/login" });
    },
    // 关闭标签
    closeTag(tag) {
culture/src/layouts/index.vue
@@ -9,7 +9,7 @@
            <div class="image">
              <img src="../assets/logo.jpg" alt="" srcset="" />
            </div>
            <div class="title">实验室流程</div>
            <div class="title">菌种库</div>
          </div>
          <!-- 左侧菜单 -->
          <div v-if="!isFold" class="sidebar-container">
culture/src/main.js
@@ -14,6 +14,7 @@
import "aieditor/dist/style.css"
import './assets/tailwind.css'
import './styles/element-variables.less'
import { fetchEncryptionKey } from './utils/encryption'
Vue.config.productionTip = false;
Vue.use(ElementUI, { size: 'small' })
@@ -62,6 +63,9 @@
  return height
}
// 获取加密密钥
// fetchEncryptionKey()
new Vue({
  router,
  store,
culture/src/router/index.js
@@ -584,17 +584,17 @@
    document.title = to.meta.title || '实验室流程';
    // 登录验证
    // if (to.path === "/login") {
    //     sessionStorage.removeItem('userInfo')
    //     next()
    // } else if (!sessionStorage.getItem('userInfo')) {
    //     next('/login')
    // } else {
    //     // 判断是否拥有要跳转菜单权限
    //     let menus = store.state.menus
    //     if (to.meta.hasOwnProperty('privilege') && !menus.includes(to.meta.privilege)) {
    //         return
    //     }
    if (to.path === "/login") {
        sessionStorage.clear();
        next()
    } else if (!sessionStorage.getItem('token')) {
        next('/login')
    } else {
        // 判断是否拥有要跳转菜单权限
        let menus = store.state.menus
        if (to.meta.hasOwnProperty('privilege') && !menus.includes(to.meta.privilege)) {
            return
        }
    // 设置标签列表
    if (!to.meta.hide || !to.meta.oneself) {
@@ -627,7 +627,7 @@
    }
    next()
    // }
    }
});
export default router;
culture/src/utils/baseurl.js
@@ -1,7 +1,7 @@
const apiConfig = {
    // 开发环境
    development: {
        baseURL: "",
        baseURL: "http://192.168.110.34:8081",
        imgUrl: "",
    },
    // 生产环境
culture/src/utils/encryption.js
New file
@@ -0,0 +1,34 @@
import axios from 'axios'
import apiConfig from './baseurl'
let encryptionKey = '2022lab02ora12to' // 默认密钥
// 从接口获取密钥
export const fetchEncryptionKey = async () => {
    try {
        const response = await axios.get(`${apiConfig.baseURL}/api/system/getEncryptionKey`)
        if (response.data && response.data.code === 200) {
            // 转换为Buffer并验证字节长度
            const keyBuffer = Buffer.from(response.data.data, 'utf-8')
            if (keyBuffer.length !== 16) {
                console.warn('无效密钥长度,使用默认密钥')
                return encryptionKey // 保持原有密钥
            }
            // 存储原始字符串和Buffer两种格式
            encryptionKey = response.data.data
            return encryptionKey
        }
    } catch (error) {
        console.error('获取加密密钥失败:', error)
    }
}
// 新增方法获取Buffer格式的密钥
export const getEncryptionKeyBuffer = () => {
    return Buffer.from(encryptionKey, 'utf-8')
}
// 获取当前密钥(保持字符串格式)
export const getEncryptionKey = () => encryptionKey
culture/src/utils/request.js
@@ -1,13 +1,10 @@
import axios from 'axios'
import apiConfig from './baseurl'
import {
  Message
} from 'element-ui'
import { Message } from 'element-ui'
import { encryptBySM4, decryptBySM4 } from './sm4'  // 添加decryptBySM4
const service = axios.create({
  baseURL: apiConfig.baseURL,
  // baseURL: apiConfig.baseURL,
  withCredentials: false, // 当跨域请求时发送cookie
  timeout: 30000, // request timeout
})
@@ -16,6 +13,10 @@
service.interceptors.request.use(
  config => {
    config['headers']['Authorization'] = `${sessionStorage.getItem('token')}`
    // 判断是否需要加密(只对/api开头的请求进行加密)
    const needEncrypt = config.url.startsWith('/api');
    if (config.method == 'get') {
      if (!config.params) config.params = {};
      config.params = {
@@ -24,8 +25,8 @@
    }
    if (config.method == 'post') {
      if (!config.data) config.data = {};
      config.data = {
        ...config.data,
      if (needEncrypt) {
        config.data = { param: encryptBySM4(config.data) };
      }
    }
    return config
@@ -42,11 +43,24 @@
      return
    }
    const res = response;
    // 新增解密处理:仅处理/api路径的POST响应
    if (res.config.method === 'post' && res.config.url.startsWith('/api')) {
      try {
        if (res.data && res.data.data) {
          // 这里假设使用decryptBySM4进行解密
          res.data.data = decryptBySM4(res.data.data);
        }
      } catch (e) {
        console.error('数据解密失败:', e);
      }
    }
    if (res.data.code == 200) {
      if (!res.data.data) {
      if (!res.data) {
        return Promise.resolve({})
      }
      return Promise.resolve(res.data.data)
      return Promise.resolve(res.data)
    } else {
      if (res.data.code == 103 || res.data.code == 401) {
        Message({
culture/src/utils/sm4.js
New file
@@ -0,0 +1,14 @@
import { sm4 } from 'sm-crypto';
import { getEncryptionKey, fetchEncryptionKey, getEncryptionKeyBuffer } from './encryption';
// SM4加密函数
export const encryptBySM4 = (data) => {
    const key = getEncryptionKeyBuffer(); // 获取当前密钥
    return sm4.encrypt(JSON.stringify(data), key);
};
// SM4解密函数
export const decryptBySM4 = (data) => {
    const key = getEncryptionKeyBuffer(); // 获取当前密钥
    return JSON.parse(sm4.decrypt(data, key));
};
culture/src/views/login/index.vue
@@ -11,7 +11,7 @@
      <div class="login-form">
        <div class="form-item flex">
          <img class="form-item-icon" :src="require('../../assets/login/account@2x.png')" alt="">
          <el-input v-model="loginForm.account" placeholder="请输入账号"></el-input>
          <el-input v-model="loginForm.username" placeholder="请输入账号"></el-input>
        </div>
        <div class="form-item flex mt-40">
@@ -28,6 +28,7 @@
  </div>
</template>
<script>
import { loginReq } from './service'
export default {
  name: 'Login',
  data() {
@@ -35,7 +36,7 @@
      windowWidth: window.innerWidth,
      loginForm: {
        account: '',
        username: '',
        password: ''
      },
      viewWidth: '',
@@ -78,8 +79,19 @@
      console.log(this.viewWidth)
    },
    login() {
      if (this.loginForm.username == '') {
        this.$message.warning('请输入账号')
        return
      }
      if (this.loginForm.password == '') {
        this.$message.warning('请输入密码')
        return
      }
      loginReq(this.loginForm).then(res => {
        sessionStorage.setItem('token', res.token)
        sessionStorage.setItem('userInfo', JSON.stringify(res.userInfo.user))
      this.$router.push('/')
      console.log(this.loginForm)
      })
    }
  }
}
culture/src/views/login/service.js
@@ -1,6 +1,6 @@
import axios from '@/utils/request';
// 登录
export const login = (data) => {
export const loginReq = (data) => {
    return axios.post('/login', { ...data })
}
culture/src/views/projectList/index.vue
@@ -3,16 +3,16 @@
        <TableCustom :queryForm="queryForm" :tableData="tableData" :total="total" @currentChange="handleCurrentChange"
            @sizeChange="handleSizeChange">
            <template #search>
                <el-form :model="form" label-width="140px" inline>
                <el-form label-width="140px" inline>
                    <el-form-item label="项目组名称:">
                        <el-input v-model="form.name" placeholder="请输入"></el-input>
                        <el-input v-model="queryForm.name" placeholder="请输入"></el-input>
                    </el-form-item>
                    <el-form-item label="项目负责人:">
                        <el-input v-model="form.name" placeholder="请输入"></el-input>
                        <el-input v-model="queryForm.name" placeholder="请输入"></el-input>
                    </el-form-item>
                    <el-form-item label="创建日期:">
                        <el-date-picker v-model="value1" type="daterange" range-separator="至" start-placeholder="开始日期"
                            end-placeholder="结束日期">
                        <el-date-picker v-model="queryForm.createdDate" type="daterange" range-separator="至"
                            start-placeholder="开始日期" end-placeholder="结束日期">
                        </el-date-picker>
                    </el-form-item>
                    <el-form-item class="search-btn-box">
@@ -54,13 +54,11 @@
</template>
<script>
import { getProjectList } from './service'
export default {
    name: 'ProjectList',
    data() {
        return {
            form: {
                name: ''
            },
            showDelConfirm: false,
            rowId: '',
            changeStatus: false,
@@ -73,6 +71,9 @@
            },
            total: 0
        }
    },
    created() {
        this.getList()
    },
    methods: {
        handleAddProject() {
@@ -113,7 +114,9 @@
            this.getList()
        },
        getList() {
            getProjectList(this.queryForm).then(res => {
                console.log(res);
            })
        }
    }
}
culture/src/views/projectList/service.js
New file
@@ -0,0 +1,6 @@
import axios from '@/utils/request';
// 列表
export const getProjectList = (data) => {
    return axios.post('/api/t-project-team/pageList', { ...data })
}
culture/vue.config.js
@@ -3,18 +3,18 @@
    return path.join(__dirname, dir)
}
module.exports = {
    outputDir: 'laboratory', // 配置打包后的文件夹名称
    outputDir: 'culture', // 配置打包后的文件夹名称
    lintOnSave: false,
    publicPath: '/',
    devServer: {
        disableHostCheck: true, //禁用主机检查 
        proxy: {
            "/api": { // 设置以什么前缀开头的请求用来代理
                target: "http://localhost:8080", //要访问的跨域的域名
                target: "http://192.168.110.34:8081", //要访问的跨域的域名
                secure: false, // 使用的是http协议则设置为false,https协议则设置为true
                changOrigin: true, //开启代理
                pathRewrite: {
                    "^/api": "",
                    "^/api": "/api",
                },
            },
        },