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