后端接口
1、路由,在 routes/api.php
中
Route::resource('photos', 'PhotoController')->only('store');
2、创建对应控制器
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;class PhotoController extends Controller
{/**** 上传图片* @param Request $request*/public function store(Request $request){if ($request->hasFile('file') && $request->file('file')->isValid()) {$path = $request->file->store('public/images');//上传到七牛云$file_path = storage_path('app/') . $path;qiniu_upload($file_path);return response()->json( 'https://image.xxx.com/' . basename($file_path));}}
}
3、定义辅助函数 qiniu.php
<?php
// 引入鉴权类
use Qiniu\Auth;
// 引入上传类
use Qiniu\Storage\UploadManager;function qiniu_upload($filePath)
{$accessKey = "fAoxxxxxxxxxxxxxxxxxxxxxxxxx";$secretKey = "dkCxxxxxxxxxxxxxxxxxxxxxxxxx";$bucket = "xxxxx";$auth = new Auth($accessKey, $secretKey);$token = $auth->uploadToken($bucket);// 上传到七牛后保存的文件名$key = basename($filePath);// 初始化 UploadManager 对象并进行文件的上传。$uploadMgr = new UploadManager();// 调用 UploadManager 的 putFile 方法进行文件的上传。$uploadMgr->putFile($token, $key, $filePath);unlink($filePath);
}
这里需要安装七牛云的包,不会用的可以看七牛官网或在评论区给我留言。
前端
1、创建 vue2
项目,此步骤省略,自行完成。
2、安装 axios
、vue2-toast
及 Vant2
前端 UI 框架,
npm install axiosnpm install toast2-vue -Snpm i vant@latest-v2 -S
3、在 main.js
中,全部代码如下,供参考:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import Vant from 'vant'
import 'vant/lib/index.css'
import axios from 'axios'
import 'vue2-toast/lib/toast.css'
import Toast from 'vue2-toast'axios.defaults.baseURL = 'https://xxx.xxx.com/'
Vue.prototype.$http = axios
Vue.use(Toast)
Vue.use(Vant)
Vue.config.productionTip = falsenew Vue({router,render: h => h(App)
}).$mount('#app')
4、在 src/router/index.js
中添加路由,代码如下:
import Vue from 'vue'
import VueRouter from 'vue-router'Vue.use(VueRouter)const routes = [{path: '/',name: 'Home',component: () => import('../views/Home.vue')}
]const router = new VueRouter({routes
})export default router
5、准备视图,在 src/views/Home.vue
中,全部代码如下:
<template><div class="home"><h2 class="van-doc-title" style="text-align: center">督查记录表</h2><van-form @submit="onSubmit"><h2 class="van-doc-demo-block__title" style="background-color: #f7f8fa;">基础信息</h2><van-fieldv-model="form.name"label="督查员:"placeholder="请输入姓名":rules="[{ required: true, message: '请填写姓名' }]"/><van-fieldreadonlyclickablename="picker":value="form.department"label="督查场部:"placeholder="点击选择"@click="showPicker = true"/><van-popup v-model="showPicker" position="bottom"><van-pickershow-toolbar:columns="stages"@confirm="onConfirm"@cancel="showPicker = false"/></van-popup><van-fieldv-model="form.address"label="督查地点:"placeholder="请输入地点名称":rules="[{ required: true, message: '请填写地点名称' }]"/><van-fieldv-model="form.head"label="岗位负责人:"placeholder="请输入负责人姓名":rules="[{ required: true, message: '请填写负责人姓名' }]"/><h2 class="van-doc-demo-block__title" style="background-color: #f7f8fa;">检查项目</h2><van-field name="radio" label="卫生情况:"><template #input><van-radio-group v-model="form.health" direction="horizontal"><van-radio name="1">合格</van-radio><van-radio name="0">不合格</van-radio></van-radio-group></template></van-field><van-field name="uploader" label="附图:"><template #input><van-uploader v-model="form.imageList" multiple :max-count="2":after-read="afterRead"/></template></van-field><van-fieldv-model="form.message"rows="2"autosizelabel="留言:"type="textarea"maxlength="50"placeholder="请输入留言"show-word-limit/><div style="display: flex;align-items: center;"><h2 class="van-doc-demo-block__title"style="font-size: 14px;color: #646566;font-weight: normal;padding-right: 15px">评分:</h2><van-ratev-model="form.rate":size="25"color="#ffd21e"void-icon="star"void-color="#eee"count="10"@change="onChange"/></div><div style="margin: 50px 16px 16px 16px;"><van-button round block type="info" native-type="submit">提交</van-button></div></van-form></div>
</template><script>
/* eslint-disable */
export default {data () {return {stages: ['总部', '杨湖场', '株山场', '天子山场', '品格饲料厂'],showPicker: false,form: {name: '',department: '',address: '',head: '',health: '1',imageList: [],message: '',rate: 0}}},methods: {// 选择框onConfirm (value) {this.form.department = valuethis.showPicker = false},// 点击评分onChange (value) {this.form.rate = value},// 点击上传afterRead (file) {file.status = 'uploading'file.message = '上传中...'const formData = new FormData()formData.append('file', file.file)this.uploadImage(formData).then(response => {// 假设返回的response.data是图片的URLfile.content = response.datafile.status = 'done'file.message = '上传成功'this.form.imageList = [...this.form.imageList] // 通过替换imageList数组的内容来更新视图})},// 图片上传至后端服务器uploadImage (formData) {const uploadUrl = 'https://xxx.xxx.com/api/photos'return this.$http.post(uploadUrl, formData, {headers: {'Content-Type': 'multipart/form-data'}})},// 表单提交async onSubmit () {const res = await this.$http.post('api/check', this.form)if (res.data.status === true) {this.$toast.center(res.data.message)this.form = {}this.form.health = '1'}}}
}
</script><style>
.van-doc-demo-block__title {padding: 10px 16px;color: rgba(69, 90, 100, 0.6);font-weight: normal;font-size: 14px;line-height: 16px;
}.van-cell {padding: 15px 16px;
}.van-button--info {background-color: #f4645f;border: 1px solid #f4645f;
}.van-radio__icon--checked .van-icon {background-color: #f4645f;border-color: #f4645f;
}
</style>
上述代码其实是实现一个 form
表单的提交,里面有个比较重要的功能,就是多图上传的问题。最终的效果如下图: