提交 e3590bb1 authored 作者: 王拯's avatar 王拯

学员提交功能完成+修改Form功能做组建

上级 25b2289c
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
"md5": "^2.2.1", "md5": "^2.2.1",
"qs": "^6.9.4", "qs": "^6.9.4",
"timeago.js": "^4.0.2", "timeago.js": "^4.0.2",
"vant": "^2.8.6", "vant": "^2.9.1",
"vue": "^2.6.11", "vue": "^2.6.11",
"vue-meta": "^2.4.0", "vue-meta": "^2.4.0",
"vue-router": "^3.3.4", "vue-router": "^3.3.4",
......
...@@ -9,6 +9,10 @@ ...@@ -9,6 +9,10 @@
/> />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" /> <link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<title>紫荆校友会</title> <title>紫荆校友会</title>
<script src="./js/aliyun-upload-sdk-1.5.0.min.js"></script>
<script src="./js/es6-promise.min.js"></script>
<script src="./js/aliyun-oss-sdk-5.3.1.min.js"></script>
<script> <script>
;(function(win, doc) { ;(function(win, doc) {
function resizeRoot() { function resizeRoot() {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
差异被折叠。
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.ES6Promise=e()}(this,function(){"use strict";function t(t){var e=typeof t;return null!==t&&("object"===e||"function"===e)}function e(t){return"function"==typeof t}function n(t){I=t}function r(t){J=t}function o(){return function(){return process.nextTick(a)}}function i(){return"undefined"!=typeof H?function(){H(a)}:c()}function s(){var t=0,e=new V(a),n=document.createTextNode("");return e.observe(n,{characterData:!0}),function(){n.data=t=++t%2}}function u(){var t=new MessageChannel;return t.port1.onmessage=a,function(){return t.port2.postMessage(0)}}function c(){var t=setTimeout;return function(){return t(a,1)}}function a(){for(var t=0;t<G;t+=2){var e=$[t],n=$[t+1];e(n),$[t]=void 0,$[t+1]=void 0}G=0}function f(){try{var t=require,e=t("vertx");return H=e.runOnLoop||e.runOnContext,i()}catch(n){return c()}}function l(t,e){var n=arguments,r=this,o=new this.constructor(p);void 0===o[et]&&k(o);var i=r._state;return i?!function(){var t=n[i-1];J(function(){return x(i,o,t,r._result)})}():E(r,o,t,e),o}function h(t){var e=this;if(t&&"object"==typeof t&&t.constructor===e)return t;var n=new e(p);return g(n,t),n}function p(){}function v(){return new TypeError("You cannot resolve a promise with itself")}function d(){return new TypeError("A promises callback cannot return that same promise.")}function _(t){try{return t.then}catch(e){return it.error=e,it}}function y(t,e,n,r){try{t.call(e,n,r)}catch(o){return o}}function m(t,e,n){J(function(t){var r=!1,o=y(n,e,function(n){r||(r=!0,e!==n?g(t,n):S(t,n))},function(e){r||(r=!0,j(t,e))},"Settle: "+(t._label||" unknown promise"));!r&&o&&(r=!0,j(t,o))},t)}function b(t,e){e._state===rt?S(t,e._result):e._state===ot?j(t,e._result):E(e,void 0,function(e){return g(t,e)},function(e){return j(t,e)})}function w(t,n,r){n.constructor===t.constructor&&r===l&&n.constructor.resolve===h?b(t,n):r===it?(j(t,it.error),it.error=null):void 0===r?S(t,n):e(r)?m(t,n,r):S(t,n)}function g(e,n){e===n?j(e,v()):t(n)?w(e,n,_(n)):S(e,n)}function A(t){t._onerror&&t._onerror(t._result),T(t)}function S(t,e){t._state===nt&&(t._result=e,t._state=rt,0!==t._subscribers.length&&J(T,t))}function j(t,e){t._state===nt&&(t._state=ot,t._result=e,J(A,t))}function E(t,e,n,r){var o=t._subscribers,i=o.length;t._onerror=null,o[i]=e,o[i+rt]=n,o[i+ot]=r,0===i&&t._state&&J(T,t)}function T(t){var e=t._subscribers,n=t._state;if(0!==e.length){for(var r=void 0,o=void 0,i=t._result,s=0;s<e.length;s+=3)r=e[s],o=e[s+n],r?x(n,r,o,i):o(i);t._subscribers.length=0}}function M(){this.error=null}function P(t,e){try{return t(e)}catch(n){return st.error=n,st}}function x(t,n,r,o){var i=e(r),s=void 0,u=void 0,c=void 0,a=void 0;if(i){if(s=P(r,o),s===st?(a=!0,u=s.error,s.error=null):c=!0,n===s)return void j(n,d())}else s=o,c=!0;n._state!==nt||(i&&c?g(n,s):a?j(n,u):t===rt?S(n,s):t===ot&&j(n,s))}function C(t,e){try{e(function(e){g(t,e)},function(e){j(t,e)})}catch(n){j(t,n)}}function O(){return ut++}function k(t){t[et]=ut++,t._state=void 0,t._result=void 0,t._subscribers=[]}function Y(t,e){this._instanceConstructor=t,this.promise=new t(p),this.promise[et]||k(this.promise),B(e)?(this.length=e.length,this._remaining=e.length,this._result=new Array(this.length),0===this.length?S(this.promise,this._result):(this.length=this.length||0,this._enumerate(e),0===this._remaining&&S(this.promise,this._result))):j(this.promise,q())}function q(){return new Error("Array Methods must be provided an Array")}function F(t){return new Y(this,t).promise}function D(t){var e=this;return new e(B(t)?function(n,r){for(var o=t.length,i=0;i<o;i++)e.resolve(t[i]).then(n,r)}:function(t,e){return e(new TypeError("You must pass an array to race."))})}function K(t){var e=this,n=new e(p);return j(n,t),n}function L(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}function N(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}function U(t){this[et]=O(),this._result=this._state=void 0,this._subscribers=[],p!==t&&("function"!=typeof t&&L(),this instanceof U?C(this,t):N())}function W(){var t=void 0;if("undefined"!=typeof global)t=global;else if("undefined"!=typeof self)t=self;else try{t=Function("return this")()}catch(e){throw new Error("polyfill failed because global object is unavailable in this environment")}var n=t.Promise;if(n){var r=null;try{r=Object.prototype.toString.call(n.resolve())}catch(e){}if("[object Promise]"===r&&!n.cast)return}t.Promise=U}var z=void 0;z=Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)};var B=z,G=0,H=void 0,I=void 0,J=function(t,e){$[G]=t,$[G+1]=e,G+=2,2===G&&(I?I(a):tt())},Q="undefined"!=typeof window?window:void 0,R=Q||{},V=R.MutationObserver||R.WebKitMutationObserver,X="undefined"==typeof self&&"undefined"!=typeof process&&"[object process]"==={}.toString.call(process),Z="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,$=new Array(1e3),tt=void 0;tt=X?o():V?s():Z?u():void 0===Q&&"function"==typeof require?f():c();var et=Math.random().toString(36).substring(16),nt=void 0,rt=1,ot=2,it=new M,st=new M,ut=0;return Y.prototype._enumerate=function(t){for(var e=0;this._state===nt&&e<t.length;e++)this._eachEntry(t[e],e)},Y.prototype._eachEntry=function(t,e){var n=this._instanceConstructor,r=n.resolve;if(r===h){var o=_(t);if(o===l&&t._state!==nt)this._settledAt(t._state,e,t._result);else if("function"!=typeof o)this._remaining--,this._result[e]=t;else if(n===U){var i=new n(p);w(i,t,o),this._willSettleAt(i,e)}else this._willSettleAt(new n(function(e){return e(t)}),e)}else this._willSettleAt(r(t),e)},Y.prototype._settledAt=function(t,e,n){var r=this.promise;r._state===nt&&(this._remaining--,t===ot?j(r,n):this._result[e]=n),0===this._remaining&&S(r,this._result)},Y.prototype._willSettleAt=function(t,e){var n=this;E(t,void 0,function(t){return n._settledAt(rt,e,t)},function(t){return n._settledAt(ot,e,t)})},U.all=F,U.race=D,U.resolve=h,U.reject=K,U._setScheduler=n,U._setAsap=r,U._asap=J,U.prototype={constructor:U,then:l,"catch":function(t){return this.then(null,t)}},U.polyfill=W,U.Promise=U,U.polyfill(),U});
\ No newline at end of file
...@@ -12,6 +12,15 @@ export function upload(data) { ...@@ -12,6 +12,15 @@ export function upload(data) {
}) })
} }
// 获取视频上传地址和凭证
export function uploadVideoAuth(data) {
return httpRequest({
url: '/api/alumni/v1/graduation/auth',
method: 'post',
data
})
}
// 获取热门推荐列表 // 获取热门推荐列表
export function getHotList(params) { export function getHotList(params) {
return httpRequest({ return httpRequest({
...@@ -89,6 +98,15 @@ export function addComment(id, data) { ...@@ -89,6 +98,15 @@ export function addComment(id, data) {
}) })
} }
// 上传资料
export function addSubmitStudent(data) {
return httpRequest({
url: `/api/alumni/v1/graduation/add`,
method: 'post',
data
})
}
// 添加回复 // 添加回复
export function addCommentReplay(id, data) { export function addCommentReplay(id, data) {
return httpRequest({ return httpRequest({
......
...@@ -88,6 +88,42 @@ ...@@ -88,6 +88,42 @@
</van-field> </van-field>
</template> </template>
<!-- 上传多个图片 -->
<template v-else-if="item.fieldType === 'upliadMultiple'">
<van-field
:border="false"
:required="false"
v-bind="item"
v-if="item.isShow ? item.isShow(ruleForm) : true"
>
<template #label>
{{ item.label }}
<span class="red" v-if="item.required">*</span>
</template>
<template #input>
<UpliadMultiple v-model="ruleForm[item.name]" />
</template>
</van-field>
</template>
<!-- 上传视频 -->
<template v-else-if="item.fieldType === 'video'">
<van-field
:border="false"
:required="false"
v-bind="item"
v-if="item.isShow ? item.isShow(ruleForm) : true"
>
<template #label>
{{ item.label }}
<span class="red" v-if="item.required">*</span>
</template>
<template #input>
<UploadVideo v-model="ruleForm[item.name]" accept="video/*" />
</template>
</van-field>
</template>
<!-- 单选 --> <!-- 单选 -->
<template v-else-if="item.fieldType === 'radio'"> <template v-else-if="item.fieldType === 'radio'">
<van-field <van-field
...@@ -168,10 +204,12 @@ ...@@ -168,10 +204,12 @@
import dayjs from 'dayjs' import dayjs from 'dayjs'
import Upload from '@/components/Upload' import Upload from '@/components/Upload'
import areaList from '@/utils/area.js' import areaList from '@/utils/area.js'
import UploadVideo from '@/components/UploadVideo'
import UpliadMultiple from '@/components/UpliadMultiple'
export default { export default {
name: 'VForm', name: 'VForm',
components: { Upload }, components: { Upload, UploadVideo, UpliadMultiple },
props: { props: {
model: { model: {
type: Object, type: Object,
......
z<template>
<van-uploader
v-model="fileList"
:after-read="afterRead"
:max-size="MaxSize"
@oversize="oversize"
@delete="onDelete"
v-bind="$attrs"
/>
</template>
<script>
import { upload } from '@/api/index'
export default {
name: 'UpliadMultiple',
// 最大3M
props: { value: {}, MaxSize: { type: Number, default: 3 * 1024 * 1024 } },
data() {
return { fileList: [], urlList: [] }
},
watch: {
value: {
immediate: true,
handler(value) {
if (!value) {
this.fileList = []
}
}
}
},
methods: {
oversize(file) {
const rawFile = file.file
if (rawFile.size > this.MaxSize) {
this.$toast('文件大小不能超过3M')
}
},
afterRead(file) {
file.status = 'uploading'
file.message = '上传中...'
let formData = new FormData()
formData.append('file', file.file)
upload(formData)
.then(response => {
if (response.success) {
file.status = 'done'
this.urlList.push({
name: file.file.name,
url: response.url
})
this.$emit('input', this.urlList)
} else {
file.status = 'failed'
file.message = '上传失败'
}
})
.catch(() => {
file.status = 'failed'
file.message = '上传失败'
})
},
onDelete(value) {
this.urlList = this.urlList.filter(k => k.name !== value.file.name)
}
}
}
</script>
<style lang="scss" scoped>
::v-deep .van-uploader__upload,
::v-deep .van-uploader__preview-image {
width: 100px;
height: 100px;
background-color: #eee;
border-radius: 0;
}
::v-deep .van-uploader__upload-icon {
color: #666;
}
</style>
<template>
<div class="uploadVideo">
<van-uploader
v-model="fileList"
@delete="onDelete"
:after-read="afterRead"
:disabled="disabled"
v-bind="$attrs"
/>
<van-progress v-if="isShow" :percentage="authProgress" />
</div>
</template>
<script>
import { uploadVideoAuth } from '@/api/index'
export default {
name: 'UploadVideo',
props: { value: {} },
data() {
return {
fileList: [],
client: null,
tempCheckpoint: null,
result: null,
statusText: '',
uploader: null,
authProgress: 0,
endpoint: [],
disabled: false,
isShow: false
}
},
watch: {
value: {
immediate: true,
handler(value) {
if (!value) {
this.fileList = []
}
}
}
},
methods: {
afterRead(file) {
if (!file) {
this.$toast('请上传文件')
return
}
this.isShow = true
this.disabled = true
uploadVideoAuth({ file_name: file.file.name })
.then(response => {
let userData = '{"Vod":{}}'
if (this.uploader) {
this.uploader.stopUpload()
this.authProgress = 0
this.statusText = ''
}
this.uploader = this.createUploader(file, response.auth)
this.uploader.addFile(file.file, null, null, null, userData)
})
.catch(() => {
file.status = 'failed'
this.statusText = '获取失败'
})
},
authUpload() {
if (this.uploader !== null) {
this.uploader.startUpload()
}
},
createUploader(file, auth) {
let self = this
let uploaders = new window.AliyunUpload.Vod({
timeout: 60000,
partSize: 1048576,
parallel: 5,
retryCount: 3,
region: 'cn-shanghai',
retryDuration: 2,
userId: '1731345321362117',
addFileSuccess: function() {
file.message = '添加文件成功, 等待上传...'
self.authUpload()
},
onUploadstarted: function(uploadInfo) {
uploaders.setUploadAuthAndAddress(
uploadInfo,
auth.upload_auth,
auth.upload_address,
auth.video_id
)
self.statusText = '文件开始上传...'
},
onUploadSucceed: function(uploadInfo) {
self.endpoint.push({
name: uploadInfo.file.name,
url: uploadInfo.endpoint
})
self.$emit('input', self.endpoint)
self.statusText = '文件上传成功!'
self.isShow = false
self.disabled = false
self.authProgress = 0
self.$toast('文件上传成功')
},
onUploadFailed: function() {
self.statusText = '文件上传失败!'
self.disabled = false
self.isShow = false
self.$toast('文件上传失败')
},
onUploadProgress: function(uploadInfo, totalSize, progress) {
let progressPercent = Math.ceil(progress * 100)
self.authProgress = progressPercent
self.statusText = '文件上传中...'
},
onUploadTokenExpired: function() {
self.statusText = '文件超时...'
self.disabled = false
self.authProgress = 0
self.$toast('文件超时')
},
onUploadEnd: function() {
self.statusText = '文件上传完毕'
}
})
return uploaders
},
onDelete(value) {
if (this.endpoint.filter(k => k.name === value.file.name).length === 0) {
this.isShow = false
if (this.uploader) {
this.uploader.stopUpload()
}
}
this.endpoint = this.endpoint.filter(k => k.name !== value.file.name)
}
}
}
</script>
<style lang="scss" scoped>
::v-deep .van-uploader__upload,
::v-deep .van-uploader__preview-image {
width: 100px;
height: 100px;
background-color: #eee;
border-radius: 0;
}
::v-deep .van-uploader__upload-icon {
color: #666;
}
.uploadVideo {
width: 100%;
}
</style>
...@@ -21,6 +21,9 @@ Vue.use(Toast) ...@@ -21,6 +21,9 @@ Vue.use(Toast)
import { Popup } from 'vant' import { Popup } from 'vant'
Vue.use(Popup) Vue.use(Popup)
import { Progress } from 'vant'
Vue.use(Progress)
import { Tab, Tabs } from 'vant' import { Tab, Tabs } from 'vant'
Vue.use(Tab) Vue.use(Tab)
Vue.use(Tabs) Vue.use(Tabs)
......
...@@ -147,6 +147,12 @@ const routes = [ ...@@ -147,6 +147,12 @@ const routes = [
path: '/group/:id/activity', path: '/group/:id/activity',
name: 'groupActivity', name: 'groupActivity',
component: () => import('@/views/group/Activity.vue') component: () => import('@/views/group/Activity.vue')
},
//学员提交
{
path: '/submitStudent',
name: 'submitStudent',
component: () => import('@/views/submitStudent/submitStudent.vue')
} }
] ]
......
<template>
<card title="学员提交" style="margin:0 20px;">
<v-form ref="form" :model="formModel" :fields="fields" @submit="onSubmit">
<input
type="button"
value="上传"
class="submit-button"
@click="handleSubmit"
/>
</v-form>
</card>
</template>
<script>
import Card from '@/components/Card'
import VForm from '@/components/Form'
import * as api from '@/api'
export default {
name: 'submitStudent',
components: { Card, VForm },
data() {
return {
formModel: { photos: [], videos: [] },
fields: [
{
name: 'mobile',
label: '手机号',
required: true,
placeholder: '请输入手机号',
maxlength: '11',
rules: [{ required: true, message: '请输入手机号' }]
},
{
fieldType: 'upliadMultiple',
name: 'photos',
label: '照片',
required: true,
placeholder: '请上传照片'
},
{
fieldType: 'video',
name: 'videos',
label: '视频',
required: true,
placeholder: '请上传视频'
}
]
}
},
watch: {
$route: {
immediate: true,
deep: true,
handler(route) {
this.formModel = Object.assign(this.formModel, route.query)
}
}
},
methods: {
handleSubmit() {
this.$refs.form.submit()
},
onSubmit(data) {
const ruleForm = this.$refs.form.ruleForm
if (!ruleForm.photos.length || ruleForm.photos.length === 0) {
this.$toast('请上传照片')
return
}
if (!ruleForm.videos.length || ruleForm.videos.length === 0) {
this.$toast('请上传视频')
return
}
const params = {
mobile: data.mobile,
photos: JSON.stringify(ruleForm.photos.map(k => k.url)),
videos: JSON.stringify(ruleForm.videos.map(k => k.url))
}
api.addSubmitStudent(params).then(response => {
if (response.success) {
this.$dialog
.alert({
confirmButtonText: '确定',
message: '上传成功'
})
.then(() => {
this.$router.replace({ name: 'my' })
})
} else {
this.$toast(response.message)
}
})
}
}
}
</script>
<style lang="scss"></style>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论