<script setup lang="ts">
|
import type { ActionItem, BasicColumn } from '@jnpf/ui/vxeTable';
|
import type { FormInstance } from 'ant-design-vue';
|
|
import { onMounted, reactive, ref, toRefs, unref } from 'vue';
|
|
import { useMessage } from '@jnpf/hooks';
|
import { getBase64WithFile, SignModal } from '@jnpf/ui';
|
import { useModal } from '@jnpf/ui/modal';
|
import { BasicVxeTable, TableAction, useVxeTable } from '@jnpf/ui/vxeTable';
|
|
import { useUserStore } from '@vben/stores';
|
|
import { CheckOutlined } from '@ant-design/icons-vue';
|
|
import { createSign, deleteSign, getSignList, updateDefaultSign, updateUserInfo } from '#/api/permission/userSetting';
|
import { delCommonWords, getCommonWordsList } from '#/api/system/commonWords';
|
import { $t } from '#/locales';
|
import { useBaseStore } from '#/store';
|
import Form from '#/views/templateCenter/commonWords/Form.vue';
|
|
interface State {
|
activeKey: string;
|
educationOptions: any[];
|
certificatesTypeOptions: any[];
|
genderOptions: any[];
|
nationOptions: any[];
|
signList: any[];
|
userForm: any;
|
userFormRule: any;
|
}
|
|
const props = defineProps({
|
user: { type: Object, default: () => ({}) },
|
});
|
const emit = defineEmits(['updateInfo']);
|
const baseStore = useBaseStore();
|
const userStore = useUserStore();
|
const { createMessage } = useMessage();
|
const userFormElRef = ref<FormInstance>();
|
const signModalRef = ref(null);
|
const state = reactive<State>({
|
activeKey: '1',
|
educationOptions: [],
|
certificatesTypeOptions: [],
|
genderOptions: [],
|
nationOptions: [],
|
signList: [],
|
userForm: {
|
realName: '',
|
signature: '',
|
gender: 1,
|
nation: '',
|
nativePlace: '',
|
certificatesType: '',
|
certificatesNumber: '',
|
education: '',
|
birthday: null,
|
telePhone: '',
|
landline: '',
|
urgentContacts: '',
|
urgentTelePhone: '',
|
postalAddress: '',
|
},
|
userFormRule: {
|
realName: [{ required: true, message: '姓名不能为空', trigger: 'blur' }],
|
},
|
});
|
const { activeKey, userForm, educationOptions, certificatesTypeOptions, genderOptions, nationOptions } = toRefs(state);
|
const columns: BasicColumn[] = [
|
{ title: '常用语', dataIndex: 'commonWordsText' },
|
{ title: '使用次数', dataIndex: 'usesNum', width: 80, align: 'center' },
|
{ title: '状态', dataIndex: 'enabledMark', width: 80, align: 'center', slots: { default: 'enabledMark' } },
|
];
|
const [registerForm, { openModal: openFormModal }] = useModal();
|
const [registerTable, { reload }] = useVxeTable({
|
api: getCommonWordsList,
|
searchInfo: { commonWordsType: 1 },
|
columns,
|
actionColumn: {
|
width: 100,
|
title: '操作',
|
dataIndex: 'action',
|
},
|
});
|
|
async function getOptions() {
|
const educationRes = (await baseStore.getDictionaryData('Education')) as any;
|
state.educationOptions = educationRes;
|
const certificateTypeRes = (await baseStore.getDictionaryData('certificateType')) as any;
|
state.certificatesTypeOptions = certificateTypeRes;
|
const sexRes = (await baseStore.getDictionaryData('sex')) as any;
|
state.genderOptions = sexRes;
|
const nationRes = (await baseStore.getDictionaryData('Nation')) as any;
|
state.nationOptions = nationRes;
|
}
|
function getInfo() {
|
for (const key of Object.keys(state.userForm)) {
|
state.userForm[key] = props.user[key];
|
}
|
}
|
function getSign() {
|
getSignList().then((res) => {
|
state.signList = res.data || [];
|
});
|
}
|
async function handleSubmit() {
|
try {
|
const values = await userFormElRef.value?.validate();
|
if (!values) return;
|
updateUserInfo(state.userForm).then((res) => {
|
createMessage.success(res.msg);
|
emit('updateInfo');
|
userStore.setUserInfo({ userName: state.userForm.realName });
|
});
|
} catch {}
|
}
|
function openSignModal() {
|
const signRef = unref(signModalRef) as any;
|
signRef?.openModal();
|
}
|
function beforeUpload(file: File) {
|
const isAccept = /image\/*/.test(file.type);
|
if (!isAccept) {
|
createMessage.error(`请上传图片`);
|
return;
|
}
|
if (file.size / 1024 > 500) {
|
createMessage.error('操作失败,图片大小超出500K');
|
return;
|
}
|
getBase64WithFile(file).then(({ result: thumbUrl }) => {
|
addSign(thumbUrl);
|
});
|
return false;
|
}
|
function addSign(signImg) {
|
const query = {
|
signImg,
|
isDefault: 0,
|
};
|
createSign(query).then((res) => {
|
createMessage.success(res.msg);
|
getSign();
|
});
|
}
|
function updateDefault(id, signImg) {
|
updateDefaultSign(id)
|
.then((res) => {
|
createMessage.success(res.msg);
|
userStore.setUserInfo({ signImg });
|
getSign();
|
})
|
.catch((_) => {
|
getSign();
|
});
|
}
|
function delSign(id) {
|
deleteSign(id).then((res) => {
|
createMessage.success(res.msg);
|
getSign();
|
});
|
}
|
function getTableActions(record): ActionItem[] {
|
return [
|
{
|
label: $t('common.editText'),
|
onClick: addOrUpdateHandle.bind(null, record.id),
|
},
|
{
|
label: $t('common.delText'),
|
color: 'error',
|
modelConfirm: {
|
onOk: handleDelete.bind(null, record.id),
|
},
|
},
|
];
|
}
|
function addOrUpdateHandle(id = '') {
|
openFormModal(true, { id, commonWordsType: 1 });
|
}
|
function handleDelete(id) {
|
delCommonWords(id).then((res) => {
|
createMessage.success(res.msg);
|
reload();
|
});
|
}
|
|
onMounted(() => {
|
getOptions();
|
getInfo();
|
getSign();
|
});
|
</script>
|
|
<template>
|
<a-tabs v-model:active-key="activeKey" class="userInfo-tabs">
|
<a-tab-pane key="1" tab="个人资料">
|
<a-form
|
:colon="false"
|
label-align="right"
|
:model="userForm"
|
:rules="state.userFormRule"
|
ref="userFormElRef"
|
:label-col="{ style: { width: '100px' } }"
|
class="pt-[10px]">
|
<a-row>
|
<a-col :span="12">
|
<a-form-item label="姓名" name="realName">
|
<a-input v-model:value="userForm.realName" :maxlength="50" placeholder="请输入" />
|
</a-form-item>
|
</a-col>
|
<a-col :span="12">
|
<a-form-item label="性别">
|
<jnpf-select v-model:value="userForm.gender" :options="genderOptions" placeholder="请选择" :field-names="{ value: 'enCode' }" show-search />
|
</a-form-item>
|
</a-col>
|
<a-col :span="12">
|
<a-form-item label="民族">
|
<jnpf-select v-model:value="userForm.nation" :options="nationOptions" placeholder="请选择" show-search />
|
</a-form-item>
|
</a-col>
|
<a-col :span="12">
|
<a-form-item label="籍贯">
|
<a-input v-model:value="userForm.nativePlace" :maxlength="50" placeholder="请输入" />
|
</a-form-item>
|
</a-col>
|
<a-col :span="12">
|
<a-form-item label="证件类型">
|
<jnpf-select v-model:value="userForm.certificatesType" :options="certificatesTypeOptions" placeholder="请选择" show-search />
|
</a-form-item>
|
</a-col>
|
<a-col :span="12">
|
<a-form-item label="证件号码">
|
<a-input v-model:value="userForm.certificatesNumber" :maxlength="50" placeholder="请输入" />
|
</a-form-item>
|
</a-col>
|
<a-col :span="12">
|
<a-form-item label="文化程度">
|
<jnpf-select v-model:value="userForm.education" :options="educationOptions" placeholder="请选择" show-search />
|
</a-form-item>
|
</a-col>
|
<a-col :span="12">
|
<a-form-item label="出生年月">
|
<jnpf-date-picker v-model:value="userForm.birthday" placeholder="请选择" format="YYYY-MM-DD" />
|
</a-form-item>
|
</a-col>
|
<a-col :span="12">
|
<a-form-item label="办公电话">
|
<a-input v-model:value="userForm.telePhone" :maxlength="20" placeholder="请输入" />
|
</a-form-item>
|
</a-col>
|
<a-col :span="12">
|
<a-form-item label="办公座机">
|
<a-input v-model:value="userForm.landline" :maxlength="50" placeholder="请输入" />
|
</a-form-item>
|
</a-col>
|
<a-col :span="12">
|
<a-form-item label="紧急联系">
|
<a-input v-model:value="userForm.urgentContacts" :maxlength="50" placeholder="请输入" />
|
</a-form-item>
|
</a-col>
|
<a-col :span="12">
|
<a-form-item label="紧急电话">
|
<a-input v-model:value="userForm.urgentTelePhone" :maxlength="50" placeholder="请输入" />
|
</a-form-item>
|
</a-col>
|
<a-col :span="24">
|
<a-form-item label="通讯地址">
|
<a-input v-model:value="userForm.postalAddress" :maxlength="300" placeholder="请输入" />
|
</a-form-item>
|
</a-col>
|
<a-col :span="24">
|
<a-form-item label="自我介绍">
|
<jnpf-textarea v-model:value="userForm.signature" :maxlength="300" placeholder="请输入" />
|
</a-form-item>
|
</a-col>
|
<a-col :span="24">
|
<a-form-item label=" ">
|
<a-button type="primary" @click="handleSubmit">保存</a-button>
|
</a-form-item>
|
</a-col>
|
</a-row>
|
</a-form>
|
</a-tab-pane>
|
<a-tab-pane key="2" tab="个人签名">
|
<a-row class="sign-list" :gutter="40">
|
<a-col :span="6" class="sign-item add-sign">
|
<div class="sign-item-main">
|
<a-dropdown trigger="click">
|
<i class="add-icon icon-ym icon-ym-btn-add" @click.prevent></i>
|
<template #overlay>
|
<a-menu>
|
<a-menu-item key="1" @click="openSignModal">在线签名</a-menu-item>
|
<a-menu-item key="3">
|
<a-upload :show-upload-list="false" accept="image/*" :before-upload="beforeUpload">
|
<div>图片上传</div>
|
</a-upload>
|
</a-menu-item>
|
</a-menu>
|
</template>
|
</a-dropdown>
|
</div>
|
</a-col>
|
<a-col :span="6" class="sign-item" :key="i" v-for="(item, i) in state.signList">
|
<div :class="item.isDefault ? 'sign-item-main active' : 'sign-item-main'">
|
<img :src="item.signImg" alt="" class="sign-img" />
|
<div class="icon-checked" v-if="item.isDefault">
|
<CheckOutlined />
|
</div>
|
<div v-if="!item.isDefault" class="add-button">
|
<a-button size="small" @click="delSign(item.id)" class="mr-[10px]">删除</a-button>
|
<a-button size="small" type="primary" @click="updateDefault(item.id, item.signImg)">设为默认</a-button>
|
</div>
|
</div>
|
</a-col>
|
</a-row>
|
</a-tab-pane>
|
<a-tab-pane key="3" tab="审批常用语" class="!p-0">
|
<BasicVxeTable @register="registerTable">
|
<template #tableTitle>
|
<a-button type="primary" pre-icon="icon-ym icon-ym-btn-add" @click="addOrUpdateHandle()">{{ $t('common.addText') }}</a-button>
|
</template>
|
<template #enabledMark="{ record }">
|
<a-tag :color="record.enabledMark == 1 ? 'success' : 'error'">{{ record.enabledMark == 1 ? '启用' : '禁用' }}</a-tag>
|
</template>
|
<template #action="{ record }">
|
<TableAction :actions="getTableActions(record)" />
|
</template>
|
</BasicVxeTable>
|
</a-tab-pane>
|
</a-tabs>
|
<SignModal ref="signModalRef" submit-on-confirm @confirm="getSign" />
|
<Form @register="registerForm" @reload="reload" />
|
</template>
|
<style lang="scss" scoped>
|
.userInfo-tabs {
|
height: 100%;
|
|
:deep(.ant-tabs-nav) {
|
margin: 0;
|
}
|
|
:deep(.ant-tabs-content-holder) {
|
height: calc(100% - 66px);
|
overflow: auto;
|
|
.ant-tabs-content {
|
height: 100%;
|
}
|
}
|
|
.ant-tabs-tabpane {
|
padding: 10px;
|
overflow-x: hidden;
|
}
|
}
|
|
.sign-list {
|
padding: 20px 50px 0;
|
|
.sign-item {
|
margin-bottom: 20px;
|
|
.sign-item-main {
|
position: relative;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
height: 160px;
|
overflow: hidden;
|
cursor: pointer;
|
background-color: #fff;
|
border-radius: 10px;
|
|
.icon-checked {
|
position: absolute;
|
right: -1px;
|
bottom: -1px;
|
display: block;
|
width: 16px;
|
height: 16px;
|
border: 16px solid var(--primary-color);
|
border-top: 16px solid transparent !important;
|
border-left: 16px solid transparent !important;
|
border-bottom-right-radius: 10px;
|
|
.anticon-check {
|
position: absolute;
|
top: -1px;
|
left: -1px;
|
font-size: 14px;
|
color: #fff;
|
}
|
}
|
|
&.active {
|
color: var(--primary-color);
|
border: 1px solid var(--primary-color);
|
box-shadow: 0 0 6px rgb(6 58 108 / 26%);
|
}
|
|
&:hover {
|
.add-button {
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
width: 100%;
|
height: 100%;
|
background-color: rgb(157 158 159 / 80%);
|
border-radius: 10px;
|
}
|
}
|
|
.add-button {
|
position: absolute;
|
display: none;
|
}
|
|
.add-icon {
|
font-size: 50px;
|
color: var(--text-color-secondary);
|
}
|
|
.sign-img {
|
width: 100%;
|
height: 100%;
|
}
|
}
|
}
|
}
|
</style>
|