Compare commits
2 Commits
4733863d6e
...
ed030b8493
| Author | SHA1 | Date | |
|---|---|---|---|
| ed030b8493 | |||
| c5685cd01d |
7
src/.idea/.idea.ZhonTai/.idea/vcs.xml
generated
Normal file
7
src/.idea/.idea.ZhonTai/.idea/vcs.xml
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
6597
zhontai.ui.admin.vue3/pnpm-lock.yaml
generated
Normal file
6597
zhontai.ui.admin.vue3/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,312 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { AxiosResponse } from 'axios'
|
||||
import {
|
||||
ApiAddInput,
|
||||
ApiSetEnableLogInput,
|
||||
ApiSetEnableParamsInput,
|
||||
ApiSetEnableResultInput,
|
||||
ApiSyncInput,
|
||||
ApiUpdateInput,
|
||||
PageInputApiGetPageInput,
|
||||
ResultOutputApiGetOutput,
|
||||
ResultOutputInt64,
|
||||
ResultOutputListApiGetListOutput,
|
||||
ResultOutputListProjectConfig,
|
||||
ResultOutputPageOutputApiEntity,
|
||||
} from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class ApiApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags api
|
||||
* @name Get
|
||||
* @summary 查询
|
||||
* @request GET:/api/admin/api/get
|
||||
* @secure
|
||||
*/
|
||||
get = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputApiGetOutput, any>({
|
||||
path: `/api/admin/api/get`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags api
|
||||
* @name GetList
|
||||
* @summary 查询列表
|
||||
* @request GET:/api/admin/api/get-list
|
||||
* @secure
|
||||
*/
|
||||
getList = (
|
||||
query?: {
|
||||
key?: string
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputListApiGetListOutput, any>({
|
||||
path: `/api/admin/api/get-list`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags api
|
||||
* @name GetPage
|
||||
* @summary 查询分页
|
||||
* @request POST:/api/admin/api/get-page
|
||||
* @secure
|
||||
*/
|
||||
getPage = (data: PageInputApiGetPageInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputPageOutputApiEntity, any>({
|
||||
path: `/api/admin/api/get-page`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags api
|
||||
* @name Add
|
||||
* @summary 添加
|
||||
* @request POST:/api/admin/api/add
|
||||
* @secure
|
||||
*/
|
||||
add = (data: ApiAddInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputInt64, any>({
|
||||
path: `/api/admin/api/add`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags api
|
||||
* @name Update
|
||||
* @summary 修改
|
||||
* @request PUT:/api/admin/api/update
|
||||
* @secure
|
||||
*/
|
||||
update = (data: ApiUpdateInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/api/update`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags api
|
||||
* @name SetEnableLog
|
||||
* @summary 设置启用接口日志
|
||||
* @request POST:/api/admin/api/set-enable-log
|
||||
* @secure
|
||||
*/
|
||||
setEnableLog = (data: ApiSetEnableLogInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/api/set-enable-log`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags api
|
||||
* @name SetEnableParams
|
||||
* @summary 设置启用请求参数
|
||||
* @request POST:/api/admin/api/set-enable-params
|
||||
* @secure
|
||||
*/
|
||||
setEnableParams = (data: ApiSetEnableParamsInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/api/set-enable-params`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags api
|
||||
* @name SetEnableResult
|
||||
* @summary 设置启用响应结果
|
||||
* @request POST:/api/admin/api/set-enable-result
|
||||
* @secure
|
||||
*/
|
||||
setEnableResult = (data: ApiSetEnableResultInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/api/set-enable-result`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags api
|
||||
* @name Delete
|
||||
* @summary 彻底删除
|
||||
* @request DELETE:/api/admin/api/delete
|
||||
* @secure
|
||||
*/
|
||||
delete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/api/delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags api
|
||||
* @name BatchDelete
|
||||
* @summary 批量彻底删除
|
||||
* @request PUT:/api/admin/api/batch-delete
|
||||
* @secure
|
||||
*/
|
||||
batchDelete = (data: number[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/api/batch-delete`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags api
|
||||
* @name SoftDelete
|
||||
* @summary 删除
|
||||
* @request DELETE:/api/admin/api/soft-delete
|
||||
* @secure
|
||||
*/
|
||||
softDelete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/api/soft-delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags api
|
||||
* @name BatchSoftDelete
|
||||
* @summary 批量删除
|
||||
* @request PUT:/api/admin/api/batch-soft-delete
|
||||
* @secure
|
||||
*/
|
||||
batchSoftDelete = (data: number[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/api/batch-soft-delete`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags api
|
||||
* @name Sync
|
||||
* @summary 同步
|
||||
* @request POST:/api/admin/api/sync
|
||||
* @secure
|
||||
*/
|
||||
sync = (data: ApiSyncInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/api/sync`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags api
|
||||
* @name GetProjects
|
||||
* @summary 获得项目列表
|
||||
* @request GET:/api/admin/api/get-projects
|
||||
* @secure
|
||||
*/
|
||||
getProjects = (
|
||||
query?: {
|
||||
/** @default "/swagger" */
|
||||
suffix?: string
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputListProjectConfig, any>({
|
||||
path: `/api/admin/api/get-projects`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,229 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { AxiosResponse } from 'axios'
|
||||
import {
|
||||
BoardAddInput,
|
||||
BoardGetOutput,
|
||||
BoardGetPageInput,
|
||||
BoardGetPageOutput,
|
||||
BoardUpdateInput,
|
||||
PageInputBoardGetPageInput,
|
||||
ResultOutputBoardGetOutput,
|
||||
ResultOutputInt64,
|
||||
ResultOutputPageOutputBoardGetPageOutput,
|
||||
BoardGetBoardUserListOutput,
|
||||
BoardAddBoardUserListInput,
|
||||
BoardRemoveBoardUserInput,
|
||||
BoardGetBoardListByUserIdOutput,
|
||||
} from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class BoardApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags board
|
||||
* @name Get
|
||||
* @summary 查询
|
||||
* @request GET:/api/admin/board/get
|
||||
* @secure
|
||||
*/
|
||||
get = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputBoardGetOutput, any>({
|
||||
path: `/api/admin/board/get`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags board
|
||||
* @name GetPage
|
||||
* @summary 查询分页
|
||||
* @request POST:/api/admin/board/get-page
|
||||
* @secure
|
||||
*/
|
||||
getPage = (data: PageInputBoardGetPageInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputPageOutputBoardGetPageOutput, any>({
|
||||
path: `/api/admin/board/get-page`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags board
|
||||
* @name Add
|
||||
* @summary 添加
|
||||
* @request POST:/api/admin/board/add
|
||||
* @secure
|
||||
*/
|
||||
add = (data: BoardAddInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputInt64, any>({
|
||||
path: `/api/admin/board/add`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags board
|
||||
* @name Update
|
||||
* @summary 修改
|
||||
* @request PUT:/api/admin/board/update
|
||||
* @secure
|
||||
*/
|
||||
update = (data: BoardUpdateInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/board/update`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags board
|
||||
* @name SoftDelete
|
||||
* @summary 软删除
|
||||
* @request DELETE:/api/admin/board/soft-delete
|
||||
* @secure
|
||||
*/
|
||||
softDelete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/board/soft-delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
|
||||
// GetBoardListByUserIdAsync
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags board
|
||||
* @name GetBoardUserList
|
||||
* @summary 获取看板用户列表
|
||||
* @request GET:/api/admin/board/get-board-user-list
|
||||
* @secure
|
||||
*/
|
||||
getBoardUserList = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
BoardId?: number
|
||||
/** 姓名 */
|
||||
Name?: string | null
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<{ success?: boolean; data?: BoardGetBoardUserListOutput[] }, any>({
|
||||
path: `/api/admin/board/get-board-user-list`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags board
|
||||
* @name AddBoardUser
|
||||
* @summary 添加看板用户
|
||||
* @request POST:/api/admin/board/add-board-user
|
||||
* @secure
|
||||
*/
|
||||
addBoardUser = (data: BoardAddBoardUserListInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/board/add-board-user`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags board
|
||||
* @name RemoveBoardUser
|
||||
* @summary 移除看板用户
|
||||
* @request POST:/api/admin/board/remove-board-user
|
||||
* @secure
|
||||
*/
|
||||
removeBoardUser = (data: BoardRemoveBoardUserInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/board/remove-board-user`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags board
|
||||
* @name GetBoardListByUserId
|
||||
* @summary 根据当前用户获取看板列表
|
||||
* @request GET:/api/admin/board/get-board-list-by-user-id
|
||||
* @secure
|
||||
*/
|
||||
getBoardListByUserId = (
|
||||
query?: {
|
||||
/** 看板名称 */
|
||||
name?: string | null
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<{ success?: boolean; data?: BoardGetBoardListByUserIdOutput[] }, any>({
|
||||
path: `/api/admin/board/get-board-list-by-user-id`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,58 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { AxiosResponse } from 'axios'
|
||||
import { ResultOutputListObject } from './data-contracts'
|
||||
import { HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class CacheApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags cache
|
||||
* @name GetList
|
||||
* @summary 查询列表
|
||||
* @request GET:/api/admin/cache/get-list
|
||||
* @secure
|
||||
*/
|
||||
getList = (params: RequestParams = {}) =>
|
||||
this.request<ResultOutputListObject, any>({
|
||||
path: `/api/admin/cache/get-list`,
|
||||
method: 'GET',
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags cache
|
||||
* @name Clear
|
||||
* @summary 清除缓存
|
||||
* @request DELETE:/api/admin/cache/clear
|
||||
* @secure
|
||||
*/
|
||||
clear = (
|
||||
query?: {
|
||||
/** 缓存键 */
|
||||
cacheKey?: string
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/cache/clear`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
import { HttpClient, ContentType, RequestParams } from './http-client'
|
||||
import { CustomNavigationInput } from './data-contracts'
|
||||
|
||||
export class CustomNavigationApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* 保存自定义导航
|
||||
* @request POST:/api/user/custom-navigation
|
||||
*/
|
||||
save = (data: CustomNavigationInput, params: RequestParams = {}) =>
|
||||
this.request<any, any>({
|
||||
path: '/api/admin/user-custom-navigation/save',
|
||||
method: 'POST',
|
||||
body: data,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* 获取自定义导航
|
||||
* @request GET:/api/user/custom-navigation
|
||||
*/
|
||||
get = (params: RequestParams = {}) =>
|
||||
this.request<any, any>({
|
||||
path: '/api/admin/user-custom-navigation/get',
|
||||
method: 'GET',
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,316 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { AxiosResponse } from 'axios'
|
||||
import {
|
||||
DictAddInput,
|
||||
DictUpdateInput,
|
||||
ExportInput,
|
||||
PageInputDictGetPageInput,
|
||||
ResultOutputDictGetOutput,
|
||||
ResultOutputDictionaryStringListDictGetListOutput,
|
||||
ResultOutputImportOutput,
|
||||
ResultOutputInt64,
|
||||
ResultOutputPageOutputDictGetPageOutput,
|
||||
} from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class DictApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags dict
|
||||
* @name Get
|
||||
* @summary 查询
|
||||
* @request GET:/api/admin/dict/get
|
||||
* @secure
|
||||
*/
|
||||
get = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputDictGetOutput, any>({
|
||||
path: `/api/admin/dict/get`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags dict
|
||||
* @name GetPage
|
||||
* @summary 查询分页
|
||||
* @request POST:/api/admin/dict/get-page
|
||||
* @secure
|
||||
*/
|
||||
getPage = (data: PageInputDictGetPageInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputPageOutputDictGetPageOutput, any>({
|
||||
path: `/api/admin/dict/get-page`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags dict
|
||||
* @name GetList
|
||||
* @summary 通过类型编码查询列表
|
||||
* @request POST:/api/admin/dict/get-list
|
||||
* @secure
|
||||
*/
|
||||
getList = (data: string[], params: RequestParams = {}) =>
|
||||
this.request<ResultOutputDictionaryStringListDictGetListOutput, any>({
|
||||
path: `/api/admin/dict/get-list`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags dict
|
||||
* @name GetListByNames
|
||||
* @summary 通过类型名称查询列表
|
||||
* @request POST:/api/admin/dict/get-list-by-names
|
||||
* @secure
|
||||
*/
|
||||
getListByNames = (data: string[], params: RequestParams = {}) =>
|
||||
this.request<ResultOutputDictionaryStringListDictGetListOutput, any>({
|
||||
path: `/api/admin/dict/get-list-by-names`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags dict
|
||||
* @name DownloadTemplate
|
||||
* @summary 下载导入模板
|
||||
* @request POST:/api/admin/dict/download-template
|
||||
* @secure
|
||||
*/
|
||||
downloadTemplate = (params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/dict/download-template`,
|
||||
method: 'POST',
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags dict
|
||||
* @name DownloadErrorMark
|
||||
* @summary 下载错误标记文件
|
||||
* @request POST:/api/admin/dict/download-error-mark
|
||||
* @secure
|
||||
*/
|
||||
downloadErrorMark = (
|
||||
query?: {
|
||||
fileId?: string
|
||||
fileName?: string
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/dict/download-error-mark`,
|
||||
method: 'POST',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags dict
|
||||
* @name ExportData
|
||||
* @summary 导出数据
|
||||
* @request POST:/api/admin/dict/export-data
|
||||
* @secure
|
||||
*/
|
||||
exportData = (data: ExportInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/dict/export-data`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags dict
|
||||
* @name ImportData
|
||||
* @summary 导入数据
|
||||
* @request POST:/api/admin/dict/import-data
|
||||
* @secure
|
||||
*/
|
||||
importData = (
|
||||
data: {
|
||||
/** @format binary */
|
||||
file: File
|
||||
},
|
||||
query?: {
|
||||
/** @format int32 */
|
||||
duplicateAction?: number
|
||||
fileId?: string
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputImportOutput, any>({
|
||||
path: `/api/admin/dict/import-data`,
|
||||
method: 'POST',
|
||||
query: query,
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.FormData,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags dict
|
||||
* @name Add
|
||||
* @summary 新增
|
||||
* @request POST:/api/admin/dict/add
|
||||
* @secure
|
||||
*/
|
||||
add = (data: DictAddInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputInt64, any>({
|
||||
path: `/api/admin/dict/add`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags dict
|
||||
* @name Update
|
||||
* @summary 修改
|
||||
* @request PUT:/api/admin/dict/update
|
||||
* @secure
|
||||
*/
|
||||
update = (data: DictUpdateInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/dict/update`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags dict
|
||||
* @name Delete
|
||||
* @summary 彻底删除
|
||||
* @request DELETE:/api/admin/dict/delete
|
||||
* @secure
|
||||
*/
|
||||
delete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/dict/delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags dict
|
||||
* @name BatchDelete
|
||||
* @summary 批量彻底删除
|
||||
* @request PUT:/api/admin/dict/batch-delete
|
||||
* @secure
|
||||
*/
|
||||
batchDelete = (data: number[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/dict/batch-delete`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags dict
|
||||
* @name SoftDelete
|
||||
* @summary 删除
|
||||
* @request DELETE:/api/admin/dict/soft-delete
|
||||
* @secure
|
||||
*/
|
||||
softDelete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/dict/soft-delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags dict
|
||||
* @name BatchSoftDelete
|
||||
* @summary 批量删除
|
||||
* @request PUT:/api/admin/dict/batch-soft-delete
|
||||
* @secure
|
||||
*/
|
||||
batchSoftDelete = (data: number[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/dict/batch-soft-delete`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,187 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { AxiosResponse } from 'axios'
|
||||
import {
|
||||
DictTypeAddInput,
|
||||
DictTypeUpdateInput,
|
||||
PageInputDictTypeGetPageInput,
|
||||
ResultOutputDictTypeGetOutput,
|
||||
ResultOutputInt64,
|
||||
ResultOutputPageOutputDictTypeGetPageOutput,
|
||||
} from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class DictTypeApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags dict-type
|
||||
* @name Get
|
||||
* @summary 查询
|
||||
* @request GET:/api/admin/dict-type/get
|
||||
* @secure
|
||||
*/
|
||||
get = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputDictTypeGetOutput, any>({
|
||||
path: `/api/admin/dict-type/get`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags dict-type
|
||||
* @name GetPage
|
||||
* @summary 查询分页
|
||||
* @request POST:/api/admin/dict-type/get-page
|
||||
* @secure
|
||||
*/
|
||||
getPage = (data: PageInputDictTypeGetPageInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputPageOutputDictTypeGetPageOutput, any>({
|
||||
path: `/api/admin/dict-type/get-page`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags dict-type
|
||||
* @name Add
|
||||
* @summary 新增
|
||||
* @request POST:/api/admin/dict-type/add
|
||||
* @secure
|
||||
*/
|
||||
add = (data: DictTypeAddInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputInt64, any>({
|
||||
path: `/api/admin/dict-type/add`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags dict-type
|
||||
* @name Update
|
||||
* @summary 修改
|
||||
* @request PUT:/api/admin/dict-type/update
|
||||
* @secure
|
||||
*/
|
||||
update = (data: DictTypeUpdateInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/dict-type/update`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags dict-type
|
||||
* @name Delete
|
||||
* @summary 彻底删除
|
||||
* @request DELETE:/api/admin/dict-type/delete
|
||||
* @secure
|
||||
*/
|
||||
delete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/dict-type/delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags dict-type
|
||||
* @name BatchDelete
|
||||
* @summary 批量彻底删除
|
||||
* @request PUT:/api/admin/dict-type/batch-delete
|
||||
* @secure
|
||||
*/
|
||||
batchDelete = (data: number[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/dict-type/batch-delete`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags dict-type
|
||||
* @name SoftDelete
|
||||
* @summary 删除
|
||||
* @request DELETE:/api/admin/dict-type/soft-delete
|
||||
* @secure
|
||||
*/
|
||||
softDelete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/dict-type/soft-delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags dict-type
|
||||
* @name BatchSoftDelete
|
||||
* @summary 批量删除
|
||||
* @request PUT:/api/admin/dict-type/batch-soft-delete
|
||||
* @secure
|
||||
*/
|
||||
batchSoftDelete = (data: number[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/dict-type/batch-soft-delete`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,387 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { AxiosResponse } from 'axios'
|
||||
import {
|
||||
DocAddGroupInput,
|
||||
DocAddImageInput,
|
||||
DocAddMenuInput,
|
||||
DocUpdateContentInput,
|
||||
DocUpdateGroupInput,
|
||||
DocUpdateMenuInput,
|
||||
ResultOutputDocGetContentOutput,
|
||||
ResultOutputDocGetGroupOutput,
|
||||
ResultOutputDocGetMenuOutput,
|
||||
ResultOutputIEnumerableObject,
|
||||
ResultOutputInt64,
|
||||
ResultOutputListDocListOutput,
|
||||
ResultOutputListString,
|
||||
ResultOutputString,
|
||||
} from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class DocApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags doc
|
||||
* @name GetGroup
|
||||
* @summary 查询分组
|
||||
* @request GET:/api/admin/doc/get-group
|
||||
* @secure
|
||||
*/
|
||||
getGroup = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputDocGetGroupOutput, any>({
|
||||
path: `/api/admin/doc/get-group`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags doc
|
||||
* @name GetMenu
|
||||
* @summary 查询菜单
|
||||
* @request GET:/api/admin/doc/get-menu
|
||||
* @secure
|
||||
*/
|
||||
getMenu = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputDocGetMenuOutput, any>({
|
||||
path: `/api/admin/doc/get-menu`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags doc
|
||||
* @name GetContent
|
||||
* @summary 查询文档内容
|
||||
* @request GET:/api/admin/doc/get-content
|
||||
* @secure
|
||||
*/
|
||||
getContent = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputDocGetContentOutput, any>({
|
||||
path: `/api/admin/doc/get-content`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags doc
|
||||
* @name GetList
|
||||
* @summary 查询文档列表
|
||||
* @request GET:/api/admin/doc/get-list
|
||||
* @secure
|
||||
*/
|
||||
getList = (
|
||||
query?: {
|
||||
key?: string
|
||||
/** @format date-time */
|
||||
start?: string
|
||||
/** @format date-time */
|
||||
end?: string
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputListDocListOutput, any>({
|
||||
path: `/api/admin/doc/get-list`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags doc
|
||||
* @name GetImageList
|
||||
* @summary 查询图片列表
|
||||
* @request GET:/api/admin/doc/get-image-list
|
||||
* @secure
|
||||
*/
|
||||
getImageList = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputListString, any>({
|
||||
path: `/api/admin/doc/get-image-list`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags doc
|
||||
* @name AddGroup
|
||||
* @summary 新增分组
|
||||
* @request POST:/api/admin/doc/add-group
|
||||
* @secure
|
||||
*/
|
||||
addGroup = (data: DocAddGroupInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputInt64, any>({
|
||||
path: `/api/admin/doc/add-group`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags doc
|
||||
* @name AddMenu
|
||||
* @summary 新增菜单
|
||||
* @request POST:/api/admin/doc/add-menu
|
||||
* @secure
|
||||
*/
|
||||
addMenu = (data: DocAddMenuInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputInt64, any>({
|
||||
path: `/api/admin/doc/add-menu`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags doc
|
||||
* @name AddImage
|
||||
* @summary 新增图片
|
||||
* @request POST:/api/admin/doc/add-image
|
||||
* @secure
|
||||
*/
|
||||
addImage = (data: DocAddImageInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputInt64, any>({
|
||||
path: `/api/admin/doc/add-image`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags doc
|
||||
* @name UpdateGroup
|
||||
* @summary 修改分组
|
||||
* @request PUT:/api/admin/doc/update-group
|
||||
* @secure
|
||||
*/
|
||||
updateGroup = (data: DocUpdateGroupInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/doc/update-group`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags doc
|
||||
* @name UpdateMenu
|
||||
* @summary 修改菜单
|
||||
* @request PUT:/api/admin/doc/update-menu
|
||||
* @secure
|
||||
*/
|
||||
updateMenu = (data: DocUpdateMenuInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/doc/update-menu`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags doc
|
||||
* @name UpdateContent
|
||||
* @summary 修改文档内容
|
||||
* @request PUT:/api/admin/doc/update-content
|
||||
* @secure
|
||||
*/
|
||||
updateContent = (data: DocUpdateContentInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/doc/update-content`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags doc
|
||||
* @name Delete
|
||||
* @summary 彻底删除文档
|
||||
* @request DELETE:/api/admin/doc/delete
|
||||
* @secure
|
||||
*/
|
||||
delete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/doc/delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags doc
|
||||
* @name DeleteImage
|
||||
* @summary 彻底删除图片
|
||||
* @request DELETE:/api/admin/doc/delete-image
|
||||
* @secure
|
||||
*/
|
||||
deleteImage = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
documentId?: number
|
||||
url?: string
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/doc/delete-image`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags doc
|
||||
* @name SoftDelete
|
||||
* @summary 删除文档
|
||||
* @request DELETE:/api/admin/doc/soft-delete
|
||||
* @secure
|
||||
*/
|
||||
softDelete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/doc/soft-delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags doc
|
||||
* @name GetPlainList
|
||||
* @summary 查询精简文档列表
|
||||
* @request GET:/api/admin/doc/get-plain-list
|
||||
* @secure
|
||||
*/
|
||||
getPlainList = (params: RequestParams = {}) =>
|
||||
this.request<ResultOutputIEnumerableObject, any>({
|
||||
path: `/api/admin/doc/get-plain-list`,
|
||||
method: 'GET',
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags doc
|
||||
* @name UploadImage
|
||||
* @summary 上传文档图片
|
||||
* @request POST:/api/admin/doc/upload-image
|
||||
* @secure
|
||||
*/
|
||||
uploadImage = (
|
||||
data: {
|
||||
/**
|
||||
* 上传文件
|
||||
* @format binary
|
||||
*/
|
||||
File?: File
|
||||
/**
|
||||
* 文档编号
|
||||
* @format int64
|
||||
*/
|
||||
Id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputString, any>({
|
||||
path: `/api/admin/doc/upload-image`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.FormData,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,260 +0,0 @@
|
||||
import { AxiosResponse } from 'axios'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
// 提交反馈的输入参数
|
||||
export interface FeedbackSubmitInput {
|
||||
title: string
|
||||
feedbackType: any
|
||||
feedbackTeam: string
|
||||
feedbackPersonName: string
|
||||
feedbackPersonEmail: string
|
||||
relatedPersons: string
|
||||
content: string
|
||||
attachmentPaths: string
|
||||
}
|
||||
|
||||
// 获取反馈分页的输入参数
|
||||
export interface PageInputFeedbackGetPageInput {
|
||||
currentPage: number
|
||||
pageSize: number
|
||||
filter: {
|
||||
title?: string
|
||||
feedbackType?: any
|
||||
feedbackTeam?: string
|
||||
feedbackPersonName?: string
|
||||
status?: any
|
||||
createdTimeStart?: string
|
||||
createdTimeEnd?: string
|
||||
}
|
||||
dynamicFilter?: any
|
||||
}
|
||||
|
||||
// 反馈列表输出项
|
||||
export interface FeedbackGetPageOutput {
|
||||
id: number
|
||||
title: string
|
||||
feedbackType: any
|
||||
feedbackTypeName: string
|
||||
feedbackTeam: string
|
||||
feedbackPersonName: string
|
||||
feedbackPersonEmail: string
|
||||
status: any
|
||||
statusName: string
|
||||
processorName: string
|
||||
processTime: string
|
||||
contentSummary: string
|
||||
createdTime: string
|
||||
}
|
||||
|
||||
// 反馈详情输出
|
||||
export interface FeedbackGetOutput {
|
||||
id: number
|
||||
title: string
|
||||
feedbackType: any
|
||||
feedbackTypeName: string
|
||||
feedbackTeam: string
|
||||
feedbackPersonName: string
|
||||
feedbackPersonEmail: string
|
||||
status: any
|
||||
statusName: string
|
||||
processorName: string
|
||||
processTime: string
|
||||
contentSummary: string
|
||||
createdTime: string
|
||||
content: string
|
||||
relatedPersons: string
|
||||
attachmentPaths: string
|
||||
processRemark: string
|
||||
createdUserId: number
|
||||
createdUserName: string
|
||||
modifiedTime: string
|
||||
}
|
||||
|
||||
// 分页输出结果
|
||||
export interface PageOutputFeedbackGetPageOutput {
|
||||
total: number
|
||||
list: FeedbackGetPageOutput[]
|
||||
}
|
||||
|
||||
// 结果输出包装
|
||||
export interface ResultOutputPageOutputFeedbackGetPageOutput {
|
||||
success: boolean
|
||||
code: string
|
||||
msg: string
|
||||
data: PageOutputFeedbackGetPageOutput
|
||||
}
|
||||
|
||||
export interface ResultOutputFeedbackGetOutput {
|
||||
success: boolean
|
||||
code: string
|
||||
msg: string
|
||||
data: FeedbackGetOutput
|
||||
}
|
||||
|
||||
export interface ResultOutputInt64 {
|
||||
success: boolean
|
||||
code: string
|
||||
msg: string
|
||||
data: number
|
||||
}
|
||||
|
||||
// 标记处理状态的输入参数
|
||||
export interface FeedbackMarkInput {
|
||||
feedbackId: number
|
||||
processRemark: string
|
||||
}
|
||||
|
||||
// 团队负责人信息
|
||||
export interface TeamProcessorOutput {
|
||||
id: number
|
||||
teamName: string
|
||||
site: string
|
||||
processorId: number
|
||||
processorName: string
|
||||
processorEmail: string
|
||||
displayName: string
|
||||
}
|
||||
|
||||
export interface ResultOutputTeamProcessorOutput {
|
||||
success: boolean
|
||||
code: string
|
||||
msg: string
|
||||
data: TeamProcessorOutput[]
|
||||
}
|
||||
|
||||
export class FeedbackApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* @name submitFeedback
|
||||
* @summary 提交意见反馈
|
||||
* @request POST:/api/admin/feedback/submit-feedback
|
||||
* @secure
|
||||
*/
|
||||
submitFeedback = (data: FeedbackSubmitInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputInt64, any>({
|
||||
path: `/api/admin/feedback/submit-feedback`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* @name getPage
|
||||
* @summary 获取反馈分页列表(用户端)
|
||||
* @request POST:/api/admin/feedback/get-page
|
||||
* @secure
|
||||
*/
|
||||
getPage = (data: PageInputFeedbackGetPageInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputPageOutputFeedbackGetPageOutput, any>({
|
||||
path: `/api/admin/feedback/get-page`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* @name getPendingPage
|
||||
* @summary 获取待处理反馈列表(处理人端)
|
||||
* @request POST:/api/admin/feedback/get-pending-page
|
||||
* @secure
|
||||
*/
|
||||
getPendingPage = (data: PageInputFeedbackGetPageInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputPageOutputFeedbackGetPageOutput, any>({
|
||||
path: `/api/admin/feedback/get-pending-page`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* @name get
|
||||
* @summary 获取反馈详情
|
||||
* @request GET:/api/admin/feedback/get
|
||||
* @secure
|
||||
*/
|
||||
get = (
|
||||
query?: {
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputFeedbackGetOutput, any>({
|
||||
path: `/api/admin/feedback/get`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* @name markAsProcessing
|
||||
* @summary 标记为处理中
|
||||
* @request POST:/api/admin/feedback/mark-as-processing
|
||||
* @secure
|
||||
*/
|
||||
markAsProcessing = (data: FeedbackMarkInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/feedback/mark-as-processing`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* @name markAsCompleted
|
||||
* @summary 标记为已处理
|
||||
* @request POST:/api/admin/feedback/mark-as-completed
|
||||
* @secure
|
||||
*/
|
||||
markAsCompleted = (data: FeedbackMarkInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/feedback/mark-as-completed`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* @name markAsRejected
|
||||
* @summary 标记为已驳回
|
||||
* @request POST:/api/admin/feedback/mark-as-rejected
|
||||
* @secure
|
||||
*/
|
||||
markAsRejected = (data: FeedbackMarkInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/feedback/mark-as-rejected`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* @name getTeamProcessors
|
||||
* @summary 获取团队负责人列表(用于下拉选择)
|
||||
* @request GET:/api/admin/feedback/get-team-processors
|
||||
* @secure
|
||||
*/
|
||||
getTeamProcessors = (params: RequestParams = {}) =>
|
||||
this.request<ResultOutputTeamProcessorOutput, any>({
|
||||
path: `/api/admin/feedback/get-team-processors`,
|
||||
method: 'GET',
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,140 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { AxiosResponse } from 'axios'
|
||||
import {
|
||||
FileDeleteInput,
|
||||
PageInputFileGetPageInput,
|
||||
ResultOutputFileEntity,
|
||||
ResultOutputListFileEntity,
|
||||
ResultOutputPageOutputFileGetPageOutput,
|
||||
} from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class FileApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags file
|
||||
* @name GetPage
|
||||
* @summary 查询分页
|
||||
* @request POST:/api/admin/file/get-page
|
||||
* @secure
|
||||
*/
|
||||
getPage = (data: PageInputFileGetPageInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputPageOutputFileGetPageOutput, any>({
|
||||
path: `/api/admin/file/get-page`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags file
|
||||
* @name Delete
|
||||
* @summary 删除
|
||||
* @request POST:/api/admin/file/delete
|
||||
* @secure
|
||||
*/
|
||||
delete = (data: FileDeleteInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/file/delete`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags file
|
||||
* @name UploadFile
|
||||
* @summary 上传文件
|
||||
* @request POST:/api/admin/file/upload-file
|
||||
* @secure
|
||||
*/
|
||||
uploadFile = (
|
||||
data: {
|
||||
/**
|
||||
* 文件
|
||||
* @format binary
|
||||
*/
|
||||
file: File
|
||||
},
|
||||
query?: {
|
||||
/**
|
||||
* 文件目录
|
||||
* @default ""
|
||||
*/
|
||||
fileDirectory?: string
|
||||
/**
|
||||
* 文件重命名
|
||||
* @default true
|
||||
*/
|
||||
fileReName?: boolean
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputFileEntity, any>({
|
||||
path: `/api/admin/file/upload-file`,
|
||||
method: 'POST',
|
||||
query: query,
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.FormData,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags file
|
||||
* @name UploadFiles
|
||||
* @summary 上传多文件
|
||||
* @request POST:/api/admin/file/upload-files
|
||||
* @secure
|
||||
*/
|
||||
uploadFiles = (
|
||||
data: {
|
||||
/** 文件列表 */
|
||||
files: File[]
|
||||
},
|
||||
query?: {
|
||||
/**
|
||||
* 文件目录
|
||||
* @default ""
|
||||
*/
|
||||
fileDirectory?: string
|
||||
/**
|
||||
* 文件重命名
|
||||
* @default true
|
||||
*/
|
||||
fileReName?: boolean
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputListFileEntity, any>({
|
||||
path: `/api/admin/file/upload-files`,
|
||||
method: 'POST',
|
||||
query: query,
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.FormData,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { LoginLogAddInput, PageInputLoginLogGetPageInput, ResultOutputInt64, ResultOutputPageOutputLoginLogGetPageOutput } from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class LoginLogApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags login-log
|
||||
* @name GetPage
|
||||
* @summary 查询分页
|
||||
* @request POST:/api/admin/login-log/get-page
|
||||
* @secure
|
||||
*/
|
||||
getPage = (data: PageInputLoginLogGetPageInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputPageOutputLoginLogGetPageOutput, any>({
|
||||
path: `/api/admin/login-log/get-page`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags login-log
|
||||
* @name Add
|
||||
* @summary 新增
|
||||
* @request POST:/api/admin/login-log/add
|
||||
* @secure
|
||||
*/
|
||||
add = (data: LoginLogAddInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputInt64, any>({
|
||||
path: `/api/admin/login-log/add`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,254 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { AxiosResponse } from 'axios'
|
||||
import {
|
||||
MsgAddInput,
|
||||
MsgAddMsgUserListInput,
|
||||
MsgUpdateInput,
|
||||
PageInputMsgGetPageInput,
|
||||
ResultOutputInt64,
|
||||
ResultOutputListMsgGetMsgUserListOutput,
|
||||
ResultOutputMsgGetOutput,
|
||||
ResultOutputPageOutputMsgGetPageOutput,
|
||||
} from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class MsgApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags msg
|
||||
* @name Get
|
||||
* @summary 查询
|
||||
* @request GET:/api/admin/msg/get
|
||||
* @secure
|
||||
*/
|
||||
get = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputMsgGetOutput, any>({
|
||||
path: `/api/admin/msg/get`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags msg
|
||||
* @name GetPage
|
||||
* @summary 查询分页
|
||||
* @request POST:/api/admin/msg/get-page
|
||||
* @secure
|
||||
*/
|
||||
getPage = (data: PageInputMsgGetPageInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputPageOutputMsgGetPageOutput, any>({
|
||||
path: `/api/admin/msg/get-page`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags msg
|
||||
* @name GetMsgUserList
|
||||
* @summary 查询消息用户列表
|
||||
* @request GET:/api/admin/msg/get-msg-user-list
|
||||
* @secure
|
||||
*/
|
||||
getMsgUserList = (
|
||||
query?: {
|
||||
/**
|
||||
* 消息Id
|
||||
* @format int64
|
||||
*/
|
||||
MsgId?: number
|
||||
/** 姓名 */
|
||||
Name?: string
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputListMsgGetMsgUserListOutput, any>({
|
||||
path: `/api/admin/msg/get-msg-user-list`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags msg
|
||||
* @name AddMsgUser
|
||||
* @summary 添加消息用户
|
||||
* @request POST:/api/admin/msg/add-msg-user
|
||||
* @secure
|
||||
*/
|
||||
addMsgUser = (data: MsgAddMsgUserListInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/msg/add-msg-user`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags msg
|
||||
* @name RemoveMsgUser
|
||||
* @summary 移除消息用户
|
||||
* @request POST:/api/admin/msg/remove-msg-user
|
||||
* @secure
|
||||
*/
|
||||
removeMsgUser = (data: MsgAddMsgUserListInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/msg/remove-msg-user`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags msg
|
||||
* @name Add
|
||||
* @summary 新增
|
||||
* @request POST:/api/admin/msg/add
|
||||
* @secure
|
||||
*/
|
||||
add = (data: MsgAddInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputInt64, any>({
|
||||
path: `/api/admin/msg/add`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags msg
|
||||
* @name Update
|
||||
* @summary 修改
|
||||
* @request PUT:/api/admin/msg/update
|
||||
* @secure
|
||||
*/
|
||||
update = (data: MsgUpdateInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/msg/update`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags msg
|
||||
* @name Delete
|
||||
* @summary 彻底删除
|
||||
* @request DELETE:/api/admin/msg/delete
|
||||
* @secure
|
||||
*/
|
||||
delete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/msg/delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags msg
|
||||
* @name BatchDelete
|
||||
* @summary 批量彻底删除
|
||||
* @request PUT:/api/admin/msg/batch-delete
|
||||
* @secure
|
||||
*/
|
||||
batchDelete = (data: number[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/msg/batch-delete`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags msg
|
||||
* @name SoftDelete
|
||||
* @summary 删除
|
||||
* @request DELETE:/api/admin/msg/soft-delete
|
||||
* @secure
|
||||
*/
|
||||
softDelete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/msg/soft-delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags msg
|
||||
* @name BatchSoftDelete
|
||||
* @summary 批量删除
|
||||
* @request PUT:/api/admin/msg/batch-soft-delete
|
||||
* @secure
|
||||
*/
|
||||
batchSoftDelete = (data: number[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/msg/batch-soft-delete`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,191 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { AxiosResponse } from 'axios'
|
||||
import {
|
||||
MsgTypeAddInput,
|
||||
MsgTypeUpdateInput,
|
||||
ResultOutputInt64,
|
||||
ResultOutputListMsgTypeGetListOutput,
|
||||
ResultOutputMsgTypeGetOutput,
|
||||
} from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class MsgTypeApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags msg-type
|
||||
* @name Get
|
||||
* @summary 查询
|
||||
* @request GET:/api/admin/msg-type/get
|
||||
* @secure
|
||||
*/
|
||||
get = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputMsgTypeGetOutput, any>({
|
||||
path: `/api/admin/msg-type/get`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags msg-type
|
||||
* @name GetList
|
||||
* @summary 查询列表
|
||||
* @request GET:/api/admin/msg-type/get-list
|
||||
* @secure
|
||||
*/
|
||||
getList = (
|
||||
query?: {
|
||||
/** 名称 */
|
||||
Name?: string
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputListMsgTypeGetListOutput, any>({
|
||||
path: `/api/admin/msg-type/get-list`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags msg-type
|
||||
* @name Add
|
||||
* @summary 新增
|
||||
* @request POST:/api/admin/msg-type/add
|
||||
* @secure
|
||||
*/
|
||||
add = (data: MsgTypeAddInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputInt64, any>({
|
||||
path: `/api/admin/msg-type/add`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags msg-type
|
||||
* @name Update
|
||||
* @summary 修改
|
||||
* @request PUT:/api/admin/msg-type/update
|
||||
* @secure
|
||||
*/
|
||||
update = (data: MsgTypeUpdateInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/msg-type/update`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags msg-type
|
||||
* @name Delete
|
||||
* @summary 彻底删除
|
||||
* @request DELETE:/api/admin/msg-type/delete
|
||||
* @secure
|
||||
*/
|
||||
delete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/msg-type/delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags msg-type
|
||||
* @name BatchDelete
|
||||
* @summary 批量彻底删除
|
||||
* @request PUT:/api/admin/msg-type/batch-delete
|
||||
* @secure
|
||||
*/
|
||||
batchDelete = (data: number[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/msg-type/batch-delete`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags msg-type
|
||||
* @name SoftDelete
|
||||
* @summary 删除
|
||||
* @request DELETE:/api/admin/msg-type/soft-delete
|
||||
* @secure
|
||||
*/
|
||||
softDelete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/msg-type/soft-delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags msg-type
|
||||
* @name BatchSoftDelete
|
||||
* @summary 批量删除
|
||||
* @request PUT:/api/admin/msg-type/batch-soft-delete
|
||||
* @secure
|
||||
*/
|
||||
batchSoftDelete = (data: number[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/msg-type/batch-soft-delete`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,148 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { AxiosResponse } from 'axios'
|
||||
import {
|
||||
OnlineAddInput,
|
||||
OnlineUpdateInput,
|
||||
PageInputOnlineGetPageInput,
|
||||
ResultOutputOnlineGetOutput,
|
||||
ResultOutputPageOutputOnlineGetPageOutput,
|
||||
} from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class OnlineApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags online
|
||||
* @name Get
|
||||
* @summary 查询在线教程
|
||||
* @request GET:/api/admin/online/get
|
||||
* @secure
|
||||
*/
|
||||
get = (
|
||||
query?: {
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputOnlineGetOutput, any>({
|
||||
path: `/api/admin/online/get`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags online
|
||||
* @name GetPage
|
||||
* @summary 查询分页
|
||||
* @request POST:/api/admin/online/get-page
|
||||
* @secure
|
||||
*/
|
||||
getPage = (data: PageInputOnlineGetPageInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputPageOutputOnlineGetPageOutput, any>({
|
||||
path: `/api/admin/online/get-page`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags online
|
||||
* @name GetList
|
||||
* @summary
|
||||
* @request POST:/api/admin/online/get-list
|
||||
* @secure
|
||||
*/
|
||||
getList = (data: string[], params: RequestParams = {}) =>
|
||||
this.request<ResultOutputListOutputOnlineGetListOutput, any>({
|
||||
path: `/api/admin/online/get-list`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags online
|
||||
* @name Add
|
||||
* @summary 新增
|
||||
* @request POST:/api/admin/online/add
|
||||
* @secure
|
||||
*/
|
||||
add = (data: OnlineAddInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/online/add`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags online
|
||||
* @name Update
|
||||
* @summary 修改
|
||||
* @request PUT:/api/admin/online/update
|
||||
* @secure
|
||||
*/
|
||||
update = (data: OnlineUpdateInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/online/update`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags online
|
||||
* @name Delete
|
||||
* @summary 删除
|
||||
* @request DELETE:/api/admin/online/delete
|
||||
* @secure
|
||||
*/
|
||||
delete = (
|
||||
query: {
|
||||
id: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/online/delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,60 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import {
|
||||
OperationLogAddInput,
|
||||
PageInputOperationLogGetPageInput,
|
||||
ResultOutputInt64,
|
||||
ResultOutputPageOutputOperationLogGetPageOutput,
|
||||
} from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class OperationLogApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags operation-log
|
||||
* @name GetPage
|
||||
* @summary 查询分页
|
||||
* @request POST:/api/admin/operation-log/get-page
|
||||
* @secure
|
||||
*/
|
||||
getPage = (data: PageInputOperationLogGetPageInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputPageOutputOperationLogGetPageOutput, any>({
|
||||
path: `/api/admin/operation-log/get-page`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags operation-log
|
||||
* @name Add
|
||||
* @summary 新增
|
||||
* @request POST:/api/admin/operation-log/add
|
||||
* @secure
|
||||
*/
|
||||
add = (data: OperationLogAddInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputInt64, any>({
|
||||
path: `/api/admin/operation-log/add`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,172 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { AxiosResponse } from 'axios'
|
||||
import {
|
||||
OrgAddInput,
|
||||
OrgUpdateInput,
|
||||
ResultOutputInt64,
|
||||
ResultOutputListOrgGetListOutput,
|
||||
ResultOutputListOrgGetSimpleListWithPathOutput,
|
||||
ResultOutputOrgGetOutput,
|
||||
} from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class OrgApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags org
|
||||
* @name Get
|
||||
* @summary 查询
|
||||
* @request GET:/api/admin/org/get
|
||||
* @secure
|
||||
*/
|
||||
get = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputOrgGetOutput, any>({
|
||||
path: `/api/admin/org/get`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags org
|
||||
* @name GetList
|
||||
* @summary 查询列表
|
||||
* @request GET:/api/admin/org/get-list
|
||||
* @secure
|
||||
*/
|
||||
getList = (
|
||||
query?: {
|
||||
key?: string
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputListOrgGetListOutput, any>({
|
||||
path: `/api/admin/org/get-list`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags org
|
||||
* @name GetSimpleListWithPath
|
||||
* @summary 获取部门路径列表
|
||||
* @request GET:/api/admin/org/get-simple-list-with-path
|
||||
* @secure
|
||||
*/
|
||||
getSimpleListWithPath = (params: RequestParams = {}) =>
|
||||
this.request<ResultOutputListOrgGetSimpleListWithPathOutput, any>({
|
||||
path: `/api/admin/org/get-simple-list-with-path`,
|
||||
method: 'GET',
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags org
|
||||
* @name Add
|
||||
* @summary 新增
|
||||
* @request POST:/api/admin/org/add
|
||||
* @secure
|
||||
*/
|
||||
add = (data: OrgAddInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputInt64, any>({
|
||||
path: `/api/admin/org/add`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags org
|
||||
* @name Update
|
||||
* @summary 修改
|
||||
* @request PUT:/api/admin/org/update
|
||||
* @secure
|
||||
*/
|
||||
update = (data: OrgUpdateInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/org/update`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags org
|
||||
* @name Delete
|
||||
* @summary 彻底删除
|
||||
* @request DELETE:/api/admin/org/delete
|
||||
* @secure
|
||||
*/
|
||||
delete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/org/delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags org
|
||||
* @name SoftDelete
|
||||
* @summary 删除
|
||||
* @request DELETE:/api/admin/org/soft-delete
|
||||
* @secure
|
||||
*/
|
||||
softDelete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/org/soft-delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,347 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { AxiosResponse } from 'axios'
|
||||
import {
|
||||
PageInputPkgGetPageInput,
|
||||
PageInputPkgGetPkgTenantListInput,
|
||||
PkgAddInput,
|
||||
PkgAddPkgTenantListInput,
|
||||
PkgSetPkgPermissionsInput,
|
||||
PkgUpdateInput,
|
||||
ResultOutputInt64,
|
||||
ResultOutputListInt64,
|
||||
ResultOutputListPkgGetListOutput,
|
||||
ResultOutputListPkgGetPkgTenantListOutput,
|
||||
ResultOutputPageOutputPkgGetPageOutput,
|
||||
ResultOutputPageOutputPkgGetPkgTenantListOutput,
|
||||
ResultOutputPkgGetOutput,
|
||||
} from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class PkgApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags pkg
|
||||
* @name Get
|
||||
* @summary 查询
|
||||
* @request GET:/api/admin/pkg/get
|
||||
* @secure
|
||||
*/
|
||||
get = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputPkgGetOutput, any>({
|
||||
path: `/api/admin/pkg/get`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags pkg
|
||||
* @name GetList
|
||||
* @summary 查询列表
|
||||
* @request GET:/api/admin/pkg/get-list
|
||||
* @secure
|
||||
*/
|
||||
getList = (
|
||||
query?: {
|
||||
/** 名称 */
|
||||
Name?: string
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputListPkgGetListOutput, any>({
|
||||
path: `/api/admin/pkg/get-list`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags pkg
|
||||
* @name GetPage
|
||||
* @summary 查询分页
|
||||
* @request POST:/api/admin/pkg/get-page
|
||||
* @secure
|
||||
*/
|
||||
getPage = (data: PageInputPkgGetPageInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputPageOutputPkgGetPageOutput, any>({
|
||||
path: `/api/admin/pkg/get-page`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags pkg
|
||||
* @name GetPkgTenantList
|
||||
* @summary 查询套餐租户列表
|
||||
* @request GET:/api/admin/pkg/get-pkg-tenant-list
|
||||
* @secure
|
||||
*/
|
||||
getPkgTenantList = (
|
||||
query?: {
|
||||
/** 租户名 */
|
||||
TenantName?: string
|
||||
/**
|
||||
* 套餐Id
|
||||
* @format int64
|
||||
*/
|
||||
PkgId?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputListPkgGetPkgTenantListOutput, any>({
|
||||
path: `/api/admin/pkg/get-pkg-tenant-list`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags pkg
|
||||
* @name GetPkgTenantPage
|
||||
* @summary 查询套餐租户分页
|
||||
* @request POST:/api/admin/pkg/get-pkg-tenant-page
|
||||
* @secure
|
||||
*/
|
||||
getPkgTenantPage = (data: PageInputPkgGetPkgTenantListInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputPageOutputPkgGetPkgTenantListOutput, any>({
|
||||
path: `/api/admin/pkg/get-pkg-tenant-page`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags pkg
|
||||
* @name GetPkgPermissionList
|
||||
* @summary 查询套餐权限列表
|
||||
* @request GET:/api/admin/pkg/get-pkg-permission-list
|
||||
* @secure
|
||||
*/
|
||||
getPkgPermissionList = (
|
||||
query?: {
|
||||
/**
|
||||
* 套餐编号
|
||||
* @format int64
|
||||
*/
|
||||
pkgId?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputListInt64, any>({
|
||||
path: `/api/admin/pkg/get-pkg-permission-list`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags pkg
|
||||
* @name SetPkgPermissions
|
||||
* @summary 设置套餐权限
|
||||
* @request POST:/api/admin/pkg/set-pkg-permissions
|
||||
* @secure
|
||||
*/
|
||||
setPkgPermissions = (data: PkgSetPkgPermissionsInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/pkg/set-pkg-permissions`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags pkg
|
||||
* @name AddPkgTenant
|
||||
* @summary 添加套餐租户
|
||||
* @request POST:/api/admin/pkg/add-pkg-tenant
|
||||
* @secure
|
||||
*/
|
||||
addPkgTenant = (data: PkgAddPkgTenantListInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/pkg/add-pkg-tenant`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags pkg
|
||||
* @name RemovePkgTenant
|
||||
* @summary 移除套餐租户
|
||||
* @request POST:/api/admin/pkg/remove-pkg-tenant
|
||||
* @secure
|
||||
*/
|
||||
removePkgTenant = (data: PkgAddPkgTenantListInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/pkg/remove-pkg-tenant`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags pkg
|
||||
* @name Add
|
||||
* @summary 新增
|
||||
* @request POST:/api/admin/pkg/add
|
||||
* @secure
|
||||
*/
|
||||
add = (data: PkgAddInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputInt64, any>({
|
||||
path: `/api/admin/pkg/add`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags pkg
|
||||
* @name Update
|
||||
* @summary 修改
|
||||
* @request PUT:/api/admin/pkg/update
|
||||
* @secure
|
||||
*/
|
||||
update = (data: PkgUpdateInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/pkg/update`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags pkg
|
||||
* @name Delete
|
||||
* @summary 彻底删除
|
||||
* @request DELETE:/api/admin/pkg/delete
|
||||
* @secure
|
||||
*/
|
||||
delete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/pkg/delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags pkg
|
||||
* @name BatchDelete
|
||||
* @summary 批量彻底删除
|
||||
* @request PUT:/api/admin/pkg/batch-delete
|
||||
* @secure
|
||||
*/
|
||||
batchDelete = (data: number[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/pkg/batch-delete`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags pkg
|
||||
* @name SoftDelete
|
||||
* @summary 删除
|
||||
* @request DELETE:/api/admin/pkg/soft-delete
|
||||
* @secure
|
||||
*/
|
||||
softDelete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/pkg/soft-delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags pkg
|
||||
* @name BatchSoftDelete
|
||||
* @summary 批量删除
|
||||
* @request PUT:/api/admin/pkg/batch-soft-delete
|
||||
* @secure
|
||||
*/
|
||||
batchSoftDelete = (data: number[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/pkg/batch-soft-delete`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,250 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { AxiosResponse } from 'axios'
|
||||
import {
|
||||
PageInputPrintTemplateGetPageInput,
|
||||
PrintTemplateAddInput,
|
||||
PrintTemplateSetEnableInput,
|
||||
PrintTemplateUpdateInput,
|
||||
PrintTemplateUpdateTemplateInput,
|
||||
ResultOutputInt64,
|
||||
ResultOutputPageOutputPrintTemplateGetPageOutput,
|
||||
ResultOutputPrintTemplateGetOutput,
|
||||
ResultOutputPrintTemplateGetUpdateTemplateOutput,
|
||||
} from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class PrintTemplateApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags print-template
|
||||
* @name Get
|
||||
* @summary 查询
|
||||
* @request GET:/api/admin/print-template/get
|
||||
* @secure
|
||||
*/
|
||||
get = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputPrintTemplateGetOutput, any>({
|
||||
path: `/api/admin/print-template/get`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags print-template
|
||||
* @name GetUpdateTemplate
|
||||
* @summary 查询修改模板
|
||||
* @request GET:/api/admin/print-template/get-update-template
|
||||
* @secure
|
||||
*/
|
||||
getUpdateTemplate = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputPrintTemplateGetUpdateTemplateOutput, any>({
|
||||
path: `/api/admin/print-template/get-update-template`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags print-template
|
||||
* @name GetPage
|
||||
* @summary 查询分页
|
||||
* @request POST:/api/admin/print-template/get-page
|
||||
* @secure
|
||||
*/
|
||||
getPage = (data: PageInputPrintTemplateGetPageInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputPageOutputPrintTemplateGetPageOutput, any>({
|
||||
path: `/api/admin/print-template/get-page`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags print-template
|
||||
* @name Add
|
||||
* @summary 新增
|
||||
* @request POST:/api/admin/print-template/add
|
||||
* @secure
|
||||
*/
|
||||
add = (data: PrintTemplateAddInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputInt64, any>({
|
||||
path: `/api/admin/print-template/add`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags print-template
|
||||
* @name Update
|
||||
* @summary 修改
|
||||
* @request PUT:/api/admin/print-template/update
|
||||
* @secure
|
||||
*/
|
||||
update = (data: PrintTemplateUpdateInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/print-template/update`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags print-template
|
||||
* @name UpdateTemplate
|
||||
* @summary 修改模板
|
||||
* @request PUT:/api/admin/print-template/update-template
|
||||
* @secure
|
||||
*/
|
||||
updateTemplate = (data: PrintTemplateUpdateTemplateInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/print-template/update-template`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags print-template
|
||||
* @name SetEnable
|
||||
* @summary 设置启用
|
||||
* @request POST:/api/admin/print-template/set-enable
|
||||
* @secure
|
||||
*/
|
||||
setEnable = (data: PrintTemplateSetEnableInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/print-template/set-enable`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags print-template
|
||||
* @name Delete
|
||||
* @summary 彻底删除
|
||||
* @request DELETE:/api/admin/print-template/delete
|
||||
* @secure
|
||||
*/
|
||||
delete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/print-template/delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags print-template
|
||||
* @name BatchDelete
|
||||
* @summary 批量彻底删除
|
||||
* @request PUT:/api/admin/print-template/batch-delete
|
||||
* @secure
|
||||
*/
|
||||
batchDelete = (data: number[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/print-template/batch-delete`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags print-template
|
||||
* @name SoftDelete
|
||||
* @summary 删除
|
||||
* @request DELETE:/api/admin/print-template/soft-delete
|
||||
* @secure
|
||||
*/
|
||||
softDelete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/print-template/soft-delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags print-template
|
||||
* @name BatchSoftDelete
|
||||
* @summary 批量删除
|
||||
* @request PUT:/api/admin/print-template/batch-soft-delete
|
||||
* @secure
|
||||
*/
|
||||
batchSoftDelete = (data: number[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/print-template/batch-soft-delete`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,229 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { AxiosResponse } from 'axios'
|
||||
import {
|
||||
PageInputRegionGetPageInput,
|
||||
RegionAddInput,
|
||||
RegionGetListInput,
|
||||
RegionLevel,
|
||||
RegionSetEnableInput,
|
||||
RegionSetHotInput,
|
||||
RegionUpdateInput,
|
||||
ResultOutputInt64,
|
||||
ResultOutputListRegionGetChildListOutput,
|
||||
ResultOutputPageOutputRegionGetPageOutput,
|
||||
ResultOutputRegionGetOutput,
|
||||
} from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class RegionApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags region
|
||||
* @name Get
|
||||
* @summary 查询
|
||||
* @request GET:/api/admin/region/get
|
||||
* @secure
|
||||
*/
|
||||
get = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputRegionGetOutput, any>({
|
||||
path: `/api/admin/region/get`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags region
|
||||
* @name GetChildList
|
||||
* @summary 查询下级列表
|
||||
* @request POST:/api/admin/region/get-child-list
|
||||
* @secure
|
||||
*/
|
||||
getChildList = (data: RegionGetListInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputListRegionGetChildListOutput, any>({
|
||||
path: `/api/admin/region/get-child-list`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags region
|
||||
* @name GetPage
|
||||
* @summary 查询分页
|
||||
* @request POST:/api/admin/region/get-page
|
||||
* @secure
|
||||
*/
|
||||
getPage = (data: PageInputRegionGetPageInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputPageOutputRegionGetPageOutput, any>({
|
||||
path: `/api/admin/region/get-page`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags region
|
||||
* @name Add
|
||||
* @summary 新增
|
||||
* @request POST:/api/admin/region/add
|
||||
* @secure
|
||||
*/
|
||||
add = (data: RegionAddInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputInt64, any>({
|
||||
path: `/api/admin/region/add`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags region
|
||||
* @name Update
|
||||
* @summary 修改
|
||||
* @request PUT:/api/admin/region/update
|
||||
* @secure
|
||||
*/
|
||||
update = (data: RegionUpdateInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/region/update`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags region
|
||||
* @name Delete
|
||||
* @summary 彻底删除
|
||||
* @request DELETE:/api/admin/region/delete
|
||||
* @secure
|
||||
*/
|
||||
delete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/region/delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags region
|
||||
* @name SoftDelete
|
||||
* @summary 删除
|
||||
* @request DELETE:/api/admin/region/soft-delete
|
||||
* @secure
|
||||
*/
|
||||
softDelete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/region/soft-delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags region
|
||||
* @name SetEnable
|
||||
* @summary 设置启用
|
||||
* @request POST:/api/admin/region/set-enable
|
||||
* @secure
|
||||
*/
|
||||
setEnable = (data: RegionSetEnableInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/region/set-enable`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags region
|
||||
* @name SetHot
|
||||
* @summary 设置热门
|
||||
* @request POST:/api/admin/region/set-hot
|
||||
* @secure
|
||||
*/
|
||||
setHot = (data: RegionSetHotInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/region/set-hot`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags region
|
||||
* @name SyncData
|
||||
* @summary 同步数据
|
||||
* @request POST:/api/admin/region/sync-data
|
||||
* @secure
|
||||
*/
|
||||
syncData = (data: RegionLevel, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/region/sync-data`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,154 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { AxiosResponse } from 'axios'
|
||||
import {
|
||||
RemoteAddInput,
|
||||
RemoteUpdateInput,
|
||||
PageInputRemoteGetPageInput,
|
||||
ResultOutputRemoteGetOutput,
|
||||
ResultOutputInt64,
|
||||
ResultOutputPageOutputRemoteGetPageOutput,
|
||||
RemoteConnectInput,
|
||||
ResultOutputRemoteConnectOutput
|
||||
} from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class RemoteApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags remote
|
||||
* @name Get
|
||||
* @summary 查询Remote
|
||||
* @request GET:/api/admin/remote/get
|
||||
* @secure
|
||||
*/
|
||||
get = (
|
||||
query?: {
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputRemoteGetOutput, any>({
|
||||
path: `/api/admin/remote/get`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags remote
|
||||
* @name GetPage
|
||||
* @summary 查询分页
|
||||
* @request POST:/api/admin/remote/get-page
|
||||
* @secure
|
||||
*/
|
||||
getPage = (data: PageInputRemoteGetPageInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputPageOutputRemoteGetPageOutput, any>({
|
||||
path: `/api/admin/remote/get-page`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags remote
|
||||
* @name Add
|
||||
* @summary 新增
|
||||
* @request POST:/api/admin/remote/add
|
||||
* @secure
|
||||
*/
|
||||
add = (data: RemoteAddInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputRemoteGetOutput, any>({
|
||||
path: `/api/admin/remote/add`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags remote
|
||||
* @name Update
|
||||
* @summary 修改
|
||||
* @request PUT:/api/admin/remote/update
|
||||
* @secure
|
||||
*/
|
||||
update = (data: RemoteUpdateInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputRemoteGetOutput, any>({
|
||||
path: `/api/admin/remote/update`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags remote
|
||||
* @name Delete
|
||||
* @summary 删除
|
||||
* @request DELETE:/api/admin/remote/delete
|
||||
* @secure
|
||||
*/
|
||||
delete = (
|
||||
query?: {
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputRemoteGetOutput, any>({
|
||||
path: `/api/admin/remote/delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags remote
|
||||
* @name Connect
|
||||
* @summary 连接远程设备
|
||||
* @request POST:/api/admin/remote/connect
|
||||
* @secure
|
||||
*/
|
||||
connect = (data: RemoteConnectInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputRemoteConnectOutput, any>({
|
||||
path: `/api/admin/remote/remote-connect`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,298 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { AxiosResponse } from 'axios'
|
||||
import {
|
||||
PageInputRoleGetPageInput,
|
||||
ResultOutputInt64,
|
||||
ResultOutputListRoleGetListOutput,
|
||||
ResultOutputListRoleGetRoleUserListOutput,
|
||||
ResultOutputPageOutputRoleGetPageOutput,
|
||||
ResultOutputRoleGetOutput,
|
||||
RoleAddInput,
|
||||
RoleAddRoleUserListInput,
|
||||
RoleSetDataScopeInput,
|
||||
RoleUpdateInput,
|
||||
} from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class RoleApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags role
|
||||
* @name Get
|
||||
* @summary 查询
|
||||
* @request GET:/api/admin/role/get
|
||||
* @secure
|
||||
*/
|
||||
get = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputRoleGetOutput, any>({
|
||||
path: `/api/admin/role/get`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags role
|
||||
* @name GetList
|
||||
* @summary 查询列表
|
||||
* @request GET:/api/admin/role/get-list
|
||||
* @secure
|
||||
*/
|
||||
getList = (
|
||||
query?: {
|
||||
/** 名称 */
|
||||
Name?: string
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputListRoleGetListOutput, any>({
|
||||
path: `/api/admin/role/get-list`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags role
|
||||
* @name GetPage
|
||||
* @summary 查询分页
|
||||
* @request POST:/api/admin/role/get-page
|
||||
* @secure
|
||||
*/
|
||||
getPage = (data: PageInputRoleGetPageInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputPageOutputRoleGetPageOutput, any>({
|
||||
path: `/api/admin/role/get-page`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags role
|
||||
* @name GetRoleUserList
|
||||
* @summary 查询角色用户列表
|
||||
* @request GET:/api/admin/role/get-role-user-list
|
||||
* @secure
|
||||
*/
|
||||
getRoleUserList = (
|
||||
query?: {
|
||||
/** 姓名 */
|
||||
Name?: string
|
||||
/**
|
||||
* 角色Id
|
||||
* @format int64
|
||||
*/
|
||||
RoleId?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputListRoleGetRoleUserListOutput, any>({
|
||||
path: `/api/admin/role/get-role-user-list`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags role
|
||||
* @name AddRoleUser
|
||||
* @summary 添加角色用户
|
||||
* @request POST:/api/admin/role/add-role-user
|
||||
* @secure
|
||||
*/
|
||||
addRoleUser = (data: RoleAddRoleUserListInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/role/add-role-user`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags role
|
||||
* @name RemoveRoleUser
|
||||
* @summary 移除角色用户
|
||||
* @request POST:/api/admin/role/remove-role-user
|
||||
* @secure
|
||||
*/
|
||||
removeRoleUser = (data: RoleAddRoleUserListInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/role/remove-role-user`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags role
|
||||
* @name Add
|
||||
* @summary 新增
|
||||
* @request POST:/api/admin/role/add
|
||||
* @secure
|
||||
*/
|
||||
add = (data: RoleAddInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputInt64, any>({
|
||||
path: `/api/admin/role/add`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags role
|
||||
* @name Update
|
||||
* @summary 修改
|
||||
* @request PUT:/api/admin/role/update
|
||||
* @secure
|
||||
*/
|
||||
update = (data: RoleUpdateInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/role/update`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags role
|
||||
* @name Delete
|
||||
* @summary 彻底删除
|
||||
* @request DELETE:/api/admin/role/delete
|
||||
* @secure
|
||||
*/
|
||||
delete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/role/delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags role
|
||||
* @name BatchDelete
|
||||
* @summary 批量彻底删除
|
||||
* @request PUT:/api/admin/role/batch-delete
|
||||
* @secure
|
||||
*/
|
||||
batchDelete = (data: number[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/role/batch-delete`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags role
|
||||
* @name SoftDelete
|
||||
* @summary 删除
|
||||
* @request DELETE:/api/admin/role/soft-delete
|
||||
* @secure
|
||||
*/
|
||||
softDelete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/role/soft-delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags role
|
||||
* @name BatchSoftDelete
|
||||
* @summary 批量删除
|
||||
* @request PUT:/api/admin/role/batch-soft-delete
|
||||
* @secure
|
||||
*/
|
||||
batchSoftDelete = (data: number[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/role/batch-soft-delete`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags role
|
||||
* @name SetDataScope
|
||||
* @summary 设置数据权限
|
||||
* @request POST:/api/admin/role/set-data-scope
|
||||
* @secure
|
||||
*/
|
||||
setDataScope = (data: RoleSetDataScopeInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/role/set-data-scope`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,113 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { AxiosResponse } from 'axios'
|
||||
import {
|
||||
ResultOutputInt64,
|
||||
ResultOutputListSearchTemplateGetListOutput,
|
||||
ResultOutputSearchTemplateGetUpdateOutput,
|
||||
SearchTemplateSaveInput,
|
||||
} from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class SearchTemplateApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags search-template
|
||||
* @name Get
|
||||
* @summary 查询
|
||||
* @request GET:/api/admin/search-template/get
|
||||
* @secure
|
||||
*/
|
||||
get = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputSearchTemplateGetUpdateOutput, any>({
|
||||
path: `/api/admin/search-template/get`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags search-template
|
||||
* @name GetList
|
||||
* @summary 查询列表
|
||||
* @request GET:/api/admin/search-template/get-list
|
||||
* @secure
|
||||
*/
|
||||
getList = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
moduleId?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputListSearchTemplateGetListOutput, any>({
|
||||
path: `/api/admin/search-template/get-list`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags search-template
|
||||
* @name Save
|
||||
* @summary 保存
|
||||
* @request POST:/api/admin/search-template/save
|
||||
* @secure
|
||||
*/
|
||||
save = (data: SearchTemplateSaveInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputInt64, any>({
|
||||
path: `/api/admin/search-template/save`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags search-template
|
||||
* @name Delete
|
||||
* @summary 彻底删除
|
||||
* @request DELETE:/api/admin/search-template/delete
|
||||
* @secure
|
||||
*/
|
||||
delete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/search-template/delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,181 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { AxiosResponse } from 'axios'
|
||||
import {
|
||||
PageInputSiteMsgGetPageInput,
|
||||
ResultOutputBoolean,
|
||||
ResultOutputPageOutputSiteMsgGetPageOutput,
|
||||
ResultOutputSiteMsgGetContentOutput,
|
||||
} from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class SiteMsgApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags site-msg
|
||||
* @name GetContent
|
||||
* @summary 获得内容
|
||||
* @request GET:/api/admin/site-msg/get-content
|
||||
* @secure
|
||||
*/
|
||||
getContent = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputSiteMsgGetContentOutput, any>({
|
||||
path: `/api/admin/site-msg/get-content`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags site-msg
|
||||
* @name GetPage
|
||||
* @summary 查询分页
|
||||
* @request POST:/api/admin/site-msg/get-page
|
||||
* @secure
|
||||
*/
|
||||
getPage = (data: PageInputSiteMsgGetPageInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputPageOutputSiteMsgGetPageOutput, any>({
|
||||
path: `/api/admin/site-msg/get-page`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags site-msg
|
||||
* @name IsUnread
|
||||
* @summary 是否未读
|
||||
* @request GET:/api/admin/site-msg/is-unread
|
||||
* @secure
|
||||
*/
|
||||
isUnread = (params: RequestParams = {}) =>
|
||||
this.request<ResultOutputBoolean, any>({
|
||||
path: `/api/admin/site-msg/is-unread`,
|
||||
method: 'GET',
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags site-msg
|
||||
* @name SetAllRead
|
||||
* @summary 全部标为已读
|
||||
* @request POST:/api/admin/site-msg/set-all-read
|
||||
* @secure
|
||||
*/
|
||||
setAllRead = (params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/site-msg/set-all-read`,
|
||||
method: 'POST',
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags site-msg
|
||||
* @name SetRead
|
||||
* @summary 标为已读
|
||||
* @request POST:/api/admin/site-msg/set-read
|
||||
* @secure
|
||||
*/
|
||||
setRead = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/site-msg/set-read`,
|
||||
method: 'POST',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags site-msg
|
||||
* @name BatchSetRead
|
||||
* @summary 批量标为已读
|
||||
* @request POST:/api/admin/site-msg/batch-set-read
|
||||
* @secure
|
||||
*/
|
||||
batchSetRead = (data: number[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/site-msg/batch-set-read`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags site-msg
|
||||
* @name SoftDelete
|
||||
* @summary 删除
|
||||
* @request DELETE:/api/admin/site-msg/soft-delete
|
||||
* @secure
|
||||
*/
|
||||
softDelete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/site-msg/soft-delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags site-msg
|
||||
* @name BatchSoftDelete
|
||||
* @summary 批量删除
|
||||
* @request POST:/api/admin/site-msg/batch-soft-delete
|
||||
* @secure
|
||||
*/
|
||||
batchSoftDelete = (data: number[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/site-msg/batch-soft-delete`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,287 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { AxiosResponse } from 'axios'
|
||||
import {
|
||||
PageInputTaskGetPageInput,
|
||||
ResultOutputPageOutputTaskGetPageOutput,
|
||||
ResultOutputString,
|
||||
ResultOutputTaskGetOutput,
|
||||
TaskAddInput,
|
||||
TaskUpdateInput,
|
||||
} from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class TaskApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags task
|
||||
* @name GetAlerEmail
|
||||
* @summary 查询报警邮件
|
||||
* @request GET:/api/admin/task/get-aler-email
|
||||
* @secure
|
||||
*/
|
||||
getAlerEmail = (
|
||||
query?: {
|
||||
id?: string
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputString, any>({
|
||||
path: `/api/admin/task/get-aler-email`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags task
|
||||
* @name Get
|
||||
* @summary 查询
|
||||
* @request GET:/api/admin/task/get
|
||||
* @secure
|
||||
*/
|
||||
get = (
|
||||
query?: {
|
||||
id?: string
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputTaskGetOutput, any>({
|
||||
path: `/api/admin/task/get`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags task
|
||||
* @name GetPage
|
||||
* @summary 查询分页
|
||||
* @request POST:/api/admin/task/get-page
|
||||
* @secure
|
||||
*/
|
||||
getPage = (data: PageInputTaskGetPageInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputPageOutputTaskGetPageOutput, any>({
|
||||
path: `/api/admin/task/get-page`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags task
|
||||
* @name Add
|
||||
* @summary 新增
|
||||
* @request POST:/api/admin/task/add
|
||||
* @secure
|
||||
*/
|
||||
add = (data: TaskAddInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputString, any>({
|
||||
path: `/api/admin/task/add`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags task
|
||||
* @name Update
|
||||
* @summary 修改
|
||||
* @request PUT:/api/admin/task/update
|
||||
* @secure
|
||||
*/
|
||||
update = (data: TaskUpdateInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/task/update`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags task
|
||||
* @name Pause
|
||||
* @summary 暂停任务
|
||||
* @request POST:/api/admin/task/pause
|
||||
* @secure
|
||||
*/
|
||||
pause = (
|
||||
query: {
|
||||
id: string
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/task/pause`,
|
||||
method: 'POST',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags task
|
||||
* @name Resume
|
||||
* @summary 启动任务
|
||||
* @request POST:/api/admin/task/resume
|
||||
* @secure
|
||||
*/
|
||||
resume = (
|
||||
query: {
|
||||
id: string
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/task/resume`,
|
||||
method: 'POST',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags task
|
||||
* @name Run
|
||||
* @summary 执行任务
|
||||
* @request POST:/api/admin/task/run
|
||||
* @secure
|
||||
*/
|
||||
run = (
|
||||
query: {
|
||||
id: string
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/task/run`,
|
||||
method: 'POST',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags task
|
||||
* @name Delete
|
||||
* @summary 删除任务
|
||||
* @request DELETE:/api/admin/task/delete
|
||||
* @secure
|
||||
*/
|
||||
delete = (
|
||||
query: {
|
||||
id: string
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/task/delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags task
|
||||
* @name BatchRun
|
||||
* @summary 批量执行任务
|
||||
* @request PUT:/api/admin/task/batch-run
|
||||
* @secure
|
||||
*/
|
||||
batchRun = (data: string[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/task/batch-run`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags task
|
||||
* @name BatchPause
|
||||
* @summary 批量暂停任务
|
||||
* @request PUT:/api/admin/task/batch-pause
|
||||
* @secure
|
||||
*/
|
||||
batchPause = (data: string[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/task/batch-pause`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags task
|
||||
* @name BatchResume
|
||||
* @summary 批量启动任务
|
||||
* @request PUT:/api/admin/task/batch-resume
|
||||
* @secure
|
||||
*/
|
||||
batchResume = (data: string[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/task/batch-resume`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags task
|
||||
* @name BatchDelete
|
||||
* @summary 批量删除任务
|
||||
* @request PUT:/api/admin/task/batch-delete
|
||||
* @secure
|
||||
*/
|
||||
batchDelete = (data: string[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/task/batch-delete`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { PageInputTaskLogGetPageInput, ResultOutputPageOutputTaskLog } from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class TaskLogApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags task-log
|
||||
* @name GetPage
|
||||
* @summary 查询分页
|
||||
* @request POST:/api/admin/task-log/get-page
|
||||
* @secure
|
||||
*/
|
||||
getPage = (data: PageInputTaskLogGetPageInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputPageOutputTaskLog, any>({
|
||||
path: `/api/admin/task-log/get-page`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,152 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class TemplateCenterApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* 获取文件夹和文件树形结构列表
|
||||
*
|
||||
* @tags 模板中心
|
||||
* @name GetTree
|
||||
* @request GET:/api/admin/template-center/get-tree
|
||||
*/
|
||||
getTree = (params: RequestParams = {}) =>
|
||||
this.request<ApiResult<TemplateCenterGetTreeOutput[]>, any>({
|
||||
path: `/api/admin/template-center/get-tree`,
|
||||
method: 'GET',
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* 新增文件夹或文件
|
||||
*
|
||||
* @tags 模板中心
|
||||
* @name Add
|
||||
* @request POST:/api/admin/template-center/add
|
||||
*/
|
||||
add = (data: TemplateCenterAddInput, params: RequestParams = {}) =>
|
||||
this.request<ApiResult, any>({
|
||||
path: `/api/admin/template-center/add`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* 修改文件夹或文件
|
||||
*
|
||||
* @tags 模板中心
|
||||
* @name Update
|
||||
* @request PUT:/api/admin/template-center/update
|
||||
*/
|
||||
update = (data: TemplateCenterUpdateInput, params: RequestParams = {}) =>
|
||||
this.request<ApiResult, any>({
|
||||
path: `/api/admin/template-center/update`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* 删除文件夹或文件
|
||||
*
|
||||
* @tags 模板中心
|
||||
* @name Delete
|
||||
* @request DELETE:/api/admin/template-center/delete
|
||||
*/
|
||||
delete = (params: { id: number }, requestParams: RequestParams = {}) =>
|
||||
this.request<ApiResult, any>({
|
||||
path: `/api/admin/template-center/delete`,
|
||||
method: 'DELETE',
|
||||
query: params,
|
||||
...requestParams,
|
||||
})
|
||||
|
||||
/**
|
||||
* 读取共享文件夹内容并添加到指定父级下
|
||||
*
|
||||
* @tags 模板中心
|
||||
* @name GetSharedFolderContent
|
||||
* @request GET:/api/admin/template-center/get-shared-folder-content
|
||||
*/
|
||||
getSharedFolderContent = (
|
||||
params: {
|
||||
folderPath?: string
|
||||
parentId?: number
|
||||
includeSubfolders?: boolean
|
||||
},
|
||||
requestParams: RequestParams = {}
|
||||
) =>
|
||||
this.request<ApiResult, any>({
|
||||
path: `/api/admin/template-center/get-shared-folder-content`,
|
||||
method: 'GET',
|
||||
query: params,
|
||||
...requestParams,
|
||||
})
|
||||
}
|
||||
|
||||
/** API返回结果 */
|
||||
export interface ApiResult<T = any> {
|
||||
success?: boolean
|
||||
code?: string
|
||||
msg?: string
|
||||
data?: T
|
||||
}
|
||||
|
||||
/** 模板中心树形结构输出 */
|
||||
export interface TemplateCenterGetTreeOutput {
|
||||
id?: number
|
||||
parentId?: number
|
||||
name?: string
|
||||
type?: number // 1=文件夹, 2=文件
|
||||
contactPerson?: string
|
||||
functionIntro?: string
|
||||
keywords?: string
|
||||
site?: string
|
||||
filePath?: string
|
||||
fileKeword?: string
|
||||
fileUrl?: string
|
||||
createdTime?: string
|
||||
modifiedTime?: string
|
||||
children?: TemplateCenterGetTreeOutput[]
|
||||
}
|
||||
|
||||
/** 新增文件夹或文件输入 */
|
||||
export interface TemplateCenterAddInput {
|
||||
parentId?: number
|
||||
name?: string
|
||||
type?: number // 1=文件夹, 2=文件
|
||||
contactPerson?: string
|
||||
functionIntro?: string
|
||||
keywords?: string
|
||||
site?: string
|
||||
filePath?: string
|
||||
fileKeword?: string
|
||||
fileUrl?: string
|
||||
}
|
||||
|
||||
/** 更新文件夹或文件输入 */
|
||||
export interface TemplateCenterUpdateInput {
|
||||
id?: number
|
||||
parentId?: number
|
||||
name?: string
|
||||
type?: number // 1=文件夹, 2=文件
|
||||
contactPerson?: string
|
||||
functionIntro?: string
|
||||
keywords?: string
|
||||
site?: string
|
||||
filePath?: string
|
||||
fileKeword?: string
|
||||
fileUrl?: string
|
||||
}
|
||||
@ -1,213 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { AxiosResponse } from 'axios'
|
||||
import {
|
||||
PageInputTenantGetPageInput,
|
||||
ResultOutputInt64,
|
||||
ResultOutputPageOutputTenantGetPageOutput,
|
||||
ResultOutputTenantGetOutput,
|
||||
ResultOutputTokenInfo,
|
||||
TenantAddInput,
|
||||
TenantSetEnableInput,
|
||||
TenantUpdateInput,
|
||||
} from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class TenantApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags tenant
|
||||
* @name Get
|
||||
* @summary 查询
|
||||
* @request GET:/api/admin/tenant/get
|
||||
* @secure
|
||||
*/
|
||||
get = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputTenantGetOutput, any>({
|
||||
path: `/api/admin/tenant/get`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags tenant
|
||||
* @name GetPage
|
||||
* @summary 查询分页
|
||||
* @request POST:/api/admin/tenant/get-page
|
||||
* @secure
|
||||
*/
|
||||
getPage = (data: PageInputTenantGetPageInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputPageOutputTenantGetPageOutput, any>({
|
||||
path: `/api/admin/tenant/get-page`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags tenant
|
||||
* @name Add
|
||||
* @summary 新增
|
||||
* @request POST:/api/admin/tenant/add
|
||||
* @secure
|
||||
*/
|
||||
add = (data: TenantAddInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputInt64, any>({
|
||||
path: `/api/admin/tenant/add`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags tenant
|
||||
* @name Update
|
||||
* @summary 修改
|
||||
* @request PUT:/api/admin/tenant/update
|
||||
* @secure
|
||||
*/
|
||||
update = (data: TenantUpdateInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/tenant/update`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags tenant
|
||||
* @name Delete
|
||||
* @summary 彻底删除
|
||||
* @request DELETE:/api/admin/tenant/delete
|
||||
* @secure
|
||||
*/
|
||||
delete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/tenant/delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags tenant
|
||||
* @name SoftDelete
|
||||
* @summary 删除
|
||||
* @request DELETE:/api/admin/tenant/soft-delete
|
||||
* @secure
|
||||
*/
|
||||
softDelete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/tenant/soft-delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags tenant
|
||||
* @name BatchSoftDelete
|
||||
* @summary 批量删除
|
||||
* @request PUT:/api/admin/tenant/batch-soft-delete
|
||||
* @secure
|
||||
*/
|
||||
batchSoftDelete = (data: number[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/tenant/batch-soft-delete`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags tenant
|
||||
* @name SetEnable
|
||||
* @summary 设置启用
|
||||
* @request POST:/api/admin/tenant/set-enable
|
||||
* @secure
|
||||
*/
|
||||
setEnable = (data: TenantSetEnableInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/tenant/set-enable`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags tenant
|
||||
* @name OneClickLogin
|
||||
* @summary 一键登录
|
||||
* @request POST:/api/admin/tenant/one-click-login
|
||||
* @secure
|
||||
*/
|
||||
oneClickLogin = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
tenantId?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputTokenInfo, any>({
|
||||
path: `/api/admin/tenant/one-click-login`,
|
||||
method: 'POST',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { AxiosResponse } from 'axios'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
import { ResultOutputListTopClickedWebsiteOutput } from './data-contracts'
|
||||
|
||||
export class UserClickApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags user-click
|
||||
* @name RecordClick
|
||||
* @summary 记录用户点击
|
||||
* @request POST:/api/admin/user-click/record-click
|
||||
* @secure
|
||||
*/
|
||||
recordClick = (
|
||||
data: {
|
||||
/** 网页类型 1:在线应用 3:模板中心 5:在线看板 */
|
||||
webType: number
|
||||
/** 网页Id */
|
||||
webId: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/user-click/record-click`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags user-click
|
||||
* @name GetTopClickedWebsites
|
||||
* @summary 获取热门点击网站
|
||||
* @request POST:/api/admin/user-click/get-top-clicked-websites
|
||||
* @secure
|
||||
*/
|
||||
getTopClickedWebsites = (
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputListTopClickedWebsiteOutput, any>({
|
||||
path: `/api/admin/user-click/get-top-clicked-websites`,
|
||||
method: 'POST',
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,206 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { AxiosResponse } from 'axios'
|
||||
import {
|
||||
ResultOutputInt64,
|
||||
ResultOutputListViewGetListOutput,
|
||||
ResultOutputViewGetOutput,
|
||||
ViewAddInput,
|
||||
ViewGetListInput,
|
||||
ViewSyncInput,
|
||||
ViewUpdateInput,
|
||||
} from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
|
||||
export class ViewApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags view
|
||||
* @name Get
|
||||
* @summary 查询
|
||||
* @request GET:/api/admin/view/get
|
||||
* @secure
|
||||
*/
|
||||
get = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputViewGetOutput, any>({
|
||||
path: `/api/admin/view/get`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags view
|
||||
* @name GetList
|
||||
* @summary 查询列表
|
||||
* @request POST:/api/admin/view/get-list
|
||||
* @secure
|
||||
*/
|
||||
getList = (data: ViewGetListInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputListViewGetListOutput, any>({
|
||||
path: `/api/admin/view/get-list`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags view
|
||||
* @name Add
|
||||
* @summary 新增
|
||||
* @request POST:/api/admin/view/add
|
||||
* @secure
|
||||
*/
|
||||
add = (data: ViewAddInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputInt64, any>({
|
||||
path: `/api/admin/view/add`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags view
|
||||
* @name Update
|
||||
* @summary 修改
|
||||
* @request PUT:/api/admin/view/update
|
||||
* @secure
|
||||
*/
|
||||
update = (data: ViewUpdateInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/view/update`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags view
|
||||
* @name Delete
|
||||
* @summary 彻底删除
|
||||
* @request DELETE:/api/admin/view/delete
|
||||
* @secure
|
||||
*/
|
||||
delete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/view/delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags view
|
||||
* @name BatchDelete
|
||||
* @summary 批量彻底删除
|
||||
* @request PUT:/api/admin/view/batch-delete
|
||||
* @secure
|
||||
*/
|
||||
batchDelete = (data: number[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/view/batch-delete`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags view
|
||||
* @name SoftDelete
|
||||
* @summary 删除
|
||||
* @request DELETE:/api/admin/view/soft-delete
|
||||
* @secure
|
||||
*/
|
||||
softDelete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/view/soft-delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags view
|
||||
* @name BatchSoftDelete
|
||||
* @summary 批量删除
|
||||
* @request PUT:/api/admin/view/batch-soft-delete
|
||||
* @secure
|
||||
*/
|
||||
batchSoftDelete = (data: number[], params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/view/batch-soft-delete`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags view
|
||||
* @name Sync
|
||||
* @summary 同步
|
||||
* @request POST:/api/admin/view/sync
|
||||
* @secure
|
||||
*/
|
||||
sync = (data: ViewSyncInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/view/sync`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
}
|
||||
@ -1,165 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="600px"
|
||||
>
|
||||
<el-form :model="form" ref="formRef" label-width="80px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="上级接口">
|
||||
<el-tree-select
|
||||
v-model="form.parentId"
|
||||
:data="apiTreeData"
|
||||
node-key="id"
|
||||
check-strictly
|
||||
default-expand-all
|
||||
render-after-expand
|
||||
fit-input-width
|
||||
clearable
|
||||
class="w100"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="接口名称" prop="label" :rules="[{ required: true, message: '请输入接口名称', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.label" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="接口地址" prop="path" :rules="[{ required: true, message: '请输入接口地址', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.path" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="接口方法" prop="httpMethods">
|
||||
<el-radio-group v-model="form.httpMethods">
|
||||
<el-radio-button label="get" />
|
||||
<el-radio-button label="put" />
|
||||
<el-radio-button label="post" />
|
||||
<el-radio-button label="patch" />
|
||||
<el-radio-button label="delete" />
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="接口描述" prop="description">
|
||||
<el-input v-model="form.description" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="排序">
|
||||
<el-input-number v-model="form.sort" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="启用">
|
||||
<el-switch v-model="form.enabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, toRefs, ref, PropType } from 'vue'
|
||||
import { ApiGetListOutput, ApiUpdateInput } from '/@/api/admin/data-contracts'
|
||||
import { ApiApi } from '/@/api/admin/Api'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
apiTreeData: {
|
||||
type: Array as PropType<ApiGetListOutput[]>,
|
||||
default: () => [],
|
||||
},
|
||||
})
|
||||
|
||||
const formRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
form: {
|
||||
enabled: true,
|
||||
} as ApiUpdateInput,
|
||||
})
|
||||
|
||||
const { form } = toRefs(state)
|
||||
|
||||
// 打开对话框
|
||||
const open = async (row: any = {}) => {
|
||||
if (row.id > 0) {
|
||||
const res = await new ApiApi().get({ id: row.id }, { loading: true })
|
||||
|
||||
if (res?.success) {
|
||||
let formData = res.data as ApiUpdateInput
|
||||
formData.parentId = formData.parentId && formData.parentId > 0 ? formData.parentId : undefined
|
||||
state.form = formData
|
||||
}
|
||||
} else {
|
||||
state.form = {
|
||||
enabled: true,
|
||||
} as ApiUpdateInput
|
||||
}
|
||||
state.showDialog = true
|
||||
}
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
state.sureLoading = true
|
||||
let res = {} as any
|
||||
state.form.parentId = state.form.parentId && state.form.parentId > 0 ? state.form.parentId : undefined
|
||||
if (state.form.id != undefined && state.form.id > 0) {
|
||||
res = await new ApiApi().update(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
} else {
|
||||
res = await new ApiApi().add(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
eventBus.emit('refreshApi')
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'admin/api/form',
|
||||
})
|
||||
</script>
|
||||
@ -1,362 +0,0 @@
|
||||
<template>
|
||||
<my-layout>
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" @submit.stop.prevent>
|
||||
<el-form-item label="接口名称">
|
||||
<el-input v-model="state.filter.name" placeholder="接口名称" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:api:add'" type="primary" icon="ele-Plus" @click="onAdd"> 新增 </el-button>
|
||||
<el-popconfirm title="确定要同步接口" hide-icon width="180" hide-after="0" @confirm="onSync">
|
||||
<template #reference>
|
||||
<el-button v-auth="'api:admin:api:sync'" :loading="state.syncLoading" type="primary" icon="ele-Refresh"> 同步 </el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table
|
||||
:data="state.apiTreeData"
|
||||
style="width: 100%"
|
||||
v-loading="state.loading"
|
||||
row-key="id"
|
||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
:expand-row-keys="state.expandRowKeys"
|
||||
border
|
||||
>
|
||||
<el-table-column prop="label" label="接口名称" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="path" label="接口地址" min-width="120" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<el-tag v-if="row.httpMethods" :type="getTagTypeByHttpMethod(row.httpMethods)" style="width: 54px">{{ row.httpMethods }}</el-tag>
|
||||
{{ row.path }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="请求日志" width="90" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
v-if="row.httpMethods"
|
||||
v-model="row.enabledLog"
|
||||
:loading="row.loadingEnabledLog"
|
||||
:active-value="true"
|
||||
:inactive-value="false"
|
||||
inline-prompt
|
||||
active-text="启用"
|
||||
inactive-text="禁用"
|
||||
:before-change="() => onSetEnableLog(row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="请求参数" width="90" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
v-if="row.httpMethods"
|
||||
v-model="row.enabledParams"
|
||||
:loading="row.loadingEnabledParams"
|
||||
:active-value="true"
|
||||
:inactive-value="false"
|
||||
inline-prompt
|
||||
active-text="启用"
|
||||
inactive-text="禁用"
|
||||
:before-change="() => onSetEnableParams(row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="响应结果" width="90" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
v-if="row.httpMethods"
|
||||
v-model="row.enabledResult"
|
||||
:loading="row.loadingEnabledResult"
|
||||
:active-value="true"
|
||||
:inactive-value="false"
|
||||
inline-prompt
|
||||
active-text="启用"
|
||||
inactive-text="禁用"
|
||||
:before-change="() => onSetEnableResult(row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sort" label="排序" width="82" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="状态" width="82" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="success" v-if="row.enabled">启用</el-tag>
|
||||
<el-tag type="danger" v-else>禁用</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160" fixed="right" header-align="center" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button v-auth="'api:admin:api:update'" icon="ele-EditPen" text type="primary" @click="onEdit(row)">编辑</el-button>
|
||||
<el-button v-auth="'api:admin:api:delete'" icon="ele-Delete" text type="danger" @click="onDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<api-form ref="apiFormRef" :title="state.apiFormTitle" :api-tree-data="state.formApiTreeData"></api-form>
|
||||
</my-layout>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/api">
|
||||
import { ref, reactive, onMounted, getCurrentInstance, onBeforeMount, defineAsyncComponent } from 'vue'
|
||||
import { ApiGetListOutput } from '/@/api/admin/data-contracts'
|
||||
import { ApiApi } from '/@/api/admin/Api'
|
||||
import { ApiApi as ApiExtApi } from '/@/api/admin.extend/Api'
|
||||
import { listToTree, treeToList, filterTree, filterList } from '/@/utils/tree'
|
||||
import { cloneDeep, isArray } from 'lodash-es'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
|
||||
// 引入组件
|
||||
const ApiForm = defineAsyncComponent(() => import('./components/api-form.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const apiFormRef = ref()
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
syncLoading: false,
|
||||
apiFormTitle: '',
|
||||
filter: {
|
||||
name: '',
|
||||
},
|
||||
apiTreeData: [] as Array<ApiGetListOutput>,
|
||||
formApiTreeData: [] as Array<ApiGetListOutput>,
|
||||
expandRowKeys: [] as string[],
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
await onQuery()
|
||||
state.expandRowKeys = treeToList(cloneDeep(state.apiTreeData))
|
||||
.filter((a: ApiGetListOutput) => a.parentId === 0)
|
||||
.map((a: ApiGetListOutput) => a.id + '') as string[]
|
||||
eventBus.off('refreshApi')
|
||||
eventBus.on('refreshApi', async () => {
|
||||
onQuery()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshApi')
|
||||
})
|
||||
|
||||
const getTagTypeByHttpMethod = (httpMethods: string) => {
|
||||
const methods = httpMethods.toLowerCase().split(/\s+/)
|
||||
if (methods.some((method) => method === 'get')) {
|
||||
return 'success'
|
||||
}
|
||||
if (methods.some((method) => method === 'delete')) {
|
||||
return 'danger'
|
||||
}
|
||||
if (methods.some((method) => method === 'patch')) {
|
||||
return 'info'
|
||||
}
|
||||
|
||||
return 'primary'
|
||||
}
|
||||
//启用或禁用请求日志
|
||||
const onSetEnableLog = (row: ApiGetListOutput & { loadingEnabledLog: boolean; loadingEnabledParams: boolean; loadingEnabledResult: boolean }) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
proxy.$modal
|
||||
.confirm(`确定要${row.enabledLog ? '禁用' : '启用'}【${row.label}】请求参数?`)
|
||||
.then(async () => {
|
||||
row.loadingEnabledLog = true
|
||||
const res = await new ApiApi()
|
||||
.setEnableLog({ apiId: row.id, enabledLog: !row.enabledLog }, { showSuccessMessage: true })
|
||||
.catch(() => {
|
||||
reject(new Error('Error'))
|
||||
})
|
||||
.finally(() => {
|
||||
row.loadingEnabledLog = false
|
||||
})
|
||||
if (res && res.success) {
|
||||
resolve(true)
|
||||
} else {
|
||||
reject(new Error('Cancel'))
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
reject(new Error('Cancel'))
|
||||
})
|
||||
})
|
||||
}
|
||||
//启用或禁用请求参数
|
||||
const onSetEnableParams = (row: ApiGetListOutput & { loadingEnabledLog: boolean; loadingEnabledParams: boolean; loadingEnabledResult: boolean }) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
proxy.$modal
|
||||
.confirm(`确定要${row.enabledParams ? '禁用' : '启用'}【${row.label}】请求参数?`)
|
||||
.then(async () => {
|
||||
row.loadingEnabledParams = true
|
||||
const res = await new ApiApi()
|
||||
.setEnableParams({ apiId: row.id, enabledParams: !row.enabledParams }, { showSuccessMessage: true })
|
||||
.catch(() => {
|
||||
reject(new Error('Error'))
|
||||
})
|
||||
.finally(() => {
|
||||
row.loadingEnabledParams = false
|
||||
})
|
||||
if (res && res.success) {
|
||||
resolve(true)
|
||||
} else {
|
||||
reject(new Error('Cancel'))
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
reject(new Error('Cancel'))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
//启用或禁用响应结果
|
||||
const onSetEnableResult = (row: ApiGetListOutput & { loadingEnabledLog: boolean; loadingEnabledParams: boolean; loadingEnabledResult: boolean }) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
proxy.$modal
|
||||
.confirm(`确定要${row.enabledResult ? '禁用' : '启用'}【${row.label}】响应结果?`)
|
||||
.then(async () => {
|
||||
row.loadingEnabledResult = true
|
||||
const res = await new ApiApi()
|
||||
.setEnableResult({ apiId: row.id, enabledResult: !row.enabledResult }, { showSuccessMessage: true })
|
||||
.catch(() => {
|
||||
reject(new Error('Error'))
|
||||
})
|
||||
.finally(() => {
|
||||
row.loadingEnabledResult = false
|
||||
})
|
||||
if (res && res.success) {
|
||||
resolve(true)
|
||||
} else {
|
||||
reject(new Error('Cancel'))
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
reject(new Error('Cancel'))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
const res = await new ApiApi().getList().catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
if (res && res.data && res.data.length > 0) {
|
||||
state.apiTreeData = filterTree(listToTree(cloneDeep(res.data)), state.filter.name, {
|
||||
filterWhere: (item: any, keyword: string) => {
|
||||
return item.label?.toLocaleLowerCase().indexOf(keyword) > -1 || item.path?.toLocaleLowerCase().indexOf(keyword) > -1
|
||||
},
|
||||
})
|
||||
|
||||
//修复#57
|
||||
state.formApiTreeData = listToTree(
|
||||
filterList(cloneDeep(res.data), '', {
|
||||
filterWhere: (item: any, word: string) => {
|
||||
return !item.httpMethods
|
||||
},
|
||||
})
|
||||
)
|
||||
} else {
|
||||
state.apiTreeData = []
|
||||
state.formApiTreeData = []
|
||||
}
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onAdd = () => {
|
||||
state.apiFormTitle = '新增接口'
|
||||
apiFormRef.value.open()
|
||||
}
|
||||
|
||||
const onEdit = (row: ApiGetListOutput) => {
|
||||
state.apiFormTitle = '编辑接口'
|
||||
apiFormRef.value.open(row)
|
||||
}
|
||||
|
||||
const onDelete = (row: ApiGetListOutput) => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要删除接口【${row.label}】?`)
|
||||
.then(async () => {
|
||||
await new ApiApi().delete({ id: row.id }, { loading: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const syncApi = async (swaggerResource: any) => {
|
||||
const res = await new ApiExtApi().getSwaggerJson(swaggerResource.url, { showErrorMessage: false })
|
||||
if (!res) {
|
||||
return
|
||||
}
|
||||
|
||||
const tags = res.tags
|
||||
const paths = res.paths
|
||||
const apis = []
|
||||
const urls = swaggerResource.url.split('/')
|
||||
const code = urls.length >= 2 ? urls[urls.length - 2] : ''
|
||||
if (code === '') {
|
||||
return
|
||||
}
|
||||
apis[apis.length] = {
|
||||
label: swaggerResource.name,
|
||||
path: code,
|
||||
}
|
||||
// tags
|
||||
if (tags && tags.length > 0) {
|
||||
tags.forEach((t: any) => {
|
||||
apis[apis.length] = {
|
||||
label: t.description,
|
||||
path: t.name,
|
||||
parentPath: code,
|
||||
}
|
||||
})
|
||||
}
|
||||
// paths
|
||||
if (paths) {
|
||||
for (const [key, value] of Object.entries(paths)) {
|
||||
const keys = Object.keys(value as any)
|
||||
const values = Object.values(value as any)
|
||||
const v = values && values.length > 0 ? values[0] : ({} as any)
|
||||
const parentPath = v.tags && v.tags.length > 0 ? v.tags[0] : ''
|
||||
apis[apis.length] = {
|
||||
label: v.summary,
|
||||
path: key,
|
||||
parentPath,
|
||||
httpMethods: keys.join(','),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return await new ApiApi().sync({ apis })
|
||||
}
|
||||
|
||||
const onSync = async () => {
|
||||
state.syncLoading = true
|
||||
const swaggerResourcePaths = ['doc/admin']
|
||||
//const swaggerResourcePaths = ['doc/admin']
|
||||
// const swaggerResourcePaths = ['doc/app']
|
||||
const swaggerResourceUrls = swaggerResourcePaths?.map((path) => `/${path}/swagger-resources`) as string[]
|
||||
const lastSwaggerResourcesIndex = swaggerResourceUrls.length - 1
|
||||
swaggerResourceUrls.forEach(async (swaggerResourceUrl, swaggerResourcesIndex) => {
|
||||
const resSwaggerResources = await new ApiExtApi().getSwaggerResources(swaggerResourceUrl, { showErrorMessage: false }).catch(() => {
|
||||
state.syncLoading = false
|
||||
})
|
||||
if (isArray(resSwaggerResources) && (resSwaggerResources?.length as number) > 0) {
|
||||
for (let index = 0, len = resSwaggerResources.length; index < len; index++) {
|
||||
const swaggerResource = resSwaggerResources[index]
|
||||
await syncApi(swaggerResource).catch(() => {
|
||||
proxy.$modal.msgSuccess(`同步${swaggerResource.name}失败`)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (swaggerResourcesIndex === lastSwaggerResourcesIndex) {
|
||||
state.syncLoading = false
|
||||
proxy.$modal.msgSuccess(`同步完成`)
|
||||
onQuery()
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -1,148 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="600px"
|
||||
>
|
||||
<el-form :model="form" ref="formRef" label-width="80px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="看板名称" prop="name" :rules="[{ required: true, message: '请输入看板名称', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.name" clearable placeholder="请输入看板名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="功能简介" prop="description">
|
||||
<el-input v-model="form.description" type="textarea" :rows="3" clearable placeholder="请输入功能简介" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="关键词" prop="keywords">
|
||||
<el-input v-model="form.keywords" clearable placeholder="请输入关键词,多个关键词用逗号分隔" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="网址" prop="url">
|
||||
<el-input v-model="form.url" clearable placeholder="请输入网址" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<!-- safetyVerification -->
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="安全认证" prop="safety">
|
||||
<el-switch v-model="form.safety" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="排序">
|
||||
<el-input-number v-model="form.sort" :min="0" :max="9999" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="启用">
|
||||
<el-switch v-model="form.enabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, toRefs, ref, PropType } from 'vue'
|
||||
import { BoardGetPageOutput, BoardUpdateInput } from '/@/api/admin/data-contracts'
|
||||
import { BoardApi } from '/@/api/admin/Board'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const formRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
form: {
|
||||
enabled: true,
|
||||
sort: 0,
|
||||
} as BoardUpdateInput,
|
||||
})
|
||||
|
||||
const { form } = toRefs(state)
|
||||
|
||||
// 打开对话框
|
||||
const open = async (row: any = {}) => {
|
||||
if (row.id > 0) {
|
||||
const res = await new BoardApi().get({ id: row.id }, { loading: true })
|
||||
|
||||
if (res?.success) {
|
||||
let formData = res.data as BoardUpdateInput
|
||||
state.form = formData
|
||||
}
|
||||
} else {
|
||||
state.form = {
|
||||
enabled: true,
|
||||
sort: 0,
|
||||
} as BoardUpdateInput
|
||||
}
|
||||
state.showDialog = true
|
||||
}
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
state.sureLoading = true
|
||||
let res = {} as any
|
||||
if (state.form.id != undefined && state.form.id > 0) {
|
||||
res = await new BoardApi().update(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
} else {
|
||||
res = await new BoardApi().add(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
eventBus.emit('refreshBoard')
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'admin/board/form',
|
||||
})
|
||||
</script>
|
||||
@ -1,329 +0,0 @@
|
||||
<template>
|
||||
<MySplitPanes>
|
||||
<pane size="55" min-size="35" max-size="65">
|
||||
<div class="my-flex-column w100 h100">
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" @submit.stop.prevent>
|
||||
<el-form-item label="看板名称">
|
||||
<el-input v-model="state.filter.name" placeholder="看板名称" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="关键词">
|
||||
<el-input v-model="state.filter.keywords" placeholder="关键词" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:board:add'" type="primary" icon="ele-Plus" @click="onAdd"> 新增 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table
|
||||
ref="boardTableRef"
|
||||
v-loading="state.loading"
|
||||
:data="state.boardListData"
|
||||
default-expand-all
|
||||
highlight-current-row
|
||||
style="width: 100%"
|
||||
@current-change="onTableCurrentChange"
|
||||
border
|
||||
>
|
||||
<el-table-column prop="name" label="看板名称" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="description" label="功能简介" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column prop="keywords" label="关键词" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="url" label="网址" min-width="150" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<el-link v-if="row.url" :href="row.url" target="_blank" type="primary">{{ row.url }}</el-link>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sort" label="排序" width="90" align="center" sortable="custom" show-overflow-tooltip />
|
||||
<el-table-column label="状态" width="82" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="success" v-if="row.enabled">启用</el-tag>
|
||||
<el-tag type="danger" v-else>禁用</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createdTime" label="创建时间" width="160" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="140" fixed="right" header-align="center" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button v-auth="'api:admin:board:update'" icon="ele-EditPen" text type="primary" @click="onEdit(row)">编辑</el-button>
|
||||
<el-button v-auth="'api:admin:board:delete'" icon="ele-Delete" text type="danger" @click="onDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="my-flex my-flex-end" style="margin-top: 10px">
|
||||
<el-pagination
|
||||
v-model:currentPage="state.pageInput.currentPage"
|
||||
v-model:page-size="state.pageInput.pageSize"
|
||||
:total="state.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
background
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</pane>
|
||||
<pane>
|
||||
<div class="my-flex-column w100 h100">
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" @submit.stop.prevent>
|
||||
<el-form-item label="姓名">
|
||||
<el-input v-model="state.userFilter.name" placeholder="姓名" @keyup.enter="onGetBoardUserList" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onGetBoardUserList"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:board:add-board-user'" type="primary" icon="ele-Plus" @click="onAddUser"> 添加 </el-button>
|
||||
<el-button v-auth="'api:admin:board:remove-board-user'" type="danger" icon="ele-Delete" @click="onRemoveUser"> 移除 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table
|
||||
ref="userTableRef"
|
||||
v-loading="state.userListLoading"
|
||||
:data="state.userListData"
|
||||
:row-key="getRowKey"
|
||||
style="width: 100%"
|
||||
border
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="name" label="姓名" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="mobile" label="手机号" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="email" label="邮箱" min-width="180" show-overflow-tooltip />
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
</pane>
|
||||
|
||||
<board-form ref="boardFormRef" :title="state.boardFormTitle"></board-form>
|
||||
<user-select
|
||||
ref="userSelectRef"
|
||||
:title="`添加【${state.boardName}】人员`"
|
||||
multiple
|
||||
:sure-loading="state.sureLoading"
|
||||
@sure="onSureUser"
|
||||
></user-select>
|
||||
</MySplitPanes>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/board">
|
||||
import { ref, reactive, onMounted, getCurrentInstance, onBeforeMount, defineAsyncComponent } from 'vue'
|
||||
import { BoardGetPageOutput, PageInputBoardGetPageInput, SortInput, BoardGetBoardUserListOutput, BoardAddBoardUserListInput, BoardRemoveBoardUserInput, UserGetPageOutput } from '/@/api/admin/data-contracts'
|
||||
import { BoardApi } from '/@/api/admin/Board'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { Pane } from 'splitpanes'
|
||||
import { ElTable } from 'element-plus'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
// 引入组件
|
||||
const BoardForm = defineAsyncComponent(() => import('./components/board-form.vue'))
|
||||
const UserSelect = defineAsyncComponent(() => import('/@/views/admin/user/components/user-select.vue'))
|
||||
const MySplitPanes = defineAsyncComponent(() => import('/@/components/my-layout/split-panes.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const boardTableRef = ref()
|
||||
const boardFormRef = ref()
|
||||
const userTableRef = ref<InstanceType<typeof ElTable>>()
|
||||
const userSelectRef = ref()
|
||||
|
||||
const defalutSort = { prop: 'sort', order: 'ascending' }
|
||||
|
||||
const getSortList = (data: { prop: string; order: any }) => {
|
||||
return [
|
||||
{
|
||||
propName: data.prop,
|
||||
order: data.order === 'ascending' ? 0 : data.order === 'descending' ? 1 : undefined,
|
||||
},
|
||||
] as [SortInput]
|
||||
}
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
userListLoading: false,
|
||||
sureLoading: false,
|
||||
boardFormTitle: '',
|
||||
filter: {
|
||||
name: '',
|
||||
keywords: '',
|
||||
},
|
||||
defalutSort: defalutSort,
|
||||
total: 0,
|
||||
pageInput: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
sortList: getSortList(defalutSort),
|
||||
} as PageInputBoardGetPageInput,
|
||||
boardListData: [] as Array<BoardGetPageOutput>,
|
||||
userFilter: {
|
||||
name: ''
|
||||
},
|
||||
userListData: [] as BoardGetBoardUserListOutput[],
|
||||
boardId: undefined as number | undefined,
|
||||
boardName: '' as string | null | undefined,
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
await onQuery()
|
||||
eventBus.off('refreshBoard')
|
||||
eventBus.on('refreshBoard', () => {
|
||||
onQuery()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshBoard')
|
||||
})
|
||||
|
||||
const formatterTime = (row: any, column: any, cellValue: any) => {
|
||||
return cellValue ? dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss') : ''
|
||||
}
|
||||
|
||||
// 生成唯一的行键,使用数组索引确保唯一性
|
||||
const getRowKey = (row: BoardGetBoardUserListOutput, index: number) => {
|
||||
return `user_${state.boardId}_${row.userId}_${index}`
|
||||
}
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
state.pageInput.filter = state.filter
|
||||
const res = await new BoardApi().getPage(state.pageInput).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
|
||||
state.boardListData = res?.data?.list ?? []
|
||||
state.total = res?.data?.total ?? 0
|
||||
|
||||
if (state.boardListData?.length > 0) {
|
||||
window.setTimeout(() => {
|
||||
boardTableRef.value?.setCurrentRow(state.boardListData[0])
|
||||
}, 100)
|
||||
}
|
||||
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onAdd = () => {
|
||||
state.boardFormTitle = '新增看板'
|
||||
boardFormRef.value.open()
|
||||
}
|
||||
|
||||
const onEdit = (row: BoardGetPageOutput) => {
|
||||
state.boardFormTitle = '编辑看板'
|
||||
boardFormRef.value.open(row)
|
||||
}
|
||||
|
||||
const onDelete = (row: BoardGetPageOutput) => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要删除【${row.name}】?`)
|
||||
.then(async () => {
|
||||
await new BoardApi().softDelete({ id: row.id }, { loading: true, showSuccessMessage: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onSizeChange = (val: number) => {
|
||||
state.pageInput.pageSize = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onCurrentChange = (val: number) => {
|
||||
state.pageInput.currentPage = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onSortChange = (data: { column: any; prop: string; order: any }) => {
|
||||
state.pageInput.sortList = getSortList(data)
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onTableCurrentChange = (currentRow: BoardGetPageOutput) => {
|
||||
if (!currentRow) {
|
||||
return
|
||||
}
|
||||
|
||||
state.boardId = currentRow.id
|
||||
state.boardName = currentRow.name
|
||||
onGetBoardUserList()
|
||||
}
|
||||
|
||||
const onGetBoardUserList = async () => {
|
||||
state.userListLoading = true
|
||||
// 清空之前的选择
|
||||
userTableRef.value?.clearSelection()
|
||||
|
||||
const res = await new BoardApi().getBoardUserList({ BoardId: state.boardId, Name: state.userFilter.name }).catch(() => {
|
||||
state.userListLoading = false
|
||||
})
|
||||
state.userListLoading = false
|
||||
if (res?.success) {
|
||||
if (res.data && res.data.length > 0) {
|
||||
state.userListData = res.data
|
||||
} else {
|
||||
state.userListData = []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const onAddUser = () => {
|
||||
if (!((state.boardId as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择看板')
|
||||
return
|
||||
}
|
||||
userSelectRef.value.open({ boardId: state.boardId })
|
||||
}
|
||||
|
||||
const onRemoveUser = () => {
|
||||
if (!((state.boardId as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择看板')
|
||||
return
|
||||
}
|
||||
|
||||
const selectionRows = userTableRef.value!.getSelectionRows() as BoardGetBoardUserListOutput[]
|
||||
console.log("🔍 ~ ~ src/views/admin/board/index.vue:286 ~ selectionRows:", selectionRows)
|
||||
|
||||
if (!((selectionRows.length as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择人员')
|
||||
return
|
||||
}
|
||||
|
||||
proxy.$modal
|
||||
.confirm(`确定要移除吗?`)
|
||||
.then(async () => {
|
||||
const userIds = selectionRows?.map((a) => a.userId)
|
||||
const input = { boardId: state.boardId, userIds } as BoardRemoveBoardUserInput
|
||||
await new BoardApi().removeBoardUser(input, { loading: true })
|
||||
onGetBoardUserList()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onSureUser = async (users: UserGetPageOutput[]) => {
|
||||
if (!(users?.length > 0)) {
|
||||
userSelectRef.value.close()
|
||||
return
|
||||
}
|
||||
|
||||
state.sureLoading = true
|
||||
const userIds = users?.map((a) => a.id)
|
||||
const input = { boardId: state.boardId, userIds } as BoardAddBoardUserListInput
|
||||
await new BoardApi().addBoardUser(input, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
state.sureLoading = false
|
||||
userSelectRef.value.close()
|
||||
onGetBoardUserList()
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -1,60 +0,0 @@
|
||||
<template>
|
||||
<my-layout>
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table v-loading="state.loading" :data="state.cacheListData" row-key="id" style="width: 100%" border>
|
||||
<el-table-column type="index" width="82" label="#" />
|
||||
<el-table-column prop="description" label="缓存名" />
|
||||
<el-table-column prop="name" label="键名" />
|
||||
<el-table-column prop="value" label="键值" />
|
||||
<el-table-column label="操作" width="180" fixed="right" header-align="center" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button v-auth="'api:admin:cache:clear'" icon="ele-Brush" text type="danger" @click="onClear(row)">清除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</my-layout>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/cache">
|
||||
import { reactive, onMounted, getCurrentInstance } from 'vue'
|
||||
import { CacheApi } from '/@/api/admin/Cache'
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
cacheListData: [] as any,
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
onQuery()
|
||||
})
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
const res = await new CacheApi().getList().catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
state.cacheListData = res?.data ?? []
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onClear = (row: any) => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要清除【${row.description}】缓存?`, { icon: 'ele-Brush' })
|
||||
.then(async () => {
|
||||
await new CacheApi().clear({ cacheKey: row.value }, { loading: true, showSuccessMessage: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -1,139 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="769px"
|
||||
>
|
||||
<el-form ref="formRef" :model="form" label-width="80px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="名称" prop="name" :rules="[{ required: true, message: '请输入名称', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.name" autocomplete="off" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="编码" prop="code">
|
||||
<el-input v-model="form.code" autocomplete="off" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="字典值" prop="value">
|
||||
<el-input v-model="form.value" autocomplete="off" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="排序" prop="sort">
|
||||
<el-input-number v-model="form.sort" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="启用" prop="enabled">
|
||||
<el-switch v-model="form.enabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="说明" prop="description">
|
||||
<el-input v-model="form.description" clearable type="textarea" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer my-flex my-flex-y-center my-flex-between">
|
||||
<div>
|
||||
<el-checkbox v-if="!(state.form?.id > 0)" v-model="state.contiAdd">连续新增</el-checkbox>
|
||||
</div>
|
||||
<div>
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</div>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/dict/form">
|
||||
import { reactive, toRefs, getCurrentInstance, ref } from 'vue'
|
||||
import { DictAddInput, DictUpdateInput } from '/@/api/admin/data-contracts'
|
||||
import { DictApi } from '/@/api/admin/Dict'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { FormInstance } from 'element-plus'
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
form: {} as DictAddInput & DictUpdateInput,
|
||||
contiAdd: false,
|
||||
})
|
||||
const { form } = toRefs(state)
|
||||
|
||||
// 打开对话框
|
||||
const open = async (row: any = {}) => {
|
||||
if (row.id > 0) {
|
||||
state.contiAdd = false
|
||||
const res = await new DictApi().get({ id: row.id }, { loading: true }).catch(() => {
|
||||
proxy.$modal.closeLoading()
|
||||
})
|
||||
|
||||
if (res?.success) {
|
||||
state.form = res.data as DictAddInput & DictUpdateInput
|
||||
}
|
||||
} else {
|
||||
state.form = { dictTypeId: row.dictTypeId, enabled: true } as DictAddInput & DictUpdateInput
|
||||
}
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value!.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
state.sureLoading = true
|
||||
let res = {} as any
|
||||
if (state.form.id != undefined && state.form.id > 0) {
|
||||
res = await new DictApi().update(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
} else {
|
||||
res = await new DictApi().add(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
}
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
if (state.contiAdd) {
|
||||
formRef.value!.resetFields()
|
||||
}
|
||||
eventBus.emit('refreshDict')
|
||||
state.showDialog = state.contiAdd
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
@ -1,123 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="769px"
|
||||
>
|
||||
<el-form ref="formRef" :model="form" label-width="80px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="名称" prop="name" :rules="[{ required: true, message: '请输入名称', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.name" autocomplete="off" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="编码" prop="code" :rules="[{ required: true, message: '请输入编码', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.code" autocomplete="off" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="排序">
|
||||
<el-input-number v-model="form.sort" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="启用">
|
||||
<el-switch v-model="form.enabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="说明">
|
||||
<el-input v-model="form.description" clearable type="textarea" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/dictType/form">
|
||||
import { reactive, toRefs, getCurrentInstance, ref } from 'vue'
|
||||
import { DictTypeAddInput, DictTypeUpdateInput } from '/@/api/admin/data-contracts'
|
||||
import { DictTypeApi } from '/@/api/admin/DictType'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const formRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
form: {} as DictTypeAddInput & DictTypeUpdateInput,
|
||||
})
|
||||
const { form } = toRefs(state)
|
||||
|
||||
// 打开对话框
|
||||
const open = async (row: any = {}) => {
|
||||
if (row.id > 0) {
|
||||
const res = await new DictTypeApi().get({ id: row.id }, { loading: true }).catch(() => {
|
||||
proxy.$modal.closeLoading()
|
||||
})
|
||||
|
||||
if (res?.success) {
|
||||
state.form = res.data as DictTypeAddInput & DictTypeUpdateInput
|
||||
}
|
||||
} else {
|
||||
state.form = { enabled: true } as DictTypeAddInput & DictTypeUpdateInput
|
||||
}
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
state.sureLoading = true
|
||||
let res = {} as any
|
||||
if (state.form.id != undefined && state.form.id > 0) {
|
||||
res = await new DictTypeApi().update(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
} else {
|
||||
res = await new DictTypeApi().add(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
}
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
eventBus.emit('refreshDictType')
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
@ -1,157 +0,0 @@
|
||||
<template>
|
||||
<div class="my-flex-column w100 h100">
|
||||
<el-card class="my-query-box mt8" shadow="never">
|
||||
<el-form :model="state.filterModel" :inline="true" @submit.stop.prevent>
|
||||
<el-form-item prop="name">
|
||||
<el-input v-model="state.filterModel.name" placeholder="名称或编码" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:dict:add'" type="primary" icon="ele-Plus" @click="onAdd"> 新增 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
v-loading="state.loading"
|
||||
:data="state.dictTypeListData"
|
||||
row-key="id"
|
||||
highlight-current-row
|
||||
style="width: 100%"
|
||||
@current-change="onTableCurrentChange"
|
||||
>
|
||||
<el-table-column prop="name" label="名称" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="code" label="编码" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="sort" label="排序" width="60" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="状态" width="82" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="success" v-if="row.enabled">启用</el-tag>
|
||||
<el-tag type="danger" v-else>禁用</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="140" fixed="right" header-align="center" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button v-auth="'api:admin:dict:update'" icon="ele-EditPen" text type="primary" @click="onEdit(row)">编辑</el-button>
|
||||
<el-button v-auth="'api:admin:dict:delete'" icon="ele-Delete" text type="danger" @click="onDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="my-flex my-flex-end" style="margin-top: 20px">
|
||||
<el-pagination
|
||||
v-model:currentPage="state.pageInput.currentPage"
|
||||
v-model:page-size="state.pageInput.pageSize"
|
||||
:total="state.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
background
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<dict-type-form ref="dictTypeFormRef" :title="state.dictTypeFormTitle"></dict-type-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/dictType">
|
||||
import { ref, reactive, onMounted, getCurrentInstance, onBeforeMount, nextTick, defineAsyncComponent } from 'vue'
|
||||
import { DictTypeGetPageOutput, PageInputDictTypeGetPageInput } from '/@/api/admin/data-contracts'
|
||||
import { DictTypeApi } from '/@/api/admin/DictType'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
|
||||
// 引入组件
|
||||
const DictTypeForm = defineAsyncComponent(() => import('./components/dict-type-form.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const tableRef = ref()
|
||||
const dictTypeFormRef = ref()
|
||||
|
||||
const emits = defineEmits(['change'])
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
dictTypeFormTitle: '',
|
||||
filterModel: {
|
||||
name: '',
|
||||
},
|
||||
total: 0,
|
||||
pageInput: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
} as PageInputDictTypeGetPageInput,
|
||||
dictTypeListData: [] as Array<DictTypeGetPageOutput>,
|
||||
lastCurrentRow: {} as DictTypeGetPageOutput,
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
onQuery()
|
||||
eventBus.off('refreshDictType')
|
||||
eventBus.on('refreshDictType', () => {
|
||||
onQuery()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshDictType')
|
||||
})
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
state.pageInput.filter = state.filterModel
|
||||
const res = await new DictTypeApi().getPage(state.pageInput).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
state.dictTypeListData = res?.data?.list ?? []
|
||||
state.total = res?.data?.total ?? 0
|
||||
if (state.dictTypeListData.length > 0) {
|
||||
nextTick(() => {
|
||||
tableRef.value!.setCurrentRow(state.dictTypeListData[0])
|
||||
})
|
||||
}
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onAdd = () => {
|
||||
state.dictTypeFormTitle = '新增字典分类'
|
||||
dictTypeFormRef.value.open()
|
||||
}
|
||||
|
||||
const onEdit = (row: DictTypeGetPageOutput) => {
|
||||
state.dictTypeFormTitle = '编辑字典分类'
|
||||
dictTypeFormRef.value.open(row)
|
||||
}
|
||||
|
||||
const onDelete = (row: DictTypeGetPageOutput) => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要删除【${row.name}】?`)
|
||||
.then(async () => {
|
||||
await new DictTypeApi().delete({ id: row.id }, { loading: true, showSuccessMessage: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onSizeChange = (val: number) => {
|
||||
state.pageInput.currentPage = 1
|
||||
state.pageInput.pageSize = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onCurrentChange = (val: number) => {
|
||||
state.pageInput.currentPage = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onTableCurrentChange = (currentRow: DictTypeGetPageOutput) => {
|
||||
if (state.lastCurrentRow?.id != currentRow?.id) {
|
||||
state.lastCurrentRow = currentRow
|
||||
emits('change', currentRow)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -1,237 +0,0 @@
|
||||
<template>
|
||||
<div class="my-flex-column w100 h100">
|
||||
<el-card class="my-query-box mt8" shadow="never">
|
||||
<el-form :model="state.filterModel" :inline="true" @submit.stop.prevent>
|
||||
<el-form-item prop="name">
|
||||
<el-input v-model="state.filterModel.name" placeholder="名称或编码" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:dict:add'" type="primary" icon="ele-Plus" @click="onAdd"> 新增 </el-button>
|
||||
<el-button v-auth="'api:admin:dict:import-data'" icon="ele-Download" type="primary" @click="onImport"> 导入 </el-button>
|
||||
<el-button v-auth="'api:admin:dict:export-data'" icon="ele-Upload" type="primary" :loading="state.export.loading" @click="onExport">
|
||||
导出
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table
|
||||
v-loading="state.loading"
|
||||
:data="state.dictListData"
|
||||
row-key="id"
|
||||
style="width: 100%"
|
||||
:default-sort="state.defalutSort"
|
||||
@sort-change="onSortChange"
|
||||
border
|
||||
>
|
||||
<el-table-column prop="name" label="名称" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="code" label="编码" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="value" label="值" width="90" sortable="custom" show-overflow-tooltip />
|
||||
<el-table-column prop="sort" label="排序" width="90" align="center" sortable="custom" show-overflow-tooltip />
|
||||
<el-table-column label="状态" width="82" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="success" v-if="row.enabled">启用</el-tag>
|
||||
<el-tag type="danger" v-else>禁用</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="140" fixed="right" header-align="center" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button v-auth="'api:admin:dict:update'" icon="ele-EditPen" text type="primary" @click="onEdit(row)">编辑</el-button>
|
||||
<el-button v-auth="'api:admin:dict:delete'" icon="ele-Delete" text type="danger" @click="onDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="my-flex my-flex-end" style="margin-top: 10px">
|
||||
<el-pagination
|
||||
v-model:currentPage="state.pageInput.currentPage"
|
||||
v-model:page-size="state.pageInput.pageSize"
|
||||
:total="state.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
background
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<dict-form ref="dictFormRef" :title="state.dictFormTitle"></dict-form>
|
||||
|
||||
<MyImport ref="dictImportRef" :title="state.import.title" v-model="state.import"></MyImport>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/dictData">
|
||||
import { ref, reactive, onMounted, getCurrentInstance, onBeforeMount, defineAsyncComponent } from 'vue'
|
||||
import { DictGetPageOutput, PageInputDictGetPageInput, DictTypeGetPageOutput, SortInput } from '/@/api/admin/data-contracts'
|
||||
import { DictApi } from '/@/api/admin/Dict'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import dayjs from 'dayjs'
|
||||
import { RequestParams } from '/@/api/admin/http-client'
|
||||
|
||||
// 引入组件
|
||||
const DictForm = defineAsyncComponent(() => import('./components/dict-form.vue'))
|
||||
const MyImport = defineAsyncComponent(() => import('/@/components/my-import/index.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const dictFormRef = ref()
|
||||
const dictImportRef = ref()
|
||||
|
||||
const defalutSort = { prop: 'sort', order: 'ascending' }
|
||||
|
||||
const getSortList = (data: { prop: string; order: any }) => {
|
||||
return [
|
||||
{
|
||||
propName: data.prop,
|
||||
order: data.order === 'ascending' ? 0 : data.order === 'descending' ? 1 : undefined,
|
||||
},
|
||||
] as [SortInput]
|
||||
}
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
dictFormTitle: '',
|
||||
filterModel: {
|
||||
name: '',
|
||||
dictTypeId: 0,
|
||||
},
|
||||
defalutSort: defalutSort,
|
||||
total: 0,
|
||||
pageInput: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
sortList: getSortList(defalutSort),
|
||||
} as PageInputDictGetPageInput,
|
||||
dictListData: [] as Array<DictGetPageOutput>,
|
||||
dictTypeName: '',
|
||||
import: {
|
||||
title: '',
|
||||
action: import.meta.env.VITE_API_URL + '/api/admin/dict/import-data',
|
||||
downloadTemplate: (params: RequestParams) => new DictApi().downloadTemplate(params),
|
||||
downloadErrorMark: (query: any, params: RequestParams) => new DictApi().downloadErrorMark(query, params),
|
||||
duplicateAction: 1,
|
||||
uniqueRules: ['字典名称', '字典编码', '字典值'],
|
||||
requiredColumns: ['字典类型', '字典名称'],
|
||||
},
|
||||
export: {
|
||||
loading: false,
|
||||
},
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
eventBus.off('refreshDict')
|
||||
eventBus.on('refreshDict', () => {
|
||||
onQuery()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshDict')
|
||||
})
|
||||
|
||||
const onSortChange = (data: { column: any; prop: string; order: any }) => {
|
||||
state.pageInput.sortList = getSortList(data)
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
state.pageInput.filter = state.filterModel
|
||||
const res = await new DictApi().getPage(state.pageInput).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
state.dictListData = res?.data?.list ?? []
|
||||
state.total = res?.data?.total ?? 0
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onAdd = () => {
|
||||
if (!(state.filterModel.dictTypeId > 0)) {
|
||||
proxy.$modal.msgWarning('请选择字典类型')
|
||||
return
|
||||
}
|
||||
state.dictFormTitle = `新增【${state.dictTypeName}】字典数据`
|
||||
dictFormRef.value.open({ dictTypeId: state.filterModel.dictTypeId })
|
||||
}
|
||||
|
||||
const onEdit = (row: DictGetPageOutput) => {
|
||||
state.dictFormTitle = `编辑【${state.dictTypeName}】字典数据`
|
||||
dictFormRef.value.open(row)
|
||||
}
|
||||
|
||||
const onDelete = (row: DictGetPageOutput) => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要删除【${row.name}】?`)
|
||||
.then(async () => {
|
||||
await new DictApi().delete({ id: row.id }, { loading: true, showSuccessMessage: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onImport = () => {
|
||||
state.import.title = `导入【${state.dictTypeName}】字典数据`
|
||||
dictImportRef.value.open()
|
||||
}
|
||||
|
||||
const onExport = async () => {
|
||||
state.export.loading = true
|
||||
|
||||
await new DictApi()
|
||||
.exportData(
|
||||
{
|
||||
dynamicFilter: {
|
||||
filters: [{ field: 'dictTypeId', operator: 6, value: state.pageInput.filter?.dictTypeId }],
|
||||
},
|
||||
sortList: state.pageInput.sortList,
|
||||
},
|
||||
{ format: 'blob', returnResponse: true }
|
||||
)
|
||||
.then((res: any) => {
|
||||
const contentDisposition = res.headers['content-disposition']
|
||||
const matchs = /filename="?([^;"]+)/i.exec(contentDisposition)
|
||||
let fileName = ''
|
||||
if (matchs && matchs.length > 1) {
|
||||
fileName = decodeURIComponent(matchs[1])
|
||||
} else {
|
||||
fileName = `数据字典列表${dayjs().format('YYYYMMDDHHmmss')}.xlsx`
|
||||
}
|
||||
const a = document.createElement('a')
|
||||
a.download = fileName
|
||||
a.href = URL.createObjectURL(res.data as Blob)
|
||||
a.click()
|
||||
URL.revokeObjectURL(a.href)
|
||||
})
|
||||
.finally(() => {
|
||||
state.export.loading = false
|
||||
})
|
||||
}
|
||||
|
||||
const onSizeChange = (val: number) => {
|
||||
state.pageInput.currentPage = 1
|
||||
state.pageInput.pageSize = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onCurrentChange = (val: number) => {
|
||||
state.pageInput.currentPage = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const refresh = (data: DictTypeGetPageOutput) => {
|
||||
if ((data?.id as number) > 0) {
|
||||
state.filterModel.dictTypeId = data.id as number
|
||||
state.dictTypeName = data.name as string
|
||||
onQuery()
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
refresh,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -1,29 +0,0 @@
|
||||
<template>
|
||||
<MySplitPanes>
|
||||
<pane size="50" min-size="30" max-size="70">
|
||||
<dict-type @change="onChange"></dict-type>
|
||||
</pane>
|
||||
<pane>
|
||||
<dict ref="dictRef"></dict>
|
||||
</pane>
|
||||
</MySplitPanes>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/dict">
|
||||
import { defineAsyncComponent, ref } from 'vue'
|
||||
import { Pane } from 'splitpanes'
|
||||
import { DictTypeGetPageOutput } from '/@/api/admin/data-contracts'
|
||||
|
||||
// 引入组件
|
||||
const DictType = defineAsyncComponent(() => import('./dict-type.vue'))
|
||||
const Dict = defineAsyncComponent(() => import('./dict.vue'))
|
||||
const MySplitPanes = defineAsyncComponent(() => import('/@/components/my-layout/split-panes.vue'))
|
||||
|
||||
const dictRef = ref()
|
||||
|
||||
const onChange = (data: DictTypeGetPageOutput) => {
|
||||
dictRef.value?.refresh(data)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -1,143 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog v-model="state.showDialog" :title="title" draggable :close-on-click-modal="false" :close-on-press-escape="false" width="600px">
|
||||
<div class="mb15">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-input v-model="state.fileDirectory" placeholder="文件目录" clearable />
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-switch v-model="state.fileReName" active-text="文件自动重命名" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div class="mt5">
|
||||
<el-alert class="my-el-alert" title="文件目录不填则默认使用本地上传格式:upload/yyyy/MM/dd" type="info" :closable="false" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<!-- :before-remove="() => false" -->
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
:action="uploadAction"
|
||||
:headers="uploadHeaders"
|
||||
:data="{ fileDirectory: state.fileDirectory, fileReName: state.fileReName }"
|
||||
drag
|
||||
multiple
|
||||
:auto-upload="false"
|
||||
:before-upload="
|
||||
() => {
|
||||
state.token = storesUserInfo.getToken()
|
||||
}
|
||||
"
|
||||
:on-success="onSuccess"
|
||||
:on-error="onError"
|
||||
>
|
||||
<el-icon class="el-icon--upload"><ele-UploadFilled /></el-icon>
|
||||
<div class="el-upload__text">拖拽上传或<em>点击上传</em></div>
|
||||
<!-- <template #tip>
|
||||
<div class="el-upload__tip"></div>
|
||||
</template> -->
|
||||
</el-upload>
|
||||
</div>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onClear">清空已上传</el-button>
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/file/upload">
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import type { UploadInstance, UploadProps, UploadFile } from 'element-plus'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { useUserInfo } from '/@/stores/userInfo'
|
||||
|
||||
const storesUserInfo = useUserInfo()
|
||||
|
||||
const uploadRef = ref<UploadInstance>()
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
fileDirectory: '',
|
||||
fileReName: true,
|
||||
fileList: [] as UploadFile[],
|
||||
token: storesUserInfo.getToken(),
|
||||
})
|
||||
|
||||
const uploadAction = computed(() => {
|
||||
return import.meta.env.VITE_API_URL + '/api/admin/file/upload-file'
|
||||
})
|
||||
|
||||
const uploadHeaders = computed(() => {
|
||||
return { Authorization: 'Bearer ' + state.token }
|
||||
})
|
||||
|
||||
// 打开对话框
|
||||
const open = async () => {
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
//上传失败
|
||||
const onError: UploadProps['onError'] = (error) => {
|
||||
let message = ''
|
||||
if (error.message) {
|
||||
try {
|
||||
message = JSON.parse(error.message)?.msg
|
||||
} catch (err) {
|
||||
message = error.message || ''
|
||||
}
|
||||
}
|
||||
if (message)
|
||||
ElMessage({
|
||||
message: message,
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
|
||||
// 上传成功
|
||||
const onSuccess: UploadProps['onSuccess'] = (response) => {
|
||||
if (response?.success) {
|
||||
eventBus.emit('refreshFile')
|
||||
}
|
||||
}
|
||||
|
||||
// 清空已上传
|
||||
const onClear = async () => {
|
||||
uploadRef.value!.clearFiles(['success', 'fail'])
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = async () => {
|
||||
uploadRef.value!.submit()
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.my-el-alert {
|
||||
border: none;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
</style>
|
||||
@ -1,190 +0,0 @@
|
||||
<template>
|
||||
<my-layout>
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :model="state.filterModel" :inline="true" @submit.stop.prevent>
|
||||
<el-form-item prop="name">
|
||||
<el-input v-model="state.filterModel.fileName" placeholder="文件名" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:file:upload-file'" type="primary" icon="ele-Upload" @click="onUpload"> 上传 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table v-loading="state.loading" :data="state.fileListData" row-key="id" style="width: 100%" border>
|
||||
<el-table-column prop="fileName" label="文件名" min-width="220">
|
||||
<template #default="{ row }">
|
||||
<div class="my-flex">
|
||||
<el-image
|
||||
v-if="isImage(row.extension)"
|
||||
:src="row.linkUrl"
|
||||
:preview-src-list="previewImglist"
|
||||
:initial-index="getInitialIndex(row.linkUrl)"
|
||||
:lazy="true"
|
||||
:hide-on-click-modal="true"
|
||||
fit="scale-down"
|
||||
preview-teleported
|
||||
style="width: 80px; height: 80px"
|
||||
/>
|
||||
<div class="ml10 my-flex-fill my-flex-y-center">
|
||||
<div>{{ (row.fileName || '') + (row.extension || '') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sizeFormat" label="大小" width="120" />
|
||||
<el-table-column prop="createdUserName" label="上传者" width="82">
|
||||
<template #default="{ row }">
|
||||
{{ row.modifiedUserName || row.createdUserName || '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createdTime" label="更新时间" width="100">
|
||||
<template #default="{ row }">
|
||||
{{ formatterTime(row.modifiedTime || row.createdTime || '') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="providerName" label="供应商" width="82" />
|
||||
<el-table-column prop="bucketName" label="存储桶" min-width="120" />
|
||||
<el-table-column prop="fileDirectory" label="目录" min-width="120" />
|
||||
<el-table-column label="操作" width="180" fixed="right" header-align="center" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-popover :width="220">
|
||||
<p>{{ row.linkUrl }}</p>
|
||||
<div class="mt10" style="text-align: right; margin: 0">
|
||||
<el-button icon="ele-CopyDocument" type="primary" @click="copyText(row.linkUrl)">复制地址</el-button>
|
||||
</div>
|
||||
<template #reference>
|
||||
<el-button text type="primary">地址</el-button>
|
||||
</template>
|
||||
</el-popover>
|
||||
<el-link class="my-el-link mr12 ml12" :href="row.linkUrl" type="primary" icon="ele-Download" underline="never" target="_blank"
|
||||
>下载</el-link
|
||||
>
|
||||
<el-button v-auth="'api:admin:file:delete'" icon="ele-Delete" text type="danger" @click="onDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="my-flex my-flex-end" style="margin-top: 10px">
|
||||
<el-pagination
|
||||
v-model:currentPage="state.pageInput.currentPage"
|
||||
v-model:page-size="state.pageInput.pageSize"
|
||||
:total="state.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
background
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<file-upload ref="fileUploadRef" title="上传文件"></file-upload>
|
||||
</my-layout>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/file">
|
||||
import { ref, reactive, onMounted, onBeforeMount, defineAsyncComponent, computed, getCurrentInstance } from 'vue'
|
||||
import { PageInputFileGetPageInput, FileGetPageOutput } from '/@/api/admin/data-contracts'
|
||||
import { FileApi } from '/@/api/admin/File'
|
||||
import dayjs from 'dayjs'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { isImage } from '/@/utils/test'
|
||||
import commonFunction from '/@/utils/commonFunction'
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const FileUpload = defineAsyncComponent(() => import('./components/file-upload.vue'))
|
||||
|
||||
const fileUploadRef = ref()
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
fileFormTitle: '',
|
||||
filterModel: {
|
||||
fileName: '',
|
||||
},
|
||||
total: 0,
|
||||
pageInput: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
} as PageInputFileGetPageInput,
|
||||
fileListData: [] as Array<FileGetPageOutput>,
|
||||
fileLogsTitle: '',
|
||||
})
|
||||
|
||||
const { copyText } = commonFunction()
|
||||
|
||||
const previewImglist = computed(() => {
|
||||
let imgList = [] as string[]
|
||||
state.fileListData.forEach((a) => {
|
||||
if (isImage(a.extension as string) && a.linkUrl) {
|
||||
imgList.push(a.linkUrl as string)
|
||||
}
|
||||
})
|
||||
return imgList
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
onQuery()
|
||||
eventBus.off('refreshFile')
|
||||
eventBus.on('refreshFile', async () => {
|
||||
onQuery()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshFile')
|
||||
})
|
||||
|
||||
const formatterTime = (cellValue: any) => {
|
||||
return dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
|
||||
const getInitialIndex = (imgUrl: string) => {
|
||||
return previewImglist.value.indexOf(imgUrl)
|
||||
}
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
const res = await new FileApi().getPage({ ...state.pageInput, filter: state.filterModel }).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
|
||||
state.fileListData = res?.data?.list ?? []
|
||||
state.total = res?.data?.total ?? 0
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onSizeChange = (val: number) => {
|
||||
state.pageInput.currentPage = 1
|
||||
state.pageInput.pageSize = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onCurrentChange = (val: number) => {
|
||||
state.pageInput.currentPage = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onUpload = () => {
|
||||
fileUploadRef.value.open()
|
||||
}
|
||||
|
||||
const onDelete = (row: FileGetPageOutput) => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要删除文件【${row.fileName}${row.extension}】?`)
|
||||
.then(async () => {
|
||||
await new FileApi().delete({ id: row.id as number }, { loading: true, showSuccessMessage: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.my-el-link {
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
@ -1,101 +0,0 @@
|
||||
<template>
|
||||
<el-drawer
|
||||
v-model="state.showDialog"
|
||||
title="操作日志详细信息"
|
||||
direction="rtl"
|
||||
destroy-on-close
|
||||
size="600"
|
||||
:append-to-body="true"
|
||||
:lock-scroll="false"
|
||||
>
|
||||
<div class="my-fill h100" style="padding: 12px">
|
||||
<el-descriptions class="margin-top" :column="1" border>
|
||||
<el-descriptions-item label="操作名称" label-class-name="label">{{ state.details.apiLabel }}</el-descriptions-item>
|
||||
<el-descriptions-item label="操作接口" label-class-name="label">{{ state.details.apiPath }}</el-descriptions-item>
|
||||
<el-descriptions-item label="操作状态" label-class-name="label"
|
||||
><el-tag :type="state.details.status ? 'success' : 'danger'" disable-transitions>{{
|
||||
state.details.status ? '成功' : '失败'
|
||||
}}</el-tag></el-descriptions-item
|
||||
>
|
||||
<el-descriptions-item label="请求方法" label-class-name="label">{{ state.details.apiMethod }}</el-descriptions-item>
|
||||
<el-descriptions-item label="响应代码 " label-class-name="label">{{ state.details.statusCode }}</el-descriptions-item>
|
||||
<el-descriptions-item label="IP地址" label-class-name="label">{{ state.details.ip }} {{ state.details.isp }}</el-descriptions-item>
|
||||
<el-descriptions-item label="IP所在地" label-class-name="label"
|
||||
>{{ state.details.country }} {{ state.details.province }} {{ state.details.city }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="浏览器信息" label-class-name="label"
|
||||
>{{ state.details.os }} {{ state.details.browser }} {{ state.details.device }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="耗时ms" label-class-name="label">{{ state.details.elapsedMilliseconds }}</el-descriptions-item>
|
||||
<el-descriptions-item label="操作账号" label-class-name="label">{{ state.details.createdUserName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="操作人员" label-class-name="label">{{ state.details.createdUserRealName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间" label-class-name="label">{{
|
||||
dayjs(state.details.createdTime).format('YYYY-MM-DD HH:mm:ss')
|
||||
}}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<el-collapse class="mt12" v-model="state.activeName">
|
||||
<el-collapse-item title="请求参数" name="params">
|
||||
<MyJsonEditor
|
||||
ref="jsonEditorRef"
|
||||
v-model="state.details.params"
|
||||
:options="{
|
||||
mainMenuBar: false,
|
||||
statusBar: false,
|
||||
onEditable: () => false,
|
||||
}"
|
||||
style="height: 400px !important"
|
||||
></MyJsonEditor>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="响应结果" name="result">
|
||||
<MyJsonEditor
|
||||
ref="jsonEditorRef"
|
||||
v-model="state.details.result"
|
||||
:options="{
|
||||
mainMenuBar: false,
|
||||
statusBar: false,
|
||||
onEditable: () => false,
|
||||
}"
|
||||
style="height: 200px !important"
|
||||
></MyJsonEditor>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="operation-log-details">
|
||||
import { reactive } from 'vue'
|
||||
import { OperationLogGetPageOutput } from '/@/api/admin/data-contracts'
|
||||
import dayjs from 'dayjs'
|
||||
import MyJsonEditor from '/@/components/my-json-editor/index.vue'
|
||||
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
details: {} as OperationLogGetPageOutput,
|
||||
activeName: ['params', 'result'],
|
||||
})
|
||||
|
||||
// 打开对话框
|
||||
const open = (row: OperationLogGetPageOutput) => {
|
||||
state.showDialog = true
|
||||
state.details = row
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep() {
|
||||
.el-descriptions .label {
|
||||
width: 120px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,137 +0,0 @@
|
||||
<template>
|
||||
<my-layout>
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form ref="filterFormRef" :model="state.filter" :inline="true" label-width="auto" :label-position="'left'" @submit.stop.prevent>
|
||||
<el-form-item label="登录账号" prop="createdUserName">
|
||||
<el-input v-model="state.filter.createdUserName" placeholder="登录账号" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="登录状态" prop="status">
|
||||
<el-select v-model="state.filter.status" :empty-values="[null]" style="width: 120px" @change="onQuery">
|
||||
<el-option v-for="status in state.statusList" :key="status.name" :label="status.name" :value="status.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="登录IP" prop="ip">
|
||||
<el-input v-model="state.filter.ip" placeholder="登录IP" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="登录时间">
|
||||
<MyDateRange
|
||||
v-model:startDate="state.filter.addStartTime as string"
|
||||
v-model:endDate="state.filter.addEndTime as string"
|
||||
:shortcuts="[]"
|
||||
style="width: 230px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
<el-button icon="ele-RefreshLeft" text bg @click="onReset(filterFormRef)"> 重置 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table v-loading="state.loading" :data="state.loginLogListData" row-key="id" style="width: 100%" border>
|
||||
<el-table-column prop="createdUserName" label="登录账号" min-width="150" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<el-badge :type="row.status ? 'success' : 'danger'" is-dot :offset="[0, 12]"></el-badge>
|
||||
{{ row.createdUserName }}<br />{{ row.nickName }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="ip" label="登录IP" min-width="150">
|
||||
<template #default="{ row }"> {{ row.ip }} {{ row.isp }} </template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="country" label="登录地区" min-width="150" show-overflow-tooltip>
|
||||
<template #default="{ row }"> {{ row.country }} {{ row.province }} {{ row.city }} </template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="os" label="操作系统" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="browser" label="浏览器" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="elapsedMilliseconds" label="耗时 ms" min-width="120" />
|
||||
<el-table-column prop="msg" label="登录信息" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column prop="createdTime" label="登录时间" :formatter="formatterTime" min-width="160" />
|
||||
</el-table>
|
||||
<div class="my-flex my-flex-end" style="margin-top: 10px">
|
||||
<el-pagination
|
||||
v-model:currentPage="state.pageInput.currentPage"
|
||||
v-model:page-size="state.pageInput.pageSize"
|
||||
:total="state.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
background
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</my-layout>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/loginLog">
|
||||
import { reactive, onMounted, ref, defineAsyncComponent } from 'vue'
|
||||
import { PageInputLoginLogGetPageInput, LoginLogGetPageInput, LoginLogGetPageOutput } from '/@/api/admin/data-contracts'
|
||||
import { LoginLogApi } from '/@/api/admin/LoginLog'
|
||||
import dayjs from 'dayjs'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
|
||||
const MyDateRange = defineAsyncComponent(() => import('/@/components/my-date-range/index.vue'))
|
||||
|
||||
const filterFormRef = ref<FormInstance>()
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
loginLogFormTitle: '',
|
||||
filter: {} as LoginLogGetPageInput,
|
||||
total: 0,
|
||||
pageInput: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
} as PageInputLoginLogGetPageInput,
|
||||
loginLogListData: [] as Array<LoginLogGetPageOutput>,
|
||||
loginLogLogsTitle: '',
|
||||
statusList: [
|
||||
{ name: '全部', value: undefined },
|
||||
{ name: '成功', value: true },
|
||||
{ name: '失败', value: false },
|
||||
],
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
onQuery()
|
||||
})
|
||||
|
||||
const formatterTime = (row: any, column: any, cellValue: any) => {
|
||||
return dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
state.pageInput.filter = state.filter
|
||||
const res = await new LoginLogApi().getPage(state.pageInput).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
|
||||
state.loginLogListData = res?.data?.list ?? []
|
||||
state.total = res?.data?.total ?? 0
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onReset = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
state.filter.addStartTime = undefined
|
||||
state.filter.addEndTime = undefined
|
||||
formEl.resetFields()
|
||||
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onSizeChange = (val: number) => {
|
||||
state.pageInput.currentPage = 1
|
||||
state.pageInput.pageSize = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onCurrentChange = (val: number) => {
|
||||
state.pageInput.currentPage = val
|
||||
onQuery()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -1,150 +0,0 @@
|
||||
<template>
|
||||
<my-layout>
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form ref="filterFormRef" :model="state.filter" :inline="true" label-width="auto" :label-position="'left'" @submit.stop.prevent>
|
||||
<el-form-item label="操作账号" prop="createdUserName">
|
||||
<el-input v-model="state.filter.createdUserName" placeholder="操作账号" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="操作状态" prop="status">
|
||||
<el-select v-model="state.filter.status" :empty-values="[null]" style="width: 120px" @change="onQuery">
|
||||
<el-option v-for="status in state.statusList" :key="status.name" :label="status.name" :value="status.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="操作接口" prop="api">
|
||||
<el-input v-model="state.filter.api" placeholder="操作接口" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="操作IP" prop="ip">
|
||||
<el-input v-model="state.filter.ip" placeholder="操作IP" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="操作时间">
|
||||
<MyDateRange v-model:startDate="state.filter.addStartTime" v-model:endDate="state.filter.addEndTime" :shortcuts="[]" style="width: 230px" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
<el-button icon="ele-RefreshLeft" text bg @click="onReset(filterFormRef)"> 重置 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table ref="tableRef" v-loading="state.loading" :data="state.operationLogListData" row-key="id" style="width: 100%" border>
|
||||
<el-table-column prop="createdUserName" label="操作账号" min-width="150" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<el-badge :type="row.status ? 'success' : 'danger'" is-dot :offset="[0, 12]"></el-badge>
|
||||
{{ row.createdUserName }}<br />{{ row.nickName }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="apiLabel" label="操作名称" min-width="220" show-overflow-tooltip />
|
||||
<el-table-column prop="apiPath" label="操作接口" min-width="260" show-overflow-tooltip />
|
||||
<el-table-column prop="ip" label="IP地址" min-width="150">
|
||||
<template #default="{ row }"> {{ row.ip }} {{ row.isp }} </template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="country" label="IP所在地" min-width="150" show-overflow-tooltip>
|
||||
<template #default="{ row }"> {{ row.country }} {{ row.province }} {{ row.city }} </template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="elapsedMilliseconds" label="耗时 ms" min-width="100" />
|
||||
<el-table-column prop="createdTime" label="操作时间" :formatter="formatterTime" min-width="160" />
|
||||
<el-table-column label="操作" width="100" fixed="right" header-align="center" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button text type="primary" @click="onShowDetails(row)">查看详情</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="my-flex my-flex-end" style="margin-top: 10px">
|
||||
<el-pagination
|
||||
v-model:currentPage="state.pageInput.currentPage"
|
||||
v-model:page-size="state.pageInput.pageSize"
|
||||
:total="state.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
background
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<Details ref="detailsRef"></Details>
|
||||
</my-layout>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/operation-log">
|
||||
import { reactive, onMounted, ref, defineAsyncComponent } from 'vue'
|
||||
import { OperationLogGetPageOutput, PageInputOperationLogGetPageInput, OperationLogGetPageInput } from '/@/api/admin/data-contracts'
|
||||
import { OperationLogApi } from '/@/api/admin/OperationLog'
|
||||
import dayjs from 'dayjs'
|
||||
import type { FormInstance, TableInstance } from 'element-plus'
|
||||
|
||||
const filterFormRef = ref<FormInstance>()
|
||||
const tableRef = ref<TableInstance>()
|
||||
const detailsRef = ref()
|
||||
|
||||
const MyDateRange = defineAsyncComponent(() => import('/@/components/my-date-range/index.vue'))
|
||||
const Details = defineAsyncComponent(() => import('./components/details.vue'))
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
oprationLogFormTitle: '',
|
||||
filter: {} as OperationLogGetPageInput,
|
||||
total: 0,
|
||||
pageInput: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
} as PageInputOperationLogGetPageInput,
|
||||
operationLogListData: [] as Array<OperationLogGetPageOutput>,
|
||||
operationLogLogsTitle: '',
|
||||
statusList: [
|
||||
{ name: '全部', value: undefined },
|
||||
{ name: '成功', value: true },
|
||||
{ name: '失败', value: false },
|
||||
],
|
||||
details: {},
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
onQuery()
|
||||
})
|
||||
|
||||
const formatterTime = (row: OperationLogGetPageOutput, column: any, cellValue: any) => {
|
||||
return dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
|
||||
const onShowDetails = (row: OperationLogGetPageOutput) => {
|
||||
detailsRef.value!.open(row)
|
||||
}
|
||||
|
||||
const onReset = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
state.filter.addStartTime = undefined
|
||||
state.filter.addEndTime = undefined
|
||||
formEl.resetFields()
|
||||
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
state.pageInput.filter = state.filter
|
||||
const res = await new OperationLogApi().getPage(state.pageInput).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
|
||||
state.operationLogListData = res?.data?.list ?? []
|
||||
state.total = res?.data?.total ?? 0
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onSizeChange = (val: number) => {
|
||||
state.pageInput.currentPage = 1
|
||||
state.pageInput.pageSize = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onCurrentChange = async (val: number) => {
|
||||
state.pageInput.currentPage = val
|
||||
await onQuery()
|
||||
tableRef.value?.setScrollTop(0)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -1,137 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="600px"
|
||||
>
|
||||
<el-form :model="form" ref="formRef" label-width="80px">
|
||||
<el-row :gutter="35">
|
||||
<el-col v-if="!(form.id > 0 && !(Number(form.parentId) > 0))" :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="上级分组" prop="parentId">
|
||||
<el-tree-select
|
||||
v-model="form.parentId"
|
||||
:data="treeData"
|
||||
node-key="id"
|
||||
:props="{ label: 'name' }"
|
||||
check-strictly
|
||||
default-expand-all
|
||||
render-after-expand
|
||||
fit-input-width
|
||||
clearable
|
||||
class="w100"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="名称" prop="name" :rules="[{ required: true, message: '请输入名称', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.name" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="编码" prop="code">
|
||||
<el-input v-model="form.code" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="排序">
|
||||
<el-input-number v-model="form.sort" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/msg-type/form">
|
||||
import { reactive, toRefs, ref, PropType } from 'vue'
|
||||
import { MsgTypeGetListOutput, MsgTypeUpdateInput } from '/@/api/admin/data-contracts'
|
||||
import { MsgTypeApi } from '/@/api/admin/MsgType'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
treeData: {
|
||||
type: Array as PropType<MsgTypeGetListOutput[]>,
|
||||
default: () => [],
|
||||
},
|
||||
})
|
||||
|
||||
const formRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
form: {} as MsgTypeUpdateInput,
|
||||
})
|
||||
|
||||
const { form } = toRefs(state)
|
||||
|
||||
// 打开对话框
|
||||
const open = async (row: MsgTypeUpdateInput = { id: 0 }) => {
|
||||
let formData = cloneDeep(row) as MsgTypeUpdateInput
|
||||
if (row.id > 0) {
|
||||
const res = await new MsgTypeApi().get({ id: row.id }, { loading: true })
|
||||
|
||||
if (res?.success) {
|
||||
formData = res.data as MsgTypeUpdateInput
|
||||
formData.parentId = formData.parentId && formData.parentId > 0 ? formData.parentId : undefined
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
state.form = formData
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
state.sureLoading = true
|
||||
let res = {} as any
|
||||
state.form.parentId = state.form.parentId && state.form.parentId > 0 ? state.form.parentId : undefined
|
||||
if (state.form.id != undefined && state.form.id > 0) {
|
||||
res = await new MsgTypeApi().update(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
} else {
|
||||
res = await new MsgTypeApi().add(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
eventBus.emit('refreshMsgType')
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
@ -1,131 +0,0 @@
|
||||
<template>
|
||||
<MyLayout>
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" @submit.stop.prevent>
|
||||
<el-form-item label="分类名称">
|
||||
<el-input v-model="state.filter.msgTypeName" placeholder="分类名称" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:msg-type:add'" type="primary" icon="ele-Plus" @click="onAdd"> 新增 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table
|
||||
ref="msgTypeTableRef"
|
||||
v-loading="state.loading"
|
||||
:data="state.msgTypeTreeData"
|
||||
row-key="id"
|
||||
default-expand-all
|
||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
style="width: 100%"
|
||||
border
|
||||
>
|
||||
<el-table-column prop="name" label="分类名称" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="code" label="分类编码" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="sort" label="排序" width="82" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="180" fixed="right" header-align="center" align="right">
|
||||
<template #default="{ row }">
|
||||
<el-button v-if="row.parentId === 0" v-auth="'api:admin:msg-type:add'" icon="ele-Plus" text type="primary" @click="onAdd(row)"
|
||||
>添加</el-button
|
||||
>
|
||||
<el-button v-auth="'api:admin:msg-type:update'" icon="ele-EditPen" text type="primary" @click="onEdit(row)">编辑</el-button>
|
||||
<el-button v-auth="'api:admin:msg-type:delete'" icon="ele-Delete" text type="danger" @click="onDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<msg-type-form ref="msgTypeFormRef" :title="state.msgTypeFormTitle" :tree-data="state.msgTypeFormTreeData"></msg-type-form>
|
||||
</MyLayout>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/msg-type">
|
||||
import { ref, reactive, onMounted, getCurrentInstance, onBeforeMount, nextTick, defineAsyncComponent } from 'vue'
|
||||
import { MsgTypeGetListOutput } from '/@/api/admin/data-contracts'
|
||||
import { MsgTypeApi } from '/@/api/admin/MsgType'
|
||||
import { listToTree, filterTree } from '/@/utils/tree'
|
||||
import { ElTable } from 'element-plus'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
|
||||
// 引入组件
|
||||
const MsgTypeForm = defineAsyncComponent(() => import('./components/msg-type-form.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const msgTypeTableRef = ref()
|
||||
const msgTypeFormRef = ref()
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
userListLoading: false,
|
||||
sureLoading: false,
|
||||
msgTypeFormTitle: '',
|
||||
filter: {
|
||||
name: '',
|
||||
msgTypeName: '',
|
||||
},
|
||||
msgTypeTreeData: [] as any,
|
||||
msgTypeFormTreeData: [] as any,
|
||||
msgTypeId: undefined as number | undefined,
|
||||
msgTypeName: '' as string | null | undefined,
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
onQuery()
|
||||
eventBus.off('refreshMsgType')
|
||||
eventBus.on('refreshMsgType', async () => {
|
||||
onQuery()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshMsgType')
|
||||
})
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
const res = await new MsgTypeApi().getList().catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
if (res && res.data && res.data.length > 0) {
|
||||
state.msgTypeTreeData = filterTree(listToTree(cloneDeep(res.data)), state.filter.msgTypeName)
|
||||
state.msgTypeFormTreeData = listToTree(cloneDeep(res.data).filter((a) => a.parentId === 0))
|
||||
if (state.msgTypeTreeData.length > 0 && state.msgTypeTreeData[0].children?.length > 0) {
|
||||
nextTick(() => {
|
||||
msgTypeTableRef.value!.setCurrentRow(state.msgTypeTreeData[0].children[0])
|
||||
})
|
||||
}
|
||||
} else {
|
||||
state.msgTypeTreeData = []
|
||||
state.msgTypeFormTreeData = []
|
||||
}
|
||||
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onAdd = (row: MsgTypeGetListOutput | undefined = undefined) => {
|
||||
state.msgTypeFormTitle = '新增消息分类'
|
||||
msgTypeFormRef.value.open({ id: 0, parentId: row?.id })
|
||||
}
|
||||
|
||||
const onEdit = (row: MsgTypeGetListOutput) => {
|
||||
state.msgTypeFormTitle = '编辑消息分类'
|
||||
msgTypeFormRef.value.open(row)
|
||||
}
|
||||
|
||||
const onDelete = (row: MsgTypeGetListOutput) => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要删除消息分类【${row.name}】?`)
|
||||
.then(async () => {
|
||||
await new MsgTypeApi().delete({ id: row.id }, { loading: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -1,253 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="830px"
|
||||
>
|
||||
<el-form :model="form" ref="formRef" label-width="auto">
|
||||
<el-row :gutter="35">
|
||||
<!-- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="分类" prop="typeId" :rules="[{ required: true, message: '请选择分类', trigger: ['change'] }]" hidden>
|
||||
<el-tree-select
|
||||
v-model="form.typeId"
|
||||
placeholder="请选择分类"
|
||||
:data="state.msgTypeTreeData"
|
||||
node-key="id"
|
||||
:props="{ label: 'name' }"
|
||||
default-expand-all
|
||||
fit-input-width
|
||||
clearable
|
||||
filterable
|
||||
class="w100"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="标题" prop="title" :rules="[{ required: true, message: '请输入标题', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.title" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item
|
||||
label="内容"
|
||||
prop="content"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入内容', trigger: ['blur', 'change'] },
|
||||
{ validator: testEditorContent, trigger: ['blur', 'change'] },
|
||||
]"
|
||||
>
|
||||
<MyEditor ref="editorRef" v-model:model-value="form.content" @onBlur="onValidateContent" @onChange="onValidateContent"></MyEditor>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="状态" prop="status" :rules="[{ required: true, message: '请选择状态', trigger: ['change'] }]">
|
||||
<el-select v-model="form.status" placeholder="请选择状态" class="w100" @change="onStatusChange">
|
||||
<el-option v-for="item in state.msgStatusList" :key="item.label" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="isScheduledStatus">
|
||||
<el-form-item
|
||||
label="发布时间"
|
||||
prop="publishTime"
|
||||
:rules="[{
|
||||
required: isScheduledStatus,
|
||||
message: '请选择发布时间',
|
||||
trigger: ['change', 'blur']
|
||||
}]"
|
||||
>
|
||||
<el-date-picker
|
||||
v-model="form.publishTime"
|
||||
type="datetime"
|
||||
placeholder="请选择发布时间"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
:disabled-date="disabledDate"
|
||||
class="w100"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/msg/form">
|
||||
import { reactive, toRefs, ref, defineAsyncComponent, getCurrentInstance, computed } from 'vue'
|
||||
import { MsgUpdateInput, MsgTypeGetListOutput } from '/@/api/admin/data-contracts'
|
||||
import { MsgApi } from '/@/api/admin/Msg'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { MsgTypeApi } from '/@/api/admin/MsgType'
|
||||
import { listToTree } from '/@/utils/tree'
|
||||
import { MsgStatusEnum } from '/@/api/admin/enum-contracts'
|
||||
import { toOptionsByValue } from '/@/utils/enum'
|
||||
|
||||
// 扩展 MsgUpdateInput 接口以包含定时发布时间
|
||||
interface ExtendedMsgUpdateInput extends MsgUpdateInput {
|
||||
publishTime?: string
|
||||
}
|
||||
|
||||
const MyEditor = defineAsyncComponent(() => import('/@/components/my-editor/index.vue'))
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const formRef = ref()
|
||||
const editorRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
form: { content: '' } as ExtendedMsgUpdateInput,
|
||||
msgTypeTreeData: [] as MsgTypeGetListOutput[],
|
||||
v: null,
|
||||
msgStatusList: toOptionsByValue(MsgStatusEnum),
|
||||
})
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const { form } = toRefs(state)
|
||||
|
||||
// 判断是否为定时发布状态
|
||||
const isScheduledStatus = computed(() => {
|
||||
return state.form.status === 3 // 3 对应 Scheduled 定时发布状态
|
||||
})
|
||||
|
||||
const testEditorContent = (rule: any, value: any, callback: any) => {
|
||||
if (!value) {
|
||||
callback()
|
||||
}
|
||||
if (editorRef.value.isEmpty()) {
|
||||
callback(new Error('请输入内容'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
const onValidateContent = () => {
|
||||
formRef.value.validateField('content')
|
||||
}
|
||||
|
||||
// 状态变化处理
|
||||
const onStatusChange = (value: number) => {
|
||||
if (value !== 3) { // 3 对应定时发布状态
|
||||
state.form.publishTime = undefined
|
||||
// 清除发布时间的验证错误
|
||||
formRef.value?.clearValidate('publishTime')
|
||||
}
|
||||
}
|
||||
|
||||
// 禁用过去日期
|
||||
const disabledDate = (time: Date) => {
|
||||
return time.getTime() < Date.now() - 86400000 // 不能选择今天之前的日期
|
||||
}
|
||||
|
||||
const getMsgTypes = async () => {
|
||||
const res = await new MsgTypeApi().getList().catch(() => {
|
||||
state.msgTypeTreeData = []
|
||||
})
|
||||
if (res?.success && res.data && res.data.length > 0) {
|
||||
state.msgTypeTreeData = listToTree(res.data)
|
||||
} else {
|
||||
state.msgTypeTreeData = []
|
||||
}
|
||||
}
|
||||
|
||||
// 打开对话框
|
||||
const open = async (row: ExtendedMsgUpdateInput = { id: 0 }) => {
|
||||
proxy.$modal.loading()
|
||||
|
||||
await getMsgTypes()
|
||||
|
||||
let formData = cloneDeep(row) as ExtendedMsgUpdateInput
|
||||
if (row.id > 0) {
|
||||
const res = await new MsgApi().get({ id: row.id }).catch(() => {
|
||||
proxy.$modal.closeLoading()
|
||||
})
|
||||
|
||||
if (res?.success) {
|
||||
formData = res.data as ExtendedMsgUpdateInput
|
||||
formData.typeId = formData.typeId && formData.typeId > 0 ? formData.typeId : undefined
|
||||
}
|
||||
}
|
||||
|
||||
state.form = formData
|
||||
state.form.typeId = 690214253387845
|
||||
|
||||
proxy.$modal.closeLoading()
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
// 定时发布验证
|
||||
if (isScheduledStatus.value) {
|
||||
if (!state.form.publishTime) {
|
||||
proxy.$message.error('选择定时发布时必须选择发布时间')
|
||||
return
|
||||
}
|
||||
|
||||
const publishTime = new Date(state.form.publishTime)
|
||||
const now = new Date()
|
||||
if (publishTime <= now) {
|
||||
proxy.$message.error('发布时间必须晚于当前时间')
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// 如果不是定时发布状态,清除发布时间
|
||||
state.form.publishTime = undefined
|
||||
}
|
||||
|
||||
state.sureLoading = true
|
||||
let res = {} as any
|
||||
if (state.form.id != undefined && state.form.id > 0) {
|
||||
res = await new MsgApi().update(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
} else {
|
||||
res = await new MsgApi().add(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
eventBus.emit('refreshMsg')
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@ -1,319 +0,0 @@
|
||||
<template>
|
||||
<MySplitPanes>
|
||||
<pane size="55" min-size="35" max-size="65">
|
||||
<div class="my-flex-column w100 h100">
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" @submit.stop.prevent>
|
||||
<el-form-item label="标题">
|
||||
<el-input v-model="state.filter.msgName" placeholder="标题" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:msg:add'" type="primary" icon="ele-Plus" @click="onAdd"> 新增 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table
|
||||
ref="msgTableRef"
|
||||
v-loading="state.loading"
|
||||
:data="state.msgData"
|
||||
default-expand-all
|
||||
highlight-current-row
|
||||
style="width: 100%"
|
||||
@current-change="onTableCurrentChange"
|
||||
border
|
||||
>
|
||||
<el-table-column prop="title" label="标题" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="typeName" label="消息分类" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="status" label="状态" min-width="90" show-overflow-tooltip :formatter="formatterMsgStatusEnum" />
|
||||
<el-table-column prop="createdTime" label="创建时间" :formatter="formatterTime" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="100" fixed="right" header-align="center" align="center">
|
||||
<template #default="{ row }">
|
||||
<my-dropdown-more v-auths="['api:admin:msg:update', 'api:admin:msg:delete']" style="margin-left: 0px">
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item v-if="auth('api:admin:msg:update')" @click="onEdit(row)">编辑</el-dropdown-item>
|
||||
<el-dropdown-item v-if="auth('api:admin:msg:delete')" @click="onDelete(row)">删除</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</my-dropdown-more>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="my-flex my-flex-end" style="margin-top: 10px">
|
||||
<el-pagination
|
||||
v-model:currentPage="state.pageInput.currentPage"
|
||||
v-model:page-size="state.pageInput.pageSize"
|
||||
:total="state.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
background
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</pane>
|
||||
<pane>
|
||||
<div class="my-flex-column w100 h100">
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" @submit.stop.prevent>
|
||||
<el-form-item label="姓名">
|
||||
<el-input v-model="state.filter.name" placeholder="姓名" @keyup.enter="onGetMsgUserList" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onGetMsgUserList"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:msg:add-msg-user'" type="primary" icon="ele-Plus" @click="onAddUser"> 添加 </el-button>
|
||||
<el-button v-auth="'api:admin:msg:remove-msg-user'" type="danger" icon="ele-Delete" @click="onRemoveUser"> 移除 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table
|
||||
ref="userTableRef"
|
||||
v-loading="state.userListLoading"
|
||||
:data="state.userListData"
|
||||
row-key="id"
|
||||
style="width: 100%"
|
||||
@row-click="onUserRowClick"
|
||||
border
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="name" label="姓名" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="是否已读" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="success" v-if="row.isRead">已读</el-tag>
|
||||
<el-tag type="info" v-else>未读</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="readTime" label="已读时间" :formatter="formatterTime" min-width="160" show-overflow-tooltip />
|
||||
<!-- <el-table-column prop="mobile" label="手机号" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="email" label="邮箱" min-width="180" show-overflow-tooltip /> -->
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
</pane>
|
||||
|
||||
<msg-form ref="msgFormRef" :title="state.msgFormTitle"></msg-form>
|
||||
<user-select
|
||||
ref="userSelectRef"
|
||||
:title="`添加【${state.msgName}】员工`"
|
||||
multiple
|
||||
:sure-loading="state.sureLoading"
|
||||
@sure="onSureUser"
|
||||
></user-select>
|
||||
</MySplitPanes>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/msg">
|
||||
import { ref, reactive, onMounted, getCurrentInstance, onBeforeMount, defineAsyncComponent } from 'vue'
|
||||
import {
|
||||
PageInputMsgGetPageInput,
|
||||
MsgGetMsgUserListOutput,
|
||||
UserGetPageOutput,
|
||||
MsgAddMsgUserListInput,
|
||||
MsgGetPageOutput,
|
||||
} from '/@/api/admin/data-contracts'
|
||||
import { MsgApi } from '/@/api/admin/Msg'
|
||||
import { ElTable } from 'element-plus'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { auth } from '/@/utils/authFunction'
|
||||
import { Pane } from 'splitpanes'
|
||||
import dayjs from 'dayjs'
|
||||
import { MsgStatusEnum } from '/@/api/admin/enum-contracts'
|
||||
import { getDescByValue } from '/@/utils/enum'
|
||||
|
||||
// 引入组件
|
||||
const MsgForm = defineAsyncComponent(() => import('./components/msg-form.vue'))
|
||||
const UserSelect = defineAsyncComponent(() => import('/@/views/admin/user/components/user-select.vue'))
|
||||
const MySplitPanes = defineAsyncComponent(() => import('/@/components/my-layout/split-panes.vue'))
|
||||
const MyDropdownMore = defineAsyncComponent(() => import('/@/components/my-dropdown-more/index.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const msgTableRef = ref()
|
||||
const msgFormRef = ref()
|
||||
const userTableRef = ref<InstanceType<typeof ElTable>>()
|
||||
const userSelectRef = ref()
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
userListLoading: false,
|
||||
sureLoading: false,
|
||||
msgFormTitle: '',
|
||||
filter: {
|
||||
name: '',
|
||||
msgName: '',
|
||||
},
|
||||
total: 0,
|
||||
pageInput: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
filter: {
|
||||
title: '',
|
||||
msgTypeValue: 690214253387845,
|
||||
},
|
||||
} as PageInputMsgGetPageInput,
|
||||
msgData: [] as any,
|
||||
userListData: [] as MsgGetMsgUserListOutput[],
|
||||
msgId: undefined as number | undefined,
|
||||
msgName: '' as string | null | undefined,
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
onQuery()
|
||||
eventBus.off('refreshMsg')
|
||||
eventBus.on('refreshMsg', () => {
|
||||
onQuery()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshMsg')
|
||||
})
|
||||
|
||||
const formatterMsgStatusEnum = (row: any, column: any, cellValue: any) => {
|
||||
return getDescByValue(MsgStatusEnum, cellValue)
|
||||
}
|
||||
|
||||
const formatterTime = (row: any, column: any, cellValue: any) => {
|
||||
return cellValue ? dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss') : ''
|
||||
}
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
if (state.pageInput.filter) state.pageInput.filter.title = state.filter.msgName
|
||||
const res = await new MsgApi().getPage(state.pageInput).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
|
||||
state.msgData = res?.data?.list ?? []
|
||||
state.total = res?.data?.total ?? 0
|
||||
|
||||
if (state.msgData?.length > 0) {
|
||||
window.setTimeout(() => {
|
||||
msgTableRef.value?.setCurrentRow(state.msgData[0])
|
||||
}, 100)
|
||||
// nextTick(() => {
|
||||
// msgTableRef.value?.setCurrentRow(state.msgData[0])
|
||||
// })
|
||||
}
|
||||
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onSizeChange = (val: number) => {
|
||||
state.pageInput.currentPage = 1
|
||||
state.pageInput.pageSize = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onCurrentChange = (val: number) => {
|
||||
state.pageInput.currentPage = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onAdd = () => {
|
||||
state.msgFormTitle = '新增活动消息'
|
||||
msgFormRef.value.open({ enabled: true })
|
||||
}
|
||||
|
||||
const onEdit = (row: MsgGetPageOutput) => {
|
||||
state.msgFormTitle = '编辑活动消息'
|
||||
msgFormRef.value.open(row)
|
||||
}
|
||||
|
||||
const onDelete = (row: MsgGetPageOutput) => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要删除消息【${row.title}】?`)
|
||||
.then(async () => {
|
||||
await new MsgApi().delete({ id: row.id }, { loading: true, showSuccessMessage: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onGetMsgUserList = async () => {
|
||||
state.userListLoading = true
|
||||
const res = await new MsgApi().getMsgUserList({ MsgId: state.msgId, Name: state.filter.name }).catch(() => {
|
||||
state.userListLoading = false
|
||||
})
|
||||
state.userListLoading = false
|
||||
if (res?.success) {
|
||||
if (res.data && res.data.length > 0) {
|
||||
state.userListData = res.data
|
||||
} else {
|
||||
state.userListData = []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const onTableCurrentChange = (currentRow: MsgGetPageOutput) => {
|
||||
if (!currentRow) {
|
||||
return
|
||||
}
|
||||
|
||||
state.msgId = currentRow.id
|
||||
state.msgName = currentRow.title
|
||||
onGetMsgUserList()
|
||||
}
|
||||
|
||||
const onUserRowClick = (row: MsgGetMsgUserListOutput) => {
|
||||
userTableRef.value!.toggleRowSelection(row, undefined)
|
||||
}
|
||||
|
||||
const onAddUser = () => {
|
||||
if (!((state.msgId as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择消息')
|
||||
return
|
||||
}
|
||||
userSelectRef.value.open({ msgId: state.msgId })
|
||||
}
|
||||
|
||||
const onRemoveUser = () => {
|
||||
if (!((state.msgId as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择消息')
|
||||
return
|
||||
}
|
||||
|
||||
const selectionRows = userTableRef.value!.getSelectionRows() as UserGetPageOutput[]
|
||||
|
||||
if (!((selectionRows.length as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择员工')
|
||||
return
|
||||
}
|
||||
|
||||
proxy.$modal
|
||||
.confirm(`确定要移除吗?`)
|
||||
.then(async () => {
|
||||
const userIds = selectionRows?.map((a) => a.id)
|
||||
const input = { msgId: state.msgId, userIds } as MsgAddMsgUserListInput
|
||||
await new MsgApi().removeMsgUser(input, { loading: true })
|
||||
onGetMsgUserList()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onSureUser = async (users: UserGetPageOutput[]) => {
|
||||
if (!(users?.length > 0)) {
|
||||
userSelectRef.value.close()
|
||||
return
|
||||
}
|
||||
|
||||
state.sureLoading = true
|
||||
const userIds = users?.map((a) => a.id)
|
||||
const input = { msgId: state.msgId, userIds } as MsgAddMsgUserListInput
|
||||
await new MsgApi().addMsgUser(input, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
state.sureLoading = false
|
||||
userSelectRef.value.close()
|
||||
onGetMsgUserList()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -1,253 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="830px"
|
||||
>
|
||||
<el-form :model="form" ref="formRef" label-width="auto">
|
||||
<el-row :gutter="35">
|
||||
<!-- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="分类" prop="typeId" :rules="[{ required: true, message: '请选择分类', trigger: ['change'] }]" hidden>
|
||||
<el-tree-select
|
||||
v-model="form.typeId"
|
||||
placeholder="请选择分类"
|
||||
:data="state.msgTypeTreeData"
|
||||
node-key="id"
|
||||
:props="{ label: 'name' }"
|
||||
default-expand-all
|
||||
fit-input-width
|
||||
clearable
|
||||
filterable
|
||||
class="w100"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="标题" prop="title" :rules="[{ required: true, message: '请输入标题', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.title" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item
|
||||
label="内容"
|
||||
prop="content"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入内容', trigger: ['blur', 'change'] },
|
||||
{ validator: testEditorContent, trigger: ['blur', 'change'] },
|
||||
]"
|
||||
>
|
||||
<MyEditor ref="editorRef" v-model:model-value="form.content" @onBlur="onValidateContent" @onChange="onValidateContent"></MyEditor>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="状态" prop="status" :rules="[{ required: true, message: '请选择状态', trigger: ['change'] }]">
|
||||
<el-select v-model="form.status" placeholder="请选择状态" class="w100" @change="onStatusChange">
|
||||
<el-option v-for="item in state.msgStatusList" :key="item.label" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="isScheduledStatus">
|
||||
<el-form-item
|
||||
label="发布时间"
|
||||
prop="publishTime"
|
||||
:rules="[{
|
||||
required: isScheduledStatus,
|
||||
message: '请选择发布时间',
|
||||
trigger: ['change', 'blur']
|
||||
}]"
|
||||
>
|
||||
<el-date-picker
|
||||
v-model="form.publishTime"
|
||||
type="datetime"
|
||||
placeholder="请选择发布时间"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
:disabled-date="disabledDate"
|
||||
class="w100"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/msg/form">
|
||||
import { reactive, toRefs, ref, defineAsyncComponent, getCurrentInstance, computed } from 'vue'
|
||||
import { MsgUpdateInput, MsgTypeGetListOutput } from '/@/api/admin/data-contracts'
|
||||
import { MsgApi } from '/@/api/admin/Msg'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { MsgTypeApi } from '/@/api/admin/MsgType'
|
||||
import { listToTree } from '/@/utils/tree'
|
||||
import { MsgStatusEnum } from '/@/api/admin/enum-contracts'
|
||||
import { toOptionsByValue } from '/@/utils/enum'
|
||||
|
||||
// 扩展 MsgUpdateInput 接口以包含定时发布时间
|
||||
interface ExtendedMsgUpdateInput extends MsgUpdateInput {
|
||||
publishTime?: string
|
||||
}
|
||||
|
||||
const MyEditor = defineAsyncComponent(() => import('/@/components/my-editor/index.vue'))
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const formRef = ref()
|
||||
const editorRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
form: { content: '' } as ExtendedMsgUpdateInput,
|
||||
msgTypeTreeData: [] as MsgTypeGetListOutput[],
|
||||
v: null,
|
||||
msgStatusList: toOptionsByValue(MsgStatusEnum),
|
||||
})
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const { form } = toRefs(state)
|
||||
|
||||
// 判断是否为定时发布状态
|
||||
const isScheduledStatus = computed(() => {
|
||||
return state.form.status === 3 // 3 对应 Scheduled 定时发布状态
|
||||
})
|
||||
|
||||
const testEditorContent = (rule: any, value: any, callback: any) => {
|
||||
if (!value) {
|
||||
callback()
|
||||
}
|
||||
if (editorRef.value.isEmpty()) {
|
||||
callback(new Error('请输入内容'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
const onValidateContent = () => {
|
||||
formRef.value.validateField('content')
|
||||
}
|
||||
|
||||
// 状态变化处理
|
||||
const onStatusChange = (value: number) => {
|
||||
if (value !== 3) { // 3 对应定时发布状态
|
||||
state.form.publishTime = undefined
|
||||
// 清除发布时间的验证错误
|
||||
formRef.value?.clearValidate('publishTime')
|
||||
}
|
||||
}
|
||||
|
||||
// 禁用过去日期
|
||||
const disabledDate = (time: Date) => {
|
||||
return time.getTime() < Date.now() - 86400000 // 不能选择今天之前的日期
|
||||
}
|
||||
|
||||
const getMsgTypes = async () => {
|
||||
const res = await new MsgTypeApi().getList().catch(() => {
|
||||
state.msgTypeTreeData = []
|
||||
})
|
||||
if (res?.success && res.data && res.data.length > 0) {
|
||||
state.msgTypeTreeData = listToTree(res.data)
|
||||
} else {
|
||||
state.msgTypeTreeData = []
|
||||
}
|
||||
}
|
||||
|
||||
// 打开对话框
|
||||
const open = async (row: ExtendedMsgUpdateInput = { id: 0 }) => {
|
||||
proxy.$modal.loading()
|
||||
|
||||
await getMsgTypes()
|
||||
|
||||
let formData = cloneDeep(row) as ExtendedMsgUpdateInput
|
||||
if (row.id > 0) {
|
||||
const res = await new MsgApi().get({ id: row.id }).catch(() => {
|
||||
proxy.$modal.closeLoading()
|
||||
})
|
||||
|
||||
if (res?.success) {
|
||||
formData = res.data as ExtendedMsgUpdateInput
|
||||
formData.typeId = formData.typeId && formData.typeId > 0 ? formData.typeId : undefined
|
||||
}
|
||||
}
|
||||
|
||||
state.form = formData
|
||||
state.form.typeId = 690213836861509
|
||||
|
||||
proxy.$modal.closeLoading()
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
// 定时发布验证
|
||||
if (isScheduledStatus.value) {
|
||||
if (!state.form.publishTime) {
|
||||
proxy.$message.error('选择定时发布时必须选择发布时间')
|
||||
return
|
||||
}
|
||||
|
||||
const publishTime = new Date(state.form.publishTime)
|
||||
const now = new Date()
|
||||
if (publishTime <= now) {
|
||||
proxy.$message.error('发布时间必须晚于当前时间')
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// 如果不是定时发布状态,清除发布时间
|
||||
state.form.publishTime = undefined
|
||||
}
|
||||
|
||||
state.sureLoading = true
|
||||
let res = {} as any
|
||||
if (state.form.id != undefined && state.form.id > 0) {
|
||||
res = await new MsgApi().update(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
} else {
|
||||
res = await new MsgApi().add(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
eventBus.emit('refreshMsg')
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@ -1,319 +0,0 @@
|
||||
<template>
|
||||
<MySplitPanes>
|
||||
<pane size="55" min-size="35" max-size="65">
|
||||
<div class="my-flex-column w100 h100">
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" @submit.stop.prevent>
|
||||
<el-form-item label="标题">
|
||||
<el-input v-model="state.filter.msgName" placeholder="标题" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:msg:add'" type="primary" icon="ele-Plus" @click="onAdd"> 新增 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table
|
||||
ref="msgTableRef"
|
||||
v-loading="state.loading"
|
||||
:data="state.msgData"
|
||||
default-expand-all
|
||||
highlight-current-row
|
||||
style="width: 100%"
|
||||
@current-change="onTableCurrentChange"
|
||||
border
|
||||
>
|
||||
<el-table-column prop="title" label="标题" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="typeName" label="消息分类" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="status" label="状态" min-width="90" show-overflow-tooltip :formatter="formatterMsgStatusEnum" />
|
||||
<el-table-column prop="createdTime" label="创建时间" :formatter="formatterTime" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="100" fixed="right" header-align="center" align="center">
|
||||
<template #default="{ row }">
|
||||
<my-dropdown-more v-auths="['api:admin:msg:update', 'api:admin:msg:delete']" style="margin-left: 0px">
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item v-if="auth('api:admin:msg:update')" @click="onEdit(row)">编辑</el-dropdown-item>
|
||||
<el-dropdown-item v-if="auth('api:admin:msg:delete')" @click="onDelete(row)">删除</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</my-dropdown-more>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="my-flex my-flex-end" style="margin-top: 10px">
|
||||
<el-pagination
|
||||
v-model:currentPage="state.pageInput.currentPage"
|
||||
v-model:page-size="state.pageInput.pageSize"
|
||||
:total="state.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
background
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</pane>
|
||||
<pane>
|
||||
<div class="my-flex-column w100 h100">
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" @submit.stop.prevent>
|
||||
<el-form-item label="姓名">
|
||||
<el-input v-model="state.filter.name" placeholder="姓名" @keyup.enter="onGetMsgUserList" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onGetMsgUserList"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:msg:add-msg-user'" type="primary" icon="ele-Plus" @click="onAddUser"> 添加 </el-button>
|
||||
<el-button v-auth="'api:admin:msg:remove-msg-user'" type="danger" icon="ele-Delete" @click="onRemoveUser"> 移除 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table
|
||||
ref="userTableRef"
|
||||
v-loading="state.userListLoading"
|
||||
:data="state.userListData"
|
||||
row-key="id"
|
||||
style="width: 100%"
|
||||
@row-click="onUserRowClick"
|
||||
border
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="name" label="姓名" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="是否已读" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="success" v-if="row.isRead">已读</el-tag>
|
||||
<el-tag type="info" v-else>未读</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="readTime" label="已读时间" :formatter="formatterTime" min-width="160" show-overflow-tooltip />
|
||||
<!-- <el-table-column prop="mobile" label="手机号" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="email" label="邮箱" min-width="180" show-overflow-tooltip /> -->
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
</pane>
|
||||
|
||||
<msg-form ref="msgFormRef" :title="state.msgFormTitle"></msg-form>
|
||||
<user-select
|
||||
ref="userSelectRef"
|
||||
:title="`添加【${state.msgName}】员工`"
|
||||
multiple
|
||||
:sure-loading="state.sureLoading"
|
||||
@sure="onSureUser"
|
||||
></user-select>
|
||||
</MySplitPanes>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/msg">
|
||||
import { ref, reactive, onMounted, getCurrentInstance, onBeforeMount, defineAsyncComponent } from 'vue'
|
||||
import {
|
||||
PageInputMsgGetPageInput,
|
||||
MsgGetMsgUserListOutput,
|
||||
UserGetPageOutput,
|
||||
MsgAddMsgUserListInput,
|
||||
MsgGetPageOutput,
|
||||
} from '/@/api/admin/data-contracts'
|
||||
import { MsgApi } from '/@/api/admin/Msg'
|
||||
import { ElTable } from 'element-plus'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { auth } from '/@/utils/authFunction'
|
||||
import { Pane } from 'splitpanes'
|
||||
import dayjs from 'dayjs'
|
||||
import { MsgStatusEnum } from '/@/api/admin/enum-contracts'
|
||||
import { getDescByValue } from '/@/utils/enum'
|
||||
|
||||
// 引入组件
|
||||
const MsgForm = defineAsyncComponent(() => import('./components/msg-form.vue'))
|
||||
const UserSelect = defineAsyncComponent(() => import('/@/views/admin/user/components/user-select.vue'))
|
||||
const MySplitPanes = defineAsyncComponent(() => import('/@/components/my-layout/split-panes.vue'))
|
||||
const MyDropdownMore = defineAsyncComponent(() => import('/@/components/my-dropdown-more/index.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const msgTableRef = ref()
|
||||
const msgFormRef = ref()
|
||||
const userTableRef = ref<InstanceType<typeof ElTable>>()
|
||||
const userSelectRef = ref()
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
userListLoading: false,
|
||||
sureLoading: false,
|
||||
msgFormTitle: '',
|
||||
filter: {
|
||||
name: '',
|
||||
msgName: '',
|
||||
},
|
||||
total: 0,
|
||||
pageInput: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
filter: {
|
||||
title: '',
|
||||
msgTypeValue: 690213836861509,
|
||||
},
|
||||
} as PageInputMsgGetPageInput,
|
||||
msgData: [] as any,
|
||||
userListData: [] as MsgGetMsgUserListOutput[],
|
||||
msgId: undefined as number | undefined,
|
||||
msgName: '' as string | null | undefined,
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
onQuery()
|
||||
eventBus.off('refreshMsg')
|
||||
eventBus.on('refreshMsg', () => {
|
||||
onQuery()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshMsg')
|
||||
})
|
||||
|
||||
const formatterMsgStatusEnum = (row: any, column: any, cellValue: any) => {
|
||||
return getDescByValue(MsgStatusEnum, cellValue)
|
||||
}
|
||||
|
||||
const formatterTime = (row: any, column: any, cellValue: any) => {
|
||||
return cellValue ? dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss') : ''
|
||||
}
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
if (state.pageInput.filter) state.pageInput.filter.title = state.filter.msgName
|
||||
const res = await new MsgApi().getPage(state.pageInput).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
|
||||
state.msgData = res?.data?.list ?? []
|
||||
state.total = res?.data?.total ?? 0
|
||||
|
||||
if (state.msgData?.length > 0) {
|
||||
window.setTimeout(() => {
|
||||
msgTableRef.value?.setCurrentRow(state.msgData[0])
|
||||
}, 100)
|
||||
// nextTick(() => {
|
||||
// msgTableRef.value?.setCurrentRow(state.msgData[0])
|
||||
// })
|
||||
}
|
||||
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onSizeChange = (val: number) => {
|
||||
state.pageInput.currentPage = 1
|
||||
state.pageInput.pageSize = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onCurrentChange = (val: number) => {
|
||||
state.pageInput.currentPage = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onAdd = () => {
|
||||
state.msgFormTitle = '新增设备消息'
|
||||
msgFormRef.value.open({ enabled: true })
|
||||
}
|
||||
|
||||
const onEdit = (row: MsgGetPageOutput) => {
|
||||
state.msgFormTitle = '编辑设备消息'
|
||||
msgFormRef.value.open(row)
|
||||
}
|
||||
|
||||
const onDelete = (row: MsgGetPageOutput) => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要删除消息【${row.title}】?`)
|
||||
.then(async () => {
|
||||
await new MsgApi().delete({ id: row.id }, { loading: true, showSuccessMessage: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onGetMsgUserList = async () => {
|
||||
state.userListLoading = true
|
||||
const res = await new MsgApi().getMsgUserList({ MsgId: state.msgId, Name: state.filter.name }).catch(() => {
|
||||
state.userListLoading = false
|
||||
})
|
||||
state.userListLoading = false
|
||||
if (res?.success) {
|
||||
if (res.data && res.data.length > 0) {
|
||||
state.userListData = res.data
|
||||
} else {
|
||||
state.userListData = []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const onTableCurrentChange = (currentRow: MsgGetPageOutput) => {
|
||||
if (!currentRow) {
|
||||
return
|
||||
}
|
||||
|
||||
state.msgId = currentRow.id
|
||||
state.msgName = currentRow.title
|
||||
onGetMsgUserList()
|
||||
}
|
||||
|
||||
const onUserRowClick = (row: MsgGetMsgUserListOutput) => {
|
||||
userTableRef.value!.toggleRowSelection(row, undefined)
|
||||
}
|
||||
|
||||
const onAddUser = () => {
|
||||
if (!((state.msgId as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择消息')
|
||||
return
|
||||
}
|
||||
userSelectRef.value.open({ msgId: state.msgId })
|
||||
}
|
||||
|
||||
const onRemoveUser = () => {
|
||||
if (!((state.msgId as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择消息')
|
||||
return
|
||||
}
|
||||
|
||||
const selectionRows = userTableRef.value!.getSelectionRows() as UserGetPageOutput[]
|
||||
|
||||
if (!((selectionRows.length as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择员工')
|
||||
return
|
||||
}
|
||||
|
||||
proxy.$modal
|
||||
.confirm(`确定要移除吗?`)
|
||||
.then(async () => {
|
||||
const userIds = selectionRows?.map((a) => a.id)
|
||||
const input = { msgId: state.msgId, userIds } as MsgAddMsgUserListInput
|
||||
await new MsgApi().removeMsgUser(input, { loading: true })
|
||||
onGetMsgUserList()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onSureUser = async (users: UserGetPageOutput[]) => {
|
||||
if (!(users?.length > 0)) {
|
||||
userSelectRef.value.close()
|
||||
return
|
||||
}
|
||||
|
||||
state.sureLoading = true
|
||||
const userIds = users?.map((a) => a.id)
|
||||
const input = { msgId: state.msgId, userIds } as MsgAddMsgUserListInput
|
||||
await new MsgApi().addMsgUser(input, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
state.sureLoading = false
|
||||
userSelectRef.value.close()
|
||||
onGetMsgUserList()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -1,253 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="830px"
|
||||
>
|
||||
<el-form :model="form" ref="formRef" label-width="auto">
|
||||
<el-row :gutter="35">
|
||||
<!-- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="分类" prop="typeId" :rules="[{ required: true, message: '请选择分类', trigger: ['change'] }]" hidden>
|
||||
<el-tree-select
|
||||
v-model="form.typeId"
|
||||
placeholder="请选择分类"
|
||||
:data="state.msgTypeTreeData"
|
||||
node-key="id"
|
||||
:props="{ label: 'name' }"
|
||||
default-expand-all
|
||||
fit-input-width
|
||||
clearable
|
||||
filterable
|
||||
class="w100"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="标题" prop="title" :rules="[{ required: true, message: '请输入标题', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.title" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item
|
||||
label="内容"
|
||||
prop="content"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入内容', trigger: ['blur', 'change'] },
|
||||
{ validator: testEditorContent, trigger: ['blur', 'change'] },
|
||||
]"
|
||||
>
|
||||
<MyEditor ref="editorRef" v-model:model-value="form.content" @onBlur="onValidateContent" @onChange="onValidateContent"></MyEditor>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="状态" prop="status" :rules="[{ required: true, message: '请选择状态', trigger: ['change'] }]">
|
||||
<el-select v-model="form.status" placeholder="请选择状态" class="w100" @change="onStatusChange">
|
||||
<el-option v-for="item in state.msgStatusList" :key="item.label" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="isScheduledStatus">
|
||||
<el-form-item
|
||||
label="发布时间"
|
||||
prop="publishTime"
|
||||
:rules="[{
|
||||
required: isScheduledStatus,
|
||||
message: '请选择发布时间',
|
||||
trigger: ['change', 'blur']
|
||||
}]"
|
||||
>
|
||||
<el-date-picker
|
||||
v-model="form.publishTime"
|
||||
type="datetime"
|
||||
placeholder="请选择发布时间"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
:disabled-date="disabledDate"
|
||||
class="w100"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/msg/form">
|
||||
import { reactive, toRefs, ref, defineAsyncComponent, getCurrentInstance, computed } from 'vue'
|
||||
import { MsgUpdateInput, MsgTypeGetListOutput } from '/@/api/admin/data-contracts'
|
||||
|
||||
// 扩展 MsgUpdateInput 接口以包含定时发布时间
|
||||
interface ExtendedMsgUpdateInput extends MsgUpdateInput {
|
||||
publishTime?: string
|
||||
}
|
||||
import { MsgApi } from '/@/api/admin/Msg'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { MsgTypeApi } from '/@/api/admin/MsgType'
|
||||
import { listToTree } from '/@/utils/tree'
|
||||
import { MsgStatusEnum } from '/@/api/admin/enum-contracts'
|
||||
import { toOptionsByValue } from '/@/utils/enum'
|
||||
|
||||
const MyEditor = defineAsyncComponent(() => import('/@/components/my-editor/index.vue'))
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const formRef = ref()
|
||||
const editorRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
form: { content: '' } as ExtendedMsgUpdateInput,
|
||||
msgTypeTreeData: [] as MsgTypeGetListOutput[],
|
||||
v: null,
|
||||
msgStatusList: toOptionsByValue(MsgStatusEnum),
|
||||
})
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const { form } = toRefs(state)
|
||||
|
||||
// 判断是否为定时发布状态
|
||||
const isScheduledStatus = computed(() => {
|
||||
return state.form.status === 3 // 3 对应 Scheduled 定时发布状态
|
||||
})
|
||||
|
||||
const testEditorContent = (rule: any, value: any, callback: any) => {
|
||||
if (!value) {
|
||||
callback()
|
||||
}
|
||||
if (editorRef.value.isEmpty()) {
|
||||
callback(new Error('请输入内容'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
const onValidateContent = () => {
|
||||
formRef.value.validateField('content')
|
||||
}
|
||||
|
||||
// 状态变化处理
|
||||
const onStatusChange = (value: number) => {
|
||||
if (value !== 3) { // 3 对应定时发布状态
|
||||
state.form.publishTime = undefined
|
||||
// 清除发布时间的验证错误
|
||||
formRef.value?.clearValidate('publishTime')
|
||||
}
|
||||
}
|
||||
|
||||
// 禁用过去日期
|
||||
const disabledDate = (time: Date) => {
|
||||
return time.getTime() < Date.now() - 86400000 // 不能选择今天之前的日期
|
||||
}
|
||||
|
||||
const getMsgTypes = async () => {
|
||||
const res = await new MsgTypeApi().getList().catch(() => {
|
||||
state.msgTypeTreeData = []
|
||||
})
|
||||
if (res?.success && res.data && res.data.length > 0) {
|
||||
state.msgTypeTreeData = listToTree(res.data)
|
||||
} else {
|
||||
state.msgTypeTreeData = []
|
||||
}
|
||||
}
|
||||
|
||||
// 打开对话框
|
||||
const open = async (row: ExtendedMsgUpdateInput = { id: 0 }) => {
|
||||
proxy.$modal.loading()
|
||||
|
||||
await getMsgTypes()
|
||||
|
||||
let formData = cloneDeep(row) as ExtendedMsgUpdateInput
|
||||
if (row.id > 0) {
|
||||
const res = await new MsgApi().get({ id: row.id }).catch(() => {
|
||||
proxy.$modal.closeLoading()
|
||||
})
|
||||
|
||||
if (res?.success) {
|
||||
formData = res.data as ExtendedMsgUpdateInput
|
||||
formData.typeId = formData.typeId && formData.typeId > 0 ? formData.typeId : undefined
|
||||
}
|
||||
}
|
||||
|
||||
state.form = formData
|
||||
state.form.typeId = 690213625348165
|
||||
|
||||
proxy.$modal.closeLoading()
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
// 定时发布验证
|
||||
if (isScheduledStatus.value) {
|
||||
if (!state.form.publishTime) {
|
||||
proxy.$message.error('选择定时发布时必须选择发布时间')
|
||||
return
|
||||
}
|
||||
|
||||
const publishTime = new Date(state.form.publishTime)
|
||||
const now = new Date()
|
||||
if (publishTime <= now) {
|
||||
proxy.$message.error('发布时间必须晚于当前时间')
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// 如果不是定时发布状态,清除发布时间
|
||||
state.form.publishTime = undefined
|
||||
}
|
||||
|
||||
state.sureLoading = true
|
||||
let res = {} as any
|
||||
if (state.form.id != undefined && state.form.id > 0) {
|
||||
res = await new MsgApi().update(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
} else {
|
||||
res = await new MsgApi().add(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
eventBus.emit('refreshMsg')
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@ -1,319 +0,0 @@
|
||||
<template>
|
||||
<MySplitPanes>
|
||||
<pane size="55" min-size="35" max-size="65">
|
||||
<div class="my-flex-column w100 h100">
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" @submit.stop.prevent>
|
||||
<el-form-item label="标题">
|
||||
<el-input v-model="state.filter.msgName" placeholder="标题" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:msg:add'" type="primary" icon="ele-Plus" @click="onAdd"> 新增 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table
|
||||
ref="msgTableRef"
|
||||
v-loading="state.loading"
|
||||
:data="state.msgData"
|
||||
default-expand-all
|
||||
highlight-current-row
|
||||
style="width: 100%"
|
||||
@current-change="onTableCurrentChange"
|
||||
border
|
||||
>
|
||||
<el-table-column prop="title" label="标题" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="typeName" label="消息分类" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="status" label="状态" min-width="90" show-overflow-tooltip :formatter="formatterMsgStatusEnum" />
|
||||
<el-table-column prop="createdTime" label="创建时间" :formatter="formatterTime" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="100" fixed="right" header-align="center" align="center">
|
||||
<template #default="{ row }">
|
||||
<my-dropdown-more v-auths="['api:admin:msg:update', 'api:admin:msg:delete']" style="margin-left: 0px">
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item v-if="auth('api:admin:msg:update')" @click="onEdit(row)">编辑</el-dropdown-item>
|
||||
<el-dropdown-item v-if="auth('api:admin:msg:delete')" @click="onDelete(row)">删除</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</my-dropdown-more>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="my-flex my-flex-end" style="margin-top: 10px">
|
||||
<el-pagination
|
||||
v-model:currentPage="state.pageInput.currentPage"
|
||||
v-model:page-size="state.pageInput.pageSize"
|
||||
:total="state.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
background
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</pane>
|
||||
<pane>
|
||||
<div class="my-flex-column w100 h100">
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" @submit.stop.prevent>
|
||||
<el-form-item label="姓名">
|
||||
<el-input v-model="state.filter.name" placeholder="姓名" @keyup.enter="onGetMsgUserList" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onGetMsgUserList"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:msg:add-msg-user'" type="primary" icon="ele-Plus" @click="onAddUser"> 添加 </el-button>
|
||||
<el-button v-auth="'api:admin:msg:remove-msg-user'" type="danger" icon="ele-Delete" @click="onRemoveUser"> 移除 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table
|
||||
ref="userTableRef"
|
||||
v-loading="state.userListLoading"
|
||||
:data="state.userListData"
|
||||
row-key="id"
|
||||
style="width: 100%"
|
||||
@row-click="onUserRowClick"
|
||||
border
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="name" label="姓名" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="是否已读" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="success" v-if="row.isRead">已读</el-tag>
|
||||
<el-tag type="info" v-else>未读</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="readTime" label="已读时间" :formatter="formatterTime" min-width="160" show-overflow-tooltip />
|
||||
<!-- <el-table-column prop="mobile" label="手机号" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="email" label="邮箱" min-width="180" show-overflow-tooltip /> -->
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
</pane>
|
||||
|
||||
<msg-form ref="msgFormRef" :title="state.msgFormTitle"></msg-form>
|
||||
<user-select
|
||||
ref="userSelectRef"
|
||||
:title="`添加【${state.msgName}】员工`"
|
||||
multiple
|
||||
:sure-loading="state.sureLoading"
|
||||
@sure="onSureUser"
|
||||
></user-select>
|
||||
</MySplitPanes>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/msg">
|
||||
import { ref, reactive, onMounted, getCurrentInstance, onBeforeMount, defineAsyncComponent } from 'vue'
|
||||
import {
|
||||
PageInputMsgGetPageInput,
|
||||
MsgGetMsgUserListOutput,
|
||||
UserGetPageOutput,
|
||||
MsgAddMsgUserListInput,
|
||||
MsgGetPageOutput,
|
||||
} from '/@/api/admin/data-contracts'
|
||||
import { MsgApi } from '/@/api/admin/Msg'
|
||||
import { ElTable } from 'element-plus'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { auth } from '/@/utils/authFunction'
|
||||
import { Pane } from 'splitpanes'
|
||||
import dayjs from 'dayjs'
|
||||
import { MsgStatusEnum } from '/@/api/admin/enum-contracts'
|
||||
import { getDescByValue } from '/@/utils/enum'
|
||||
|
||||
// 引入组件
|
||||
const MsgForm = defineAsyncComponent(() => import('./components/msg-form.vue'))
|
||||
const UserSelect = defineAsyncComponent(() => import('/@/views/admin/user/components/user-select.vue'))
|
||||
const MySplitPanes = defineAsyncComponent(() => import('/@/components/my-layout/split-panes.vue'))
|
||||
const MyDropdownMore = defineAsyncComponent(() => import('/@/components/my-dropdown-more/index.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const msgTableRef = ref()
|
||||
const msgFormRef = ref()
|
||||
const userTableRef = ref<InstanceType<typeof ElTable>>()
|
||||
const userSelectRef = ref()
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
userListLoading: false,
|
||||
sureLoading: false,
|
||||
msgFormTitle: '',
|
||||
filter: {
|
||||
name: '',
|
||||
msgName: '',
|
||||
},
|
||||
total: 0,
|
||||
pageInput: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
filter: {
|
||||
title: '',
|
||||
msgTypeValue: 690213625348165,
|
||||
},
|
||||
} as PageInputMsgGetPageInput,
|
||||
msgData: [] as any,
|
||||
userListData: [] as MsgGetMsgUserListOutput[],
|
||||
msgId: undefined as number | undefined,
|
||||
msgName: '' as string | null | undefined,
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
onQuery()
|
||||
eventBus.off('refreshMsg')
|
||||
eventBus.on('refreshMsg', () => {
|
||||
onQuery()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshMsg')
|
||||
})
|
||||
|
||||
const formatterMsgStatusEnum = (row: any, column: any, cellValue: any) => {
|
||||
return getDescByValue(MsgStatusEnum, cellValue)
|
||||
}
|
||||
|
||||
const formatterTime = (row: any, column: any, cellValue: any) => {
|
||||
return cellValue ? dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss') : ''
|
||||
}
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
if (state.pageInput.filter) state.pageInput.filter.title = state.filter.msgName
|
||||
const res = await new MsgApi().getPage(state.pageInput).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
|
||||
state.msgData = res?.data?.list ?? []
|
||||
state.total = res?.data?.total ?? 0
|
||||
|
||||
if (state.msgData?.length > 0) {
|
||||
window.setTimeout(() => {
|
||||
msgTableRef.value?.setCurrentRow(state.msgData[0])
|
||||
}, 100)
|
||||
// nextTick(() => {
|
||||
// msgTableRef.value?.setCurrentRow(state.msgData[0])
|
||||
// })
|
||||
}
|
||||
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onSizeChange = (val: number) => {
|
||||
state.pageInput.currentPage = 1
|
||||
state.pageInput.pageSize = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onCurrentChange = (val: number) => {
|
||||
state.pageInput.currentPage = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onAdd = () => {
|
||||
state.msgFormTitle = '新增配液消息'
|
||||
msgFormRef.value.open({ enabled: true })
|
||||
}
|
||||
|
||||
const onEdit = (row: MsgGetPageOutput) => {
|
||||
state.msgFormTitle = '编辑配液消息'
|
||||
msgFormRef.value.open(row)
|
||||
}
|
||||
|
||||
const onDelete = (row: MsgGetPageOutput) => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要删除消息【${row.title}】?`)
|
||||
.then(async () => {
|
||||
await new MsgApi().delete({ id: row.id }, { loading: true, showSuccessMessage: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onGetMsgUserList = async () => {
|
||||
state.userListLoading = true
|
||||
const res = await new MsgApi().getMsgUserList({ MsgId: state.msgId, Name: state.filter.name }).catch(() => {
|
||||
state.userListLoading = false
|
||||
})
|
||||
state.userListLoading = false
|
||||
if (res?.success) {
|
||||
if (res.data && res.data.length > 0) {
|
||||
state.userListData = res.data
|
||||
} else {
|
||||
state.userListData = []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const onTableCurrentChange = (currentRow: MsgGetPageOutput) => {
|
||||
if (!currentRow) {
|
||||
return
|
||||
}
|
||||
|
||||
state.msgId = currentRow.id
|
||||
state.msgName = currentRow.title
|
||||
onGetMsgUserList()
|
||||
}
|
||||
|
||||
const onUserRowClick = (row: MsgGetMsgUserListOutput) => {
|
||||
userTableRef.value!.toggleRowSelection(row, undefined)
|
||||
}
|
||||
|
||||
const onAddUser = () => {
|
||||
if (!((state.msgId as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择消息')
|
||||
return
|
||||
}
|
||||
userSelectRef.value.open({ msgId: state.msgId })
|
||||
}
|
||||
|
||||
const onRemoveUser = () => {
|
||||
if (!((state.msgId as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择消息')
|
||||
return
|
||||
}
|
||||
|
||||
const selectionRows = userTableRef.value!.getSelectionRows() as UserGetPageOutput[]
|
||||
|
||||
if (!((selectionRows.length as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择员工')
|
||||
return
|
||||
}
|
||||
|
||||
proxy.$modal
|
||||
.confirm(`确定要移除吗?`)
|
||||
.then(async () => {
|
||||
const userIds = selectionRows?.map((a) => a.id)
|
||||
const input = { msgId: state.msgId, userIds } as MsgAddMsgUserListInput
|
||||
await new MsgApi().removeMsgUser(input, { loading: true })
|
||||
onGetMsgUserList()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onSureUser = async (users: UserGetPageOutput[]) => {
|
||||
if (!(users?.length > 0)) {
|
||||
userSelectRef.value.close()
|
||||
return
|
||||
}
|
||||
|
||||
state.sureLoading = true
|
||||
const userIds = users?.map((a) => a.id)
|
||||
const input = { msgId: state.msgId, userIds } as MsgAddMsgUserListInput
|
||||
await new MsgApi().addMsgUser(input, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
state.sureLoading = false
|
||||
userSelectRef.value.close()
|
||||
onGetMsgUserList()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -1,253 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="830px"
|
||||
>
|
||||
<el-form :model="form" ref="formRef" label-width="auto">
|
||||
<el-row :gutter="35">
|
||||
<!-- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="分类" prop="typeId" :rules="[{ required: true, message: '请选择分类', trigger: ['change'] }]" hidden>
|
||||
<el-tree-select
|
||||
v-model="form.typeId"
|
||||
placeholder="请选择分类"
|
||||
:data="state.msgTypeTreeData"
|
||||
node-key="id"
|
||||
:props="{ label: 'name' }"
|
||||
default-expand-all
|
||||
fit-input-width
|
||||
clearable
|
||||
filterable
|
||||
class="w100"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="标题" prop="title" :rules="[{ required: true, message: '请输入标题', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.title" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item
|
||||
label="内容"
|
||||
prop="content"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入内容', trigger: ['blur', 'change'] },
|
||||
{ validator: testEditorContent, trigger: ['blur', 'change'] },
|
||||
]"
|
||||
>
|
||||
<MyEditor ref="editorRef" v-model:model-value="form.content" @onBlur="onValidateContent" @onChange="onValidateContent"></MyEditor>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="状态" prop="status" :rules="[{ required: true, message: '请选择状态', trigger: ['change'] }]">
|
||||
<el-select v-model="form.status" placeholder="请选择状态" class="w100" @change="onStatusChange">
|
||||
<el-option v-for="item in state.msgStatusList" :key="item.label" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="isScheduledStatus">
|
||||
<el-form-item
|
||||
label="发布时间"
|
||||
prop="publishTime"
|
||||
:rules="[{
|
||||
required: isScheduledStatus,
|
||||
message: '请选择发布时间',
|
||||
trigger: ['change', 'blur']
|
||||
}]"
|
||||
>
|
||||
<el-date-picker
|
||||
v-model="form.publishTime"
|
||||
type="datetime"
|
||||
placeholder="请选择发布时间"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
:disabled-date="disabledDate"
|
||||
class="w100"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/msg/form">
|
||||
import { reactive, toRefs, ref, defineAsyncComponent, getCurrentInstance, computed } from 'vue'
|
||||
import { MsgUpdateInput, MsgTypeGetListOutput } from '/@/api/admin/data-contracts'
|
||||
import { MsgApi } from '/@/api/admin/Msg'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { MsgTypeApi } from '/@/api/admin/MsgType'
|
||||
import { listToTree } from '/@/utils/tree'
|
||||
import { MsgStatusEnum } from '/@/api/admin/enum-contracts'
|
||||
import { toOptionsByValue } from '/@/utils/enum'
|
||||
|
||||
const MyEditor = defineAsyncComponent(() => import('/@/components/my-editor/index.vue'))
|
||||
|
||||
// 扩展 MsgUpdateInput 接口以包含定时发布时间
|
||||
interface ExtendedMsgUpdateInput extends MsgUpdateInput {
|
||||
publishTime?: string
|
||||
}
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const formRef = ref()
|
||||
const editorRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
form: { content: '' } as ExtendedMsgUpdateInput,
|
||||
msgTypeTreeData: [] as MsgTypeGetListOutput[],
|
||||
v: null,
|
||||
msgStatusList: toOptionsByValue(MsgStatusEnum),
|
||||
})
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const { form } = toRefs(state)
|
||||
|
||||
// 判断是否为定时发布状态
|
||||
const isScheduledStatus = computed(() => {
|
||||
return state.form.status === 3 // 3 对应 Scheduled 定时发布状态
|
||||
})
|
||||
|
||||
const testEditorContent = (rule: any, value: any, callback: any) => {
|
||||
if (!value) {
|
||||
callback()
|
||||
}
|
||||
if (editorRef.value.isEmpty()) {
|
||||
callback(new Error('请输入内容'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
const onValidateContent = () => {
|
||||
formRef.value.validateField('content')
|
||||
}
|
||||
|
||||
const getMsgTypes = async () => {
|
||||
const res = await new MsgTypeApi().getList().catch(() => {
|
||||
state.msgTypeTreeData = []
|
||||
})
|
||||
if (res?.success && res.data && res.data.length > 0) {
|
||||
state.msgTypeTreeData = listToTree(res.data)
|
||||
} else {
|
||||
state.msgTypeTreeData = []
|
||||
}
|
||||
}
|
||||
|
||||
// 状态变化处理
|
||||
const onStatusChange = (value: number) => {
|
||||
if (value !== 3) { // 3 对应定时发布状态
|
||||
state.form.publishTime = undefined
|
||||
// 清除发布时间的验证错误
|
||||
formRef.value?.clearValidate('publishTime')
|
||||
}
|
||||
}
|
||||
|
||||
// 禁用过去日期
|
||||
const disabledDate = (time: Date) => {
|
||||
return time.getTime() < Date.now() - 86400000 // 不能选择今天之前的日期
|
||||
}
|
||||
|
||||
// 打开对话框
|
||||
const open = async (row: ExtendedMsgUpdateInput = { id: 0 }) => {
|
||||
proxy.$modal.loading()
|
||||
|
||||
await getMsgTypes()
|
||||
|
||||
let formData = cloneDeep(row) as ExtendedMsgUpdateInput
|
||||
if (row.id > 0) {
|
||||
const res = await new MsgApi().get({ id: row.id }).catch(() => {
|
||||
proxy.$modal.closeLoading()
|
||||
})
|
||||
|
||||
if (res?.success) {
|
||||
formData = res.data as ExtendedMsgUpdateInput
|
||||
formData.typeId = formData.typeId && formData.typeId > 0 ? formData.typeId : undefined
|
||||
}
|
||||
}
|
||||
|
||||
state.form = formData
|
||||
state.form.typeId = 690213714493509
|
||||
|
||||
proxy.$modal.closeLoading()
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
// 定时发布验证
|
||||
if (isScheduledStatus.value) {
|
||||
if (!state.form.publishTime) {
|
||||
proxy.$message.error('选择定时发布时必须选择发布时间')
|
||||
return
|
||||
}
|
||||
|
||||
const publishTime = new Date(state.form.publishTime)
|
||||
const now = new Date()
|
||||
if (publishTime <= now) {
|
||||
proxy.$message.error('发布时间必须晚于当前时间')
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// 如果不是定时发布状态,清除发布时间
|
||||
state.form.publishTime = undefined
|
||||
}
|
||||
|
||||
state.sureLoading = true
|
||||
let res = {} as any
|
||||
if (state.form.id != undefined && state.form.id > 0) {
|
||||
res = await new MsgApi().update(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
} else {
|
||||
res = await new MsgApi().add(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
eventBus.emit('refreshMsg')
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@ -1,319 +0,0 @@
|
||||
<template>
|
||||
<MySplitPanes>
|
||||
<pane size="55" min-size="35" max-size="65">
|
||||
<div class="my-flex-column w100 h100">
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" @submit.stop.prevent>
|
||||
<el-form-item label="标题">
|
||||
<el-input v-model="state.filter.msgName" placeholder="标题" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:msg:add'" type="primary" icon="ele-Plus" @click="onAdd"> 新增 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table
|
||||
ref="msgTableRef"
|
||||
v-loading="state.loading"
|
||||
:data="state.msgData"
|
||||
default-expand-all
|
||||
highlight-current-row
|
||||
style="width: 100%"
|
||||
@current-change="onTableCurrentChange"
|
||||
border
|
||||
>
|
||||
<el-table-column prop="title" label="标题" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="typeName" label="消息分类" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="status" label="状态" min-width="90" show-overflow-tooltip :formatter="formatterMsgStatusEnum" />
|
||||
<el-table-column prop="createdTime" label="创建时间" :formatter="formatterTime" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="100" fixed="right" header-align="center" align="center">
|
||||
<template #default="{ row }">
|
||||
<my-dropdown-more v-auths="['api:admin:msg:update', 'api:admin:msg:delete']" style="margin-left: 0px">
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item v-if="auth('api:admin:msg:update')" @click="onEdit(row)">编辑</el-dropdown-item>
|
||||
<el-dropdown-item v-if="auth('api:admin:msg:delete')" @click="onDelete(row)">删除</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</my-dropdown-more>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="my-flex my-flex-end" style="margin-top: 10px">
|
||||
<el-pagination
|
||||
v-model:currentPage="state.pageInput.currentPage"
|
||||
v-model:page-size="state.pageInput.pageSize"
|
||||
:total="state.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
background
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</pane>
|
||||
<pane>
|
||||
<div class="my-flex-column w100 h100">
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" @submit.stop.prevent>
|
||||
<el-form-item label="姓名">
|
||||
<el-input v-model="state.filter.name" placeholder="姓名" @keyup.enter="onGetMsgUserList" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onGetMsgUserList"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:msg:add-msg-user'" type="primary" icon="ele-Plus" @click="onAddUser"> 添加 </el-button>
|
||||
<el-button v-auth="'api:admin:msg:remove-msg-user'" type="danger" icon="ele-Delete" @click="onRemoveUser"> 移除 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table
|
||||
ref="userTableRef"
|
||||
v-loading="state.userListLoading"
|
||||
:data="state.userListData"
|
||||
row-key="id"
|
||||
style="width: 100%"
|
||||
@row-click="onUserRowClick"
|
||||
border
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="name" label="姓名" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="是否已读" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="success" v-if="row.isRead">已读</el-tag>
|
||||
<el-tag type="info" v-else>未读</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="readTime" label="已读时间" :formatter="formatterTime" min-width="160" show-overflow-tooltip />
|
||||
<!-- <el-table-column prop="mobile" label="手机号" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="email" label="邮箱" min-width="180" show-overflow-tooltip /> -->
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
</pane>
|
||||
|
||||
<msg-form ref="msgFormRef" :title="state.msgFormTitle"></msg-form>
|
||||
<user-select
|
||||
ref="userSelectRef"
|
||||
:title="`添加【${state.msgName}】员工`"
|
||||
multiple
|
||||
:sure-loading="state.sureLoading"
|
||||
@sure="onSureUser"
|
||||
></user-select>
|
||||
</MySplitPanes>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/msg">
|
||||
import { ref, reactive, onMounted, getCurrentInstance, onBeforeMount, defineAsyncComponent } from 'vue'
|
||||
import {
|
||||
PageInputMsgGetPageInput,
|
||||
MsgGetMsgUserListOutput,
|
||||
UserGetPageOutput,
|
||||
MsgAddMsgUserListInput,
|
||||
MsgGetPageOutput,
|
||||
} from '/@/api/admin/data-contracts'
|
||||
import { MsgApi } from '/@/api/admin/Msg'
|
||||
import { ElTable } from 'element-plus'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { auth } from '/@/utils/authFunction'
|
||||
import { Pane } from 'splitpanes'
|
||||
import dayjs from 'dayjs'
|
||||
import { MsgStatusEnum } from '/@/api/admin/enum-contracts'
|
||||
import { getDescByValue } from '/@/utils/enum'
|
||||
|
||||
// 引入组件
|
||||
const MsgForm = defineAsyncComponent(() => import('./components/msg-form.vue'))
|
||||
const UserSelect = defineAsyncComponent(() => import('/@/views/admin/user/components/user-select.vue'))
|
||||
const MySplitPanes = defineAsyncComponent(() => import('/@/components/my-layout/split-panes.vue'))
|
||||
const MyDropdownMore = defineAsyncComponent(() => import('/@/components/my-dropdown-more/index.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const msgTableRef = ref()
|
||||
const msgFormRef = ref()
|
||||
const userTableRef = ref<InstanceType<typeof ElTable>>()
|
||||
const userSelectRef = ref()
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
userListLoading: false,
|
||||
sureLoading: false,
|
||||
msgFormTitle: '',
|
||||
filter: {
|
||||
name: '',
|
||||
msgName: '',
|
||||
},
|
||||
total: 0,
|
||||
pageInput: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
filter: {
|
||||
title: '',
|
||||
msgTypeValue: 690213714493509,
|
||||
},
|
||||
} as PageInputMsgGetPageInput,
|
||||
msgData: [] as any,
|
||||
userListData: [] as MsgGetMsgUserListOutput[],
|
||||
msgId: undefined as number | undefined,
|
||||
msgName: '' as string | null | undefined,
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
onQuery()
|
||||
eventBus.off('refreshMsg')
|
||||
eventBus.on('refreshMsg', () => {
|
||||
onQuery()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshMsg')
|
||||
})
|
||||
|
||||
const formatterMsgStatusEnum = (row: any, column: any, cellValue: any) => {
|
||||
return getDescByValue(MsgStatusEnum, cellValue)
|
||||
}
|
||||
|
||||
const formatterTime = (row: any, column: any, cellValue: any) => {
|
||||
return cellValue ? dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss') : ''
|
||||
}
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
if (state.pageInput.filter) state.pageInput.filter.title = state.filter.msgName
|
||||
const res = await new MsgApi().getPage(state.pageInput).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
|
||||
state.msgData = res?.data?.list ?? []
|
||||
state.total = res?.data?.total ?? 0
|
||||
|
||||
if (state.msgData?.length > 0) {
|
||||
window.setTimeout(() => {
|
||||
msgTableRef.value?.setCurrentRow(state.msgData[0])
|
||||
}, 100)
|
||||
// nextTick(() => {
|
||||
// msgTableRef.value?.setCurrentRow(state.msgData[0])
|
||||
// })
|
||||
}
|
||||
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onSizeChange = (val: number) => {
|
||||
state.pageInput.currentPage = 1
|
||||
state.pageInput.pageSize = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onCurrentChange = (val: number) => {
|
||||
state.pageInput.currentPage = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onAdd = () => {
|
||||
state.msgFormTitle = '新增物料消息'
|
||||
msgFormRef.value.open({ enabled: true })
|
||||
}
|
||||
|
||||
const onEdit = (row: MsgGetPageOutput) => {
|
||||
state.msgFormTitle = '编辑物料消息'
|
||||
msgFormRef.value.open(row)
|
||||
}
|
||||
|
||||
const onDelete = (row: MsgGetPageOutput) => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要删除消息【${row.title}】?`)
|
||||
.then(async () => {
|
||||
await new MsgApi().delete({ id: row.id }, { loading: true, showSuccessMessage: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onGetMsgUserList = async () => {
|
||||
state.userListLoading = true
|
||||
const res = await new MsgApi().getMsgUserList({ MsgId: state.msgId, Name: state.filter.name }).catch(() => {
|
||||
state.userListLoading = false
|
||||
})
|
||||
state.userListLoading = false
|
||||
if (res?.success) {
|
||||
if (res.data && res.data.length > 0) {
|
||||
state.userListData = res.data
|
||||
} else {
|
||||
state.userListData = []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const onTableCurrentChange = (currentRow: MsgGetPageOutput) => {
|
||||
if (!currentRow) {
|
||||
return
|
||||
}
|
||||
|
||||
state.msgId = currentRow.id
|
||||
state.msgName = currentRow.title
|
||||
onGetMsgUserList()
|
||||
}
|
||||
|
||||
const onUserRowClick = (row: MsgGetMsgUserListOutput) => {
|
||||
userTableRef.value!.toggleRowSelection(row, undefined)
|
||||
}
|
||||
|
||||
const onAddUser = () => {
|
||||
if (!((state.msgId as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择消息')
|
||||
return
|
||||
}
|
||||
userSelectRef.value.open({ msgId: state.msgId })
|
||||
}
|
||||
|
||||
const onRemoveUser = () => {
|
||||
if (!((state.msgId as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择消息')
|
||||
return
|
||||
}
|
||||
|
||||
const selectionRows = userTableRef.value!.getSelectionRows() as UserGetPageOutput[]
|
||||
|
||||
if (!((selectionRows.length as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择员工')
|
||||
return
|
||||
}
|
||||
|
||||
proxy.$modal
|
||||
.confirm(`确定要移除吗?`)
|
||||
.then(async () => {
|
||||
const userIds = selectionRows?.map((a) => a.id)
|
||||
const input = { msgId: state.msgId, userIds } as MsgAddMsgUserListInput
|
||||
await new MsgApi().removeMsgUser(input, { loading: true })
|
||||
onGetMsgUserList()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onSureUser = async (users: UserGetPageOutput[]) => {
|
||||
if (!(users?.length > 0)) {
|
||||
userSelectRef.value.close()
|
||||
return
|
||||
}
|
||||
|
||||
state.sureLoading = true
|
||||
const userIds = users?.map((a) => a.id)
|
||||
const input = { msgId: state.msgId, userIds } as MsgAddMsgUserListInput
|
||||
await new MsgApi().addMsgUser(input, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
state.sureLoading = false
|
||||
userSelectRef.value.close()
|
||||
onGetMsgUserList()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -1,253 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="830px"
|
||||
>
|
||||
<el-form :model="form" ref="formRef" label-width="auto">
|
||||
<el-row :gutter="35">
|
||||
<!-- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="分类" prop="typeId" :rules="[{ required: true, message: '请选择分类', trigger: ['change'] }]" hidden>
|
||||
<el-tree-select
|
||||
v-model="form.typeId"
|
||||
placeholder="请选择分类"
|
||||
:data="state.msgTypeTreeData"
|
||||
node-key="id"
|
||||
:props="{ label: 'name' }"
|
||||
default-expand-all
|
||||
fit-input-width
|
||||
clearable
|
||||
filterable
|
||||
class="w100"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="标题" prop="title" :rules="[{ required: true, message: '请输入标题', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.title" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item
|
||||
label="内容"
|
||||
prop="content"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入内容', trigger: ['blur', 'change'] },
|
||||
{ validator: testEditorContent, trigger: ['blur', 'change'] },
|
||||
]"
|
||||
>
|
||||
<MyEditor ref="editorRef" v-model:model-value="form.content" @onBlur="onValidateContent" @onChange="onValidateContent"></MyEditor>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="状态" prop="status" :rules="[{ required: true, message: '请选择状态', trigger: ['change'] }]">
|
||||
<el-select v-model="form.status" placeholder="请选择状态" class="w100" @change="onStatusChange">
|
||||
<el-option v-for="item in state.msgStatusList" :key="item.label" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="isScheduledStatus">
|
||||
<el-form-item
|
||||
label="发布时间"
|
||||
prop="publishTime"
|
||||
:rules="[{
|
||||
required: isScheduledStatus,
|
||||
message: '请选择发布时间',
|
||||
trigger: ['change', 'blur']
|
||||
}]"
|
||||
>
|
||||
<el-date-picker
|
||||
v-model="form.publishTime"
|
||||
type="datetime"
|
||||
placeholder="请选择发布时间"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
:disabled-date="disabledDate"
|
||||
class="w100"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/msg/form">
|
||||
import { reactive, toRefs, ref, defineAsyncComponent, getCurrentInstance, computed } from 'vue'
|
||||
import { MsgUpdateInput, MsgTypeGetListOutput } from '/@/api/admin/data-contracts'
|
||||
import { MsgApi } from '/@/api/admin/Msg'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { MsgTypeApi } from '/@/api/admin/MsgType'
|
||||
import { listToTree } from '/@/utils/tree'
|
||||
import { MsgStatusEnum } from '/@/api/admin/enum-contracts'
|
||||
import { toOptionsByValue } from '/@/utils/enum'
|
||||
|
||||
const MyEditor = defineAsyncComponent(() => import('/@/components/my-editor/index.vue'))
|
||||
|
||||
// 扩展 MsgUpdateInput 接口以包含定时发布时间
|
||||
interface ExtendedMsgUpdateInput extends MsgUpdateInput {
|
||||
publishTime?: string
|
||||
}
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const formRef = ref()
|
||||
const editorRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
form: { content: '' } as ExtendedMsgUpdateInput,
|
||||
msgTypeTreeData: [] as MsgTypeGetListOutput[],
|
||||
v: null,
|
||||
msgStatusList: toOptionsByValue(MsgStatusEnum),
|
||||
})
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const { form } = toRefs(state)
|
||||
|
||||
// 判断是否为定时发布状态
|
||||
const isScheduledStatus = computed(() => {
|
||||
return state.form.status === 3 // 3 对应 Scheduled 定时发布状态
|
||||
})
|
||||
|
||||
const testEditorContent = (rule: any, value: any, callback: any) => {
|
||||
if (!value) {
|
||||
callback()
|
||||
}
|
||||
if (editorRef.value.isEmpty()) {
|
||||
callback(new Error('请输入内容'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
const onValidateContent = () => {
|
||||
formRef.value.validateField('content')
|
||||
}
|
||||
|
||||
const getMsgTypes = async () => {
|
||||
const res = await new MsgTypeApi().getList().catch(() => {
|
||||
state.msgTypeTreeData = []
|
||||
})
|
||||
if (res?.success && res.data && res.data.length > 0) {
|
||||
state.msgTypeTreeData = listToTree(res.data)
|
||||
} else {
|
||||
state.msgTypeTreeData = []
|
||||
}
|
||||
}
|
||||
|
||||
// 状态变化处理
|
||||
const onStatusChange = (value: number) => {
|
||||
if (value !== 3) { // 3 对应定时发布状态
|
||||
state.form.publishTime = undefined
|
||||
// 清除发布时间的验证错误
|
||||
formRef.value?.clearValidate('publishTime')
|
||||
}
|
||||
}
|
||||
|
||||
// 禁用过去日期
|
||||
const disabledDate = (time: Date) => {
|
||||
return time.getTime() < Date.now() - 86400000 // 不能选择今天之前的日期
|
||||
}
|
||||
|
||||
// 打开对话框
|
||||
const open = async (row: ExtendedMsgUpdateInput = { id: 0 }) => {
|
||||
proxy.$modal.loading()
|
||||
|
||||
await getMsgTypes()
|
||||
|
||||
let formData = cloneDeep(row) as ExtendedMsgUpdateInput
|
||||
if (row.id > 0) {
|
||||
const res = await new MsgApi().get({ id: row.id }).catch(() => {
|
||||
proxy.$modal.closeLoading()
|
||||
})
|
||||
|
||||
if (res?.success) {
|
||||
formData = res.data as ExtendedMsgUpdateInput
|
||||
formData.typeId = formData.typeId && formData.typeId > 0 ? formData.typeId : undefined
|
||||
}
|
||||
}
|
||||
|
||||
state.form = formData
|
||||
state.form.typeId = 690214203293765
|
||||
|
||||
proxy.$modal.closeLoading()
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
// 定时发布验证
|
||||
if (isScheduledStatus.value) {
|
||||
if (!state.form.publishTime) {
|
||||
proxy.$message.error('选择定时发布时必须选择发布时间')
|
||||
return
|
||||
}
|
||||
|
||||
const publishTime = new Date(state.form.publishTime)
|
||||
const now = new Date()
|
||||
if (publishTime <= now) {
|
||||
proxy.$message.error('发布时间必须晚于当前时间')
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// 如果不是定时发布状态,清除发布时间
|
||||
state.form.publishTime = undefined
|
||||
}
|
||||
|
||||
state.sureLoading = true
|
||||
let res = {} as any
|
||||
if (state.form.id != undefined && state.form.id > 0) {
|
||||
res = await new MsgApi().update(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
} else {
|
||||
res = await new MsgApi().add(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
eventBus.emit('refreshMsg')
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@ -1,319 +0,0 @@
|
||||
<template>
|
||||
<MySplitPanes>
|
||||
<pane size="55" min-size="35" max-size="65">
|
||||
<div class="my-flex-column w100 h100">
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" @submit.stop.prevent>
|
||||
<el-form-item label="标题">
|
||||
<el-input v-model="state.filter.msgName" placeholder="标题" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:msg:add'" type="primary" icon="ele-Plus" @click="onAdd"> 新增 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table
|
||||
ref="msgTableRef"
|
||||
v-loading="state.loading"
|
||||
:data="state.msgData"
|
||||
default-expand-all
|
||||
highlight-current-row
|
||||
style="width: 100%"
|
||||
@current-change="onTableCurrentChange"
|
||||
border
|
||||
>
|
||||
<el-table-column prop="title" label="标题" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="typeName" label="消息分类" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="status" label="状态" min-width="90" show-overflow-tooltip :formatter="formatterMsgStatusEnum" />
|
||||
<el-table-column prop="createdTime" label="创建时间" :formatter="formatterTime" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="100" fixed="right" header-align="center" align="center">
|
||||
<template #default="{ row }">
|
||||
<my-dropdown-more v-auths="['api:admin:msg:update', 'api:admin:msg:delete']" style="margin-left: 0px">
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item v-if="auth('api:admin:msg:update')" @click="onEdit(row)">编辑</el-dropdown-item>
|
||||
<el-dropdown-item v-if="auth('api:admin:msg:delete')" @click="onDelete(row)">删除</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</my-dropdown-more>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="my-flex my-flex-end" style="margin-top: 10px">
|
||||
<el-pagination
|
||||
v-model:currentPage="state.pageInput.currentPage"
|
||||
v-model:page-size="state.pageInput.pageSize"
|
||||
:total="state.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
background
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</pane>
|
||||
<pane>
|
||||
<div class="my-flex-column w100 h100">
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" @submit.stop.prevent>
|
||||
<el-form-item label="姓名">
|
||||
<el-input v-model="state.filter.name" placeholder="姓名" @keyup.enter="onGetMsgUserList" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onGetMsgUserList"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:msg:add-msg-user'" type="primary" icon="ele-Plus" @click="onAddUser"> 添加 </el-button>
|
||||
<el-button v-auth="'api:admin:msg:remove-msg-user'" type="danger" icon="ele-Delete" @click="onRemoveUser"> 移除 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table
|
||||
ref="userTableRef"
|
||||
v-loading="state.userListLoading"
|
||||
:data="state.userListData"
|
||||
row-key="id"
|
||||
style="width: 100%"
|
||||
@row-click="onUserRowClick"
|
||||
border
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="name" label="姓名" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="是否已读" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="success" v-if="row.isRead">已读</el-tag>
|
||||
<el-tag type="info" v-else>未读</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="readTime" label="已读时间" :formatter="formatterTime" min-width="160" show-overflow-tooltip />
|
||||
<!-- <el-table-column prop="mobile" label="手机号" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="email" label="邮箱" min-width="180" show-overflow-tooltip /> -->
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
</pane>
|
||||
|
||||
<msg-form ref="msgFormRef" :title="state.msgFormTitle"></msg-form>
|
||||
<user-select
|
||||
ref="userSelectRef"
|
||||
:title="`添加【${state.msgName}】员工`"
|
||||
multiple
|
||||
:sure-loading="state.sureLoading"
|
||||
@sure="onSureUser"
|
||||
></user-select>
|
||||
</MySplitPanes>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/msg">
|
||||
import { ref, reactive, onMounted, getCurrentInstance, onBeforeMount, defineAsyncComponent } from 'vue'
|
||||
import {
|
||||
PageInputMsgGetPageInput,
|
||||
MsgGetMsgUserListOutput,
|
||||
UserGetPageOutput,
|
||||
MsgAddMsgUserListInput,
|
||||
MsgGetPageOutput,
|
||||
} from '/@/api/admin/data-contracts'
|
||||
import { MsgApi } from '/@/api/admin/Msg'
|
||||
import { ElTable } from 'element-plus'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { auth } from '/@/utils/authFunction'
|
||||
import { Pane } from 'splitpanes'
|
||||
import dayjs from 'dayjs'
|
||||
import { MsgStatusEnum } from '/@/api/admin/enum-contracts'
|
||||
import { getDescByValue } from '/@/utils/enum'
|
||||
|
||||
// 引入组件
|
||||
const MsgForm = defineAsyncComponent(() => import('./components/msg-form.vue'))
|
||||
const UserSelect = defineAsyncComponent(() => import('/@/views/admin/user/components/user-select.vue'))
|
||||
const MySplitPanes = defineAsyncComponent(() => import('/@/components/my-layout/split-panes.vue'))
|
||||
const MyDropdownMore = defineAsyncComponent(() => import('/@/components/my-dropdown-more/index.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const msgTableRef = ref()
|
||||
const msgFormRef = ref()
|
||||
const userTableRef = ref<InstanceType<typeof ElTable>>()
|
||||
const userSelectRef = ref()
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
userListLoading: false,
|
||||
sureLoading: false,
|
||||
msgFormTitle: '',
|
||||
filter: {
|
||||
name: '',
|
||||
msgName: '',
|
||||
},
|
||||
total: 0,
|
||||
pageInput: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
filter: {
|
||||
title: '',
|
||||
msgTypeValue: 690214203293765,
|
||||
},
|
||||
} as PageInputMsgGetPageInput,
|
||||
msgData: [] as any,
|
||||
userListData: [] as MsgGetMsgUserListOutput[],
|
||||
msgId: undefined as number | undefined,
|
||||
msgName: '' as string | null | undefined,
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
onQuery()
|
||||
eventBus.off('refreshMsg')
|
||||
eventBus.on('refreshMsg', () => {
|
||||
onQuery()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshMsg')
|
||||
})
|
||||
|
||||
const formatterMsgStatusEnum = (row: any, column: any, cellValue: any) => {
|
||||
return getDescByValue(MsgStatusEnum, cellValue)
|
||||
}
|
||||
|
||||
const formatterTime = (row: any, column: any, cellValue: any) => {
|
||||
return cellValue ? dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss') : ''
|
||||
}
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
if (state.pageInput.filter) state.pageInput.filter.title = state.filter.msgName
|
||||
const res = await new MsgApi().getPage(state.pageInput).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
|
||||
state.msgData = res?.data?.list ?? []
|
||||
state.total = res?.data?.total ?? 0
|
||||
|
||||
if (state.msgData?.length > 0) {
|
||||
window.setTimeout(() => {
|
||||
msgTableRef.value?.setCurrentRow(state.msgData[0])
|
||||
}, 100)
|
||||
// nextTick(() => {
|
||||
// msgTableRef.value?.setCurrentRow(state.msgData[0])
|
||||
// })
|
||||
}
|
||||
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onSizeChange = (val: number) => {
|
||||
state.pageInput.currentPage = 1
|
||||
state.pageInput.pageSize = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onCurrentChange = (val: number) => {
|
||||
state.pageInput.currentPage = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onAdd = () => {
|
||||
state.msgFormTitle = '新增工艺消息'
|
||||
msgFormRef.value.open({ enabled: true })
|
||||
}
|
||||
|
||||
const onEdit = (row: MsgGetPageOutput) => {
|
||||
state.msgFormTitle = '编辑工艺消息'
|
||||
msgFormRef.value.open(row)
|
||||
}
|
||||
|
||||
const onDelete = (row: MsgGetPageOutput) => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要删除消息【${row.title}】?`)
|
||||
.then(async () => {
|
||||
await new MsgApi().delete({ id: row.id }, { loading: true, showSuccessMessage: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onGetMsgUserList = async () => {
|
||||
state.userListLoading = true
|
||||
const res = await new MsgApi().getMsgUserList({ MsgId: state.msgId, Name: state.filter.name }).catch(() => {
|
||||
state.userListLoading = false
|
||||
})
|
||||
state.userListLoading = false
|
||||
if (res?.success) {
|
||||
if (res.data && res.data.length > 0) {
|
||||
state.userListData = res.data
|
||||
} else {
|
||||
state.userListData = []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const onTableCurrentChange = (currentRow: MsgGetPageOutput) => {
|
||||
if (!currentRow) {
|
||||
return
|
||||
}
|
||||
|
||||
state.msgId = currentRow.id
|
||||
state.msgName = currentRow.title
|
||||
onGetMsgUserList()
|
||||
}
|
||||
|
||||
const onUserRowClick = (row: MsgGetMsgUserListOutput) => {
|
||||
userTableRef.value!.toggleRowSelection(row, undefined)
|
||||
}
|
||||
|
||||
const onAddUser = () => {
|
||||
if (!((state.msgId as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择消息')
|
||||
return
|
||||
}
|
||||
userSelectRef.value.open({ msgId: state.msgId })
|
||||
}
|
||||
|
||||
const onRemoveUser = () => {
|
||||
if (!((state.msgId as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择消息')
|
||||
return
|
||||
}
|
||||
|
||||
const selectionRows = userTableRef.value!.getSelectionRows() as UserGetPageOutput[]
|
||||
|
||||
if (!((selectionRows.length as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择员工')
|
||||
return
|
||||
}
|
||||
|
||||
proxy.$modal
|
||||
.confirm(`确定要移除吗?`)
|
||||
.then(async () => {
|
||||
const userIds = selectionRows?.map((a) => a.id)
|
||||
const input = { msgId: state.msgId, userIds } as MsgAddMsgUserListInput
|
||||
await new MsgApi().removeMsgUser(input, { loading: true })
|
||||
onGetMsgUserList()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onSureUser = async (users: UserGetPageOutput[]) => {
|
||||
if (!(users?.length > 0)) {
|
||||
userSelectRef.value.close()
|
||||
return
|
||||
}
|
||||
|
||||
state.sureLoading = true
|
||||
const userIds = users?.map((a) => a.id)
|
||||
const input = { msgId: state.msgId, userIds } as MsgAddMsgUserListInput
|
||||
await new MsgApi().addMsgUser(input, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
state.sureLoading = false
|
||||
userSelectRef.value.close()
|
||||
onGetMsgUserList()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -1,253 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="830px"
|
||||
>
|
||||
<el-form :model="form" ref="formRef" label-width="auto">
|
||||
<el-row :gutter="35">
|
||||
<!-- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="分类" prop="typeId" :rules="[{ required: true, message: '请选择分类', trigger: ['change'] }]" hidden>
|
||||
<el-tree-select
|
||||
v-model="form.typeId"
|
||||
placeholder="请选择分类"
|
||||
:data="state.msgTypeTreeData"
|
||||
node-key="id"
|
||||
:props="{ label: 'name' }"
|
||||
default-expand-all
|
||||
fit-input-width
|
||||
clearable
|
||||
filterable
|
||||
class="w100"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="标题" prop="title" :rules="[{ required: true, message: '请输入标题', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.title" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item
|
||||
label="内容"
|
||||
prop="content"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入内容', trigger: ['blur', 'change'] },
|
||||
{ validator: testEditorContent, trigger: ['blur', 'change'] },
|
||||
]"
|
||||
>
|
||||
<MyEditor ref="editorRef" v-model:model-value="form.content" @onBlur="onValidateContent" @onChange="onValidateContent"></MyEditor>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="状态" prop="status" :rules="[{ required: true, message: '请选择状态', trigger: ['change'] }]">
|
||||
<el-select v-model="form.status" placeholder="请选择状态" class="w100" @change="onStatusChange">
|
||||
<el-option v-for="item in state.msgStatusList" :key="item.label" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="isScheduledStatus">
|
||||
<el-form-item
|
||||
label="发布时间"
|
||||
prop="publishTime"
|
||||
:rules="[{
|
||||
required: isScheduledStatus,
|
||||
message: '请选择发布时间',
|
||||
trigger: ['change', 'blur']
|
||||
}]"
|
||||
>
|
||||
<el-date-picker
|
||||
v-model="form.publishTime"
|
||||
type="datetime"
|
||||
placeholder="请选择发布时间"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
:disabled-date="disabledDate"
|
||||
class="w100"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/msg/form">
|
||||
import { reactive, toRefs, ref, defineAsyncComponent, getCurrentInstance, computed } from 'vue'
|
||||
import { MsgUpdateInput, MsgTypeGetListOutput } from '/@/api/admin/data-contracts'
|
||||
import { MsgApi } from '/@/api/admin/Msg'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { MsgTypeApi } from '/@/api/admin/MsgType'
|
||||
import { listToTree } from '/@/utils/tree'
|
||||
import { MsgStatusEnum } from '/@/api/admin/enum-contracts'
|
||||
import { toOptionsByValue } from '/@/utils/enum'
|
||||
|
||||
const MyEditor = defineAsyncComponent(() => import('/@/components/my-editor/index.vue'))
|
||||
|
||||
// 扩展 MsgUpdateInput 接口以包含定时发布时间
|
||||
interface ExtendedMsgUpdateInput extends MsgUpdateInput {
|
||||
publishTime?: string
|
||||
}
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const formRef = ref()
|
||||
const editorRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
form: { content: '' } as ExtendedMsgUpdateInput,
|
||||
msgTypeTreeData: [] as MsgTypeGetListOutput[],
|
||||
v: null,
|
||||
msgStatusList: toOptionsByValue(MsgStatusEnum),
|
||||
})
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const { form } = toRefs(state)
|
||||
|
||||
// 判断是否为定时发布状态
|
||||
const isScheduledStatus = computed(() => {
|
||||
return state.form.status === 3 // 3 对应 Scheduled 定时发布状态
|
||||
})
|
||||
|
||||
const testEditorContent = (rule: any, value: any, callback: any) => {
|
||||
if (!value) {
|
||||
callback()
|
||||
}
|
||||
if (editorRef.value.isEmpty()) {
|
||||
callback(new Error('请输入内容'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
const onValidateContent = () => {
|
||||
formRef.value.validateField('content')
|
||||
}
|
||||
|
||||
const getMsgTypes = async () => {
|
||||
const res = await new MsgTypeApi().getList().catch(() => {
|
||||
state.msgTypeTreeData = []
|
||||
})
|
||||
if (res?.success && res.data && res.data.length > 0) {
|
||||
state.msgTypeTreeData = listToTree(res.data)
|
||||
} else {
|
||||
state.msgTypeTreeData = []
|
||||
}
|
||||
}
|
||||
|
||||
// 状态变化处理
|
||||
const onStatusChange = (value: number) => {
|
||||
if (value !== 3) { // 3 对应定时发布状态
|
||||
state.form.publishTime = undefined
|
||||
// 清除发布时间的验证错误
|
||||
formRef.value?.clearValidate('publishTime')
|
||||
}
|
||||
}
|
||||
|
||||
// 禁用过去日期
|
||||
const disabledDate = (time: Date) => {
|
||||
return time.getTime() < Date.now() - 86400000 // 不能选择今天之前的日期
|
||||
}
|
||||
|
||||
// 打开对话框
|
||||
const open = async (row: ExtendedMsgUpdateInput = { id: 0 }) => {
|
||||
proxy.$modal.loading()
|
||||
|
||||
await getMsgTypes()
|
||||
|
||||
let formData = cloneDeep(row) as ExtendedMsgUpdateInput
|
||||
if (row.id > 0) {
|
||||
const res = await new MsgApi().get({ id: row.id }).catch(() => {
|
||||
proxy.$modal.closeLoading()
|
||||
})
|
||||
|
||||
if (res?.success) {
|
||||
formData = res.data as ExtendedMsgUpdateInput
|
||||
formData.typeId = formData.typeId && formData.typeId > 0 ? formData.typeId : undefined
|
||||
}
|
||||
}
|
||||
|
||||
state.form = formData
|
||||
state.form.typeId = 690214370156613
|
||||
|
||||
proxy.$modal.closeLoading()
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
// 定时发布验证
|
||||
if (isScheduledStatus.value) {
|
||||
if (!state.form.publishTime) {
|
||||
proxy.$message.error('选择定时发布时必须选择发布时间')
|
||||
return
|
||||
}
|
||||
|
||||
const publishTime = new Date(state.form.publishTime)
|
||||
const now = new Date()
|
||||
if (publishTime <= now) {
|
||||
proxy.$message.error('发布时间必须晚于当前时间')
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// 如果不是定时发布状态,清除发布时间
|
||||
state.form.publishTime = undefined
|
||||
}
|
||||
|
||||
state.sureLoading = true
|
||||
let res = {} as any
|
||||
if (state.form.id != undefined && state.form.id > 0) {
|
||||
res = await new MsgApi().update(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
} else {
|
||||
res = await new MsgApi().add(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
eventBus.emit('refreshMsg')
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@ -1,319 +0,0 @@
|
||||
<template>
|
||||
<MySplitPanes>
|
||||
<pane size="55" min-size="35" max-size="65">
|
||||
<div class="my-flex-column w100 h100">
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" @submit.stop.prevent>
|
||||
<el-form-item label="标题">
|
||||
<el-input v-model="state.filter.msgName" placeholder="标题" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:msg:add'" type="primary" icon="ele-Plus" @click="onAdd"> 新增 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table
|
||||
ref="msgTableRef"
|
||||
v-loading="state.loading"
|
||||
:data="state.msgData"
|
||||
default-expand-all
|
||||
highlight-current-row
|
||||
style="width: 100%"
|
||||
@current-change="onTableCurrentChange"
|
||||
border
|
||||
>
|
||||
<el-table-column prop="title" label="标题" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="typeName" label="消息分类" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="status" label="状态" min-width="90" show-overflow-tooltip :formatter="formatterMsgStatusEnum" />
|
||||
<el-table-column prop="createdTime" label="创建时间" :formatter="formatterTime" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="100" fixed="right" header-align="center" align="center">
|
||||
<template #default="{ row }">
|
||||
<my-dropdown-more v-auths="['api:admin:msg:update', 'api:admin:msg:delete']" style="margin-left: 0px">
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item v-if="auth('api:admin:msg:update')" @click="onEdit(row)">编辑</el-dropdown-item>
|
||||
<el-dropdown-item v-if="auth('api:admin:msg:delete')" @click="onDelete(row)">删除</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</my-dropdown-more>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="my-flex my-flex-end" style="margin-top: 10px">
|
||||
<el-pagination
|
||||
v-model:currentPage="state.pageInput.currentPage"
|
||||
v-model:page-size="state.pageInput.pageSize"
|
||||
:total="state.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
background
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</pane>
|
||||
<pane>
|
||||
<div class="my-flex-column w100 h100">
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" @submit.stop.prevent>
|
||||
<el-form-item label="姓名">
|
||||
<el-input v-model="state.filter.name" placeholder="姓名" @keyup.enter="onGetMsgUserList" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onGetMsgUserList"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:msg:add-msg-user'" type="primary" icon="ele-Plus" @click="onAddUser"> 添加 </el-button>
|
||||
<el-button v-auth="'api:admin:msg:remove-msg-user'" type="danger" icon="ele-Delete" @click="onRemoveUser"> 移除 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table
|
||||
ref="userTableRef"
|
||||
v-loading="state.userListLoading"
|
||||
:data="state.userListData"
|
||||
row-key="id"
|
||||
style="width: 100%"
|
||||
@row-click="onUserRowClick"
|
||||
border
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="name" label="姓名" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="是否已读" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="success" v-if="row.isRead">已读</el-tag>
|
||||
<el-tag type="info" v-else>未读</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="readTime" label="已读时间" :formatter="formatterTime" min-width="160" show-overflow-tooltip />
|
||||
<!-- <el-table-column prop="mobile" label="手机号" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="email" label="邮箱" min-width="180" show-overflow-tooltip /> -->
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
</pane>
|
||||
|
||||
<msg-form ref="msgFormRef" :title="state.msgFormTitle"></msg-form>
|
||||
<user-select
|
||||
ref="userSelectRef"
|
||||
:title="`添加【${state.msgName}】员工`"
|
||||
multiple
|
||||
:sure-loading="state.sureLoading"
|
||||
@sure="onSureUser"
|
||||
></user-select>
|
||||
</MySplitPanes>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/msg">
|
||||
import { ref, reactive, onMounted, getCurrentInstance, onBeforeMount, defineAsyncComponent } from 'vue'
|
||||
import {
|
||||
PageInputMsgGetPageInput,
|
||||
MsgGetMsgUserListOutput,
|
||||
UserGetPageOutput,
|
||||
MsgAddMsgUserListInput,
|
||||
MsgGetPageOutput,
|
||||
} from '/@/api/admin/data-contracts'
|
||||
import { MsgApi } from '/@/api/admin/Msg'
|
||||
import { ElTable } from 'element-plus'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { auth } from '/@/utils/authFunction'
|
||||
import { Pane } from 'splitpanes'
|
||||
import dayjs from 'dayjs'
|
||||
import { MsgStatusEnum } from '/@/api/admin/enum-contracts'
|
||||
import { getDescByValue } from '/@/utils/enum'
|
||||
|
||||
// 引入组件
|
||||
const MsgForm = defineAsyncComponent(() => import('./components/msg-form.vue'))
|
||||
const UserSelect = defineAsyncComponent(() => import('/@/views/admin/user/components/user-select.vue'))
|
||||
const MySplitPanes = defineAsyncComponent(() => import('/@/components/my-layout/split-panes.vue'))
|
||||
const MyDropdownMore = defineAsyncComponent(() => import('/@/components/my-dropdown-more/index.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const msgTableRef = ref()
|
||||
const msgFormRef = ref()
|
||||
const userTableRef = ref<InstanceType<typeof ElTable>>()
|
||||
const userSelectRef = ref()
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
userListLoading: false,
|
||||
sureLoading: false,
|
||||
msgFormTitle: '',
|
||||
filter: {
|
||||
name: '',
|
||||
msgName: '',
|
||||
},
|
||||
total: 0,
|
||||
pageInput: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
filter: {
|
||||
title: '',
|
||||
msgTypeValue: 690214305554501,
|
||||
},
|
||||
} as PageInputMsgGetPageInput,
|
||||
msgData: [] as any,
|
||||
userListData: [] as MsgGetMsgUserListOutput[],
|
||||
msgId: undefined as number | undefined,
|
||||
msgName: '' as string | null | undefined,
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
onQuery()
|
||||
eventBus.off('refreshMsg')
|
||||
eventBus.on('refreshMsg', () => {
|
||||
onQuery()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshMsg')
|
||||
})
|
||||
|
||||
const formatterMsgStatusEnum = (row: any, column: any, cellValue: any) => {
|
||||
return getDescByValue(MsgStatusEnum, cellValue)
|
||||
}
|
||||
|
||||
const formatterTime = (row: any, column: any, cellValue: any) => {
|
||||
return cellValue ? dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss') : ''
|
||||
}
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
if (state.pageInput.filter) state.pageInput.filter.title = state.filter.msgName
|
||||
const res = await new MsgApi().getPage(state.pageInput).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
|
||||
state.msgData = res?.data?.list ?? []
|
||||
state.total = res?.data?.total ?? 0
|
||||
|
||||
if (state.msgData?.length > 0) {
|
||||
window.setTimeout(() => {
|
||||
msgTableRef.value?.setCurrentRow(state.msgData[0])
|
||||
}, 100)
|
||||
// nextTick(() => {
|
||||
// msgTableRef.value?.setCurrentRow(state.msgData[0])
|
||||
// })
|
||||
}
|
||||
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onSizeChange = (val: number) => {
|
||||
state.pageInput.currentPage = 1
|
||||
state.pageInput.pageSize = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onCurrentChange = (val: number) => {
|
||||
state.pageInput.currentPage = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onAdd = () => {
|
||||
state.msgFormTitle = '新增制度消息'
|
||||
msgFormRef.value.open({ enabled: true })
|
||||
}
|
||||
|
||||
const onEdit = (row: MsgGetPageOutput) => {
|
||||
state.msgFormTitle = '编辑制度消息'
|
||||
msgFormRef.value.open(row)
|
||||
}
|
||||
|
||||
const onDelete = (row: MsgGetPageOutput) => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要删除消息【${row.title}】?`)
|
||||
.then(async () => {
|
||||
await new MsgApi().delete({ id: row.id }, { loading: true, showSuccessMessage: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onGetMsgUserList = async () => {
|
||||
state.userListLoading = true
|
||||
const res = await new MsgApi().getMsgUserList({ MsgId: state.msgId, Name: state.filter.name }).catch(() => {
|
||||
state.userListLoading = false
|
||||
})
|
||||
state.userListLoading = false
|
||||
if (res?.success) {
|
||||
if (res.data && res.data.length > 0) {
|
||||
state.userListData = res.data
|
||||
} else {
|
||||
state.userListData = []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const onTableCurrentChange = (currentRow: MsgGetPageOutput) => {
|
||||
if (!currentRow) {
|
||||
return
|
||||
}
|
||||
|
||||
state.msgId = currentRow.id
|
||||
state.msgName = currentRow.title
|
||||
onGetMsgUserList()
|
||||
}
|
||||
|
||||
const onUserRowClick = (row: MsgGetMsgUserListOutput) => {
|
||||
userTableRef.value!.toggleRowSelection(row, undefined)
|
||||
}
|
||||
|
||||
const onAddUser = () => {
|
||||
if (!((state.msgId as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择消息')
|
||||
return
|
||||
}
|
||||
userSelectRef.value.open({ msgId: state.msgId })
|
||||
}
|
||||
|
||||
const onRemoveUser = () => {
|
||||
if (!((state.msgId as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择消息')
|
||||
return
|
||||
}
|
||||
|
||||
const selectionRows = userTableRef.value!.getSelectionRows() as UserGetPageOutput[]
|
||||
|
||||
if (!((selectionRows.length as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择员工')
|
||||
return
|
||||
}
|
||||
|
||||
proxy.$modal
|
||||
.confirm(`确定要移除吗?`)
|
||||
.then(async () => {
|
||||
const userIds = selectionRows?.map((a) => a.id)
|
||||
const input = { msgId: state.msgId, userIds } as MsgAddMsgUserListInput
|
||||
await new MsgApi().removeMsgUser(input, { loading: true })
|
||||
onGetMsgUserList()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onSureUser = async (users: UserGetPageOutput[]) => {
|
||||
if (!(users?.length > 0)) {
|
||||
userSelectRef.value.close()
|
||||
return
|
||||
}
|
||||
|
||||
state.sureLoading = true
|
||||
const userIds = users?.map((a) => a.id)
|
||||
const input = { msgId: state.msgId, userIds } as MsgAddMsgUserListInput
|
||||
await new MsgApi().addMsgUser(input, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
state.sureLoading = false
|
||||
userSelectRef.value.close()
|
||||
onGetMsgUserList()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -1,188 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="600px"
|
||||
>
|
||||
<el-form :model="form" ref="formRef" label-width="110px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="网站名称" prop="websiteName" :rules="[{ required: true, message: '请输入网站名称', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.websiteName" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="网站地址" prop="websiteUrl" :rules="[{ required: true, message: '请输入网站地址', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.websiteUrl" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="适用Site" prop="applicableSite" :rules="[{ required: true, message: '请选择适用Site', trigger: ['blur', 'change'] }]">
|
||||
<el-select v-model="form.applicableSite" placeholder="请选择适用Site" clearable class="w100">
|
||||
<el-option v-for="item in state.Site" :key="item.code" :label="item.name" :value="item.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="一级标题" prop="primaryTitle" :rules="[{ required: true, message: '请选择一级标题', trigger: ['blur', 'change'] }]">
|
||||
<el-select v-model="form.primaryTitle" placeholder="请选择一级标题" clearable class="w100">
|
||||
<el-option v-for="item in state.OnlineWebOne" :key="item.code" :label="item.name" :value="item.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="二级标题" prop="secondaryTitle" :rules="[{ required: true, message: '请选择二级标题', trigger: ['blur', 'change'] }]">
|
||||
<el-select v-model="form.secondaryTitle" placeholder="请选择二级标题" clearable class="w100">
|
||||
<el-option v-for="item in state.OnlineWebTwo" :key="item.code" :label="item.name" :value="item.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="联系人" prop="contactPerson">
|
||||
<el-input v-model="form.contactPerson" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="教程地址" prop="tutorialUrl">
|
||||
<el-input v-model="form.tutorialUrl" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="功能介绍" prop="functionIntro" :rules="[{ required: true, message: '请输入功能介绍', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.functionIntro" type="textarea" rows="3" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="关键词" prop="keywords" :rules="[{ required: true, message: '请输入关键词', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.keywords" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/online/form">
|
||||
import { reactive, toRefs, ref } from 'vue'
|
||||
import { OnlineUpdateInput, DictGetListOutput } from '/@/api/admin/data-contracts'
|
||||
import { OnlineApi } from '/@/api/admin/Online'
|
||||
import { DictApi } from '/@/api/admin/Dict'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
|
||||
/** 字典分类 */
|
||||
/** 字典分类 */
|
||||
const DictType = {
|
||||
OnlineWebOne: { dictTypeCode: 'OnlineWebOne', desc: '一级标题' },
|
||||
OnlineWebTwo: { dictTypeCode: 'OnlineWebTwo', desc: '二级标题' },
|
||||
Site: { dictTypeCode: 'Site', desc: '适用站点' },
|
||||
}
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const formRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
OnlineWebOne: [] as DictGetListOutput[] | null,
|
||||
OnlineWebTwo: [] as DictGetListOutput[] | null,
|
||||
Site: [] as DictGetListOutput[] | null,
|
||||
|
||||
form: {} as OnlineUpdateInput,
|
||||
})
|
||||
|
||||
const { form } = toRefs(state)
|
||||
|
||||
// 获取字典数据
|
||||
const getDictList = async () => {
|
||||
const res = await new DictApi().getList([DictType.OnlineWebOne.dictTypeCode, DictType.OnlineWebTwo.dictTypeCode, DictType.Site.dictTypeCode]).catch(() => {})
|
||||
if (res?.success && res.data) {
|
||||
state.OnlineWebOne = res.data.onlineWebOne
|
||||
state.OnlineWebTwo = res.data.onlineWebTwo
|
||||
state.Site = res.data.site
|
||||
}
|
||||
|
||||
console.log("🔍 ~ getDictList() callback ~ src/views/admin/online/index.vue:221 ~ getDictList():", state.OnlineWebOne, state.OnlineWebTwo, state.Site)
|
||||
}
|
||||
|
||||
// 打开对话框
|
||||
const open = async (row: Partial<OnlineUpdateInput> = { id: 0 }) => {
|
||||
await getDictList()
|
||||
let formData = cloneDeep(row) as OnlineUpdateInput
|
||||
if (row.id && row.id > 0) {
|
||||
const res = await new OnlineApi().get({ id: row.id })
|
||||
|
||||
if (res?.success) {
|
||||
formData = res.data as OnlineUpdateInput
|
||||
}
|
||||
} else {
|
||||
formData = {
|
||||
id: 0,
|
||||
websiteName: '',
|
||||
primaryTitle: '',
|
||||
secondaryTitle: '',
|
||||
contactPerson: '',
|
||||
tutorialUrl: '',
|
||||
applicableSite: '',
|
||||
functionIntro: '',
|
||||
keywords: '',
|
||||
websiteUrl: '',
|
||||
}
|
||||
}
|
||||
|
||||
state.form = formData
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
state.sureLoading = true
|
||||
let res = {} as any
|
||||
if (state.form.id != undefined && state.form.id > 0) {
|
||||
res = await new OnlineApi().update(state.form).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
} else {
|
||||
res = await new OnlineApi().add(state.form).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success === true) {
|
||||
eventBus.emit('refreshOnline')
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
@ -1,215 +0,0 @@
|
||||
<template>
|
||||
<my-layout>
|
||||
<div class="my-query-box mt8" style="position: relative">
|
||||
<el-card shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" label-width="auto" :label-position="'left'" @submit.stop.prevent>
|
||||
<el-form-item label="关键词">
|
||||
<el-input v-model="state.filter.websiteName" placeholder="请输入网站名称、功能简介、关键词、网址" style="width: 350px" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="一级标题">
|
||||
<el-select v-model="state.filter.primaryTitle" placeholder="请选择一级标题" clearable style="width: 150px" @change="onQuery">
|
||||
<el-option v-for="item in state.OnlineWebOne" :key="item.code" :label="item.name" :value="item.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="二级标题">
|
||||
<el-select v-model="state.filter.secondaryTitle" placeholder="请选择二级标题" clearable style="width: 150px" @change="onQuery">
|
||||
<el-option v-for="item in state.OnlineWebTwo" :key="item.code" :label="item.name" :value="item.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建日期">
|
||||
<MyDateRange v-model:startDate="state.filter.startCreatedTime" v-model:endDate="state.filter.endCreatedTime" style="width: 230px" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:online:add'" type="primary" icon="ele-Plus" @click="onAdd"> 新增 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<el-card class="my-fill mt8 el-card-table" shadow="never">
|
||||
<el-table ref="tableRef" v-loading="state.loading" :data="state.onlineListData" row-key="id" style="width: 100%" border>
|
||||
<el-table-column type="index" label="序号" width="60" :index="indexMethod" />
|
||||
<el-table-column prop="websiteName" label="网站名称" min-width="120" />
|
||||
<el-table-column prop="primaryTitle" label="主标题" min-width="120" />
|
||||
<el-table-column prop="secondaryTitle" label="副标题" min-width="120" />
|
||||
<el-table-column prop="contactPerson" label="联系人" width="100" />
|
||||
<el-table-column prop="tutorialUrl" label="教程地址" min-width="200">
|
||||
<template #default="{ row }">
|
||||
<el-link type="primary" :href="row.tutorialUrl" target="_blank">{{ row.tutorialUrl }}</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="websiteUrl" label="网站地址" min-width="200">
|
||||
<template #default="{ row }">
|
||||
<el-link type="primary" :href="row.websiteUrl" target="_blank">{{ row.websiteUrl }}</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createdTime" label="创建时间" :formatter="formatterTime" width="100" />
|
||||
<el-table-column label="操作" width="150" fixed="right" header-align="center" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button v-auth="'api:admin:online:update'" icon="ele-Edit" text type="primary" @click="onUpdate(row)">修改</el-button>
|
||||
<el-button v-auth="'api:admin:online:delete'" icon="ele-Delete" text type="danger" @click="onDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="my-flex my-flex-end" style="margin-top: 10px">
|
||||
<el-pagination
|
||||
v-model:currentPage="state.pageInput.currentPage"
|
||||
v-model:page-size="state.pageInput.pageSize"
|
||||
:total="state.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
background
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<online-form ref="onlineFormRef" :title="state.onlineFormTitle"></online-form>
|
||||
</my-layout>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/online">
|
||||
import { ref, reactive, onMounted, onBeforeMount, getCurrentInstance, defineAsyncComponent } from 'vue'
|
||||
import { ElTable, ElMessageBox, ElMessage } from 'element-plus'
|
||||
import { OnlineGetOutput, PageInputOnlineGetPageInput, DictGetListOutput } from '/@/api/admin/data-contracts'
|
||||
import { OnlineApi } from '/@/api/admin/Online'
|
||||
import { DictApi } from '/@/api/admin/Dict'
|
||||
import dayjs from 'dayjs'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
|
||||
// 引入组件
|
||||
const OnlineForm = defineAsyncComponent(() => import('./components/online-form.vue'))
|
||||
const MyDateRange = defineAsyncComponent(() => import('/@/components/my-date-range/index.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const onlineFormRef = ref()
|
||||
const tableRef = ref<InstanceType<typeof ElTable>>()
|
||||
|
||||
/** 字典分类 */
|
||||
const DictType = {
|
||||
OnlineWebOne: { dictTypeCode: 'OnlineWebOne', desc: '一级标题' },
|
||||
OnlineWebTwo: { dictTypeCode: 'OnlineWebTwo', desc: '二级标题' },
|
||||
}
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
onlineFormTitle: '',
|
||||
OnlineWebOne: [] as DictGetListOutput[] | null,
|
||||
OnlineWebTwo: [] as DictGetListOutput[] | null,
|
||||
filter: {
|
||||
websiteName: '',
|
||||
primaryTitle: '',
|
||||
secondaryTitle: '',
|
||||
startCreatedTime: undefined,
|
||||
endCreatedTime: undefined,
|
||||
},
|
||||
total: 0,
|
||||
pageInput: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
filter: {},
|
||||
} as PageInputOnlineGetPageInput,
|
||||
onlineListData: [] as Array<OnlineGetOutput>,
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
getDictList()
|
||||
|
||||
onQuery()
|
||||
eventBus.off('refreshOnline')
|
||||
eventBus.on('refreshOnline', async () => {
|
||||
onQuery()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshOnline')
|
||||
})
|
||||
|
||||
// 格式化时间
|
||||
const formatterTime = (row: any, column: any, cellValue: any) => {
|
||||
if (!cellValue) return ''
|
||||
return dayjs(cellValue).format('YYYY-MM-DD')
|
||||
}
|
||||
|
||||
// 序号
|
||||
const indexMethod = (index: number) => {
|
||||
return ((state.pageInput.currentPage || 1) - 1) * (state.pageInput.pageSize || 20) + index + 1
|
||||
}
|
||||
|
||||
// 查询
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
const res = await new OnlineApi()
|
||||
.getPage({
|
||||
...state.pageInput,
|
||||
filter: state.filter,
|
||||
})
|
||||
.catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
|
||||
state.loading = false
|
||||
|
||||
if (res?.success) {
|
||||
state.onlineListData = res.data?.list ?? []
|
||||
state.total = res.data?.total ?? 0
|
||||
}
|
||||
}
|
||||
|
||||
// 新增
|
||||
const onAdd = () => {
|
||||
state.onlineFormTitle = '新增'
|
||||
onlineFormRef.value.open()
|
||||
}
|
||||
|
||||
// 修改
|
||||
const onUpdate = (row: OnlineGetOutput) => {
|
||||
state.onlineFormTitle = '修改'
|
||||
onlineFormRef.value.open(row)
|
||||
}
|
||||
|
||||
// 删除
|
||||
const onDelete = async (row: OnlineGetOutput) => {
|
||||
ElMessageBox.confirm(`确定删除在线教程:【${row.websiteName}】?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(async () => {
|
||||
const res = await new OnlineApi().delete({ id: row.id })
|
||||
if (res?.status === 200) {
|
||||
ElMessage.success('删除成功')
|
||||
onQuery()
|
||||
}
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
// 分页大小改变
|
||||
const onSizeChange = (val: number) => {
|
||||
state.pageInput.pageSize = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
// 分页改变
|
||||
const onCurrentChange = (val: number) => {
|
||||
state.pageInput.currentPage = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
// 获取字典数据
|
||||
const getDictList = async () => {
|
||||
const res = await new DictApi().getList([DictType.OnlineWebOne.dictTypeCode, DictType.OnlineWebTwo.dictTypeCode]).catch(() => {})
|
||||
if (res?.success && res.data) {
|
||||
state.OnlineWebOne = res.data.onlineWebOne
|
||||
state.OnlineWebTwo = res.data.onlineWebTwo
|
||||
}
|
||||
|
||||
console.log("🔍 ~ getDictList() callback ~ src/views/admin/online/index.vue:221 ~ getDictList():", state.OnlineWebOne, state.OnlineWebTwo)
|
||||
}
|
||||
</script>
|
||||
@ -1,167 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="600px"
|
||||
>
|
||||
<el-form :model="form" ref="formRef" label-width="80px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="上级部门" prop="parentId" :rules="[{ required: true, message: '请输入上级部门', trigger: ['change'] }]">
|
||||
<el-tree-select
|
||||
v-model="form.parentId"
|
||||
:data="state.data"
|
||||
node-key="id"
|
||||
:props="{ label: 'name' }"
|
||||
check-strictly
|
||||
default-expand-all
|
||||
render-after-expand
|
||||
fit-input-width
|
||||
clearable
|
||||
class="w100"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="部门名称" prop="name" :rules="[{ required: true, message: '请输入部门名称', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.name" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="部门编码" prop="code">
|
||||
<el-input v-model="form.code" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="部门值" prop="value">
|
||||
<el-input v-model="form.value" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="排序">
|
||||
<el-input-number v-model="form.sort" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="启用">
|
||||
<el-switch v-model="form.enabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="说明">
|
||||
<el-input v-model="form.description" clearable type="textarea" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/org/form">
|
||||
import { reactive, toRefs, ref, getCurrentInstance } from 'vue'
|
||||
import { OrgUpdateInput } from '/@/api/admin/data-contracts'
|
||||
import { OrgApi } from '/@/api/admin/Org'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { listToTree } from '/@/utils/tree'
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const formRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
form: {
|
||||
enabled: true,
|
||||
} as OrgUpdateInput,
|
||||
data: [],
|
||||
})
|
||||
|
||||
const { form } = toRefs(state)
|
||||
|
||||
const query = async () => {
|
||||
const res = await new OrgApi().getList().catch(() => {})
|
||||
if (res && res.data && res.data.length > 0) {
|
||||
state.data = listToTree(res.data)
|
||||
} else {
|
||||
state.data = []
|
||||
}
|
||||
}
|
||||
|
||||
// 打开对话框
|
||||
const open = async (row: any = {}) => {
|
||||
proxy.$modal.loading()
|
||||
await query()
|
||||
proxy.$modal.closeLoading()
|
||||
|
||||
if (row.id > 0) {
|
||||
const res = await new OrgApi().get({ id: row.id }, { loading: true })
|
||||
|
||||
if (res?.success) {
|
||||
let formData = res.data as OrgUpdateInput
|
||||
formData.parentId = formData.parentId && formData.parentId > 0 ? formData.parentId : undefined
|
||||
state.form = formData
|
||||
}
|
||||
} else {
|
||||
state.form = {
|
||||
enabled: true,
|
||||
parentId: row.parentId > 0 ? row.parentId : undefined,
|
||||
} as OrgUpdateInput
|
||||
}
|
||||
state.showDialog = true
|
||||
}
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
state.sureLoading = true
|
||||
let res = {} as any
|
||||
state.form.parentId = state.form.parentId && state.form.parentId > 0 ? state.form.parentId : undefined
|
||||
if (state.form.id != undefined && state.form.id > 0) {
|
||||
res = await new OrgApi().update(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
} else {
|
||||
res = await new OrgApi().add(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
eventBus.emit('refreshOrg')
|
||||
eventBus.emit('refreshOrgImg')
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
@ -1,208 +0,0 @@
|
||||
<template>
|
||||
<div v-loading="state.loading" class="h100">
|
||||
<vue3-tree-org
|
||||
ref="orgRef"
|
||||
:data="state.data"
|
||||
:props="{
|
||||
id: 'id',
|
||||
pid: 'parentId',
|
||||
label: 'name',
|
||||
expand: 'expand',
|
||||
children: 'children',
|
||||
}"
|
||||
center
|
||||
:horizontal="false"
|
||||
:collapsable="false"
|
||||
:only-one-node="false"
|
||||
:clone-node-drag="false"
|
||||
:node-draggable="false"
|
||||
:define-menus="[
|
||||
{ name: '复制文本', command: 'copy' },
|
||||
{ name: '新增部门', command: 'onAdd' },
|
||||
{ name: '编辑部门', command: 'onEdit' },
|
||||
{ name: '删除部门', command: 'onDelete' },
|
||||
]"
|
||||
:label-style="state.style"
|
||||
:filter-node-method="filterNodeMethod"
|
||||
@on-node-dblclick="onNodeDblclick"
|
||||
@on-contextmenu="onContextmenu"
|
||||
v-bind="$attrs"
|
||||
>
|
||||
<template v-if="state.showOrgCount" v-slot:expand="{ node }">
|
||||
<div>{{ node.children.length }}</div>
|
||||
</template>
|
||||
</vue3-tree-org>
|
||||
|
||||
<org-form ref="orgFormRef" :title="state.orgFormTitle"></org-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/org-tree-img">
|
||||
import { ref, reactive, onMounted, getCurrentInstance, onBeforeMount, defineAsyncComponent } from 'vue'
|
||||
import { OrgGetListOutput } from '/@/api/admin/data-contracts'
|
||||
import { OrgApi } from '/@/api/admin/Org'
|
||||
import { listToTree } from '/@/utils/tree'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
|
||||
// 引入组件
|
||||
const OrgForm = defineAsyncComponent(() => import('./org-form.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const orgRef = ref()
|
||||
const orgFormRef = ref()
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
orgFormTitle: '',
|
||||
filter: {
|
||||
name: '',
|
||||
},
|
||||
style: {
|
||||
background: '#fff',
|
||||
color: '#5e6d82',
|
||||
},
|
||||
showOrgCount: true,
|
||||
data: [] as any,
|
||||
orgTreeData: [] as Array<OrgGetListOutput>,
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
onQuery()
|
||||
eventBus.off('refreshOrgImg')
|
||||
eventBus.on('refreshOrgImg', () => {
|
||||
onQuery()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshOrgImg')
|
||||
})
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
const res = await new OrgApi().getList().catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
if (res && res.data && res.data.length > 0) {
|
||||
const data = listToTree(res.data, {
|
||||
extraData: {
|
||||
expand: true,
|
||||
},
|
||||
})
|
||||
state.orgTreeData = data
|
||||
state.data = data?.length > 0 ? data[0] : {}
|
||||
state.data['disabled'] = true
|
||||
} else {
|
||||
state.data = []
|
||||
}
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onAdd = (row: OrgGetListOutput) => {
|
||||
state.orgFormTitle = '新增部门'
|
||||
orgFormRef.value.open({ parentId: row?.id })
|
||||
}
|
||||
|
||||
const onEdit = (row: OrgGetListOutput) => {
|
||||
state.orgFormTitle = '编辑部门'
|
||||
orgFormRef.value.open(row)
|
||||
}
|
||||
|
||||
const onDelete = (row: OrgGetListOutput) => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要删除部门【${row.name}】?`)
|
||||
.then(async () => {
|
||||
await new OrgApi().delete({ id: row.id }, { loading: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onContextmenu = ({ node, command }: any) => {
|
||||
switch (command) {
|
||||
case 'onAdd':
|
||||
onAdd(node.$$data)
|
||||
break
|
||||
case 'onEdit':
|
||||
onEdit(node.$$data)
|
||||
break
|
||||
case 'onDelete':
|
||||
onDelete(node.$$data)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const filter = (filterword: string) => {
|
||||
orgRef.value.filter(filterword)
|
||||
}
|
||||
|
||||
const filterNodeMethod = (value: string, data: any) => {
|
||||
if (!value) return true
|
||||
return data.label.indexOf(value) !== -1
|
||||
}
|
||||
|
||||
const onNodeDblclick = (e: any, data: any) => {}
|
||||
|
||||
defineExpose({
|
||||
filter,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.zm-tree-contextmenu {
|
||||
background-color: var(--el-bg-color-overlay);
|
||||
border-color: var(--el-border-color);
|
||||
li:hover {
|
||||
background-color: var(--el-color-primary-light-9);
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep() {
|
||||
.icon-fullscreen:before {
|
||||
content: '\e603' !important;
|
||||
}
|
||||
.tree-org {
|
||||
margin-top: 5px;
|
||||
}
|
||||
.zm-tree-org {
|
||||
background-color: var(--el-bg-color-overlay);
|
||||
padding: 0px;
|
||||
}
|
||||
.tree-org-node__inner {
|
||||
background-color: var(--el-bg-color) !important;
|
||||
color: var(--el-text-color-primary) !important;
|
||||
border: 1px solid var(--el-border-color);
|
||||
}
|
||||
.tree-org-node:not(:first-child):before,
|
||||
.tree-org-node:not(:last-child):after,
|
||||
.tree-org-node:after,
|
||||
.tree-org-node__children:before {
|
||||
border-color: var(--el-border-color);
|
||||
}
|
||||
.zm-tree-handle .zm-tree-handle-item {
|
||||
background-color: var(--el-bg-color-overlay);
|
||||
color: var(--el-text-color-primary);
|
||||
border-color: var(--el-border-color);
|
||||
.zm-tree-restore {
|
||||
border-color: var(--el-text-color-primary);
|
||||
}
|
||||
.zm-tree-restore:after {
|
||||
border-top-color: var(--el-text-color-primary);
|
||||
border-right-color: var(--el-text-color-primary);
|
||||
}
|
||||
&:hover {
|
||||
background-color: var(--el-color-primary-light-9);
|
||||
color: var(--el-color-primary);
|
||||
border-color: var(--el-color-primary-light-7);
|
||||
.zm-tree-restore,
|
||||
.zm-tree-restore:after {
|
||||
border-color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,150 +0,0 @@
|
||||
<template>
|
||||
<el-card shadow="never" style="margin-top: 8px" body-style="padding:0px;" class="my-fill">
|
||||
<template #header>
|
||||
<div class="my-flex">
|
||||
<el-input v-model="state.filterText" placeholder="筛选部门" clearable />
|
||||
<el-dropdown trigger="hover">
|
||||
<div class="my-flex my-flex-items-center my-icon-more">
|
||||
<my-icon name="more" color="var(--color)" size="22"></my-icon>
|
||||
</div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item @click="expandAllNodes(true)">展开全部</el-dropdown-item>
|
||||
<el-dropdown-item @click="expandAllNodes(false)">收缩全部</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
<el-scrollbar v-loading="state.loading" height="100%" max-height="100%" :always="false" wrap-style="padding:10px">
|
||||
<el-tree
|
||||
ref="orgMenuRef"
|
||||
:data="state.orgTreeData"
|
||||
node-key="id"
|
||||
:props="{ children: 'children', label: 'name' }"
|
||||
:filter-node-method="onFilterNode"
|
||||
highlight-current
|
||||
check-strictly
|
||||
default-expand-all
|
||||
render-after-expand
|
||||
:expand-on-click-node="false"
|
||||
v-bind="$attrs"
|
||||
@node-click="onNodeClick"
|
||||
@check-change="onCheckChange"
|
||||
/>
|
||||
</el-scrollbar>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/org/menu">
|
||||
import { onMounted, reactive, ref, watch, nextTick, PropType } from 'vue'
|
||||
import { OrgGetListOutput } from '/@/api/admin/data-contracts'
|
||||
import { OrgApi } from '/@/api/admin/Org'
|
||||
import { listToTree } from '/@/utils/tree'
|
||||
import { ElTree } from 'element-plus'
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Array as PropType<number[] | undefined | null>,
|
||||
default: () => [],
|
||||
},
|
||||
selectFirstNode: {
|
||||
type: Boolean,
|
||||
default: () => false,
|
||||
},
|
||||
})
|
||||
|
||||
const orgMenuRef = ref<InstanceType<typeof ElTree>>()
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
filterText: '',
|
||||
orgTreeData: [] as Array<OrgGetListOutput>,
|
||||
lastKey: 0,
|
||||
})
|
||||
|
||||
watch(
|
||||
() => state.filterText,
|
||||
(val) => {
|
||||
orgMenuRef.value?.filter(val)
|
||||
}
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
initData()
|
||||
})
|
||||
|
||||
const emits = defineEmits<{
|
||||
(e: 'node-click', node: OrgGetListOutput | null): void
|
||||
(e: 'update:modelValue', node: any[] | undefined | null): void
|
||||
}>()
|
||||
|
||||
/**
|
||||
* 展开或收缩所有树节点
|
||||
* @param expanded 是否展开
|
||||
*/
|
||||
const expandAllNodes = (expanded: boolean) => {
|
||||
if (!orgMenuRef.value) return
|
||||
|
||||
const treeNodes = orgMenuRef.value.store.nodesMap
|
||||
Object.values(treeNodes).forEach((node) => {
|
||||
node.expanded = expanded
|
||||
})
|
||||
}
|
||||
|
||||
const onFilterNode = (value: string, data: OrgGetListOutput) => {
|
||||
if (!value) return true
|
||||
return data.name?.indexOf(value) !== -1
|
||||
}
|
||||
|
||||
const onNodeClick = (node: OrgGetListOutput) => {
|
||||
if (state.lastKey === node.id) {
|
||||
state.lastKey = 0
|
||||
orgMenuRef.value?.setCurrentKey(undefined)
|
||||
emits('node-click', null)
|
||||
} else {
|
||||
state.lastKey = node.id as number
|
||||
emits('node-click', node)
|
||||
}
|
||||
}
|
||||
|
||||
const onCheckChange = () => {
|
||||
emits('update:modelValue', orgMenuRef.value?.getCheckedKeys())
|
||||
}
|
||||
|
||||
const initData = async () => {
|
||||
state.loading = true
|
||||
const res = await new OrgApi().getList().catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
state.loading = false
|
||||
if (res?.success && res.data && res.data.length > 0) {
|
||||
state.orgTreeData = listToTree(res.data)
|
||||
if (state.orgTreeData.length > 0 && props.selectFirstNode) {
|
||||
nextTick(() => {
|
||||
const firstNode = state.orgTreeData[0]
|
||||
orgMenuRef.value?.setCurrentKey(firstNode.id)
|
||||
onNodeClick(firstNode)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
state.orgTreeData = []
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
orgMenuRef,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.my-icon-more {
|
||||
cursor: pointer;
|
||||
--el-button-text-color: var(--el-text-color-regular);
|
||||
--el-button-hover-text-color: var(--el-color-primary);
|
||||
color: var(--el-button-text-color);
|
||||
fill: currentColor;
|
||||
&:hover {
|
||||
color: var(--el-button-hover-text-color);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,165 +0,0 @@
|
||||
<template>
|
||||
<MyLayout>
|
||||
<el-card v-show="state.showQuery" class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" label-width="auto" @submit.stop.prevent>
|
||||
<el-form-item label="部门名称">
|
||||
<el-input v-model="state.filter.name" placeholder="部门名称" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<div class="my-tools-box mb8 my-flex my-flex-between">
|
||||
<div>
|
||||
<el-button v-show="state.showOrgList" v-auth="'api:admin:org:add'" type="primary" icon="ele-Plus" @click="onAdd"> 新增 </el-button>
|
||||
</div>
|
||||
<div>
|
||||
<el-tooltip effect="dark" :content="state.showQuery ? '隐藏查询' : '显示查询'" placement="top">
|
||||
<el-button :icon="state.showQuery ? 'ele-ArrowUp' : 'ele-ArrowDown'" circle @click="state.showQuery = !state.showQuery" />
|
||||
</el-tooltip>
|
||||
|
||||
<el-tooltip effect="dark" :content="state.showOrgList ? '部门图形' : '部门列表'" placement="top">
|
||||
<el-button :icon="state.showOrgList ? 'ele-Share' : 'ele-Grid'" circle @click="onChangeOrgList" />
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<el-table
|
||||
v-if="state.showOrgList"
|
||||
:data="state.data"
|
||||
style="width: 100%"
|
||||
v-loading="state.loading"
|
||||
row-key="id"
|
||||
default-expand-all
|
||||
border
|
||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
>
|
||||
<el-table-column prop="name" label="部门名称" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="code" label="部门编码" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="value" label="部门值" min-width="82" show-overflow-tooltip />
|
||||
<el-table-column prop="sort" label="排序" width="82" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="状态" width="82" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="success" v-if="row.enabled">启用</el-tag>
|
||||
<el-tag type="danger" v-else>禁用</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="200" fixed="right" header-align="center" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button v-if="auth('api:admin:org:add')" icon="ele-Plus" text type="primary" @click="onAdd(row)"> 新增 </el-button>
|
||||
<el-button v-if="auth('api:admin:org:update') && row.parentId > 0" icon="ele-EditPen" text type="primary" @click="onEdit(row)"
|
||||
>编辑</el-button
|
||||
>
|
||||
<el-button v-if="auth('api:admin:org:delete') && row.parentId > 0" icon="ele-Delete" text type="danger" @click="onDelete(row)"
|
||||
>删除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<OrgImg ref="orgImgRef" v-else></OrgImg>
|
||||
</el-card>
|
||||
|
||||
<org-form ref="orgFormRef" :title="state.orgFormTitle"></org-form>
|
||||
</MyLayout>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/org">
|
||||
import { ref, reactive, onMounted, getCurrentInstance, onBeforeMount, defineAsyncComponent } from 'vue'
|
||||
import { OrgGetListOutput } from '/@/api/admin/data-contracts'
|
||||
import { OrgApi } from '/@/api/admin/Org'
|
||||
import { listToTree, filterList } from '/@/utils/tree'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { auth } from '/@/utils/authFunction'
|
||||
|
||||
// 引入组件
|
||||
const OrgForm = defineAsyncComponent(() => import('./components/org-form.vue'))
|
||||
const OrgImg = defineAsyncComponent(() => import('./components/org-img.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const orgFormRef = ref()
|
||||
const orgImgRef = ref()
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
orgFormTitle: '',
|
||||
filter: {
|
||||
name: '',
|
||||
},
|
||||
data: [] as Array<OrgGetListOutput>,
|
||||
showQuery: true,
|
||||
showOrgList: true,
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
Query()
|
||||
eventBus.off('refreshOrg')
|
||||
eventBus.on('refreshOrg', () => {
|
||||
Query()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshOrg')
|
||||
})
|
||||
|
||||
const onChangeOrgList = () => {
|
||||
state.showOrgList = !state.showOrgList
|
||||
if (state.showOrgList) {
|
||||
Query()
|
||||
}
|
||||
}
|
||||
|
||||
const onQuery = () => {
|
||||
if (state.showOrgList) {
|
||||
Query()
|
||||
} else {
|
||||
orgImgRef.value.filter(state.filter.name)
|
||||
}
|
||||
}
|
||||
|
||||
const Query = async () => {
|
||||
state.loading = true
|
||||
const res = await new OrgApi().getList().catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
if (res && res.data && res.data.length > 0) {
|
||||
state.data = listToTree(
|
||||
state.filter.name
|
||||
? filterList(res.data, state.filter.name, {
|
||||
filterWhere: (item: any, filterword: string) => {
|
||||
return item.name?.toLocaleLowerCase().indexOf(filterword) > -1
|
||||
},
|
||||
})
|
||||
: res.data
|
||||
)
|
||||
} else {
|
||||
state.data = []
|
||||
}
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onAdd = (row: OrgGetListOutput) => {
|
||||
state.orgFormTitle = '新增部门'
|
||||
orgFormRef.value.open({ parentId: row.id })
|
||||
}
|
||||
|
||||
const onEdit = (row: OrgGetListOutput) => {
|
||||
state.orgFormTitle = '编辑部门'
|
||||
orgFormRef.value.open(row)
|
||||
}
|
||||
|
||||
const onDelete = (row: OrgGetListOutput) => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要删除部门【${row.name}】?`)
|
||||
.then(async () => {
|
||||
await new OrgApi().delete({ id: row.id }, { loading: true })
|
||||
Query()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -1,257 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="600px"
|
||||
>
|
||||
<el-form :model="form" ref="formRef" label-width="80px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="所属平台">
|
||||
<el-select v-model="form.platform" disabled placeholder="请选择所属平台" class="w100">
|
||||
<el-option v-for="item in state.dictData[DictType.PlatForm.name]" :key="item.code" :label="item.name" :value="item.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="上级菜单">
|
||||
<el-tree-select
|
||||
v-model="form.parentId"
|
||||
:data="permissionTreeData"
|
||||
node-key="id"
|
||||
check-strictly
|
||||
default-expand-all
|
||||
render-after-expand
|
||||
fit-input-width
|
||||
clearable
|
||||
filterable
|
||||
class="w100"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="API接口">
|
||||
<el-tree-select
|
||||
v-model="form.apiIds"
|
||||
:data="state.apiTreeData"
|
||||
node-key="id"
|
||||
:props="{ label: 'path' }"
|
||||
render-after-expand
|
||||
fit-input-width
|
||||
clearable
|
||||
filterable
|
||||
multiple
|
||||
collapse-tags
|
||||
collapse-tags-tooltip
|
||||
:filter-node-method="onApiFilterNode"
|
||||
class="w100"
|
||||
:default-expanded-keys="state.expandRowKeys"
|
||||
@current-change="onApiCurrentChange"
|
||||
>
|
||||
<template #default="{ data }">
|
||||
<span class="my-flex my-flex-between">
|
||||
<span>{{ data.label }}</span>
|
||||
<span class="my-line-1 my-mlr-12" :title="data.path">
|
||||
{{ data.path }}
|
||||
</span>
|
||||
</span>
|
||||
</template>
|
||||
</el-tree-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="名称" prop="label" :rules="[{ required: true, message: '请输入名称', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.label" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="编码" prop="code" :rules="[{ required: true, message: '请输入编码', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.code" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="排序">
|
||||
<el-input-number v-model="form.sort" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="启用">
|
||||
<el-switch v-model="form.enabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="说明">
|
||||
<el-input v-model="form.description" clearable type="textarea" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/permission/permission-dot-form">
|
||||
import { reactive, toRefs, getCurrentInstance, ref, PropType, markRaw } from 'vue'
|
||||
import { PermissionGetListOutput, PermissionUpdateDotInput, ApiGetListOutput, DictGetListOutput } from '/@/api/admin/data-contracts'
|
||||
import { PermissionApi } from '/@/api/admin/Permission'
|
||||
import { ApiApi } from '/@/api/admin/Api'
|
||||
import { listToTree, treeToList } from '/@/utils/tree'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { trimStart, replace, cloneDeep } from 'lodash-es'
|
||||
import { DictApi } from '/@/api/admin/Dict'
|
||||
|
||||
/** 字典分类 */
|
||||
const DictType = {
|
||||
PlatForm: { name: 'platform', desc: '平台' },
|
||||
}
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
permissionTreeData: {
|
||||
type: Array as PropType<PermissionGetListOutput[]>,
|
||||
default: () => [],
|
||||
},
|
||||
})
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const formRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
form: { enabled: true } as PermissionUpdateDotInput,
|
||||
apiTreeData: [] as ApiGetListOutput[],
|
||||
expandRowKeys: [] as number[],
|
||||
dictData: {
|
||||
[DictType.PlatForm.name]: [] as DictGetListOutput[] | null,
|
||||
},
|
||||
})
|
||||
|
||||
const { form } = toRefs(state)
|
||||
|
||||
const getDictList = async () => {
|
||||
const res = await new DictApi().getList([DictType.PlatForm.name]).catch(() => {})
|
||||
if (res?.success && res.data) {
|
||||
state.dictData = markRaw(res.data)
|
||||
}
|
||||
}
|
||||
|
||||
const getApis = async () => {
|
||||
const res = await new ApiApi().getList()
|
||||
if (res?.success && res.data && res.data.length > 0) {
|
||||
state.apiTreeData = listToTree(res.data) as ApiGetListOutput[]
|
||||
} else {
|
||||
state.apiTreeData = []
|
||||
}
|
||||
}
|
||||
|
||||
// 打开对话框
|
||||
const open = async (
|
||||
row: PermissionUpdateDotInput = {
|
||||
id: 0,
|
||||
enabled: true,
|
||||
parentId: undefined,
|
||||
},
|
||||
isCopy = false
|
||||
) => {
|
||||
proxy.$modal.loading()
|
||||
await getDictList()
|
||||
await getApis()
|
||||
|
||||
state.expandRowKeys = treeToList(cloneDeep(state.apiTreeData))
|
||||
.filter((a: ApiGetListOutput) => a.parentId === 0)
|
||||
.map((a: ApiGetListOutput) => a.id) as number[]
|
||||
|
||||
if (row.id > 0) {
|
||||
const res = await new PermissionApi().getDot({ id: row.id }).catch(() => {
|
||||
proxy.$modal.closeLoading()
|
||||
})
|
||||
|
||||
if (res?.success) {
|
||||
let formData = res.data as PermissionUpdateDotInput
|
||||
formData.platform = row.platform
|
||||
formData.parentId = formData.parentId && formData.parentId > 0 ? formData.parentId : undefined
|
||||
if (isCopy) formData.id = 0
|
||||
state.form = formData
|
||||
}
|
||||
} else {
|
||||
state.form = row
|
||||
}
|
||||
|
||||
proxy.$modal.closeLoading()
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
const onApiFilterNode = (value: string, data: ApiGetListOutput) => {
|
||||
if (!value) return true
|
||||
return data.label?.indexOf(value) !== -1 || data.path?.indexOf(value) !== -1
|
||||
}
|
||||
|
||||
const onApiCurrentChange = (data: ApiGetListOutput) => {
|
||||
if (data?.httpMethods) {
|
||||
if (!state.form.label) {
|
||||
state.form.label = data.label
|
||||
}
|
||||
if (!state.form.code) {
|
||||
state.form.code = trimStart(replace(data.path || '', /\//g, ':'), ':')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
state.sureLoading = true
|
||||
let res = {} as any
|
||||
state.form.parentId = state.form.parentId && state.form.parentId > 0 ? state.form.parentId : undefined
|
||||
if (state.form.id != undefined && state.form.id > 0) {
|
||||
res = await new PermissionApi().updateDot(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
} else {
|
||||
res = await new PermissionApi().addDot(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
eventBus.emit('refreshPermission')
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.my-mlr-12 {
|
||||
margin-left: 12px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
</style>
|
||||
@ -1,201 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="600px"
|
||||
>
|
||||
<el-form :model="form" ref="formRef" label-width="80px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="所属平台">
|
||||
<el-select v-model="form.platform" disabled placeholder="请选择所属平台" class="w100">
|
||||
<el-option v-for="item in state.dictData[DictType.PlatForm.name]" :key="item.code" :label="item.name" :value="item.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="上级分组">
|
||||
<el-tree-select
|
||||
v-model="form.parentId"
|
||||
:data="permissionTreeData"
|
||||
node-key="id"
|
||||
check-strictly
|
||||
default-expand-all
|
||||
render-after-expand
|
||||
fit-input-width
|
||||
clearable
|
||||
:empty-values="[0, null, undefined]"
|
||||
class="w100"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="名称" prop="label" :rules="[{ required: true, message: '请输入名称', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.label" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="路由地址" prop="path" :rules="[{ required: true, message: '请输入路由地址', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.path" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="重定向">
|
||||
<el-input v-model="form.redirect" clearable placeholder="重定向地址" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="图标" prop="icon">
|
||||
<my-select-icon v-model="form.icon" clearable class="w100" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="排序">
|
||||
<el-input-number v-model="form.sort" class="w100" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="启用">
|
||||
<el-switch v-model="form.enabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="展开">
|
||||
<el-switch v-model="form.opened" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="隐藏">
|
||||
<el-switch v-model="form.hidden" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/permission/permission-group-form">
|
||||
import { reactive, toRefs, getCurrentInstance, ref, PropType, defineAsyncComponent, markRaw } from 'vue'
|
||||
import { PermissionGetListOutput, PermissionUpdateGroupInput, DictGetListOutput } from '/@/api/admin/data-contracts'
|
||||
import { PermissionApi } from '/@/api/admin/Permission'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { DictApi } from '/@/api/admin/Dict'
|
||||
|
||||
// 引入组件
|
||||
const MySelectIcon = defineAsyncComponent(() => import('/@/components/my-select-icon/index.vue'))
|
||||
|
||||
/** 字典分类 */
|
||||
const DictType = {
|
||||
PlatForm: { name: 'platform', desc: '平台' },
|
||||
}
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
permissionTreeData: {
|
||||
type: Array as PropType<PermissionGetListOutput[]>,
|
||||
default: () => [],
|
||||
},
|
||||
})
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
const formRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
form: { enabled: true, opened: true } as PermissionUpdateGroupInput,
|
||||
dictData: {
|
||||
[DictType.PlatForm.name]: [] as DictGetListOutput[] | null,
|
||||
},
|
||||
})
|
||||
const { form } = toRefs(state)
|
||||
|
||||
const getDictList = async () => {
|
||||
const res = await new DictApi().getList([DictType.PlatForm.name]).catch(() => {})
|
||||
if (res?.success && res.data) {
|
||||
state.dictData = markRaw(res.data)
|
||||
}
|
||||
}
|
||||
|
||||
// 打开对话框
|
||||
const open = async (
|
||||
row: PermissionUpdateGroupInput = {
|
||||
id: 0,
|
||||
enabled: true,
|
||||
opened: true,
|
||||
icon: 'ele-Memo',
|
||||
parentId: undefined,
|
||||
},
|
||||
isCopy = false
|
||||
) => {
|
||||
proxy.$modal.loading()
|
||||
await getDictList()
|
||||
if (row.id > 0) {
|
||||
const res = await new PermissionApi().getGroup({ id: row.id }).catch(() => {
|
||||
proxy.$modal.closeLoading()
|
||||
})
|
||||
|
||||
if (res?.success) {
|
||||
let formData = res.data as PermissionUpdateGroupInput
|
||||
formData.platform = row.platform
|
||||
formData.parentId = formData.parentId && formData.parentId > 0 ? formData.parentId : undefined
|
||||
if (isCopy) formData.id = 0
|
||||
state.form = formData
|
||||
}
|
||||
} else {
|
||||
state.form = row
|
||||
}
|
||||
proxy.$modal.closeLoading()
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
state.sureLoading = true
|
||||
let res = {} as any
|
||||
state.form.parentId = state.form.parentId && state.form.parentId > 0 ? state.form.parentId : undefined
|
||||
if (state.form.id != undefined && state.form.id > 0) {
|
||||
res = await new PermissionApi().updateGroup(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
} else {
|
||||
res = await new PermissionApi().addGroup(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
eventBus.emit('refreshPermission')
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
@ -1,296 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="600px"
|
||||
>
|
||||
<el-form :model="form" ref="formRef" label-width="80px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="所属平台">
|
||||
<el-select v-model="form.platform" disabled placeholder="请选择所属平台" class="w100">
|
||||
<el-option v-for="item in state.dictData[DictType.PlatForm.name]" :key="item.code" :label="item.name" :value="item.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="上级分组">
|
||||
<el-tree-select
|
||||
v-model="form.parentId"
|
||||
:data="permissionTreeData"
|
||||
node-key="id"
|
||||
check-strictly
|
||||
default-expand-all
|
||||
render-after-expand
|
||||
fit-input-width
|
||||
clearable
|
||||
class="w100"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="视图">
|
||||
<el-tree-select
|
||||
v-model="form.viewId"
|
||||
:data="state.viewTreeData"
|
||||
node-key="id"
|
||||
:props="{ label: 'path' }"
|
||||
default-expand-all
|
||||
render-after-expand
|
||||
fit-input-width
|
||||
clearable
|
||||
filterable
|
||||
:filter-node-method="onViewFilterNode"
|
||||
class="w100"
|
||||
@current-change="onViewCurrentChange"
|
||||
>
|
||||
<template #default="{ data }">
|
||||
<span class="my-flex my-flex-between">
|
||||
<span>{{ data.label }}</span>
|
||||
<span class="my-line-1 my-ml-12" :title="data.path">
|
||||
{{ data.path }}
|
||||
</span>
|
||||
</span>
|
||||
</template>
|
||||
</el-tree-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="名称" prop="label" :rules="[{ required: true, message: '请输入名称', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.label" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="路由地址" prop="path" :rules="[{ required: true, message: '请输入路由地址', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.path" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="路由命名">
|
||||
<el-input v-model="form.name" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="链接地址">
|
||||
<el-input v-model="form.link" clearable placeholder="内嵌/外链链接地址" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="图标" prop="icon">
|
||||
<my-select-icon v-model="form.icon" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="排序">
|
||||
<el-input-number v-model="form.sort" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="系统">
|
||||
<el-switch v-model="form.isSystem" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="启用">
|
||||
<el-switch v-model="form.enabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="内嵌窗口">
|
||||
<el-switch v-model="form.isIframe" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="缓存">
|
||||
<el-switch v-model="form.isKeepAlive" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="固定">
|
||||
<el-switch v-model="form.isAffix" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="隐藏">
|
||||
<el-switch v-model="form.hidden" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="新窗口">
|
||||
<el-switch v-model="form.newWindow" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="链接外显">
|
||||
<el-switch v-model="form.external" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/permission/permission-menu-form">
|
||||
import { reactive, toRefs, getCurrentInstance, ref, PropType, defineAsyncComponent, markRaw } from 'vue'
|
||||
import { PermissionGetListOutput, PermissionUpdateMenuInput, ViewGetListOutput, DictGetListOutput } from '/@/api/admin/data-contracts'
|
||||
import { PermissionApi } from '/@/api/admin/Permission'
|
||||
import { ViewApi } from '/@/api/admin/View'
|
||||
import { listToTree } from '/@/utils/tree'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { DictApi } from '/@/api/admin/Dict'
|
||||
|
||||
// 引入组件
|
||||
const MySelectIcon = defineAsyncComponent(() => import('/@/components/my-select-icon/index.vue'))
|
||||
|
||||
/** 字典分类 */
|
||||
const DictType = {
|
||||
PlatForm: { name: 'platform', desc: '平台' },
|
||||
}
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
permissionTreeData: {
|
||||
type: Array as PropType<PermissionGetListOutput[]>,
|
||||
default: () => [],
|
||||
},
|
||||
})
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const formRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
form: { enabled: true, isKeepAlive: true } as PermissionUpdateMenuInput,
|
||||
viewTreeData: [] as ViewGetListOutput[],
|
||||
dictData: {
|
||||
[DictType.PlatForm.name]: [] as DictGetListOutput[] | null,
|
||||
},
|
||||
})
|
||||
const { form } = toRefs(state)
|
||||
|
||||
const getDictList = async () => {
|
||||
const res = await new DictApi().getList([DictType.PlatForm.name]).catch(() => {})
|
||||
if (res?.success && res.data) {
|
||||
state.dictData = markRaw(res.data)
|
||||
}
|
||||
}
|
||||
|
||||
const getViews = async (platform: string) => {
|
||||
const res = await new ViewApi().getList({ platform: platform })
|
||||
if (res?.success && res.data && res.data.length > 0) {
|
||||
state.viewTreeData = listToTree(res.data) as ViewGetListOutput[]
|
||||
} else {
|
||||
state.viewTreeData = []
|
||||
}
|
||||
}
|
||||
|
||||
// 打开对话框
|
||||
const open = async (
|
||||
row: PermissionUpdateMenuInput = {
|
||||
id: 0,
|
||||
enabled: true,
|
||||
isKeepAlive: true,
|
||||
icon: 'ele-Memo',
|
||||
parentId: undefined,
|
||||
},
|
||||
isCopy = false
|
||||
) => {
|
||||
proxy.$modal.loading()
|
||||
|
||||
await getDictList()
|
||||
await getViews(row.platform as string)
|
||||
|
||||
if (row.id > 0) {
|
||||
const res = await new PermissionApi().getMenu({ id: row.id }).catch(() => {
|
||||
proxy.$modal.closeLoading()
|
||||
})
|
||||
|
||||
if (res?.success) {
|
||||
let formData = res.data as PermissionUpdateMenuInput
|
||||
formData.platform = row.platform
|
||||
formData.parentId = formData.parentId && formData.parentId > 0 ? formData.parentId : undefined
|
||||
if (isCopy) formData.id = 0
|
||||
state.form = formData
|
||||
}
|
||||
} else {
|
||||
state.form = row
|
||||
}
|
||||
|
||||
proxy.$modal.closeLoading()
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
const onViewFilterNode = (value: string, data: ViewGetListOutput) => {
|
||||
if (!value) return true
|
||||
return data.label?.indexOf(value) !== -1 || data.path?.indexOf(value) !== -1
|
||||
}
|
||||
|
||||
const onViewCurrentChange = (data: ViewGetListOutput) => {
|
||||
if (data) {
|
||||
if (!state.form.label) {
|
||||
state.form.label = data.label
|
||||
}
|
||||
if (!state.form.path) {
|
||||
state.form.path = '/' + data.path
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
state.sureLoading = true
|
||||
let res = {} as any
|
||||
state.form.parentId = state.form.parentId && state.form.parentId > 0 ? state.form.parentId : undefined
|
||||
if (state.form.id != undefined && state.form.id > 0) {
|
||||
res = await new PermissionApi().updateMenu(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
} else {
|
||||
res = await new PermissionApi().addMenu(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
eventBus.emit('refreshPermission')
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.my-ml-12 {
|
||||
margin-left: 12px;
|
||||
}
|
||||
</style>
|
||||
@ -1,312 +0,0 @@
|
||||
<template>
|
||||
<my-layout>
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" @submit.stop.prevent>
|
||||
<el-form-item label="平台">
|
||||
<el-select v-model="state.filter.platform" placeholder="平台" :empty-values="[null]" @change="onQuery" style="width: 100px">
|
||||
<el-option v-for="item in state.dictData[DictType.PlatForm.name]" :key="item.code" :label="item.name" :value="item.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="权限名称">
|
||||
<el-input v-model="state.filter.label" placeholder="权限名称" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
<el-dropdown
|
||||
v-auths="['api:admin:permission:addgroup', 'api:admin:permission:addmenu', 'api:admin:permission:adddot']"
|
||||
style="margin-left: 12px"
|
||||
>
|
||||
<el-button type="primary"
|
||||
>新增<el-icon class="el-icon--right"><ele-ArrowDown /></el-icon
|
||||
></el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item v-if="auth('api:admin:permission:addgroup')" @click="onAdd({ type: 1 })">新增分组</el-dropdown-item>
|
||||
<el-dropdown-item v-if="auth('api:admin:permission:addmenu')" @click="onAdd({ type: 2 })">新增菜单</el-dropdown-item>
|
||||
<el-dropdown-item v-if="auth('api:admin:permission:adddot')" @click="onAdd({ type: 3 })">新增权限点</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table
|
||||
:data="state.permissionTreeData"
|
||||
style="width: 100%"
|
||||
v-loading="state.loading"
|
||||
row-key="id"
|
||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
:expand-row-keys="state.expandRowKeys"
|
||||
border
|
||||
>
|
||||
<el-table-column prop="label" label="权限名称" width="240" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<SvgIcon :name="row.icon" style="vertical-align: -2px" />
|
||||
{{ row.label }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="type" label="类型" width="82" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ row.type === 1 ? '分组' : row.type === 2 ? '菜单' : row.type === 3 ? '权限点' : '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="path" label="权限地址" min-width="240" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<div v-if="row.type === 1 || row.type === 2">
|
||||
{{ row.path ? '路由地址:' + row.path : '' }}
|
||||
{{ row.viewPath ? '视图地址:' + row.viewPath : '' }}
|
||||
{{ row.redirect ? '重定向地址:' + row.redirect : '' }}
|
||||
{{ row.link ? '链接地址:' + row.link : '' }}
|
||||
</div>
|
||||
<div v-if="row.type === 3">接口地址:{{ row.apiPaths }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sort" label="排序" width="82" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="状态" width="82" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="success" v-if="row.enabled">启用</el-tag>
|
||||
<el-tag type="danger" v-else>禁用</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160" fixed="right" header-align="center" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
v-if="
|
||||
(row.type === 1 && auth('api:admin:permission:updategroup')) ||
|
||||
(row.type === 2 && auth('api:admin:permission:updatemenu')) ||
|
||||
(row.type === 3 && auth('api:admin:permission:updatedot'))
|
||||
"
|
||||
icon="ele-EditPen"
|
||||
text
|
||||
type="primary"
|
||||
@click="onEdit(row)"
|
||||
>编辑</el-button
|
||||
>
|
||||
<my-dropdown-more
|
||||
v-auths="[
|
||||
'api:admin:permission:delete',
|
||||
'api:admin:permission:addgroup',
|
||||
'api:admin:permission:addmenu',
|
||||
'api:admin:permission:adddot',
|
||||
]"
|
||||
>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item v-if="row.type === 1 && auth('api:admin:permission:addgroup')" @click="onAdd({ type: 1, parentId: row.id })">
|
||||
新增分组
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-if="row.type === 1 && auth('api:admin:permission:addmenu')" @click="onAdd({ type: 2, parentId: row.id })">
|
||||
新增菜单
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-if="row.type === 2 && auth('api:admin:permission:adddot')" @click="onAdd({ type: 3, parentId: row.id })">
|
||||
新增权限点
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-if="auth('api:admin:permission:delete')" @click="onDelete(row)">删除</el-dropdown-item>
|
||||
<el-dropdown-item v-if="row.type === 1 && auth('api:admin:permission:addgroup')" @click="onCopy(row)"> 复制 </el-dropdown-item>
|
||||
<el-dropdown-item v-if="row.type === 2 && auth('api:admin:permission:addmenu')" @click="onCopy(row)"> 复制 </el-dropdown-item>
|
||||
<el-dropdown-item v-if="row.type === 3 && auth('api:admin:permission:adddot')" @click="onCopy(row)"> 复制 </el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</my-dropdown-more>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<permission-group-form
|
||||
ref="permissionGroupFormRef"
|
||||
:title="state.permissionFormTitle"
|
||||
:permission-tree-data="state.formPermissionGroupTreeData"
|
||||
></permission-group-form>
|
||||
|
||||
<permission-menu-form
|
||||
ref="permissionMenuFormRef"
|
||||
:title="state.permissionFormTitle"
|
||||
:permission-tree-data="state.formPermissionGroupTreeData"
|
||||
></permission-menu-form>
|
||||
|
||||
<permission-dot-form
|
||||
ref="permissionDotFormRef"
|
||||
:title="state.permissionFormTitle"
|
||||
:permission-tree-data="state.formPermissionMenuTreeData"
|
||||
></permission-dot-form>
|
||||
</my-layout>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/permission">
|
||||
import { ref, reactive, onMounted, getCurrentInstance, onBeforeMount, defineAsyncComponent, markRaw } from 'vue'
|
||||
import { PermissionGetListOutput, PermissionGetListInput, DictGetListOutput } from '/@/api/admin/data-contracts'
|
||||
import { PermissionApi } from '/@/api/admin/Permission'
|
||||
import { listToTree, treeToList, filterTree } from '/@/utils/tree'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { auth } from '/@/utils/authFunction'
|
||||
import { DictApi } from '/@/api/admin/Dict'
|
||||
import { PlatformType } from '/@/api/admin.extend/enum-contracts'
|
||||
|
||||
// 引入组件
|
||||
const PermissionGroupForm = defineAsyncComponent(() => import('./components/permission-group-form.vue'))
|
||||
const PermissionMenuForm = defineAsyncComponent(() => import('./components/permission-menu-form.vue'))
|
||||
const PermissionDotForm = defineAsyncComponent(() => import('./components/permission-dot-form.vue'))
|
||||
const MyDropdownMore = defineAsyncComponent(() => import('/@/components/my-dropdown-more/index.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const DictType = {
|
||||
PlatForm: { name: 'platform', desc: '平台' },
|
||||
}
|
||||
|
||||
const permissionGroupFormRef = ref()
|
||||
const permissionMenuFormRef = ref()
|
||||
const permissionDotFormRef = ref()
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
permissionFormTitle: '',
|
||||
filter: {
|
||||
platform: PlatformType.Web.name,
|
||||
name: '',
|
||||
} as PermissionGetListInput,
|
||||
permissionTreeData: [] as Array<PermissionGetListOutput>,
|
||||
formPermissionGroupTreeData: [] as Array<PermissionGetListOutput>,
|
||||
formPermissionMenuTreeData: [] as Array<PermissionGetListOutput>,
|
||||
expandRowKeys: [] as string[],
|
||||
dictData: {
|
||||
[DictType.PlatForm.name]: [] as DictGetListOutput[] | null,
|
||||
},
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
await getDictList()
|
||||
await onQuery()
|
||||
state.expandRowKeys = treeToList(cloneDeep(state.permissionTreeData))
|
||||
.filter((a: PermissionGetListOutput) => a.opened === true)
|
||||
.map((a: PermissionGetListOutput) => a.id + '') as string[]
|
||||
eventBus.off('refreshPermission')
|
||||
eventBus.on('refreshPermission', async () => {
|
||||
onQuery()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshPermission')
|
||||
})
|
||||
|
||||
const getDictList = async () => {
|
||||
const res = await new DictApi().getList([DictType.PlatForm.name]).catch(() => {})
|
||||
if (res?.success && res.data) {
|
||||
state.dictData = markRaw(res.data)
|
||||
}
|
||||
}
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
const res = await new PermissionApi()
|
||||
.getList({
|
||||
platform: state.filter.platform,
|
||||
})
|
||||
.catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
if (res && res.data && res.data.length > 0) {
|
||||
const label = state.filter.label || ''
|
||||
state.permissionTreeData = filterTree(listToTree(cloneDeep(res.data)), '', {
|
||||
filterWhere: (item: any, keyword: string) => {
|
||||
return item.label?.toLocaleLowerCase().indexOf(label) > -1 || item.path?.toLocaleLowerCase().indexOf(label) > -1
|
||||
},
|
||||
})
|
||||
state.formPermissionGroupTreeData = listToTree(cloneDeep(res.data).filter((a: any) => a.type === 1))
|
||||
state.formPermissionMenuTreeData = listToTree(cloneDeep(res.data).filter((a: any) => a.type === 1 || a.type === 2))
|
||||
} else {
|
||||
state.permissionTreeData = []
|
||||
state.formPermissionGroupTreeData = []
|
||||
state.formPermissionMenuTreeData = []
|
||||
}
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onAdd = (row: PermissionGetListOutput) => {
|
||||
switch (row.type) {
|
||||
case 1:
|
||||
state.permissionFormTitle = '新增分组'
|
||||
permissionGroupFormRef.value.open({
|
||||
id: 0,
|
||||
platform: state.filter.platform,
|
||||
enabled: true,
|
||||
opened: true,
|
||||
icon: 'ele-Memo',
|
||||
parentId: row.parentId,
|
||||
})
|
||||
break
|
||||
case 2:
|
||||
state.permissionFormTitle = '新增菜单'
|
||||
permissionMenuFormRef.value.open({
|
||||
id: 0,
|
||||
platform: state.filter.platform,
|
||||
enabled: true,
|
||||
isKeepAlive: true,
|
||||
icon: 'ele-Memo',
|
||||
parentId: row.parentId,
|
||||
})
|
||||
break
|
||||
case 3:
|
||||
state.permissionFormTitle = '新增权限点'
|
||||
permissionDotFormRef.value.open({
|
||||
id: 0,
|
||||
platform: state.filter.platform,
|
||||
parentId: row.parentId,
|
||||
enabled: true,
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const onEdit = (row: PermissionGetListOutput) => {
|
||||
row.platform = state.filter.platform
|
||||
switch (row.type) {
|
||||
case 1:
|
||||
state.permissionFormTitle = '编辑分组'
|
||||
permissionGroupFormRef.value.open(row)
|
||||
break
|
||||
case 2:
|
||||
state.permissionFormTitle = '编辑菜单'
|
||||
permissionMenuFormRef.value.open(row)
|
||||
break
|
||||
case 3:
|
||||
state.permissionFormTitle = '编辑权限点'
|
||||
permissionDotFormRef.value.open(row)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const onCopy = (row: PermissionGetListOutput) => {
|
||||
switch (row.type) {
|
||||
case 1:
|
||||
state.permissionFormTitle = '新增分组'
|
||||
permissionGroupFormRef.value.open(row, true)
|
||||
break
|
||||
case 2:
|
||||
state.permissionFormTitle = '新增菜单'
|
||||
permissionMenuFormRef.value.open(row, true)
|
||||
break
|
||||
case 3:
|
||||
state.permissionFormTitle = '新增权限点'
|
||||
permissionDotFormRef.value.open(row, true)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const onDelete = (row: PermissionGetListOutput) => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要删除${row.type === 1 ? '分组' : row.type === 2 ? '菜单' : row.type === 3 ? '权限点' : ''}【${row.label}】?`)
|
||||
.then(async () => {
|
||||
await new PermissionApi().delete({ id: row.id }, { loading: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -1,140 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="475px"
|
||||
>
|
||||
<el-form ref="formRef" :model="form" label-width="80px" label-position="left">
|
||||
<el-row :gutter="35">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="旧密码" prop="oldPassword" :rules="[{ required: true, message: '请输入旧密码', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.oldPassword" show-password autocomplete="off" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item
|
||||
label="新密码"
|
||||
prop="newPassword"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入新密码', trigger: ['blur', 'change'] },
|
||||
{ validator: testNewPassword, trigger: ['blur', 'change'] },
|
||||
{ validator: validatorPwd, trigger: ['blur', 'change'] },
|
||||
]"
|
||||
>
|
||||
<el-input v-model="form.newPassword" show-password autocomplete="off" clearable @input="onInputNewPassword" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item
|
||||
label="确认密码"
|
||||
prop="confirmPassword"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入确认密码', trigger: ['blur', 'change'] },
|
||||
{ validator: testConfirmPassword, trigger: ['blur', 'change'] },
|
||||
]"
|
||||
>
|
||||
<el-input v-model="form.confirmPassword" show-password autocomplete="off" clearable @input="onInputConfirmPassword" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/personal/change-password-form">
|
||||
import { reactive, toRefs, ref } from 'vue'
|
||||
import { UserChangePasswordInput } from '/@/api/admin/data-contracts'
|
||||
import { UserApi } from '/@/api/admin/User'
|
||||
import { verifyCnAndSpace } from '/@/utils/toolsValidate'
|
||||
import { validatorPwd } from '/@/utils/validators'
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const formRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
form: {} as UserChangePasswordInput,
|
||||
})
|
||||
const { form } = toRefs(state)
|
||||
|
||||
// 新密码验证器
|
||||
const testNewPassword = (rule: any, value: any, callback: any) => {
|
||||
if (value) {
|
||||
if (state.form.confirmPassword) {
|
||||
formRef.value.validateField('confirmPassword')
|
||||
}
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
// 确认密码验证器
|
||||
const testConfirmPassword = (rule: any, value: any, callback: any) => {
|
||||
if (value) {
|
||||
if (value !== state.form.newPassword) {
|
||||
callback(new Error('确认密码和新密码不一致'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 输入新密码
|
||||
const onInputNewPassword = (val: string) => {
|
||||
state.form.newPassword = verifyCnAndSpace(val)
|
||||
}
|
||||
|
||||
// 输入确认密码
|
||||
const onInputConfirmPassword = (val: string) => {
|
||||
state.form.confirmPassword = verifyCnAndSpace(val)
|
||||
}
|
||||
|
||||
// 打开对话框
|
||||
const open = async () => {
|
||||
state.showDialog = true
|
||||
state.form = {} as UserChangePasswordInput
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
state.sureLoading = true
|
||||
const res = await new UserApi().changePassword(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
@ -1,411 +0,0 @@
|
||||
<template>
|
||||
<div class="personal layout-pd" v-loading="state.loading">
|
||||
<el-row>
|
||||
<!-- 个人信息 -->
|
||||
<el-col :xs="24" :sm="24">
|
||||
<el-card shadow="hover" header="个人信息">
|
||||
<div class="personal-user">
|
||||
<div class="personal-user-left">
|
||||
<el-upload
|
||||
class="h100 personal-user-left-upload"
|
||||
:action="avatarAction"
|
||||
:headers="avatarHeaders"
|
||||
:data="{ autoUpdate: true }"
|
||||
:show-file-list="false"
|
||||
:before-upload="
|
||||
() => {
|
||||
state.token = storesUserInfo.getToken()
|
||||
state.avatarLoading = true
|
||||
}
|
||||
"
|
||||
:on-success="onAvatarSuccess"
|
||||
:on-error="onAvatarError"
|
||||
>
|
||||
<img :src="avatar" />
|
||||
</el-upload>
|
||||
</div>
|
||||
<div class="personal-user-right">
|
||||
<el-row>
|
||||
<el-col :span="24" class="personal-title mb18">{{ currentTime }},{{ personalInfo.name }} </el-col>
|
||||
<el-col :span="24">
|
||||
<el-row>
|
||||
<el-col v-if="personalForm.nickName" :xs="24" :sm="8" class="personal-item mb6">
|
||||
<div class="personal-item-label">昵称:</div>
|
||||
<div class="personal-item-value">{{ personalInfo.nickName }}</div>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="16" class="personal-item mb6">
|
||||
<div class="personal-item-label">登录地区:</div>
|
||||
<div class="personal-item-value">
|
||||
{{ personalInfo.lastLoginCountry }} {{ personalInfo.lastLoginProvince }} {{ personalInfo.lastLoginCity }}
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-row>
|
||||
<el-col :xs="24" :sm="8" class="personal-item mb6">
|
||||
<div class="personal-item-label">登录IP:</div>
|
||||
<div class="personal-item-value">{{ personalInfo.lastLoginIP }}</div>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="16" class="personal-item mb6">
|
||||
<div class="personal-item-label">登录时间:</div>
|
||||
<div class="personal-item-value">{{ personalInfo.lastLoginTime }}</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<!-- 更新信息 -->
|
||||
<el-col :span="24">
|
||||
<el-card shadow="hover" class="mt15 personal-edit" header="更新信息">
|
||||
<div class="personal-edit-title">基本信息</div>
|
||||
<el-form ref="formRef" :model="personalForm" label-width="60px" class="mt35 mb35">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4">
|
||||
<el-form-item label="姓名" prop="name" :rules="[{ required: true, message: '请输入姓名', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="personalForm.name" placeholder="请输入姓名" clearable></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4">
|
||||
<el-form-item label="昵称">
|
||||
<el-input v-model="personalForm.nickName" placeholder="请输入昵称" clearable></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item>
|
||||
<el-popconfirm title="确定要更新个人信息吗?" hide-icon hide-after="0" width="180" @confirm="onUpdateBasic">
|
||||
<template #reference>
|
||||
<el-button :loading="state.updateLoading" type="primary">
|
||||
<el-icon>
|
||||
<ele-Position />
|
||||
</el-icon>
|
||||
更新个人信息
|
||||
</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<div class="personal-edit-safe-box">
|
||||
<div class="personal-edit-safe-item">
|
||||
<div class="personal-edit-safe-item-left">
|
||||
<div class="personal-edit-safe-item-left-label">密保手机</div>
|
||||
<div class="personal-edit-safe-item-left-value">已绑定手机:{{ personalInfo.mobile }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="personal-edit-safe-box">
|
||||
<div class="personal-edit-safe-item">
|
||||
<div class="personal-edit-safe-item-left">
|
||||
<div class="personal-edit-safe-item-left-label">密保邮箱</div>
|
||||
<div class="personal-edit-safe-item-left-value">已绑定邮箱:{{ personalInfo.email }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="admin/personal">
|
||||
import { reactive, computed, onMounted, toRefs, ref, getCurrentInstance, defineAsyncComponent } from 'vue'
|
||||
import { formatAxis } from '/@/utils/formatTime'
|
||||
import { UserApi } from '/@/api/admin/User'
|
||||
import { UserGetBasicOutput } from '/@/api/admin/data-contracts'
|
||||
import { useUserInfo } from '/@/stores/userInfo'
|
||||
import pinia from '/@/stores/index'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { AxiosResponse } from 'axios'
|
||||
|
||||
// 引入组件
|
||||
const ChangePasswordForm = defineAsyncComponent(() => import('./components/change-password-form.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
const changePasswordFormRef = ref()
|
||||
const formRef = ref()
|
||||
const storesUserInfo = useUserInfo(pinia)
|
||||
const { userInfos } = storeToRefs(storesUserInfo)
|
||||
|
||||
// 定义变量内容
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
newsInfoList: [] as any,
|
||||
recommendList: [] as any,
|
||||
personalInfo: {
|
||||
avatar: '',
|
||||
mobile: '',
|
||||
email: '',
|
||||
name: '',
|
||||
nickName: '',
|
||||
} as UserGetBasicOutput,
|
||||
personalForm: {
|
||||
name: '',
|
||||
nickName: '',
|
||||
},
|
||||
avatarLoading: false,
|
||||
updateLoading: false,
|
||||
token: storesUserInfo.getToken(),
|
||||
})
|
||||
|
||||
const { personalInfo, personalForm } = toRefs(state)
|
||||
|
||||
// 当前时间提示语
|
||||
const currentTime = computed(() => {
|
||||
return formatAxis(new Date())
|
||||
})
|
||||
|
||||
// 上传头像请求头部
|
||||
const avatarHeaders = computed(() => {
|
||||
return { Authorization: 'Bearer ' + state.token }
|
||||
})
|
||||
|
||||
// 头像地址
|
||||
const avatar = computed(() => {
|
||||
return userInfos.value.photo || 'https://img2.baidu.com/it/u=1978192862,2048448374&fm=253&fmt=auto&app=138&f=JPEG?w=504&h=500'
|
||||
})
|
||||
|
||||
// 上传头像请求url
|
||||
const avatarAction = computed(() => {
|
||||
return import.meta.env.VITE_API_URL + '/api/admin/user/avatar-upload'
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
initData()
|
||||
})
|
||||
|
||||
// 初始化数据
|
||||
const initData = async () => {
|
||||
state.loading = true
|
||||
const res = await new UserApi().getBasic().catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
if (res?.success) {
|
||||
state.personalForm.name = res.data?.name as string
|
||||
state.personalForm.nickName = res.data?.nickName as string
|
||||
state.personalInfo = res.data as UserGetBasicOutput
|
||||
}
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
// 上传头像成功
|
||||
const onAvatarSuccess = (res: AxiosResponse) => {
|
||||
state.avatarLoading = false
|
||||
if (!res?.success) {
|
||||
if (res.msg) {
|
||||
proxy.$modal.msgError(res.msg)
|
||||
}
|
||||
return
|
||||
}
|
||||
state.personalInfo.avatar = res.data
|
||||
storesUserInfo.setPhoto(res.data)
|
||||
}
|
||||
|
||||
// 上传头像失败
|
||||
const onAvatarError = (error: any) => {
|
||||
state.avatarLoading = false
|
||||
let message = ''
|
||||
if (error.message) {
|
||||
try {
|
||||
message = JSON.parse(error.message)?.msg
|
||||
} catch (err) {
|
||||
message = error.message || ''
|
||||
}
|
||||
}
|
||||
if (message) proxy.$modal.msgError(message)
|
||||
}
|
||||
|
||||
// 更新个人信息
|
||||
const onUpdateBasic = async () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
state.updateLoading = true
|
||||
const res = await new UserApi().updateBasic(state.personalForm, { showSuccessMessage: true }).catch(() => {
|
||||
state.updateLoading = false
|
||||
})
|
||||
state.updateLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
state.personalInfo.nickName = state.personalForm.nickName
|
||||
state.personalInfo.name = state.personalForm.name
|
||||
storesUserInfo.setUserName(state.personalForm.nickName || state.personalForm.name)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 修改密码
|
||||
const onChangePassword = () => {
|
||||
changePasswordFormRef.value.open()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use '/@/theme/mixins/index.scss' as *;
|
||||
.personal {
|
||||
.personal-user {
|
||||
height: 130px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.personal-user-left {
|
||||
width: 100px;
|
||||
height: 130px;
|
||||
border-radius: 3px;
|
||||
:deep(.el-upload) {
|
||||
height: 100%;
|
||||
}
|
||||
.personal-user-left-upload {
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 3px;
|
||||
}
|
||||
&:hover {
|
||||
img {
|
||||
animation: logoAnimation 0.3s ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.personal-user-right {
|
||||
flex: 1;
|
||||
padding: 0 15px;
|
||||
.personal-title {
|
||||
font-size: 18px;
|
||||
@include text-ellipsis(1);
|
||||
}
|
||||
.personal-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 13px;
|
||||
.personal-item-label {
|
||||
color: var(--el-text-color-secondary);
|
||||
@include text-ellipsis(1);
|
||||
}
|
||||
.personal-item-value {
|
||||
@include text-ellipsis(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.personal-info {
|
||||
.personal-info-more {
|
||||
float: right;
|
||||
color: var(--el-text-color-secondary);
|
||||
font-size: 13px;
|
||||
&:hover {
|
||||
color: var(--el-color-primary);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.personal-info-box {
|
||||
height: 130px;
|
||||
overflow: hidden;
|
||||
.personal-info-ul {
|
||||
list-style: none;
|
||||
.personal-info-li {
|
||||
font-size: 13px;
|
||||
padding-bottom: 10px;
|
||||
.personal-info-li-title {
|
||||
display: inline-block;
|
||||
@include text-ellipsis(1);
|
||||
color: var(--el-text-color-secondary);
|
||||
text-decoration: none;
|
||||
}
|
||||
& a:hover {
|
||||
color: var(--el-color-primary);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.personal-recommend-row {
|
||||
.personal-recommend-col {
|
||||
.personal-recommend {
|
||||
position: relative;
|
||||
height: 100px;
|
||||
border-radius: 3px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
i {
|
||||
right: 0px !important;
|
||||
bottom: 0px !important;
|
||||
transition: all ease 0.3s;
|
||||
}
|
||||
}
|
||||
i {
|
||||
position: absolute;
|
||||
right: -10px;
|
||||
bottom: -10px;
|
||||
font-size: 70px;
|
||||
transform: rotate(-30deg);
|
||||
transition: all ease 0.3s;
|
||||
}
|
||||
.personal-recommend-auto {
|
||||
padding: 15px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 5%;
|
||||
color: var(--next-color-white);
|
||||
.personal-recommend-msg {
|
||||
font-size: 12px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.personal-edit {
|
||||
.personal-edit-title {
|
||||
position: relative;
|
||||
padding-left: 10px;
|
||||
color: var(--el-text-color-regular);
|
||||
&::after {
|
||||
content: '';
|
||||
width: 2px;
|
||||
height: 10px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
.personal-edit-safe-box {
|
||||
border-bottom: 1px solid var(--el-border-color-light, #ebeef5);
|
||||
padding: 15px 0;
|
||||
.personal-edit-safe-item {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.personal-edit-safe-item-left {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
.personal-edit-safe-item-left-label {
|
||||
color: var(--el-text-color-regular);
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.personal-edit-safe-item-left-value {
|
||||
color: var(--el-text-color-secondary);
|
||||
@include text-ellipsis(1);
|
||||
margin-right: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
&:last-of-type {
|
||||
padding-bottom: 0;
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,125 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="600px"
|
||||
>
|
||||
<el-form :model="form" ref="formRef" label-width="80px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="名称" prop="name" :rules="[{ required: true, message: '请输入名称', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.name" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="编码" prop="code">
|
||||
<el-input v-model="form.code" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="排序">
|
||||
<el-input-number v-model="form.sort" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="启用">
|
||||
<el-switch v-model="form.enabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="说明">
|
||||
<el-input v-model="form.description" clearable type="textarea" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/pkg/form">
|
||||
import { reactive, toRefs, ref } from 'vue'
|
||||
import { PkgUpdateInput } from '/@/api/admin/data-contracts'
|
||||
import { PkgApi } from '/@/api/admin/Pkg'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const formRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
form: {} as PkgUpdateInput,
|
||||
})
|
||||
|
||||
const { form } = toRefs(state)
|
||||
|
||||
// 打开对话框
|
||||
const open = async (row: PkgUpdateInput = { id: 0 }) => {
|
||||
let formData = cloneDeep(row) as PkgUpdateInput
|
||||
if (row.id > 0) {
|
||||
const res = await new PkgApi().get({ id: row.id }, { loading: true })
|
||||
|
||||
if (res?.success) {
|
||||
formData = res.data as PkgUpdateInput
|
||||
formData.parentId = formData.parentId && formData.parentId > 0 ? formData.parentId : undefined
|
||||
}
|
||||
}
|
||||
|
||||
state.form = formData
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
state.sureLoading = true
|
||||
let res = {} as any
|
||||
state.form.parentId = state.form.parentId && state.form.parentId > 0 ? state.form.parentId : undefined
|
||||
if (state.form.id != undefined && state.form.id > 0) {
|
||||
res = await new PkgApi().update(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
} else {
|
||||
res = await new PkgApi().add(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
eventBus.emit('refreshPkg')
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
@ -1,217 +0,0 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="innerTitle"
|
||||
append-to-body
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="780px"
|
||||
>
|
||||
<template #header="{ close, titleId, titleClass }">
|
||||
<div class="my-header">
|
||||
<div :id="titleId" :class="titleClass">
|
||||
设置{{ innerTitle }}
|
||||
<el-select v-model="state.platform" placeholder="请选择所属平台" style="width: 100px" @change="onQuery">
|
||||
<el-option v-for="item in state.dictData[DictType.PlatForm.name]" :key="item.code" :label="item.name" :value="item.code" />
|
||||
</el-select>
|
||||
菜单权限
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div>
|
||||
<el-tree
|
||||
ref="permissionTreeRef"
|
||||
:data="state.permissionTreeData"
|
||||
node-key="id"
|
||||
show-checkbox
|
||||
highlight-current
|
||||
default-expand-all
|
||||
check-on-click-node
|
||||
:expand-on-click-node="false"
|
||||
:props="{ class: customNodeClass }"
|
||||
:default-checked-keys="state.checkedKeys"
|
||||
/>
|
||||
</div>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/pkg/components/set-pkg-menu">
|
||||
import { ref, reactive, getCurrentInstance, computed, markRaw } from 'vue'
|
||||
import { PkgGetListOutput, PkgSetPkgPermissionsInput, DictGetListOutput, PermissionGetPermissionListOutput } from '/@/api/admin/data-contracts'
|
||||
import { PkgApi } from '/@/api/admin/Pkg'
|
||||
import { PermissionApi } from '/@/api/admin/Permission'
|
||||
import { ElTree } from 'element-plus'
|
||||
import { DictApi } from '/@/api/admin/Dict'
|
||||
import { PlatformType } from '/@/api/admin.extend/enum-contracts'
|
||||
|
||||
/** 字典分类 */
|
||||
const DictType = {
|
||||
PlatForm: { name: 'platform', desc: '平台' },
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const innerTitle = computed(() => {
|
||||
return props.title ? props.title : state.pkgName ? `设置【${state.pkgName}】菜单权限` : '设置菜单权限'
|
||||
})
|
||||
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
loading: false,
|
||||
sureLoading: false,
|
||||
permissionTreeData: [] as PermissionGetPermissionListOutput[],
|
||||
pkgId: 0 as number | undefined,
|
||||
pkgName: '' as string | undefined | null,
|
||||
checkedKeys: [],
|
||||
platform: PlatformType.Web.name,
|
||||
dictData: {
|
||||
[DictType.PlatForm.name]: [] as DictGetListOutput[] | null,
|
||||
},
|
||||
})
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
const permissionTreeRef = ref<InstanceType<typeof ElTree>>()
|
||||
|
||||
const getDictList = async () => {
|
||||
const res = await new DictApi().getList([DictType.PlatForm.name]).catch(() => {})
|
||||
if (res?.success && res.data) {
|
||||
state.dictData = markRaw(res.data)
|
||||
}
|
||||
}
|
||||
|
||||
const getPkgPermissionList = async () => {
|
||||
const res = await new PkgApi().getPkgPermissionList({ pkgId: state.pkgId })
|
||||
state.checkedKeys = res?.success ? (res.data as never[]) : []
|
||||
}
|
||||
|
||||
// 打开对话框
|
||||
const open = async (pkg: PkgGetListOutput) => {
|
||||
await getDictList()
|
||||
state.pkgId = pkg.id
|
||||
state.pkgName = pkg.name
|
||||
proxy.$modal.loading()
|
||||
await onQuery()
|
||||
await getPkgPermissionList()
|
||||
proxy.$modal.closeLoading()
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
// 关闭对话框
|
||||
const close = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
|
||||
const res = await new PermissionApi().getPermissionList({ platform: state.platform }).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
if (res && res.data && res.data.length > 0) {
|
||||
state.permissionTreeData = res.data
|
||||
} else {
|
||||
state.permissionTreeData = []
|
||||
}
|
||||
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const customNodeClass = (data: any, node: any) => {
|
||||
let isPenultimate = true
|
||||
for (const key in data.children) {
|
||||
if (data.children[key]?.children?.length ?? 0 > 0) {
|
||||
isPenultimate = false
|
||||
break
|
||||
}
|
||||
}
|
||||
return data.children?.length > 0 && isPenultimate ? `is-penultimate level${node.level}` : ''
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = async () => {
|
||||
state.sureLoading = true
|
||||
const permissionIds = permissionTreeRef.value?.getCheckedKeys(true)
|
||||
const input = {
|
||||
platform: state.platform,
|
||||
pkgId: state.pkgId,
|
||||
permissionIds: permissionIds,
|
||||
} as PkgSetPkgPermissionsInput
|
||||
const res = await new PkgApi().setPkgPermissions(input, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
state.showDialog = false
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
close,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-dialog__body) {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
:deep(.is-penultimate) {
|
||||
.el-tree-node__children {
|
||||
padding-left: 65px;
|
||||
white-space: pre-wrap;
|
||||
line-height: 100%;
|
||||
|
||||
.el-tree-node {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.el-tree-node__content {
|
||||
padding-left: 12px !important;
|
||||
padding-right: 12px;
|
||||
|
||||
.el-tree-node__expand-icon.is-leaf {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.level1 {
|
||||
.el-tree-node__children {
|
||||
padding-left: 36px;
|
||||
}
|
||||
}
|
||||
&.level2 {
|
||||
.el-tree-node__children {
|
||||
padding-left: 54x;
|
||||
}
|
||||
}
|
||||
&.level3 {
|
||||
.el-tree-node__children {
|
||||
padding-left: 72px;
|
||||
}
|
||||
}
|
||||
&.level4 {
|
||||
.el-tree-node__children {
|
||||
padding-left: 90px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,338 +0,0 @@
|
||||
<template>
|
||||
<MySplitPanes>
|
||||
<pane size="50" min-size="30" max-size="70">
|
||||
<div class="my-flex-column w100 h100">
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" @submit.stop.prevent>
|
||||
<el-form-item label="套餐名">
|
||||
<el-input v-model="state.filter.pkgName" placeholder="套餐名" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:pkg:add'" type="primary" icon="ele-Plus" @click="onAdd"> 新增 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table
|
||||
ref="pkgTableRef"
|
||||
v-loading="state.loading"
|
||||
:data="state.pkgData"
|
||||
default-expand-all
|
||||
highlight-current-row
|
||||
style="width: 100%"
|
||||
border
|
||||
@current-change="onTableCurrentChange"
|
||||
>
|
||||
<el-table-column prop="name" label="套餐名" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="sort" label="排序" width="82" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="100" fixed="right" header-align="center" align="center">
|
||||
<template #default="{ row }">
|
||||
<my-dropdown-more
|
||||
v-auths="['api:admin:pkg:set-pkg-permissions', 'api:admin:pkg:update', 'api:admin:pkg:delete']"
|
||||
style="margin-left: 0px"
|
||||
>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item v-if="auth('api:admin:pkg:set-pkg-permissions')" @click="onSetPkgMenu(row)">菜单权限</el-dropdown-item>
|
||||
<el-dropdown-item v-if="auth('api:admin:pkg:update')" @click="onEdit(row)">编辑套餐</el-dropdown-item>
|
||||
<el-dropdown-item v-if="auth('api:admin:pkg:delete')" @click="onDelete(row)">删除套餐</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</my-dropdown-more>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="my-flex my-flex-end" style="margin-top: 10px">
|
||||
<el-pagination
|
||||
v-model:currentPage="state.pageInput.currentPage"
|
||||
v-model:page-size="state.pageInput.pageSize"
|
||||
:total="state.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
background
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</pane>
|
||||
<pane>
|
||||
<div class="my-flex-column w100 h100">
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" @submit.stop.prevent>
|
||||
<el-form-item label="企业名">
|
||||
<el-input v-model="state.filter.name" placeholder="企业名" @keyup.enter="onGetPkgTenantList" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onGetPkgTenantList"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:pkg:add-pkg-tenant'" type="primary" icon="ele-Plus" @click="onAddTenant"> 添加企业 </el-button>
|
||||
<el-button v-auth="'api:admin:pkg:remove-pkg-tenant'" type="danger" icon="ele-Delete" @click="onRemoveTenant"> 移除企业 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table
|
||||
ref="tenantTableRef"
|
||||
v-loading="state.tenantListLoading"
|
||||
:data="state.tenantData"
|
||||
row-key="id"
|
||||
style="width: 100%"
|
||||
border
|
||||
@row-click="onTenantRowClick"
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="name" label="企业名" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="code" label="企业编码" min-width="120" show-overflow-tooltip />
|
||||
</el-table>
|
||||
<div class="my-flex my-flex-end" style="margin-top: 10px">
|
||||
<el-pagination
|
||||
v-model:currentPage="state.tenantPageInput.currentPage"
|
||||
v-model:page-size="state.tenantPageInput.pageSize"
|
||||
:total="state.tenantTotal"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
background
|
||||
@size-change="onTenantSizeChange"
|
||||
@current-change="onTenantCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</pane>
|
||||
|
||||
<pkg-form ref="pkgFormRef" :title="state.pkgFormTitle"></pkg-form>
|
||||
<tenant-select
|
||||
ref="tenantSelectRef"
|
||||
:title="`添加【${state.pkgName}】企业`"
|
||||
multiple
|
||||
:sure-loading="state.sureLoading"
|
||||
@sure="onSureTenant"
|
||||
></tenant-select>
|
||||
<set-pkg-menu ref="setPkgMenuRef"></set-pkg-menu>
|
||||
</MySplitPanes>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/pkg">
|
||||
import { ref, reactive, onMounted, getCurrentInstance, onBeforeMount, nextTick, defineAsyncComponent } from 'vue'
|
||||
import {
|
||||
PageInputPkgGetPageInput,
|
||||
PkgGetPkgTenantListOutput,
|
||||
PkgGetPageOutput,
|
||||
PkgAddPkgTenantListInput,
|
||||
PageInputPkgGetPkgTenantListInput,
|
||||
} from '/@/api/admin/data-contracts'
|
||||
import { PkgApi } from '/@/api/admin/Pkg'
|
||||
import { ElTable } from 'element-plus'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { auth } from '/@/utils/authFunction'
|
||||
import { Pane } from 'splitpanes'
|
||||
|
||||
// 引入组件
|
||||
const PkgForm = defineAsyncComponent(() => import('./components/pkg-form.vue'))
|
||||
const SetPkgMenu = defineAsyncComponent(() => import('./components/set-pkg-menu.vue'))
|
||||
const TenantSelect = defineAsyncComponent(() => import('/@/views/admin/tenant/components/tenant-select.vue'))
|
||||
const MyDropdownMore = defineAsyncComponent(() => import('/@/components/my-dropdown-more/index.vue'))
|
||||
const MySplitPanes = defineAsyncComponent(() => import('/@/components/my-layout/split-panes.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const pkgTableRef = ref()
|
||||
const pkgFormRef = ref()
|
||||
const tenantTableRef = ref<InstanceType<typeof ElTable>>()
|
||||
const tenantSelectRef = ref()
|
||||
const setPkgMenuRef = ref()
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
tenantListLoading: false,
|
||||
sureLoading: false,
|
||||
pkgFormTitle: '',
|
||||
filter: {
|
||||
name: '',
|
||||
pkgName: '',
|
||||
},
|
||||
total: 0,
|
||||
pageInput: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
filter: {
|
||||
name: '',
|
||||
},
|
||||
} as PageInputPkgGetPageInput,
|
||||
pkgData: [] as any,
|
||||
tenantPageInput: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
filter: {
|
||||
pkgId: null,
|
||||
tenantName: '',
|
||||
},
|
||||
} as PageInputPkgGetPkgTenantListInput,
|
||||
tenantData: [] as PkgGetPkgTenantListOutput[],
|
||||
tenantTotal: 0,
|
||||
pkgId: undefined as number | undefined,
|
||||
pkgName: '' as string | null | undefined,
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
onQuery()
|
||||
eventBus.off('refreshPkg')
|
||||
eventBus.on('refreshPkg', async () => {
|
||||
onQuery()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshPkg')
|
||||
})
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
if (state.pageInput.filter) state.pageInput.filter.name = state.filter.pkgName
|
||||
const res = await new PkgApi().getPage(state.pageInput).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
|
||||
state.pkgData = res?.data?.list ?? []
|
||||
state.total = res?.data?.total ?? 0
|
||||
|
||||
if (state.pkgData?.length > 0) {
|
||||
nextTick(() => {
|
||||
pkgTableRef.value!.setCurrentRow(state.pkgData[0])
|
||||
})
|
||||
}
|
||||
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onSizeChange = (val: number) => {
|
||||
state.pageInput.currentPage = 1
|
||||
state.pageInput.pageSize = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onCurrentChange = (val: number) => {
|
||||
state.pageInput.currentPage = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onTableCurrentChange = (currentRow: PkgGetPageOutput) => {
|
||||
if (!currentRow) {
|
||||
return
|
||||
}
|
||||
|
||||
state.pkgId = currentRow.id
|
||||
state.pkgName = currentRow.name
|
||||
onGetPkgTenantList()
|
||||
}
|
||||
|
||||
const onAdd = () => {
|
||||
state.pkgFormTitle = '新增套餐'
|
||||
pkgFormRef.value.open({ enabled: true })
|
||||
}
|
||||
|
||||
const onEdit = (row: PkgGetPageOutput) => {
|
||||
state.pkgFormTitle = '编辑套餐'
|
||||
pkgFormRef.value.open(row)
|
||||
}
|
||||
|
||||
const onDelete = (row: PkgGetPageOutput) => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要删除套餐【${row.name}】?`)
|
||||
.then(async () => {
|
||||
await new PkgApi().delete({ id: row.id }, { loading: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onGetPkgTenantList = async () => {
|
||||
state.tenantListLoading = true
|
||||
state.tenantPageInput.filter = { pkgId: state.pkgId, tenantName: state.filter.name }
|
||||
const res = await new PkgApi().getPkgTenantPage(state.tenantPageInput).catch(() => {
|
||||
state.tenantListLoading = false
|
||||
})
|
||||
state.tenantListLoading = false
|
||||
if (res?.success) {
|
||||
state.tenantData = res?.data?.list ?? []
|
||||
state.tenantTotal = res?.data?.total ?? 0
|
||||
}
|
||||
}
|
||||
|
||||
const onTenantSizeChange = (val: number) => {
|
||||
state.tenantPageInput.pageSize = val
|
||||
onGetPkgTenantList()
|
||||
}
|
||||
|
||||
const onTenantCurrentChange = (val: number) => {
|
||||
state.tenantPageInput.currentPage = val
|
||||
onGetPkgTenantList()
|
||||
}
|
||||
|
||||
const onTenantRowClick = (row: PkgGetPkgTenantListOutput) => {
|
||||
tenantTableRef.value!.toggleRowSelection(row, undefined)
|
||||
}
|
||||
|
||||
const onAddTenant = () => {
|
||||
if (!((state.pkgId as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择套餐')
|
||||
return
|
||||
}
|
||||
tenantSelectRef.value.open({ pkgId: state.pkgId })
|
||||
}
|
||||
|
||||
const onRemoveTenant = () => {
|
||||
if (!((state.pkgId as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择套餐')
|
||||
return
|
||||
}
|
||||
|
||||
const selectionRows = tenantTableRef.value!.getSelectionRows() as PkgGetPageOutput[]
|
||||
|
||||
if (!((selectionRows.length as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择租户')
|
||||
return
|
||||
}
|
||||
|
||||
proxy.$modal
|
||||
.confirm(`确定要移除吗?`)
|
||||
.then(async () => {
|
||||
const tenantIds = selectionRows?.map((a) => a.id)
|
||||
const input = { pkgId: state.pkgId, tenantIds } as PkgAddPkgTenantListInput
|
||||
await new PkgApi().removePkgTenant(input, { loading: true })
|
||||
onGetPkgTenantList()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onSureTenant = async (tenants: PkgGetPageOutput[]) => {
|
||||
if (!(tenants?.length > 0)) {
|
||||
tenantSelectRef.value.close()
|
||||
return
|
||||
}
|
||||
|
||||
state.sureLoading = true
|
||||
const tenantIds = tenants?.map((a) => a.id)
|
||||
const input = { pkgId: state.pkgId, tenantIds } as PkgAddPkgTenantListInput
|
||||
await new PkgApi().addPkgTenant(input, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
state.sureLoading = false
|
||||
tenantSelectRef.value.close()
|
||||
onGetPkgTenantList()
|
||||
}
|
||||
|
||||
const onSetPkgMenu = (pkg: PkgGetPageOutput) => {
|
||||
if (!((pkg?.id as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择套餐')
|
||||
return
|
||||
}
|
||||
setPkgMenuRef.value.open(pkg)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -1,236 +0,0 @@
|
||||
<template>
|
||||
<el-drawer v-model="state.visible" direction="ltr" destroy-on-close size="100%" @closed="onClosed">
|
||||
<template #header="{ titleId, titleClass }">
|
||||
<div class="my-flex my-flex-between mr10">
|
||||
<span :id="titleId" :class="titleClass">{{ title }}</span>
|
||||
<div>
|
||||
<el-button ref="saveRef" type="primary" round :loading="state.saveLoading">
|
||||
<template #icon>
|
||||
<el-icon>
|
||||
<my-icon name="save" color="var(--color)"></my-icon>
|
||||
</el-icon>
|
||||
</template>
|
||||
保存
|
||||
</el-button>
|
||||
<el-popover ref="popoverSaveRef" placement="bottom-end" :virtual-ref="saveRef" trigger="click" virtual-triggering width="auto" title="提示">
|
||||
<p class="my-flex my-flex-items-center">
|
||||
<SvgIcon name="ele-Warning" size="16" color="var(--el-color-warning)" class="mr5" />
|
||||
确定要保存设计模板吗?
|
||||
</p>
|
||||
<div class="mt10" style="text-align: right; margin: 0">
|
||||
<el-button text @click="onSaveCancel">取消</el-button>
|
||||
<el-button type="primary" @click="onSave"> 保存并关闭 </el-button>
|
||||
<el-button type="primary" @click="onSave(false)"> 保存 </el-button>
|
||||
</div>
|
||||
</el-popover>
|
||||
|
||||
<el-tooltip content="刷新" placement="bottom">
|
||||
<el-button ref="refreshRef" link>
|
||||
<template #icon>
|
||||
<el-icon size="18px">
|
||||
<ele-Refresh></ele-Refresh>
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-popover ref="popoverRefreshRef" placement="bottom" :virtual-ref="refreshRef" trigger="click" virtual-triggering :width="230">
|
||||
<p class="my-flex my-flex-items-center">确定要刷新设计模板吗?</p>
|
||||
<div class="mt10" style="text-align: right; margin: 0">
|
||||
<el-button text @click="onRefreshCancel">取消</el-button>
|
||||
<el-button type="primary" @click="onRefresh">确定</el-button>
|
||||
</div>
|
||||
</el-popover>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<Design ref="designRef" :title="title" v-model:printData="state.printTemplate.printData"></Design>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/print-template-deisgn">
|
||||
import { reactive, ref, getCurrentInstance, nextTick } from 'vue'
|
||||
import Design from './design.vue'
|
||||
import { PrintTemplateGetPageOutput } from '/@/api/admin/data-contracts'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { PrintTemplateApi } from '/@/api/admin/PrintTemplate'
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const designRef = ref()
|
||||
const saveRef = ref()
|
||||
const popoverSaveRef = ref()
|
||||
const refreshRef = ref()
|
||||
const popoverRefreshRef = ref()
|
||||
|
||||
const state = reactive({
|
||||
visible: false,
|
||||
saveLoading: false,
|
||||
refreshLoading: false,
|
||||
printTemplate: {
|
||||
id: 0,
|
||||
version: 0,
|
||||
printData: '{}',
|
||||
},
|
||||
})
|
||||
|
||||
const loadData = async () => {
|
||||
if (state.printTemplate.id > 0) {
|
||||
state.refreshLoading = true
|
||||
const res = await new PrintTemplateApi().getUpdateTemplate({ id: state.printTemplate.id }).catch(() => {
|
||||
state.refreshLoading = false
|
||||
})
|
||||
state.refreshLoading = false
|
||||
if (res?.success) {
|
||||
const printTemplate = res.data
|
||||
state.printTemplate.id = printTemplate?.id as number
|
||||
state.printTemplate.version = printTemplate?.version as number
|
||||
state.printTemplate.printData = printTemplate?.printData || ('{}' as string)
|
||||
|
||||
nextTick(() => {
|
||||
designRef.value?.hiprintTemplate.clear()
|
||||
const template = JSON.parse(printTemplate?.template || '{}')
|
||||
designRef.value?.hiprintTemplate.update(template)
|
||||
designRef.value?.setPaper(template)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const onSaveCancel = () => {
|
||||
popoverSaveRef.value?.hide?.()
|
||||
}
|
||||
|
||||
const onRefreshCancel = () => {
|
||||
popoverRefreshRef.value?.hide?.()
|
||||
}
|
||||
|
||||
const onRefresh = () => {
|
||||
onRefreshCancel()
|
||||
loadData()
|
||||
}
|
||||
|
||||
//保存
|
||||
const onSave = async (close = true) => {
|
||||
try {
|
||||
if (designRef.value?.hiprintTemplate) {
|
||||
if (state.printTemplate.id != undefined && state.printTemplate.id > 0) {
|
||||
state.saveLoading = true
|
||||
const res = await new PrintTemplateApi()
|
||||
.updateTemplate(
|
||||
{
|
||||
id: state.printTemplate.id,
|
||||
version: state.printTemplate.version,
|
||||
template: JSON.stringify(designRef.value?.hiprintTemplate.getJson() || {}),
|
||||
printData: state.printTemplate.printData as string,
|
||||
},
|
||||
{ showSuccessMessage: true }
|
||||
)
|
||||
.catch(() => {
|
||||
state.saveLoading = false
|
||||
})
|
||||
|
||||
state.printTemplate.version = state.printTemplate.version + 1
|
||||
state.saveLoading = false
|
||||
onSaveCancel()
|
||||
if (res?.success) {
|
||||
eventBus.emit('refreshPrintTemplate')
|
||||
if (close) state.visible = false
|
||||
}
|
||||
} else {
|
||||
proxy.$modal.msgWarning('请选择打印模板')
|
||||
}
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
// 打开对话框
|
||||
const open = async (row: PrintTemplateGetPageOutput = {}) => {
|
||||
state.visible = true
|
||||
|
||||
state.printTemplate.id = row.id as number
|
||||
await loadData()
|
||||
}
|
||||
|
||||
// 关闭
|
||||
const onClosed = () => {
|
||||
state.visible = false
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep() {
|
||||
.left-box {
|
||||
.el-tabs__header {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.el-tab-pane {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.rect-printElement-types .hiprint-printElement-type a.ep-draggable-item {
|
||||
height: auto;
|
||||
color: #666;
|
||||
box-shadow: none !important;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.hiprint-printElement-type a.ep-draggable-item:before {
|
||||
display: block;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
content: '';
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.hline']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/hline.svg');
|
||||
}
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.vline']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/vline.svg');
|
||||
}
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.rect']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/rect.svg');
|
||||
}
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.oval']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/oval.svg');
|
||||
}
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.barcode']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/barcode.svg');
|
||||
}
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.qrcode']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/qrcode.svg');
|
||||
}
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.text']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/text.svg');
|
||||
}
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.longText']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/longText.svg');
|
||||
}
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.table']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/table.svg');
|
||||
}
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.emptyTable']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/emptyTable.svg');
|
||||
}
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.html']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/html.svg');
|
||||
}
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.image']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/image.svg');
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,594 +0,0 @@
|
||||
<template>
|
||||
<div class="h100 w100 my-design" style="position: relative">
|
||||
<div class="my-flex w100 h100">
|
||||
<div style="width: 220px; min-width: 220px; border-right: 1px solid var(--el-border-color)">
|
||||
<el-tabs tab-position="top" stretch class="h100 left-box">
|
||||
<el-tab-pane label="组件">
|
||||
<el-scrollbar height="100%" max-height="100%" :always="false" wrap-style="padding:10px">
|
||||
<!-- 拖拽组件 -->
|
||||
<div ref="epContainerRef" class="rect-printElement-types hiprintEpContainer"></div>
|
||||
</el-scrollbar>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="数据源">
|
||||
<MyJsonEditor
|
||||
v-model="printData"
|
||||
:options="{
|
||||
mode: 'text',
|
||||
mainMenuBar: true,
|
||||
statusBar: false,
|
||||
showErrorTable: false,
|
||||
modes: [],
|
||||
}"
|
||||
></MyJsonEditor>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
<div class="my-fill" style="overflow: hidden; min-width: 520px">
|
||||
<!-- 操作栏 -->
|
||||
<div style="padding: 10px 10px 0px 10px; border-bottom: 1px solid var(--el-border-color)">
|
||||
<div class="my-flex my-flex-wrap">
|
||||
<div>
|
||||
<!-- 纸张 -->
|
||||
<el-select v-model="state.curPaper.type" placeholder="纸张" class="mr2 mb10" style="width: 70px" @change="onSetPaper">
|
||||
<el-option v-for="item in state.paperTypes" :key="item.type" :label="item.type" :value="item.type" />
|
||||
</el-select>
|
||||
<!-- 自定义纸张 -->
|
||||
<el-tooltip content="自定义纸张" placement="top">
|
||||
<el-button ref="paperRef" :type="state.curPaper.type === '' ? 'primary' : ''" class="mr10 mb10">
|
||||
<el-icon>
|
||||
<my-icon name="customSize" color="var(--color)"></my-icon>
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-popover ref="popoverRef" :virtual-ref="paperRef" trigger="click" virtual-triggering width="auto" title="设置纸张宽高(mm)">
|
||||
<p class="my-flex my-flex-items-center my-flex-between">
|
||||
<el-input-number
|
||||
v-model="state.customPaper.width"
|
||||
placeholder="宽"
|
||||
:precision="1"
|
||||
:step="1"
|
||||
min="0"
|
||||
controls-position="right"
|
||||
style="width: 110px"
|
||||
class="mr6"
|
||||
>
|
||||
</el-input-number>
|
||||
~
|
||||
<el-input-number
|
||||
v-model="state.customPaper.height"
|
||||
placeholder="高"
|
||||
:precision="1"
|
||||
:step="1"
|
||||
min="0"
|
||||
controls-position="right"
|
||||
style="width: 110px"
|
||||
class="ml6"
|
||||
>
|
||||
</el-input-number>
|
||||
</p>
|
||||
<div class="mt10">
|
||||
<el-button type="primary" class="w100" @click="onCustomPaper"> 确定 </el-button>
|
||||
</div>
|
||||
</el-popover>
|
||||
|
||||
<!-- 缩放 -->
|
||||
<el-input-number
|
||||
v-model="state.scaleValue"
|
||||
:precision="1"
|
||||
:step="0.1"
|
||||
min="0.5"
|
||||
max="5"
|
||||
class="mr10 mb10"
|
||||
@change="onChangeScale"
|
||||
style="width: 120px"
|
||||
>
|
||||
<template #decrease-icon>
|
||||
<SvgIcon name="ele-ZoomOut" />
|
||||
</template>
|
||||
<template #increase-icon>
|
||||
<SvgIcon name="ele-ZoomIn" />
|
||||
</template>
|
||||
</el-input-number>
|
||||
</div>
|
||||
|
||||
<!-- 排版 -->
|
||||
<el-button-group class="my-flex mr10 mb10">
|
||||
<el-tooltip content="左对齐" placement="top">
|
||||
<el-button @click="onSetElsAlign('left')">
|
||||
<el-icon>
|
||||
<my-icon name="left" color="var(--color)"></my-icon>
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="居中" placement="top">
|
||||
<el-button @click="onSetElsAlign('vertical')">
|
||||
<el-icon>
|
||||
<my-icon name="vertical" color="var(--color)"></my-icon>
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="右对齐" placement="top">
|
||||
<el-button @click="onSetElsAlign('right')">
|
||||
<el-icon>
|
||||
<my-icon name="right" color="var(--color)"></my-icon>
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="顶对齐" placement="top">
|
||||
<el-button @click="onSetElsAlign('top')">
|
||||
<el-icon>
|
||||
<my-icon name="top" color="var(--color)"></my-icon>
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="垂直居中" placement="top">
|
||||
<el-button @click="onSetElsAlign('horizontal')">
|
||||
<el-icon>
|
||||
<my-icon name="horizontal" color="var(--color)"></my-icon>
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="底对齐" placement="top">
|
||||
<el-button @click="onSetElsAlign('bottom')">
|
||||
<el-icon>
|
||||
<my-icon name="bottom" color="var(--color)"></my-icon>
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="横向分散" placement="top">
|
||||
<el-button @click="onSetElsAlign('distributeHor')">
|
||||
<el-icon>
|
||||
<my-icon name="distributeHor" color="var(--color)"></my-icon>
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="纵向分散" placement="top">
|
||||
<el-button @click="onSetElsAlign('distributeVer')">
|
||||
<el-icon>
|
||||
<my-icon name="distributeVer" color="var(--color)"></my-icon>
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="旋转" placement="top">
|
||||
<el-button @click="onRotatePaper">
|
||||
<el-icon>
|
||||
<my-icon name="rotate" color="var(--color)"></my-icon>
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</el-button-group>
|
||||
|
||||
<!-- 操作 -->
|
||||
<el-button-group class="my-flex mb10">
|
||||
<el-tooltip content="预览" placement="top">
|
||||
<el-button icon="ele-View" @click="onPreView"></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="清空" placement="top">
|
||||
<el-button icon="ele-Delete" @click="onClearPaper"></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="打印" placement="top">
|
||||
<el-button icon="ele-Printer" @click="onPrint"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="查看模板JSON" placement="top">
|
||||
<el-button @click="onViewJson">
|
||||
<el-icon>
|
||||
<my-icon name="json" color="var(--color)"></my-icon>
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</el-button-group>
|
||||
</div>
|
||||
</div>
|
||||
<el-scrollbar
|
||||
ref="printTemplateScrollbarRef"
|
||||
height="100%"
|
||||
max-height="100%"
|
||||
:always="false"
|
||||
wrap-style="background-color: #fff;color: #333;"
|
||||
>
|
||||
<!-- 画布 -->
|
||||
<div ref="designRef" class="hiprint-printTemplate"></div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<div style="width: 350px; min-width: 350px; border-left: 1px solid var(--el-border-color)">
|
||||
<el-scrollbar height="100%" max-height="100%" :always="false" wrap-style="padding:0px">
|
||||
<!-- 配置 -->
|
||||
<div id="hiprint-printElementOptionSetting"></div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<PrintPreview ref="previewRef"></PrintPreview>
|
||||
<ViewJson ref="previewJsonDialogRef" title="查看模板JSON"></ViewJson>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/print-template-deisgn">
|
||||
import { reactive, ref, onMounted, nextTick, getCurrentInstance } from 'vue'
|
||||
import { hiprint } from 'vue-plugin-hiprint'
|
||||
import providers from './providers'
|
||||
import PrintPreview from './preview.vue'
|
||||
import ViewJson from './view-json.vue'
|
||||
import MyJsonEditor from '/@/components/my-json-editor/index.vue'
|
||||
|
||||
const title = defineModel('title', { type: String })
|
||||
const printData = defineModel('printData', { type: String })
|
||||
|
||||
interface IPaperType {
|
||||
type: string
|
||||
width: number
|
||||
height: number
|
||||
}
|
||||
|
||||
const state = reactive({
|
||||
visible: false,
|
||||
sureLoading: false,
|
||||
scaleValue: 1,
|
||||
// 当前纸张
|
||||
curPaper: {
|
||||
type: 'A4',
|
||||
width: 210,
|
||||
height: 296.6,
|
||||
} as IPaperType,
|
||||
// 自定义纸张
|
||||
customPaper: {
|
||||
type: '',
|
||||
width: 220,
|
||||
height: 80,
|
||||
} as IPaperType,
|
||||
// 纸张类型
|
||||
paperTypes: [
|
||||
{
|
||||
type: 'A3',
|
||||
width: 420,
|
||||
height: 296.6,
|
||||
},
|
||||
{
|
||||
type: 'A4',
|
||||
width: 210,
|
||||
height: 296.6,
|
||||
},
|
||||
{
|
||||
type: 'A5',
|
||||
width: 210,
|
||||
height: 147.6,
|
||||
},
|
||||
{
|
||||
type: 'B3',
|
||||
width: 500,
|
||||
height: 352.6,
|
||||
},
|
||||
{
|
||||
type: 'B4',
|
||||
width: 250,
|
||||
height: 352.6,
|
||||
},
|
||||
{
|
||||
type: 'B5',
|
||||
width: 250,
|
||||
height: 175.6,
|
||||
},
|
||||
] as IPaperType[],
|
||||
showSaveDialog: false,
|
||||
})
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
let hiprintTemplate = ref()
|
||||
const paperRef = ref()
|
||||
const popoverRef = ref()
|
||||
const printTemplateScrollbarRef = ref()
|
||||
const previewRef = ref()
|
||||
const previewJsonDialogRef = ref()
|
||||
const epContainerRef = ref()
|
||||
const designRef = ref()
|
||||
const epDraggableItemRef = ref()
|
||||
|
||||
onMounted(() => {
|
||||
buildProvider()
|
||||
buildDesigner()
|
||||
})
|
||||
|
||||
// 构建拖拽组件
|
||||
const buildProvider = () => {
|
||||
let provider = providers[0]
|
||||
hiprint.init({ providers: [provider.f] })
|
||||
|
||||
if (epContainerRef.value) {
|
||||
epContainerRef.value.innerHTML = ''
|
||||
}
|
||||
|
||||
hiprint.PrintElementTypeManager.build(epContainerRef.value, provider.value)
|
||||
}
|
||||
|
||||
// 构建设计器
|
||||
const buildDesigner = (template = {} as any) => {
|
||||
if (designRef.value) {
|
||||
designRef.value.innerHTML = ''
|
||||
}
|
||||
hiprintTemplate.value = new hiprint.PrintTemplate({
|
||||
template: template,
|
||||
settingContainer: '#hiprint-printElementOptionSetting',
|
||||
paginationContainer: '.hiprint-printPagination',
|
||||
fontList: [
|
||||
{ title: '微软雅黑', value: 'Microsoft YaHei' },
|
||||
{ title: '黑体', value: 'STHeitiSC-Light' },
|
||||
{ title: '思源黑体', value: 'SourceHanSansCN-Normal' },
|
||||
{ title: '王羲之书法体', value: '王羲之书法体' },
|
||||
{ title: '宋体', value: 'SimSun' },
|
||||
{ title: '华为楷体', value: 'STKaiti' },
|
||||
{ title: 'cursive', value: 'cursive' },
|
||||
],
|
||||
history: true,
|
||||
})
|
||||
|
||||
hiprintTemplate.value.design(designRef.value)
|
||||
|
||||
designRef.value.querySelector('.hiprint-printPaper')?.firstChild.click()
|
||||
}
|
||||
|
||||
const setPaper = (template = {} as any) => {
|
||||
if (template?.panels?.length > 0) {
|
||||
const width = template.panels[0].width
|
||||
const height = template.panels[0].height
|
||||
const paperType = state.paperTypes.find((a) => a.width == width && a.height == height)
|
||||
state.curPaper = { type: paperType?.type || '', width: width, height: height }
|
||||
if (state.curPaper.type === '') {
|
||||
state.customPaper.width = width
|
||||
state.customPaper.height = height
|
||||
}
|
||||
} else {
|
||||
onSetPaper(state.curPaper.type)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置纸张大小
|
||||
* @param type [A3, A4, A5, B3, B4, B5, '']
|
||||
* @param value {width,height} mm
|
||||
*/
|
||||
const onSetPaper = (type: string, value?: { width: number; height: number }) => {
|
||||
try {
|
||||
const paperType = state.paperTypes.find((x) => x.type == type)
|
||||
if (paperType) {
|
||||
state.curPaper = { type: type, width: paperType.width, height: paperType.height }
|
||||
hiprintTemplate.value.setPaper(paperType.width, paperType.height)
|
||||
} else {
|
||||
state.curPaper = { type: '', width: value?.width as number, height: value?.height as number }
|
||||
hiprintTemplate.value.setPaper(value?.width, value?.height)
|
||||
}
|
||||
nextTick(() => {
|
||||
printTemplateScrollbarRef.value.update()
|
||||
})
|
||||
} catch (error) {
|
||||
proxy.$modal.msgError(`操作失败: ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
//自定义纸张
|
||||
const onCustomPaper = () => {
|
||||
popoverRef.value?.hide?.()
|
||||
onSetPaper('', { width: state.customPaper.width, height: state.customPaper.height })
|
||||
}
|
||||
|
||||
//排版
|
||||
const onSetElsAlign = (e: any) => {
|
||||
hiprintTemplate.value.setElsAlign(e)
|
||||
}
|
||||
|
||||
// 缩放
|
||||
const onChangeScale = () => {
|
||||
if (hiprintTemplate.value) {
|
||||
// scaleVal: 放大缩小值, false: 不保存(不传也一样), 如果传 true, 打印时也会放大
|
||||
hiprintTemplate.value.zoom(state.scaleValue)
|
||||
}
|
||||
}
|
||||
|
||||
// 旋转
|
||||
const onRotatePaper = () => {
|
||||
if (hiprintTemplate.value) {
|
||||
hiprintTemplate.value.rotatePaper()
|
||||
}
|
||||
}
|
||||
|
||||
//预览
|
||||
const onPreView = () => {
|
||||
if (hiprintTemplate.value) {
|
||||
previewRef.value.open(hiprintTemplate.value.getJson() || {}, JSON.parse(printData.value || '{}'), title.value)
|
||||
}
|
||||
}
|
||||
|
||||
// 清空
|
||||
const onClearPaper = () => {
|
||||
proxy.$modal
|
||||
.confirm(`确定要清空设计模板吗?`)
|
||||
.then(async () => {
|
||||
try {
|
||||
if (hiprintTemplate.value) {
|
||||
hiprintTemplate.value.clear()
|
||||
}
|
||||
} catch (error) {}
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
//打印
|
||||
const onPrint = async () => {
|
||||
if (hiprintTemplate.value) {
|
||||
hiprintTemplate.value.print(JSON.parse(printData.value || '{}'))
|
||||
}
|
||||
}
|
||||
|
||||
//查看Json
|
||||
const onViewJson = () => {
|
||||
if (hiprintTemplate.value) {
|
||||
let templateJson = JSON.stringify(hiprintTemplate.value.getJson() || {})
|
||||
previewJsonDialogRef.value.open(templateJson)
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
hiprintTemplate,
|
||||
setPaper,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.hiprint-printElement {
|
||||
color: #000;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.hiprint-printTemplate {
|
||||
padding: 15px 10px 10px 15px;
|
||||
}
|
||||
:deep() {
|
||||
.jsoneditor {
|
||||
border-width: 0px;
|
||||
}
|
||||
.jsoneditor-menu {
|
||||
color: var(--el-text-color-primary);
|
||||
background-color: var(--el-color-primary);
|
||||
border-bottom: 1px solid var(--el-border-color);
|
||||
}
|
||||
|
||||
textarea.jsoneditor-text {
|
||||
background-color: var(--el-bg-color-overlay);
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
|
||||
.hiprint-option-items {
|
||||
padding: 10px;
|
||||
}
|
||||
.prop-tabs {
|
||||
background-color: var(--el-bg-color);
|
||||
border-style: none;
|
||||
box-shadow: none;
|
||||
border-color: var(--el-border-color);
|
||||
}
|
||||
.prop-tabs .prop-tab-items {
|
||||
display: flex;
|
||||
height: 40px;
|
||||
padding: 0px;
|
||||
border-bottom-color: var(--el-border-color);
|
||||
}
|
||||
.prop-tabs .prop-tab-items .prop-tab-item {
|
||||
background-color: var(--el-bg-color);
|
||||
flex: 1;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
.prop-tabs .prop-tab-items li.active {
|
||||
border-bottom: 2px solid var(--el-color-primary);
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
.prop-tabs .prop-tab-items .prop-tab-item .tab-title {
|
||||
font-weight: normal;
|
||||
}
|
||||
.prop-tabs .hiprint-option-items {
|
||||
background-color: var(--el-bg-color);
|
||||
padding: 10px;
|
||||
}
|
||||
.hiprint-option-item-settingBtn {
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
background-color: var(--el-color-primary);
|
||||
}
|
||||
.prop-tabs .hiprint-option-item-settingBtn {
|
||||
width: 45%;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.hiprint-option-item-submitBtn {
|
||||
background-color: var(--el-color-primary);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.hiprint-option-item-deleteBtn {
|
||||
background-color: var(--el-color-danger);
|
||||
margin-left: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.hiprint-option-items .hiprint-option-item-field input,
|
||||
.hiprint-option-items .hiprint-option-item-field select,
|
||||
.hiprint-option-items .hiprint-option-item-field textarea {
|
||||
border: none;
|
||||
background-color: var(--el-bg-color);
|
||||
border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
|
||||
box-shadow: 0 0 0 1px var(--el-input-border-color, var(--el-border-color)) inset;
|
||||
padding: 1px 11px;
|
||||
height: calc(var(--el-component-size, 32px));
|
||||
line-height: calc(var(--el-component-size, 32px) - 2px);
|
||||
&:hover {
|
||||
box-shadow: 0 0 0 1px var(--el-border-color-hover) inset;
|
||||
}
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 1px var(--el-color-primary) inset;
|
||||
}
|
||||
}
|
||||
|
||||
.left-box {
|
||||
.el-tabs__header {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.el-tab-pane {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.rect-printElement-types .hiprint-printElement-type a.ep-draggable-item {
|
||||
height: auto;
|
||||
color: #666;
|
||||
box-shadow: none !important;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.hiprint-printElement-type a.ep-draggable-item:before {
|
||||
display: block;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
content: '';
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.hline']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/hline.svg');
|
||||
}
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.vline']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/vline.svg');
|
||||
}
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.rect']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/rect.svg');
|
||||
}
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.oval']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/oval.svg');
|
||||
}
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.barcode']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/barcode.svg');
|
||||
}
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.qrcode']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/qrcode.svg');
|
||||
}
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.text']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/text.svg');
|
||||
}
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.longText']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/longText.svg');
|
||||
}
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.table']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/table.svg');
|
||||
}
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.emptyTable']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/emptyTable.svg');
|
||||
}
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.html']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/html.svg');
|
||||
}
|
||||
.hiprint-printElement-type a.ep-draggable-item[tid='comModule.image']:before {
|
||||
background-image: url('/@/assets/svgs/hiprint/image.svg');
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,122 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="600px"
|
||||
>
|
||||
<el-form :model="form" ref="formRef" label-width="80px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="模板名称" prop="name" :rules="[{ required: true, message: '请输入模板名称', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.name" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="模板编码" prop="code" :rules="[{ required: true, message: '请输入模板编码', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.code" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="排序">
|
||||
<el-input-number v-model="form.sort" class="w100" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="启用">
|
||||
<el-switch v-model="form.enabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/print-template-form">
|
||||
import { reactive, toRefs, ref } from 'vue'
|
||||
import { PrintTemplateUpdateInput, PrintTemplateGetOutput } from '/@/api/admin/data-contracts'
|
||||
import { PrintTemplateApi } from '/@/api/admin/PrintTemplate'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const formRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
form: {
|
||||
enabled: true,
|
||||
} as PrintTemplateUpdateInput & PrintTemplateGetOutput,
|
||||
})
|
||||
|
||||
const { form } = toRefs(state)
|
||||
|
||||
// 打开对话框
|
||||
const open = async (row: any = {}) => {
|
||||
if (row.id > 0) {
|
||||
const res = await new PrintTemplateApi().get({ id: row.id }, { loading: true })
|
||||
|
||||
if (res?.success) {
|
||||
let formData = res.data as PrintTemplateUpdateInput & PrintTemplateGetOutput
|
||||
state.form = formData
|
||||
}
|
||||
} else {
|
||||
state.form = {
|
||||
enabled: true,
|
||||
} as PrintTemplateUpdateInput & PrintTemplateGetOutput
|
||||
}
|
||||
|
||||
state.showDialog = true
|
||||
}
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
state.sureLoading = true
|
||||
let res = {} as any
|
||||
|
||||
if (state.form.id != undefined && state.form.id > 0) {
|
||||
res = await new PrintTemplateApi().update(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
} else {
|
||||
res = await new PrintTemplateApi().add(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
eventBus.emit('refreshPrintTemplate')
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
@ -1,119 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="state.title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="true"
|
||||
:width="width"
|
||||
:show-close="false"
|
||||
style="max-width: 90%"
|
||||
body-class="preview-box"
|
||||
>
|
||||
<template #header="{ titleId, titleClass }">
|
||||
<div class="my-flex my-flex-between mr10">
|
||||
<span :id="titleId" :class="titleClass">{{ state.title }}</span>
|
||||
<div>
|
||||
<el-button type="primary" @click="onExport">
|
||||
<template #icon>
|
||||
<el-icon>
|
||||
<my-icon name="export" color="var(--color)"></my-icon>
|
||||
</el-icon>
|
||||
</template>
|
||||
导出PDF
|
||||
</el-button>
|
||||
<el-button type="primary" icon="ele-Printer" @click="onPrint">打 印</el-button>
|
||||
<el-button @click="onCancel">关 闭</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div ref="previewContainerRef"></div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, nextTick, computed } from 'vue'
|
||||
import { hiprint } from 'vue-plugin-hiprint'
|
||||
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
width: 0,
|
||||
title: '',
|
||||
printData: {},
|
||||
template: {} as any,
|
||||
})
|
||||
|
||||
const width = computed(() => {
|
||||
return `${state.width + 20}mm`
|
||||
})
|
||||
|
||||
const hiprintTemplate = ref()
|
||||
const previewContainerRef = ref<HTMLElement | null>(null) // 引用容器
|
||||
|
||||
// 打开对话框
|
||||
const open = async (template: any, printData: {}, title = '打印模板') => {
|
||||
state.title = title
|
||||
state.template = template
|
||||
state.printData = printData
|
||||
hiprintTemplate.value = new hiprint.PrintTemplate({
|
||||
template: state.template,
|
||||
})
|
||||
state.width = hiprintTemplate.value.printPanels?.length > 0 ? hiprintTemplate.value.printPanels[0].width : 210
|
||||
const htmlElements = hiprintTemplate.value.getHtml(printData)
|
||||
|
||||
state.showDialog = true
|
||||
|
||||
await nextTick()
|
||||
|
||||
// 清空容器
|
||||
if (previewContainerRef.value) {
|
||||
previewContainerRef.value.innerHTML = ''
|
||||
}
|
||||
|
||||
// 将 HTML 元素对象插入到容器中
|
||||
if (htmlElements?.length > 0 && previewContainerRef.value) {
|
||||
htmlElements.each((index: number, element: HTMLElement) => {
|
||||
previewContainerRef.value?.appendChild(element)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 导出PDF
|
||||
const onExport = () => {
|
||||
hiprintTemplate.value.toPdf(state.printData, state.title)
|
||||
}
|
||||
|
||||
//打印
|
||||
const onPrint = async () => {
|
||||
if (hiprintTemplate.value) {
|
||||
hiprintTemplate.value.print(state.printData)
|
||||
}
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep() {
|
||||
.el-dialog__body {
|
||||
overflow-x: auto;
|
||||
}
|
||||
.preview-box {
|
||||
background-color: var(--el-bg-color-overlay);
|
||||
}
|
||||
.hiprint-printPaper {
|
||||
background-color: var(--el-color-white);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,165 +0,0 @@
|
||||
import { hiprint } from 'vue-plugin-hiprint'
|
||||
import logoImg from '/@/assets/logo-mini.svg'
|
||||
|
||||
export const comProvider = function () {
|
||||
var addElementTypes = function (context: any) {
|
||||
context.removePrintElementTypes('comModule')
|
||||
context.addPrintElementTypes('comModule', [
|
||||
new hiprint.PrintElementTypeGroup('常用组件', [
|
||||
{
|
||||
tid: 'comModule.text',
|
||||
title: '文本',
|
||||
data: '',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
tid: 'comModule.longText',
|
||||
title: '长文本',
|
||||
data: '',
|
||||
type: 'longText',
|
||||
options: {
|
||||
width: 500,
|
||||
},
|
||||
},
|
||||
{
|
||||
tid: 'comModule.table',
|
||||
field: 'table',
|
||||
title: '表格',
|
||||
type: 'table',
|
||||
groupFields: ['name'],
|
||||
groupFooterFormatter: function (group: any, option: any) {
|
||||
return '这里自定义统计脚信息'
|
||||
},
|
||||
options: {
|
||||
width: 500,
|
||||
},
|
||||
columns: [
|
||||
[
|
||||
{
|
||||
title: '行号',
|
||||
fixed: true,
|
||||
rowspan: 2,
|
||||
field: 'id',
|
||||
width: 70,
|
||||
},
|
||||
{ title: '人员信息', colspan: 2 },
|
||||
{ title: '销售统计', colspan: 2 },
|
||||
],
|
||||
[
|
||||
{
|
||||
title: '姓名',
|
||||
align: 'left',
|
||||
field: 'name',
|
||||
width: 100,
|
||||
},
|
||||
{ title: '性别', field: 'gender', width: 100 },
|
||||
{
|
||||
title: '销售数量',
|
||||
field: 'count',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '销售金额',
|
||||
field: 'amount',
|
||||
width: 100,
|
||||
},
|
||||
],
|
||||
],
|
||||
editable: true,
|
||||
columnDisplayEditable: true, //列显示是否能编辑
|
||||
columnDisplayIndexEditable: true, //列顺序显示是否能编辑
|
||||
columnTitleEditable: true, //列标题是否能编辑
|
||||
columnResizable: true, //列宽是否能调整
|
||||
columnAlignEditable: true, //列对齐是否调整
|
||||
isEnableEditField: true, //编辑字段
|
||||
isEnableContextMenu: true, //开启右键菜单 默认true
|
||||
isEnableInsertRow: true, //插入行
|
||||
isEnableDeleteRow: true, //删除行
|
||||
isEnableInsertColumn: true, //插入列
|
||||
isEnableDeleteColumn: true, //删除列
|
||||
isEnableMergeCell: true, //合并单元格
|
||||
},
|
||||
{
|
||||
tid: 'comModule.emptyTable',
|
||||
title: '空白表格',
|
||||
type: 'table',
|
||||
options: {
|
||||
width: 500,
|
||||
},
|
||||
columns: [
|
||||
[
|
||||
{
|
||||
title: '',
|
||||
field: '',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
field: '',
|
||||
width: 100,
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
{
|
||||
tid: 'comModule.html',
|
||||
title: 'html',
|
||||
formatter: function (data: any, options: any) {
|
||||
return '<div style="height:50pt;width:50pt;background:red;border-radius: 50%;"></div>'
|
||||
},
|
||||
type: 'html',
|
||||
},
|
||||
{
|
||||
tid: 'comModule.image',
|
||||
title: '图片',
|
||||
type: 'image',
|
||||
options: { field: '', src: logoImg },
|
||||
},
|
||||
]),
|
||||
new hiprint.PrintElementTypeGroup('辅助组件', [
|
||||
{
|
||||
tid: 'comModule.hline',
|
||||
title: '横线',
|
||||
type: 'hline',
|
||||
},
|
||||
{
|
||||
tid: 'comModule.vline',
|
||||
title: '竖线',
|
||||
type: 'vline',
|
||||
},
|
||||
{
|
||||
tid: 'comModule.rect',
|
||||
title: '矩形',
|
||||
type: 'rect',
|
||||
},
|
||||
{
|
||||
tid: 'comModule.oval',
|
||||
title: '椭圆',
|
||||
type: 'oval',
|
||||
},
|
||||
{
|
||||
tid: 'comModule.barcode',
|
||||
title: '条形码',
|
||||
type: 'barcode',
|
||||
},
|
||||
{
|
||||
tid: 'comModule.qrcode',
|
||||
title: '二维码',
|
||||
type: 'qrcode',
|
||||
},
|
||||
]),
|
||||
])
|
||||
}
|
||||
return {
|
||||
addElementTypes: addElementTypes,
|
||||
}
|
||||
}
|
||||
|
||||
export default [
|
||||
{
|
||||
name: '常用组件',
|
||||
value: 'comModule',
|
||||
type: 1,
|
||||
f: comProvider(),
|
||||
},
|
||||
]
|
||||
@ -1,67 +0,0 @@
|
||||
<template>
|
||||
<el-drawer v-model="state.showDialog" direction="rtl" destroy-on-close :size="size">
|
||||
<template #header="{ titleId, titleClass }">
|
||||
<h4 :id="titleId" :class="titleClass">{{ title }}</h4>
|
||||
<el-icon v-if="state.isFull" class="el-drawer__btn" @click="state.isFull = !state.isFull" title="还原"><ele-CopyDocument /></el-icon>
|
||||
<el-icon v-else class="el-drawer__btn" @click="state.isFull = !state.isFull" title="最大化"><ele-FullScreen /></el-icon>
|
||||
</template>
|
||||
<div class="my-fill h100">
|
||||
<MyJsonEditor
|
||||
v-model="state.templateJson"
|
||||
:options="{
|
||||
mainMenuBar: false,
|
||||
statusBar: false,
|
||||
onEditable: () => false,
|
||||
}"
|
||||
></MyJsonEditor>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, computed } from 'vue'
|
||||
import MyJsonEditor from '/@/components/my-json-editor/index.vue'
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '查看JSON',
|
||||
},
|
||||
})
|
||||
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
isFull: false,
|
||||
isMobile: document.body.clientWidth < 1000,
|
||||
templateJson: '',
|
||||
})
|
||||
|
||||
const size = computed(() => {
|
||||
return state.isMobile ? '100%' : state.isFull ? '100%' : '45%'
|
||||
})
|
||||
|
||||
// 打开对话框
|
||||
const open = (templateJson: any) => {
|
||||
state.templateJson = templateJson
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.el-alert {
|
||||
border-width: 0px !important;
|
||||
margin-left: 110px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.el-drawer__btn {
|
||||
cursor: pointer;
|
||||
margin-right: 8px;
|
||||
&:hover {
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,201 +0,0 @@
|
||||
<template>
|
||||
<my-layout>
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form ref="filterFormRef" :model="state.filter" :inline="true" label-width="auto" :label-position="'left'" @submit.stop.prevent>
|
||||
<el-form-item label="模板名称" prop="name">
|
||||
<el-input v-model="state.filter.name" placeholder="模板名称" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="模板编码" prop="code">
|
||||
<el-input v-model="state.filter.code" placeholder="模板编码" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
<el-button icon="ele-RefreshLeft" text bg @click="onReset"> 重置 </el-button>
|
||||
<el-button v-if="auth('api:admin:print-template:add')" type="primary" icon="ele-Plus" @click="onAdd"> 新增 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table v-loading="state.loading" :data="state.dataList" default-expand-all highlight-current-row style="width: 100%" border>
|
||||
<el-table-column prop="name" label="模板名称" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="code" label="模板编码" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="sort" label="排序" width="82" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="状态" width="88" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
v-if="auth('api:admin:print-template:set-enable')"
|
||||
v-model="row.enabled"
|
||||
:loading="row.loading"
|
||||
:active-value="true"
|
||||
:inactive-value="false"
|
||||
inline-prompt
|
||||
active-text="启用"
|
||||
inactive-text="禁用"
|
||||
:before-change="() => onSetEnable(row)"
|
||||
/>
|
||||
<template v-else>
|
||||
<el-tag type="success" v-if="row.enabled">启用</el-tag>
|
||||
<el-tag type="danger" v-else>禁用</el-tag>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160" fixed="right" header-align="center" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button v-auth="'api:admin:print-template:update'" text type="primary" @click="onEdit(row)"> 编辑 </el-button>
|
||||
<el-button v-auth="'api:admin:print-template:design'" text type="primary" @click="onDesign(row)"> 设计 </el-button>
|
||||
<el-button v-auth="'api:admin:print-template:delete'" text type="danger" @click="onDelete(row)"> 删除 </el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="my-flex my-flex-end" style="margin-top: 10px">
|
||||
<el-pagination
|
||||
v-model:currentPage="state.pageInput.currentPage"
|
||||
v-model:page-size="state.pageInput.pageSize"
|
||||
:total="state.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
background
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<PrintTemplateForm ref="formRef" :title="state.formTitle"></PrintTemplateForm>
|
||||
<PrintTemplateDesignDialog ref="designDialogRef" :title="state.designTitle"></PrintTemplateDesignDialog>
|
||||
</my-layout>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/print-template">
|
||||
import { ref, reactive, onMounted, getCurrentInstance, onBeforeMount, defineAsyncComponent } from 'vue'
|
||||
import { PageInputPrintTemplateGetPageInput, PrintTemplateGetPageOutput } from '/@/api/admin/data-contracts'
|
||||
import { PrintTemplateApi } from '/@/api/admin/PrintTemplate'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { auth } from '/@/utils/authFunction'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
|
||||
// 引入组件
|
||||
const PrintTemplateForm = defineAsyncComponent(() => import('./components/form.vue'))
|
||||
const PrintTemplateDesignDialog = defineAsyncComponent(() => import('./components/design-dialog.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const filterFormRef = ref<FormInstance>()
|
||||
const formRef = ref()
|
||||
const designDialogRef = ref()
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
formTitle: '',
|
||||
designTitle: '',
|
||||
total: 0,
|
||||
filter: {
|
||||
name: '',
|
||||
code: '',
|
||||
},
|
||||
pageInput: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
} as PageInputPrintTemplateGetPageInput,
|
||||
dataList: [] as Array<PrintTemplateGetPageOutput>,
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
await onQuery()
|
||||
|
||||
eventBus.off('refreshPrintTemplate')
|
||||
eventBus.on('refreshPrintTemplate', async () => {
|
||||
onQuery()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshPrintTemplate')
|
||||
})
|
||||
|
||||
const onSizeChange = (val: number) => {
|
||||
state.pageInput.currentPage = 1
|
||||
state.pageInput.pageSize = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onCurrentChange = (val: number) => {
|
||||
state.pageInput.currentPage = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
state.pageInput.filter = state.filter
|
||||
const res = await new PrintTemplateApi().getPage(state.pageInput).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
|
||||
state.dataList = res?.data?.list ?? []
|
||||
state.total = res?.data?.total ?? 0
|
||||
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onReset = () => {
|
||||
filterFormRef.value!.resetFields()
|
||||
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onAdd = () => {
|
||||
state.formTitle = '新增打印模板'
|
||||
formRef.value.open()
|
||||
}
|
||||
|
||||
const onEdit = (row: PrintTemplateGetPageOutput) => {
|
||||
state.formTitle = '编辑打印模板'
|
||||
formRef.value.open(row)
|
||||
}
|
||||
|
||||
const onDesign = (row: PrintTemplateGetPageOutput) => {
|
||||
state.designTitle = row.name ? row.name : '设计打印模板'
|
||||
designDialogRef.value.open(row)
|
||||
}
|
||||
|
||||
const onDelete = (row: PrintTemplateGetPageOutput) => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要删除打印模板【${row.name}】?`)
|
||||
.then(async () => {
|
||||
await new PrintTemplateApi().delete({ id: row.id }, { loading: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
//启用或禁用
|
||||
const onSetEnable = (row: PrintTemplateGetPageOutput & { loading: boolean }) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
proxy.$modal
|
||||
.confirm(`确定要${row.enabled ? '禁用' : '启用'}【${row.name}】?`)
|
||||
.then(async () => {
|
||||
row.loading = true
|
||||
const res = await new PrintTemplateApi()
|
||||
.setEnable({ printTemplateId: row.id, enabled: !row.enabled }, { showSuccessMessage: true })
|
||||
.catch(() => {
|
||||
reject(new Error('Error'))
|
||||
})
|
||||
.finally(() => {
|
||||
row.loading = false
|
||||
})
|
||||
if (res && res.success) {
|
||||
resolve(true)
|
||||
onQuery()
|
||||
} else {
|
||||
reject(new Error('Cancel'))
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
reject(new Error('Cancel'))
|
||||
})
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -1,193 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form ref="formRef" :model="form" size="large" class="login-content-form">
|
||||
<div class="login-title">注册账号</div>
|
||||
<el-form-item
|
||||
class="login-animation1"
|
||||
prop="email"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入邮箱地址', trigger: ['blur', 'change'] },
|
||||
{ validator: testEmail, trigger: ['blur', 'change'] },
|
||||
]"
|
||||
>
|
||||
<el-input ref="emailRef" text :placeholder="$t('message.email.placeholder1')" v-model="form.email" clearable autocomplete="off">
|
||||
<template #prefix>
|
||||
<el-icon class="el-input__icon"><ele-Promotion /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item class="login-animation2" prop="code" :rules="[{ required: true, message: '请输入邮箱验证码', trigger: ['blur', 'change'] }]">
|
||||
<MyInputCode v-model="form.code" :email="form.email" :validate="validatorEmail" @send="onSend" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="hasPassword"
|
||||
class="login-animation3"
|
||||
prop="password"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入密码', trigger: ['blur', 'change'] },
|
||||
{ validator: validatorPwd, trigger: ['blur', 'change'] },
|
||||
]"
|
||||
>
|
||||
<el-input v-model="form.password" :placeholder="'输入密码'" show-password autocomplete="off" clearable @input="onInputPassword">
|
||||
<template #prefix>
|
||||
<el-icon class="el-input__icon"><ele-Unlock /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
class="login-animation3 mb10"
|
||||
prop="corpName"
|
||||
:rules="[{ required: true, message: '请填写完整企业名称', trigger: ['blur', 'change'] }]"
|
||||
>
|
||||
<el-input ref="emailRef" text :placeholder="$t('请填写完整企业名称')" v-model="form.corpName" clearable autocomplete="off">
|
||||
<template #prefix>
|
||||
<el-icon class="el-input__icon"><ele-OfficeBuilding /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item class="login-animation4 mb5">
|
||||
<el-button round type="primary" v-waves class="login-content-submit" :loading="state.loading" @click="onReg">
|
||||
<span>{{ $t('注册') }}</span>
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item class="login-animation5 mb5 login-agree" prop="agree" :rules="[{ validator: validatorAgree, trigger: ['change'] }]">
|
||||
<div class="my-flex my-flex-items-center f12">
|
||||
<el-checkbox v-model="form.agree">我已阅读并同意</el-checkbox>
|
||||
<div class="my-flex my-flex-items-center ml5">
|
||||
<el-link underline="never" type="primary" class="f12" target="_blank" href="https://zhontai.net/admin/introduce.html">服务协议</el-link>、
|
||||
<el-link underline="never" type="primary" class="f12" target="_blank" href="https://zhontai.net/admin/introduce.html">隐私政策</el-link>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/reg-email">
|
||||
import { reactive, toRefs, ref, defineAsyncComponent } from 'vue'
|
||||
import { AuthRegByEmailInput } from '/@/api/admin/data-contracts'
|
||||
import { AuthApi } from '/@/api/admin/Auth'
|
||||
import { verifyCnAndSpace } from '/@/utils/toolsValidate'
|
||||
import { validatorPwd, validatorAgree } from '/@/utils/validators'
|
||||
import { testEmail } from '/@/utils/test'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
const MyInputCode = defineAsyncComponent(() => import('/@/components/my-input-code/index.vue'))
|
||||
const isReg = defineModel('isReg', { type: Boolean, default: false })
|
||||
const hasPassword = defineModel('hasPassword', { type: Boolean, default: false })
|
||||
|
||||
const formRef = ref()
|
||||
const emailRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
loading: false,
|
||||
form: {
|
||||
agree: false,
|
||||
email: '',
|
||||
code: '',
|
||||
codeId: '',
|
||||
password: '',
|
||||
corpName: '中台',
|
||||
} as AuthRegByEmailInput & { agree: false },
|
||||
})
|
||||
const { form } = toRefs(state)
|
||||
|
||||
//验证邮箱
|
||||
const validatorEmail = (callback: Function) => {
|
||||
formRef.value.validateField('email', (isValid: boolean) => {
|
||||
if (!isValid) {
|
||||
emailRef.value?.focus()
|
||||
return
|
||||
}
|
||||
callback?.()
|
||||
})
|
||||
}
|
||||
|
||||
//发送验证码
|
||||
const onSend = (codeId: string) => {
|
||||
state.form.codeId = codeId
|
||||
}
|
||||
|
||||
// 输入密码
|
||||
const onInputPassword = (val: string) => {
|
||||
state.form.password = verifyCnAndSpace(val)
|
||||
}
|
||||
|
||||
// 打开对话框
|
||||
const open = async () => {
|
||||
state.showDialog = true
|
||||
state.form = {} as AuthRegByEmailInput & { agree: false }
|
||||
}
|
||||
|
||||
// 注册
|
||||
const onReg = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
state.loading = true
|
||||
const res = await new AuthApi().regByEmail(state.form, { showSuccessMessage: false }).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
state.loading = false
|
||||
|
||||
if (res?.success) {
|
||||
ElMessage.success('注册成功')
|
||||
isReg.value = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.login-content-form {
|
||||
.login-title {
|
||||
margin-bottom: 50px;
|
||||
font-size: 27px;
|
||||
text-align: center;
|
||||
letter-spacing: 3px;
|
||||
color: var(--el-text-color-primary);
|
||||
position: relative;
|
||||
}
|
||||
.login-remind {
|
||||
color: #7f8792;
|
||||
margin-right: 5px;
|
||||
}
|
||||
@for $i from 1 through 5 {
|
||||
.login-animation#{$i} {
|
||||
opacity: 0;
|
||||
animation-name: error-num;
|
||||
animation-duration: 0.5s;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: calc($i/10) + s;
|
||||
}
|
||||
}
|
||||
.login-content-code {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
.login-content-submit {
|
||||
width: 100%;
|
||||
letter-spacing: 2px;
|
||||
font-weight: 300;
|
||||
margin-top: 15px;
|
||||
}
|
||||
.login-msg {
|
||||
color: var(--el-text-color-placeholder);
|
||||
}
|
||||
.f12 {
|
||||
font-size: 12px;
|
||||
}
|
||||
:deep() {
|
||||
.el-checkbox__input.is-checked + .el-checkbox__label {
|
||||
color: unset;
|
||||
}
|
||||
.login-agree.el-form-item--large .el-form-item__content {
|
||||
line-height: unset !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,201 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form ref="formRef" :model="form" size="large" class="login-content-form">
|
||||
<div class="login-title">注册账号</div>
|
||||
<el-form-item
|
||||
class="login-animation1"
|
||||
prop="mobile"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入手机号', trigger: ['blur', 'change'] },
|
||||
{ validator: testMobile, trigger: ['blur', 'change'] },
|
||||
]"
|
||||
>
|
||||
<el-input
|
||||
ref="phoneRef"
|
||||
text
|
||||
:placeholder="$t('message.mobile.placeholder1')"
|
||||
maxlength="11"
|
||||
v-model="form.mobile"
|
||||
clearable
|
||||
autocomplete="off"
|
||||
>
|
||||
<template #prefix>
|
||||
<el-icon class="el-input__icon"><ele-Iphone /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item class="login-animation2" prop="code" :rules="[{ required: true, message: '请输入短信验证码', trigger: ['blur', 'change'] }]">
|
||||
<MyInputCode v-model="form.code" :mobile="form.mobile" :validate="validatorMobile" @send="onSend" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="hasPassword"
|
||||
class="login-animation3"
|
||||
prop="password"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入密码', trigger: ['blur', 'change'] },
|
||||
{ validator: validatorPwd, trigger: ['blur', 'change'] },
|
||||
]"
|
||||
>
|
||||
<el-input v-model="form.password" :placeholder="'输入密码'" show-password autocomplete="off" clearable @input="onInputPassword">
|
||||
<template #prefix>
|
||||
<el-icon class="el-input__icon"><ele-Unlock /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
class="login-animation3 mb10"
|
||||
prop="corpName"
|
||||
:rules="[{ required: true, message: '请填写完整企业名称', trigger: ['blur', 'change'] }]"
|
||||
>
|
||||
<el-input ref="emailRef" text :placeholder="$t('请填写完整企业名称')" v-model="form.corpName" clearable autocomplete="off">
|
||||
<template #prefix>
|
||||
<el-icon class="el-input__icon"><ele-OfficeBuilding /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item class="login-animation4 mb5">
|
||||
<el-button round type="primary" v-waves class="login-content-submit" :loading="state.loading" @click="onReg">
|
||||
<span>{{ $t('注册') }}</span>
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item class="login-animation5 mb5 login-agree" prop="agree" :rules="[{ validator: validatorAgree, trigger: ['change'] }]">
|
||||
<div class="my-flex my-flex-items-center f12">
|
||||
<el-checkbox v-model="form.agree">我已阅读并同意</el-checkbox>
|
||||
<div class="my-flex my-flex-items-center ml5">
|
||||
<el-link underline="never" type="primary" class="f12" target="_blank" href="https://zhontai.net/admin/introduce.html">服务协议</el-link>、
|
||||
<el-link underline="never" type="primary" class="f12" target="_blank" href="https://zhontai.net/admin/introduce.html">隐私政策</el-link>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/reg-email">
|
||||
import { reactive, toRefs, ref, defineAsyncComponent } from 'vue'
|
||||
import { AuthRegByMobileInput } from '/@/api/admin/data-contracts'
|
||||
import { AuthApi } from '/@/api/admin/Auth'
|
||||
import { verifyCnAndSpace } from '/@/utils/toolsValidate'
|
||||
import { validatorPwd, validatorAgree } from '/@/utils/validators'
|
||||
import { testMobile } from '/@/utils/test'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
const MyInputCode = defineAsyncComponent(() => import('/@/components/my-input-code/index.vue'))
|
||||
const isReg = defineModel('isReg', { type: Boolean, default: false })
|
||||
const hasPassword = defineModel('hasPassword', { type: Boolean, default: false })
|
||||
|
||||
const formRef = ref()
|
||||
const phoneRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
loading: false,
|
||||
form: {
|
||||
agree: false,
|
||||
mobile: '',
|
||||
code: '',
|
||||
codeId: '',
|
||||
password: '',
|
||||
corpName: '中台',
|
||||
} as AuthRegByMobileInput & { agree: false },
|
||||
})
|
||||
const { form } = toRefs(state)
|
||||
|
||||
//验证手机号
|
||||
const validatorMobile = (callback: Function) => {
|
||||
formRef.value.validateField('mobile', (isValid: boolean) => {
|
||||
if (!isValid) {
|
||||
phoneRef.value?.focus()
|
||||
return
|
||||
}
|
||||
callback?.()
|
||||
})
|
||||
}
|
||||
|
||||
//发送验证码
|
||||
const onSend = (codeId: string) => {
|
||||
state.form.codeId = codeId
|
||||
}
|
||||
|
||||
// 输入密码
|
||||
const onInputPassword = (val: string) => {
|
||||
state.form.password = verifyCnAndSpace(val)
|
||||
}
|
||||
|
||||
// 打开对话框
|
||||
const open = async () => {
|
||||
state.showDialog = true
|
||||
state.form = {} as AuthRegByMobileInput & { agree: false }
|
||||
}
|
||||
|
||||
// 注册
|
||||
const onReg = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
state.loading = true
|
||||
const res = await new AuthApi().regByMobile(state.form, { showSuccessMessage: false }).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
state.loading = false
|
||||
|
||||
if (res?.success) {
|
||||
ElMessage.success('注册成功')
|
||||
isReg.value = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.login-content-form {
|
||||
.login-title {
|
||||
margin-bottom: 50px;
|
||||
font-size: 27px;
|
||||
text-align: center;
|
||||
letter-spacing: 3px;
|
||||
color: var(--el-text-color-primary);
|
||||
position: relative;
|
||||
}
|
||||
.login-remind {
|
||||
color: #7f8792;
|
||||
margin-right: 5px;
|
||||
}
|
||||
@for $i from 1 through 5 {
|
||||
.login-animation#{$i} {
|
||||
opacity: 0;
|
||||
animation-name: error-num;
|
||||
animation-duration: 0.5s;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: calc($i/10) + s;
|
||||
}
|
||||
}
|
||||
.login-content-code {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
.login-content-submit {
|
||||
width: 100%;
|
||||
letter-spacing: 2px;
|
||||
font-weight: 300;
|
||||
margin-top: 15px;
|
||||
}
|
||||
.login-msg {
|
||||
color: var(--el-text-color-placeholder);
|
||||
}
|
||||
.f12 {
|
||||
font-size: 12px;
|
||||
}
|
||||
:deep() {
|
||||
.el-checkbox__input.is-checked + .el-checkbox__label {
|
||||
color: unset;
|
||||
}
|
||||
.login-agree.el-form-item--large .el-form-item__content {
|
||||
line-height: unset !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,183 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="600px"
|
||||
>
|
||||
<el-form :model="form" ref="formRef" label-width="80px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="上级地区">
|
||||
<RegionSelect v-model="form.parentIdList" v-model:parentId="form.parentId" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="类型" prop="level" :rules="[{ required: true, message: '请选择类型', trigger: ['change'] }]">
|
||||
<el-select v-model="form.level" placeholder="请选择类型" class="w100">
|
||||
<el-option v-for="item in state.regionLevelList" :key="item.label" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="地区名称" prop="name" :rules="[{ required: true, message: '请输入地区名称', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.name" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="地区简称">
|
||||
<el-input v-model="form.shortName" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="地区代码" prop="code" :rules="[{ required: true, message: '请输入地区代码', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.code" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="驻地">
|
||||
<el-input v-model="form.capital" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="人口">
|
||||
<el-input v-model="form.population" clearable>
|
||||
<template #append>万人</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="面积">
|
||||
<el-input v-model="form.area" clearable>
|
||||
<template #append>km²</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="区号">
|
||||
<el-input v-model="form.areaCode" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="邮编">
|
||||
<el-input v-model="form.zipCode" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="热门">
|
||||
<el-switch v-model="form.hot" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="排序">
|
||||
<el-input-number v-model="form.sort" class="w100" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="启用">
|
||||
<el-switch v-model="form.enabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, toRefs, ref, defineAsyncComponent } from 'vue'
|
||||
import { RegionUpdateInput, RegionGetOutput } from '/@/api/admin/data-contracts'
|
||||
import { RegionApi } from '/@/api/admin/Region'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { RegionLevel as RegionLevelEnum } from '/@/api/admin/enum-contracts'
|
||||
import { toOptionsByValue } from '/@/utils/enum'
|
||||
|
||||
const RegionSelect = defineAsyncComponent(() => import('./region-select.vue'))
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const formRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
regionLevelList: toOptionsByValue(RegionLevelEnum),
|
||||
form: {
|
||||
enabled: true,
|
||||
hot: false,
|
||||
} as RegionUpdateInput & RegionGetOutput,
|
||||
})
|
||||
|
||||
const { form } = toRefs(state)
|
||||
|
||||
// 打开对话框
|
||||
const open = async (row: any = {}) => {
|
||||
if (row.id > 0) {
|
||||
const res = await new RegionApi().get({ id: row.id }, { loading: true })
|
||||
|
||||
if (res?.success) {
|
||||
let formData = res.data as RegionUpdateInput & RegionGetOutput
|
||||
formData.parentId = formData.parentId && formData.parentId > 0 ? formData.parentId : undefined
|
||||
state.form = formData
|
||||
}
|
||||
} else {
|
||||
state.form = {
|
||||
enabled: true,
|
||||
hot: false,
|
||||
} as RegionUpdateInput & RegionGetOutput
|
||||
}
|
||||
|
||||
state.showDialog = true
|
||||
}
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
state.sureLoading = true
|
||||
let res = {} as any
|
||||
|
||||
state.form.parentId = state.form.parentId && state.form.parentId > 0 ? state.form.parentId : undefined
|
||||
if (state.form.id != undefined && state.form.id > 0) {
|
||||
res = await new RegionApi().update(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
} else {
|
||||
res = await new RegionApi().add(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
eventBus.emit('refreshRegion')
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
@ -1,59 +0,0 @@
|
||||
<template>
|
||||
<el-cascader
|
||||
placeholder="请选择上级地区"
|
||||
:options="state.regionList"
|
||||
:props="cascaderProps"
|
||||
:persistent="true"
|
||||
filterable
|
||||
clearable
|
||||
class="w100"
|
||||
@change="onChange"
|
||||
v-bind="$attrs"
|
||||
><template #default="{ data }">
|
||||
<span>{{ data.name }}</span>
|
||||
<my-icon v-if="data.hot" name="hot" color="#ea322b" size="12" class="ml5"></my-icon>
|
||||
</template>
|
||||
</el-cascader>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from 'vue'
|
||||
import type { CascaderProps } from 'element-plus'
|
||||
import { RegionApi } from '/@/api/admin/Region'
|
||||
|
||||
const parentId = defineModel('parentId', { type: Number, default: undefined })
|
||||
|
||||
const state = reactive({
|
||||
regionList: [] as any,
|
||||
})
|
||||
|
||||
const cascaderProps: CascaderProps = {
|
||||
checkStrictly: true,
|
||||
value: 'id',
|
||||
label: 'name',
|
||||
lazy: true,
|
||||
lazyLoad(node, resolve) {
|
||||
const value = node.value as number
|
||||
new RegionApi()
|
||||
.getChildList({ parentId: value > 0 ? value : 0 })
|
||||
.then((r) => {
|
||||
resolve(r.data as any)
|
||||
})
|
||||
.catch(() => {
|
||||
resolve([])
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
const onChange = (value: any) => {
|
||||
parentId.value = value && value.length > 0 ? value[value.length - 1] : undefined
|
||||
}
|
||||
|
||||
const reset = () => {
|
||||
state.regionList = []
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
reset,
|
||||
})
|
||||
</script>
|
||||
@ -1,330 +0,0 @@
|
||||
<template>
|
||||
<my-layout>
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form ref="filterFormRef" :model="state.filter" :inline="true" label-width="auto" :label-position="'left'" @submit.stop.prevent>
|
||||
<el-form-item label="" prop="parentId">
|
||||
<RegionSelect ref="regionSelectRef" v-model:parentId="state.filter.parentId" placeholder="上级地区" />
|
||||
</el-form-item>
|
||||
<el-form-item label="" prop="name">
|
||||
<el-input v-model="state.filter.name" placeholder="地区名" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="类型" prop="level">
|
||||
<el-select v-model="state.filter.level" empty-values="[null]" style="width: 100px" @change="onQuery">
|
||||
<el-option label="全部" :value="undefined" />
|
||||
<el-option v-for="item in state.regionLevelList" :key="item.label" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="enabled">
|
||||
<el-select v-model="state.filter.enabled" :empty-values="[null]" style="width: 100px" @change="onQuery">
|
||||
<el-option v-for="item in state.statusList" :key="item.name" :label="item.name" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="热门" prop="hot">
|
||||
<el-select v-model="state.filter.hot" :empty-values="[null]" style="width: 100px" @change="onQuery">
|
||||
<el-option v-for="item in state.hotList" :key="item.name" :label="item.name" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
<el-button icon="ele-RefreshLeft" text bg @click="onReset"> 重置 </el-button>
|
||||
<el-button v-if="auth('api:admin:region:add')" type="primary" icon="ele-Plus" @click="onAdd"> 新增 </el-button>
|
||||
<el-button v-if="auth('api:admin:region:sync-data')" ref="syncRef" :loading="state.sync.loading" type="primary" icon="ele-Refresh">
|
||||
同步
|
||||
</el-button>
|
||||
<el-popover
|
||||
v-if="auth('api:admin:region:sync-data')"
|
||||
ref="popoverRef"
|
||||
:virtual-ref="syncRef"
|
||||
trigger="click"
|
||||
virtual-triggering
|
||||
:width="300"
|
||||
>
|
||||
<p class="my-flex my-flex-items-center">
|
||||
确定要同步数据?
|
||||
<!-- 确定要同步至
|
||||
<el-select v-model="state.sync.regionLevel" :teleported="false" style="width: 75px; margin: 0px 5px">
|
||||
<el-option v-for="item in state.regionLevelList" :key="item.label" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
? -->
|
||||
</p>
|
||||
<div class="mt10" style="text-align: right">
|
||||
<el-button text @click="onSyncCancel">取消</el-button>
|
||||
<el-button type="primary" @click="onSync"> 确定 </el-button>
|
||||
</div>
|
||||
</el-popover>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table v-loading="state.loading" :data="state.dataList" default-expand-all highlight-current-row style="width: 100%" border>
|
||||
<el-table-column prop="name" label="地区名" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="code" label="代码" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="level" label="类型" min-width="140" show-overflow-tooltip :formatter="formatterEnum" />
|
||||
<el-table-column prop="pinyin" label="拼音" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="sort" label="排序" width="82" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="状态" width="88" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
v-if="auth('api:admin:region:set-enable')"
|
||||
v-model="row.enabled"
|
||||
:loading="row.loading"
|
||||
:active-value="true"
|
||||
:inactive-value="false"
|
||||
inline-prompt
|
||||
active-text="启用"
|
||||
inactive-text="禁用"
|
||||
:before-change="() => onSetEnable(row)"
|
||||
/>
|
||||
<template v-else>
|
||||
<el-tag type="success" v-if="row.enabled">启用</el-tag>
|
||||
<el-tag type="danger" v-else>禁用</el-tag>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="热门" width="88" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
v-if="auth('api:admin:region:set-hot')"
|
||||
v-model="row.hot"
|
||||
:loading="row.hotLoading"
|
||||
:active-value="true"
|
||||
:inactive-value="false"
|
||||
inline-prompt
|
||||
active-text="是"
|
||||
inactive-text="否"
|
||||
:before-change="() => onSetHot(row)"
|
||||
/>
|
||||
<template v-else>
|
||||
<el-tag type="success" v-if="row.enabled">是</el-tag>
|
||||
<el-tag type="danger" v-else>否</el-tag>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160" fixed="right" header-align="center" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button v-auth="'api:admin:region:update'" icon="ele-EditPen" text type="primary" @click="onEdit(row)">编辑</el-button>
|
||||
<el-button v-auth="'api:admin:region:delete'" icon="ele-Delete" text type="danger" @click="onDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="my-flex my-flex-end" style="margin-top: 10px">
|
||||
<el-pagination
|
||||
v-model:currentPage="state.pageInput.currentPage"
|
||||
v-model:page-size="state.pageInput.pageSize"
|
||||
:total="state.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
background
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<RegionForm ref="formRef" :title="state.formTitle"></RegionForm>
|
||||
</my-layout>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/region">
|
||||
import { ref, reactive, onMounted, getCurrentInstance, onBeforeMount, defineAsyncComponent } from 'vue'
|
||||
import { PageInputRegionGetPageInput, RegionGetPageOutput, RegionLevel } from '/@/api/admin/data-contracts'
|
||||
import { RegionLevel as RegionLevelEnum } from '/@/api/admin/enum-contracts'
|
||||
import { RegionApi } from '/@/api/admin/Region'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { auth } from '/@/utils/authFunction'
|
||||
import { toOptionsByValue, getDescByValue } from '/@/utils/enum'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
|
||||
// 引入组件
|
||||
const RegionForm = defineAsyncComponent(() => import('./components/region-form.vue'))
|
||||
const RegionSelect = defineAsyncComponent(() => import('./components/region-select.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const regionSelectRef = ref()
|
||||
const filterFormRef = ref<FormInstance>()
|
||||
const formRef = ref()
|
||||
const syncRef = ref()
|
||||
const popoverRef = ref()
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
sync: {
|
||||
loading: false,
|
||||
regionLevel: 2 as RegionLevel,
|
||||
},
|
||||
formTitle: '',
|
||||
total: 0,
|
||||
statusList: [
|
||||
{ name: '全部', value: undefined },
|
||||
{ name: '启用', value: true },
|
||||
{ name: '禁用', value: false },
|
||||
],
|
||||
hotList: [
|
||||
{ name: '全部', value: undefined },
|
||||
{ name: '是', value: true },
|
||||
{ name: '否', value: false },
|
||||
],
|
||||
regionLevelList: toOptionsByValue(RegionLevelEnum),
|
||||
filter: {
|
||||
parentId: undefined as number | undefined,
|
||||
name: '',
|
||||
enabled: undefined,
|
||||
hot: undefined,
|
||||
level: undefined,
|
||||
},
|
||||
pageInput: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
} as PageInputRegionGetPageInput,
|
||||
dataList: [] as Array<RegionGetPageOutput>,
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
await onQuery()
|
||||
|
||||
eventBus.off('refreshRegion')
|
||||
eventBus.on('refreshRegion', async () => {
|
||||
onQuery()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshRegion')
|
||||
})
|
||||
|
||||
const formatterEnum = (row: any, column: any, cellValue: any) => {
|
||||
return getDescByValue(RegionLevelEnum, cellValue)
|
||||
}
|
||||
|
||||
const onSizeChange = (val: number) => {
|
||||
state.pageInput.currentPage = 1
|
||||
state.pageInput.pageSize = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onCurrentChange = (val: number) => {
|
||||
state.pageInput.currentPage = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
state.pageInput.filter = state.filter
|
||||
const res = await new RegionApi().getPage(state.pageInput).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
|
||||
state.dataList = res?.data?.list ?? []
|
||||
state.total = res?.data?.total ?? 0
|
||||
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onReset = () => {
|
||||
regionSelectRef.value.reset()
|
||||
filterFormRef.value!.resetFields()
|
||||
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onAdd = () => {
|
||||
state.formTitle = '新增地区'
|
||||
formRef.value.open()
|
||||
}
|
||||
|
||||
const onEdit = (row: RegionGetPageOutput) => {
|
||||
state.formTitle = '编辑地区'
|
||||
formRef.value.open(row)
|
||||
}
|
||||
|
||||
const onDelete = (row: RegionGetPageOutput) => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要删除地区【${row.name}】?`)
|
||||
.then(async () => {
|
||||
await new RegionApi().delete({ id: row.id }, { loading: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
//启用或禁用
|
||||
const onSetEnable = (row: RegionGetPageOutput & { loading: boolean }) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
proxy.$modal
|
||||
.confirm(`确定要${row.enabled ? '禁用' : '启用'}【${row.name}】?`)
|
||||
.then(async () => {
|
||||
row.loading = true
|
||||
const res = await new RegionApi()
|
||||
.setEnable({ regionId: row.id, enabled: !row.enabled }, { showSuccessMessage: true })
|
||||
.catch(() => {
|
||||
reject(new Error('Error'))
|
||||
})
|
||||
.finally(() => {
|
||||
row.loading = false
|
||||
})
|
||||
if (res && res.success) {
|
||||
resolve(true)
|
||||
onQuery()
|
||||
} else {
|
||||
reject(new Error('Cancel'))
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
reject(new Error('Cancel'))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
//设置热门
|
||||
const onSetHot = (row: RegionGetPageOutput & { loading: boolean; hotLoading: boolean }) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
proxy.$modal
|
||||
.confirm(`确定要${row.hot ? '关闭' : '开启'}【${row.name}】热门?`)
|
||||
.then(async () => {
|
||||
row.hotLoading = true
|
||||
const res = await new RegionApi()
|
||||
.setHot({ regionId: row.id, hot: !row.hot }, { showSuccessMessage: true })
|
||||
.catch(() => {
|
||||
reject(new Error('Error'))
|
||||
})
|
||||
.finally(() => {
|
||||
row.hotLoading = false
|
||||
})
|
||||
if (res && res.success) {
|
||||
resolve(true)
|
||||
onQuery()
|
||||
} else {
|
||||
reject(new Error('Cancel'))
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
reject(new Error('Cancel'))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const onSyncCancel = () => {
|
||||
popoverRef.value?.hide?.()
|
||||
}
|
||||
|
||||
const onSync = async () => {
|
||||
onSyncCancel()
|
||||
state.sync.loading = true
|
||||
await new RegionApi()
|
||||
.syncData(state.sync.regionLevel, { showErrorMessage: false })
|
||||
.then(() => {
|
||||
proxy.$modal.msgSuccess(`同步完成`)
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {
|
||||
proxy.$modal.msgError(`同步失败`)
|
||||
})
|
||||
.finally(() => {
|
||||
state.sync.loading = false
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -1,272 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog v-model="state.showDialog" destroy-on-close :title="title" draggable :close-on-click-modal="false"
|
||||
:close-on-press-escape="false" width="600px">
|
||||
<el-form :model="form" ref="formRef" label-width="110px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="图片" prop="imgUrl">
|
||||
<el-upload class="remote-uploader" :action="remoteUrlAction"
|
||||
:headers="uploadHeaders" :data="{ autoUpdate: true }" :show-file-list="false"
|
||||
:before-upload="beforeUpload" :on-success="remoteUrlSuccess" :on-error="remoteUrlError">
|
||||
<img style="width: 100px; height: 100px;" :src="remoteUrl" />
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="站点" prop="site"
|
||||
:rules="[{ required: true, message: '请选择站点', trigger: ['blur', 'change'] }]">
|
||||
<el-select v-model="form.site" placeholder="请选择站点" clearable class="w100">
|
||||
<el-option v-for="item in state.Site" :key="item.code" :label="item.name"
|
||||
:value="item.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="名称" prop="name"
|
||||
:rules="[{ required: true, message: '请输入名称', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.name" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="IP地址" prop="ipAddress"
|
||||
:rules="[{ required: true, message: '请输入IP地址', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.ipAddress" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="域" prop="domain"
|
||||
:rules="[{ required: true, message: '请输入域', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.domain" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="用户名" prop="username">
|
||||
<el-input v-model="form.username" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/remote/form">
|
||||
import { reactive, toRefs, ref, getCurrentInstance, computed } from 'vue'
|
||||
import { RemoteUpdateInput, DictGetListOutput } from '/@/api/admin/data-contracts'
|
||||
import { RemoteApi } from '/@/api/admin/Remote'
|
||||
import { DictApi } from '/@/api/admin/Dict'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useUserInfo } from '/@/stores/userInfo'
|
||||
import pinia from '/@/stores/index'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { AxiosResponse } from 'axios'
|
||||
import type { UploadProps, UploadInstance, UploadUserFile } from 'element-plus'
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
const storesUserInfo = useUserInfo(pinia)
|
||||
const { userInfos } = storeToRefs(storesUserInfo)
|
||||
|
||||
/** 字典分类 */
|
||||
/** 字典分类 */
|
||||
const DictType = {
|
||||
RemoteSite: { dictTypeCode: 'RemoteSite', desc: '站点' },
|
||||
}
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const formRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
Site: [] as DictGetListOutput[] | null,
|
||||
form: {} as RemoteUpdateInput,
|
||||
remoteUrlLoading: false,
|
||||
updateLoading: false,
|
||||
token: storesUserInfo.getToken(),
|
||||
})
|
||||
|
||||
const { form } = toRefs(state)
|
||||
|
||||
|
||||
// 获取字典数据
|
||||
const getDictList = async () => {
|
||||
const res = await new DictApi().getList([DictType.RemoteSite.dictTypeCode]).catch(() => { })
|
||||
if (res?.success && res.data) {
|
||||
state.Site = res.data.remoteSite
|
||||
}
|
||||
}
|
||||
|
||||
// 打开对话框
|
||||
const open = async (row: Partial<RemoteUpdateInput> = { id: 0 }) => {
|
||||
await getDictList()
|
||||
let formData = cloneDeep(row) as RemoteUpdateInput
|
||||
if (row.id && row.id > 0) {
|
||||
const res = await new RemoteApi().get({ id: row.id })
|
||||
|
||||
if (res?.success) {
|
||||
formData = res.data as RemoteUpdateInput
|
||||
}
|
||||
} else {
|
||||
formData = {
|
||||
id: 0,
|
||||
imgUrl: '',
|
||||
site: '',
|
||||
name: '',
|
||||
ipAddress: '',
|
||||
domain: '',
|
||||
username: '',
|
||||
}
|
||||
}
|
||||
|
||||
state.form = formData
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
state.sureLoading = true
|
||||
let res = {} as any
|
||||
if (state.form.id != undefined && state.form.id > 0) {
|
||||
res = await new RemoteApi().update(state.form).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
} else {
|
||||
res = await new RemoteApi().add(state.form).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success === true) {
|
||||
eventBus.emit('refreshRemote')
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 上传头像请求头部
|
||||
const uploadHeaders = computed(() => {
|
||||
return {
|
||||
Authorization: 'Bearer ' + storesUserInfo.getToken()
|
||||
}
|
||||
})
|
||||
|
||||
// 头像地址
|
||||
const remoteUrl = computed(() => {
|
||||
return state.form.imgUrl || import.meta.env.VITE_API_URL + '/upload/2025-06-24/685abf87-d315-b804-0004-bfbb4a755111.png'
|
||||
})
|
||||
|
||||
// 上传头像请求url
|
||||
const remoteUrlAction = computed(() => {
|
||||
return import.meta.env.VITE_API_URL + '/api/admin/remote/remote-upload'
|
||||
})
|
||||
|
||||
const beforeUpload: UploadProps['beforeUpload'] = (file) => {
|
||||
state.token = storesUserInfo.getToken()
|
||||
console.log("🔍 ~ beforeUpload ~ state.token:", state.token)
|
||||
state.remoteUrlLoading = true
|
||||
return true
|
||||
}
|
||||
|
||||
const remoteUrlSuccess = (res: AxiosResponse) => {
|
||||
state.remoteUrlLoading = false
|
||||
if (!res?.success) {
|
||||
if (res.msg) {
|
||||
proxy.$modal.msgError(res.msg)
|
||||
}
|
||||
return
|
||||
}
|
||||
state.form.imgUrl = res.data
|
||||
}
|
||||
|
||||
// 上传头像失败
|
||||
const remoteUrlError = (error: any) => {
|
||||
state.remoteUrlLoading = false
|
||||
let message = ''
|
||||
if (error.message) {
|
||||
try {
|
||||
message = JSON.parse(error.message)?.msg
|
||||
} catch (err) {
|
||||
message = error.message || ''
|
||||
}
|
||||
}
|
||||
if (message) proxy.$modal.msgError(message)
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.remote-uploader {
|
||||
:deep(.el-upload--picture-card) {
|
||||
--el-upload-picture-card-size: 100px;
|
||||
width: var(--el-upload-picture-card-size);
|
||||
height: var(--el-upload-picture-card-size);
|
||||
line-height: var(--el-upload-picture-card-size);
|
||||
}
|
||||
|
||||
:deep(.el-upload-list--picture-card .el-upload-list__item) {
|
||||
width: var(--el-upload-picture-card-size);
|
||||
height: var(--el-upload-picture-card-size);
|
||||
}
|
||||
|
||||
:deep(.el-upload-list__item-thumbnail) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
:deep(.el-icon) {
|
||||
font-size: 20px;
|
||||
color: var(--el-text-color-regular);
|
||||
}
|
||||
|
||||
:deep(.el-upload--picture-card:hover) {
|
||||
border-color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
:deep(.el-upload-list__item-actions) {
|
||||
span {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,201 +0,0 @@
|
||||
<template>
|
||||
<my-layout>
|
||||
<div class="my-query-box mt8" style="position: relative">
|
||||
<el-card shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" label-width="auto" :label-position="'left'" @submit.stop.prevent>
|
||||
<el-form-item label="关键词">
|
||||
<el-input v-model="state.filter.name" placeholder="请输入名称、IP地址、域名" style="width: 350px" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="站点">
|
||||
<el-select v-model="state.filter.site" placeholder="请选择站点" clearable style="width: 150px" @change="onQuery">
|
||||
<el-option v-for="item in state.Site" :key="item.code" :label="item.name" :value="item.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建日期">
|
||||
<MyDateRange v-model:startDate="state.filter.startCreatedTime" v-model:endDate="state.filter.endCreatedTime" style="width: 230px" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:remote:add'" type="primary" icon="ele-Plus" @click="onAdd"> 新增 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<el-card class="my-fill mt8 el-card-table" shadow="never">
|
||||
<el-table ref="tableRef" v-loading="state.loading" :data="state.remoteListData" row-key="id" style="width: 100%" border>
|
||||
<el-table-column type="index" label="序号" width="60" :index="indexMethod" />
|
||||
<el-table-column prop="imgUrl" label="图片" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-image :src="row.imgUrl" fit="contain" style="width: 50px; height: 50px" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="name" label="名称" min-width="120" />
|
||||
<el-table-column prop="site" label="站点" min-width="120" />
|
||||
<el-table-column prop="ipAddress" label="IP地址" min-width="120" />
|
||||
<el-table-column prop="domain" label="域" min-width="120" />
|
||||
<el-table-column prop="username" label="用户名" min-width="120" />
|
||||
<el-table-column prop="createdTime" label="创建时间" :formatter="formatterTime" width="100" />
|
||||
<el-table-column label="操作" width="150" fixed="right" header-align="center" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button v-auth="'api:admin:remote:update'" icon="ele-Edit" text type="primary" @click="onUpdate(row)">修改</el-button>
|
||||
<el-button v-auth="'api:admin:remote:delete'" icon="ele-Delete" text type="danger" @click="onDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="my-flex my-flex-end" style="margin-top: 10px">
|
||||
<el-pagination
|
||||
v-model:currentPage="state.pageInput.currentPage"
|
||||
v-model:page-size="state.pageInput.pageSize"
|
||||
:total="state.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
background
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<remote-form ref="remoteFormRef" :title="state.remoteFormTitle"></remote-form>
|
||||
</my-layout>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/remote">
|
||||
import { ref, reactive, onMounted, onBeforeMount, getCurrentInstance, defineAsyncComponent } from 'vue'
|
||||
import { ElTable, ElMessageBox, ElMessage } from 'element-plus'
|
||||
import { RemoteGetOutput, PageInputRemoteGetPageInput, DictGetListOutput } from '/@/api/admin/data-contracts'
|
||||
import { RemoteApi } from '/@/api/admin/Remote'
|
||||
import { DictApi } from '/@/api/admin/Dict'
|
||||
import dayjs from 'dayjs'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
|
||||
// 引入组件
|
||||
const RemoteForm = defineAsyncComponent(() => import('./components/remote-form.vue'))
|
||||
const MyDateRange = defineAsyncComponent(() => import('/@/components/my-date-range/index.vue'))
|
||||
const MyUpload = defineAsyncComponent(() => import('/@/components/my-upload/index.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const remoteFormRef = ref()
|
||||
const tableRef = ref<InstanceType<typeof ElTable>>()
|
||||
|
||||
/** 字典分类 */
|
||||
const DictType = {
|
||||
RemoteSite: { dictTypeCode: 'RemoteSite', desc: '站点' },
|
||||
}
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
remoteFormTitle: '',
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
Site: [] as DictGetListOutput[],
|
||||
filter: {
|
||||
name: '',
|
||||
site: '',
|
||||
startCreatedTime: undefined,
|
||||
endCreatedTime: undefined,
|
||||
},
|
||||
total: 0,
|
||||
pageInput: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
filter: {},
|
||||
} as PageInputRemoteGetPageInput,
|
||||
remoteListData: [] as Array<RemoteGetOutput>,
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
getDictList()
|
||||
onQuery()
|
||||
eventBus.off('refreshRemote')
|
||||
eventBus.on('refreshRemote', async () => {
|
||||
onQuery()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshRemote')
|
||||
})
|
||||
|
||||
// 格式化时间
|
||||
const formatterTime = (row: any, column: any, cellValue: any) => {
|
||||
if (!cellValue) return ''
|
||||
return dayjs(cellValue).format('YYYY-MM-DD')
|
||||
}
|
||||
|
||||
// 序号
|
||||
const indexMethod = (index: number) => {
|
||||
return ((state.pageInput.currentPage || 1) - 1) * (state.pageInput.pageSize || 20) + index + 1
|
||||
}
|
||||
|
||||
// 查询
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
const res = await new RemoteApi()
|
||||
.getPage({
|
||||
...state.pageInput,
|
||||
filter: state.filter,
|
||||
})
|
||||
.catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
|
||||
state.loading = false
|
||||
|
||||
if (res?.success) {
|
||||
state.remoteListData = res.data?.list ?? []
|
||||
state.total = res.data?.total ?? 0
|
||||
}
|
||||
}
|
||||
|
||||
// 新增
|
||||
const onAdd = () => {
|
||||
state.remoteFormTitle = '新增'
|
||||
remoteFormRef.value.open()
|
||||
}
|
||||
|
||||
// 修改
|
||||
const onUpdate = (row: RemoteGetOutput) => {
|
||||
state.remoteFormTitle = '修改'
|
||||
remoteFormRef.value.open(row)
|
||||
}
|
||||
|
||||
// 删除
|
||||
const onDelete = async (row: RemoteGetOutput) => {
|
||||
ElMessageBox.confirm(`确定删除远程连接:【${row.name}】?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(async () => {
|
||||
const res = await new RemoteApi().delete({ id: row.id })
|
||||
if (res?.status === 200) {
|
||||
ElMessage.success('删除成功')
|
||||
onQuery()
|
||||
}
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
// 分页大小改变
|
||||
const onSizeChange = (val: number) => {
|
||||
state.pageInput.pageSize = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
// 分页改变
|
||||
const onCurrentChange = (val: number) => {
|
||||
state.pageInput.currentPage = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
// 获取字典数据
|
||||
const getDictList = async () => {
|
||||
const res = await new DictApi().getList([DictType.RemoteSite.dictTypeCode]).catch(() => {})
|
||||
if (res?.success && res.data) {
|
||||
state.Site = res.data.remoteSite || []
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,142 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="600px"
|
||||
>
|
||||
<el-form :model="form" ref="formRef" label-width="80px">
|
||||
<el-row :gutter="35">
|
||||
<el-col v-if="form.type === 2" :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="上级分组" prop="parentId" :rules="[{ required: true, message: '请选择上级分组', trigger: ['change'] }]">
|
||||
<el-tree-select
|
||||
v-model="form.parentId"
|
||||
:data="roleTreeData"
|
||||
node-key="id"
|
||||
:props="{ label: 'name' }"
|
||||
check-strictly
|
||||
default-expand-all
|
||||
render-after-expand
|
||||
fit-input-width
|
||||
clearable
|
||||
class="w100"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="名称" prop="name" :rules="[{ required: true, message: '请输入名称', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.name" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-if="form.type === 2" :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="编码" prop="code">
|
||||
<el-input v-model="form.code" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="排序">
|
||||
<el-input-number v-model="form.sort" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-if="form.type === 2" :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="说明">
|
||||
<el-input v-model="form.description" clearable type="textarea" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/role/form">
|
||||
import { reactive, toRefs, ref, PropType } from 'vue'
|
||||
import { RoleGetListOutput, RoleUpdateInput } from '/@/api/admin/data-contracts'
|
||||
import { RoleApi } from '/@/api/admin/Role'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
roleTreeData: {
|
||||
type: Array as PropType<RoleGetListOutput[]>,
|
||||
default: () => [],
|
||||
},
|
||||
})
|
||||
|
||||
const formRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
form: {} as RoleUpdateInput,
|
||||
})
|
||||
|
||||
const { form } = toRefs(state)
|
||||
|
||||
// 打开对话框
|
||||
const open = async (row: RoleUpdateInput = { id: 0 }) => {
|
||||
let formData = cloneDeep(row) as RoleUpdateInput
|
||||
if (row.id > 0) {
|
||||
const res = await new RoleApi().get({ id: row.id }, { loading: true })
|
||||
|
||||
if (res?.success) {
|
||||
formData = res.data as RoleUpdateInput
|
||||
formData.parentId = formData.parentId && formData.parentId > 0 ? formData.parentId : undefined
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
state.form = formData
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
state.sureLoading = true
|
||||
let res = {} as any
|
||||
state.form.parentId = state.form.parentId && state.form.parentId > 0 ? state.form.parentId : undefined
|
||||
if (state.form.id != undefined && state.form.id > 0) {
|
||||
res = await new RoleApi().update(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
} else {
|
||||
res = await new RoleApi().add(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
eventBus.emit('refreshRole')
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
@ -1,131 +0,0 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="innerTitle"
|
||||
append-to-body
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="480px"
|
||||
>
|
||||
<el-form :model="form" ref="formRef" label-width="80px" label-position="top">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="数据范围">
|
||||
<el-select key="dataScope" v-model="form.dataScope" placeholder="请选择" class="w100">
|
||||
<el-option v-for="item in state.dataScopeList" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
|
||||
<org-menu
|
||||
ref="orgRef"
|
||||
show-checkbox
|
||||
check-on-click-node
|
||||
v-model="form.orgIds"
|
||||
:default-checked-keys="form.orgIds"
|
||||
class="w100"
|
||||
v-show="form.dataScope === 5"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/role/components/set-role-data-scope">
|
||||
import { ref, toRefs, reactive, computed, defineAsyncComponent } from 'vue'
|
||||
import { RoleGetListOutput, RoleSetDataScopeInput } from '/@/api/admin/data-contracts'
|
||||
import { RoleApi } from '/@/api/admin/Role'
|
||||
|
||||
const OrgMenu = defineAsyncComponent(() => import('/@/views/admin/org/components/org-menu.vue'))
|
||||
|
||||
const orgRef = ref()
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const innerTitle = computed(() => {
|
||||
return props.title ? props.title : state.roleName ? `设置【${state.roleName}】数据权限` : '设置数据权限'
|
||||
})
|
||||
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
loading: false,
|
||||
sureLoading: false,
|
||||
permissionTreeData: [],
|
||||
roleId: 0 as number | undefined,
|
||||
roleName: '' as string | undefined | null,
|
||||
checkedKeys: [] as number[] | undefined | null,
|
||||
form: {} as RoleSetDataScopeInput,
|
||||
dataScopeList: [
|
||||
{ label: '全部', value: 1 },
|
||||
{ label: '本部门和下级部门', value: 2 },
|
||||
{ label: '本部门', value: 3 },
|
||||
{ label: '本人数据', value: 4 },
|
||||
{ label: '指定部门', value: 5 },
|
||||
],
|
||||
})
|
||||
|
||||
const { form } = toRefs(state)
|
||||
|
||||
// 打开对话框
|
||||
const open = async (role: RoleGetListOutput) => {
|
||||
state.roleId = role.id
|
||||
state.roleName = role.name
|
||||
|
||||
if ((role.id as number) > 0) {
|
||||
const res = await new RoleApi().get({ id: role.id }, { loading: true })
|
||||
|
||||
if (res?.success) {
|
||||
const data = res.data
|
||||
state.form = { roleId: data?.id, dataScope: data?.dataScope, orgIds: data?.orgIds } as RoleSetDataScopeInput
|
||||
|
||||
state.showDialog = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭对话框
|
||||
const close = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = async () => {
|
||||
state.sureLoading = true
|
||||
const res = await new RoleApi().setDataScope(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
state.showDialog = false
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
close,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-dialog__body) {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,215 +0,0 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
append-to-body
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="780px"
|
||||
>
|
||||
<template #header="{ close, titleId, titleClass }">
|
||||
<div class="my-header">
|
||||
<div :id="titleId" :class="titleClass">
|
||||
设置{{ innerTitle }}
|
||||
<el-select v-model="state.platform" placeholder="请选择所属平台" style="width: 100px" @change="onQuery">
|
||||
<el-option v-for="item in state.dictData[DictType.PlatForm.name]" :key="item.code" :label="item.name" :value="item.code" />
|
||||
</el-select>
|
||||
菜单权限
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div>
|
||||
<el-tree
|
||||
ref="permissionTreeRef"
|
||||
:data="state.permissionTreeData"
|
||||
node-key="id"
|
||||
show-checkbox
|
||||
highlight-current
|
||||
default-expand-all
|
||||
check-on-click-node
|
||||
:expand-on-click-node="false"
|
||||
:props="{ class: customNodeClass }"
|
||||
:default-checked-keys="state.checkedKeys"
|
||||
/>
|
||||
</div>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/role/components/set-role-menu">
|
||||
import { ref, reactive, getCurrentInstance, computed, markRaw } from 'vue'
|
||||
import { RoleGetListOutput, PermissionAssignInput, DictGetListOutput, PermissionGetPermissionListOutput } from '/@/api/admin/data-contracts'
|
||||
import { PermissionApi } from '/@/api/admin/Permission'
|
||||
import { ElTree } from 'element-plus'
|
||||
import { DictApi } from '/@/api/admin/Dict'
|
||||
import { PlatformType } from '/@/api/admin.extend/enum-contracts'
|
||||
|
||||
/** 字典分类 */
|
||||
const DictType = {
|
||||
PlatForm: { name: 'platform', desc: '平台' },
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const innerTitle = computed(() => {
|
||||
return props.title ? props.title : state.roleName ? `${state.roleName}` : ''
|
||||
})
|
||||
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
loading: false,
|
||||
sureLoading: false,
|
||||
permissionTreeData: [] as PermissionGetPermissionListOutput[],
|
||||
roleId: 0 as number | undefined,
|
||||
roleName: '' as string | undefined | null,
|
||||
checkedKeys: [],
|
||||
platform: PlatformType.Web.name,
|
||||
dictData: {
|
||||
[DictType.PlatForm.name]: [] as DictGetListOutput[] | null,
|
||||
},
|
||||
})
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
const permissionTreeRef = ref<InstanceType<typeof ElTree>>()
|
||||
|
||||
const getDictList = async () => {
|
||||
const res = await new DictApi().getList([DictType.PlatForm.name]).catch(() => {})
|
||||
if (res?.success && res.data) {
|
||||
state.dictData = markRaw(res.data)
|
||||
}
|
||||
}
|
||||
|
||||
const getRolePermissionList = async () => {
|
||||
const res = await new PermissionApi().getRolePermissionList({ roleId: state.roleId })
|
||||
state.checkedKeys = res?.success ? (res.data as never[]) : []
|
||||
}
|
||||
|
||||
// 打开对话框
|
||||
const open = async (role: RoleGetListOutput) => {
|
||||
await getDictList()
|
||||
state.roleId = role.id
|
||||
state.roleName = role.name
|
||||
proxy.$modal.loading()
|
||||
await onQuery()
|
||||
await getRolePermissionList()
|
||||
proxy.$modal.closeLoading()
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
// 关闭对话框
|
||||
const close = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
|
||||
const res = await new PermissionApi().getPermissionList({ platform: state.platform }).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
if (res && res.data && res.data.length > 0) {
|
||||
state.permissionTreeData = res.data
|
||||
} else {
|
||||
state.permissionTreeData = []
|
||||
}
|
||||
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const customNodeClass = (data: any, node: any) => {
|
||||
let isPenultimate = true
|
||||
for (const key in data.children) {
|
||||
if (data.children[key]?.children?.length ?? 0 > 0) {
|
||||
isPenultimate = false
|
||||
break
|
||||
}
|
||||
}
|
||||
return data.children?.length > 0 && isPenultimate ? `is-penultimate level${node.level}` : ''
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = async () => {
|
||||
state.sureLoading = true
|
||||
const permissionIds = permissionTreeRef.value?.getCheckedKeys(true)
|
||||
const input = {
|
||||
platform: state.platform,
|
||||
roleId: state.roleId,
|
||||
permissionIds: permissionIds,
|
||||
} as PermissionAssignInput
|
||||
const res = await new PermissionApi().assign(input, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
state.showDialog = false
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
close,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-dialog__body) {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
:deep(.is-penultimate) {
|
||||
.el-tree-node__children {
|
||||
padding-left: 65px;
|
||||
white-space: pre-wrap;
|
||||
line-height: 100%;
|
||||
|
||||
.el-tree-node {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.el-tree-node__content {
|
||||
padding-left: 12px !important;
|
||||
padding-right: 12px;
|
||||
|
||||
.el-tree-node__expand-icon.is-leaf {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.level1 {
|
||||
.el-tree-node__children {
|
||||
padding-left: 36px;
|
||||
}
|
||||
}
|
||||
&.level2 {
|
||||
.el-tree-node__children {
|
||||
padding-left: 54x;
|
||||
}
|
||||
}
|
||||
&.level3 {
|
||||
.el-tree-node__children {
|
||||
padding-left: 72px;
|
||||
}
|
||||
}
|
||||
&.level4 {
|
||||
.el-tree-node__children {
|
||||
padding-left: 90px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,333 +0,0 @@
|
||||
<template>
|
||||
<MySplitPanes>
|
||||
<pane size="50" min-size="30" max-size="70">
|
||||
<div class="my-flex-column w100 h100">
|
||||
<el-card class="my-query-box mt8" shadow="never">
|
||||
<el-form :inline="true" @submit.stop.prevent>
|
||||
<el-form-item label="角色名称">
|
||||
<el-input v-model="state.filter.roleName" placeholder="角色名称" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
<el-dropdown v-auth="'api:admin:role:add'" style="margin-left: 12px">
|
||||
<el-button type="primary"
|
||||
>新增<el-icon class="el-icon--right"><ele-ArrowDown /></el-icon
|
||||
></el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item @click="onAdd(1)">新增分组</el-dropdown-item>
|
||||
<el-dropdown-item @click="onAdd(2)">新增角色</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table
|
||||
ref="roleTableRef"
|
||||
v-loading="state.loading"
|
||||
:data="state.roleTreeData"
|
||||
row-key="id"
|
||||
default-expand-all
|
||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
highlight-current-row
|
||||
style="width: 100%"
|
||||
border
|
||||
@current-change="onCurrentChange"
|
||||
>
|
||||
<el-table-column prop="name" label="角色名称" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="sort" label="排序" width="82" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="100" fixed="right" header-align="center" align="right">
|
||||
<template #default="{ row }">
|
||||
<el-button v-if="row.type === 1" v-auth="'api:admin:role:add'" icon="ele-Plus" text type="primary" @click="onAdd(2, row)"></el-button>
|
||||
<my-dropdown-more icon-only v-auths="['api:admin:permission:assign', 'api:admin:role:update', 'api:admin:role:delete']">
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item v-if="row.type === 2 && auth('api:admin:permission:assign')" @click="onSetRoleMenu(row)"
|
||||
>菜单权限</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item v-if="row.type === 2" @click="onSetRoleDataScope(row)">数据权限</el-dropdown-item>
|
||||
<el-dropdown-item v-if="auth('api:admin:role:update')" @click="onEdit(row)"
|
||||
>编辑{{ row.type === 1 ? '分组' : '角色' }}</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item v-if="auth('api:admin:role:delete')" @click="onDelete(row)"
|
||||
>删除{{ row.type === 1 ? '分组' : '角色' }}</el-dropdown-item
|
||||
>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</my-dropdown-more>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
</pane>
|
||||
<pane>
|
||||
<div class="my-flex-column w100 h100">
|
||||
<el-card class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" @submit.stop.prevent>
|
||||
<el-form-item label="姓名">
|
||||
<el-input v-model="state.filter.name" placeholder="姓名" @keyup.enter="onGetRoleUserList" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onGetRoleUserList"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:role:add-role-user'" type="primary" icon="ele-Plus" @click="onAddUser"> 添加员工 </el-button>
|
||||
<el-button v-auth="'api:admin:role:remove-role-user'" type="danger" icon="ele-Delete" @click="onRemoveUser"> 移除员工 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<el-table
|
||||
ref="userTableRef"
|
||||
v-loading="state.userListLoading"
|
||||
:data="state.userListData"
|
||||
row-key="id"
|
||||
style="width: 100%"
|
||||
border
|
||||
@row-click="onUserRowClick"
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="name" label="姓名" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="mobile" label="手机号" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="email" label="邮箱" min-width="180" show-overflow-tooltip />
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
</pane>
|
||||
|
||||
<role-form ref="roleFormRef" :title="state.roleFormTitle" :role-tree-data="state.roleFormTreeData"></role-form>
|
||||
<user-select
|
||||
ref="userSelectRef"
|
||||
:title="`添加【${state.roleName}】员工`"
|
||||
multiple
|
||||
:sure-loading="state.sureLoading"
|
||||
@sure="onSureUser"
|
||||
></user-select>
|
||||
<set-role-menu ref="setRoleMenuRef"></set-role-menu>
|
||||
<set-role-data-scope ref="setRoleDataScopeRef"></set-role-data-scope>
|
||||
</MySplitPanes>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/role">
|
||||
import { ref, reactive, onMounted, getCurrentInstance, onBeforeMount, nextTick, defineAsyncComponent } from 'vue'
|
||||
import { RoleGetListOutput, RoleGetRoleUserListOutput, UserGetPageOutput, RoleAddRoleUserListInput, RoleType } from '/@/api/admin/data-contracts'
|
||||
import { RoleApi } from '/@/api/admin/Role'
|
||||
import { listToTree, filterTree } from '/@/utils/tree'
|
||||
import { ElTable } from 'element-plus'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { auth } from '/@/utils/authFunction'
|
||||
import { Pane } from 'splitpanes'
|
||||
|
||||
// 引入组件
|
||||
const RoleForm = defineAsyncComponent(() => import('./components/role-form.vue'))
|
||||
const SetRoleMenu = defineAsyncComponent(() => import('./components/set-role-menu.vue'))
|
||||
const SetRoleDataScope = defineAsyncComponent(() => import('./components/set-role-data-scope.vue'))
|
||||
const UserSelect = defineAsyncComponent(() => import('/@/views/admin/user/components/user-select.vue'))
|
||||
const MyDropdownMore = defineAsyncComponent(() => import('/@/components/my-dropdown-more/index.vue'))
|
||||
const MySplitPanes = defineAsyncComponent(() => import('/@/components/my-layout/split-panes.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const roleTableRef = ref()
|
||||
const roleFormRef = ref()
|
||||
const userTableRef = ref<InstanceType<typeof ElTable>>()
|
||||
const userSelectRef = ref()
|
||||
const setRoleMenuRef = ref()
|
||||
const setRoleDataScopeRef = ref()
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
userListLoading: false,
|
||||
sureLoading: false,
|
||||
roleFormTitle: '',
|
||||
filter: {
|
||||
name: '',
|
||||
roleName: '',
|
||||
},
|
||||
roleTreeData: [] as any,
|
||||
roleFormTreeData: [] as any,
|
||||
userListData: [] as RoleGetRoleUserListOutput[],
|
||||
roleId: undefined as number | undefined,
|
||||
roleName: '' as string | null | undefined,
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
onQuery()
|
||||
eventBus.off('refreshRole')
|
||||
eventBus.on('refreshRole', async () => {
|
||||
onQuery()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshRole')
|
||||
})
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
const res = await new RoleApi().getList().catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
if (res && res.data && res.data.length > 0) {
|
||||
state.roleTreeData = filterTree(listToTree(cloneDeep(res.data)), state.filter.roleName)
|
||||
state.roleFormTreeData = listToTree(cloneDeep(res.data).filter((a) => a.parentId === 0))
|
||||
if (state.roleTreeData.length > 0 && state.roleTreeData[0].children?.length > 0) {
|
||||
nextTick(() => {
|
||||
roleTableRef.value!.setCurrentRow(state.roleTreeData[0].children[0])
|
||||
})
|
||||
}
|
||||
} else {
|
||||
state.roleTreeData = []
|
||||
state.roleFormTreeData = []
|
||||
}
|
||||
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onAdd = (type: RoleType, row: RoleGetListOutput | undefined = undefined) => {
|
||||
switch (type) {
|
||||
case 1:
|
||||
state.roleFormTitle = '新增分组'
|
||||
roleFormRef.value.open({ type: 1 })
|
||||
break
|
||||
case 2:
|
||||
state.roleFormTitle = '新增角色'
|
||||
roleFormRef.value.open({ type: 2, parentId: row?.id, dataScope: 1 })
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const onEdit = (row: RoleGetListOutput) => {
|
||||
switch (row.type) {
|
||||
case 1:
|
||||
state.roleFormTitle = '编辑分组'
|
||||
break
|
||||
case 2:
|
||||
state.roleFormTitle = '编辑角色'
|
||||
break
|
||||
}
|
||||
roleFormRef.value.open(row)
|
||||
}
|
||||
|
||||
const onDelete = (row: RoleGetListOutput) => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要删除角色【${row.name}】?`)
|
||||
.then(async () => {
|
||||
await new RoleApi().delete({ id: row.id }, { loading: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onGetRoleUserList = async () => {
|
||||
state.userListLoading = true
|
||||
const res = await new RoleApi().getRoleUserList({ RoleId: state.roleId, Name: state.filter.name }).catch(() => {
|
||||
state.userListLoading = false
|
||||
})
|
||||
state.userListLoading = false
|
||||
if (res?.success) {
|
||||
if (res.data && res.data.length > 0) {
|
||||
state.userListData = res.data
|
||||
} else {
|
||||
state.userListData = []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const onCurrentChange = (currentRow: RoleGetListOutput, oldCurrentRow: RoleGetListOutput) => {
|
||||
if (!currentRow) {
|
||||
return
|
||||
}
|
||||
|
||||
if (currentRow?.id !== oldCurrentRow?.id && (oldCurrentRow?.id as number) > 0) {
|
||||
if ((currentRow?.parentId as number) === 0) {
|
||||
roleTableRef.value!.setCurrentRow(oldCurrentRow)
|
||||
}
|
||||
} else {
|
||||
if ((currentRow?.parentId as number) === 0) {
|
||||
roleTableRef.value!.setCurrentRow()
|
||||
}
|
||||
}
|
||||
|
||||
if ((currentRow?.parentId as number) !== 0 && (oldCurrentRow?.parentId as number) !== 0 && (currentRow?.id as number) > 0) {
|
||||
state.roleId = currentRow.id
|
||||
state.roleName = currentRow.name
|
||||
onGetRoleUserList()
|
||||
}
|
||||
}
|
||||
|
||||
const onUserRowClick = (row: RoleGetRoleUserListOutput) => {
|
||||
userTableRef.value!.toggleRowSelection(row, undefined)
|
||||
}
|
||||
|
||||
const onAddUser = () => {
|
||||
if (!((state.roleId as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择角色')
|
||||
return
|
||||
}
|
||||
userSelectRef.value.open({ roleId: state.roleId })
|
||||
}
|
||||
|
||||
const onRemoveUser = () => {
|
||||
if (!((state.roleId as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择角色')
|
||||
return
|
||||
}
|
||||
|
||||
const selectionRows = userTableRef.value!.getSelectionRows() as UserGetPageOutput[]
|
||||
|
||||
if (!((selectionRows.length as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择员工')
|
||||
return
|
||||
}
|
||||
|
||||
proxy.$modal
|
||||
.confirm(`确定要移除吗?`)
|
||||
.then(async () => {
|
||||
const userIds = selectionRows?.map((a) => a.id)
|
||||
const input = { roleId: state.roleId, userIds } as RoleAddRoleUserListInput
|
||||
await new RoleApi().removeRoleUser(input, { loading: true })
|
||||
onGetRoleUserList()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onSureUser = async (users: UserGetPageOutput[]) => {
|
||||
if (!(users?.length > 0)) {
|
||||
userSelectRef.value.close()
|
||||
return
|
||||
}
|
||||
|
||||
state.sureLoading = true
|
||||
const userIds = users?.map((a) => a.id)
|
||||
const input = { roleId: state.roleId, userIds } as RoleAddRoleUserListInput
|
||||
await new RoleApi().addRoleUser(input, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
state.sureLoading = false
|
||||
userSelectRef.value.close()
|
||||
onGetRoleUserList()
|
||||
}
|
||||
|
||||
const onSetRoleMenu = (role: RoleGetListOutput) => {
|
||||
if (!((role?.id as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择角色')
|
||||
return
|
||||
}
|
||||
setRoleMenuRef.value.open(role)
|
||||
}
|
||||
|
||||
const onSetRoleDataScope = (role: RoleGetListOutput) => {
|
||||
if (!((role?.id as number) > 0)) {
|
||||
proxy.$modal.msgWarning('请选择角色')
|
||||
return
|
||||
}
|
||||
setRoleDataScopeRef.value.open(role)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -1,73 +0,0 @@
|
||||
<template>
|
||||
<div class="w100 h100 my-msg-card-box">
|
||||
<div class="h100 my-msg-box">
|
||||
<div class="h100 w-e-text-container my-msg-content-box" v-html="state.msg.content"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/site-msg/detail">
|
||||
import { reactive, onMounted } from 'vue'
|
||||
import { SiteMsgApi } from '/@/api/admin/SiteMsg'
|
||||
import { SiteMsgGetContentOutput } from '/@/api/admin/data-contracts'
|
||||
import { LocationQuery, useRoute } from 'vue-router'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
query: {} as LocationQuery,
|
||||
msg: {} as SiteMsgGetContentOutput,
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
state.query = route.query
|
||||
await getContent()
|
||||
if (!state.msg?.isRead) await sedRead()
|
||||
})
|
||||
|
||||
const sedRead = async () => {
|
||||
const res = await new SiteMsgApi().setRead({ id: (state.query.id || 0) as number }).catch(() => {})
|
||||
if (res?.success) {
|
||||
eventBus.emit('refreshSiteMsg')
|
||||
eventBus.emit('checkUnreadMsg')
|
||||
}
|
||||
}
|
||||
|
||||
const getContent = async () => {
|
||||
state.loading = true
|
||||
|
||||
const res = await new SiteMsgApi().getContent({ id: Number(state.query.id) }).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
|
||||
state.msg = res?.data as SiteMsgGetContentOutput
|
||||
|
||||
state.loading = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.my-msg-card-box {
|
||||
padding: 10px;
|
||||
:deep() {
|
||||
.el-card__body {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.my-msg-box {
|
||||
padding: 20px;
|
||||
|
||||
.my-msg-content-box {
|
||||
min-width: 320px;
|
||||
max-width: 700px;
|
||||
border: 1px solid var(--next-border-color-light);
|
||||
background-color: var(--el-color-white);
|
||||
color: var(--el-color-black);
|
||||
margin: auto;
|
||||
padding: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,272 +0,0 @@
|
||||
<template>
|
||||
<MyLayout>
|
||||
<el-card v-show="state.showQuery" class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form class="my-form-inline" :inline="true" label-width="auto" @submit.stop.prevent>
|
||||
<el-form-item label="">
|
||||
<el-select v-model="state.filter.isRead" :empty-values="[undefined]" style="width: 90px" @change="onQuery">
|
||||
<el-option v-for="status in state.statusList" :key="status.name" :label="status.name" :value="status.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="分类">
|
||||
<el-tree-select
|
||||
v-model="state.filter.typeId"
|
||||
placeholder="请选择分类"
|
||||
:data="state.msgTypeTreeData"
|
||||
node-key="id"
|
||||
:props="{ label: 'name' }"
|
||||
check-strictly
|
||||
default-expand-all
|
||||
fit-input-width
|
||||
clearable
|
||||
filterable
|
||||
@change="onQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="标题">
|
||||
<el-input v-model="state.filter.title" placeholder="标题" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<div class="my-tools-box mb8 my-flex my-flex-between">
|
||||
<div>
|
||||
<el-button type="danger" :disabled="!isRowSelect" :loading="state.loadingBatchDelete" @click="onBatchDelete">删除</el-button>
|
||||
<el-button type="primary" :disabled="!isRowSelect" :loading="state.loadingBatchSetRead" @click="onBatchSetRead">标为已读</el-button>
|
||||
<el-button type="primary" :loading="state.loadingSetAllRead" @click="onSetAllRead">全部已读</el-button>
|
||||
</div>
|
||||
<div>
|
||||
<el-tooltip effect="dark" :content="state.showQuery ? '隐藏查询' : '显示查询'" placement="top">
|
||||
<el-button :icon="state.showQuery ? 'ele-ArrowUp' : 'ele-ArrowDown'" circle @click="state.showQuery = !state.showQuery" />
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
:data="state.msgList"
|
||||
style="width: 100%"
|
||||
v-loading="state.loading"
|
||||
row-key="id"
|
||||
default-expand-all
|
||||
border
|
||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="title" label="标题" min-width="120" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<div class="my-flex my-flex-items-center">
|
||||
<MyLink
|
||||
:model-value="{
|
||||
path: '/site-msg/detail',
|
||||
query: { id: row.id, tagsViewName: row.title },
|
||||
}"
|
||||
icon="ele-Message"
|
||||
:type="row.isRead ? '' : 'primary'"
|
||||
:bold="!row.isRead"
|
||||
>
|
||||
{{ row.title }}
|
||||
</MyLink>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="typeName" label="消息分类" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="receivedTime" label="接收时间" :formatter="formatterTime" min-width="160" show-overflow-tooltip />
|
||||
</el-table>
|
||||
<div class="my-flex my-flex-end" style="margin-top: 10px">
|
||||
<el-pagination
|
||||
v-model:currentPage="state.pageInput.currentPage"
|
||||
v-model:page-size="state.pageInput.pageSize"
|
||||
:total="state.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
background
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</MyLayout>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/site-msg">
|
||||
import { ref, reactive, onMounted, getCurrentInstance, onBeforeMount, computed, defineAsyncComponent } from 'vue'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import dayjs from 'dayjs'
|
||||
import { SiteMsgApi } from '/@/api/admin/SiteMsg'
|
||||
import { PageInputSiteMsgGetPageInput, SiteMsgGetPageOutput, MsgTypeGetListOutput } from '/@/api/admin/data-contracts'
|
||||
import { listToTree } from '/@/utils/tree'
|
||||
import { MsgTypeApi } from '/@/api/admin/MsgType'
|
||||
import { ElTable } from 'element-plus'
|
||||
|
||||
const MyLink = defineAsyncComponent(() => import('/@/components/my-link/index.vue'))
|
||||
|
||||
const tableRef = ref<InstanceType<typeof ElTable>>()
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
showQuery: true,
|
||||
loadingSetAllRead: false,
|
||||
loadingBatchDelete: false,
|
||||
loadingBatchSetRead: false,
|
||||
orgFormTitle: '',
|
||||
statusList: [
|
||||
{ name: '全部', value: null },
|
||||
{ name: '已读', value: true },
|
||||
{ name: '未读', value: false },
|
||||
],
|
||||
filter: {
|
||||
isRead: null,
|
||||
typeId: null,
|
||||
title: '',
|
||||
},
|
||||
pageInput: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
filter: {
|
||||
isRead: null,
|
||||
typeId: null,
|
||||
title: '',
|
||||
},
|
||||
} as PageInputSiteMsgGetPageInput,
|
||||
total: 0,
|
||||
msgList: [] as SiteMsgGetPageOutput[],
|
||||
msgTypeTreeData: [] as MsgTypeGetListOutput[],
|
||||
})
|
||||
|
||||
const selectionRows = computed(() => {
|
||||
return tableRef.value?.getSelectionRows()
|
||||
})
|
||||
|
||||
const rowSelectCount = computed(() => {
|
||||
return selectionRows.value?.length
|
||||
})
|
||||
|
||||
const isRowSelect = computed(() => {
|
||||
return rowSelectCount.value > 0
|
||||
})
|
||||
|
||||
const selectionIds = computed(() => {
|
||||
return selectionRows.value?.map((a: any) => a.id)
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
await getMsgTypes()
|
||||
onQuery()
|
||||
eventBus.off('refreshSiteMsg')
|
||||
eventBus.on('refreshSiteMsg', () => {
|
||||
onQuery()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshSiteMsg')
|
||||
})
|
||||
|
||||
const formatterTime = (row: any, column: any, cellValue: any) => {
|
||||
return cellValue ? dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss') : ''
|
||||
}
|
||||
|
||||
const getMsgTypes = async () => {
|
||||
const res = await new MsgTypeApi().getList().catch(() => {
|
||||
state.msgTypeTreeData = []
|
||||
})
|
||||
if (res?.success && res.data && res.data.length > 0) {
|
||||
state.msgTypeTreeData = listToTree(res.data)
|
||||
} else {
|
||||
state.msgTypeTreeData = []
|
||||
}
|
||||
}
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
if (state.pageInput.filter) {
|
||||
state.pageInput.filter = state.filter
|
||||
}
|
||||
|
||||
const res = await new SiteMsgApi().getPage(state.pageInput).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
|
||||
state.msgList = res?.data?.list ?? []
|
||||
state.total = res?.data?.total ?? 0
|
||||
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onSizeChange = (val: number) => {
|
||||
state.pageInput.currentPage = 1
|
||||
state.pageInput.pageSize = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onCurrentChange = (val: number) => {
|
||||
state.pageInput.currentPage = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onSetAllRead = () => {
|
||||
proxy.$modal
|
||||
.confirm(`确认标记所有消息为已读吗?`)
|
||||
.then(async () => {
|
||||
state.loadingSetAllRead = true
|
||||
const res = await new SiteMsgApi().setAllRead().catch(() => {
|
||||
state.loadingSetAllRead = false
|
||||
})
|
||||
|
||||
state.loadingSetAllRead = false
|
||||
if (res?.success) {
|
||||
proxy.$modal.msgSuccess('标记所有已读成功')
|
||||
onQuery()
|
||||
}
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onBatchDelete = () => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要删除消息?`)
|
||||
.then(async () => {
|
||||
state.loadingBatchDelete = true
|
||||
const res = await new SiteMsgApi().batchSoftDelete(selectionIds.value).catch(() => {
|
||||
state.loadingBatchDelete = false
|
||||
})
|
||||
state.loadingBatchDelete = false
|
||||
if (res?.success) {
|
||||
proxy.$modal.msgSuccess('删除成功')
|
||||
onQuery()
|
||||
}
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onBatchSetRead = () => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要标记消息为已读?`)
|
||||
.then(async () => {
|
||||
state.loadingBatchSetRead = true
|
||||
const res = await new SiteMsgApi().batchSetRead(selectionIds.value).catch(() => {
|
||||
state.loadingBatchSetRead = false
|
||||
})
|
||||
state.loadingBatchSetRead = false
|
||||
if (res?.success) {
|
||||
proxy.$modal.msgSuccess('标记已读成功')
|
||||
onQuery()
|
||||
}
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.my-form-inline {
|
||||
:deep() {
|
||||
.el-select {
|
||||
--el-select-width: 192px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,112 +0,0 @@
|
||||
<template>
|
||||
<el-drawer v-model="state.showDialog" direction="rtl" destroy-on-close :size="size">
|
||||
<template #header="{ titleId, titleClass }">
|
||||
<h4 :id="titleId" :class="titleClass">{{ title }}</h4>
|
||||
<el-icon v-if="state.isFull" class="el-drawer__btn" @click="state.isFull = !state.isFull" title="还原"><ele-CopyDocument /></el-icon>
|
||||
<el-icon v-else class="el-drawer__btn" @click="state.isFull = !state.isFull" title="最大化"><ele-FullScreen /></el-icon>
|
||||
</template>
|
||||
<div class="my-fill h100" style="padding: 20px">
|
||||
<div class="mb10 my-flex my-flex-end">
|
||||
<el-button type="primary" @click="onJsonShell">Shell</el-button>
|
||||
<el-button type="primary" @click="onJsonHttp">Http</el-button>
|
||||
</div>
|
||||
<MyJsonEditor ref="jsonEditorRef" v-model="state.content" :options="{ modes: [] }"></MyJsonEditor>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div style="flex: auto; padding: 20px !important">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure">确 定</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, computed, ref } from 'vue'
|
||||
import MyJsonEditor from '/@/components/my-json-editor/index.vue'
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: 'Json编辑器',
|
||||
},
|
||||
})
|
||||
|
||||
const emits = defineEmits(['sure'])
|
||||
|
||||
const jsonEditorRef = ref()
|
||||
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
isFull: false,
|
||||
isMobile: document.body.clientWidth < 1000,
|
||||
content: '',
|
||||
topic: '',
|
||||
})
|
||||
|
||||
const size = computed(() => {
|
||||
return state.isMobile ? '100%' : state.isFull ? '100%' : '50%'
|
||||
})
|
||||
|
||||
const onJsonShell = () => {
|
||||
state.topic = '[shell]'
|
||||
state.content = `{
|
||||
"desc": "任务描述",
|
||||
"arguments": "-plaintext -d \\"{ \\\\\\"id\\\\\\": 1 }\\" \${grpcAddress} YourNamespace.YourGrpcService/YourMethod",
|
||||
"moduleName": "YourModuleName"
|
||||
}`
|
||||
jsonEditorRef.value.jsonEditor.set(JSON.parse(state.content))
|
||||
}
|
||||
|
||||
const onJsonHttp = () => {
|
||||
state.topic = '[系统预留]Http请求'
|
||||
state.content = `{
|
||||
"method": "get",
|
||||
"url": "",
|
||||
"header": {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
"body": "{}"
|
||||
}`
|
||||
jsonEditorRef.value.jsonEditor.set(JSON.parse(state.content))
|
||||
}
|
||||
|
||||
// 打开对话框
|
||||
const open = (task: any) => {
|
||||
if (task) {
|
||||
state.topic = task.topic || ''
|
||||
state.content = task.body || ''
|
||||
}
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
emits('sure', { topic: state.topic, body: state.content })
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.el-alert {
|
||||
border-width: 0px !important;
|
||||
margin-left: 110px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.el-drawer__btn {
|
||||
cursor: pointer;
|
||||
margin-right: 8px;
|
||||
&:hover {
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,264 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="600px"
|
||||
>
|
||||
<el-form :model="form" ref="formRef" label-width="110px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="任务标题" prop="topic" :rules="[{ required: true, message: '请输入任务标题', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.topic" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="任务参数" prop="body">
|
||||
<template #label>
|
||||
<div class="my-flex-y-center">
|
||||
任务参数<el-tooltip effect="dark" placement="top" hide-after="0">
|
||||
<template #content>设置Json数据</template>
|
||||
<SvgIcon name="ele-InfoFilled" class="ml5" />
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-input v-model="form.body" clearable type="textarea" rows="6" />
|
||||
<el-link icon="ele-Edit" underline="never" style="line-height: normal; margin-top: 5px" @click="onOpenJson">Json</el-link>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item prop="alarmEmail">
|
||||
<template #label>
|
||||
<div class="my-flex-y-center">
|
||||
报警邮件<el-tooltip effect="dark" placement="top" hide-after="0">
|
||||
<template #content>多个邮件地址用逗号分隔</template>
|
||||
<SvgIcon name="ele-InfoFilled" class="ml5" />
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-input v-model="form.alarmEmail" clearable placeholder="多个邮件地址用逗号分隔" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item prop="failRetryCount">
|
||||
<template #label>
|
||||
<div class="my-flex-y-center">失败重试次数</div>
|
||||
</template>
|
||||
<el-input-number v-model="form.failRetryCount" :min="0" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item prop="failRetryCount">
|
||||
<template #label>
|
||||
<div class="my-flex-y-center">重试间隔(秒)</div>
|
||||
</template>
|
||||
<el-input-number v-model="form.failRetryInterval" :min="0" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item prop="round" :rules="[{ required: true, message: '请输入执行轮数', trigger: ['blur', 'change'] }]">
|
||||
<template #label>
|
||||
<div class="my-flex-y-center">
|
||||
执行轮次<el-tooltip effect="dark" placement="top" hide-after="0">
|
||||
<template #content>循环多少次,-1为无限循环</template>
|
||||
<SvgIcon name="ele-InfoFilled" class="ml5" />
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-input-number v-model="form.round" :min="-1" :disabled="form.interval === 21" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="定时类型" prop="interval" :rules="[{ required: true, message: '请选择定时类型', trigger: ['change'] }]">
|
||||
<el-select v-model="form.interval" style="width: 150px" @change="onIntervalChange">
|
||||
<el-option v-for="item in state.intervals" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-space fill class="w100">
|
||||
<el-form-item
|
||||
label="定时参数"
|
||||
prop="intervalArgument"
|
||||
:rules="[{ required: true, message: '请输入定时参数', trigger: ['blur', 'change'] }]"
|
||||
>
|
||||
<el-input v-model="form.intervalArgument" clearable>
|
||||
<template #append v-if="form.interval === 21">
|
||||
<el-button icon="ele-Clock" @click="onOpenCronDialog" />
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-alert v-if="form.interval === 1" type="info" :closable="false">
|
||||
设置 5 则每5秒触发,执行N次
|
||||
<br />
|
||||
设置 5, 5, 10, 10, 60, 60 则每次按不同的间隔秒数触发,执行6次
|
||||
</el-alert>
|
||||
<el-alert v-else-if="form.interval === 11" type="info" :closable="false"> 设置 08:00:00 则每天 08:00:00 触发,执行N次 </el-alert>
|
||||
<el-alert v-else-if="form.interval === 12" type="info" :closable="false">
|
||||
设置 1:08:00:00 则每周一 08:00:00 触发
|
||||
<br />
|
||||
设置 0:08:00:00 则每周日 08:00:00 触发
|
||||
</el-alert>
|
||||
<el-alert v-else-if="form.interval === 13" type="info" :closable="false">
|
||||
设置 1:08:00:00 则每月1日 08:00:00 触发
|
||||
<br />
|
||||
设置 -1:08:00:00 则每月最后一日 08:00:00 触发
|
||||
</el-alert>
|
||||
<el-alert v-else-if="form.interval === 21" type="info" :closable="false">
|
||||
设置 0/10 * * * * ? 则从0秒开始每10秒执行一次
|
||||
<br />
|
||||
<pre style="line-height: 20px">
|
||||
new FreeSchedulerBuilder()
|
||||
...
|
||||
.UseCustomInterval(task =>
|
||||
{
|
||||
//利用 cron 功能库解析 task.IntervalArgument 得到下一次执行时间
|
||||
//与当前时间相减,得到 TimeSpan,若返回 null 则任务完成
|
||||
return TimeSpan.FromSeconds(5);
|
||||
})
|
||||
.Build();
|
||||
</pre
|
||||
>
|
||||
</el-alert>
|
||||
</el-space>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<MyCronDialog ref="myCronDialogRef" @fill="onFillCron"></MyCronDialog>
|
||||
|
||||
<JsonEditorDialog ref="jsonEditorDialogRef" @sure="onSureArgs"></JsonEditorDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/task/form">
|
||||
import { reactive, toRefs, ref, defineAsyncComponent } from 'vue'
|
||||
import { TaskUpdateInput } from '/@/api/admin/data-contracts'
|
||||
import { TaskApi } from '/@/api/admin/Task'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
|
||||
const MyCronDialog = defineAsyncComponent(() => import('/@/components/my-cron/dialog.vue'))
|
||||
|
||||
const JsonEditorDialog = defineAsyncComponent(() => import('./json-editor-dialog.vue'))
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const formRef = ref()
|
||||
const myCronDialogRef = ref()
|
||||
const jsonEditorDialogRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
form: {} as TaskUpdateInput,
|
||||
intervals: [
|
||||
{ label: '按秒触发', value: 1 },
|
||||
{ label: '每天', value: 11 },
|
||||
{ label: '每周几', value: 12 },
|
||||
{ label: '每月第几日', value: 13 },
|
||||
{ label: 'Cron表达式', value: 21 },
|
||||
],
|
||||
})
|
||||
|
||||
const { form } = toRefs(state)
|
||||
|
||||
//确定Cron表达式
|
||||
const onFillCron = (value: any) => {
|
||||
form.value.intervalArgument = value
|
||||
}
|
||||
|
||||
//确定任务参数
|
||||
const onSureArgs = (task: any) => {
|
||||
form.value.topic = task.topic
|
||||
form.value.body = task.body
|
||||
}
|
||||
|
||||
// 打开对话框
|
||||
const open = async (row: TaskUpdateInput = { id: '' }) => {
|
||||
let formData = cloneDeep(row) as TaskUpdateInput
|
||||
if (row.id) {
|
||||
const res = await new TaskApi().get({ id: row.id }, { loading: true })
|
||||
|
||||
if (res?.success) {
|
||||
formData = res.data as TaskUpdateInput
|
||||
}
|
||||
}
|
||||
|
||||
state.form = formData
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
//打开Cron对话框
|
||||
const onOpenCronDialog = () => {
|
||||
myCronDialogRef.value.open(state.form.intervalArgument)
|
||||
}
|
||||
|
||||
//打开Json对话框
|
||||
const onOpenJson = () => {
|
||||
jsonEditorDialogRef.value.open(state.form)
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
state.sureLoading = true
|
||||
let res = {} as any
|
||||
if (state.form.id) {
|
||||
res = await new TaskApi().update(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
} else {
|
||||
res = await new TaskApi().add(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
eventBus.emit('refreshTask')
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const onIntervalChange = () => {
|
||||
state.form.intervalArgument = ''
|
||||
if (state.form.interval === 21) state.form.round = -1
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.el-alert {
|
||||
border-width: 0px !important;
|
||||
margin-left: 110px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,133 +0,0 @@
|
||||
<template>
|
||||
<el-drawer v-model="state.showDialog" direction="ltr" :size="size">
|
||||
<template #header="{ titleId, titleClass }">
|
||||
<h4 :id="titleId" :class="titleClass">{{ title }}</h4>
|
||||
<el-icon v-if="state.isFull" class="el-drawer__btn" @click="state.isFull = !state.isFull" title="还原"><ele-CopyDocument /></el-icon>
|
||||
<el-icon v-else class="el-drawer__btn" @click="state.isFull = !state.isFull" title="最大化"><ele-FullScreen /></el-icon>
|
||||
</template>
|
||||
<div class="my-fill h100">
|
||||
<el-table v-loading="state.loading" :data="state.taskLogListData" row-key="id" style="width: 100%">
|
||||
<el-table-column prop="round" label="当前次数" width="90" />
|
||||
<el-table-column prop="success" label="状态" width="90">
|
||||
<template #default="{ row }">
|
||||
<el-tag v-if="!row.success" type="danger" disable-transitions>失败</el-tag>
|
||||
<el-tag v-else type="success" disable-transitions>成功</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="elapsedMilliseconds" label="耗时(ms)" width="100" />
|
||||
<el-table-column prop="exception" label="异常" min-width="180" />
|
||||
|
||||
<el-table-column prop="createTime" label="创建时间" :formatter="formatterTime" width="160" />
|
||||
<el-table-column prop="remark" label="备注" min-width="180" />
|
||||
</el-table>
|
||||
<div class="my-flex my-flex-end" style="margin-top: 20px; padding: 0px 10px">
|
||||
<el-pagination
|
||||
v-model:currentPage="state.pageInput.currentPage"
|
||||
v-model:page-size="state.pageInput.pageSize"
|
||||
:total="state.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
background
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div style="flex: auto; padding: 20px !important">
|
||||
<el-button @click="onQuery" type="primary">刷 新</el-button>
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/taskLog">
|
||||
import { reactive, computed } from 'vue'
|
||||
import { ResultOutputPageOutputTaskLog, PageInputTaskLogGetPageInput, TaskGetPageOutput } from '/@/api/admin/data-contracts'
|
||||
import { TaskLogApi } from '/@/api/admin/TaskLog'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
loading: false,
|
||||
isFull: false,
|
||||
isMobile: document.body.clientWidth < 1000,
|
||||
taskLogFormTitle: '',
|
||||
total: 0,
|
||||
pageInput: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
filter: {
|
||||
taskId: null,
|
||||
},
|
||||
} as PageInputTaskLogGetPageInput,
|
||||
taskLogListData: [] as Array<ResultOutputPageOutputTaskLog>,
|
||||
})
|
||||
|
||||
const size = computed(() => {
|
||||
return state.isMobile ? '100%' : state.isFull ? '100%' : '50%'
|
||||
})
|
||||
|
||||
const formatterTime = (row: any, column: any, cellValue: any) => {
|
||||
return dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
const res = await new TaskLogApi().getPage(state.pageInput).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
|
||||
state.taskLogListData = res?.data?.list ?? []
|
||||
state.total = res?.data?.total ?? 0
|
||||
state.loading = false
|
||||
}
|
||||
const onSizeChange = (val: number) => {
|
||||
state.pageInput.currentPage = 1
|
||||
state.pageInput.pageSize = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onCurrentChange = (val: number) => {
|
||||
state.pageInput.currentPage = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
// 打开对话框
|
||||
const open = (row: TaskGetPageOutput) => {
|
||||
if (state.pageInput.filter) state.pageInput.filter.taskId = row.id
|
||||
onQuery()
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.my-drawer-body-padding {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.el-drawer__btn {
|
||||
cursor: pointer;
|
||||
margin-right: 8px;
|
||||
&:hover {
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,397 +0,0 @@
|
||||
<template>
|
||||
<my-layout>
|
||||
<div class="my-query-box mt8" style="position: relative">
|
||||
<el-card shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" label-width="auto" :label-position="'left'" @submit.stop.prevent>
|
||||
<el-form-item label="任务分组">
|
||||
<el-select v-model="state.filter.groupName" :empty-values="[null, undefined]" style="width: 120px" @change="onQuery">
|
||||
<el-option v-for="group in state.groupList" :key="group.name" :label="group.name" :value="group.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="任务名称">
|
||||
<el-input v-model="state.filter.taskName" placeholder="任务名称" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="任务状态">
|
||||
<el-select v-model="state.filter.taskStatus" :empty-values="[null]" style="width: 120px" @change="onQuery">
|
||||
<el-option v-for="status in state.statusList" :key="status.name" :label="status.name" :value="status.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建日期">
|
||||
<MyDateRange v-model:startDate="state.filter.startAddTime" v-model:endDate="state.filter.endAddTime" style="width: 230px" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:task:add'" type="primary" icon="ele-Plus" @click="onAdd"> 新增 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div
|
||||
v-show="rowSelectCount > 0"
|
||||
class="my-flex my-flex-items-center pl10"
|
||||
style="position: absolute; top: 0; bottom: 0; left: 0; right: 0; background-color: var(--el-bg-color)"
|
||||
>
|
||||
<el-text class="mx-1"
|
||||
>已选中 <el-text class="mx-1" type="primary">{{ rowSelectCount }}</el-text> 项</el-text
|
||||
>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button v-auth="'api:admin:task:run'" icon="ele-Promotion" text type="primary" @click="onBatchRun">执行</el-button>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button v-auth="'api:admin:task:pause'" icon="ele-CaretRight" text type="primary" @click="onBatchStart">启动</el-button>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button v-auth="'api:admin:task:resume'" icon="ele-VideoPause" text type="primary" @click="onBatchPause">停止</el-button>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button v-auth="'api:admin:task:delete'" icon="ele-Delete" text type="danger" @click="onBatchDelete">删除</el-button>
|
||||
|
||||
<el-button size="large" link @click="onClear" style="position: absolute; right: 6px; top: 6px">
|
||||
<svgIcon name="ele-Close" size="18"></svgIcon>
|
||||
</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<el-card class="my-fill mt8 el-card-table" shadow="never">
|
||||
<el-table ref="tableRef" v-loading="state.loading" :data="state.taskListData" row-key="id" style="width: 100%" border>
|
||||
<el-table-column type="selection" width="40" />
|
||||
<el-table-column type="index" label="序号" width="60" :index="indexMethod" />
|
||||
<el-table-column prop="topic" label="任务名称" min-width="260">
|
||||
<template #default="{ row }">
|
||||
<div>{{ row.id }}</div>
|
||||
<div>{{ row.topic }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" label="任务状态" width="95">
|
||||
<template #default="{ row }">
|
||||
<el-tag v-if="row.status === 0 || row.status === 'Running'" disable-transitions>运行中</el-tag>
|
||||
<el-tag v-if="row.status === 1 || row.status === 'Paused'" type="info" disable-transitions>停止</el-tag>
|
||||
<el-tag v-if="row.status === 2 || row.status === 'Completed'" type="success" disable-transitions>完成</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="round" label="运行次数" width="90" />
|
||||
<el-table-column prop="currentRound" label="当前次数" width="90" />
|
||||
<el-table-column prop="errorTimes" label="失败次数" width="90">
|
||||
<template #default="{ row }">
|
||||
<el-text class="mx-1" type="danger">{{ row.errorTimes }}</el-text>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="body" label="任务数据" min-width="260" />
|
||||
<el-table-column prop="intervalArgument" label="定时参数" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<div>{{ formatterInterval(row.interval) }}</div>
|
||||
<div>{{ row.intervalArgument }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="创建时间" :formatter="formatterTime" width="100" />
|
||||
<el-table-column prop="lastRunTime" label="最后运行时间" :formatter="formatterTime" width="120" />
|
||||
<el-table-column label="操作" width="210" fixed="right" header-align="center" align="center">
|
||||
<template #default="{ row }">
|
||||
<div class="my-flex">
|
||||
<el-button v-auth="'api:admin:task-log:get-page'" icon="ele-Tickets" text type="primary" @click="onShowLogs(row)">日志</el-button>
|
||||
<el-button v-auth="'api:admin:task:update'" icon="ele-Edit" text type="primary" @click="onUpdate(row)">修改</el-button>
|
||||
<el-button v-auth="'api:admin:task:delete'" icon="ele-Delete" text type="danger" @click="onDelete(row)">删除</el-button>
|
||||
</div>
|
||||
|
||||
<div class="my-flex">
|
||||
<el-button v-auth="'api:admin:task:run'" icon="ele-Promotion" text type="primary" @click="onRun(row)">执行</el-button>
|
||||
<el-button v-auth="'api:admin:task:update'" icon="ele-CopyDocument" text type="primary" @click="onCopy(row)"> 复制 </el-button>
|
||||
<el-button
|
||||
v-if="row.status === 1 || row.status === 'Paused'"
|
||||
v-auth="'api:admin:task:pause'"
|
||||
icon="ele-CaretRight"
|
||||
text
|
||||
type="primary"
|
||||
@click="onStart(row)"
|
||||
>
|
||||
启动
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="row.status === 0 || row.status === 'Running'"
|
||||
v-auth="'api:admin:task:resume'"
|
||||
icon="ele-VideoPause"
|
||||
text
|
||||
type="primary"
|
||||
@click="onPause(row)"
|
||||
>
|
||||
停止
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="my-flex my-flex-end" style="margin-top: 10px">
|
||||
<el-pagination
|
||||
v-model:currentPage="state.pageInput.currentPage"
|
||||
v-model:page-size="state.pageInput.pageSize"
|
||||
:total="state.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
background
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<task-logs ref="taskLogsRef" :title="state.taskLogsTitle"></task-logs>
|
||||
<task-form ref="taskFormRef" :title="state.taskFormTitle"></task-form>
|
||||
</my-layout>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/task">
|
||||
import { ref, reactive, onMounted, onBeforeMount, getCurrentInstance, defineAsyncComponent, computed } from 'vue'
|
||||
import { ElTable, ElMessage } from 'element-plus'
|
||||
import { TaskGetPageOutput, PageInputTaskGetPageInput, TaskStatus } from '/@/api/admin/data-contracts'
|
||||
import { TaskApi } from '/@/api/admin/Task'
|
||||
import dayjs from 'dayjs'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
|
||||
// 引入组件
|
||||
const TaskLogs = defineAsyncComponent(() => import('./components/task-logs.vue'))
|
||||
const TaskForm = defineAsyncComponent(() => import('./components/task-form.vue'))
|
||||
const MyDateRange = defineAsyncComponent(() => import('/@/components/my-date-range/index.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const taskLogsRef = ref()
|
||||
const taskFormRef = ref()
|
||||
const tableRef = ref<InstanceType<typeof ElTable>>()
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
taskFormTitle: '',
|
||||
filter: {
|
||||
taskName: '',
|
||||
groupName: '',
|
||||
taskStatus: undefined as TaskStatus | undefined,
|
||||
startAddTime: undefined,
|
||||
endAddTime: undefined,
|
||||
},
|
||||
total: 0,
|
||||
pageInput: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
} as PageInputTaskGetPageInput,
|
||||
taskListData: [] as Array<TaskGetPageOutput>,
|
||||
taskLogsTitle: '',
|
||||
groupList: [{ name: '全部', value: '' }],
|
||||
statusList: [
|
||||
{ name: '全部', value: undefined },
|
||||
{ name: '运行中', value: 0 },
|
||||
{ name: '停止', value: 1 },
|
||||
{ name: '已完成', value: 2 },
|
||||
],
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
onQuery()
|
||||
eventBus.off('refreshTask')
|
||||
eventBus.on('refreshTask', async () => {
|
||||
onQuery()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshTask')
|
||||
})
|
||||
|
||||
const rowSelectCount = computed(() => {
|
||||
return tableRef.value?.getSelectionRows().length
|
||||
})
|
||||
|
||||
const taskIds = computed(() => {
|
||||
return tableRef.value?.getSelectionRows().map((a: any) => a.id)
|
||||
})
|
||||
|
||||
const indexMethod = (index: number) => {
|
||||
if (state.pageInput.currentPage && state.pageInput.pageSize) return index + 1 + (state.pageInput.currentPage - 1) * state.pageInput.pageSize
|
||||
else return index
|
||||
}
|
||||
|
||||
const formatterInterval = (cellValue: any) => {
|
||||
let label = ''
|
||||
switch (cellValue) {
|
||||
case 1:
|
||||
case 'SEC':
|
||||
label = '按秒触发'
|
||||
break
|
||||
case 11:
|
||||
case 'RunOnDay':
|
||||
label = '每天'
|
||||
break
|
||||
case 12:
|
||||
case 'RunOnWeek':
|
||||
label = '每周几'
|
||||
break
|
||||
case 13:
|
||||
case 'RunOnMonth':
|
||||
label = '每月第几日'
|
||||
break
|
||||
case 21:
|
||||
case 'Custom':
|
||||
label = 'Cron表达式'
|
||||
break
|
||||
}
|
||||
return label
|
||||
}
|
||||
|
||||
const formatterTime = (row: any, column: any, cellValue: any) => {
|
||||
return dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
|
||||
const onClear = () => {
|
||||
tableRef.value?.clearSelection()
|
||||
}
|
||||
|
||||
const onQuery = async () => {
|
||||
state.loading = true
|
||||
state.pageInput.filter = state.filter
|
||||
const res = await new TaskApi().getPage(state.pageInput).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
|
||||
state.taskListData = res?.data?.list ?? []
|
||||
state.total = res?.data?.total ?? 0
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onAdd = () => {
|
||||
state.taskFormTitle = '新增任务'
|
||||
taskFormRef.value.open()
|
||||
}
|
||||
|
||||
const onUpdate = (row: TaskGetPageOutput) => {
|
||||
state.taskFormTitle = '修改任务'
|
||||
taskFormRef.value.open(row)
|
||||
}
|
||||
|
||||
const onCopy = (row: TaskGetPageOutput) => {
|
||||
state.taskFormTitle = '新增任务'
|
||||
var task = cloneDeep(row)
|
||||
task.id = null
|
||||
taskFormRef.value.open(task)
|
||||
}
|
||||
|
||||
// 查看日志
|
||||
const onShowLogs = (row: TaskGetPageOutput) => {
|
||||
state.taskLogsTitle = `${row.topic}${row.id}运行日志`
|
||||
taskLogsRef.value.open(row)
|
||||
}
|
||||
|
||||
const onRun = (row: TaskGetPageOutput) => {
|
||||
proxy.$modal
|
||||
.confirm(`确定要运行【${row.topic}】任务?`)
|
||||
.then(async () => {
|
||||
await new TaskApi().run({ id: row.id as string }, { loading: true, showSuccessMessage: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onPause = (row: TaskGetPageOutput) => {
|
||||
proxy.$modal
|
||||
.confirm(`确定要停止【${row.topic}】任务?`)
|
||||
.then(async () => {
|
||||
await new TaskApi().pause({ id: row.id as string }, { loading: true, showSuccessMessage: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onStart = (row: TaskGetPageOutput) => {
|
||||
proxy.$modal
|
||||
.confirm(`确定要启动【${row.topic}】任务?`)
|
||||
.then(async () => {
|
||||
await new TaskApi().resume({ id: row.id as string }, { loading: true, showSuccessMessage: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onDelete = (row: TaskGetPageOutput) => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要删除【${row.topic}】任务?`)
|
||||
.then(async () => {
|
||||
await new TaskApi().delete({ id: row.id as string }, { loading: true, showSuccessMessage: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const checkRowSelect = () => {
|
||||
if (rowSelectCount.value > 0) {
|
||||
return true
|
||||
} else {
|
||||
ElMessage({
|
||||
message: '请选择任务再操作',
|
||||
type: 'warning',
|
||||
})
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
const onBatchRun = () => {
|
||||
if (!checkRowSelect()) {
|
||||
return
|
||||
}
|
||||
|
||||
proxy.$modal
|
||||
.confirm(`确定要运行 ${rowSelectCount.value} 项任务?`)
|
||||
.then(async () => {
|
||||
await new TaskApi().batchRun(taskIds.value, { loading: true, showSuccessMessage: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onBatchPause = () => {
|
||||
if (!checkRowSelect()) {
|
||||
return
|
||||
}
|
||||
|
||||
proxy.$modal
|
||||
.confirm(`确定要停止 ${rowSelectCount.value} 项任务?`)
|
||||
.then(async () => {
|
||||
await new TaskApi().batchPause(taskIds.value, { loading: true, showSuccessMessage: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onBatchStart = () => {
|
||||
if (!checkRowSelect()) {
|
||||
return
|
||||
}
|
||||
|
||||
proxy.$modal
|
||||
.confirm(`确定要启动 ${rowSelectCount.value} 项任务?`)
|
||||
.then(async () => {
|
||||
await new TaskApi().batchResume(taskIds.value, { loading: true, showSuccessMessage: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onBatchDelete = () => {
|
||||
if (!checkRowSelect()) {
|
||||
return
|
||||
}
|
||||
|
||||
proxy.$modal
|
||||
.confirm(`确定要删除 ${rowSelectCount.value} 项任务?`)
|
||||
.then(async () => {
|
||||
await new TaskApi().batchDelete(taskIds.value, { loading: true, showSuccessMessage: true })
|
||||
onQuery()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onSizeChange = (val: number) => {
|
||||
state.pageInput.currentPage = 1
|
||||
state.pageInput.pageSize = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onCurrentChange = (val: number) => {
|
||||
state.pageInput.currentPage = val
|
||||
onQuery()
|
||||
}
|
||||
</script>
|
||||
@ -1,152 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
title="加载共享文件夹"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="600px"
|
||||
>
|
||||
<el-form :model="form" ref="formRef" label-width="120px">
|
||||
<el-alert
|
||||
v-if="state.isReadonly"
|
||||
title="当前为指定文件夹加载模式,父级文件夹和文件路径已自动设置"
|
||||
type="info"
|
||||
:closable="false"
|
||||
style="margin-bottom: 20px"
|
||||
/>
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="父级文件夹">
|
||||
<el-input
|
||||
v-if="state.isReadonly"
|
||||
v-model="state.parentName"
|
||||
readonly
|
||||
placeholder="根目录"
|
||||
class="w100"
|
||||
/>
|
||||
<el-tree-select
|
||||
v-else
|
||||
v-model="form.parentId"
|
||||
:data="templateTreeData.filter(item => (item.type || 1) === 1)"
|
||||
node-key="id"
|
||||
check-strictly
|
||||
default-expand-all
|
||||
render-after-expand
|
||||
fit-input-width
|
||||
clearable
|
||||
:empty-values="[0, null, undefined]"
|
||||
class="w100"
|
||||
:props="{ label: 'name', value: 'id' }"
|
||||
placeholder="请选择父级文件夹,为空则表示根目录"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="文件夹路径" prop="folderPath" :rules="[{ required: true, message: '请输入文件夹路径', trigger: ['blur', 'change'] }]">
|
||||
<el-input
|
||||
v-model="form.folderPath"
|
||||
:readonly="state.isReadonly"
|
||||
clearable
|
||||
placeholder="请输入共享文件夹路径"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="包含子文件夹">
|
||||
<el-switch v-model="form.includeSubfolders" />
|
||||
<el-text type="info" size="small" style="margin-left: 10px">
|
||||
是否包含子文件夹内容
|
||||
</el-text>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" :loading="state.sureLoading">开始加载</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/templatecenter/folder-load-form">
|
||||
import { reactive, toRefs, getCurrentInstance, ref, PropType } from 'vue'
|
||||
import { TemplateCenterGetTreeOutput } from '/@/api/admin/TemplateCenter'
|
||||
import { TemplateCenterApi } from '/@/api/admin/TemplateCenter'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
|
||||
defineProps({
|
||||
templateTreeData: {
|
||||
type: Array as PropType<TemplateCenterGetTreeOutput[]>,
|
||||
default: () => [],
|
||||
},
|
||||
})
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
const formRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
isReadonly: false,
|
||||
parentName: '',
|
||||
form: {
|
||||
parentId: undefined as number | undefined,
|
||||
folderPath: '',
|
||||
includeSubfolders: false,
|
||||
},
|
||||
})
|
||||
const { form } = toRefs(state)
|
||||
|
||||
// 打开对话框
|
||||
const open = async (parentId?: number, parentName?: string, folderPath?: string) => {
|
||||
state.isReadonly = !!(parentId && parentName) // 如果传入了父级信息,则为只读模式
|
||||
state.parentName = parentName || ''
|
||||
|
||||
state.form = {
|
||||
parentId: parentId || undefined,
|
||||
folderPath: folderPath || '',
|
||||
includeSubfolders: false,
|
||||
}
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
state.sureLoading = true
|
||||
|
||||
const res = await new TemplateCenterApi().getSharedFolderContent({
|
||||
folderPath: state.form.folderPath,
|
||||
parentId: state.form.parentId && state.form.parentId > 0 ? state.form.parentId : undefined,
|
||||
includeSubfolders: state.form.includeSubfolders,
|
||||
}, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
eventBus.emit('refreshTemplateCenter')
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -1,427 +0,0 @@
|
||||
<template>
|
||||
<el-dialog v-model="state.isShowDialog" title="关键词生成助手" width="800px" destroy-on-close>
|
||||
<div class="keyword-helper">
|
||||
<!-- 使用说明 -->
|
||||
<el-alert
|
||||
title="使用说明"
|
||||
description="支持格式:通用关键词&后缀|特定关键词&后缀,如:报告模板,报告信息&doc,docx|报表&xlsx,xls|归档&pdf"
|
||||
type="info"
|
||||
:closable="false"
|
||||
style="margin-bottom: 20px"
|
||||
/>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<!-- 左侧:关键词配置 -->
|
||||
<el-col :span="12">
|
||||
<el-card header="关键词配置" shadow="never">
|
||||
<!-- 通用关键词 -->
|
||||
<div class="section">
|
||||
<h4>通用关键词</h4>
|
||||
<el-input
|
||||
v-model="state.commonKeywords"
|
||||
placeholder="输入通用关键词,用逗号分隔"
|
||||
type="textarea"
|
||||
:rows="2"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 特定后缀关键词 -->
|
||||
<div class="section">
|
||||
<h4>
|
||||
特定后缀关键词
|
||||
<el-button type="primary" link size="small" @click="addExtensionGroup">
|
||||
<el-icon><Plus /></el-icon>
|
||||
添加组合
|
||||
</el-button>
|
||||
</h4>
|
||||
|
||||
<div v-for="(group, index) in state.extensionGroups" :key="index" class="extension-group">
|
||||
<el-row :gutter="10" align="middle">
|
||||
<el-col :span="10">
|
||||
<el-input
|
||||
v-model="group.keywords"
|
||||
placeholder="关键词,用逗号分隔"
|
||||
size="small"
|
||||
/>
|
||||
</el-col>
|
||||
<el-col :span="2" class="text-center">
|
||||
<span>&</span>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<el-select
|
||||
v-model="group.extensions"
|
||||
placeholder="选择文件后缀"
|
||||
multiple
|
||||
collapse-tags
|
||||
collapse-tags-tooltip
|
||||
size="small"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option-group label="文档类">
|
||||
<el-option label="doc" value="doc" />
|
||||
<el-option label="docx" value="docx" />
|
||||
<el-option label="pdf" value="pdf" />
|
||||
<el-option label="txt" value="txt" />
|
||||
<el-option label="md" value="md" />
|
||||
</el-option-group>
|
||||
<el-option-group label="表格类">
|
||||
<el-option label="xlsx" value="xlsx" />
|
||||
<el-option label="xls" value="xls" />
|
||||
<el-option label="csv" value="csv" />
|
||||
</el-option-group>
|
||||
<el-option-group label="演示文稿">
|
||||
<el-option label="ppt" value="ppt" />
|
||||
<el-option label="pptx" value="pptx" />
|
||||
</el-option-group>
|
||||
<el-option-group label="图片类">
|
||||
<el-option label="jpg" value="jpg" />
|
||||
<el-option label="jpeg" value="jpeg" />
|
||||
<el-option label="png" value="png" />
|
||||
<el-option label="gif" value="gif" />
|
||||
</el-option-group>
|
||||
<el-option-group label="压缩类">
|
||||
<el-option label="zip" value="zip" />
|
||||
<el-option label="rar" value="rar" />
|
||||
<el-option label="7z" value="7z" />
|
||||
</el-option-group>
|
||||
<el-option-group label="代码类">
|
||||
<el-option label="js" value="js" />
|
||||
<el-option label="ts" value="ts" />
|
||||
<el-option label="vue" value="vue" />
|
||||
<el-option label="html" value="html" />
|
||||
<el-option label="css" value="css" />
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="2">
|
||||
<el-button
|
||||
type="danger"
|
||||
link
|
||||
size="small"
|
||||
@click="removeExtensionGroup(index)"
|
||||
>
|
||||
<el-icon><Delete /></el-icon>
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 快速模板 -->
|
||||
<div class="section">
|
||||
<h4>快速模板</h4>
|
||||
<el-space wrap>
|
||||
<el-button
|
||||
v-for="template in templates"
|
||||
:key="template.name"
|
||||
size="small"
|
||||
@click="applyTemplate(template)"
|
||||
>
|
||||
{{ template.name }}
|
||||
</el-button>
|
||||
</el-space>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<!-- 右侧:预览和生成 -->
|
||||
<el-col :span="12">
|
||||
<el-card header="预览和生成" shadow="never">
|
||||
<div class="section">
|
||||
<h4>生成结果</h4>
|
||||
<el-input
|
||||
v-model="generatedKeywords"
|
||||
type="textarea"
|
||||
:rows="6"
|
||||
readonly
|
||||
placeholder="配置左侧选项后,将在此显示生成的关键词"
|
||||
/>
|
||||
<div style="margin-top: 10px; text-align: right">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
:disabled="!generatedKeywords"
|
||||
@click="copyToClipboard"
|
||||
>
|
||||
<el-icon><CopyDocument /></el-icon>
|
||||
复制到剪贴板
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h4>格式说明</h4>
|
||||
<div class="format-example">
|
||||
<p><strong>基本格式:</strong></p>
|
||||
<code>通用关键词&后缀|特定关键词&后缀</code>
|
||||
|
||||
<p><strong>示例解释:</strong></p>
|
||||
<div class="example-item">
|
||||
<code>报告模板,报告信息&doc,docx</code>
|
||||
<span>→ 在doc/docx文件中搜索"报告模板"或"报告信息"</span>
|
||||
</div>
|
||||
<div class="example-item">
|
||||
<code>|报表&xlsx,xls</code>
|
||||
<span>→ 在xlsx/xls文件中搜索"报表"</span>
|
||||
</div>
|
||||
<div class="example-item">
|
||||
<code>|归档&pdf</code>
|
||||
<span>→ 在pdf文件中搜索"归档"</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="state.isShowDialog = false">取消</el-button>
|
||||
<el-button type="primary" @click="applyKeywords">应用关键词</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="KeywordHelper">
|
||||
import { reactive, computed } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { Plus, Delete, CopyDocument } from '@element-plus/icons-vue'
|
||||
|
||||
// 接口定义
|
||||
interface ExtensionGroup {
|
||||
keywords: string
|
||||
extensions: string[]
|
||||
}
|
||||
|
||||
interface Template {
|
||||
name: string
|
||||
commonKeywords: string
|
||||
extensionGroups: ExtensionGroup[]
|
||||
}
|
||||
|
||||
// 组件状态
|
||||
const state = reactive({
|
||||
isShowDialog: false,
|
||||
commonKeywords: '',
|
||||
extensionGroups: [] as ExtensionGroup[]
|
||||
})
|
||||
|
||||
// 快速模板
|
||||
const templates: Template[] = [
|
||||
{
|
||||
name: '办公文档',
|
||||
commonKeywords: '文档,模板',
|
||||
extensionGroups: [
|
||||
{ keywords: '报告,总结', extensions: ['doc', 'docx'] },
|
||||
{ keywords: '报表,统计', extensions: ['xlsx', 'xls'] },
|
||||
{ keywords: '演示,汇报', extensions: ['ppt', 'pptx'] }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '项目管理',
|
||||
commonKeywords: '项目,管理',
|
||||
extensionGroups: [
|
||||
{ keywords: '需求,方案', extensions: ['doc', 'docx', 'pdf'] },
|
||||
{ keywords: '计划,进度', extensions: ['xlsx', 'xls'] },
|
||||
{ keywords: '设计,原型', extensions: ['png', 'jpg', 'pdf'] }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '技术文档',
|
||||
commonKeywords: '技术,开发',
|
||||
extensionGroups: [
|
||||
{ keywords: 'API,接口', extensions: ['md', 'pdf'] },
|
||||
{ keywords: '代码,脚本', extensions: ['js', 'ts', 'vue'] },
|
||||
{ keywords: '配置,部署', extensions: ['json', 'yml', 'xml'] }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '财务相关',
|
||||
commonKeywords: '财务,会计',
|
||||
extensionGroups: [
|
||||
{ keywords: '报表,账单', extensions: ['xlsx', 'xls'] },
|
||||
{ keywords: '合同,协议', extensions: ['doc', 'docx', 'pdf'] },
|
||||
{ keywords: '发票,凭证', extensions: ['pdf', 'jpg', 'png'] }
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
// 计算生成的关键词
|
||||
const generatedKeywords = computed(() => {
|
||||
const parts: string[] = []
|
||||
|
||||
// 添加通用关键词
|
||||
if (state.commonKeywords.trim()) {
|
||||
parts.push(state.commonKeywords.trim())
|
||||
}
|
||||
|
||||
// 添加特定后缀关键词
|
||||
state.extensionGroups.forEach(group => {
|
||||
if (group.keywords.trim() && group.extensions.length > 0) {
|
||||
const keywordsPart = group.keywords.trim()
|
||||
const extensionsPart = group.extensions.join(',')
|
||||
parts.push(`${keywordsPart}&${extensionsPart}`)
|
||||
}
|
||||
})
|
||||
|
||||
return parts.join('|')
|
||||
})
|
||||
|
||||
// 添加扩展组
|
||||
const addExtensionGroup = () => {
|
||||
state.extensionGroups.push({
|
||||
keywords: '',
|
||||
extensions: []
|
||||
})
|
||||
}
|
||||
|
||||
// 删除扩展组
|
||||
const removeExtensionGroup = (index: number) => {
|
||||
state.extensionGroups.splice(index, 1)
|
||||
}
|
||||
|
||||
// 应用模板
|
||||
const applyTemplate = (template: Template) => {
|
||||
state.commonKeywords = template.commonKeywords
|
||||
state.extensionGroups = [...template.extensionGroups]
|
||||
}
|
||||
|
||||
// 复制到剪贴板
|
||||
const copyToClipboard = async () => {
|
||||
if (!generatedKeywords.value) return
|
||||
|
||||
try {
|
||||
await navigator.clipboard.writeText(generatedKeywords.value)
|
||||
ElMessage.success('已复制到剪贴板')
|
||||
} catch (err) {
|
||||
// 降级处理
|
||||
const textArea = document.createElement('textarea')
|
||||
textArea.value = generatedKeywords.value
|
||||
document.body.appendChild(textArea)
|
||||
textArea.select()
|
||||
document.execCommand('copy')
|
||||
document.body.removeChild(textArea)
|
||||
ElMessage.success('已复制到剪贴板')
|
||||
}
|
||||
}
|
||||
|
||||
// 清空配置
|
||||
const clearAll = () => {
|
||||
state.commonKeywords = ''
|
||||
state.extensionGroups = []
|
||||
}
|
||||
|
||||
// 暴露给父组件的方法
|
||||
const emit = defineEmits<{
|
||||
apply: [keywords: string]
|
||||
}>()
|
||||
|
||||
// 打开对话框
|
||||
const open = (currentKeywords?: string) => {
|
||||
clearAll()
|
||||
|
||||
// 如果有当前关键词,尝试解析
|
||||
if (currentKeywords) {
|
||||
parseExistingKeywords(currentKeywords)
|
||||
}
|
||||
|
||||
state.isShowDialog = true
|
||||
}
|
||||
|
||||
// 解析现有关键词
|
||||
const parseExistingKeywords = (keywords: string) => {
|
||||
const parts = keywords.split('|')
|
||||
|
||||
for (const part of parts) {
|
||||
if (part.includes('&')) {
|
||||
// 特定后缀关键词
|
||||
const [keywordsPart, extensionsPart] = part.split('&')
|
||||
state.extensionGroups.push({
|
||||
keywords: keywordsPart.trim(),
|
||||
extensions: extensionsPart.split(',').map(e => e.trim())
|
||||
})
|
||||
} else {
|
||||
// 通用关键词
|
||||
state.commonKeywords = part.trim()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 应用关键词
|
||||
const applyKeywords = () => {
|
||||
if (generatedKeywords.value) {
|
||||
emit('apply', generatedKeywords.value)
|
||||
state.isShowDialog = false
|
||||
ElMessage.success('关键词已应用')
|
||||
} else {
|
||||
ElMessage.warning('请先配置关键词')
|
||||
}
|
||||
}
|
||||
|
||||
// 暴露方法给父组件
|
||||
defineExpose({
|
||||
open
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.keyword-helper {
|
||||
.section {
|
||||
margin-bottom: 20px;
|
||||
|
||||
h4 {
|
||||
margin: 0 0 10px 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
.extension-group {
|
||||
margin-bottom: 10px;
|
||||
padding: 10px;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.format-example {
|
||||
font-size: 12px;
|
||||
color: #606266;
|
||||
|
||||
p {
|
||||
margin: 10px 0 5px 0;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: #f5f7fa;
|
||||
padding: 2px 4px;
|
||||
border-radius: 3px;
|
||||
font-family: 'Courier New', monospace;
|
||||
}
|
||||
|
||||
.example-item {
|
||||
margin: 8px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
|
||||
span {
|
||||
color: #909399;
|
||||
font-size: 11px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user