You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
flyapps/fir_client/src/components/FirApps.vue

1206 lines
43 KiB

<template>
<div>
<el-container>
<el-header style="height: 100px">
<el-dialog
:title="getDelappTitle"
:visible.sync="willDeleteApp"
width="50%">
<span>删除后不可恢复请谨慎操作</span>
<span slot="footer" class="dialog-footer">
<el-button @click="willDeleteApp = false"> </el-button>
<el-button type="danger" @click="delApp"> </el-button>
</span>
</el-dialog>
<el-dialog class="upload-app"
:visible.sync="willuploadApp"
:destroy-on-close="true"
:show-close="!uploading"
width="40%"
:close-on-click-modal="false"
@closed="closeUpload">
<div v-if="!uploading" style="">
<el-row :gutter="20">
<el-col :span="6">
<div class="grid-content bg-purple">
<div style="width: 100px;height: 100px">
<el-avatar shape="square" :size="100" :src="analyseappinfo.icon"></el-avatar>
</div>
</div>
</el-col>
<el-col :span="18">
<div class="grid-content bg-purple">
<el-row :gutter="20" style="margin-top: 8px;">
<el-col :span="18">
{{ analyseappinfo.version}} (Build {{ analyseappinfo.buildversion}}) {{
analyseappinfo.release_type_id|getiOStype}}
</el-col>
</el-row>
<el-row :gutter="20" style="margin-top: 18px;">
<el-col :span="18">
<el-input v-model="analyseappinfo.appname"></el-input>
</el-col>
</el-row>
</div>
</el-col>
</el-row>
<el-divider></el-divider>
<el-row :gutter="20">
<el-col :span="6">
<div class="grid-content bg-purple">
<el-row :gutter="20" style="margin-top: 18px;">
<el-col :span="18" :offset="8">
<span>短连接</span>
</el-col>
</el-row>
</div>
</el-col>
<el-col :span="18">
<div class="grid-content bg-purple">
<el-row :gutter="20" style="margin-top: 10px;">
<el-col :span="18">
<el-input v-model="analyseappinfo.short">
<template slot="prepend">{{analyseappinfo.domain_name}}/</template>
</el-input>
</el-col>
</el-row>
</div>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="6">
<div class="grid-content bg-purple">
<el-row :gutter="20" style="margin-top: 18px;">
<el-col :span="18" :offset="8">
<span>更新日志</span>
</el-col>
</el-row>
</div>
</el-col>
<el-col :span="18">
<div class="grid-content bg-purple">
<el-row :gutter="20" style="margin-top: 10px;">
<el-col :span="18">
<el-input type="textarea"
v-model="analyseappinfo.changelog"
placeholder="请输入内容"
rows="5"
show-word-limit></el-input>
</el-col>
</el-row>
</div>
</el-col>
</el-row>
</div>
<div v-if="uploading" class="wrap">
<!--包裹所有元素的容器-->
<div class="cube">
<!--前面图片 -->
<div class="out_front">
<img src="../assets/imgs/1.png" class="pic">
</div>
<!--后面图片 -->
<div class="out_back">
<img src="../assets/imgs/5.png" class="pic">
</div>
<!--左面图片 -->
<div class="out_left">
<img src="../assets/imgs/6.png" class="pic">
</div>
<!--右面图片 -->
<div class="out_right">
<img src="../assets/imgs/7.png" class="pic">
</div>
<!--上面图片 -->
<div class="out_top">
<img src="../assets/imgs/8.png" class="pic">
</div>
<!--下面图片 -->
<div class="out_bottom">
<img src="../assets/imgs/9.png" class="pic">
</div>
<!--小正方体 -->
<span class="in_front">
<img :src="this.analyseappinfo.icon" class="in_pic">
</span>
<span class="in_back">
<img :src="this.analyseappinfo.icon" class="in_pic">
</span>
<span class="in_left">
<img :src="this.analyseappinfo.icon" class="in_pic">
</span>
<span class="in_right">
<img :src="this.analyseappinfo.icon" class="in_pic">
</span>
<span class="in_top">
<img :src="this.analyseappinfo.icon" class="in_pic">
</span>
<span class="in_bottom">
<img :src="this.analyseappinfo.icon" class="in_pic">
</span>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-progress :text-inside="true" :stroke-width="26" :percentage="uploadprocess"
v-if="uploadflag === true"></el-progress>
<el-button type="primary" plain @click="uploadcloud" v-else>{{ analyseappinfo.is_new|get_upload_text}}</el-button>
</span>
</el-dialog>
<el-row>
<el-col :span="4">
<el-radio-group v-model="searchfromtype">
<el-radio-button label="android" icon="el-icon-mobile-phone"><i
class="iconfont icon-android2"/>
</el-radio-button>
<el-radio-button label="ios"><i class="iconfont icon-ios"/>
</el-radio-button>
</el-radio-group>
</el-col>
<el-col :span="5">
<el-input
placeholder="请输入名称搜索"
v-model="keysearch"
@click="searchapps"
clearable prefix-icon="el-icon-search">
</el-input>
</el-col>
<el-col :span="7" class="surplus-card">
<el-row>
<el-col :span="8">
<div>
<span class="name">iOS应用</span>
<el-divider direction="vertical"></el-divider>
</div>
<div>
<span class="value">{{ hdata.ios_count }}</span>
<el-divider direction="vertical"></el-divider>
</div>
</el-col>
<el-col :span="8">
<div>
<span class="name">Android应用</span>
<el-divider direction="vertical"></el-divider>
</div>
<div>
<span class="value">{{ hdata.android_count }}</span>
<el-divider direction="vertical"></el-divider>
</div>
</el-col>
<el-col :span="8">
<div>
<span class="name">总应用</span>
<el-divider direction="vertical"></el-divider>
</div>
<div>
<span class="value">{{ hdata.ios_count + hdata.android_count}}</span>
<el-divider direction="vertical"></el-divider>
</div>
</el-col>
</el-row>
</el-col>
<el-col :span="8" class="surplus-card">
<el-row>
<el-col :span="8">
<div>
<span class="name">今日苹果下载次数</span>
<el-divider direction="vertical"></el-divider>
</div>
<div>
<span class="value">{{ hdata.ios_today_hits_count }}</span>
<el-divider direction="vertical"></el-divider>
</div>
</el-col>
<el-col :span="8">
<div>
<span class="name">今日安卓下载次数</span>
<el-divider direction="vertical"></el-divider>
</div>
<div>
<span class="value">{{ hdata.android_today_hits_count }}</span>
<el-divider direction="vertical"></el-divider>
</div>
</el-col>
<el-col :span="8">
<div>
<span class="name">总共下载次数</span>
<el-divider direction="vertical"></el-divider>
</div>
<div>
<span class="value">{{ hdata.all_hits_count}}</span>
<el-divider direction="vertical"></el-divider>
</div>
</el-col>
</el-row>
</el-col>
</el-row>
</el-header>
<div
ref="appmain" style="margin: 40px 20px">
<el-row style="max-height: 460px; margin: 0 auto;" :gutter="10" class="page-apps">
<el-col style="width: 33%;height: 460px ">
<div class=" app-animator appdownload">
<div class=" card app card-ios" style="padding: 0">
<el-upload
drag
:show-file-list="false"
:before-upload="beforeAvatarUpload"
accept=".ipa , .apk"
action="#"
multiple>
<i class="el-icon-upload" style="color: #fff"></i>
<div class="el-upload__text" style="color: #fff;margin-top: 20px">拖拽到这里上传</div>
</el-upload>
</div>
</div>
</el-col>
<el-col style="width: 33%;height: 460px"
v-for="(r,index) in applists" :key="r.id" @click="appInfos(index)">
<div class=" app-animator">
<div class="card app card-ios">
<i class=" type-icon iconfont icon-ios" v-if="r.type === 1" src=""></i>
<i class="type-icon iconfont icon-android2" v-if="r.type === 0"></i>
<div class="type-mark" v-if="r.type === 1"></div>
<div class="type-mark" style="border-top: 48px solid #A4C639" v-if="r.type === 0"></div>
<a class="appicon" @click="appInfos(r)">
<img class="icon ng-isolate-scope" width="100" height="100"
:src="r.master_release.icon_url|make_icon_url"></a>
<div class="combo-info ng-scope" v-if="r.has_combo !== null ">
<i class="el-icon-copy-document" style="transform:rotateX(180deg);"></i>
<a @click="appInfos(r.has_combo)">
<img class="icon ng-isolate-scope" width="45" height="45"
:src="r.has_combo.master_release.icon_url|make_icon_url">
</a>
</div>
<br>
<p class="appname"><i class="el-icon-user-solid"></i><span class="ng-binding">{{ r.name }}</span>
</p>
<table>
<tbody>
<tr>
<td class="ng-binding">应用大小:</td>
<td><span
class="ng-binding">{{ r.master_release.binary_size }}</span>
</td>
</tr>
<tr>
<td class="ng-binding">应用平台:</td>
<td><span class="ng-binding">{{ r.type |getapptype }}</span></td>
</tr>
<tr>
<td class="ng-binding">应用标识:</td>
<td><span class="ng-binding">{{ r.bundle_id | autoformat }}</span></td>
</tr>
<tr>
<td class="ng-binding">最新版本:</td>
<td><span class="ng-binding">{{ r.master_release.app_version }}(Build {{ r.master_release.build_version }})</span>
</td>
</tr>
<tr v-if="r.type === 1 && r.master_release.binary_url === ''">
<td class="ng-binding">打包类型:</td>
<td><span class="ng-binding">
{{ r.master_release.release_type|getiOStype }}
</span></td>
</tr>
<tr v-if=" r.master_release.binary_url !== ''">
<td>第三方平台下载:</td>
<td>
<span>
<el-tooltip :content="r.master_release.binary_url" placement="top">
<a target="_blank" :href="r.master_release.binary_url">{{ r.master_release.binary_url| autoformat}}</a>
</el-tooltip>
</span>
</td>
</tr>
</tbody>
</table>
<div class="action">
<el-button @click="appInfos(r)">
<i class="icon-pen el-icon-edit"></i> 管理
</el-button>
<el-button @click="appDownload(r)" target="_blank" class="ng-binding">
<i class="icon-eye el-icon-view"></i> 预览
</el-button>
<el-button @click="DeleteApp(r)" class="btn btn-remove" icon="el-icon-delete"
circle></el-button>
</div>
</div>
</div>
</el-col>
</el-row>
</div>
</el-container>
</div>
</template>
<script>
import {getapps, deleteapp, analyseApps, getuploadurl} from "../restful";
import {
getScrollHeight,
getScrollTop,
getWindowHeight,
getappinfo,
uploadqiniuoss,
dataURLtoFile,
uploadaliyunoss,
uploadlocalstorage
} from "../utils";
export default {
name: "FirApps",
data() {
return {
analyseappinfo: {'appname': '', 'short': '', 'changelog': ''},
keysearch: '',
searchfromtype: '',
applists: [],
orgapplists: [],
hdata: {},
willDeleteApp: false,
willuploadApp: false,
uploading: false,
delapp: {},
has_next: false,
query: {'page': 1, size: 20},
searchflag: false,
uploadflag: false,
autoloadflag: true,
firstloadflag: true,
currentfile: null,
uploadprocess: 0,
uploadsuccess: 0,
loadingobj: null
}
}, methods: {
updateappinfo(file) {
this.uploadsuccess += 1;
if (this.uploadsuccess === 2) {
this.$message.success(file.name + '上传成功');
analyseApps(data => {
if (data.code === 1000) {
let app_uuid = this.analyseappinfo.app_uuid;
this.closeUpload();
this.$router.push({name: 'FirAppInfostimeline', params: {id: app_uuid}});
}
}, {'methods': 'PUT', 'data': this.analyseappinfo});
}
},
uploadtostorage(file, certinfo) {
if (this.analyseappinfo.storage === 1) {
// eslint-disable-next-line no-unused-vars,no-unreachable
uploadqiniuoss(file, certinfo, this, res => {
this.updateappinfo(file)
}, process => {
if (this.uploadsuccess === 1) {
this.uploadprocess = process;
}
})
} else if (this.analyseappinfo.storage === 2) {
// eslint-disable-next-line no-unused-vars
uploadaliyunoss(file, certinfo, this, res => {
this.updateappinfo(file)
}, process => {
if (this.uploadsuccess === 1) {
this.uploadprocess = process;
}
});
} else {
//本地
certinfo.upload_url = getuploadurl();
certinfo.ftype = 'app';
certinfo.app_id = this.analyseappinfo.app_uuid;
// eslint-disable-next-line no-unused-vars,no-unreachable
uploadlocalstorage(file, certinfo, this, res => {
this.updateappinfo(file)
}, process => {
if (this.uploadsuccess === 1) {
this.uploadprocess = process;
}
})
}
},
getuploadtoken(loading) {
analyseApps(data => {
if (data.code === 1000) {
this.analyseappinfo.short = data.data.short;
this.analyseappinfo.domain_name = data.data.domain_name;
this.analyseappinfo.app_uuid = data.data.app_uuid;
this.analyseappinfo.upload_token = data.data.upload_token;
this.analyseappinfo.upload_key = data.data.upload_key;
this.analyseappinfo.png_key = data.data.png_key;
this.analyseappinfo.png_token = data.data.png_token;
this.analyseappinfo.storage = data.data.storage;
this.analyseappinfo.is_new = data.data.is_new;
this.analyseappinfo.binary_url = data.data.binary_url;
this.willuploadApp = true;
} else {
this.$message.error("上传token获取失败,请刷新重试")
}
loading.close();
}, {
'methos': true,
'data': {"bundleid": this.analyseappinfo.bundleid, "type": this.analyseappinfo.type}
})
},
uploadcloud() {
if (this.analyseappinfo.binary_url !== '') {
this.$confirm(`该应用存在第三方下载链接 <a target="_blank" href="${this.analyseappinfo.binary_url}"> ${this.analyseappinfo.binary_url} </a>更新之后将不会自动跳转第三方下载若您还需要第三方跳转请在第三方平台更新该应用`, '确定更新应用', {
confirmButtonText: '确定',
cancelButtonText: '取消',
dangerouslyUseHTMLString: true,
type: 'warning'
}).then(() => {
this.$message({
type: 'success',
message: '开始更新'
});
this.uploadstorage()
}).catch(() => {
this.$message({
type: 'info',
message: '已取消更新'
});
this.closeUpload();
});
} else {
this.uploadstorage()
}
},
uploadstorage() {
this.uploadflag = true;
this.uploading = true;
let file = dataURLtoFile(this.analyseappinfo.icon, this.analyseappinfo.png_key);
this.uploadtostorage(file, {
'upload_key': this.analyseappinfo.png_key,
'upload_token': this.analyseappinfo.png_token
});
file = this.currentfile;
this.uploadtostorage(file, {
'upload_key': this.analyseappinfo.upload_key,
'upload_token': this.analyseappinfo.upload_token
});
},
closeUpload() {
this.uploadsuccess = 0;
this.uploadprocess = 0;
this.uploadflag = false;
this.uploading = false;
this.willuploadApp = false;
this.currentfile = null;
this.uploadflag = false;
this.analyseappinfo = {};
},
searchFun() {
let keysearch = this.keysearch.replace(/^\s+|\s+$/g, "");
if (keysearch === '') {
this.searchflag = false;
this.applists = [];
this.orgapplists = [];
this.query.page = 1;
if (this.searchfromtype) {
this.getappsFun({"type": this.searchfromtype});
} else {
this.getappsFun({});
}
} else {
this.searchflag = true
}
if (this.searchflag) {
this.applists = [];
this.orgapplists = [];
if (this.searchfromtype) {
this.getappsFun({"type": this.searchfromtype, 'page': 1, size: 999});
} else {
this.getappsFun({'page': 1, size: 999});
}
}
},
auto_load() {
// eslint-disable-next-line no-console
// console.log(getScrollTop() , getWindowHeight(),getScrollTop() + getWindowHeight(), getScrollHeight());
if (getScrollTop() + getWindowHeight() >= getScrollHeight()) {
if (this.has_next) { //先判断下一页是否有数据
if (this.autoloadflag) {
this.autoloadflag = false;
if (this.applists.length === 0) {
this.query.page = 1;
} else {
this.query.page += 1;
}
if (this.searchfromtype !== '') {
this.query.type = this.searchfromtype;
}
this.getappsFun(this.query);
}
} else {
if (!this.has_next) {
this.$message.success("已经到底啦")
}
}
}
},
searchapps() {
let keysearch = this.keysearch.replace(/^\s+|\s+$/g, "");
let newapplists = [];
for (let i = 0; i < this.orgapplists.length; i++) {
if (this.orgapplists[i].name.search(keysearch) === 0) {
newapplists.push(this.orgapplists[i]);
}
}
if (keysearch === "") {
this.applists = this.orgapplists.slice();
} else {
this.applists = newapplists.slice();
}
},
getappsFun(parms) {
this.loadingobj = this.$loading({
lock: true,
text: '加载中',
spinner: 'el-icon-loading',
// background: 'rgba(0, 0, 0, 0.7)'
});
getapps(data => {
if (data.code === 1000) {
this.loadingobj.close();
if (this.firstloadflag) {
window.addEventListener('scroll', this.auto_load);
this.firstloadflag = false
}
this.autoloadflag = true;
if (this.uploadflag) {
this.applists = data.data;
this.uploadflag = false;
} else {
this.applists = this.applists.concat(data.data);
}
this.has_next = data.has_next;
this.orgapplists = this.applists.slice(); //深拷贝
this.hdata = data.hdata;
this.$store.dispatch("getUser", data.userinfo);
this.searchapps();
let upload_domain = data.hdata.upload_domain;
if (!upload_domain) {
upload_domain = location.origin;
}
// this.$store.dispatch('doucurrentapp', {'firapps':1});
} else {
this.loadingobj.close();
this.$router.push({name: 'FirLogin'});
}
}, parms);
},
beforeAvatarUpload(file) {
const loading = this.$loading({
lock: true,
text: '应用解析中',
spinner: 'el-icon-loading',
// background: 'rgba(0, 0, 0, 0.7)'
});
getappinfo(file, appinfo => {
if (appinfo.bundleid) {
this.analyseappinfo = appinfo;
this.getuploadtoken(loading);
this.currentfile = file;
} else {
this.$message.error("应用解析失败,请检查是否为APP应用")
}
}, err => {
loading.close();
this.$message.error("应用解析失败,请检查是否为APP应用");
// eslint-disable-next-line no-console
console.log('err ----> ', err);
});
return false;
},
delApp() {
this.willDeleteApp = false;
deleteapp(data => {
if (data.code === 1000) {
for (let i = 0; i < this.applists.length; i++) {
if (this.delapp.app_id === this.applists[i].app_id) {
this.applists.splice(i, 1);
this.orgapplists.splice(i, 1);
}
}
this.$message.success(this.delapp.name + '删除成功');
this.delapp = {};
} else {
this.$message.error('删除失败,请联系管理员');
}
}, {
"app_id": this.delapp.app_id
});
},
DeleteApp(delapp) {
//页面删除按钮触发
this.willDeleteApp = true;
this.delapp = delapp;
},
appInfos(app) {
this.$router.push({name: 'FirAppInfostimeline', params: {id: app.app_id}})
},
appDownload(app) {
this.$router.push({name: 'FirDownload', params: {short: app.short}})
}
}, computed: {
getDelappTitle() {
return `删除应用 ${this.delapp.name}`
},
getBH: function () {
let sch = this.$refs.appmain.scrollHeight;
if (sch === 0 || sch < window.innerHeight) {
sch = window.innerHeight;
} else {
sch += 280;
}
return sch;
}
},
filters: {
getiOStype: function (type) {
let ftype = '';
if (type === 1) {
ftype = '内测版'
} else if (type === 2) {
ftype = '企业版'
}
return ftype
},
formatsize: function (size) {
return size / 1000;
},
autoformat: function (packname) {
if ((packname.length) > 20) {
return packname.split('').slice(0, 20).join('') + '...';
} else {
return packname
}
},
getapptype: function (type) {
let ftype = '';
if (type === 0) {
ftype = 'Android'
} else {
ftype = 'iOS'
}
return ftype
},
make_icon_url(icon_url) {
if (!icon_url.startsWith("http")) {
return location.origin + icon_url
} else {
return icon_url
}
},
get_upload_text(is_new) {
if (is_new) {
return '新应用上传'
} else {
return '应用更新'
}
}
}, mounted() {
this.$store.dispatch('doucurrentapp', {});
this.getappsFun({});
// window.addEventListener('scroll',this.auto_load);
},
destroyed() {
window.removeEventListener('scroll', this.auto_load, false);
this.loadingobj.close();
},
watch: {
// eslint-disable-next-line no-unused-vars
keysearch: function (val, oldVal) {
// this.searchapps()
this.searchFun()
},
// eslint-disable-next-line no-unused-vars
searchfromtype: function (val, oldVal) {
this.applists = [];
this.query.page = 1;
// this.keysearch='';
this.searchFun();
// this.getappsFun({"type": this.searchfromtype});
},
}
}
</script>
<style scoped>
.el-container {
margin: 10px auto 100px;
width: 1166px;
position: relative;
padding-bottom: 1px;
background-color: #bfe7f9;
color: #9b9b9b;
-webkit-font-smoothing: antialiased;
border-radius: 1%;
}
.el-header {
margin-top: 20px;
padding-top: 30px;
border-bottom: 1px solid rgba(208, 208, 208, .5);
background-color: #d5f9f9;
border-radius: 10px;
}
.surplus-card {
height: 40px;
text-align: right;
display: inline-block;
vertical-align: middle;
/*border-right: 1px solid #9b9b9b;*/
}
.surplus-card .name {
font-size: 12px;
color: #9b9b9b;
}
.surplus-card .value {
font-size: 16px;
color: #434343;
}
.appdownload {
width: 96%;
height: 96%;
margin: 2px auto; /*水平居中*/
/*background: #f8ba0b;*/
border-radius: 5px;
}
.appdownload /deep/ .el-upload-dragger {
width: 349.22px;
height: 430px;
background: #9cb8f8;
border: 0;
}
.appdownload /deep/ .el-icon-upload {
margin-top: 50%;
}
.appdownload /deep/ .el-upload-list__item-name {
margin-top: -43px;
}
.page-apps .card.app .action a, .page-apps .card.app .appname, .page-apps .card.app table tr td, .upload-modal .state-form .release-body .input-addon {
font-family: 'Open Sans', sans-serif
}
.page-apps .row-apps-top > div {
height: 100%
}
.page-apps .card.app .appicon img, .page-apps .card.app .combo-info img {
border-radius: 17.54%
}
.page-apps .card.app {
position: relative;
padding: 45px;
height: 340px;
background-color: #fff;
-webkit-transition: all .25s;
transition: all .25s
}
.page-apps .card.app:hover {
-webkit-transform: translateY(-4px);
transform: translateY(-4px);
box-shadow: 0 15px 30px rgba(0, 0, 0, .1)
}
.page-apps .card.app .type-icon {
position: absolute;
top: 9px;
right: 7px;
z-index: 2;
color: #fff;
}
.page-apps .card.app .type-mark {
position: absolute;
top: 0;
right: 0;
z-index: 1
}
.page-apps .card.app .type-mark i {
position: absolute;
top: 9px;
right: 7px
}
.page-apps .card.app .appicon {
display: inline-block;
width: 100px;
height: 100px;
cursor: pointer
}
.page-apps .card.app .appname {
margin-top: 36px;
font-size: 18px;
cursor: pointer;
display: inline-block
}
.page-apps .card.app .appname i {
color: #f8ba0b;
font-size: 16px;
margin-right: 6px
}
.page-apps .card.app:hover .appname {
color: #4a4a4a
}
.page-apps .card.app .combo-info {
display: inline-block;
margin-left: 26px;
vertical-align: bottom
}
.page-apps .card.app .combo-info i {
margin-right: 14px;
font-size: 20px
}
.page-apps .card.app table {
width: 100%;
table-layout: fixed
}
.page-apps .card.app table tr td {
padding: 2px 0;
font-size: 12px;
color: #9b9b9b;
}
.page-apps .card.app table tr td > span {
display: inline-block
}
.page-apps .card.app table tr td:last-child {
color: #1a1a1a;
width: 58%
}
.page-apps .card.app .action {
position: absolute;
padding: 20px 0 40px 40px;
left: 0;
bottom: 0;
width: 100%
}
.page-apps .card.app .action .el-button {
text-decoration: none;
border: 1px solid;
text-align: center;
padding: 8px 20px;
margin-right: 4px;
border-radius: 40px;
color: #9b9b9b;
-webkit-transition: all .25s;
transition: all .25s;
display: inline-block
}
.page-apps .card.app .action .el-button:hover {
color: #7e9bf8
}
.page-apps .card.app .action .el-button i {
font-size: 18px;
margin-right: 4px;
display: inline-block;
vertical-align: middle
}
.page-apps .card.app .action .btn-remove {
font-size: 0;
border: 1px solid;
background: 0;
padding: 10px;
border-radius: 50%;
vertical-align: top;
color: #9b9b9b;
}
.page-apps .card.app .action .btn-remove {
font-size: 16px
}
.page-apps .card.app .action .btn-remove:hover {
background-color: #ec4242;
color: #fff
}
.page-apps .card-android .type-mark {
height: 0;
width: 0;
border-top: 48px solid #a4c639;
border-left: 48px solid transparent
}
.page-apps .card-ios .type-mark {
height: 0;
width: 0;
border-top: 48px solid #c6c7c9;
/*border-top-right-radius: 10px;*/
border-left: 48px solid transparent;
}
.page-apps .card-ios {
border-radius: 10px;
}
.page-apps .card.card-invite .appname {
color: #4a4a4a;
margin-top: 0
}
.page-apps .card.card-invite .actions button {
display: block;
padding: 8px;
width: 120px;
border: 1px solid #4a4a4a;
border-radius: 20px;
background-color: transparent
}
.page-apps .card.card-invite .actions button:first-child {
position: absolute;
bottom: 44px;
margin: 0;
background-color: #4a4a4a;
color: #fff
}
.page-apps .card.card-invite .actions button:last-child {
position: absolute;
bottom: 44px;
left: 170px;
border-color: transparent
}
.page-apps .card.card-invite .actions button:last-child:hover {
color: #4a4a4a
}
/*最外层容器样式*/
.wrap {
width: 100px;
height: 100px;
/*margin: 119px;*/
margin: 120px auto 119px auto;
position: relative;
}
/*包裹所有容器样式*/
.cube {
width: 50px;
height: 50px;
margin: 0 auto;
transform-style: preserve-3d;
transform: rotateX(-30deg) rotateY(-80deg);
animation: rotate linear 20s infinite;
}
@-webkit-keyframes rotate {
from {
transform: rotateX(0deg) rotateY(0deg);
}
to {
transform: rotateX(360deg) rotateY(360deg);
}
}
.cube div {
position: absolute;
width: 200px;
height: 200px;
opacity: 0.8;
transition: all .4s;
}
/*定义所有图片样式*/
.pic {
width: 200px;
height: 200px;
}
.cube .out_front {
transform: rotateY(0deg) translateZ(100px);
}
.cube .out_back {
transform: translateZ(-100px) rotateY(180deg);
}
.cube .out_left {
transform: rotateY(-90deg) translateZ(100px);
}
.cube .out_right {
transform: rotateY(90deg) translateZ(100px);
}
.cube .out_top {
transform: rotateX(90deg) translateZ(100px);
}
.cube .out_bottom {
transform: rotateX(-90deg) translateZ(100px);
}
/*定义小正方体样式*/
.cube span {
display: block;
width: 100px;
height: 100px;
position: absolute;
top: 50px;
left: 50px;
}
.cube .in_pic {
width: 100px;
height: 100px;
}
.cube .in_front {
transform: rotateY(0deg) translateZ(50px);
}
.cube .in_back {
transform: translateZ(-50px) rotateY(180deg);
}
.cube .in_left {
transform: rotateY(-90deg) translateZ(50px);
}
.cube .in_right {
transform: rotateY(90deg) translateZ(50px);
}
.cube .in_top {
transform: rotateX(90deg) translateZ(50px);
}
.cube .in_bottom {
transform: rotateX(-90deg) translateZ(50px);
}
/*鼠标移入后样式*/
.cube:hover .out_front {
transform: rotateY(0deg) translateZ(200px);
}
.cube:hover .out_back {
transform: translateZ(-200px) rotateY(180deg);
}
.cube:hover .out_left {
transform: rotateY(-90deg) translateZ(200px);
}
.cube:hover .out_right {
transform: rotateY(90deg) translateZ(200px);
}
.cube:hover .out_top {
transform: rotateX(90deg) translateZ(200px);
}
.cube:hover .out_bottom {
transform: rotateX(-90deg) translateZ(200px);
}
</style>