v1.3 版本发布,代码同步后端v1.3版本

This commit is contained in:
郑杰
2018-12-31 17:07:02 +08:00
parent 7f2e4ed3f9
commit c97e401918
38 changed files with 1338 additions and 40 deletions

View File

@@ -1,10 +1,9 @@
<template>
<div class="errPage-container">
<el-button icon="arrow-left" class="pan-back-btn" @click="back">返回</el-button>
<el-row>
<el-col :span="12">
<h1 class="text-jumbo text-ginormous">Oops!</h1>
gif来源<a href="https://zh.airbnb.com/" target="_blank">airbnb</a> 页面
图片来源<a href="https://zh.airbnb.com/" target="_blank">airbnb</a> 页面
<h2>你没有权限去该页面</h2>
<h6>如有不满请联系你领导</h6>
<ul class="list-unstyled">
@@ -12,7 +11,7 @@
<li class="link-type">
<router-link to="/dashboard">回首页</router-link>
</li>
<li class="link-type"><a href="https://www.taobao.com/">随便看看</a></li>
<li class="link-type"><a href="https://www.jianshu.com/">随便看看</a></li>
<li><a href="#" @click.prevent="dialogVisible=true">点我看图</a></li>
</ul>
</el-col>
@@ -52,7 +51,7 @@ export default {
<style rel="stylesheet/scss" lang="scss" scoped>
.errPage-container {
width: 800px;
width: 600px;
max-width: 100%;
margin: 100px auto;
.pan-back-btn {

View File

@@ -21,11 +21,11 @@
首页
</el-dropdown-item>
</router-link>
<a target="_blank" href="https://github.com/elunez/eladmin">
<router-link to="/user/center">
<el-dropdown-item>
项目地址
个人中心
</el-dropdown-item>
</a>
</router-link>
<el-dropdown-item divided>
<span style="display:block;" @click="logout">退出登录</span>
</el-dropdown-item>

View File

@@ -37,7 +37,6 @@
<script>
import { md5 } from '@/utils/md5'
export default {
name: 'Login',
data() {

View File

@@ -22,7 +22,7 @@
<span v-else class="badge">{{ scope.row.logType }}</span>
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建日期" width="160px">
<el-table-column prop="createTime" label="创建日期" width="180px">
<template slot-scope="scope">
<span>{{ time(scope.row.createTime) }}</span>
</template>

View File

@@ -18,7 +18,6 @@
</span>
<span style="color: #DE00CC">{{ item.className+' ' }}</span>
<span v-html="item.body"/>
<span>{{ item.exception }}</span>
</div>
</div>
</div>
@@ -34,7 +33,7 @@ export default {
data() {
return {
height: document.documentElement.clientHeight - 132 + 'px;',
data: [{ name: 'elAdmin-', timestamp: parseTime(new Date()), threadName: 'system-prompt-message', level: 'INFO', className: 'me.zhengjie.AppRun' + ' :', body: '(*^ω^*) 欢迎使用,暂无日志输出~', exception: '' }],
data: [{ name: 'elAdmin-', timestamp: parseTime(new Date()), threadName: 'system-prompt-message', level: 'INFO', className: 'me.zhengjie.AppRun' + ' :', body: '(*^ω^*) 欢迎使用,暂无日志输出~' }],
// level
INFO: '#0000ff', WARN: '#FFFF00', ERROR: '#FF0000', DEBUG: '#DEA000'
}
@@ -80,7 +79,6 @@ export default {
}, 5000)
},
connection(_this) {
// 建立连接对象,注意部署到线上后也要修改对应的地址
const socket = new SockJS(this.socketApi)// 连接服务端提供的通信接口,连接以后才可以订阅广播消息和个人消息
// 获取STOMP子协议的客户端对象
this.stompClient = Stomp.over(socket)

View File

@@ -0,0 +1,172 @@
<template>
<div class="app-container">
<div id="content-main" :style="'width:'+width">
<el-card shadow="never" class="box-card user-info">
<div class="avatar-content">
<el-upload
:show-file-list="false"
:on-success="handleSuccess"
:on-error="handleError"
:headers="headers"
:action="updateAvatarApi"
class="avatar-uploader">
<img v-if="avatar" :src="avatar" title="点击上传头像" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"/>
</el-upload>
</div>
<div class="user-info-content">
<div>登录账号{{ name }}</div>
<div>注册时间{{ createTime }}</div>
<div>账号状态<span style="color: #909399">正常</span></div>
</div>
</el-card>
<el-card shadow="never" class="box-card reset-pass">
<h4 class="account-label-icon">登录密码</h4>
<updatePass/>
<p>安全性高的密码可使账号更安全建议设置同时包含字母数字符号的密码</p>
</el-card>
<el-card shadow="never" class="box-card reset-email">
<h4 class="account-label-icon">邮箱验证</h4>
<updateEmail :email="email"/>
<p>你的邮箱{{ formatEmail(email) }} </p>
<h4>绑定邮箱可用于</h4>
<ul>
<li>安全管理密码重置与修改</li>
<li>账号使用使用邮箱登录系统</li>
<li>站内通知站内信接收</li>
</ul>
</el-card>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import { regEmail } from '@/utils/index'
import updatePass from './center/updatePass'
import updateEmail from './center/updateEmail'
import { getToken } from '@/utils/auth'
import store from '@/store'
export default {
name: 'Center',
components: { updatePass, updateEmail },
data() {
return {
width: document.documentElement.clientWidth - 180 + 'px;',
headers: {
'Authorization': 'Bearer ' + getToken()
}
}
},
computed: {
...mapGetters([
'avatar',
'name',
'email',
'createTime',
'updateAvatarApi'
])
},
methods: {
formatEmail(mail) {
return regEmail(mail)
},
handleSuccess(response, file, fileList) {
this.$notify({
title: '头像修改成功',
type: 'success',
duration: 2500
})
store.dispatch('GetInfo').then(() => {})
},
// 监听上传失败
handleError(e, file, fileList) {
const msg = JSON.parse(e.message)
this.$notify({
title: msg.message,
type: 'error',
duration: 2500
})
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss">
.box-card{
border: 0px;
border-bottom: 1px solid #ECEDFE;
border-radius: unset;
h4{
height: 26px;
margin: 0 0 7px;
line-height: 26px;
font-size: 1.1rem;
font-weight: 500;
color: #444242;
display: inline-block;
}
p{
font-family: Lantinghei;
font-size: 90%;
color: #747474;
}
ul{
padding: 0;
margin: 7px 0 0;
list-style: none;
font-size: 80%;
}
li {
float: left;
margin: 0 30px 10px 0!important;
}
li:before {
width: 8px;
height: 8px;
background-color: #52acd9;
color: #52acd9;
display: inline-block;
border-radius: 50%;
margin-right: 5px;
content: '';
box-sizing: border-box;
}
}
.user-info{
height: 170px;
}
.reset-email{
border-bottom: 0px;
}
.avatar-content, .user-info-content {
float: left;
}
.user-info-content{
font-family: Lantinghei;
position: relative;
font-size: 14px;
margin: 25px;
div{
margin-bottom: 15px;
}
}
.avatar-uploader-icon {
font-size: 28px;
width: 120px;
height: 120px;
line-height: 120px;
text-align: center;
}
.avatar {
width: 120px;
height: 120px;
display: block;
border-radius: 50%;
}
</style>

View File

@@ -0,0 +1,150 @@
<template>
<div style="display: inline-block">
<el-button size="mini" class="button" type="info" @click="dialog = true">修改</el-button>
<el-dialog :visible.sync="dialog" :title="title" width="475px" @close="cancel">
<el-form ref="form" :model="form" :rules="rules" size="small" label-width="88px">
<el-form-item label="新邮箱" prop="email">
<el-input v-model="form.email" auto-complete="on" style="width: 200px;"/>
<el-button :loading="codeLoading" :disabled="isDisabled" size="small" @click="sendCode">{{ buttonName }}</el-button>
</el-form-item>
<el-form-item label="验证码" prop="code">
<el-input v-model="form.code" style="width: 320px;"/>
</el-form-item>
<el-form-item label="当前密码" prop="pass">
<el-input v-model="form.pass" type="password" style="width: 320px;"/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="text" @click="cancel">取消</el-button>
<el-button :loading="loading" type="primary" @click="doSubmit">确认</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import store from '@/store'
import { md5 } from '@/utils/md5'
import { validatEmail } from '@/utils/validate'
import { validPass, updateEmail } from '@/api/user'
import { resetEmail } from '@/api/code'
export default {
props: {
email: {
type: String,
required: true
}
},
data() {
const validatePass = (rule, value, callback) => {
validPass(md5(value)).then(res => {
if (res.status === 200) {
callback()
} else {
callback(new Error('密码错误,请重新输入'))
}
})
}
const validMail = (rule, value, callback) => {
if (value === '') {
callback(new Error('新邮箱不能为空'))
} else if (value === this.email) {
callback(new Error('新邮箱不能与旧邮箱相同'))
} else if (validatEmail(value)) {
callback()
} else {
callback(new Error('邮箱格式错误'))
}
}
return {
loading: false, dialog: false, title: '修改邮箱', form: { pass: '', email: '', code: '' },
user: { email: '', password: '' }, codeLoading: false,
codeData: { type: 'email', value: '' },
buttonName: '获取验证码', isDisabled: false, time: 60,
rules: {
pass: [
{ required: true, validator: validatePass, trigger: 'blur' }
],
email: [
{ required: true, validator: validMail, trigger: 'blur' }
],
code: [
{ required: true, message: '验证码不能为空', trigger: 'blur' }
]
}
}
},
methods: {
cancel() {
this.resetForm()
},
sendCode() {
if (this.form.email && this.form.email !== this.email) {
this.codeLoading = true
this.buttonName = '验证码发送中'
this.codeData.value = this.form.email
const _this = this
resetEmail(this.codeData).then(res => {
this.$message({
showClose: true,
message: '发送成功有效期5分钟',
type: 'success'
})
this.codeLoading = false
this.isDisabled = true
this.buttonName = this.time-- + '秒后重新发送'
this.timer = window.setInterval(function() {
_this.buttonName = _this.time + '秒后重新发送'
--_this.time
if (_this.time < 0) {
_this.buttonName = '重新发送'
_this.time = 60
_this.isDisabled = false
clearInterval(this.timer)
}
}, 1000)
}).catch(err => {
this.codeLoading = false
console.log(err.response.data.message)
})
}
},
doSubmit() {
this.$refs['form'].validate((valid) => {
if (valid) {
this.loading = true
this.user = { email: this.form.email, password: md5(this.form.pass) }
updateEmail(this.form.code, this.user).then(res => {
this.loading = false
this.resetForm()
this.$notify({
title: '邮箱修改成功',
type: 'success',
duration: 1500
})
store.dispatch('GetInfo').then(() => {})
}).catch(err => {
this.loading = false
console.log(err.response.data.message)
})
} else {
return false
}
})
},
resetForm() {
this.dialog = false
this.$refs['form'].resetFields()
clearInterval(this.timer)
this.time = 60
this.buttonName = '获取验证码'
this.isDisabled = false
this.form = { pass: '', email: '', code: '' }
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,102 @@
<template>
<div style="display: inline-block">
<el-button size="mini" class="button" type="info" @click="dialog = true">修改</el-button>
<el-dialog :visible.sync="dialog" :title="title" width="500px" @close="cancel">
<el-form ref="form" :model="form" :rules="rules" size="small" label-width="88px">
<el-form-item label="旧密码" prop="oldPass">
<el-input v-model="form.oldPass" type="password" auto-complete="on" style="width: 370px;"/>
</el-form-item>
<el-form-item label="新密码" prop="newPass">
<el-input v-model="form.newPass" type="password" auto-complete="on" style="width: 370px;"/>
</el-form-item>
<el-form-item label="确认密码" prop="confirmPass">
<el-input v-model="form.confirmPass" type="password" auto-complete="on" style="width: 370px;"/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="text" @click="cancel">取消</el-button>
<el-button :loading="loading" type="primary" @click="doSubmit">确认</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import store from '@/store'
import { md5 } from '@/utils/md5'
import { validPass, updatePass } from '@/api/user'
export default {
data() {
const validatePass = (rule, value, callback) => {
validPass(md5(value)).then(res => {
if (res.status === 200) {
callback()
} else {
callback(new Error('旧密码错误,请检查'))
}
})
}
const confirmPass = (rule, value, callback) => {
if (this.form.newPass !== value) {
callback(new Error('两次输入的密码不一致'))
} else {
callback()
}
}
return {
loading: false, dialog: false, title: '修改密码', form: { oldPass: '', newPass: '', confirmPass: '' },
rules: {
oldPass: [
{ required: true, validator: validatePass, trigger: 'blur' }
],
newPass: [
{ required: true, message: '请输入新密码', trigger: 'blur' },
{ min: 6, max: 20, message: '长度在 6 到 20 个字符', trigger: 'blur' }
],
confirmPass: [
{ required: true, validator: confirmPass, trigger: 'blur' }
]
}
}
},
methods: {
cancel() {
this.resetForm()
},
doSubmit() {
this.$refs['form'].validate((valid) => {
if (valid) {
this.loading = true
updatePass(md5(this.form.confirmPass)).then(res => {
this.resetForm()
this.$notify({
title: '密码修改成功,请重新登录',
type: 'success',
duration: 1500
})
setTimeout(() => {
store.dispatch('LogOut').then(() => {
location.reload() // 为了重新实例化vue-router对象 避免bug
})
}, 1500)
}).catch(err => {
this.loading = false
console.log(err.response.data.message)
})
} else {
return false
}
})
},
resetForm() {
this.dialog = false
this.$refs['form'].resetFields()
this.form = { oldPass: '', newPass: '', confirmPass: '' }
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,30 @@
<template>
<el-tabs v-model="activeName" style="padding-left: 5px;">
<el-tab-pane label="参数配置" name="first">
<Config/>
</el-tab-pane>
<el-tab-pane label="支付测试" name="second">
<ToPay/>
</el-tab-pane>
<el-tab-pane label="使用说明" name="third">
<Description/>
</el-tab-pane>
</el-tabs>
</template>
<script>
import Config from './module/config'
import ToPay from './module/toPay'
import Description from './module/description'
export default {
components: { Config, ToPay, Description },
data() {
return {
activeName: 'second'
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,96 @@
<template>
<el-form ref="form" :model="form" :rules="rules" style="margin-top: 6px;" size="small" label-width="100px">
<el-form-item label="appID" prop="appID">
<el-input v-model="form.appID" style="width: 40%"/>
<span style="color: #C0C0C0;margin-left: 10px;">应用APPID,收款账号既是APPID对应支付宝账号</span>
</el-form-item>
<el-form-item label="商家账号" prop="sysServiceProviderId">
<el-input v-model="form.sysServiceProviderId" style="width: 40%;"/>
<span style="color: #C0C0C0;margin-left: 10px;">商家账号</span>
</el-form-item>
<el-form-item label="商户私钥" prop="privateKey">
<el-input v-model="form.privateKey" type="password" style="width: 40%;"/>
<span style="color: #C0C0C0;margin-left: 10px;">商户私钥你的PKCS8格式RSA2私钥</span>
</el-form-item>
<el-form-item label="支付宝公钥" prop="publicKey">
<el-input v-model="form.publicKey" type="password" style="width: 40%;"/>
<span style="color: #C0C0C0;margin-left: 10px;">支付宝公钥</span>
</el-form-item>
<el-form-item label="回调地址" prop="returnUrl">
<el-input v-model="form.returnUrl" style="width: 40%;"/>
<span style="color: #C0C0C0;margin-left: 10px;">订单完成后返回的地址</span>
</el-form-item>
<el-form-item label="异步通知" prop="notifyUrl">
<el-input v-model="form.notifyUrl" style="width: 40%;"/>
<span style="color: #C0C0C0;margin-left: 10px;">支付结果异步通知地址</span>
</el-form-item>
<el-button :loading="loading" style="margin-left:5%;" size="medium" type="success" @click="doSubmit">保存配置</el-button>
</el-form>
</template>
<script>
import { get, update } from '@/api/alipay'
export default {
name: 'Config',
data() {
return {
loading: false,
form: { appID: '', sysServiceProviderId: '', privateKey: '', publicKey: '', returnUrl: '', notifyUrl: '' },
rules: {
appID: [
{ required: true, message: '请输入appID', trigger: 'blur' }
],
sysServiceProviderId: [
{ required: true, message: '请输入商家账号', trigger: 'blur' }
],
privateKey: [
{ required: true, message: '商户私钥不能为空', trigger: 'blur' }
],
publicKey: [
{ required: true, message: '支付宝公钥不能为空', trigger: 'blur' }
],
returnUrl: [
{ required: true, message: '回调地址不能为空', trigger: 'blur' }
],
notifyUrl: [
{ required: true, message: '回调地址不能为空', trigger: 'blur' }
]
}
}
},
created() {
this.init()
},
methods: {
init() {
get().then(res => {
this.form = res
})
},
doSubmit() {
this.$refs['form'].validate((valid) => {
if (valid) {
this.loading = true
update(this.form).then(res => {
this.$notify({
title: '修改成功',
type: 'success',
duration: 2500
})
this.loading = false
}).catch(err => {
this.loading = false
console.log(err.response.data.message)
})
} else {
return false
}
})
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,35 @@
<template>
<div>
<blockquote class="my-blockquote">注意</blockquote>
<pre class="my-code">
测试所用参数都是沙箱环境仅供测试所用申请地址<a style="color: #00a0e9" href="https://openhome.alipay.com/platform/appDaily.htm?tab=info" target="_blank">支付宝开发平台</a>
如需付款测试请使用
账号uuxesw9745@sandbox.com
密码111111
支付密码111111
文明测试谢谢</pre>
<blockquote class="my-blockquote"> 支付设置</blockquote>
<pre class="my-code">
支付提供两个测试地址
PC端与手机端并且使用如下代码识别
if (/(Android)/i.test(navigator.userAgent)){ // 判断是否为Android手机
url = "/aliPay/toPayAsWeb"
}else if(/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)){ // 判断是否为苹果手机
url = "/aliPay/toPayAsWeb"
} else {
url = "/aliPay/toPayAsPC"
}</pre>
<blockquote class="my-blockquote">更多帮助</blockquote>
<pre class="my-code">更多帮助请查看系统源码</pre>
</div>
</template>
<script>
import '@/styles/description.scss'
export default {
name: 'Description'
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,84 @@
<template>
<div>
<el-form ref="form" :model="form" :rules="rules" style="margin-top: 6px;" size="small" label-width="90px">
<el-form-item label="商品名称" prop="subject">
<el-input v-model="form.subject" style="width: 35%"/>
</el-form-item>
<el-form-item label="商品价格" prop="totalAmount">
<el-input v-model="form.totalAmount" style="width: 35%"/>
<span style="color: #C0C0C0;margin-left: 10px;">测试允许区间(0,5000]</span>
</el-form-item>
<el-form-item label="商品描述" prop="body">
<el-input v-model="form.body" style="width: 35%" rows="8" type="textarea"/>
</el-form-item>
<el-button :loading="loading" style="margin-left:2%;" size="medium" type="success" @click="doSubmit">去支付</el-button>
</el-form>
</div>
</template>
<script>
import { toAliPay } from '@/api/alipay'
export default {
data() {
return {
url: '',
// 新窗口的引用
newWin: null,
loading: false, form: { subject: '', totalAmount: '', body: '' },
rules: {
subject: [
{ required: true, message: '商品名称不能为空', trigger: 'blur' }
],
totalAmount: [
{ required: true, message: '商品价格不能为空', trigger: 'blur' }
],
body: [
{ required: true, message: '商品描述不能为空', trigger: 'blur' }
]
}
}
},
watch: {
url(newVal, oldVal) {
if (newVal && this.newWin) {
this.newWin.sessionStorage.clear()
this.newWin.location.href = newVal
// 重定向后把url和newWin重置
this.url = ''
this.newWin = null
}
}
},
methods: {
doSubmit() {
this.$refs['form'].validate((valid) => {
if (valid) {
this.loading = true
// 先打开一个空的新窗口,再请求
this.newWin = window.open()
let url = ''
if (/(Android)/i.test(navigator.userAgent)) { // 判断是否为Android手机
url = 'aliPay/toPayAsWeb'
} else if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) { // 判断是否为苹果手机
url = 'aliPay/toPayAsWeb'
} else {
url = 'aliPay/toPayAsPC'
}
toAliPay(url, this.form).then(res => {
this.loading = false
this.url = res
}).catch(err => {
this.loading = false
console.log(err.response.data.message)
})
} else {
return false
}
})
}
}
}
</script>
<style scoped>
</style>

View File

@@ -1,9 +1,9 @@
<template>
<el-tabs v-model="activeName" style="padding-left: 5px;" @tab-click="handleClick">
<el-tabs v-model="activeName" style="padding-left: 5px;">
<el-tab-pane label="邮箱配置" name="first">
<Config/>
</el-tab-pane>
<el-tab-pane label="邮件测试" name="second">
<el-tab-pane label="发送邮件" name="second">
<Send/>
</el-tab-pane>
<el-tab-pane label="使用说明" name="third">
@@ -20,12 +20,7 @@ export default {
components: { Config, Send, Description },
data() {
return {
activeName: 'first'
}
},
methods: {
handleClick(tab, event) {
console.log(tab, event)
activeName: 'second'
}
}
}

View File

@@ -44,7 +44,10 @@ export default {
},
computed: {
...mapGetters([
'imagesUploadApi'
// sm.ms图床
'imagesUploadApi',
// 七牛云 按需选择
'qiNiuUploadApi'
])
},
mounted() {
@@ -54,6 +57,7 @@ export default {
editor.customConfig.uploadImgHeaders = this.headers
// 自定义文件名,不可修改,修改后会上传失败
editor.customConfig.uploadFileName = 'file'
// 上传到哪儿,按需选择
editor.customConfig.uploadImgServer = this.imagesUploadApi // 上传图片到服务器
editor.customConfig.onchange = (html) => {
this.form.content = html

View File

@@ -13,7 +13,7 @@
<el-table-column prop="size" label="文件大小"/>
<el-table-column prop="height" label="高度"/>
<el-table-column prop="width" label="宽度"/>
<el-table-column prop="createTime" label="创建日期">
<el-table-column width="180px" prop="createTime" label="创建日期">
<template slot-scope="scope">
<span>{{ time(scope.row.createTime) }}</span>
</template>

View File

@@ -51,7 +51,7 @@ export default {
this.pictures.push({ uid, id })
},
handleBeforeRemove(file, fileList) {
for (var i = 0; i < this.pictures.length; i++) {
for (let i = 0; i < this.pictures.length; i++) {
if (this.pictures[i].uid === file.uid) {
del(this.pictures[i].id).then(res => {})
return true

View File

@@ -21,7 +21,6 @@ export default {
methods: {
checkPermission,
toQuery() {
console.log(this.query)
this.$parent.page = 0
this.$parent.init()
}

View File

@@ -0,0 +1,30 @@
<template>
<el-tabs v-model="activeName" style="padding-left: 5px;">
<el-tab-pane label="存储配置" name="first">
<Config/>
</el-tab-pane>
<el-tab-pane label="文件列表" name="second">
<List/>
</el-tab-pane>
<el-tab-pane label="使用说明" name="third">
<Description/>
</el-tab-pane>
</el-tabs>
</template>
<script>
import Config from './module/config'
import List from './module/list'
import Description from './module/description'
export default {
components: { Config, List, Description },
data() {
return {
activeName: 'second'
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,100 @@
<template>
<el-form ref="form" :model="form" :rules="rules" style="margin-top: 6px;" size="small" label-width="130px">
<el-form-item label="Access Key" prop="accessKey">
<el-input v-model="form.accessKey" style="width: 35%"/>
<span style="color: #C0C0C0;margin-left: 10px;">accessKey在安全中心秘钥管理中查看</span>
</el-form-item>
<el-form-item label="Secret Key" prop="secretKey">
<el-input v-model="form.secretKey" type="password" style="width: 35%;"/>
<span style="color: #C0C0C0;margin-left: 10px;">secretKey在安全中心秘钥管理中查看</span>
</el-form-item>
<el-form-item label="空间名称" prop="bucket">
<el-input v-model="form.bucket" style="width: 35%;"/>
<span style="color: #C0C0C0;margin-left: 10px;">存储空间名称作为唯一的 Bucket 识别符</span>
</el-form-item>
<el-form-item label="外链域名" prop="host">
<el-input v-model="form.host" style="width: 35%;"/>
<span style="color: #C0C0C0;margin-left: 10px;">外链域名可自定义需在七牛云绑定</span>
</el-form-item>
<el-form-item label="存储区域" prop="port">
<el-select v-model="form.zone" placeholder="请选择存储区域">
<el-option
v-for="item in zones"
:key="item"
:label="item"
:value="item"/>
</el-select>
<span style="color: #C0C0C0;margin-left: 10px;">北美区域尚未支持自定义数据处理服务一旦创建区域无法修改请谨慎选择</span>
</el-form-item>
<el-form-item label="空间类型" prop="host">
<el-radio v-model="form.type" label="公开">公开</el-radio>
<el-radio v-model="form.type" label="私有" >私有</el-radio>
<span style="color: #C0C0C0;margin-left: 10px;">公开和私有仅对 Bucket 的读文件生效修改删除写入等对 Bucket 的操作均需要拥有者的授权才能进行操作</span>
</el-form-item>
<el-button :loading="loading" style="margin-left:5%;" size="medium" type="success" @click="doSubmit">保存配置</el-button>
</el-form>
</template>
<script>
import { get, update } from '@/api/qiniu'
export default {
name: 'Config',
data() {
return {
zones: ['华东', '华北', '华南', '北美', '东南亚'],
loading: false, form: { accessKey: '', secretKey: '', bucket: '', host: '', zone: '', type: '' },
rules: {
accessKey: [
{ required: true, message: '请输入accessKey', trigger: 'blur' }
],
secretKey: [
{ required: true, message: '请输入secretKey', trigger: 'blur' }
],
bucket: [
{ required: true, message: '请输入空间名称', trigger: 'blur' }
],
host: [
{ required: true, message: '请输入外链域名', trigger: 'blur' }
],
type: [
{ required: true, message: '空间类型不能为空', trigger: 'blur' }
]
}
}
},
created() {
this.init()
},
methods: {
init() {
get().then(res => {
this.form = res
})
},
doSubmit() {
this.$refs['form'].validate((valid) => {
if (valid) {
this.loading = true
update(this.form).then(res => {
this.$notify({
title: '修改成功',
type: 'success',
duration: 2500
})
this.loading = false
}).catch(err => {
this.loading = false
console.log(err.response.data.message)
})
} else {
return false
}
})
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,66 @@
<template>
<div>
<blockquote class="my-blockquote">注意</blockquote>
<pre class="my-code">
1尽量使用英文文件名进行上传中文文件名在私有空间下下载会出现问题
2配置时外链域名需带上协议也就是必须http/https开头
3如果七牛云中存在数据使用同步按钮即可将数据同步到数据库
4本次集成了七牛云的常用操作上传下载删除同步支持私有空间上传下载
5项目中配置存入数据库如需测试请使用临时空间进行测试测试完成及时修改配置反正数据泄露</pre>
<blockquote class="my-blockquote"> 开始使用</blockquote>
<pre class="my-code">
#引入依赖
&lt;dependency&gt;
&lt;groupId&gt;com.qiniu&lt;/groupId&gt;
&lt;artifactId&gt;qiniu-java-sdk&lt;/artifactId&gt;
&lt;version&gt;[7.2.0, 7.2.99]&lt;/version&gt;
&lt;dependency&gt;
#简单的上传文件
//构造一个带指定Zone对象的配置类
Configuration cfg = new Configuration(Zone.zone0());
//...其他参数参考类注释
UploadManager uploadManager = new UploadManager(cfg);
//...生成上传凭证,然后准备上传
String accessKey = "your access key";
String secretKey = "your secret key";
String bucket = "your bucket name";
//默认不指定key的情况下以文件内容的hash值作为文件名
String key = null;
try {
byte[] uploadBytes = "hello qiniu cloud".getBytes("utf-8");
Auth auth = Auth.create(accessKey, secretKey);
String upToken = auth.uploadToken(bucket);
try {
Response response = uploadManager.put(uploadBytes, key, upToken);
//解析上传成功的结果
DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
System.out.println(putRet.key);
System.out.println(putRet.hash);
} catch (QiniuException ex) {
Response r = ex.response;
System.err.println(r.toString());
try {
System.err.println(r.bodyString());
} catch (QiniuException ex2) {
//ignore
}
}
} catch (UnsupportedEncodingException ex) {
//ignore
}</pre>
<blockquote class="my-blockquote">更多帮助</blockquote>
<pre class="my-code">更多帮助请查看系统源码或者七牛云java开发文档
七牛云官网<a style="color: #00a2d4" href="https://sso.qiniu.com/" target="_blank">https://sso.qiniu.com/</a>
七牛云java开发文档<a style="color: #00a2d4" href="https://developer.qiniu.com/kodo/sdk/1239/java#3" target="_blank">https://developer.qiniu.com/kodo/sdk/1239/java#3</a></pre>
</div>
</template>
<script>
import '@/styles/description.scss'
export default {
name: 'Description'
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,133 @@
<template>
<div class="app-container">
<search :query="query"/>
<!--表格渲染-->
<el-table v-loading="loading" :data="data" size="small" border style="width: 100%;">
<el-table-column :show-overflow-tooltip="true" prop="key" label="文件名"/>
<el-table-column prop="bucket" label="空间名称"/>
<el-table-column :show-overflow-tooltip="true" prop="url" label="地址/私有空间需下载访问">
<template slot-scope="scope">
<a :href="scope.row.url" style="color: #42b983" target="_blank">{{ scope.row.url }}</a>
</template>
</el-table-column>
<el-table-column prop="size" label="文件大小"/>
<el-table-column prop="type" label="空间类型"/>
<el-table-column width="180px" prop="updateTime" label="更新日期">
<template slot-scope="scope">
<span>{{ time(scope.row.updateTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="160px" align="center">
<template slot-scope="scope">
<el-button
:loading="downloadLoading"
size="mini"
@click="download(scope.row.id)">下载</el-button>
<el-popover
v-if="checkPermission(['ADMIN','PICTURE_ALL','PICTURE_DELETE'])"
v-model="scope.row.delPopover"
placement="top"
width="180">
<p>确定删除本条数据吗</p>
<div style="text-align: right; margin: 0">
<el-button size="mini" type="text" @click="scope.row.delPopover = false">取消</el-button>
<el-button :loading="delLoading" type="primary" size="mini" @click="subDelete(scope.$index, scope.row)">确定</el-button>
</div>
<el-button slot="reference" type="danger" size="mini" @click="scope.row.delPopover = true">删除</el-button>
</el-popover>
</template>
</el-table-column>
</el-table>
<!--分页组件-->
<el-pagination
:total="total"
style="margin-top: 8px;"
layout="total, prev, pager, next, sizes"
@size-change="sizeChange"
@current-change="pageChange"/>
</div>
</template>
<script>
import checkPermission from '@/utils/permission' // 权限判断函数
import initData from '../../../../mixins/initData'
import { del, download } from '@/api/qiniu'
import { parseTime } from '@/utils/index'
import search from './module/search'
export default {
components: { search },
mixins: [initData],
data() {
return {
url: '',
// 新窗口的引用
newWin: null,
downloadLoading: false, delLoading: false, sup_this: this
}
},
watch: {
url(newVal, oldVal) {
if (newVal && this.newWin) {
this.newWin.sessionStorage.clear()
this.newWin.location.href = newVal
// 重定向后把url和newWin重置
this.url = ''
this.newWin = null
}
}
},
created() {
this.$nextTick(() => {
this.init()
})
},
methods: {
checkPermission,
beforeInit() {
this.url = 'api/qiNiuContent'
const sort = 'id,desc'
const query = this.query
const value = query.value
this.params = { page: this.page, size: this.size, sort: sort }
if (value) { this.params['key'] = value }
return true
},
subDelete(index, row) {
this.delLoading = true
del(row.id).then(res => {
this.delLoading = false
row.delPopover = false
this.init()
this.$notify({
title: '删除成功',
type: 'success',
duration: 2500
})
}).catch(err => {
this.delLoading = false
row.delPopover = false
console.log(err.response.data.message)
})
},
download(id) {
this.downloadLoading = true
// 先打开一个空的新窗口,再请求
this.newWin = window.open()
download(id).then(res => {
this.downloadLoading = false
this.url = res
}).catch(err => {
this.downloadLoading = false
console.log(err.response.data.message)
})
},
time(time) {
return parseTime(time)
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,90 @@
<template>
<div>
<el-button class="filter-item" size="mini" type="primary" icon="el-icon-upload" @click="dialog = true">上传文件</el-button>
<el-dialog :visible.sync="dialog" width="400px" @close="doSubmit">
<el-upload
:before-remove="handleBeforeRemove"
:on-success="handleSuccess"
:on-error="handleError"
:file-list="fileList"
:headers="headers"
:action="qiNiuUploadApi"
class="upload-demo"
multiple>
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" style="display: block;width: 330px" class="el-upload__tip">请勿上传违法文件且文件不超过5M</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="doSubmit">确认</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import { del } from '@/api/qiniu'
import { getToken } from '@/utils/auth'
export default {
data() {
return {
headers: {
'Authorization': 'Bearer ' + getToken()
},
dialog: false,
dialogImageUrl: '',
dialogVisible: false,
fileList: [],
files: []
}
},
computed: {
...mapGetters([
'qiNiuUploadApi'
])
},
methods: {
handleSuccess(response, file, fileList) {
const uid = file.uid
const id = response.id
this.files.push({ uid, id })
},
handleBeforeRemove(file, fileList) {
for (let i = 0; i < this.files.length; i++) {
if (this.files[i].uid === file.uid) {
del(this.files[i].id).then(res => {})
return true
}
}
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url
this.dialogVisible = true
},
// 刷新列表数据
doSubmit() {
this.fileList = []
this.dialogVisible = false
this.dialogImageUrl = ''
this.dialog = false
this.$parent.$parent.init()
},
// 监听上传失败
handleError(e, file, fileList) {
const msg = JSON.parse(e.message)
this.$notify({
title: msg.message,
type: 'error',
duration: 2500
})
}
}
}
</script>
<style scoped>
div{
display: inline-block;
margin-left: 5px;
margin-right: 5px;
}
</style>

View File

@@ -0,0 +1,54 @@
<template>
<div class="head-container">
<el-input v-model="query.value" clearable placeholder="输入文件名称搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="toQuery"/>
<el-button class="filter-item" size="mini" type="primary" icon="el-icon-search" @click="toQuery">搜索</el-button>
<add/>
<el-button :icon="icon" class="filter-item" size="mini" type="primary" @click="synchronize">{{ buttonName }}</el-button>
</div>
</template>
<script>
import add from './add'
import { sync } from '@/api/qiniu'
// 查询条件
export default {
components: { add },
props: {
query: {
type: Object,
required: true
}
},
data() {
return {
icon: 'el-icon-refresh',
buttonName: '同步数据'
}
},
methods: {
toQuery() {
this.$parent.page = 0
this.$parent.init()
},
synchronize() {
this.icon = 'el-icon-loading'
this.buttonName = '同步中'
sync().then(res => {
this.icon = 'el-icon-refresh'
this.buttonName = '同步数据'
this.$message({
showClose: true,
message: '数据同步成功',
type: 'success',
duration: 1500
})
this.toQuery()
}).catch(err => {
this.icon = 'el-icon-refresh'
this.buttonName = '同步数据'
console.log(err.response.data.message)
})
}
}
}
</script>