封装函数式弹窗、入职财务接口对接、开票申请接口对接
This commit is contained in:
@@ -30,8 +30,8 @@ export const FinanceIssueInvoice = (data: any) => {
|
||||
// 开票分页查询
|
||||
export const FinanceIssueDetail = (data: any) => {
|
||||
const formData = new FormData();
|
||||
formData.append("page", data.page);
|
||||
formData.append("per_page", data.per_page);
|
||||
formData.append("page", data.pageNum);
|
||||
formData.append("per_page", data.pageSize);
|
||||
return request({
|
||||
url: `${AUTH_BASE_URL}/finance/issue-Detail`,
|
||||
method: "post",
|
||||
|
||||
@@ -8,7 +8,7 @@ import { usePermissionStoreHook } from "@/store/modules/permission-store";
|
||||
import { useDictStoreHook } from "@/store/modules/dict-store";
|
||||
import { useTagsViewStore } from "@/store";
|
||||
import { cleanupWebSocket } from "@/plugins/websocket";
|
||||
import { userLogin } from "@/api/calibration/login";
|
||||
import { UserGetInfo, userLogin } from "@/api/calibration/login";
|
||||
|
||||
export const useUserStore = defineStore("user", () => {
|
||||
// 用户信息
|
||||
@@ -32,7 +32,7 @@ export const useUserStore = defineStore("user", () => {
|
||||
AuthStorage.setTokens(accessToken, refreshToken, rememberMe.value);
|
||||
userLogin(LoginFormData)
|
||||
.then(() => {
|
||||
console.log("login success");
|
||||
getUserInfo(LoginFormData.username);
|
||||
resolve();
|
||||
})
|
||||
.catch((error) => {
|
||||
@@ -50,16 +50,16 @@ export const useUserStore = defineStore("user", () => {
|
||||
*
|
||||
* @returns {UserInfo} 用户信息
|
||||
*/
|
||||
function getUserInfo() {
|
||||
function getUserInfo(username: string) {
|
||||
return new Promise<UserInfo>((resolve, reject) => {
|
||||
UserAPI.getInfo()
|
||||
.then((data) => {
|
||||
if (!data) {
|
||||
UserGetInfo(username)
|
||||
.then((res: any) => {
|
||||
if (!res) {
|
||||
reject("Verification failed, please Login again.");
|
||||
return;
|
||||
}
|
||||
Object.assign(userInfo.value, { ...data });
|
||||
resolve(data);
|
||||
setUserInfo(res.data);
|
||||
resolve(res);
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error);
|
||||
@@ -67,6 +67,9 @@ export const useUserStore = defineStore("user", () => {
|
||||
});
|
||||
}
|
||||
|
||||
const setUserInfo = (info: any) => {
|
||||
userInfo.value = info;
|
||||
};
|
||||
/**
|
||||
* 登出
|
||||
*/
|
||||
@@ -148,6 +151,7 @@ export const useUserStore = defineStore("user", () => {
|
||||
rememberMe,
|
||||
isLoggedIn: () => !!AuthStorage.getAccessToken(),
|
||||
getUserInfo,
|
||||
setUserInfo,
|
||||
login,
|
||||
logout,
|
||||
resetAllState,
|
||||
|
||||
81
src/utils/functionDialogBox/index.ts
Normal file
81
src/utils/functionDialogBox/index.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { ElButton, ElDialog } from "element-plus";
|
||||
import { Component, DefineComponent } from "vue";
|
||||
import { h, createApp } from "vue";
|
||||
|
||||
// 定义模态框属性接口
|
||||
interface ModalProps {
|
||||
title?: string;
|
||||
width?: string | number;
|
||||
ok?: (result: any) => void;
|
||||
cancel?: () => void;
|
||||
[key: string]: any; // 允许其他 Element Plus Dialog 属性
|
||||
}
|
||||
|
||||
interface DialogInstance {
|
||||
unmount: () => void;
|
||||
}
|
||||
|
||||
// 函数式弹窗组件
|
||||
export const functionDialogBox = (
|
||||
component: Component | DefineComponent | null,
|
||||
props: Record<string, any>,
|
||||
modalProps: ModalProps
|
||||
): DialogInstance => {
|
||||
const open = ref(true);
|
||||
const formRef = ref();
|
||||
const dialog = () =>
|
||||
h(
|
||||
ElDialog,
|
||||
{
|
||||
...modalProps,
|
||||
modelValue: open.value,
|
||||
onOpen() {},
|
||||
onClosed() {
|
||||
app.unmount();
|
||||
document.body.removeChild(div);
|
||||
},
|
||||
},
|
||||
{
|
||||
default: () => h(component || h("div"), { ref: formRef, ...props }),
|
||||
footer: () => [
|
||||
h(
|
||||
ElButton,
|
||||
{
|
||||
type: "primary",
|
||||
async onClick() {
|
||||
await formRef.value?.submit?.();
|
||||
const awd = formRef.value?.getForm?.();
|
||||
modalProps?.ok?.(awd);
|
||||
unmount();
|
||||
},
|
||||
},
|
||||
() => "确定"
|
||||
),
|
||||
h(
|
||||
ElButton,
|
||||
{
|
||||
onClick() {
|
||||
modalProps?.cancel?.();
|
||||
unmount();
|
||||
},
|
||||
},
|
||||
() => "取消"
|
||||
),
|
||||
],
|
||||
}
|
||||
);
|
||||
|
||||
const app = createApp(dialog);
|
||||
|
||||
const div = document.createElement("div");
|
||||
document.body.appendChild(div);
|
||||
app.mount(div);
|
||||
|
||||
function unmount() {
|
||||
open.value = false;
|
||||
}
|
||||
|
||||
return {
|
||||
unmount,
|
||||
};
|
||||
};
|
||||
@@ -23,7 +23,7 @@ const generateRandomToken = () => {
|
||||
*/
|
||||
const httpRequest = axios.create({
|
||||
baseURL: import.meta.env.VITE_APP_BASE_API,
|
||||
timeout: 50000,
|
||||
timeout: 500000,
|
||||
headers: { "Content-Type": "application/json;charset=utf-8" },
|
||||
paramsSerializer: (params) => qs.stringify(params),
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<el-form ref="fomrRef" :model="formInline" label-width="auto" :rules="rules">
|
||||
<el-form-item label="审核人员" prop="personincharge">
|
||||
<el-select v-model="formInline.personincharge" placeholder="请选择审核人员(负责人或者部门)">
|
||||
<el-option v-for="item in options" :key="item.id" :label="item.name" :value="item.name" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { UserDepartment } from "@/api/calibration/department";
|
||||
|
||||
const fomrRef = ref();
|
||||
const options = ref<any[]>([]);
|
||||
const rules = ref({
|
||||
personincharge: [{ required: true, message: "请选择审核人员", trigger: "change" }],
|
||||
});
|
||||
|
||||
const DepartmentList = (name: string = "") => {
|
||||
UserDepartment(name).then((res: any) => {
|
||||
options.value = res.data;
|
||||
});
|
||||
};
|
||||
|
||||
const formInline = reactive({
|
||||
personincharge: "",
|
||||
});
|
||||
|
||||
const getForm = () => {
|
||||
return formInline;
|
||||
};
|
||||
const submit = () => {
|
||||
return fomrRef.value?.validate();
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
submit,
|
||||
getForm,
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
DepartmentList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -1,83 +0,0 @@
|
||||
<!-- 部门树 -->
|
||||
<template>
|
||||
<el-card shadow="never">
|
||||
<el-input v-model="deptName" placeholder="部门名称" clearable @input="deptNameInput">
|
||||
<template #prefix>
|
||||
<el-icon><Search /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
<el-tree
|
||||
ref="deptTreeRef"
|
||||
class="mt-2"
|
||||
:data="deptList"
|
||||
:props="{ children: 'children', label: 'name', disabled: '' }"
|
||||
node-key="id"
|
||||
highlight-current
|
||||
:current-node-key="deptList?.length ? deptList[0].id : ''"
|
||||
:expand-on-click-node="false"
|
||||
:filter-node-method="handleFilter"
|
||||
default-expand-all
|
||||
@node-click="handleNodeClick"
|
||||
/>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { UserDepartment } from "@/api/calibration/department";
|
||||
import { throttle } from "@/utils/auxiliaryFunction";
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: [String, Number],
|
||||
default: undefined,
|
||||
},
|
||||
});
|
||||
|
||||
const deptList = ref<any[]>(); // 部门列表
|
||||
const deptTreeRef = ref(); // 部门树
|
||||
const deptName = ref(""); // 部门名称
|
||||
|
||||
const emits = defineEmits(["node-click", "update:modelValue"]);
|
||||
|
||||
const deptId = useVModel(props, "modelValue", emits);
|
||||
|
||||
// watchEffect(
|
||||
// () => {
|
||||
// deptTreeRef.value.filter(deptName.value);
|
||||
// },
|
||||
// {
|
||||
// flush: "post", // watchEffect会在DOM挂载或者更新之前就会触发,此属性控制在DOM元素更新后运行
|
||||
// }
|
||||
// );
|
||||
|
||||
const deptNameInput = throttle((value: string) => {
|
||||
DepartmentList(value);
|
||||
}, 300);
|
||||
/**
|
||||
* 部门筛选
|
||||
*/
|
||||
function handleFilter(value: string, data: any) {
|
||||
if (!value) {
|
||||
return true;
|
||||
}
|
||||
return data.label.indexOf(value) !== -1;
|
||||
}
|
||||
|
||||
/** 部门树节点 Click */
|
||||
function handleNodeClick(data: { [key: string]: any }) {
|
||||
deptId.value = data.name;
|
||||
emits("node-click");
|
||||
}
|
||||
const DepartmentList = (name: string = "") => {
|
||||
UserDepartment(name).then((res: any) => {
|
||||
deptList.value = res.data;
|
||||
if (deptList.value && deptList.value.length > 0) {
|
||||
deptId.value = deptList.value[0].name;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onBeforeMount(() => {
|
||||
DepartmentList();
|
||||
});
|
||||
</script>
|
||||
@@ -1,198 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="visible"
|
||||
:align-center="true"
|
||||
title="导入数据"
|
||||
width="600px"
|
||||
@close="handleClose"
|
||||
>
|
||||
<el-scrollbar max-height="60vh">
|
||||
<el-form
|
||||
ref="importFormRef"
|
||||
style="padding-right: var(--el-dialog-padding-primary)"
|
||||
:model="importFormData"
|
||||
:rules="importFormRules"
|
||||
>
|
||||
<el-form-item label="文件名" prop="files">
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
v-model:file-list="importFormData.files"
|
||||
class="w-full"
|
||||
accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
|
||||
:drag="true"
|
||||
:limit="1"
|
||||
:auto-upload="false"
|
||||
:on-exceed="handleFileExceed"
|
||||
>
|
||||
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
||||
<div class="el-upload__text">
|
||||
将文件拖到此处,或
|
||||
<em>点击上传</em>
|
||||
</div>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">
|
||||
格式为*.xlsx / *.xls,文件不超过一个
|
||||
<el-link
|
||||
type="primary"
|
||||
icon="download"
|
||||
underline="never"
|
||||
@click="handleDownloadTemplate"
|
||||
>
|
||||
下载模板
|
||||
</el-link>
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-scrollbar>
|
||||
<template #footer>
|
||||
<div style="padding-right: var(--el-dialog-padding-primary)">
|
||||
<el-button v-if="resultData.length > 0" type="primary" @click="handleShowResult">
|
||||
错误信息
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
:disabled="importFormData.files.length === 0"
|
||||
@click="handleUpload"
|
||||
>
|
||||
确 定
|
||||
</el-button>
|
||||
<el-button @click="handleClose">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="resultVisible" title="导入结果" width="600px">
|
||||
<el-alert
|
||||
:title="`导入结果:${invalidCount}条无效数据,${validCount}条有效数据`"
|
||||
type="warning"
|
||||
:closable="false"
|
||||
/>
|
||||
<el-table :data="resultData" style="width: 100%; max-height: 400px">
|
||||
<el-table-column prop="index" align="center" width="100" type="index" label="序号" />
|
||||
<el-table-column prop="message" label="错误信息" width="400">
|
||||
<template #default="scope">
|
||||
{{ scope.row }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="handleCloseResult">关闭</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ElMessage, type UploadUserFile } from "element-plus";
|
||||
import UserAPI from "@/api/system/user-api";
|
||||
import { ApiCodeEnum } from "@/enums/api/code-enum";
|
||||
|
||||
const emit = defineEmits(["import-success"]);
|
||||
const visible = defineModel("modelValue", {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
default: false,
|
||||
});
|
||||
|
||||
const resultVisible = ref(false);
|
||||
const resultData = ref<string[]>([]);
|
||||
const invalidCount = ref(0);
|
||||
const validCount = ref(0);
|
||||
|
||||
const importFormRef = ref(null);
|
||||
const uploadRef = ref(null);
|
||||
|
||||
const importFormData = reactive<{
|
||||
files: UploadUserFile[];
|
||||
}>({
|
||||
files: [],
|
||||
});
|
||||
|
||||
watch(visible, (newValue) => {
|
||||
if (newValue) {
|
||||
resultData.value = [];
|
||||
resultVisible.value = false;
|
||||
invalidCount.value = 0;
|
||||
validCount.value = 0;
|
||||
}
|
||||
});
|
||||
|
||||
const importFormRules = {
|
||||
files: [{ required: true, message: "文件不能为空", trigger: "blur" }],
|
||||
};
|
||||
|
||||
// 文件超出个数限制
|
||||
const handleFileExceed = () => {
|
||||
ElMessage.warning("只能上传一个文件");
|
||||
};
|
||||
|
||||
// 下载导入模板
|
||||
const handleDownloadTemplate = () => {
|
||||
UserAPI.downloadTemplate().then((response: any) => {
|
||||
const fileData = response.data;
|
||||
const fileName = decodeURI(response.headers["content-disposition"].split(";")[1].split("=")[1]);
|
||||
const fileType =
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8";
|
||||
|
||||
const blob = new Blob([fileData], { type: fileType });
|
||||
const downloadUrl = window.URL.createObjectURL(blob);
|
||||
|
||||
const downloadLink = document.createElement("a");
|
||||
downloadLink.href = downloadUrl;
|
||||
downloadLink.download = fileName;
|
||||
|
||||
document.body.appendChild(downloadLink);
|
||||
downloadLink.click();
|
||||
|
||||
document.body.removeChild(downloadLink);
|
||||
window.URL.revokeObjectURL(downloadUrl);
|
||||
});
|
||||
};
|
||||
|
||||
// 上传文件
|
||||
const handleUpload = async () => {
|
||||
if (!importFormData.files.length) {
|
||||
ElMessage.warning("请选择文件");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await UserAPI.import("1", importFormData.files[0].raw as File);
|
||||
if (result.code === ApiCodeEnum.SUCCESS && result.invalidCount === 0) {
|
||||
ElMessage.success("导入成功,导入数据:" + result.validCount + "条");
|
||||
emit("import-success");
|
||||
handleClose();
|
||||
} else {
|
||||
ElMessage.error("上传失败");
|
||||
resultVisible.value = true;
|
||||
resultData.value = result.messageList;
|
||||
invalidCount.value = result.invalidCount;
|
||||
validCount.value = result.validCount;
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
ElMessage.error("上传失败:" + error);
|
||||
}
|
||||
};
|
||||
|
||||
// 显示错误信息
|
||||
const handleShowResult = () => {
|
||||
resultVisible.value = true;
|
||||
};
|
||||
|
||||
// 关闭错误信息弹窗
|
||||
const handleCloseResult = () => {
|
||||
resultVisible.value = false;
|
||||
};
|
||||
|
||||
// 关闭弹窗
|
||||
const handleClose = () => {
|
||||
importFormData.files.length = 0;
|
||||
visible.value = false;
|
||||
};
|
||||
</script>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -460,7 +460,7 @@ const loading = ref(false);
|
||||
// 弹窗状态
|
||||
const dialog = reactive({
|
||||
visible: false,
|
||||
title: "新增用户",
|
||||
title: "新增人员",
|
||||
});
|
||||
|
||||
// 表单数据
|
||||
@@ -698,7 +698,7 @@ async function handleOpenDialog(data?: any): Promise<void> {
|
||||
|
||||
// 编辑:加载用户数据
|
||||
if (data?.id) {
|
||||
dialog.title = "修改用户";
|
||||
dialog.title = "修改人员";
|
||||
try {
|
||||
const data1 = deepCloneByJSON(data);
|
||||
data1.academic = parseJsonToArray(data1.academic);
|
||||
@@ -713,7 +713,7 @@ async function handleOpenDialog(data?: any): Promise<void> {
|
||||
}
|
||||
} else {
|
||||
// 新增:设置默认值
|
||||
dialog.title = "新增用户";
|
||||
dialog.title = "新增人员";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user