no message
This commit is contained in:
parent
97ea16f344
commit
3359fde4aa
16
package.json
16
package.json
@ -16,24 +16,26 @@
|
|||||||
"jquery": "^3.5.1",
|
"jquery": "^3.5.1",
|
||||||
"laravel-mix": "^6.0.6",
|
"laravel-mix": "^6.0.6",
|
||||||
"lodash": "^4.17.19",
|
"lodash": "^4.17.19",
|
||||||
|
"postcss": "^8.1.14",
|
||||||
|
"resolve-url-loader": "^3.1.3",
|
||||||
|
"sass": "^1.34.0",
|
||||||
|
"sass-loader": "^11.1.1",
|
||||||
"stylus": "^0.54.8",
|
"stylus": "^0.54.8",
|
||||||
"stylus-loader": "^3.0.2",
|
"stylus-loader": "^3.0.2",
|
||||||
"vue": "^2.6.12",
|
"vue": "^2.6.12",
|
||||||
|
"vue-loader": "^15.9.7",
|
||||||
"vue-router": "^3.4.2",
|
"vue-router": "^3.4.2",
|
||||||
"vue-template-compiler": "^2.6.11",
|
"vue-template-compiler": "^2.6.11"
|
||||||
"postcss": "^8.1.14"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@chenfengyuan/vue-qrcode": "^1.0.2",
|
"echarts": "^5.1.1",
|
||||||
"echarts": "^5.0.0",
|
"tinymce": "^5.8.1",
|
||||||
"internal-ip": "^6.1.0",
|
|
||||||
"tinymce": "^5.6.2",
|
|
||||||
"view-design-hi": "^4.5.0-4",
|
"view-design-hi": "^4.5.0-4",
|
||||||
"vue-clipboard2": "^0.3.1",
|
"vue-clipboard2": "^0.3.1",
|
||||||
"vue-emoji-picker": "^1.0.1",
|
"vue-emoji-picker": "^1.0.1",
|
||||||
"vue-kityminder-gg": "^1.3.6",
|
"vue-kityminder-gg": "^1.3.6",
|
||||||
"vue-resize-observer": "^1.0.37",
|
"vue-resize-observer": "^1.0.37",
|
||||||
"vuedraggable": "^2.24.3",
|
"vuedraggable": "^2.24.3",
|
||||||
"xlsx": "^0.16.9"
|
"xlsx": "^0.17.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
0
resources/css/app.css
vendored
0
resources/css/app.css
vendored
212
resources/js/App.vue
Executable file
212
resources/js/App.vue
Executable file
@ -0,0 +1,212 @@
|
|||||||
|
<template>
|
||||||
|
<div id="app">
|
||||||
|
<transition :name="transitionName">
|
||||||
|
<keep-alive>
|
||||||
|
<router-view class="child-view"></router-view>
|
||||||
|
</keep-alive>
|
||||||
|
</transition>
|
||||||
|
<Spinner/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Spinner from "./common/components/Spinner";
|
||||||
|
export default {
|
||||||
|
components: {Spinner},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
transitionName: null,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.checkToken();
|
||||||
|
//
|
||||||
|
if ($A.getToken() !== false) {
|
||||||
|
$A.getUserInfo(true);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
let hash = window.location.hash;
|
||||||
|
if (hash.indexOf("#") === 0) {
|
||||||
|
hash = hash.substr(1);
|
||||||
|
if (hash) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
hash = $A.removeURLParameter(hash, 'token');
|
||||||
|
this.goForward({path: hash});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.sessionStorage('/', 1);
|
||||||
|
let pathname = window.location.pathname;
|
||||||
|
if (pathname && this.sessionStorage(pathname) === 0) {
|
||||||
|
this.sessionStorage(pathname, this.sessionStorage('::count') + 1);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
setInterval(this.searchEnter, 1000);
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'$route' (To, From) {
|
||||||
|
if (this.transitionName === null) {
|
||||||
|
this.transitionName = 'app-slide-no';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (typeof To.name === 'undefined' || typeof From.name === 'undefined') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.slideType(To, From);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
checkToken() {
|
||||||
|
let token = $A.urlParameter("token");
|
||||||
|
if ($A.count(token) > 10) {
|
||||||
|
$.setToken(decodeURIComponent(token));
|
||||||
|
$A.getUserInfo(true);
|
||||||
|
let path = $A.removeURLParameter(window.location.href, 'token');
|
||||||
|
let uri = document.createElement('a');
|
||||||
|
uri.href = path;
|
||||||
|
if (uri.pathname) {
|
||||||
|
let query = $A.urlParameterAll();
|
||||||
|
if (typeof query['token'] !== "undefined") delete query['token'];
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.goForward({path: uri.pathname, query}, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
slideType(To, From) {
|
||||||
|
let isBack = this.$router.isBack;
|
||||||
|
this.$router.isBack = false;
|
||||||
|
//
|
||||||
|
let ToIndex = this.sessionStorage(To.path);
|
||||||
|
let FromIndex = this.sessionStorage(From.path);
|
||||||
|
if (ToIndex && ToIndex < FromIndex) {
|
||||||
|
isBack = true; //后退
|
||||||
|
this.sessionStorage(true, ToIndex);
|
||||||
|
}else{
|
||||||
|
isBack = false; //前进
|
||||||
|
this.sessionStorage(To.path, this.sessionStorage('::count') + 1);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
if (To.meta.slide === false || From.meta.slide === false)
|
||||||
|
{
|
||||||
|
//取消动画
|
||||||
|
this.transitionName = 'app-slide-no'
|
||||||
|
}
|
||||||
|
else if (To.meta.slide === 'up' || From.meta.slide === 'up' || To.meta.slide === 'down' || From.meta.slide === 'down')
|
||||||
|
{
|
||||||
|
//上下动画
|
||||||
|
if (isBack) {
|
||||||
|
this.transitionName = 'app-slide-down'
|
||||||
|
} else {
|
||||||
|
this.transitionName = 'app-slide-up'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//左右动画(默认)
|
||||||
|
if (isBack) {
|
||||||
|
this.transitionName = 'app-slide-right'
|
||||||
|
} else {
|
||||||
|
this.transitionName = 'app-slide-left'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sessionStorage(path, num) {
|
||||||
|
let conut = 0;
|
||||||
|
let history = JSON.parse(window.sessionStorage['__history__'] || '{}');
|
||||||
|
if (path === true) {
|
||||||
|
let items = {};
|
||||||
|
for(let i in history){
|
||||||
|
if (history.hasOwnProperty(i)) {
|
||||||
|
if (parseInt(history[i]) <= num) {
|
||||||
|
items[i] = history[i];
|
||||||
|
conut++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
history = items;
|
||||||
|
history['::count'] = Math.max(num, conut);
|
||||||
|
window.sessionStorage['__history__'] = JSON.stringify(history);
|
||||||
|
return history;
|
||||||
|
}
|
||||||
|
if (typeof num === 'undefined') {
|
||||||
|
return parseInt(history[path] || 0);
|
||||||
|
}
|
||||||
|
if (path === "/") num = 1;
|
||||||
|
history[path] = num;
|
||||||
|
for(let key in history){ if (history.hasOwnProperty(key) && key !== '::count') { conut++; } }
|
||||||
|
history['::count'] = Math.max(num, conut);
|
||||||
|
window.sessionStorage['__history__'] = JSON.stringify(history);
|
||||||
|
},
|
||||||
|
|
||||||
|
searchEnter() {
|
||||||
|
let row = $A(".sreachBox");
|
||||||
|
if (row.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (row.attr("data-enter-init") === "init") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
row.attr("data-enter-init", "init");
|
||||||
|
//
|
||||||
|
let buttons = row.find("button[type='button']");
|
||||||
|
let button = null;
|
||||||
|
if (buttons.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
buttons.each((index, item) => {
|
||||||
|
if ($A(item).text().indexOf("搜索")) {
|
||||||
|
button = $A(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (button === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
row.find("input.ivu-input").keydown(function(e) {
|
||||||
|
if (e.keyCode == 13) {
|
||||||
|
if (!button.hasClass("ivu-btn-loading") ) {
|
||||||
|
button.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body { overflow-x: hidden; }
|
||||||
|
</style>
|
||||||
|
<!--suppress CssUnusedSymbol -->
|
||||||
|
<style scoped>
|
||||||
|
.child-view {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 100%;
|
||||||
|
transition: all .3s cubic-bezier(.55, 0, .1, 1);
|
||||||
|
}
|
||||||
|
.app-slide-no-leave-to {display: none;}
|
||||||
|
/**
|
||||||
|
* 左右模式
|
||||||
|
*/
|
||||||
|
.app-slide-left-leave-active{z-index:1;transform:translate(0,0)}
|
||||||
|
.app-slide-left-leave-to{z-index:1;transform:translate(0,0)}
|
||||||
|
.app-slide-left-enter-active{opacity:0;z-index:2;transform:translate(30%,0)}
|
||||||
|
.app-slide-left-enter-to{opacity:1;z-index:2;transform:translate(0,0)}
|
||||||
|
.app-slide-right-leave-active{opacity:1;z-index:2;transform:translate(0,0)}
|
||||||
|
.app-slide-right-leave-to{opacity:0;z-index:2;transform:translate(30%,0)}
|
||||||
|
.app-slide-right-enter-active{z-index:1;transform:translate(0,0)}
|
||||||
|
.app-slide-right-enter{z-index:1;transform:translate(0,0)}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上下模式
|
||||||
|
*/
|
||||||
|
.app-slide-up-leave-active{z-index:1;transform:translate(0,0)}
|
||||||
|
.app-slide-up-leave-to{z-index:1;transform:translate(0,0)}
|
||||||
|
.app-slide-up-enter-active{opacity:0;z-index:2;transform:translate(0,20%)}
|
||||||
|
.app-slide-up-enter-to{opacity:1;z-index:2;transform:translate(0,0)}
|
||||||
|
.app-slide-down-leave-active{opacity:1;z-index:2;transform:translate(0,0)}
|
||||||
|
.app-slide-down-leave-to{opacity:0;z-index:2;transform:translate(0,20%)}
|
||||||
|
.app-slide-down-enter-active{z-index:1;transform:translate(0,0)}
|
||||||
|
.app-slide-down-enter{z-index:1;transform:translate(0,0)}
|
||||||
|
</style>
|
82
resources/js/app.js
vendored
82
resources/js/app.js
vendored
@ -1 +1,81 @@
|
|||||||
require('./bootstrap');
|
import Vue from 'vue'
|
||||||
|
import App from './App.vue'
|
||||||
|
import routes from './routes'
|
||||||
|
import VueRouter from 'vue-router'
|
||||||
|
import ViewUI from 'view-design-hi';
|
||||||
|
import Language from './common/language/index'
|
||||||
|
import Mixins from './common/mixins/index'
|
||||||
|
|
||||||
|
import './common/functions/index'
|
||||||
|
import './main'
|
||||||
|
|
||||||
|
Vue.use(VueRouter);
|
||||||
|
Vue.use(ViewUI);
|
||||||
|
Vue.use(Language);
|
||||||
|
Vue.use(Mixins);
|
||||||
|
|
||||||
|
import PageTitle from './common/components/PageTitle.vue'
|
||||||
|
import Loading from './common/components/Loading.vue'
|
||||||
|
import AutoTip from './common/components/AutoTip.vue'
|
||||||
|
import TableAction from './common/components/TableAction.vue'
|
||||||
|
|
||||||
|
Vue.component('PageTitle', PageTitle);
|
||||||
|
Vue.component('Loading', Loading);
|
||||||
|
Vue.component('AutoTip', AutoTip);
|
||||||
|
Vue.component('TableAction', TableAction);
|
||||||
|
|
||||||
|
|
||||||
|
const originalPush = VueRouter.prototype.push
|
||||||
|
VueRouter.prototype.push = function push(location) {
|
||||||
|
return originalPush.call(this, location).catch(err => err)
|
||||||
|
}
|
||||||
|
const router = new VueRouter({
|
||||||
|
mode: 'history',
|
||||||
|
routes
|
||||||
|
});
|
||||||
|
|
||||||
|
//进度条配置
|
||||||
|
ViewUI.LoadingBar.config({
|
||||||
|
color: '#3fcc25',
|
||||||
|
failedColor: '#ff0000'
|
||||||
|
});
|
||||||
|
router.beforeEach((to, from, next) => {
|
||||||
|
ViewUI.LoadingBar.start();
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
router.afterEach((to, from, next) => {
|
||||||
|
ViewUI.LoadingBar.finish();
|
||||||
|
});
|
||||||
|
|
||||||
|
//加载函数
|
||||||
|
Vue.prototype.goForward = function(location, isReplace) {
|
||||||
|
if (typeof location === 'string') location = {name: location};
|
||||||
|
if (isReplace === true) {
|
||||||
|
this.$router.replace(location);
|
||||||
|
}else{
|
||||||
|
this.$router.push(location);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//返回函数
|
||||||
|
Vue.prototype.goBack = function (number) {
|
||||||
|
let history = $A.jsonParse(window.sessionStorage['__history__'] || '{}');
|
||||||
|
if ($A.runNum(history['::count']) > 2) {
|
||||||
|
this.$router.go(typeof number === 'number' ? number : -1);
|
||||||
|
} else {
|
||||||
|
this.$router.replace(typeof number === "object" ? number : {path: '/'});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Vue.prototype.$A = $A;
|
||||||
|
|
||||||
|
Vue.config.productionTip = false;
|
||||||
|
|
||||||
|
const app = new Vue({
|
||||||
|
el: '#app',
|
||||||
|
router,
|
||||||
|
template: '<App/>',
|
||||||
|
components: { App }
|
||||||
|
});
|
||||||
|
|
||||||
|
$A.app = app;
|
||||||
|
28
resources/js/bootstrap.js
vendored
28
resources/js/bootstrap.js
vendored
@ -1,28 +0,0 @@
|
|||||||
window._ = require('lodash');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We'll load the axios HTTP library which allows us to easily issue requests
|
|
||||||
* to our Laravel back-end. This library automatically handles sending the
|
|
||||||
* CSRF token as a header based on the value of the "XSRF" token cookie.
|
|
||||||
*/
|
|
||||||
|
|
||||||
window.axios = require('axios');
|
|
||||||
|
|
||||||
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Echo exposes an expressive API for subscribing to channels and listening
|
|
||||||
* for events that are broadcast by Laravel. Echo and event broadcasting
|
|
||||||
* allows your team to easily build robust real-time web applications.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// import Echo from 'laravel-echo';
|
|
||||||
|
|
||||||
// window.Pusher = require('pusher-js');
|
|
||||||
|
|
||||||
// window.Echo = new Echo({
|
|
||||||
// broadcaster: 'pusher',
|
|
||||||
// key: process.env.MIX_PUSHER_APP_KEY,
|
|
||||||
// cluster: process.env.MIX_PUSHER_APP_CLUSTER,
|
|
||||||
// forceTLS: true
|
|
||||||
// });
|
|
85
resources/js/common/components/AutoTip.vue
Normal file
85
resources/js/common/components/AutoTip.vue
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
<template>
|
||||||
|
<Tooltip transfer :content="text" :placement="placement" :theme="tooltipTheme" :delay="delay" :disabled="!showTooltip" :max-width="tooltipMaxWidth" class="ivu-table-cell-tooltip">
|
||||||
|
<span ref="content" @mouseenter="handleTooltipIn" class="ivu-table-cell-tooltip-content">
|
||||||
|
<template v-if="existSlot"><slot/></template>
|
||||||
|
<template v-else>{{text}}</template>
|
||||||
|
</span>
|
||||||
|
</Tooltip>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'AutoTip',
|
||||||
|
props: {
|
||||||
|
content: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
placement: {
|
||||||
|
default: 'bottom'
|
||||||
|
},
|
||||||
|
tooltipTheme: {
|
||||||
|
default: 'dark'
|
||||||
|
},
|
||||||
|
tooltipMaxWidth: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: 300
|
||||||
|
},
|
||||||
|
delay: {
|
||||||
|
type: Number,
|
||||||
|
default: 100
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
slotText: '',
|
||||||
|
showTooltip: false // 鼠标滑过overflow文本时,再检查是否需要显示
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted () {
|
||||||
|
this.updateConetne()
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeUpdate () {
|
||||||
|
this.updateConetne()
|
||||||
|
},
|
||||||
|
|
||||||
|
activated() {
|
||||||
|
this.updateConetne()
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
text() {
|
||||||
|
const {content, slotText} = this;
|
||||||
|
if (content) {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
if (typeof slotText === 'undefined' || slotText.length < 1 || typeof slotText[0].text !== 'string') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return slotText[0].text;
|
||||||
|
},
|
||||||
|
existSlot() {
|
||||||
|
const {slotText} = this;
|
||||||
|
return !(typeof slotText === 'undefined' || slotText.length < 1);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
updateConetne () {
|
||||||
|
this.slotText = this.$slots.default;
|
||||||
|
},
|
||||||
|
handleTooltipIn () {
|
||||||
|
const $content = this.$refs.content;
|
||||||
|
let range = document.createRange();
|
||||||
|
range.setStart($content, 0);
|
||||||
|
range.setEnd($content, $content.childNodes.length);
|
||||||
|
const rangeWidth = range.getBoundingClientRect().width;
|
||||||
|
this.showTooltip = Math.floor(rangeWidth) > Math.floor($content.offsetWidth);
|
||||||
|
range = null;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
594
resources/js/common/components/ImgUpload.vue
Executable file
594
resources/js/common/components/ImgUpload.vue
Executable file
@ -0,0 +1,594 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div v-if="type !== 'callback'" class="imgcomp-upload-list" v-for="item in uploadList">
|
||||||
|
<template v-if="item.status === 'finished'">
|
||||||
|
<div class="imgcomp-upload-img" v-bind:style="{ 'background-image': 'url(' + __thumb(item.thumb) + ')' }"></div>
|
||||||
|
<div class="imgcomp-upload-list-cover">
|
||||||
|
<Icon type="ios-eye-outline" @click.native="handleView(item)"></Icon>
|
||||||
|
<Icon type="ios-trash-outline" @click.native="handleRemove(item)"></Icon>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<Progress v-if="item.showProgress" :percent="item.percentage" hide-info></Progress>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div class="add-box" v-bind:class="{ 'callback-add-box': type === 'callback' }">
|
||||||
|
<div class="add-box-icon">
|
||||||
|
<Icon type="md-add" size="32"></Icon>
|
||||||
|
</div>
|
||||||
|
<div class="add-box-upload">
|
||||||
|
<div class="add-box-item" @click="browsePicture">
|
||||||
|
<span>{{$L('浏览')}}<em v-if="type === 'callback'">{{$L('图片')}}</em></span>
|
||||||
|
</div>
|
||||||
|
<div class="add-box-item">
|
||||||
|
<Upload
|
||||||
|
name="image"
|
||||||
|
ref="upload"
|
||||||
|
accept="image/*"
|
||||||
|
:action="actionUrl"
|
||||||
|
:data="uploadParams"
|
||||||
|
:show-upload-list="false"
|
||||||
|
:max-size="maxSize"
|
||||||
|
:format="['jpg', 'jpeg', 'gif', 'png']"
|
||||||
|
:default-file-list="defaultList"
|
||||||
|
:on-progress="handleProgress"
|
||||||
|
:on-success="handleSuccess"
|
||||||
|
:on-error="handleError"
|
||||||
|
:on-format-error="handleFormatError"
|
||||||
|
:on-exceeded-size="handleMaxSize"
|
||||||
|
:before-upload="handleBeforeUpload"
|
||||||
|
:multiple=multiple>
|
||||||
|
<span>{{$L('上传')}}<em v-if="type === 'callback'">{{$L('图片')}}</em></span>
|
||||||
|
</Upload>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Modal :title="$L('浏览图片空间的图片')" v-model="browseVisible" class="img-upload-modal" class-name="simple-modal" width="710">
|
||||||
|
<div class="browse-load" v-if="isLoading">{{$L('加载中...')}}</div>
|
||||||
|
<div class="browse-list" :class="httpType==='input'?'browse-list-disabled':''" ref="browselistbox">
|
||||||
|
<div class="browse-item" v-for="item in browseList" @click="browseItem(item)">
|
||||||
|
<Icon v-if="item.active" class="browse-icon" type="ios-checkmark-circle"></Icon>
|
||||||
|
<div class="browse-img" v-bind:style="{ 'background-image': 'url(' + item.thumb + ')' }"></div>
|
||||||
|
<div class="browse-title">{{item.title}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div slot="footer" class="img-upload-foot">
|
||||||
|
<div v-if="type !== 'callback' && http && httpType===''" class="img-upload-foot-input" @click="httpType='input'">
|
||||||
|
<Icon type="ios-image" size="22"/>
|
||||||
|
<div class="img-upload-foot-httptitle">{{$L('自定义图片地址')}}</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="type !== 'callback' && http && httpType==='input'" class="img-upload-foot-input">
|
||||||
|
<Input v-model="httpValue" :placeholder="$L('以 http:// 或 https:// 开头')" @on-search="httpEnter" search :enter-button="$L('确定')">
|
||||||
|
<span slot="prepend" @click="httpType=''" style="cursor:pointer">{{$L('自定义地址')}}: </span>
|
||||||
|
</Input>
|
||||||
|
</div>
|
||||||
|
<Button v-if="httpType===''" @click="browseVisible=false">{{$L('关闭')}}</Button>
|
||||||
|
<Button v-if="httpType===''" type="primary" @click="handleCallback(true)">{{$L('完成')}}</Button>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
<Modal :title="$L('查看图片')" v-model="visible" class="img-upload-modal" class-name="simple-modal" draggable>
|
||||||
|
<div style="max-height:480px;overflow:auto;">
|
||||||
|
<a :href="imgVisible" target="_blank"><img :src="imgVisible" v-if="visible" style="max-width:100%;max-height:900px;display:block;margin:0 auto"></a>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.img-upload-modal {
|
||||||
|
.ivu-modal-mask {
|
||||||
|
z-index: 1001;
|
||||||
|
}
|
||||||
|
.ivu-modal-no-mask {
|
||||||
|
background-color: rgba(55,55,55,.2);
|
||||||
|
}
|
||||||
|
.ivu-modal-wrap {
|
||||||
|
z-index: 1001;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.imgcomp-upload-list{
|
||||||
|
display: inline-block;
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 60px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #fff;
|
||||||
|
position: relative;
|
||||||
|
box-shadow: 0 1px 1px rgba(0,0,0,.2);
|
||||||
|
margin-right: 4px;
|
||||||
|
vertical-align: top;
|
||||||
|
.imgcomp-upload-img {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-position: center;
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
.imgcomp-upload-list-cover{
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: rgba(0,0,0,.6);
|
||||||
|
}
|
||||||
|
.imgcomp-upload-list-cover i{
|
||||||
|
color: #fff;
|
||||||
|
font-size: 24px;
|
||||||
|
cursor: pointer;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin: 0;
|
||||||
|
transition: all .2s;
|
||||||
|
}
|
||||||
|
.imgcomp-upload-list-cover i:hover{
|
||||||
|
font-size: 28px;
|
||||||
|
}
|
||||||
|
.ivu-progress-outer {
|
||||||
|
background-color: rgba(0, 0, 0, 0.68);
|
||||||
|
.ivu-progress-inner{
|
||||||
|
width: 88%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.imgcomp-upload-list:hover .imgcomp-upload-list-cover{
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.img-upload-foot {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
.img-upload-foot-input {
|
||||||
|
flex: 1;
|
||||||
|
text-align: left;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
.img-upload-foot-httptitle {
|
||||||
|
cursor: pointer;
|
||||||
|
padding-left: 3px;
|
||||||
|
margin-right: 22px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.add-box {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
line-height: 60px;
|
||||||
|
display: inline-block;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px dashed #dddee1;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
vertical-align: top;
|
||||||
|
.add-box-icon {
|
||||||
|
i {
|
||||||
|
vertical-align:middle;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.add-box-upload {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
color: #ffffff;
|
||||||
|
padding-top: 9px;
|
||||||
|
background: rgba(0, 0, 0, 0.6);
|
||||||
|
.add-box-item {
|
||||||
|
height: 22px;
|
||||||
|
line-height: 22px;
|
||||||
|
cursor: pointer;
|
||||||
|
.ivu-upload-drag,.ivu-upload-drag:hover {
|
||||||
|
background:transparent;
|
||||||
|
border:0;
|
||||||
|
border-radius:0;
|
||||||
|
}
|
||||||
|
span {
|
||||||
|
transition: all .2s;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.add-box-item:hover {
|
||||||
|
span {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
em {
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.add-box:hover {
|
||||||
|
border-color: rgba(0,0,0,.6);
|
||||||
|
.add-box-upload {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.callback-add-box {
|
||||||
|
display: block;
|
||||||
|
width: auto;
|
||||||
|
height: 25px;
|
||||||
|
line-height: 25px;
|
||||||
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
.add-box-icon {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.add-box-upload {
|
||||||
|
display: block;
|
||||||
|
width: auto;
|
||||||
|
background: transparent;
|
||||||
|
color: #333;
|
||||||
|
padding: 0;
|
||||||
|
> div {
|
||||||
|
display: inline-block;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.browse-load {
|
||||||
|
margin: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.browse-list {
|
||||||
|
max-height: 540px;
|
||||||
|
overflow: auto;
|
||||||
|
.browse-item {
|
||||||
|
margin: 10px 15px;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
.browse-img {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKoAAABxCAAAAABg5GeyAAACW0lEQVR4Ae3XVRLjMBAE0L3/rSwKM3OcSNPyLVYOLvM6UD0Bd03LVe9XH+RlhlRSSSWVVFJJJZVUUkkllVRSSSWVVFJJJZVUUkl9WyqppJJKKqmkkgpURP17xngOAR5NxW5wlJ9MaLQh83F4NHWmd/gZtdVBaOldfDB1bq5UpJFbFOC6LKnYrkRO209PAw+hIuzWB8Ep5es8HvYo4z4tE1X8UeRwlMM2D5Bzkc7kj6Bi3VTKDDwEeUcrMxrUvGDXTnHa6kK69SDN9sgq1clxKSbNHqqnYmdri81Q9QHf1JPt1Frncaib2XbiTKL2GkHaurnY9LOulMV0O7G6Kw+g9sw2ohhm62KezVJaaufjWC1TnOkr1exilJ7Ji0vxCCqO9V4UwV4PYr9+apouhGYLKfnahdpqegjmeoXOpXgANe70pKT6Zhu19qkY2nC0PZS527lQOyInqr8Uvc5jqfUb1X+PGh5IhW90S2quh3FQC2XRcF66TUkTXPcLKm5FtdR9RJq+2hWII7UpFtmsQLEyzsdJtkxxpr6gLotbUSlV9yeT0Trmzk2XPdUThLYarUbWOY9j04xXQ2u+pMZLYSumGmNUH3HbM9qOAwSHodN2Pks25F2j3aI7+IxqNsB+YLWb16ukSjiW4xNB0gMoMfApBS/XZQgi3p9/5RsiKNKZEOwYFVIF5VyTyD19sbyjIJiNJRZxpNbx2S8sGKvGZNHJBniBu9Wy5WxjGuQFqIAcBHiRGyt4ua5gSCWVVFJJJZVUUkkllVRSSSWVVFJJJZVUUkkllVRSSSWVVFI/AgO0SXIVYHeGAAAAAElFTkSuQmCC);
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
.browse-title {
|
||||||
|
display: block;
|
||||||
|
width: 64px;
|
||||||
|
margin-top: 5px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.browse-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 64px;
|
||||||
|
font-size: 36px;
|
||||||
|
padding-top: 15px;
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.browse-list-disabled {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.browse-list-disabled:after {
|
||||||
|
position: absolute;
|
||||||
|
content: '';
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(255, 255, 255, 0.9);
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'ImgUpload',
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
},
|
||||||
|
num: {
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
otherParams: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
uploadIng: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
actionUrl: $A.apiUrl('system/imgupload'),
|
||||||
|
params: {
|
||||||
|
token: $A.getToken(),
|
||||||
|
width: this.width,
|
||||||
|
height: this.height
|
||||||
|
},
|
||||||
|
multiple: this.num > 1,
|
||||||
|
visible: false,
|
||||||
|
browseVisible: false,
|
||||||
|
isLoading: false,
|
||||||
|
browseList: [],
|
||||||
|
browseListNext: [],
|
||||||
|
imgVisible: '',
|
||||||
|
defaultList: this.initItems(this.value),
|
||||||
|
uploadList: [],
|
||||||
|
maxNum: Math.min(Math.max($A.runNum(this.num), 1), 99),
|
||||||
|
httpValue: '',
|
||||||
|
httpType: '',
|
||||||
|
maxSize: 2048
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.uploadList = this.$refs.upload.fileList;
|
||||||
|
this.$emit('input', this.uploadList);
|
||||||
|
//
|
||||||
|
let browseBox = $A(this.$refs.browselistbox);
|
||||||
|
browseBox.scroll(()=>{
|
||||||
|
let nHight = browseBox[0].scrollHeight;
|
||||||
|
let nTop = browseBox[0].scrollTop;
|
||||||
|
let boxHight = browseBox.height();
|
||||||
|
if(nTop + boxHight >= nHight) {
|
||||||
|
//到底了
|
||||||
|
if (this.browseListNext.length > 0) {
|
||||||
|
let tmpNext = this.browseListNext;
|
||||||
|
this.browseListNext = [];
|
||||||
|
this.browsePictureFor(tmpNext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value (val) {
|
||||||
|
if (typeof val === 'string') {
|
||||||
|
this.$emit('input', this.initItems(val));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (val === this.$refs.upload.fileList) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$refs.upload.fileList = this.initItems(val);
|
||||||
|
this.uploadList = this.$refs.upload.fileList;
|
||||||
|
},
|
||||||
|
browseVisible() {
|
||||||
|
this.httpType = '';
|
||||||
|
this.httpValue = '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
uploadParams() {
|
||||||
|
if (Object.keys(this.otherParams).length > 0) {
|
||||||
|
return Object.assign(this.params, this.otherParams);
|
||||||
|
} else {
|
||||||
|
return this.params;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleCallback(file) {
|
||||||
|
if (this.type === 'callback') {
|
||||||
|
if (file === true) {
|
||||||
|
this.$emit('on-callback', this.uploadList);
|
||||||
|
this.$refs.upload.fileList = [];
|
||||||
|
this.uploadList = this.$refs.upload.fileList;
|
||||||
|
}else if (typeof file === "object") {
|
||||||
|
this.$emit('on-callback', [file]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.browseVisible = false;
|
||||||
|
},
|
||||||
|
initItems(items) {
|
||||||
|
//数据初始化
|
||||||
|
if (typeof items === 'string') {
|
||||||
|
items = [{'url': items}];
|
||||||
|
}
|
||||||
|
let lists = [];
|
||||||
|
$A.each(items, (index, item)=>{
|
||||||
|
if (typeof item === 'string') item = {'url': item};
|
||||||
|
if (item.url) {
|
||||||
|
item.active = true;
|
||||||
|
item.status = 'finished';
|
||||||
|
if (typeof item.path === 'undefined') item.path = item.url;
|
||||||
|
if (typeof item.thumb === 'undefined') item.thumb = item.url;
|
||||||
|
lists.push(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return lists;
|
||||||
|
},
|
||||||
|
handleView (item) {
|
||||||
|
//查看
|
||||||
|
this.visible = true;
|
||||||
|
this.imgVisible = item.url;
|
||||||
|
},
|
||||||
|
handleRemove (item) {
|
||||||
|
//删除
|
||||||
|
let fileList = this.$refs.upload.fileList;
|
||||||
|
this.$refs.upload.fileList.splice(fileList.indexOf(item), 1);
|
||||||
|
this.$emit('input', this.$refs.upload.fileList);
|
||||||
|
},
|
||||||
|
handleProgress() {
|
||||||
|
//开始上传
|
||||||
|
this.$emit('update:uploadIng', this.uploadIng + 1);
|
||||||
|
},
|
||||||
|
handleSuccess (res, file) {
|
||||||
|
//上传完成
|
||||||
|
this.$emit('update:uploadIng', this.uploadIng - 1);
|
||||||
|
if (res.ret === 1) {
|
||||||
|
file.url = res.data.url;
|
||||||
|
file.path = res.data.path;
|
||||||
|
file.thumb = res.data.thumb;
|
||||||
|
this.handleCallback(file);
|
||||||
|
}else{
|
||||||
|
$A.noticeWarning({
|
||||||
|
title: this.$L('上传失败'),
|
||||||
|
desc: this.$L('文件 ' + file.name + ' 上传失败 ' + res.msg),
|
||||||
|
});
|
||||||
|
this.$refs.upload.fileList.pop();
|
||||||
|
}
|
||||||
|
this.$emit('input', this.$refs.upload.fileList);
|
||||||
|
},
|
||||||
|
handleError() {
|
||||||
|
//上传错误
|
||||||
|
this.$emit('update:uploadIng', this.uploadIng - 1);
|
||||||
|
},
|
||||||
|
handleFormatError (file) {
|
||||||
|
//上传类型错误
|
||||||
|
$A.noticeWarning({
|
||||||
|
title: this.$L('文件格式不正确'),
|
||||||
|
desc: this.$L('文件 ' + file.name + ' 格式不正确,请上传 jpg、jpeg、gif、png 格式的图片。')
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleMaxSize (file) {
|
||||||
|
//上传大小错误
|
||||||
|
$A.noticeWarning({
|
||||||
|
title: this.$L('超出文件大小限制'),
|
||||||
|
desc: this.$L('文件 ' + file.name + ' 太大,不能超过' + $A.bytesToSize(this.maxSize * 1024))
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleBeforeUpload () {
|
||||||
|
//上传前判断
|
||||||
|
let check = this.uploadList.length < this.maxNum;
|
||||||
|
if (!check && this.uploadList.length == 1) {
|
||||||
|
this.handleRemove(this.uploadList[0]);
|
||||||
|
check = this.uploadList.length < this.maxNum;
|
||||||
|
}
|
||||||
|
if (!check) {
|
||||||
|
$A.noticeWarning(this.$L('最多只能上传 ' + this.maxNum + ' 张图片。'));
|
||||||
|
}
|
||||||
|
this.params = {
|
||||||
|
token: $A.getToken(),
|
||||||
|
width: this.width,
|
||||||
|
height: this.height
|
||||||
|
};
|
||||||
|
return check;
|
||||||
|
},
|
||||||
|
handleClick() {
|
||||||
|
//手动上传
|
||||||
|
if (this.handleBeforeUpload()) {
|
||||||
|
this.$refs.upload.handleClick()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleManual(file) {
|
||||||
|
//手动传file
|
||||||
|
if (this.handleBeforeUpload()) {
|
||||||
|
this.$refs.upload.upload(file);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
browsePicture(path) {
|
||||||
|
//获取图片空间
|
||||||
|
this.browseVisible = true;
|
||||||
|
this.browseList = [];
|
||||||
|
this.browseListNext = [];
|
||||||
|
this.isLoading = true;
|
||||||
|
$A.apiAjax({
|
||||||
|
url: 'system/imgview',
|
||||||
|
data: { path: path?path:'' },
|
||||||
|
beforeSend: true,
|
||||||
|
complete: true,
|
||||||
|
error: true,
|
||||||
|
success: (res) => {
|
||||||
|
this.isLoading = false;
|
||||||
|
if (res.ret === 1) {
|
||||||
|
let dirs = res.data['dirs'];
|
||||||
|
for (let i = 0; i < dirs.length; i++) {
|
||||||
|
this.browseList.push(dirs[i]);
|
||||||
|
}
|
||||||
|
this.browsePictureFor(res.data['files']);
|
||||||
|
}else if (res.ret === -2) {
|
||||||
|
this.browseVisible = false;
|
||||||
|
$A.noticeWarning(res.msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
browsePictureFor(files) {
|
||||||
|
for (let o = 0; o < files.length; o++) {
|
||||||
|
for (let j = 0; j < this.uploadList.length; j++) {
|
||||||
|
if (this.uploadList[j]['url'] === files[o]['url']
|
||||||
|
|| this.uploadList[j]['url'] === files[o]['path']) {
|
||||||
|
files[o]['active'] = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (o < 100) {
|
||||||
|
this.browseList.push(files[o]);
|
||||||
|
}else{
|
||||||
|
this.browseListNext.push(files[o]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
browseItem(item) {
|
||||||
|
//点击选择图片
|
||||||
|
if (item.type === 'dir') {
|
||||||
|
//目录
|
||||||
|
this.browsePicture(item.path);
|
||||||
|
}else if (item.type === 'file') {
|
||||||
|
//文件
|
||||||
|
if (item.active) {
|
||||||
|
let fileList = this.$refs.upload.fileList;
|
||||||
|
this.$refs.upload.fileList.splice(fileList.indexOf(item), 1);
|
||||||
|
item.active = false;
|
||||||
|
}else{
|
||||||
|
if (this.maxNum === 1) {
|
||||||
|
for (let i = 0; i < this.browseList.length; i++) {
|
||||||
|
this.browseList[i].active = false;
|
||||||
|
}
|
||||||
|
this.$refs.upload.fileList = [];
|
||||||
|
this.uploadList = this.$refs.upload.fileList;
|
||||||
|
}
|
||||||
|
let check = this.uploadList.length < this.maxNum;
|
||||||
|
if (!check) {
|
||||||
|
$A.noticeWarning(this.$L('最多只能选择 ' + this.maxNum + ' 张图片。'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
item.active = true;
|
||||||
|
item.status = 'finished';
|
||||||
|
this.$refs.upload.fileList.push(item);
|
||||||
|
this.uploadList = this.$refs.upload.fileList;
|
||||||
|
}
|
||||||
|
this.$emit('input', this.$refs.upload.fileList);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
__thumb(url) {
|
||||||
|
if ($A.strExists(url, "?", false)) {
|
||||||
|
return url + "&__thumb=true";
|
||||||
|
}else{
|
||||||
|
return url + "?__thumb=true";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
httpEnter() {
|
||||||
|
this.$emit('input', this.initItems(this.httpValue));
|
||||||
|
this.browseVisible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
108
resources/js/common/components/Loading.vue
Normal file
108
resources/js/common/components/Loading.vue
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
<template>
|
||||||
|
<svg viewBox="25 25 50 50" class="common-loading"><circle cx="50" cy="50" r="20" fill="none" stroke-width="5" stroke-miterlimit="10" class="w-path"></circle></svg>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.common-loading {
|
||||||
|
-webkit-animation: rotate 2s linear infinite;
|
||||||
|
animation: rotate 2s linear infinite;
|
||||||
|
-webkit-transform-origin: center center;
|
||||||
|
transform-origin: center center;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
margin: auto;
|
||||||
|
overflow: hidden;
|
||||||
|
.w-path {
|
||||||
|
stroke-dasharray: 1,200;
|
||||||
|
stroke-dashoffset: 0;
|
||||||
|
-webkit-animation: dash 1.5s ease-in-out infinite,color 6s ease-in-out infinite;
|
||||||
|
animation: dash 1.5s ease-in-out infinite,color 6s ease-in-out infinite;
|
||||||
|
stroke-linecap: round;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@-webkit-keyframes rotate {
|
||||||
|
to {
|
||||||
|
-webkit-transform: rotate(1turn);
|
||||||
|
transform: rotate(1turn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes rotate {
|
||||||
|
to {
|
||||||
|
-webkit-transform: rotate(1turn);
|
||||||
|
transform: rotate(1turn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@-webkit-keyframes dash {
|
||||||
|
0% {
|
||||||
|
stroke-dasharray: 1,200;
|
||||||
|
stroke-dashoffset: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
stroke-dasharray: 89,200;
|
||||||
|
stroke-dashoffset: -35
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
stroke-dasharray: 89,200;
|
||||||
|
stroke-dashoffset: -124
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes dash {
|
||||||
|
0% {
|
||||||
|
stroke-dasharray: 1,200;
|
||||||
|
stroke-dashoffset: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
stroke-dasharray: 89,200;
|
||||||
|
stroke-dashoffset: -35
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
stroke-dasharray: 89,200;
|
||||||
|
stroke-dashoffset: -124
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@-webkit-keyframes color {
|
||||||
|
0%,to {
|
||||||
|
stroke: #d62d20
|
||||||
|
}
|
||||||
|
|
||||||
|
40% {
|
||||||
|
stroke: #0057e7
|
||||||
|
}
|
||||||
|
|
||||||
|
66% {
|
||||||
|
stroke: #008744
|
||||||
|
}
|
||||||
|
|
||||||
|
80%,90% {
|
||||||
|
stroke: #ffa700
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes color {
|
||||||
|
0%,to {
|
||||||
|
stroke: #d62d20
|
||||||
|
}
|
||||||
|
|
||||||
|
40% {
|
||||||
|
stroke: #0057e7
|
||||||
|
}
|
||||||
|
|
||||||
|
66% {
|
||||||
|
stroke: #008744
|
||||||
|
}
|
||||||
|
|
||||||
|
80%,90% {
|
||||||
|
stroke: #ffa700
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Loading',
|
||||||
|
}
|
||||||
|
</script>
|
64
resources/js/common/components/PageTitle.vue
Executable file
64
resources/js/common/components/PageTitle.vue
Executable file
@ -0,0 +1,64 @@
|
|||||||
|
<template>
|
||||||
|
<h1 v-if="false"><slot/></h1>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'PageTitle',
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pagePath: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.pagePath = this.$route.path;
|
||||||
|
this.updateTitle()
|
||||||
|
},
|
||||||
|
beforeUpdate () {
|
||||||
|
this.updateTitle()
|
||||||
|
},
|
||||||
|
activated() {
|
||||||
|
this.updateTitle()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
updateTitle () {
|
||||||
|
let pageTitle;
|
||||||
|
if (this.title) {
|
||||||
|
pageTitle = this.title;
|
||||||
|
} else {
|
||||||
|
let slots = this.$slots.default;
|
||||||
|
if (typeof slots === 'undefined' || slots.length < 1 || typeof slots[0].text !== 'string') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let {text} = slots[0];
|
||||||
|
pageTitle = text;
|
||||||
|
}
|
||||||
|
let {title} = document;
|
||||||
|
if (pageTitle !== title && this.pagePath === this.$route.path) this.setTile(pageTitle);
|
||||||
|
},
|
||||||
|
setTile(title) {
|
||||||
|
document.title = title;
|
||||||
|
let mobile = navigator.userAgent.toLowerCase();
|
||||||
|
if (/iphone|ipad|ipod/.test(mobile)) {
|
||||||
|
let iframe = document.createElement('iframe');
|
||||||
|
iframe.style.display = 'none';
|
||||||
|
let iframeCallback = function () {
|
||||||
|
setTimeout(function () {
|
||||||
|
iframe.removeEventListener('load', iframeCallback);
|
||||||
|
document.body.removeChild(iframe)
|
||||||
|
}, 0)
|
||||||
|
};
|
||||||
|
iframe.addEventListener('load', iframeCallback);
|
||||||
|
document.body.appendChild(iframe)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
32
resources/js/common/components/Spinner.vue
Normal file
32
resources/js/common/components/Spinner.vue
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<template>
|
||||||
|
<div class="common-spinner">
|
||||||
|
<Loading class="common-circular"></Loading>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.common-spinner {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 9999;
|
||||||
|
bottom: 20px;
|
||||||
|
right: 20px;
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
.common-circular {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Spinner',
|
||||||
|
}
|
||||||
|
</script>
|
545
resources/js/common/components/TEditor.vue
Executable file
545
resources/js/common/components/TEditor.vue
Executable file
@ -0,0 +1,545 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="teditor-box" :class="[spinShow?'teditor-loadstyle':'teditor-loadedstyle']">
|
||||||
|
<textarea ref="myTextarea" :id="id">{{ content }}</textarea>
|
||||||
|
<Spin fix v-if="spinShow">
|
||||||
|
<Icon type="ios-loading" size=18 class="upload-control-spin-icon-load"></Icon>
|
||||||
|
<div>{{$L('加载组件中...')}}</div>
|
||||||
|
</Spin>
|
||||||
|
<ImgUpload
|
||||||
|
ref="myUpload"
|
||||||
|
class="upload-control"
|
||||||
|
type="callback"
|
||||||
|
:uploadIng.sync="uploadIng"
|
||||||
|
@on-callback="editorImage"
|
||||||
|
num="50"/>
|
||||||
|
<Upload
|
||||||
|
name="files"
|
||||||
|
ref="fileUpload"
|
||||||
|
class="upload-control"
|
||||||
|
:action="actionUrl"
|
||||||
|
:data="params"
|
||||||
|
multiple
|
||||||
|
:format="uploadFormat"
|
||||||
|
:show-upload-list="false"
|
||||||
|
:max-size="maxSize"
|
||||||
|
:on-progress="handleProgress"
|
||||||
|
:on-success="handleSuccess"
|
||||||
|
:on-error="handleError"
|
||||||
|
:on-format-error="handleFormatError"
|
||||||
|
:on-exceeded-size="handleMaxSize"
|
||||||
|
:before-upload="handleBeforeUpload"/>
|
||||||
|
</div>
|
||||||
|
<Spin fix v-if="uploadIng > 0">
|
||||||
|
<Icon type="ios-loading" class="upload-control-spin-icon-load"></Icon>
|
||||||
|
<div>{{$L('正在上传文件...')}}</div>
|
||||||
|
</Spin>
|
||||||
|
<Modal v-model="transfer" class="teditor-transfer" @on-visible-change="transferChange" class-name="simple-modal" footer-hide fullscreen transfer>
|
||||||
|
<div slot="close">
|
||||||
|
<Button type="primary" size="small">{{$L('完成')}}</Button>
|
||||||
|
</div>
|
||||||
|
<div class="teditor-transfer-body">
|
||||||
|
<textarea :id="'T_' + id">{{ content }}</textarea>
|
||||||
|
</div>
|
||||||
|
<Spin fix v-if="uploadIng > 0">
|
||||||
|
<Icon type="ios-loading" class="upload-control-spin-icon-load"></Icon>
|
||||||
|
<div>{{$L('正在上传文件...')}}</div>
|
||||||
|
</Spin>
|
||||||
|
</Modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.teditor-box {
|
||||||
|
textarea {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
.tox-tinymce {
|
||||||
|
box-shadow: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-color: #dddee1;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
.tox-statusbar {
|
||||||
|
span.tox-statusbar__branding {
|
||||||
|
a {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.teditor-transfer {
|
||||||
|
background-color: #ffffff;
|
||||||
|
.tox-toolbar {
|
||||||
|
> div:last-child {
|
||||||
|
> button:last-child {
|
||||||
|
margin-right: 64px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ivu-modal-header {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.ivu-modal-close {
|
||||||
|
top: 7px;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
.teditor-transfer-body {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
textarea {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
.tox-tinymce {
|
||||||
|
border: 0;
|
||||||
|
.tox-statusbar {
|
||||||
|
span.tox-statusbar__branding {
|
||||||
|
a {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.tox {
|
||||||
|
&.tox-silver-sink {
|
||||||
|
z-index: 13000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.teditor-loadstyle {
|
||||||
|
width: 100%;
|
||||||
|
height: 180px;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.teditor-loadedstyle {
|
||||||
|
width: 100%;
|
||||||
|
max-height: inherit;
|
||||||
|
overflow: inherit;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.upload-control {
|
||||||
|
display: none;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import tinymce from 'tinymce/tinymce';
|
||||||
|
import ImgUpload from "./ImgUpload";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'TEditor',
|
||||||
|
components: {ImgUpload},
|
||||||
|
props: {
|
||||||
|
id: {
|
||||||
|
type: String,
|
||||||
|
default: () => {
|
||||||
|
return "tinymce_" + Math.round(Math.random() * 10000);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
default: 360,
|
||||||
|
},
|
||||||
|
htmlClass: {
|
||||||
|
default: '',
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return [
|
||||||
|
'advlist autolink lists link image charmap print preview hr anchor pagebreak imagetools',
|
||||||
|
'searchreplace visualblocks visualchars code',
|
||||||
|
'insertdatetime media nonbreaking save table contextmenu directionality',
|
||||||
|
'emoticons paste textcolor colorpicker imagetools codesample'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toolbar: {
|
||||||
|
type: String,
|
||||||
|
default: ' undo redo | styleselect | uploadImages | uploadFiles | bold italic underline forecolor backcolor | alignleft aligncenter alignright | bullist numlist outdent indent | link image emoticons media codesample | preview screenload',
|
||||||
|
},
|
||||||
|
other_options: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
readonly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
content: '',
|
||||||
|
editor: null,
|
||||||
|
editorT: null,
|
||||||
|
cTinyMce: null,
|
||||||
|
checkerTimeout: null,
|
||||||
|
isTyping: false,
|
||||||
|
|
||||||
|
spinShow: true,
|
||||||
|
transfer: false,
|
||||||
|
|
||||||
|
uploadIng: 0,
|
||||||
|
uploadFormat: ['jpg', 'jpeg', 'png', 'gif', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'esp', 'pdf', 'rar', 'zip', 'gz'],
|
||||||
|
actionUrl: $A.apiUrl('system/fileupload'),
|
||||||
|
params: { token: $A.getToken() },
|
||||||
|
maxSize: 10240
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.content = this.value;
|
||||||
|
this.init();
|
||||||
|
},
|
||||||
|
activated() {
|
||||||
|
this.content = this.value;
|
||||||
|
this.init();
|
||||||
|
},
|
||||||
|
deactivated() {
|
||||||
|
if (this.editor !== null) {
|
||||||
|
this.editor.destroy();
|
||||||
|
}
|
||||||
|
this.spinShow = true;
|
||||||
|
$A(this.$refs.myTextarea).show();
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value(newValue) {
|
||||||
|
if (newValue == null) {
|
||||||
|
newValue = "";
|
||||||
|
}
|
||||||
|
if (!this.isTyping) {
|
||||||
|
if (this.getEditor() !== null) {
|
||||||
|
this.getEditor().setContent(newValue);
|
||||||
|
} else{
|
||||||
|
this.content = newValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
readonly(value) {
|
||||||
|
if (this.editor !== null) {
|
||||||
|
if (value) {
|
||||||
|
this.editor.setMode('readonly');
|
||||||
|
} else {
|
||||||
|
this.editor.setMode('design');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
init() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
tinymce.init(this.concatAssciativeArrays(this.options(false), this.other_options));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
initTransfer() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
tinymce.init(this.concatAssciativeArrays(this.options(true), this.other_options));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
options(isFull) {
|
||||||
|
return {
|
||||||
|
selector: (isFull ? '#T_' : '#') + this.id,
|
||||||
|
base_url: $A.serverUrl('js/build'),
|
||||||
|
language: "zh_CN",
|
||||||
|
toolbar: this.toolbar,
|
||||||
|
plugins: this.plugins,
|
||||||
|
save_onsavecallback: (e) => {
|
||||||
|
this.$emit('editorSave', e);
|
||||||
|
},
|
||||||
|
paste_data_images: true,
|
||||||
|
menu: {
|
||||||
|
view: {
|
||||||
|
title: 'View',
|
||||||
|
items: 'code | visualaid visualchars visualblocks | spellchecker | preview fullscreen screenload | showcomments'
|
||||||
|
},
|
||||||
|
insert: {
|
||||||
|
title: "Insert",
|
||||||
|
items: "image link media addcomment pageembed template codesample inserttable | charmap emoticons hr | pagebreak nonbreaking anchor toc | insertdatetime | uploadImages browseImages | uploadFiles"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
codesample_languages: [
|
||||||
|
{text:"HTML/VUE/XML",value:"markup"},
|
||||||
|
{text:"JavaScript",value:"javascript"},
|
||||||
|
{text:"CSS",value:"css"},
|
||||||
|
{text:"PHP",value:"php"},
|
||||||
|
{text:"Ruby",value:"ruby"},
|
||||||
|
{text:"Python",value:"python"},
|
||||||
|
{text:"Java",value:"java"},
|
||||||
|
{text:"C",value:"c"},
|
||||||
|
{text:"C#",value:"csharp"},
|
||||||
|
{text:"C++",value:"cpp"}
|
||||||
|
],
|
||||||
|
height: isFull ? '100%' : ($A.rightExists(this.height, '%') ? this.height : ($A.runNum(this.height) || 360)),
|
||||||
|
resize: !isFull,
|
||||||
|
convert_urls:false,
|
||||||
|
toolbar_mode: 'sliding',
|
||||||
|
toolbar_drawer: 'floating',
|
||||||
|
setup: (editor) => {
|
||||||
|
editor.ui.registry.addMenuButton('uploadImages', {
|
||||||
|
text: this.$L('图片'),
|
||||||
|
tooltip: this.$L('上传/浏览 图片'),
|
||||||
|
fetch: (callback) => {
|
||||||
|
let items = [{
|
||||||
|
type: 'menuitem',
|
||||||
|
text: this.$L('上传图片'),
|
||||||
|
onAction: () => {
|
||||||
|
this.$refs.myUpload.handleClick();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
type: 'menuitem',
|
||||||
|
text: this.$L('浏览图片'),
|
||||||
|
onAction: () => {
|
||||||
|
this.$refs.myUpload.browsePicture();
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
callback(items);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
editor.ui.registry.addMenuItem('uploadImages', {
|
||||||
|
text: this.$L('上传图片'),
|
||||||
|
onAction: () => {
|
||||||
|
this.$refs.myUpload.handleClick();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
editor.ui.registry.addMenuItem('browseImages', {
|
||||||
|
text: this.$L('浏览图片'),
|
||||||
|
onAction: () => {
|
||||||
|
this.$refs.myUpload.browsePicture();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
editor.ui.registry.addButton('uploadFiles', {
|
||||||
|
text: this.$L('文件'),
|
||||||
|
tooltip: this.$L('上传文件'),
|
||||||
|
onAction: () => {
|
||||||
|
if (this.handleBeforeUpload()) {
|
||||||
|
this.$refs.fileUpload.handleClick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
editor.ui.registry.addMenuItem('uploadFiles', {
|
||||||
|
text: this.$L('上传文件'),
|
||||||
|
onAction: () => {
|
||||||
|
if (this.handleBeforeUpload()) {
|
||||||
|
this.$refs.fileUpload.handleClick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (isFull) {
|
||||||
|
editor.ui.registry.addButton('screenload', {
|
||||||
|
icon: 'fullscreen',
|
||||||
|
tooltip: this.$L('退出全屏'),
|
||||||
|
onAction: () => {
|
||||||
|
this.closeFull();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
editor.ui.registry.addMenuItem('screenload', {
|
||||||
|
text: this.$L('退出全屏'),
|
||||||
|
onAction: () => {
|
||||||
|
this.closeFull();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
editor.on('Init', (e) => {
|
||||||
|
this.editorT = editor;
|
||||||
|
this.editorT.setContent(this.content);
|
||||||
|
if (this.readonly) {
|
||||||
|
this.editorT.setMode('readonly');
|
||||||
|
} else {
|
||||||
|
this.editorT.setMode('design');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
editor.ui.registry.addButton('screenload', {
|
||||||
|
icon: 'fullscreen',
|
||||||
|
tooltip: this.$L('全屏'),
|
||||||
|
onAction: () => {
|
||||||
|
this.content = editor.getContent();
|
||||||
|
this.transfer = true;
|
||||||
|
this.initTransfer();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
editor.ui.registry.addMenuItem('screenload', {
|
||||||
|
text: this.$L('全屏'),
|
||||||
|
onAction: () => {
|
||||||
|
this.content = editor.getContent();
|
||||||
|
this.transfer = true;
|
||||||
|
this.initTransfer();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
editor.on('Init', (e) => {
|
||||||
|
this.spinShow = false;
|
||||||
|
this.editor = editor;
|
||||||
|
this.editor.setContent(this.content);
|
||||||
|
if (this.readonly) {
|
||||||
|
this.editor.setMode('readonly');
|
||||||
|
} else {
|
||||||
|
this.editor.setMode('design');
|
||||||
|
}
|
||||||
|
this.$emit('editorInit', this.editor);
|
||||||
|
});
|
||||||
|
editor.on('KeyUp', (e) => {
|
||||||
|
if (this.editor !== null) {
|
||||||
|
this.submitNewContent();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
editor.on('Change', (e) => {
|
||||||
|
if (this.editor !== null) {
|
||||||
|
if (this.getContent() !== this.value) {
|
||||||
|
this.submitNewContent();
|
||||||
|
}
|
||||||
|
this.$emit('editorChange', e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
closeFull() {
|
||||||
|
this.content = this.getContent();
|
||||||
|
this.$emit('input', this.content);
|
||||||
|
this.transfer = false;
|
||||||
|
if (this.editorT != null) {
|
||||||
|
this.editorT.destroy();
|
||||||
|
this.editorT = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
transferChange(visible) {
|
||||||
|
if (!visible && this.editorT != null) {
|
||||||
|
this.content = this.editorT.getContent();
|
||||||
|
this.$emit('input', this.content);
|
||||||
|
this.editorT.destroy();
|
||||||
|
this.editorT = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getEditor() {
|
||||||
|
return this.transfer ? this.editorT : this.editor;
|
||||||
|
},
|
||||||
|
|
||||||
|
concatAssciativeArrays(array1, array2) {
|
||||||
|
if (array2.length === 0) return array1;
|
||||||
|
if (array1.length === 0) return array2;
|
||||||
|
let dest = [];
|
||||||
|
for (let key in array1) {
|
||||||
|
if (array1.hasOwnProperty(key)) {
|
||||||
|
dest[key] = array1[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let key in array2) {
|
||||||
|
if (array2.hasOwnProperty(key)) {
|
||||||
|
dest[key] = array2[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dest;
|
||||||
|
},
|
||||||
|
|
||||||
|
submitNewContent() {
|
||||||
|
this.isTyping = true;
|
||||||
|
if (this.checkerTimeout !== null) {
|
||||||
|
clearTimeout(this.checkerTimeout);
|
||||||
|
}
|
||||||
|
this.checkerTimeout = setTimeout(() => {
|
||||||
|
this.isTyping = false;
|
||||||
|
}, 300);
|
||||||
|
this.$emit('input', this.getContent());
|
||||||
|
},
|
||||||
|
|
||||||
|
insertContent(content) {
|
||||||
|
if (this.getEditor() !== null) {
|
||||||
|
this.getEditor().insertContent(content);
|
||||||
|
}else{
|
||||||
|
this.content+= content;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getContent() {
|
||||||
|
if (this.getEditor() === null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return this.getEditor().getContent();
|
||||||
|
},
|
||||||
|
|
||||||
|
insertImage(src) {
|
||||||
|
this.insertContent('<img src="' + src + '">');
|
||||||
|
},
|
||||||
|
|
||||||
|
editorImage(lists) {
|
||||||
|
for (let i = 0; i < lists.length; i++) {
|
||||||
|
let item = lists[i];
|
||||||
|
if (typeof item === 'object' && typeof item.url === "string") {
|
||||||
|
this.insertImage(item.url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/********************文件上传部分************************/
|
||||||
|
|
||||||
|
handleProgress() {
|
||||||
|
//开始上传
|
||||||
|
this.uploadIng++;
|
||||||
|
},
|
||||||
|
|
||||||
|
handleSuccess(res, file) {
|
||||||
|
//上传完成
|
||||||
|
this.uploadIng--;
|
||||||
|
if (res.ret === 1) {
|
||||||
|
this.insertContent(`<a href="${res.data.url}" target="_blank">${res.data.name} (${$A.bytesToSize(res.data.size * 1024)})</a>`);
|
||||||
|
} else {
|
||||||
|
$A.noticeWarning({
|
||||||
|
title: this.$L('上传失败'),
|
||||||
|
desc: this.$L('文件 ' + file.name + ' 上传失败,' + res.msg)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleError() {
|
||||||
|
//上传错误
|
||||||
|
this.uploadIng--;
|
||||||
|
},
|
||||||
|
|
||||||
|
handleFormatError(file) {
|
||||||
|
//上传类型错误
|
||||||
|
$A.noticeWarning({
|
||||||
|
title: this.$L('文件格式不正确'),
|
||||||
|
desc: this.$L('文件 ' + file.name + ' 格式不正确,仅支持上传:' + this.uploadFormat.join(','))
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
handleMaxSize(file) {
|
||||||
|
//上传大小错误
|
||||||
|
$A.noticeWarning({
|
||||||
|
title: this.$L('超出文件大小限制'),
|
||||||
|
desc: this.$L('文件 ' + file.name + ' 太大,不能超过:' + $A.bytesToSize(this.maxSize * 1024))
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
handleBeforeUpload() {
|
||||||
|
//上传前判断
|
||||||
|
this.params = {
|
||||||
|
token: $A.getToken(),
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
84
resources/js/common/components/TableAction.vue
Normal file
84
resources/js/common/components/TableAction.vue
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<template>
|
||||||
|
<div class="td-action" :style="tdStyle">
|
||||||
|
<div ref="action" @mouseenter="handleIn" class="td-action-container" v-resize="onResize"><slot></slot></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'TableAction',
|
||||||
|
props: {
|
||||||
|
column: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
minWidth: {
|
||||||
|
type: Number,
|
||||||
|
default: 80
|
||||||
|
},
|
||||||
|
align: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.onUpdate();
|
||||||
|
},
|
||||||
|
activated() {
|
||||||
|
this.onUpdate();
|
||||||
|
},
|
||||||
|
beforeUpdate() {
|
||||||
|
this.onUpdate();
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
tdStyle() {
|
||||||
|
const style = {};
|
||||||
|
const {align} = this;
|
||||||
|
if (['left', 'center', 'right'].includes(align.toLowerCase())) {
|
||||||
|
style.textAlign = align;
|
||||||
|
}
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleIn() {
|
||||||
|
if (this.$refs.action.offsetWidth != this.width) {
|
||||||
|
this.onUpdate();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onUpdate() {
|
||||||
|
this.onResize({
|
||||||
|
width: this.$refs.action.offsetWidth,
|
||||||
|
height: this.$refs.action.offsetHeight,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onResize({ width, height }) {
|
||||||
|
$A(".ivu-table-column-" + this.column.__id).each((index, el) => {
|
||||||
|
let action = $A(el).find(".td-action-container")
|
||||||
|
if (action.length > 0) {
|
||||||
|
width = Math.max(width, action[0].offsetWidth)
|
||||||
|
height = Math.max(height, action[0].offsetHeight)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
let newWidth = Math.max(this.minWidth, this.width + 26);
|
||||||
|
if (this.column.minWidth) {
|
||||||
|
newWidth = Math.max(this.column.minWidth, newWidth);
|
||||||
|
}
|
||||||
|
if (this.column.maxWidth) {
|
||||||
|
newWidth = Math.min(this.column.maxWidth, newWidth);
|
||||||
|
}
|
||||||
|
newWidth != this.column.width && this.$set(this.column, 'width', newWidth)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
222
resources/js/common/components/TagInput.vue
Executable file
222
resources/js/common/components/TagInput.vue
Executable file
@ -0,0 +1,222 @@
|
|||||||
|
<template>
|
||||||
|
<div class="tags-wrap" @paste="pasteText($event)" @click="clickWrap">
|
||||||
|
<div class="tags-item" v-for="(text, index) in disSource">
|
||||||
|
<span class="tags-content" @click.stop="">{{text}}</span><span class="tags-del" @click.stop="delTag(index)">×</span>
|
||||||
|
</div>
|
||||||
|
<textarea ref="myTextarea" class="tags-input" :style="{ minWidth: minWidth + 'px' }" :placeholder="tis || placeholder"
|
||||||
|
v-model="content" @keydown.enter="downEnter($event)" @keyup="addTag($event, content)"
|
||||||
|
@blur="addTag(false, content)" @keydown.delete="delTag(false)" :disabled="disabled" :readonly="readonly"></textarea>
|
||||||
|
<span ref="myPlaceholder" v-if="showPlaceholder || tis !== ''" class="tags-placeholder">{{tis || placeholder}}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.tags-wrap {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 32px;
|
||||||
|
padding: 2px 7px;
|
||||||
|
border: 1px solid #dddee1;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #495060;
|
||||||
|
background: #fff;
|
||||||
|
position: relative;
|
||||||
|
cursor: text;
|
||||||
|
vertical-align: middle;
|
||||||
|
line-height: normal;
|
||||||
|
-webkit-transition: border .2s ease-in-out, background .2s ease-in-out, -webkit-box-shadow .2s ease-in-out;
|
||||||
|
transition: border .2s ease-in-out, background .2s ease-in-out, -webkit-box-shadow .2s ease-in-out;
|
||||||
|
.tags-item, .tags-input {
|
||||||
|
position: relative;
|
||||||
|
float: left;
|
||||||
|
color: #495060;
|
||||||
|
background-color: #f1f8ff;
|
||||||
|
border-radius: 3px;
|
||||||
|
line-height: 22px;
|
||||||
|
margin: 2px 6px 2px 0;
|
||||||
|
padding: 0 20px 0 6px;
|
||||||
|
.tags-content {
|
||||||
|
line-height: 22px;
|
||||||
|
}
|
||||||
|
.tags-del {
|
||||||
|
width: 20px;
|
||||||
|
height: 22px;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
position: absolute;
|
||||||
|
top: -1px;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.tags-input {
|
||||||
|
max-width: 80%;
|
||||||
|
padding: 0;
|
||||||
|
background-color: inherit;
|
||||||
|
border: none;
|
||||||
|
color: inherit;
|
||||||
|
height: 22px;
|
||||||
|
line-height: 22px;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
outline: none;
|
||||||
|
resize: none;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.tags-input::placeholder {
|
||||||
|
color: #bbbbbb;
|
||||||
|
}
|
||||||
|
.tags-placeholder {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
z-index: -1;
|
||||||
|
color: #ffffff00;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags-wrap::after {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
height: 0;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'TagInput',
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
cut: {
|
||||||
|
default: ','
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
readonly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
placeholder: {
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
max: {
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
let disSource = [];
|
||||||
|
this.value.split(",").forEach((item) => {
|
||||||
|
if (item) {
|
||||||
|
disSource.push(item)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
minWidth: 80,
|
||||||
|
|
||||||
|
tis: '',
|
||||||
|
tisTimeout: null,
|
||||||
|
|
||||||
|
showPlaceholder: true,
|
||||||
|
|
||||||
|
content: '',
|
||||||
|
|
||||||
|
disSource: disSource,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.wayMinWidth();
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
placeholder() {
|
||||||
|
this.wayMinWidth();
|
||||||
|
},
|
||||||
|
value (val) {
|
||||||
|
let disSource = [];
|
||||||
|
if ($A.count(val) > 0) {
|
||||||
|
val.split(",").forEach((item) => {
|
||||||
|
if (item) {
|
||||||
|
disSource.push(item)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.disSource = disSource;
|
||||||
|
},
|
||||||
|
disSource(val) {
|
||||||
|
let temp = '';
|
||||||
|
val.forEach((item) => {
|
||||||
|
if (temp != '') {
|
||||||
|
temp += this.cut;
|
||||||
|
}
|
||||||
|
temp += item;
|
||||||
|
});
|
||||||
|
this.$emit('input', temp);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
wayMinWidth() {
|
||||||
|
this.showPlaceholder = true;
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.myPlaceholder) {
|
||||||
|
this.minWidth = Math.max(this.minWidth, this.$refs.myPlaceholder.offsetWidth);
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
try {
|
||||||
|
this.minWidth = Math.max(this.minWidth, this.$refs.myPlaceholder.offsetWidth);
|
||||||
|
this.showPlaceholder = false;
|
||||||
|
}catch (e) { }
|
||||||
|
if (!$A(this.$refs.myPlaceholder).is(":visible")) {
|
||||||
|
this.wayMinWidth();
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
pasteText(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let content = (e.clipboardData || window.clipboardData).getData('text');
|
||||||
|
this.addTag(false, content)
|
||||||
|
},
|
||||||
|
clickWrap() {
|
||||||
|
this.$refs.myTextarea.focus();
|
||||||
|
},
|
||||||
|
downEnter(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
},
|
||||||
|
addTag(e, content) {
|
||||||
|
if (e.keyCode === 13 || e === false) {
|
||||||
|
if (content.trim() != '' && this.disSource.indexOf(content.trim()) === -1) {
|
||||||
|
this.disSource.push(content.trim());
|
||||||
|
}
|
||||||
|
this.content = '';
|
||||||
|
} else {
|
||||||
|
if (this.max > 0 && this.disSource.length >= this.max) {
|
||||||
|
this.content = '';
|
||||||
|
this.tis = '最多只能添加' + this.max + '个';
|
||||||
|
clearInterval(this.tisTimeout);
|
||||||
|
this.tisTimeout = setTimeout(() => { this.tis = ''; }, 2000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let temp = content.trim();
|
||||||
|
let cutPos = temp.length - this.cut.length;
|
||||||
|
if (temp != '' && temp.substring(cutPos) === this.cut) {
|
||||||
|
temp = temp.substring(0, cutPos);
|
||||||
|
if (temp.trim() != '' && this.disSource.indexOf(temp.trim()) === -1) {
|
||||||
|
this.disSource.push(temp.trim());
|
||||||
|
}
|
||||||
|
this.content = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
delTag(index) {
|
||||||
|
if (index === false) {
|
||||||
|
if (this.content !== '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
index = this.disSource.length - 1;
|
||||||
|
}
|
||||||
|
this.disSource.splice(index, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
21
resources/js/common/directives/clickoutside.js
vendored
Executable file
21
resources/js/common/directives/clickoutside.js
vendored
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
export default {
|
||||||
|
bind (el, binding, vnode) {
|
||||||
|
function documentHandler (e) {
|
||||||
|
if (el.contains(e.target)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (binding.expression) {
|
||||||
|
binding.value(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
el.__vueClickOutside__ = documentHandler;
|
||||||
|
document.addEventListener('click', documentHandler);
|
||||||
|
},
|
||||||
|
update () {
|
||||||
|
|
||||||
|
},
|
||||||
|
unbind (el, binding) {
|
||||||
|
document.removeEventListener('click', el.__vueClickOutside__);
|
||||||
|
delete el.__vueClickOutside__;
|
||||||
|
}
|
||||||
|
};
|
108
resources/js/common/directives/popper-novalue.js
vendored
Executable file
108
resources/js/common/directives/popper-novalue.js
vendored
Executable file
@ -0,0 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* https://github.com/freeze-component/vue-popper
|
||||||
|
* */
|
||||||
|
import Vue from 'vue';
|
||||||
|
const isServer = Vue.prototype.$isServer;
|
||||||
|
const Popper = isServer ? function() {} : require('popper.js/dist/umd/popper.js'); // eslint-disable-line
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
placement: {
|
||||||
|
type: String,
|
||||||
|
default: 'bottom'
|
||||||
|
},
|
||||||
|
boundariesPadding: {
|
||||||
|
type: Number,
|
||||||
|
default: 5
|
||||||
|
},
|
||||||
|
reference: Object,
|
||||||
|
popper: Object,
|
||||||
|
offset: {
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
transition: String,
|
||||||
|
options: {
|
||||||
|
type: Object,
|
||||||
|
default () {
|
||||||
|
return {
|
||||||
|
modifiers: {
|
||||||
|
computeStyle:{
|
||||||
|
gpuAcceleration: false,
|
||||||
|
},
|
||||||
|
preventOverflow :{
|
||||||
|
boundariesElement: 'window'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
visible: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
visible(val) {
|
||||||
|
if (val) {
|
||||||
|
if (this.handleIndexIncrease) this.handleIndexIncrease(); // just use for Poptip
|
||||||
|
this.updatePopper();
|
||||||
|
this.$emit('on-popper-show');
|
||||||
|
} else {
|
||||||
|
this.$emit('on-popper-hide');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
createPopper() {
|
||||||
|
if (isServer) return;
|
||||||
|
if (!/^(top|bottom|left|right)(-start|-end)?$/g.test(this.placement)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = this.options;
|
||||||
|
const popper = this.popper || this.$refs.popper;
|
||||||
|
const reference = this.reference || this.$refs.reference;
|
||||||
|
|
||||||
|
if (!popper || !reference) return;
|
||||||
|
|
||||||
|
if (this.popperJS && this.popperJS.hasOwnProperty('destroy')) {
|
||||||
|
this.popperJS.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
options.placement = this.placement;
|
||||||
|
|
||||||
|
if (!options.modifiers.offset) {
|
||||||
|
options.modifiers.offset = {};
|
||||||
|
}
|
||||||
|
options.modifiers.offset.offset = this.offset;
|
||||||
|
options.onCreate =()=>{
|
||||||
|
this.$nextTick(this.updatePopper);
|
||||||
|
this.$emit('created', this);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.popperJS = new Popper(reference, popper, options);
|
||||||
|
|
||||||
|
},
|
||||||
|
updatePopper() {
|
||||||
|
if (isServer) return;
|
||||||
|
this.popperJS ? this.popperJS.update() : this.createPopper();
|
||||||
|
},
|
||||||
|
doDestroy() {
|
||||||
|
if (isServer) return;
|
||||||
|
if (this.visible) return;
|
||||||
|
this.popperJS.destroy();
|
||||||
|
this.popperJS = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updated (){
|
||||||
|
this.$nextTick(()=>this.updatePopper());
|
||||||
|
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
if (isServer) return;
|
||||||
|
if (this.popperJS) {
|
||||||
|
this.popperJS.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
77
resources/js/common/directives/transfer-dom.js
vendored
Normal file
77
resources/js/common/directives/transfer-dom.js
vendored
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
// Thanks to: https://github.com/airyland/vux/blob/v2/src/directives/transfer-dom/index.js
|
||||||
|
// Thanks to: https://github.com/calebroseland/vue-dom-portal
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get target DOM Node
|
||||||
|
* @param {(Node|string|Boolean)} [node=document.body] DOM Node, CSS selector, or Boolean
|
||||||
|
* @return {Node} The target that the el will be appended to
|
||||||
|
*/
|
||||||
|
function getTarget (node) {
|
||||||
|
if (node === void 0) {
|
||||||
|
node = document.body
|
||||||
|
}
|
||||||
|
if (node === true) { return document.body }
|
||||||
|
return node instanceof window.Node ? node : document.querySelector(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
const directive = {
|
||||||
|
inserted (el, { value }, vnode) {
|
||||||
|
if ( el.dataset && el.dataset.transfer !== 'true') return false;
|
||||||
|
el.className = el.className ? el.className + ' v-transfer-dom' : 'v-transfer-dom';
|
||||||
|
const parentNode = el.parentNode;
|
||||||
|
if (!parentNode) return;
|
||||||
|
const home = document.createComment('');
|
||||||
|
let hasMovedOut = false;
|
||||||
|
|
||||||
|
if (value !== false) {
|
||||||
|
parentNode.replaceChild(home, el); // moving out, el is no longer in the document
|
||||||
|
getTarget(value).appendChild(el); // moving into new place
|
||||||
|
hasMovedOut = true
|
||||||
|
}
|
||||||
|
if (!el.__transferDomData) {
|
||||||
|
el.__transferDomData = {
|
||||||
|
parentNode: parentNode,
|
||||||
|
home: home,
|
||||||
|
target: getTarget(value),
|
||||||
|
hasMovedOut: hasMovedOut
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
componentUpdated (el, { value }) {
|
||||||
|
if ( el.dataset && el.dataset.transfer !== 'true') return false;
|
||||||
|
// need to make sure children are done updating (vs. `update`)
|
||||||
|
const ref$1 = el.__transferDomData;
|
||||||
|
if (!ref$1) return;
|
||||||
|
// homes.get(el)
|
||||||
|
const parentNode = ref$1.parentNode;
|
||||||
|
const home = ref$1.home;
|
||||||
|
const hasMovedOut = ref$1.hasMovedOut; // recall where home is
|
||||||
|
|
||||||
|
if (!hasMovedOut && value) {
|
||||||
|
// remove from document and leave placeholder
|
||||||
|
parentNode.replaceChild(home, el);
|
||||||
|
// append to target
|
||||||
|
getTarget(value).appendChild(el);
|
||||||
|
el.__transferDomData = Object.assign({}, el.__transferDomData, { hasMovedOut: true, target: getTarget(value) });
|
||||||
|
} else if (hasMovedOut && value === false) {
|
||||||
|
// previously moved, coming back home
|
||||||
|
parentNode.replaceChild(el, home);
|
||||||
|
el.__transferDomData = Object.assign({}, el.__transferDomData, { hasMovedOut: false, target: getTarget(value) });
|
||||||
|
} else if (value) {
|
||||||
|
// already moved, going somewhere else
|
||||||
|
getTarget(value).appendChild(el);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
unbind (el) {
|
||||||
|
if (el.dataset && el.dataset.transfer !== 'true') return false;
|
||||||
|
el.className = el.className.replace('v-transfer-dom', '');
|
||||||
|
const ref$1 = el.__transferDomData;
|
||||||
|
if (!ref$1) return;
|
||||||
|
if (el.__transferDomData.hasMovedOut === true) {
|
||||||
|
el.__transferDomData.parentNode && el.__transferDomData.parentNode.appendChild(el)
|
||||||
|
}
|
||||||
|
el.__transferDomData = null
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default directive;
|
219
resources/js/common/directives/v-click-outside-x.js
vendored
Normal file
219
resources/js/common/directives/v-click-outside-x.js
vendored
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
const CLICK = 'click';
|
||||||
|
const captureInstances = Object.create(null);
|
||||||
|
const nonCaptureInstances = Object.create(null);
|
||||||
|
const instancesList = [captureInstances, nonCaptureInstances];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The common event handler for bot capture and non-capture events.
|
||||||
|
*
|
||||||
|
* @param {!Object} context - The event context.
|
||||||
|
* @param {!Object} instances - The capture or non-capture registered instances.
|
||||||
|
* @param {Event} event - The event object.
|
||||||
|
* @returns {undefined} Default.
|
||||||
|
*/
|
||||||
|
const commonHandler = function _onCommonEvent(context, instances, event) {
|
||||||
|
const {target} = event;
|
||||||
|
|
||||||
|
const itemIteratee = function _itemIteratee(item) {
|
||||||
|
const {el} = item;
|
||||||
|
|
||||||
|
if (el !== target && !el.contains(target)) {
|
||||||
|
const {binding} = item;
|
||||||
|
|
||||||
|
if (binding.modifiers.stop) {
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (binding.modifiers.prevent) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.value.call(context, event);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const keysIteratee = function _keysIteratee(eventName) {
|
||||||
|
return instances[eventName].forEach(itemIteratee);
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.keys(instances).forEach(keysIteratee);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler for capture events.
|
||||||
|
*
|
||||||
|
* @param {Event} event - The event object.
|
||||||
|
*/
|
||||||
|
const captureEventHandler = function onCaptureEvent(event) {
|
||||||
|
/* eslint-disable-next-line babel/no-invalid-this */
|
||||||
|
commonHandler(this, captureInstances, event);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler for non-capture events.
|
||||||
|
*
|
||||||
|
* @param {Event} event - The event object.
|
||||||
|
*/
|
||||||
|
const nonCaptureEventHandler = function onNonCaptureEvent(event) {
|
||||||
|
/* eslint-disable-next-line babel/no-invalid-this */
|
||||||
|
commonHandler(this, nonCaptureInstances, event);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the correct event handler: Capture or non-capture.
|
||||||
|
*
|
||||||
|
* @param {boolean} useCapture - Indicate which handler to use; 'true' to use
|
||||||
|
* capture handler or 'false' for non-capture.
|
||||||
|
* @returns {Function} - The event handler.
|
||||||
|
*/
|
||||||
|
const getEventHandler = function _getEventHandler(useCapture) {
|
||||||
|
return useCapture ? captureEventHandler : nonCaptureEventHandler;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The directive definition.
|
||||||
|
* {@link https://vuejs.org/v2/guide/custom-directive.html|Custom directive}
|
||||||
|
*
|
||||||
|
* @namespace
|
||||||
|
* @property {!Object} $_captureInstances - Registered capture instances.
|
||||||
|
* @property {!Object} $_nonCaptureInstances - Registered non-capture instances.
|
||||||
|
* @property {Function} $_onCaptureEvent - Event handler for capture events.
|
||||||
|
* @property {Function} $_onNonCaptureEvent - Event handler for non-capture events.
|
||||||
|
* @property {Function} bind - Called only once, when the directive is first
|
||||||
|
* bound to the element.
|
||||||
|
* @property {Function} unbind - Called only once, when the directive is unbound
|
||||||
|
* from the element.
|
||||||
|
* @property {string} version - The version number of this release.
|
||||||
|
*/
|
||||||
|
export const directive = Object.defineProperties(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
$_captureInstances: {
|
||||||
|
value: captureInstances,
|
||||||
|
},
|
||||||
|
|
||||||
|
$_nonCaptureInstances: {
|
||||||
|
value: nonCaptureInstances,
|
||||||
|
},
|
||||||
|
|
||||||
|
$_onCaptureEvent: {
|
||||||
|
value: captureEventHandler,
|
||||||
|
},
|
||||||
|
|
||||||
|
$_onNonCaptureEvent: {
|
||||||
|
value: nonCaptureEventHandler,
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注意,这里的 arg 修改为 capture,这样可以动态设置,原先的事件作为 modifiers
|
||||||
|
* */
|
||||||
|
bind: {
|
||||||
|
value: function bind(el, binding) {
|
||||||
|
if (typeof binding.value !== 'function') {
|
||||||
|
throw new TypeError('Binding value must be a function.');
|
||||||
|
}
|
||||||
|
|
||||||
|
let eventType;
|
||||||
|
const modifiers = binding.modifiers;
|
||||||
|
if (modifiers.click) eventType = 'click';
|
||||||
|
else if (modifiers.mousedown) eventType = 'mousedown';
|
||||||
|
else if (modifiers.touchstart) eventType = 'touchstart';
|
||||||
|
else eventType = CLICK;
|
||||||
|
|
||||||
|
const useCapture = binding.arg;
|
||||||
|
|
||||||
|
const normalisedBinding = {
|
||||||
|
...binding,
|
||||||
|
...{
|
||||||
|
modifiers: {
|
||||||
|
...{
|
||||||
|
capture: false,
|
||||||
|
prevent: false,
|
||||||
|
stop: false,
|
||||||
|
},
|
||||||
|
...binding.modifiers,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const instances = useCapture ? captureInstances : nonCaptureInstances;
|
||||||
|
|
||||||
|
if (!Array.isArray(instances[eventType])) {
|
||||||
|
instances[eventType] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instances[eventType].push({el, binding: normalisedBinding}) === 1) {
|
||||||
|
if (typeof document === 'object' && document) {
|
||||||
|
document.addEventListener(
|
||||||
|
eventType,
|
||||||
|
getEventHandler(useCapture),
|
||||||
|
useCapture,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
unbind: {
|
||||||
|
value: function unbind(el) {
|
||||||
|
const compareElements = function _compareElements(item) {
|
||||||
|
return item.el !== el;
|
||||||
|
};
|
||||||
|
|
||||||
|
const instancesIteratee = function _instancesIteratee(instances) {
|
||||||
|
const instanceKeys = Object.keys(instances);
|
||||||
|
|
||||||
|
if (instanceKeys.length) {
|
||||||
|
const useCapture = instances === captureInstances;
|
||||||
|
|
||||||
|
const keysIteratee = function _keysIteratee(eventName) {
|
||||||
|
const newInstance = instances[eventName].filter(compareElements);
|
||||||
|
|
||||||
|
if (newInstance.length) {
|
||||||
|
instances[eventName] = newInstance;
|
||||||
|
} else {
|
||||||
|
if (typeof document === 'object' && document) {
|
||||||
|
document.removeEventListener(
|
||||||
|
eventName,
|
||||||
|
getEventHandler(useCapture),
|
||||||
|
useCapture,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete instances[eventName];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
instanceKeys.forEach(keysIteratee);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
instancesList.forEach(instancesIteratee);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Note: This needs to be manually updated to match package.json. */
|
||||||
|
version: {
|
||||||
|
enumerable: true,
|
||||||
|
value: '3.7.1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Function} Vue - The constructor.
|
||||||
|
* @property {Function} directive - You can register a global custom directive
|
||||||
|
* with the Vue.directive() method, passing in a directiveID followed by a
|
||||||
|
* definition object.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Vue.js plugin should expose an install method. The method will be called
|
||||||
|
* with the Vue constructor as the first argument, along with possible options.
|
||||||
|
* {@link https://vuejs.org/v2/guide/plugins.html#Writing-a-Plugin|Writing a plugin}.
|
||||||
|
*
|
||||||
|
* @param {Vue} Vue - The Vue function.
|
||||||
|
*/
|
||||||
|
export function install(Vue) {
|
||||||
|
Vue.directive('click-outside', directive);
|
||||||
|
}
|
1549
resources/js/common/functions/index.js
vendored
Executable file
1549
resources/js/common/functions/index.js
vendored
Executable file
File diff suppressed because it is too large
Load Diff
233
resources/js/common/language/index.js
vendored
Normal file
233
resources/js/common/language/index.js
vendored
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
const languageTypeLists = {
|
||||||
|
"EN": "English",
|
||||||
|
"KM": "ភាសាខ្មែរ",
|
||||||
|
"TH": "ภาษาไทย",
|
||||||
|
"KO": "한국어",
|
||||||
|
"JA": "日本語",
|
||||||
|
"CN": "中文-简体",
|
||||||
|
"TC": "中文-繁體",
|
||||||
|
};
|
||||||
|
const languageCachesObjects = {};
|
||||||
|
const languageListenerObjects = [];
|
||||||
|
|
||||||
|
export default {
|
||||||
|
install(Vue) {
|
||||||
|
Vue.mixin({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
languageInit: false,
|
||||||
|
languageData: [],
|
||||||
|
languageType: window.localStorage['__language:type__'] || this.__getNavigatorLanguage(),
|
||||||
|
languageList: languageTypeLists,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
languageType: {
|
||||||
|
handler(type) {
|
||||||
|
if (type && typeof this.initLanguage === "function") {
|
||||||
|
this.initLanguage();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 获取浏览器默认语言
|
||||||
|
* @returns {string}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
__getNavigatorLanguage() {
|
||||||
|
let lang = 'EN';
|
||||||
|
let navLang = (navigator.language || navigator.userLanguage + "").toUpperCase();
|
||||||
|
switch (navLang) {
|
||||||
|
case "EN":
|
||||||
|
case "KM":
|
||||||
|
case "TH":
|
||||||
|
case "KO":
|
||||||
|
case "JA":
|
||||||
|
lang = navLang
|
||||||
|
break;
|
||||||
|
case "ZH-CN":
|
||||||
|
case "ZH":
|
||||||
|
lang = 'CN'
|
||||||
|
break;
|
||||||
|
case "ZH-TW":
|
||||||
|
case "ZH-HK":
|
||||||
|
lang = 'TC'
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return window.localStorage['__language:type__'] = lang;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化语言数据
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
__initLanguageData() {
|
||||||
|
if (this.languageInit === false) {
|
||||||
|
this.languageInit = true;
|
||||||
|
//
|
||||||
|
this.addLanguageData(require("../../../lang/language.js").default);
|
||||||
|
//
|
||||||
|
languageListenerObjects.push((lang) => {
|
||||||
|
this.languageType = lang;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否数组
|
||||||
|
* @param obj
|
||||||
|
* @returns {boolean}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
__isArray(obj) {
|
||||||
|
return typeof (obj) == "object" && Object.prototype.toString.call(obj).toLowerCase() == '[object array]' && typeof obj.length == "number";
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 监听语言变化
|
||||||
|
* @param callback
|
||||||
|
*/
|
||||||
|
setLanguageListener(callback) {
|
||||||
|
if (typeof callback === 'function') {
|
||||||
|
languageListenerObjects.push((lang) => {
|
||||||
|
callback(lang);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 语言包数据
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
addLanguageData(data) {
|
||||||
|
if (!this.__isArray(data)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.__initLanguageData();
|
||||||
|
this.languageData.push(...data);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 变化语言
|
||||||
|
* @param language
|
||||||
|
*/
|
||||||
|
setLanguage(language) {
|
||||||
|
this.__initLanguageData();
|
||||||
|
setTimeout(() => {
|
||||||
|
window.localStorage['__language:type__'] = language;
|
||||||
|
languageListenerObjects.forEach((call) => {
|
||||||
|
if (typeof call === 'function') {
|
||||||
|
call(language);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 10)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取语言
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
getLanguage() {
|
||||||
|
this.__initLanguageData();
|
||||||
|
return this.languageType;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 替换%遍历
|
||||||
|
* @param text
|
||||||
|
* @param objects
|
||||||
|
*/
|
||||||
|
replaceArgumentsLanguage(text, objects) {
|
||||||
|
let j = 1;
|
||||||
|
while (text.indexOf("%") !== -1) {
|
||||||
|
if (typeof objects[j] === "object") {
|
||||||
|
text = text.replace("%", "");
|
||||||
|
} else {
|
||||||
|
text = text.replace("%", objects[j]);
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 译文转义
|
||||||
|
* @param val
|
||||||
|
* @returns {string|*}
|
||||||
|
*/
|
||||||
|
replaceEscape(val) {
|
||||||
|
if (!val || val == '') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return val.replace(/%/g, '%').replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示语言
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
$L(text) {
|
||||||
|
if (typeof arguments[1] !== "undefined") {
|
||||||
|
return this.$L(this.replaceArgumentsLanguage(text, arguments));
|
||||||
|
}
|
||||||
|
if (typeof text !== "string" || !text) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
this.__initLanguageData();
|
||||||
|
//
|
||||||
|
if (typeof languageCachesObjects[text] === "undefined") {
|
||||||
|
let tmpRege = null;
|
||||||
|
let tmpData = this.languageData.find((obj) => {
|
||||||
|
return Object.values(obj).find((val) => {
|
||||||
|
tmpRege = new RegExp("^" + this.replaceEscape(val).replace(/%/g, "(.*?)") + "$", "g");
|
||||||
|
return !!text.match(tmpRege);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
languageCachesObjects[text] = {
|
||||||
|
rege: tmpRege,
|
||||||
|
data: tmpData,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const {rege, data} = languageCachesObjects[text];
|
||||||
|
if (data
|
||||||
|
&& typeof data === "object"
|
||||||
|
&& typeof data[this.languageType] !== "undefined"
|
||||||
|
&& data[this.languageType]) {
|
||||||
|
let index = 0;
|
||||||
|
let value = data[this.languageType];
|
||||||
|
value = value.replace(/%/g, function () {
|
||||||
|
return "$" + (++index);
|
||||||
|
});
|
||||||
|
return text.replace(rege, value);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
if (this.languageType == "CN") {
|
||||||
|
try {
|
||||||
|
let key = '__language:Undefined__';
|
||||||
|
let languageTmp = JSON.parse(window.localStorage[key] || '[]');
|
||||||
|
if (!this.__isArray(languageTmp)) {
|
||||||
|
languageTmp = [];
|
||||||
|
}
|
||||||
|
let tmpRege = null;
|
||||||
|
let tmpData = languageTmp.find((val) => {
|
||||||
|
tmpRege = new RegExp("^" + val.replace(/%/g, "(.*?)") + "$", "g");
|
||||||
|
return !!text.match(tmpRege);
|
||||||
|
});
|
||||||
|
if (!tmpData) {
|
||||||
|
languageTmp.push(text);
|
||||||
|
window.localStorage[key] = JSON.stringify(languageTmp);
|
||||||
|
}
|
||||||
|
} catch (e) { }
|
||||||
|
}
|
||||||
|
//
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
55
resources/js/common/mixins/index.js
vendored
Normal file
55
resources/js/common/mixins/index.js
vendored
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
export default {
|
||||||
|
install(Vue) {
|
||||||
|
Vue.mixin({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
mixinId: 0,
|
||||||
|
//用户信息
|
||||||
|
userLogin: false,
|
||||||
|
userInfo: {},
|
||||||
|
userName: '',
|
||||||
|
userId: 0,
|
||||||
|
//浏览器宽度≤768返回true
|
||||||
|
windowMax768: window.innerWidth <= 768,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
if (typeof window.__mixinId != "number") window.__mixinId = 0;
|
||||||
|
this.mixinId = window.__mixinId++;
|
||||||
|
//
|
||||||
|
this.userLogin = $A.getToken() !== false;
|
||||||
|
this.userInfo = $A.getUserInfo();
|
||||||
|
this.userName = this.userInfo.username || '';
|
||||||
|
this.userId = parseInt(this.userInfo.userid);
|
||||||
|
$A.setOnUserInfoListener('mixins_' + this.mixinId, (data, isLogin) => {
|
||||||
|
this.userLogin = isLogin;
|
||||||
|
this.userInfo = data;
|
||||||
|
this.userName = this.userInfo.username || '';
|
||||||
|
this.userId = parseInt(this.userInfo.userid);
|
||||||
|
});
|
||||||
|
//
|
||||||
|
window.addEventListener('resize', this.windowMax768Listener);
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeDestroy() {
|
||||||
|
$A.removeUserInfoListener('mixins_' + this.mixinId);
|
||||||
|
window.removeEventListener('resize', this.windowMax768Listener);
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
isArray(obj) {
|
||||||
|
return typeof (obj) == "object" && Object.prototype.toString.call(obj).toLowerCase() == '[object array]' && typeof obj.length == "number";
|
||||||
|
},
|
||||||
|
|
||||||
|
isJson(obj) {
|
||||||
|
return typeof (obj) == "object" && Object.prototype.toString.call(obj).toLowerCase() == "[object object]" && typeof obj.length == "undefined";
|
||||||
|
},
|
||||||
|
|
||||||
|
windowMax768Listener() {
|
||||||
|
this.windowMax768 = window.innerWidth <= 768
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
1027
resources/js/main.js
vendored
Executable file
1027
resources/js/main.js
vendored
Executable file
File diff suppressed because it is too large
Load Diff
45
resources/js/pages/404.vue
Normal file
45
resources/js/pages/404.vue
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<template>
|
||||||
|
<div class="page-404">
|
||||||
|
<div class="flex-center position-ref full-height">
|
||||||
|
<div class="code">404</div>
|
||||||
|
<div class="message">Not Found</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.page-404 {
|
||||||
|
background-color: #fff;
|
||||||
|
color: #636b6f;
|
||||||
|
font-weight: 400;
|
||||||
|
height: 100vh;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
.full-height {
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-center {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.position-ref {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code {
|
||||||
|
border-right: 2px solid;
|
||||||
|
font-size: 26px;
|
||||||
|
padding: 0 15px 0 15px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
font-size: 18px;
|
||||||
|
padding: 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
14
resources/js/pages/dashboard/index.vue
Normal file
14
resources/js/pages/dashboard/index.vue
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<template>
|
||||||
|
<div>dashboard</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
21
resources/js/pages/index.vue
Normal file
21
resources/js/pages/index.vue
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<template>
|
||||||
|
<div></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
if (this.usrLogin) {
|
||||||
|
this.goForward({path: '/dashboard'}, true);
|
||||||
|
} else {
|
||||||
|
this.goForward({path: '/login'}, true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deactivated() {
|
||||||
|
this.$destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
25
resources/js/pages/login/index.vue
Normal file
25
resources/js/pages/login/index.vue
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<template>
|
||||||
|
<div class="page-login">
|
||||||
|
<PageTitle>{{$L('登录页面')}}</PageTitle>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.page-login {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
22
resources/js/routes.js
vendored
Executable file
22
resources/js/routes.js
vendored
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
export default [
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
name: 'index',
|
||||||
|
component: resolve => require(['./pages/index.vue'], resolve)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '*',
|
||||||
|
name: '404',
|
||||||
|
component: resolve => require(['./pages/404.vue'], resolve),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/login',
|
||||||
|
name: 'login',
|
||||||
|
component: resolve => require(['./pages/login/index.vue'], resolve),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/dashboard',
|
||||||
|
name: 'dashboard',
|
||||||
|
component: resolve => require(['./pages/dashboard/index.vue'], resolve),
|
||||||
|
},
|
||||||
|
]
|
2
resources/lang/language.js
vendored
Normal file
2
resources/lang/language.js
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
exports.default = [
|
||||||
|
];
|
876
resources/public/js/html2md.js
vendored
876
resources/public/js/html2md.js
vendored
@ -1,876 +0,0 @@
|
|||||||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.toMarkdown = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
|
||||||
/*
|
|
||||||
* to-markdown - https://github.com/LCTT/LCTT-Helper/blob/master/js/to-markdown.js
|
|
||||||
*
|
|
||||||
* Copyright 2011+, Dom Christie
|
|
||||||
* Licenced under the MIT licence
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use strict'
|
|
||||||
|
|
||||||
var toMarkdown
|
|
||||||
var converters
|
|
||||||
var mdConverters = require('./lib/md-converters')
|
|
||||||
var gfmConverters = require('./lib/gfm-converters')
|
|
||||||
var HtmlParser = require('./lib/html-parser')
|
|
||||||
var collapse = require('collapse-whitespace')
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Utilities
|
|
||||||
*/
|
|
||||||
|
|
||||||
var blocks = ['address', 'article', 'aside', 'audio', 'blockquote', 'body',
|
|
||||||
'canvas', 'center', 'dd', 'dir', 'div', 'dl', 'dt', 'fieldset', 'figcaption',
|
|
||||||
'figure', 'footer', 'form', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7',
|
|
||||||
'header', 'hgroup', 'hr', 'html', 'isindex', 'li', 'main', 'menu', 'nav',
|
|
||||||
'noframes', 'noscript', 'ol', 'output', 'p', 'pre', 'section', 'table',
|
|
||||||
'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'ul'
|
|
||||||
]
|
|
||||||
|
|
||||||
function isBlock (node) {
|
|
||||||
return blocks.indexOf(node.nodeName.toLowerCase()) !== -1
|
|
||||||
}
|
|
||||||
|
|
||||||
var voids = [
|
|
||||||
'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input',
|
|
||||||
'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr'
|
|
||||||
]
|
|
||||||
|
|
||||||
function isVoid (node) {
|
|
||||||
return voids.indexOf(node.nodeName.toLowerCase()) !== -1
|
|
||||||
}
|
|
||||||
|
|
||||||
function htmlToDom (string) {
|
|
||||||
var tree = new HtmlParser().parseFromString(string, 'text/html')
|
|
||||||
collapse(tree.documentElement, isBlock)
|
|
||||||
return tree
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Flattens DOM tree into single array
|
|
||||||
*/
|
|
||||||
|
|
||||||
function bfsOrder (node) {
|
|
||||||
var inqueue = [node]
|
|
||||||
var outqueue = []
|
|
||||||
var elem
|
|
||||||
var children
|
|
||||||
var i
|
|
||||||
|
|
||||||
while (inqueue.length > 0) {
|
|
||||||
elem = inqueue.shift()
|
|
||||||
outqueue.push(elem)
|
|
||||||
children = elem.childNodes
|
|
||||||
for (i = children.length - 1; i >= 0; i--) {
|
|
||||||
if (children[i].nodeType === 1) inqueue.push(children[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
outqueue.shift()
|
|
||||||
return outqueue
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Contructs a Markdown string of replacement text for a given node
|
|
||||||
*/
|
|
||||||
|
|
||||||
function getContent (node) {
|
|
||||||
var text = ''
|
|
||||||
for (var i = 0; i < node.childNodes.length; i++) {
|
|
||||||
if (node.childNodes[i].nodeType === 1) {
|
|
||||||
text += node.childNodes[i]._replacement
|
|
||||||
} else if (node.childNodes[i].nodeType === 3) {
|
|
||||||
text += node.childNodes[i].data
|
|
||||||
} else continue
|
|
||||||
}
|
|
||||||
return text
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns the HTML string of an element with its contents converted
|
|
||||||
*/
|
|
||||||
|
|
||||||
function outer (node, content) {
|
|
||||||
return node.cloneNode(false).outerHTML.replace('><', '>' + content + '<')
|
|
||||||
}
|
|
||||||
|
|
||||||
function canConvert (node, filter) {
|
|
||||||
if (typeof filter === 'string') {
|
|
||||||
return filter === node.nodeName.toLowerCase()
|
|
||||||
}
|
|
||||||
if (Array.isArray(filter)) {
|
|
||||||
return filter.indexOf(node.nodeName.toLowerCase()) !== -1
|
|
||||||
} else if (typeof filter === 'function') {
|
|
||||||
return filter.call(toMarkdown, node)
|
|
||||||
} else {
|
|
||||||
throw new TypeError('`filter` needs to be a string, array, or function')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isFlankedByWhitespace (side, node) {
|
|
||||||
var sibling
|
|
||||||
var regExp
|
|
||||||
var isFlanked
|
|
||||||
|
|
||||||
if (side === 'left') {
|
|
||||||
sibling = node.previousSibling
|
|
||||||
regExp = / $/
|
|
||||||
} else {
|
|
||||||
sibling = node.nextSibling
|
|
||||||
regExp = /^ /
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sibling) {
|
|
||||||
if (sibling.nodeType === 3) {
|
|
||||||
isFlanked = regExp.test(sibling.nodeValue)
|
|
||||||
} else if (sibling.nodeType === 1 && !isBlock(sibling)) {
|
|
||||||
isFlanked = regExp.test(sibling.textContent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return isFlanked
|
|
||||||
}
|
|
||||||
|
|
||||||
function flankingWhitespace (node, content) {
|
|
||||||
var leading = ''
|
|
||||||
var trailing = ''
|
|
||||||
|
|
||||||
if (!isBlock(node)) {
|
|
||||||
var hasLeading = /^[ \r\n\t]/.test(content)
|
|
||||||
var hasTrailing = /[ \r\n\t]$/.test(content)
|
|
||||||
|
|
||||||
if (hasLeading && !isFlankedByWhitespace('left', node)) {
|
|
||||||
leading = ' '
|
|
||||||
}
|
|
||||||
if (hasTrailing && !isFlankedByWhitespace('right', node)) {
|
|
||||||
trailing = ' '
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return { leading: leading, trailing: trailing }
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Finds a Markdown converter, gets the replacement, and sets it on
|
|
||||||
* `_replacement`
|
|
||||||
*/
|
|
||||||
|
|
||||||
function process (node) {
|
|
||||||
var replacement
|
|
||||||
var content = getContent(node)
|
|
||||||
|
|
||||||
// Remove blank nodes
|
|
||||||
if (!isVoid(node) && !/A|TH|TD/.test(node.nodeName) && /^\s*$/i.test(content)) {
|
|
||||||
node._replacement = ''
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < converters.length; i++) {
|
|
||||||
var converter = converters[i]
|
|
||||||
|
|
||||||
if (canConvert(node, converter.filter)) {
|
|
||||||
if (typeof converter.replacement !== 'function') {
|
|
||||||
throw new TypeError(
|
|
||||||
'`replacement` needs to be a function that returns a string'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
var whitespace = flankingWhitespace(node, content)
|
|
||||||
|
|
||||||
if (whitespace.leading || whitespace.trailing) {
|
|
||||||
content = content.trim()
|
|
||||||
}
|
|
||||||
replacement = whitespace.leading +
|
|
||||||
converter.replacement.call(toMarkdown, content, node) +
|
|
||||||
whitespace.trailing
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
node._replacement = replacement
|
|
||||||
}
|
|
||||||
|
|
||||||
toMarkdown = function (input, options) {
|
|
||||||
options = options || {}
|
|
||||||
|
|
||||||
if (typeof input !== 'string') {
|
|
||||||
throw new TypeError(input + ' is not a string')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input === '') {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
|
|
||||||
// Escape potential ol triggers
|
|
||||||
input = input.replace(/(\d+)\. /g, '$1\\. ')
|
|
||||||
|
|
||||||
var clone = htmlToDom(input).body
|
|
||||||
var nodes = bfsOrder(clone)
|
|
||||||
var output
|
|
||||||
|
|
||||||
converters = mdConverters.slice(0)
|
|
||||||
if (options.gfm) {
|
|
||||||
converters = gfmConverters.concat(converters)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.converters) {
|
|
||||||
converters = options.converters.concat(converters)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process through nodes in reverse (so deepest child elements are first).
|
|
||||||
for (var i = nodes.length - 1; i >= 0; i--) {
|
|
||||||
process(nodes[i])
|
|
||||||
}
|
|
||||||
output = getContent(clone)
|
|
||||||
|
|
||||||
return output.replace(/^[\t\r\n]+|[\t\r\n\s]+$/g, '')
|
|
||||||
.replace(/\n\s+\n/g, '\n\n')
|
|
||||||
.replace(/\n{3,}/g, '\n\n')
|
|
||||||
}
|
|
||||||
|
|
||||||
toMarkdown.isBlock = isBlock
|
|
||||||
toMarkdown.isVoid = isVoid
|
|
||||||
toMarkdown.outer = outer
|
|
||||||
|
|
||||||
module.exports = toMarkdown
|
|
||||||
|
|
||||||
},{"./lib/gfm-converters":2,"./lib/html-parser":3,"./lib/md-converters":4,"collapse-whitespace":6}],2:[function(require,module,exports){
|
|
||||||
'use strict'
|
|
||||||
|
|
||||||
function cell (content, node) {
|
|
||||||
var index = Array.prototype.indexOf.call(node.parentNode.childNodes, node)
|
|
||||||
var prefix = ' '
|
|
||||||
if (index === 0) prefix = '| '
|
|
||||||
return prefix + content + ' |'
|
|
||||||
}
|
|
||||||
|
|
||||||
var highlightRegEx = /highlight highlight-(\S+)/
|
|
||||||
|
|
||||||
module.exports = [
|
|
||||||
{
|
|
||||||
filter: 'br',
|
|
||||||
replacement: function () {
|
|
||||||
return '\n'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
filter: ['del', 's', 'strike'],
|
|
||||||
replacement: function (content) {
|
|
||||||
return '~~' + content + '~~'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
filter: function (node) {
|
|
||||||
return node.type === 'checkbox' && node.parentNode.nodeName === 'LI'
|
|
||||||
},
|
|
||||||
replacement: function (content, node) {
|
|
||||||
return (node.checked ? '[x]' : '[ ]') + ' '
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
filter: ['th', 'td'],
|
|
||||||
replacement: function (content, node) {
|
|
||||||
return cell(content, node)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
filter: 'tr',
|
|
||||||
replacement: function (content, node) {
|
|
||||||
var borderCells = ''
|
|
||||||
var alignMap = { left: ':--', right: '--:', center: ':-:' }
|
|
||||||
|
|
||||||
if (node.parentNode.nodeName === 'THEAD') {
|
|
||||||
for (var i = 0; i < node.childNodes.length; i++) {
|
|
||||||
var align = node.childNodes[i].attributes.align
|
|
||||||
var border = '---'
|
|
||||||
|
|
||||||
if (align) border = alignMap[align.value] || border
|
|
||||||
|
|
||||||
borderCells += cell(border, node.childNodes[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return '\n' + content + (borderCells ? '\n' + borderCells : '')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
filter: 'table',
|
|
||||||
replacement: function (content) {
|
|
||||||
return '\n\n' + content + '\n\n'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
filter: ['thead', 'tbody', 'tfoot'],
|
|
||||||
replacement: function (content) {
|
|
||||||
return content
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Fenced code blocks
|
|
||||||
{
|
|
||||||
filter: function (node) {
|
|
||||||
return node.nodeName === 'PRE' &&
|
|
||||||
node.firstChild &&
|
|
||||||
node.firstChild.nodeName === 'CODE'
|
|
||||||
},
|
|
||||||
replacement: function (content, node) {
|
|
||||||
return '\n\n```\n' + node.firstChild.textContent + '\n```\n\n'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Syntax-highlighted code blocks
|
|
||||||
{
|
|
||||||
filter: function (node) {
|
|
||||||
return node.nodeName === 'PRE' &&
|
|
||||||
node.parentNode.nodeName === 'DIV' &&
|
|
||||||
highlightRegEx.test(node.parentNode.className)
|
|
||||||
},
|
|
||||||
replacement: function (content, node) {
|
|
||||||
var language = node.parentNode.className.match(highlightRegEx)[1]
|
|
||||||
return '\n\n```' + language + '\n' + node.textContent + '\n```\n\n'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
filter: function (node) {
|
|
||||||
return node.nodeName === 'DIV' &&
|
|
||||||
highlightRegEx.test(node.className)
|
|
||||||
},
|
|
||||||
replacement: function (content) {
|
|
||||||
return '\n\n' + content + '\n\n'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
},{}],3:[function(require,module,exports){
|
|
||||||
/*
|
|
||||||
* Set up window for Node.js
|
|
||||||
*/
|
|
||||||
|
|
||||||
var _window = (typeof window !== 'undefined' ? window : this)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Parsing HTML strings
|
|
||||||
*/
|
|
||||||
|
|
||||||
function canParseHtmlNatively () {
|
|
||||||
var Parser = _window.DOMParser
|
|
||||||
var canParse = false
|
|
||||||
|
|
||||||
// Adapted from https://gist.github.com/1129031
|
|
||||||
// Firefox/Opera/IE throw errors on unsupported types
|
|
||||||
try {
|
|
||||||
// WebKit returns null on unsupported types
|
|
||||||
if (new Parser().parseFromString('', 'text/html')) {
|
|
||||||
canParse = true
|
|
||||||
}
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
return canParse
|
|
||||||
}
|
|
||||||
|
|
||||||
function createHtmlParser () {
|
|
||||||
var Parser = function () {}
|
|
||||||
|
|
||||||
// For Node.js environments
|
|
||||||
if (typeof document === 'undefined') {
|
|
||||||
var jsdom = require('jsdom')
|
|
||||||
Parser.prototype.parseFromString = function (string) {
|
|
||||||
return jsdom.jsdom(string, {
|
|
||||||
features: {
|
|
||||||
FetchExternalResources: [],
|
|
||||||
ProcessExternalResources: false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!shouldUseActiveX()) {
|
|
||||||
Parser.prototype.parseFromString = function (string) {
|
|
||||||
var doc = document.implementation.createHTMLDocument('')
|
|
||||||
doc.open()
|
|
||||||
doc.write(string)
|
|
||||||
doc.close()
|
|
||||||
return doc
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Parser.prototype.parseFromString = function (string) {
|
|
||||||
var doc = new window.ActiveXObject('htmlfile')
|
|
||||||
doc.designMode = 'on' // disable on-page scripts
|
|
||||||
doc.open()
|
|
||||||
doc.write(string)
|
|
||||||
doc.close()
|
|
||||||
return doc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Parser
|
|
||||||
}
|
|
||||||
|
|
||||||
function shouldUseActiveX () {
|
|
||||||
var useActiveX = false
|
|
||||||
|
|
||||||
try {
|
|
||||||
document.implementation.createHTMLDocument('').open()
|
|
||||||
} catch (e) {
|
|
||||||
if (window.ActiveXObject) useActiveX = true
|
|
||||||
}
|
|
||||||
|
|
||||||
return useActiveX
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = canParseHtmlNatively() ? _window.DOMParser : createHtmlParser()
|
|
||||||
|
|
||||||
},{"jsdom":8}],4:[function(require,module,exports){
|
|
||||||
'use strict'
|
|
||||||
module.exports = [
|
|
||||||
// P标签处理
|
|
||||||
{
|
|
||||||
filter: 'p',
|
|
||||||
replacement: function (content, node) {
|
|
||||||
var attrClass = node.getAttribute('class') || ''
|
|
||||||
|
|
||||||
if (attrClass === 'command') {
|
|
||||||
if (!content.endsWith('\n')) {
|
|
||||||
content += '\n'
|
|
||||||
}
|
|
||||||
return '\n```\n' + content + '```\n'
|
|
||||||
} else {
|
|
||||||
return '\n\n' + content + '\n\n'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// BR 标签处理
|
|
||||||
{
|
|
||||||
filter: 'br',
|
|
||||||
replacement: function () {
|
|
||||||
return ' \n'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// H1 处理
|
|
||||||
{
|
|
||||||
filter: 'h1',
|
|
||||||
replacement: function (content, node) {
|
|
||||||
if (typeof titleLock === "undefined") {
|
|
||||||
var titleLock = false;
|
|
||||||
}
|
|
||||||
if (!titleLock) {
|
|
||||||
titleLock = true;
|
|
||||||
return content + "\n" + "=".repeat(60);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return '\n\n' + '# ' + content + '\n\n'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// H2-H7 标签处理
|
|
||||||
{
|
|
||||||
filter: ['h2', 'h3', 'h4', 'h5', 'h6', 'h7'],
|
|
||||||
replacement: function (content, node) {
|
|
||||||
var hLevel = node.nodeName.charAt(1)
|
|
||||||
var hPrefix = '##'
|
|
||||||
hLevel = hLevel - 2
|
|
||||||
for (var i = 0; i < hLevel; i++) {
|
|
||||||
hPrefix += '#'
|
|
||||||
}
|
|
||||||
return '\n\n' + hPrefix + ' ' + content + '\n\n'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// HR 标签处理
|
|
||||||
{
|
|
||||||
filter: 'hr',
|
|
||||||
replacement: function () {
|
|
||||||
return '\n\n* * *\n\n'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// em i 斜体处理
|
|
||||||
{
|
|
||||||
filter: ['em', 'i'],
|
|
||||||
replacement: function (content) {
|
|
||||||
return ' _' + content + '_ '
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// Strong b 粗体处理
|
|
||||||
{
|
|
||||||
filter: ['strong', 'b'],
|
|
||||||
replacement: function (content) {
|
|
||||||
return '**' + content + '**'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// Inline code
|
|
||||||
{
|
|
||||||
filter: function (node) {
|
|
||||||
var hasSiblings = node.previousSibling || node.nextSibling
|
|
||||||
var isCodeBlock = node.parentNode.nodeName === 'PRE' && !hasSiblings
|
|
||||||
|
|
||||||
return node.nodeName === 'CODE' && !isCodeBlock
|
|
||||||
},
|
|
||||||
replacement: function (content) {
|
|
||||||
return '`' + content + '`'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// A 标签处理
|
|
||||||
{
|
|
||||||
filter: function (node) {
|
|
||||||
return node.nodeName === 'A' && node.getAttribute('href')
|
|
||||||
},
|
|
||||||
replacement: function (content, node) {
|
|
||||||
return '[' + content + '](' + node.getAttribute('href') + ')'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 特殊情况下的A标签处理
|
|
||||||
{
|
|
||||||
filter: function (node) {
|
|
||||||
return node.nodeName === 'A' && node.getAttribute('style')
|
|
||||||
},
|
|
||||||
replacement: function (content, node) {
|
|
||||||
return content
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// IMG 标签处理
|
|
||||||
{
|
|
||||||
filter: 'img',
|
|
||||||
replacement: function (content, node) {
|
|
||||||
var alt = node.alt || ''
|
|
||||||
var src = node.getAttribute('src') || ''
|
|
||||||
var title = node.title || ''
|
|
||||||
var titlePart = title ? ' "' + title + '"' : ''
|
|
||||||
return src ? '\n![' + alt + ']' + '(' + src + titlePart + ')\n' : ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 代码块处理
|
|
||||||
{
|
|
||||||
filter: 'pre',
|
|
||||||
replacement: function (content, node) {
|
|
||||||
let contentText = node.innerText
|
|
||||||
if (!contentText.endsWith('\n')) {
|
|
||||||
contentText += '\n'
|
|
||||||
}
|
|
||||||
return '\n```\n' + contentText + '```\n'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 行内代码处理
|
|
||||||
{
|
|
||||||
filter: 'code',
|
|
||||||
replacement: function (content, node) {
|
|
||||||
return '`' + content + '`'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// IFrame 提醒
|
|
||||||
{
|
|
||||||
filter: 'iframe',
|
|
||||||
replacement: function (content, node) {
|
|
||||||
console.log(node);
|
|
||||||
console.log(content);
|
|
||||||
return '\n ** 此处有iframe,请手动处理 ** \n'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// Canvas 提醒
|
|
||||||
{
|
|
||||||
filter: 'canvas',
|
|
||||||
replacement: function (content, node) {
|
|
||||||
return '\n ** 此处有Canvas,请手动处理 ** \n'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// div 处理
|
|
||||||
{
|
|
||||||
filter: 'div',
|
|
||||||
replacement: function (content, node) {
|
|
||||||
var attrClass = node.getAttribute('class') || ''
|
|
||||||
if (attrClass === 'code') {
|
|
||||||
if (!content.endsWith('\n')) {
|
|
||||||
content += '\n'
|
|
||||||
}
|
|
||||||
return '\n```\n' + content + '```\n'
|
|
||||||
} else {
|
|
||||||
return content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'filter': 'textarea',
|
|
||||||
replacement: function (content, node) {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 直接返回内容的标签
|
|
||||||
{
|
|
||||||
filter: ['figure', 'span', 'small', 'section', 'font', 'asymspc', 'button', 'article', 'figcaption'],
|
|
||||||
replacement: function (content) {
|
|
||||||
return content
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 引用
|
|
||||||
{
|
|
||||||
filter: 'blockquote',
|
|
||||||
replacement: function (content) {
|
|
||||||
content = content.trim()
|
|
||||||
content = content.replace(/\n{3,}/g, '\n\n')
|
|
||||||
content = content.replace(/^/gm, '> ')
|
|
||||||
return '\n\n' + content + '\n\n'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 列表项
|
|
||||||
{
|
|
||||||
filter: 'li',
|
|
||||||
replacement: function (content, node) {
|
|
||||||
content = content.replace(/^\s+/, '').replace(/\n/gm, '\n ')
|
|
||||||
var prefix = '* '
|
|
||||||
var parent = node.parentNode
|
|
||||||
var index = Array.prototype.indexOf.call(parent.children, node) + 1
|
|
||||||
|
|
||||||
prefix = /ol/i.test(parent.nodeName) ? index + '. ' : '* '
|
|
||||||
return prefix + content + '\n'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 有序/无序列表
|
|
||||||
{
|
|
||||||
filter: ['ul', 'ol'],
|
|
||||||
replacement: function (content, node) {
|
|
||||||
var strings = []
|
|
||||||
for (var i = 0; i < node.childNodes.length; i++) {
|
|
||||||
strings.push(node.childNodes[i]._replacement)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (/li/i.test(node.parentNode.nodeName)) {
|
|
||||||
return '\n' + strings.join('\n')
|
|
||||||
}
|
|
||||||
return '\n\n' + strings.join('\n') + '\n\n'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 判断是否是block,如果是block,前后加空行
|
|
||||||
{
|
|
||||||
filter: function (node) {
|
|
||||||
return this.isBlock(node)
|
|
||||||
},
|
|
||||||
replacement: function (content, node) {
|
|
||||||
return '\n\n' + this.outer(node, content) + '\n\n'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Anything else!
|
|
||||||
{
|
|
||||||
filter: function () {
|
|
||||||
return true
|
|
||||||
},
|
|
||||||
replacement: function (content, node) {
|
|
||||||
return this.outer(node, content)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
},{}],5:[function(require,module,exports){
|
|
||||||
/**
|
|
||||||
* This file automatically generated from `build.js`.
|
|
||||||
* Do not manually edit.
|
|
||||||
*/
|
|
||||||
|
|
||||||
module.exports = [
|
|
||||||
"address",
|
|
||||||
"article",
|
|
||||||
"aside",
|
|
||||||
"blockquote",
|
|
||||||
"canvas",
|
|
||||||
"dd",
|
|
||||||
"div",
|
|
||||||
"dl",
|
|
||||||
"dt",
|
|
||||||
"fieldset",
|
|
||||||
"figcaption",
|
|
||||||
"figure",
|
|
||||||
"footer",
|
|
||||||
"form",
|
|
||||||
"h1",
|
|
||||||
"h2",
|
|
||||||
"h3",
|
|
||||||
"h4",
|
|
||||||
"h5",
|
|
||||||
"h6",
|
|
||||||
"h7",
|
|
||||||
"header",
|
|
||||||
"hgroup",
|
|
||||||
"hr",
|
|
||||||
"li",
|
|
||||||
"main",
|
|
||||||
"nav",
|
|
||||||
"noscript",
|
|
||||||
"ol",
|
|
||||||
"output",
|
|
||||||
"p",
|
|
||||||
"pre",
|
|
||||||
"section",
|
|
||||||
"table",
|
|
||||||
"tfoot",
|
|
||||||
"ul",
|
|
||||||
"video"
|
|
||||||
];
|
|
||||||
|
|
||||||
},{}],6:[function(require,module,exports){
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var voidElements = require('void-elements');
|
|
||||||
Object.keys(voidElements).forEach(function (name) {
|
|
||||||
voidElements[name.toUpperCase()] = 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
var blockElements = {};
|
|
||||||
require('block-elements').forEach(function (name) {
|
|
||||||
blockElements[name.toUpperCase()] = 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* isBlockElem(node) determines if the given node is a block element.
|
|
||||||
*
|
|
||||||
* @param {Node} node
|
|
||||||
* @return {Boolean}
|
|
||||||
*/
|
|
||||||
function isBlockElem(node) {
|
|
||||||
return !!(node && blockElements[node.nodeName]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* isVoid(node) determines if the given node is a void element.
|
|
||||||
*
|
|
||||||
* @param {Node} node
|
|
||||||
* @return {Boolean}
|
|
||||||
*/
|
|
||||||
function isVoid(node) {
|
|
||||||
return !!(node && voidElements[node.nodeName]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* whitespace(elem [, isBlock]) removes extraneous whitespace from an
|
|
||||||
* the given element. The function isBlock may optionally be passed in
|
|
||||||
* to determine whether or not an element is a block element; if none
|
|
||||||
* is provided, defaults to using the list of block elements provided
|
|
||||||
* by the `block-elements` module.
|
|
||||||
*
|
|
||||||
* @param {Node} elem
|
|
||||||
* @param {Function} blockTest
|
|
||||||
*/
|
|
||||||
function collapseWhitespace(elem, isBlock) {
|
|
||||||
if (!elem.firstChild || elem.nodeName === 'PRE') return;
|
|
||||||
|
|
||||||
if (typeof isBlock !== 'function') {
|
|
||||||
isBlock = isBlockElem;
|
|
||||||
}
|
|
||||||
|
|
||||||
var prevText = null;
|
|
||||||
var prevVoid = false;
|
|
||||||
|
|
||||||
var prev = null;
|
|
||||||
var node = next(prev, elem);
|
|
||||||
|
|
||||||
while (node !== elem) {
|
|
||||||
if (node.nodeType === 3) {
|
|
||||||
// Node.TEXT_NODE
|
|
||||||
var text = node.data.replace(/[ \r\n\t]+/g, ' ');
|
|
||||||
|
|
||||||
if ((!prevText || / $/.test(prevText.data)) && !prevVoid && text[0] === ' ') {
|
|
||||||
text = text.substr(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// `text` might be empty at this point.
|
|
||||||
if (!text) {
|
|
||||||
node = remove(node);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
node.data = text;
|
|
||||||
prevText = node;
|
|
||||||
} else if (node.nodeType === 1) {
|
|
||||||
// Node.ELEMENT_NODE
|
|
||||||
if (isBlock(node) || node.nodeName === 'BR') {
|
|
||||||
if (prevText) {
|
|
||||||
prevText.data = prevText.data.replace(/ $/, '');
|
|
||||||
}
|
|
||||||
|
|
||||||
prevText = null;
|
|
||||||
prevVoid = false;
|
|
||||||
} else if (isVoid(node)) {
|
|
||||||
// Avoid trimming space around non-block, non-BR void elements.
|
|
||||||
prevText = null;
|
|
||||||
prevVoid = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
node = remove(node);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var nextNode = next(prev, node);
|
|
||||||
prev = node;
|
|
||||||
node = nextNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prevText) {
|
|
||||||
prevText.data = prevText.data.replace(/ $/, '');
|
|
||||||
if (!prevText.data) {
|
|
||||||
remove(prevText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* remove(node) removes the given node from the DOM and returns the
|
|
||||||
* next node in the sequence.
|
|
||||||
*
|
|
||||||
* @param {Node} node
|
|
||||||
* @return {Node} node
|
|
||||||
*/
|
|
||||||
function remove(node) {
|
|
||||||
var next = node.nextSibling || node.parentNode;
|
|
||||||
|
|
||||||
node.parentNode.removeChild(node);
|
|
||||||
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* next(prev, current) returns the next node in the sequence, given the
|
|
||||||
* current and previous nodes.
|
|
||||||
*
|
|
||||||
* @param {Node} prev
|
|
||||||
* @param {Node} current
|
|
||||||
* @return {Node}
|
|
||||||
*/
|
|
||||||
function next(prev, current) {
|
|
||||||
if (prev && prev.parentNode === current || current.nodeName === 'PRE') {
|
|
||||||
return current.nextSibling || current.parentNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
return current.firstChild || current.nextSibling || current.parentNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = collapseWhitespace;
|
|
||||||
|
|
||||||
},{"block-elements":5,"void-elements":7}],7:[function(require,module,exports){
|
|
||||||
/**
|
|
||||||
* This file automatically generated from `pre-publish.js`.
|
|
||||||
* Do not manually edit.
|
|
||||||
*/
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
"area": true,
|
|
||||||
"base": true,
|
|
||||||
"br": true,
|
|
||||||
"col": true,
|
|
||||||
"embed": true,
|
|
||||||
"hr": true,
|
|
||||||
"img": true,
|
|
||||||
"input": true,
|
|
||||||
"keygen": true,
|
|
||||||
"link": true,
|
|
||||||
"menuitem": true,
|
|
||||||
"meta": true,
|
|
||||||
"param": true,
|
|
||||||
"source": true,
|
|
||||||
"track": true,
|
|
||||||
"wbr": true
|
|
||||||
};
|
|
||||||
|
|
||||||
},{}],8:[function(require,module,exports){
|
|
||||||
|
|
||||||
},{}]},{},[1])(1)
|
|
||||||
});
|
|
2
resources/scss/app.scss
vendored
Normal file
2
resources/scss/app.scss
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
@import "loading";
|
||||||
|
@import "main";
|
75
resources/scss/loading.scss
vendored
Executable file
75
resources/scss/loading.scss
vendored
Executable file
@ -0,0 +1,75 @@
|
|||||||
|
.app-view-loading {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 99999;
|
||||||
|
background-color: rgba(255, 255, 255, 0.7);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
color: #ccc;
|
||||||
|
margin: 0;
|
||||||
|
font: 11px verdana;
|
||||||
|
line-height: 16px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> span {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
margin: 2px;
|
||||||
|
background: #007DB6;
|
||||||
|
border-radius: 8px;
|
||||||
|
animation: app-view-loadanim 1s infinite alternate;
|
||||||
|
|
||||||
|
&:nth-of-type(2) {
|
||||||
|
background: #008FB2;
|
||||||
|
animation-delay: 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-of-type(3) {
|
||||||
|
background: #009B9E;
|
||||||
|
animation-delay: 0.4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-of-type(4) {
|
||||||
|
background: #00A77D;
|
||||||
|
animation-delay: 0.6s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-of-type(5) {
|
||||||
|
background: #00B247;
|
||||||
|
animation-delay: 0.8s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-of-type(6) {
|
||||||
|
background: #5AB027;
|
||||||
|
animation-delay: 1.0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-of-type(7) {
|
||||||
|
background: #A0B61E;
|
||||||
|
animation-delay: 1.2s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes app-view-loadanim {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
285
resources/scss/main.scss
vendored
Executable file
285
resources/scss/main.scss
vendored
Executable file
@ -0,0 +1,285 @@
|
|||||||
|
*[hidden="hidden"] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-loading {
|
||||||
|
animation: icon-loading-load 0.6s infinite linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes icon-loading-load {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ivu-modal-wrap {
|
||||||
|
&.simple-modal {
|
||||||
|
.ivu-modal {
|
||||||
|
top: 100px;
|
||||||
|
padding-bottom: 100px;
|
||||||
|
@media (max-height: 900px) {
|
||||||
|
top: 35px;
|
||||||
|
padding-bottom: 35px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ivu-modal-header,
|
||||||
|
.ivu-modal-footer {
|
||||||
|
border-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-network-add-tabs {
|
||||||
|
.ivu-tabs-tabpane {
|
||||||
|
padding: 10px 6px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.form-network-add-in-out {
|
||||||
|
padding: 0 6px;
|
||||||
|
.select-in-type {
|
||||||
|
span.ivu-radio {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.select-in-type-item-checked {
|
||||||
|
color: #2d8cf0;
|
||||||
|
border: 1px solid #2d8cf0 !important;
|
||||||
|
}
|
||||||
|
.select-in-type-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
min-width: 90px;
|
||||||
|
border: 1px solid #E8EBEE;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0 12px;
|
||||||
|
margin: 0 8px 0 0;
|
||||||
|
> span {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.select-in-type-icon {
|
||||||
|
margin-left: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.select-in-node {
|
||||||
|
margin-top: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-info-show {
|
||||||
|
display: flex;
|
||||||
|
.column {
|
||||||
|
color: #6D6D6D;
|
||||||
|
margin: 5px 0;
|
||||||
|
min-width: 70px;
|
||||||
|
max-width: 100px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.value {
|
||||||
|
flex: 1;
|
||||||
|
width: 0;
|
||||||
|
color: #414141;
|
||||||
|
margin: 5px 0 5px 5px;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ivu-select-dropdown {
|
||||||
|
max-height: 360px;
|
||||||
|
&.select-node {
|
||||||
|
.ivu-select-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
.option-title {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.ivu-tag {
|
||||||
|
margin-left: 18px;
|
||||||
|
margin-right: 0;
|
||||||
|
transform: scale(0.9);
|
||||||
|
transform-origin: right center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ivu-tooltip-popper {
|
||||||
|
.ivu-tooltip-inner {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ivu-table {
|
||||||
|
table {
|
||||||
|
width: 100% !important;
|
||||||
|
.ivu-table-cell {
|
||||||
|
padding-left: 12px;
|
||||||
|
padding-right: 12px;
|
||||||
|
}
|
||||||
|
thead {
|
||||||
|
.ivu-table-cell {
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tbody {
|
||||||
|
.tree-icon-loading {
|
||||||
|
.ivu-table-cell {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.ivu-table-cell-tree {
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.td-ellipsis {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
max-width: 100%;
|
||||||
|
.remark-text {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
align-items: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
|
.remark-icon {
|
||||||
|
display: none;
|
||||||
|
font-size: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.remark-tag {
|
||||||
|
display: inline-block;
|
||||||
|
height: 22px;
|
||||||
|
line-height: 22px;
|
||||||
|
margin: 2px 4px 2px 0;
|
||||||
|
border: 1px solid #e8eaec;
|
||||||
|
border-radius: 3px;
|
||||||
|
background: #f7f7f7;
|
||||||
|
font-size: 12px;
|
||||||
|
vertical-align: middle;
|
||||||
|
opacity: 1;
|
||||||
|
color: #515a6e;
|
||||||
|
padding: 0 4px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: visible;
|
||||||
|
&.pointer-tag {
|
||||||
|
cursor: pointer;
|
||||||
|
color: #1890ff;
|
||||||
|
background: #e6f7ff;
|
||||||
|
border-color: #91d5ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.icon-tooltip {
|
||||||
|
.ivu-tooltip-rel {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.td-action {
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
vertical-align: middle;
|
||||||
|
.td-action-container {
|
||||||
|
display: inline-block;
|
||||||
|
a {
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 0 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ivu-table-row-hover {
|
||||||
|
&:hover {
|
||||||
|
.td-ellipsis {
|
||||||
|
.remark-icon {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:before {
|
||||||
|
background-color: #efefef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.auto-height-top {
|
||||||
|
.ivu-table {
|
||||||
|
.ivu-table-body {
|
||||||
|
table {
|
||||||
|
td {
|
||||||
|
height: auto;
|
||||||
|
vertical-align: top;
|
||||||
|
.ivu-table-cell {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 48px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
.node-line {
|
||||||
|
max-width: 100%;
|
||||||
|
.td-ellipsis {
|
||||||
|
.remark-line {
|
||||||
|
margin: 2px 6px 2px 0;
|
||||||
|
&:hover {
|
||||||
|
border-color: #888;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.remark-tag {
|
||||||
|
margin: 0;
|
||||||
|
transform: scale(0.8);
|
||||||
|
}
|
||||||
|
.remark-icon {
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
color: #2d8cf0;
|
||||||
|
}
|
||||||
|
.ivu-icon {
|
||||||
|
vertical-align: unset;
|
||||||
|
transform: scale(1.2);
|
||||||
|
&.ivu-icon-md-remove-circle {
|
||||||
|
background-image: url("data:image/svg+xml;base64,PHN2ZyB0PSIxNjIxMDAxMDg0MzAxIiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjE4NjUiIHdpZHRoPSIyNTYiIGhlaWdodD0iMjU2Ij48cGF0aCBkPSJNNTEyIDUxMm0tNTEyIDBhNTEyIDUxMiAwIDEgMCAxMDI0IDAgNTEyIDUxMiAwIDEgMC0xMDI0IDBaIiBmaWxsPSIjRkZGRkZGIiBwLWlkPSIxODY2Ij48L3BhdGg+PHBhdGggZD0iTTUxMiAwYTUxMiA1MTIgMCAxIDAgMCAxMDI0QTUxMiA1MTIgMCAwIDAgNTEyIDB6IG0zODQgNTEyYzAgODIuNzM5Mi0yNi40MTkyIDE1OS4zMzQ0LTcxLjA2NTYgMjIyLjEwNTZMMjg5Ljg5NDQgMTk5LjA2NTZBMzgxLjc0NzIgMzgxLjc0NzIgMCAwIDEgNTEyIDEyOCAzODQuNDA5NiAzODQuNDA5NiAwIDAgMSA4OTYgNTEyeiBtLTc2OCAwYzAtODMuMzUzNiAyNi43MjY0LTE2MC40NjA4IDcxLjk4NzItMjIzLjQzNjhsNTM1LjU1MiA1MzUuMzQ3MkEzODEuNzQ3MiAzODEuNzQ3MiAwIDAgMSA1MTIgODk2IDM4NC40MDk2IDM4NC40MDk2IDAgMCAxIDEyOCA1MTJ6IiBmaWxsPSIjZmYwMDAwIiBwLWlkPSIxODY3IiBkYXRhLXNwbS1hbmNob3ItaWQ9ImEzMTN4Ljc3ODEwNjkuMC5pMCIgY2xhc3M9InNlbGVjdGVkIj48L3BhdGg+PC9zdmc+");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
background-size: 94%;
|
||||||
|
background-position: center;
|
||||||
|
vertical-align: text-top;
|
||||||
|
&:before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.node-signal-box {
|
||||||
|
margin-left: 1px;
|
||||||
|
.node-ping-value {
|
||||||
|
margin-left: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ivu-table-cell-tooltip {
|
||||||
|
width: auto;
|
||||||
|
.ivu-tooltip-rel {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
webpack.mix.js
vendored
21
webpack.mix.js
vendored
@ -11,8 +11,21 @@ const mix = require('laravel-mix');
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
function getFileName(str) {
|
||||||
|
if (/resources_js_pages_(.*?)_vue/.test(str)) {
|
||||||
|
return /resources_js_pages_(.*?)_vue/.exec(str)[1];
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
mix.js('resources/js/app.js', 'public/js')
|
mix.vue({ version: 2 })
|
||||||
.postCss('resources/css/app.css', 'public/css', [
|
.copy('resources/public', 'public')
|
||||||
//
|
.js('resources/js/app.js', 'public/js')
|
||||||
]).copy('resources/public', 'public');
|
.sass('resources/scss/app.scss','public/css')
|
||||||
|
.webpackConfig({
|
||||||
|
output: {
|
||||||
|
chunkFilename: function ({chunk}) {
|
||||||
|
return `js/build/${ getFileName(chunk.id) }.${ mix.inProduction() ? '[hash:8].' : '' }js`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user