宝塔面板部署前后端分离项目项目踩到的坑

宝塔面板部署前后端分离项目项目踩到的坑

项目模式采用了前后端分离的模式。前端是使用iview前端框架,使用的是iview-admin框架。后台使用的是thinkPHP5的PHP框架。
跨域是通过后台解决的。

1.部署后台项目

首先打开宝塔面板输入账号和密码进行登陆。宝塔面板默认安装的目录是在/www下,网站根目录则是/www/wwwroot。安装宝塔面板时已经默认生成好了面板访问地址、用户名和账号。
在这里插入图片描述
所以我们上传的项目基本存放在/www/wwwroot下。在此之前,我们需要创建好后台项目需要用到的数据库。

1.1创建数据库

选择数据库,点击添加数据库按钮
在这里插入图片描述
在弹出数据库添加表单中填写类似如下信息
在这里插入图片描述
默认会生成一个这个数据库指定的用户和用户密码,这个基本上没什么用户只是数据库权限问题。在tp项目中直接配置的数据库全局用户root也可以正常访问这个数据库。

1.2上传代码文件

上传项目源代码文件目录
点击文件,首先需要新建一个目录来存放项目前端和后台文件。例如这里新建了2020JianKongServer这个目录

在这里插入图片描述
点击进入2020JianKongServer目录,点击上传按钮,选择上传目录,就可以将整个项目源代码文件上传
在这里插入图片描述
这里上传好了后台代码文件夹

在这里插入图片描述
接下来,我们还需要对项目中的数据库配置改换为服务器数据库的配置
打开TP项目数据配置文件(/www/wwwroot/2020JianKongServer/admin/application)database.php文件,双击文件进行编辑,配置如下
在这里插入图片描述

1.3创建站点

然后创建站点,其实相当于配置web服务器的虚拟机。选择网站,创建站点让外界能访问后台接口
在这里插入图片描述
然后TP项目还需要配置站点伪静态,点击设置按钮
在这里插入图片描述
在弹出的设置弹窗中,选择伪静态,点击选择下拉框,可以看到有thinkPHP选项,选中该选项,
在这里插入图片描述

之后就会在文本域中输入配置信息。点击保存即可
在这里插入图片描述
千万不要忘记重启站点
在这里插入图片描述

1.4验证部署是否成功

验证后台项目是否正常访问,在浏览器中输入站点地址进行访问
如果出现如下结果,则说名接口可以正常访问
在这里插入图片描述
后台接口出入安全考虑,可以对其进行进行安全组设置。

2.部署前端项目

2.1打包项目代码

打包前需要将src/config/index.js中的将请求后台的路径进行修改

baseUrl: {
    dev: 'https://produce.com/',
    pro: 'http://XXXXX:9003'
  },

打开命令行终端,在项目路径下执行命令npm run build进行打包。
打包成功之后项目中多出dist目录。这个目录可以自定义命名。

2.2上传代码文件

将打包生成的文件夹(默认生成的是dist文件夹)上传到服务器中。上传步骤和部署后台项目一致。

2.3创建站点

选择网站,创建站点让外界能访问项目界面
在这里插入图片描述
由于vue项目的路由模式如果是history的话,需要web服务器进行相应的配置,否则刷新界面的时候将会报404的错误。这里的web服务器是Nginx。宝塔面板中的Nginx配置文件在/www/server/nginx/conf中
在这里插入图片描述
打开nginx.conf文件,可以看到里面导入宝塔面板Nginx所有的.conf后缀的文件配置


...

server
    {
        listen 888;
        server_name phpmyadmin;
        index index.html index.htm index.php;
        root  /www/server/phpmyadmin;
            location ~ /tmp/ {
                return 403;
            }

        #error_page   404   /404.html;
        include enable-php.conf;

        location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
        {
            expires      30d;
        }

        location ~ .*\.(js|css)?$
        {
            expires      12h;
        }

        location ~ /\.
        {
            deny all;
        }

        access_log  /www/wwwlogs/access.log;
    }
include /www/server/panel/vhost/nginx/*.conf;
}

在这种情况下,所以应该在宝塔面板中修改相应站点的配置。
在这里插入图片描述
将配置内容拉倒最下方,将
location / {
try_files $uri $uri/ /index.html;
}
加入到配置内容中
在这里插入图片描述
点击保存即可,千万别忘记重启站点,否则配置将不会起效。这样就解决刷新报错404的问题。

2.4验证部署是否成功

在浏览器中输入站点进行访问到正常系统界面,则说明部署成功。

2.5遇到问题

1.报错XMLHttpRequest:对预检请求的响应未通过访问控制检查: 没有HTTP正常状态
报错如下:

Access to XMLHttpRequest at http://xxx.xxx from origin 'http://localhost:8000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.

刚开始以为是跨域问题,然后在本地访问服务器上接口的时候又没有报跨域问题,在本地又是可以正常请求的,但是部署服务器上就是不行报错,在network里面打开报错的接口login。返回的结果说是后台不存在login模块(由于测试部署直接没有写登陆模块)。然后终于想到引起问题的原因了,首先说本地为何成功?由于登陆是请求后台登陆的接口已经被mock拦截了返回了token和登陆用户信息,但是打包之后,mock模块将不起作用了。所以登陆操作将请求后台接口,然而后台没有做登陆模块的接口,所以报错500的错误。那么如何跳过登陆呢,
捋一下前端的登陆思路,在不要发起对后台登陆接口的操作。
这里看一下router中的index,js


...

router.beforeEach((to, from, next) => {
  iView.LoadingBar.start()
  const token = getToken()

  // console.log("路由跳转钱",token,to.name)
  if (!token && to.name !== LOGIN_PAGE_NAME) {
    // 未登录且要跳转的页面不是登录页
    next({
      name: LOGIN_PAGE_NAME // 跳转到登录页
    })
  } else if (!token && to.name === LOGIN_PAGE_NAME) {
    // 未登陆且要跳转的页面是登录页
    next() // 跳转
  } else if (token && to.name === LOGIN_PAGE_NAME) {
    // 已登录且要跳转的页面是登录页
    next({
      name: homeName // 跳转到homeName页
    })
  } else {
    if (store.state.user.hasGetInfo) {
      turnTo(to, store.state.user.access, next)
    } else {
      store.dispatch('getUserInfo').then(user => {
        // 拉取用户信息,通过用户权限和跳转的页面的name来判断是否有权限访问;access必须是一个数组,如:['super_admin'] ['super_admin', 'admin']
        turnTo(to, user.access, next)
      }).catch(() => {
        setToken('')
        next({
          name: 'login'
        })
      })
    }
  }
})

...

以看出router每次跳转前都需要进行验证是否登陆操作。
然后登陆操作用到了store里面的方法,然后是在store的module里面的user,js中
在这里插入图片描述
那么需要对handleLogin、handleLogOut、getUserInfo等进行修改,修改如下:

// 登录
handleLogin ({ commit }, { userName, password }) {
  userName = userName.trim()
  return new Promise((resolve, reject) => {
    commit('setToken', 'super_admin')
    resolve()
  })
},

// 退出登录
handleLogOut ({ state, commit }) {
  return new Promise((resolve, reject) => {
    // 如果你的退出登录无需请求接口,则可以直接使用下面三行代码而无需使用logout调用接口
    commit('setToken', '')
    commit('setAccess', [])
    resolve()
  })
},

// 获取用户相关信息
getUserInfo ({ state, commit }) {
  return new Promise((resolve, reject) => {
    try {
    //根据mock中返回的用户信息来修改
      const USER_MAP = {
        super_admin: {
          name: 'super_admin',
          user_id: '1',
          access: ['super_admin', 'admin'],
          token: 'super_admin',
          avatar: 'https://file.iviewui.com/dist/a0e88e83800f138b94d2414621bd9704.png'
        },
        admin: {
          name: 'admin',
          user_id: '2',
          access: ['admin'],
          token: 'admin',
          avatar: 'https://avatars0.githubusercontent.com/u/20942571?s=460&v=4'
        }
      }
      const data = USER_MAP[state.token];
      commit('setAvatar', data.avatar)
      commit('setUserName', data.name)
      commit('setUserId', data.user_id)
      commit('setAccess', data.access)
      commit('setHasGetInfo', true)
      resolve(data)
    } catch (error) {
      reject(error)
    }
  })
},

则再次打包进行部署之后,这样的问题就没了。

猜你喜欢

转载自blog.csdn.net/qq_23257451/article/details/115531648