feat(base-ui):i18n

This commit is contained in:
wang-liang0615 2024-01-02 16:39:41 +08:00
parent 70d674ac4f
commit 3401cf4a1e
50 changed files with 4755 additions and 3345 deletions

View File

@ -1,5 +1,5 @@
<template>
<a-config-provider :locale="locale">
<a-config-provider :locale="antdLocale">
<div id="app" :class="{ 'ops-fullscreen': isOpsFullScreen, 'ops-only-topmenu': isOpsOnlyTopMenu }">
<router-view v-if="alive" />
</div>
@ -7,8 +7,9 @@
</template>
<script>
import { mapActions } from 'vuex'
import { mapState, mapActions, mapMutations } from 'vuex'
import zhCN from 'ant-design-vue/lib/locale-provider/zh_CN'
import enUS from 'ant-design-vue/lib/locale-provider/en_US'
import { AppDeviceEnquire } from '@/utils/mixin'
import { debounce } from './utils/util'
@ -24,20 +25,28 @@ export default {
},
data() {
return {
locale: zhCN,
alive: true,
timer: null,
}
},
computed: {
...mapState(['locale']),
antdLocale() {
if (this.locale === 'zh') {
return zhCN
}
return enUS
},
isOpsFullScreen() {
return this.$route.name === 'cmdb_screen'
return ['cmdb_screen'].includes(this.$route.name)
},
isOpsOnlyTopMenu() {
return ['fullscreen_index', 'setting_person'].includes(this.$route.name)
return ['fullscreen_index', 'setting_person', 'notice_center'].includes(this.$route.name)
},
},
created() {
this.SET_LOCALE(localStorage.getItem('ops_locale') || 'zh')
this.$i18n.locale = localStorage.getItem('ops_locale') || 'zh'
this.timer = setInterval(() => {
this.setTime(new Date().getTime())
}, 1000)
@ -184,6 +193,7 @@ export default {
},
methods: {
...mapActions(['setTime']),
...mapMutations(['SET_LOCALE']),
reload() {
this.alive = false
this.$nextTick(() => {

View File

@ -1,29 +1,37 @@
export const ruleTypeList = [
{ value: 'and', label: '与' },
{ value: 'or', label: '或' },
import i18n from '@/lang'
export const ruleTypeList = () => {
return [
{ value: 'and', label: i18n.t('cmdbFilterComp.and') },
{ value: 'or', label: i18n.t('cmdbFilterComp.or') },
// { value: 'not', label: '非' },
]
]
}
export const expList = [
{ value: 'is', label: '等于' },
{ value: '~is', label: '不等于' },
{ value: 'contain', label: '包含' },
{ value: '~contain', label: '不包含' },
{ value: 'start_with', label: '以...开始' },
{ value: '~start_with', label: '不以...开始' },
{ value: 'end_with', label: '以...结束' },
{ value: '~end_with', label: '不以...结束' },
{ value: '~value', label: '为空' }, // 为空的定义有点绕
{ value: 'value', label: '不为空' },
]
export const expList = () => {
return [
{ value: 'is', label: i18n.t('cmdbFilterComp.is') },
{ value: '~is', label: i18n.t('cmdbFilterComp.~is') },
{ value: 'contain', label: i18n.t('cmdbFilterComp.contain') },
{ value: '~contain', label: i18n.t('cmdbFilterComp.~contain') },
{ value: 'start_with', label: i18n.t('cmdbFilterComp.start_with') },
{ value: '~start_with', label: i18n.t('cmdbFilterComp.~start_with') },
{ value: 'end_with', label: i18n.t('cmdbFilterComp.end_with') },
{ value: '~end_with', label: i18n.t('cmdbFilterComp.~end_with') },
{ value: '~value', label: i18n.t('cmdbFilterComp.~value') }, // 为空的定义有点绕
{ value: 'value', label: i18n.t('cmdbFilterComp.value') },
]
}
export const advancedExpList = [
{ value: 'in', label: 'in查询' },
{ value: '~in', label: '非in查询' },
{ value: 'range', label: '范围' },
{ value: '~range', label: '范围外' },
{ value: 'compare', label: '比较' },
]
export const advancedExpList = () => {
return [
{ value: 'in', label: i18n.t('cmdbFilterComp.in') },
{ value: '~in', label: i18n.t('cmdbFilterComp.~in') },
{ value: 'range', label: i18n.t('cmdbFilterComp.range') },
{ value: '~range', label: i18n.t('cmdbFilterComp.~range') },
{ value: 'compare', label: i18n.t('cmdbFilterComp.compare') },
]
}
export const compareTypeList = [
{ value: '1', label: '>' },

View File

@ -1,11 +1,11 @@
<template>
<div>
<a-space :style="{ display: 'flex', marginBottom: '10px' }" v-for="(item, index) in ruleList" :key="item.id">
<div :style="{ width: '50px', height: '24px', position: 'relative' }">
<div :style="{ width: '70px', height: '24px', position: 'relative' }">
<treeselect
v-if="index"
class="custom-treeselect"
:style="{ width: '50px', '--custom-height': '24px', position: 'absolute', top: '-17px', left: 0 }"
:style="{ width: '70px', '--custom-height': '24px', position: 'absolute', top: '-17px', left: 0 }"
v-model="item.type"
:multiple="false"
:clearable="false"
@ -91,7 +91,7 @@
searchable
v-if="isChoiceByProperty(item.property) && (item.exp === 'is' || item.exp === '~is')"
:options="getChoiceValueByProperty(item.property)"
placeholder="请选择"
:placeholder="$t('placeholder2')"
:normalizer="
(node) => {
return {
@ -119,9 +119,21 @@
v-else-if="item.exp === 'range' || item.exp === '~range'"
:style="{ width: '175px' }"
>
<a-input class="ops-input" size="small" v-model="item.min" :style="{ width: '78px' }" placeholder="最小值" />
<a-input
class="ops-input"
size="small"
v-model="item.min"
:style="{ width: '78px' }"
:placeholder="$t('min')"
/>
~
<a-input class="ops-input" size="small" v-model="item.max" :style="{ width: '78px' }" placeholder="最大值" />
<a-input
class="ops-input"
size="small"
v-model="item.max"
:style="{ width: '78px' }"
:placeholder="$t('max')"
/>
</a-input-group>
<a-input-group size="small" compact v-else-if="item.exp === 'compare'" :style="{ width: '175px' }">
<treeselect
@ -151,19 +163,23 @@
v-else-if="item.exp !== 'value' && item.exp !== '~value'"
size="small"
v-model="item.value"
:placeholder="item.exp === 'in' || item.exp === '~in' ? '以 ; 分隔' : ''"
:placeholder="item.exp === 'in' || item.exp === '~in' ? $t('cmdbFilterComp.split', { separator: ';' }) : ''"
class="ops-input"
:style="{ width: '175px' }"
></a-input>
<div v-else :style="{ width: '175px' }"></div>
<a-tooltip title="复制">
<a-tooltip :title="$t('copy')">
<a class="operation" @click="handleCopyRule(item)"><ops-icon type="icon-xianxing-copy"/></a>
</a-tooltip>
<a-tooltip title="删除">
<a-tooltip :title="$t('delete')">
<a class="operation" @click="handleDeleteRule(item)"><ops-icon type="icon-xianxing-delete"/></a>
</a-tooltip>
<a-tooltip :title="$t('cmdbFilterComp.addHere')" :needAddHere="needAddHere">
<a class="operation" @click="handleAddRuleAt(item)"><a-icon type="plus-circle"/></a>
</a-tooltip>
</a-space>
<div class="table-filter-add">
<a @click="handleAddRule">+ 新增</a>
<a @click="handleAddRule">+ {{ $t('new') }}</a>
</div>
</div>
</template>
@ -191,12 +207,13 @@ export default {
required: true,
default: () => [],
},
needAddHere: {
type: Boolean,
default: false,
},
},
data() {
return {
ruleTypeList,
expList,
advancedExpList,
compareTypeList,
}
},
@ -210,6 +227,15 @@ export default {
return val
},
},
ruleTypeList() {
return ruleTypeList()
},
expList() {
return expList()
},
advancedExpList() {
return advancedExpList()
},
},
methods: {
getExpListByProperty(property) {
@ -217,10 +243,10 @@ export default {
const _find = this.canSearchPreferenceAttrList.find((item) => item.name === property)
if (_find && ['0', '1', '3', '4', '5'].includes(_find.value_type)) {
return [
{ value: 'is', label: '等于' },
{ value: '~is', label: '不等于' },
{ value: '~value', label: '为空' }, // 为空的定义有点绕
{ value: 'value', label: '不为空' },
{ value: 'is', label: this.$t('cmdbFilterComp.is') },
{ value: '~is', label: this.$t('cmdbFilterComp.~is') },
{ value: '~value', label: this.$t('cmdbFilterComp.~value') }, // 为空的定义有点绕
{ value: 'value', label: this.$t('cmdbFilterComp.value') },
]
}
return this.expList
@ -255,6 +281,19 @@ export default {
}
this.$emit('change', this.ruleList)
},
handleAddRuleAt(item) {
const idx = this.ruleList.findIndex((r) => r.id === item.id)
if (idx > -1) {
this.ruleList.splice(idx, 0, {
id: uuidv4(),
type: 'and',
property: this.canSearchPreferenceAttrList[0]?.name,
exp: 'is',
value: null,
})
}
this.$emit('change', this.ruleList)
},
getChoiceValueByProperty(property) {
const _find = this.canSearchPreferenceAttrList.find((item) => item.name === property)
if (_find) {

View File

@ -9,23 +9,25 @@
@visibleChange="visibleChange"
>
<slot name="popover_item">
<a-button type="primary" ghost>条件过滤<a-icon type="filter"/></a-button>
<a-button type="primary" ghost>{{ $t('cmdbFilterComp.conditionFilter') }}<a-icon type="filter"/></a-button>
</slot>
<template slot="content">
<Expression
:needAddHere="needAddHere"
v-model="ruleList"
:canSearchPreferenceAttrList="canSearchPreferenceAttrList.filter((attr) => !attr.is_password)"
/>
<a-divider :style="{ margin: '10px 0' }" />
<div style="width:534px">
<div style="width:554px">
<a-space :style="{ display: 'flex', justifyContent: 'flex-end' }">
<a-button type="primary" size="small" @click="handleSubmit">确定</a-button>
<a-button size="small" @click="handleClear">清空</a-button>
<a-button type="primary" size="small" @click="handleSubmit">{{ $t('confirm') }}</a-button>
<a-button size="small" @click="handleClear">{{ $t('clear') }}</a-button>
</a-space>
</div>
</template>
</a-popover>
<Expression
:needAddHere="needAddHere"
v-else
v-model="ruleList"
:canSearchPreferenceAttrList="canSearchPreferenceAttrList.filter((attr) => !attr.is_password)"
@ -63,6 +65,10 @@ export default {
type: Boolean,
default: true,
},
needAddHere: {
type: Boolean,
default: false,
},
},
data() {
return {

View File

@ -1,8 +1,10 @@
export const iconTypeList = [
import i18n from '@/lang'
export const iconTypeList = () => [
// { value: '0', label: '常用' },
{ value: '1', label: '线性' },
{ value: '2', label: '实底' },
{ value: '3', label: '多色' }
{ value: '1', label: i18n.t('customIconSelect.outlined') },
{ value: '2', label: i18n.t('customIconSelect.filled') },
{ value: '3', label: i18n.t('customIconSelect.multicolor') }
]
export const commonIconList = ['changyong-ubuntu',

View File

@ -16,7 +16,7 @@
{{ item.label }}
</div>
<div :class="`${currentIconType === '4' ? 'selected' : ''}`" @click="handleChangeIconType('4')">
自定义
{{ this.$t('customIconSelect.custom') }}
</div>
<a-upload
slot="description"
@ -26,7 +26,7 @@
accept=".svg,.png,.jpg,.jpeg"
v-if="currentIconType === '4'"
>
<a-button icon="plus" size="small" type="primary">添加</a-button>
<a-button icon="plus" size="small" type="primary">{{ $t('add') }}</a-button>
</a-upload>
</div>
<div class="custom-icon-select-popover-content">
@ -55,11 +55,11 @@
@click="clickCustomIcon(icon)"
>
<div class="custom-icon-select-popover-content-img-box">
<img :src="`/api/common-setting/v1/file/${icon.data.url}`" />
<img v-if="icon.data && icon.data.url" :src="`/api/common-setting/v1/file/${icon.data.url}`" />
<a-popconfirm
overlayClassName="custom-icon-select-confirm-popover"
:getPopupContainer="(trigger) => trigger.parentNode"
title="确认删除?"
:title="$t('confirmDelete')"
@confirm="(e) => deleteIcon(e, icon)"
@cancel="
(e) => {
@ -102,27 +102,27 @@
</template>
<a-form class="custom-icon-select-form" :form="form" v-show="currentIconType === '4' && formVisible">
<a-form-item
label="名称"
:label="$t('name')"
:labelCol="{ span: 4 }"
:wrapperCol="{ span: 16 }"
><a-input
v-decorator="['name', { rules: [{ required: true, message: '请输入名称' }] }]"
v-decorator="['name', { rules: [{ required: true, message: $t('placeholder1') }] }]"
/></a-form-item>
<a-form-item label="预览" :labelCol="{ span: 4 }">
<a-form-item :label="$t('customIconSelect.preview')" :labelCol="{ span: 4 }">
<div class="custom-icon-select-form-img">
<img :src="formImg" />
</div>
</a-form-item>
<a-form-item label=" " :colon="false" :labelCol="{ span: 16 }">
<a-space>
<a-button size="small" @click="handleCancel">取消</a-button>
<a-button size="small" type="primary" @click="handleOk">确定</a-button>
<a-button size="small" @click="handleCancel">{{ $t('cancel') }}</a-button>
<a-button size="small" type="primary" @click="handleOk">{{ $t('confirm') }}</a-button>
</a-space>
</a-form-item>
</a-form>
</div>
<div class="custom-icon-select-block" id="custom-icon-select-block" @click="showSelect">
<div class="custom-icon-select-block" :id="`custom-icon-select-block-${uuid}`" @click="showSelect">
<img v-if="value.id && value.url" :src="`/api/common-setting/v1/file/${value.url}`" />
<ops-icon
v-else
@ -134,6 +134,7 @@
</template>
<script>
import { v4 as uuidv4 } from 'uuid'
import { ColorPicker } from 'element-ui'
import {
iconTypeList,
@ -166,7 +167,6 @@ export default {
data() {
return {
form: this.$form.createForm(this),
iconTypeList,
commonIconList,
linearIconList,
fillIconList,
@ -177,6 +177,7 @@ export default {
formVisible: false,
formImg: null,
file: null,
uuid: uuidv4(),
}
},
computed: {
@ -200,6 +201,9 @@ export default {
const splitFileName = this.file.name.split('.')
return splitFileName.splice(0, splitFileName.length - 1).join('')
},
iconTypeList() {
return iconTypeList()
},
},
mounted() {
document.addEventListener('click', this.eventListener)
@ -217,7 +221,7 @@ export default {
eventListener(e) {
if (this.visible) {
const dom = document.getElementById(`custom-icon-select-popover`)
const dom_icon = document.getElementById(`custom-icon-select-block`)
const dom_icon = document.getElementById(`custom-icon-select-block-${this.uuid}`)
e.stopPropagation()
e.preventDefault()
if (dom) {
@ -249,12 +253,11 @@ export default {
color: '',
})
} else {
this.$emit('change', { name: icon.data.name, id: icon.id, url: icon.data.url })
this.$emit('change', { name: icon.data.name, id: icon.id, url: icon?.data?.url })
}
},
showSelect() {
this.visible = true
console.log(this.value)
if (!this.value.name) {
this.currentIconType = '3'
return
@ -278,7 +281,7 @@ export default {
beforeUpload(file) {
const isLt2M = file.size / 1024 / 1024 < 2
if (!isLt2M) {
this.$message.error('图片大小不可超过2MB!')
this.$message.error(this.$t('customIconSelect.sizeLimit'))
return false
}
@ -306,7 +309,7 @@ export default {
this.form.validateFields((err, values) => {
if (!err) {
addFileData('ops-custom-icon', { data: { name: values.name, url: res.file_name } }).then(() => {
this.$message.success('上传成功!')
this.$message.success(this.$t('uploadSuccess'))
this.handleCancel()
this.getFileData()
})
@ -318,7 +321,7 @@ export default {
e.stopPropagation()
e.preventDefault()
deleteFileData('ops-custom-icon', icon.id).then(() => {
this.$message.success('删除成功!')
this.$message.success(this.$t('deleteSuccess'))
this.handleCancel()
this.getFileData()
})

View File

@ -6,17 +6,17 @@
:flat="true"
:multiple="true"
:options="employeeTreeSelectOption"
placeholder="请输入搜索内容"
:placeholder="$t('placeholderSearch')"
v-model="treeValue"
:max-height="height - 50"
noChildrenText=""
noOptionsText=""
:clearable="false"
:always-open="true"
:default-expand-level="1"
:default-expand-level="showInternship ? 0 : 1"
:class="{ 'employee-transfer': true, 'employee-transfer-has-input': !!inputValue }"
@search-change="changeInputValue"
noResultsText="暂无数据"
:noResultsText="$t('noData')"
openDirection="below"
>
</treeselect>
@ -85,6 +85,10 @@ export default {
type: Boolean,
default: false,
},
showInternship: {
type: Boolean,
default: false,
},
},
data() {
return {
@ -99,13 +103,22 @@ export default {
},
computed: {
employeeTreeSelectOption() {
return formatOption(
const formatOptions = formatOption(
this.allTreeDepAndEmp,
2,
this.isDisabledAllCompany,
this.uniqueKey || 'department_id',
this.uniqueKey || 'employee_id'
)
if (this.showInternship) {
formatOptions.push(
...[
{ id: -2, label: '全职' },
{ id: -3, label: '实习生' },
]
)
}
return formatOptions
},
allTreeDepAndEmp() {
if (this.getDataBySelf) {
@ -148,12 +161,16 @@ export default {
const department = []
const user = []
this.rightData.forEach((item) => {
if (item === -2 || item === -3) {
department.push(item)
} else {
const _split = item.split('-')
if (_split[0] === 'department') {
department.push(Number(_split[1]))
} else {
user.push(Number(_split[1]))
}
}
})
const _idx = department.findIndex((item) => item === 0)
if (_idx > -1) {
@ -191,6 +208,12 @@ export default {
}
},
getLabel(id) {
if (id === -2) {
return '全职'
}
if (id === -3) {
return '实习生'
}
const _split = id.split('-')
const type = _split[0]
const _id = Number(_split[1])

View File

@ -161,6 +161,9 @@ export default {
}
return null
},
renderI18n(title) {
return this.$t(`${title}`)
},
renderMenuItem(menu) {
const isShowDot = menu.path.substr(0, 22) === '/cmdb/instances/types/'
const isShowGrant = menu.path.substr(0, 20) === '/cmdb/relationviews/'
@ -183,7 +186,7 @@ export default {
<tag {...{ props, attrs }}>
{this.renderIcon({ icon: menu.meta.icon, customIcon: menu.meta.customIcon, name: menu.meta.name, typeId: menu.meta.typeId, routeName: menu.name, selectedIcon: menu.meta.selectedIcon, })}
<span>
<span class={menu.meta.title.length > 10 ? 'scroll' : ''}>{menu.meta.title}</span>
<span class={this.renderI18n(menu.meta.title).length > 10 ? 'scroll' : ''}>{this.renderI18n(menu.meta.title)}</span>
{isShowDot &&
<a-popover
overlayClassName="custom-menu-extra-submenu"
@ -217,7 +220,7 @@ export default {
<SubMenu {...{ key: menu.path }}>
<span slot="title">
{this.renderIcon({ icon: menu.meta.icon, selectedIcon: menu.meta.selectedIcon, routeName: menu.name })}
<span>{menu.meta.title}</span>
<span>{this.renderI18n(menu.meta.title)}</span>
</span>
{itemArr}
</SubMenu>

View File

@ -3,9 +3,9 @@
<slot></slot>
<template #empty>
<slot name="empty">
<div>
<img :style="{ width: '100px' }" :src="require('@/assets/data_empty.png')" />
<div>暂无数据</div>
<div :style="{ paddingTop: '10px' }">
<img :style="{ width: '100px', height: '90px' }" :src="require('@/assets/data_empty.png')" />
<div>{{ $t('noData') }}</div>
</div>
</slot>
</template>

View File

@ -3,12 +3,12 @@
<a-switch
class="role-transfer-switch"
v-model="isUserRole"
checked-children="用户"
un-checked-children="虚拟"
:checked-children="$t('user')"
:un-checked-children="$t('visual')"
@change="loadRoles"
/>
<div class="role-transfer-left">
<a-input placeholder="请输入搜索内容" v-model="searchValue" />
<a-input :placeholder="$t('placeholderSearch')" v-model="searchValue" />
<div v-for="item in filterAllRoles" :key="item.id" @click="handleSelectedLeft(item.id)">
<a-checkbox :checked="selectedLeft.includes(item.id)" />
<div :title="item.name" class="role-transfer-left-role">{{ item.name }}</div>

View File

@ -10,9 +10,10 @@
>
<a-icon type="setting" />
</span>
<span class="locale" @click="changeLang">{{ locale === 'zh' ? 'English' : '中文' }}</span>
<a-popover
trigger="click"
:overlayStyle="{ width: '120px' }"
:overlayStyle="{ width: '150px' }"
placement="bottomRight"
overlayClassName="custom-user"
>
@ -20,12 +21,12 @@
<router-link :to="{ name: 'setting_person' }" :style="{ color: '#000000a6' }">
<div class="custom-user-item">
<a-icon type="user" :style="{ marginRight: '10px' }" />
<span>个人中心</span>
<span>{{ $t('topMenu.personalCenter') }}</span>
</div>
</router-link>
<div @click="handleLogout" class="custom-user-item">
<a-icon type="logout" :style="{ marginRight: '10px' }" />
<span>退出登录</span>
<span>{{ $t('topMenu.logout') }}</span>
</div>
</template>
<span class="action ant-dropdown-link user-dropdown-menu">
@ -44,8 +45,9 @@
</template>
<script>
import { mapState, mapActions, mapGetters, mapMutations } from 'vuex'
import DocumentLink from './DocumentLink.vue'
import { mapState, mapActions, mapGetters } from 'vuex'
import { setDocumentTitle, domTitle } from '@/utils/domUtil'
export default {
name: 'UserMenu',
@ -53,21 +55,24 @@ export default {
DocumentLink,
},
computed: {
...mapState(['user']),
...mapState(['user', 'locale']),
hasBackendPermission() {
return this.user?.roles?.permissions.includes('acl_admin', 'backend_admin') || false
return this.user?.detailPermissions?.backend?.length
},
},
methods: {
...mapActions(['Logout']),
...mapGetters(['nickname', 'avatar']),
...mapMutations(['SET_LOCALE']),
handleLogout() {
const that = this
this.$confirm({
title: '提示',
content: '确认注销登录 ?',
content: '真的要注销登录吗 ?',
onOk() {
// localStorage.removeItem('ops_cityps_currentId')
localStorage.clear()
return that.Logout()
},
onCancel() {},
@ -76,9 +81,22 @@ export default {
handleClick() {
this.$router.push('/setting')
},
changeLang() {
if (this.locale === 'zh') {
this.SET_LOCALE('en')
this.$i18n.locale = 'en'
} else {
this.SET_LOCALE('zh')
this.$i18n.locale = 'zh'
}
this.$nextTick(() => {
setDocumentTitle(`${this.$t(this.$route.meta.title)} - ${domTitle}`)
})
},
},
}
</script>
<style lang="less">
@import '~@/style/static.less';
.color {
@ -98,4 +116,11 @@ export default {
color: #000000a6;
}
}
.locale {
cursor: pointer;
&:hover {
color: #custom_colors[color_1];
}
}
</style>

View File

@ -38,11 +38,18 @@ import CardTitle from '@/components/CardTitle'
import ElementUI from 'element-ui'
import Treeselect from '@riophae/vue-treeselect'
import OpsTable from '@/components/OpsTable'
import VueI18n from 'vue-i18n'
import i18n from '@/lang'
Vue.config.productionTip = false
Vue.prototype.$bus = EventBus
VXETable.setup({
i18n: (key, args) => i18n.t(key, args)
})
Vue.use(VXETable)
VXETable.use(VXETablePluginExportXLSX)
Vue.use(VueI18n)
Vue.config.productionTip = false
@ -75,4 +82,3 @@ Vue.component('CustomRadio', CustomRadio)
Vue.component('CardTitle', CardTitle)
Vue.component('Treeselect', Treeselect)
Vue.component('OpsTable', OpsTable)

View File

@ -7,6 +7,7 @@ import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { setDocumentTitle, domTitle } from '@/utils/domUtil'
import { ACCESS_TOKEN } from './store/global/mutation-types'
import i18n from '@/lang'
NProgress.configure({ showSpinner: false })
@ -17,7 +18,7 @@ const whitePath = ['/user/login', '/user/logout', '/user/register', '/api/sso/lo
// 登录页面处理处理 是否使用单点登录
router.beforeEach(async (to, from, next) => {
NProgress.start() // start progress bar
to.meta && (!!to.meta.title && setDocumentTitle(`${to.meta.title} - ${domTitle}`))
to.meta && (!!to.meta.title && setDocumentTitle(`${i18n.t(to.meta.title)} - ${domTitle}`))
const authed = store.state.authed
const auth_type = localStorage.getItem('ops_auth_type')

140
cmdb-ui/src/lang/en.js Normal file
View File

@ -0,0 +1,140 @@
import cmdb_en from '@/modules/cmdb/lang/en.js'
import cs_en from '../views/setting/lang/en.js'
import acl_en from '@/modules/acl/lang/en.js'
export default {
screen: 'Big Screen',
dashboard: 'Dashboard',
admin: 'Admin',
user: 'User',
role: 'Role',
operation: 'Operation',
login: 'Login',
refresh: 'Refresh',
cancel: 'Cancel',
confirm: 'Confirm',
create: 'Create',
edit: 'Edit',
deleting: 'Deleting',
deletingTip: 'Deleting, total of {total}, {successNum} succeeded, {errorNum} failed',
grant: 'Grant',
login_at: 'Login At',
logout_at: 'Logout At',
createSuccess: 'Create Success',
editSuccess: 'edit Success',
warning: 'Warning',
export: 'Export',
placeholderSearch: 'Please Search',
success: 'Success',
fail: 'Fail',
browser: 'Browser',
status: 'Status',
type: 'Type',
description: 'Description',
new: 'New',
add: 'Add',
define: 'Define',
update: 'Update',
clear: 'Clear',
delete: 'Delete',
copy: 'Copy',
created_at: 'Created At',
updated_at: 'Updated At',
placeholder1: 'Please Input',
placeholder2: 'Please Select',
confirmDelete: 'Confirm delete?',
confirmDelete2: 'Confirm delete [{name}]?',
query: 'Query',
search: 'Search',
hide: 'Hide',
expand: 'Expand',
save: 'Save',
submit: 'Submit',
upload: 'Import',
download: 'Export',
name: 'Name',
alias: 'Alias',
desc: 'Description',
other: 'Other',
icon: 'Icon',
addSuccess: 'Added successfully',
uploadSuccess: 'Import successfully',
saveSuccess: 'Save successfully',
copySuccess: 'Copy successfully',
updateSuccess: 'Updated successfully',
deleteSuccess: 'Deleted successfully',
operateSuccess: 'The operation was successful',
noPermission: 'No Permission',
noData: 'No Data',
seconds: 'Seconds',
createdAt: 'Created At',
updatedAt: 'Updated At',
deletedAt: 'Deleted At',
required: 'required',
email: 'Email',
wechat: 'Wechat',
dingding: 'DingTalk',
feishu: 'Feishu',
bot: 'Robot',
checkAll: 'Select All',
loading: 'Loading...',
view: 'View',
reset: 'Reset',
yes: 'Yes',
no: 'No',
all: 'All',
selectRows: 'Selected: {rows} items',
itemsPerPage: '/page',
'星期一': 'Monday',
'星期二': 'Tuesday',
'星期三': 'Wednesday',
'星期四': 'Thursday',
'星期五': 'Friday',
'星期六': 'Saturday',
'星期日': 'Sunday',
hour: 'hour',
'items/page': '{items} items/page',
max: 'Max',
min: 'Min',
visual: 'Visual',
pagination: {
total: '{range0}-{range1} of {total} items'
},
topMenu: {
personalCenter: 'Personal Center',
logout: 'logout',
},
cmdbFilterComp: {
conditionFilter: 'Conditional filtering',
and: 'and',
or: 'or',
is: 'equal',
'~is': 'not equal',
contain: 'contain',
'~contain': 'not contain',
start_with: 'start_with',
'~start_with': 'not start_with',
end_with: 'end_with',
'~end_with': 'not end_with',
'~value': 'null',
value: 'not null',
in: 'in',
'~in': 'not in',
range: 'range',
'~range': 'out of range',
compare: 'compare',
addHere: 'Add Here',
split: 'split by {separator}'
},
customIconSelect: {
outlined: 'Outlined',
filled: 'Filled',
multicolor: 'Multicolor',
custom: 'Custom',
preview: 'Preview',
sizeLimit: 'The image size cannot exceed 2MB!'
},
cmdb: cmdb_en,
cs: cs_en,
acl: acl_en,
}

18
cmdb-ui/src/lang/index.js Normal file
View File

@ -0,0 +1,18 @@
import VueI18n from 'vue-i18n'
import zh from './zh'
import en from './en'
import Vue from 'vue'
import zhCN from 'vxe-table/lib/locale/lang/zh-CN'
import enUS from 'vxe-table/lib/locale/lang/en-US'
Vue.use(VueI18n)
const i18n = new VueI18n({
locale: 'zh', // 初始化中文
messages: {
'zh': { ...zh, ...zhCN },
'en': { ...en, ...enUS },
},
silentTranslationWarn: true
})
export default i18n

140
cmdb-ui/src/lang/zh.js Normal file
View File

@ -0,0 +1,140 @@
import cmdb_zh from '@/modules/cmdb/lang/zh.js'
import cs_zh from '../views/setting/lang/zh.js'
import acl_zh from '@/modules/acl/lang/zh.js'
export default {
screen: '大屏',
dashboard: '仪表盘',
admin: '管理员',
user: '用户',
role: '角色',
operation: '操作',
login: '登录',
refresh: '刷新',
cancel: '取消',
confirm: '确定',
create: '创建',
edit: '编辑',
deleting: '正在删除',
deletingTip: '正在删除,共{total}个,成功{successNum}个,失败{errorNum}个',
grant: '授权',
login_at: '登录时间',
logout_at: '登出时间',
createSuccess: '创建成功',
editSuccess: '修改成功',
warning: '警告',
export: '导出',
placeholderSearch: '请查找',
success: '成功',
fail: '失败',
browser: '浏览器',
status: '状态',
type: '类型',
description: '描述',
new: '新增',
add: '添加',
define: '定义',
update: '修改',
clear: '清空',
delete: '删除',
copy: '复制',
created_at: '创建日期',
updated_at: '更新日期',
placeholder1: '请输入',
placeholder2: '请选择',
confirmDelete: '确认删除?',
confirmDelete2: '确认删除【{name}】?',
query: '查询',
search: '搜索',
hide: '隐藏',
expand: '展开',
save: '保存',
submit: '提交',
upload: '导入',
download: '导出',
name: '名称',
alias: '别名',
desc: '描述',
other: '其他',
icon: '图标',
addSuccess: '新增成功',
uploadSuccess: '导入成功',
saveSuccess: '保存成功',
copySuccess: '复制成功',
updateSuccess: '更新成功',
deleteSuccess: '删除成功',
operateSuccess: '操作成功',
noPermission: '权限不足',
noData: '暂无数据',
seconds: '秒',
createdAt: '创建时间',
updatedAt: '更新时间',
deletedAt: '删除时间',
required: '必须',
email: '邮件',
wechat: '企业微信',
dingding: '钉钉',
feishu: '飞书',
bot: '机器人',
checkAll: '全选',
loading: '加载中...',
view: '查看',
reset: '重置',
yes: '是',
no: '否',
all: '全部',
selectRows: '选取:{rows} 项',
itemsPerPage: '/页',
'星期一': '星期一',
'星期二': '星期二',
'星期三': '星期三',
'星期四': '星期四',
'星期五': '星期五',
'星期六': '星期六',
'星期日': '星期日',
hour: '小时',
'items/page': '{items} 条/页',
max: '最大值',
min: '最小值',
visual: '虚拟',
pagination: {
total: '当前展示 {range0}-{range1} 条数据, 共 {total} 条'
},
topMenu: {
personalCenter: '个人中心',
logout: '退出登录',
},
cmdbFilterComp: {
conditionFilter: '条件过滤',
and: '与',
or: '或',
is: '等于',
'~is': '不等于',
contain: '包含',
'~contain': '不包含',
start_with: '以...开始',
'~start_with': '不以...开始',
end_with: '以...结束',
'~end_with': '不以...结束',
'~value': '为空',
value: '不为空',
in: 'in查询',
'~in': '非in查询',
range: '范围',
'~range': '范围外',
compare: '比较',
addHere: '在此处添加',
split: '以 {separator} 分隔'
},
customIconSelect: {
outlined: '线框',
filled: '实底',
multicolor: '多色',
custom: '自定义',
preview: '预览',
sizeLimit: '图片大小不可超过2MB'
},
cmdb: cmdb_zh,
cs: cs_zh,
acl: acl_zh,
}

View File

@ -10,6 +10,7 @@ import './guard' // guard permission control
import './utils/filter' // global filter
import Setting from './config/setting'
import { Icon } from 'ant-design-vue'
import i18n from './lang'
import iconFont from '../public/iconfont/iconfont'
@ -22,6 +23,7 @@ async function start() {
const _vue = new Vue({
router,
store,
i18n,
created: bootstrap,
render: h => h(App)
}).$mount('#app')

View File

@ -34,6 +34,7 @@ export const generatorDynamicRouter = async () => {
name: 'notice_center',
component: BasicLayout,
children: [{
hidden: true,
path: '/noticecenter',
name: 'notice_center',
meta: { title: '消息中心' },
@ -50,53 +51,53 @@ export const generatorDynamicRouter = async () => {
hidden: true,
path: '/setting/person',
name: 'setting_person',
meta: { title: '个人中心', },
meta: { title: 'cs.menu.person', },
component: () => import(/* webpackChunkName: "setting" */ '@/views/setting/person/index')
},
{
path: '/setting/companyinfo',
name: 'company_info',
meta: { title: '公司信息', appName: 'backend', icon: 'ops-setting-companyInfo', selectedIcon: 'ops-setting-companyInfo-selected', permission: ['acl_admin', 'backend_admin'] },
meta: { title: 'cs.menu.companyInfo', appName: 'backend', icon: 'ops-setting-companyInfo', selectedIcon: 'ops-setting-companyInfo-selected', permission: ['公司信息', 'backend_admin'] },
component: () => import(/* webpackChunkName: "setting" */ '@/views/setting/companyInfo/index')
},
{
path: '/setting/companystructure',
name: 'company_structure',
meta: { title: '公司架构', appName: 'backend', icon: 'ops-setting-companyStructure', selectedIcon: 'ops-setting-companyStructure-selected', permission: ['acl_admin', 'backend_admin'] },
meta: { title: 'cs.menu.companyStructure', appName: 'backend', icon: 'ops-setting-companyStructure', selectedIcon: 'ops-setting-companyStructure-selected', permission: ['公司架构', 'backend_admin'] },
component: () => import(/* webpackChunkName: "setting" */ '@/views/setting/companyStructure/index')
},
{
path: '/setting/notice',
name: 'notice',
component: RouteView,
meta: { title: '通知设置', appName: 'backend', icon: 'ops-setting-notice', selectedIcon: 'ops-setting-notice-selected', permission: ['通知设置', 'backend_admin'] },
meta: { title: 'cs.menu.notice', appName: 'backend', icon: 'ops-setting-notice', selectedIcon: 'ops-setting-notice-selected', permission: ['通知设置', 'backend_admin'] },
redirect: '/setting/notice/email',
children: [{
path: '/setting/notice/email',
name: 'notice_email',
meta: { title: '邮件设置', icon: 'ops-setting-notice-email', selectedIcon: 'ops-setting-notice-email-selected' },
meta: { title: 'cs.menu.email', icon: 'ops-setting-notice-email', selectedIcon: 'ops-setting-notice-email-selected' },
component: () => import(/* webpackChunkName: "setting" */ '@/views/setting/notice/email/index')
}, {
path: '/setting/notice/wx',
name: 'notice_wx',
meta: { title: '企业微信', icon: 'ops-setting-notice-wx', selectedIcon: 'ops-setting-notice-wx-selected' },
meta: { title: 'cs.menu.wx', icon: 'ops-setting-notice-wx', selectedIcon: 'ops-setting-notice-wx-selected' },
component: () => import(/* webpackChunkName: "setting" */ '@/views/setting/notice/wx')
}, {
path: '/setting/notice/dingding',
name: 'notice_dingding',
meta: { title: '钉钉', icon: 'ops-setting-notice-dingding', selectedIcon: 'ops-setting-notice-dingding-selected' },
meta: { title: 'cs.menu.dingding', icon: 'ops-setting-notice-dingding', selectedIcon: 'ops-setting-notice-dingding-selected' },
component: () => import(/* webpackChunkName: "setting" */ '@/views/setting/notice/dingding')
}, {
path: '/setting/notice/feishu',
name: 'notice_feishu',
meta: { title: '飞书', icon: 'ops-setting-notice-feishu', selectedIcon: 'ops-setting-notice-feishu-selected' },
meta: { title: 'cs.menu.feishu', icon: 'ops-setting-notice-feishu', selectedIcon: 'ops-setting-notice-feishu-selected' },
component: () => import(/* webpackChunkName: "setting" */ '@/views/setting/notice/feishu')
}]
},
{
path: '/setting/auth',
name: 'company_auth',
meta: { title: '认证设置', appName: 'backend', icon: 'ops-setting-auth', selectedIcon: 'ops-setting-auth-selected', permission: ['acl_admin'] },
meta: { title: 'cs.menu.auth', appName: 'backend', icon: 'ops-setting-auth', selectedIcon: 'ops-setting-auth-selected', permission: ['acl_admin'] },
component: () => import(/* webpackChunkName: "setting" */ '@/views/setting/auth/index')
},
]

View File

@ -24,6 +24,7 @@ const store = new Vuex.Store({
windowWidth: 800,
windowHeight: 600,
currentTime: 0,
locale: 'zh'
},
mutations: {
SET_WINDOW_SIZE(state, { width, height }) {
@ -33,6 +34,10 @@ const store = new Vuex.Store({
SET_TIME: (state, time) => {
state.currentTime = time
},
SET_LOCALE: (state, locale) => {
state.locale = locale
localStorage.setItem('ops_locale', locale)
}
},
actions: {
setWindowSize({ commit }) {

View File

@ -1,7 +1,7 @@
<template>
<a-form-model ref="form" :model="form" :label-col="labelCol" :wrapper-col="wrapperCol" :rules="rules">
<SpanTitle>基本</SpanTitle>
<a-form-model-item label="是否启用" prop="enable">
<SpanTitle>{{ $t('cs.auth.basic') }}</SpanTitle>
<a-form-model-item :label="$t('cs.auth.isEnable')" prop="enable">
<a-switch
:checked="Boolean(form.enable)"
@change="
@ -11,26 +11,26 @@
"
/>
</a-form-model-item>
<a-form-model-item label="服务端地址" prop="cas_server" help="不包括url path例如https://xxx.com">
<a-input v-model="form.cas_server" placeholder="请输入服务端地址" />
<a-form-model-item :label="$t('cs.auth.cas.server')" prop="cas_server" :help="$t('cs.auth.cas.serverHelp')">
<a-input v-model="form.cas_server" :placeholder="$t('cs.auth.cas.serverPlaceholder')" />
</a-form-model-item>
<a-form-model-item label="验证服务端地址" prop="cas_validate_server" help="不包括url path例如https://xxx.com">
<a-input v-model="form.cas_validate_server" placeholder="请输入验证服务端地址" />
<a-form-model-item :label="$t('cs.auth.cas.validateServer')" prop="cas_validate_server" :help="$t('cs.auth.cas.validateServerHelp')">
<a-input v-model="form.cas_validate_server" :placeholder="$t('cs.auth.cas.validateServerPlaceholder')" />
</a-form-model-item>
<SpanTitle>其他</SpanTitle>
<a-form-model-item label="登录路由" prop="cas_login_route">
<SpanTitle>{{ $t('cs.auth.other') }}</SpanTitle>
<a-form-model-item :label="$t('cs.auth.cas.loginRoute')" prop="cas_login_route">
<a-input v-model="form.cas_login_route" placeholder="/cas/built-in/cas/login" />
</a-form-model-item>
<a-form-model-item label="注销路由" prop="cas_logout_route">
<a-form-model-item :label="$t('cs.auth.cas.logoutRoute')" prop="cas_logout_route">
<a-input v-model="form.cas_logout_route" placeholder="/cas/built-in/cas/logout" />
</a-form-model-item>
<a-form-model-item label="验证路由" prop="cas_validate_route">
<a-form-model-item :label="$t('cs.auth.cas.validateRoute')" prop="cas_validate_route">
<a-input v-model="form.cas_validate_route" placeholder="/cas/built-in/cas/serviceValidate" />
</a-form-model-item>
<a-form-model-item label="重定向路由" prop="cas_after_login">
<a-input v-model="form.cas_after_login" placeholder="请输入重定向路由" />
<a-form-model-item :label="$t('cs.auth.cas.afterLoginRoute')" prop="cas_after_login">
<a-input v-model="form.cas_after_login" :placeholder="$t('cs.auth.cas.afterLoginRoutePlaceholder')" />
</a-form-model-item>
<a-form-model-item label="用户属性映射" prop="cas_user_map" :wrapper-col="{ span: 15 }">
<a-form-model-item :label="$t('cs.auth.cas.userMap')" prop="cas_user_map" :wrapper-col="{ span: 15 }">
<vue-json-editor
:style="{ '--custom-height': `${200}px` }"
v-model="form.cas_user_map"
@ -73,16 +73,20 @@ export default {
labelCol: { span: 3 },
wrapperCol: { span: 10 },
form: _.cloneDeep(defaultForm),
rules: {
enable: [{ required: true }],
cas_server: [{ required: true, message: '请输入服务端地址' }],
cas_login_route: [{ required: true, message: '请输入登录路由' }],
cas_logout_route: [{ required: true, message: '请输入注销路由' }],
cas_validate_route: [{ required: true, message: '请输入验证路由' }],
},
isJsonRight: true,
}
},
computed: {
rules() {
return {
enable: [{ required: true }],
cas_server: [{ required: true, message: this.$t('cs.auth.cas.serverPlaceholder') }],
cas_login_route: [{ required: true, message: this.$t('cs.auth.cas.loginRoutePlaceholder') }],
cas_logout_route: [{ required: true, message: this.$t('cs.auth.cas.logoutRoutePlaceholder') }],
cas_validate_route: [{ required: true, message: this.$t('cs.auth.cas.validateRoutePlaceholder') }],
}
}
},
methods: {
setData(data) {
if (data) {

View File

@ -1,10 +1,10 @@
<template>
<a-form-model ref="form" :model="form" :label-col="labelCol" :wrapper-col="wrapperCol" :rules="rules">
<SpanTitle>基本</SpanTitle>
<SpanTitle>{{ $t('cs.auth.basic') }}</SpanTitle>
<a-form-model-item
label="自动跳转到第三方登录页"
:label="$t('cs.auth.autoRedirectLogin')"
prop="auto_redirect"
help="如果关闭,则会弹出跳转到第三方登录页的确认,点取消按钮会进入系统内置的登录页"
:help="$t('cs.auth.autoRedirectLoginHelp')"
>
<a-switch
:checked="Boolean(form.auto_redirect)"

View File

@ -15,12 +15,12 @@
<a-row>
<a-col :offset="item.value === 'AuthCommonConfig' ? 5 : 3">
<a-space>
<a-button :loading="loading" type="primary" @click="handleSave">保存</a-button>
<a-button :loading="loading" type="primary" @click="handleSave">{{ $t('save') }}</a-button>
<template v-if="item.value === 'LDAP'">
<a-button :loading="loading" ghost type="primary" @click="handleTest('connect')">测试连接</a-button>
<a-button :loading="loading" ghost type="primary" @click="handleTest('login')">测试登录</a-button>
<a-button :loading="loading" ghost type="primary" @click="handleTest('connect')">{{ $t('cs.auth.testConnect') }}</a-button>
<a-button :loading="loading" ghost type="primary" @click="handleTest('login')">{{ $t('cs.auth.testLogin') }}</a-button>
</template>
<a-button :loading="loading" @click="handleReset">重置</a-button>
<a-button :loading="loading" @click="handleReset">{{ $t('reset') }}</a-button>
</a-space>
</a-col>
</a-row>
@ -42,7 +42,20 @@ export default {
name: 'Auth',
components: { LDAP, CAS, AuthCommonConfig, OAUTH2, LoginModal },
data() {
const authList = [
return {
activeKey: 'LDAP',
dataTypeId: null,
loading: false,
enable_list: [],
}
},
mounted() {
this.changeActiveKey()
this.getAuthDataEnable()
},
computed: {
authList() {
return [
{
value: 'LDAP',
label: 'LDAP',
@ -61,21 +74,11 @@ export default {
},
{
value: 'AuthCommonConfig',
label: '通用',
label: this.$t('cs.auth.common'),
},
]
return {
authList,
activeKey: 'LDAP',
dataTypeId: null,
loading: false,
enable_list: [],
}
},
mounted() {
this.changeActiveKey()
this.getAuthDataEnable()
},
methods: {
getAuthDataEnable() {
getAuthDataEnable().then((res) => {
@ -105,7 +108,7 @@ export default {
this.loading = false
})
}
this.$message.success('保存成功')
this.$message.success(this.$t('saveSuccess'))
this.changeActiveKey()
this.getAuthDataEnable()
})
@ -128,7 +131,7 @@ export default {
}
testLDAP(type, { data: _data })
.then((res) => {
this.$message.success('测试成功')
this.$message.success(this.$t('cs.auth.testSuccess'))
})
.finally(() => {
this.loading = false

View File

@ -1,7 +1,7 @@
<template>
<a-form-model ref="form" :model="form" :label-col="labelCol" :wrapper-col="wrapperCol" :rules="rules">
<SpanTitle>基本</SpanTitle>
<a-form-model-item label="是否启用" prop="enable">
<SpanTitle>{{ $t('cs.auth.basic') }}</SpanTitle>
<a-form-model-item :label="$t('cs.auth.isEnable')" prop="enable">
<a-switch
:checked="Boolean(form.enable)"
@change="
@ -12,22 +12,22 @@
/>
</a-form-model-item>
<a-form-model-item
label="服务器地址"
:label="$t('cs.auth.ldap.serverAddress')"
prop="ldap_server"
help="例如: 192.168.1.6 或者 ldap://192.168.1.6 或者 ldap://192.168.1.6:389"
:help="$t('cs.auth.ldap.serverAddressHelp')"
>
<a-input v-model="form.ldap_server" placeholder="请输入服务器地址" />
<a-input v-model="form.ldap_server" :placeholder="$t('cs.auth.ldap.serverAddressPlaceholder')" />
</a-form-model-item>
<a-form-model-item label="" prop="ldap_domain">
<a-input v-model="form.ldap_domain" placeholder="请输入域" />
<a-form-model-item :label="$t('cs.auth.ldap.domain')" prop="ldap_domain">
<a-input v-model="form.ldap_domain" :placeholder="$t('cs.auth.ldap.domainPlaceholder')" />
</a-form-model-item>
<SpanTitle>用户</SpanTitle>
<SpanTitle>{{ $t('cs.auth.ldap.user') }}</SpanTitle>
<a-form-model-item
label="用户名称"
:label="$t('cs.auth.ldap.username')"
prop="ldap_user_dn"
help="用户dn: cn={},ou=users,dc=xxx,dc=com {}会替换成用户名"
:help="$t('cs.auth.ldap.userHelp')"
>
<a-input v-model="form.ldap_user_dn" placeholder="请输入用户名称" />
<a-input v-model="form.ldap_user_dn" :placeholder="$t('cs.auth.ldap.userPlaceholder')" />
</a-form-model-item>
</a-form-model>
</template>
@ -46,11 +46,15 @@ export default {
ldap_server: '',
ldap_domain: '',
ldap_user_dn: 'cn={},ou=users,dc=xxx,dc=com',
}
}
},
rules: {
computed: {
rules() {
return {
enable: [{ required: true }],
ldap_server: [{ required: true, message: '请输入服务器地址' }],
},
ldap_server: [{ required: true, message: this.$t('cs.auth.ldap.domainPlaceholder') }],
}
}
},
methods: {

View File

@ -1,23 +1,23 @@
<template>
<a-modal :visible="visible" @cancel="handleCancel" @ok="handleOK">
<a-form :form="form" :label-col="{ span: 5 }" :wrapper-col="{ span: 12 }">
<a-form-item label="用户名/邮箱">
<a-form-item :label="$t('cs.auth.usernameOrEmail')">
<a-input
v-decorator="[
'username',
{
rules: [{ required: true, message: '请输入用户名或邮箱' }],
rules: [{ required: true, message: $t('cs.auth.usernameOrEmailPlaceholder') }],
validateTrigger: 'change',
},
]"
>
</a-input>
</a-form-item>
<a-form-item label="密码">
<a-form-item :label="$t('cs.auth.password')">
<a-input
type="password"
autocomplete="false"
v-decorator="['password', { rules: [{ required: true, message: '请输入密码' }], validateTrigger: 'blur' }]"
v-decorator="['password', { rules: [{ required: true, message: $t('cs.auth.passwordPlaceholder') }], validateTrigger: 'blur' }]"
>
</a-input>
</a-form-item>
@ -25,8 +25,8 @@
</a-modal>
</template>
<script>
export default {
<script>
export default {
name: 'LoginModal',
data() {
return {
@ -50,7 +50,7 @@
})
},
},
}
</script>
}
</script>
<style></style>
<style></style>

View File

@ -1,7 +1,7 @@
<template>
<a-form-model ref="form" :model="form" :label-col="labelCol" :wrapper-col="wrapperCol" :rules="rules">
<SpanTitle>基本</SpanTitle>
<a-form-model-item label="是否启用" prop="enable">
<SpanTitle>{{ $t('cs.auth.basic') }}</SpanTitle>
<a-form-model-item :label="$t('cs.auth.isEnable')" prop="enable">
<a-switch
:checked="Boolean(form.enable)"
@change="
@ -11,20 +11,20 @@
"
/>
</a-form-model-item>
<a-form-model-item label="客户端ID" prop="client_id">
<a-input v-model="form.client_id" placeholder="请输入客户端ID" />
<a-form-model-item :label="$t('cs.auth.oauth2.clientId')" prop="client_id">
<a-input v-model="form.client_id" :placeholder="$t('cs.auth.oauth2.clientIdPlaceholder')" />
</a-form-model-item>
<a-form-model-item label="客户端密钥" prop="client_secret">
<a-input v-model="form.client_secret" placeholder="请输入客户端密钥" />
<a-form-model-item :label="$t('cs.auth.oauth2.clientSecret')" prop="client_secret">
<a-input v-model="form.client_secret" :placeholder="$t('cs.auth.oauth2.clientSecretPlaceholder')" />
</a-form-model-item>
<a-form-model-item label="授权链接" prop="authorize_url">
<a-input v-model="form.authorize_url" placeholder="请输入授权链接" />
<a-form-model-item :label="$t('cs.auth.oauth2.authorizeUrl')" prop="authorize_url">
<a-input v-model="form.authorize_url" :placeholder="$t('cs.auth.oauth2.authorizeUrlPlaceholder')" />
</a-form-model-item>
<a-form-model-item label="令牌链接" prop="token_url">
<a-input v-model="form.token_url" placeholder="请输入令牌链接" />
<a-form-model-item :label="$t('cs.auth.oauth2.tokenUrl')" prop="token_url">
<a-input v-model="form.token_url" :placeholder="$t('cs.auth.oauth2.tokenUrlPlaceholder')" />
</a-form-model-item>
<SpanTitle>其他</SpanTitle>
<a-form-model-item label="用户信息" prop="user_info" :wrapper-col="{ span: 15 }">
<a-form-model-item :label="$t('cs.auth.oauth2.userInfo')" prop="user_info" :wrapper-col="{ span: 15 }">
<vue-json-editor
:style="{ '--custom-height': `${200}px` }"
v-model="form.user_info"
@ -35,11 +35,11 @@
@has-error="onJsonError"
/>
</a-form-model-item>
<a-form-model-item label="范围" prop="scopes">
<a-select mode="tags" v-model="form.scopes" placeholder="请输入范围" />
<a-form-model-item :label="$t('cs.auth.oauth2.scopes')" prop="scopes">
<a-select mode="tags" v-model="form.scopes" :placeholder="$t('cs.auth.oauth2.scopesPlaceholder')" />
</a-form-model-item>
<a-form-model-item label="重定向路由" prop="after_login">
<a-input v-model="form.after_login" placeholder="请输入重定向路由" />
<a-form-model-item :label="$t('cs.auth.cas.afterLoginRoute')" prop="after_login">
<a-input v-model="form.after_login" :placeholder="$t('cs.auth.cas.afterLoginRoutePlaceholder')" />
</a-form-model-item>
</a-form-model>
</template>
@ -78,14 +78,18 @@ export default {
labelCol: { span: 3 },
wrapperCol: { span: 10 },
form: _.cloneDeep(defaultForm),
rules: {
enable: [{ required: true }],
client_id: [{ required: true, message: '请输入客户端ID' }],
client_secret: [{ required: true, message: '请输入客户端密钥' }],
},
isJsonRight: true,
}
},
computed: {
rules() {
return {
enable: [{ required: true }],
client_id: [{ required: true, message: this.$t('cs.auth.oauth2.clientIdPlaceholder') }],
client_secret: [{ required: true, message: this.$t('cs.auth.oauth2.clientSecretPlaceholder') }],
}
}
},
methods: {
setData(data) {
if (data) {

View File

@ -1,47 +1,47 @@
<template>
<div class="ops-setting-companyinfo" :style="{ height: `${windowHeight - 64}px` }">
<a-form-model ref="infoData" :model="infoData" :label-col="labelCol" :wrapper-col="wrapperCol" :rules="rule">
<SpanTitle>公司描述</SpanTitle>
<a-form-model-item label="名称" prop="name">
<a-input v-model="infoData.name" :disabled="!isEditable" />
<SpanTitle>{{ $t('cs.companyInfo.spanCompany') }}</SpanTitle>
<a-form-model-item :label="$t('cs.companyInfo.name')" prop="name">
<a-input v-model="infoData.name" :disabled="!isEditable"/>
</a-form-model-item>
<a-form-model-item label="描述">
<a-input v-model="infoData.description" type="textarea" :disabled="!isEditable" />
<a-form-model-item :label="$t('cs.companyInfo.description')">
<a-input v-model="infoData.description" type="textarea" :disabled="!isEditable"/>
</a-form-model-item>
<SpanTitle>公司地址</SpanTitle>
<a-form-model-item label="国家/地区">
<a-input v-model="infoData.country" :disabled="!isEditable" />
<SpanTitle>{{ $t('cs.companyInfo.spanAddress') }}</SpanTitle>
<a-form-model-item :label="$t('cs.companyInfo.country')">
<a-input v-model="infoData.country" :disabled="!isEditable"/>
</a-form-model-item>
<a-form-model-item label="城市">
<a-input v-model="infoData.city" :disabled="!isEditable" />
<a-form-model-item :label="$t('cs.companyInfo.city')">
<a-input v-model="infoData.city" :disabled="!isEditable"/>
</a-form-model-item>
<a-form-model-item label="地址">
<a-input v-model="infoData.address" :disabled="!isEditable" />
<a-form-model-item :label="$t('cs.companyInfo.address')">
<a-input v-model="infoData.address" :disabled="!isEditable"/>
</a-form-model-item>
<a-form-model-item label="邮编">
<a-input v-model="infoData.postCode" :disabled="!isEditable" />
<a-form-model-item :label="$t('cs.companyInfo.postcode')">
<a-input v-model="infoData.postCode" :disabled="!isEditable"/>
</a-form-model-item>
<SpanTitle>联系方式</SpanTitle>
<a-form-model-item label="网站">
<a-input v-model="infoData.website" :disabled="!isEditable" />
<SpanTitle>{{ $t('cs.companyInfo.spanContract') }}</SpanTitle>
<a-form-model-item :label="$t('cs.companyInfo.website')">
<a-input v-model="infoData.website" :disabled="!isEditable"/>
</a-form-model-item>
<a-form-model-item label="电话号码" prop="phone">
<a-input v-model="infoData.phone" :disabled="!isEditable" />
<a-form-model-item :label="$t('cs.companyInfo.phone')" prop="phone">
<a-input v-model="infoData.phone" :disabled="!isEditable"/>
</a-form-model-item>
<a-form-model-item label="传真号码" prop="faxCode">
<a-input v-model="infoData.faxCode" :disabled="!isEditable" />
<a-form-model-item :label="$t('cs.companyInfo.faxCode')" prop="faxCode">
<a-input v-model="infoData.faxCode" :disabled="!isEditable"/>
</a-form-model-item>
<a-form-model-item label="电子邮箱" prop="email">
<a-input v-model="infoData.email" :disabled="!isEditable" />
<a-form-model-item :label="$t('cs.companyInfo.email')" prop="email">
<a-input v-model="infoData.email" :disabled="!isEditable"/>
</a-form-model-item>
<SpanTitle>公司标识</SpanTitle>
<a-form-model-item label="Messenger地址" prop="messenger">
<a-input v-model="infoData.messenger" :disabled="!isEditable" />
<SpanTitle>{{ $t('cs.companyInfo.spanLogo') }}</SpanTitle>
<a-form-model-item :label="$t('cs.companyInfo.messenger')" prop="messenger">
<a-input v-model="infoData.messenger" :disabled="!isEditable"/>
</a-form-model-item>
<a-form-model-item label="部署域名" prop="domainName">
<a-input v-model="infoData.domainName" :disabled="!isEditable" />
<a-form-model-item :label="$t('cs.companyInfo.domainName')" prop="domainName">
<a-input v-model="infoData.domainName" :disabled="!isEditable"/>
</a-form-model-item>
<a-form-model-item label="公司logo">
<a-form-model-item :label="$t('cs.companyInfo.logo')">
<a-space>
<a-upload
:disabled="!isEditable"
@ -60,7 +60,7 @@
:style="{ width: '400px', height: '80px' }"
@click="eidtImageOption.type = 'Logo'"
>
<img :src="`/api/common-setting/v1/file/${infoData.logoName}`" alt="avatar" />
<img :src="`/api/common-setting/v1/file/${infoData.logoName}`" alt="avatar"/>
<a-icon
v-if="isEditable"
type="minus-circle"
@ -70,8 +70,8 @@
/>
</div>
<div v-else @click="eidtImageOption.type = 'Logo'">
<a-icon type="plus" />
<div class="ant-upload-text">上传</div>
<a-icon type="plus"/>
<div class="ant-upload-text">{{ $t('cs.companyInfo.upload') }}</div>
</div>
</a-upload>
@ -92,7 +92,7 @@
:style="{ width: '82px', height: '82px' }"
@click="eidtImageOption.type = 'SmallLogo'"
>
<img :src="`/api/common-setting/v1/file/${infoData.smallLogoName}`" alt="avatar" />
<img :src="`/api/common-setting/v1/file/${infoData.smallLogoName}`" alt="avatar"/>
<a-icon
v-if="isEditable"
type="minus-circle"
@ -102,15 +102,15 @@
/>
</div>
<div v-else @click="eidtImageOption.type = 'SmallLogo'">
<a-icon type="plus" />
<div class="ant-upload-text">上传</div>
<a-icon type="plus"/>
<div class="ant-upload-text">{{ $t('cs.companyInfo.upload') }}</div>
</div>
</a-upload>
</a-space>
</a-form-model-item>
<a-form-model-item :wrapper-col="{ span: 14, offset: 3 }" v-if="isEditable">
<a-button type="primary" @click="onSubmit"> 保存 </a-button>
<a-button ghost type="primary" style="margin-left: 28px" @click="resetForm"> 重置 </a-button>
<a-button type="primary" @click="onSubmit"> {{ $t('save') }}</a-button>
<a-button ghost type="primary" style="margin-left: 28px" @click="resetForm"> {{ $t('reset') }}</a-button>
</a-form-model-item>
</a-form-model>
<edit-image
@ -132,6 +132,7 @@ import { mapMutations, mapState } from 'vuex'
import SpanTitle from '../components/spanTitle.vue'
import EditImage from '../components/EditImage.vue'
import { mixinPermissions } from '@/utils/mixin'
export default {
name: 'CompanyInfo',
mixins: [mixinPermissions],
@ -156,48 +157,9 @@ export default {
messenger: '',
domainName: '',
},
rule: {
name: [{ required: true, whitespace: true, message: '请输入名称', trigger: 'blur' }],
phone: [
{
required: false,
whitespace: true,
pattern: new RegExp('^([0-9]|-)+$', 'g'),
message: '请输入正确的电话号码',
trigger: 'blur',
},
],
faxCode: [
{
required: false,
whitespace: true,
pattern: new RegExp('^([0-9]|-)+$', 'g'),
message: '请输入正确的传真号码',
trigger: 'blur',
},
],
email: [
{
required: false,
whitespace: true,
pattern: new RegExp('^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(.[a-zA-Z0-9-]+)*.[a-zA-Z0-9]{2,6}$', 'g'),
message: '请输入正确的邮箱地址',
trigger: 'blur',
},
],
},
getId: -1,
showEditImage: false,
editImage: null,
eidtImageOption: {
type: 'Logo',
fixedNumber: [15, 4],
title: '编辑企业logo',
previewWidth: '200px',
previewHeight: '40px',
autoCropWidth: 200,
autoCropHeight: 40,
},
editImage: null
}
},
async mounted() {
@ -216,6 +178,49 @@ export default {
isEditable() {
return this.hasDetailPermission('backend', '公司信息', ['update'])
},
rule() {
return {
name: [{ required: true, whitespace: true, message: this.$t('cs.companyInfo.nameValidate'), trigger: 'blur' }],
phone: [
{
required: false,
whitespace: true,
pattern: new RegExp('^([0-9]|-)+$', 'g'),
message: this.$t('cs.companyInfo.phoneValidate'),
trigger: 'blur',
},
],
faxCode: [
{
required: false,
whitespace: true,
pattern: new RegExp('^([0-9]|-)+$', 'g'),
message: this.$t('cs.companyInfo.faxCodeValidate'),
trigger: 'blur',
},
],
email: [
{
required: false,
whitespace: true,
pattern: new RegExp('^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(.[a-zA-Z0-9-]+)*.[a-zA-Z0-9]{2,6}$', 'g'),
message: this.$t('cs.companyInfo.emailValidate'),
trigger: 'blur',
},
],
}
},
eidtImageOption () {
return {
type: 'Logo',
fixedNumber: [15, 4],
title: this.$t('cs.companyInfo.editCompanyLogo'),
previewWidth: '200px',
previewHeight: '40px',
autoCropWidth: 200,
autoCropHeight: 40,
}
}
},
methods: {
...mapMutations(['SET_FILENAME', 'SET_SMALL_FILENAME']),
@ -235,9 +240,9 @@ export default {
}
this.SET_FILENAME(this.infoData.logoName)
this.SET_SMALL_FILENAME(this.infoData.smallFileName)
this.$message.success('保存成功')
this.$message.success(this.$t('saveSuccess'))
} else {
this.$message.warning('检查您的输入是否正确!')
this.$message.warning(this.$t('cs.companyInfo.checkInputCorrect'))
return false
}
})
@ -267,7 +272,7 @@ export default {
this.eidtImageOption = {
type: 'Logo',
fixedNumber: [20, 4],
title: '编辑企业logo',
title: this.$t('cs.companyInfo.editCompanyLogo'),
previewWidth: '200px',
previewHeight: '40px',
autoCropWidth: 200,
@ -277,14 +282,14 @@ export default {
this.eidtImageOption = {
type: 'SmallLogo',
fixedNumber: [4, 4],
title: '编辑企业logo缩略图',
title: this.$t('cs.companyInfo.editCompanyLogoSmall'),
previewWidth: '80px',
previewHeight: '80px',
autoCropWidth: 250,
autoCropHeight: 250,
}
}
reader.onload = function(e) {
reader.onload = function (e) {
let result
if (typeof e.target.result === 'object') {
// 把Array Buffer转化为blob 如果是base64不需要
@ -314,7 +319,7 @@ export default {
beforeUpload(file) {
const isLt2M = file.size / 1024 / 1024 < 2
if (!isLt2M) {
this.$message.error('图片大小不可超过2MB!')
this.$message.error(this.$t('cs.companyInfo.imageSizeLimit2MB'))
}
return isLt2M
},

View File

@ -10,54 +10,54 @@
>
<a-form-model v-if="visible && batchProps.type === 'department_id'">
<div :style="{ width: '420px', display: 'inline-block', margin: '0 7px' }">
<div :style="{ height: '40px', lineHeight: '40px' }">选择部门:</div>
<div :style="{ height: '40px', lineHeight: '40px' }">{{ $t('cs.companyStructure.selectDepartment') }}:</div>
<DepartmentTreeSelect v-model="batchForm.value"> </DepartmentTreeSelect>
</div>
</a-form-model>
<a-form-model v-else-if="batchProps.type === 'direct_supervisor_id'" ref="ruleForm">
<div :style="{ width: '420px', display: 'inline-block', margin: '0 7px' }">
<div :style="{ height: '40px', lineHeight: '40px' }">选择上级:</div>
<div :style="{ height: '40px', lineHeight: '40px' }">{{ $t('cs.companyStructure.selectDirectSupervisor') }}:</div>
<EmployeeTreeSelect v-model="batchForm.value" />
</div>
</a-form-model>
<a-form-model v-else-if="batchProps.type === 'position_name'">
<a-form-model-item label="编辑岗位">
<a-form-model-item :label="$t('cs.companyStructure.editPosition')">
<a-input v-model="batchForm.value" />
</a-form-model-item>
</a-form-model>
<a-form-model v-else-if="batchProps.type === 'annual_leave'">
<a-form-model-item label="编辑年假">
<a-form-model-item :label="$t('cs.companyStructure.editAnnualLeave')">
<a-input-number
:min="0"
:step="1"
:style="{ width: '100%' }"
v-model="batchForm.value"
placeholder="请输入年假"
:formatter="(value) => `${value} `"
:placeholder="$t('cs.companyStructure.annualLeavePlaceholder')"
:formatter="(value) => `${value} $t('cs.companyStructure.day')`"
/>
</a-form-model-item>
</a-form-model>
<a-form-model v-else-if="batchProps.type === 'password'" ref="batchForm" :model="batchForm" :rules="rules">
<a-form-model-item label="重置密码" prop="password">
<a-form-model-item :label="$t('cs.companyStructure.resetPassword')" prop="password">
<a-input-password v-model="batchForm.value" />
</a-form-model-item>
<a-form-model-item label="确认密码" prop="repeatPassword">
<a-form-model-item :label="$t('cs.companyStructure.confirmPassword')" prop="repeatPassword">
<a-input-password v-model="batchForm.confirmValue" />
</a-form-model-item>
</a-form-model>
<a-form-model v-else-if="batchProps.type === 'block' && batchProps.state === 1">
<a-icon type="info-circle" :style="{ color: '#FF9E58', fontSize: '16px', marginRight: '10px' }" />
<span v-if="batchProps.selectedRowKeys.length > 1">这些用户将会被禁用是否继续?</span>
<span v-else>该用户将会被禁用是否继续?</span>
<span v-if="batchProps.selectedRowKeys.length > 1">{{ $t('cs.companyStructure.batchBlockUserConfirm') }}</span>
<span v-else>{{ $t('cs.companyStructure.blockUserConfirm') }}</span>
</a-form-model>
<a-form-model v-else-if="batchProps.type === 'block' && batchProps.state === 0">
<a-icon type="info-circle" :style="{ color: '#FF9E58', fontSize: '16px', marginRight: '10px' }" />
<span v-if="batchProps.selectedRowKeys.length > 1">这些用户将会被恢复是否继续?</span>
<span v-else>该用户将会被恢复是否继续?</span>
<span v-if="batchProps.selectedRowKeys.length > 1">{{ $t('cs.companyStructure.batchRecoverUserConfirm') }}</span>
<span v-else>{{ $t('cs.companyStructure.recoverUserConfirm') }}</span>
</a-form-model>
<template slot="footer">
<a-button key="back" @click="close"> 取消 </a-button>
<a-button key="submit" type="primary" @click="batchModalHandleOk"> 确定 </a-button>
<a-button key="back" @click="close"> {{ $t('cancel') }} </a-button>
<a-button key="submit" type="primary" @click="batchModalHandleOk"> {{ $t('confirm') }} </a-button>
</template>
</a-modal>
</template>
@ -75,7 +75,7 @@ export default {
const validatePass = (rule, value, callback) => {
console.log(this.batchForm)
if (this.batchForm.value === '') {
callback(new Error('请输入密码'))
callback(new Error(this.$t('cs.companyStructure.password_placeholder')))
} else {
this.$refs.batchForm.validateField('repeatPassword')
callback()
@ -84,9 +84,9 @@ export default {
const validatePass2 = (rule, value, callback) => {
console.log(this.batchForm)
if (this.batchForm.confirmValue === '') {
callback(new Error('请输入密码'))
callback(new Error(this.$t('cs.companyStructure.passwordPlaceholder')))
} else if (this.batchForm.confirmValue !== this.batchForm.value) {
callback(new Error('两次密码不一致'))
callback(new Error(this.$t('cs.person.thePasswordEnteredTwiceIsInconsistent')))
} else {
callback()
}
@ -115,19 +115,19 @@ export default {
this.visible = true
this.batchProps = batchProps
const { type, selectedRowKeys, state } = batchProps
this.title = '批量编辑'
this.title = this.$t('cs.companyStructure.batchEdit')
if (type === 'department_id') {
this.batchForm.value = null
} else if (type === 'direct_supervisor_id') {
this.batchForm.value = undefined
} else if (type === 'password') {
if (selectedRowKeys.length <= 1) {
this.title = '重置密码'
this.title = this.$t('cs.companyStructure.resetPassword')
}
} else if (type === 'block') {
this.batchForm.value = state
if (selectedRowKeys.length <= 1) {
this.title = state ? '禁用' : '恢复'
this.title = state ? this.$t('cs.companyStructure.block') : this.$t('cs.companyStructure.recover')
}
}
},
@ -163,7 +163,7 @@ export default {
})
if (res.length) {
this.$notification.error({
message: '操作失败',
message: this.$t('cs.companyStructure.opFailed'),
description: res
.map((item) => `${getDirectorName(this.allFlatEmployees, item.employee_id)}${item.err}`)
.join('\n'),
@ -175,7 +175,7 @@ export default {
},
})
} else {
this.$message.success('操作成功')
this.$message.success(this.$t('cs.companyStructure.opSuccess'))
}
if (this.batchProps.type === 'department_id') {
Bus.$emit('clickSelectGroup', 1)

View File

@ -1,7 +1,7 @@
<template>
<a-modal
:visible="visible"
title="批量导入"
:title="$t('cs.companyStructure.batchImport')"
dialogClass="ops-modal setting-structure-upload"
:width="800"
@cancel="close"
@ -22,15 +22,17 @@
<a-upload :multiple="false" :customRequest="customRequest" accept=".xlsx" :showUploadList="false">
<a-button :style="{ marginBottom: '20px' }" type="primary"> <a-icon type="upload" />选择文件</a-button>
</a-upload>
<p><a @click="download">点击下载员工导入模板</a></p>
<p><a @click="download">{{ $t('cs.companyStructure.clickDownloadImportTemplate') }}</a></p>
</template>
<div
:style="{ height: '60px', display: 'flex', justifyContent: 'center', alignItems: 'center' }"
v-if="currentStep === 3"
>
导入总数据{{ allCount }}, 导入成功 <span :style="{ color: '#2362FB' }">{{ allCount - errorCount }}</span> ,
导入失败<span :style="{ color: '#D81E06' }">{{ errorCount }}</span
>
{{ $t('cs.companyStructure.importSuccess', {allCount: allCount}) }}<span :style="{ color: '#2362FB' }">{{ allCount - errorCount }}</span>
{{ $t('cs.companyStructure.count')}},
{{ $t('cs.companyStructure.importError') }}<span :style="{ color: '#D81E06' }">{{ errorCount }}</span
>{{ $t('cs.companyStructure.count')}}
</div>
<vxe-table
v-if="currentStep === 2 || has_error"
@ -45,46 +47,53 @@
:max-height="400"
:column-config="{ resizable: true }"
>
<vxe-column field="email" title="邮箱" min-width="120" fixed="left"></vxe-column>
<vxe-column field="username" title="用户名" min-width="80"></vxe-column>
<vxe-column field="nickname" title="姓名" min-width="80"></vxe-column>
<vxe-column field="password" title="密码" min-width="80"></vxe-column>
<vxe-column field="sex" title="性别" min-width="60"></vxe-column>
<vxe-column field="mobile" title="手机号" min-width="80"></vxe-column>
<vxe-column field="position_name" title="岗位" min-width="80"></vxe-column>
<vxe-column field="department_name" title="部门" min-width="80"></vxe-column>
<vxe-column field="entry_date" title="目前主体入职日期" min-width="120"></vxe-column>
<vxe-column field="is_internship" title="正式/实习生" min-width="120"></vxe-column>
<vxe-column field="leave_date" title="离职日期" min-width="120"></vxe-column>
<vxe-column field="id_card" title="身份证号码" min-width="120"></vxe-column>
<vxe-column field="nation" title="民族" min-width="80"></vxe-column>
<vxe-column field="id_place" title="籍贯" min-width="80"></vxe-column>
<vxe-column field="party" title="组织关系" min-width="80"></vxe-column>
<vxe-column field="household_registration_type" title="户籍类型" min-width="80"></vxe-column>
<vxe-column field="hometown" title="户口所在地" min-width="80"></vxe-column>
<vxe-column field="marry" title="婚姻情况" min-width="80"></vxe-column>
<vxe-column field="max_degree" title="最高学历" min-width="80"></vxe-column>
<vxe-column field="emergency_person" title="紧急联系人" min-width="120"></vxe-column>
<vxe-column field="emergency_phone" title="紧急联系电话" min-width="120"></vxe-column>
<vxe-column field="bank_card_number" title="卡号" min-width="120"></vxe-column>
<vxe-column field="bank_card_name" title="银行" min-width="80"></vxe-column>
<vxe-column field="opening_bank" title="开户行" min-width="80"></vxe-column>
<vxe-column field="account_opening_location" title="开户地" min-width="120"></vxe-column>
<vxe-column field="school" title="学校" min-width="80"></vxe-column>
<vxe-column field="major" title="专业" min-width="80"></vxe-column>
<vxe-column field="education" title="学历" min-width="80"></vxe-column>
<vxe-column field="graduation_year" title="毕业年份" min-width="120"></vxe-column>
<vxe-column v-if="has_error" field="err" title="失败原因" min-width="120" fixed="right">
<vxe-column field="email" :title="$t('cs.companyStructure.email')" min-width="120" fixed="left"></vxe-column>
<vxe-column field="username" :title="$t('cs.companyStructure.username')" min-width="80" ></vxe-column>
<vxe-column field="nickname" :title="$t('cs.companyStructure.nickname')" min-width="80"></vxe-column>
<vxe-column field="password" :title="$t('cs.companyStructure.password')" min-width="80"></vxe-column>
<vxe-column field="sex" :title="$t('cs.companyStructure.sex')" min-width="60"></vxe-column>
<vxe-column field="mobile" :title="$t('cs.companyStructure.mobile')" min-width="80"></vxe-column>
<vxe-column field="position_name" :title="$t('cs.companyStructure.positionName')" min-width="80"></vxe-column>
<vxe-column field="department_name" :title="$t('cs.companyStructure.departmentName')" min-width="80"></vxe-column>
<vxe-column field="current_company" v-if="useDFC" :title="$t('cs.companyStructure.currentCompany')" min-width="120"></vxe-column>
<vxe-column field="dfc_entry_date" v-if="useDFC" :title="$t('cs.companyStructure.dfcEntryDate')" min-width="120"></vxe-column>
<vxe-column field="entry_date" :title="$t('cs.companyStructure.entryDate')" min-width="120"></vxe-column>
<vxe-column field="is_internship" :title="$t('cs.companyStructure.isInternship')" min-width="120"></vxe-column>
<vxe-column field="leave_date" :title="$t('cs.companyStructure.leaveDate')" min-width="120"></vxe-column>
<vxe-column field="id_card" :title="$t('cs.companyStructure.idCard')" min-width="120"></vxe-column>
<vxe-column field="nation" :title="$t('cs.companyStructure.nation')" min-width="80"></vxe-column>
<vxe-column field="id_place" :title="$t('cs.companyStructure.idPlace')" min-width="80"></vxe-column>
<vxe-column field="party" :title="$t('cs.companyStructure.party')" min-width="80"></vxe-column>
<vxe-column field="household_registration_type" :title="$t('cs.companyStructure.householdRegistrationType')" min-width="80"></vxe-column>
<vxe-column field="hometown" :title="$t('cs.companyStructure.homewtown')" min-width="80"></vxe-column>
<vxe-column field="marry" :title="$t('cs.companyStructure.marry')" min-width="80"></vxe-column>
<vxe-column field="max_degree" :title="$t('cs.companyStructure.maxDegree')" min-width="80"></vxe-column>
<vxe-column field="emergency_person" :title="$t('cs.companyStructure.emergencyPerson')" min-width="120"></vxe-column>
<vxe-column field="emergency_phone" :title="$t('cs.companyStructure.emergencyPhone')" min-width="120"></vxe-column>
<vxe-column field="bank_card_number" :title="$t('cs.companyStructure.bankCardNumber')" min-width="120"></vxe-column>
<vxe-column field="bank_card_name" :title="$t('cs.companyStructure.bankCardName')" min-width="80"></vxe-column>
<vxe-column field="opening_bank" :title="$t('cs.companyStructure.openingBank')" min-width="80"></vxe-column>
<vxe-column field="account_opening_location" :title="$t('cs.companyStructure.accountOpeningLocation')" min-width="120"></vxe-column>
<vxe-column field="school" :title="$t('cs.companyStructure.school')" min-width="80"></vxe-column>
<vxe-column field="major" :title="$t('cs.companyStructure.major')" min-width="80"></vxe-column>
<vxe-column field="education" :title="$t('cs.companyStructure.education')" min-width="80"></vxe-column>
<vxe-column field="graduation_year" :title="$t('cs.companyStructure.graduationYear')" min-width="120"></vxe-column>
<vxe-column field="birth_date" :title="$t('cs.companyStructure.birthDate')" min-width="120"></vxe-column>
<vxe-column field="birth_place" :title="$t('cs.companyStructure.birthPlace')" min-width="120"></vxe-column>
<vxe-column field="nationality_region" :title="$t('cs.companyStructure.nationalityRegion')" min-width="120"></vxe-column>
<vxe-column field="first_entry_date" :title="$t('cs.companyStructure.firstEntryDate')" min-width="120"></vxe-column>
<vxe-column field="estimated_departure_date" :title="$t('cs.companyStructure.estimatedDepartureDate')" min-width="120"></vxe-column>
<vxe-column v-if="has_error" field="err" :title="$t('cs.companyStructure.importFailedReason')" min-width="120" fixed="right">
<template #default="{ row }">
<span :style="{ color: '#D81E06' }">{{ row.err }}</span>
</template>
</vxe-column>
</vxe-table>
<a-space slot="footer">
<a-button size="small" type="primary" ghost @click="close">取消</a-button>
<a-button v-if="currentStep !== 1" size="small" type="primary" ghost @click="goPre">上一步</a-button>
<a-button v-if="currentStep !== 3" size="small" type="primary" @click="goNext">下一步</a-button>
<a-button v-else size="small" type="primary" @click="close">完成</a-button>
<a-button size="small" type="primary" ghost @click="close">{{ $t('cancel') }}</a-button>
<a-button v-if="currentStep !== 1" size="small" type="primary" ghost @click="goPre">{{ $t('cs.companyStructure.prevStep') }}</a-button>
<a-button v-if="currentStep !== 3" size="small" type="primary" @click="goNext">{{ $t('cs.companyStructure.nextStep') }}</a-button>
<a-button v-else size="small" type="primary" @click="close">{{ $t('cs.companyStructure.done') }}</a-button>
</a-space>
</a-modal>
</template>
@ -98,17 +107,17 @@ export default {
const stepList = [
{
value: 1,
label: '上传文件',
label: this.$t('cs.companyStructure.uploadFile'),
icon: 'icon-shidi-tianjia',
},
{
value: 2,
label: '确认数据',
label: this.$t('cs.companyStructure.confirmData'),
icon: 'icon-shidi-yunshangchuan',
},
{
value: 3,
label: '上传完成',
label: this.$t('cs.companyStructure.uploadDone'),
icon: 'icon-shidi-queren',
},
]
@ -235,10 +244,10 @@ export default {
this.errorCount = errData.length
this.currentStep += 1
this.importData = errData
this.$message.error('数据存在错误')
this.$message.error(this.$t('cs.companyStructure.dataErr'))
} else {
this.currentStep += 1
this.$message.success('操作成功')
this.$message.success(this.$t('cs.companyStructure.opSuccess'))
}
this.$emit('refresh')
}

View File

@ -3,7 +3,7 @@
destroyOnClose
width="500px"
v-model="visible"
:title="type === 'add' ? '创建子部门' : '编辑部门'"
:title="type === 'add' ? $t('cs.companyStructure.createSubDepartment') : $t('cs.companyStructure.editDepartment')"
layout="inline"
@cancel="close"
>
@ -14,10 +14,10 @@
:label-col="labelCol"
:wrapper-col="wrapperCol"
>
<a-form-model-item ref="title" label="部门名称" prop="department_name">
<a-input v-model="departmentFormData.department_name" placeholder="请输入部门名称" />
<a-form-model-item ref="title" :label="$t('cs.companyStructure.departmentLabel')" prop="department_name">
<a-input v-model="departmentFormData.department_name" :placeholder="$t('cs.companyStructure.departmentLabelPlaceholder')" />
</a-form-model-item>
<a-form-model-item label="上级部门" prop="department_parent_id">
<a-form-model-item :label="$t('cs.companyStructure.parentDepartment')" prop="department_parent_id">
<DepartmentTreeSelect v-model="departmentFormData.department_parent_id" />
<!-- <Treeselect
v-else
@ -37,13 +37,13 @@
"
/> -->
</a-form-model-item>
<a-form-model-item label="部门负责人" prop="department_director_id">
<a-form-model-item :label="$t('cs.companyStructure.departmentDirector')" prop="department_director_id">
<EmployeeTreeSelect v-model="departmentFormData.department_director_id" />
</a-form-model-item>
</a-form-model>
<template slot="footer">
<a-button key="back" @click="close"> 取消 </a-button>
<a-button key="submit" type="primary" @click="departmentModalHandleOk"> 确定 </a-button>
<a-button key="back" @click="close"> {{ $t('cancel') }} </a-button>
<a-button key="submit" type="primary" @click="departmentModalHandleOk"> {{ $t('confirm') }} </a-button>
</template>
</a-modal>
</template>
@ -67,10 +67,6 @@ export default {
department_parent_id: '',
department_director_id: undefined,
},
rules: {
department_name: [{ required: true, message: '请输入部门名称' }],
department_parent_id: [{ required: true, message: '请选择上级部门' }],
},
currentDepartmentParentList: [],
selectDepartment: {},
type: 'add',
@ -81,6 +77,12 @@ export default {
allFlatEmployees() {
return this.provide_allFlatEmployees()
},
rules () {
return {
department_name: [{ required: true, message: this.$t('cs.companyStructure.departmentLabelPlaceholder') }],
department_parent_id: [{ required: true, message: this.$t('cs.companyStructure.parentDepartmentPlaceholder') }],
}
}
},
mounted() {},
methods: {
@ -129,7 +131,7 @@ export default {
} else if (this.type === 'add') {
await postDepartment(params)
}
this.$message.success('操作成功')
this.$message.success(this.$t('cs.companyStructure.opSuccess'))
this.$emit('refresh')
Bus.$emit('updateAllIncludeDepartment')
this.close()

View File

@ -10,349 +10,225 @@
:body-style="{ height: `${windowHeight - 320}px`, overflow: 'hidden', overflowY: 'scroll' }"
>
<a-form-model ref="employeeFormData" :model="employeeFormData" :rules="rules" :colon="false">
<a-form-model-item
ref="email"
label="邮箱"
prop="email"
:style="formModalItemStyle"
v-if="attributes.findIndex((v) => v == 'email') !== -1"
>
<a-input v-model="employeeFormData.email" placeholder="请输入邮箱" />
<a-form-model-item ref="email" :label="$t('cs.companyStructure.email')" prop="email" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='email')!==-1">
<a-input v-model="employeeFormData.email" :placeholder="$t('cs.companyStructure.emailPlaceholder')"/>
</a-form-model-item>
<a-form-model-item
ref="username"
label="用户名"
prop="username"
:style="formModalItemStyle"
v-if="attributes.findIndex((v) => v == 'username') !== -1"
>
<a-input v-model="employeeFormData.username" placeholder="请输入用户名" />
<a-form-model-item ref="username" :label="$t('cs.companyStructure.username')" prop="username" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='username')!==-1">
<a-input v-model="employeeFormData.username" :placeholder="$t('cs.companyStructure.usernamePlaceholder')" />
</a-form-model-item>
<a-form-model-item
v-if="type === 'add'"
ref="password"
label="登录密码"
:label="$t('cs.companyStructure.password')"
prop="password"
:style="formModalItemStyle"
>
<a-input-password v-model="employeeFormData.password" placeholder="请输入登录密码" />
<a-input-password v-model="employeeFormData.password" :placeholder="$t('cs.companyStructure.passwordPlaceholder')" />
</a-form-model-item>
<a-form-model-item
ref="nickname"
label="姓名"
prop="nickname"
:style="formModalItemStyle"
v-if="attributes.findIndex((v) => v == 'nickname') !== -1"
>
<a-input v-model="employeeFormData.nickname" placeholder="请输入姓名" />
<a-form-model-item ref="nickname" :label="$t('cs.companyStructure.nickname')" prop="nickname" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='nickname')!==-1">
<a-input v-model="employeeFormData.nickname" :placeholder="$t('cs.companyStructure.nicknamePlaceholder')" />
</a-form-model-item>
<a-form-model-item
label="性别"
prop="sex"
:style="formModalItemStyle"
v-if="attributes.findIndex((v) => v == 'sex') !== -1"
>
<a-select v-model="employeeFormData.sex" placeholder="请选择性别">
<a-select-option value=""> </a-select-option>
<a-select-option value=""> </a-select-option>
<a-form-model-item :label="$t('cs.companyStructure.sex')" prop="sex" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='sex')!==-1">
<a-select v-model="employeeFormData.sex" :placeholder="$t('cs.companyStructure.sexPlaceholder')">
<a-select-option value=""> {{ $t('cs.companyStructure.male') }} </a-select-option>
<a-select-option value=""> {{ $t('cs.companyStructure.female') }} </a-select-option>
</a-select>
</a-form-model-item>
<a-form-model-item
ref="mobile"
label="手机号"
prop="mobile"
:style="formModalItemStyle"
v-if="attributes.findIndex((v) => v == 'mobile') !== -1"
>
<a-input v-model="employeeFormData.mobile" placeholder="请输入手机号" />
<a-form-model-item ref="mobile" :label="$t('cs.companyStructure.mobile')" prop="mobile" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='mobile')!==-1">
<a-input v-model="employeeFormData.mobile" :placeholder="$t('cs.companyStructure.mobilePlaceholder')" />
</a-form-model-item>
<div
:style="{ width: '361px', display: 'inline-block', margin: '0 7px' }"
v-if="attributes.findIndex((v) => v == 'department_id') !== -1"
>
<div :style="{ height: '41px', lineHeight: '40px' }">部门</div>
<div :style="{ width: '361px', display: 'inline-block', margin: '0 7px' }" v-if="attributes.findIndex(v=>v=='department_id')!==-1">
<div :style="{ height: '41px', lineHeight: '40px' }">{{ $t('cs.companyStructure.departmentName') }}</div>
<DepartmentTreeSelect v-model="employeeFormData.department_id" />
</div>
<a-form-model-item
ref="position_name"
label="岗位"
prop="position_name"
:style="formModalItemStyle"
v-if="attributes.findIndex((v) => v == 'position_name') !== -1"
>
<a-input v-model="employeeFormData.position_name" placeholder="请输入岗位" />
<a-form-model-item ref="position_name" :label="$t('cs.companyStructure.positionName')" prop="position_name" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='position_name')!==-1">
<a-input v-model="employeeFormData.position_name" :placeholder="$t('cs.companyStructure.positionNamePlaceholder')" />
</a-form-model-item>
<div
:style="{ width: '361px', display: 'inline-block', margin: '0 7px' }"
v-if="attributes.findIndex((v) => v == 'direct_supervisor_id') !== -1"
>
<div :style="{ height: '41px', lineHeight: '40px' }">上级</div>
<div :style="{ width: '361px', display: 'inline-block', margin: '0 7px' }" v-if="attributes.findIndex(v=>v=='direct_supervisor_id')!==-1">
<div :style="{ height: '41px', lineHeight: '40px' }">{{ $t('cs.companyStructure.selectDirectSupervisor') }}</div>
<EmployeeTreeSelect v-model="employeeFormData.direct_supervisor_id" />
</div>
<a-form-model-item
ref="annual_leave"
label="年假"
prop="annual_leave"
:style="formModalItemStyle"
v-if="attributes.findIndex((v) => v == 'annual_leave') !== -1"
>
<!-- <a-form-model-item :label="角色" prop="role" :style="formModalItemStyle">
<a-select mode="multiple" v-model="employeeFormData.role" :placeholder="请选择角色">
<a-select-option value="PM"> PM </a-select-option>
<a-select-option value="Test"> Test </a-select-option>
<a-select-option value="Tevelop"> Develop </a-select-option>
</a-select>
</a-form-model-item> -->
<a-form-model-item ref="annual_leave" :label="$t('cs.companyStructure.annualLeave')" prop="annual_leave" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='annual_leave')!==-1">
<a-input-number
:min="0"
:step="1"
:style="{ width: '100%' }"
v-model="employeeFormData.annual_leave"
placeholder="请输入年假"
:formatter="(value) => `${value} `"
:placeholder="$t('cs.companyStructure.annualLeavePlaceholder')"
:formatter="(value) => `${value} $t('cs.companyStructure.day')`"
/>
</a-form-model-item>
<a-form-model-item
ref="virtual_annual_leave"
label="虚拟年假"
prop="virtual_annual_leave"
:style="formModalItemStyle"
v-if="attributes.findIndex((v) => v == 'virtual_annual_leave') !== -1"
>
<a-form-model-item ref="virtual_annual_leave" :label="$t('cs.companyStructure.virtualAnnualLeave')" prop="virtual_annual_leave" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='virtual_annual_leave')!==-1">
<a-input-number
:min="0"
:step="1"
:style="{ width: '100%' }"
v-model="employeeFormData.virtual_annual_leave"
placeholder="请输入虚拟年假"
:formatter="(value) => `${value} `"
:placeholder="$t('cs.companyStructure.virtualAnnualLeavePlaceholder')"
:formatter="(value) => `${value} $t('cs.companyStructure.day')`"
/>
</a-form-model-item>
<a-form-model-item
ref="parenting_leave"
label="育儿假"
prop="parenting_leave"
:style="formModalItemStyle"
v-if="attributes.findIndex((v) => v == 'parenting_leave') !== -1"
>
<a-form-model-item ref="parenting_leave" :label="$t('cs.companyStructure.parentingLeave')" prop="parenting_leave" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='parenting_leave')!==-1">
<a-input-number
:min="0"
:step="1"
:style="{ width: '100%' }"
v-model="employeeFormData.parenting_leave"
placeholder="请输入育儿假"
:formatter="(value) => `${value} `"
:placeholder="$t('cs.companyStructure.parentingLeavePlaceholder')"
:formatter="(value) => `${value} $t('cs.companyStructure.day')`"
/>
</a-form-model-item>
<a-form-model-item
ref="entry_date"
label="目前主体入职日期"
prop="entry_date"
:style="formModalItemStyle"
v-if="attributes.findIndex((v) => v == 'entry_date') !== -1"
>
<a-date-picker
placeholder="请选择目前主体入职日期"
v-model="employeeFormData.entry_date"
:style="{ width: '100%' }"
@change="onChange($event, 'entry_date')"
></a-date-picker>
<a-form-model-item v-if="attributes.findIndex(v=>v=='current_company')!==-1" ref="current_company" :label="$t('cs.companyStructure.currentCompany')" prop="current_company" :style="formModalItemStyle">
<a-input v-model="employeeFormData.current_company" :placeholder="$t('cs.companyStructure.currentCompanyPlaceholder')" />
</a-form-model-item>
<a-form-model-item
ref="is_internship"
label="正式/实习生"
prop="is_internship"
:style="formModalItemStyle"
v-if="attributes.findIndex((v) => v == 'is_internship') !== -1"
>
<a-select v-model="employeeFormData.is_internship" placeholder="请选择是否正式/实习生">
<a-select-option :value="0"> 正式 </a-select-option>
<a-select-option :value="1"> 实习生 </a-select-option>
<a-form-model-item v-if="attributes.findIndex(v=>v=='dfc_entry_date')!==-1" ref="dfc_entry_date" :label="$t('cs.companyStructure.dfcEntryDate')" prop="dfc_entry_date" :style="formModalItemStyle">
<a-date-picker :placeholder="$t('cs.companyStructure.dfcEntryDatePlaceholder')" v-model="employeeFormData.dfc_entry_date" :style="{ width: '100%'}" @change="onChange($event, 'dfc_entry_date')"></a-date-picker>
</a-form-model-item>
<a-form-model-item ref="entry_date" :label="$t('cs.companyStructure.entryDate')" prop="entry_date" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='entry_date')!==-1">
<a-date-picker :placeholder="$t('cs.companyStructure.entryDatePlaceholder')" v-model="employeeFormData.entry_date" :style="{ width: '100%'}" @change="onChange($event, 'entry_date')"></a-date-picker>
</a-form-model-item>
<a-form-model-item ref="is_internship" :label="$t('cs.companyStructure.isInternship')" prop="is_internship" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='is_internship')!==-1">
<a-select v-model="employeeFormData.is_internship" :placeholder="$t('cs.companyStructure.isInternshipPlaceholder')">
<a-select-option :value="0"> {{ $t('cs.companyStructure.fullTime') }} </a-select-option>
<a-select-option :value="1"> {{ $t('cs.companyStructure.internship') }} </a-select-option>
</a-select>
</a-form-model-item>
<a-form-model-item
ref="leave_date"
label="离职日期"
prop="leave_date"
:style="formModalItemStyle"
v-if="attributes.findIndex((v) => v == 'leave_date') !== -1"
>
<a-date-picker
v-model="employeeFormData.leave_date"
placeholder="请选择离职日期"
:style="{ width: '100%' }"
@change="onChange($event, 'leave_date')"
></a-date-picker>
<a-form-model-item ref="leave_date" :label="$t('cs.companyStructure.leaveDate')" prop="leave_date" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='leave_date')!==-1">
<a-date-picker v-model="employeeFormData.leave_date" :placeholder="$t('cs.companyStructure.leaveDatePlaceholder')" :style="{ width: '100%'}" @change="onChange($event, 'leave_date')"></a-date-picker>
</a-form-model-item>
<a-form-model-item
ref="id_card"
label="身份证号码"
prop="id_card"
:style="formModalItemStyle"
v-if="attributes.findIndex((v) => v == 'id_card') !== -1"
>
<a-input v-model="employeeFormData.id_card" placeholder="请输入身份证号码" />
<a-form-model-item ref="id_card" :label="$t('cs.companyStructure.idCard')" prop="id_card" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='id_card')!==-1">
<a-input v-model="employeeFormData.id_card" :placeholder="$t('cs.companyStructure.idCardPlaceholder')" />
</a-form-model-item>
<a-form-model-item
ref="nation"
label="民族"
prop="nation"
:style="formModalItemStyle"
v-if="attributes.findIndex((v) => v == 'nation') !== -1"
>
<a-input v-model="employeeFormData.nation" placeholder="请输入民族" />
<a-form-model-item ref="nation" :label="$t('cs.companyStructure.nation')" prop="nation" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='nation')!==-1">
<a-input v-model="employeeFormData.nation" :placeholder="$t('cs.companyStructure.nationPlaceholder')" />
</a-form-model-item>
<a-form-model-item
ref="id_place"
label="籍贯"
prop="id_place"
:style="formModalItemStyle"
v-if="attributes.findIndex((v) => v == 'id_place') !== -1"
>
<a-input v-model="employeeFormData.id_place" placeholder="请输入籍贯" />
<a-form-model-item ref="id_place" :label="$t('cs.companyStructure.idPlace')" prop="id_place" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='id_place')!==-1">
<a-input v-model="employeeFormData.id_place" :placeholder="$t('cs.companyStructure.idPlacePlaceholder')" />
</a-form-model-item>
<a-form-model-item
ref="party"
label="组织关系"
prop="party"
:style="formModalItemStyle"
v-if="attributes.findIndex((v) => v == 'party') !== -1"
>
<a-select v-model="employeeFormData.party" placeholder="请选择组织关系">
<a-select-option value="党员"> 党员 </a-select-option>
<a-select-option value="团员"> 团员 </a-select-option>
<a-select-option value="群众"> 群众 </a-select-option>
<a-form-model-item ref="party" :label="$t('cs.companyStructure.party')" prop="party" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='party')!==-1">
<a-select v-model="employeeFormData.party" :placeholder="$t('cs.companyStructure.')">
<a-select-option value="党员"> {{ $t('cs.companyStructure.partyMember') }} </a-select-option>
<a-select-option value="团员"> {{ $t('cs.companyStructure.member') }} </a-select-option>
<a-select-option value="群众"> {{ $t('cs.companyStructure.masses') }} </a-select-option>
</a-select>
</a-form-model-item>
<a-form-model-item
ref="household_registration_type"
label="户籍类型"
prop="household_registration_type"
:style="formModalItemStyle"
v-if="attributes.findIndex((v) => v == 'household_registration_type') !== -1"
>
<a-select v-model="employeeFormData.household_registration_type" placeholder="请选择户籍类型">
<a-select-option value="城镇"> 城镇 </a-select-option>
<a-select-option value="农业"> 农业 </a-select-option>
<a-form-model-item ref="household_registration_type" :label="$t('cs.companyStructure.householdRegistrationType')" prop="household_registration_type" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='household_registration_type')!==-1">
<a-select v-model="employeeFormData.household_registration_type" :placeholder="$t('cs.companyStructure.')">
<a-select-option value="城镇"> {{ $t('cs.companyStructure.town') }} </a-select-option>
<a-select-option value="农业"> {{ $t('cs.companyStructure.agriculture') }} </a-select-option>
</a-select>
</a-form-model-item>
<a-form-model-item
ref="hometown"
label="户口所在地"
prop="hometown"
:style="formModalItemStyle"
v-if="attributes.findIndex((v) => v == 'hometown') !== -1"
>
<a-input v-model="employeeFormData.hometown" placeholder="请输入户口所在地" />
<a-form-model-item ref="hometown" :label="$t('cs.companyStructure.hometown')" prop="hometown" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='hometown')!==-1">
<a-input v-model="employeeFormData.hometown" :placeholder="$t('cs.companyStructure.hometownPlaceholder')" />
</a-form-model-item>
<a-form-model-item
ref="marry"
label="婚姻情况"
prop="marry"
:style="formModalItemStyle"
v-if="attributes.findIndex((v) => v == 'marry') !== -1"
>
<a-select v-model="employeeFormData.marry" placeholder="请选择婚姻情况">
<a-select-option value="未婚"> 未婚 </a-select-option>
<a-select-option value="已婚"> 已婚 </a-select-option>
<a-form-model-item ref="marry" :label="$t('cs.companyStructure.marry')" prop="marry" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='marry')!==-1">
<a-select v-model="employeeFormData.marry" :placeholder="$t('cs.companyStructure.')">
<a-select-option value="未婚"> {{ $t('cs.companyStructure.unmarried') }}</a-select-option>
<a-select-option value="已婚"> {{ $t('cs.companyStructure.married') }} </a-select-option>
</a-select>
</a-form-model-item>
<a-form-model-item
ref="max_degree"
label="最高学历"
prop="max_degree"
:style="formModalItemStyle"
v-if="attributes.findIndex((v) => v == 'max_degree') !== -1"
>
<a-select v-model="employeeFormData.max_degree" placeholder="请选择最高学历">
<a-select-option value="博士"> 博士 </a-select-option>
<a-select-option value="硕士"> 硕士 </a-select-option>
<a-select-option value="本科"> 本科 </a-select-option>
<a-select-option value="专科"> 专科 </a-select-option>
<a-select-option value="高中"> 高中 </a-select-option>
<a-form-model-item ref="max_degree" :label="$t('cs.companyStructure.maxDegree')" prop="max_degree" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='max_degree')!==-1">
<a-select v-model="employeeFormData.max_degree" :placeholder="$t('cs.companyStructure.maxDegreePlaceholder')">
<a-select-option value="博士"> {{ $t('cs.companyStructure.phd') }} </a-select-option>
<a-select-option value="硕士"> {{ $t('cs.companyStructure.master') }} </a-select-option>
<a-select-option value="本科"> {{ $t('cs.companyStructure.undergraduate') }} </a-select-option>
<a-select-option value="专科"> {{ $t('cs.companyStructure.specialist') }} </a-select-option>
<a-select-option value="高中"> {{ $t('cs.companyStructure.highSchool') }} </a-select-option>
</a-select>
</a-form-model-item>
<a-form-model-item
ref="emergency_person"
label="紧急联系人"
prop="emergency_person"
:style="formModalItemStyle"
v-if="attributes.findIndex((v) => v == 'emergency_person') !== -1"
>
<a-input v-model="employeeFormData.emergency_person" placeholder="请输入紧急联系人" />
<a-form-model-item ref="emergency_person" :label="$t('cs.companyStructure.emergencyPerson')" prop="emergency_person" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='emergency_person')!==-1">
<a-input v-model="employeeFormData.emergency_person" :placeholder="$t('cs.companyStructure.emergencyPersonPlaceholder')" />
</a-form-model-item>
<a-form-model-item
ref="emergency_phone"
label="紧急联系电话"
prop="emergency_phone"
:style="formModalItemStyle"
v-if="attributes.findIndex((v) => v == 'emergency_phone') !== -1"
>
<a-input v-model="employeeFormData.emergency_phone" placeholder="请输入紧急联系电话" />
<a-form-model-item ref="emergency_phone" :label="$t('cs.companyStructure.emergencyPhone')" prop="emergency_phone" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='emergency_phone')!==-1">
<a-input v-model="employeeFormData.emergency_phone" :placeholder="$t('cs.companyStructure.emergencyPhonePlaceholder')" />
</a-form-model-item>
<a-form-model-item
label="教育经历"
prop="employeeFormData"
:style="{ display: 'inline-block', width: '100%', margin: '0 7px' }"
v-if="attributes.findIndex((v) => v == 'educational_experience') !== -1"
<a-form-model-item ref="birth_date" :label="$t('cs.companyStructure.birthDate')" prop="birth_date" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='birth_date')!==-1">
<a-date-picker v-model="employeeFormData.birth_date" :placeholder="$t('cs.companyStructure.birthDatePlaceholder')" :style="{ width: '100%'}" @change="onChange($event, 'birth_date')"></a-date-picker>
</a-form-model-item>
<a-form-model-item ref="birth_place" :label="$t('cs.companyStructure.birthPlace')" prop="birth_place" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='birth_place')!==-1">
<a-input v-model="employeeFormData.birth_place" :placeholder="$t('cs.companyStructure.birthPlacePlaceholder')" />
</a-form-model-item>
<a-form-model-item ref="nationality_region" :label="$t('cs.companyStructure.nationalityRegion')" prop="nationality_region" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='nationality_region')!==-1">
<a-input v-model="employeeFormData.nationality_region" :placeholder="$t('cs.companyStructure.nationalityRegionPlaceholder')" />
</a-form-model-item>
<a-form-model-item ref="first_entry_date" :label="$t('cs.companyStructure.firstEntryDate')" prop="first_entry_date" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='first_entry_date')!==-1">
<a-date-picker v-model="employeeFormData.first_entry_date" :placeholder="$t('cs.companyStructure.firstEntryDatePlaceholder')" :style="{ width: '100%'}" @change="onChange($event, 'first_entry_date')"></a-date-picker>
</a-form-model-item>
<a-form-model-item ref="estimated_departure_date" :label="$t('cs.companyStructure.estimatedDepartureDate')" prop="estimated_departure_date" :style="formModalItemStyle" v-if="attributes.findIndex(v=>v=='estimated_departure_date')!==-1">
<a-date-picker v-model="employeeFormData.estimated_departure_date" :placeholder="$t('cs.companyStructure.estimatedDepartureDatePlaceholder')" :style="{ width: '100%'}" @change="onChange($event, 'estimated_departure_date')"></a-date-picker>
</a-form-model-item>
<a-form-model-item :label="$t('cs.companyStructure.educationalExperience')" prop="employeeFormData" :style="{ display: 'inline-block', width: '100%', margin: '0 7px'}" v-if="attributes.findIndex(v=>v=='educational_experience')!==-1">
<a-row
:gutter="[8,{xs:8}]"
v-for="(item) in educational_experience"
:key="item.id"
>
<a-row :gutter="[8, { xs: 8 }]" v-for="item in educational_experience" :key="item.id">
<a-col :span="5">
<a-input v-model="item.school" placeholder="学校" allowClear></a-input>
<a-input v-model="item.school" :placeholder="$t('cs.companyStructure.school')" allowClear></a-input>
</a-col>
<a-col :span="5">
<a-input v-model="item.major" placeholder="专业" allowClear></a-input>
<a-input v-model="item.major" :placeholder="$t('cs.companyStructure.major')" allowClear></a-input>
</a-col>
<a-col :span="5">
<a-select v-model="item.education" placeholder="学历" allowClear>
<a-select-option value="小学"> 小学 </a-select-option>
<a-select-option value="初中"> 初中 </a-select-option>
<a-select-option value="中专/高中"> 中专/高中 </a-select-option>
<a-select-option value="专科"> 专科 </a-select-option>
<a-select-option value="本科"> 本科 </a-select-option>
<a-select-option value="硕士"> 硕士 </a-select-option>
<a-select-option value="博士"> 博士 </a-select-option>
<a-select v-model="item.education" :placeholder="$t('cs.companyStructure.education')" allowClear>
<a-select-option value="小学"> {{ $t('cs.companyStructure.primarySchool') }} </a-select-option>
<a-select-option value="初中"> {{ $t('cs.companyStructure.juniorHighSchool') }} </a-select-option>
<a-select-option value="中专/高中"> {{ $t('cs.companyStructure.technicalSecondaryOrHighSchool') }} </a-select-option>
<a-select-option value="专科"> {{ $t('cs.companyStructure.specialist') }} </a-select-option>
<a-select-option value="本科"> {{ $t('cs.companyStructure.undergraduate') }} </a-select-option>
<a-select-option value="硕士"> {{ $t('cs.companyStructure.master') }} </a-select-option>
<a-select-option value="博士"> {{ $t('cs.companyStructure.phd') }} </a-select-option>
</a-select>
</a-col>
<a-col :span="5">
<a-month-picker
v-model="item.graduation_year"
placeholder="毕业年份"
@change="onChange($event, 'graduation_year', item.id)"
></a-month-picker>
<a-month-picker v-model="item.graduation_year" :placeholder="$t('cs.companyStructure.graduationYearPlaceholder')" @change="onChange($event, 'graduation_year',item.id)" ></a-month-picker>
</a-col>
<a-col :span="1">
<a @click="addEducation">
<a
@click="addEducation"
>
<a-icon type="plus-circle" />
</a>
</a-col>
<a-col :span="1" v-if="educational_experience.length > 1">
<a @click="() => removeEducation(item.id)" :style="{ color: 'red' }">
<a
@click="() => removeEducation(item.id)"
:style="{ color: 'red' }"
>
<a-icon type="delete" />
</a>
</a-col>
</a-row>
</a-form-model-item>
<a-form-model-item
label="子女信息"
prop="employeeFormData"
:style="{ display: 'inline-block', width: '100%', margin: '0 7px' }"
v-if="attributes.findIndex((v) => v == 'children_information') !== -1"
>
<a-form-model-item :label="$t('cs.companyStructure.childrenInformation')" prop="employeeFormData" :style="{ display: 'inline-block', width: '100%', margin: '0 7px'}" v-if="attributes.findIndex(v=>v=='children_information')!==-1">
<!-- <a-space
v-for="(item,index) in educational_experience"
:key="index"
align="baseline"
> -->
<a-row :gutter="[8, { xs: 8 }]" v-for="item in children_information" :key="item.id">
<a-row
:gutter="[8,{xs:8}]"
v-for="(item) in children_information"
:key="item.id"
>
<a-col :span="5">
<a-input v-model="item.name" placeholder="姓名" allowClear></a-input>
<a-input v-model="item.name" :placeholder="$t('cs.companyStructure.childrenName')" allowClear></a-input>
</a-col>
<a-col :span="5">
<a-select v-model="item.gender" placeholder="请选择性别" allowClear>
<a-select-option value=""> </a-select-option>
<a-select-option value=""> </a-select-option>
<a-select v-model="item.gender" :placeholder="$t('cs.companyStructure.sex')" allowClear>
<a-select-option value=""> {{ $t('cs.companyStructure.male') }} </a-select-option>
<a-select-option value=""> {{ $t('cs.companyStructure.female') }} </a-select-option>
</a-select>
</a-col>
<a-col :span="5">
<a-date-picker
v-model="item.birthday"
placeholder="出生日期"
@change="onChange($event, 'birth_date', item.id)"
></a-date-picker>
<a-date-picker v-model="item.birthday" :placeholder="$t('cs.companyStructure.birthDatePlaceholder')" @change="onChange($event, 'birthday',item.id)"></a-date-picker>
</a-col>
<a-col :span="5">
<a-input-number
@ -360,52 +236,52 @@
:step="1"
:style="{ width: '100%' }"
v-model="item.parental_leave_left"
placeholder="请输入剩余育儿假"
:formatter="(value) => `${value} `"
:placeholder="$t('cs.companyStructure.')"
:formatter="(value) => `${value} $t('cs.companyStructure.day')`"
/>
</a-col>
<a-col :span="1">
<a @click="addChildren">
<a
@click="addChildren"
>
<a-icon type="plus-circle" />
</a>
</a-col>
<a-col :span="1" v-if="children_information.length > 1">
<a @click="() => removeChildren(item.id)" :style="{ color: 'red' }">
<a
@click="() => removeChildren(item.id)"
:style="{ color: 'red' }"
>
<a-icon type="delete" />
</a>
</a-col>
</a-row>
</a-form-model-item>
<a-form-model-item
label="银行卡"
:label="$t('cs.companyStructure.bankCardInfo')"
prop="bank_card"
:style="{ display: 'inline-block', width: '98%', margin: '0 7px 24px' }"
v-if="
attributes.findIndex((v) => v == 'bank_card_number') !== -1 ||
attributes.findIndex((v) => v == 'bank_card_name') !== -1 ||
attributes.findIndex((v) => v == 'opening_bank') !== -1 ||
attributes.findIndex((v) => v == 'account_opening_location') !== -1
"
:style="{display: 'inline-block', width: '98%', margin: '0 7px 24px'}"
v-if="attributes.findIndex(v=>v=='bank_card_number')!==-1 || attributes.findIndex(v=>v=='bank_card_name')!==-1 || attributes.findIndex(v=>v=='opening_bank')!==-1 || attributes.findIndex(v=>v=='account_opening_location')!==-1"
>
<a-row :gutter="[8, { xs: 8 }]">
<a-col :span="6" v-if="attributes.findIndex((v) => v == 'bank_card_number') !== -1">
<a-input v-model="employeeFormData.bank_card_number" placeholder="卡号" allowClear></a-input>
<a-row :gutter="[8,{xs:8}]">
<a-col :span="6" v-if="attributes.findIndex(v=>v=='bank_card_number')!==-1">
<a-input v-model="employeeFormData.bank_card_number" :placeholder="$t('cs.companyStructure.bankCardNumberPlaceholder')" allowClear></a-input>
</a-col>
<a-col :span="6" v-if="attributes.findIndex((v) => v == 'bank_card_name') !== -1">
<a-input v-model="employeeFormData.bank_card_name" placeholder="银行" allowClear></a-input>
<a-col :span="6" v-if="attributes.findIndex(v=>v=='bank_card_name')!==-1">
<a-input v-model="employeeFormData.bank_card_name" :placeholder="$t('cs.companyStructure.bankCardNamePlaceholder')" allowClear></a-input>
</a-col>
<a-col :span="6" v-if="attributes.findIndex((v) => v == 'opening_bank') !== -1">
<a-input v-model="employeeFormData.opening_bank" placeholder="开户行" allowClear></a-input>
<a-col :span="6" v-if="attributes.findIndex(v=>v=='opening_bank')!==-1">
<a-input v-model="employeeFormData.opening_bank" :placeholder="$t('cs.companyStructure.openingBankPlaceholder')" allowClear></a-input>
</a-col>
<a-col :span="6" v-if="attributes.findIndex((v) => v == 'account_opening_location') !== -1">
<a-input v-model="employeeFormData.account_opening_location" placeholder="开户地" allowClear></a-input>
<a-col :span="6" v-if="attributes.findIndex(v=>v=='account_opening_location')!==-1">
<a-input v-model="employeeFormData.account_opening_location" :placeholder="$t('cs.companyStructure.accountOpeningLocationPlaceholder')" allowClear></a-input>
</a-col>
</a-row>
</a-form-model-item>
</a-form-model>
<template slot="footer">
<a-button key="back" @click="close"> 取消 </a-button>
<a-button type="primary" @click="employeeModalHandleOk"> 确定 </a-button>
<a-button key="back" @click="close"> {{ $t('cancel') }} </a-button>
<a-button type="primary" @click="employeeModalHandleOk"> {{ $t('confirm') }} </a-button>
</template>
</a-modal>
</template>
@ -425,38 +301,11 @@ export default {
visible: false,
employeeFormData: {},
formModalItemStyle: { display: 'inline-block', width: '48%', margin: '0 7px 24px', overflow: 'hidden' },
rules: {
email: [
{ required: true, whitespace: true, message: '请输入邮箱', trigger: 'blur' },
{
pattern: /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/,
message: '邮箱格式错误',
trigger: 'blur',
},
{ max: 50, message: '字符数须小于50' },
],
username: [
{ required: true, whitespace: true, message: '请输入用户名', trigger: 'blur' },
{ max: 20, message: '字符数须小于20' },
],
password: [{ required: true, whitespace: true, message: '请输入密码', trigger: 'blur' }],
nickname: [
{ required: true, whitespace: true, message: '请输入姓名', trigger: 'blur' },
{ max: 20, message: '字符数须小于20' },
],
mobile: [
{
pattern: /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
message: '请输入正确的手机号',
trigger: 'blur',
},
],
},
type: 'add',
educational_experience: [],
children_information: [],
file_is_show: true,
attributes: [],
attributes: []
}
},
created() {
@ -477,10 +326,39 @@ export default {
},
title() {
if (this.type === 'add') {
return '新建员工'
return this.$t('cs.companyStructure.createEmployee')
}
return '编辑员工'
return this.$t('cs.companyStructure.editEmployee')
},
rules() {
return {
email: [
{ required: true, whitespace: true, message: this.$t('cs.companyStructure.emailPlaceholder'), trigger: 'blur' },
{
pattern: /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/,
message: this.$t('cs.companyStructure.emailFormatErr'),
trigger: 'blur',
},
{ max: 50, message: this.$t('cs.person.inputStrCountLimit', { limit: 50 }) },
],
username: [
{ required: true, whitespace: true, message: '请输入用户名', trigger: 'blur' },
{ max: 20, message: this.$t('cs.person.inputStrCountLimit', { limit: 20 }) },
],
password: [{ required: true, whitespace: true, message: '请输入密码', trigger: 'blur' }],
nickname: [
{ required: true, whitespace: true, message: '请输入姓名', trigger: 'blur' },
{ max: 20, message: this.$t('cs.person.inputStrCountLimit', { limit: 20 }) },
],
mobile: [
{
pattern: /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
message: this.$t('cs.companyStructure.mobileFormatErr'),
trigger: 'blur',
},
],
}
}
},
beforeDestroy() {
Bus.$off('getAttributes')
@ -488,8 +366,7 @@ export default {
methods: {
async open(getData, type) {
// 提交时去掉school, major, education, graduation_year, name, gender, birthday, parental_leave_left
const { school, major, education, graduation_year, name, gender, birthday, parental_leave_left, ...newGetData } =
getData
const { school, major, education, graduation_year, name, gender, birthday, parental_leave_left, ...newGetData } = getData
const _getData = _.cloneDeep(newGetData)
const { direct_supervisor_id } = newGetData
if (direct_supervisor_id) {
@ -502,54 +379,46 @@ export default {
// if (type !== 'add' && this.employeeFormData.educational_experience.length !== 0) {
// this.educational_experience = this.employeeFormData.educational_experience
// }
this.children_information = this.formatChildrenInformationList() || [
{
this.children_information = this.formatChildrenInformationList() || [{
id: uuidv4(),
name: '',
gender: undefined,
birthday: null,
parental_leave_left: 0,
},
]
this.educational_experience = this.formatEducationalExperienceList() || [
{
parental_leave_left: 0
}]
this.educational_experience = this.formatEducationalExperienceList() || [{
id: uuidv4(),
school: '',
major: '',
education: undefined,
graduation_year: null,
},
]
graduation_year: null
}]
this.type = type
this.visible = true
},
close() {
this.$refs.employeeFormData.resetFields()
this.educational_experience = [
{
this.educational_experience = [{
school: '',
major: '',
education: undefined,
graduation_year: null,
},
]
this.children_information = [
{
graduation_year: null
}]
this.children_information = [{
id: uuidv4(),
name: '',
gender: undefined,
birthday: null,
parental_leave_left: 0,
},
]
parental_leave_left: 0
}]
this.visible = false
},
formatChildrenInformationList() {
let arr = []
arr = this.employeeFormData.children_information ? this.employeeFormData.children_information : undefined
if (arr && arr.length) {
arr.forEach((item) => {
arr.forEach(item => {
item.id = uuidv4()
})
return arr
@ -560,7 +429,7 @@ export default {
let arr = []
arr = this.employeeFormData.educational_experience ? this.employeeFormData.educational_experience : undefined
if (arr && arr.length) {
arr.forEach((item) => {
arr.forEach(item => {
item.id = uuidv4()
})
return arr
@ -573,12 +442,12 @@ export default {
school: '',
major: '',
education: undefined,
graduation_year: null,
graduation_year: null
}
this.educational_experience.push(newEducational_experience)
},
removeEducation(removeId) {
const _idx = this.educational_experience.findIndex((item) => item.id === removeId)
const _idx = this.educational_experience.findIndex(item => item.id === removeId)
if (_idx !== -1) {
this.educational_experience.splice(_idx, 1)
}
@ -589,12 +458,12 @@ export default {
name: '',
gender: undefined,
birthday: null,
parental_leave_left: 0,
parental_leave_left: 0
}
this.children_information.push(newChildrenInfo)
},
removeChildren(removeId) {
const _idx = this.children_information.findIndex((item) => item.id === removeId)
const _idx = this.children_information.findIndex(item => item.id === removeId)
if (_idx !== -1) {
this.children_information.splice(_idx, 1)
}
@ -615,10 +484,10 @@ export default {
// }
if (date !== null) {
if (param === 'graduation_year') {
const _idx = this.educational_experience.findIndex((item) => item.id === id)
const _idx = this.educational_experience.findIndex(item => item.id === id)
this.educational_experience[_idx].graduation_year = moment(date).format('YYYY-MM')
} else if (param === 'birth_date') {
const _idx = this.children_information.findIndex((item) => item.id === id)
} else if (param === 'birthday') {
const _idx = this.children_information.findIndex(item => item.id === id)
this.children_information[_idx].birthday = moment(date).format('YYYY-MM-DD')
} else {
this.employeeFormData[param] = moment(date).format('YYYY-MM-DD')
@ -649,12 +518,12 @@ export default {
if (this.type === 'edit') {
await putEmployee(getFormData.employee_id, getFormData)
}
this.$message.success('操作成功')
this.$message.success(this.$t('cs.companyStructure.opSuccess'))
this.$emit('refresh')
Bus.$emit('updataAllIncludeEmployees')
this.close()
} else {
this.$message.warning('检查您的输入是否正确!')
this.$message.warning(this.$t('cs.companyInfo.checkInputCorrect'))
return false
}
})

View File

@ -21,7 +21,7 @@
:class="{ 'group-selected': groupIndex === activeGroupIndex }"
>
<div class="ops-setting-structure-sidebar-group-header-avatar">
<a-icon :type="group.icon" />
<a-icon :type="group.icon"/>
</div>
<span
class="ops-setting-structure-sidebar-group-header-title"
@ -46,7 +46,7 @@
>
<div class="ops-setting-structure-sidebar-group-category-item-title" @click="clickSelectItem(0)">
<div class="item-title">
在职员工
{{ $t('cs.companyStructure.activeEmployee') }}
</div>
<div class="item-count">
<div class="item-count-before">{{ activeEmployeeCount }}</div>
@ -61,7 +61,7 @@
>
<div class="ops-setting-structure-sidebar-group-category-item-title" @click="clickSelectItem(1)">
<div class="item-title">
停用员工
{{ $t('cs.companyStructure.blockEmployee') }}
</div>
<div class="item-count">
<div class="item-count-before">{{ deactiveEmployeeCount }}</div>
@ -70,7 +70,7 @@
</div>
</div>
</CollapseTransition>
<ul :style="{ marginTop: '10px' }" v-if="activeGroupIndex === groupIndex && activeGroupIndex === 1" >
<ul :style="{ marginTop: '10px' }" v-if="activeGroupIndex === groupIndex && activeGroupIndex === 1">
<CategroyTree
v-for="(subTree, subIndex) in departmentList"
:id="subTree.id"
@ -96,7 +96,7 @@
v-model="filterName"
:style="{ minWidth: '200px' }"
class="ops-input ops-input-radius"
placeholder="请输入姓名/邮箱"
:placeholder="$t('cs.role.inputNameOrEmail')"
@search="updateTableDataByFilter()"
/>
</div>
@ -123,16 +123,16 @@
</div>
</template>
<span :style="{ whiteSpace: 'nowrap' }">
<a-icon class="screening-box-scene-icon" type="filter" />
<a-icon class="screening-box-scene-icon" type="filter"/>
{{ getCurrentSceneLabel() }}
<a-icon class="screening-box-scene-icon" :type="displayTimeIcon" />
<a-icon class="screening-box-scene-icon" :type="displayTimeIcon"/>
</span>
</a-popover>
</div>
<SearchForm
ref="search"
:canSearchPreferenceAttrList="canSearchPreferenceAttrList"
@refresh="handleSearch" />
@refresh="handleSearch"/>
</div>
<div>
<a-space v-if="isEditable">
@ -144,10 +144,12 @@
icon="plus"
ghost
/>
<a-button type="primary" size="small" ghost @click="batchUpload"> 批量导入 </a-button>
<a-button type="primary" size="small" ghost @click="batchUpload">
{{ $t('cs.companyStructure.batchImport') }}
</a-button>
<template v-if="activeGroupIndex === 1 && selectDepartment.hasOwnProperty('id')">
<a-button type="primary" size="small" ghost @click="openDepartmentModal('add')">
创建子部门
{{ $t('cs.companyStructure.createSubDepartment') }}
</a-button>
<a-button
type="primary"
@ -156,10 +158,10 @@
@click="openDepartmentModal('edit')"
v-if="selectDepartment.id"
>
编辑部门
{{ $t('cs.companyStructure.editDepartment') }}
</a-button>
<a-button v-if="selectDepartment.id" type="danger" size="small" ghost @click="deleteDepartment">
删除部门
{{ $t('cs.companyStructure.deleteDepartment') }}
</a-button>
</template>
</a-space>
@ -168,25 +170,26 @@
<div class="ops-setting-batch">
<div>
<div :style="{ marginTop: '8px' }" class="ops-list-batch-action" v-show="!!selectedRowKeys.length">
<span @click="downloadEmployeeAll">下载全部</span>
<a-divider type="vertical" />
<span @click="exportSelectEvent">下载选中</span>
<a-divider type="vertical" />
<span @click="openBatchModal('department_id')">编辑部门</span>
<a-divider type="vertical" />
<span @click="openBatchModal('direct_supervisor_id')">编辑上级</span>
<a-divider type="vertical" />
<span @click="openBatchModal('position_name')">编辑岗位</span>
<a-divider type="vertical" />
<span @click="openBatchModal('annual_leave')">编辑年假</span>
<a-divider type="vertical" />
<span @click="openBatchModal('password')">重置密码</span>
<a-divider type="vertical" />
<span @click="openBatchModal('block', null, 1)">禁用</span>
<a-divider type="vertical" />
<span @click="openBatchModal('block', null, 0)">恢复</span>
<a-divider type="vertical" />
<span>选取: {{ selectedRowKeys.length }} </span>
<span @click="downloadEmployeeAll">{{ $t('cs.companyStructure.downloadAll') }}</span>
<a-divider type="vertical"/>
<span @click="exportSelectEvent">{{ $t('cs.companyStructure.downloadSelected') }}</span>
<a-divider type="vertical"/>
<span @click="openBatchModal('department_id')">{{ $t('cs.companyStructure.editDepartment') }}</span>
<a-divider type="vertical"/>
<span
@click="openBatchModal('direct_supervisor_id')">{{ $t('cs.companyStructure.editDirectSupervisor') }}</span>
<a-divider type="vertical"/>
<span @click="openBatchModal('position_name')">{{ $t('cs.companyStructure.editPosition') }}</span>
<a-divider type="vertical"/>
<span @click="openBatchModal('annual_leave')">{{ $t('cs.companyStructure.editAnnualLeave') }}</span>
<a-divider type="vertical"/>
<span @click="openBatchModal('password')">{{ $t('cs.companyStructure.resetPassword') }}</span>
<a-divider type="vertical"/>
<span @click="openBatchModal('block', null, 1)">{{ $t('cs.companyStructure.block') }}</span>
<a-divider type="vertical"/>
<span @click="openBatchModal('block', null, 0)">{{ $t('cs.companyStructure.recover') }}</span>
<a-divider type="vertical"/>
<span>{{ $t('selectRows', {rows: selectedRowKeys.length}) }}</span>
</div>
</div>
<!-- <div>
@ -197,14 +200,15 @@
</div>
</div>
<!-- 批量操作对话框 -->
<BatchModal ref="BatchModal" @refresh="updateAll" />
<BatchModal ref="BatchModal" @refresh="updateAll"/>
<!-- 部门表单对话框 -->
<DepartmentModal ref="DepartmentModal" @refresh="clickSelectGroup(1)" />
<DepartmentModal ref="DepartmentModal" @refresh="clickSelectGroup(1)"/>
<!-- 员工表单对话框 -->
<EmployeeModal ref="EmployeeModal" @refresh="updateAll" />
<EmployeeModal ref="EmployeeModal" @refresh="updateAll"/>
<!-- 表格展示 -->
<EmployeeTable
ref="employeeTable"
:tableData="tableData"
:tableHeight="tableHeight"
@sortChangeEvent="sortChangeEvent"
@ -226,15 +230,15 @@
:page-size-options="pageSizeOptions"
:current="tablePage.currentPage"
:total="tablePage.totalResult"
:show-total="(total, range) => `当前展示 ${range[0]}-${range[1]} 条数据, 共 ${total} 条`"
:show-total="(total, range) => $t('pagination.total', { range0: range[0], range1: range[1], total:total })"
:page-size="tablePage.pageSize"
:default-current="1"
@change="pageOrSizeChange"
@showSizeChange="pageOrSizeChange"
>
<template #buildOptionText="props">
<span v-if="props.value !== '9999'">{{ props.value }}/</span>
<span v-else>全部</span>
<span v-if="props.value !== '9999'">{{ props.value }}{{ $t('itemsPerPage') }}</span>
<span v-else>{{ $t('all') }}</span>
</template>
</a-pagination>
</div>
@ -288,74 +292,16 @@ export default {
SearchForm
},
data() {
const canSearchPreferenceAttrList = [
{ label: '姓名', value: 'nickname' },
{ label: '用户名', value: 'username' },
{ label: '邮箱', value: 'email' },
{ label: '性别', value: 'sex', is_choice: true, choice_value: [{ label: '', value: '' }, { label: '', value: '' }] },
{ label: '手机号', value: 'mobile' },
{ label: '部门', value: 'department_name' },
{ label: '岗位', value: 'position_name' },
{ label: '直接上级', value: 'direct_supervisor_id' },
{ label: '年假', value: 'annual_leave' },
{ label: '目前所属主体', value: 'current_company' },
{ label: '初始入职日期', value: 'dfc_entry_date' },
{ label: '目前主体入职日期', value: 'entry_date' },
{ label: '正式/实习生', value: 'is_internship', is_choice: true, choice_value: [{ label: '正式', value: 0 }, { label: '实习生', value: 1 }] },
{ label: '离职日期', value: 'leave_date' },
{ label: '身份证号码', value: 'id_card' },
{ label: '民族', value: 'nation' },
{ label: '籍贯', value: 'id_place' },
{ label: '组织关系', value: 'party', is_choice: true, choice_value: [{ label: '党员', value: '党员' }, { label: '团员', value: '团员' }, { label: '群众', value: '群众' }] },
{ label: '户籍类型', value: 'household_registration_type', is_choice: true, choice_value: [{ label: '城镇', value: '城镇' }, { label: '农业', value: '农业' }] },
{ label: '户口所在地', value: 'hometown' },
{ label: '婚姻情况', value: 'marry', is_choice: true, choice_value: [{ label: '未婚', value: '未婚' }, { label: '已婚', value: '已婚' }] },
{ label: '最高学历', value: 'max_degree', is_choice: true, choice_value: [{ label: '博士', value: '博士' }, { label: '硕士', value: '硕士' }, { label: '本科', value: '本科' }, { label: '专科', value: '专科' }, { label: '高中', value: '高中' }] },
{ label: '紧急联系人', value: 'emergency_person' },
{ label: '紧急联系电话', value: 'emergency_phone' },
{ label: '卡号', value: 'bank_card_number' },
{ label: '银行', value: 'bank_card_name' },
{ label: '开户行', value: 'opening_bank' },
{ label: '开户地', value: 'account_opening_location' },
{ label: '上次登录时间', value: 'last_login' },
]
return {
isActive: '',
visible: true,
sceneList: [
{
label: '全部',
value: -1,
},
{
label: '在职员工',
value: 0,
},
{
label: '停用员工',
value: 1,
},
],
localStorageKey: 'setting-company-strcutre',
localStorageKey: 'itsm-company-strcutre',
localStoragePaneLengthPixel: 'setting-structure-paneLengthPixel',
displayTimeIcon: 'down',
currentScene: '',
// historySceneitemSelected: 'history-scene-item-selected',
// historySceneItem: 'history-scene-item',
paneLengthPixel: 204,
groupData: [
{
id: 0,
title: '员工',
icon: 'user',
},
{
id: 1,
title: '部门',
icon: 'apartment',
},
],
tableData: [],
activeEmployeeCount: 0,
deactiveEmployeeCount: 0,
@ -378,7 +324,6 @@ export default {
allTreeDepartment: [],
allTreeDepAndEmp: [],
isFolder: false,
canSearchPreferenceAttrList,
attributes: [],
pageSizeOptions: ['50', '100', '200', '9999'],
expression: [],
@ -413,6 +358,115 @@ export default {
isEditable() {
return this.hasDetailPermission('backend', '公司架构', ['update'])
},
canSearchPreferenceAttrList() {
return [
{ label: this.$t('cs.companyStructure.nickname'), value: 'nickname' },
{ label: this.$t('cs.companyStructure.username'), value: 'username' },
{ label: this.$t('cs.companyStructure.email'), value: 'email' },
{
label: this.$t('cs.companyStructure.sex'),
value: 'sex',
is_choice: true,
choice_value: [
{ label: this.$t('cs.companyStructure.male'), value: '' },
{ label: this.$t('cs.companyStructure.female'), value: '' }]
},
{ label: this.$t('cs.companyStructure.mobile'), value: 'mobile' },
{ label: this.$t('cs.companyStructure.departmentName'), value: 'department_name' },
{ label: this.$t('cs.companyStructure.positionName'), value: 'position_name' },
{ label: this.$t('cs.companyStructure.departmentDirector'), value: 'direct_supervisor_id' },
{ label: this.$t('cs.companyStructure.annualLeave'), value: 'annual_leave' },
{ label: this.$t('cs.companyStructure.currentCompany'), value: 'current_company' },
{ label: this.$t('cs.companyStructure.dfcEntryDate'), value: 'dfc_entry_date' },
{ label: this.$t('cs.companyStructure.entryDate'), value: 'entry_date' },
{
label: this.$t('cs.companyStructure.isInternship'),
value: 'is_internship',
is_choice: true,
choice_value: [{ label: this.$t('cs.companyStructure.fullTime'), value: 0 },
{ label: this.$t('cs.companyStructure.internship'), value: 1 }]
},
{ label: this.$t('cs.companyStructure.leaveDate'), value: 'leave_date' },
{ label: this.$t('cs.companyStructure.idCard'), value: 'id_card' },
{ label: this.$t('cs.companyStructure.nation'), value: 'nation' },
{ label: this.$t('cs.companyStructure.idPlace'), value: 'id_place' },
{
label: this.$t('cs.companyStructure.party'),
value: 'party',
is_choice: true,
choice_value: [
{ label: this.$t('cs.companyStructure.partyMember'), value: '党员' },
{ label: this.$t('cs.companyStructure.member'), value: '团员' },
{ label: this.$t('cs.companyStructure.masses'), value: '群众' }]
},
{
label: this.$t('cs.companyStructure.householdRegistrationType'),
value: 'household_registration_type',
is_choice: true,
choice_value: [{ label: this.$t('cs.companyStructure.town'), value: '城镇' }, { label: this.$t('cs.companyStructure.agriculture'), value: '农业' }]
},
{ label: this.$t('cs.companyStructure.hometown'), value: 'hometown' },
{
label: this.$t('cs.companyStructure.marry'),
value: 'marry',
is_choice: true,
choice_value: [{ label: this.$t('cs.companyStructure.unmarried'), value: '未婚' }, { label: this.$t('cs.companyStructure.married'), value: '已婚' }]
},
{
label: this.$t('cs.companyStructure.maxDegree'),
value: 'max_degree',
is_choice: true,
choice_value: [{ label: this.$t('cs.companyStructure.phd'), value: '博士' }, { label: this.$t('cs.companyStructure.master'), value: '硕士' }, {
label: this.$t('cs.companyStructure.undergraduate'),
value: '本科'
}, { label: this.$t('cs.companyStructure.specialist'), value: '专科' }, { label: this.$t('cs.companyStructure.highSchool'), value: '高中' }]
},
{ label: this.$t('cs.companyStructure.emergencyPerson'), value: 'emergency_person' },
{ label: this.$t('cs.companyStructure.emergencyPhone'), value: 'emergency_phone' },
{ label: this.$t('cs.companyStructure.bankCardNumber'), value: 'bank_card_number' },
{ label: this.$t('cs.companyStructure.bankCardName'), value: 'bank_card_name' },
{ label: this.$t('cs.companyStructure.openingBank'), value: 'opening_bank' },
{ label: this.$t('cs.companyStructure.accountOpeningLocation'), value: 'account_opening_location' },
{ label: this.$t('cs.companyStructure.birthDate'), value: 'birth_date' },
{ label: this.$t('cs.companyStructure.nationalityRegion'), value: 'nationality_region' },
{ label: this.$t('cs.companyStructure.birthPlace'), value: 'birth_place' },
{ label: this.$t('cs.companyStructure.firstEntryDate'), value: 'first_entry_date' },
{ label: this.$t('cs.companyStructure.estimatedDepartureDate'), value: 'estimated_departure_date' },
// { label: '角色', value: 'roles' },
{ label: this.$t('cs.companyStructure.lastLogin'), value: 'last_login' },
]
},
sceneList () {
return [
{
label: this.$t('all'),
value: -1,
},
{
label: this.$t('cs.companyStructure.activeEmployee'),
value: 0,
},
{
label: this.$t('cs.companyStructure.blockEmployee'),
value: 1,
},
]
},
groupData () {
return [
{
id: 0,
title: this.$t('cs.companyStructure.employee'),
icon: 'user',
},
{
id: 1,
title: this.$t('cs.companyStructure.departmentName'),
icon: 'apartment',
},
]
}
},
provide() {
return {
@ -470,6 +524,9 @@ export default {
Bus.$on('clickSelectGroup', async (index) => {
this.clickSelectGroup(index)
})
Bus.$on('changeSelectedRowKeys', (selectedRowKeys) => {
this.selectedRowKeys = selectedRowKeys
})
this.getAllFlatEmployees()
this.getAllFlatDepartment()
this.getAllTreeDepartment()
@ -480,6 +537,7 @@ export default {
Bus.$off('updateAllIncludeDepartment')
Bus.$off('selectDepartment')
Bus.$off('reqChildren')
Bus.$off('changeSelectedRowKeys')
},
methods: {
// mouseOver: function() {
@ -579,55 +637,7 @@ export default {
order: this.tableSortData || 'direct_supervisor_id',
})
}
// console.log(this.activeGroupIndex, reqEmployeeData)
this.tableData = reqEmployeeData.data_list
if (reqEmployeeData.data_list.length) {
// 筛选教育经历数组中学历最高的一条记录
if (reqEmployeeData.data_list[0].educational_experience) {
reqEmployeeData.data_list.forEach((row, row_index) => {
const educational_experience = row.educational_experience
if (educational_experience.length > 1) {
let max_index = 0
educational_experience.forEach((item, index) => {
if (index < educational_experience.length - 1) {
max_index = item.graduation_year > educational_experience[index + 1].graduation_year ? index : index + 1
}
})
this.tableData[row_index].school = educational_experience[max_index].school
this.tableData[row_index].major = educational_experience[max_index].major
this.tableData[row_index].education = educational_experience[max_index].education
this.tableData[row_index].graduation_year = educational_experience[max_index].graduation_year
} else if (educational_experience.length === 1) {
this.tableData[row_index].school = educational_experience[0].school
this.tableData[row_index].major = educational_experience[0].major
this.tableData[row_index].education = educational_experience[0].education
this.tableData[row_index].graduation_year = educational_experience[0].graduation_year
} else {
this.tableData[row_index].school = ''
this.tableData[row_index].major = ''
this.tableData[row_index].education = ''
this.tableData[row_index].graduation_year = ''
}
})
}
// 筛选子女信息中第一位展示在employeeTable
if (reqEmployeeData.data_list[0].children_information) {
reqEmployeeData.data_list.forEach((row, row_index) => {
const children_information = row.children_information
if (children_information.length) {
this.tableData[row_index].name = children_information[0].name
this.tableData[row_index].gender = children_information[0].gender
this.tableData[row_index].birthday = children_information[0].birthday
this.tableData[row_index].parental_leave_left = children_information[0].parental_leave_left
} else {
this.tableData[row_index].name = ''
this.tableData[row_index].gender = ''
this.tableData[row_index].birthday = ''
this.tableData[row_index].parental_leave_left = ''
}
})
}
}
this.tableData = this.FilterTableData(reqEmployeeData)
this.tablePage = {
...this.tablePage,
currentPage: reqEmployeeData.page,
@ -661,6 +671,16 @@ export default {
order: this.tableSortData || 'direct_supervisor_id',
})
}
this.tableData = this.FilterTableData(reqEmployeeData)
this.tablePage = {
...this.tablePage,
currentPage: reqEmployeeData.page,
pageSize: reqEmployeeData.page_size,
totalResult: reqEmployeeData.total,
}
this.loading = false
},
FilterTableData(reqEmployeeData) {
const tableData = reqEmployeeData.data_list
// 筛选教育经历数组中学历最高的一条记录
if (reqEmployeeData.data_list.length) {
@ -668,6 +688,7 @@ export default {
// reqEmployeeData.data_list.forEach((row, row_index) => {
for (let index = 0, len = reqEmployeeData.data_list.length; index < len; index++) {
const educational_experience = reqEmployeeData.data_list[index].educational_experience
if (educational_experience) {
if (educational_experience.length > 1) {
let max_index = 0
educational_experience.forEach((item, index) => {
@ -692,11 +713,13 @@ export default {
}
}
}
}
// 筛选子女信息中第一位展示在employeeTable
if (reqEmployeeData.data_list[0].children_information) {
// reqEmployeeData.data_list.forEach((row, row_index) => {
for (let row_index = 0, len = reqEmployeeData.data_list.length; row_index < len; row_index++) {
const children_information = reqEmployeeData.data_list[row_index].children_information
if (children_information) {
if (children_information.length) {
tableData[row_index].name = children_information[0].name
tableData[row_index].gender = children_information[0].gender
@ -711,14 +734,8 @@ export default {
}
}
}
this.tableData = tableData
this.tablePage = {
...this.tablePage,
currentPage: reqEmployeeData.page,
pageSize: reqEmployeeData.page_size,
totalResult: reqEmployeeData.total,
}
this.loading = false
return tableData
},
updateAll() {
// this.expression = []
@ -771,6 +788,11 @@ export default {
a.click()
window.URL.revokeObjectURL(url)
})
this.$refs.employeeTable.getVxetableRef().clearCheckboxRow()
this.$refs.employeeTable.getVxetableRef().clearCheckboxReserve()
this.$refs.employeeTable.getVxetableRef().clearSort()
this.tableSortData = undefined
this.selectedRowKeys = []
},
reset() {
this.filterName = ''
@ -842,18 +864,18 @@ export default {
if (this.selectDepartment.hasOwnProperty('id')) {
this.$refs.DepartmentModal.open({ type, selectDepartment: this.selectDepartment })
} else {
this.$message.error('请选择部门')
this.$message.error(this.$t('cs.companyStructure.selectDepartment'))
}
},
async deleteDepartment() {
const that = this
this.$confirm({
title: '警告',
content: `确认删除 ${this.selectDepartment.title}`,
title: this.$t('warning'),
content: this.$t('confirmDelete2', { name: this.selectDepartment.title }),
onOk() {
deleteDepartmentById(that.selectDepartment.id).then((res) => {
that.clickSelectGroup(1)
that.$message.success('删除成功!')
that.$message.success(that.$t('deleteSuccess'))
Bus.$emit('updateAllIncludeDepartment')
})
},
@ -883,7 +905,13 @@ export default {
this.updateTableDataByFilter()
},
filterChangeEvent({ column, property, values, datas, filterList, $event }) {
if (property === 'is_internship') {
if (property === 'roles') {
this.tableFilterData = {
...this.tableFilterData,
// role_id_list: values && values.length ? values.join(',') : undefined,
role_id_list: values && values.length ? values : undefined,
}
} else if (property === 'is_internship') {
this.tableFilterData = {
...this.tableFilterData,
is_internship: values && values.length ? values[0] : undefined,
@ -1098,7 +1126,8 @@ export default {
}
}
}
.ops-setting-batch{
.ops-setting-batch {
width: 100%;
display: flex;
justify-content: space-between;

View File

@ -18,14 +18,13 @@
:img="cropperImg"
output-type="png"
@realTime="realTime"
v-bind="eidtImageOption"
/>
<div class="ops-modal-preview">
<div class="ops-modal-preview-name">预览</div>
<div class="ops-modal-preview-name">{{ $t('cs.components.preview') }}</div>
<img
:style="{
width: eidtImageOption.previewWidth,
height: eidtImageOption.previewHeight,
width: previewWidth,
height: previewHeight,
border: '1px solid #f2f2f2',
}"
:src="previewImg"
@ -35,7 +34,7 @@
</div>
<div slot="footer" class="ops-modal-dialog-footer">
<a-button type="primary" @click="submitImage()">确定</a-button>
<a-button type="primary" @click="submitImage()">{{ $t('confirm') }}</a-button>
</div>
</a-modal>
</template>
@ -50,7 +49,7 @@ export default {
props: {
title: {
type: String,
default: '编辑头像',
default: () => this.$t('cs.components.editAvatar'),
},
show: {
type: Boolean,
@ -60,9 +59,13 @@ export default {
type: String,
default: '',
},
eidtImageOption: {
type: Object,
default: () => {},
previewWidth: {
type: String,
default: '60px',
},
previewHeight: {
type: String,
default: '60px',
},
},
data() {

View File

@ -9,7 +9,7 @@
>
<div slot="popover_item" class="search-form-bar-filter">
<a-icon :class="filterExp.length ? 'search-form-bar-filter-icon' : 'search-form-bar-filter-icon_selected'" type="filter"/>
条件过滤
{{ $t('cs.components.conditionFilter') }}
<a-icon :class="filterExp.length ? 'search-form-bar-filter-icon' : 'search-form-bar-filter-icon_selected'" type="down"/>
</div>
</FilterComp>

View File

@ -2,12 +2,12 @@
<treeselect
:multiple="false"
:options="departemntTreeSelectOption"
placeholder="请选择部门"
:placeholder="readOnly ? '' : $t('cs.companyStructure.selectDepartment')"
v-model="treeValue"
:normalizer="normalizer"
noChildrenText=""
noOptionsText=""
class="ops-setting-treeselect"
:noChildrenText="$t('cs.components.empty')"
:noOptionsText="$t('cs.components.empty')"
:class="className ? className : 'ops-setting-treeselect'"
v-bind="$attrs"
appendToBody
:zIndex="1050"
@ -28,6 +28,10 @@ export default {
type: [String, Array, Number, null],
default: null,
},
className: {
type: String,
default: 'ops-setting-treeselect',
},
},
data() {
return {
@ -46,7 +50,15 @@ export default {
},
}
},
inject: ['provide_allTreeDepartment'],
inject: {
provide_allTreeDepartment: {
from: 'provide_allTreeDepartment',
},
readOnly: {
from: 'readOnly',
default: false,
},
},
computed: {
departemntTreeSelectOption() {
return this.provide_allTreeDepartment()

View File

@ -26,7 +26,7 @@
<vxe-column
field="nickname"
min-width="100px"
title="姓名"
:title="$t('cs.companyStructure.nickname')"
sortable
v-if="checkedCols.findIndex((v) => v == 'nickname') !== -1 && attributes.findIndex((v) => v == 'nickname') !== -1"
key="nickname"
@ -49,7 +49,7 @@
</vxe-column>
<vxe-column
field="username"
title="用户名"
:title="$t('cs.companyStructure.username')"
min-width="120px"
sortable
v-if="checkedCols.findIndex((v) => v == 'username') !== -1 && attributes.findIndex((v) => v == 'username') !== -1"
@ -58,13 +58,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>用户名</span>
<span>{{ $t('cs.companyStructure.username') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="email"
title="邮箱"
:title="$t('cs.companyStructure.email')"
min-width="140px"
sortable
v-if="checkedCols.findIndex((v) => v == 'email') !== -1 && attributes.findIndex((v) => v == 'email') !== -1"
@ -73,13 +73,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>邮箱</span>
<span>{{ $t('cs.companyStructure.email') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="sex"
title="性别"
:title="$t('cs.companyStructure.sex')"
width="70px"
sortable
align="center"
@ -89,13 +89,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>性别</span>
<span>{{ $t('cs.companyStructure.sex') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="mobile"
title="手机号"
:title="$t('cs.companyStructure.mobile')"
min-width="100px"
v-if="checkedCols.findIndex((v) => v == 'mobile') !== -1 && attributes.findIndex((v) => v == 'mobile') !== -1"
sortable
@ -104,13 +104,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>手机号</span>
<span>{{ $t('cs.companyStructure.mobile') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="department_name"
title="部门"
:title="$t('cs.companyStructure.departmentName')"
min-width="90px"
sortable
v-if="
@ -122,7 +122,7 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>部门</span>
<span>{{ $t('cs.companyStructure.departmentName') }}</span>
</span>
</template>
<template #default="{ row }">
@ -132,7 +132,7 @@
</vxe-column>
<vxe-column
field="position_name"
title="岗位"
:title="$t('cs.companyStructure.positionName')"
min-width="120px"
sortable
v-if="
@ -144,13 +144,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>岗位</span>
<span>{{ $t('cs.companyStructure.positionName') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="direct_supervisor_id"
title="直接上级"
:title="$t('cs.companyStructure.supervisor')"
min-width="120px"
sortable
v-if="
@ -162,7 +162,7 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>直接上级</span>
<span>{{ $t('cs.companyStructure.supervisor') }}</span>
</span>
</template>
<template #default="{ row }">
@ -173,7 +173,7 @@
</vxe-column>
<vxe-column
field="annual_leave"
title="年假"
:title="$t('cs.companyStructure.annualLeave')"
sortable
min-width="80"
v-if="
@ -186,13 +186,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>年假</span>
<span>{{ $t('cs.companyStructure.annualLeave') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="virtual_annual_leave"
title="虚拟年假"
:title="$t('cs.companyStructure.virtualAnnualLeave')"
sortable
min-width="100"
v-if="
@ -205,13 +205,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>虚拟年假</span>
<span>{{ $t('cs.companyStructure.virtualAnnualLeave') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="parenting_leave"
title="育儿假"
:title="$t('cs.companyStructure.parentingLeave')"
sortable
min-width="100"
v-if="
@ -224,13 +224,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>育儿假</span>
<span>{{ $t('cs.companyStructure.parentingLeave') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="entry_date"
title="目前主体入职日期"
:title="$t('cs.companyStructure.entryDate')"
sortable
min-width="150"
v-if="
@ -243,13 +243,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>目前主体入职日期</span>
<span>{{ $t('cs.companyStructure.entryDate') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="is_internship"
title="正式/实习生"
:title="$t('cs.companyStructure.isInternship')"
sortable
min-width="140"
v-bind="tableType === 'structure' ? { filters: internOptions, 'filter-multiple': false } : {}"
@ -263,7 +263,7 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>正式/实习生</span>
<span>{{ $t('cs.companyStructure.isInternship') }}</span>
</span>
</template>
<template #default="{ row }">
@ -272,7 +272,7 @@
>I
<vxe-column
field="leave_date"
title="离职日期"
:title="$t('cs.companyStructure.leaveDate')"
sortable
min-width="100"
v-if="
@ -285,13 +285,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>离职日期</span>
<span>{{ $t('cs.companyStructure.leaveDate') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="id_card"
title="身份证号码"
:title="$t('cs.companyStructure.idCard')"
sortable
min-width="120"
v-if="
@ -304,13 +304,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>身份证号码</span>
<span>{{ $t('cs.companyStructure.idCard') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="nation"
title="民族"
:title="$t('cs.companyStructure.nation')"
sortable
min-width="80"
v-if="
@ -323,13 +323,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>民族</span>
<span>{{ $t('cs.companyStructure.idPlace') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="id_place"
title="籍贯"
:title="$t('cs.companyStructure.nation')"
sortable
min-width="120"
v-if="
@ -342,13 +342,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>籍贯</span>
<span>{{ $t('cs.companyStructure.idPlace') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="party"
title="组织关系"
:title="$t('cs.companyStructure.party')"
sortable
min-width="100"
v-if="
@ -361,13 +361,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>组织关系</span>
<span>{{ $t('cs.companyStructure.party') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="household_registration_type"
title="户籍类型"
:title="$t('cs.companyStructure.householdRegistrationType')"
sortable
min-width="100"
v-if="
@ -380,13 +380,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>户籍类型</span>
<span>{{ $t('cs.companyStructure.hometown') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="hometown"
title="户口所在地"
:title="$t('cs.companyStructure.householdRegistrationType') "
sortable
min-width="120"
v-if="
@ -399,13 +399,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>户口所在地</span>
<span>{{ $t('cs.companyStructure.hometown') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="marry"
title="婚姻情况"
:title="$t('cs.companyStructure.marry')"
sortable
min-width="100"
v-if="
@ -418,13 +418,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>婚姻情况</span>
<span>{{ $t('cs.companyStructure.marry') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="max_degree"
title="最高学历"
:title="$t('cs.companyStructure.maxDegree')"
sortable
min-width="100"
v-if="
@ -437,13 +437,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>最高学历</span>
<span>{{ $t('cs.companyStructure.maxDegree') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="emergency_person"
title="紧急联系人"
:title="$t('cs.companyStructure.emergencyPerson')"
sortable
min-width="110"
v-if="
@ -456,13 +456,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>紧急联系人</span>
<span>{{ $t('cs.companyStructure.emergencyPerson') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="emergency_phone"
title="紧急联系电话"
:title="$t('cs.companyStructure.emergencyPhone')"
sortable
min-width="120"
v-if="
@ -475,13 +475,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>紧急联系电话</span>
<span>{{ $t('cs.companyStructure.emergencyPhone') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="bank_card_number"
title="卡号"
:title="$t('cs.companyStructure.bankCardNumber')"
sortable
min-width="120"
v-if="
@ -494,13 +494,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>卡号</span>
<span>{{ $t('cs.companyStructure.bankCardNumber') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="bank_card_name"
title="银行"
:title="$t('cs.companyStructure.bankCardName')"
sortable
min-width="100"
v-if="
@ -513,13 +513,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>银行</span>
<span>{{ $t('cs.companyStructure.bankCardName') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="opening_bank"
title="开户行"
:title="$t('cs.companyStructure.openingBank')"
sortable
min-width="100"
v-if="
@ -532,13 +532,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>开户行</span>
<span>{{ $t('cs.companyStructure.openingBank') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="account_opening_location"
title="开户地"
:title="$t('cs.companyStructure.accountOpeningLocation')"
sortable
min-width="120"
v-if="
@ -551,13 +551,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>开户地</span>
<span>{{ $t('cs.companyStructure.accountOpeningLocation') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="school"
title="学校"
:title="$t('cs.companyStructure.school')"
min-width="100"
v-if="
checkedCols.findIndex((v) => v == 'school') !== -1 &&
@ -569,13 +569,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>学校</span>
<span>{{ $t('cs.companyStructure.school') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="major"
title="专业"
:title="$t('cs.companyStructure.major')"
min-width="100"
v-if="
checkedCols.findIndex((v) => v == 'major') !== -1 &&
@ -587,13 +587,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>专业</span>
<span>{{ $t('cs.companyStructure.major') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="education"
title="学历"
:title="$t('cs.companyStructure.education')"
min-width="80"
v-if="
checkedCols.findIndex((v) => v == 'education') !== -1 &&
@ -605,13 +605,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>学历</span>
<span>{{ $t('cs.companyStructure.education') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="graduation_year"
title="毕业年份"
:title="$t('cs.companyStructure.graduationYear')"
min-width="100"
v-if="
checkedCols.findIndex((v) => v == 'graduation_year') !== -1 &&
@ -623,13 +623,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>毕业年份</span>
<span>{{ $t('cs.companyStructure.graduationYear') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="name"
title="子女姓名"
:title="$t('cs.companyStructure.childrenName')"
min-width="80"
v-if="
checkedCols.findIndex((v) => v == 'name') !== -1 &&
@ -641,13 +641,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>子女姓名</span>
<span>{{ $t('cs.companyStructure.childrenName') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="gender"
title="子女性别"
:title="$t('cs.companyStructure.sex')"
min-width="80"
v-if="
checkedCols.findIndex((v) => v == 'gender') !== -1 &&
@ -659,13 +659,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>子女性别</span>
<span>{{ $t('cs.companyStructure.sex') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="birthday"
title="子女出生日期"
:title="$t('cs.companyStructure.birthDate')"
min-width="100"
v-if="
checkedCols.findIndex((v) => v == 'birthday') !== -1 &&
@ -677,13 +677,13 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>子女出生日期</span>
<span>{{ $t('cs.companyStructure.birthDate') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="parental_leave_left"
title="剩余育儿假"
:title="$t('cs.companyStructure.leftParentingLeave')"
min-width="100"
v-if="
checkedCols.findIndex((v) => v == 'parental_leave_left') !== -1 &&
@ -695,13 +695,103 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>剩余育儿假</span>
<span>{{ $t('cs.companyStructure.leftParentingLeave') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="birth_date"
:title="$t('cs.companyStructure.birthDate')"
min-width="100"
v-if="
checkedCols.findIndex((v) => v == 'birth_date') !== -1 &&
tableType == 'structure' &&
attributes.findIndex((v) => v == 'birth_date') !== -1
"
key="birth_date"
>
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>{{ $t('cs.companyStructure.birthDate') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="birth_place"
:title="$t('cs.companyStructure.birthPlace')"
min-width="100"
v-if="
checkedCols.findIndex((v) => v == 'birth_place') !== -1 &&
tableType == 'structure' &&
attributes.findIndex((v) => v == 'birth_place') !== -1
"
key="birth_place"
>
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>{{ $t('cs.companyStructure.birthPlace') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="nationality_region"
:title="$t('cs.companyStructure.nationalityRegion')"
min-width="100"
v-if="
checkedCols.findIndex((v) => v == 'nationality_region') !== -1 &&
tableType == 'structure' &&
attributes.findIndex((v) => v == 'nationality_region') !== -1
"
key="nationality_region"
>
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>{{ $t('cs.companyStructure.nationalityRegion') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="first_entry_date"
:title="$t('cs.companyStructure.firstEntryDate')"
min-width="100"
v-if="
checkedCols.findIndex((v) => v == 'first_entry_date') !== -1 &&
tableType == 'structure' &&
attributes.findIndex((v) => v == 'first_entry_date') !== -1
"
key="first_entry_date"
>
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>{{ $t('cs.companyStructure.firstEntryDate') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="estimated_departure_date"
:title="$t('cs.companyStructure.estimatedDepartureDate')"
min-width="100"
v-if="
checkedCols.findIndex((v) => v == 'estimated_departure_date') !== -1 &&
tableType == 'structure' &&
attributes.findIndex((v) => v == 'estimated_departure_date') !== -1
"
key="estimated_departure_date"
>
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>{{ $t('cs.companyStructure.estimatedDepartureDate') }}</span>
</span>
</template>
</vxe-column>
<vxe-column
field="last_login"
title="上次登录时间"
:title="$t('cs.companyStructure.lastLogin')"
min-width="140px"
sortable
:formatter="formatDate"
@ -715,7 +805,7 @@
<template #header>
<span class="vxe-handle">
<OpsMoveIcon class="move-icon" />
<span>上次登录时间</span>
<span>{{ $t('cs.companyStructure.lastLogin') }}</span>
</span>
</template>
</vxe-column>
@ -728,10 +818,10 @@
key="control"
>
<template #header>
<span>操作</span>
<span>{{ $t('operation') }}</span>
<template>
<a-popover
title="请选择需要展示的列"
:title="$t('cs.companyStructure.selectDisplayColumn')"
placement="bottom"
v-model="visible"
trigger="click"
@ -741,7 +831,7 @@
>
<template slot="content">
<div :style="{ maxHeight: `${windowHeight - 320}px`, overflowY: 'auto', width: '160px' }">
<a-checkbox-group v-model="unsbmitCheckedCols" :options="options" style="display: grid">
<a-checkbox-group v-model="unsbmitCheckedCols" :options="options" style="display: grid;">
</a-checkbox-group>
</div>
<div
@ -753,36 +843,44 @@
justifyContent: 'flex-end',
}"
>
<a-button :style="{ marginRight: '10px' }" size="small" @click="handleCancel">取消</a-button>
<a-button size="small" @click="handleSubmit" type="primary">确定</a-button>
<a-button :style="{ marginRight: '10px' }" size="small" @click="handleCancel">{{ $t('cancel') }}</a-button>
<a-button size="small" @click="handleSubmit" type="primary">{{ $t('confirm') }}</a-button>
</div>
</template>
<a-icon type="control" style="cursor: pointer" />
<a-icon type="control" style="cursor: pointer;" />
</a-popover>
</template>
</template>
<template #default="{ row }">
<a-space v-if="tableType === 'structure'">
<a><a-icon type="edit" @click="openEmployeeModal(row, 'edit')" /></a>
<a><a-icon type="edit" @click="openEmployeeModal(row, 'edit')"/></a>
<a-tooltip>
<template slot="title"> 重置密码 </template>
<a><a-icon type="reload" @click="openBatchModal('password', row)" /></a>
<template slot="title">
{{ $t('cs.companyStructure.resetPassword') }}
</template>
<a><a-icon type="reload" @click="openBatchModal('password', row)"/></a>
</a-tooltip>
<a-tooltip v-if="!row.block">
<template slot="title"> 禁用 </template>
<template slot="title">
{{ $t('cs.companyStructure.block') }}
</template>
<a :style="{ color: 'red' }" @click="openBatchModal('block', row, 1)">
<ops-icon type="icon-xianxing-weilianjie" />
</a>
</a-tooltip>
<a-tooltip v-else>
<template slot="title"> 恢复 </template>
<template slot="title">
{{ $t('cs.companyStructure.recover') }}
</template>
<a @click="openBatchModal('block', row, 0)">
<ops-icon type="icon-xianxing-yilianjie" />
</a>
</a-tooltip>
</a-space>
<a-tooltip v-else>
<template slot="title"> 移除 </template>
<template slot="title">
{{ $t('cs.role.remove') }}
</template>
<a :style="{ color: 'red' }" @click="removeEmployee(row)">
<ops-icon type="icon-xianxing-shanchuyonghu" />
</a>
@ -792,7 +890,7 @@
<template #empty>
<div>
<img :style="{ width: '200px' }" :src="require('@/assets/data_empty.png')" />
<div>暂无数据</div>
<div>{{ $t('noData') }}</div>
</div>
</template>
</vxe-table>
@ -833,46 +931,49 @@ export default {
},
data() {
const options = [
{ label: '姓名', value: 'nickname' },
{ label: '用户名', value: 'username' },
{ label: '邮箱', value: 'email' },
{ label: '性别', value: 'sex' },
{ label: '手机号', value: 'mobile' },
{ label: '部门', value: 'department_name' },
{ label: '岗位', value: 'position_name' },
{ label: '直接上级', value: 'direct_supervisor_id' },
{ label: '年假', value: 'annual_leave' },
{ label: '虚拟年假', value: 'virtual_annual_leave' },
{ label: '育儿假', value: 'parenting_leave' },
{ label: '目前所属主体', value: 'current_company' },
{ label: '初始入职日期', value: 'dfc_entry_date' },
{ label: '目前主体入职日期', value: 'entry_date' },
{ label: '正式/实习生', value: 'is_internship' },
{ label: '离职日期', value: 'leave_date' },
{ label: '身份证号码', value: 'id_card' },
{ label: '民族', value: 'nation' },
{ label: '籍贯', value: 'id_place' },
{ label: '组织关系', value: 'party' },
{ label: '户籍类型', value: 'household_registration_type' },
{ label: '户口所在地', value: 'hometown' },
{ label: '婚姻情况', value: 'marry' },
{ label: '最高学历', value: 'max_degree' },
{ label: '紧急联系人', value: 'emergency_person' },
{ label: '紧急联系电话', value: 'emergency_phone' },
{ label: '卡号', value: 'bank_card_number' },
{ label: '银行', value: 'bank_card_name' },
{ label: '开户行', value: 'opening_bank' },
{ label: '开户地', value: 'account_opening_location' },
{ label: '学校', value: 'school' },
{ label: '专业', value: 'major' },
{ label: '学历', value: 'education' },
{ label: '毕业年份', value: 'graduation_year' },
{ label: '子女姓名', value: 'name' },
{ label: '子女性别', value: 'gender' },
{ label: '子女出生日期', value: 'birthday' },
{ label: '剩余育儿假', value: 'parental_leave_left' },
{ label: '角色', value: 'roles' },
{ label: '上次登录时间', value: 'last_login' },
{ label: this.$t('cs.companyStructure.nickname'), value: 'nickname' },
{ label: this.$t('cs.companyStructure.username'), value: 'username' },
{ label: this.$t('cs.companyStructure.email'), value: 'email' },
{ label: this.$t('cs.companyStructure.sex'), value: 'sex' },
{ label: this.$t('cs.companyStructure.mobile'), value: 'mobile' },
{ label: this.$t('cs.companyStructure.departmentName'), value: 'department_name' },
{ label: this.$t('cs.companyStructure.positionName'), value: 'position_name' },
{ label: this.$t('cs.companyStructure.supervisor'), value: 'direct_supervisor_id' },
{ label: this.$t('cs.companyStructure.annualLeave'), value: 'annual_leave' },
{ label: this.$t('cs.companyStructure.virtualAnnualLeave'), value: 'virtual_annual_leave' },
{ label: this.$t('cs.companyStructure.parentingLeave'), value: 'parenting_leave' },
{ label: this.$t('cs.companyStructure.entryDate'), value: 'entry_date' },
{ label: this.$t('cs.companyStructure.isInternship'), value: 'is_internship' },
{ label: this.$t('cs.companyStructure.leaveDate'), value: 'leave_date' },
{ label: this.$t('cs.companyStructure.idCard'), value: 'id_card' },
{ label: this.$t('cs.companyStructure.nation'), value: 'nation' },
{ label: this.$t('cs.companyStructure.idPlace'), value: 'id_place' },
{ label: this.$t('cs.companyStructure.party'), value: 'party' },
{ label: this.$t('cs.companyStructure.householdRegistrationType'), value: 'household_registration_type' },
{ label: this.$t('cs.companyStructure.hometown'), value: 'hometown' },
{ label: this.$t('cs.companyStructure.marry'), value: 'marry' },
{ label: this.$t('cs.companyStructure.maxDegree'), value: 'max_degree' },
{ label: this.$t('cs.companyStructure.emergencyPerson'), value: 'emergency_person' },
{ label: this.$t('cs.companyStructure.emergencyPhone'), value: 'emergency_phone' },
{ label: this.$t('cs.companyStructure.bankCardNumber'), value: 'bank_card_number' },
{ label: this.$t('cs.companyStructure.bankCardName'), value: 'bank_card_name' },
{ label: this.$t('cs.companyStructure.openingBank'), value: 'opening_bank' },
{ label: this.$t('cs.companyStructure.accountOpeningLocation'), value: 'account_opening_location' },
{ label: this.$t('cs.companyStructure.school'), value: 'school' },
{ label: this.$t('cs.companyStructure.major'), value: 'major' },
{ label: this.$t('cs.companyStructure.education'), value: 'education' },
{ label: this.$t('cs.companyStructure.graduationYear'), value: 'graduation_year' },
{ label: this.$t('cs.companyStructure.childrenName'), value: 'name' },
{ label: this.$t('cs.companyStructure.childrenGender'), value: 'gender' },
{ label: this.$t('cs.companyStructure.childrenBirthday'), value: 'birthday' },
{ label: this.$t('cs.companyStructure.leftParentingLeave'), value: 'parental_leave_left' },
{ label: this.$t('cs.companyStructure.birthDate'), value: 'birth_date' },
{ label: this.$t('cs.companyStructure.nationalityRegion'), value: 'nationality_region' },
{ label: this.$t('cs.companyStructure.birthPlace'), value: 'birth_place' },
{ label: this.$t('cs.companyStructure.firstEntryDate'), value: 'first_entry_date' },
{ label: this.$t('cs.companyStructure.estimatedDepartureDate'), value: 'estimated_departure_date' },
{ label: this.$t('cs.companyStructure.role'), value: 'roles' },
{ label: this.$t('cs.companyStructure.lastLogin'), value: 'last_login' },
]
const checkedCols = JSON.parse(localStorage.getItem('setting-table-CheckedCols')) || [
'nickname',
@ -889,7 +990,6 @@ export default {
'roles',
'last_login',
'current_company',
'dfc_entry_date',
'is_internship',
'entry_date',
'leave_date',
@ -924,24 +1024,28 @@ export default {
visible: false,
tableDragClassName: [], // 表格拖拽的参数
attributes: [],
internMap: [
{
id: 0,
label: '正式',
},
{
id: 1,
label: '实习生',
},
],
internOptions: [
{ label: '正式', value: 0 },
{ label: '实习生', value: 1 },
],
}
},
inject: ['provide_allFlatEmployees', 'provide_allFlatDepartments'],
computed: {
internOptions() {
return [
{ label: this.$t('cs.companyStructure.fullTime'), value: 0 },
{ label: this.$t('cs.companyStructure.internship'), value: 1 },
]
},
internMap() {
return [
{
id: 0,
label: this.$t('cs.companyStructure.fullTime'),
},
{
id: 1,
label: this.$t('cs.companyStructure.internship'),
},
]
},
allFlatEmployees() {
return this.provide_allFlatEmployees()
},
@ -956,9 +1060,6 @@ export default {
Bus.$on('reqExportSelectEvent', () => {
this.exportExcel()
})
this.options = this.options
.filter((item) => item.label !== '目前所属主体')
.filter((item) => item.label !== '初始入职日期')
this.unsbmitCheckedCols = this.checkedCols
},
beforeDestroy() {
@ -1064,8 +1165,8 @@ export default {
removeEmployee(row) {
const that = this
this.$confirm({
title: '提示',
content: '确认移除该员工?',
title: that.$t('warning'),
content: that.$t('cs.role.confirmRemoveEmployee'),
onOk() {
that.$emit('removeEmployee', row)
},
@ -1140,7 +1241,7 @@ export default {
useStyle: true, // 是否导出样式
isFooter: false, // 是否导出表尾比如合计
// 过滤那个字段导出
columnFilterMethod: function (column, $columnIndex) {
columnFilterMethod: function(column, $columnIndex) {
return !(column.$columnIndex === 0)
// 0是复选框 不导出
},

View File

@ -3,12 +3,12 @@
:disable-branch-nodes="multiple ? false : true"
:multiple="multiple"
:options="employeeTreeSelectOption"
placeholder="请选择员工"
:placeholder="readOnly ? '' : placeholder || $t('cs.components.selectEmployee')"
v-model="treeValue"
:max-height="200"
noChildrenText=""
noOptionsText=""
:class="className ? className: 'ops-setting-treeselect'"
:noChildrenText="$t('cs.components.empty')"
:noOptionsText="$t('cs.components.empty')"
:class="className ? className : 'ops-setting-treeselect'"
value-consists-of="LEAF_PRIORITY"
:limit="20"
:limitText="(count) => `+ ${count}`"
@ -42,13 +42,37 @@ export default {
},
className: {
type: String,
default: 'ops-setting-treeselect'
}
default: 'ops-setting-treeselect',
},
placeholder: {
type: String,
default: '',
},
idType: {
type: Number,
default: 1,
},
departmentKey: {
type: String,
default: 'department_id',
},
employeeKey: {
type: String,
default: 'employee_id',
},
},
data() {
return {}
},
inject: ['provide_allTreeDepAndEmp'],
inject: {
provide_allTreeDepAndEmp: {
from: 'provide_allTreeDepAndEmp',
},
readOnly: {
from: 'readOnly',
default: false,
},
},
computed: {
treeValue: {
get() {
@ -63,12 +87,11 @@ export default {
return this.provide_allTreeDepAndEmp()
},
employeeTreeSelectOption() {
return formatOption(this.allTreeDepAndEmp)
return formatOption(this.allTreeDepAndEmp, this.idType, false, this.departmentKey, this.employeeKey)
},
},
methods: {},
}
</script>
<style scoped>
</style>
<style scoped></style>

View File

@ -1,5 +1,5 @@
<template>
<a-modal title="关联员工" :visible="visible" @cancel="handleCancel" @ok="handleOK">
<a-modal :title="$t('cs.role.associatedEmployees')" :visible="visible" @cancel="handleCancel" @ok="handleOK">
<EmployeeTreeSelect v-model="values" :multiple="true" />
</a-modal>
</template>

View File

@ -1,20 +1,22 @@
import i18n from '@/lang'
export const ruleTypeList = [
{ value: '&', label: '与' },
{ value: '|', label: '或' },
{ value: '&', label: i18n.t('cs.components.and') },
{ value: '|', label: i18n.t('cs.components.or') },
// { value: 'not', label: '非' },
]
export const expList = [
{ value: 1, label: '等于' },
{ value: 2, label: '不等于' },
{ value: 1, label: i18n.t('cs.components.equal') },
{ value: 2, label: i18n.t('cs.components.notEqual') },
// { value: 'contain', label: '包含' },
// { value: '~contain', label: '不包含' },
// { value: 'start_with', label: '以...开始' },
// { value: '~start_with', label: '不以...开始' },
// { value: 'end_with', label: '以...结束' },
// { value: '~end_with', label: '不以...结束' },
{ value: 7, label: '为空' }, // 为空的定义有点绕
{ value: 8, label: '不为空' },
{ value: 7, label: i18n.t('cs.components.isEmpty') }, // 为空的定义有点绕
{ value: 8, label: i18n.t('cs.components.isNotEmpty') },
]
export const advancedExpList = [
@ -22,12 +24,12 @@ export const advancedExpList = [
// { value: '~in', label: '非in查询' },
// { value: 'range', label: '范围' },
// { value: '~range', label: '范围外' },
{ value: 'compare', label: '比较' },
{ value: 'compare', label: i18n.t('cs.components.compare') },
]
export const compareTypeList = [
{ value: 5, label: '大于' },
{ value: 5, label: i18n.t('cs.components.moreThan') },
// { value: '2', label: '>=' },
{ value: 6, label: '小于' },
{ value: 6, label: i18n.t('cs.components.lessThan') },
// { value: '4', label: '<=' },
]

View File

@ -7,7 +7,7 @@
@visibleChange="visibleChange"
>
<slot name="popover_item">
<a-button type="primary" ghost>条件过滤<a-icon type="filter"/></a-button>
<a-button type="primary" ghost>{{ $t('cs.components.conditionFilter') }}<a-icon type="filter"/></a-button>
</slot>
<template slot="content">
<svg
@ -106,7 +106,7 @@
searchable
v-if="isChoiceByProperty(item.column) && (item.operator === 1 || item.operator === 2)"
:options="getChoiceValueByProperty(item.column)"
placeholder="请选择"
:placeholder="$t('cs.components.selectPlaceholder')"
:normalizer="
(node) => {
return {
@ -133,26 +133,26 @@
v-else-if="item.operator !== 7 && item.operator !== 8"
size="small"
v-model="item.value"
:placeholder="item.exp === 'in' || item.exp === '~in' ? '以 ; 分隔' : ''"
:placeholder="item.exp === 'in' || item.exp === '~in' ? $t('cs.components.operatorInPlaceholder') : ''"
class="ops-input"
></a-input>
<!-- <div v-else :style="{ width: '175px' }"></div> -->
<a-tooltip title="复制">
<a-tooltip :title="$t('cs.components.copy')">
<a class="operation" @click="handleCopyRule(item)"><a-icon type="copy"/></a>
</a-tooltip>
<a-tooltip title="删除">
<a-tooltip :title="$t('delete')">
<a class="operation" @click="handleDeleteRule(item)" :style="{ color: 'red' }"><a-icon type="delete"/></a>
</a-tooltip>
</a-space>
<div class="table-filter-add">
<a @click="handleAddRule">+ 新增</a>
<a @click="handleAddRule">+ {{ $t('new') }}</a>
</div>
<a-divider :style="{ margin: '10px 0' }" />
<div style="width:534px">
<a-space :style="{ display: 'flex', justifyContent: 'flex-end' }">
<a-button type="primary" size="small" @click="handleSubmit">确定</a-button>
<a-button size="small" @click="handleClear">清空</a-button>
<a-button type="primary" size="small" @click="handleSubmit">{{ $t('confirm') }}</a-button>
<a-button size="small" @click="handleClear">{{ $t('clear') }}</a-button>
</a-space>
</div>
</template>

View File

@ -0,0 +1,443 @@
const cs_en = {
menu: {
person: 'Personal Center',
companyInfo: 'Company Info',
companyStructure: 'Company Structure',
notice: 'Notification Settings',
email: 'Email Settings',
wx: 'WeChat Work',
dingding: 'DingTalk',
feishu: 'Feishu',
auth: 'Auth Settings',
role: 'Role Management',
sys: 'System Role',
technician: 'Technician Role',
user: 'User Role',
group: 'User Group',
duty: 'Duty Management',
},
companyInfo: {
spanCompany: 'Description',
name: 'Company Name',
nameValidate: 'Please enter name',
description: 'Description',
spanAddress: 'Address',
country: 'Country/Region',
city: 'City',
address: 'Address',
postcode: 'Postal Code',
spanContract: 'Contact Information',
spanLogo: 'Company Logo',
website: 'Website',
phone: 'Phone Number',
phoneValidate: 'Please enter a valid phone number',
faxCode: 'Fax Number',
faxCodeValidate: 'Please enter a valid fax number',
email: 'Email',
emailValidate: 'Please enter a valid email address',
messenger: 'Messenger Address',
domainName: 'Deployment Domain',
logo: 'Company Logo',
upload: 'Upload',
editCompanyLogo: 'Edit Company Logo',
editCompanyLogoSmall: 'Edit Company Logo Thumbnail',
imageSizeLimit2MB: 'Image size does not exceed 2MB',
checkInputCorrect: 'Please check if the input content is correct',
},
companyStructure: {
batchImport: 'Batch Import',
batchEdit: 'Batch Edit',
selectFile: 'Select File',
clickDownloadImportTemplate: 'Click to download Employee Import Template',
importSuccess: 'Imported total {allCount} items, imported successfully',
importFailed: 'Import failed',
count: 'items',
email: 'Email',
emailPlaceholder: 'Please enter email',
emailFormatErr: 'Email format error',
username: 'Username',
usernamePlaceholder: 'Please enter username',
nickname: 'Full Name',
nicknamePlaceholder: 'Please enter full name',
password: 'Password',
passwordPlaceholder: 'Please enter password',
sex: 'Gender',
sexPlaceholder: 'Please select gender',
male: 'Male',
female: 'Female',
mobile: 'Mobile Number',
mobilePlaceholder: 'Please enter mobile number',
mobileFormatErr: 'Please enter a valid mobile number',
positionName: 'Position',
positionNamePlaceholder: 'Please enter position',
employee: 'Employee',
departmentName: 'Department',
currentCompany: 'Current Company',
currentCompanyPlaceholder: 'Please select current company',
dfcEntryDate: 'Initial Entry Date',
dfcEntryDatePlaceholder: 'Please select initial entry date',
entryDate: 'Current Company Entry Date',
entryDatePlaceholder: 'Please select current company entry date',
isInternship: 'Full-time/Intern',
isInternshipPlaceholder: 'Please select full-time/intern',
internship: 'Intern',
fullTime: 'Full-time',
leaveDate: 'Resignation Date',
leaveDatePlaceholder: 'Please select resignation date',
idCard: 'ID Card Number',
idCardPlaceholder: 'Please enter ID card number',
nation: 'Ethnicity',
nationPlaceholder: 'Please select ethnicity',
idPlace: 'Native Place',
idPlacePlaceholder: 'Please enter native place',
party: 'Political Affiliation',
partyPlaceholder: 'Please select political affiliation',
partyMember: 'Party Member',
member: 'League Member',
masses: 'Masses',
householdRegistrationType: 'Residency Type',
householdRegistrationTypePlaceholder: 'Please select residency type',
town: 'Urban',
agriculture: 'Rural',
hometown: 'Residence Location',
hometownPlaceholder: 'Please enter residence location',
marry: 'Marital Status',
unmarried: 'Unmarried',
married: 'Married',
marryPlaceholder: 'Please select marital status',
maxDegree: 'Highest Degree',
maxDegreePlaceholder: 'Please select highest degree',
phd: 'PhD',
master: 'Master',
undergraduate: 'Bachelor',
specialist: 'Associate',
highSchool: 'High School',
technicalSecondaryOrHighSchool: 'Technical/High School',
juniorHighSchool: 'Junior High School',
primarySchool: 'Primary School',
emergencyPerson: 'Emergency Contact',
emergencyPersonPlaceholder: 'Please enter emergency contact',
emergencyPhone: 'Emergency Contact Number',
emergencyPhonePlaceholder: 'Please enter emergency contact number',
bankCardInfo: 'Bank Card',
bankCardNumber: 'Bank Card Number',
bankCardNumberPlaceholder: 'Please enter bank card number',
bankCardName: 'Bank',
bankCardNamePlaceholder: 'Please enter bank',
openingBank: 'Issuing Bank',
openingBankPlaceholder: 'Please enter issuing bank',
accountOpeningLocation: 'Account Opening Location',
accountOpeningLocationPlaceholder: 'Please enter account opening location',
school: 'Graduated School',
schoolPlaceholder: 'Please enter graduated school',
major: 'Major',
majorPlaceholder: 'Please enter major',
education: 'Education',
educationPlaceholder: 'Please select education',
educationalExperience: 'Education History',
graduationYear: 'Graduation Year',
graduationYearPlaceholder: 'Please select graduation year',
birthDate: 'Date of Birth',
birthDatePlaceholder: 'Please select date of birth',
birthPlace: 'Place of Birth',
birthPlacePlaceholder: 'Please enter place of birth',
nationalityRegion: 'Nationality/Region',
nationalityRegionPlaceholder: 'Please select nationality/region',
firstEntryDate: 'First Entry Date',
firstEntryDatePlaceholder: 'Please select first entry date',
estimatedDepartureDate: 'Estimated Departure Date',
estimatedDepartureDatePlaceholder: 'Please select estimated departure date',
lastLogin: 'Last Login Time',
importFailedReason: 'Failure Reason',
selectDepartment: 'Select Department',
supervisor: 'Supervisor',
editDirectSupervisor: 'Edit Supervisor',
selectDirectSupervisor: 'Select Supervisor',
annualLeave: 'Annual Leave',
editPosition: 'Edit Position',
editAnnualLeave: 'Edit Annual Leave',
annualLeavePlaceholder: 'Please enter annual leave',
virtualAnnualLeave: 'Virtual Annual Leave',
virtualAnnualLeavePlaceholder: 'Please enter virtual annual leave',
parentingLeave: 'Parenting Leave',
leftParentingLeave: 'Remaining Parenting Leave',
parentingLeavePlaceholder: 'Please enter parenting leave',
day: 'day(s)',
resetPassword: 'Reset Password',
confirmPassword: 'Confirm Password',
block: 'Disable',
blockUserConfirm: 'This user will be disabled, continue?',
batchBlockUserConfirm: 'These users will be disabled, continue?',
recover: 'Recover',
recoverUserConfirm: 'This user will be recovered, continue?',
batchRecoverUserConfirm: 'These users will be recovered, continue?',
opFailed: 'Operation failed',
opSuccess: 'Operation successful',
createSubDepartment: 'Create Sub-department',
editDepartment: 'Edit Department',
deleteDepartment: 'Delete Department',
downloadAll: 'Download All',
downloadSelected: 'Download Selected',
departmentLabel: 'Department Name',
departmentLabelPlaceholder: 'Please enter department name',
parentDepartment: 'Parent Department',
parentDepartmentPlaceholder: 'Please select parent department',
departmentDirector: 'Department Director',
childrenInformation: 'Children Information',
childrenName: 'Children Name',
childrenGender: 'Children Gender',
childrenBirthday: 'Children Birthday',
allEmployee: 'All Employees',
activeEmployee: 'Active',
blockEmployee: 'Disabled',
prevStep: 'Previous',
nextStep: 'Next',
done: 'Done',
uploadFile: 'Upload File',
confirmData: 'Confirm Data',
uploadDone: 'Upload Done',
dataErr: 'Data Error',
createEmployee: 'Create Employee',
editEmployee: 'Edit Employee',
role: 'Role',
selectDisplayColumn: 'Please select columns to display'
},
auth: {
basic: 'Basic',
other: 'Other',
isEnable: 'Is Enabled',
common: 'Common',
testConnect: 'Test Connection',
testLogin: 'Test Login',
testSuccess: 'Test Successful',
ldap: {
serverAddress: 'Server Address',
serverAddressHelp: 'E.g. 192.168.1.6 or ldap://192.168.1.6 or ldap://192.168.1.6:389',
serverAddressPlaceholder: 'Please enter server address',
domain: 'Domain',
domainPlaceholder: 'Please enter domain',
user: 'User',
username: 'Username',
userPlaceholder: 'Please enter username',
userHelp: 'User DN: cn={},ou=users,dc=xxx,dc=com {} will be replaced by username'
},
cas: {
server: 'Server Address',
serverHelp: 'Without url path, e.g. https://xxx.com',
serverPlaceholder: 'Please enter CAS server address',
validateServer: 'Validation Server Address',
validateServerHelp: 'Without url path, e.g. https://xxx.com',
validateServerPlaceholder: 'Please enter validation server address',
loginRoute: 'Login Route',
loginRoutePlaceholder: 'Please enter login route',
logoutRoute: 'Logout Route',
logoutRoutePlaceholder: 'Please enter logout route',
validateRoute: 'Validate Route',
validateRoutePlaceholder: 'Please enter validate route',
afterLoginRoute: 'Redirect Route',
afterLoginRoutePlaceholder: 'Please enter redirect route',
userMap: 'User Attribute Mapping'
},
autoRedirectLogin: 'Auto Redirect to Third-party Login Page',
autoRedirectLoginHelp: 'If disabled, a confirmation will be displayed to redirect to third-party login page. Click the Cancel button will go to the built-in login page',
usernameOrEmail: 'Username/Email',
usernameOrEmailPlaceholder: 'Please enter username/email',
password: 'Password',
passwordPlaceholder: 'Please enter password',
oauth2: {
clientId: 'Client ID',
clientIdPlaceholder: 'Please enter client ID',
clientSecret: 'Client Secret',
clientSecretPlaceholder: 'Please enter client secret',
authorizeUrl: 'Authorize URL',
authorizeUrlPlaceholder: 'Please enter authorize URL',
tokenUrl: 'Token URL',
tokenUrlPlaceholder: 'Please enter token URL',
userInfo: 'User Info',
scopes: 'Scopes',
scopesPlaceholder: 'Please enter scopes',
}
},
duty: {
basicSetting: 'Basic Settings',
ruleName: 'Title',
ruleNamePlaceholder: 'Please enter title',
principalId: 'Person in Charge',
specifyId: 'Appointee',
principalIdPlaceholder: 'Please select person in charge/single select',
remark: 'Remark',
remarkPlaceholder: 'Please enter remark',
remindTime: 'Duty Remind Time',
remindWay: 'Remind Way',
remindPeople: 'Remind People',
mainDutyPeople: 'Main Duty Person',
deputyDutyPeople: 'Deputy Duty Person',
dutyRule: 'Duty Rule',
'一': 'Mon',
'二': 'Tue',
'三': 'Wed',
'四': 'Thu',
'五': 'Fri',
'六': 'Sat',
'日': 'Sun',
searchPlaceholder: 'Please search',
dutyTable: 'Duty Schedule',
dutyMember: 'Duty Member',
dutyMemberPlaceholder: 'Please select duty member',
startDutyMember: 'Start Duty Member',
startEndDate: 'Start End Date',
startEndDatePlaceholder: 'Please select start end date',
dutyPeriod: 'Duty Period',
dutyFrequency: 'Duty Frequency',
fullDay: 'Full Day',
specifyTime: 'Specify Time',
monthDayFormat: 'MM/DD',
week: 'Week',
month: 'Month',
hour: 'Hour',
min: 'min',
before: 'Before',
fixed: 'Fixed Time',
removeHolidays: 'Remove Holidays',
offDutyReceiver: 'Off-duty Receiver',
offDutyReceiverPlaceholder: 'Please select off-duty receiver',
titleLimit: 'Please enter title (20 characters)',
remarkLimit: 'Remark 150 characters max',
frequencyLimit: 'Please enter duty frequency (positive integer)'
},
group: {
groupName: 'User Group',
groupNamePlaceholder: 'Please enter user group',
addGroup: 'Add Group',
editGroup: 'Edit Group',
},
components: {
preview: 'Preview',
copy: 'Copy',
editAvatar: 'Edit Avatar',
conditionFilter: 'Condition Filter',
selectPlaceholder: 'Please select',
empty: 'Empty',
and: 'And',
or: 'Or',
equal: 'Equal',
notEqual: 'Not Equal',
isEmpty: 'Is Empty',
isNotEmpty: 'Is Not Empty',
compare: 'Compare',
moreThan: 'More Than',
lessThan: 'Less Than',
operatorInPlaceholder: 'Separate by ;',
selectEmployee: 'Select Employee'
},
notice: {
corpid: 'Corp ID',
agentid: 'Self-built App ID',
corpsecret: 'Self-built App Secret',
itsmAppId: 'ITSM App ID',
robot: 'Robot',
selectRobot: 'Please select robot',
robotConfigErrorTips: 'Please fill out robot configuration completely',
webhookAddress: 'Webhook Address',
appKey: 'App Key',
appSecret: 'App Secret',
robotCode: 'Robot Code',
sendServer: 'Outgoing Server',
connectProtocol: 'Connection Protocol',
ews: 'EWS(Exchange Web Services)',
authType: 'Auth Type',
base: 'Base',
oauth: 'OAuth',
ip: 'Server Name/IP Address',
username: 'Username',
password: 'Password',
email: 'Email Address',
emailType: 'Email Type',
port: 'Port',
testEmailConfig: 'Test Email Settings',
testRecyclingBin: 'Test Recycle Bin',
receiveEmailFailed: 'Receive email failed',
emailServiceNotConfig: 'Email server is not configured, please configure one email server',
troubleshooting: 'Troubleshooting',
emailConfig: 'Email Settings',
receiveEmailInterval: 'Get Email Interval',
startProxyServer: 'Start Proxy Server',
configProxyServer: 'Config Proxy Server',
startEmailTest: 'Start Email Test',
disableCreationOfRequestsViaEmail: 'Disable Creation of Requests Via Email',
specifyAllowedEmails: 'Specify Allowed Emails/Domains, Separate Multiple Values By Comma',
specifyAllowedEmailsExample: 'E.g. user@domain.com,*@domain.com',
specifyAllowedEmailsLimit: 'Limit cannot apply to requests already in sessions, it will aggregate to its parent ticket',
messageConfig: 'Message Settings',
moveWrongMessagesToFolder: 'Move Messages to Wrong Folder',
knowMore: 'Learn More',
configProxySettings: 'Config Proxy Settings',
host: 'Host',
isEncrypted: 'Is Encrypted',
emailTest: 'Email Test',
testSendAddress: 'Test Send Email Address',
testMailSend: 'Test Mail Send',
portPlaceholder: 'Please enter port',
testSendAddressPlaceholder: 'Please enter test send email address',
emailSendSuccess: 'Email Send Success',
title: 'Title',
},
person: {
spanTitle: 'Personal Info',
accountAndPassword: 'Account Password',
avatar: 'Avatar',
changeAvatar: 'Change Avatar',
email: 'Email',
wechatApp: 'WeChat Work',
feishuApp: 'Feishu',
dingdingApp: 'DingTalk',
bindInfo: 'Bind Info',
newPassword: 'New Password',
confirmPassword: 'Confirm Password',
pleaseConfirmNewPasswordSecondTime: 'Please confirm new password again',
thePasswordEnteredTwiceIsInconsistent: 'The password entered twice is inconsistent',
inputStrCountLimit20: 'Character count must be less than 20',
inputStrCountLimit: 'Character count must be less than {limit}',
alert: 'Warning',
confirmUnbind: 'Confirm unbind?',
unbindSuccess: 'Unbind successful',
bindSuccess: 'Bind successful',
},
role: {
systemRole: 'System Role',
technicianRole: 'Technician Role',
userRole: 'User Role',
authorizedByTheCreator: 'Authorized By The Creator',
authorizeAccordingToRules: 'Authorize According To Rules',
expression: 'Expression',
matchResults: 'Match Results',
matchResultEmpty: 'Empty',
pleaseFillInTheCompleteRules: 'Please fill in the complete rules',
roleName: 'Role Name',
pleaseEnterRoleName: 'Please enter role name',
appName: 'App Name',
pleaseEnterAppName: 'Please enter app name',
createRole: 'Create Role',
editRole: 'Edit Role',
copyRole: 'Copy Role From {roleName}',
associatedEmployees: 'Associated Employees',
inputNameOrEmail: 'Enter Name/Email',
remove: 'Remove',
confirmRemoveEmployee: 'Confirm remove this employee?',
removeSuccess: 'Remove successful',
associatedSuccess: 'Associate successful',
roleEmployee: 'Role Employee',
operationPermission: 'Operation Permission',
dataPermission: 'Data Permission',
confirmDeleteRole: 'Confirm delete role [{roleName}]?',
deleteRoleSuccess: 'Delete successful',
mySelf: 'My self',
mySubordinates: 'My Subordinates',
myDepartment: 'My Department',
myDepartmentAndSubordinateDepartments: 'My Department And Subordinate Departments',
test: 'Test',
selectApp: 'Select App',
}
}
export default cs_en

View File

@ -0,0 +1,442 @@
const cs_zh = {
menu: {
person: '个人中心',
companyInfo: '公司信息',
companyStructure: '公司架构',
notice: '通知设置',
email: '邮件设置',
wx: '企业微信',
dingding: '钉钉',
feishu: '飞书',
auth: '认证设置',
role: '角色管理',
sys: '系统角色',
technician: '技术员角色',
user: '用户角色',
group: '用户分组',
duty: '值班管理',
},
companyInfo: {
spanCompany: '公司描述',
name: '公司名称',
nameValidate: '请输入名称',
description: '描述',
spanAddress: '公司地址',
country: '国家/地区',
city: '城市',
address: '地址',
postcode: '邮政编码',
spanContract: '联系方式',
spanLogo: '公司标识',
website: '网站',
phone: '电话号码',
phoneValidate: '请输入正确的电话号码',
faxCode: '传真号码',
faxCodeValidate: '请输入正确的传真号码',
email: '邮箱',
emailValidate: '请输入正确的邮箱地址',
messenger: 'Messenger地址',
domainName: '部署域名',
logo: '公司logo',
upload: '上传',
editCompanyLogo: '编辑公司logo',
editCompanyLogoSmall: '编辑公司logo缩略图',
imageSizeLimit2MB: '图片大小不超过2MB',
checkInputCorrect: '请检查输入内容是否正确',
},
companyStructure: {
batchImport: '批量导入',
batchEdit: '批量编辑',
selectFile: '选择文件',
clickDownloadImportTemplate: '点击下载《员工导入模板》',
importSuccess: '导入总数据 {allCount} 条, 导入成功',
importFailed: '导入失败',
count: '条',
email: '邮箱',
emailPlaceholder: '请输入邮箱',
emailFormatErr: '邮箱格式错误',
username: '用户名',
usernamePlaceholder: '请输入用户名',
nickname: '姓名',
nicknamePlaceholder: '请输入姓名',
password: '密码',
passwordPlaceholder: '请输入密码',
sex: '性别',
sexPlaceholder: '请选择性别',
male: '男',
female: '女',
mobile: '手机号',
mobilePlaceholder: '请输入手机号',
mobileFormatErr: '请输入正确的手机号',
positionName: '岗位',
positionNamePlaceholder: '请输入岗位',
employee: '员工',
departmentName: '部门',
currentCompany: '目前所属主体',
currentCompanyPlaceholder: '请选择目前所属主体',
dfcEntryDate: '初始入职日期',
dfcEntryDatePlaceholder: '请选择初始入职日期',
entryDate: '目前主体入职日期',
entryDatePlaceholder: '请选择目前主体入职日期',
isInternship: '正式/实习生',
isInternshipPlaceholder: '请选择正式/实习生',
internship: '实习生',
fullTime: '正式',
leaveDate: '离职日期',
leaveDatePlaceholder: '请选择离职日期',
idCard: '身份证号',
idCardPlaceholder: '请输入身份证号',
nation: '民族',
nationPlaceholder: '请选择民族',
idPlace: '籍贯',
idPlacePlaceholder: '请输入籍贯',
party: '组织关系',
partyPlaceholder: '请选择组织关系',
partyMember: '党员',
member: '团员',
masses: '群众',
householdRegistrationType: '户籍类型',
householdRegistrationTypePlaceholder: '请选择户籍类型',
town: '城镇',
agriculture: '农业',
hometown: '户口所在地',
hometownPlaceholder: '请输入户口所在地',
marry: '婚姻状况',
unmarried: '未婚',
married: '已婚',
marryPlaceholder: '请选择婚姻状况',
maxDegree: '最高学历',
maxDegreePlaceholder: '请选择最高学历',
phd: '博士',
master: '硕士',
undergraduate: '本科',
specialist: '专科',
highSchool: '高中',
technicalSecondaryOrHighSchool: '中专/高中',
juniorHighSchool: '初中',
primarySchool: '小学',
emergencyPerson: '紧急联系人',
emergencyPersonPlaceholder: '请输入紧急联系人',
emergencyPhone: '紧急联系人电话',
emergencyPhonePlaceholder: '请输入紧急联系人电话',
bankCardInfo: '银行卡',
bankCardNumber: '银行卡号',
bankCardNumberPlaceholder: '请输入银行卡号',
bankCardName: '银行',
bankCardNamePlaceholder: '请输入银行',
openingBank: '开户行',
openingBankPlaceholder: '请输入开户行',
accountOpeningLocation: '开户地',
accountOpeningLocationPlaceholder: '请输入开户地',
school: '毕业学校',
schoolPlaceholder: '请输入毕业学校',
major: '专业',
majorPlaceholder: '请输入专业',
education: '学历',
educationPlaceholder: '请选择学历',
educationalExperience: '教育经历',
graduationYear: '毕业年份',
graduationYearPlaceholder: '请选择毕业年份',
birthDate: '出生日期',
birthDatePlaceholder: '请选择出生日期',
birthPlace: '出生地',
birthPlacePlaceholder: '请输入出生地',
nationalityRegion: '国籍/地区',
nationalityRegionPlaceholder: '请选择国籍/地区',
firstEntryDate: '首次入境日期',
firstEntryDatePlaceholder: '请选择首次入境日期',
estimatedDepartureDate: '预计离境日期',
estimatedDepartureDatePlaceholder: '请选择预计离境日期',
lastLogin: '上次登录时间',
importFailedReason: '失败原因',
selectDepartment: '选择部门',
supervisor: '上级',
editDirectSupervisor: '编辑上级',
selectDirectSupervisor: '选择上级',
annualLeave: '年假',
editPosition: '编辑岗位',
editAnnualLeave: '编辑年假',
annualLeavePlaceholder: '请输入年假',
virtualAnnualLeave: '虚拟年假',
virtualAnnualLeavePlaceholder: '请输入虚拟年假',
parentingLeave: '育儿假',
leftParentingLeave: '剩余育儿假',
parentingLeavePlaceholder: '请输入育儿假',
day: '天',
resetPassword: '重置密码',
confirmPassword: '确认密码',
block: '禁用',
blockUserConfirm: '该用户将会被禁用,是否继续?',
batchBlockUserConfirm: '这些用户将会被禁用,是否继续?',
recover: '恢复',
recoverUserConfirm: '该用户将会被恢复,是否继续?',
batchRecoverUserConfirm: '这些用户将会被恢复,是否继续?',
opFailed: '操作失败',
opSuccess: '操作成功',
createSubDepartment: '创建子部门',
editDepartment: '编辑部门',
deleteDepartment: '删除部门',
downloadAll: '下载全部',
downloadSelected: '下载选中',
departmentLabel: '部门名称',
departmentLabelPlaceholder: '请输入部门名称',
parentDepartment: '上级部门',
parentDepartmentPlaceholder: '请选择上级部门',
departmentDirector: '部门负责人',
childrenInformation: '子女信息',
childrenName: '子女姓名',
childrenGender: '子女性别',
childrenBirthday: '子女出生日期',
allEmployee: '全部',
activeEmployee: '在职员工',
blockEmployee: '停用员工',
prevStep: '上一步',
nextStep: '下一步',
done: '完成',
uploadFile: '上传文件',
confirmData: '确认数据',
uploadDone: '上传完成',
dataErr: '数据有误',
createEmployee: '新建员工',
editEmployee: '编辑员工',
role: '角色',
selectDisplayColumn: '请选择需要展示的列'
},
auth: {
basic: '基本',
other: '其他',
isEnable: '是否启用',
common: '通用',
testConnect: '测试连接',
testLogin: '测试登录',
testSuccess: '测试成功',
ldap: {
serverAddress: '服务器地址',
serverAddressHelp: '例如: 192.168.1.6 或者 ldap://192.168.1.6 或者 ldap://192.168.1.6:389',
serverAddressPlaceholder: '请输入服务器地址',
domain: '域',
domainPlaceholder: '请输入域',
user: '用户',
username: '用户名称',
userPlaceholder: '请输入用户名称',
userHelp: '用户dn: cn={},ou=users,dc=xxx,dc=com {}会替换成用户名'
},
cas: {
server: '服务端地址',
serverHelp: '不包括url path例如https://xxx.com',
serverPlaceholder: '请输入cas服务器地址',
validateServer: '验证服务端地址',
validateServerHelp: '不包括url path例如https://xxx.com',
validateServerPlaceholder: '请输入验证服务端地址',
loginRoute: '登录路由',
loginRoutePlaceholder: '请输入登录路由',
logoutRoute: '注销路由',
logoutRoutePlaceholder: '请输入注销路由',
validateRoute: '验证路由',
validateRoutePlaceholder: '请输入验证路由',
afterLoginRoute: '重定向路由',
afterLoginRoutePlaceholder: '请输入重定向路由',
userMap: '用户属性映射'
},
autoRedirectLogin: '自动跳转到第三方登录页',
autoRedirectLoginHelp: '如果关闭,则会弹出跳转到第三方登录页的确认,点取消按钮会进入系统内置的登录页',
usernameOrEmail: '用户名/邮箱',
usernameOrEmailPlaceholder: '请输入用户名/邮箱',
password: '密码',
passwordPlaceholder: '请输入密码',
oauth2: {
clientId: '客户端ID',
clientIdPlaceholder: '请输入客户端ID',
clientSecret: '客户端密钥',
clientSecretPlaceholder: '请输入客户端密钥',
authorizeUrl: '授权链接',
authorizeUrlPlaceholder: '请输入授权链接',
tokenUrl: '令牌链接',
tokenUrlPlaceholder: '请输入令牌链接',
userInfo: '用户信息',
scopes: '授权范围',
scopesPlaceholder: '请输入授权范围',
}
},
duty: {
basicSetting: '基础设置',
ruleName: '标题',
ruleNamePlaceholder: '请输入标题',
principalId: '负责人',
specifyId: '指定人',
principalIdPlaceholder: '请选择负责人/单选',
remark: '备注',
remarkPlaceholder: '请输入备注',
remindTime: '值班提醒时间',
remindWay: '提醒方式',
remindPeople: '提醒人',
mainDutyPeople: '主值班人',
deputyDutyPeople: '副值班人',
dutyRule: '排班规则',
'一': '一',
'二': '二',
'三': '三',
'四': '四',
'五': '五',
'六': '六',
'日': '日',
searchPlaceholder: '请查找',
dutyTable: '值班表',
dutyMember: '值班人员',
dutyMemberPlaceholder: '请选择值班人员',
startDutyMember: '开始值班人员',
startEndDate: '起止日期',
startEndDatePlaceholder: '请选择起止日期',
dutyPeriod: '值班时段',
dutyFrequency: '值班频次',
fullDay: '全天',
specifyTime: '指定时间',
monthDayFormat: 'MM月DD日',
week: '周',
month: '月',
hour: '小时',
min: '分',
before: '提前',
fixed: '固定时间',
removeHolidays: '是否去除节假日',
offDutyReceiver: '非值班时间接收人',
offDutyReceiverPlaceholder: '请选择非值班时间接收人',
titleLimit: '请输入标题20个字符',
remarkLimit: '备注150个字符以内',
frequencyLimit: '请输入值班频次(正整数)'
},
group: {
groupName: '用户分组',
groupNamePlaceholder: '请输入用户分组',
addGroup: '新增分组',
editGroup: '编辑分组',
},
components: {
preview: '预览',
copy: '复制',
editAvatar: '编辑头像',
conditionFilter: '条件过滤',
selectPlaceholder: '请选择',
empty: '空',
and: '与',
or: '或',
equal: '等于',
notEqual: '不等于',
isEmpty: '为空',
isNotEmpty: '不为空',
compare: '比较',
moreThan: '大于',
lessThan: '小于',
operatorInPlaceholder: '以 ; 分隔',
selectEmployee: '选择员工'
},
notice: {
corpid: '企业ID',
agentid: '自建应用ID',
corpsecret: '自建应用密钥',
itsmAppId: 'ITSM应用ID',
robot: '机器人',
selectRobot: '请选择机器人',
robotConfigErrorTips: '请完整填写机器人配置',
webhookAddress: 'Webhook地址',
appKey: '应用Key',
appSecret: '应用密码',
robotCode: '机器人码',
sendServer: '发送服务器',
connectProtocol: '连接协议',
ews: 'EWS(Exchange Web服务)',
authType: '认证类型',
base: '基本',
oauth: 'OAuth',
ip: '服务器名/IP地址',
username: '用户名',
password: '密码',
email: '邮件地址',
emailType: '邮件类型',
port: '端口',
testEmailConfig: '测试邮件设置',
testRecyclingBin: '测试回收箱',
receiveEmailFailed: '接收邮件失败',
emailServiceNotConfig: '邮箱服务器未配置,请配置一个邮箱服务器',
troubleshooting: '故障诊断',
emailConfig: '邮件设置',
receiveEmailInterval: '获取邮件间隔',
startProxyServer: '启动代理服务器',
configProxyServer: '配置代理服务器',
startEmailTest: '启动邮件测试',
disableCreationOfRequestsViaEmail: '禁用通过邮件创建请求',
specifyAllowedEmails: '指定允许的邮件/域名,逗号分隔多个值',
specifyAllowedEmailsExample: '例如:user@domain.com,*@domain.com',
specifyAllowedEmailsLimit: '限制不能适用于已在会话中的请求,它将聚集到它的上级工单中',
messageConfig: '消息设置',
moveWrongMessagesToFolder: '将消息移动到错误的文件夹',
knowMore: '了解更多',
configProxySettings: '配置代理设置',
host: '主机',
isEncrypted: '是否加密',
emailTest: '邮件测试',
testSendAddress: '测试发送邮件地址',
testMailSend: '测试邮件发送',
portPlaceholder: '请输入端口',
testSendAddressPlaceholder: '请输入测试发送邮件地址',
emailSendSuccess: '已发送邮件,请查收',
title: '名称',
},
person: {
spanTitle: '个人信息',
accountAndPassword: '账号密码',
avatar: '头像',
changeAvatar: '更换头像',
email: '邮件',
wechatApp: '企业微信',
feishuApp: '飞书',
dingdingApp: '钉钉',
bindInfo: '绑定信息',
newPassword: '新密码',
confirmPassword: '确认密码',
pleaseConfirmNewPasswordSecondTime: '请再次确认新密码',
thePasswordEnteredTwiceIsInconsistent: '两次输入的密码不一致',
inputStrCountLimit20: '字符数须小于20',
inputStrCountLimit: '字符数须小于{limit}',
alert: '警告',
confirmUnbind: '确认解绑?',
unbindSuccess: '解绑成功',
bindSuccess: '绑定成功',
},
role: {
systemRole: '系统角色',
technicianRole: '技术员角色',
userRole: '用户角色',
authorizedByTheCreator: '按照创建人授权',
authorizeAccordingToRules: '按照规则授权',
expression: '表达式',
matchResults: '匹配结果',
matchResultEmpty: '无',
pleaseFillInTheCompleteRules: '请填写完整的规则',
roleName: '角色名称',
pleaseEnterRoleName: '请输入角色名称',
appName: '应用名称',
pleaseEnterAppName: '请输入应用名称',
createRole: '新建角色',
editRole: '编辑角色',
copyRole: '从 {roleName} 复制角色',
associatedEmployees: '关联员工',
inputNameOrEmail: '请输入姓名/邮箱',
remove: '移除',
confirmRemoveEmployee: '确认移除该员工?',
removeSuccess: '移除成功',
associatedSuccess: '关联成功',
roleEmployee: '角色员工',
operationPermission: '操作权限',
dataPermission: '数据权限',
confirmDeleteRole: '确认删除角色 [{roleName}]?',
deleteRoleSuccess: '删除成功',
mySelf: '本人', // Myself
mySubordinates: '本人及下属', // my subordinates
myDepartment: '本部门', // my department
myDepartmentAndSubordinateDepartments: '本部门及下属部门',
test: '测试',
selectApp: '选择应用',
}
}
export default cs_zh

View File

@ -15,7 +15,7 @@
<vxe-input v-model="row[col.field]" type="text"></vxe-input>
</template>
</vxe-column>
<vxe-column title="操作" width="80" v-if="!disabled">
<vxe-column :title="$t('operation')" width="80" v-if="!disabled">
<template #default="{ row }">
<template v-if="$refs.xTable.isActiveByRow(row)">
<a @click="saveRowEvent(row)"><a-icon type="save"/></a>
@ -27,15 +27,10 @@
</template>
</vxe-column>
</vxe-table>
<div :style="{ color: '#f5222d' }" v-if="errorFlag">请完整填写机器人配置</div>
<a-button
v-if="!disabled"
icon="plus-circle"
class="ops-button-primary"
type="primary"
@click="insertEvent"
>添加</a-button
>
<div :style="{ color: '#f5222d' }" v-if="errorFlag">{{ $t('cs.notice.robotConfigErrorTips') }}</div>
<a-button v-if="!disabled" icon="plus-circle" class="ops-button-primary" type="primary" @click="insertEvent">{{
$t('add')
}}</a-button>
</div>
</template>
@ -45,18 +40,7 @@ export default {
props: {
columns: {
type: Array,
default: () => [
{
field: 'name',
title: '名称',
required: true,
},
{
field: 'url',
title: 'Webhook地址',
required: true,
},
],
default: () => [],
},
disabled: {
type: Boolean,

View File

@ -1,29 +1,29 @@
<template>
<div class="notice-dingding-wrapper" :style="{ height: `${windowHeight - 64}px` }">
<a-form-model ref="dingdingForm" :model="dingdingData" :label-col="labelCol" :wrapper-col="wrapperCol">
<SpanTitle>基础设置</SpanTitle>
<a-form-model-item label="应用Key">
<SpanTitle>{{ $t('cs.duty.basicSetting') }}</SpanTitle>
<a-form-model-item :label="$t('cs.notice.appKey')">
<a-input v-model="dingdingData.appKey" :disabled="!isEditable" />
</a-form-model-item>
<a-form-model-item label="应用密码">
<a-form-model-item :label="$t('cs.notice.appSecret')">
<a-input v-model="dingdingData.appSecret" :disabled="!isEditable" />
</a-form-model-item>
<a-form-model-item label="机器人码">
<a-form-model-item :label="$t('cs.notice.robotCode')">
<a-input v-model="dingdingData.robotCode" :disabled="!isEditable" />
</a-form-model-item>
<a-form-model-item label="机器人">
<a-form-model-item :label="$t('cs.notice.robot')">
<Bot
ref="bot"
:disabled="!isEditable"
:columns="[
{
field: 'name',
title: '名称',
title: $t('cs.notice.title'),
required: true,
},
{
field: 'url',
title: 'Webhook地址',
title: $t('cs.notice.webhookAddress'),
required: true,
},
{
@ -34,7 +34,7 @@
]"
/>
</a-form-model-item>
<!-- <a-form-model-item label="测试邮件设置">
<!-- <a-form-model-item :label="测试邮件设置">
<a-button type="primary" ghost>测试回收箱</a-button>
<br />
<span
@ -47,8 +47,8 @@
<a-row v-if="isEditable">
<a-col :span="16" :offset="3">
<a-form-model-item :label-col="labelCol" :wrapper-col="wrapperCol">
<a-button type="primary" @click="onSubmit"> 保存 </a-button>
<a-button ghost type="primary" style="margin-left: 28px;" @click="resetForm"> 重置 </a-button>
<a-button type="primary" @click="onSubmit"> {{ $t('save') }} </a-button>
<a-button ghost type="primary" style="margin-left: 28px;" @click="resetForm"> {{ $t('reset') }} </a-button>
</a-form-model-item>
</a-col>
</a-row>
@ -106,14 +106,14 @@ export default {
this.$refs.bot.getData(async (flag, bot) => {
if (flag) {
if (this.id) {
await putNoticeConfigByPlatform(this.id, { info: { ...this.dingdingData, bot, label: '钉钉' } })
await putNoticeConfigByPlatform(this.id, { info: { ...this.dingdingData, bot, label: this.$t('cs.person.dingdingApp') } })
} else {
await postNoticeConfigByPlatform({
platform: 'dingdingApp',
info: { ...this.dingdingData, bot, label: '钉钉' },
info: { ...this.dingdingData, bot, label: this.$t('cs.person.dingdingApp') },
})
}
this.$message.success('保存成功')
this.$message.success(this.$t('saveSuccess'))
this.getData()
}
})

View File

@ -4,7 +4,7 @@
<!-- <a-tab-pane key="1" tab="接收服务器">
<Receive />
</a-tab-pane> -->
<a-tab-pane key="2" tab="发送服务器">
<a-tab-pane key="2" :tab="$t('cs.notice.sendServer')">
<Send />
</a-tab-pane>
</a-tabs>

View File

@ -1,33 +1,33 @@
<template>
<div class="notice-email-wrapper" :style="{ height: `${windowHeight - 104}px` }">
<a-form-model :model="settingData" :label-col="labelCol" :wrapper-col="wrapperCol">
<SpanTitle>基础设置</SpanTitle>
<a-form-model-item label="连接协议">
<SpanTitle>{{ $t('cs.duty.basicSetting') }}</SpanTitle>
<a-form-model-item :label="$t('cs.notice.connectProtocol')">
<a-radio-group v-model="settingData.connectProtocol" :default-value="1" @change="changeConnectProtocol">
<a-radio :value="1" :default-checked="true"> POP/IMAP/POPS/IMAPS </a-radio>
<a-radio :value="2"> EWS(Exchange Web服务) </a-radio>
<a-radio :value="2">{{ $t('cs.notice.ews') }}</a-radio>
</a-radio-group>
</a-form-model-item>
<a-form-model-item label="认证类型">
<a-form-model-item :label="$t('cs.notice.authType')">
<a-select v-model="settingData.authentication">
<a-select-option value="Base"> 基本 </a-select-option>
<a-select-option value="OAuth"> OAuth </a-select-option>
<a-select-option value="Base"> {{ $t('cs.notice.base') }} </a-select-option>
<a-select-option value="OAuth"> {{ $t('cs.notice.oauth') }} </a-select-option>
</a-select>
</a-form-model-item>
<a-form-model-item label="服务器名/IP地址" prop="IP">
<a-form-model-item :label="$t('cs.notice.ip')" prop="IP">
<a-input v-model="settingData.IP" />
</a-form-model-item>
<a-form-model-item label="用户名">
<a-form-model-item :label="$t('cs.notice.username')">
<a-input v-model="settingData.username" />
</a-form-model-item>
<a-form-model-item label="密码">
<a-form-model-item :label="$t('cs.notice.password')">
<a-input v-model="settingData.password" />
</a-form-model-item>
<a-form-model-item label="邮件地址">
<a-form-model-item :label="$t('cs.notice.email')">
<a-input v-model="settingData.email" />
</a-form-model-item>
<template v-if="settingData.connectProtocol === 1">
<a-form-model-item label="邮件类型">
<a-form-model-item :label="$t('cs.notice.emailType')">
<a-select v-model="settingData.emailType">
<a-select-option value="POP"> POP </a-select-option>
<a-select-option value="IMAP"> IMAP </a-select-option>
@ -35,78 +35,78 @@
<a-select-option value="IMAPS"> IMAPS </a-select-option>
</a-select>
</a-form-model-item>
<a-form-model-item label="端口">
<a-form-model-item :label="$t('cs.notice.port')">
<a-input v-model="settingData.port" />
</a-form-model-item>
</template>
<a-form-model-item label="测试邮件设置">
<a-button type="primary" ghost>测试回收箱</a-button>
<a-form-model-item :label="$t('cs.notice.oauth')">
<a-button type="primary" ghost>{{ $t('cs.notice.testRecyclingBin') }}</a-button>
<br />
<span class="notice-email-error-tips">
<ops-icon type="icon-shidi-quxiao" :style="{ color: '#D81E06' }" />
邮件接收失败
{{ $t('cs.notice.receiveEmailFailed') }}
</span>
<br />
<span
>邮箱服务器未配置请配置一个邮箱服务器 <a-divider type="vertical" :style="{ backgroundColor: '#2F54EB' }" />
<a>故障诊断</a></span
>{{ $('cs.notice.emailServiceNotConfig') }} <a-divider type="vertical" :style="{ backgroundColor: '#2F54EB' }" />
<a>{{ $('cs.notice.troubleshooting') }}</a></span
>
</a-form-model-item>
<SpanTitle>邮件设置</SpanTitle>
<a-form-model-item label="获取邮件间隔" :wrapperCol="{ span: 4 }">
<SpanTitle>{{ $('cs.notice.emailConfig') }}</SpanTitle>
<a-form-model-item :label="$('cs.notice.receiveEmailInterval')" :wrapperCol="{ span: 4 }">
<a-input class="ant-input-after" v-model="settingData.getEmailTimeout" />
<span :style="{ position: 'absolute', marginLeft: '8px' }"></span>
<span :style="{ position: 'absolute', marginLeft: '8px' }">{{ $t('cs.duty.min') }}</span>
</a-form-model-item>
<a-row>
<a-col :span="16" :offset="3">
<a-checkbox :default-checked="false" disabled>启动代理服务器</a-checkbox>
<a-checkbox :default-checked="false" disabled>{{ $('cs.notice.startProxyServer') }}</a-checkbox>
<a-icon type="info-circle" :style="{ color: '#FF9E58', fontSize: '16px' }" />
<a-divider type="vertical" :style="{ backgroundColor: '#2F54EB' }" />
<a @click="configProxySetting">配置代理设置</a>
<a @click="configProxySetting">{{ $('cs.notice.configProxyServer') }}</a>
<br />
<a-checkbox :default-checked="false">启动邮件测试</a-checkbox>
<a-checkbox :default-checked="false">{{ $('cs.notice.startEmailTest') }}</a-checkbox>
<br /><br />
<a-checkbox :default-checked="false" @change="changeCreateReqByEmail">禁用通过邮件创建请求</a-checkbox>
<a-checkbox :default-checked="false" @change="changeCreateReqByEmail">{{ $('cs.notice.disableCreationOfRequestsViaEmail') }}</a-checkbox>
<br />
<template v-if="settingData.banReqByEmail">
<strong>指定允许的邮件/域名,逗号分隔多个值</strong>
<strong>{{ $('cs.notice.specifyAllowedEmails') }}</strong>
<a-input type="textarea" :style="{ borderRadius: '8px', borderColor: '#2F54EB' }" />
<p :style="{ fontSize: '12px' }">例如:user@domain.com,*@domain.com</p>
<p :style="{ fontSize: '12px' }">限制不能适用于已在会话中的请求,它将聚集到它的上级工单中</p>
<p :style="{ fontSize: '12px' }">{{ $('cs.notice.specifyAllowedEmailsExample') }}</p>
<p :style="{ fontSize: '12px' }">{{ $('cs.notice.specifyAllowedEmailsLimit') }}</p>
</template>
</a-col>
</a-row>
<SpanTitle>消息设置</SpanTitle>
<SpanTitle>{{ $('cs.notice.messageConfig') }}</SpanTitle>
<a-row>
<a-col :span="16" :offset="3">
<a-checkbox :default-checked="false">将消息移动到错误的文件夹</a-checkbox>
<a-checkbox :default-checked="false">{{ $('cs.notice.moveWrongMessagesToFolder') }}</a-checkbox>
<a-icon type="info-circle" :style="{ color: '#FF9E58', fontSize: '16px' }" />
<a-divider type="vertical" :style="{ backgroundColor: '#2F54EB' }" />
<a href="#">了解更多</a>
<a href="#">{{ $('cs.notice.knowMore') }}</a>
</a-col>
</a-row>
<br /><br />
<a-row>
<a-col :span="16" :offset="3">
<a-form-model-item :label-col="labelCol" :wrapper-col="wrapperCol">
<a-button type="primary" @click="onSubmit"> 保存 </a-button>
<a-button ghost type="primary" style="margin-left: 28px;" @click="resetForm"> 重置 </a-button>
<a-button type="primary" @click="onSubmit"> {{ $('save') }} </a-button>
<a-button ghost type="primary" style="margin-left: 28px;" @click="resetForm"> {{ $('reset') }} </a-button>
</a-form-model-item>
</a-col>
</a-row>
</a-form-model>
<a-modal dialogClass="ops-modal" width="500px" v-model="visible" title="配置代理设置">
<a-modal dialogClass="ops-modal" width="500px" v-model="visible" :title="$('cs.notice.configProxySettings')">
<a-form-model v-model="proxySetting" :label-col="{ span: 4 }" :wrapper-col="{ span: 19 }">
<a-form-model-item label="主机">
<a-form-model-item :label="$('cs.notice.host')">
<a-input v-model="proxySetting.host" />
</a-form-model-item>
<a-form-model-item label="端口">
<a-form-model-item :label="$('cs.notice.port')">
<a-input v-model="proxySetting.port" />
</a-form-model-item>
<a-form-model-item label="用户名">
<a-form-model-item :label="$('cs.notice.username')">
<a-input v-model="proxySetting.username" />
</a-form-model-item>
<a-form-model-item label="密码">
<a-form-model-item :label="$('cs.notice.password')">
<a-input v-model="proxySetting.password" />
</a-form-model-item>
</a-form-model>

View File

@ -1,46 +1,46 @@
<template>
<div class="notice-email-wrapper" :style="{ height: `${windowHeight - 104}px` }">
<a-form-model ref="sendForm" :model="settingData" :label-col="labelCol" :rules="rules" :wrapper-col="wrapperCol">
<SpanTitle>基础设置</SpanTitle>
<a-form-model-item label="是否加密">
<SpanTitle>{{ $t('cs.duty.basicSetting') }}</SpanTitle>
<a-form-model-item :label="$t('cs.notice.isEncrypted')">
<a-radio-group v-model="settingData.tls" :disabled="!isEditable">
<a-radio :value="true">
{{ $t('yes') }}
</a-radio>
<a-radio :value="false">
{{ $t('no') }}
</a-radio>
</a-radio-group>
</a-form-model-item>
<a-form-model-item label="端口" prop="port">
<a-form-model-item :label="$t('cs.notice.port')" prop="port">
<a-input v-model="settingData.port" :disabled="!isEditable" />
</a-form-model-item>
<a-form-model-item label="邮件服务器" prop="host">
<a-form-model-item :label="$t('cs.notice.host')" prop="host">
<a-input v-model="settingData.host" :disabled="!isEditable" />
</a-form-model-item>
<a-form-model-item label="用户名" prop="account">
<a-form-model-item :label="$t('cs.notice.username')" prop="account">
<a-input v-model="settingData.account" :disabled="!isEditable" />
</a-form-model-item>
<a-form-model-item label="密码" prop="password">
<a-form-model-item :label="$t('cs.notice.password')" prop="password">
<a-input-password v-model="settingData.password" :disabled="!isEditable" />
</a-form-model-item>
<SpanTitle>邮件测试</SpanTitle>
<a-form-model-item label="测试发送邮件地址" prop="receive_address">
<SpanTitle>{{ $t('cs.notice.emailTest') }}</SpanTitle>
<a-form-model-item :label="$t('cs.notice.testSendAddress')" prop="receive_address">
<a-input v-model="settingData.receive_address" :disabled="!isEditable">
<span
v-if="isEditable"
:style="{ cursor: 'pointer' }"
@click="testSendEmail"
slot="addonAfter"
>测试邮件发送</span
>{{ $t('cs.notice.testMailSend') }}</span
>
</a-input>
</a-form-model-item>
<a-row v-if="isEditable">
<a-col :span="16" :offset="3">
<a-form-model-item :label-col="labelCol" :wrapper-col="wrapperCol">
<a-button type="primary" @click="onSubmit"> 保存 </a-button>
<a-button ghost type="primary" style="margin-left: 28px;" @click="resetForm"> 重置 </a-button>
<a-button type="primary" @click="onSubmit"> {{ $t('save') }} </a-button>
<a-button ghost type="primary" style="margin-left: 28px;" @click="resetForm"> {{ $t('reset') }} </a-button>
</a-form-model-item>
</a-col>
</a-row>
@ -74,32 +74,34 @@ export default {
password: '',
port: '',
receive_address: '',
},
rules: {
port: [{ required: true, message: '请输入端口', trigger: 'blur' }],
host: [{ required: true, whitespace: true, message: '请输入服务器', trigger: 'blur' }],
account: [
{ required: true, whitespace: true, message: '请输入用户名', trigger: 'blur' },
{
pattern: /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/,
message: '邮箱格式错误',
trigger: 'blur',
},
],
password: [{ required: false, whitespace: true, message: '请输入密码', trigger: 'blur' }],
receive_address: [
{ required: false, whitespace: true, message: '请输入测试发送邮件地址', trigger: 'blur' },
{
pattern: /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/,
message: '邮箱格式错误',
trigger: 'blur',
},
],
},
}
}
},
computed: {
...mapState({
rules() {
return {
port: [{ required: true, message: this.$t('cs.notice.portPlaceholder'), trigger: 'blur' }],
host: [{ required: true, whitespace: true, message: this.$t('cs.auth.ldap.serverAddressPlaceholder'), trigger: 'blur' }],
account: [
{ required: true, whitespace: true, message: this.$t('cs.auth.ldap.userPlaceholder'), trigger: 'blur' },
{
pattern: /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/,
message: this.$t('cs.companyStructure.emailFormatErr'),
trigger: 'blur',
},
],
password: [{ required: false, whitespace: true, message: this.$t('cs.companyStructure.passwordPlaceholder'), trigger: 'blur' }],
receive_address: [
{ required: false, whitespace: true, message: this.$t('cs.notice.testSendAddressPlaceholder'), trigger: 'blur' },
{
pattern: /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/,
message: this.$t('cs.companyStructure.emailFormatErr'),
trigger: 'blur',
},
]
}
},
windowHeight: (state) => state.windowHeight,
}),
isEditable() {
@ -135,17 +137,17 @@ export default {
await sendTestEmail(this.settingData.receive_address, {
info: { ...this.settingData, receive_address: undefined },
})
this.$message.success('已发送邮件,请查收')
this.$message.success(this.$t('cs.notice.emailSendSuccess'))
},
onSubmit() {
this.$refs.sendForm.validate(async (valid) => {
if (valid) {
if (this.id) {
await putNoticeConfigByPlatform(this.id, { info: { ...this.settingData, label: '邮箱' } })
await putNoticeConfigByPlatform(this.id, { info: { ...this.settingData, label: this.$t('cs.companyInfo.email') } })
} else {
await postNoticeConfigByPlatform({ platform: 'email', info: { ...this.settingData, label: '邮箱' } })
await postNoticeConfigByPlatform({ platform: 'email', info: { ...this.settingData, label: this.$t('cs.companyInfo.email') } })
}
this.$message.success('保存成功')
this.$message.success(this.$t('saveSuccess'))
this.getData()
}
})

View File

@ -1,26 +1,26 @@
<template>
<div class="notice-feishu-wrapper" :style="{ height: `${windowHeight - 64}px` }">
<a-form-model ref="feishuForm" :model="feishuData" :label-col="labelCol" :wrapper-col="wrapperCol">
<SpanTitle>基础设置</SpanTitle>
<a-form-model-item label="应用ID">
<SpanTitle>{{ $t('cs.duty.basicSetting') }}</SpanTitle>
<a-form-model-item :label="$t('cs.notice.appKey')">
<a-input v-model="feishuData.id" :disabled="!isEditable" />
</a-form-model-item>
<a-form-model-item label="应用密码">
<a-form-model-item :label="$t('cs.notice.appSecret')">
<a-input v-model="feishuData.password" :disabled="!isEditable" />
</a-form-model-item>
<a-form-model-item label="机器人">
<a-form-model-item :label="$t('cs.notice.robot')">
<Bot
ref="bot"
:disabled="!isEditable"
:columns="[
{
field: 'name',
title: '名称',
title: $t('cs.notice.title'),
required: true,
},
{
field: 'url',
title: 'Webhook地址',
title: $t('cs.notice.webhookAddress'),
required: true,
},
]"
@ -29,8 +29,8 @@
<a-row v-if="isEditable">
<a-col :span="16" :offset="3">
<a-form-model-item :label-col="labelCol" :wrapper-col="wrapperCol">
<a-button type="primary" @click="onSubmit"> 保存 </a-button>
<a-button ghost type="primary" style="margin-left: 28px;" @click="resetForm"> 重置 </a-button>
<a-button type="primary" @click="onSubmit"> {{ $t('save') }} </a-button>
<a-button ghost type="primary" style="margin-left: 28px;" @click="resetForm"> {{ $t('reset') }} </a-button>
</a-form-model-item>
</a-col>
</a-row>
@ -87,14 +87,14 @@ export default {
this.$refs.bot.getData(async (flag, bot) => {
if (flag) {
if (this.id) {
await putNoticeConfigByPlatform(this.id, { info: { ...this.feishuData, bot, label: '飞书' } })
await putNoticeConfigByPlatform(this.id, { info: { ...this.feishuData, bot, label: this.$t('cs.person.feishuApp') } })
} else {
await postNoticeConfigByPlatform({
platform: 'feishuApp',
info: { ...this.feishuData, bot, label: '飞书' },
info: { ...this.feishuData, bot, label: this.$t('cs.person.feishuApp') },
})
}
this.$message.success('保存成功')
this.$message.success(this.$t('saveSuccess'))
this.getData()
}
})

View File

@ -1,23 +1,38 @@
<template>
<div class="notice-wx-wrapper" :style="{ height: `${windowHeight - 64}px` }">
<a-form-model ref="wxForm" :model="wxData" :label-col="labelCol" :wrapper-col="wrapperCol">
<SpanTitle>基础设置</SpanTitle>
<a-form-model-item label="企业ID">
<SpanTitle>{{ $t('cs.duty.basicSetting') }}</SpanTitle>
<a-form-model-item :label="$t('cs.notice.corpid')">
<a-input v-model="wxData.corpid" :disabled="!isEditable" />
</a-form-model-item>
<a-form-model-item label="自建应用ID">
<a-form-model-item :label="$t('cs.notice.agentid')">
<a-input v-model="wxData.agentid" :disabled="!isEditable" />
</a-form-model-item>
<a-form-model-item label="自建应用密码">
<a-form-model-item :label="$t('cs.notice.corpsecret')">
<a-input-password v-model="wxData.corpsecret" :disabled="!isEditable" />
</a-form-model-item>
<a-form-model-item label="ITSM AppId">
<a-input v-model="wxData.itsm_app_id" :disabled="!isEditable" />
</a-form-model-item>
<a-form-model-item label="机器人">
<Bot ref="bot" :disabled="!isEditable" />
<a-form-model-item :label="$t('cs.notice.robot')">
<Bot
ref="bot"
:disabled="!isEditable"
:columns="[
{
field: 'name',
title: $t('cs.notice.title'),
required: true,
},
{
field: 'url',
title: $t('cs.notice.webhookAddress'),
required: true,
},
]"
/>
</a-form-model-item>
<!-- <a-form-model-item label="测试邮件设置">
<!-- <a-form-model-item :label="测试邮件设置">
<a-button type="primary" ghost>测试回收箱</a-button>
<br />
<span
@ -30,8 +45,8 @@
<a-row v-if="isEditable">
<a-col :span="16" :offset="3">
<a-form-model-item :label-col="labelCol" :wrapper-col="wrapperCol">
<a-button type="primary" @click="onSubmit"> 保存 </a-button>
<a-button ghost type="primary" style="margin-left: 28px;" @click="resetForm"> 重置 </a-button>
<a-button type="primary" @click="onSubmit"> {{ $t('save') }} </a-button>
<a-button ghost type="primary" style="margin-left: 28px;" @click="resetForm"> {{ $t('reset') }} </a-button>
</a-form-model-item>
</a-col>
</a-row>
@ -89,14 +104,16 @@ export default {
this.$refs.bot.getData(async (flag, bot) => {
if (flag) {
if (this.id) {
await putNoticeConfigByPlatform(this.id, { info: { ...this.wxData, bot, label: '企业微信' } })
await putNoticeConfigByPlatform(this.id, {
info: { ...this.wxData, bot, label: this.$t('cs.person.wechatApp') },
})
} else {
await postNoticeConfigByPlatform({
platform: 'wechatApp',
info: { ...this.wxData, bot, label: '企业微信' },
info: { ...this.wxData, bot, label: this.$t('cs.person.wechatApp') },
})
}
this.$message.success('保存成功')
this.$message.success(this.$t('saveSuccess'))
this.getData()
}
})

View File

@ -12,7 +12,7 @@
"
:class="{ 'setting-person-left-item': true, 'setting-person-left-item-selected': current === '1' }"
>
<ops-icon type="icon-shidi-yonghu" />个人信息
<ops-icon type="icon-shidi-yonghu" />{{ $t('cs.person.spanTitle') }}
</div>
<div
@click="
@ -25,7 +25,7 @@
"
:class="{ 'setting-person-left-item': true, 'setting-person-left-item-selected': current === '2' }"
>
<a-icon type="unlock" theme="filled" />账号密码
<a-icon type="unlock" theme="filled" />{{ $t('cs.person.accountAndPassword') }}
</div>
</div>
<div class="setting-person-right">
@ -39,7 +39,7 @@
:wrapperCol="{ span: 10 }"
>
<div v-show="current === '1'">
<a-form-model-item label="头像" :style="{ display: 'flex', alignItems: 'center' }">
<a-form-model-item :label="$t('cs.person.avatar')" :style="{ display: 'flex', alignItems: 'center' }">
<a-space>
<a-avatar v-if="form.avatar" :src="`/api/common-setting/v1/file/${form.avatar}`" :size="64"> </a-avatar>
<a-avatar v-else style="backgroundColor:#F0F5FF" :size="64">
@ -53,44 +53,44 @@
:style="{ width: '310px', height: '100px' }"
accept=".svg,.png,.jpg,.jpeg"
>
<a-button type="primary" ghost size="small">更换头像</a-button>
<a-button type="primary" ghost size="small">{{ $t('cs.person.changeAvatar') }}</a-button>
</a-upload>
</a-space>
</a-form-model-item>
<a-form-model-item label="姓名" prop="nickname">
<a-form-model-item :label="$t('cs.companyStructure.nickname')" prop="nickname">
<a-input v-model="form.nickname" />
</a-form-model-item>
<a-form-model-item label="用户名">
<a-form-model-item :label="$t('cs.companyStructure.username')">
<div class="setting-person-right-disabled">{{ form.username }}</div>
</a-form-model-item>
<a-form-model-item label="邮箱">
<a-form-model-item :label="$t('cs.companyStructure.email')">
<div class="setting-person-right-disabled">{{ form.email }}</div>
</a-form-model-item>
<a-form-model-item label="直属上级">
<a-form-model-item :label="$t('cs.companyStructure.supervisor')">
<div class="setting-person-right-disabled">
{{ getDirectorName(allFlatEmployees, form.direct_supervisor_id) }}
</div>
</a-form-model-item>
<a-form-model-item label="性别">
<a-form-model-item :label="$t('cs.companyStructure.sex')">
<a-select v-model="form.sex">
<a-select-option value=""></a-select-option>
<a-select-option value=""></a-select-option>
<a-select-option value="">{{ $t('cs.companyStructure.male') }}</a-select-option>
<a-select-option value="">{{ $t('cs.companyStructure.female') }}</a-select-option>
</a-select>
</a-form-model-item>
<a-form-model-item label="手机号" prop="mobile">
<a-form-model-item :label="$t('cs.companyStructure.mobile')" prop="mobile">
<a-input v-model="form.mobile" />
</a-form-model-item>
<a-form-model-item label="部门">
<a-form-model-item :label="$t('cs.companyStructure.departmentName')">
<div class="setting-person-right-disabled">
{{ getDepartmentName(allFlatDepartments, form.department_id) }}
</div>
</a-form-model-item>
<a-form-model-item label="岗位">
<a-form-model-item :label="$t('cs.companyStructure.positionName')">
<div class="setting-person-right-disabled">{{ form.position_name }}</div>
</a-form-model-item>
<a-form-model-item label="绑定信息">
<a-form-model-item :label="$t('cs.person.bindInfo')">
<a-space>
<a-tooltip title="企业微信">
<a-tooltip :title="$t('cs.person.wechatApp')">
<div
@click="handleBind('wechatApp', form.notice_info && form.notice_info.wechatApp)"
:class="{
@ -101,7 +101,7 @@
<ops-icon type="ops-setting-notice-wx" />
</div>
</a-tooltip>
<a-tooltip title="飞书">
<a-tooltip :title="$t('cs.person.feishuApp')">
<div
@click="handleBind('feishuApp', form.notice_info && form.notice_info.feishuApp)"
:class="{
@ -112,7 +112,7 @@
<ops-icon type="ops-setting-notice-feishu" />
</div>
</a-tooltip>
<a-tooltip title="钉钉">
<a-tooltip :title="$t('cs.person.dingdingApp')">
<div
@click="handleBind('dingdingApp', form.notice_info && form.notice_info.dingdingApp)"
:class="{
@ -127,16 +127,16 @@
</a-form-model-item>
</div>
<div v-show="current === '2'">
<a-form-model-item label="新密码" prop="password1">
<a-form-model-item :label="$t('cs.person.newPassword')" prop="password1">
<a-input v-model="form.password1" />
</a-form-model-item>
<a-form-model-item label="确认密码" prop="password2">
<a-form-model-item :label="$t('cs.person.confirmPassword')" prop="password2">
<a-input v-model="form.password2" />
</a-form-model-item>
</div>
<div style="margin-right: 120px">
<a-form-model-item label=" ">
<a-button type="primary" @click="handleSave" :style="{ width: '100%' }">保存</a-button>
<a-button type="primary" @click="handleSave" :style="{ width: '100%' }">{{ $t('save') }}</a-button>
</a-form-model-item>
</div>
</a-form-model>
@ -150,7 +150,7 @@
:preview-height="eidtImageOption.previewHeight"
preview-radius="0"
width="550px"
save-button-title="确定"
:save-button-title="$t('confirm')"
@save="submitImage"
@close="showEditImage = false"
/>
@ -175,50 +175,70 @@ export default {
name: 'Person',
components: { EditImage },
data() {
const validatePassword = (rule, value, callback) => {
if (!value) {
callback(new Error('请二次确认新密码'))
}
if (value !== this.form.password1) {
callback(new Error('两次输入密码不一致'))
}
callback()
}
return {
current: '1',
form: {},
rules1: {
nickname: [
{ required: true, whitespace: true, message: '请输入姓名', trigger: 'blur' },
{ max: 20, message: '字符数须小于20' },
],
mobile: [
{
pattern: /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
message: '请输入正确的手机号',
trigger: 'blur',
},
],
},
rules2: {
password1: [{ required: true, message: '请输入新密码', trigger: 'blur' }],
password2: [{ required: true, message: '两次输入密码不一致', trigger: 'blur', validator: validatePassword }],
},
allFlatEmployees: [],
allFlatDepartments: [],
showEditImage: false,
eidtImageOption: {
type: 'avatar',
fixedNumber: [4, 4],
title: '编辑头像',
previewWidth: '60px',
previewHeight: '60px',
},
editImage: null,
}
},
computed: {
...mapGetters(['uid']),
rules1() {
return {
nickname: [
{
required: true,
whitespace: true,
message: this.$t('cs.companyStructure.nicknamePlaceholder'),
trigger: 'blur',
},
{ max: 20, message: this.$t('cs.person.inputStrCountLimit', { limit: 20 }) },
],
mobile: [
{
pattern: /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
message: this.$t('cs.companyStructure.mobileFormatErr'),
trigger: 'blur',
},
],
}
},
rules2() {
const validatePassword = (rule, value, callback) => {
if (!value) {
callback(new Error(this.$t('cs.person.pleaseConfirmNewPasswordSecondTime')))
}
if (value !== this.form.password1) {
callback(new Error(this.$t('cs.person.thePasswordEnteredTwiceIsInconsistent')))
}
callback()
}
return {
password1: [
{ required: true, message: this.$t('cs.person.pleaseConfirmNewPasswordSecondTime'), trigger: 'blur' },
],
password2: [
{
required: true,
message: this.$t('cs.person.thePasswordEnteredTwiceIsInconsistent'),
trigger: 'blur',
validator: validatePassword,
},
],
}
},
eidtImageOption() {
return {
type: 'avatar',
fixedNumber: [4, 4],
title: this.$t('cs.components.editAvatar'),
previewWidth: '60px',
previewHeight: '60px',
}
},
},
mounted() {
this.getAllFlatEmployees()
@ -251,13 +271,13 @@ export default {
const params = { nickname, mobile, sex, avatar }
if (this.current === '1') {
await updateEmployeeByUid(this.uid, params).then((res) => {
this.$message.success('保存成功!')
this.$message.success(this.$t('saveSuccess'))
this.getEmployeeByUid()
this.GetInfo()
})
} else {
await updatePasswordByUid(this.uid, { password: password1 }).then((res) => {
this.$message.success('保存成功!')
this.$message.success(this.$t('saveSuccess'))
})
}
}
@ -283,7 +303,7 @@ export default {
beforeUpload(file) {
const isLt2M = file.size / 1024 / 1024 < 2
if (!isLt2M) {
this.$message.error('图片大小不可超过2MB!')
this.$message.error(this.$t('cs.companyInfo.imageSizeLimit2MB'))
}
return isLt2M
},
@ -298,12 +318,12 @@ export default {
if (isBind) {
const that = this
this.$confirm({
title: '警告',
content: `确认解绑`,
title: this.$t('warning'),
content: this.$t('cs.person.confirmUnbind'),
onOk() {
unbindPlatformByUid(platform, that.uid)
.then(() => {
that.$message.success('解绑成功!')
that.$message.success(this.$t('cs.person.unbindSuccess'))
})
.finally(() => {
that.getEmployeeByUid()
@ -319,7 +339,7 @@ export default {
await updateEmployeeByUid(this.uid, params)
bindPlatformByUid(platform, this.uid)
.then(() => {
this.$message.success('绑定成功!')
this.$message.success(this.$t('cs.person.bindSuccess'))
})
.finally(() => {
this.getEmployeeByUid()