feat(address-book): 添加通讯录导入导出功能
This commit is contained in:
2
components.d.ts
vendored
2
components.d.ts
vendored
@@ -52,6 +52,7 @@ declare module '@vue/runtime-core' {
|
||||
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
||||
ElTree: typeof import('element-plus/es')['ElTree']
|
||||
ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']
|
||||
ElUpload: typeof import('element-plus/es')['ElUpload']
|
||||
FvCheckbox: typeof import('./src/fvcomponents/fvCheckbox/index.vue')['default']
|
||||
FvForm: typeof import('./src/fvcomponents/fvForm/index.vue')['default']
|
||||
FvFormDialog: typeof import('./src/fvcomponents/fvFormDialog/index.vue')['default']
|
||||
@@ -68,6 +69,7 @@ declare module '@vue/runtime-core' {
|
||||
IconSelect: typeof import('./src/components/iconSelect/index.vue')['default']
|
||||
IconSupport: typeof import('./src/components/icons/IconSupport.vue')['default']
|
||||
IconTooling: typeof import('./src/components/icons/IconTooling.vue')['default']
|
||||
ImportExcel: typeof import('./src/components/ImportExcel.vue')['default']
|
||||
InfoLiveCall: typeof import('./src/components/infoLiveCall/index.vue')['default']
|
||||
LiveCall: typeof import('./src/components/liveCall/index.vue')['default']
|
||||
LiveCallItem: typeof import('./src/components/liveCall/LiveCallItem.vue')['default']
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import request from '@/utils/request.js'
|
||||
import axios from "axios";
|
||||
import {getToken} from "@/utils/auth";
|
||||
|
||||
export const addContact = (data) => {
|
||||
return request({
|
||||
@@ -28,3 +30,23 @@ export const deleteContact = (contactIds) => {
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
export const importContact = (data) => {
|
||||
return request({
|
||||
url: '/contact/import',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export const exportContact = (data) => {
|
||||
return axios.post(
|
||||
`${import.meta.env.VITE_BASE_URL}/contact/export`,data,
|
||||
{
|
||||
responseType: 'blob',
|
||||
headers: {
|
||||
Authorization: getToken()
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
105
src/components/ImportExcel.vue
Normal file
105
src/components/ImportExcel.vue
Normal file
@@ -0,0 +1,105 @@
|
||||
<template>
|
||||
<el-upload :file-list="[]"
|
||||
:limit="maxSize"
|
||||
with-credentials
|
||||
:multiple="multiple"
|
||||
:http-request="httpRequestHandle"
|
||||
:data="uploadParams"
|
||||
:auto-upload="true"
|
||||
:show-file-list="false"
|
||||
:before-upload="beforeUpload"
|
||||
:on-remove="handleRemove"
|
||||
>
|
||||
<el-button color="#DED0B2" style="margin-left: 10px; margin-right: 10px;" :loading="loading" v-perm="['order:contacts:import']" :disabled="disabled">导入</el-button>
|
||||
</el-upload>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {ElMessageBox, ElNotification} from "element-plus";
|
||||
import {getToken} from '@/utils/auth'
|
||||
import axios from "axios";
|
||||
|
||||
const props = defineProps({
|
||||
value: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return []
|
||||
}
|
||||
},
|
||||
maxSize: {
|
||||
type: Number,
|
||||
default: 30
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
})
|
||||
|
||||
const loading = ref(false)
|
||||
const baseURL = import.meta.env.VITE_BASE_URL
|
||||
const uploadFileUrl = ref(baseURL + "/contact/import")
|
||||
const headers = reactive({
|
||||
authorization: getToken()
|
||||
})
|
||||
const uploadParams = ref({})
|
||||
const emit = defineEmits(["input", "getFile", "delete"])
|
||||
|
||||
const handleRemove = (file) => {
|
||||
emit("delete", file.response.data.id)
|
||||
}
|
||||
const beforeUpload = () => {
|
||||
loading.value = true
|
||||
return true
|
||||
}
|
||||
const httpRequestHandle = (param) => {
|
||||
// loading.value=true
|
||||
let file = param.file
|
||||
axios.post(uploadFileUrl.value, {
|
||||
file: file
|
||||
}, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
...headers
|
||||
}
|
||||
}).then(res => {
|
||||
loading.value=false
|
||||
handleUploadSuccess(res)
|
||||
}).catch(error => {
|
||||
loading.value=false
|
||||
uploadError(error)
|
||||
})
|
||||
}
|
||||
const handleUploadSuccess = (res) => {
|
||||
let data = res.data
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: data.code === 1000 ? '导入成功' : '导入失败',
|
||||
type: data.code === 1000 ? 'success' : 'error'
|
||||
})
|
||||
emit("success")
|
||||
}
|
||||
const uploadError = (error) => {
|
||||
loading.value = false
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: "导入失败,请稍后再试!",
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
defineExpose({
|
||||
handleRemove
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
a {
|
||||
font-size: 14px;
|
||||
color: #2a99ff;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,19 +1,27 @@
|
||||
<template>
|
||||
<div class="address-book">
|
||||
<fvSearchForm :searchConfig="searchConfig" @search="searchAddressBook"></fvSearchForm>
|
||||
<fvTable ref="tableIns" :tableConfig="addressBookTableConfig" @headBtnClick="headBtnClick"
|
||||
@selectionChange="selectionChange"></fvTable>
|
||||
<fvFormDialog ref="formDialogRef" :title="dialogTitle" :dialogType="dialogType"
|
||||
:form-schema="formSchema" :form-rules="formRules"
|
||||
@dialogSubmit="handleSubmitAddressBook"></fvFormDialog>
|
||||
</div>
|
||||
<div style="display: flex;">
|
||||
<el-button type="primary" v-perm="auths.add" @click="handleAdd">新增</el-button>
|
||||
<import-excel @success="importAddress"/>
|
||||
<el-button type="info" v-perm="auths.export" @click="handleExport">导出</el-button>
|
||||
<el-button type="danger" v-perm="auths.delete" @click="handleMoreDelete">删除</el-button>
|
||||
</div>
|
||||
<!-- @headBtnClick="headBtnClick"-->
|
||||
<fvTable ref="tableIns" :tableConfig="addressBookTableConfig"
|
||||
@selectionChange="selectionChange"></fvTable>
|
||||
<fvFormDialog ref="formDialogRef" :title="dialogTitle" :dialogType="dialogType"
|
||||
:form-schema="formSchema" :form-rules="formRules"
|
||||
@dialogSubmit="handleSubmitAddressBook"></fvFormDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
import fvSelect from '@/fvcomponents/fvSelect/index.vue'
|
||||
import {addContact, editContact, getContactDetail, deleteContact} from "@/api/address-book";
|
||||
import {addContact, editContact, getContactDetail, deleteContact, exportContact} from "@/api/address-book";
|
||||
import {ElMessage, ElMessageBox} from "element-plus";
|
||||
import {reactive} from "vue";
|
||||
import ImportExcel from "@/components/ImportExcel.vue";
|
||||
|
||||
const router = useRouter()
|
||||
const tableIns = ref()
|
||||
@@ -50,8 +58,8 @@ const formRules = reactive({
|
||||
{required: true, message: "请输入姓名", trigger: ["change", "blur"]}
|
||||
],
|
||||
phone: [
|
||||
{required: true, message: "请输入手机号码", trigger: ["change", "blur"]},
|
||||
{ validator: checkPhone, trigger: ["change", "blur"]},
|
||||
{required: true, message: "请输入手机号码", trigger: ["change", "blur"]},
|
||||
{validator: checkPhone, trigger: ["change", "blur"]},
|
||||
]
|
||||
});
|
||||
const formSchema = computed(() => {
|
||||
@@ -128,7 +136,7 @@ const formSchema = computed(() => {
|
||||
props: {
|
||||
placeholder: '请输入手机号',
|
||||
clearable: true,
|
||||
controls:false
|
||||
controls: false
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -181,6 +189,8 @@ const searchConfig = reactive([
|
||||
const auths = reactive({
|
||||
add: ['order:contacts:add'],
|
||||
edit: ['order:contacts:edit'],
|
||||
import: ['order:contacts:import'],
|
||||
export: ['order:contacts:export'],
|
||||
delete: ['order:contacts:del'],
|
||||
})
|
||||
const addressBookTableConfig = reactive({
|
||||
@@ -248,8 +258,8 @@ const addressBookTableConfig = reactive({
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
let btn = []
|
||||
btn.push({label: '编辑', prem: auths.edit, func: () => handleEdit(row), type: 'primary'})
|
||||
btn.push({label: '删除', prem: auths.delete,func: () => handleSingleDelete(row), type: 'danger'})
|
||||
btn.push({label: '编辑', prem: auths.edit, func: () => handleEdit(row), type: 'primary'})
|
||||
btn.push({label: '删除', prem: auths.delete, func: () => handleSingleDelete(row), type: 'danger'})
|
||||
return (
|
||||
<div style={{width: '100%'}}>
|
||||
{
|
||||
@@ -272,8 +282,10 @@ const addressBookTableConfig = reactive({
|
||||
api: '/contact/list',
|
||||
params: {},
|
||||
btns: [
|
||||
{name: '新增', key: 'add', type: 'primary' , auth: auths.add},
|
||||
{name: '删除', key: 'delete', type: 'danger', auth: auths.delete},
|
||||
// {name: '新增', key: 'add', type: 'primary', auth: auths.add},
|
||||
// {name: '导入', key: 'import', type: 'warning', auth: auths.import},
|
||||
// {name: '导出', key: 'export', type: 'info', auth: auths.export},
|
||||
// {name: '删除', key: 'delete', type: 'danger', auth: auths.delete},
|
||||
]
|
||||
})
|
||||
const searchAddressBook = (val) => {
|
||||
@@ -286,18 +298,50 @@ const searchAddressBook = (val) => {
|
||||
addressBookTableConfig.params = obj
|
||||
tableIns.value.refresh()
|
||||
}
|
||||
|
||||
const importAddress = () => {
|
||||
tableIns.value.refresh()
|
||||
}
|
||||
const headBtnClick = (key) => {
|
||||
switch (key) {
|
||||
case 'add':
|
||||
handleAdd()
|
||||
break;
|
||||
case 'import':
|
||||
handleImport()
|
||||
break;
|
||||
case 'export':
|
||||
handleExport()
|
||||
break;
|
||||
case 'delete':
|
||||
handleMoreDelete()
|
||||
break;
|
||||
}
|
||||
}
|
||||
//通讯录导入
|
||||
const handleImport = () => {
|
||||
|
||||
}
|
||||
//通讯录导出
|
||||
const handleExport = () => {
|
||||
exportContact().then(res => {
|
||||
let link = document.createElement('a')
|
||||
try {
|
||||
let blob = new Blob([res.data], {type: 'application/vnd.ms-excel'});
|
||||
let _fileName = "运维智能语音服务系统-通讯录.xlsx"
|
||||
link.style.display = 'none';
|
||||
// 兼容不同浏览器的URL对象
|
||||
const url = window.URL || window.webkitURL || window.moxURL;
|
||||
link.href = url.createObjectURL(blob);
|
||||
link.setAttribute('download', _fileName.substring(_fileName.lastIndexOf('_') + 1))
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
url.revokeObjectURL(link.href);//销毁url对象
|
||||
} catch (e) {
|
||||
console.log('下载的文件出错', e)
|
||||
}
|
||||
})
|
||||
}
|
||||
const handleAdd = () => {
|
||||
formDialogRef.value.openOrCloseDialog(true)
|
||||
dialogTitle.value = "新增通讯录";
|
||||
@@ -333,7 +377,7 @@ const selectionChange = (selection) => {
|
||||
if (selection.length !== 0) {
|
||||
contactIds.value = selection.map(item => item.contactsId).join()
|
||||
} else {
|
||||
contactIds.value=''
|
||||
contactIds.value = ''
|
||||
}
|
||||
}
|
||||
const deleteContactMethod = (contactsId) => {
|
||||
@@ -347,17 +391,17 @@ const deleteContactMethod = (contactsId) => {
|
||||
})
|
||||
}
|
||||
const handleMoreDelete = () => {
|
||||
if(contactIds.value){
|
||||
ElMessageBox.confirm(`确认删除选择的通讯录吗?`, '系统提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
if (contactIds.value) {
|
||||
ElMessageBox.confirm(`确认删除选择的通讯录吗?`, '系统提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
deleteContactMethod(contactIds.value)
|
||||
})
|
||||
}else{
|
||||
ElMessage.warning("请选择要删除的通讯录")
|
||||
}
|
||||
})
|
||||
} else {
|
||||
ElMessage.warning("请选择要删除的通讯录")
|
||||
}
|
||||
}
|
||||
const handleSingleDelete = (row) => {
|
||||
ElMessageBox.confirm(`确认删除姓名为${row.name}的通讯录吗?`, '系统提示', {
|
||||
@@ -374,13 +418,13 @@ const handleSubmitAddressBook = async (formInstance) => {
|
||||
if (!formInstance) return;
|
||||
let validate = await formInstance.validate()
|
||||
if (!validate.isValidate) return;
|
||||
if(formInstance.getValues().role=='0'&&!formInstance.getValues().team){
|
||||
ElMessage.warning('请输入班组信息');
|
||||
return;
|
||||
if (formInstance.getValues().role == '0' && !formInstance.getValues().team) {
|
||||
ElMessage.warning('请输入班组信息');
|
||||
return;
|
||||
}
|
||||
if(formInstance.getValues().role=='1'&&!formInstance.getValues().dispatchUnit){
|
||||
ElMessage.warning('请输入拨打单位');
|
||||
return;
|
||||
if (formInstance.getValues().role == '1' && !formInstance.getValues().dispatchUnit) {
|
||||
ElMessage.warning('请输入拨打单位');
|
||||
return;
|
||||
}
|
||||
if (dialogType.value === "add") {
|
||||
|
||||
@@ -407,11 +451,12 @@ const handleSubmitAddressBook = async (formInstance) => {
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.address-book{
|
||||
.address-book {
|
||||
|
||||
.el-input-number {
|
||||
width: 100% !important;
|
||||
.el-input__inner{
|
||||
|
||||
.el-input__inner {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user