首页的统计图和票据的状态分标签展示
This commit is contained in:
parent
b840ca4974
commit
f070b02da9
@ -13,8 +13,8 @@ export default mergeConfig(
|
||||
},
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://59.110.238.182:8081',
|
||||
// target: 'http://192.168.3.158:8081',
|
||||
target: 'http://106.53.179.133:8081',
|
||||
// target: 'http://192.168.243.246:8081',
|
||||
// target: 'http://localhost:5173',
|
||||
changeOrigin: true,
|
||||
},
|
||||
|
@ -3,10 +3,9 @@
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="shortcut icon" type="image/x-icon"
|
||||
href="https://unpkg.byted-static.com/latest/byted/arco-config/assets/favicon.ico">
|
||||
<link rel="icon" href="./src/image/票据服务.png" type="image/x-icon">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>中山学院学习平台</title>
|
||||
<title>票据管理系统</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
@ -13,10 +13,7 @@
|
||||
"type:check": "vue-tsc --noEmit --skipLibCheck",
|
||||
"lint-staged": "npx lint-staged",
|
||||
"prepare": "husky install",
|
||||
|
||||
"start": "npm run dev"
|
||||
|
||||
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,ts,jsx,tsx}": [
|
||||
@ -40,6 +37,8 @@
|
||||
"axios": "^0.24.0",
|
||||
"dayjs": "^1.11.5",
|
||||
"echarts": "^5.4.0",
|
||||
"exceljs": "^4.4.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"lodash": "^4.17.21",
|
||||
"mitt": "^3.0.0",
|
||||
"nprogress": "^0.2.0",
|
||||
@ -50,12 +49,14 @@
|
||||
"vue": "^3.2.40",
|
||||
"vue-echarts": "^6.2.3",
|
||||
"vue-i18n": "^9.2.2",
|
||||
"vue-router": "^4.0.14"
|
||||
"vue-router": "^4.0.14",
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@arco-plugins/vite-vue": "^1.4.5",
|
||||
"@commitlint/cli": "^17.1.2",
|
||||
"@commitlint/config-conventional": "^17.1.0",
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/lodash": "^4.14.186",
|
||||
"@types/mockjs": "^1.0.7",
|
||||
"@types/nprogress": "^0.2.0",
|
||||
|
@ -75,10 +75,12 @@ axios.interceptors.response.use(
|
||||
const { response } = error;
|
||||
console.log('error', error);
|
||||
|
||||
if (response.status === '401') {
|
||||
if (response.status === 401) {
|
||||
|
||||
router.push({
|
||||
name: 'login',
|
||||
});
|
||||
|
||||
}
|
||||
else {
|
||||
Message.error({
|
||||
|
@ -18,8 +18,13 @@ export interface RoleListRecord extends RoleRecord {
|
||||
}
|
||||
|
||||
// 查询所有的角色列表、
|
||||
export function queryRoleList() {
|
||||
return axios.get('/api/rest/role');
|
||||
export function queryRoleList(data: any) {
|
||||
// return axios.get('/api/rest/role',data);
|
||||
return axios({
|
||||
url: '/api/rest/role', // 路径
|
||||
method: 'get',
|
||||
params: data, // 参数
|
||||
})
|
||||
}
|
||||
|
||||
// 切换启用状态
|
||||
|
@ -7,7 +7,7 @@ export interface TicketCreateRecord {
|
||||
type: string;
|
||||
contactEmail: string;
|
||||
companyName: string;
|
||||
attachId: string;
|
||||
attachId: [];
|
||||
auditorId: string;
|
||||
submit: boolean;
|
||||
userId: undefined;
|
||||
@ -15,6 +15,9 @@ export interface TicketCreateRecord {
|
||||
}
|
||||
|
||||
export interface TicketRecord extends TicketCreateRecord {
|
||||
auditor: any;
|
||||
createTime(createTime: any): unknown;
|
||||
deptName: any;
|
||||
value: any;
|
||||
id: undefined;
|
||||
status: string
|
||||
@ -83,3 +86,8 @@ export function home(data: any){
|
||||
params: data, // 参数
|
||||
});
|
||||
}
|
||||
|
||||
// 首页统计图
|
||||
export function chart(){
|
||||
return axios.get('/api/rest/bill/trend')
|
||||
}
|
@ -29,6 +29,8 @@ export interface PasswordReSetModel {
|
||||
|
||||
// 添加用户数据
|
||||
export interface CreateRecord {
|
||||
value: any;
|
||||
code: any;
|
||||
|
||||
username: string;
|
||||
nickName: string;
|
||||
@ -107,10 +109,15 @@ export function resetPassword(data: PasswordReSetModel) {
|
||||
}
|
||||
|
||||
// 注册用户
|
||||
export function create(data: CreateRecord) {
|
||||
export function register(data: CreateRecord) {
|
||||
return axios.post('/api/rest/user/register', data);
|
||||
}
|
||||
|
||||
// 新建用户
|
||||
export function create(data: CreateRecord) {
|
||||
return axios.post('/api/rest/user', data);
|
||||
}
|
||||
|
||||
// 模糊查询用户列表
|
||||
export function queryUserList(params: any) {
|
||||
return axios({
|
||||
@ -158,6 +165,11 @@ export function deptAudit(id: string,roleId:string){
|
||||
});
|
||||
}
|
||||
|
||||
// 获取验证码
|
||||
export function code(data: string){
|
||||
return axios.get(`/api/rest/user/send-email?email=${data}`);
|
||||
}
|
||||
|
||||
export function switchRole(roleId: number) {
|
||||
return axios.patch<UserState>(`/api/user/self/switch-role/${roleId}`);
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
<template>
|
||||
<a-layout-footer class="footer">Arco Pro</a-layout-footer>
|
||||
<a-layout-footer class="footer"></a-layout-footer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup></script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.footer {
|
||||
.footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 40px;
|
||||
color: var(--color-text-2);
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -2,10 +2,7 @@
|
||||
<div class="navbar">
|
||||
<div class="left-side">
|
||||
<a-space>
|
||||
<img
|
||||
alt="logo"
|
||||
src="//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/dfdba5317c0c20ce20e64fac803d52bc.svg~tplv-49unhts6dw-image.image"
|
||||
/>
|
||||
<img style="height: 24px" alt="logo" src="../../image/票据服务.png" />
|
||||
<a-typography-title
|
||||
:style="{ margin: 0, fontSize: '18px' }"
|
||||
:heading="5"
|
||||
@ -112,6 +109,9 @@
|
||||
|
||||
<li>
|
||||
<a-dropdown trigger="click">
|
||||
<a-button style="margin-right: 20px" status="normal">{{
|
||||
userStore.nickName
|
||||
}}</a-button>
|
||||
<a-avatar
|
||||
:size="32"
|
||||
:style="{ marginRight: '8px', cursor: 'pointer' }"
|
||||
|
@ -8,7 +8,7 @@
|
||||
"menuCollapse": false,
|
||||
"footer": true,
|
||||
"themeColor": "#165DFF",
|
||||
"menuWidth": 220,
|
||||
"menuWidth": 200,
|
||||
"globalSettings": false,
|
||||
"device": "desktop",
|
||||
"tabBar": false,
|
||||
|
BIN
src/image/票据服务.png
Normal file
BIN
src/image/票据服务.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
@ -9,7 +9,7 @@ const SYSTEM: AppRouteRecordRaw = {
|
||||
locale: 'menu.system',
|
||||
icon: 'icon-computer',
|
||||
requiresAuth: true,
|
||||
order: 1,
|
||||
order: 2,
|
||||
},
|
||||
children: [
|
||||
// {
|
||||
|
@ -9,7 +9,7 @@ const TICKET: AppRouteRecordRaw = {
|
||||
locale: 'menu.ticket',
|
||||
icon: 'icon-folder-add',
|
||||
requiresAuth: true,
|
||||
order: 4,
|
||||
order: 1,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
|
@ -9,7 +9,7 @@ const USER: AppRouteRecordRaw = {
|
||||
locale: 'menu.user',
|
||||
icon: 'icon-user',
|
||||
requiresAuth: true,
|
||||
order: 7,
|
||||
order: 3,
|
||||
},
|
||||
children: [
|
||||
// {
|
||||
|
@ -27,8 +27,8 @@ const useRoleStore = defineStore('role', {
|
||||
},
|
||||
actions: {
|
||||
// 获取所有的角色列表
|
||||
async getRoleList() {
|
||||
return queryRoleList();
|
||||
async getRoleList(params: any) {
|
||||
return queryRoleList(params);
|
||||
},
|
||||
|
||||
async enabledRole(id: string) {
|
||||
|
@ -11,7 +11,8 @@ import {
|
||||
audit,
|
||||
uploadFile,
|
||||
attachment,
|
||||
home
|
||||
home,
|
||||
chart,
|
||||
} from '@/api/ticket';
|
||||
import { ticketStore } from './type';
|
||||
|
||||
@ -61,7 +62,7 @@ const useTicketStore = defineStore('ticket', {
|
||||
return update(data);
|
||||
},
|
||||
|
||||
async uploadFileTicket(file: any) {
|
||||
async uploadFile(file: any) {
|
||||
return uploadFile(file);
|
||||
},
|
||||
|
||||
@ -75,7 +76,11 @@ const useTicketStore = defineStore('ticket', {
|
||||
|
||||
async getHome(data: any){
|
||||
return home(data);
|
||||
}
|
||||
},
|
||||
|
||||
async getChart(){
|
||||
return chart();
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -10,10 +10,12 @@ import {
|
||||
enabled,
|
||||
remove,
|
||||
create,
|
||||
register,
|
||||
UserRecord,
|
||||
update,
|
||||
userDetail,
|
||||
deptAudit
|
||||
deptAudit,
|
||||
code
|
||||
} from '@/api/user';
|
||||
import { setToken, clearToken } from '@/utils/auth';
|
||||
import { removeRouteListener } from '@/utils/route-listener';
|
||||
@ -92,11 +94,16 @@ const useUserStore = defineStore('user', {
|
||||
return remove(id);
|
||||
},
|
||||
|
||||
// Register user
|
||||
// Create user
|
||||
async createUser(data: UserRecord) {
|
||||
return create(data);
|
||||
},
|
||||
|
||||
// register user
|
||||
async registerUser(data: UserRecord) {
|
||||
return register(data);
|
||||
},
|
||||
|
||||
// Update user
|
||||
async updateUser(data: UserRecord) {
|
||||
return update(data);
|
||||
@ -110,6 +117,10 @@ const useUserStore = defineStore('user', {
|
||||
return deptAudit(deptId,roleId)
|
||||
},
|
||||
|
||||
async getCode(params: string){
|
||||
return code(params)
|
||||
},
|
||||
|
||||
logoutCallBack() {
|
||||
const appStore = useAppStore();
|
||||
this.resetInfo();
|
||||
|
@ -26,6 +26,8 @@ export interface PostData {
|
||||
export interface Pagination {
|
||||
page: number;
|
||||
size: number;
|
||||
current: number;
|
||||
total: null | number;
|
||||
}
|
||||
|
||||
export type TimeRanger = [string, string];
|
||||
|
69
src/utils/excel.ts
Normal file
69
src/utils/excel.ts
Normal file
@ -0,0 +1,69 @@
|
||||
// 新建 @/utils/excel.ts
|
||||
|
||||
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类型
|
||||
|
||||
export interface DownloadExcelPrams {
|
||||
columns: { title: string, key: string }[];
|
||||
rows: object[];
|
||||
name: string
|
||||
}
|
||||
|
||||
// 导出下载文件
|
||||
export function downloadExcel({ columns, rows, name = '未命名文件' }: DownloadExcelPrams) {
|
||||
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
workbook.creator = 'Start-front';
|
||||
workbook.lastModifiedBy = 'Start-front';
|
||||
workbook.created = new Date(1985, 8, 30);
|
||||
workbook.modified = new Date();
|
||||
workbook.lastPrinted = new Date(2016, 9, 27);
|
||||
|
||||
// 将工作簿添加一个sheet页sheet1
|
||||
const sheet1 = workbook.addWorksheet(name);
|
||||
// 表头数据添加
|
||||
sheet1.columns = columns.map(item => ({
|
||||
header: item.title,
|
||||
key: item.key,
|
||||
width: 20
|
||||
}));
|
||||
// 表格内容添加
|
||||
rows.map(item => sheet1.addRow(item));
|
||||
workbook.xlsx.writeBuffer().then(buffer => {
|
||||
saveAs(
|
||||
new Blob([buffer], { type: 'application/octet-stream' }),
|
||||
`${name}.xlsx`
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// 读取文件为json格式
|
||||
export function readExcle(fileItem:FileItem) {
|
||||
console.log('读取文件...',fileItem);
|
||||
return new Promise((resove,reject)=>{
|
||||
try {
|
||||
let workbook:XLSX.Sheet;
|
||||
const reader = new FileReader();
|
||||
reader.readAsBinaryString(fileItem.file as File); // 发起异步请求
|
||||
reader.onload = function(ev){
|
||||
const data = ev.target?.result;
|
||||
workbook = XLSX.read(data, {type: 'binary'});
|
||||
const sheetNames = workbook.SheetNames; // 工作表名称集合
|
||||
sheetNames.forEach((name:string) => {
|
||||
const worksheet = workbook.Sheets[name]; // 只能通过工作表名称来获取指定工作表
|
||||
const jsonres = XLSX.utils.sheet_to_json(worksheet);
|
||||
resove(jsonres)
|
||||
});
|
||||
} // onload
|
||||
} catch (error) {
|
||||
Message.error('读取失败,请选择正确文件');
|
||||
reject(error);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
<template>
|
||||
<div style="width: 100%">
|
||||
<a-grid :cols="24" :row-gap="16" class="panel">
|
||||
<a-grid-item
|
||||
class="panel-col"
|
||||
@ -103,12 +104,19 @@
|
||||
<a-divider class="panel-border" />
|
||||
</a-grid-item>
|
||||
</a-grid>
|
||||
<a-card :bordered="false" v-if="userStore.permissions === 'admin'">
|
||||
<a-space id="TicketEcharts" style="width: 98%; height: 400px"></a-space>
|
||||
</a-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useTicketStore, useUserStore } from '@/store';
|
||||
import { ref } from 'vue';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
const { t } = useI18n();
|
||||
const ticketStore = useTicketStore();
|
||||
const userStore = useUserStore();
|
||||
const formData = ref({
|
||||
@ -118,6 +126,72 @@ 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);
|
||||
const option = {
|
||||
title: {
|
||||
text: t('workplace.chart'),
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
},
|
||||
legend: {
|
||||
data: [
|
||||
t('workplace.pass'),
|
||||
t('workplace.notPass'),
|
||||
t('workplace.notAudit'),
|
||||
],
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true,
|
||||
},
|
||||
toolbox: {
|
||||
feature: {
|
||||
saveAsImage: {},
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: res.data.dates,
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: t('workplace.pass'),
|
||||
type: 'line',
|
||||
data: res.data.status2Counts,
|
||||
},
|
||||
{
|
||||
name: t('workplace.notPass'),
|
||||
type: 'line',
|
||||
data: res.data.status3Counts,
|
||||
},
|
||||
{
|
||||
name: t('workplace.notAudit'),
|
||||
type: 'line',
|
||||
data: res.data.status1Counts,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
myChart.setOption(option);
|
||||
});
|
||||
|
||||
const getHomeData = async (params: {
|
||||
auditorId: number | undefined;
|
||||
userId: number | string | undefined;
|
||||
|
@ -40,4 +40,6 @@ export default {
|
||||
'workplace.notPass': 'notPass',
|
||||
'workplace.notAudit': 'notAudit',
|
||||
'workplace.notFiled': 'notFiled',
|
||||
'workplace.total': 'total',
|
||||
'workplace.chart':' Ticket Chart'
|
||||
};
|
||||
|
@ -38,4 +38,6 @@ export default {
|
||||
'workplace.notPass': '审核不通过',
|
||||
'workplace.notAudit': '待审核',
|
||||
'workplace.notFiled': '待提交',
|
||||
'workplace.total': '票据总数',
|
||||
'workplace.chart':'票据分析图'
|
||||
};
|
||||
|
@ -94,6 +94,40 @@
|
||||
:placeholder="$t('user.info.username.placeholder')"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item
|
||||
field="email"
|
||||
:label="$t('user.info.email')"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
type: 'email',
|
||||
message: t('user.info.email.required'),
|
||||
},
|
||||
]"
|
||||
:validate-trigger="['change', 'input']"
|
||||
>
|
||||
<a-input
|
||||
v-model="formData.email"
|
||||
:placeholder="$t('user.info.emailCode.placeholder')"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item
|
||||
field="phone"
|
||||
:label="$t('user.info.phone')"
|
||||
:rules="[
|
||||
{ required: true, message: t('user.info.phone.required') },
|
||||
{ match: /^1[3-9]\d{9}$/, message: t('user.info.phone.format') },
|
||||
]"
|
||||
:validate-trigger="['change', 'input']"
|
||||
>
|
||||
<a-input
|
||||
v-model="formData.phone"
|
||||
:placeholder="$t('user.info.phone.placeholder')"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item
|
||||
field="password"
|
||||
:label="$t('user.info.password')"
|
||||
@ -111,43 +145,37 @@
|
||||
:placeholder="$t('user.info.nickName.placeholder')"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
field="phone"
|
||||
:label="$t('user.info.phone')"
|
||||
:rules="[
|
||||
{ required: true, message: t('user.info.phone.required') },
|
||||
{ match: /^1[3-9]\d{9}$/, message: t('user.info.phone.format') },
|
||||
]"
|
||||
:validate-trigger="['change', 'input']"
|
||||
>
|
||||
<a-input
|
||||
v-model="formData.phone"
|
||||
:placeholder="$t('user.info.phone.placeholder')"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
field="email"
|
||||
:label="$t('user.info.email')"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
type: 'email',
|
||||
message: t('user.info.email.required'),
|
||||
},
|
||||
]"
|
||||
:validate-trigger="['change', 'input']"
|
||||
>
|
||||
<a-input
|
||||
v-model="formData.email"
|
||||
:placeholder="$t('user.info.email.placeholder')"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item field="address" :label="$t('user.info.address')">
|
||||
<a-input
|
||||
v-model="formData.address"
|
||||
:placeholder="$t('user.info.address.placeholder')"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
field="code"
|
||||
:label="$t('user.info.code')"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: t('user.info.code.required'),
|
||||
},
|
||||
]"
|
||||
:validate-trigger="['change', 'input']"
|
||||
>
|
||||
<a-input
|
||||
v-model="formData.code"
|
||||
:placeholder="$t('user.info.code.placeholder')"
|
||||
/>
|
||||
<a-button
|
||||
type="primary"
|
||||
style="margin-left: 50px; margin-right: 50px"
|
||||
@click="getCodeData"
|
||||
:disabled="flag"
|
||||
>发送验证码
|
||||
<div v-if="flag">({{ totalCount }}s)</div>
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</template>
|
||||
@ -179,19 +207,22 @@ const formData = ref<CreateRecord>({
|
||||
nickName: '',
|
||||
password: '',
|
||||
phone: '',
|
||||
email: '',
|
||||
email: '@qq.com',
|
||||
enabled: 'true',
|
||||
address: '',
|
||||
deptId: 235,
|
||||
roleId: undefined,
|
||||
permissionIds: [],
|
||||
authorities: [],
|
||||
code: '',
|
||||
});
|
||||
|
||||
const flag = ref(false);
|
||||
const totalCount = ref(60);
|
||||
const deptOptions = ref();
|
||||
const getDeptData = async () => {
|
||||
const res = await deptList();
|
||||
deptOptions.value = res.data;
|
||||
deptOptions.value = res.data.records;
|
||||
};
|
||||
|
||||
const loginConfig = useStorage('login-config', {
|
||||
@ -207,6 +238,7 @@ const userInfo = reactive({
|
||||
password: loginConfig.value.password,
|
||||
});
|
||||
|
||||
// 登录
|
||||
const handleSubmit = async ({
|
||||
// 处理表单提交的异步函数
|
||||
errors,
|
||||
@ -253,23 +285,53 @@ const handleSubmit = async ({
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 记住密码
|
||||
const setRememberPassword = (value: boolean) => {
|
||||
loginConfig.value.rememberPassword = value;
|
||||
};
|
||||
|
||||
// 打开弹窗
|
||||
const handleClick = () => {
|
||||
setVisible(true);
|
||||
};
|
||||
|
||||
// 关闭弹窗
|
||||
const handleCancel = async () => {
|
||||
userCreateRef.value?.resetFields();
|
||||
setVisible(false);
|
||||
};
|
||||
|
||||
// 获取验证码
|
||||
const getCodeData = async () => {
|
||||
if (formData.value.email === '') {
|
||||
Message.error({
|
||||
content: t('user.info.email.required'),
|
||||
duration: 5 * 1000,
|
||||
});
|
||||
} else {
|
||||
const res = await userStore.getCode(formData.value.email);
|
||||
if (res.status === 200) {
|
||||
flag.value = true;
|
||||
setInterval(() => {
|
||||
if (totalCount.value !== 0) {
|
||||
totalCount.value = totalCount.value * 1 - 1;
|
||||
}
|
||||
}, 1000);
|
||||
setTimeout(() => {
|
||||
flag.value = false;
|
||||
totalCount.value = 60;
|
||||
}, 60000);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 提交注册
|
||||
const handleOk = async () => {
|
||||
const valid = await userCreateRef.value?.validate();
|
||||
if (!valid) {
|
||||
const res = await userStore.createUser(formData.value);
|
||||
// formData.value.username = formData.value.email;
|
||||
const res = await userStore.registerUser(formData.value);
|
||||
if (res.status === 200) {
|
||||
Message.success({
|
||||
content: t('create.sucess'),
|
||||
|
@ -1,32 +1,24 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<div class="logo">
|
||||
<img
|
||||
alt="logo"
|
||||
src="//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/dfdba5317c0c20ce20e64fac803d52bc.svg~tplv-49unhts6dw-image.image"
|
||||
/>
|
||||
<div class="logo-text">Hello World!</div>
|
||||
<div class="logo-text">Hello Ticket!</div>
|
||||
</div>
|
||||
<LoginBanner />
|
||||
<div class="content">
|
||||
<div class="content-inner">
|
||||
<LoginForm />
|
||||
</div>
|
||||
<div class="footer">
|
||||
<Footer />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import Footer from '@/components/footer/index.vue';
|
||||
import LoginBanner from './components/banner.vue';
|
||||
import LoginForm from './components/login-form.vue';
|
||||
import LoginBanner from './components/banner.vue';
|
||||
import LoginForm from './components/login-form.vue';
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.container {
|
||||
.container {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
|
||||
@ -50,9 +42,9 @@
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.logo {
|
||||
.logo {
|
||||
position: fixed;
|
||||
top: 24px;
|
||||
left: 22px;
|
||||
@ -66,16 +58,16 @@
|
||||
color: var(--color-fill-1);
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less" scoped>
|
||||
// responsive
|
||||
@media (max-width: @screen-lg) {
|
||||
// responsive
|
||||
@media (max-width: @screen-lg) {
|
||||
.container {
|
||||
.banner {
|
||||
width: 25%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -1,11 +1,11 @@
|
||||
export default {
|
||||
'login.form.title': 'ZSC Learning Platform',
|
||||
'login.form.userName.errMsg': 'Username cannot be empty',
|
||||
'login.form.userName.errMsg': 'Username cannot be empty(Email)',
|
||||
'login.form.password.errMsg': 'Password cannot be empty',
|
||||
'login.form.login.errMsg': 'Login error, refresh and try again',
|
||||
'login.form.login.success': 'welcome to use',
|
||||
'login.form.userName.placeholder': 'Username: admin',
|
||||
'login.form.password.placeholder': 'Password: admin',
|
||||
'login.form.userName.placeholder': 'Username(Email)',
|
||||
'login.form.password.placeholder': 'Password',
|
||||
'login.form.rememberPassword': 'Remember password',
|
||||
'login.form.forgetPassword': 'Forgot password',
|
||||
'login.form.login': 'login',
|
||||
|
@ -1,6 +1,6 @@
|
||||
export default {
|
||||
'login.form.title': '中山学院学习平台',
|
||||
'login.form.userName.errMsg': '用户名不能为空',
|
||||
'login.form.title': '票据管理系统',
|
||||
'login.form.userName.errMsg': '账号不能为空',
|
||||
'login.form.password.errMsg': '密码不能为空',
|
||||
'login.form.login.errMsg': '登录出错,请刷新重试',
|
||||
'login.form.login.success': '欢迎使用',
|
||||
@ -10,11 +10,15 @@ export default {
|
||||
'login.form.forgetPassword': '忘记密码',
|
||||
'login.form.login': '登录',
|
||||
'login.form.register': '注册账号',
|
||||
'login.banner.slogan1': '开箱即用的高质量模板',
|
||||
'login.banner.subSlogan1': '丰富的的页面模板,覆盖大多数典型业务场景',
|
||||
'login.banner.slogan2': '内置了常见问题的解决方案',
|
||||
'login.banner.subSlogan2': '国际化,路由配置,状态管理应有尽有',
|
||||
'login.banner.slogan3': '接入可视化增强工具AUX',
|
||||
'login.banner.subSlogan3': '实现灵活的区块式开发',
|
||||
'create.user': '注册用户'
|
||||
|
||||
'login.banner.slogan1': '数据查询',
|
||||
'login.banner.subSlogan1': '用户可以通过关键词、条件组合等方式进行快速查询和检索',
|
||||
'login.banner.slogan2': '数据存储',
|
||||
'login.banner.subSlogan2': '系统具备强大的数据存储功能,能够将海量数据存储在数据库中',
|
||||
'login.banner.slogan3': '数据输出',
|
||||
'login.banner.subSlogan3': '系统可以将查询和分析结果以表格和图表导出',
|
||||
|
||||
'create.user': '注册用户',
|
||||
'user.info.emailCode.placeholder':'请输入Email(用于获取验证码)',
|
||||
'user.info.email.required':'Email不能为空',
|
||||
};
|
||||
|
@ -1,25 +1,26 @@
|
||||
<template>
|
||||
<a-button v-if="props.isCreate" type="primary" @click="handleClick">
|
||||
<template #icon><icon-plus /></template>
|
||||
{{ modalTitle }}
|
||||
{{ t('create') }}
|
||||
</a-button>
|
||||
<a-button
|
||||
v-if="!props.isCreate"
|
||||
type="outline"
|
||||
size="small"
|
||||
:style="{ marginRight: '10px' }"
|
||||
:style="{ marginRight: '10px', padding: '7px' }"
|
||||
@click="handleClick"
|
||||
>
|
||||
{{ modalTitle }}
|
||||
<template #icon><icon-edit /></template>
|
||||
{{ t('edit') }}
|
||||
</a-button>
|
||||
<a-modal
|
||||
width="600px"
|
||||
width="700px"
|
||||
:visible="visible"
|
||||
@ok="handleSubmit"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<template #title>{{ modalTitle }}</template>
|
||||
<a-form ref="createEditRef" :model="formData" :style="{ width: '500px' }">
|
||||
<a-form ref="createEditRef" :model="formData" :style="{ width: '650px' }">
|
||||
<a-form-item
|
||||
field="name"
|
||||
:label="$t('dept.info.name')"
|
||||
@ -35,6 +36,7 @@
|
||||
<a-textarea
|
||||
v-model="formData.remark"
|
||||
:placeholder="$t('dept.info.remark.placeholder')"
|
||||
style="height: 100px"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
@ -58,7 +60,7 @@ const props = defineProps({
|
||||
});
|
||||
const { t } = useI18n();
|
||||
const modalTitle = computed(() => {
|
||||
return props.isCreate ? t('create') : t('edit');
|
||||
return props.isCreate ? t('createDept') : t('editDept');
|
||||
});
|
||||
const { visible, setVisible } = useVisible(false);
|
||||
const deptStore = useDeptStore();
|
||||
|
@ -1,13 +1,13 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<Breadcrumb :items="['menu.system', 'menu.system.dept']" />
|
||||
<a-card class="general-card" :title="$t('menu.list.searchTable')">
|
||||
<a-card class="general-card" title=" ">
|
||||
<a-row>
|
||||
<a-col :flex="1">
|
||||
<a-form
|
||||
:model="formModel"
|
||||
:label-col-props="{ span: 6 }"
|
||||
:wrapper-col-props="{ span: 18 }"
|
||||
:wrapper-col-props="{ span: 12 }"
|
||||
label-align="right"
|
||||
>
|
||||
<a-row :gutter="16">
|
||||
@ -118,6 +118,8 @@
|
||||
:data="renderData"
|
||||
:bordered="false"
|
||||
:size="size"
|
||||
:pagination="false"
|
||||
style="margin-bottom: 40px"
|
||||
>
|
||||
<template #index="{ rowIndex }">
|
||||
{{ rowIndex + 1 }}
|
||||
@ -146,12 +148,28 @@
|
||||
type="error"
|
||||
@ok="handleDelete(record)"
|
||||
>
|
||||
<a-button type="primary" size="small" status="danger">
|
||||
<a-button
|
||||
type="primary"
|
||||
size="small"
|
||||
status="danger"
|
||||
style="padding: 7px"
|
||||
>
|
||||
<template #icon><icon-delete /></template>
|
||||
{{ $t('delete') }}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
</template>
|
||||
</a-table>
|
||||
<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
|
||||
/>
|
||||
</a-card>
|
||||
</div>
|
||||
</template>
|
||||
@ -161,6 +179,7 @@ import { computed, ref, watch } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import useTableOption from '@/hooks/table-option';
|
||||
import { Pagination } from '@/types/global';
|
||||
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
|
||||
import dayjs from 'dayjs';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
@ -187,6 +206,12 @@ const generateFormModel = () => {
|
||||
code: '',
|
||||
};
|
||||
};
|
||||
const pagination: Pagination = {
|
||||
page: 1,
|
||||
size: 10,
|
||||
current: 1,
|
||||
total: 10,
|
||||
};
|
||||
|
||||
const { t } = useI18n();
|
||||
const renderData = ref<DeptRecord[]>([]);
|
||||
@ -202,10 +227,16 @@ const columns = computed<TableColumnData[]>(() => [
|
||||
{
|
||||
title: t('deptTable.columns.name'),
|
||||
dataIndex: 'name',
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('deptTable.columns.id'),
|
||||
dataIndex: 'id',
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('deptTable.columns.remark'),
|
||||
@ -215,6 +246,9 @@ const columns = computed<TableColumnData[]>(() => [
|
||||
title: t('deptTable.columns.createTime'),
|
||||
dataIndex: 'createTime',
|
||||
slotName: 'createTime',
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('deptTable.columns.enabled'),
|
||||
@ -233,8 +267,11 @@ const fetchData = async (params?: Partial<DeptRecord>) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const res = await deptStore.getDeptList(params);
|
||||
const { data } = res;
|
||||
renderData.value = data;
|
||||
|
||||
renderData.value = res.data.records;
|
||||
pagination.page = res.data.page;
|
||||
pagination.current = res.data.current;
|
||||
pagination.total = res.data.total;
|
||||
} catch (err) {
|
||||
// you can report use errorHandler or other
|
||||
} finally {
|
||||
@ -245,12 +282,26 @@ const fetchData = async (params?: Partial<DeptRecord>) => {
|
||||
// 查询
|
||||
const search = () => {
|
||||
fetchData({
|
||||
...pagination,
|
||||
...formModel.value,
|
||||
});
|
||||
} as unknown as any);
|
||||
};
|
||||
|
||||
search();
|
||||
|
||||
// 分页发生改变
|
||||
const onPageChange = (current: number) => {
|
||||
pagination.page = current;
|
||||
pagination.current = current;
|
||||
search();
|
||||
};
|
||||
|
||||
// 数据条数改变
|
||||
const onSizeChange = (size: number) => {
|
||||
pagination.size = size;
|
||||
search();
|
||||
};
|
||||
|
||||
// 重置
|
||||
const reset = () => {
|
||||
formModel.value = generateFormModel();
|
||||
|
@ -21,5 +21,9 @@ export default {
|
||||
'dept.info.remark': 'Remark',
|
||||
'dept.info.remark.placeholder': 'Please enter Remark',
|
||||
|
||||
'Confirm the deletion of this department' :'Confirm the deletion of this department?'
|
||||
'Confirm the deletion of this department' :'Confirm the deletion of this department?',
|
||||
|
||||
// modalTitle
|
||||
'createDept': 'Create Dept',
|
||||
'editDept': 'Edit Dept Info'
|
||||
};
|
||||
|
@ -5,8 +5,8 @@ export default {
|
||||
'searchTable.form.deptName.placeholder': '请输入部门名称',
|
||||
|
||||
'deptTable.columns.index': '序号',
|
||||
'deptTable.columns.name': '区域名称',
|
||||
'deptTable.columns.id': '区域ID',
|
||||
'deptTable.columns.name': '部门名称',
|
||||
'deptTable.columns.id': '部门ID',
|
||||
'deptTable.columns.remark': '备注',
|
||||
'deptTable.columns.enabled': '是否启用',
|
||||
'deptTable.columns.createTime': '创建时间',
|
||||
@ -21,5 +21,10 @@ export default {
|
||||
'dept.info.remark': '备注',
|
||||
'dept.info.remark.placeholder': '请输入备注',
|
||||
|
||||
'Confirm the deletion of this department' :'确认删除此部门?'
|
||||
'Confirm the deletion of this department' :'确认删除此部门?',
|
||||
|
||||
|
||||
// modalTitle
|
||||
'createDept': '新增部门',
|
||||
'editDept': '修改部门信息'
|
||||
};
|
||||
|
@ -1,25 +1,26 @@
|
||||
<template>
|
||||
<a-button v-if="props.isCreate" type="primary" @click="handleClick">
|
||||
<template #icon><icon-plus /></template>
|
||||
{{ modalTitle }}
|
||||
{{ t('create') }}
|
||||
</a-button>
|
||||
<a-button
|
||||
v-if="!props.isCreate"
|
||||
type="outline"
|
||||
size="small"
|
||||
:style="{ marginRight: '10px' }"
|
||||
:style="{ marginRight: '10px', padding: '7px' }"
|
||||
@click="handleClick"
|
||||
>
|
||||
{{ modalTitle }}
|
||||
<template #icon><icon-edit /></template>
|
||||
{{ t('edit') }}
|
||||
</a-button>
|
||||
<a-modal
|
||||
width="600px"
|
||||
width="700px"
|
||||
:visible="visible"
|
||||
@ok="handleSubmit"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<template #title>{{ modalTitle }}</template>
|
||||
<a-form ref="createEditRef" :model="formData" :style="{ width: '500px' }">
|
||||
<a-form ref="createEditRef" :model="formData" :style="{ width: '650px' }">
|
||||
<a-form-item
|
||||
field="name"
|
||||
:label="$t('role.info.name')"
|
||||
@ -35,7 +36,9 @@
|
||||
<a-form-item field="remark" :label="$t('role.info.remark')">
|
||||
<a-textarea
|
||||
v-model="formData.remark"
|
||||
:show-word-limit="true"
|
||||
:placeholder="$t('role.info.remark.placeholder')"
|
||||
style="height: 100px"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
@ -60,7 +63,7 @@ const props = defineProps({
|
||||
});
|
||||
const { t } = useI18n();
|
||||
const modalTitle = computed(() => {
|
||||
return props.isCreate ? t('create') : t('edit');
|
||||
return props.isCreate ? t('createRole') : t('editRole');
|
||||
});
|
||||
const { visible, setVisible } = useVisible(false);
|
||||
const createEditRef = ref<FormInstance>();
|
||||
|
@ -1,7 +1,46 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<Breadcrumb :items="['menu.system', 'menu.system.role']" />
|
||||
<a-card class="general-card" :title="$t('menu.role.list')">
|
||||
<a-card class="general-card" title=" ">
|
||||
<a-row>
|
||||
<a-col :flex="1">
|
||||
<a-form
|
||||
:model="formModel"
|
||||
:label-col-props="{ span: 6 }"
|
||||
:wrapper-col-props="{ span: 12 }"
|
||||
label-align="right"
|
||||
>
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item field="title" :label="$t('searchTable.form.name')">
|
||||
<a-input
|
||||
v-model="formModel.name"
|
||||
:placeholder="$t('searchTable.form.name.placeholder')"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-col>
|
||||
<a-divider style="height: 42px" direction="vertical" />
|
||||
<a-col :flex="'46px'" style="text-align: right">
|
||||
<a-space :size="18">
|
||||
<a-button type="primary" @click="search">
|
||||
<template #icon>
|
||||
<icon-search />
|
||||
</template>
|
||||
{{ $t('searchTable.form.search') }}
|
||||
</a-button>
|
||||
<a-button @click="reset">
|
||||
<template #icon>
|
||||
<icon-refresh />
|
||||
</template>
|
||||
{{ $t('searchTable.form.reset') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-divider style="margin-top: 10px" />
|
||||
<a-row style="margin-bottom: 16px">
|
||||
<a-col :span="12">
|
||||
<a-space>
|
||||
@ -77,6 +116,7 @@
|
||||
:bordered="false"
|
||||
:size="size"
|
||||
@page-change="onPageChange"
|
||||
style="margin-bottom: 40px"
|
||||
>
|
||||
<template #index="{ rowIndex }">
|
||||
{{ rowIndex + 1 }}
|
||||
@ -105,12 +145,28 @@
|
||||
type="error"
|
||||
@ok="handleDelete(record)"
|
||||
>
|
||||
<a-button type="primary" size="small" status="danger">
|
||||
<a-button
|
||||
type="primary"
|
||||
size="small"
|
||||
status="danger"
|
||||
style="padding: 7px"
|
||||
>
|
||||
<template #icon><icon-delete /></template>
|
||||
{{ $t('delete') }}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
</template>
|
||||
</a-table>
|
||||
<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
|
||||
/>
|
||||
</a-card>
|
||||
</div>
|
||||
</template>
|
||||
@ -119,6 +175,7 @@
|
||||
import { computed, ref, reactive, watch, nextTick } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { Pagination } from '@/types/global';
|
||||
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import useTableOption from '@/hooks/table-option';
|
||||
@ -143,6 +200,19 @@ const {
|
||||
deepClone,
|
||||
} = useTableOption();
|
||||
const roleStore = useRoleStore();
|
||||
const generateFormModel = () => {
|
||||
return {
|
||||
name: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
const formModel = ref(generateFormModel());
|
||||
const pagination: Pagination = {
|
||||
page: 1,
|
||||
size: 10,
|
||||
current: 1,
|
||||
total: 10,
|
||||
};
|
||||
|
||||
// 表格头部
|
||||
const columns = computed<TableColumnData[]>(() => [
|
||||
@ -154,19 +224,21 @@ const columns = computed<TableColumnData[]>(() => [
|
||||
{
|
||||
title: t('roleTable.columns.name'),
|
||||
dataIndex: 'name',
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('roleTable.columns.remark'),
|
||||
dataIndex: 'remark',
|
||||
},
|
||||
// {
|
||||
// title: t('roleTable.columns.authorities'),
|
||||
// dataIndex: 'authorities',
|
||||
// },
|
||||
{
|
||||
title: t('roleTable.columns.createTime'),
|
||||
dataIndex: 'createTime',
|
||||
slotName: 'createTime',
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('roleTable.columns.enabled'),
|
||||
@ -181,11 +253,15 @@ const columns = computed<TableColumnData[]>(() => [
|
||||
]);
|
||||
|
||||
// 获取表格数据
|
||||
const fetchData = async () => {
|
||||
const fetchData = async (params: any) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const res = await roleStore.getRoleList();
|
||||
renderData.value = res.data;
|
||||
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;
|
||||
pagination.total = res.data.total;
|
||||
} catch (err) {
|
||||
// you can report use errorHandler or other
|
||||
} finally {
|
||||
@ -193,7 +269,33 @@ const fetchData = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
fetchData();
|
||||
// 模糊查询
|
||||
const search = () => {
|
||||
fetchData({
|
||||
...pagination,
|
||||
...formModel.value,
|
||||
} as unknown as any);
|
||||
};
|
||||
|
||||
search();
|
||||
|
||||
// 分页发生改变
|
||||
const onPageChange = (current: number) => {
|
||||
pagination.page = current;
|
||||
pagination.current = current;
|
||||
search();
|
||||
};
|
||||
|
||||
// 数据条数改变
|
||||
const onSizeChange = (size: number) => {
|
||||
pagination.size = size;
|
||||
search();
|
||||
};
|
||||
|
||||
// 重置
|
||||
const reset = () => {
|
||||
formModel.value = generateFormModel();
|
||||
};
|
||||
|
||||
// 是否启用
|
||||
const enabledStatus = async (record: string) => {
|
||||
@ -220,7 +322,7 @@ const handleDelete = async (record: RoleRecord) => {
|
||||
content: t('delete.role.sucess'),
|
||||
duration: 5 * 1000,
|
||||
});
|
||||
fetchData();
|
||||
search();
|
||||
} else {
|
||||
Message.error({
|
||||
content: t('delete.role.fail'),
|
||||
|
@ -14,6 +14,9 @@ export default {
|
||||
'delete.role.sucess': 'Delete Role Sucess',
|
||||
'delete.role.fail': 'Delete Role Fail',
|
||||
|
||||
'searchTable.form.name':'Name',
|
||||
'searchTable.form.name.placeholder':'Please enter Name',
|
||||
|
||||
'role.info.name': 'Name',
|
||||
'role.info.name.placeholder': 'Please enter Name',
|
||||
'role.info.name.required': 'Name is required',
|
||||
@ -27,4 +30,9 @@ export default {
|
||||
|
||||
'modify.status.sucess':'Modify status sucess',
|
||||
'modify.status.fail':'Modify status fail',
|
||||
|
||||
|
||||
// modalTitle
|
||||
'createRole': 'Create Role',
|
||||
'editRole': 'Edit Role Info',
|
||||
};
|
||||
|
@ -14,6 +14,9 @@ export default {
|
||||
'delete.role.sucess': '删除角色成功',
|
||||
'delete.role.fail': '删除角色失败',
|
||||
|
||||
'searchTable.form.name':'角色名称',
|
||||
'searchTable.form.name.placeholder':'请输入角色名称',
|
||||
|
||||
'role.info.name': '角色名称',
|
||||
'role.info.name.placeholder': '请输入角色名称',
|
||||
'role.info.name.required': '角色不能为空',
|
||||
@ -27,4 +30,9 @@ export default {
|
||||
|
||||
'modify.status.sucess':'修改状态成功',
|
||||
'modify.status.fail':'修改状态失败',
|
||||
|
||||
|
||||
// modalTitle
|
||||
'createRole': '新增角色',
|
||||
'editRole': '修改角色信息'
|
||||
};
|
||||
|
@ -1,26 +1,27 @@
|
||||
<template>
|
||||
<a-button v-if="props.isCreate" type="primary" @click="handleClick">
|
||||
<template #icon><icon-plus /></template>
|
||||
{{ modalTitle }}
|
||||
{{ t('create') }}
|
||||
</a-button>
|
||||
<a-button
|
||||
v-if="!props.isCreate"
|
||||
type="outline"
|
||||
size="small"
|
||||
:style="{ marginRight: '10px' }"
|
||||
:style="{ marginRight: '10px', padding: '7px' }"
|
||||
@click="handleClick"
|
||||
>
|
||||
{{ modalTitle }}
|
||||
<template #icon><icon-edit /></template>
|
||||
{{ t('edit') }}
|
||||
</a-button>
|
||||
|
||||
<a-modal
|
||||
width="600px"
|
||||
width="700px"
|
||||
:visible="visible"
|
||||
@ok="handleSubmit"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<template #title>{{ modalTitle }}</template>
|
||||
<a-form ref="CreateRef" :model="formData" :style="{ width: '500px' }">
|
||||
<a-form ref="CreateRef" :model="formData" :style="{ width: '650px' }">
|
||||
<a-form-item
|
||||
field="username"
|
||||
:label="$t('user.info.username')"
|
||||
@ -42,21 +43,20 @@
|
||||
<div v-else>{{ formData.username }}</div>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
field="password"
|
||||
:label="$t('user.info.password')"
|
||||
v-if="isCreate"
|
||||
field="email"
|
||||
:label="$t('user.info.email')"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
type: 'email',
|
||||
message: t('user.info.email.required'),
|
||||
},
|
||||
]"
|
||||
:validate-trigger="['change', 'input']"
|
||||
:rules="[{ required: true, message: t('user.info.password.required') }]"
|
||||
>
|
||||
<a-input
|
||||
v-model="formData.password"
|
||||
:placeholder="$t('user.info.password.placeholder')"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item field="nickName" :label="$t('user.info.nickName')">
|
||||
<a-input
|
||||
v-model="formData.nickName"
|
||||
:placeholder="$t('user.info.nickName.placeholder')"
|
||||
v-model="formData.email"
|
||||
:placeholder="$t('user.info.email.placeholder')"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
@ -74,22 +74,24 @@
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
field="email"
|
||||
:label="$t('user.info.email')"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
type: 'email',
|
||||
message: t('user.info.email.required'),
|
||||
},
|
||||
]"
|
||||
field="password"
|
||||
:label="$t('user.info.password')"
|
||||
v-if="isCreate"
|
||||
:validate-trigger="['change', 'input']"
|
||||
:rules="[{ required: true, message: t('user.info.password.required') }]"
|
||||
>
|
||||
<a-input
|
||||
v-model="formData.email"
|
||||
:placeholder="$t('user.info.email.placeholder')"
|
||||
v-model="formData.password"
|
||||
:placeholder="$t('user.info.password.placeholder')"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item field="nickName" :label="$t('user.info.nickName')">
|
||||
<a-input
|
||||
v-model="formData.nickName"
|
||||
:placeholder="$t('user.info.nickName.placeholder')"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item field="address" :label="$t('user.info.address')">
|
||||
<a-input
|
||||
v-model="formData.address"
|
||||
@ -139,11 +141,10 @@
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import useVisible from '@/hooks/visible';
|
||||
import { computed, PropType, ref } from 'vue';
|
||||
import { CreateRecord, UserRecord } from '@/api/user';
|
||||
import { CreateRecord } from '@/api/user';
|
||||
import { FormInstance } from '@arco-design/web-vue/es/form';
|
||||
import { queryRoleList } from '@/api/role';
|
||||
import { deptList } from '@/api/dept';
|
||||
import { computedAsync } from '@vueuse/core';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { useUserStore } from '@/store';
|
||||
|
||||
@ -155,7 +156,7 @@ const props = defineProps({
|
||||
});
|
||||
const { t } = useI18n();
|
||||
const modalTitle = computed(() => {
|
||||
return props.isCreate ? t('create') : t('edit');
|
||||
return props.isCreate ? t('createUser') : t('editUser');
|
||||
});
|
||||
const { visible, setVisible } = useVisible(false);
|
||||
const checkKeys = ref<number[]>([]);
|
||||
@ -180,32 +181,16 @@ let formDifer = {};
|
||||
const userStore = useUserStore();
|
||||
|
||||
// 部门数据
|
||||
// const deptOptions = computedAsync(async () => {
|
||||
// const { data } = await deptList();
|
||||
// const deptData = data.filter((item: any) => {
|
||||
// return item.enabled !== false;
|
||||
// });
|
||||
// return deptData;
|
||||
// });
|
||||
|
||||
const deptOptions = ref();
|
||||
const getDeptData = async () => {
|
||||
const res = await deptList();
|
||||
deptOptions.value = res.data;
|
||||
deptOptions.value = res.data.records;
|
||||
};
|
||||
// 角色数据
|
||||
// const roleOptions = computedAsync(async () => {
|
||||
// const res = await queryRoleList();
|
||||
// const roleData = res.data.filter((item: any) => {
|
||||
// return item.enabled !== false;
|
||||
// });
|
||||
// return roleData;
|
||||
// });
|
||||
|
||||
const roleOptions = ref();
|
||||
const getRoleData = async () => {
|
||||
const res = await queryRoleList();
|
||||
roleOptions.value = res.data.filter((item: any) => {
|
||||
const res = await queryRoleList('');
|
||||
roleOptions.value = res.data.records.filter((item: any) => {
|
||||
return item.enabled !== false;
|
||||
});
|
||||
};
|
||||
@ -215,7 +200,6 @@ const handleClick = () => {
|
||||
getDeptData();
|
||||
getRoleData();
|
||||
const userId = props.prem?.id;
|
||||
|
||||
// 编辑
|
||||
if (!props.isCreate && userId) {
|
||||
formData.value = props.prem;
|
||||
@ -242,6 +226,7 @@ const handleSubmit = async () => {
|
||||
formData.value.permissionIds = checkKeys.value;
|
||||
// 新增
|
||||
if (props.isCreate) {
|
||||
// formData.value.username = formData.value.email;
|
||||
const res = await userStore.createUser(formData.value);
|
||||
if (res.status === 200) {
|
||||
Message.success({
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<Breadcrumb :items="['menu.system', 'menu.system.user']" />
|
||||
<a-card class="general-card" :title="$t('menu.list.searchTable')">
|
||||
<a-card class="general-card" title=" ">
|
||||
<a-row>
|
||||
<a-col :flex="1">
|
||||
<a-form
|
||||
@ -80,15 +80,26 @@
|
||||
</a-row>
|
||||
|
||||
<a-divider style="margin-top: 0" />
|
||||
<a-row style="margin-bottom: 16px">
|
||||
<a-row>
|
||||
<a-col :span="12">
|
||||
<a-space>
|
||||
<UserEdit ref="createUserRef" :is-create="true" @refresh="search" />
|
||||
</a-space>
|
||||
<a-button @click="generateExcel" style="margin-left: 20px">
|
||||
<template #icon>
|
||||
<icon-download size="18" />
|
||||
</template>
|
||||
{{ $t('searchTable.operation.download') }}
|
||||
</a-button>
|
||||
</a-col>
|
||||
<a-col
|
||||
:span="12"
|
||||
style="display: flex; align-items: center; justify-content: end"
|
||||
style="
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: end;
|
||||
padding-bottom: 20px;
|
||||
"
|
||||
>
|
||||
<a-tooltip :content="$t('searchTable.actions.refresh')">
|
||||
<div class="action-icon" @click="search">
|
||||
@ -152,12 +163,15 @@
|
||||
<a-table
|
||||
row-key="id"
|
||||
:loading="loading"
|
||||
:pagination="pagination"
|
||||
:pagination="false"
|
||||
:columns="(cloneColumns as TableColumnData[])"
|
||||
:data="renderData"
|
||||
:bordered="false"
|
||||
:size="size"
|
||||
@page-change="onPageChange"
|
||||
style="margin-bottom: 40px"
|
||||
:filter-icon-align-left="alignLeft"
|
||||
@change="handleSortChange"
|
||||
>
|
||||
<template #index="{ rowIndex }">
|
||||
{{ rowIndex + 1 + (pagination.current - 1) * pagination.size }}
|
||||
@ -177,12 +191,12 @@
|
||||
:is-create="false"
|
||||
@refresh="fetchData"
|
||||
/>
|
||||
<!-- <Userc
|
||||
<Userc
|
||||
ref="editUserRef"
|
||||
:user="record"
|
||||
:is-create="false"
|
||||
@refresh="search"
|
||||
/> -->
|
||||
/>
|
||||
<!-- <a-popconfirm
|
||||
content="确认删除此用户?"
|
||||
type="error"
|
||||
@ -194,22 +208,31 @@
|
||||
</a-popconfirm> -->
|
||||
</template>
|
||||
</a-table>
|
||||
<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
|
||||
/>
|
||||
</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 { UserRecord, UserParams } from '@/api/user';
|
||||
import { Pagination } from '@/types/global';
|
||||
import type { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
|
||||
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import Sortable from 'sortablejs';
|
||||
import { useUserStore } from '@/store';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { downloadExcel, DownloadExcelPrams } from '@/utils/excel';
|
||||
import useTableOption from '@/hooks/table-option';
|
||||
import UserEdit from './components/user-edit.vue';
|
||||
|
||||
@ -245,13 +268,12 @@ const {
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
const basePagination: Pagination = {
|
||||
const pagination: Pagination = {
|
||||
page: 1,
|
||||
size: 10,
|
||||
current: 1,
|
||||
total: null,
|
||||
};
|
||||
const pagination = reactive({
|
||||
...basePagination,
|
||||
});
|
||||
|
||||
const columns = computed<TableColumnData[]>(() => [
|
||||
{
|
||||
@ -263,18 +285,30 @@ const columns = computed<TableColumnData[]>(() => [
|
||||
{
|
||||
title: t('userTable.columns.username'),
|
||||
dataIndex: 'username',
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('userTable.columns.phone'),
|
||||
dataIndex: 'phone',
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('userTable.columns.email'),
|
||||
dataIndex: 'email',
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('userTable.columns.nickName'),
|
||||
dataIndex: 'nickName',
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('userTable.columns.address'),
|
||||
@ -311,9 +345,10 @@ const fetchData = async (
|
||||
try {
|
||||
const res = await userStore.getUserList(params);
|
||||
renderData.value = res.data.records;
|
||||
pagination.page = res.data.page;
|
||||
pagination.current = res.data.current;
|
||||
pagination.total = res.data.total;
|
||||
// pagination.size = data.size;
|
||||
pagination.size = res.data.size;
|
||||
} catch (err) {
|
||||
// you can report use errorHandler or other
|
||||
} finally {
|
||||
@ -321,26 +356,58 @@ const fetchData = async (
|
||||
}
|
||||
};
|
||||
|
||||
// 下载表格
|
||||
const generateExcel = () => {
|
||||
const param: DownloadExcelPrams = {
|
||||
columns: [
|
||||
{ title: '用户名', key: 'username' },
|
||||
{ title: '昵称', key: 'nickName' },
|
||||
{ title: '电话号码', key: 'phone' },
|
||||
{ title: '部门Id', key: 'deptId' },
|
||||
{ title: '角色Id', key: 'roleId' },
|
||||
{ title: 'email', key: 'email' },
|
||||
{ title: '启用状态', key: 'enabled' },
|
||||
],
|
||||
rows: renderData.value,
|
||||
name: '用户表格',
|
||||
};
|
||||
downloadExcel(param);
|
||||
};
|
||||
|
||||
// 查询
|
||||
const search = () => {
|
||||
fetchData({
|
||||
...basePagination,
|
||||
...pagination,
|
||||
...formModel.value,
|
||||
} as unknown as UserParams);
|
||||
};
|
||||
|
||||
// 分页
|
||||
// 分页发生改变
|
||||
const onPageChange = (current: number) => {
|
||||
fetchData({ ...basePagination, current });
|
||||
pagination.page = current;
|
||||
pagination.current = current;
|
||||
search();
|
||||
};
|
||||
|
||||
fetchData();
|
||||
// 数据条数改变
|
||||
const onSizeChange = (size: number) => {
|
||||
pagination.size = size;
|
||||
search();
|
||||
};
|
||||
|
||||
search();
|
||||
|
||||
// 重置
|
||||
const reset = () => {
|
||||
formModel.value = generateFormModel();
|
||||
};
|
||||
|
||||
// 表格内部排序
|
||||
const alignLeft = ref(false);
|
||||
const handleSortChange = (data: any, extra: any, currentDataSource: any) => {
|
||||
console.log('change', data, extra, currentDataSource);
|
||||
};
|
||||
|
||||
// 是否启用
|
||||
const enabledStatus = async (record: string) => {
|
||||
record.enabled = !record.enabled;
|
||||
|
@ -65,4 +65,8 @@ export default {
|
||||
'user.info.role.placeholder': 'Please select Role',
|
||||
'user.info.role.required': 'Role is required',
|
||||
|
||||
|
||||
// modalTitle
|
||||
'createUser': 'Create User',
|
||||
'editUser': 'Edit User Info'
|
||||
};
|
||||
|
@ -16,7 +16,7 @@ export default {
|
||||
'searchTable.form.selectDefault': '全部',
|
||||
'searchTable.operation.create': '新建',
|
||||
'searchTable.operation.import': '批量导入',
|
||||
'searchTable.operation.download': '下载',
|
||||
'searchTable.operation.download': '导出',
|
||||
// columns
|
||||
'userTable.columns.index': '序号',
|
||||
'userTable.columns.nickName': '昵称',
|
||||
@ -64,5 +64,10 @@ export default {
|
||||
'user.info.role':'角色',
|
||||
'user.info.role.placeholder': '请选择角色',
|
||||
'user.info.role.required': '请选择一个',
|
||||
'user.info.code':'验证码',
|
||||
'user.info.code.placeholder':'请输入验证码',
|
||||
|
||||
// modalTitle
|
||||
'createUser': '新增用户',
|
||||
'editUser': '修改用户信息'
|
||||
}
|
@ -1,33 +1,36 @@
|
||||
<template>
|
||||
<!-- 新增 -->
|
||||
<a-button
|
||||
v-permission="['BILL_QUERY']"
|
||||
v-if="props.isCreate"
|
||||
type="primary"
|
||||
size="small"
|
||||
:style="{ marginRight: '10px' }"
|
||||
@click="handleClick"
|
||||
>
|
||||
<template #icon><icon-plus /></template>
|
||||
{{ modalTitle }}
|
||||
</a-button>
|
||||
|
||||
<!-- 修改 -->
|
||||
<a-button
|
||||
v-permission="['BILL_UPDATE']"
|
||||
v-if="!props.isCreate"
|
||||
size="small"
|
||||
type="primary"
|
||||
:style="{ marginRight: '10px' }"
|
||||
:style="{ marginRight: '10px', padding: '7px' }"
|
||||
@click="handleClick"
|
||||
>
|
||||
<template #icon><icon-edit /></template>
|
||||
{{ modalTitle }}
|
||||
</a-button>
|
||||
<a-modal
|
||||
width="600px"
|
||||
width="700px"
|
||||
:visible="visible"
|
||||
:footer="false"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<template #title>{{ modalTitle }}</template>
|
||||
<a-form ref="createEditRef" :model="formData" :style="{ width: '500px' }">
|
||||
<a-form ref="createEditRef" :model="formData" :style="{ width: '650px' }">
|
||||
<a-form-item
|
||||
field="companyName"
|
||||
:label="$t('ticket.info.companyName')"
|
||||
@ -54,18 +57,6 @@
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<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')"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item
|
||||
field="money"
|
||||
:label="$t('ticket.info.money')"
|
||||
@ -105,16 +96,6 @@
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item field="attachment" :label="$t('ticket.info.attachment')">
|
||||
<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="$t('ticket.info.dept')"
|
||||
@ -159,6 +140,29 @@
|
||||
>
|
||||
{{ formData.comment }}
|
||||
</a-form-item>
|
||||
|
||||
<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-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">
|
||||
{{ $t('cancel') }}</a-button
|
||||
@ -182,10 +186,9 @@
|
||||
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 { FileItem, Message } from '@arco-design/web-vue';
|
||||
import { useTicketStore, useUserStore, useRoleStore } from '@/store';
|
||||
import { TicketRecord } from '@/api/ticket';
|
||||
import { deptList } from '@/api/dept';
|
||||
@ -216,7 +219,7 @@ const formData = ref<TicketRecord>({
|
||||
type: '',
|
||||
contactEmail: '',
|
||||
companyName: '',
|
||||
attachId: '',
|
||||
attachId: [],
|
||||
auditorId: '',
|
||||
userId: undefined,
|
||||
submit: '',
|
||||
@ -228,7 +231,7 @@ const emit = defineEmits(['refresh']);
|
||||
const deptOptions = ref();
|
||||
const getDeptData = async () => {
|
||||
const res = await deptList();
|
||||
deptOptions.value = res.data;
|
||||
deptOptions.value = res.data.records;
|
||||
};
|
||||
|
||||
const typesOptions = computed<SelectOptionData[]>(() => [
|
||||
@ -250,8 +253,8 @@ let auiditRoleId = '';
|
||||
|
||||
// 获取审核员ID
|
||||
const getRoleId = async () => {
|
||||
const res = await roleStore.getRoleList();
|
||||
res.data.forEach((item: any) => {
|
||||
const res = await roleStore.getRoleList('');
|
||||
res.data.records.forEach((item: any) => {
|
||||
if (item.name === 'auditor') {
|
||||
auiditRoleId = item.id;
|
||||
}
|
||||
@ -277,12 +280,13 @@ const optionDept = async (flag: boolean) => {
|
||||
|
||||
let formDifer = {};
|
||||
const fileList = ref([]);
|
||||
const attachList = ref([]);
|
||||
|
||||
// 上传附件
|
||||
const Onchange = async (option: any) => {
|
||||
const FormDatas = new FormData();
|
||||
FormDatas.append('file', option.fileItem.file);
|
||||
const res = await ticketStore.uploadFileTicket(FormDatas);
|
||||
const res = await ticketStore.uploadFile(FormDatas);
|
||||
if (res.status === 200) {
|
||||
Message.success({
|
||||
content: t('upload.sucess'),
|
||||
@ -290,7 +294,10 @@ const Onchange = async (option: any) => {
|
||||
});
|
||||
res.data.name = res.data.fileName;
|
||||
fileList.value.push(res.data);
|
||||
formData.value.attachId = res.data.id;
|
||||
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'),
|
||||
@ -300,8 +307,13 @@ const Onchange = async (option: any) => {
|
||||
};
|
||||
|
||||
// 删除附件
|
||||
const removeAttact = () => {
|
||||
fileList.value.pop();
|
||||
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);
|
||||
};
|
||||
|
||||
// 组件被点击时
|
||||
@ -317,12 +329,13 @@ const handleClick = () => {
|
||||
// 票据数据
|
||||
formData.value = res.data;
|
||||
|
||||
// 附件内容
|
||||
if (formData.value.attachId) {
|
||||
const data = await ticketStore.getAttachment(formData.value.attachId);
|
||||
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);
|
||||
}
|
||||
});
|
||||
attachList.value = formData.value.attachId;
|
||||
// 审核员信息
|
||||
const auditInfo = await userStore.getUserDetail(
|
||||
formData.value.auditorId
|
||||
@ -389,7 +402,7 @@ const handleOk = async () => {
|
||||
}
|
||||
}
|
||||
createEditRef.value?.resetFields();
|
||||
removeAttact();
|
||||
attachList.value = [];
|
||||
emit('refresh');
|
||||
setVisible(false);
|
||||
}
|
||||
@ -430,7 +443,8 @@ const handleStorage = async () => {
|
||||
}
|
||||
}
|
||||
createEditRef.value?.resetFields();
|
||||
removeAttact();
|
||||
attachList.value = [];
|
||||
fileList.value = [];
|
||||
emit('refresh');
|
||||
setVisible(false);
|
||||
}
|
||||
@ -438,7 +452,8 @@ const handleStorage = async () => {
|
||||
|
||||
// 关闭
|
||||
const handleCancel = async () => {
|
||||
removeAttact();
|
||||
attachList.value = [];
|
||||
fileList.value = [];
|
||||
createEditRef.value?.resetFields();
|
||||
setVisible(false);
|
||||
};
|
||||
|
@ -1,33 +1,37 @@
|
||||
<template>
|
||||
<!-- 详情 -->
|
||||
<a-button
|
||||
v-permission="['BILL_QUERY']"
|
||||
v-if="props.isDetail"
|
||||
type="outline"
|
||||
size="small"
|
||||
:style="{ marginRight: '10px' }"
|
||||
:style="{ marginRight: '10px', padding: '7px' }"
|
||||
@click="handleClick"
|
||||
>
|
||||
<template #icon><icon-eye /></template>
|
||||
{{ modalTitle }}
|
||||
</a-button>
|
||||
|
||||
<!-- 审核 -->
|
||||
<a-button
|
||||
v-permission="['BILL_AUDIT']"
|
||||
v-if="!props.isDetail"
|
||||
size="small"
|
||||
type="primary"
|
||||
:style="{ marginRight: '10px' }"
|
||||
:style="{ marginRight: '10px', padding: '7px' }"
|
||||
@click="handleClick"
|
||||
>
|
||||
<template #icon><icon-search /></template>
|
||||
{{ modalTitle }}
|
||||
</a-button>
|
||||
<a-modal
|
||||
width="600px"
|
||||
width="700px"
|
||||
:visible="visible"
|
||||
@ok="handleSubmit"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<template #title>{{ modalTitle }}</template>
|
||||
<a-form ref="createEditRef" :model="formData" :style="{ width: '500px' }">
|
||||
<a-form ref="createEditRef" :model="formData" :style="{ width: '650px' }">
|
||||
<a-form-item field="companyName" :label="$t('ticket.info.companyName')">
|
||||
<div>
|
||||
{{ formData.companyName }}
|
||||
@ -70,39 +74,16 @@
|
||||
</div>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item field="attachment" :label="$t('ticket.info.attachment')">
|
||||
<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="$t('ticket.info.dept')">
|
||||
<a-tree-select
|
||||
v-model="formData.deptId"
|
||||
:field-names="{
|
||||
key: 'id',
|
||||
title: 'name',
|
||||
children: 'children',
|
||||
}"
|
||||
:data="deptOptions"
|
||||
disabled
|
||||
style="color: black"
|
||||
/>
|
||||
{{ formData.deptName }}
|
||||
</a-form-item>
|
||||
|
||||
<!-- 审核员 -->
|
||||
<a-form-item field="auditorId" :label="$t('ticket.info.auditor')">
|
||||
<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>
|
||||
{{ formData.auditor }}
|
||||
</a-form-item>
|
||||
|
||||
<!-- 审核状态 -->
|
||||
<a-form-item
|
||||
field="status"
|
||||
:label="$t('ticket.info.status')"
|
||||
@ -112,7 +93,6 @@
|
||||
{{ formData.status }}
|
||||
</div>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item
|
||||
field="status"
|
||||
v-else
|
||||
@ -121,18 +101,37 @@
|
||||
:validate-trigger="['change', 'input']"
|
||||
:rules="[{ required: true, message: t('ticket.info.status.required') }]"
|
||||
>
|
||||
<a-radio-group
|
||||
v-for="i in statusOptions"
|
||||
:key="i.value"
|
||||
v-model="formData.submit"
|
||||
>
|
||||
<a-radio :value="i.value">{{ i.label }}</a-radio>
|
||||
<a-radio-group v-model="formData.submit" default-value="true">
|
||||
<a-radio value="true">{{ t('pass') }}</a-radio>
|
||||
<a-radio value="false">{{ t('failed') }}</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item field="comment" :label="$t('ticket.info.comment')">
|
||||
<a-textarea v-model="formData.comment" v-if="!props.isDetail" />
|
||||
<div v-else>{{ formData.comment }} </div>
|
||||
<!-- 审核意见 -->
|
||||
<a-form-item
|
||||
field="comment"
|
||||
:label="$t('ticket.info.comment')"
|
||||
v-if="!props.isDetail"
|
||||
>
|
||||
<a-textarea v-model="formData.comment" style="height: 200px" />
|
||||
</a-form-item>
|
||||
<a-form-item field="comment" :label="$t('ticket.info.comment')" v-else>
|
||||
<div>{{ formData.comment || '无' }}</div>
|
||||
</a-form-item>
|
||||
|
||||
<!-- 附件 -->
|
||||
<a-form-item field="attachment" :label="$t('ticket.info.attachment')">
|
||||
<a-upload
|
||||
: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>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
@ -142,7 +141,6 @@
|
||||
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';
|
||||
@ -178,8 +176,10 @@ const formData = ref<TicketRecord>({
|
||||
companyName: '',
|
||||
attachId: '',
|
||||
auditorId: '',
|
||||
submit: undefined,
|
||||
submit: true,
|
||||
comment: '',
|
||||
deptName: '',
|
||||
auditor: '',
|
||||
});
|
||||
|
||||
const emit = defineEmits(['refresh']);
|
||||
@ -187,15 +187,15 @@ const emit = defineEmits(['refresh']);
|
||||
const deptOptions = ref();
|
||||
const getDeptData = async () => {
|
||||
const res = await deptList();
|
||||
deptOptions.value = res.data;
|
||||
deptOptions.value = res.data.records;
|
||||
};
|
||||
|
||||
let auiditRoleId = '';
|
||||
|
||||
// 获取审核员ID
|
||||
const getRoleId = async () => {
|
||||
const res = await roleStore.getRoleList();
|
||||
res.data.forEach((item: any) => {
|
||||
const res = await roleStore.getRoleList('');
|
||||
res.data.records.forEach((item: any) => {
|
||||
if (item.name === 'auditor') {
|
||||
auiditRoleId = item.id;
|
||||
}
|
||||
@ -216,17 +216,6 @@ const optionDept = async () => {
|
||||
auditorOptions.value = res.data.records;
|
||||
};
|
||||
|
||||
const statusOptions = computed<SelectOptionData[]>(() => [
|
||||
{
|
||||
label: t('pass'),
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
label: t('failed'),
|
||||
value: false,
|
||||
},
|
||||
]);
|
||||
|
||||
const fileList = ref([]);
|
||||
// 组件被点击时
|
||||
const handleClick = async () => {
|
||||
@ -237,18 +226,29 @@ const handleClick = async () => {
|
||||
const res = await ticketStore.getDetail(ticketId);
|
||||
// 票据数据
|
||||
formData.value = res.data;
|
||||
|
||||
formData.value.submit = 'true';
|
||||
// 附件内容
|
||||
if (formData.value.attachId) {
|
||||
const data = await ticketStore.getAttachment(formData.value.attachId);
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
// 审核员信息
|
||||
const auditInfo = await userStore.getUserDetail(formData.value.auditorId);
|
||||
formData.value.deptId = auditInfo.data.deptId;
|
||||
optionDept().then(() => {
|
||||
deptOptions.value.forEach((item: any) => {
|
||||
if (item.id === formData.value.deptId) {
|
||||
formData.value.deptName = item.name;
|
||||
}
|
||||
});
|
||||
auditorOptions.value.forEach((item: any) => {
|
||||
if (item.id === formData.value.auditorId) {
|
||||
formData.value.auditor = item.username;
|
||||
}
|
||||
});
|
||||
setVisible(true);
|
||||
});
|
||||
};
|
||||
@ -271,7 +271,7 @@ const handleSubmit = async () => {
|
||||
});
|
||||
}
|
||||
}
|
||||
fileList.value.pop();
|
||||
fileList.value = [];
|
||||
emit('refresh');
|
||||
setVisible(false);
|
||||
}
|
||||
@ -279,7 +279,7 @@ const handleSubmit = async () => {
|
||||
|
||||
// 关闭
|
||||
const handleCancel = async () => {
|
||||
fileList.value.pop();
|
||||
fileList.value = [];
|
||||
createEditRef.value?.resetFields();
|
||||
setVisible(false);
|
||||
};
|
||||
|
@ -1,7 +1,18 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<Breadcrumb :items="['menu.ticket', 'menu.ticket.manage']" />
|
||||
<a-card class="general-card" :title="$t('menu.list.searchTable')">
|
||||
<a-card class="general-card">
|
||||
<a-tabs default-active-key="PASS" @change="changeTop">
|
||||
<a-tab-pane key="PASS" :title="t('pass')"> </a-tab-pane>
|
||||
<a-tab-pane key="FAILED" :title="t('failed')"> </a-tab-pane>
|
||||
<a-tab-pane key="EXAMINE" :title="t('unreviewed')"> </a-tab-pane>
|
||||
<a-tab-pane
|
||||
key="SUBMIT"
|
||||
:title="t('drafts')"
|
||||
v-if="userStore.permissions !== 'auditor'"
|
||||
>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
<a-row>
|
||||
<a-col :flex="1">
|
||||
<a-form
|
||||
@ -11,6 +22,7 @@
|
||||
label-align="right"
|
||||
>
|
||||
<a-row :gutter="16">
|
||||
<!-- 公司名称 -->
|
||||
<a-col :span="8">
|
||||
<a-form-item
|
||||
field="companyName"
|
||||
@ -25,6 +37,7 @@
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<!-- 标题 -->
|
||||
<a-col :span="8">
|
||||
<a-form-item
|
||||
field="title"
|
||||
@ -36,9 +49,42 @@
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<!-- 用户 -->
|
||||
<a-col :span="8">
|
||||
<a-form-item
|
||||
field="userName"
|
||||
:label="$t('searchTable.form.userName')"
|
||||
>
|
||||
<a-input
|
||||
v-model="formModel.userName"
|
||||
:placeholder="$t('searchTable.form.committer.placeholder')"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<!-- 金额 -->
|
||||
<a-col :span="8">
|
||||
<a-form-item
|
||||
field="money"
|
||||
:label="$t('searchTable.form.money')"
|
||||
>
|
||||
<a-input-group>
|
||||
<a-input
|
||||
v-model="formModel.minMoney"
|
||||
:placeholder="$t('searchTable.form.min')"
|
||||
/>
|
||||
<a-input
|
||||
v-model="formModel.maxMoney"
|
||||
:placeholder="$t('searchTable.form.max')"
|
||||
/>
|
||||
</a-input-group>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<!-- 票据类型 -->
|
||||
<a-col :span="8">
|
||||
<a-form-item field="type" :label="$t('searchTable.form.type')">
|
||||
<a-select
|
||||
@ -49,15 +95,16 @@
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<!-- 时间 -->
|
||||
<a-col :span="8">
|
||||
<a-form-item
|
||||
field="status"
|
||||
:label="$t('searchTable.form.status')"
|
||||
>
|
||||
<a-select
|
||||
v-model="formModel.status"
|
||||
:options="statusOptions"
|
||||
:placeholder="$t('searchTable.form.status.placeholder')"
|
||||
<a-form-item field="time" :label="$t('searchTable.form.time')">
|
||||
<a-range-picker
|
||||
v-model="formModel.time"
|
||||
style="width: 360px"
|
||||
show-time
|
||||
@select="onSelect"
|
||||
value-format="YYYY-MM-DD"
|
||||
:allow-clear="false"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
@ -88,12 +135,19 @@
|
||||
<a-col :span="12">
|
||||
<a-space>
|
||||
<TicketForm
|
||||
v-if="formModel.status === 'SUBMIT'"
|
||||
ref="createEditRef"
|
||||
:prem="ticketItem"
|
||||
:prem="formModel"
|
||||
:is-create="true"
|
||||
@refresh="search"
|
||||
/>
|
||||
</a-space>
|
||||
<a-button @click="generateExcel" style="margin-left: 5px">
|
||||
<template #icon>
|
||||
<icon-download size="16" />
|
||||
</template>
|
||||
{{ $t('searchTable.operation.download') }}
|
||||
</a-button>
|
||||
</a-col>
|
||||
<a-col
|
||||
:span="12"
|
||||
@ -162,10 +216,23 @@
|
||||
:columns="(cloneColumns as TableColumnData[])"
|
||||
:data="renderData"
|
||||
:bordered="false"
|
||||
:pagination="pagination"
|
||||
:pagination="false"
|
||||
:size="size"
|
||||
:expandable="expandable"
|
||||
@page-change="onPageChange"
|
||||
style="margin-bottom: 40px"
|
||||
>
|
||||
<template #expand-row="{ record }">
|
||||
<!-- 下面展示子表格,根据需求对子table进行属性配置 -->
|
||||
<a-descriptions layout="inline-horizontal" :column="1" bordered>
|
||||
<descriptions-item :label="t('ticket.info.contactEmail')">
|
||||
{{ record.contactEmail }}
|
||||
</descriptions-item>
|
||||
<descriptions-item :label="t('ticket.info.body')">
|
||||
{{ record.body }}
|
||||
</descriptions-item>
|
||||
</a-descriptions>
|
||||
</template>
|
||||
<template #index="{ rowIndex }">
|
||||
{{ rowIndex + 1 + (pagination.current - 1) * pagination.size }}
|
||||
</template>
|
||||
@ -173,6 +240,21 @@
|
||||
{{ dayjs(record.createTime).format('YYYY-MM-DD') }}
|
||||
</template>
|
||||
|
||||
<template #status="{ record }">
|
||||
<a-button status="success" v-if="record.status === '审核通过'">{{
|
||||
record.status
|
||||
}}</a-button>
|
||||
<a-button status="danger" v-if="record.status === '审核未通过'">{{
|
||||
record.status
|
||||
}}</a-button>
|
||||
<a-button status="normal" v-if="record.status === '待审核'">{{
|
||||
record.status
|
||||
}}</a-button>
|
||||
<a-button status="warning" v-if="record.status === '待提交'">{{
|
||||
record.status
|
||||
}}</a-button>
|
||||
</template>
|
||||
|
||||
<template #operations="{ record }">
|
||||
<!-- 详情 -->
|
||||
<TicketEdit
|
||||
@ -210,18 +292,33 @@
|
||||
size="small"
|
||||
status="danger"
|
||||
v-permission="['BILL_DELETE']"
|
||||
v-if="
|
||||
record.status === '待提交' || record.status === '审核未通过'
|
||||
"
|
||||
style="padding: 7px"
|
||||
>
|
||||
<template #icon><icon-delete /></template>
|
||||
{{ $t('delete') }}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
</template>
|
||||
</a-table>
|
||||
<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
|
||||
/>
|
||||
</a-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, watch, reactive } from 'vue';
|
||||
import { computed, reactive, ref, watch } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import useTableOption from '@/hooks/table-option';
|
||||
@ -232,6 +329,7 @@ import dayjs from 'dayjs';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { useTicketStore, useUserStore } from '@/store';
|
||||
import { TicketRecord } from '@/api/ticket';
|
||||
import { downloadExcel, DownloadExcelPrams } from '@/utils/excel';
|
||||
import TicketEdit from './components/ticket-edit.vue';
|
||||
import TicketForm from './components/form-edit.vue';
|
||||
|
||||
@ -255,13 +353,27 @@ const generateFormModel = () => {
|
||||
companyName: '',
|
||||
title: '',
|
||||
type: '',
|
||||
status: '',
|
||||
// 默认先展示票据审核通过的
|
||||
status: 'PASS',
|
||||
time: [],
|
||||
userName: '',
|
||||
minMoney: '',
|
||||
maxMoney: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
};
|
||||
};
|
||||
|
||||
const { t } = useI18n();
|
||||
const renderData = ref<TicketRecord[]>([]);
|
||||
const formModel = ref(generateFormModel());
|
||||
const currentStatus = ref('PASS');
|
||||
|
||||
// 拓展行
|
||||
const expandable = reactive({
|
||||
title: ' ',
|
||||
expandedRowRender: (record: any) => {},
|
||||
});
|
||||
|
||||
// 表格头部
|
||||
const columns = computed<TableColumnData[]>(() => [
|
||||
@ -273,6 +385,9 @@ const columns = computed<TableColumnData[]>(() => [
|
||||
{
|
||||
title: t('ticketTable.columns.companyName'),
|
||||
dataIndex: 'companyName',
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('ticketTable.columns.title'),
|
||||
@ -281,14 +396,36 @@ const columns = computed<TableColumnData[]>(() => [
|
||||
{
|
||||
title: t('ticketTable.columns.money'),
|
||||
dataIndex: 'money',
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('ticketTable.columns.userName'),
|
||||
dataIndex: 'userName',
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('ticketTable.columns.createTime'),
|
||||
dataIndex: 'createTime',
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
},
|
||||
slotName: 'createTime',
|
||||
},
|
||||
{
|
||||
title: t('ticketTable.columns.type'),
|
||||
dataIndex: 'type',
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('ticketTable.columns.status'),
|
||||
dataIndex: 'status',
|
||||
slotName: 'status',
|
||||
},
|
||||
{
|
||||
title: t('searchTable.columns.operations'),
|
||||
@ -312,39 +449,56 @@ const typesOptions = computed<SelectOptionData[]>(() => [
|
||||
},
|
||||
]);
|
||||
|
||||
const statusOptions = computed<SelectOptionData[]>(() => [
|
||||
{
|
||||
label: t('unsubmitted'),
|
||||
value: 'SUBMIT',
|
||||
},
|
||||
{
|
||||
label: t('unreviewed'),
|
||||
value: 'EXAMINE',
|
||||
},
|
||||
{
|
||||
label: t('pass'),
|
||||
value: 'PASS',
|
||||
},
|
||||
{
|
||||
label: t('failed'),
|
||||
value: 'FAILED',
|
||||
},
|
||||
]);
|
||||
|
||||
// 基础分页查询的信息
|
||||
const basePagination: Pagination = {
|
||||
const pagination: Pagination = {
|
||||
page: 1,
|
||||
size: 10,
|
||||
current: 1,
|
||||
total: 1,
|
||||
};
|
||||
|
||||
// 映射
|
||||
const pagination = reactive({
|
||||
...basePagination,
|
||||
});
|
||||
// 下载表格
|
||||
const generateExcel = () => {
|
||||
const param: DownloadExcelPrams = {
|
||||
columns: [
|
||||
{ title: '公司', key: 'companyName' },
|
||||
{ title: '标题', key: 'title' },
|
||||
{ title: '金额', key: 'money' },
|
||||
{ title: '内容', key: 'body' },
|
||||
{ title: '联系邮箱', key: 'contactEmail' },
|
||||
{ title: '创建时间', key: 'createTime' },
|
||||
{ title: '类型', key: 'type' },
|
||||
{ title: '审核状态', key: 'status' },
|
||||
],
|
||||
rows: renderData.value,
|
||||
name: '票据表格',
|
||||
};
|
||||
downloadExcel(param);
|
||||
};
|
||||
|
||||
// 时间段选择
|
||||
const onSelect = (dateString: any, date: any) => {
|
||||
formModel.value.startTime = String(dateString[0]);
|
||||
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) => {
|
||||
fetchData({ ...basePagination, ...formModel.value, current });
|
||||
pagination.page = current;
|
||||
pagination.current = current;
|
||||
search();
|
||||
};
|
||||
|
||||
// 数据条数改变
|
||||
const onSizeChange = (size: number) => {
|
||||
pagination.size = size;
|
||||
search();
|
||||
};
|
||||
|
||||
// 获取数据
|
||||
@ -383,22 +537,32 @@ const fetchData = async (params: {
|
||||
|
||||
// 模糊查询
|
||||
const search = () => {
|
||||
// 删除time
|
||||
const { time, ...auditDate } = formModel.value;
|
||||
|
||||
fetchData({
|
||||
...basePagination,
|
||||
...formModel.value,
|
||||
current: '1',
|
||||
...pagination,
|
||||
...auditDate,
|
||||
} as unknown as any);
|
||||
};
|
||||
|
||||
// 切换标签页
|
||||
const changeTop = (key: any) => {
|
||||
formModel.value.status = key;
|
||||
currentStatus.value = key;
|
||||
search();
|
||||
};
|
||||
|
||||
search();
|
||||
|
||||
// 重置
|
||||
const reset = () => {
|
||||
formModel.value = generateFormModel();
|
||||
formModel.value.status = currentStatus.value;
|
||||
};
|
||||
|
||||
// 删除票据
|
||||
const handleDelete = async (record) => {
|
||||
const handleDelete = async (record: any) => {
|
||||
const res = await ticketStore.removeTicket(record.id);
|
||||
if (res.status === 200) {
|
||||
Message.success({
|
||||
|
@ -16,10 +16,19 @@ export default {
|
||||
'searchTable.form.companyName.placeholder': 'Please enter Company',
|
||||
'searchTable.form.title':'Title',
|
||||
'searchTable.form.title.placeholder': 'Please enter Title',
|
||||
'searchTable.form.money':'Money',
|
||||
'searchTable.form.money.placeholder': 'Please enter Money',
|
||||
'searchTable.form.userName':'UserName',
|
||||
'searchTable.form.userName.placeholder': 'Please enter UserName',
|
||||
'searchTable.form.type':'Type',
|
||||
'searchTable.form.type.placeholder': 'Please select Type',
|
||||
'searchTable.form.status': 'Status',
|
||||
'searchTable.form.status.placeholder': 'Please select Status',
|
||||
'searchTable.form.time':'Time',
|
||||
'searchTable.form.time.placeholder': 'Please select Time',
|
||||
'searchTable.form.min':'Min money',
|
||||
'searchTable.form.max':'Max money',
|
||||
|
||||
|
||||
'Confirm the deletion of this ticket': 'Confirm the deletion of this ticket?',
|
||||
|
||||
@ -44,37 +53,39 @@ export default {
|
||||
'unreviewed': 'Unreviewed',
|
||||
'pass': 'Pass',
|
||||
'failed': 'Failed',
|
||||
'drafts': 'Drafts',
|
||||
|
||||
"ticket.info.companyName": 'Company',
|
||||
"ticket.info.companyName": 'Company:',
|
||||
"ticket.info.companyName.required": 'CompanyName is required',
|
||||
"ticket.info.companyName.placeholder": 'Please enter CompanyName',
|
||||
"ticket.info.title": 'Title',
|
||||
"ticket.info.title": 'Title:',
|
||||
"ticket.info.title.required": 'Title is required',
|
||||
"ticket.info.title.placeholder": 'Please enter Title',
|
||||
"ticket.info.body": 'Content',
|
||||
"ticket.info.body": 'Content:',
|
||||
"ticket.info.body.required": 'Content is required',
|
||||
"ticket.info.body.placeholder": 'Please enter Content',
|
||||
"ticket.info.money": 'Money',
|
||||
"ticket.info.money": 'Money:',
|
||||
"ticket.info.money.required": 'Money is required',
|
||||
"ticket.info.money.placeholder": 'Please enter Money',
|
||||
"ticket.info.contactEmail": 'Email',
|
||||
"ticket.info.createTime": 'CreateTime',
|
||||
"ticket.info.contactEmail": 'Email:',
|
||||
"ticket.info.createTime": 'CreateTime:',
|
||||
"ticket.info.contactEmail.required": 'contactEmail is required',
|
||||
"ticket.info.contactEmail.placeholder": 'Please enter contactEmail',
|
||||
"ticket.info.type": 'Type',
|
||||
"ticket.info.type": 'Type:',
|
||||
"ticket.info.type.required": 'Type is required',
|
||||
"ticket.info.type.placeholder": 'Please select Type',
|
||||
"ticket.info.attachment": 'Attachment',
|
||||
"ticket.info.dept": 'Dept',
|
||||
"ticket.info.attachment": 'Attachment:',
|
||||
"ticket.info.dept": 'Dept:',
|
||||
"ticket.info.dept.required": 'Dept is required',
|
||||
"ticket.info.dept.placeholder": 'Please select Dept',
|
||||
"ticket.info.auditor": 'Auditor',
|
||||
"ticket.info.auditor": 'Auditor:',
|
||||
"ticket.info.auditor.required": 'Auditor is required',
|
||||
"ticket.info.auditor.placeholder": 'Please select Auditor',
|
||||
"ticket.info.status": 'Status',
|
||||
"ticket.info.status": 'Status:',
|
||||
"ticket.info.status.required": 'Status is required',
|
||||
"ticket.info.status.placeholder": 'Please select Status',
|
||||
"ticket.info.comment": 'Comment',
|
||||
"ticket.info.comment": 'Comment:',
|
||||
"ticketTable.columns.userName":'userName',
|
||||
|
||||
'upload.sucess': 'Upload Sucess',
|
||||
'upload.fail': 'Upload Fail',
|
||||
|
@ -15,10 +15,19 @@ export default {
|
||||
'searchTable.form.companyName.placeholder': '请输入公司名称',
|
||||
'searchTable.form.title':'标题',
|
||||
'searchTable.form.title.placeholder': '请输入标题',
|
||||
'searchTable.form.money':'金额',
|
||||
'searchTable.form.money.placeholder': '请输入金额',
|
||||
'searchTable.form.userName':'用户',
|
||||
'searchTable.form.committer.placeholder': '请输入票据提交的用户',
|
||||
'searchTable.form.type':'类型',
|
||||
'searchTable.form.type.placeholder': '请选择票据类型',
|
||||
'searchTable.form.status': '状态',
|
||||
'searchTable.form.status.placeholder': '请选择状态',
|
||||
'searchTable.form.time':'时间',
|
||||
'searchTable.form.time.placeholder': '请选择时间段',
|
||||
'searchTable.form.min':'最小金额',
|
||||
'searchTable.form.max':'最大金额',
|
||||
|
||||
|
||||
'Confirm the deletion of this ticket': '确定删除此票据?',
|
||||
|
||||
@ -43,37 +52,40 @@ export default {
|
||||
'unreviewed': '待审核',
|
||||
'pass': '审核通过',
|
||||
'failed': '审核未通过',
|
||||
'drafts':'草稿箱',
|
||||
|
||||
"ticket.info.companyName": '公司',
|
||||
"ticket.info.companyName": '公司:',
|
||||
"ticket.info.companyName.required": '公司名称不能为空',
|
||||
"ticket.info.companyName.placeholder": '请输入公司名称',
|
||||
"ticket.info.title": '标题',
|
||||
"ticket.info.title": '标题:',
|
||||
"ticket.info.title.required": '标题不能为空',
|
||||
"ticket.info.title.placeholder": '请输入标题',
|
||||
"ticket.info.body": '内容',
|
||||
"ticket.info.body": '内容:',
|
||||
"ticket.info.body.required": '内容不能为空',
|
||||
"ticket.info.body.placeholder": '请输入内容',
|
||||
"ticket.info.money": '金额',
|
||||
"ticket.info.money": '金额:',
|
||||
"ticket.info.money.required": '金额不能为空',
|
||||
"ticket.info.money.placeholder": '请输入金额',
|
||||
"ticket.info.contactEmail": '联系邮箱',
|
||||
"ticket.info.createTime": '创建时间',
|
||||
"ticket.info.contactEmail": '联系邮箱:',
|
||||
"ticket.info.createTime": '创建时间:',
|
||||
"ticket.info.contactEmail.required": '联系邮箱不能为空',
|
||||
"ticket.info.contactEmail.placeholder": '请输入联系邮箱',
|
||||
"ticket.info.type": '票据类型',
|
||||
"ticket.info.type": '票据类型:',
|
||||
"ticket.info.type.required": '票据类型不能为空',
|
||||
"ticket.info.type.placeholder": '请选择票据类型',
|
||||
"ticket.info.attachment": '附件',
|
||||
"ticket.info.dept": '部门',
|
||||
"ticket.info.attachment": '附件:',
|
||||
"ticket.info.dept": '部门:',
|
||||
"ticket.info.dept.required": '部门不能为空',
|
||||
"ticket.info.dept.placeholder": '请选择提交的部门',
|
||||
"ticket.info.auditor": '审核员',
|
||||
"ticket.info.auditor": '审核员:',
|
||||
"ticket.info.auditor.required": '审核员不能为空',
|
||||
"ticket.info.auditor.placeholder": '请选择审核员',
|
||||
"ticket.info.status": '审核状态',
|
||||
"ticket.info.status": '审核状态:',
|
||||
"ticket.info.status.required": '审核状态不能为空',
|
||||
"ticket.info.status.placeholder": '请选择审核状态',
|
||||
"ticket.info.comment": '审核意见',
|
||||
"ticket.info.comment": '审核意见:',
|
||||
"ticketTable.columns.userName":'用户',
|
||||
|
||||
|
||||
'upload.sucess': '上传成功',
|
||||
'upload.fail': '上传失败',
|
||||
|
@ -6,7 +6,7 @@
|
||||
:label-col-props="{ span: 8 }"
|
||||
:wrapper-col-props="{ span: 16 }"
|
||||
>
|
||||
<a-form-item
|
||||
<!-- <a-form-item
|
||||
field="oldPassword"
|
||||
:label="$t('userSetting.passwordReset.form.label.oldPassword')"
|
||||
:rules="[{ required: true, message: $t('login.form.password.errMsg') }]"
|
||||
@ -19,7 +19,7 @@
|
||||
allow-clear
|
||||
>
|
||||
</a-input-password>
|
||||
</a-form-item>
|
||||
</a-form-item> -->
|
||||
|
||||
<a-form-item
|
||||
field="password"
|
||||
|
@ -93,7 +93,7 @@ const fileList = ref<FileItem[]>([file]);
|
||||
const Onchange = async (option: any) => {
|
||||
const FormDatas = new FormData();
|
||||
FormDatas.append('file', option.fileItem.file);
|
||||
const res = await ticketStore.uploadFileTicket(FormDatas);
|
||||
const res = await ticketStore.uploadFile(FormDatas);
|
||||
if (res.status === 200) {
|
||||
Message.success({
|
||||
content: t('upload.sucess'),
|
||||
|
Loading…
Reference in New Issue
Block a user