Commit 82cd849f by 胡锦波

1. init 非报错添加

parent d2a29820
......@@ -3269,8 +3269,7 @@
"base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"dev": true
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
},
"batch": {
"version": "0.6.1",
......@@ -4665,6 +4664,11 @@
"randomfill": "^1.0.3"
}
},
"crypto-js": {
"version": "4.1.1",
"resolved": "http://npm.job.qinqinxiaobao.com/crypto-js/-/crypto-js-4.1.1.tgz",
"integrity": "sha1-nkhbzwNSEEG9hYRHhrg/t2GXNs8="
},
"css-color-names": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz",
......@@ -9268,6 +9272,25 @@
"integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==",
"dev": true
},
"oidc-client": {
"version": "1.11.5",
"resolved": "http://npm.job.qinqinxiaobao.com/oidc-client/-/oidc-client-1.11.5.tgz",
"integrity": "sha1-Agqhk9aKPh+Hok/L9QBztzjekrs=",
"requires": {
"acorn": "^7.4.1",
"base64-js": "^1.5.1",
"core-js": "^3.8.3",
"crypto-js": "^4.0.0",
"serialize-javascript": "^4.0.0"
},
"dependencies": {
"acorn": {
"version": "7.4.1",
"resolved": "http://npm.job.qinqinxiaobao.com/acorn/-/acorn-7.4.1.tgz",
"integrity": "sha1-/q7SVZc9LndVW4PbwIhRpsY1IPo="
}
}
},
"on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
......@@ -10516,7 +10539,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
"dev": true,
"requires": {
"safe-buffer": "^5.1.0"
}
......@@ -10973,8 +10995,7 @@
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"dev": true
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"safe-regex": {
"version": "1.1.0",
......@@ -11085,7 +11106,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
"integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
"dev": true,
"requires": {
"randombytes": "^2.1.0"
}
......
......@@ -12,6 +12,7 @@
"core-js": "^3.6.5",
"element-ui": "^2.15.7",
"lodash": "^4.17.21",
"oidc-client": "^1.11.5",
"uniplat-sdk": "^0.1.350-private",
"vue": "^2.6.11",
"vue-class-component": "^7.2.3",
......
import { UserManagerSettings } from "oidc-client";
import { Envir, Environment } from "./env";
export interface ApiConfig {
clientId: string;
clientSecret: string;
host?: string;
scope: string;
/**
* 组织管理后台地址
*/
manager: string;
passport: string;
chatApi: string;
chatWebSocket: string;
salaryUpload: string;
root: string;
rootDomain: string;
fileDownload: string;
accountCenter: string;
sdk: string;
enterpriseUrl: string;
}
export interface Config {
oidc: UserManagerSettings;
api: ApiConfig;
}
const pro = Envir.isPro();
const envir = Envir.getEnvir();
const clientId = "teamix-team-manager-web-pc";
const hostOptions = new Map<Environment, string>([
[Environment.Dev, window.location.origin],
[Environment.Pro, "https://account.hrs100.com"],
[Environment.Test, "http://106.120.107.150:7772"],
[Environment.Stage, "https://pre-account.hrs100.com"]
]);
const rootDomainOptions = new Map<Environment, string>([
[Environment.Dev, window.location.origin],
[Environment.Pro, "https://{0}.hrs100.com"],
[Environment.Test, "http://a.web.test.hrs100.cn"],
[Environment.Stage, "https://pre-{0}.hrs100.com"]
]);
const host = hostOptions.get(envir);
const rootDomain = rootDomainOptions.get(envir);
const api = {
clientId,
clientSecret: pro ? "qqxb#teammix#2019" : "123456",
scope: "api.workapps.open",
root: host
} as ApiConfig;
const oidc = {
client_id: clientId,
redirect_uri: `${host}/oidc-redirect`,
response_type: "id_token token",
scope:
"workapps.client api.workapps.user api.workapps.org api.workapps.open openid",
silent_redirect_uri: `${host}/oidc-silent-redirect`,
post_logout_redirect_uri: host
} as UserManagerSettings;
function getValue(map: Map<Environment, string>) {
return map.get(envir) || map.get(Environment.Dev);
}
const authorityOptions = new Map<Environment, string>([
[Environment.Dev, "http://106.120.107.150:5000"],
[Environment.Pro, "https://passport.teammix.com"],
[Environment.Stage, "https://pre-passport.teammix.com"]
]);
Object.assign(oidc, { authority: getValue(authorityOptions) });
Object.assign(api, { rootDomain });
export default { oidc, api };
export const enum Environment {
Dev,
Pro,
Test,
Stage,
Pre
}
export const enum EnvironmentText {
Dev = 'dev',
Pro = 'pro',
Test = 'test',
Stage = 'stage'
}
export class Envir {
public static isDev() {
return process.env.NODE_ENV === "development";
}
/**
* 正式线
*/
public static isPro() {
return process.env.NODE_ENV === "production" && !process.env.VUE_APP_HRS_ENV;
}
/**
* 正式线的镜像版本
*/
public static isStaging() {
return process.env.NODE_ENV === "production" && process.env.VUE_APP_HRS_ENV === 'stage';
}
/**
* 测试线
*/
public static isTesting() {
return process.env.NODE_ENV === "production" && process.env.VUE_APP_HRS_ENV === 'test';
}
public static getEnvir() {
if (this.isPro()) {
return Environment.Pro;
}
if (this.isTesting()) {
return Environment.Test;
}
if (this.isStaging()) {
return Environment.Stage;
}
return Environment.Dev;
}
public static getEnvirString() {
if (this.isPro()) {
return EnvironmentText.Pro;
}
if (this.isTesting()) {
return EnvironmentText.Test;
}
if (this.isStaging()) {
return EnvironmentText.Stage;
}
return EnvironmentText.Dev;
}
}
export class Uuid {
public static execute() {
const s: (number | string)[] = [];
const hexDigits = "0123456789abcdef";
for (let i = 0; i < 36; i++) {
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
}
s[14] = "4";
s[19] = hexDigits.substr((+s[19] & 0x3) | 0x8, 1);
s[8] = s[13] = s[18] = s[23] = "-";
return s.join("");
}
}
/* eslint-disable */
import { Envir } from './env';
const enable = !Envir.isPro();
const logger = {
log: (msg: string | any, ...params: any[]) => {
enable && console.log(msg, params);
},
error: (msg: string | any) => {
console.error(msg);
}
};
export default logger;
<pre>
<code>
<hrs-button class="pre-icon pre-icon-email">按钮带Email图标</hrs-button>
<hrs-button class="pre-icon pre-icon-back">按钮带返回图标</hrs-button>
</code>
</pre>
<template>
<el-button
class="fs-button"
:class="innerClass"
v-bind="$attrs"
@click="onClick"
>
<slot></slot>
</el-button>
</template>
<script lang="ts">
import { Vue, Component, Prop } from "vue-property-decorator";
/**
* 支持的 type 值,默认值为 default.
*/
const BUTTON_TYPES = [
"primary",
"default",
"info",
"plain",
"text",
"text-primary",
"text-info",
"icon",
"danger",
];
/**
* 支持的 size 值,默认值为 default
*/
const BUTTON_SIZES = ["extra-large", "large", "default", "medium", "small"];
@Component({ name: "FsButton" })
export default class HrsButton extends Vue {
@Prop({
required: false,
default: "default",
validator: (v) => !v || BUTTON_TYPES.indexOf(v) > -1,
})
private type!: string;
@Prop({
required: false,
default: "default",
validator: (v) => !v || BUTTON_SIZES.indexOf(v) > -1,
})
private size!: string;
@Prop({ required: false, default: undefined })
private autoWidth!: boolean;
/**
* 圆角属性,默认为有圆角 4px,如果有赋值则圆角则为 20px
*/
@Prop({
required: false,
default: "default",
validator: (v) => !v || v === "default",
})
private radius!: string;
private get innerClass() {
return (
`fs-button--${this.size} fs-button-type--${this.type}` +
(this.radius === "default" ? " default-radius" : "") +
(this.autoWidth !== undefined ? ` auto-width` : "")
);
}
private onClick(e: MouseEvent) {
this.$emit("click", e);
}
}
</script>
<style lang="less" scoped>
@import "~@/css/element-ui-override/fs-button.less";
</style>
<template>
<div class="nums-input">
<input type="number" v-model="value" placeholder="组合数量" />
<div class="operated-button">
<span
class="increase"
:class="{ disabled: max * 1 <= value * 1 }"
@click="onIncrease"
>
<i class="el-icon-arrow-up"></i>
</span>
<span
class="decrease"
:class="{ disabled: min * 1 >= value * 1 }"
@click="onDecrease"
>
<i class="el-icon-arrow-down"></i
></span>
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue, Prop, Watch } from "vue-property-decorator";
import { popupService } from "./popup";
@Component({ components: {} })
export default class InputNumsNew extends Vue {
@Prop({ default: 0 })
private min!: number;
@Prop({ default: 999 })
private max!: number;
private value = 0;
@Watch("value")
private onValueChange() {
if (this.min !== undefined && this.min > this.value * 1) {
this.value = this.min;
this.warnMessage2Min();
}
if (this.max !== undefined && this.max < this.value * 1) {
this.value = this.max;
this.warnMessage2Max();
}
}
private onIncrease() {
if (this.max === undefined || this.max > this.value) {
this.value = this.value * 1 + 1;
}
}
private onDecrease() {
if (this.max === undefined || this.min < this.value) {
this.value = this.value * 1 - 1;
}
}
private warnMessage2Max() {
popupService.toast.warn(`当前数量超过最大值${this.max}`);
}
private warnMessage2Min() {
popupService.toast.warn(`当前数量超过最小值${this.min}`);
}
}
</script>
<style lang="less" scoped>
@import "~@/css/variables.less";
.nums-input {
width: 117px;
position: relative;
overflow: hidden;
input {
width: 100%;
height: 32px;
padding-left: 10px;
padding-right: 34px;
outline: none;
border: 1px solid #e6e6e6;
border-radius: 2px;
transition: all 0.5s;
line-height: 32px;
&:focus {
transition: all 0.5s;
border: 1px solid @mainColor;
}
}
input::-webkit-input-placeholder {
color: #ccc;
}
.operated-button {
position: absolute;
top: 1px;
bottom: 1px;
right: 1px;
span {
display: block;
width: 18px;
height: 15px;
line-height: 15px;
cursor: pointer;
text-align: center;
&.increase {
border-left: 1px solid #e6e6e6;
border-bottom: 1px solid #e6e6e6;
}
&.decrease {
border-left: 1px solid #e6e6e6;
}
i {
color: #999;
font-size: 13px;
transform: scale(0.8);
line-height: 1;
}
&:hover {
i {
color: @mainColor;
}
}
&.disabled {
cursor: not-allowed;
i {
color: #999;
}
}
}
}
}
</style>
<template>
<el-input-number
class="el-input-nums"
v-bind="$attrs"
v-on="$listeners"
:value="value"
@blur="onBlur"
@focus="onFocus"
:class="[{ 'no-empty': value }, { focus: focus2Current }]"
>
</el-input-number>
</template>
<script lang="ts">
import { Vue, Component, Model } from "vue-property-decorator";
@Component({ name: "HrsInput" })
export default class HrsInputNumber extends Vue {
@Model("input", { required: true })
private value!: string | number;
private focus2Current = false;
private onBlur() {
this.focus2Current = false;
}
private onFocus() {
this.focus2Current = true;
}
}
</script>
<style lang="less">
@import "~@/css/variables.less";
@no-empty-color: #ffffff;
.el-input-nums {
&.focus,
&.no-empty {
input {
background-color: @no-empty-color;
}
}
&.el-input-number {
.el-input-number__decrease,
.el-input-number__increase {
width: 17px;
background-color: #fff;
}
.el-input {
input {
text-align: left;
}
}
}
}
</style>
<template>
<el-input
ref="innerElInput"
class="fs-input"
@input="onInput"
@clear="onClear"
@blur="onBlur"
v-bind="$attrs"
:value="value"
@focus="onFocus"
:class="[innerClass, { 'no-empty': value }, { focus: focus2Current }]"
>
<template slot="prefix">
<slot name="prefix"></slot>
</template>
<template slot="suffix">
<slot name="suffix"></slot>
</template>
<template slot="prepend">
<slot name="prepend"></slot>
</template>
<template slot="append">
<slot name="append"></slot>
</template>
</el-input>
</template>
<script lang="ts">
import { Vue, Component, Prop, Model, Ref } from "vue-property-decorator";
/**
* 支持的 type 值,默认值为 default.
*/
const INPUT_TYPES = ["default", "underline", "round", "plain"];
@Component({ name: "HrsInput" })
export default class HrsInput extends Vue {
/**
* 这里用 shape 来命名是因为 input 本身就有type = text/password/textarea 等值来控制器其特定逻辑
*/
@Prop({
required: false,
default: "default",
validator: (v) => !v || INPUT_TYPES.indexOf(v) > -1,
})
private shape!: string;
private focus2Current = false;
@Model("input", { required: true })
private value!: string | number;
@Prop({ required: false })
private autofocus!: boolean;
@Ref() private innerElInput!: { focus: () => void };
private get innerClass() {
return `fs-input--${this.shape}`;
}
private onInput(v: string | number) {
this.$emit("input", v);
}
private onClear(e: MouseEvent) {
this.$emit("clear", e);
}
private onBlur(e: MouseEvent) {
this.focus2Current = false;
this.$emit("blur", e);
}
private onFocus(e: MouseEvent) {
this.focus2Current = true;
this.$emit("focus", e);
}
mounted() {
if (this.autofocus !== undefined) {
this.focus();
}
}
focus() {
if (this.innerElInput) {
this.innerElInput.focus();
}
}
}
</script>
<style lang="less">
@import "~@/css/variables.less";
@border-color: #e6e6e6;
@background-color: #ffffff;
@no-empty-color: #ffffff;
@disabled-color: #f5f7fa;
@count-color: #cccccc;
@placeholder-color: #cccccc;
.fs-input {
border-color: @border-color;
.el-input__inner {
height: 38px;
border-radius: 4px;
}
&.fs-input--default {
.el-input__inner,
.el-textarea__inner {
background-color: @background-color;
}
}
&.el-textarea {
border-radius: 4px;
.el-input__count {
font-size: 14px;
height: 17px;
right: 12px;
bottom: 14px;
line-height: 20px;
color: #888;
}
}
&.focus,
&.no-empty {
&.fs-input--default {
.el-input__inner,
.el-textarea__inner {
background-color: @no-empty-color;
}
}
}
&.is-disabled {
&.fs-input--default {
.el-input__inner,
.el-textarea__inner {
background-color: @disabled-color;
}
}
}
input::-webkit-input-placeholder {
font-size: 14px;
color: @placeholder-color;
line-height: 24px;
}
textarea::-webkit-input-placeholder {
font-size: 14px;
color: @placeholder-color;
line-height: 24px;
}
&.is-disabled {
.el-input__inner {
&:hover,
&:focus,
&:active {
border-color: @border-color;
}
}
}
.el-input__inner {
border-radius: 2px;
&:hover,
&:focus,
&:active {
border-color: @mainColor;
}
}
&.fs-input--underline {
.el-input__inner {
padding-left: 0;
border: none;
border-bottom: 1px solid @border-color;
& + .el-input__prefix {
left: -5px;
}
}
&.el-input--prefix {
.el-input__inner {
padding-left: 20px;
}
}
.el-input__inner {
&:hover,
&:focus,
&:active {
border-color: @mainColor;
}
}
&.is-disabled {
.el-input__inner {
&:hover,
&:focus,
&:active {
border-color: @border-color;
}
}
}
}
&.fs-input--plain {
.el-input__inner {
border-color: transparent;
}
.el-input__inner {
&:hover,
&:focus,
&:active {
border-color: @mainColor;
}
}
&.is-disabled {
.el-input__inner {
&:hover,
&:focus,
&:active {
border-color: transparent;
}
}
}
}
.el-textarea__inner {
border-radius: 2px;
&:focus {
border-color: @mainColor;
}
}
}
.show-limit {
.el-input__suffix {
// height: 17px;
// bottom: -22px;
right: 12px;
// top: auto;
.el-input__count {
.el-input__count-inner {
font-size: 14px;
padding: 0px;
color: #888888;
}
}
}
}
.el-input,
.el-select {
input {
background-color: @background-color;
}
&.no-empty {
input {
background-color: @no-empty-color;
}
}
}
.el-input {
input {
padding-left: 10px;
}
}
</style>
import Vue, { CreateElement, VNode } from 'vue';
import { MessageBox, Message } from 'element-ui';
import { MessageBoxData, ElMessageBoxOptions } from 'element-ui/types/message-box';
import { ElMessageOptions, ElMessageComponent } from 'element-ui/types/message';
import logger from '@/api/logger';
export interface ConfirmDialogOption {
title?: string;
/**
* 默认为 warning, 可选参数。如果不想icon 显示,请将 hideIcon 置为 true
*/
type?: 'success' | 'warning';
/**
* 主描述
*/
primaryText: string;
/**
* 次级描述文字,可选
*/
secondaryText?: string;
/**
* 主按钮文字,默认为“确认”
*/
primaryButtonText?: string;
/**
* 次级按钮文字,默认为“取消”
*/
secondaryButtonText?: string;
/**
* 主按钮默认位置,默认居左,此值默认 false
*/
primaryButtonRight?: boolean;
/**
* 默认不同类型的 confirm 框主体内容显示会有一个图标,如果此值为 true,图标会被隐藏,默认此值为 false
*/
hideIcon?: boolean;
hidePrimaryButton?: boolean;
hideSecondaryButton?: boolean;
/**
* 描述性文字(包括主描述和次级描述)是否根据 type 不同有自己的颜色。
* 此属性在 hideIcon 为 true 时不起作用。
* 此属性只在 type 为 warning 时生效。
*/
textColored?: boolean;
/**
* 是否在窗口打开时自动给第一个能获得焦点的元素聚焦,默认 false
*/
autoFocusWhenDialogOpened?: boolean;
/**
* 是否将message作为html渲染
*/
useHtml?: boolean;
hideClose?: boolean;
}
export interface ToastService {
info(message: string): void;
warn(message: string): void;
success(message: string): void;
message(option: ElMessageOptions): void;
error(e: any, message?: string): void;
}
export interface PopupService {
confirm(option: ConfirmDialogOption): Promise<MessageBoxData>;
noop: () => void;
toast: ToastService;
}
interface CachedSuccessMessage {
message: string;
component: ElMessageComponent;
}
const customMessageBoxClassPrefix = 'fs-message-box-';
const vue = new Vue();
const render: CreateElement = vue.$createElement;
const messageType2Class: { [key: string]: string } = {
default: 'icon-default',
success: 'icon-success',
warning: 'icon-warning'
};
const buttonClasses = ['fs-button', 'fs-button--large'];
const primaryButtonClasses = [...buttonClasses, 'fs-button-type--primary'].join(' ');
const secondaryButtonClasses4Success = [...buttonClasses, 'fs-button-type--default'].join(' ');
const secondaryButtonClasses4Default = [...buttonClasses, 'fs-button-type--plain'].join(' ');
const successMessageCache: CachedSuccessMessage[] = [];
const service: PopupService = {
confirm: (option: ConfirmDialogOption) => {
const customClasses = ['custom'];
const elOption: ElMessageBoxOptions = {
title: option.title,
closeOnClickModal: false,
confirmButtonText: option.primaryButtonText || '确定',
cancelButtonText: option.secondaryButtonText || '取消',
type: option.type || 'warning',
confirmButtonClass: primaryButtonClasses,
cancelButtonClass: option.type === 'success' ? secondaryButtonClasses4Success : secondaryButtonClasses4Default,
showCancelButton: !option.hideSecondaryButton,
showConfirmButton: !option.hidePrimaryButton,
dangerouslyUseHTMLString: option.useHtml,
showClose: !option.hideClose,
};
if (option.hideSecondaryButton || option.hidePrimaryButton) {
customClasses.push(`hide-secondary-button`);
}
if (option.primaryButtonRight) {
const current = elOption.confirmButtonClass;
elOption.confirmButtonClass = elOption.cancelButtonClass;
elOption.cancelButtonClass = current;
} else {
customClasses.push('reverse-button-direction');
}
customClasses.push(messageType2Class.default);
customClasses.push(messageType2Class[elOption.type as string]);
customClasses.push(option.title ? 'has-title' : 'hide-title');
if (option.hideIcon) {
customClasses.push('hide-icon');
} else {
if (option.type === 'warning' && option.textColored) {
customClasses.push('text-colored');
}
if (option.title) {
customClasses.push(`has-title-icon`);
}
}
const nodes: VNode[] = [];
nodes.push(render('p', {
staticClass: `${customMessageBoxClassPrefix}-primary-text`,
domProps: { innerHTML: option.primaryText }
}));
if (option.secondaryText) {
nodes.push(render('p', {
staticClass: `${customMessageBoxClassPrefix}-secondary-text`,
domProps: { innerHTML: option.secondaryText }
}));
} else {
customClasses.push('primary-message-text');
}
elOption.message = render('div', nodes);
elOption.customClass = customClasses.map(i => `${customMessageBoxClassPrefix}-${i}`).join(' ');
if (!option.autoFocusWhenDialogOpened) {
setTimeout(() => {
const element = document.activeElement as HTMLElement;
if (element) {
const parent = element.parentNode as HTMLElement;
if (parent && parent.classList && parent.classList.contains('el-message-box__btns')) {
element.blur();
}
}
}, 50);
}
const openModal = (open: boolean) => {
const body = document.querySelector('body');
if (body) {
if (open) {
body.classList.add('modal-active');
} else {
body.classList.remove('modal-active');
}
}
};
openModal(true);
return MessageBox.confirm('', elOption).finally(() => openModal(false));
},
noop: () => { return false; },
toast: {
info: message => Message({ message, type: 'info', showClose: true }),
warn: message => Message({ message, type: 'warning', showClose: true }),
success: message => {
const same = successMessageCache.find(i => i.message === message);
if (same) {
return;
}
const component = Message({
message,
type: 'success',
showClose: true,
onClose: () => {
const index = successMessageCache.findIndex(i => i.component === component);
if (index > -1) {
successMessageCache.splice(index, 1);
}
}
});
successMessageCache.push({ message, component });
},
message: option => Message(option),
error: (e, message) => {
const m = message || e.message || e.msg || (_.isString(e) && e) || '操作失败';
if (/com.(.*)exception/i.test(m)) {
logger.error(m);
service.toast.warn('系统出现异常');
} else {
service.toast.warn(m);
}
}
}
};
export { service as popupService };
<template>
<el-select
v-bind="$attrs"
v-on="$listeners"
:value="value"
@blur="onBlur"
@focus="onFocus"
:popper-class="innerClass"
>
<slot></slot>
</el-select>
</template>
<script lang="ts">
import { Vue, Component, Model, Prop } from "vue-property-decorator";
@Component({ name: "HrsSelect", inheritAttrs: false })
export default class HrsInput extends Vue {
@Model("input", { required: true })
private value!: string | number;
@Prop()
private innerClass!: string;
private focus2Current = false;
private isEmpty(value: any) {
return value === "" || value === undefined || value === null;
}
private onBlur(e: MouseEvent) {
this.focus2Current = false;
this.$emit("blur", e);
}
private onFocus() {
this.focus2Current = true;
}
}
</script>
<style lang="less">
@import "~@/css/variables.less";
@background-color: #fafafa;
@no-empty-color: #ffffff;
.el-input,
.el-select {
input {
background-color: @no-empty-color;
}
// &.focus,
// &.no-empty {
// input {
// background-color: @no-empty-color;
// }
// }
}
</style>
......@@ -8,4 +8,7 @@ export enum Direction {
ApplicationSetting,
ManagerSetting,
ManagerLog,
Redirect,
SilentRedirect,
}
......@@ -4,6 +4,7 @@ import { Dictionary } from "vue-router/types/router";
import { Direction } from './direction';
import { MetaHeader } from './meta-header';
import { setCompatibleUrl } from './compatible-url';
import { loginRouters } from "@/router/sub-router/login";
Vue.use(VueRouter);
......@@ -12,6 +13,7 @@ const routes: Array<RouteConfig> = [
path: "",
redirect: "/workadmin/home"
},
...loginRouters,
{
path: '/workadmin',
component: () => import('@/views/pages/main.vue'),
......
export class MetaHeader {
public static readonly root = '组织管理后台';
public static readonly home = '首页';
public static readonly addressBook = '通讯录';
public static readonly applicationRecord = '申请加入记录';
......
// import { Direction } from '../direction';
// import { MetaHeader } from '../meta-header';
export const loginRouters = [
// {
// path: "/login",
// meta: { direction: Direction.Login, title: MetaHeader.root },
// component: () => import("@/views/login/index.vue"),
// },
// {
// path: "/redirect",
// meta: { direction: Direction.Redirect2Domain, title: MetaHeader.root },
// component: () => import("@/views/login/custom-domain-nav.vue"),
// },
// {
// path: "/oidc-redirect",
// meta: { direction: Direction.Redirect, title: MetaHeader.root },
// component: () => import("@/views/login/redirect.vue"),
// },
// {
// path: "/oidc-silent-redirect",
// meta: { direction: Direction.SilentRedirect, title: MetaHeader.root },
// component: () => import("@/views/login/silent-redirect.vue"),
// },
// {
// path: '/signout',
// component: () => import('@/views/login/signout.vue'),
// meta: { direction: Direction.Signout, title: MetaHeader.root }
// },
// {
// path: '/authcode',
// component: () => import('@/views/components/authcode-host'),
// meta: { direction: Direction.Authcode, title: MetaHeader.root }
// },
// {
// path: '/upgrade',
// component: () => import('@/views/error/upgrade.vue'),
// meta: { direction: Direction.Upgrading, title: MetaHeader.root }
// },
// {
// path: '/error',
// component: () => import('@/views/error/index.vue'),
// children: [
// {
// path: '403',
// component: () => import('@/views/error/403.vue'),
// meta: { direction: Direction.Error403, title: MetaHeader.root }
// },
// {
// path: '404',
// component: () => import('@/views/error/404.vue'),
// meta: { direction: Direction.Error404, title: MetaHeader.root }
// },
// {
// path: '500',
// component: () => import('@/views/error/500.vue'),
// meta: { direction: Direction.Error500, title: MetaHeader.root }
// }
// ]
// },
// {
// path: '/how-to-adjust-system-time',
// component: () => import('@/views/error/adjust-system-time.vue'),
// meta: { direction: Direction.AdjustTime, title: MetaHeader.root }
// },
];
<template>
<div
v-loading="!error"
class="
d-flex
redirecting
justify-content-center
align-items-center
flex-fill
"
:class="{ bg: error }"
>
{{ error }}
<div v-if="error">。点击<a href="/">这里</a>返回首页重试。</div>
</div>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import { setupOidcManager, TokenManager } from "@/api/token";
import config from "@/api/config";
@Component({ components: {} })
export default class Redirect extends Vue {
private error = "";
mounted() {
document.title = "登录中...";
const oidc = setupOidcManager();
oidc.getUser().then((u) => {
if (u && !TokenManager.isExpired(u)) {
return (window.location.href = config.api.root);
}
oidc.signinRedirectCallback()
.then((user) => {
const remote = user.state?.returnUrl;
window.location.href = remote || config.api.root;
})
.catch((error) => (this.error = `登录失败,${error}`));
});
}
}
</script>
<style lang="less" scoped>
.redirecting {
font-size: 30px;
padding: 400px 50px;
}
</style>
<template>
<div></div>
</template>
<script lang="ts">
import { setupOidcManager } from "@/api/token";
import logger from "@/core-ui/controller/logger";
import { Component, Vue } from "vue-property-decorator";
@Component({ components: {} })
export default class SilentRedirect extends Vue {
mounted() {
const oidc = setupOidcManager();
oidc.signinSilentCallback().then().catch(logger.error);
}
}
</script>
<style lang="less" scoped>
.login-message {
font-size: 25px;
padding-top: 25%;
text-align: center;
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment