1. 复制
- template
<a-button type="primary" @click="copyUrl(item.response)">Copy URL</a-button>
- methods
copyUrl (shareLink) { var input = document.createElement('input') input.value = shareLink document.body.appendChild(input) input.select() document.execCommand('Copy') document.body.removeChild(input) this.$message.success('复制成功') }
2. 图片预览v-viewer
- 安装
npm install v-viewer -S
- 引入
import 'viewerjs/dist/viewer.css' import Viewer from 'v-viewer' import Vue from 'vue' Vue.use(Viewer)
- 使用
只需要将v-viewer指令添加到任意元素即可,该元素下的所有img元素都会被viewer自动处理。(放置for循环外,否则无法切换上下张)<div v-if="title === '安卓素材'" class="material_box" v-viewer> <div v-for="item in recordAndroid" :key="item.id" class="material_item"> <img :src="item.materialUrl" alt=""> <div class="btns"> <a-button type="primary" @click="copyUrl(item.response)">Copy URL</a-button> </div> </div> </div>
3. 阻止浏览器自动填充表单
-
bug: 新建账密时自动填充了当前账号的信息
-
解决:
<!-- 阻止浏览器自动填充表单 start-->
<input type="password" class="hide" id="passWord"/>
<input type="text" class="hide" id="userName"/>
<!-- 阻止浏览器自动填充表单 end-->
<a-form-item label='用户名' v-bind="formItemLayout" :validateStatus="validateStatus" :help="help">
<a-input type="text" @blur="handleUserNameBlur" placeholder="用户名不能少于4个字符" v-decorator="['username',{rules: [{ required: true, message: '用户名不能为空'}]}]"/>
</a-form-item>
<a-form-item label='密码' v-bind="formItemLayout">
<a-input type='password' placeholder="至少6位密码,区分大小写"
v-decorator="[
'password',
{rules: [
{ required: true, message: '密码不能为空'},
{ min: 6, message: '至少6位密码'},
{ validator: this.handlePasswordLevel }],validateTrigger: ['change','blur']}]"/>
</a-form-item>
将迷惑浏览器的两个input框隐藏掉
.hide{
width: 0;
position: absolute;
border: transparent;
}
- 注意 '假’input框的id不要和真input的id重复哦
4. 禁止表单自动提示
- 像这样~
- 解决:
autocomplete="off"
属性
可以写在input上
也可以写在form上
html <a-form :form="form" autocomplete="off">
5. 图片在固定的盒子里自适应
- css
img {
width: auto;
height: auto;
max-height: 100%;
max-width: 100%;
}
- 效果
6. 新旧密码及强度验证
<template>
<div>
<!-- 密码修改 -->
<a-modal
title="密码修改"
:keyboard="false"
:maskClosable="false"
:closable="false"
v-model="show"
@cancel="cancelUpdatePassword"
@ok="handleUpdatePassword">
<a-form :autoFormCreate="(form)=>{this.form = form}">
<a-form-item
label='旧密码'
v-bind="formItemLayout"
fieldDecoratorId="oldPassword"
:fieldDecoratorOptions="{rules: [{ required: true, message: '请输入旧密码'}, { validator: this.handleOldPassowrd }], validateTrigger: ['blur']}">
<a-input type="password"
autocomplete="false"
v-model="oldPassword"
placeholder="请输入旧密码"></a-input>
</a-form-item>
<a-popover placement="rightTop" trigger="click" :visible="state.passwordLevelChecked">
<template slot="content">
<div :style="{ width: '240px' }">
<div :class="['update-password', passwordLevelClass]">强度:<span>{{ passwordLevelName }}</span></div>
<a-progress :percent="state.percent" :showInfo="false" :strokeColor=" passwordLevelColor "/>
<div style="margin-top: 10px;">
<span>请至少输入 6 个字符。请不要使用容易被猜到的密码。</span>
</div>
</div>
</template>
<a-form-item
label='新密码'
v-bind="formItemLayout"
fieldDecoratorId="password"
:fieldDecoratorOptions="{rules: [{ required: true, message: '至少6位密码,区分大小写'}, { validator: this.handlePasswordLevel }], validateTrigger: ['change', 'blur']}">
<a-input type="password"
@click="handlePasswordInputClick"
v-model="newPassword"
autocomplete="false"
placeholder="至少6位密码,区分大小写"></a-input>
</a-form-item>
</a-popover>
<a-form-item
label='再次确认'
v-bind="formItemLayout"
fieldDecoratorId="password2"
:fieldDecoratorOptions="{rules: [{ required: true, message: '至少6位密码,区分大小写' }, { validator: this.handlePasswordCheck }], validateTrigger: ['change', 'blur']}">
<a-input type="password" autocomplete="false" placeholder="确认密码"></a-input>
</a-form-item>
</a-form>
</a-modal>
</div>
</template>
<script>
const formItemLayout = {
labelCol: { span: 4 },
wrapperCol: { span: 18 }
}
const levelNames = {
0: '低',
1: '低',
2: '中',
3: '强'
}
const levelClass = {
0: 'error',
1: 'error',
2: 'warning',
3: 'success'
}
const levelColor = {
0: '#ff0000',
1: '#ff0000',
2: '#ff7e05',
3: '#52c41a'
}
export default {
props: {
updatePasswordModelVisible: {
default: false
},
user: {
required: true
}
},
data () {
return {
form: null,
formItemLayout,
state: {
passwordLevel: 0,
passwordLevelChecked: false,
percent: 10,
progressColor: '#FF0000'
},
oldPassword: '',
newPassword: '',
validateStatus: '',
help: ''
}
},
computed: {
show: {
get: function () {
return this.updatePasswordModelVisible
},
set: function () {
}
},
passwordLevelClass () {
return levelClass[this.state.passwordLevel]
},
passwordLevelName () {
return levelNames[this.state.passwordLevel]
},
passwordLevelColor () {
return levelColor[this.state.passwordLevel]
}
},
methods: {
isMobile () {
return this.$store.state.setting.isMobile
},
cancelUpdatePassword () {
this.state.passwordLevelChecked = false
this.form.resetFields()
this.$emit('cancel')
},
handleUpdatePassword () {
this.form.validateFields((err, values) => {
if (!err) {
this.$put('user/password', {
password: this.newPassword,
username: this.user.username
}).then(() => {
this.state.passwordLevelChecked = false
this.$emit('success')
this.form.resetFields()
})
}
})
},
handlePasswordLevel (rule, value, callback) {
let level = 0
// 判断这个字符串中有没有数字
if (/[0-9]/.test(value)) {
level++
}
// 判断字符串中有没有字母
if (/[a-zA-Z]/.test(value)) {
level++
}
// 判断字符串中有没有特殊符号
if (/[^0-9a-zA-Z_]/.test(value)) {
level++
}
this.state.passwordLevel = level
this.state.percent = level * 30
if (level >= 2) {
if (level >= 3) {
this.state.percent = 100
}
callback()
} else {
if (level === 0) {
this.state.percent = 10
}
callback(new Error('密码强度不够'))
}
},
handlePasswordCheck (rule, value, callback) {
let password = this.form.getFieldValue('password')
if (value === undefined) {
callback(new Error('请输入密码'))
}
if (value && password && value.trim() !== password.trim()) {
callback(new Error('两次密码不一致'))
}
callback()
},
handlePasswordInputClick () {
if (!this.isMobile()) {
this.state.passwordLevelChecked = true
return
}
this.state.passwordLevelChecked = false
},
handleOldPassowrd (rule, value, callback) {
let password = this.oldPassword
if (this.oldPassword.trim().length) {
this.$get('user/password/check', {
password: password,
username: this.user.username
}).then((r) => {
if (r.data) {
callback()
} else {
callback(new Error('旧密码不正确'))
}
})
} else {
callback()
}
}
}
}
</script>
<style lang="less">
.update-password {
&.error {
color: #ff0000;
}
&.warning {
color: #ff7e05;
}
&.success {
color: #52c41a;
}
}
</style>
表格第一行总计
- 像这样~
- 表头:
columns () { return [{ title: '日期', dataIndex: 'bizDate', }, { title: '渠道广告位', dataIndex: 'channelAdPosition' }, { title: '渠道', dataIndex: 'channelName' }, { title: '位置', dataIndex: 'adTypeName' }, { title: 'APP名称', dataIndex: 'channelAppName' }, { title: '系统', dataIndex: 'os' }, { title: '请求数', dataIndex: 'requestCount' }, { title: '成功数', dataIndex: 'successCount' }, { title: '失败数', dataIndex: 'failCount' }, { title: '超时数', dataIndex: 'timeoutCount' }, { title: '展现数', dataIndex: 'showCount' }, { title: '点击数', dataIndex: 'clickCount' }, { title: '收益', dataIndex: 'income' }, { title: 'CPC', dataIndex: 'cpc' }, { title: 'CPM', dataIndex: 'cpm' }] },
- 数据处理
fetch (params = {}) {
this.loading = true
this.$get('地址', {
...params
}).then((r) => {
let data = r.data.data
this.loading = false
this.dataSource = data
let requestCount = 0
let successCount = 0
let showCount = 0
let clickCount = 0
let failCount = 0
let timeoutCount = 0
let os = '总计'
for (var i = 0; i < this.dataSource.length; i++) {
let item = this.dataSource[i]
requestCount += item.requestCount
successCount += item.successCount
showCount += item.showCount
clickCount += item.clickCount
failCount += item.failCount
timeoutCount += item.timeoutCount
}
let arr = {
clickCount: clickCount,
os: os,
requestCount: requestCount,
showCount: showCount,
successCount: successCount,
failCount: failCount,
timeoutCount: timeoutCount
}
this.dataSource.splice(0, 0, arr)
})
}