关闭TS校验和完善票据查询功能

This commit is contained in:
2024-05-29 10:03:12 +08:00
parent 4f05a4b12e
commit 69fd1b6b88
23 changed files with 368 additions and 389 deletions

View File

@ -36,7 +36,7 @@ module.exports = {
},
},
rules: {
'prettier/prettier': 1,
'prettier/prettier': 0,
// Vue: Recommended rules to be closed or modify
'vue/require-default-prop': 0,
'vue/singleline-html-element-content-newline': 0,

View File

@ -14,7 +14,6 @@ export default mergeConfig(
proxy: {
'/api': {
target: 'http://106.53.179.133:8081',
// target: 'http://192.168.243.246:8081',
// target: 'http://localhost:5173',
changeOrigin: true,
},

View File

@ -1,8 +1,7 @@
import axios from 'axios';
import type { AxiosRequestConfig, AxiosResponse } from 'axios';
import { Message, Modal } from '@arco-design/web-vue';
import { Message } from '@arco-design/web-vue';
import { getToken } from '@/utils/auth';
import { useUserStore } from '@/store';
import router from '@/router';
export interface HttpResponse<T = unknown> {
@ -73,7 +72,7 @@ axios.interceptors.response.use(
},
(error) => {
const { response } = error;
console.log('error', error);
// console.log('error', error);
if (response.status === 401) {

View File

@ -6,6 +6,11 @@
<a-typography-title
:style="{ margin: 0, fontSize: '18px' }"
:heading="5"
@click="
{
router.push({ name: 'Workplace' });
}
"
>
{{ $t('ticket.manage.system') }}
</a-typography-title>
@ -107,6 +112,9 @@
</a-tooltip>
</li>
<li>
<a-button status="normal">{{ userStore.permissions }}</a-button>
</li>
<li>
<a-dropdown trigger="click">
<a-button style="margin-right: 20px" status="normal">{{
@ -153,17 +161,16 @@ import { useDark, useToggle, useFullscreen } from '@vueuse/core';
import { useAppStore, useUserStore } from '@/store';
import { LOCALE_OPTIONS } from '@/locale';
import useLocale from '@/hooks/locale';
import useUser from '@/hooks/user';
import Menu from '@/components/menu/index.vue';
import userIcon from '@/assets/images/user-circle.png';
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();
const { changeLocale, currentLocale } = useLocale();
const { isFullscreen, toggle: toggleFullScreen } = useFullscreen();
const locales = [...LOCALE_OPTIONS];
@ -192,18 +199,9 @@ const handleToggleTheme = () => {
const setVisible = () => {
appStore.updateSettings({ globalSettings: true });
};
const refBtn = ref();
const triggerBtn = ref();
const defaultRole = ref(userStore.role?.id);
const setPopoverVisible = () => {
const event = new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true,
});
refBtn.value.dispatchEvent(event);
};
const triggerBtn = ref();
const handleLogout = () => {
clearToken();
router.push({

View File

@ -2,14 +2,12 @@ import type { Router, RouteRecordNormalized } from 'vue-router';
import NProgress from 'nprogress'; // progress bar
import usePermission from '@/hooks/permission';
import { useUserStore, useAppStore } from '@/store';
import { appRoutes } from '../routes';
import { useAppStore } from '@/store';
import { WHITE_LIST, NOT_FOUND } from '../constants';
export default function setupPermissionGuard(router: Router) {
router.beforeEach(async (to, from, next) => {
const appStore = useAppStore();
const userStore = useUserStore();
const Permission = usePermission();
const permissionsAllow = Permission.accessRouter(to);

View File

@ -6,7 +6,6 @@ import {
LoginData,
me,
queryUserList,
UserParams,
enabled,
remove,
create,
@ -72,7 +71,7 @@ const useUserStore = defineStore('user', {
async login(loginForm: LoginData, token: string) {
try {
setToken(token);
const res = await userLogin(loginForm);
await userLogin(loginForm);
} catch (err) {
clearToken();
throw err;

View File

@ -2,7 +2,6 @@
import saveAs from 'file-saver'; // https://www.npmjs.com/package/file-saver
import ExcelJS from 'exceljs'; // https://github.com/exceljs/exceljs/blob/master/README_zh.md
import dayjs from 'dayjs'; // https://dayjs.fenxianglu.cn/
import * as XLSX from 'xlsx'; // https://www.npmjs.com/package/xlsx
import { Message } from '@arco-design/web-vue'; // https://arco.design/vue/component/message
import { FileItem } from '@arco-design/web-vue/es/upload/interfaces'; // arco类型
@ -44,7 +43,6 @@ export function downloadExcel({ columns, rows, name = '未命名文件' }: Downl
// 读取文件为json格式
export function readExcle(fileItem:FileItem) {
console.log('读取文件...',fileItem);
return new Promise((resove,reject)=>{
try {
let workbook:XLSX.Sheet;

View File

@ -10,26 +10,26 @@
</template>
<script lang="ts" setup>
import { computed } from 'vue';
import { useUserStore } from '@/store';
import { computed } from 'vue';
import { useUserStore } from '@/store';
const userStore = useUserStore();
const userInfo = computed(() => {
return {
name: userStore.username,
};
});
const userStore = useUserStore();
const userInfo = computed(() => {
return {
name: userStore.username,
};
});
</script>
<style scoped lang="less">
.banner {
width: 100%;
padding: 20px 20px 0 20px;
background-color: var(--color-bg-2);
border-radius: 4px 4px 0 0;
}
.banner {
width: 100%;
padding: 20px 20px 0 20px;
background-color: var(--color-bg-2);
border-radius: 4px 4px 0 0;
}
:deep(.arco-icon-home) {
margin-right: 6px;
}
:deep(.arco-icon-home) {
margin-right: 6px;
}
</style>

View File

@ -5,7 +5,7 @@
class="panel-col"
:span="{ xs: 12, sm: 12, md: 12, lg: 12, xl: 12, xxl: 6 }"
>
<a-space>
<a-space @click="to('PASS')">
<a-avatar :size="54" class="col-avatar">
<img
alt="avatar"
@ -16,7 +16,6 @@
:title="$t('workplace.pass')"
:value="formData.pass || 0"
:value-from="0"
animation
show-group-separator
>
<template #suffix>
@ -29,7 +28,7 @@
class="panel-col"
:span="{ xs: 12, sm: 12, md: 12, lg: 12, xl: 12, xxl: 6 }"
>
<a-space>
<a-space @click="to('FAILED')">
<a-avatar :size="54" class="col-avatar">
<img
alt="avatar"
@ -40,7 +39,6 @@
:title="$t('workplace.notPass')"
:value="formData.notPass || 0"
:value-from="0"
animation
show-group-separator
>
<template #suffix>
@ -53,7 +51,7 @@
class="panel-col"
:span="{ xs: 12, sm: 12, md: 12, lg: 12, xl: 12, xxl: 6 }"
>
<a-space>
<a-space @click="to('EXAMINE')">
<a-avatar :size="54" class="col-avatar">
<img
alt="avatar"
@ -64,7 +62,6 @@
:title="$t('workplace.notAudit')"
:value="formData.notAudit || 0"
:value-from="0"
animation
show-group-separator
>
<template #suffix>
@ -79,7 +76,7 @@
:span="{ xs: 12, sm: 12, md: 12, lg: 12, xl: 12, xxl: 6 }"
style="border-right: none"
>
<a-space>
<a-space @click="to('SUBMIT')">
<a-avatar :size="54" class="col-avatar">
<img
alt="avatar"
@ -91,7 +88,6 @@
:title="$t('workplace.notFiled')"
:value="formData.notFiled || 0"
:value-from="0"
animation
show-group-separator
>
<template #suffix>
@ -104,7 +100,7 @@
<a-divider class="panel-border" />
</a-grid-item>
</a-grid>
<a-card :bordered="false" v-if="userStore.permissions === 'admin'">
<a-card :bordered="false">
<a-space id="TicketEcharts" style="width: 98%; height: 400px"></a-space>
</a-card>
</div>
@ -115,6 +111,7 @@ import { useI18n } from 'vue-i18n';
import { useTicketStore, useUserStore } from '@/store';
import { onMounted, ref } from 'vue';
import * as echarts from 'echarts';
import router from '@/router';
const { t } = useI18n();
const ticketStore = useTicketStore();
@ -126,14 +123,8 @@ const formData = ref({
pass: undefined,
});
const getEchartData = () => {
const res = ticketStore.getChart();
console.log('chart', res);
};
onMounted(async () => {
const res = await ticketStore.getChart();
console.log('chart', res.data);
type EChartsOption = echarts.EChartsOption;
const chartDom = document.getElementById('TicketEcharts');
const myChart = echarts.init(chartDom);
@ -208,6 +199,15 @@ const getHomeData = async (params: {
formData.value = res.data;
});
};
const to = (key: string) => {
router.push({
name: 'TicketManage',
query: {
status: key,
},
});
};
getHomeData({});
</script>

View File

@ -15,70 +15,70 @@
</template>
<script lang="ts" setup>
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import bannerImage from '@/assets/images/login-banner.png';
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import bannerImage from '@/assets/images/login-banner.png';
const { t } = useI18n();
const carouselItem = computed(() => [
{
slogan: t('login.banner.slogan1'),
subSlogan: t('login.banner.subSlogan1'),
image: bannerImage,
},
{
slogan: t('login.banner.slogan2'),
subSlogan: t('login.banner.subSlogan2'),
image: bannerImage,
},
{
slogan: t('login.banner.slogan3'),
subSlogan: t('login.banner.subSlogan3'),
image: bannerImage,
},
]);
const { t } = useI18n();
const carouselItem = computed(() => [
{
slogan: t('login.banner.slogan1'),
subSlogan: t('login.banner.subSlogan1'),
image: bannerImage,
},
{
slogan: t('login.banner.slogan2'),
subSlogan: t('login.banner.subSlogan2'),
image: bannerImage,
},
{
slogan: t('login.banner.slogan3'),
subSlogan: t('login.banner.subSlogan3'),
image: bannerImage,
},
]);
</script>
<style lang="less" scoped>
.banner {
.banner {
display: flex;
align-items: center;
justify-content: center;
&-inner {
flex: 1;
height: 100%;
}
}
.carousel {
height: 100%;
&-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
&-inner {
flex: 1;
height: 100%;
}
}
.carousel {
height: 100%;
&-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
}
&-title {
color: var(--color-fill-1);
font-weight: 500;
font-size: 20px;
line-height: 28px;
}
&-sub-title {
margin-top: 8px;
color: var(--color-text-3);
font-size: 14px;
line-height: 22px;
}
&-image {
width: 320px;
margin-top: 30px;
}
}
&-title {
color: var(--color-fill-1);
font-weight: 500;
font-size: 20px;
line-height: 28px;
}
&-sub-title {
margin-top: 8px;
color: var(--color-text-3);
font-size: 14px;
line-height: 22px;
}
&-image {
width: 320px;
margin-top: 30px;
}
}
</style>

View File

@ -192,7 +192,6 @@ import { useStorage } from '@vueuse/core';
import { useUserStore } from '@/store';
import useLoading from '@/hooks/loading';
import { LoginData, CreateRecord } from '@/api/user';
import { deptList } from '@/api/dept';
const router = useRouter();
const { t } = useI18n();
@ -219,11 +218,6 @@ const formData = ref<CreateRecord>({
const flag = ref(false);
const totalCount = ref(60);
const deptOptions = ref();
const getDeptData = async () => {
const res = await deptList();
deptOptions.value = res.data.records;
};
const loginConfig = useStorage('login-config', {
// 使 useStorage
@ -257,10 +251,10 @@ const handleSubmit = async ({
try {
const res = await userStore.me();
await userStore.login(values as LoginData, res.data.csrf.token);
const csrf = await userStore.me();
await userStore.me();
await userStore.info();
//
const { redirect, ...othersQuery } = router.currentRoute.value.query;
const { ...othersQuery } = router.currentRoute.value.query;
router.push({
name: 'Workplace',
query: {

View File

@ -48,8 +48,8 @@ import { useI18n } from 'vue-i18n';
import useVisible from '@/hooks/visible';
import { computed, PropType, ref } from 'vue';
import { FormInstance } from '@arco-design/web-vue/es/form';
import { Message, TreeNodeData } from '@arco-design/web-vue';
import { DeptRecord, DeptCreateRecord } from '@/api/dept';
import { Message } from '@arco-design/web-vue';
import { DeptRecord } from '@/api/dept';
import { useDeptStore } from '@/store';
const props = defineProps({

View File

@ -163,12 +163,12 @@
<a-pagination
style="float: right; position: relative; right: 1px; bottom: 25px"
:total="pagination.total"
@page-size-change="onSizeChange"
:size="size"
@change="onPageChange"
show-total
show-jumper
show-page-size
@page-size-change="onSizeChange"
@change="onPageChange"
/>
</a-card>
</div>

View File

@ -50,7 +50,6 @@ import { useI18n } from 'vue-i18n';
import useVisible from '@/hooks/visible';
import { computed, PropType, ref } from 'vue';
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 { RoleRecord } from '@/api/role';
import { useRoleStore } from '@/store';

View File

@ -115,8 +115,8 @@
:data="renderData"
:bordered="false"
:size="size"
@page-change="onPageChange"
style="margin-bottom: 40px"
@page-change="onPageChange"
>
<template #index="{ rowIndex }">
{{ rowIndex + 1 }}
@ -160,19 +160,19 @@
<a-pagination
style="float: right; position: relative; right: 1px; bottom: 25px"
:total="pagination.total"
@page-size-change="onSizeChange"
:size="size"
@change="onPageChange"
show-total
show-jumper
show-page-size
@page-size-change="onSizeChange"
@change="onPageChange"
/>
</a-card>
</div>
</template>
<script lang="ts" setup>
import { computed, ref, reactive, watch, nextTick } from 'vue';
import { computed, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import useLoading from '@/hooks/loading';
import { Pagination } from '@/types/global';
@ -181,11 +181,9 @@ import { Message } from '@arco-design/web-vue';
import useTableOption from '@/hooks/table-option';
import dayjs from 'dayjs';
import { useRoleStore } from '@/store';
import { RoleRecord, RoleCreateRecord } from '@/api/role';
import { RoleRecord } from '@/api/role';
import RoleEdit from './components/role-edit.vue';
type SizeProps = 'mini' | 'small' | 'medium' | 'large';
type Column = TableColumnData & { checked?: true };
const { loading, setLoading } = useLoading(true);
const { t } = useI18n();
const renderData = ref<RoleRecord[]>([]);
@ -257,7 +255,6 @@ const fetchData = async (params: any) => {
setLoading(true);
try {
const res = await roleStore.getRoleList(params);
console.log('info', res.data);
renderData.value = res.data.records;
pagination.page = res.data.page;
pagination.current = res.data.current;

View File

@ -85,7 +85,7 @@
<a-space>
<UserEdit ref="createUserRef" :is-create="true" @refresh="search" />
</a-space>
<a-button @click="generateExcel" style="margin-left: 20px">
<a-button style="margin-left: 20px" @click="generateExcel">
<template #icon>
<icon-download size="18" />
</template>
@ -168,10 +168,10 @@
:data="renderData"
:bordered="false"
:size="size"
@page-change="onPageChange"
style="margin-bottom: 40px"
:filter-icon-align-left="alignLeft"
@change="handleSortChange"
@page-change="onPageChange"
>
<template #index="{ rowIndex }">
{{ rowIndex + 1 + (pagination.current - 1) * pagination.size }}
@ -211,12 +211,12 @@
<a-pagination
style="float: right; position: relative; right: 1px; bottom: 25px"
:total="pagination.total"
@page-size-change="onSizeChange"
:size="size"
@change="onPageChange"
show-total
show-jumper
show-page-size
@page-size-change="onSizeChange"
@change="onPageChange"
/>
</a-card>
</div>
@ -236,9 +236,6 @@ import { downloadExcel, DownloadExcelPrams } from '@/utils/excel';
import useTableOption from '@/hooks/table-option';
import UserEdit from './components/user-edit.vue';
type SizeProps = 'mini' | 'small' | 'medium' | 'large';
type Column = TableColumnData & { checked?: true };
const generateFormModel = () => {
return {
id: '',
@ -404,9 +401,7 @@ const reset = () => {
//
const alignLeft = ref(false);
const handleSortChange = (data: any, extra: any, currentDataSource: any) => {
console.log('change', data, extra, currentDataSource);
};
const handleSortChange = (data: any, extra: any, currentDataSource: any) => {};
//
const enabledStatus = async (record: string) => {

View File

@ -24,149 +24,205 @@
<template #icon><icon-edit /></template>
{{ modalTitle }}
</a-button>
<a-modal
width="700px"
width="800px"
:visible="visible"
:footer="false"
@cancel="handleCancel"
>
<template #title>{{ modalTitle }}</template>
<a-form ref="createEditRef" :model="formData" :style="{ width: '650px' }">
<a-form-item
field="companyName"
:label="$t('ticket.info.companyName')"
:validate-trigger="['change', 'input']"
:rules="[
{ required: true, message: t('ticket.info.companyName.required') },
]"
style="line-height: 18px"
>
<a-input
v-model="formData.companyName"
:placeholder="$t('ticket.info.companyName.placeholder')"
/>
</a-form-item>
<a-form
ref="createEditRef"
:label-col-props="{ span: 6 }"
:wrapper-col-props="{ span: 15 }"
label-align="right"
:model="formData"
:style="{ width: '750px' }"
>
<a-row>
<a-col :span="12">
<a-form-item
field="companyName"
:label="$t('ticket.info.companyName')"
:validate-trigger="['change', 'input']"
:rules="[
{
required: true,
message: t('ticket.info.companyName.required'),
},
]"
style="line-height: 18px"
>
<a-input
v-model="formData.companyName"
:placeholder="$t('ticket.info.companyName.placeholder')"
/>
</a-form-item>
</a-col>
<a-form-item
field="title"
:label="$t('ticket.info.title')"
:validate-trigger="['change', 'input']"
:rules="[{ required: true, message: t('ticket.info.title.required') }]"
>
<a-input
v-model="formData.title"
:placeholder="$t('ticket.info.title.placeholder')"
/>
</a-form-item>
<a-col :span="12">
<a-form-item
field="title"
:label="$t('ticket.info.title')"
:validate-trigger="['change', 'input']"
:rules="[
{ required: true, message: t('ticket.info.title.required') },
]"
>
<a-input
v-model="formData.title"
:placeholder="$t('ticket.info.title.placeholder')"
/>
</a-form-item>
</a-col>
</a-row>
<a-form-item
field="money"
:label="$t('ticket.info.money')"
:validate-trigger="['change', 'input']"
:rules="[{ required: true, message: t('ticket.info.money.required') }]"
>
<a-input
v-model="formData.money"
:placeholder="$t('ticket.info.money.placeholder')"
/>
</a-form-item>
<a-row>
<a-col :span="12">
<a-form-item
field="money"
:label="$t('ticket.info.money')"
:validate-trigger="['change', 'input']"
:rules="[
{ required: true, message: t('ticket.info.money.required') },
]"
>
<a-input
v-model="formData.money"
:placeholder="$t('ticket.info.money.placeholder')"
/>
</a-form-item>
</a-col>
<a-form-item
field="contactEmail"
:label="$t('ticket.info.contactEmail')"
:validate-trigger="['change', 'input']"
:rules="[
{ required: true, message: t('ticket.info.contactEmail.required') },
]"
>
<a-input
v-model="formData.contactEmail"
:placeholder="$t('ticket.info.contactEmail.placeholder')"
/>
</a-form-item>
<a-col :span="12">
<a-form-item
field="contactEmail"
:label="$t('ticket.info.contactEmail')"
:validate-trigger="['change', 'input']"
:rules="[
{
required: true,
message: t('ticket.info.contactEmail.required'),
},
]"
>
<a-input
v-model="formData.contactEmail"
:placeholder="$t('ticket.info.contactEmail.placeholder')"
/>
</a-form-item>
</a-col>
</a-row>
<a-form-item
field="type"
:label="$t('ticket.info.type')"
:validate-trigger="['change', 'input']"
:rules="[{ required: true, message: t('ticket.info.type.required') }]"
>
<a-select
v-model="formData.type"
:options="typesOptions"
:placeholder="$t('ticket.info.type.placeholder')"
/>
</a-form-item>
<a-row>
<a-col :span="12">
<a-form-item
field="type"
:label="$t('ticket.info.type')"
:validate-trigger="['change', 'input']"
:rules="[
{ required: true, message: t('ticket.info.type.required') },
]"
>
<a-select
v-model="formData.type"
:options="typesOptions"
:placeholder="$t('ticket.info.type.placeholder')"
/>
</a-form-item>
</a-col>
<a-form-item
field="deptId"
:label="$t('ticket.info.dept')"
:rules="[{ required: true, message: t('ticket.info.dept.required') }]"
:validate-trigger="['change']"
>
<a-tree-select
v-model="formData.deptId"
:field-names="{
key: 'id',
title: 'name',
children: 'children',
}"
:data="deptOptions"
:placeholder="$t('ticket.info.dept.placeholder')"
@change="optionDept(true)"
/>
</a-form-item>
<a-col :span="12">
<a-form-item
field="deptId"
:label="$t('ticket.info.dept')"
:rules="[
{ required: true, message: t('ticket.info.dept.required') },
]"
:validate-trigger="['change']"
>
<a-tree-select
v-model="formData.deptId"
:field-names="{
key: 'id',
title: 'name',
children: 'children',
}"
:data="deptOptions"
:placeholder="$t('ticket.info.dept.placeholder')"
@change="optionDept(true)"
/>
</a-form-item>
</a-col>
</a-row>
<a-form-item
field="auditorId"
:label="$t('ticket.info.auditor')"
:rules="[
{ required: true, message: t('ticket.info.auditor.required') },
]"
:validate-trigger="['change']"
>
<a-select
v-model="formData.auditorId"
:placeholder="$t('ticket.info.auditor.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-row>
<a-col :span="12">
<a-row>
<a-form-item
field="auditorId"
:label="$t('ticket.info.auditor')"
:rules="[
{ required: true, message: t('ticket.info.auditor.required') },
]"
:validate-trigger="['change']"
>
<a-select
v-model="formData.auditorId"
:placeholder="$t('ticket.info.auditor.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-row>
<a-row>
<a-form-item
field="comment"
:label="$t('ticket.info.comment')"
v-if="formData.comment"
>
{{ formData.comment }}
</a-form-item>
</a-row>
<a-form-item
field="comment"
:label="$t('ticket.info.comment')"
v-if="formData.comment"
>
{{ formData.comment }}
</a-form-item>
<a-row>
<a-form-item
field="body"
:label="$t('ticket.info.body')"
:validate-trigger="['change', 'input']"
:rules="[
{ required: true, message: t('ticket.info.body.required') },
]"
>
<a-textarea
v-model="formData.body"
:placeholder="$t('ticket.info.body.placeholder')"
style="height: 150px"
/>
</a-form-item>
</a-row>
</a-col>
<a-form-item
field="body"
:label="$t('ticket.info.body')"
:validate-trigger="['change', 'input']"
:rules="[{ required: true, message: t('ticket.info.body.required') }]"
>
<a-textarea
v-model="formData.body"
:placeholder="$t('ticket.info.body.placeholder')"
style="height: 100px"
/>
</a-form-item>
<a-col :span="12"
><a-form-item
field="attachment"
:label="$t('ticket.info.attachment')"
>
<a-upload
:file-list="fileList"
:custom-request="Onchange"
:limit="5"
:on-before-remove="removeAttact"
/>
</a-form-item>
</a-col>
</a-row>
<a-form-item field="attachment" :label="$t('ticket.info.attachment')">
<a-upload
:file-list="fileList"
:custom-request="Onchange"
:limit="5"
:on-before-remove="removeAttact"
/>
</a-form-item>
<a-form-item>
<a-button type="dashed" @click="handleCancel">
<a-form-item style="display: flex; justify-content: center">
<a-button type="dashed" style="margin-left: 30px" @click="handleCancel">
{{ $t('cancel') }}</a-button
>
<a-button
@ -296,10 +352,8 @@ const Onchange = async (option: any) => {
});
res.data.name = res.data.fileName;
fileList.value.push(res.data);
console.log('res', res.data.id);
attachList.value.push(res.data.id);
formData.value.attachId = attachList;
console.log('poti', formData.value.attachId);
} else {
Message.error({
content: t('upload.fail'),
@ -310,12 +364,9 @@ const Onchange = async (option: any) => {
//
const removeAttact = (fileItem: FileItem) => {
console.log('2', fileItem.id, fileList.value, attachList.value);
fileList.value = fileList.value.filter((item) => item.id !== fileItem.id);
attachList.value = attachList.value.filter((item) => item !== fileItem.id);
console.log('3', fileList.value, attachList.value);
formData.value.attachId = attachList.value;
console.log('3', formData.value.attachId);
};
//
@ -332,7 +383,6 @@ const handleClick = () => {
formData.value = res.data;
formData.value.attachId.forEach(async (item: any) => {
console.log('item,', item);
const data = await ticketStore.getAttachment(item);
data.data.name = data.data.fileName;
fileList.value.push(data.data);

View File

@ -1,8 +1,8 @@
<template>
<!-- 详情 -->
<a-button
v-permission="['BILL_QUERY']"
v-if="props.isDetail"
v-permission="['BILL_QUERY']"
type="outline"
size="small"
:style="{ marginRight: '10px', padding: '7px', border: '0px' }"
@ -14,8 +14,8 @@
<!-- 审核 -->
<a-button
v-permission="['BILL_AUDIT']"
v-if="!props.isDetail"
v-permission="['BILL_AUDIT']"
type="outline"
size="small"
:style="{ marginRight: '10px', padding: '7px', border: '0px' }"
@ -178,11 +178,14 @@
</a-radio-group>
</a-form-item>
<a-form-item
v-if="!props.isDetail"
field="comment"
:label="$t('ticket.info.comment')"
v-if="!props.isDetail"
>
<a-textarea v-model="formData.comment" style="height: 200px" />
<a-textarea
v-model="formData.comment"
style="height: 200px; background-color: white; border: 1px solid"
/>
</a-form-item>
</div>
@ -193,14 +196,14 @@
style="margin-left: -110px"
>
<a-upload
v-if="fileList.length !== 0"
v-model="formData.attachId"
:file-list="fileList"
:custom-request="Onchange"
:limit="5"
:disabled="true"
:on-before-remove="removeAttact"
:show-remove-button="false"
v-model="formData.attachId"
v-if="fileList.length !== 0"
/>
<div v-else></div>
</a-form-item>
@ -214,8 +217,7 @@ import { useI18n } from 'vue-i18n';
import useVisible from '@/hooks/visible';
import { computed, PropType, ref } from 'vue';
import { FormInstance } from '@arco-design/web-vue/es/form';
import { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
import { Button, Message } from '@arco-design/web-vue';
import { Message } from '@arco-design/web-vue';
import { useTicketStore, useUserStore, useRoleStore } from '@/store';
import { TicketRecord } from '@/api/ticket';
import { deptList } from '@/api/dept';
@ -299,9 +301,9 @@ const handleClick = async () => {
//
formData.value = res.data;
formData.value.submit = 'true';
//
formData.value.attachId.forEach(async (item: any) => {
// console.log('item,', item);
const data = await ticketStore.getAttachment(item);
data.data.name = data.data.fileName;
fileList.value.push(data.data);

View File

@ -2,15 +2,19 @@
<div class="container">
<Breadcrumb :items="['menu.ticket', 'menu.ticket.manage']" />
<a-card class="general-card">
<a-tabs default-active-key="" @change="changeTop">
<a-tab-pane key="" :title="t('set')"> </a-tab-pane>
<a-tab-pane key="PASS" :title="t('pass')"> </a-tab-pane>
<a-tabs
default-active-key="ALL"
:active-key="tabKey"
@tab-click="changeTop"
>
<a-tab-pane key="ALL" :title="t('set')"> </a-tab-pane>
<a-tab-pane key="FAILED" :title="t('failed')"> </a-tab-pane>
<a-tab-pane key="PASS" :title="t('pass')"> </a-tab-pane>
<a-tab-pane key="EXAMINE" :title="t('unreviewed')"> </a-tab-pane>
<a-tab-pane
v-if="userStore.permissions !== 'auditor'"
key="SUBMIT"
:title="t('drafts')"
v-if="userStore.permissions !== 'auditor'"
>
</a-tab-pane>
</a-tabs>
@ -103,9 +107,9 @@
v-model="formModel.time"
style="width: 360px"
show-time
@select="onSelect"
value-format="YYYY-MM-DD"
:allow-clear="false"
@select="onSelect"
/>
</a-form-item>
</a-col>
@ -143,7 +147,7 @@
@refresh="search"
/>
</a-space>
<a-button @click="generateExcel" style="margin-left: 5px">
<a-button style="margin-left: 5px" @click="generateExcel">
<template #icon>
<icon-download size="16" />
</template>
@ -220,12 +224,12 @@
:pagination="false"
:size="size"
:expandable="expandable"
@page-change="onPageChange"
style="margin-bottom: 40px"
@page-change="onPageChange"
>
<template #expand-row="{ record }">
<!-- 下面展示子表格,根据需求对子table进行属性配置 -->
<a-descriptions layout="inline-horizontal" :column="1" bordered>
<a-descriptions layout="inline-horizontal" :column="1">
<descriptions-item :label="t('ticket.info.contactEmail')">
{{ record.contactEmail }}
</descriptions-item>
@ -242,16 +246,16 @@
</template>
<template #status="{ record }">
<a-button status="success" v-if="record.status === '审核通过'">{{
<a-button v-if="record.status === '审核通过'" status="success">{{
record.status
}}</a-button>
<a-button status="danger" v-if="record.status === '审核未通过'">{{
<a-button v-if="record.status === '审核未通过'" status="danger">{{
record.status
}}</a-button>
<a-button status="normal" v-if="record.status === '待审核'">{{
<a-button v-if="record.status === '待审核'" status="normal">{{
record.status
}}</a-button>
<a-button status="warning" v-if="record.status === '待提交'">{{
<a-button v-if="record.status === '待提交'" status="warning">{{
record.status
}}</a-button>
</template>
@ -267,20 +271,20 @@
<!-- 修改 -->
<TicketForm
v-if="record.status === '待提交' || record.status === '审核未通过'"
ref="createEditRef"
:prem="record"
:is-create="false"
@refresh="search"
v-if="record.status === '待提交' || record.status === '审核未通过'"
/>
<!-- 审核 -->
<TicketEdit
v-if="record.status === '待审核'"
ref="editRef"
:prem="record"
:is-detail="false"
@refresh="search"
v-if="record.status === '待审核'"
/>
<a-popconfirm
@ -288,12 +292,12 @@
@ok="handleDelete(record)"
>
<a-button
type="outline"
size="small"
v-permission="['BILL_DELETE']"
v-if="
record.status === '待提交' || record.status === '审核未通过'
"
v-permission="['BILL_DELETE']"
type="outline"
size="small"
style="padding: 7px; border: 0px"
>
<template #icon><icon-delete /></template>
@ -305,19 +309,19 @@
<a-pagination
style="float: right; position: relative; right: 1px; bottom: 25px"
:total="pagination.total"
@page-size-change="onSizeChange"
:size="size"
@change="onPageChange"
show-total
show-jumper
show-page-size
@page-size-change="onSizeChange"
@change="onPageChange"
/>
</a-card>
</div>
</template>
<script lang="ts" setup>
import { computed, reactive, ref, watch } from 'vue';
import { computed, reactive, ref, watch, onMounted } from 'vue';
import { useI18n } from 'vue-i18n';
import useLoading from '@/hooks/loading';
import useTableOption from '@/hooks/table-option';
@ -329,6 +333,7 @@ import { Message } from '@arco-design/web-vue';
import { useTicketStore, useUserStore } from '@/store';
import { TicketRecord } from '@/api/ticket';
import { downloadExcel, DownloadExcelPrams } from '@/utils/excel';
import { useRoute } from 'vue-router';
import TicketEdit from './components/ticket-edit.vue';
import TicketForm from './components/form-edit.vue';
@ -352,7 +357,7 @@ const generateFormModel = () => {
companyName: '',
title: '',
type: '',
//
//
status: '',
time: [],
userName: '',
@ -368,6 +373,12 @@ const renderData = ref<TicketRecord[]>([]);
const formModel = ref(generateFormModel());
const currentStatus = ref('PASS');
//
onMounted(() => {
const router = useRoute();
changeTop(router.query.status);
});
//
const expandable = reactive({
title: ' ',
@ -481,12 +492,6 @@ const onSelect = (dateString: any, date: any) => {
formModel.value.endTime = String(dateString[1]);
};
//
const onChange = (dateString: any, date: any) => {
formModel.value.startTime = String(dateString[0]);
formModel.value.endTime = String(dateString[1]);
};
//
const onPageChange = (current: number) => {
pagination.page = current;
@ -534,26 +539,31 @@ const fetchData = async (params: {
}
};
const tabKey = ref('ALL');
//
const search = () => {
// time
const { time, ...auditDate } = formModel.value;
changeTop('ALL');
};
//
const changeTop = (key: any) => {
tabKey.value = key;
if (tabKey.value === 'ALL') {
formModel.value.status = '';
} else {
formModel.value.status = key;
}
currentStatus.value = key;
const { time, ...auditDate } = formModel.value;
fetchData({
...pagination,
...auditDate,
} as unknown as any);
};
//
const changeTop = (key: any) => {
formModel.value.status = key;
currentStatus.value = key;
search();
};
search();
//
const reset = () => {
formModel.value = generateFormModel();

View File

@ -48,7 +48,7 @@ export default {
'tax': '税务支票',
'other': '其他支票',
'set':'票据集合',
'set':'所有票据',
'unsubmitted': '待提交',
'unreviewed': '待审核',
'pass': '审核通过',

View File

@ -3,7 +3,7 @@
ref="formRef"
:model="formData"
class="form"
:label-col-props="{ span: 8 }"
:label-col-props="{ span: 5 }"
:wrapper-col-props="{ span: 16 }"
>
<a-form-item

View File

@ -3,24 +3,9 @@
ref="formRef"
:model="formData"
class="form"
:label-col-props="{ span: 8 }"
:label-col-props="{ span: 5 }"
:wrapper-col-props="{ span: 16 }"
>
<!-- <a-form-item
field="oldPassword"
:label="$t('userSetting.passwordReset.form.label.oldPassword')"
:rules="[{ required: true, message: $t('login.form.password.errMsg') }]"
>
<a-input-password
v-model="formData.oldPassword"
:placeholder="
$t('userSetting.passwordReset.form.label.oldPassword.placeholder')
"
allow-clear
>
</a-input-password>
</a-form-item> -->
<a-form-item
field="password"
:label="$t('userSetting.passwordReset.form.label.newPassword')"
@ -98,9 +83,6 @@ const user = useUser();
const validate = async () => {
const vali = await formRef.value?.validate();
if (!vali) {
// do some thing
// you also can use html-type to submit
const res = await resetPassword(formData.value);
if (res.status === 200) {
Message.success({

View File

@ -48,12 +48,8 @@
<script lang="ts" setup>
import { useI18n } from 'vue-i18n';
import { ref } from 'vue';
import type {
FileItem,
RequestOption,
} from '@arco-design/web-vue/es/upload/interfaces';
import type { FileItem } from '@arco-design/web-vue/es/upload/interfaces';
import { useUserStore, useTicketStore } 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';
@ -101,7 +97,7 @@ const Onchange = async (option: any) => {
});
res.data.name = res.data.fileName;
fileList.value.push(res.data);
const data = await selfUpdate({ avatar: res.data.id });
await selfUpdate({ avatar: res.data.id });
await userStore.info();
} else {
Message.error({
@ -110,43 +106,6 @@ const Onchange = async (option: any) => {
});
}
};
// 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);
// }
// })();
// return {
// abort() {
// controller.abort();
// },
// };
// };
</script>
<style scoped lang="less">