mirror of
https://github.com/kuaifan/dootask.git
synced 2026-01-16 12:08:12 +00:00
perf: 优化国际化提升访问速度
This commit is contained in:
parent
e5ee52ac7e
commit
9f7151820f
@ -44,6 +44,7 @@ import NetworkException from "./components/NetworkException";
|
||||
import AudioManager from "./components/AudioManager";
|
||||
import TaskOperation from "./pages/manage/components/TaskOperation";
|
||||
import {mapState} from "vuex";
|
||||
import {languageType} from "./language";
|
||||
|
||||
export default {
|
||||
components: {TaskOperation, AudioManager, NetworkException, PreviewImageState, RightBottom, FloatSpinner},
|
||||
@ -153,10 +154,6 @@ export default {
|
||||
|
||||
themeMode() {
|
||||
this.synchThemeLanguage();
|
||||
},
|
||||
|
||||
languageType() {
|
||||
this.synchThemeLanguage();
|
||||
}
|
||||
},
|
||||
|
||||
@ -198,7 +195,7 @@ export default {
|
||||
this.iframes = this.iframes.filter(({key}) => key != 'synchThemeLanguage')
|
||||
this.iframes.push({
|
||||
key: 'synchThemeLanguage',
|
||||
url: $A.apiUrl(`../setting/theme_language?theme=${this.themeMode}&language=${this.languageType}`)
|
||||
url: $A.apiUrl(`../setting/theme_language?theme=${this.themeMode}&language=${languageType}`)
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
6
resources/assets/js/app.js
vendored
6
resources/assets/js/app.js
vendored
@ -1,6 +1,8 @@
|
||||
const isElectron = window && window.process && window.process.type;
|
||||
const isEEUiApp = window && window.navigator && /eeui/i.test(window.navigator.userAgent);
|
||||
|
||||
import {switchLanguage as $L} from "./language";
|
||||
|
||||
import './functions/common'
|
||||
import './functions/eeui'
|
||||
import './functions/web'
|
||||
@ -12,7 +14,6 @@ import routes from './routes'
|
||||
import VueRouter from 'vue-router'
|
||||
import VueClipboard from 'vue-clipboard2'
|
||||
import ViewUI from 'view-design-hi'
|
||||
import Language from './language/index'
|
||||
import store from './store/index'
|
||||
import mixin from "./store/mixin"
|
||||
|
||||
@ -28,7 +29,6 @@ Vue.use(VueClipboard, {
|
||||
}
|
||||
});
|
||||
Vue.use(VueRouter);
|
||||
Vue.use(Language);
|
||||
|
||||
import PageTitle from './components/PageTitle.vue'
|
||||
import Loading from './components/Loading.vue'
|
||||
@ -149,6 +149,7 @@ if (isElectron) {
|
||||
}
|
||||
|
||||
Vue.prototype.$A = $A;
|
||||
Vue.prototype.$L = $L;
|
||||
Vue.prototype.$Electron = $A.Electron;
|
||||
Vue.prototype.$Platform = $A.Platform;
|
||||
Vue.prototype.$isMainElectron = $A.isMainElectron;
|
||||
@ -170,7 +171,6 @@ const app = new Vue({
|
||||
|
||||
$A.goForward = app.goForward;
|
||||
$A.goBack = app.goBack;
|
||||
$A.getLanguage = app.getLanguage;
|
||||
$A.Message = app.$Message;
|
||||
$A.Notice = app.$Notice;
|
||||
$A.Modal = app.$Modal;
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
<script>
|
||||
import {mapState} from "vuex";
|
||||
import IFrame from "../pages/manage/components/IFrame";
|
||||
import {languageType} from "../language";
|
||||
|
||||
export default {
|
||||
name: "Drawio",
|
||||
@ -67,7 +68,7 @@ export default {
|
||||
},
|
||||
created() {
|
||||
let language = 'en';
|
||||
switch (this.getLanguage()) {
|
||||
switch (languageType) {
|
||||
case 'CN':
|
||||
case 'TC':
|
||||
language = 'zh'
|
||||
|
||||
@ -64,6 +64,7 @@
|
||||
|
||||
import {mapState} from "vuex";
|
||||
import IFrame from "../pages/manage/components/IFrame";
|
||||
import {languageType} from "../language";
|
||||
|
||||
export default {
|
||||
name: "OnlyOffice",
|
||||
@ -210,7 +211,7 @@ export default {
|
||||
}
|
||||
//
|
||||
let lang = "zh";
|
||||
switch (this.getLanguage()) {
|
||||
switch (languageType) {
|
||||
case 'CN':
|
||||
case 'TC':
|
||||
lang = "zh";
|
||||
|
||||
4
resources/assets/js/language/data.js
vendored
Normal file
4
resources/assets/js/language/data.js
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
let languageDefaultData = [
|
||||
|
||||
];
|
||||
export { languageDefaultData };
|
||||
467
resources/assets/js/language/index.js
vendored
467
resources/assets/js/language/index.js
vendored
@ -1,4 +1,104 @@
|
||||
const languageTypeLists = {
|
||||
import {languageDefaultData} from "./data";
|
||||
|
||||
let languageUtils = {
|
||||
/**
|
||||
* 是否数组
|
||||
* @param obj
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isArray(obj) {
|
||||
return typeof (obj) == "object" && Object.prototype.toString.call(obj).toLowerCase() == '[object array]' && typeof obj.length == "number";
|
||||
},
|
||||
|
||||
/**
|
||||
* 转换Ascii编码
|
||||
* @param value
|
||||
* @returns {string}
|
||||
*/
|
||||
convertAscii(value) {
|
||||
if (typeof value !== "string") {
|
||||
value = String(value)
|
||||
}
|
||||
let nativecode = value.split("");
|
||||
let ascii = "";
|
||||
for (let i = 0; i < nativecode.length; i++) {
|
||||
let code = Number(nativecode[i].charCodeAt(0));
|
||||
if (code > 127) {
|
||||
let charAscii = code.toString(16);
|
||||
charAscii = String("0000").substring(charAscii.length, 4) + charAscii;
|
||||
ascii += "\\u" + charAscii;
|
||||
} else {
|
||||
ascii += nativecode[i];
|
||||
}
|
||||
}
|
||||
return ascii
|
||||
},
|
||||
|
||||
/**
|
||||
* 替换(*)遍历
|
||||
* @param text
|
||||
* @param objects
|
||||
* @returns {*}
|
||||
*/
|
||||
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, '\\$&').replace(/~%~/g, '(.*?)');
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取语言
|
||||
* @returns {string}
|
||||
*/
|
||||
getLanguage() {
|
||||
if (typeof window.localStorage['__language:type__'] === "string") {
|
||||
return window.localStorage['__language:type__'];
|
||||
}
|
||||
let lang = 'EN';
|
||||
let navLang = ((window.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;
|
||||
}
|
||||
};
|
||||
let languageInit = false;
|
||||
let languageData = [];
|
||||
let languageType = languageUtils.getLanguage();
|
||||
let languageList = {
|
||||
"EN": "English",
|
||||
"KM": "ភាសាខ្មែរ",
|
||||
"TH": "ภาษาไทย",
|
||||
@ -7,269 +107,118 @@ const languageTypeLists = {
|
||||
"CN": "简体中文",
|
||||
"TC": "繁體中文",
|
||||
};
|
||||
const languageCachesObjects = {};
|
||||
const languageListenerObjects = [];
|
||||
let languageAsciis = {};
|
||||
|
||||
export default {
|
||||
install(Vue) {
|
||||
Vue.mixin({
|
||||
data() {
|
||||
return {
|
||||
languageInit: false,
|
||||
languageData: [],
|
||||
languageType: window.localStorage['__language:type__'] || this.__getNavigatorLanguage(),
|
||||
languageList: languageTypeLists,
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 添加语言数据
|
||||
* @param data
|
||||
*/
|
||||
function addLanguage(data) {
|
||||
if (!languageUtils.isArray(data)) {
|
||||
return;
|
||||
}
|
||||
languageData.unshift(...data);
|
||||
}
|
||||
|
||||
watch: {
|
||||
languageType: {
|
||||
handler(type) {
|
||||
if (type && typeof this.initLanguage === "function") {
|
||||
this.initLanguage();
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
},
|
||||
/**
|
||||
* 设置语言
|
||||
* @param language
|
||||
*/
|
||||
function setLanguage(language) {
|
||||
if (language === undefined) {
|
||||
return
|
||||
}
|
||||
$A.modalConfirm({
|
||||
content: '切换语言需要刷新后生效,是否确定刷新?',
|
||||
cancelText: '取消',
|
||||
okText: '确定',
|
||||
onOk: () => {
|
||||
window.localStorage['__language:type__'] = language;
|
||||
$A.reloadUrl()
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
},
|
||||
/**
|
||||
* 获取当前语言
|
||||
* @returns {string}
|
||||
*/
|
||||
function getLanguage() {
|
||||
return languageType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化语言数据
|
||||
* @private
|
||||
*/
|
||||
__initLanguageData() {
|
||||
if (this.languageInit === undefined) {
|
||||
this.languageInit = false;
|
||||
this.languageData = [];
|
||||
this.languageType = window.localStorage['__language:type__'] || this.__getNavigatorLanguage();
|
||||
this.languageList = languageTypeLists;
|
||||
}
|
||||
if (this.languageInit === false) {
|
||||
this.languageInit = true;
|
||||
//
|
||||
this.addLanguageData(require("./language.js").default);
|
||||
this.addLanguageData(window.languageData);
|
||||
//
|
||||
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";
|
||||
},
|
||||
|
||||
/**
|
||||
* 转换Ascii编码
|
||||
* @param value
|
||||
* @returns {string}
|
||||
* @private
|
||||
*/
|
||||
__convertAscii(value) {
|
||||
if (typeof value !== "string") {
|
||||
value = String(value)
|
||||
}
|
||||
let nativecode = value.split("");
|
||||
let ascii = "";
|
||||
for (let i = 0; i < nativecode.length; i++) {
|
||||
let code = Number(nativecode[i].charCodeAt(0));
|
||||
if (code > 127) {
|
||||
let charAscii = code.toString(16);
|
||||
charAscii = String("0000").substring(charAscii.length, 4) + charAscii;
|
||||
ascii += "\\u" + charAscii;
|
||||
} else {
|
||||
ascii += nativecode[i];
|
||||
}
|
||||
}
|
||||
return ascii
|
||||
},
|
||||
|
||||
/**
|
||||
* 监听语言变化
|
||||
* @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.unshift(...data);
|
||||
},
|
||||
|
||||
/**
|
||||
* 变化语言
|
||||
* @param language
|
||||
*/
|
||||
setLanguage(language) {
|
||||
if (language === undefined) {
|
||||
return
|
||||
}
|
||||
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, '\\$&').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();
|
||||
//
|
||||
const ascii = this.__convertAscii(text)
|
||||
if (typeof languageCachesObjects[ascii] === "undefined") {
|
||||
let tmpKey = null;
|
||||
let tmpRege = null;
|
||||
let tmpData = this.languageData.find((obj) => {
|
||||
tmpKey = `${obj._ || obj.CN}`
|
||||
if (tmpKey.indexOf("(*)") === -1) {
|
||||
tmpRege = null;
|
||||
return text == tmpKey
|
||||
} else {
|
||||
tmpRege = new RegExp("^" + this.replaceEscape(tmpKey) + "$", "g");
|
||||
return !!text.match(tmpRege);
|
||||
}
|
||||
});
|
||||
languageCachesObjects[ascii] = {rege: tmpRege, data: tmpData};
|
||||
}
|
||||
const {rege, data} = languageCachesObjects[ascii];
|
||||
if (data) {
|
||||
let value = data[this.languageType];
|
||||
if (value) {
|
||||
if (rege === null) {
|
||||
return value
|
||||
}
|
||||
let index = 0;
|
||||
value = value.replace(/\(\*\)/g, function () {
|
||||
return "$" + (++index);
|
||||
});
|
||||
return text.replace(rege, value);
|
||||
}
|
||||
}
|
||||
//
|
||||
if (window.systemInfo.debug === "yes") {
|
||||
setTimeout(_ => {
|
||||
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) { }
|
||||
}, 10)
|
||||
}
|
||||
//
|
||||
return text;
|
||||
}
|
||||
/**
|
||||
* 转换语言
|
||||
* @param text
|
||||
* @returns {string|*}
|
||||
*/
|
||||
function switchLanguage(text) {
|
||||
if (typeof arguments[1] !== "undefined") {
|
||||
return switchLanguage(languageUtils.replaceArgumentsLanguage(text, arguments));
|
||||
}
|
||||
if (typeof text !== "string" || !text) {
|
||||
return text;
|
||||
}
|
||||
//
|
||||
if (languageInit === false) {
|
||||
languageInit = true;
|
||||
addLanguage(languageDefaultData);
|
||||
addLanguage(window.languageData);
|
||||
}
|
||||
//
|
||||
const ascii = languageUtils.convertAscii(text)
|
||||
if (typeof languageAsciis[ascii] === "undefined") {
|
||||
let tmpKey = null;
|
||||
let tmpRege = null;
|
||||
let tmpData = languageData.find((obj) => {
|
||||
tmpKey = `${obj._ || obj.CN}`
|
||||
if (tmpKey.indexOf("(*)") === -1) {
|
||||
tmpRege = null;
|
||||
return text == tmpKey
|
||||
} else {
|
||||
tmpRege = new RegExp("^" + languageUtils.replaceEscape(tmpKey) + "$", "g");
|
||||
return !!text.match(tmpRege);
|
||||
}
|
||||
});
|
||||
languageAsciis[ascii] = {rege: tmpRege, data: tmpData};
|
||||
}
|
||||
const {rege, data} = languageAsciis[ascii];
|
||||
if (data) {
|
||||
let value = data[languageType];
|
||||
if (value) {
|
||||
if (rege === null) {
|
||||
return value
|
||||
}
|
||||
let index = 0;
|
||||
value = value.replace(/\(\*\)/g, function () {
|
||||
return "$" + (++index);
|
||||
});
|
||||
return text.replace(rege, value);
|
||||
}
|
||||
}
|
||||
//
|
||||
if (window.systemInfo.debug === "yes") {
|
||||
setTimeout(_ => {
|
||||
try {
|
||||
let key = '__language:Undefined__';
|
||||
let languageTmp = JSON.parse(window.localStorage[key] || '[]');
|
||||
if (!languageUtils.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) { }
|
||||
}, 10)
|
||||
}
|
||||
//
|
||||
return text;
|
||||
}
|
||||
|
||||
export { languageType, languageList, addLanguage, setLanguage, getLanguage, switchLanguage };
|
||||
|
||||
3
resources/assets/js/language/language.js
vendored
3
resources/assets/js/language/language.js
vendored
@ -1,3 +0,0 @@
|
||||
exports.default = [
|
||||
|
||||
];
|
||||
@ -11,7 +11,7 @@
|
||||
<Button v-if="proShow" class="header-right-pro no-dark-content" size="small" @click="onPro">{{$L('Pro版')}}</Button>
|
||||
|
||||
<div class="header-right-1">
|
||||
<Dropdown trigger="click" @on-click="setLanguage">
|
||||
<Dropdown trigger="click" @on-click="onLanguage">
|
||||
<a href="javascript:void(0)" class="header-right-1-dropdown">
|
||||
{{ currentLanguage }}
|
||||
<Icon type="ios-arrow-down"></Icon>
|
||||
@ -21,7 +21,7 @@
|
||||
v-for="(item, key) in languageList"
|
||||
:key="key"
|
||||
:name="key"
|
||||
:selected="getLanguage() === key">{{ item }}</DropdownItem>
|
||||
:selected="languageType === key">{{ item }}</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
</div>
|
||||
@ -51,7 +51,7 @@
|
||||
<DropdownMenu slot="list">
|
||||
<DropdownItem @click.native="login">{{ $L("登录") }}</DropdownItem>
|
||||
<DropdownItem @click.native="register">{{ $L("注册帐号") }}</DropdownItem>
|
||||
<Dropdown placement="right-start" @on-click="setLanguage" transfer>
|
||||
<Dropdown placement="right-start" @on-click="onLanguage" transfer>
|
||||
<DropdownItem>
|
||||
<div class="header-nav-dropdown-item">
|
||||
{{ currentLanguage }}
|
||||
@ -63,7 +63,7 @@
|
||||
v-for="(item, key) in languageList"
|
||||
:key="key"
|
||||
:name="key"
|
||||
:selected="getLanguage() === key">{{ item }}</DropdownItem>
|
||||
:selected="languageType === key">{{ item }}</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
<Dropdown trigger="click" placement="right-end" @on-click="setTheme" transfer>
|
||||
@ -199,10 +199,14 @@
|
||||
|
||||
<script>
|
||||
import {mapState} from "vuex";
|
||||
import {languageList, languageType, setLanguage} from "../language";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
languageList,
|
||||
languageType,
|
||||
|
||||
proShow: false,
|
||||
needStartHome: false,
|
||||
homeFooter: '',
|
||||
@ -216,7 +220,7 @@ export default {
|
||||
},
|
||||
|
||||
currentLanguage() {
|
||||
return this.languageList[this.languageType] || "Language";
|
||||
return languageList[languageType] || "Language";
|
||||
},
|
||||
|
||||
appTitle() {
|
||||
@ -292,6 +296,10 @@ export default {
|
||||
} else {
|
||||
this.goForward({name: 'login'}, true);
|
||||
}
|
||||
},
|
||||
|
||||
onLanguage(l) {
|
||||
setLanguage(l)
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@ -103,7 +103,7 @@
|
||||
:selected="themeMode === item.value">{{$L(item.name)}}</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
<Dropdown placement="right-start" transfer @on-click="setLanguage">
|
||||
<Dropdown placement="right-start" transfer @on-click="onLanguage">
|
||||
<DropdownItem divided>
|
||||
<div class="login-setting-item">
|
||||
{{currentLanguage}}
|
||||
@ -115,7 +115,7 @@
|
||||
v-for="(item, key) in languageList"
|
||||
:key="key"
|
||||
:name="key"
|
||||
:selected="getLanguage() === key">{{item}}</DropdownItem>
|
||||
:selected="languageType === key">{{item}}</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
</DropdownMenu>
|
||||
@ -144,12 +144,16 @@
|
||||
<script>
|
||||
import {mapState} from "vuex";
|
||||
import {Store} from "le5le-store";
|
||||
import {languageList, languageType, setLanguage} from "../language";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
loadIng: 0,
|
||||
|
||||
languageList,
|
||||
languageType,
|
||||
|
||||
codeNeed: false,
|
||||
codeUrl: $A.apiUrl('users/login/codeimg?_=' + Math.random()),
|
||||
|
||||
@ -222,7 +226,7 @@ export default {
|
||||
},
|
||||
|
||||
currentLanguage() {
|
||||
return this.languageList[this.languageType] || 'Language'
|
||||
return languageList[languageType] || 'Language'
|
||||
},
|
||||
|
||||
welcomeTitle() {
|
||||
@ -490,6 +494,10 @@ export default {
|
||||
this.goForward({name: 'manage-dashboard'}, true);
|
||||
}
|
||||
},
|
||||
|
||||
onLanguage(l) {
|
||||
setLanguage(l)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -99,7 +99,7 @@
|
||||
placement="right-start"
|
||||
transfer
|
||||
transfer-class-name="page-manage-menu-dropdown"
|
||||
@on-click="setLanguage">
|
||||
@on-click="onLanguage">
|
||||
<DropdownItem divided>
|
||||
<div class="manage-menu-flex">
|
||||
{{currentLanguage}}
|
||||
@ -111,7 +111,7 @@
|
||||
v-for="(item, key) in languageList"
|
||||
:key="key"
|
||||
:name="key"
|
||||
:selected="getLanguage() === key">{{item}}</DropdownItem>
|
||||
:selected="languageType === key">{{item}}</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
<!-- 其他菜单 -->
|
||||
@ -375,6 +375,7 @@ import DialogModal from "./manage/components/DialogModal";
|
||||
import TaskModal from "./manage/components/TaskModal";
|
||||
import notificationKoro from "notification-koro1";
|
||||
import {Store} from "le5le-store";
|
||||
import {languageList, languageType, setLanguage} from "../language";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -396,6 +397,9 @@ export default {
|
||||
return {
|
||||
loadIng: 0,
|
||||
|
||||
languageList,
|
||||
languageType,
|
||||
|
||||
mateName: /macintosh|mac os x/i.test(navigator.userAgent) ? '⌘' : 'Ctrl',
|
||||
|
||||
addShow: false,
|
||||
@ -404,7 +408,12 @@ export default {
|
||||
columns: '',
|
||||
flow: 'open',
|
||||
},
|
||||
addRule: {},
|
||||
addRule: {
|
||||
name: [
|
||||
{ required: true, message: this.$L('请填写项目名称!'), trigger: 'change' },
|
||||
{ type: 'string', min: 2, message: this.$L('项目名称至少2个字!'), trigger: 'change' }
|
||||
]
|
||||
},
|
||||
|
||||
addTaskShow: false,
|
||||
addTaskSubscribe: null,
|
||||
@ -564,7 +573,7 @@ export default {
|
||||
},
|
||||
|
||||
currentLanguage() {
|
||||
return this.languageList[this.languageType] || 'Language'
|
||||
return languageList[languageType] || 'Language'
|
||||
},
|
||||
|
||||
menu() {
|
||||
@ -733,13 +742,8 @@ export default {
|
||||
},
|
||||
|
||||
methods: {
|
||||
initLanguage() {
|
||||
this.addRule = {
|
||||
name: [
|
||||
{ required: true, message: this.$L('请填写项目名称!'), trigger: 'change' },
|
||||
{ type: 'string', min: 2, message: this.$L('项目名称至少2个字!'), trigger: 'change' }
|
||||
]
|
||||
};
|
||||
onLanguage(l) {
|
||||
setLanguage(l)
|
||||
},
|
||||
|
||||
chackPass() {
|
||||
|
||||
@ -52,6 +52,7 @@ import Calendar from "./components/Calendar";
|
||||
import moment from "moment";
|
||||
import {Store} from "le5le-store";
|
||||
import TaskMenu from "./components/TaskMenu";
|
||||
import {addLanguage} from "../../language";
|
||||
|
||||
export default {
|
||||
components: {TaskMenu, Calendar},
|
||||
@ -78,6 +79,57 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
addLanguage([
|
||||
{"_": "{日}","CN": "日","EN": "Sun","TC": "日","KM": "Sun","TH": "Sun","KO": "Sun","JA": "Sun"},
|
||||
{"_": "{一}","CN": "一","EN": "Mon","TC": "一","KM": "Mon","TH": "Mon","KO": "Mon","JA": "Mon"},
|
||||
{"_": "{二}","CN": "二","EN": "Tue","TC": "二","KM": "Tue","TH": "Tue","KO": "Tue","JA": "Tue"},
|
||||
{"_": "{三}","CN": "三","EN": "Wed","TC": "三","KM": "Wed","TH": "Wed","KO": "Wed","JA": "Wed"},
|
||||
{"_": "{四}","CN": "四","EN": "Thu","TC": "四","KM": "Thu","TH": "Thu","KO": "Thu","JA": "Thu"},
|
||||
{"_": "{五}","CN": "五","EN": "Fri","TC": "五","KM": "Fri","TH": "Fri","KO": "Fri","JA": "Fri"},
|
||||
{"_": "{六}","CN": "六","EN": "Sat","TC": "六","KM": "Sat","TH": "Sat","KO": "Sat","JA": "Sat"},
|
||||
]);
|
||||
let daynames = [
|
||||
this.$L('{日}'),
|
||||
this.$L('{一}'),
|
||||
this.$L('{二}'),
|
||||
this.$L('{三}'),
|
||||
this.$L('{四}'),
|
||||
this.$L('{五}'),
|
||||
this.$L('{六}')
|
||||
];
|
||||
this.calendarWeek = {daynames};
|
||||
this.calendarMonth = {daynames};
|
||||
this.calendarTheme = {
|
||||
'common.border': '1px solid rgba(0,0,0,0)',
|
||||
'month.dayname.fontSize': '14px',
|
||||
'month.dayname.borderLeft': '1px solid rgba(0,0,0,0)',
|
||||
'month.dayname.height': '50px',
|
||||
}
|
||||
if (this.windowLarge) {
|
||||
this.calendarTheme = {
|
||||
'common.border': '1px solid #f4f5f5',
|
||||
'month.dayname.fontSize': '14px',
|
||||
'month.dayname.borderLeft': '1px solid #f4f5f5',
|
||||
'month.dayname.height': '50px',
|
||||
}
|
||||
}
|
||||
this.calendarTemplate = {
|
||||
titlePlaceholder: () => {
|
||||
return this.$L("任务描述")
|
||||
},
|
||||
popupSave: () => {
|
||||
return this.$L("保存");
|
||||
},
|
||||
popupEdit: () => {
|
||||
return this.$L("详情");
|
||||
},
|
||||
popupDelete: () => {
|
||||
return this.$L("删除");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
activated() {
|
||||
this.$refs.cal.resetRender();
|
||||
this.setRenderRange();
|
||||
@ -187,57 +239,6 @@ export default {
|
||||
},
|
||||
|
||||
methods: {
|
||||
initLanguage() {
|
||||
this.addLanguageData([
|
||||
{"_": "{日}","CN": "日","EN": "Sun","TC": "日","KM": "Sun","TH": "Sun","KO": "Sun","JA": "Sun"},
|
||||
{"_": "{一}","CN": "一","EN": "Mon","TC": "一","KM": "Mon","TH": "Mon","KO": "Mon","JA": "Mon"},
|
||||
{"_": "{二}","CN": "二","EN": "Tue","TC": "二","KM": "Tue","TH": "Tue","KO": "Tue","JA": "Tue"},
|
||||
{"_": "{三}","CN": "三","EN": "Wed","TC": "三","KM": "Wed","TH": "Wed","KO": "Wed","JA": "Wed"},
|
||||
{"_": "{四}","CN": "四","EN": "Thu","TC": "四","KM": "Thu","TH": "Thu","KO": "Thu","JA": "Thu"},
|
||||
{"_": "{五}","CN": "五","EN": "Fri","TC": "五","KM": "Fri","TH": "Fri","KO": "Fri","JA": "Fri"},
|
||||
{"_": "{六}","CN": "六","EN": "Sat","TC": "六","KM": "Sat","TH": "Sat","KO": "Sat","JA": "Sat"},
|
||||
]);
|
||||
let daynames = [
|
||||
this.$L('{日}'),
|
||||
this.$L('{一}'),
|
||||
this.$L('{二}'),
|
||||
this.$L('{三}'),
|
||||
this.$L('{四}'),
|
||||
this.$L('{五}'),
|
||||
this.$L('{六}')
|
||||
];
|
||||
this.calendarWeek = {daynames};
|
||||
this.calendarMonth = {daynames};
|
||||
this.calendarTheme = {
|
||||
'common.border': '1px solid rgba(0,0,0,0)',
|
||||
'month.dayname.fontSize': '14px',
|
||||
'month.dayname.borderLeft': '1px solid rgba(0,0,0,0)',
|
||||
'month.dayname.height': '50px',
|
||||
}
|
||||
if (this.windowLarge) {
|
||||
this.calendarTheme = {
|
||||
'common.border': '1px solid #f4f5f5',
|
||||
'month.dayname.fontSize': '14px',
|
||||
'month.dayname.borderLeft': '1px solid #f4f5f5',
|
||||
'month.dayname.height': '50px',
|
||||
}
|
||||
}
|
||||
this.calendarTemplate = {
|
||||
titlePlaceholder: () => {
|
||||
return this.$L("任务描述")
|
||||
},
|
||||
popupSave: () => {
|
||||
return this.$L("保存");
|
||||
},
|
||||
popupEdit: () => {
|
||||
return this.$L("详情");
|
||||
},
|
||||
popupDelete: () => {
|
||||
return this.$L("删除");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getTask(time) {
|
||||
if (this.loadIng > 0) {
|
||||
clearTimeout(this.loadTimeout)
|
||||
|
||||
@ -66,29 +66,7 @@ export default {
|
||||
keys: {},
|
||||
keyIs: false,
|
||||
|
||||
columns: [],
|
||||
list: [],
|
||||
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
noText: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getLists();
|
||||
},
|
||||
watch: {
|
||||
keyIs(v) {
|
||||
if (!v) {
|
||||
this.keys = {}
|
||||
this.setPage(1)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initLanguage() {
|
||||
this.columns = [
|
||||
columns: [
|
||||
{
|
||||
title: 'ID',
|
||||
key: 'id',
|
||||
@ -198,9 +176,27 @@ export default {
|
||||
}, vNode);
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
list: [],
|
||||
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
noText: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getLists();
|
||||
},
|
||||
watch: {
|
||||
keyIs(v) {
|
||||
if (!v) {
|
||||
this.keys = {}
|
||||
this.setPage(1)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSearch() {
|
||||
this.page = 1;
|
||||
this.getLists();
|
||||
|
||||
@ -90,29 +90,7 @@ export default {
|
||||
keys: {},
|
||||
keyIs: false,
|
||||
|
||||
columns: [],
|
||||
list: [],
|
||||
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
noText: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getLists();
|
||||
},
|
||||
watch: {
|
||||
keyIs(v) {
|
||||
if (!v) {
|
||||
this.keys = {}
|
||||
this.setPage(1)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initLanguage() {
|
||||
this.columns = [
|
||||
columns: [
|
||||
{
|
||||
title: 'ID',
|
||||
key: 'id',
|
||||
@ -195,9 +173,27 @@ export default {
|
||||
key: 'created_at',
|
||||
width: 168,
|
||||
},
|
||||
]
|
||||
},
|
||||
],
|
||||
list: [],
|
||||
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
noText: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getLists();
|
||||
},
|
||||
watch: {
|
||||
keyIs(v) {
|
||||
if (!v) {
|
||||
this.keys = {}
|
||||
this.setPage(1)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSearch() {
|
||||
this.page = 1;
|
||||
this.getLists();
|
||||
|
||||
@ -76,37 +76,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
loadIng: 0,
|
||||
columns: [],
|
||||
lists: [],
|
||||
listPage: 1,
|
||||
listTotal: 0,
|
||||
listPageSize: 20,
|
||||
noDataText: "数据加载中.....",
|
||||
|
||||
keys: {},
|
||||
keyIs: false,
|
||||
|
||||
reportTypeList: [
|
||||
{value: "", label: this.$L('全部')},
|
||||
{value: "weekly", label: this.$L('周报')},
|
||||
{value: "daily", label: this.$L('日报')},
|
||||
],
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getLists();
|
||||
},
|
||||
watch: {
|
||||
keyIs(v) {
|
||||
if (!v) {
|
||||
this.keys = {}
|
||||
this.setPage(1)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initLanguage() {
|
||||
this.columns = [{
|
||||
columns: [{
|
||||
title: this.$L("名称"),
|
||||
key: 'title',
|
||||
sortable: true,
|
||||
@ -157,9 +127,35 @@ export default {
|
||||
}
|
||||
});
|
||||
},
|
||||
}];
|
||||
},
|
||||
}],
|
||||
lists: [],
|
||||
listPage: 1,
|
||||
listTotal: 0,
|
||||
listPageSize: 20,
|
||||
noDataText: "数据加载中.....",
|
||||
|
||||
keys: {},
|
||||
keyIs: false,
|
||||
|
||||
reportTypeList: [
|
||||
{value: "", label: this.$L('全部')},
|
||||
{value: "weekly", label: this.$L('周报')},
|
||||
{value: "daily", label: this.$L('日报')},
|
||||
],
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getLists();
|
||||
},
|
||||
watch: {
|
||||
keyIs(v) {
|
||||
if (!v) {
|
||||
this.keys = {}
|
||||
this.setPage(1)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSearch() {
|
||||
this.listPage = 1;
|
||||
this.getLists();
|
||||
|
||||
@ -91,40 +91,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
loadIng: 0,
|
||||
columns: [],
|
||||
lists: [],
|
||||
listPage: 1,
|
||||
listTotal: 0,
|
||||
listPageSize: 20,
|
||||
noDataText: "数据加载中.....",
|
||||
|
||||
keys: {},
|
||||
keyIs: false,
|
||||
|
||||
selectIds: [],
|
||||
selectAction: '',
|
||||
|
||||
reportTypeList: [
|
||||
{value: "", label: this.$L('全部')},
|
||||
{value: "weekly", label: this.$L('周报')},
|
||||
{value: "daily", label: this.$L('日报')},
|
||||
],
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getLists();
|
||||
},
|
||||
watch: {
|
||||
keyIs(v) {
|
||||
if (!v) {
|
||||
this.keys = {}
|
||||
this.setPage(1)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initLanguage() {
|
||||
this.columns = [{
|
||||
columns: [{
|
||||
type: 'selection',
|
||||
width: 50,
|
||||
align: 'right'
|
||||
@ -195,9 +162,38 @@ export default {
|
||||
}
|
||||
});
|
||||
},
|
||||
}];
|
||||
},
|
||||
}],
|
||||
lists: [],
|
||||
listPage: 1,
|
||||
listTotal: 0,
|
||||
listPageSize: 20,
|
||||
noDataText: "数据加载中.....",
|
||||
|
||||
keys: {},
|
||||
keyIs: false,
|
||||
|
||||
selectIds: [],
|
||||
selectAction: '',
|
||||
|
||||
reportTypeList: [
|
||||
{value: "", label: this.$L('全部')},
|
||||
{value: "weekly", label: this.$L('周报')},
|
||||
{value: "daily", label: this.$L('日报')},
|
||||
],
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getLists();
|
||||
},
|
||||
watch: {
|
||||
keyIs(v) {
|
||||
if (!v) {
|
||||
this.keys = {}
|
||||
this.setPage(1)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSearch() {
|
||||
this.listPage = 1;
|
||||
this.getLists();
|
||||
|
||||
@ -72,38 +72,7 @@ export default {
|
||||
keys: {},
|
||||
keyIs: false,
|
||||
|
||||
columns: [],
|
||||
list: [],
|
||||
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
noText: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
},
|
||||
computed: {
|
||||
...mapState(['cacheTasks'])
|
||||
},
|
||||
watch: {
|
||||
projectId: {
|
||||
handler() {
|
||||
this.getLists();
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
keyIs(v) {
|
||||
if (!v) {
|
||||
this.keys = {}
|
||||
this.setPage(1)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initLanguage() {
|
||||
this.columns = [
|
||||
columns: [
|
||||
{
|
||||
title: 'ID',
|
||||
key: 'id',
|
||||
@ -238,9 +207,36 @@ export default {
|
||||
}, vNodes);
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
list: [],
|
||||
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
noText: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
},
|
||||
computed: {
|
||||
...mapState(['cacheTasks'])
|
||||
},
|
||||
watch: {
|
||||
projectId: {
|
||||
handler() {
|
||||
this.getLists();
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
keyIs(v) {
|
||||
if (!v) {
|
||||
this.keys = {}
|
||||
this.setPage(1)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSearch() {
|
||||
this.page = 1;
|
||||
this.getLists();
|
||||
|
||||
@ -72,38 +72,7 @@ export default {
|
||||
keys: {},
|
||||
keyIs: false,
|
||||
|
||||
columns: [],
|
||||
list: [],
|
||||
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
noText: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
},
|
||||
computed: {
|
||||
...mapState(['cacheTasks'])
|
||||
},
|
||||
watch: {
|
||||
projectId: {
|
||||
handler() {
|
||||
this.getLists();
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
keyIs(v) {
|
||||
if (!v) {
|
||||
this.keys = {}
|
||||
this.setPage(1)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initLanguage() {
|
||||
this.columns = [
|
||||
columns: [
|
||||
{
|
||||
title: 'ID',
|
||||
key: 'id',
|
||||
@ -186,9 +155,36 @@ export default {
|
||||
}, vNodes);
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
list: [],
|
||||
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
noText: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
},
|
||||
computed: {
|
||||
...mapState(['cacheTasks'])
|
||||
},
|
||||
watch: {
|
||||
projectId: {
|
||||
handler() {
|
||||
this.getLists();
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
keyIs(v) {
|
||||
if (!v) {
|
||||
this.keys = {}
|
||||
this.setPage(1)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSearch() {
|
||||
this.page = 1;
|
||||
this.getLists();
|
||||
|
||||
@ -266,111 +266,7 @@ export default {
|
||||
keys: {},
|
||||
keyIs: false,
|
||||
|
||||
columns: [],
|
||||
list: [],
|
||||
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
noText: '',
|
||||
|
||||
departmentEditShow: false,
|
||||
departmentEditLoading: 0,
|
||||
departmentEditData: {},
|
||||
|
||||
disableShow: false,
|
||||
disableLoading: 0,
|
||||
disableData: {},
|
||||
disableOptions: {
|
||||
shortcuts: [
|
||||
{
|
||||
text: this.$L('12:00'),
|
||||
value () {
|
||||
return $A.Date($A.formatDate("Y-m-d 12:00:00"));
|
||||
},
|
||||
onClick: (picker) => {
|
||||
picker.handlePickSuccess();
|
||||
}
|
||||
},
|
||||
{
|
||||
text: this.$L('17:00'),
|
||||
value () {
|
||||
return $A.Date($A.formatDate("Y-m-d 17:00:00"));
|
||||
},
|
||||
onClick: (picker) => {
|
||||
picker.handlePickSuccess();
|
||||
}
|
||||
},
|
||||
{
|
||||
text: this.$L('18:00'),
|
||||
value () {
|
||||
return $A.Date($A.formatDate("Y-m-d 18:00:00"));
|
||||
},
|
||||
onClick: (picker) => {
|
||||
picker.handlePickSuccess();
|
||||
}
|
||||
},
|
||||
{
|
||||
text: this.$L('19:00'),
|
||||
value () {
|
||||
return $A.Date($A.formatDate("Y-m-d 19:00:00"));
|
||||
},
|
||||
onClick: (picker) => {
|
||||
picker.handlePickSuccess();
|
||||
}
|
||||
},
|
||||
{
|
||||
text: this.$L('现在'),
|
||||
value () {
|
||||
return new Date();
|
||||
},
|
||||
onClick: (picker) => {
|
||||
picker.handlePickSuccess();
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
departmentShow: false,
|
||||
departmentLoading: 0,
|
||||
departmentSelect: -1,
|
||||
departmentData: {
|
||||
id: 0,
|
||||
name: '',
|
||||
parent_id: 0,
|
||||
owner_userid: [],
|
||||
dialog_group: 'new',
|
||||
dialog_useid: 0
|
||||
},
|
||||
departmentList: [],
|
||||
|
||||
dialogLoad: false,
|
||||
dialogList: [],
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getLists();
|
||||
this.getDepartmentLists();
|
||||
},
|
||||
watch: {
|
||||
keyIs(v) {
|
||||
if (!v) {
|
||||
this.keys = {}
|
||||
this.setPage(1)
|
||||
}
|
||||
},
|
||||
departmentSelect() {
|
||||
this.setPage(1)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
departmentParentDisabled() {
|
||||
return !!(this.departmentData.id > 0 && this.departmentList.find(({parent_id}) => parent_id == this.departmentData.id));
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
initLanguage() {
|
||||
this.columns = [
|
||||
columns: [
|
||||
{
|
||||
title: 'ID',
|
||||
key: 'userid',
|
||||
@ -632,9 +528,109 @@ export default {
|
||||
]);
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
list: [],
|
||||
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
noText: '',
|
||||
|
||||
departmentEditShow: false,
|
||||
departmentEditLoading: 0,
|
||||
departmentEditData: {},
|
||||
|
||||
disableShow: false,
|
||||
disableLoading: 0,
|
||||
disableData: {},
|
||||
disableOptions: {
|
||||
shortcuts: [
|
||||
{
|
||||
text: this.$L('12:00'),
|
||||
value () {
|
||||
return $A.Date($A.formatDate("Y-m-d 12:00:00"));
|
||||
},
|
||||
onClick: (picker) => {
|
||||
picker.handlePickSuccess();
|
||||
}
|
||||
},
|
||||
{
|
||||
text: this.$L('17:00'),
|
||||
value () {
|
||||
return $A.Date($A.formatDate("Y-m-d 17:00:00"));
|
||||
},
|
||||
onClick: (picker) => {
|
||||
picker.handlePickSuccess();
|
||||
}
|
||||
},
|
||||
{
|
||||
text: this.$L('18:00'),
|
||||
value () {
|
||||
return $A.Date($A.formatDate("Y-m-d 18:00:00"));
|
||||
},
|
||||
onClick: (picker) => {
|
||||
picker.handlePickSuccess();
|
||||
}
|
||||
},
|
||||
{
|
||||
text: this.$L('19:00'),
|
||||
value () {
|
||||
return $A.Date($A.formatDate("Y-m-d 19:00:00"));
|
||||
},
|
||||
onClick: (picker) => {
|
||||
picker.handlePickSuccess();
|
||||
}
|
||||
},
|
||||
{
|
||||
text: this.$L('现在'),
|
||||
value () {
|
||||
return new Date();
|
||||
},
|
||||
onClick: (picker) => {
|
||||
picker.handlePickSuccess();
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
departmentShow: false,
|
||||
departmentLoading: 0,
|
||||
departmentSelect: -1,
|
||||
departmentData: {
|
||||
id: 0,
|
||||
name: '',
|
||||
parent_id: 0,
|
||||
owner_userid: [],
|
||||
dialog_group: 'new',
|
||||
dialog_useid: 0
|
||||
},
|
||||
departmentList: [],
|
||||
|
||||
dialogLoad: false,
|
||||
dialogList: [],
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getLists();
|
||||
this.getDepartmentLists();
|
||||
},
|
||||
watch: {
|
||||
keyIs(v) {
|
||||
if (!v) {
|
||||
this.keys = {}
|
||||
this.setPage(1)
|
||||
}
|
||||
},
|
||||
departmentSelect() {
|
||||
this.setPage(1)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
departmentParentDisabled() {
|
||||
return !!(this.departmentData.id > 0 && this.departmentList.find(({parent_id}) => parent_id == this.departmentData.id));
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onSearch() {
|
||||
this.page = 1;
|
||||
this.getLists();
|
||||
|
||||
@ -512,6 +512,198 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
const sort = $A.getStorageJson("cacheFileSort")
|
||||
this.columns = [
|
||||
{
|
||||
type: 'selection',
|
||||
width: 50,
|
||||
align: 'right'
|
||||
},
|
||||
{
|
||||
title: this.$L('文件名'),
|
||||
key: 'name',
|
||||
minWidth: 300,
|
||||
sortable: true,
|
||||
render: (h, {row}) => {
|
||||
let array = [];
|
||||
let isCreate = !/^\d+$/.test(row.id);
|
||||
if (isCreate) {
|
||||
// 新建
|
||||
array.push(h('Input', {
|
||||
props: {
|
||||
elementId: 'input_' + row.id,
|
||||
value: row.newname,
|
||||
autofocus: true,
|
||||
disabled: !!row._load,
|
||||
},
|
||||
style: {
|
||||
width: 'auto'
|
||||
},
|
||||
on: {
|
||||
'on-change': (event) => {
|
||||
row.newname = event.target.value;
|
||||
},
|
||||
'on-blur': () => {
|
||||
const file = this.files.find(({id}) => id == row.id);
|
||||
if (file) {
|
||||
file.newname = row.newname;
|
||||
this.onBlur(file)
|
||||
}
|
||||
},
|
||||
'on-enter': () => {
|
||||
const file = this.files.find(({id}) => id == row.id);
|
||||
if (file) {
|
||||
file.newname = row.newname;
|
||||
this.onEnter(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
}))
|
||||
return h('div', {
|
||||
class: 'file-nbox'
|
||||
}, [
|
||||
h('div', {
|
||||
class: `no-dark-before file-name file-icon ${row.type}`,
|
||||
}, array),
|
||||
]);
|
||||
} else {
|
||||
// 编辑、查看
|
||||
array.push(h('QuickEdit', {
|
||||
props: {
|
||||
value: row.name,
|
||||
autoEdit: !!row._edit,
|
||||
clickOutSide: false,
|
||||
},
|
||||
on: {
|
||||
'on-edit-change': (b) => {
|
||||
const file = this.files.find(({id}) => id == row.id);
|
||||
if (file) {
|
||||
setTimeout(() => {
|
||||
this.setEdit(file.id, b)
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
'on-update': (val, cb) => {
|
||||
const file = this.files.find(({id}) => id == row.id);
|
||||
if (file) {
|
||||
file.newname = val
|
||||
this.onEnter(file);
|
||||
}
|
||||
cb();
|
||||
}
|
||||
}
|
||||
}, [
|
||||
h('AutoTip', {
|
||||
props: {
|
||||
placement: 'right'
|
||||
}
|
||||
}, $A.getFileName(row))
|
||||
]));
|
||||
//
|
||||
const iconArray = [];
|
||||
if (row.share) {
|
||||
if (row.userid != this.userId) {
|
||||
iconArray.push(h('UserAvatar', {
|
||||
props: {
|
||||
userid: row.userid,
|
||||
size: 20
|
||||
},
|
||||
}))
|
||||
} else {
|
||||
iconArray.push(h('i', {
|
||||
class: 'taskfont',
|
||||
domProps: {
|
||||
innerHTML: ''
|
||||
},
|
||||
}))
|
||||
}
|
||||
} else if (this.isParentShare) {
|
||||
iconArray.push(h('UserAvatar', {
|
||||
props: {
|
||||
userid: row.created_id,
|
||||
size: 20
|
||||
},
|
||||
}, [
|
||||
row.created_id != row.userid ? h('p', [h('strong', this.$L('成员创建于') + ": " + row.created_at)]) : h('p', this.$L('所有者创建') + ": " + row.created_at)
|
||||
]))
|
||||
}
|
||||
const shearClass = this.shearIds.includes(row.id) ? ' shear' : '';
|
||||
const shareClass = row.share ? ' share' : '';
|
||||
return h('div', {
|
||||
class: `file-nbox${shearClass}`,
|
||||
attrs: {
|
||||
'data-id': row.id
|
||||
}
|
||||
}, [
|
||||
h('div', {
|
||||
class: `no-dark-before file-name file-icon ${row.type}${shareClass}`,
|
||||
}, array),
|
||||
iconArray
|
||||
]);
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: this.$L('大小'),
|
||||
key: 'size',
|
||||
width: 110,
|
||||
resizable: true,
|
||||
sortable: true,
|
||||
render: (h, {row}) => {
|
||||
if (row.type == 'folder') {
|
||||
return h('div', '-')
|
||||
}
|
||||
return h('AutoTip', $A.bytesToSize(row.size));
|
||||
}
|
||||
},
|
||||
{
|
||||
title: this.$L('类型'),
|
||||
key: 'type',
|
||||
width: 110,
|
||||
resizable: true,
|
||||
sortable: true,
|
||||
render: (h, {row}) => {
|
||||
let type = this.types.find(({value, name}) => value == row.type && name);
|
||||
if (type) {
|
||||
return h('AutoTip', this.$L(type.name));
|
||||
} else {
|
||||
return h('div', (row.ext || row.type).toUpperCase())
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: this.$L('所有者'),
|
||||
key: 'userid',
|
||||
width: 130,
|
||||
resizable: true,
|
||||
sortable: true,
|
||||
render: (h, {row}) => {
|
||||
return h('UserAvatar', {
|
||||
props: {
|
||||
size: 18,
|
||||
userid: row.userid,
|
||||
showIcon: false,
|
||||
showName: true,
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
title: this.$L('最后修改'),
|
||||
key: 'updated_at',
|
||||
width: 168,
|
||||
resizable: true,
|
||||
sortable: true,
|
||||
},
|
||||
].map(item => {
|
||||
if (item.key === sort.key) {
|
||||
item.sortType = sort.order
|
||||
}
|
||||
return item;
|
||||
});
|
||||
},
|
||||
|
||||
mounted() {
|
||||
if (!this.tableMode && this.$isEEUiApp) {
|
||||
this.tableMode = 'block';
|
||||
@ -702,198 +894,6 @@ export default {
|
||||
},
|
||||
|
||||
methods: {
|
||||
initLanguage() {
|
||||
const sort = $A.getStorageJson("cacheFileSort")
|
||||
this.columns = [
|
||||
{
|
||||
type: 'selection',
|
||||
width: 50,
|
||||
align: 'right'
|
||||
},
|
||||
{
|
||||
title: this.$L('文件名'),
|
||||
key: 'name',
|
||||
minWidth: 300,
|
||||
sortable: true,
|
||||
render: (h, {row}) => {
|
||||
let array = [];
|
||||
let isCreate = !/^\d+$/.test(row.id);
|
||||
if (isCreate) {
|
||||
// 新建
|
||||
array.push(h('Input', {
|
||||
props: {
|
||||
elementId: 'input_' + row.id,
|
||||
value: row.newname,
|
||||
autofocus: true,
|
||||
disabled: !!row._load,
|
||||
},
|
||||
style: {
|
||||
width: 'auto'
|
||||
},
|
||||
on: {
|
||||
'on-change': (event) => {
|
||||
row.newname = event.target.value;
|
||||
},
|
||||
'on-blur': () => {
|
||||
const file = this.files.find(({id}) => id == row.id);
|
||||
if (file) {
|
||||
file.newname = row.newname;
|
||||
this.onBlur(file)
|
||||
}
|
||||
},
|
||||
'on-enter': () => {
|
||||
const file = this.files.find(({id}) => id == row.id);
|
||||
if (file) {
|
||||
file.newname = row.newname;
|
||||
this.onEnter(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
}))
|
||||
return h('div', {
|
||||
class: 'file-nbox'
|
||||
}, [
|
||||
h('div', {
|
||||
class: `no-dark-before file-name file-icon ${row.type}`,
|
||||
}, array),
|
||||
]);
|
||||
} else {
|
||||
// 编辑、查看
|
||||
array.push(h('QuickEdit', {
|
||||
props: {
|
||||
value: row.name,
|
||||
autoEdit: !!row._edit,
|
||||
clickOutSide: false,
|
||||
},
|
||||
on: {
|
||||
'on-edit-change': (b) => {
|
||||
const file = this.files.find(({id}) => id == row.id);
|
||||
if (file) {
|
||||
setTimeout(() => {
|
||||
this.setEdit(file.id, b)
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
'on-update': (val, cb) => {
|
||||
const file = this.files.find(({id}) => id == row.id);
|
||||
if (file) {
|
||||
file.newname = val
|
||||
this.onEnter(file);
|
||||
}
|
||||
cb();
|
||||
}
|
||||
}
|
||||
}, [
|
||||
h('AutoTip', {
|
||||
props: {
|
||||
placement: 'right'
|
||||
}
|
||||
}, $A.getFileName(row))
|
||||
]));
|
||||
//
|
||||
const iconArray = [];
|
||||
if (row.share) {
|
||||
if (row.userid != this.userId) {
|
||||
iconArray.push(h('UserAvatar', {
|
||||
props: {
|
||||
userid: row.userid,
|
||||
size: 20
|
||||
},
|
||||
}))
|
||||
} else {
|
||||
iconArray.push(h('i', {
|
||||
class: 'taskfont',
|
||||
domProps: {
|
||||
innerHTML: ''
|
||||
},
|
||||
}))
|
||||
}
|
||||
} else if (this.isParentShare) {
|
||||
iconArray.push(h('UserAvatar', {
|
||||
props: {
|
||||
userid: row.created_id,
|
||||
size: 20
|
||||
},
|
||||
}, [
|
||||
row.created_id != row.userid ? h('p', [h('strong', this.$L('成员创建于') + ": " + row.created_at)]) : h('p', this.$L('所有者创建') + ": " + row.created_at)
|
||||
]))
|
||||
}
|
||||
const shearClass = this.shearIds.includes(row.id) ? ' shear' : '';
|
||||
const shareClass = row.share ? ' share' : '';
|
||||
return h('div', {
|
||||
class: `file-nbox${shearClass}`,
|
||||
attrs: {
|
||||
'data-id': row.id
|
||||
}
|
||||
}, [
|
||||
h('div', {
|
||||
class: `no-dark-before file-name file-icon ${row.type}${shareClass}`,
|
||||
}, array),
|
||||
iconArray
|
||||
]);
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: this.$L('大小'),
|
||||
key: 'size',
|
||||
width: 110,
|
||||
resizable: true,
|
||||
sortable: true,
|
||||
render: (h, {row}) => {
|
||||
if (row.type == 'folder') {
|
||||
return h('div', '-')
|
||||
}
|
||||
return h('AutoTip', $A.bytesToSize(row.size));
|
||||
}
|
||||
},
|
||||
{
|
||||
title: this.$L('类型'),
|
||||
key: 'type',
|
||||
width: 110,
|
||||
resizable: true,
|
||||
sortable: true,
|
||||
render: (h, {row}) => {
|
||||
let type = this.types.find(({value, name}) => value == row.type && name);
|
||||
if (type) {
|
||||
return h('AutoTip', this.$L(type.name));
|
||||
} else {
|
||||
return h('div', (row.ext || row.type).toUpperCase())
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: this.$L('所有者'),
|
||||
key: 'userid',
|
||||
width: 130,
|
||||
resizable: true,
|
||||
sortable: true,
|
||||
render: (h, {row}) => {
|
||||
return h('UserAvatar', {
|
||||
props: {
|
||||
size: 18,
|
||||
userid: row.userid,
|
||||
showIcon: false,
|
||||
showName: true,
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
title: this.$L('最后修改'),
|
||||
key: 'updated_at',
|
||||
width: 168,
|
||||
resizable: true,
|
||||
sortable: true,
|
||||
},
|
||||
].map(item => {
|
||||
if (item.key === sort.key) {
|
||||
item.sortType = sort.order
|
||||
}
|
||||
return item;
|
||||
});
|
||||
},
|
||||
|
||||
getFileList() {
|
||||
if (this.$route.name !== 'manage-file') {
|
||||
return;
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
|
||||
<script>
|
||||
import ImgUpload from "../../../components/ImgUpload";
|
||||
import {languageList, languageType, setLanguage} from "../../../language";
|
||||
|
||||
export default {
|
||||
components: {ImgUpload},
|
||||
@ -23,6 +24,8 @@ export default {
|
||||
return {
|
||||
loadIng: 0,
|
||||
|
||||
languageList,
|
||||
|
||||
formData: {
|
||||
language: '',
|
||||
},
|
||||
@ -37,14 +40,14 @@ export default {
|
||||
|
||||
methods: {
|
||||
initData() {
|
||||
this.$set(this.formData, 'language', this.getLanguage());
|
||||
this.$set(this.formData, 'language', languageType);
|
||||
this.formData_bak = $A.cloneJSON(this.formData);
|
||||
},
|
||||
|
||||
submitForm() {
|
||||
this.$refs.formData.validate((valid) => {
|
||||
if (valid) {
|
||||
this.setLanguage(this.formData.language)
|
||||
setLanguage(this.formData.language)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
@ -33,15 +33,7 @@ export default {
|
||||
checkpass: '',
|
||||
},
|
||||
|
||||
ruleDatum: { },
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['userInfo']),
|
||||
},
|
||||
methods: {
|
||||
initLanguage() {
|
||||
this.ruleDatum = {
|
||||
ruleDatum: {
|
||||
oldpass: [
|
||||
{ required: true, message: this.$L('请输入旧密码!'), trigger: 'change' },
|
||||
{ type: 'string', min: 6, message: this.$L('密码长度至少6位!'), trigger: 'change' }
|
||||
@ -78,9 +70,13 @@ export default {
|
||||
trigger: 'change'
|
||||
}
|
||||
],
|
||||
};
|
||||
},
|
||||
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['userInfo']),
|
||||
},
|
||||
methods: {
|
||||
submitForm() {
|
||||
this.$refs.formDatum.validate((valid) => {
|
||||
if (valid) {
|
||||
|
||||
@ -42,7 +42,19 @@ export default {
|
||||
profession: ''
|
||||
},
|
||||
|
||||
ruleData: { },
|
||||
ruleData: {
|
||||
email: [
|
||||
{required: true, message: this.$L('请输入邮箱地址!'), trigger: 'change'},
|
||||
],
|
||||
tel: [
|
||||
{required: true, message: this.$L('请输入联系电话!'), trigger: 'change'},
|
||||
{type: 'string', min: 6, message: this.$L('电话长度至少6位!'), trigger: 'change'}
|
||||
],
|
||||
nickname: [
|
||||
{required: true, message: this.$L('请输入昵称!'), trigger: 'change'},
|
||||
{type: 'string', min: 2, message: this.$L('昵称长度至少2位!'), trigger: 'change'}
|
||||
]
|
||||
},
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@ -57,22 +69,6 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initLanguage() {
|
||||
this.ruleData = {
|
||||
email: [
|
||||
{required: true, message: this.$L('请输入邮箱地址!'), trigger: 'change'},
|
||||
],
|
||||
tel: [
|
||||
{required: true, message: this.$L('请输入联系电话!'), trigger: 'change'},
|
||||
{type: 'string', min: 6, message: this.$L('电话长度至少6位!'), trigger: 'change'}
|
||||
],
|
||||
nickname: [
|
||||
{required: true, message: this.$L('请输入昵称!'), trigger: 'change'},
|
||||
{type: 'string', min: 2, message: this.$L('昵称长度至少2位!'), trigger: 'change'}
|
||||
]
|
||||
};
|
||||
},
|
||||
|
||||
initData() {
|
||||
this.$set(this.formData, 'userimg', $A.strExists(this.userInfo.userimg, '/avatar') ? '' : this.userInfo.userimg);
|
||||
this.$set(this.formData, 'email', this.userInfo.email);
|
||||
|
||||
@ -16,13 +16,13 @@
|
||||
<a class="right-info" target="_blank" href="https://github.com/kuaifan/dootask">
|
||||
<Icon class="right-icon" type="logo-github"/>
|
||||
</a>
|
||||
<Dropdown class="right-info" trigger="click" @on-click="setLanguage">
|
||||
<Dropdown class="right-info" trigger="click" @on-click="onLanguage">
|
||||
<div>
|
||||
<Icon class="right-icon" type="md-globe"/>
|
||||
<Icon type="md-arrow-dropdown"/>
|
||||
</div>
|
||||
<Dropdown-menu slot="list">
|
||||
<Dropdown-item v-for="(item, key) in languageList" :key="key" :name="key" :selected="getLanguage() === key">{{item}}</Dropdown-item>
|
||||
<Dropdown-item v-for="(item, key) in languageList" :key="key" :name="key" :selected="languageType === key">{{item}}</Dropdown-item>
|
||||
</Dropdown-menu>
|
||||
</Dropdown>
|
||||
</dd>
|
||||
@ -945,9 +945,14 @@
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import {languageList, languageType, setLanguage} from "../language";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
languageList,
|
||||
languageType,
|
||||
|
||||
active: 2,
|
||||
|
||||
body1: true,
|
||||
@ -969,6 +974,10 @@ export default {
|
||||
},
|
||||
|
||||
methods: {
|
||||
onLanguage(l) {
|
||||
setLanguage(l)
|
||||
},
|
||||
|
||||
getSetting() {
|
||||
this.$store.dispatch("call", {
|
||||
url: 'system/setting',
|
||||
|
||||
9
resources/assets/js/store/actions.js
vendored
9
resources/assets/js/store/actions.js
vendored
@ -1,4 +1,5 @@
|
||||
import {Store} from 'le5le-store';
|
||||
import {languageType} from "../language";
|
||||
|
||||
export default {
|
||||
/**
|
||||
@ -12,7 +13,7 @@ export default {
|
||||
if (!$A.isJson(params)) params = {url: params}
|
||||
const header = {
|
||||
'Content-Type': 'application/json',
|
||||
'language': $A.getLanguage(),
|
||||
'language': languageType,
|
||||
'token': state.userToken,
|
||||
'fd': $A.getSessionStorageString("userWsFd"),
|
||||
'version': window.systemInfo.version || "0.0.1",
|
||||
@ -2787,11 +2788,7 @@ export default {
|
||||
state.wsCall[msgId] = callback
|
||||
}
|
||||
try {
|
||||
state.ws.send(JSON.stringify({
|
||||
type,
|
||||
msgId,
|
||||
data
|
||||
}))
|
||||
state.ws.send(JSON.stringify({type, msgId, data}))
|
||||
resolve()
|
||||
} catch (e) {
|
||||
typeof callback === "function" && callback(null, false)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user