🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
1. 官方文档地址: ​ ThinkPHP6.0:[https://www.kancloud.cn/manual/thinkphp6\_0/1037479](https://www.kancloud.cn/manual/thinkphp6_0/1037479) ​ ElemetUI:[https://element.eleme.cn/#/zh-CN](https://element.eleme.cn/#/zh-CN) ​ axios:[https://www.kancloud.cn/yunye/axios/234845](https://www.kancloud.cn/yunye/axios/234845) ​ Vue:[https://cn.vuejs.org/v2/guide](https://cn.vuejs.org/v2/guide) 2. 创建码云仓库 3. 克隆到本地 ~~~linux git clone 你自己的仓库地址 0608 ~~~ 4. 创建数据库 ~~~sql -- 创建数据库 0608 create database `0608` charset utf8; -- 创建数据表 user create table `user` ( `id` int(11) primary key auto_increment comment '用户ID', `name` varchar(30) not null default '未知' comment '用户名', `pwd` varchar(32) not null default '未知' comment '用户密码' ) engine = InnoDB; -- 给 user.name 添加唯一索引 alter table `user` add unique key u_name(`name`); -- 给 user.pwd 添加普通索引 alter table `user` add index u_pwd(`pwd`); -- 创建数据表 school create table `school` ( `id` int(11) primary key auto_increment comment '学校ID', `name` varchar(30) not null default '未知' comment '学校名', `city` varchar(30) not null default '未知' comment '学校城市', `num` varchar(30) not null default '0' comment '学校人数' ) engine = InnoDB; ~~~ 5. 进入项目 ~~~linux cd 0608 ~~~ 6. 安装ThinkPHP6.0 ~~~linux composer create-project topthink/think php ~~~ 7. 配置域名/URL重写 ~~~nginx # 自行去配置域名 # url 重写 location / { # 省略部分代码 if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s=/$1 last; } } ~~~ 8. 修改配置文件 .env 【来源于项目中的 .example.env】 ~~~php APP_DEBUG = true [APP] DEFAULT_TIMEZONE = Asia/Shanghai [DATABASE] TYPE = mysql HOSTNAME = 127.0.0.1 DATABASE = 0608 USERNAME = root PASSWORD = root HOSTPORT = 3306 CHARSET = utf8 DEBUG = true [LANG] default_lang = zh-cn ~~~ 9. 开启错误调试模式 ~~~php // 1 .env 文件中第 1 行 APP_DEBUG = true // 2 config/app.php 中第 33 行 'show_error_msg' => true ~~~ 10. 初始化vue 查看node、npm、cnpm、vue-cli是否安装成功 ~~~js // 查看 node 版本 node -v // 查看 npm 版本 npm -v // 查看 cnpm 版本 cnpm -v // 查看 vue 版本 vue -V // 初始化项目 vue init webpack vue ~~~ 11. 进入vue进行测试、查看是否安装成功 ~~~js // 进入 vue 项目中 cd vue // npm 启动项目 npm run dev ~~~ 12. 安装 Element-UI、axios ~~~js // 安装 ElementUI cnpm install element-ui --save // 安装 axios cnpm install axios --save ~~~ 13. 在 vue/src/main.js 中增加以下内容 ~~~js // 引入 elementUI // https://element.eleme.cn/#/zh-CN/component/quickstart import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; Vue.use(ElementUI); // 引入 axios // https://segmentfault.com/a/1190000013128858 import axios from 'axios' Vue.prototype.$ajax = axios ~~~ 14. 将初始化好的项目提交到远程仓库 ~~~js // 进入项目中 cd 0608 // 查看状态【红色、提示使用 git add 】 git status // 添加代码到仓库 git add ./ // 查看状态【绿色、Changes to be committed:】 git status // 提交代码到本地仓库 git commit -m '提交注释' // 查看状态 git status // 将远程仓库的更新拉取到本地 git pull // 查看状态 git status // 将本地的更新提交到远程仓库 git push ~~~ 15. 添加资源控制器/模型层/资源路由 ~~~php // 使用命令行:创建资源控制器 php think make:controller School // 使用命令行:创建模型 php think make:model School // 添加资源路由 php/route/app.php // 跨域请求【路由->跨域请求】 Route::resource('school', 'School')->allowCrossDomain(); ~~~ 16. 编辑 curd 接口 - 控制器 - School.php ~~~php <?php declare(strict_types=1); namespace app\controller; use app\model\School as ModelSchool; use think\facade\Validate; use think\Request; class School { /** * 显示资源列表 * 【get】http://0608.cc/school * 【get】http://0608.cc/school?page=2 * * @return \think\Response */ public function index(ModelSchool $school) { $pageSize = 3; $res = $school->getPage($pageSize); if ($res) { return json(['code' => 0, 'msg' => 'ok', 'res' => $res]); } else { return json(['code' => 1, 'msg' => 'no', 'res' => null]); } } /** * 显示创建资源表单页. * * @return \think\Response */ public function create() { // } /** * 保存新建的资源 * 【post】http://0608.cc/school?name=shbw&city=&num=10000 * * @param \think\Request $request * @return \think\Response */ public function save(Request $request, ModelSchool $school) { // 接收数据 $data['name'] = $request->param('name', ''); $data['city'] = $request->param('city', ''); $data['num'] = $request->param('num', '0'); // 数据验证 $rule = [ 'name' => 'require|max:30|min:2', 'city' => 'require', 'num' => 'require' ]; $message = [ 'name.require' => '学校名称是必填项', 'name.max' => '学校名称最多30位', 'name.min' => '学校名称最少2位', 'city.require' => '学校所在城市是必填项', 'num.require' => '学校现有人数是必填项' ]; // 粘贴来自于手册:验证->验证规则->方法定义 $validate = Validate::rule($rule)->message($message); if (!$validate->check($data)) { return json(['code' => 1, 'msg' => $validate->getError(), 'res' => null]); } // 调用模型 $res = $school->addOne($data); if ($res) { return json(['code' => 0, 'msg' => '添加成功', 'res' => $res]); } else { return json(['code' => 1, 'msg' => '添加失败', 'res' => $res]); } } /** * 显示指定的资源 * 【get】http://0608.cc/school/3 * * @param int $id * @return \think\Response */ public function read($id, ModelSchool $school ) { $where['id'] = $id; $res = $school->selOne($where); if ($res) { return json(['code' => 0, 'msg' => '查询成功', 'res' => $res]); } else { return json(['code' => 1, 'msg' => '查询失败', 'res' => $res]); } } /** * 显示编辑资源表单页. * * @param int $id * @return \think\Response */ public function edit($id) { // } /** * 保存更新的资源 * 【put】http://0608.cc/school/3?name=bjbw3&city=bj3&num=30000 * * @param \think\Request $request * @param int $id * @return \think\Response */ public function update(Request $request, $id, ModelSchool $school) { // 接收数据 $where['id'] = $id; $data['name'] = $request->param('name', ''); $data['city'] = $request->param('city', ''); $data['num'] = $request->param('num', '0'); // 数据验证 $rule = [ 'name' => 'require|max:30|min:2', 'city' => 'require', 'num' => 'require' ]; $message = [ 'name.require' => '学校名称是必填项', 'name.max' => '学校名称最多30位', 'name.min' => '学校名称最少2位', 'city.require' => '学校所在城市是必填项', 'num.require' => '学校现有人数是必填项' ]; // 粘贴来自于手册:验证->验证规则->方法定义 $validate = Validate::rule($rule)->message($message); if (!$validate->check($data)) { return json(['code' => 1, 'msg' => $validate->getError(), 'res' => null]); } // 调用模型 $res = $school->updOne($where, $data); if ($res) { return json(['code' => 0, 'msg' => '修改成功', 'res' => $res]); } else { return json(['code' => 1, 'msg' => '修改失败', 'res' => $res]); } } /** * 删除指定资源 * 【delete】http://0608.cc/school/1 * * @param int $id * @return \think\Response */ public function delete($id, ModelSchool $school) { $where['id'] = $id; $res = $school->delOne($where); if ($res) { return json(['code' => 0, 'msg' => '删除成功', 'res' => $res]); } else { return json(['code' => 1, 'msg' => '删除失败', 'res' => $res]); } } } ~~~ 17. 编辑 curd 接口 - 模型层 - School.php ~~~php <?php declare (strict_types = 1); namespace app\model; use think\Model; /** * @mixin think\Model */ class School extends Model { protected $table = 'school'; protected $pk = 'id'; // 设置字段信息 protected $schema = [ 'id' => 'int', 'name' => 'string', 'city' => 'string', 'num' => 'string' ]; /** * 分页 */ public function getPage( $pageSize) { return self::paginate( $pageSize ); } /** * 添加一条数据 */ public function addOne($data) { return self::insert( $data ); } /** * 删除数据 */ public function delOne($where) { return self::where( $where )->delete(); } /** * 修改 */ public function updOne($where,$data) { return self::where( $where )->update( $data ); } /** * 查询一条 */ public function selOne($where) { return self::where( $where )->find(); } } ~~~ 18. 使用Postman测试 curd 接口 ~~~php # 展示/分页 get http://0608.cc/school http://0608.cc/school?page=2 # 添加 post http://0608.cc/school?name=shbw&city=&num=10000 # 根据 ID 查询一个 get http://0608.cc/school/3 # 修改 put http://0608.cc/school/3?name=shbw&city=&num=10000 # 删除 delete http://0608.cc/school/1 ~~~ 19. Vue中添加路由/页面 ~~~js // 在 vue/src/ 中增加 page/school/{ list.vue,add.vue } // 增加路由 vue/router/index.js import Vue from 'vue' import Router from 'vue-router' import HelloWorld from '@/components/HelloWorld' // 导入登录页面 import login from '@/page/main/login.vue' // 导入以下页面 import schoolList from '@/page/school/list.vue' import schoolAdd from '@/page/school/add.vue' import schoolEdit from '@/page/school/edit.vue' Vue.use(Router) export default new Router({ routes: [{ path: '/', name: 'HelloWorld', component: HelloWorld }, { path: '/login', name: 'login', component: login }, { path: '/schoolList', name: 'schoolList', component: schoolList }, { path: '/schoolAdd', name: 'schoolAdd', component: schoolAdd }, { path: '/schoolEdit', name: 'schoolEdit', component: schoolEdit } ] }) ~~~ 20. 展示页面 - list.vue ~~~vue <template> <div> <a href="/#/schoolAdd"><el-button type="button" size="small" style="float: left;">数据添加</el-button></a> <!-- 展示表格 start https://element.eleme.cn/#/zh-CN/component/table --> <el-table :data="tableData" stripe style="width: 100%"> <el-table-column prop="id" label="ID" width="150"></el-table-column> <el-table-column prop="name" label="学校名" width="150"></el-table-column> <el-table-column prop="city" label="所在城市" width="150"></el-table-column> <el-table-column prop="num" label="人数" width="150"></el-table-column> <el-table-column label="操作"> <template slot-scope="scope"> <el-button @click.native.prevent="deleteRow(scope.row)" type="text" size="small">删除</el-button> <el-button @click.native.prevent="editRow(scope.row)" type="text" size="small">编辑</el-button> </template> </el-table-column> </el-table> <!-- 展示表格 end --> <!-- 分页控件 start https://element.eleme.cn/#/zh-CN/component/pagination --> <el-pagination background layout="prev, pager, next" :total="total" :page-size="pageSize" @current-change="getCurrentPage"></el-pagination> <!-- 分页控件 end --> </div> </template> <script> export default { data() { return { tableData: [], currentPage: 1, total: 0, pageSize: 3 }; }, created() { var _self = this; _self.getPage(); }, methods: { // 调用接口、获取分页数据 getPage: function() { var _self = this; // 使用 ajax 请求后台提供的展示接口 _self.$ajax .get('http://0608.cc/school', { params: { page: _self.currentPage } }) .then(function(response) { _self.tableData = response.data.res.data; _self.total = response.data.res.total; }) .catch(function(error) { console.log(error); }); }, //当前页改变事件 getCurrentPage: function(page) { var _self = this; // 改变当前页码 _self.currentPage = page; // 获取当前页数据 _self.getPage(); }, // 删除一条数据 deleteRow(data) { var _self = this; var id = data.id; _self.$ajax .delete('http://0608.cc/school/' + id) .then(function(response) { alert(response.data.msg); if (response.data.code == 0) { _self.getPage(); } }) .catch(function(error) { console.log(error); }); }, // 编辑 editRow(row) { this.$router.push({ name: 'schoolEdit', params: row }); } } }; </script> <style></style> ~~~ 21. 添加页面 - add.vue ~~~vue <template> <div> <a href="/#/schoolList"><el-button type="button" size="small" style="float: left;">数据列表</el-button></a> <br /> <br /> <!-- 表单 start https://element.eleme.cn/#/zh-CN/component/form --> <el-form :model="dataForm" status-icon ref="dataForm" label-width="100px" class=""> <el-form-item label="学校名称" prop="name"><el-input type="text" v-model="dataForm.name"></el-input></el-form-item> <el-form-item label="所在城市" prop="city"><el-input type="text" v-model="dataForm.city"></el-input></el-form-item> <el-form-item label="人数" prop="num"><el-input type="number" v-model.number="dataForm.num"></el-input></el-form-item> <el-form-item> <el-button type="primary" @click="submitForm()">提交</el-button> <el-button @click="resetForm('dataForm')">重置</el-button> </el-form-item> </el-form> <!-- 表单 end --> </div> </template> <script> export default { data() { return { dataForm: { name: '', city: '', num: '' } }; }, methods: { submitForm() { var _self = this; _self.$ajax .post('http://0608.cc/school', _self.dataForm) .then(function(response) { // 不管成功与失败、都弹出消息 alert(response.data.msg); // 判断是否成功、成功跳转至展示页面 if (response.data.code == 0) { _self.$router.push({ name: 'schoolList' }); } }) .catch(function(error) { console.log(error); }); }, resetForm(formName) { this.$refs[formName].resetFields(); } } }; </script> <style></style> ~~~ 22. 修改页面 ~~~vue <template> <div> <a href="/#/schoolList"><el-button type="button" size="small" style="float: left;">数据列表</el-button></a> <br /> <br /> <!-- 表单 start https://element.eleme.cn/#/zh-CN/component/form --> <el-form :model="dataForm" status-icon ref="dataForm" label-width="100px" class=""> <el-form-item label="学校名称" prop="name"><el-input type="text" v-model="dataForm.name"></el-input></el-form-item> <el-form-item label="所在城市" prop="city"><el-input type="text" v-model="dataForm.city"></el-input></el-form-item> <el-form-item label="人数" prop="num"><el-input type="number" v-model.number="dataForm.num"></el-input></el-form-item> <el-form-item> <el-button type="primary" @click="submitForm()">提交</el-button> <el-button @click="resetForm('dataForm')">重置</el-button> </el-form-item> </el-form> <!-- 表单 end --> </div> </template> <script> export default { data() { return { dataId: this.$route.params.id, dataForm: { name: this.$route.params.name, city: this.$route.params.city, num: this.$route.params.num } }; }, methods: { submitForm() { var _self = this; _self.$ajax .put('http://0608.cc/school/' + _self.dataId, _self.dataForm) .then(function(response) { // 不管成功与失败、都弹出消息 alert(response.data.msg); // 判断是否成功、成功跳转至展示页面 if (response.data.code == 0) { _self.$router.push({ name: 'schoolList' }); } }) .catch(function(error) { console.log(error); }); }, resetForm(formName) { this.$refs[formName].resetFields(); } } }; </script> <style></style> ~~~ 23. 登录页面 ~~~vue <template> <div> <!-- 表单 start https://element.eleme.cn/#/zh-CN/component/form --> <el-form :model="dataForm" status-icon ref="dataForm" label-width="100px" class=""> <el-form-item label="用户名" prop="name"><el-input type="text" v-model="dataForm.name"></el-input></el-form-item> <el-form-item label="密码" prop="pwd"><el-input type="password" v-model="dataForm.pwd"></el-input></el-form-item> <el-form-item> <el-button type="primary" @click="submitForm()">登录</el-button> <el-button @click="resetForm('dataForm')">重置</el-button> </el-form-item> </el-form> <!-- 表单 end --> </div> </template> <script> export default { data() { return { dataForm: { name: '', pwd: '' } }; }, methods: { submitForm() { var _self = this; _self.$ajax .get('http://0608.cc/login', { params: _self.dataForm }) .then(function(response) { // 不管成功与失败、都弹出消息 alert(response.data.msg); // 判断是否成功、成功跳转至展示页面 if (response.data.code == 0) { _self.$router.push({ name: 'schoolList' }); } }) .catch(function(error) { console.log(error); }); }, resetForm(formName) { this.$refs[formName].resetFields(); } } }; </script> <style></style> ~~~ 24. 完工!! 25. 声明本人博客的所有东西,部分源于网络书籍和视频,其他的是个人的理解感悟,经过自己整理撰写成博客。本人博客均只用于个人学习、复习,不作为商业用途,如有侵权,请联系我修改或删除。联系邮箱:itlaowen@163.com 26. https://www.cnblogs.com/laowenBlog/p/13066263.html