提交票据审核及页面权限分配
This commit is contained in:
parent
2ba70dd160
commit
a00df77cf6
@ -2,6 +2,7 @@ import axios from 'axios';
|
|||||||
import type { AxiosRequestConfig, AxiosResponse } from 'axios';
|
import type { AxiosRequestConfig, AxiosResponse } from 'axios';
|
||||||
import { Message, Modal } from '@arco-design/web-vue';
|
import { Message, Modal } from '@arco-design/web-vue';
|
||||||
import { getToken } from '@/utils/auth';
|
import { getToken } from '@/utils/auth';
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
|
|
||||||
export interface HttpResponse<T = unknown> {
|
export interface HttpResponse<T = unknown> {
|
||||||
status: number;
|
status: number;
|
||||||
|
@ -28,22 +28,22 @@ export function enabled(id: string) {
|
|||||||
return axios.patch(`/api/rest/role/${id}/toggle`);
|
return axios.patch(`/api/rest/role/${id}/toggle`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除用户
|
// 删除
|
||||||
export function remove(id: string) {
|
export function remove(id: string) {
|
||||||
return axios.delete(`/api/rest/role/${id}`);
|
return axios.delete(`/api/rest/role/${id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加角色
|
// 添加
|
||||||
export function create(data: RoleCreateRecord) {
|
export function create(data: RoleCreateRecord) {
|
||||||
return axios.post(`/api/rest/role`, data);
|
return axios.post(`/api/rest/role`, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新用户
|
// 更新
|
||||||
export function update(data: RoleRecord) {
|
export function update(data: RoleRecord) {
|
||||||
return axios.patch(`/api/rest/role/${data.id}`, data);
|
return axios.patch(`/api/rest/role/${data.id}`, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取用户详情
|
// 获取详情
|
||||||
export function getDetail(id: string) {
|
export function getDetail(id: string) {
|
||||||
return axios.get<RoleRecord>(`/api/rest/role/${id}`);
|
return axios.get<RoleRecord>(`/api/rest/role/${id}`);
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,28 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
export interface TicketCreateRecord {
|
export interface TicketCreateRecord {
|
||||||
remark: string;
|
|
||||||
createTime: string;
|
|
||||||
title: string;
|
title: string;
|
||||||
body: string;
|
body: string;
|
||||||
money: undefined;
|
money: undefined;
|
||||||
status: string;
|
|
||||||
type: string;
|
type: string;
|
||||||
contactEmail: string;
|
contactEmail: string;
|
||||||
companyName: string;
|
companyName: string;
|
||||||
|
attachId: string;
|
||||||
|
auditorId: string;
|
||||||
|
submit: boolean;
|
||||||
|
userId: undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TicketRecord extends TicketCreateRecord {
|
export interface TicketRecord extends TicketCreateRecord {
|
||||||
|
value: any;
|
||||||
id: undefined;
|
id: undefined;
|
||||||
|
status: string
|
||||||
|
}
|
||||||
|
export interface auditRecord {
|
||||||
|
auditorId: string;
|
||||||
|
comment: string;
|
||||||
|
result: string;
|
||||||
|
ticketId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function queryTicket(data: any) {
|
export function queryTicket(data: any) {
|
||||||
@ -28,9 +37,10 @@ export function getDetail(id: string) {
|
|||||||
return axios.get(`/api/rest/bill/${id}`);
|
return axios.get(`/api/rest/bill/${id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 更新票据
|
// 更新票据
|
||||||
export function update(data: TicketRecord) {
|
export function update(data: TicketRecord) {
|
||||||
return axios.patch(`/api/rest/user/${data.id}`, data);
|
return axios.patch(`/api/rest/bill/${data.id}`, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除票据
|
// 删除票据
|
||||||
@ -42,3 +52,28 @@ export function remove(id: string) {
|
|||||||
export function create(params: TicketCreateRecord) {
|
export function create(params: TicketCreateRecord) {
|
||||||
return axios.post('/api/rest/bill', params);
|
return axios.post('/api/rest/bill', params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 上传附件
|
||||||
|
export function uploadFile(file: any) {
|
||||||
|
return axios.post('/api/rest/attachment', file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取附件信息
|
||||||
|
export function attachment(id:string){
|
||||||
|
return axios.get(`/api/rest/attachment/find/${id}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 审核
|
||||||
|
export function audit(ticketId: string, params: auditRecord) {
|
||||||
|
return axios.patch(`/api/rest/bill/audit/${ticketId}`, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 审核员管理的票据列表
|
||||||
|
export function auditTickctList(data: any){
|
||||||
|
return axios({
|
||||||
|
url: '/api/rest/bill/audit/list', // 路径
|
||||||
|
method: 'get',
|
||||||
|
params: data, // 参数
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ export interface PasswordReSetModel {
|
|||||||
|
|
||||||
// 添加用户数据
|
// 添加用户数据
|
||||||
export interface CreateRecord {
|
export interface CreateRecord {
|
||||||
|
|
||||||
username: string;
|
username: string;
|
||||||
nickName: string;
|
nickName: string;
|
||||||
password: string;
|
password: string;
|
||||||
@ -39,8 +40,9 @@ export interface CreateRecord {
|
|||||||
enabled: string;
|
enabled: string;
|
||||||
address: string;
|
address: string;
|
||||||
deptId: DeptRecord | undefined;
|
deptId: DeptRecord | undefined;
|
||||||
roleId: RoleRecord | undefined;
|
roleId: string| RoleRecord | undefined;
|
||||||
permissionIds: (number | undefined)[];
|
permissionIds: (number | undefined)[];
|
||||||
|
authorities: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SelfRecord {
|
export interface SelfRecord {
|
||||||
@ -53,12 +55,16 @@ export interface SelfRecord {
|
|||||||
|
|
||||||
// 用户数据
|
// 用户数据
|
||||||
export interface UserRecord extends CreateRecord {
|
export interface UserRecord extends CreateRecord {
|
||||||
id: number;
|
value: any;
|
||||||
|
id: string;
|
||||||
|
avatar: string;
|
||||||
|
createAt: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UserParams extends Partial<UserRecord> {
|
export interface UserParams extends Partial<UserRecord> {
|
||||||
page: number;
|
page: number;
|
||||||
size: number;
|
size: number;
|
||||||
|
current: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Pageable {
|
export interface Pageable {
|
||||||
@ -108,14 +114,20 @@ export function create(data: CreateRecord) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 模糊查询用户列表
|
// 模糊查询用户列表
|
||||||
export function queryUserList(params: UserParams) {
|
export function queryUserList(params: any) {
|
||||||
return axios({
|
return axios({
|
||||||
url: '/api/rest/user/query',
|
url: '/api/rest/user',
|
||||||
params,
|
params,
|
||||||
method: 'get',
|
method: 'get',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 根据id查询用户信息
|
||||||
|
export function userDetail(id: string){
|
||||||
|
return axios.get(`/api/rest/user/${id}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 是否启用
|
// 是否启用
|
||||||
export function enabled(id: string) {
|
export function enabled(id: string) {
|
||||||
return axios.patch(`/api/rest/user/${id}/toggle`);
|
return axios.patch(`/api/rest/user/${id}/toggle`);
|
||||||
@ -135,15 +147,23 @@ export function selfUpdate(data: UserState) {
|
|||||||
return axios.patch<Res>(`/api/rest/user/self`, data);
|
return axios.patch<Res>(`/api/rest/user/self`, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function switchRole(roleId: number) {
|
|
||||||
return axios.patch<UserState>(`/api/user/self/switch-role/${roleId}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取个人用户信息
|
// 获取个人用户信息
|
||||||
export function getUserInfo() {
|
export function getUserInfo() {
|
||||||
return axios.get<UserState>('/api/rest/user/self');
|
return axios.get<UserState>('/api/rest/user/self');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 部门的审核员
|
||||||
|
export function deptAudit(id: string,roleId:string){
|
||||||
|
return axios({
|
||||||
|
url: `/api/rest/user/dept/${id}?roleId=${roleId}`, // 路径
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function switchRole(roleId: number) {
|
||||||
|
return axios.patch<UserState>(`/api/user/self/switch-role/${roleId}`);
|
||||||
|
}
|
||||||
|
|
||||||
export function getUserDetail(id: number) {
|
export function getUserDetail(id: number) {
|
||||||
return axios.get<UserState>(`/api/user/${id}`);
|
return axios.get<UserState>(`/api/user/${id}`);
|
||||||
}
|
}
|
||||||
|
@ -204,8 +204,11 @@ import useUser from '@/hooks/user';
|
|||||||
import Menu from '@/components/menu/index.vue';
|
import Menu from '@/components/menu/index.vue';
|
||||||
import userIcon from '@/assets/images/user-circle.png';
|
import userIcon from '@/assets/images/user-circle.png';
|
||||||
import { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
|
import { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import { clearToken } from '@/utils/auth';
|
||||||
import MessageBox from '../message-box/index.vue';
|
import MessageBox from '../message-box/index.vue';
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const { logout } = useUser();
|
const { logout } = useUser();
|
||||||
@ -257,7 +260,12 @@ const setPopoverVisible = () => {
|
|||||||
refBtn.value.dispatchEvent(event);
|
refBtn.value.dispatchEvent(event);
|
||||||
};
|
};
|
||||||
const handleLogout = () => {
|
const handleLogout = () => {
|
||||||
logout();
|
// logout();
|
||||||
|
|
||||||
|
clearToken();
|
||||||
|
router.push({
|
||||||
|
name: 'login',
|
||||||
|
});
|
||||||
};
|
};
|
||||||
const setDropDownVisible = () => {
|
const setDropDownVisible = () => {
|
||||||
const event = new MouseEvent('click', {
|
const event = new MouseEvent('click', {
|
||||||
|
@ -6,12 +6,13 @@ export default function usePermission() {
|
|||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
return {
|
return {
|
||||||
accessRouter(route: RouteLocationNormalized | RouteRecordRaw) {
|
accessRouter(route: RouteLocationNormalized | RouteRecordRaw) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
!route.meta?.requiresAuth ||
|
!route.meta?.requiresAuth ||
|
||||||
!route.meta?.permissions ||
|
!route.meta?.permissions ||
|
||||||
route.meta?.permissions?.includes('*') ||
|
route.meta?.permissions?.includes('*') ||
|
||||||
intersection(route.meta?.permissions, userStore.permissions).length > 0
|
intersection(route.meta?.permissions, userStore.permissions).length > 0
|
||||||
// route.meta?.permissions?.includes(userStore.permissions)
|
|| route.meta?.permissions?.includes(userStore.permissions)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
// TODO 不知道是干嘛的
|
// TODO 不知道是干嘛的
|
||||||
|
@ -12,6 +12,7 @@ export default function setupPermissionGuard(router: Router) {
|
|||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const Permission = usePermission();
|
const Permission = usePermission();
|
||||||
const permissionsAllow = Permission.accessRouter(to);
|
const permissionsAllow = Permission.accessRouter(to);
|
||||||
|
|
||||||
if (appStore.menuFromServer) {
|
if (appStore.menuFromServer) {
|
||||||
// 针对来自服务端的菜单配置进行处理
|
// 针对来自服务端的菜单配置进行处理
|
||||||
// Handle routing configuration from the server
|
// Handle routing configuration from the server
|
||||||
|
@ -14,6 +14,7 @@ export default function setupUserLoginInfoGuard(router: Router) {
|
|||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
await userStore.info();
|
await userStore.info();
|
||||||
|
|
||||||
next();
|
next();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await userStore.logout();
|
await userStore.logout();
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
export default {
|
// export default {
|
||||||
path: 'https://arco.design',
|
// path: 'https://arco.design',
|
||||||
name: 'arcoWebsite',
|
// name: 'arcoWebsite',
|
||||||
meta: {
|
// meta: {
|
||||||
locale: 'menu.arcoWebsite',
|
// locale: 'menu.arcoWebsite',
|
||||||
icon: 'icon-link',
|
// icon: 'icon-link',
|
||||||
requiresAuth: true,
|
// requiresAuth: true,
|
||||||
order: 8,
|
// order: 8,
|
||||||
},
|
// },
|
||||||
};
|
// };
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
export default {
|
// export default {
|
||||||
path: 'https://arco.design/vue/docs/pro/faq',
|
// path: 'https://arco.design/vue/docs/pro/faq',
|
||||||
name: 'faq',
|
// name: 'faq',
|
||||||
meta: {
|
// meta: {
|
||||||
locale: 'menu.faq',
|
// locale: 'menu.faq',
|
||||||
icon: 'icon-question-circle',
|
// icon: 'icon-question-circle',
|
||||||
requiresAuth: true,
|
// requiresAuth: true,
|
||||||
order: 9,
|
// order: 9,
|
||||||
},
|
// },
|
||||||
};
|
// };
|
||||||
|
@ -23,16 +23,16 @@ const DASHBOARD: AppRouteRecordRaw = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
// {
|
||||||
path: 'monitor', // 一级路径
|
// path: 'monitor', // 一级路径
|
||||||
name: 'Monitor', // 路由名称
|
// name: 'Monitor', // 路由名称
|
||||||
component: () => import('@/views/dashboard/monitor/index.vue'), // 要跳转的视图,这里要跳转到页面的基本布局
|
// component: () => import('@/views/dashboard/monitor/index.vue'), // 要跳转的视图,这里要跳转到页面的基本布局
|
||||||
meta: {
|
// meta: {
|
||||||
locale: 'menu.dashboard.monitor', // 菜单名字
|
// locale: 'menu.dashboard.monitor', // 菜单名字
|
||||||
requiresAuth: true, // 需要登录鉴权
|
// requiresAuth: true, // 需要登录鉴权
|
||||||
permissions: ['admin'], // 只允许管理员用户访问
|
// permissions: ['admin'], // 只允许管理员用户访问
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ const SYSTEM: AppRouteRecordRaw = {
|
|||||||
meta: {
|
meta: {
|
||||||
locale: 'menu.system.role',
|
locale: 'menu.system.role',
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
permissions: ['*'],
|
permissions: ['admin'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -39,7 +39,7 @@ const SYSTEM: AppRouteRecordRaw = {
|
|||||||
meta: {
|
meta: {
|
||||||
locale: 'menu.system.dept',
|
locale: 'menu.system.dept',
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
permissions: ['*'],
|
permissions: ['admin'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -49,7 +49,7 @@ const SYSTEM: AppRouteRecordRaw = {
|
|||||||
meta: {
|
meta: {
|
||||||
locale: 'menu.system.user',
|
locale: 'menu.system.user',
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
permissions: ['*'],
|
permissions: ['admin'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -22,16 +22,16 @@ const TICKET: AppRouteRecordRaw = {
|
|||||||
permissions: ['*'],
|
permissions: ['*'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
path: 'form',
|
// path: 'form',
|
||||||
name: 'TicketForm',
|
// name: 'TicketForm',
|
||||||
component: () => import('@/views/ticket/form/index.vue'),
|
// component: () => import('@/views/ticket/form/index.vue'),
|
||||||
meta: {
|
// meta: {
|
||||||
locale: 'menu.ticket.form',
|
// locale: 'menu.ticket.form',
|
||||||
requiresAuth: true,
|
// requiresAuth: true,
|
||||||
permissions: ['*'],
|
// permissions: ['*'],
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,11 +2,17 @@ import { defineStore } from 'pinia';
|
|||||||
import {
|
import {
|
||||||
TicketRecord,
|
TicketRecord,
|
||||||
TicketCreateRecord,
|
TicketCreateRecord,
|
||||||
|
auditRecord,
|
||||||
queryTicket,
|
queryTicket,
|
||||||
remove,
|
remove,
|
||||||
getDetail,
|
getDetail,
|
||||||
create,
|
create,
|
||||||
update,
|
update,
|
||||||
|
uploadFile,
|
||||||
|
attachment,
|
||||||
|
audit,
|
||||||
|
auditTickctList,
|
||||||
|
|
||||||
} from '@/api/ticket';
|
} from '@/api/ticket';
|
||||||
import { ticketStore } from './type';
|
import { ticketStore } from './type';
|
||||||
|
|
||||||
@ -22,6 +28,7 @@ const useTicketStore = defineStore('ticket', {
|
|||||||
type: undefined,
|
type: undefined,
|
||||||
contactEmail: undefined,
|
contactEmail: undefined,
|
||||||
companyName: undefined,
|
companyName: undefined,
|
||||||
|
userId: undefined,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
getters: {
|
getters: {
|
||||||
@ -49,6 +56,22 @@ const useTicketStore = defineStore('ticket', {
|
|||||||
async updateTicket(data: TicketRecord) {
|
async updateTicket(data: TicketRecord) {
|
||||||
return update(data);
|
return update(data);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async uploadFileTicket(file: any) {
|
||||||
|
return uploadFile(file);
|
||||||
|
},
|
||||||
|
|
||||||
|
async getAttachment(id: string){
|
||||||
|
return attachment(id);
|
||||||
|
},
|
||||||
|
|
||||||
|
async auditTicket(ticketId: string, data: auditRecord) {
|
||||||
|
return audit(ticketId, data);
|
||||||
|
},
|
||||||
|
|
||||||
|
async auditTickctList(data:any){
|
||||||
|
return auditTickctList(data);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -9,4 +9,5 @@ export interface ticketStore {
|
|||||||
type?: undefined;
|
type?: undefined;
|
||||||
contactEmail?: string;
|
contactEmail?: string;
|
||||||
companyName?: string;
|
companyName?: string;
|
||||||
|
userId?: undefined;
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@ import {
|
|||||||
create,
|
create,
|
||||||
UserRecord,
|
UserRecord,
|
||||||
update,
|
update,
|
||||||
|
userDetail,
|
||||||
|
deptAudit
|
||||||
} from '@/api/user';
|
} from '@/api/user';
|
||||||
import { setToken, clearToken } from '@/utils/auth';
|
import { setToken, clearToken } from '@/utils/auth';
|
||||||
import { removeRouteListener } from '@/utils/route-listener';
|
import { removeRouteListener } from '@/utils/route-listener';
|
||||||
@ -32,6 +34,7 @@ const useUserStore = defineStore('user', {
|
|||||||
role: undefined,
|
role: undefined,
|
||||||
roles: undefined,
|
roles: undefined,
|
||||||
permissions: [],
|
permissions: [],
|
||||||
|
authorities: [],
|
||||||
}),
|
}),
|
||||||
|
|
||||||
getters: {
|
getters: {
|
||||||
@ -51,10 +54,11 @@ const useUserStore = defineStore('user', {
|
|||||||
this.$reset();
|
this.$reset();
|
||||||
},
|
},
|
||||||
|
|
||||||
// Get user's information
|
|
||||||
async info() {
|
async info() {
|
||||||
const res = await getUserInfo();
|
const res = await getUserInfo();
|
||||||
this.setInfo(res.data);
|
console.log("we",res);
|
||||||
|
res.data.user.permissions = res.data.permissions
|
||||||
|
this.setInfo(res.data.user);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Get user's crsf
|
// Get user's crsf
|
||||||
@ -74,7 +78,7 @@ const useUserStore = defineStore('user', {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// Get user's List
|
// Get user's List
|
||||||
async getUserList(data: UserParams) {
|
async getUserList(data: any) {
|
||||||
return queryUserList(data);
|
return queryUserList(data);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -98,6 +102,14 @@ const useUserStore = defineStore('user', {
|
|||||||
return update(data);
|
return update(data);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async getUserDetail(id: string){
|
||||||
|
return userDetail(id);
|
||||||
|
},
|
||||||
|
|
||||||
|
async getDeptAudit(deptId: string,roleId: string){
|
||||||
|
return deptAudit(deptId,roleId)
|
||||||
|
},
|
||||||
|
|
||||||
logoutCallBack() {
|
logoutCallBack() {
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
this.resetInfo();
|
this.resetInfo();
|
||||||
|
@ -2,6 +2,7 @@ import { RoleRecord } from '@/api/role';
|
|||||||
|
|
||||||
export type RoleType = '' | '*' | 'admin' | 'user' | string[];
|
export type RoleType = '' | '*' | 'admin' | 'user' | string[];
|
||||||
export interface UserState {
|
export interface UserState {
|
||||||
|
[x: string]: { value: any; id: string; avatar: string; createAt: string; username: string; nickName: string; password: string; phone: string; email: string; enabled: string; address: string; deptId: { id: string; remark: string; createTime: string; name: string; enabled: string; }|undefined; roleId: string|{ id: string; name: string; dataScope: string; permissionIds: (number|undefined)[]; remark: string; authorities: (number|undefined)[]; }|undefined; permissionIds: (number|undefined)[]; authorities: string[]; };
|
||||||
username?: string;
|
username?: string;
|
||||||
nickName?: string;
|
nickName?: string;
|
||||||
avatar?: string;
|
avatar?: string;
|
||||||
@ -13,5 +14,6 @@ export interface UserState {
|
|||||||
id?: number;
|
id?: number;
|
||||||
role?: RoleRecord;
|
role?: RoleRecord;
|
||||||
roles?: RoleRecord[];
|
roles?: RoleRecord[];
|
||||||
permissions?: string[] | '' | '*' | 'admin' | 'user';
|
permissions?: string[] | '' | '*' | 'admin' | 'user'|'auditor';
|
||||||
|
authorities?: string[]
|
||||||
}
|
}
|
||||||
|
@ -51,21 +51,100 @@
|
|||||||
>
|
>
|
||||||
{{ $t('login.form.rememberPassword') }}
|
{{ $t('login.form.rememberPassword') }}
|
||||||
</a-checkbox>
|
</a-checkbox>
|
||||||
<a-link>{{ $t('login.form.forgetPassword') }}</a-link>
|
<!-- <a-link>{{ $t('login.form.forgetPassword') }}</a-link> -->
|
||||||
</div>
|
</div>
|
||||||
<a-button type="primary" html-type="submit" long :loading="loading">
|
<a-button type="primary" html-type="submit" long :loading="loading">
|
||||||
{{ $t('login.form.login') }}
|
{{ $t('login.form.login') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
|
|
||||||
<a-button type="text" long class="login-form-register-btn">
|
<a-button
|
||||||
|
type="text"
|
||||||
|
long
|
||||||
|
class="login-form-register-btn"
|
||||||
|
@click="handleClick"
|
||||||
|
>
|
||||||
{{ $t('login.form.register') }}
|
{{ $t('login.form.register') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-form>
|
</a-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<a-modal
|
||||||
|
width="600px"
|
||||||
|
:visible="visible"
|
||||||
|
@ok="handleOk"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
>
|
||||||
|
<template #title>{{ modalTitle }}</template>
|
||||||
|
<a-form ref="userCreateRef" :model="formData" :style="{ width: '500px' }">
|
||||||
|
<a-form-item
|
||||||
|
field="username"
|
||||||
|
label="用户名"
|
||||||
|
:validate-trigger="['change', 'input']"
|
||||||
|
:rules="[{ required: true, message: '用户名不能为空' }]"
|
||||||
|
>
|
||||||
|
<a-input v-model="formData.username" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
field="password"
|
||||||
|
label="密码"
|
||||||
|
:validate-trigger="['change', 'input']"
|
||||||
|
:rules="[{ required: true, message: '密码不能为空' }]"
|
||||||
|
>
|
||||||
|
<a-input v-model="formData.password" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item field="nickName" label="昵称">
|
||||||
|
<a-input v-model="formData.nickName" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
field="phone"
|
||||||
|
label="电话"
|
||||||
|
:rules="[
|
||||||
|
{ required: true, message: '电话不能为空' },
|
||||||
|
{ match: /^1[3-9]\d{9}$/, message: '请输入正确格式的电话号码' },
|
||||||
|
]"
|
||||||
|
:validate-trigger="['change', 'input']"
|
||||||
|
>
|
||||||
|
<a-input v-model="formData.phone" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
field="email"
|
||||||
|
label="邮箱"
|
||||||
|
:rules="[
|
||||||
|
{ required: true, type: 'email', message: '请输入正确格式的邮箱' },
|
||||||
|
]"
|
||||||
|
:validate-trigger="['change', 'input']"
|
||||||
|
>
|
||||||
|
<a-input v-model="formData.email" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item field="address" label="地址">
|
||||||
|
<a-input v-model="formData.address" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
field="deptId"
|
||||||
|
label="部门"
|
||||||
|
:rules="[{ required: true, message: '请选择部门' }]"
|
||||||
|
:validate-trigger="['change']"
|
||||||
|
>
|
||||||
|
<a-tree-select
|
||||||
|
v-model="formData.deptId"
|
||||||
|
:field-names="{
|
||||||
|
key: 'id',
|
||||||
|
title: 'name',
|
||||||
|
children: 'children',
|
||||||
|
}"
|
||||||
|
:data="deptOptions"
|
||||||
|
allow-clear
|
||||||
|
placeholder="请选择父部门 ..."
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</a-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import useVisible from '@/hooks/visible';
|
||||||
|
import { FormInstance } from '@arco-design/web-vue/es/form';
|
||||||
import { ref, reactive } from 'vue';
|
import { ref, reactive } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
@ -74,14 +153,35 @@ import { useI18n } from 'vue-i18n';
|
|||||||
import { useStorage } from '@vueuse/core';
|
import { useStorage } from '@vueuse/core';
|
||||||
import { useUserStore } from '@/store';
|
import { useUserStore } from '@/store';
|
||||||
import useLoading from '@/hooks/loading';
|
import useLoading from '@/hooks/loading';
|
||||||
import { LoginData } from '@/api/user';
|
import { LoginData, CreateRecord } from '@/api/user';
|
||||||
|
import { deptList } from '@/api/dept';
|
||||||
|
import { computedAsync } from '@vueuse/core';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const errorMessage = ref('');
|
const errorMessage = ref('');
|
||||||
const { loading, setLoading } = useLoading();
|
const { loading, setLoading } = useLoading();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
const { visible, setVisible } = useVisible(false);
|
||||||
|
const userCreateRef = ref<FormInstance>();
|
||||||
|
const modalTitle = '注册用户信息';
|
||||||
|
const formData = ref<CreateRecord>({
|
||||||
|
username: '',
|
||||||
|
nickName: '',
|
||||||
|
password: '',
|
||||||
|
phone: '',
|
||||||
|
email: '',
|
||||||
|
enabled: 'true',
|
||||||
|
address: '',
|
||||||
|
deptId: undefined,
|
||||||
|
roleId: undefined,
|
||||||
|
permissionIds: [],
|
||||||
|
authorities: [],
|
||||||
|
});
|
||||||
|
const deptOptions = computedAsync(async () => {
|
||||||
|
const { data } = await deptList();
|
||||||
|
return data;
|
||||||
|
});
|
||||||
const loginConfig = useStorage('login-config', {
|
const loginConfig = useStorage('login-config', {
|
||||||
// 使用 useStorage 创建一个响应式变量,存储登录相关配置
|
// 使用 useStorage 创建一个响应式变量,存储登录相关配置
|
||||||
rememberPassword: true,
|
rememberPassword: true,
|
||||||
@ -114,7 +214,7 @@ const handleSubmit = async ({
|
|||||||
const res = await userStore.me();
|
const res = await userStore.me();
|
||||||
await userStore.login(values as LoginData, res.data.csrf.token);
|
await userStore.login(values as LoginData, res.data.csrf.token);
|
||||||
const csrf = await userStore.me();
|
const csrf = await userStore.me();
|
||||||
|
await userStore.info();
|
||||||
// 获取路由信息,处理重定向
|
// 获取路由信息,处理重定向
|
||||||
const { redirect, ...othersQuery } = router.currentRoute.value.query;
|
const { redirect, ...othersQuery } = router.currentRoute.value.query;
|
||||||
router.push({
|
router.push({
|
||||||
@ -144,6 +244,30 @@ const handleSubmit = async ({
|
|||||||
const setRememberPassword = (value: boolean) => {
|
const setRememberPassword = (value: boolean) => {
|
||||||
loginConfig.value.rememberPassword = value;
|
loginConfig.value.rememberPassword = value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleClick = () => {
|
||||||
|
setVisible(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = async () => {
|
||||||
|
userCreateRef.value?.resetFields();
|
||||||
|
setVisible(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOk = async () => {
|
||||||
|
const valid = await userCreateRef.value?.validate();
|
||||||
|
if (!valid) {
|
||||||
|
const res = await userStore.createUser(formData.value);
|
||||||
|
if (res.status === 200) {
|
||||||
|
Message.success({
|
||||||
|
content: `${modalTitle}成功`,
|
||||||
|
duration: 5 * 1000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
userCreateRef.value?.resetFields();
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@ -132,7 +132,7 @@
|
|||||||
:model-value="record.enabled"
|
:model-value="record.enabled"
|
||||||
:checked-value="true"
|
:checked-value="true"
|
||||||
:unchecked-value="false"
|
:unchecked-value="false"
|
||||||
@change="enabledStatus(record.id)"
|
@change="enabledStatus(record)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #operations="{ record }">
|
<template #operations="{ record }">
|
||||||
@ -254,8 +254,9 @@ const reset = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 是否启用
|
// 是否启用
|
||||||
const enabledStatus = async (id: string) => {
|
const enabledStatus = async (record: string) => {
|
||||||
const res = await deptStore.enabledDept(id);
|
record.enabled = !record.enabled;
|
||||||
|
const res = await deptStore.enabledDept(record.id);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
Message.success({
|
Message.success({
|
||||||
content: t('modify.status.sucess'),
|
content: t('modify.status.sucess'),
|
||||||
@ -267,7 +268,7 @@ const enabledStatus = async (id: string) => {
|
|||||||
duration: 3 * 1000,
|
duration: 3 * 1000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
search();
|
// search();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDelete = async (record) => {
|
const handleDelete = async (record) => {
|
||||||
|
@ -193,6 +193,7 @@ fetchData();
|
|||||||
|
|
||||||
// 是否启用
|
// 是否启用
|
||||||
const enabledStatus = async (record: string) => {
|
const enabledStatus = async (record: string) => {
|
||||||
|
record.enabled = !record.enabled;
|
||||||
const res = await roleStore.enabledRole(record.id);
|
const res = await roleStore.enabledRole(record.id);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
Message.success({
|
Message.success({
|
||||||
@ -205,7 +206,7 @@ const enabledStatus = async (record: string) => {
|
|||||||
duration: 3 * 1000,
|
duration: 3 * 1000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
fetchData();
|
// fetchData();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDelete = async (record: RoleRecord) => {
|
const handleDelete = async (record: RoleRecord) => {
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
@cancel="handleCancel"
|
@cancel="handleCancel"
|
||||||
>
|
>
|
||||||
<template #title>{{ modalTitle }}</template>
|
<template #title>{{ modalTitle }}</template>
|
||||||
<a-form ref="userCreateRef" :model="formData" :style="{ width: '500px' }">
|
<a-form ref="CreateRef" :model="formData" :style="{ width: '500px' }">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
field="username"
|
field="username"
|
||||||
label="用户名"
|
label="用户名"
|
||||||
@ -140,6 +140,7 @@ const formData = ref<CreateRecord>({
|
|||||||
deptId: undefined,
|
deptId: undefined,
|
||||||
roleId: undefined,
|
roleId: undefined,
|
||||||
permissionIds: [],
|
permissionIds: [],
|
||||||
|
authorities: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
let formDifer = {};
|
let formDifer = {};
|
||||||
@ -197,7 +198,6 @@ const handleSubmit = async () => {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
formDifer.id = formData.value.id;
|
formDifer.id = formData.value.id;
|
||||||
console.log('2', formDifer);
|
|
||||||
const res = await userStore.updateUser(formDifer);
|
const res = await userStore.updateUser(formDifer);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
Message.success({
|
Message.success({
|
||||||
@ -207,14 +207,15 @@ const handleSubmit = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emit('refresh');
|
// emit('refresh');
|
||||||
checkKeys.value = [];
|
checkKeys.value = [];
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCancel = async () => {
|
const handleCancel = async () => {
|
||||||
userCreateRef.value?.resetFields();
|
/// emit('refresh');
|
||||||
|
// userCreateRef.value?.resetFields();
|
||||||
checkKeys.value = [];
|
checkKeys.value = [];
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
};
|
};
|
||||||
|
@ -47,11 +47,11 @@
|
|||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="9">
|
<a-col :span="9">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
field="enabled"
|
field="enable"
|
||||||
:label="$t('searchTable.form.status')"
|
:label="$t('searchTable.form.status')"
|
||||||
>
|
>
|
||||||
<a-select
|
<a-select
|
||||||
v-model="formModel.enabled"
|
v-model="formModel.enable"
|
||||||
:options="statusOptions"
|
:options="statusOptions"
|
||||||
:placeholder="$t('searchTable.form.status.placeholder')"
|
:placeholder="$t('searchTable.form.status.placeholder')"
|
||||||
/>
|
/>
|
||||||
@ -223,7 +223,7 @@ const generateFormModel = () => {
|
|||||||
phone: '',
|
phone: '',
|
||||||
email: '',
|
email: '',
|
||||||
createdTime: [],
|
createdTime: [],
|
||||||
enabled: '',
|
enable: '',
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -302,14 +302,15 @@ const statusOptions = computed<SelectOptionData[]>(() => [
|
|||||||
value: 'false',
|
value: 'false',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
const fetchData = async (params: UserParams = { page: 1, size: 10 }) => {
|
const fetchData = async (
|
||||||
|
params: UserParams = { page: 1, size: 10, current: 1 }
|
||||||
|
) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const res = await userStore.getUserList(params);
|
const res = await userStore.getUserList(params);
|
||||||
const { data } = res;
|
renderData.value = res.data.records;
|
||||||
renderData.value = data.list;
|
pagination.current = res.data.current;
|
||||||
pagination.current = params.page;
|
pagination.total = res.data.total;
|
||||||
pagination.total = data.total;
|
|
||||||
// pagination.size = data.size;
|
// pagination.size = data.size;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// you can report use errorHandler or other
|
// you can report use errorHandler or other
|
||||||
@ -327,7 +328,7 @@ const search = () => {
|
|||||||
|
|
||||||
const onPageChange = (current: number) => {
|
const onPageChange = (current: number) => {
|
||||||
const page = current;
|
const page = current;
|
||||||
fetchData({ ...basePagination, page });
|
fetchData({ ...basePagination, current });
|
||||||
};
|
};
|
||||||
|
|
||||||
fetchData();
|
fetchData();
|
||||||
@ -337,6 +338,7 @@ const reset = () => {
|
|||||||
|
|
||||||
// 是否启用
|
// 是否启用
|
||||||
const enabledStatus = async (record: string) => {
|
const enabledStatus = async (record: string) => {
|
||||||
|
record.enabled = !record.enabled;
|
||||||
const res = await userStore.enabledUser(record.id);
|
const res = await userStore.enabledUser(record.id);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
Message.success({
|
Message.success({
|
||||||
@ -349,7 +351,6 @@ const enabledStatus = async (record: string) => {
|
|||||||
duration: 3 * 1000,
|
duration: 3 * 1000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
search();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDelete = async (record: UserRecord) => {
|
const handleDelete = async (record: UserRecord) => {
|
||||||
|
@ -1,6 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<a-space width="450px" v-if="!props.isCreate">
|
<a-space width="450px">
|
||||||
<a-form ref="createEditRef" :model="formData" :style="{ width: '450px' }">
|
|
||||||
|
<a-form
|
||||||
|
v-if="visible"
|
||||||
|
ref="createEditRef"
|
||||||
|
:model="formData"
|
||||||
|
:style="{ width: '450px' }"
|
||||||
|
>
|
||||||
|
<a-form style="text-align: center" v-model="formTitle">
|
||||||
|
<h2>{{ formTitle }}</h2>
|
||||||
|
</a-form>
|
||||||
<a-form-item
|
<a-form-item
|
||||||
field="companyName"
|
field="companyName"
|
||||||
label="公司"
|
label="公司"
|
||||||
@ -37,10 +46,6 @@
|
|||||||
<a-input v-model="formData.money" />
|
<a-input v-model="formData.money" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item field="createTime" label="创建时间">
|
|
||||||
<a-input v-model="formData.createTime" />
|
|
||||||
</a-form-item>
|
|
||||||
|
|
||||||
<a-form-item
|
<a-form-item
|
||||||
field="contactEmail"
|
field="contactEmail"
|
||||||
label="联系邮箱"
|
label="联系邮箱"
|
||||||
@ -56,41 +61,73 @@
|
|||||||
:validate-trigger="['change', 'input']"
|
:validate-trigger="['change', 'input']"
|
||||||
:rules="[{ required: true, message: '票据类型不能为空' }]"
|
:rules="[{ required: true, message: '票据类型不能为空' }]"
|
||||||
>
|
>
|
||||||
<a-input v-model="formData.type" />
|
<a-select
|
||||||
|
v-model="formData.type"
|
||||||
|
:options="typesOptions"
|
||||||
|
:placeholder="$t('searchTable.form.type.placeholder')"
|
||||||
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item field="status" label="审核状态" v-if="props.isDetail">
|
<a-form-item field="attachment" label="附件">
|
||||||
<div>
|
<a-upload
|
||||||
{{ formData.status }}
|
:file-list="fileList"
|
||||||
</div>
|
:custom-request="Onchange"
|
||||||
</a-form-item>
|
:limit="1"
|
||||||
<a-form-item
|
:on-before-remove="removeAttact"
|
||||||
v-else
|
v-model="formData.attachId"
|
||||||
field="status"
|
|
||||||
label="审核状态"
|
|
||||||
:disabled="props.isDetail"
|
|
||||||
:validate-trigger="['change', 'input']"
|
|
||||||
:rules="[{ required: true, message: '审核状态不能为空' }]"
|
|
||||||
>
|
|
||||||
<a-select
|
|
||||||
v-model="formData.status"
|
|
||||||
:options="statusOptions"
|
|
||||||
:placeholder="$t('searchTable.form.status.placeholder')"
|
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item
|
||||||
|
field="deptId"
|
||||||
|
label="部门"
|
||||||
|
:rules="[{ required: true, message: '请选择部门' }]"
|
||||||
|
:validate-trigger="['change']"
|
||||||
|
>
|
||||||
|
<a-tree-select
|
||||||
|
v-model="formData.deptId"
|
||||||
|
:field-names="{
|
||||||
|
key: 'id',
|
||||||
|
title: 'name',
|
||||||
|
children: 'children',
|
||||||
|
}"
|
||||||
|
:data="deptOptions"
|
||||||
|
allow-clear
|
||||||
|
placeholder="请选择部门 ..."
|
||||||
|
@change="optionDept()"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item field="auditorId" label="审核员">
|
||||||
|
<a-select v-model="formData.auditorId" placeholder="请选择审核员">
|
||||||
|
<div v-for="(item, id) in auditorOptions" :key="id">
|
||||||
|
<a-option :value="item.id">{{ item.username }} </a-option>
|
||||||
|
</div>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item>
|
||||||
|
<a-button type="outline" @click="handleStorage">暂存</a-button>
|
||||||
|
<a-button type="primary" style="margin-left: 15px" @click="handleOk"
|
||||||
|
>提交</a-button
|
||||||
|
>
|
||||||
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
import useVisible from '@/hooks/visible';
|
import useVisible from '@/hooks/visible';
|
||||||
import { computed, PropType, ref, watch } from 'vue';
|
import { computed, PropType, ref, watch } from 'vue';
|
||||||
import { FormInstance } from '@arco-design/web-vue/es/form';
|
import { FormInstance } from '@arco-design/web-vue/es/form';
|
||||||
|
import { computedAsync } from '@vueuse/core';
|
||||||
import { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
|
import { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
import useTableOption from '@/hooks/table-option';
|
import useTableOption from '@/hooks/table-option';
|
||||||
import { useTicketStore } from '@/store';
|
import { useTicketStore, useUserStore } from '@/store';
|
||||||
import { TicketRecord } from '@/api/ticket';
|
import { TicketRecord } from '@/api/ticket';
|
||||||
|
import { deptList } from '@/api/dept';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
prem: {
|
prem: {
|
||||||
@ -100,27 +137,47 @@ const props = defineProps({
|
|||||||
isVisible: Boolean,
|
isVisible: Boolean,
|
||||||
});
|
});
|
||||||
console.log('ef', props);
|
console.log('ef', props);
|
||||||
|
const { t } = useI18n();
|
||||||
const ticketStore = useTicketStore();
|
const ticketStore = useTicketStore();
|
||||||
const modalTitle = computed(() => {
|
const userStore = useUserStore();
|
||||||
return props.isCreate ? '详情' : '审核';
|
const formTitle = computed(() => {
|
||||||
|
return props.isCreate ? '添加票据' : '修改票据信息';
|
||||||
});
|
});
|
||||||
const { visible, setVisible } = useVisible(true);
|
|
||||||
const createEditRef = ref<FormInstance>();
|
const createEditRef = ref<FormInstance>();
|
||||||
|
|
||||||
const formData = ref<TicketRecord>({
|
const formData = ref<TicketRecord>({
|
||||||
id: undefined,
|
id: undefined,
|
||||||
remark: '',
|
|
||||||
createTime: '',
|
|
||||||
title: '',
|
title: '',
|
||||||
body: '',
|
body: '',
|
||||||
money: undefined,
|
money: undefined,
|
||||||
status: '',
|
|
||||||
type: '',
|
type: '',
|
||||||
contactEmail: '',
|
contactEmail: '',
|
||||||
companyName: '',
|
companyName: '',
|
||||||
|
attachId: '',
|
||||||
|
auditorId: '',
|
||||||
|
submit: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['refresh']);
|
const emit = defineEmits(['refresh']);
|
||||||
|
|
||||||
|
const deptOptions = computedAsync(async () => {
|
||||||
|
const { data } = await deptList();
|
||||||
|
return data;
|
||||||
|
});
|
||||||
|
const typesOptions = computed<SelectOptionData[]>(() => [
|
||||||
|
{
|
||||||
|
label: '银行支票',
|
||||||
|
value: 'BANK',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '税务支票',
|
||||||
|
value: 'TAX',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '其他支票',
|
||||||
|
value: 'OTHER',
|
||||||
|
},
|
||||||
|
]);
|
||||||
const statusOptions = computed<SelectOptionData[]>(() => [
|
const statusOptions = computed<SelectOptionData[]>(() => [
|
||||||
{
|
{
|
||||||
label: '待审核',
|
label: '待审核',
|
||||||
@ -135,43 +192,97 @@ const statusOptions = computed<SelectOptionData[]>(() => [
|
|||||||
value: 'FAILED',
|
value: 'FAILED',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
const auditorOptions = ref([]);
|
||||||
const handleClick = () => {
|
const optionDept = async () => {
|
||||||
|
auditorOptions.value = [];
|
||||||
|
const res = await userStore.getUserList({
|
||||||
const ticketId = props.prem?.id;
|
page: 1,
|
||||||
ticketStore
|
size: 100,
|
||||||
.getDetail(ticketId)
|
roleId: '54',
|
||||||
.then((res) => {
|
deptId: formData.value.deptId,
|
||||||
formData.value = res.data.bill;
|
});
|
||||||
})
|
auditorOptions.value = res.data.list;
|
||||||
.then(() => {
|
|
||||||
setVisible(true);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const fileList = ref([]);
|
||||||
|
|
||||||
|
const Onchange = async (option: any) => {
|
||||||
|
// 发送请求给后端
|
||||||
|
const FormDatas = new FormData();
|
||||||
|
FormDatas.append('file', option.fileItem.file);
|
||||||
|
const res = await ticketStore.uploadFileTicket(FormDatas);
|
||||||
|
console.log('res', res);
|
||||||
|
if (res.status === 200) {
|
||||||
|
Message.success({
|
||||||
|
content: t('上传成功'),
|
||||||
|
duration: 3 * 1000,
|
||||||
|
});
|
||||||
|
res.data.name = res.data.fileName;
|
||||||
|
fileList.value.push(res.data);
|
||||||
|
formData.value.attachId = res.data.id;
|
||||||
|
} else {
|
||||||
|
Message.error({
|
||||||
|
content: t('上传失败'),
|
||||||
|
duration: 3 * 1000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeAttact = () => {
|
||||||
|
fileList.value.pop();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleStorage = async () => {
|
||||||
const valid = await createEditRef.value?.validate();
|
const valid = await createEditRef.value?.validate();
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
|
formData.value.submit = false;
|
||||||
if (props.isCreate) {
|
if (props.isCreate) {
|
||||||
createEditRef.value?.resetFields();
|
const res = await ticketStore.createTicket(formData.value);
|
||||||
|
if (res.status === 200) {
|
||||||
|
Message.success({
|
||||||
|
content: '暂存成功',
|
||||||
|
duration: 5 * 1000,
|
||||||
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const res = await ticketStore.updateTicket(formData.value);
|
const res = await ticketStore.updateTicket(formData.value);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
Message.success({
|
Message.success({
|
||||||
content: `${modalTitle.value}成功`,
|
content: '暂存成功',
|
||||||
duration: 5 * 1000,
|
duration: 5 * 1000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emit('refresh');
|
createEditRef.value?.resetFields();
|
||||||
setVisible(false);
|
removeAttact();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCancel = async () => {
|
const handleOk = async () => {
|
||||||
createEditRef.value?.resetFields();
|
const valid = await createEditRef.value?.validate();
|
||||||
setVisible(false);
|
if (!valid) {
|
||||||
|
formData.value.submit = true;
|
||||||
|
if (props.isCreate) {
|
||||||
|
const res = await ticketStore.createTicket(formData.value);
|
||||||
|
if (res.status === 200) {
|
||||||
|
Message.success({
|
||||||
|
content: `提交成功`,
|
||||||
|
duration: 5 * 1000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const res = await ticketStore.updateTicket(formData.value);
|
||||||
|
if (res.status === 200) {
|
||||||
|
Message.success({
|
||||||
|
content: `提交成功`,
|
||||||
|
duration: 5 * 1000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createEditRef.value?.resetFields();
|
||||||
|
removeAttact();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -16,15 +16,17 @@
|
|||||||
type="outline"
|
type="outline"
|
||||||
size="small"
|
size="small"
|
||||||
@click="handleCreate"
|
@click="handleCreate"
|
||||||
style="margin-left: 70px"
|
style="margin-left: 120px"
|
||||||
>新建</a-button
|
>新建</a-button
|
||||||
>
|
>
|
||||||
<a-list
|
<a-list
|
||||||
:style="{ width: `300px` }"
|
:style="{ width: `350px` }"
|
||||||
:virtualListProps="{
|
:virtualListProps="{
|
||||||
height: 550,
|
height: 550,
|
||||||
}"
|
}"
|
||||||
:data="uncommitData"
|
:data="uncommitData"
|
||||||
|
:pagination-props="paginationProps"
|
||||||
|
@page-change="onPageChange"
|
||||||
>
|
>
|
||||||
<template #item="{ item, id }">
|
<template #item="{ item, id }">
|
||||||
<a-list-item :key="id">
|
<a-list-item :key="id">
|
||||||
@ -39,89 +41,12 @@
|
|||||||
</a-col>
|
</a-col>
|
||||||
<a-divider style="height: 600px" direction="vertical" />
|
<a-divider style="height: 600px" direction="vertical" />
|
||||||
<a-col :flex="3">
|
<a-col :flex="3">
|
||||||
<!-- <TicketForm
|
<TicketForm
|
||||||
ref="createEditRef"
|
ref="createEditRef"
|
||||||
:prem="ticketItem"
|
:prem="ticketItem"
|
||||||
:is-create="false"
|
:is-create="true"
|
||||||
:is-visible="true"
|
:is-visible="visible"
|
||||||
/> -->
|
/>
|
||||||
<a-form
|
|
||||||
v-if="visible"
|
|
||||||
ref="createEditRef"
|
|
||||||
:model="formData"
|
|
||||||
:style="{ width: '450px' }"
|
|
||||||
>
|
|
||||||
<a-form style="text-align: center" v-model="formTitle">
|
|
||||||
<h2>{{ formTitle }}</h2>
|
|
||||||
</a-form>
|
|
||||||
<a-form-item
|
|
||||||
field="companyName"
|
|
||||||
label="公司"
|
|
||||||
:validate-trigger="['change', 'input']"
|
|
||||||
:rules="[{ required: true, message: '公司不能为空' }]"
|
|
||||||
>
|
|
||||||
<a-input v-model="formData.companyName" />
|
|
||||||
</a-form-item>
|
|
||||||
|
|
||||||
<a-form-item
|
|
||||||
field="title"
|
|
||||||
label="标题"
|
|
||||||
:validate-trigger="['change', 'input']"
|
|
||||||
:rules="[{ required: true, message: '标题不能为空' }]"
|
|
||||||
>
|
|
||||||
<a-input v-model="formData.title" />
|
|
||||||
</a-form-item>
|
|
||||||
|
|
||||||
<a-form-item
|
|
||||||
field="body"
|
|
||||||
label="内容"
|
|
||||||
:validate-trigger="['change', 'input']"
|
|
||||||
:rules="[{ required: true, message: '内容不能为空' }]"
|
|
||||||
>
|
|
||||||
<a-textarea v-model="formData.body" />
|
|
||||||
</a-form-item>
|
|
||||||
|
|
||||||
<a-form-item
|
|
||||||
field="money"
|
|
||||||
label="金额"
|
|
||||||
:validate-trigger="['change', 'input']"
|
|
||||||
:rules="[{ required: true, message: '金额不能为空' }]"
|
|
||||||
>
|
|
||||||
<a-input v-model="formData.money" />
|
|
||||||
</a-form-item>
|
|
||||||
|
|
||||||
<a-form-item
|
|
||||||
field="contactEmail"
|
|
||||||
label="联系邮箱"
|
|
||||||
:validate-trigger="['change', 'input']"
|
|
||||||
:rules="[{ required: true, message: '联系邮箱不能为空' }]"
|
|
||||||
>
|
|
||||||
<a-input v-model="formData.contactEmail" />
|
|
||||||
</a-form-item>
|
|
||||||
|
|
||||||
<a-form-item
|
|
||||||
field="type"
|
|
||||||
label="票据类型"
|
|
||||||
:validate-trigger="['change', 'input']"
|
|
||||||
:rules="[{ required: true, message: '票据类型不能为空' }]"
|
|
||||||
>
|
|
||||||
<a-select
|
|
||||||
v-model="formData.type"
|
|
||||||
:options="typesOptions"
|
|
||||||
:placeholder="$t('searchTable.form.type.placeholder')"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
|
|
||||||
<a-form-item>
|
|
||||||
<a-button type="outline" @click="handleStorage">暂存</a-button>
|
|
||||||
<a-button
|
|
||||||
type="primary"
|
|
||||||
style="margin-left: 15px"
|
|
||||||
@click="handleOk"
|
|
||||||
>提交</a-button
|
|
||||||
>
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-card>
|
</a-card>
|
||||||
@ -133,83 +58,67 @@ import { computed, ref, watch, reactive } from 'vue';
|
|||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import useLoading from '@/hooks/loading';
|
import useLoading from '@/hooks/loading';
|
||||||
import { Pagination } from '@/types/global';
|
import { Pagination } from '@/types/global';
|
||||||
|
import { computedAsync } from '@vueuse/core';
|
||||||
import type { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
|
import type { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
|
||||||
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
|
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
|
||||||
|
import useTableOption from '@/hooks/table-option';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { FileItem, Message } from '@arco-design/web-vue';
|
||||||
import { FormInstance } from '@arco-design/web-vue/es/form';
|
import { FormInstance } from '@arco-design/web-vue/es/form';
|
||||||
import useVisible from '@/hooks/visible';
|
import useVisible from '@/hooks/visible';
|
||||||
import { useTicketStore } from '@/store';
|
import { useTicketStore, useUserStore, useDeptStore } from '@/store';
|
||||||
import { TicketRecord } from '@/api/ticket';
|
import { TicketRecord } from '@/api/ticket';
|
||||||
// import TicketForm from './components/form-edit.vue';
|
import TicketForm from './components/form-edit.vue';
|
||||||
|
|
||||||
|
const { deepClone } = useTableOption();
|
||||||
const createEditRef = ref<FormInstance>();
|
const createEditRef = ref<FormInstance>();
|
||||||
const { loading, setLoading } = useLoading(true);
|
const { loading, setLoading } = useLoading(true);
|
||||||
const ticketStore = useTicketStore();
|
const ticketStore = useTicketStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const deptStore = useDeptStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const uncommitData = ref<TicketRecord[]>([]);
|
const uncommitData = ref<TicketRecord[]>([]);
|
||||||
const ticketStatus = ref('SUBMIT');
|
const ticketStatus = ref('SUBMIT');
|
||||||
const renderData = () => {
|
const renderData = () => {
|
||||||
return {
|
return {
|
||||||
id: undefined,
|
id: undefined,
|
||||||
remark: '',
|
|
||||||
createTime: '',
|
|
||||||
title: '',
|
title: '',
|
||||||
body: '',
|
body: '',
|
||||||
money: undefined,
|
money: undefined,
|
||||||
status: '',
|
|
||||||
type: '',
|
type: '',
|
||||||
contactEmail: '',
|
contactEmail: '',
|
||||||
companyName: '',
|
companyName: '',
|
||||||
|
attachId: '',
|
||||||
|
auditorId: '',
|
||||||
|
submit: Boolean,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const formData = ref(renderData());
|
const formData = ref(renderData());
|
||||||
const { visible, setVisible } = useVisible(false);
|
const { visible, setVisible } = useVisible(false);
|
||||||
let formTitle = '新建票据';
|
let formTitle = '新建票据';
|
||||||
const isCreate = ref('false');
|
const isCreate = ref('true');
|
||||||
const typesOptions = computed<SelectOptionData[]>(() => [
|
const paginationProps = reactive({
|
||||||
{
|
defaultPageSize: 10,
|
||||||
label: 'Bank',
|
total: 10,
|
||||||
value: 'Bank',
|
});
|
||||||
},
|
|
||||||
{
|
let ticketItem = '';
|
||||||
label: 'Tax',
|
const params = {
|
||||||
value: 'Tax',
|
page: 1,
|
||||||
},
|
current: 1,
|
||||||
{
|
size: 10,
|
||||||
label: 'Other',
|
status: ticketStatus.value,
|
||||||
value: 'Other',
|
};
|
||||||
},
|
|
||||||
]);
|
|
||||||
const statusOptions = computed<SelectOptionData[]>(() => [
|
|
||||||
{
|
|
||||||
label: '待审核',
|
|
||||||
value: 'EXAMINE',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '审核通过',
|
|
||||||
value: 'PASS',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '审核未通过',
|
|
||||||
value: 'FAILED',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 获取未提交数据
|
// 获取未提交数据
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const params = {
|
|
||||||
page: 1,
|
|
||||||
current: 1,
|
|
||||||
size: 20,
|
|
||||||
status: ticketStatus.value,
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ticketStore.getTicketList(params).then((res) => {
|
ticketStore.getTicketList(params).then((res) => {
|
||||||
uncommitData.value = res.data.records;
|
uncommitData.value = res.data.records;
|
||||||
|
paginationProps.defaultPageSize = params.size;
|
||||||
|
paginationProps.total = res.data.total;
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// you can report use errorHandler or other
|
// you can report use errorHandler or other
|
||||||
@ -218,6 +127,12 @@ const fetchData = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 分页发生改变
|
||||||
|
const onPageChange = (current: number) => {
|
||||||
|
params.current = current;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
const changeStatus = () => {
|
const changeStatus = () => {
|
||||||
fetchData();
|
fetchData();
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
@ -235,10 +150,11 @@ const handleCreate = () => {
|
|||||||
const handleEdit = (item: any) => {
|
const handleEdit = (item: any) => {
|
||||||
isCreate.value = 'false';
|
isCreate.value = 'false';
|
||||||
formTitle = '修改票据信息';
|
formTitle = '修改票据信息';
|
||||||
ticketStore.getDetail(item.id).then((res) => {
|
ticketItem = item.id;
|
||||||
console.log('qwe', res);
|
// ticketStore.getDetail(item.id).then((res) => {
|
||||||
});
|
// console.log('qwe', res);
|
||||||
formData.value = item;
|
// });
|
||||||
|
// formData.value = item;
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -252,56 +168,6 @@ const handleDelete = async (item: any) => {
|
|||||||
changeStatus();
|
changeStatus();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleStorage = async () => {
|
|
||||||
const valid = await createEditRef.value?.validate();
|
|
||||||
if (!valid) {
|
|
||||||
formData.value.status = 'SUBMIT';
|
|
||||||
if (isCreate.value) {
|
|
||||||
const res = await ticketStore.createTicket(formData.value);
|
|
||||||
if (res.status === 200) {
|
|
||||||
Message.success({
|
|
||||||
content: '暂存成功',
|
|
||||||
duration: 5 * 1000,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const res = await ticketStore.updateTicket(formData.value);
|
|
||||||
if (res.status === 200) {
|
|
||||||
Message.success({
|
|
||||||
content: '暂存成功',
|
|
||||||
duration: 5 * 1000,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleOk = async () => {
|
|
||||||
const valid = await createEditRef.value?.validate();
|
|
||||||
if (!valid) {
|
|
||||||
formData.value.status = 'EXAMINE';
|
|
||||||
if (isCreate.value) {
|
|
||||||
const res = await ticketStore.createTicket(formData.value);
|
|
||||||
if (res.status === 200) {
|
|
||||||
Message.success({
|
|
||||||
content: `提交成功`,
|
|
||||||
duration: 5 * 1000,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const res = await ticketStore.updateTicket(formData.value);
|
|
||||||
if (res.status === 200) {
|
|
||||||
Message.success({
|
|
||||||
content: `提交成功`,
|
|
||||||
duration: 5 * 1000,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
createEditRef.value?.resetFields();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
413
src/views/ticket/manage/components/form-edit.vue
Normal file
413
src/views/ticket/manage/components/form-edit.vue
Normal file
@ -0,0 +1,413 @@
|
|||||||
|
<template>
|
||||||
|
<a-button
|
||||||
|
v-if="props.isCreate"
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
:style="{ marginRight: '10px' }"
|
||||||
|
@click="handleClick"
|
||||||
|
>
|
||||||
|
{{ modalTitle }}
|
||||||
|
</a-button>
|
||||||
|
|
||||||
|
<a-button
|
||||||
|
v-if="!props.isCreate"
|
||||||
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
:style="{ marginRight: '10px' }"
|
||||||
|
@click="handleClick"
|
||||||
|
>
|
||||||
|
{{ modalTitle }}
|
||||||
|
</a-button>
|
||||||
|
<a-modal
|
||||||
|
width="600px"
|
||||||
|
:visible="visible"
|
||||||
|
:footer="false"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
>
|
||||||
|
<template #title>{{ modalTitle }}</template>
|
||||||
|
<a-form ref="createEditRef" :model="formData" :style="{ width: '500px' }">
|
||||||
|
<a-form-item
|
||||||
|
field="companyName"
|
||||||
|
label="公司"
|
||||||
|
:validate-trigger="['change', 'input']"
|
||||||
|
:rules="[{ required: true, message: '公司不能为空' }]"
|
||||||
|
>
|
||||||
|
<a-input v-model="formData.companyName" />
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item
|
||||||
|
field="title"
|
||||||
|
label="标题"
|
||||||
|
:validate-trigger="['change', 'input']"
|
||||||
|
:rules="[{ required: true, message: '标题不能为空' }]"
|
||||||
|
>
|
||||||
|
<a-input v-model="formData.title" />
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item
|
||||||
|
field="body"
|
||||||
|
label="内容"
|
||||||
|
:validate-trigger="['change', 'input']"
|
||||||
|
:rules="[{ required: true, message: '内容不能为空' }]"
|
||||||
|
>
|
||||||
|
<a-textarea v-model="formData.body" />
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item
|
||||||
|
field="money"
|
||||||
|
label="金额"
|
||||||
|
:validate-trigger="['change', 'input']"
|
||||||
|
:rules="[{ required: true, message: '金额不能为空' }]"
|
||||||
|
>
|
||||||
|
<a-input v-model="formData.money" />
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item
|
||||||
|
field="contactEmail"
|
||||||
|
label="联系邮箱"
|
||||||
|
:validate-trigger="['change', 'input']"
|
||||||
|
:rules="[{ required: true, message: '联系邮箱不能为空' }]"
|
||||||
|
>
|
||||||
|
<a-input v-model="formData.contactEmail" />
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item
|
||||||
|
field="type"
|
||||||
|
label="票据类型"
|
||||||
|
:validate-trigger="['change', 'input']"
|
||||||
|
:rules="[{ required: true, message: '票据类型不能为空' }]"
|
||||||
|
>
|
||||||
|
<a-select
|
||||||
|
v-model="formData.type"
|
||||||
|
:options="typesOptions"
|
||||||
|
:placeholder="$t('searchTable.form.type.placeholder')"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item field="attachment" label="附件">
|
||||||
|
<a-upload
|
||||||
|
:file-list="fileList"
|
||||||
|
:custom-request="Onchange"
|
||||||
|
:limit="1"
|
||||||
|
:on-before-remove="removeAttact"
|
||||||
|
v-model="formData.attachId"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item
|
||||||
|
field="deptId"
|
||||||
|
label="部门"
|
||||||
|
:rules="[{ required: true, message: '请选择部门' }]"
|
||||||
|
:validate-trigger="['change']"
|
||||||
|
>
|
||||||
|
<a-tree-select
|
||||||
|
v-model="formData.deptId"
|
||||||
|
:field-names="{
|
||||||
|
key: 'id',
|
||||||
|
title: 'name',
|
||||||
|
children: 'children',
|
||||||
|
}"
|
||||||
|
:data="deptOptions"
|
||||||
|
placeholder="请选择部门 ..."
|
||||||
|
@change="optionDept(true)"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item field="auditorId" label="审核员">
|
||||||
|
<a-select v-model="formData.auditorId" placeholder="请选择审核员">
|
||||||
|
<div v-for="(item, id) in auditorOptions" :key="id">
|
||||||
|
<a-option :value="item.id">{{ item.username }} </a-option>
|
||||||
|
</div>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item field="status" label="审核状态" v-if="!props.isCreate">
|
||||||
|
{{ formData.status }}
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item field="comment" label="审核意见" v-if="auditData.comment">
|
||||||
|
{{ auditData.comment }}
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<a-button type="dashed" @click="handleCancel">取消</a-button>
|
||||||
|
<a-button
|
||||||
|
type="outline"
|
||||||
|
style="margin-left: 15px"
|
||||||
|
@click="handleStorage"
|
||||||
|
>暂存</a-button
|
||||||
|
>
|
||||||
|
<a-button type="primary" style="margin-left: 15px" @click="handleOk"
|
||||||
|
>提交</a-button
|
||||||
|
>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import useVisible from '@/hooks/visible';
|
||||||
|
import { computed, PropType, ref } from 'vue';
|
||||||
|
import { computedAsync } from '@vueuse/core';
|
||||||
|
import { FormInstance } from '@arco-design/web-vue/es/form';
|
||||||
|
import { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
|
||||||
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
import { useTicketStore, useUserStore, useRoleStore } from '@/store';
|
||||||
|
import { TicketRecord, auditRecord } from '@/api/ticket';
|
||||||
|
import { deptList } from '@/api/dept';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
prem: {
|
||||||
|
type: Object as PropType<TicketRecord>,
|
||||||
|
},
|
||||||
|
isCreate: Boolean,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const ticketStore = useTicketStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const roleStore = useRoleStore();
|
||||||
|
const modalTitle = computed(() => {
|
||||||
|
return props.isCreate ? '新增' : '修改';
|
||||||
|
});
|
||||||
|
const { visible, setVisible } = useVisible(false);
|
||||||
|
const createEditRef = ref<FormInstance>();
|
||||||
|
|
||||||
|
const formData = ref<TicketRecord>({
|
||||||
|
id: undefined,
|
||||||
|
title: '',
|
||||||
|
body: '',
|
||||||
|
money: undefined,
|
||||||
|
status: '',
|
||||||
|
type: '',
|
||||||
|
contactEmail: '',
|
||||||
|
companyName: '',
|
||||||
|
attachId: '',
|
||||||
|
auditorId: '',
|
||||||
|
userId: undefined,
|
||||||
|
submit: '',
|
||||||
|
comment: '',
|
||||||
|
});
|
||||||
|
const auditData = ref<auditRecord>({
|
||||||
|
auditorId: '',
|
||||||
|
comment: '',
|
||||||
|
result: '',
|
||||||
|
ticketId: '',
|
||||||
|
});
|
||||||
|
const emit = defineEmits(['refresh']);
|
||||||
|
|
||||||
|
const deptOptions = computedAsync(async () => {
|
||||||
|
const { data } = await deptList();
|
||||||
|
return data;
|
||||||
|
});
|
||||||
|
const typesOptions = computed<SelectOptionData[]>(() => [
|
||||||
|
{
|
||||||
|
label: '银行支票',
|
||||||
|
value: 'BANK',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '税务支票',
|
||||||
|
value: 'TAX',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '其他支票',
|
||||||
|
value: 'OTHER',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const statusOptions = computed<SelectOptionData[]>(() => [
|
||||||
|
{
|
||||||
|
label: '待审核',
|
||||||
|
value: 'EXAMINE',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '审核通过',
|
||||||
|
value: 'PASS',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '审核未通过',
|
||||||
|
value: 'FAILED',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
let auiditRoleId = '';
|
||||||
|
const getRoleId = async () => {
|
||||||
|
const res = await roleStore.getRoleList();
|
||||||
|
res.data.forEach((item: any) => {
|
||||||
|
if (item.name === 'auditor') {
|
||||||
|
auiditRoleId = item.id;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
getRoleId();
|
||||||
|
|
||||||
|
const auditorOptions = ref([]);
|
||||||
|
const optionDept = async (flag: boolean) => {
|
||||||
|
if (flag) {
|
||||||
|
formData.value.auditorId = undefined;
|
||||||
|
}
|
||||||
|
auditorOptions.value = [];
|
||||||
|
const res = await userStore.getUserList({
|
||||||
|
page: 1,
|
||||||
|
size: 100,
|
||||||
|
roleId: auiditRoleId,
|
||||||
|
deptId: formData.value.deptId,
|
||||||
|
});
|
||||||
|
auditorOptions.value = res.data.records;
|
||||||
|
};
|
||||||
|
let formDifer = {};
|
||||||
|
const fileList = ref([]);
|
||||||
|
const Onchange = async (option: any) => {
|
||||||
|
// 发送请求给后端
|
||||||
|
const FormDatas = new FormData();
|
||||||
|
FormDatas.append('file', option.fileItem.file);
|
||||||
|
const res = await ticketStore.uploadFileTicket(FormDatas);
|
||||||
|
if (res.status === 200) {
|
||||||
|
Message.success({
|
||||||
|
content: t('上传成功'),
|
||||||
|
duration: 3 * 1000,
|
||||||
|
});
|
||||||
|
res.data.name = res.data.fileName;
|
||||||
|
fileList.value.push(res.data);
|
||||||
|
formData.value.attachId = res.data.id;
|
||||||
|
} else {
|
||||||
|
Message.error({
|
||||||
|
content: t('上传失败'),
|
||||||
|
duration: 3 * 1000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeAttact = () => {
|
||||||
|
fileList.value.pop();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClick = () => {
|
||||||
|
const ticketId = props.prem?.id;
|
||||||
|
if (ticketId) {
|
||||||
|
ticketStore
|
||||||
|
.getDetail(ticketId)
|
||||||
|
.then(async (res) => {
|
||||||
|
formData.value = res.data.bill;
|
||||||
|
auditData.value = res.data.audit;
|
||||||
|
|
||||||
|
if (formData.value.attachId) {
|
||||||
|
const data = await ticketStore.getAttachment(formData.value.attachId);
|
||||||
|
data.data.name = data.data.fileName;
|
||||||
|
fileList.value.push(data.data);
|
||||||
|
}
|
||||||
|
const auditInfo = await userStore.getUserDetail(
|
||||||
|
auditData.value.auditorId
|
||||||
|
);
|
||||||
|
formData.value.deptId = auditInfo.data.deptId;
|
||||||
|
formData.value.auditorId = auditData.value.auditorId;
|
||||||
|
formDifer = { ...res.data.bill };
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
optionDept(false).then(() => {
|
||||||
|
setVisible(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 做出只修改的部分
|
||||||
|
const diffDataForm = (newData: any, oldData: any) => {
|
||||||
|
const result = {}; // 报错修改的字段内容
|
||||||
|
Object.keys(oldData).forEach((key) => {
|
||||||
|
if (oldData[key] !== newData[key]) {
|
||||||
|
result[key] = newData[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOk = async () => {
|
||||||
|
const valid = await createEditRef.value?.validate();
|
||||||
|
if (!valid) {
|
||||||
|
formData.value.submit = true;
|
||||||
|
formData.value.status = 'EXAMINE';
|
||||||
|
if (props.isCreate) {
|
||||||
|
formData.value.userId = userStore.id;
|
||||||
|
const res = await ticketStore.createTicket(formData.value);
|
||||||
|
if (res.status === 200) {
|
||||||
|
Message.success({
|
||||||
|
content: `添加成功`,
|
||||||
|
duration: 5 * 1000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
formDifer = diffDataForm(formData.value, formDifer);
|
||||||
|
|
||||||
|
if (Object.keys(formDifer).length === 0) {
|
||||||
|
Message.success({
|
||||||
|
content: `未作任何修改`,
|
||||||
|
duration: 3 * 1000,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
formDifer.id = formData.value.id;
|
||||||
|
formDifer.submit = true;
|
||||||
|
const res = await ticketStore.updateTicket(formDifer);
|
||||||
|
if (res.status === 200) {
|
||||||
|
Message.success({
|
||||||
|
content: `提交成功`,
|
||||||
|
duration: 5 * 1000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
createEditRef.value?.resetFields();
|
||||||
|
removeAttact();
|
||||||
|
emit('refresh');
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleStorage = async () => {
|
||||||
|
const valid = await createEditRef.value?.validate();
|
||||||
|
if (!valid) {
|
||||||
|
formData.value.submit = false;
|
||||||
|
if (props.isCreate) {
|
||||||
|
const res = await ticketStore.createTicket(formData.value);
|
||||||
|
if (res.status === 200) {
|
||||||
|
Message.success({
|
||||||
|
content: '暂存成功',
|
||||||
|
duration: 5 * 1000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
formDifer = diffDataForm(formData.value, formDifer);
|
||||||
|
if (Object.keys(formDifer).length === 0) {
|
||||||
|
Message.success({
|
||||||
|
content: `未作任何修改`,
|
||||||
|
duration: 3 * 1000,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
formDifer.id = formData.value.id;
|
||||||
|
formDifer.submit = false;
|
||||||
|
const res = await ticketStore.updateTicket(formDifer);
|
||||||
|
if (res.status === 200) {
|
||||||
|
Message.success({
|
||||||
|
content: `修改成功`,
|
||||||
|
duration: 5 * 1000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
createEditRef.value?.resetFields();
|
||||||
|
removeAttact();
|
||||||
|
emit('refresh');
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = async () => {
|
||||||
|
removeAttact();
|
||||||
|
createEditRef.value?.resetFields();
|
||||||
|
setVisible(false);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|
@ -26,90 +26,87 @@
|
|||||||
>
|
>
|
||||||
<template #title>{{ modalTitle }}</template>
|
<template #title>{{ modalTitle }}</template>
|
||||||
<a-form ref="createEditRef" :model="formData" :style="{ width: '500px' }">
|
<a-form ref="createEditRef" :model="formData" :style="{ width: '500px' }">
|
||||||
<a-form-item
|
<a-form-item field="companyName" label="公司">
|
||||||
field="companyName"
|
|
||||||
label="公司"
|
|
||||||
:validate-trigger="['change', 'input']"
|
|
||||||
:rules="[{ required: true, message: '公司不能为空' }]"
|
|
||||||
>
|
|
||||||
<!-- <a-input v-model="formData.companyName" /> -->
|
|
||||||
<div>
|
<div>
|
||||||
{{ formData.companyName }}
|
{{ formData.companyName }}
|
||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item
|
<a-form-item field="title" label="标题">
|
||||||
field="title"
|
|
||||||
label="标题"
|
|
||||||
:validate-trigger="['change', 'input']"
|
|
||||||
:rules="[{ required: true, message: '标题不能为空' }]"
|
|
||||||
>
|
|
||||||
<!-- <a-input v-model="formData.title" /> -->
|
|
||||||
<div>
|
<div>
|
||||||
{{ formData.title }}
|
{{ formData.title }}
|
||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item
|
<a-form-item field="body" label="内容">
|
||||||
field="body"
|
|
||||||
label="内容"
|
|
||||||
:validate-trigger="['change', 'input']"
|
|
||||||
:rules="[{ required: true, message: '内容不能为空' }]"
|
|
||||||
>
|
|
||||||
<!-- <a-textarea v-model="formData.body" /> -->
|
|
||||||
<div>
|
<div>
|
||||||
{{ formData.body }}
|
{{ formData.body }}
|
||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item
|
<a-form-item field="money" label="金额">
|
||||||
field="money"
|
|
||||||
label="金额"
|
|
||||||
:validate-trigger="['change', 'input']"
|
|
||||||
:rules="[{ required: true, message: '金额不能为空' }]"
|
|
||||||
>
|
|
||||||
<!-- <a-input v-model="formData.money" /> -->
|
|
||||||
<div>
|
<div>
|
||||||
{{ formData.money }}
|
{{ formData.money }}
|
||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item field="createTime" label="创建时间">
|
<a-form-item field="createTime" label="创建时间">
|
||||||
<!-- <a-input v-model="formData.createTime" /> -->
|
|
||||||
<div>
|
<div>
|
||||||
{{ formData.createTime }}
|
{{ dayjs(formData.createTime).format('YYYY-MM-DD') }}
|
||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item
|
<a-form-item field="contactEmail" label="联系邮箱">
|
||||||
field="contactEmail"
|
|
||||||
label="联系邮箱"
|
|
||||||
:validate-trigger="['change', 'input']"
|
|
||||||
:rules="[{ required: true, message: '联系邮箱不能为空' }]"
|
|
||||||
>
|
|
||||||
<!-- <a-input v-model="formData.contactEmail" /> -->
|
|
||||||
<div>
|
<div>
|
||||||
{{ formData.contactEmail }}
|
{{ formData.contactEmail }}
|
||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item
|
<a-form-item field="type" label="票据类型">
|
||||||
field="type"
|
|
||||||
label="票据类型"
|
|
||||||
:validate-trigger="['change', 'input']"
|
|
||||||
:rules="[{ required: true, message: '票据类型不能为空' }]"
|
|
||||||
>
|
|
||||||
<!-- <a-input v-model="formData.type" /> -->
|
|
||||||
<div>
|
<div>
|
||||||
{{ formData.type }}
|
{{ formData.type }}
|
||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item field="attachment" label="附件">
|
||||||
|
<a-upload
|
||||||
|
:file-list="fileList"
|
||||||
|
:custom-request="Onchange"
|
||||||
|
:limit="1"
|
||||||
|
:on-before-remove="removeAttact"
|
||||||
|
:show-remove-button="false"
|
||||||
|
v-model="formData.attachId"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item field="deptId" label="部门">
|
||||||
|
<a-tree-select
|
||||||
|
v-model="formData.deptId"
|
||||||
|
:field-names="{
|
||||||
|
key: 'id',
|
||||||
|
title: 'name',
|
||||||
|
children: 'children',
|
||||||
|
}"
|
||||||
|
:data="deptOptions"
|
||||||
|
disabled
|
||||||
|
style="color: black"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item field="auditorId" label="审核员">
|
||||||
|
<a-select v-model="formData.auditorId" disabled style="color: black">
|
||||||
|
<div v-for="(item, id) in auditorOptions" :key="id">
|
||||||
|
<a-option :value="item.id">{{ item.username }} </a-option>
|
||||||
|
</div>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item field="status" label="审核状态" v-if="props.isDetail">
|
<a-form-item field="status" label="审核状态" v-if="props.isDetail">
|
||||||
<div>
|
<div>
|
||||||
{{ formData.status }}
|
{{ formData.status }}
|
||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item
|
<a-form-item
|
||||||
v-else
|
v-else
|
||||||
field="status"
|
field="status"
|
||||||
@ -124,6 +121,11 @@
|
|||||||
:placeholder="$t('searchTable.form.status.placeholder')"
|
:placeholder="$t('searchTable.form.status.placeholder')"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item field="comment" label="审核意见">
|
||||||
|
<a-textarea v-model="auditData.comment" v-if="!props.isDetail" />
|
||||||
|
<div v-else>{{ auditData.comment }} </div>
|
||||||
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</template>
|
</template>
|
||||||
@ -131,11 +133,14 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import useVisible from '@/hooks/visible';
|
import useVisible from '@/hooks/visible';
|
||||||
import { computed, PropType, ref } from 'vue';
|
import { computed, PropType, ref } from 'vue';
|
||||||
|
import { computedAsync } from '@vueuse/core';
|
||||||
import { FormInstance } from '@arco-design/web-vue/es/form';
|
import { FormInstance } from '@arco-design/web-vue/es/form';
|
||||||
import { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
|
import { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
import { useTicketStore } from '@/store';
|
import { useTicketStore, useUserStore, useRoleStore } from '@/store';
|
||||||
import { TicketRecord } from '@/api/ticket';
|
import { TicketRecord, auditRecord } from '@/api/ticket';
|
||||||
|
import { deptList } from '@/api/dept';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
prem: {
|
prem: {
|
||||||
@ -143,10 +148,9 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
isDetail: Boolean,
|
isDetail: Boolean,
|
||||||
});
|
});
|
||||||
|
const userStore = useUserStore();
|
||||||
console.log('props', props);
|
|
||||||
|
|
||||||
const ticketStore = useTicketStore();
|
const ticketStore = useTicketStore();
|
||||||
|
const roleStore = useRoleStore();
|
||||||
const modalTitle = computed(() => {
|
const modalTitle = computed(() => {
|
||||||
return props.isDetail ? '详情' : '审核';
|
return props.isDetail ? '详情' : '审核';
|
||||||
});
|
});
|
||||||
@ -155,23 +159,55 @@ const createEditRef = ref<FormInstance>();
|
|||||||
|
|
||||||
const formData = ref<TicketRecord>({
|
const formData = ref<TicketRecord>({
|
||||||
id: undefined,
|
id: undefined,
|
||||||
remark: '',
|
|
||||||
createTime: '',
|
|
||||||
title: '',
|
title: '',
|
||||||
body: '',
|
body: '',
|
||||||
money: undefined,
|
money: undefined,
|
||||||
status: '',
|
|
||||||
type: '',
|
type: '',
|
||||||
contactEmail: '',
|
contactEmail: '',
|
||||||
companyName: '',
|
companyName: '',
|
||||||
|
attachId: '',
|
||||||
|
auditorId: '',
|
||||||
|
submit: '',
|
||||||
|
});
|
||||||
|
const auditData = ref<auditRecord>({
|
||||||
|
auditorId: '',
|
||||||
|
comment: '',
|
||||||
|
result: '',
|
||||||
|
ticketId: '',
|
||||||
|
});
|
||||||
|
const emit = defineEmits(['refresh']);
|
||||||
|
const deptOptions = computedAsync(async () => {
|
||||||
|
const { data } = await deptList();
|
||||||
|
return data;
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['refresh']);
|
let auiditRoleId = '';
|
||||||
|
const getRoleId = async () => {
|
||||||
|
const res = await roleStore.getRoleList();
|
||||||
|
res.data.forEach((item: any) => {
|
||||||
|
if (item.name === 'auditor') {
|
||||||
|
auiditRoleId = item.id;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
getRoleId();
|
||||||
|
|
||||||
|
const auditorOptions = ref([]);
|
||||||
|
const optionDept = async () => {
|
||||||
|
auditorOptions.value = [];
|
||||||
|
const res = await userStore.getUserList({
|
||||||
|
page: 1,
|
||||||
|
size: auiditRoleId,
|
||||||
|
roleId: '54',
|
||||||
|
deptId: formData.value.deptId,
|
||||||
|
});
|
||||||
|
auditorOptions.value = res.data.records;
|
||||||
|
};
|
||||||
const statusOptions = computed<SelectOptionData[]>(() => [
|
const statusOptions = computed<SelectOptionData[]>(() => [
|
||||||
{
|
// {
|
||||||
label: '待审核',
|
// label: '待审核',
|
||||||
value: 'EXAMINE',
|
// value: 'EXAMINE',
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
label: '审核通过',
|
label: '审核通过',
|
||||||
value: 'PASS',
|
value: 'PASS',
|
||||||
@ -181,16 +217,36 @@ const statusOptions = computed<SelectOptionData[]>(() => [
|
|||||||
value: 'FAILED',
|
value: 'FAILED',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
const fileList = ref([]);
|
||||||
const handleClick = () => {
|
const handleClick = async () => {
|
||||||
const ticketId = props.prem?.id;
|
const ticketId = props.prem?.id;
|
||||||
ticketStore
|
ticketStore
|
||||||
.getDetail(ticketId)
|
.getDetail(ticketId)
|
||||||
.then((res) => {
|
.then(async (res) => {
|
||||||
formData.value = res.data.bill;
|
formData.value = res.data.bill;
|
||||||
|
if (!props.isDetail) {
|
||||||
|
if (formData.value.status === '审核通过') {
|
||||||
|
formData.value.status = 'PASS';
|
||||||
|
} else if (formData.value.status === '审核未通过') {
|
||||||
|
formData.value.status = 'FAILED';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auditData.value = res.data.audit;
|
||||||
|
if (formData.value.attachId) {
|
||||||
|
const data = await ticketStore.getAttachment(formData.value.attachId);
|
||||||
|
data.data.name = data.data.fileName;
|
||||||
|
fileList.value.push(data.data);
|
||||||
|
}
|
||||||
|
const auditInfo = await userStore.getUserDetail(
|
||||||
|
auditData.value.auditorId
|
||||||
|
);
|
||||||
|
formData.value.deptId = auditInfo.data.deptId;
|
||||||
|
formData.value.auditorId = auditData.value.auditorId;
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setVisible(true);
|
optionDept().then(() => {
|
||||||
|
setVisible(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -200,7 +256,11 @@ const handleSubmit = async () => {
|
|||||||
if (props.isDetail) {
|
if (props.isDetail) {
|
||||||
createEditRef.value?.resetFields();
|
createEditRef.value?.resetFields();
|
||||||
} else {
|
} else {
|
||||||
const res = await ticketStore.updateTicket(formData.value);
|
auditData.value.result = formData.value.status;
|
||||||
|
const res = await ticketStore.auditTicket(
|
||||||
|
formData.value.id,
|
||||||
|
auditData.value
|
||||||
|
);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
Message.success({
|
Message.success({
|
||||||
content: `${modalTitle.value}成功`,
|
content: `${modalTitle.value}成功`,
|
||||||
@ -208,12 +268,14 @@ const handleSubmit = async () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fileList.value.pop();
|
||||||
emit('refresh');
|
emit('refresh');
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCancel = async () => {
|
const handleCancel = async () => {
|
||||||
|
fileList.value.pop();
|
||||||
createEditRef.value?.resetFields();
|
createEditRef.value?.resetFields();
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
};
|
};
|
||||||
|
@ -73,12 +73,13 @@
|
|||||||
<a-row style="margin-bottom: 16px">
|
<a-row style="margin-bottom: 16px">
|
||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
<a-space>
|
<a-space>
|
||||||
<!-- <DeptEdit
|
<TicketForm
|
||||||
ref="createRef"
|
ref="createEditRef"
|
||||||
:trees="renderData"
|
:prem="ticketItem"
|
||||||
:is-create="true"
|
:is-create="true"
|
||||||
@refresh="search"
|
@refresh="search"
|
||||||
/> -->
|
v-if="userStore.permissions !== 'auditor'"
|
||||||
|
/>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col
|
<a-col
|
||||||
@ -167,22 +168,48 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #operations="{ record }">
|
<template #operations="{ record }">
|
||||||
|
<!-- 详情 -->
|
||||||
<TicketEdit
|
<TicketEdit
|
||||||
ref="editRef"
|
ref="editRef"
|
||||||
:prem="record"
|
:prem="record"
|
||||||
:is-detail="true"
|
:is-detail="true"
|
||||||
@refresh="search"
|
@refresh="search"
|
||||||
|
v-if="
|
||||||
|
userStore.permissions === 'admin' ||
|
||||||
|
(userStore.permissions === 'user' &&
|
||||||
|
(record.status == '审核未通过' || record.status == '待提交'
|
||||||
|
? false
|
||||||
|
: true))
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
<!-- <TicketEdit
|
<!-- 修改 -->
|
||||||
|
<TicketForm
|
||||||
|
ref="createEditRef"
|
||||||
|
:prem="record"
|
||||||
|
:is-create="false"
|
||||||
|
@refresh="search"
|
||||||
|
v-if="
|
||||||
|
userStore.permissions == 'user' &&
|
||||||
|
(record.status == '审核未通过' || record.status == '待提交'
|
||||||
|
? true
|
||||||
|
: false)
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 审核 -->
|
||||||
|
<TicketEdit
|
||||||
ref="editRef"
|
ref="editRef"
|
||||||
:prem="record"
|
:prem="record"
|
||||||
:is-detail="false"
|
:is-detail="false"
|
||||||
@refresh="search"
|
@refresh="search"
|
||||||
/> -->
|
v-if="userStore.permissions === 'auditor'"
|
||||||
|
/>
|
||||||
|
|
||||||
<a-popconfirm
|
<a-popconfirm
|
||||||
content="确认删除此部门?"
|
content="确认删除此部门?"
|
||||||
type="error"
|
type="error"
|
||||||
@ok="handleDelete(record)"
|
@ok="handleDelete(record)"
|
||||||
|
v-if="userStore.permissions === 'admin'"
|
||||||
>
|
>
|
||||||
<a-button type="primary" size="small" status="danger">
|
<a-button type="primary" size="small" status="danger">
|
||||||
删除
|
删除
|
||||||
@ -204,12 +231,15 @@ import type { SelectOptionData } from '@arco-design/web-vue/es/select/interface'
|
|||||||
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
|
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
import { useTicketStore } from '@/store';
|
import { useTicketStore, useUserStore } from '@/store';
|
||||||
import { TicketRecord } from '@/api/ticket';
|
import { TicketRecord } from '@/api/ticket';
|
||||||
import TicketEdit from './components/ticket-edit.vue';
|
import TicketEdit from './components/ticket-edit.vue';
|
||||||
|
import TicketForm from './components/form-edit.vue';
|
||||||
|
|
||||||
const { loading, setLoading } = useLoading(true);
|
const { loading, setLoading } = useLoading(true);
|
||||||
const ticketStore = useTicketStore();
|
const ticketStore = useTicketStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
cloneColumns,
|
cloneColumns,
|
||||||
showColumns,
|
showColumns,
|
||||||
@ -270,20 +300,24 @@ const columns = computed<TableColumnData[]>(() => [
|
|||||||
|
|
||||||
const typesOptions = computed<SelectOptionData[]>(() => [
|
const typesOptions = computed<SelectOptionData[]>(() => [
|
||||||
{
|
{
|
||||||
label: 'Bank',
|
label: '银行支票',
|
||||||
value: 'Bank',
|
value: 'BANK',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Tax',
|
label: '税务支票',
|
||||||
value: 'Tax',
|
value: 'TAX',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Other',
|
label: '其他支票',
|
||||||
value: 'Other',
|
value: 'OTHER',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const statusOptions = computed<SelectOptionData[]>(() => [
|
const statusOptions = computed<SelectOptionData[]>(() => [
|
||||||
|
{
|
||||||
|
label: '待提交',
|
||||||
|
value: 'SUBMIT',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '待审核',
|
label: '待审核',
|
||||||
value: 'EXAMINE',
|
value: 'EXAMINE',
|
||||||
@ -315,10 +349,23 @@ const onPageChange = (current: number) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 获取数据
|
// 获取数据
|
||||||
const fetchData = async (params: { page: 1; current: 1; size: 10 }) => {
|
const fetchData = async (params: {
|
||||||
|
userId: number | undefined;
|
||||||
|
page: 1;
|
||||||
|
current: 1;
|
||||||
|
size: 10;
|
||||||
|
}) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const res = await ticketStore.getTicketList(params);
|
let res = {};
|
||||||
|
if (userStore.permissions === 'admin') {
|
||||||
|
res = await ticketStore.getTicketList(params);
|
||||||
|
} else if (userStore.permissions === 'auditor') {
|
||||||
|
res = await ticketStore.auditTickctList(params);
|
||||||
|
} else if (userStore.permissions === 'user') {
|
||||||
|
params.userId = userStore.id;
|
||||||
|
res = await ticketStore.getTicketList(params);
|
||||||
|
}
|
||||||
renderData.value = res.data.records;
|
renderData.value = res.data.records;
|
||||||
pagination.page = params.page;
|
pagination.page = params.page;
|
||||||
pagination.current = params.current;
|
pagination.current = params.current;
|
||||||
|
@ -83,7 +83,7 @@ import { ref } from 'vue';
|
|||||||
import { useUserStore } from '@/store';
|
import { useUserStore } from '@/store';
|
||||||
import { FormInstance } from '@arco-design/web-vue/es/form';
|
import { FormInstance } from '@arco-design/web-vue/es/form';
|
||||||
import { UserState } from '@/store/modules/user/types';
|
import { UserState } from '@/store/modules/user/types';
|
||||||
import { selfUpdate } from '@/api/user';
|
import { selfUpdate, getUserInfo } from '@/api/user';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
@ -99,6 +99,7 @@ const validate = async () => {
|
|||||||
// you also can use html-type to submit
|
// you also can use html-type to submit
|
||||||
const res = await selfUpdate(formData.value);
|
const res = await selfUpdate(formData.value);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
|
await userStore.info();
|
||||||
Message.success({
|
Message.success({
|
||||||
content: '编辑成功',
|
content: '编辑成功',
|
||||||
duration: 5 * 1000,
|
duration: 5 * 1000,
|
||||||
|
@ -35,119 +35,113 @@
|
|||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<template #label="{ label }">{{ $t(label) }} :</template>
|
<template #label="{ label }">{{ $t(label) }} :</template>
|
||||||
<!-- <template #value="{ value, data }">-->
|
<!-- <template #value="{ value, data }">-->
|
||||||
<!-- <a-tag-->
|
<!-- <a-tag-->
|
||||||
<!-- v-if="data.label === 'userSetting.label.certification'"-->
|
<!-- v-if="data.label === 'userSetting.label.certification'"-->
|
||||||
<!-- color="green"-->
|
<!-- color="green"-->
|
||||||
<!-- size="small"-->
|
<!-- size="small"-->
|
||||||
<!-- >-->
|
<!-- >-->
|
||||||
<!-- 已认证-->
|
<!-- 已认证-->
|
||||||
<!-- </a-tag>-->
|
<!-- </a-tag>-->
|
||||||
<!-- <span v-else>{{ value }}</span>-->
|
<!-- <span v-else>{{ value }}</span>-->
|
||||||
<!-- </template>-->
|
<!-- </template>-->
|
||||||
</a-descriptions>
|
</a-descriptions>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-card>
|
</a-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import type {
|
import type {
|
||||||
FileItem,
|
FileItem,
|
||||||
RequestOption,
|
RequestOption,
|
||||||
} from '@arco-design/web-vue/es/upload/interfaces';
|
} from '@arco-design/web-vue/es/upload/interfaces';
|
||||||
import { useUserStore } from '@/store';
|
import { useUserStore } from '@/store';
|
||||||
import { userUploadApi } from '@/api/user-center';
|
import { userUploadApi } from '@/api/user-center';
|
||||||
import userIcon from '@/assets/images/user-circle.png';
|
import userIcon from '@/assets/images/user-circle.png';
|
||||||
import type { DescData } from '@arco-design/web-vue/es/descriptions/interface';
|
import type { DescData } from '@arco-design/web-vue/es/descriptions/interface';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const file = {
|
const file = {
|
||||||
uid: '-2',
|
uid: '-2',
|
||||||
name: 'avatar.png',
|
name: 'avatar.png',
|
||||||
url: userStore.avatar ? userStore.avatar : userIcon,
|
url: userStore.avatar ? userStore.avatar : userIcon,
|
||||||
};
|
};
|
||||||
const renderData = [
|
const renderData = [
|
||||||
{
|
{
|
||||||
label: 'userSetting.label.name',
|
label: 'userSetting.label.name',
|
||||||
value: userStore.username,
|
value: userStore.username,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'userSetting.label.accountId',
|
label: 'userSetting.label.accountId',
|
||||||
value: userStore.id,
|
value: userStore.id,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'userSetting.label.phone',
|
label: 'userSetting.label.phone',
|
||||||
value: userStore.phone,
|
value: userStore.phone,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'userSetting.label.registrationDate',
|
label: 'userSetting.label.registrationDate',
|
||||||
value: dayjs(userStore.createAt).format('YYYY-MM-DD hh:mm:ss'),
|
value: dayjs(userStore.createAt).format('YYYY-MM-DD hh:mm:ss'),
|
||||||
},
|
},
|
||||||
] as DescData[];
|
] as DescData[];
|
||||||
const fileList = ref<FileItem[]>([file]);
|
const fileList = ref<FileItem[]>([file]);
|
||||||
const uploadChange = (fileItemList: FileItem[], fileItem: FileItem) => {
|
const uploadChange = (fileItemList: FileItem[], fileItem: FileItem) => {
|
||||||
fileList.value = [fileItem];
|
fileList.value = [fileItem];
|
||||||
};
|
};
|
||||||
const customRequest = (options: RequestOption) => {
|
const customRequest = (options: RequestOption) => {
|
||||||
// docs: https://axios-http.com/docs/cancellation
|
// docs: https://axios-http.com/docs/cancellation
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
|
|
||||||
(async function requestWrap() {
|
(async function requestWrap() {
|
||||||
const {
|
const { onProgress, onError, onSuccess, fileItem, name = 'file' } = options;
|
||||||
onProgress,
|
onProgress(20);
|
||||||
onError,
|
const formData = new FormData();
|
||||||
onSuccess,
|
formData.append(name as string, fileItem.file as Blob);
|
||||||
fileItem,
|
const onUploadProgress = (event: ProgressEvent) => {
|
||||||
name = 'file',
|
let percent;
|
||||||
} = options;
|
if (event.total > 0) {
|
||||||
onProgress(20);
|
percent = (event.loaded / event.total) * 100;
|
||||||
const formData = new FormData();
|
|
||||||
formData.append(name as string, fileItem.file as Blob);
|
|
||||||
const onUploadProgress = (event: ProgressEvent) => {
|
|
||||||
let percent;
|
|
||||||
if (event.total > 0) {
|
|
||||||
percent = (event.loaded / event.total) * 100;
|
|
||||||
}
|
|
||||||
onProgress(parseInt(String(percent), 10), event);
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
// https://github.com/axios/axios/issues/1630
|
|
||||||
// https://github.com/nuysoft/Mock/issues/127
|
|
||||||
|
|
||||||
const res = await userUploadApi(formData, {
|
|
||||||
controller,
|
|
||||||
onUploadProgress,
|
|
||||||
});
|
|
||||||
onSuccess(res);
|
|
||||||
} catch (error) {
|
|
||||||
onError(error);
|
|
||||||
}
|
}
|
||||||
})();
|
onProgress(parseInt(String(percent), 10), event);
|
||||||
return {
|
|
||||||
abort() {
|
|
||||||
controller.abort();
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
// https://github.com/axios/axios/issues/1630
|
||||||
|
// https://github.com/nuysoft/Mock/issues/127
|
||||||
|
|
||||||
|
const res = await userUploadApi(formData, {
|
||||||
|
controller,
|
||||||
|
onUploadProgress,
|
||||||
|
});
|
||||||
|
onSuccess(res);
|
||||||
|
} catch (error) {
|
||||||
|
onError(error);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
return {
|
||||||
|
abort() {
|
||||||
|
controller.abort();
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.arco-card {
|
.arco-card {
|
||||||
padding: 14px 0 4px 4px;
|
padding: 14px 0 4px 4px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
:deep(.arco-avatar-trigger-icon-button) {
|
:deep(.arco-avatar-trigger-icon-button) {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
background-color: #e8f3ff;
|
background-color: #e8f3ff;
|
||||||
.arco-icon-camera {
|
.arco-icon-camera {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
color: rgb(var(--arcoblue-6));
|
color: rgb(var(--arcoblue-6));
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
Loading…
Reference in New Issue
Block a user