Pre Merge pull request !76 from dhb52/v-next-dev
commit
6f752b58df
|
|
@ -26,6 +26,10 @@
|
||||||
"#/*": "./src/*"
|
"#/*": "./src/*"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@form-create/ant-design-vue": "catalog:",
|
||||||
|
"@form-create/antd-designer": "catalog:",
|
||||||
|
"@tinymce/tinymce-vue": "catalog:",
|
||||||
|
"@types/lodash.clonedeep": "catalog:",
|
||||||
"@vben/access": "workspace:*",
|
"@vben/access": "workspace:*",
|
||||||
"@vben/common-ui": "workspace:*",
|
"@vben/common-ui": "workspace:*",
|
||||||
"@vben/constants": "workspace:*",
|
"@vben/constants": "workspace:*",
|
||||||
|
|
@ -40,14 +44,16 @@
|
||||||
"@vben/styles": "workspace:*",
|
"@vben/styles": "workspace:*",
|
||||||
"@vben/types": "workspace:*",
|
"@vben/types": "workspace:*",
|
||||||
"@vben/utils": "workspace:*",
|
"@vben/utils": "workspace:*",
|
||||||
"@tinymce/tinymce-vue": "catalog:",
|
|
||||||
"@vueuse/core": "catalog:",
|
"@vueuse/core": "catalog:",
|
||||||
"ant-design-vue": "catalog:",
|
"ant-design-vue": "catalog:",
|
||||||
|
"axios": "catalog:",
|
||||||
"crypto-js": "catalog:",
|
"crypto-js": "catalog:",
|
||||||
"dayjs": "catalog:",
|
"dayjs": "catalog:",
|
||||||
"highlight.js": "catalog:",
|
"highlight.js": "catalog:",
|
||||||
|
"lodash.clonedeep": "catalog:",
|
||||||
"pinia": "catalog:",
|
"pinia": "catalog:",
|
||||||
"vue": "catalog:",
|
"vue": "catalog:",
|
||||||
|
"vue-dompurify-html": "catalog:",
|
||||||
"vue-router": "catalog:"
|
"vue-router": "catalog:"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
|
@ -115,7 +115,9 @@ export type ComponentType =
|
||||||
| 'DatePicker'
|
| 'DatePicker'
|
||||||
| 'DefaultButton'
|
| 'DefaultButton'
|
||||||
| 'Divider'
|
| 'Divider'
|
||||||
|
| 'FileUpload'
|
||||||
| 'IconPicker'
|
| 'IconPicker'
|
||||||
|
| 'ImageUpload'
|
||||||
| 'Input'
|
| 'Input'
|
||||||
| 'InputNumber'
|
| 'InputNumber'
|
||||||
| 'InputPassword'
|
| 'InputPassword'
|
||||||
|
|
@ -125,16 +127,14 @@ export type ComponentType =
|
||||||
| 'RadioGroup'
|
| 'RadioGroup'
|
||||||
| 'RangePicker'
|
| 'RangePicker'
|
||||||
| 'Rate'
|
| 'Rate'
|
||||||
|
| 'RichTextarea'
|
||||||
| 'Select'
|
| 'Select'
|
||||||
| 'Space'
|
| 'Space'
|
||||||
| 'Switch'
|
| 'Switch'
|
||||||
| 'Textarea'
|
| 'Textarea'
|
||||||
| 'RichTextarea'
|
|
||||||
| 'TimePicker'
|
| 'TimePicker'
|
||||||
| 'TreeSelect'
|
| 'TreeSelect'
|
||||||
| 'Upload'
|
| 'Upload'
|
||||||
| 'FileUpload'
|
|
||||||
| 'ImageUpload'
|
|
||||||
| BaseFormComponentType;
|
| BaseFormComponentType;
|
||||||
|
|
||||||
async function initComponentAdapter() {
|
async function initComponentAdapter() {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import type { Recordable } from '@vben/types';
|
||||||
|
|
||||||
import { h } from 'vue';
|
import { h } from 'vue';
|
||||||
|
|
||||||
import { IconifyIcon } from '@vben/icons';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
|
@ -6,12 +8,11 @@ import { setupVbenVxeTable, useVbenVxeGrid } from '@vben/plugins/vxe-table';
|
||||||
import { isFunction, isString } from '@vben/utils';
|
import { isFunction, isString } from '@vben/utils';
|
||||||
|
|
||||||
import { Button, Image, Popconfirm, Switch } from 'ant-design-vue';
|
import { Button, Image, Popconfirm, Switch } from 'ant-design-vue';
|
||||||
|
|
||||||
import { DictTag } from '#/components/dict-tag';
|
import { DictTag } from '#/components/dict-tag';
|
||||||
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
import { useVbenForm } from './form';
|
import { useVbenForm } from './form';
|
||||||
import type { Recordable } from '@vben/types';
|
|
||||||
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
setupVbenVxeTable({
|
setupVbenVxeTable({
|
||||||
configVxeTable: (vxeUI) => {
|
configVxeTable: (vxeUI) => {
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,17 @@ export namespace BpmCategoryApi {
|
||||||
|
|
||||||
/** 查询流程分类分页 */
|
/** 查询流程分类分页 */
|
||||||
export async function getCategoryPage(params: PageParam) {
|
export async function getCategoryPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<BpmCategoryApi.CategoryVO>>('/bpm/category/page', { params });
|
return requestClient.get<PageResult<BpmCategoryApi.CategoryVO>>(
|
||||||
|
'/bpm/category/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询流程分类详情 */
|
/** 查询流程分类详情 */
|
||||||
export async function getCategory(id: number) {
|
export async function getCategory(id: number) {
|
||||||
return requestClient.get<BpmCategoryApi.CategoryVO>(`/bpm/category/get?id=${id}`);
|
return requestClient.get<BpmCategoryApi.CategoryVO>(
|
||||||
|
`/bpm/category/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增流程分类 */
|
/** 新增流程分类 */
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { baseRequestClient, requestClient } from '#/api/request';
|
|
||||||
import type { AuthPermissionInfo } from '@vben/types';
|
import type { AuthPermissionInfo } from '@vben/types';
|
||||||
|
|
||||||
|
import { baseRequestClient, requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace AuthApi {
|
export namespace AuthApi {
|
||||||
/** 登录接口参数 */
|
/** 登录接口参数 */
|
||||||
export interface LoginParams {
|
export interface LoginParams {
|
||||||
|
|
@ -41,9 +42,9 @@ export namespace AuthApi {
|
||||||
|
|
||||||
/** 注册接口参数 */
|
/** 注册接口参数 */
|
||||||
export interface RegisterParams {
|
export interface RegisterParams {
|
||||||
username: string
|
username: string;
|
||||||
password: string
|
password: string;
|
||||||
captchaVerification: string
|
captchaVerification: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 重置密码接口参数 */
|
/** 重置密码接口参数 */
|
||||||
|
|
@ -68,16 +69,22 @@ export async function loginApi(data: AuthApi.LoginParams) {
|
||||||
|
|
||||||
/** 刷新 accessToken */
|
/** 刷新 accessToken */
|
||||||
export async function refreshTokenApi(refreshToken: string) {
|
export async function refreshTokenApi(refreshToken: string) {
|
||||||
return baseRequestClient.post(`/system/auth/refresh-token?refreshToken=${refreshToken}`);
|
return baseRequestClient.post(
|
||||||
|
`/system/auth/refresh-token?refreshToken=${refreshToken}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 退出登录 */
|
/** 退出登录 */
|
||||||
export async function logoutApi(accessToken: string) {
|
export async function logoutApi(accessToken: string) {
|
||||||
return baseRequestClient.post('/system/auth/logout', {}, {
|
return baseRequestClient.post(
|
||||||
|
'/system/auth/logout',
|
||||||
|
{},
|
||||||
|
{
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${accessToken}`,
|
Authorization: `Bearer ${accessToken}`,
|
||||||
}
|
},
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获取权限信息 */
|
/** 获取权限信息 */
|
||||||
|
|
@ -96,7 +103,9 @@ export async function getTenantSimpleList() {
|
||||||
|
|
||||||
/** 使用租户域名,获得租户信息 */
|
/** 使用租户域名,获得租户信息 */
|
||||||
export async function getTenantByWebsite(website: string) {
|
export async function getTenantByWebsite(website: string) {
|
||||||
return requestClient.get<AuthApi.TenantResult>(`/system/tenant/get-by-website?website=${website}`);
|
return requestClient.get<AuthApi.TenantResult>(
|
||||||
|
`/system/tenant/get-by-website?website=${website}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获取验证码 */
|
/** 获取验证码 */
|
||||||
|
|
@ -111,23 +120,23 @@ export async function checkCaptcha(data: any) {
|
||||||
|
|
||||||
/** 获取登录验证码 */
|
/** 获取登录验证码 */
|
||||||
export const sendSmsCode = (data: AuthApi.SmsCodeParams) => {
|
export const sendSmsCode = (data: AuthApi.SmsCodeParams) => {
|
||||||
return requestClient.post('/system/auth/send-sms-code', data )
|
return requestClient.post('/system/auth/send-sms-code', data);
|
||||||
}
|
};
|
||||||
|
|
||||||
/** 短信验证码登录 */
|
/** 短信验证码登录 */
|
||||||
export const smsLogin = (data: AuthApi.SmsLoginParams) => {
|
export const smsLogin = (data: AuthApi.SmsLoginParams) => {
|
||||||
return requestClient.post('/system/auth/sms-login', data)
|
return requestClient.post('/system/auth/sms-login', data);
|
||||||
}
|
};
|
||||||
|
|
||||||
/** 注册 */
|
/** 注册 */
|
||||||
export const register = (data: AuthApi.RegisterParams) => {
|
export const register = (data: AuthApi.RegisterParams) => {
|
||||||
return requestClient.post('/system/auth/register', data)
|
return requestClient.post('/system/auth/register', data);
|
||||||
}
|
};
|
||||||
|
|
||||||
/** 通过短信重置密码 */
|
/** 通过短信重置密码 */
|
||||||
export const smsResetPassword = (data: AuthApi.ResetPasswordParams) => {
|
export const smsResetPassword = (data: AuthApi.ResetPasswordParams) => {
|
||||||
return requestClient.post('/system/auth/reset-password', data)
|
return requestClient.post('/system/auth/reset-password', data);
|
||||||
}
|
};
|
||||||
|
|
||||||
/** 社交授权的跳转 */
|
/** 社交授权的跳转 */
|
||||||
export const socialAuthRedirect = (type: number, redirectUri: string) => {
|
export const socialAuthRedirect = (type: number, redirectUri: string) => {
|
||||||
|
|
@ -137,9 +146,12 @@ export const socialAuthRedirect = (type: number, redirectUri: string) => {
|
||||||
redirectUri,
|
redirectUri,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/** 社交快捷登录 */
|
/** 社交快捷登录 */
|
||||||
export const socialLogin = (data: AuthApi.SocialLoginParams) => {
|
export const socialLogin = (data: AuthApi.SocialLoginParams) => {
|
||||||
return requestClient.post<AuthApi.LoginResult>('/system/auth/social-login', data);
|
return requestClient.post<AuthApi.LoginResult>(
|
||||||
}
|
'/system/auth/social-login',
|
||||||
|
data,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -32,11 +32,13 @@ export namespace InfraApiAccessLogApi {
|
||||||
export function getApiAccessLogPage(params: PageParam) {
|
export function getApiAccessLogPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<InfraApiAccessLogApi.SystemApiAccessLog>>(
|
return requestClient.get<PageResult<InfraApiAccessLogApi.SystemApiAccessLog>>(
|
||||||
'/infra/api-access-log/page',
|
'/infra/api-access-log/page',
|
||||||
{ params }
|
{ params },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 导出 API 访问日志 */
|
/** 导出 API 访问日志 */
|
||||||
export function exportApiAccessLog(params: any) {
|
export function exportApiAccessLog(params: any) {
|
||||||
return requestClient.download('/infra/api-access-log/export-excel', { params });
|
return requestClient.download('/infra/api-access-log/export-excel', {
|
||||||
|
params,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,16 +36,20 @@ export namespace InfraApiErrorLogApi {
|
||||||
export function getApiErrorLogPage(params: PageParam) {
|
export function getApiErrorLogPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<InfraApiErrorLogApi.SystemApiErrorLog>>(
|
return requestClient.get<PageResult<InfraApiErrorLogApi.SystemApiErrorLog>>(
|
||||||
'/infra/api-error-log/page',
|
'/infra/api-error-log/page',
|
||||||
{ params }
|
{ params },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 更新 API 错误日志的处理状态 */
|
/** 更新 API 错误日志的处理状态 */
|
||||||
export function updateApiErrorLogStatus(id: number, processStatus: number) {
|
export function updateApiErrorLogStatus(id: number, processStatus: number) {
|
||||||
return requestClient.put(`/infra/api-error-log/update-status?id=${id}&processStatus=${processStatus}`);
|
return requestClient.put(
|
||||||
|
`/infra/api-error-log/update-status?id=${id}&processStatus=${processStatus}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 导出 API 错误日志 */
|
/** 导出 API 错误日志 */
|
||||||
export function exportApiErrorLog(params: any) {
|
export function exportApiErrorLog(params: any) {
|
||||||
return requestClient.download('/infra/api-error-log/export-excel', { params });
|
return requestClient.download('/infra/api-error-log/export-excel', {
|
||||||
|
params,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,21 +79,30 @@ export namespace InfraCodegenApi {
|
||||||
|
|
||||||
/** 查询列表代码生成表定义 */
|
/** 查询列表代码生成表定义 */
|
||||||
export function getCodegenTableList(dataSourceConfigId: number) {
|
export function getCodegenTableList(dataSourceConfigId: number) {
|
||||||
return requestClient.get<InfraCodegenApi.CodegenTable[]>('/infra/codegen/table/list?', {
|
return requestClient.get<InfraCodegenApi.CodegenTable[]>(
|
||||||
|
'/infra/codegen/table/list?',
|
||||||
|
{
|
||||||
params: { dataSourceConfigId },
|
params: { dataSourceConfigId },
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询列表代码生成表定义 */
|
/** 查询列表代码生成表定义 */
|
||||||
export function getCodegenTablePage(params: PageParam) {
|
export function getCodegenTablePage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<InfraCodegenApi.CodegenTable>>('/infra/codegen/table/page', { params });
|
return requestClient.get<PageResult<InfraCodegenApi.CodegenTable>>(
|
||||||
|
'/infra/codegen/table/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询详情代码生成表定义 */
|
/** 查询详情代码生成表定义 */
|
||||||
export function getCodegenTable(tableId: number) {
|
export function getCodegenTable(tableId: number) {
|
||||||
return requestClient.get<InfraCodegenApi.CodegenDetail>('/infra/codegen/detail', {
|
return requestClient.get<InfraCodegenApi.CodegenDetail>(
|
||||||
|
'/infra/codegen/detail',
|
||||||
|
{
|
||||||
params: { tableId },
|
params: { tableId },
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 修改代码生成表定义 */
|
/** 修改代码生成表定义 */
|
||||||
|
|
@ -110,9 +119,12 @@ export function syncCodegenFromDB(tableId: number) {
|
||||||
|
|
||||||
/** 预览生成代码 */
|
/** 预览生成代码 */
|
||||||
export function previewCodegen(tableId: number) {
|
export function previewCodegen(tableId: number) {
|
||||||
return requestClient.get<InfraCodegenApi.CodegenPreview[]>('/infra/codegen/preview', {
|
return requestClient.get<InfraCodegenApi.CodegenPreview[]>(
|
||||||
|
'/infra/codegen/preview',
|
||||||
|
{
|
||||||
params: { tableId },
|
params: { tableId },
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 下载生成代码 */
|
/** 下载生成代码 */
|
||||||
|
|
@ -124,11 +136,16 @@ export function downloadCodegen(tableId: number) {
|
||||||
|
|
||||||
/** 获得表定义 */
|
/** 获得表定义 */
|
||||||
export function getSchemaTableList(params: any) {
|
export function getSchemaTableList(params: any) {
|
||||||
return requestClient.get<InfraCodegenApi.DatabaseTable[]>('/infra/codegen/db/table/list', { params });
|
return requestClient.get<InfraCodegenApi.DatabaseTable[]>(
|
||||||
|
'/infra/codegen/db/table/list',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 基于数据库的表结构,创建代码生成器的表定义 */
|
/** 基于数据库的表结构,创建代码生成器的表定义 */
|
||||||
export function createCodegenList(data: InfraCodegenApi.CodegenCreateListReqVO) {
|
export function createCodegenList(
|
||||||
|
data: InfraCodegenApi.CodegenCreateListReqVO,
|
||||||
|
) {
|
||||||
return requestClient.post('/infra/codegen/create-list', data);
|
return requestClient.post('/infra/codegen/create-list', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace InfraConfigApi {
|
export namespace InfraConfigApi {
|
||||||
/** 参数配置信息 */
|
/** 参数配置信息 */
|
||||||
export interface InfraConfig {
|
export interface InfraConfig {
|
||||||
|
|
@ -18,19 +19,26 @@ export namespace InfraConfigApi {
|
||||||
|
|
||||||
/** 查询参数列表 */
|
/** 查询参数列表 */
|
||||||
export function getConfigPage(params: PageParam) {
|
export function getConfigPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<InfraConfigApi.InfraConfig>>('/infra/config/page', {
|
return requestClient.get<PageResult<InfraConfigApi.InfraConfig>>(
|
||||||
params
|
'/infra/config/page',
|
||||||
});
|
{
|
||||||
|
params,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询参数详情 */
|
/** 查询参数详情 */
|
||||||
export function getConfig(id: number) {
|
export function getConfig(id: number) {
|
||||||
return requestClient.get<InfraConfigApi.InfraConfig>(`/infra/config/get?id=${id}`);
|
return requestClient.get<InfraConfigApi.InfraConfig>(
|
||||||
|
`/infra/config/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 根据参数键名查询参数值 */
|
/** 根据参数键名查询参数值 */
|
||||||
export function getConfigKey(configKey: string) {
|
export function getConfigKey(configKey: string) {
|
||||||
return requestClient.get<string>(`/infra/config/get-value-by-key?key=${configKey}`);
|
return requestClient.get<string>(
|
||||||
|
`/infra/config/get-value-by-key?key=${configKey}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增参数 */
|
/** 新增参数 */
|
||||||
|
|
@ -51,6 +59,6 @@ export function deleteConfig(id: number) {
|
||||||
/** 导出参数 */
|
/** 导出参数 */
|
||||||
export function exportConfig(params: any) {
|
export function exportConfig(params: any) {
|
||||||
return requestClient.download('/infra/config/export', {
|
return requestClient.download('/infra/config/export', {
|
||||||
params
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,21 +14,29 @@ export namespace InfraDataSourceConfigApi {
|
||||||
|
|
||||||
/** 查询数据源配置列表 */
|
/** 查询数据源配置列表 */
|
||||||
export function getDataSourceConfigList() {
|
export function getDataSourceConfigList() {
|
||||||
return requestClient.get<InfraDataSourceConfigApi.InfraDataSourceConfig[]>('/infra/data-source-config/list');
|
return requestClient.get<InfraDataSourceConfigApi.InfraDataSourceConfig[]>(
|
||||||
|
'/infra/data-source-config/list',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询数据源配置详情 */
|
/** 查询数据源配置详情 */
|
||||||
export function getDataSourceConfig(id: number) {
|
export function getDataSourceConfig(id: number) {
|
||||||
return requestClient.get<InfraDataSourceConfigApi.InfraDataSourceConfig>(`/infra/data-source-config/get?id=${id}`);
|
return requestClient.get<InfraDataSourceConfigApi.InfraDataSourceConfig>(
|
||||||
|
`/infra/data-source-config/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增数据源配置 */
|
/** 新增数据源配置 */
|
||||||
export function createDataSourceConfig(data: InfraDataSourceConfigApi.InfraDataSourceConfig) {
|
export function createDataSourceConfig(
|
||||||
|
data: InfraDataSourceConfigApi.InfraDataSourceConfig,
|
||||||
|
) {
|
||||||
return requestClient.post('/infra/data-source-config/create', data);
|
return requestClient.post('/infra/data-source-config/create', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 修改数据源配置 */
|
/** 修改数据源配置 */
|
||||||
export function updateDataSourceConfig(data: InfraDataSourceConfigApi.InfraDataSourceConfig) {
|
export function updateDataSourceConfig(
|
||||||
|
data: InfraDataSourceConfigApi.InfraDataSourceConfig,
|
||||||
|
) {
|
||||||
return requestClient.put('/infra/data-source-config/update', data);
|
return requestClient.put('/infra/data-source-config/update', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,17 @@ export namespace Demo01ContactApi {
|
||||||
|
|
||||||
/** 查询示例联系人分页 */
|
/** 查询示例联系人分页 */
|
||||||
export function getDemo01ContactPage(params: PageParam) {
|
export function getDemo01ContactPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<Demo01ContactApi.Demo01Contact>>('/infra/demo01-contact/page', { params });
|
return requestClient.get<PageResult<Demo01ContactApi.Demo01Contact>>(
|
||||||
|
'/infra/demo01-contact/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询示例联系人详情 */
|
/** 查询示例联系人详情 */
|
||||||
export function getDemo01Contact(id: number) {
|
export function getDemo01Contact(id: number) {
|
||||||
return requestClient.get<Demo01ContactApi.Demo01Contact>(`/infra/demo01-contact/get?id=${id}`);
|
return requestClient.get<Demo01ContactApi.Demo01Contact>(
|
||||||
|
`/infra/demo01-contact/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增示例联系人 */
|
/** 新增示例联系人 */
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,17 @@ export namespace Demo02CategoryApi {
|
||||||
|
|
||||||
/** 查询示例分类列表 */
|
/** 查询示例分类列表 */
|
||||||
export function getDemo02CategoryList(params: any) {
|
export function getDemo02CategoryList(params: any) {
|
||||||
return requestClient.get<Demo02CategoryApi.Demo02Category[]>('/infra/demo02-category/list', { params });
|
return requestClient.get<Demo02CategoryApi.Demo02Category[]>(
|
||||||
|
'/infra/demo02-category/list',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询示例分类详情 */
|
/** 查询示例分类详情 */
|
||||||
export function getDemo02Category(id: number) {
|
export function getDemo02Category(id: number) {
|
||||||
return requestClient.get<Demo02CategoryApi.Demo02Category>(`/infra/demo02-category/get?id=${id}`);
|
return requestClient.get<Demo02CategoryApi.Demo02Category>(
|
||||||
|
`/infra/demo02-category/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增示例分类 */
|
/** 新增示例分类 */
|
||||||
|
|
|
||||||
|
|
@ -32,12 +32,17 @@ export namespace Demo03StudentApi {
|
||||||
|
|
||||||
/** 查询学生分页 */
|
/** 查询学生分页 */
|
||||||
export function getDemo03StudentPage(params: PageParam) {
|
export function getDemo03StudentPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<Demo03StudentApi.Demo03Student>>('/infra/demo03-student/page', { params });
|
return requestClient.get<PageResult<Demo03StudentApi.Demo03Student>>(
|
||||||
|
'/infra/demo03-student/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询学生详情 */
|
/** 查询学生详情 */
|
||||||
export function getDemo03Student(id: number) {
|
export function getDemo03Student(id: number) {
|
||||||
return requestClient.get<Demo03StudentApi.Demo03Student>(`/infra/demo03-student/get?id=${id}`);
|
return requestClient.get<Demo03StudentApi.Demo03Student>(
|
||||||
|
`/infra/demo03-student/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增学生 */
|
/** 新增学生 */
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,17 @@ export namespace Demo03StudentApi {
|
||||||
|
|
||||||
/** 查询学生分页 */
|
/** 查询学生分页 */
|
||||||
export function getDemo03StudentPage(params: PageParam) {
|
export function getDemo03StudentPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<Demo03StudentApi.Demo03Student>>('/infra/demo03-student/page', { params });
|
return requestClient.get<PageResult<Demo03StudentApi.Demo03Student>>(
|
||||||
|
'/infra/demo03-student/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询学生详情 */
|
/** 查询学生详情 */
|
||||||
export function getDemo03Student(id: number) {
|
export function getDemo03Student(id: number) {
|
||||||
return requestClient.get<Demo03StudentApi.Demo03Student>(`/infra/demo03-student/get?id=${id}`);
|
return requestClient.get<Demo03StudentApi.Demo03Student>(
|
||||||
|
`/infra/demo03-student/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增学生 */
|
/** 新增学生 */
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace InfraFileConfigApi {
|
export namespace InfraFileConfigApi {
|
||||||
/** 文件客户端配置 */
|
/** 文件客户端配置 */
|
||||||
export interface FileClientConfig {
|
export interface FileClientConfig {
|
||||||
|
|
@ -32,14 +33,19 @@ export namespace InfraFileConfigApi {
|
||||||
|
|
||||||
/** 查询文件配置列表 */
|
/** 查询文件配置列表 */
|
||||||
export function getFileConfigPage(params: PageParam) {
|
export function getFileConfigPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<InfraFileConfigApi.InfraFileConfig>>('/infra/file-config/page', {
|
return requestClient.get<PageResult<InfraFileConfigApi.InfraFileConfig>>(
|
||||||
params
|
'/infra/file-config/page',
|
||||||
});
|
{
|
||||||
|
params,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询文件配置详情 */
|
/** 查询文件配置详情 */
|
||||||
export function getFileConfig(id: number) {
|
export function getFileConfig(id: number) {
|
||||||
return requestClient.get<InfraFileConfigApi.InfraFileConfig>(`/infra/file-config/get?id=${id}`);
|
return requestClient.get<InfraFileConfigApi.InfraFileConfig>(
|
||||||
|
`/infra/file-config/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 更新文件配置为主配置 */
|
/** 更新文件配置为主配置 */
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
|
import type { AxiosRequestConfig, PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
|
||||||
import type { AxiosRequestConfig } from '@vben/request';
|
|
||||||
|
|
||||||
/** Axios 上传进度事件 */
|
/** Axios 上传进度事件 */
|
||||||
export type AxiosProgressEvent = AxiosRequestConfig['onUploadProgress'];
|
export type AxiosProgressEvent = AxiosRequestConfig['onUploadProgress'];
|
||||||
|
|
@ -34,9 +34,12 @@ export namespace InfraFileApi {
|
||||||
|
|
||||||
/** 查询文件列表 */
|
/** 查询文件列表 */
|
||||||
export function getFilePage(params: PageParam) {
|
export function getFilePage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<InfraFileApi.InfraFile>>('/infra/file/page', {
|
return requestClient.get<PageResult<InfraFileApi.InfraFile>>(
|
||||||
params
|
'/infra/file/page',
|
||||||
});
|
{
|
||||||
|
params,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除文件 */
|
/** 删除文件 */
|
||||||
|
|
@ -46,9 +49,12 @@ export function deleteFile(id: number) {
|
||||||
|
|
||||||
/** 获取文件预签名地址 */
|
/** 获取文件预签名地址 */
|
||||||
export function getFilePresignedUrl(path: string) {
|
export function getFilePresignedUrl(path: string) {
|
||||||
return requestClient.get<InfraFileApi.FilePresignedUrlRespVO>('/infra/file/presigned-url', {
|
return requestClient.get<InfraFileApi.FilePresignedUrlRespVO>(
|
||||||
params: { path }
|
'/infra/file/presigned-url',
|
||||||
});
|
{
|
||||||
|
params: { path },
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 创建文件 */
|
/** 创建文件 */
|
||||||
|
|
@ -57,6 +63,9 @@ export function createFile(data: InfraFileApi.InfraFile) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 上传文件 */
|
/** 上传文件 */
|
||||||
export function uploadFile(data: InfraFileApi.FileUploadReqVO, onUploadProgress?: AxiosProgressEvent) {
|
export function uploadFile(
|
||||||
|
data: InfraFileApi.FileUploadReqVO,
|
||||||
|
onUploadProgress?: AxiosProgressEvent,
|
||||||
|
) {
|
||||||
return requestClient.upload('/infra/file/upload', data, { onUploadProgress });
|
return requestClient.upload('/infra/file/upload', data, { onUploadProgress });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,17 @@ export namespace InfraJobLogApi {
|
||||||
|
|
||||||
/** 查询任务日志列表 */
|
/** 查询任务日志列表 */
|
||||||
export function getJobLogPage(params: PageParam) {
|
export function getJobLogPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<InfraJobLogApi.InfraJobLog>>('/infra/job-log/page', { params });
|
return requestClient.get<PageResult<InfraJobLogApi.InfraJobLog>>(
|
||||||
|
'/infra/job-log/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询任务日志详情 */
|
/** 查询任务日志详情 */
|
||||||
export function getJobLog(id: number) {
|
export function getJobLog(id: number) {
|
||||||
return requestClient.get<InfraJobLogApi.InfraJobLog>(`/infra/job-log/get?id=${id}`);
|
return requestClient.get<InfraJobLogApi.InfraJobLog>(
|
||||||
|
`/infra/job-log/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 导出定时任务日志 */
|
/** 导出定时任务日志 */
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,10 @@ export namespace InfraJobApi {
|
||||||
|
|
||||||
/** 查询任务列表 */
|
/** 查询任务列表 */
|
||||||
export function getJobPage(params: PageParam) {
|
export function getJobPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<InfraJobApi.InfraJob>>('/infra/job/page', { params });
|
return requestClient.get<PageResult<InfraJobApi.InfraJob>>(
|
||||||
|
'/infra/job/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询任务详情 */
|
/** 查询任务详情 */
|
||||||
|
|
@ -52,7 +55,7 @@ export function exportJob(params: any) {
|
||||||
export function updateJobStatus(id: number, status: number) {
|
export function updateJobStatus(id: number, status: number) {
|
||||||
const params = {
|
const params = {
|
||||||
id,
|
id,
|
||||||
status
|
status,
|
||||||
};
|
};
|
||||||
return requestClient.put('/infra/job/update-status', { params });
|
return requestClient.put('/infra/job/update-status', { params });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,6 @@
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace InfraRedisApi {
|
export namespace InfraRedisApi {
|
||||||
/** Redis 监控信息 */
|
|
||||||
export interface InfraRedisMonitorInfo {
|
|
||||||
info: InfraRedisInfo;
|
|
||||||
dbSize: number;
|
|
||||||
commandStats: InfraRedisCommandStats[];
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Redis 信息 */
|
/** Redis 信息 */
|
||||||
export interface InfraRedisInfo {
|
export interface InfraRedisInfo {
|
||||||
io_threaded_reads_processed: string;
|
io_threaded_reads_processed: string;
|
||||||
|
|
@ -180,9 +173,18 @@ export namespace InfraRedisApi {
|
||||||
calls: number;
|
calls: number;
|
||||||
usec: number;
|
usec: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Redis 监控信息 */
|
||||||
|
export interface InfraRedisMonitorInfo {
|
||||||
|
info: InfraRedisInfo;
|
||||||
|
dbSize: number;
|
||||||
|
commandStats: InfraRedisCommandStats[];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获取 Redis 监控信息 */
|
/** 获取 Redis 监控信息 */
|
||||||
export function getRedisMonitorInfo() {
|
export function getRedisMonitorInfo() {
|
||||||
return requestClient.get<InfraRedisApi.InfraRedisMonitorInfo>('/infra/redis/get-monitor-info');
|
return requestClient.get<InfraRedisApi.InfraRedisMonitorInfo>(
|
||||||
|
'/infra/redis/get-monitor-info',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,10 @@ import { useAuthStore } from '#/store';
|
||||||
|
|
||||||
import { refreshTokenApi } from './core';
|
import { refreshTokenApi } from './core';
|
||||||
|
|
||||||
const { apiURL, tenantEnable } = useAppConfig(import.meta.env, import.meta.env.PROD);
|
const { apiURL, tenantEnable } = useAppConfig(
|
||||||
|
import.meta.env,
|
||||||
|
import.meta.env.PROD,
|
||||||
|
);
|
||||||
|
|
||||||
function createRequestClient(baseURL: string, options?: RequestClientOptions) {
|
function createRequestClient(baseURL: string, options?: RequestClientOptions) {
|
||||||
const client = new RequestClient({
|
const client = new RequestClient({
|
||||||
|
|
@ -76,7 +79,9 @@ function createRequestClient(baseURL: string, options?: RequestClientOptions) {
|
||||||
config.headers.Authorization = formatToken(accessStore.accessToken);
|
config.headers.Authorization = formatToken(accessStore.accessToken);
|
||||||
config.headers['Accept-Language'] = preferences.app.locale;
|
config.headers['Accept-Language'] = preferences.app.locale;
|
||||||
// 添加租户编号
|
// 添加租户编号
|
||||||
config.headers['tenant-id'] = tenantEnable ? accessStore.tenantId : undefined;
|
config.headers['tenant-id'] = tenantEnable
|
||||||
|
? accessStore.tenantId
|
||||||
|
: undefined;
|
||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
@ -130,7 +135,9 @@ baseRequestClient.addRequestInterceptor({
|
||||||
fulfilled: (config) => {
|
fulfilled: (config) => {
|
||||||
const accessStore = useAccessStore();
|
const accessStore = useAccessStore();
|
||||||
// 添加租户编号
|
// 添加租户编号
|
||||||
config.headers['tenant-id'] = tenantEnable? accessStore.tenantId : undefined;
|
config.headers['tenant-id'] = tenantEnable
|
||||||
|
? accessStore.tenantId
|
||||||
|
: undefined;
|
||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,9 @@ export namespace SystemDeptApi {
|
||||||
|
|
||||||
/** 查询部门(精简)列表 */
|
/** 查询部门(精简)列表 */
|
||||||
export async function getSimpleDeptList() {
|
export async function getSimpleDeptList() {
|
||||||
return requestClient.get<SystemDeptApi.SystemDept[]>('/system/dept/simple-list');
|
return requestClient.get<SystemDeptApi.SystemDept[]>(
|
||||||
|
'/system/dept/simple-list',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询部门列表 */
|
/** 查询部门列表 */
|
||||||
|
|
@ -28,7 +30,9 @@ export async function getDeptList() {
|
||||||
|
|
||||||
/** 查询部门详情 */
|
/** 查询部门详情 */
|
||||||
export async function getDept(id: number) {
|
export async function getDept(id: number) {
|
||||||
return requestClient.get<SystemDeptApi.SystemDept>(`/system/dept/get?id=${id}`);
|
return requestClient.get<SystemDeptApi.SystemDept>(
|
||||||
|
`/system/dept/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增部门 */
|
/** 新增部门 */
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,16 @@ import { requestClient } from '#/api/request';
|
||||||
export namespace SystemDictDataApi {
|
export namespace SystemDictDataApi {
|
||||||
/** 字典数据 */
|
/** 字典数据 */
|
||||||
export type SystemDictData = {
|
export type SystemDictData = {
|
||||||
id?: number;
|
|
||||||
colorType: string;
|
colorType: string;
|
||||||
|
createTime: Date;
|
||||||
cssClass: string;
|
cssClass: string;
|
||||||
dictType: string;
|
dictType: string;
|
||||||
|
id?: number;
|
||||||
label: string;
|
label: string;
|
||||||
remark: string;
|
remark: string;
|
||||||
sort?: number;
|
sort?: number;
|
||||||
status: number;
|
status: number;
|
||||||
value: string;
|
value: string;
|
||||||
createTime: Date;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,23 @@
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export type DictTypeVO = {
|
||||||
|
createTime: Date;
|
||||||
|
id: number | undefined;
|
||||||
|
name: string;
|
||||||
|
remark: string;
|
||||||
|
status: number;
|
||||||
|
type: string;
|
||||||
|
};
|
||||||
|
|
||||||
export namespace SystemDictTypeApi {
|
export namespace SystemDictTypeApi {
|
||||||
/** 字典类型 */
|
/** 字典类型 */
|
||||||
export type SystemDictType = {
|
export type SystemDictType = {
|
||||||
|
createTime: Date;
|
||||||
id?: number;
|
id?: number;
|
||||||
name: string;
|
name: string;
|
||||||
remark: string;
|
remark: string;
|
||||||
status: number;
|
status: number;
|
||||||
type: string;
|
type: string;
|
||||||
createTime: Date;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,9 @@ export namespace SystemLoginLogApi {
|
||||||
|
|
||||||
/** 查询登录日志列表 */
|
/** 查询登录日志列表 */
|
||||||
export function getLoginLogPage(params: PageParam) {
|
export function getLoginLogPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<SystemLoginLogApi.SystemLoginLog>>('/system/login-log/page',
|
return requestClient.get<PageResult<SystemLoginLogApi.SystemLoginLog>>(
|
||||||
{ params }
|
'/system/login-log/page',
|
||||||
|
{ params },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,22 +23,28 @@ export namespace SystemMailAccountApi {
|
||||||
export function getMailAccountPage(params: PageParam) {
|
export function getMailAccountPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<SystemMailAccountApi.SystemMailAccount>>(
|
return requestClient.get<PageResult<SystemMailAccountApi.SystemMailAccount>>(
|
||||||
'/system/mail-account/page',
|
'/system/mail-account/page',
|
||||||
{ params }
|
{ params },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询邮箱账号详情 */
|
/** 查询邮箱账号详情 */
|
||||||
export function getMailAccount(id: number) {
|
export function getMailAccount(id: number) {
|
||||||
return requestClient.get<SystemMailAccountApi.SystemMailAccount>(`/system/mail-account/get?id=${id}`);
|
return requestClient.get<SystemMailAccountApi.SystemMailAccount>(
|
||||||
|
`/system/mail-account/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增邮箱账号 */
|
/** 新增邮箱账号 */
|
||||||
export function createMailAccount(data: SystemMailAccountApi.SystemMailAccount) {
|
export function createMailAccount(
|
||||||
|
data: SystemMailAccountApi.SystemMailAccount,
|
||||||
|
) {
|
||||||
return requestClient.post('/system/mail-account/create', data);
|
return requestClient.post('/system/mail-account/create', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 修改邮箱账号 */
|
/** 修改邮箱账号 */
|
||||||
export function updateMailAccount(data: SystemMailAccountApi.SystemMailAccount) {
|
export function updateMailAccount(
|
||||||
|
data: SystemMailAccountApi.SystemMailAccount,
|
||||||
|
) {
|
||||||
return requestClient.put('/system/mail-account/update', data);
|
return requestClient.put('/system/mail-account/update', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,5 +55,7 @@ export function deleteMailAccount(id: number) {
|
||||||
|
|
||||||
/** 获得邮箱账号精简列表 */
|
/** 获得邮箱账号精简列表 */
|
||||||
export function getSimpleMailAccountList() {
|
export function getSimpleMailAccountList() {
|
||||||
return requestClient.get<SystemMailAccountApi.SystemMailAccount[]>('/system/mail-account/simple-list');
|
return requestClient.get<SystemMailAccountApi.SystemMailAccount[]>(
|
||||||
|
'/system/mail-account/simple-list',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,15 @@ export namespace SystemMailLogApi {
|
||||||
export function getMailLogPage(params: PageParam) {
|
export function getMailLogPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<SystemMailLogApi.SystemMailLog>>(
|
return requestClient.get<PageResult<SystemMailLogApi.SystemMailLog>>(
|
||||||
'/system/mail-log/page',
|
'/system/mail-log/page',
|
||||||
{ params }
|
{ params },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询邮件日志详情 */
|
/** 查询邮件日志详情 */
|
||||||
export function getMailLog(id: number) {
|
export function getMailLog(id: number) {
|
||||||
return requestClient.get<SystemMailLogApi.SystemMailLog>(`/system/mail-log/get?id=${id}`);
|
return requestClient.get<SystemMailLogApi.SystemMailLog>(
|
||||||
|
`/system/mail-log/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 重新发送邮件 */
|
/** 重新发送邮件 */
|
||||||
|
|
|
||||||
|
|
@ -28,24 +28,29 @@ export namespace SystemMailTemplateApi {
|
||||||
|
|
||||||
/** 查询邮件模版列表 */
|
/** 查询邮件模版列表 */
|
||||||
export function getMailTemplatePage(params: PageParam) {
|
export function getMailTemplatePage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<SystemMailTemplateApi.SystemMailTemplate>>(
|
return requestClient.get<
|
||||||
'/system/mail-template/page',
|
PageResult<SystemMailTemplateApi.SystemMailTemplate>
|
||||||
{ params }
|
>('/system/mail-template/page', { params });
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询邮件模版详情 */
|
/** 查询邮件模版详情 */
|
||||||
export function getMailTemplate(id: number) {
|
export function getMailTemplate(id: number) {
|
||||||
return requestClient.get<SystemMailTemplateApi.SystemMailTemplate>(`/system/mail-template/get?id=${id}`);
|
return requestClient.get<SystemMailTemplateApi.SystemMailTemplate>(
|
||||||
|
`/system/mail-template/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增邮件模版 */
|
/** 新增邮件模版 */
|
||||||
export function createMailTemplate(data: SystemMailTemplateApi.SystemMailTemplate) {
|
export function createMailTemplate(
|
||||||
|
data: SystemMailTemplateApi.SystemMailTemplate,
|
||||||
|
) {
|
||||||
return requestClient.post('/system/mail-template/create', data);
|
return requestClient.post('/system/mail-template/create', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 修改邮件模版 */
|
/** 修改邮件模版 */
|
||||||
export function updateMailTemplate(data: SystemMailTemplateApi.SystemMailTemplate) {
|
export function updateMailTemplate(
|
||||||
|
data: SystemMailTemplateApi.SystemMailTemplate,
|
||||||
|
) {
|
||||||
return requestClient.put('/system/mail-template/update', data);
|
return requestClient.put('/system/mail-template/update', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,17 +23,23 @@ export namespace SystemMenuApi {
|
||||||
|
|
||||||
/** 查询菜单(精简)列表 */
|
/** 查询菜单(精简)列表 */
|
||||||
export async function getSimpleMenusList() {
|
export async function getSimpleMenusList() {
|
||||||
return requestClient.get<SystemMenuApi.SystemMenu[]>('/system/menu/simple-list');
|
return requestClient.get<SystemMenuApi.SystemMenu[]>(
|
||||||
|
'/system/menu/simple-list',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询菜单列表 */
|
/** 查询菜单列表 */
|
||||||
export async function getMenuList(params?: Record<string, any>) {
|
export async function getMenuList(params?: Record<string, any>) {
|
||||||
return requestClient.get<SystemMenuApi.SystemMenu[]>('/system/menu/list', { params });
|
return requestClient.get<SystemMenuApi.SystemMenu[]>('/system/menu/list', {
|
||||||
|
params,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获取菜单详情 */
|
/** 获取菜单详情 */
|
||||||
export async function getMenu(id: number) {
|
export async function getMenu(id: number) {
|
||||||
return requestClient.get<SystemMenuApi.SystemMenu>(`/system/menu/get?id=${id}`);
|
return requestClient.get<SystemMenuApi.SystemMenu>(
|
||||||
|
`/system/menu/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增菜单 */
|
/** 新增菜单 */
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace SystemNoticeApi {
|
export namespace SystemNoticeApi {
|
||||||
/** 公告信息 */
|
/** 公告信息 */
|
||||||
export interface SystemNotice {
|
export interface SystemNotice {
|
||||||
|
|
@ -17,12 +18,17 @@ export namespace SystemNoticeApi {
|
||||||
|
|
||||||
/** 查询公告列表 */
|
/** 查询公告列表 */
|
||||||
export function getNoticePage(params: PageParam) {
|
export function getNoticePage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<SystemNoticeApi.SystemNotice>>('/system/notice/page', { params });
|
return requestClient.get<PageResult<SystemNoticeApi.SystemNotice>>(
|
||||||
|
'/system/notice/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询公告详情 */
|
/** 查询公告详情 */
|
||||||
export function getNotice(id: number) {
|
export function getNotice(id: number) {
|
||||||
return requestClient.get<SystemNoticeApi.SystemNotice>(`/system/notice/get?id=${id}`);
|
return requestClient.get<SystemNoticeApi.SystemNotice>(
|
||||||
|
`/system/notice/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增公告 */
|
/** 新增公告 */
|
||||||
|
|
|
||||||
|
|
@ -22,18 +22,16 @@ export namespace SystemNotifyMessageApi {
|
||||||
|
|
||||||
/** 查询站内信消息列表 */
|
/** 查询站内信消息列表 */
|
||||||
export function getNotifyMessagePage(params: PageParam) {
|
export function getNotifyMessagePage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<SystemNotifyMessageApi.SystemNotifyMessage>>(
|
return requestClient.get<
|
||||||
'/system/notify-message/page',
|
PageResult<SystemNotifyMessageApi.SystemNotifyMessage>
|
||||||
{ params },
|
>('/system/notify-message/page', { params });
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获得我的站内信分页 */
|
/** 获得我的站内信分页 */
|
||||||
export function getMyNotifyMessagePage(params: PageParam) {
|
export function getMyNotifyMessagePage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<SystemNotifyMessageApi.SystemNotifyMessage>>(
|
return requestClient.get<
|
||||||
'/system/notify-message/my-page',
|
PageResult<SystemNotifyMessageApi.SystemNotifyMessage>
|
||||||
{ params },
|
>('/system/notify-message/my-page', { params });
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 批量标记已读 */
|
/** 批量标记已读 */
|
||||||
|
|
@ -48,7 +46,9 @@ export function updateAllNotifyMessageRead() {
|
||||||
|
|
||||||
/** 获取当前用户的最新站内信列表 */
|
/** 获取当前用户的最新站内信列表 */
|
||||||
export function getUnreadNotifyMessageList() {
|
export function getUnreadNotifyMessageList() {
|
||||||
return requestClient.get<SystemNotifyMessageApi.SystemNotifyMessage[]>('/system/notify-message/get-unread-list');
|
return requestClient.get<SystemNotifyMessageApi.SystemNotifyMessage[]>(
|
||||||
|
'/system/notify-message/get-unread-list',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获得当前用户的未读站内信数量 */
|
/** 获得当前用户的未读站内信数量 */
|
||||||
|
|
|
||||||
|
|
@ -26,24 +26,29 @@ export namespace SystemNotifyTemplateApi {
|
||||||
|
|
||||||
/** 查询站内信模板列表 */
|
/** 查询站内信模板列表 */
|
||||||
export function getNotifyTemplatePage(params: PageParam) {
|
export function getNotifyTemplatePage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<SystemNotifyTemplateApi.SystemNotifyTemplate>>(
|
return requestClient.get<
|
||||||
'/system/notify-template/page',
|
PageResult<SystemNotifyTemplateApi.SystemNotifyTemplate>
|
||||||
{ params },
|
>('/system/notify-template/page', { params });
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询站内信模板详情 */
|
/** 查询站内信模板详情 */
|
||||||
export function getNotifyTemplate(id: number) {
|
export function getNotifyTemplate(id: number) {
|
||||||
return requestClient.get<SystemNotifyTemplateApi.SystemNotifyTemplate>(`/system/notify-template/get?id=${id}`);
|
return requestClient.get<SystemNotifyTemplateApi.SystemNotifyTemplate>(
|
||||||
|
`/system/notify-template/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增站内信模板 */
|
/** 新增站内信模板 */
|
||||||
export function createNotifyTemplate(data: SystemNotifyTemplateApi.SystemNotifyTemplate) {
|
export function createNotifyTemplate(
|
||||||
|
data: SystemNotifyTemplateApi.SystemNotifyTemplate,
|
||||||
|
) {
|
||||||
return requestClient.post('/system/notify-template/create', data);
|
return requestClient.post('/system/notify-template/create', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 修改站内信模板 */
|
/** 修改站内信模板 */
|
||||||
export function updateNotifyTemplate(data: SystemNotifyTemplateApi.SystemNotifyTemplate) {
|
export function updateNotifyTemplate(
|
||||||
|
data: SystemNotifyTemplateApi.SystemNotifyTemplate,
|
||||||
|
) {
|
||||||
return requestClient.put('/system/notify-template/update', data);
|
return requestClient.put('/system/notify-template/update', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,10 +59,14 @@ export function deleteNotifyTemplate(id: number) {
|
||||||
|
|
||||||
/** 导出站内信模板 */
|
/** 导出站内信模板 */
|
||||||
export function exportNotifyTemplate(params: any) {
|
export function exportNotifyTemplate(params: any) {
|
||||||
return requestClient.download('/system/notify-template/export-excel', { params });
|
return requestClient.download('/system/notify-template/export-excel', {
|
||||||
|
params,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 发送站内信 */
|
/** 发送站内信 */
|
||||||
export function sendNotify(data: SystemNotifyTemplateApi.SystemNotifySendReqVO) {
|
export function sendNotify(
|
||||||
|
data: SystemNotifyTemplateApi.SystemNotifySendReqVO,
|
||||||
|
) {
|
||||||
return requestClient.post('/system/notify-template/send-notify', data);
|
return requestClient.post('/system/notify-template/send-notify', data);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace SystemOAuth2ClientApi {
|
export namespace SystemOAuth2ClientApi {
|
||||||
/** OAuth2.0 客户端信息 */
|
/** OAuth2.0 客户端信息 */
|
||||||
export interface SystemOAuth2Client {
|
export interface SystemOAuth2Client {
|
||||||
|
|
@ -27,23 +28,29 @@ export namespace SystemOAuth2ClientApi {
|
||||||
|
|
||||||
/** 查询 OAuth2.0 客户端列表 */
|
/** 查询 OAuth2.0 客户端列表 */
|
||||||
export function getOAuth2ClientPage(params: PageParam) {
|
export function getOAuth2ClientPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<SystemOAuth2ClientApi.SystemOAuth2Client>>('/system/oauth2-client/page',
|
return requestClient.get<
|
||||||
{ params }
|
PageResult<SystemOAuth2ClientApi.SystemOAuth2Client>
|
||||||
);
|
>('/system/oauth2-client/page', { params });
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询 OAuth2.0 客户端详情 */
|
/** 查询 OAuth2.0 客户端详情 */
|
||||||
export function getOAuth2Client(id: number) {
|
export function getOAuth2Client(id: number) {
|
||||||
return requestClient.get<SystemOAuth2ClientApi.SystemOAuth2Client>(`/system/oauth2-client/get?id=${id}`);
|
return requestClient.get<SystemOAuth2ClientApi.SystemOAuth2Client>(
|
||||||
|
`/system/oauth2-client/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增 OAuth2.0 客户端 */
|
/** 新增 OAuth2.0 客户端 */
|
||||||
export function createOAuth2Client(data: SystemOAuth2ClientApi.SystemOAuth2Client) {
|
export function createOAuth2Client(
|
||||||
|
data: SystemOAuth2ClientApi.SystemOAuth2Client,
|
||||||
|
) {
|
||||||
return requestClient.post('/system/oauth2-client/create', data);
|
return requestClient.post('/system/oauth2-client/create', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 修改 OAuth2.0 客户端 */
|
/** 修改 OAuth2.0 客户端 */
|
||||||
export function updateOAuth2Client(data: SystemOAuth2ClientApi.SystemOAuth2Client) {
|
export function updateOAuth2Client(
|
||||||
|
data: SystemOAuth2ClientApi.SystemOAuth2Client,
|
||||||
|
) {
|
||||||
return requestClient.put('/system/oauth2-client/update', data);
|
return requestClient.put('/system/oauth2-client/update', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ import { requestClient } from '#/api/request';
|
||||||
/** OAuth2.0 授权信息响应 */
|
/** OAuth2.0 授权信息响应 */
|
||||||
export interface OAuth2OpenAuthorizeInfoRespVO {
|
export interface OAuth2OpenAuthorizeInfoRespVO {
|
||||||
client: {
|
client: {
|
||||||
name: string;
|
|
||||||
logo: string;
|
logo: string;
|
||||||
|
name: string;
|
||||||
};
|
};
|
||||||
scopes: {
|
scopes: {
|
||||||
key: string;
|
key: string;
|
||||||
|
|
@ -14,7 +14,9 @@ export interface OAuth2OpenAuthorizeInfoRespVO {
|
||||||
|
|
||||||
/** 获得授权信息 */
|
/** 获得授权信息 */
|
||||||
export function getAuthorize(clientId: string) {
|
export function getAuthorize(clientId: string) {
|
||||||
return requestClient.get<OAuth2OpenAuthorizeInfoRespVO>(`/system/oauth2/authorize?clientId=${clientId}`);
|
return requestClient.get<OAuth2OpenAuthorizeInfoRespVO>(
|
||||||
|
`/system/oauth2/authorize?clientId=${clientId}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 发起授权 */
|
/** 发起授权 */
|
||||||
|
|
@ -25,7 +27,7 @@ export function authorize(
|
||||||
state: string,
|
state: string,
|
||||||
autoApprove: boolean,
|
autoApprove: boolean,
|
||||||
checkedScopes: string[],
|
checkedScopes: string[],
|
||||||
uncheckedScopes: string[]
|
uncheckedScopes: string[],
|
||||||
) {
|
) {
|
||||||
// 构建 scopes
|
// 构建 scopes
|
||||||
const scopes: Record<string, boolean> = {};
|
const scopes: Record<string, boolean> = {};
|
||||||
|
|
@ -39,15 +41,15 @@ export function authorize(
|
||||||
// 发起请求
|
// 发起请求
|
||||||
return requestClient.post<string>('/system/oauth2/authorize', null, {
|
return requestClient.post<string>('/system/oauth2/authorize', null, {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
},
|
},
|
||||||
params: {
|
params: {
|
||||||
response_type: responseType,
|
response_type: responseType,
|
||||||
client_id: clientId,
|
client_id: clientId,
|
||||||
redirect_uri: redirectUri,
|
redirect_uri: redirectUri,
|
||||||
state: state,
|
state,
|
||||||
auto_approve: autoApprove,
|
auto_approve: autoApprove,
|
||||||
scope: JSON.stringify(scopes)
|
scope: JSON.stringify(scopes),
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace SystemOAuth2TokenApi {
|
export namespace SystemOAuth2TokenApi {
|
||||||
/** OAuth2.0 令牌信息 */
|
/** OAuth2.0 令牌信息 */
|
||||||
export interface SystemOAuth2Token {
|
export interface SystemOAuth2Token {
|
||||||
|
|
@ -17,12 +18,17 @@ export namespace SystemOAuth2TokenApi {
|
||||||
|
|
||||||
/** 查询 OAuth2.0 令牌列表 */
|
/** 查询 OAuth2.0 令牌列表 */
|
||||||
export function getOAuth2TokenPage(params: PageParam) {
|
export function getOAuth2TokenPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<SystemOAuth2TokenApi.SystemOAuth2Token>>('/system/oauth2-token/page', {
|
return requestClient.get<PageResult<SystemOAuth2TokenApi.SystemOAuth2Token>>(
|
||||||
params
|
'/system/oauth2-token/page',
|
||||||
});
|
{
|
||||||
|
params,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除 OAuth2.0 令牌 */
|
/** 删除 OAuth2.0 令牌 */
|
||||||
export function deleteOAuth2Token(accessToken: string) {
|
export function deleteOAuth2Token(accessToken: string) {
|
||||||
return requestClient.delete(`/system/oauth2-token/delete?accessToken=${accessToken}`);
|
return requestClient.delete(
|
||||||
|
`/system/oauth2-token/delete?accessToken=${accessToken}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,9 @@ export namespace SystemOperateLogApi {
|
||||||
|
|
||||||
/** 查询操作日志列表 */
|
/** 查询操作日志列表 */
|
||||||
export function getOperateLogPage(params: PageParam) {
|
export function getOperateLogPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<SystemOperateLogApi.SystemOperateLog>>('/system/operate-log/page',
|
return requestClient.get<PageResult<SystemOperateLogApi.SystemOperateLog>>(
|
||||||
{ params }
|
'/system/operate-log/page',
|
||||||
|
{ params },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
import type {PageParam, PageResult} from '@vben/request';
|
|
||||||
|
|
||||||
export namespace SystemPostApi {
|
export namespace SystemPostApi {
|
||||||
/** 岗位信息 */
|
/** 岗位信息 */
|
||||||
|
|
@ -16,19 +17,26 @@ export namespace SystemPostApi {
|
||||||
|
|
||||||
/** 查询岗位列表 */
|
/** 查询岗位列表 */
|
||||||
export function getPostPage(params: PageParam) {
|
export function getPostPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<SystemPostApi.SystemPost>>('/system/post/page', {
|
return requestClient.get<PageResult<SystemPostApi.SystemPost>>(
|
||||||
params
|
'/system/post/page',
|
||||||
});
|
{
|
||||||
|
params,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获取岗位精简信息列表 */
|
/** 获取岗位精简信息列表 */
|
||||||
export function getSimplePostList() {
|
export function getSimplePostList() {
|
||||||
return requestClient.get<SystemPostApi.SystemPost[]>('/system/post/simple-list');
|
return requestClient.get<SystemPostApi.SystemPost[]>(
|
||||||
|
'/system/post/simple-list',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询岗位详情 */
|
/** 查询岗位详情 */
|
||||||
export function getPost(id: number) {
|
export function getPost(id: number) {
|
||||||
return requestClient.get<SystemPostApi.SystemPost>(`/system/post/get?id=${id}`);
|
return requestClient.get<SystemPostApi.SystemPost>(
|
||||||
|
`/system/post/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增岗位 */
|
/** 新增岗位 */
|
||||||
|
|
@ -49,6 +57,6 @@ export function deletePost(id: number) {
|
||||||
/** 导出岗位 */
|
/** 导出岗位 */
|
||||||
export function exportPost(params: any) {
|
export function exportPost(params: any) {
|
||||||
return requestClient.download('/system/post/export', {
|
return requestClient.download('/system/post/export', {
|
||||||
params
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace SystemRoleApi {
|
export namespace SystemRoleApi {
|
||||||
/** 角色信息 */
|
/** 角色信息 */
|
||||||
export interface SystemRole {
|
export interface SystemRole {
|
||||||
|
|
@ -18,17 +19,24 @@ export namespace SystemRoleApi {
|
||||||
|
|
||||||
/** 查询角色列表 */
|
/** 查询角色列表 */
|
||||||
export function getRolePage(params: PageParam) {
|
export function getRolePage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<SystemRoleApi.SystemRole>>('/system/role/page', { params });
|
return requestClient.get<PageResult<SystemRoleApi.SystemRole>>(
|
||||||
|
'/system/role/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询角色(精简)列表 */
|
/** 查询角色(精简)列表 */
|
||||||
export function getSimpleRoleList() {
|
export function getSimpleRoleList() {
|
||||||
return requestClient.get<SystemRoleApi.SystemRole[]>('/system/role/simple-list');
|
return requestClient.get<SystemRoleApi.SystemRole[]>(
|
||||||
|
'/system/role/simple-list',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询角色详情 */
|
/** 查询角色详情 */
|
||||||
export function getRole(id: number) {
|
export function getRole(id: number) {
|
||||||
return requestClient.get<SystemRoleApi.SystemRole>(`/system/role/get?id=${id}`);
|
return requestClient.get<SystemRoleApi.SystemRole>(
|
||||||
|
`/system/role/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增角色 */
|
/** 新增角色 */
|
||||||
|
|
|
||||||
|
|
@ -27,12 +27,16 @@ export function getSmsChannelPage(params: PageParam) {
|
||||||
|
|
||||||
/** 获得短信渠道精简列表 */
|
/** 获得短信渠道精简列表 */
|
||||||
export function getSimpleSmsChannelList() {
|
export function getSimpleSmsChannelList() {
|
||||||
return requestClient.get<SystemSmsChannelApi.SystemSmsChannel[]>('/system/sms-channel/simple-list');
|
return requestClient.get<SystemSmsChannelApi.SystemSmsChannel[]>(
|
||||||
|
'/system/sms-channel/simple-list',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询短信渠道详情 */
|
/** 查询短信渠道详情 */
|
||||||
export function getSmsChannel(id: number) {
|
export function getSmsChannel(id: number) {
|
||||||
return requestClient.get<SystemSmsChannelApi.SystemSmsChannel>(`/system/sms-channel/get?id=${id}`);
|
return requestClient.get<SystemSmsChannelApi.SystemSmsChannel>(
|
||||||
|
`/system/sms-channel/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增短信渠道 */
|
/** 新增短信渠道 */
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,10 @@ export namespace SystemSmsLogApi {
|
||||||
|
|
||||||
/** 查询短信日志列表 */
|
/** 查询短信日志列表 */
|
||||||
export function getSmsLogPage(params: PageParam) {
|
export function getSmsLogPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<SystemSmsLogApi.SystemSmsLog>>('/system/sms-log/page', { params });
|
return requestClient.get<PageResult<SystemSmsLogApi.SystemSmsLog>>(
|
||||||
|
'/system/sms-log/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 导出短信日志 */
|
/** 导出短信日志 */
|
||||||
|
|
|
||||||
|
|
@ -37,16 +37,22 @@ export function getSmsTemplatePage(params: PageParam) {
|
||||||
|
|
||||||
/** 查询短信模板详情 */
|
/** 查询短信模板详情 */
|
||||||
export function getSmsTemplate(id: number) {
|
export function getSmsTemplate(id: number) {
|
||||||
return requestClient.get<SystemSmsTemplateApi.SystemSmsTemplate>(`/system/sms-template/get?id=${id}`);
|
return requestClient.get<SystemSmsTemplateApi.SystemSmsTemplate>(
|
||||||
|
`/system/sms-template/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增短信模板 */
|
/** 新增短信模板 */
|
||||||
export function createSmsTemplate(data: SystemSmsTemplateApi.SystemSmsTemplate) {
|
export function createSmsTemplate(
|
||||||
|
data: SystemSmsTemplateApi.SystemSmsTemplate,
|
||||||
|
) {
|
||||||
return requestClient.post('/system/sms-template/create', data);
|
return requestClient.post('/system/sms-template/create', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 修改短信模板 */
|
/** 修改短信模板 */
|
||||||
export function updateSmsTemplate(data: SystemSmsTemplateApi.SystemSmsTemplate) {
|
export function updateSmsTemplate(
|
||||||
|
data: SystemSmsTemplateApi.SystemSmsTemplate,
|
||||||
|
) {
|
||||||
return requestClient.put('/system/sms-template/update', data);
|
return requestClient.put('/system/sms-template/update', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,7 +63,9 @@ export function deleteSmsTemplate(id: number) {
|
||||||
|
|
||||||
/** 导出短信模板 */
|
/** 导出短信模板 */
|
||||||
export function exportSmsTemplate(params: any) {
|
export function exportSmsTemplate(params: any) {
|
||||||
return requestClient.download('/system/sms-template/export-excel', { params });
|
return requestClient.download('/system/sms-template/export-excel', {
|
||||||
|
params,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 发送短信 */
|
/** 发送短信 */
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace SystemSocialClientApi {
|
export namespace SystemSocialClientApi {
|
||||||
/** 社交客户端信息 */
|
/** 社交客户端信息 */
|
||||||
export interface SystemSocialClient {
|
export interface SystemSocialClient {
|
||||||
|
|
@ -18,23 +19,29 @@ export namespace SystemSocialClientApi {
|
||||||
|
|
||||||
/** 查询社交客户端列表 */
|
/** 查询社交客户端列表 */
|
||||||
export function getSocialClientPage(params: PageParam) {
|
export function getSocialClientPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<SystemSocialClientApi.SystemSocialClient>>('/system/social-client/page',
|
return requestClient.get<
|
||||||
{ params }
|
PageResult<SystemSocialClientApi.SystemSocialClient>
|
||||||
);
|
>('/system/social-client/page', { params });
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询社交客户端详情 */
|
/** 查询社交客户端详情 */
|
||||||
export function getSocialClient(id: number) {
|
export function getSocialClient(id: number) {
|
||||||
return requestClient.get<SystemSocialClientApi.SystemSocialClient>(`/system/social-client/get?id=${id}`);
|
return requestClient.get<SystemSocialClientApi.SystemSocialClient>(
|
||||||
|
`/system/social-client/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增社交客户端 */
|
/** 新增社交客户端 */
|
||||||
export function createSocialClient(data: SystemSocialClientApi.SystemSocialClient) {
|
export function createSocialClient(
|
||||||
|
data: SystemSocialClientApi.SystemSocialClient,
|
||||||
|
) {
|
||||||
return requestClient.post('/system/social-client/create', data);
|
return requestClient.post('/system/social-client/create', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 修改社交客户端 */
|
/** 修改社交客户端 */
|
||||||
export function updateSocialClient(data: SystemSocialClientApi.SystemSocialClient) {
|
export function updateSocialClient(
|
||||||
|
data: SystemSocialClientApi.SystemSocialClient,
|
||||||
|
) {
|
||||||
return requestClient.put('/system/social-client/update', data);
|
return requestClient.put('/system/social-client/update', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,14 +35,17 @@ export namespace SystemSocialUserApi {
|
||||||
|
|
||||||
/** 查询社交用户列表 */
|
/** 查询社交用户列表 */
|
||||||
export function getSocialUserPage(params: PageParam) {
|
export function getSocialUserPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<SystemSocialUserApi.SystemSocialUser>>('/system/social-user/page',
|
return requestClient.get<PageResult<SystemSocialUserApi.SystemSocialUser>>(
|
||||||
{ params }
|
'/system/social-user/page',
|
||||||
|
{ params },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询社交用户详情 */
|
/** 查询社交用户详情 */
|
||||||
export function getSocialUser(id: number) {
|
export function getSocialUser(id: number) {
|
||||||
return requestClient.get<SystemSocialUserApi.SystemSocialUser>(`/system/social-user/get?id=${id}`);
|
return requestClient.get<SystemSocialUserApi.SystemSocialUser>(
|
||||||
|
`/system/social-user/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 社交绑定,使用 code 授权码 */
|
/** 社交绑定,使用 code 授权码 */
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,9 @@ export namespace SystemTenantPackageApi {
|
||||||
|
|
||||||
/** 租户套餐列表 */
|
/** 租户套餐列表 */
|
||||||
export function getTenantPackagePage(params: PageParam) {
|
export function getTenantPackagePage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<SystemTenantPackageApi.SystemTenantPackage>>(
|
return requestClient.get<
|
||||||
'/system/tenant-package/page',
|
PageResult<SystemTenantPackageApi.SystemTenantPackage>
|
||||||
{ params }
|
>('/system/tenant-package/page', { params });
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询租户套餐详情 */
|
/** 查询租户套餐详情 */
|
||||||
|
|
@ -31,12 +30,16 @@ export function getTenantPackage(id: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增租户套餐 */
|
/** 新增租户套餐 */
|
||||||
export function createTenantPackage(data: SystemTenantPackageApi.SystemTenantPackage) {
|
export function createTenantPackage(
|
||||||
|
data: SystemTenantPackageApi.SystemTenantPackage,
|
||||||
|
) {
|
||||||
return requestClient.post('/system/tenant-package/create', data);
|
return requestClient.post('/system/tenant-package/create', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 修改租户套餐 */
|
/** 修改租户套餐 */
|
||||||
export function updateTenantPackage(data: SystemTenantPackageApi.SystemTenantPackage) {
|
export function updateTenantPackage(
|
||||||
|
data: SystemTenantPackageApi.SystemTenantPackage,
|
||||||
|
) {
|
||||||
return requestClient.put('/system/tenant-package/update', data);
|
return requestClient.put('/system/tenant-package/update', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,5 +50,7 @@ export function deleteTenantPackage(id: number) {
|
||||||
|
|
||||||
/** 获取租户套餐精简信息列表 */
|
/** 获取租户套餐精简信息列表 */
|
||||||
export function getTenantPackageList() {
|
export function getTenantPackageList() {
|
||||||
return requestClient.get<SystemTenantPackageApi.SystemTenantPackage[]>('/system/tenant-package/get-simple-list');
|
return requestClient.get<SystemTenantPackageApi.SystemTenantPackage[]>(
|
||||||
|
'/system/tenant-package/get-simple-list',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,17 +19,24 @@ export namespace SystemTenantApi {
|
||||||
|
|
||||||
/** 租户列表 */
|
/** 租户列表 */
|
||||||
export function getTenantPage(params: PageParam) {
|
export function getTenantPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<SystemTenantApi.SystemTenant>>('/system/tenant/page', { params });
|
return requestClient.get<PageResult<SystemTenantApi.SystemTenant>>(
|
||||||
|
'/system/tenant/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获取租户精简信息列表 */
|
/** 获取租户精简信息列表 */
|
||||||
export function getSimpleTenantList() {
|
export function getSimpleTenantList() {
|
||||||
return requestClient.get<SystemTenantApi.SystemTenant[]>('/system/tenant/simple-list');
|
return requestClient.get<SystemTenantApi.SystemTenant[]>(
|
||||||
|
'/system/tenant/simple-list',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询租户详情 */
|
/** 查询租户详情 */
|
||||||
export function getTenant(id: number) {
|
export function getTenant(id: number) {
|
||||||
return requestClient.get<SystemTenantApi.SystemTenant>(`/system/tenant/get?id=${id}`,);
|
return requestClient.get<SystemTenantApi.SystemTenant>(
|
||||||
|
`/system/tenant/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增租户 */
|
/** 新增租户 */
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import type {PageParam, PageResult} from '@vben/request';
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
|
@ -23,12 +23,17 @@ export namespace SystemUserApi {
|
||||||
|
|
||||||
/** 查询用户管理列表 */
|
/** 查询用户管理列表 */
|
||||||
export function getUserPage(params: PageParam) {
|
export function getUserPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<SystemUserApi.SystemUser>>('/system/user/page', { params });
|
return requestClient.get<PageResult<SystemUserApi.SystemUser>>(
|
||||||
|
'/system/user/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询用户详情 */
|
/** 查询用户详情 */
|
||||||
export function getUser(id: number) {
|
export function getUser(id: number) {
|
||||||
return requestClient.get<SystemUserApi.SystemUser>(`/system/user/get?id=${id}`);
|
return requestClient.get<SystemUserApi.SystemUser>(
|
||||||
|
`/system/user/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增用户 */
|
/** 新增用户 */
|
||||||
|
|
@ -60,7 +65,7 @@ export function importUserTemplate() {
|
||||||
export function importUser(file: File, updateSupport: boolean) {
|
export function importUser(file: File, updateSupport: boolean) {
|
||||||
return requestClient.upload('/system/user/import', {
|
return requestClient.upload('/system/user/import', {
|
||||||
file,
|
file,
|
||||||
updateSupport
|
updateSupport,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,5 +81,7 @@ export function updateUserStatus(id: number, status: number) {
|
||||||
|
|
||||||
/** 获取用户精简信息列表 */
|
/** 获取用户精简信息列表 */
|
||||||
export function getSimpleUserList() {
|
export function getSimpleUserList() {
|
||||||
return requestClient.get<SystemUserApi.SystemUser[]>('/system/user/simple-list');
|
return requestClient.get<SystemUserApi.SystemUser[]>(
|
||||||
|
'/system/user/simple-list',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { createApp, watchEffect } from 'vue';
|
import { createApp, watchEffect } from 'vue';
|
||||||
|
import VueDOMPurifyHTML from 'vue-dompurify-html';
|
||||||
|
|
||||||
import { registerAccessDirective } from '@vben/access';
|
import { registerAccessDirective } from '@vben/access';
|
||||||
import { registerLoadingDirective } from '@vben/common-ui/es/loading';
|
import { registerLoadingDirective } from '@vben/common-ui/es/loading';
|
||||||
|
|
@ -10,6 +11,7 @@ import '@vben/styles/antd';
|
||||||
import { useTitle } from '@vueuse/core';
|
import { useTitle } from '@vueuse/core';
|
||||||
|
|
||||||
import { $t, setupI18n } from '#/locales';
|
import { $t, setupI18n } from '#/locales';
|
||||||
|
import { setupFormCreate } from '#/plugins/formCreate';
|
||||||
|
|
||||||
import { initComponentAdapter } from './adapter/component';
|
import { initComponentAdapter } from './adapter/component';
|
||||||
import App from './app.vue';
|
import App from './app.vue';
|
||||||
|
|
@ -39,7 +41,7 @@ async function bootstrap(namespace: string) {
|
||||||
// 国际化 i18n 配置
|
// 国际化 i18n 配置
|
||||||
await setupI18n(app);
|
await setupI18n(app);
|
||||||
|
|
||||||
// 配置 pinia-tore
|
// 配置 pinia-store
|
||||||
await initStores(app, { namespace });
|
await initStores(app, { namespace });
|
||||||
|
|
||||||
// 安装权限指令
|
// 安装权限指令
|
||||||
|
|
@ -52,6 +54,12 @@ async function bootstrap(namespace: string) {
|
||||||
// 配置路由及路由守卫
|
// 配置路由及路由守卫
|
||||||
app.use(router);
|
app.use(router);
|
||||||
|
|
||||||
|
// formCreate
|
||||||
|
setupFormCreate(app);
|
||||||
|
|
||||||
|
// vue-dompurify-html
|
||||||
|
app.use(VueDOMPurifyHTML);
|
||||||
|
|
||||||
// 配置Motion插件
|
// 配置Motion插件
|
||||||
const { MotionPlugin } = await import('@vben/plugins/motion');
|
const { MotionPlugin } = await import('@vben/plugins/motion');
|
||||||
app.use(MotionPlugin);
|
app.use(MotionPlugin);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
export { useApiSelect } from './src/components/useApiSelect';
|
||||||
|
|
||||||
|
export { useFormCreateDesigner } from './src/useFormCreateDesigner';
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
<!-- 数据字典 Select 选择器 -->
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, useAttrs } from 'vue';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Checkbox,
|
||||||
|
CheckboxGroup,
|
||||||
|
Radio,
|
||||||
|
RadioGroup,
|
||||||
|
Select,
|
||||||
|
SelectOption,
|
||||||
|
} from 'ant-design-vue';
|
||||||
|
|
||||||
|
import {
|
||||||
|
getBoolDictOptions,
|
||||||
|
getIntDictOptions,
|
||||||
|
getStrDictOptions,
|
||||||
|
} from '#/utils/dict';
|
||||||
|
|
||||||
|
// 接受父组件参数
|
||||||
|
interface Props {
|
||||||
|
dictType: string; // 字典类型
|
||||||
|
valueType?: 'bool' | 'int' | 'str'; // 字典值类型
|
||||||
|
selectType?: 'checkbox' | 'radio' | 'select'; // 选择器类型,下拉框 select、多选框 checkbox、单选框 radio
|
||||||
|
// eslint-disable-next-line vue/require-default-prop
|
||||||
|
formCreateInject?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineOptions({ name: 'DictSelect' });
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
valueType: 'str',
|
||||||
|
selectType: 'select',
|
||||||
|
});
|
||||||
|
|
||||||
|
const attrs = useAttrs();
|
||||||
|
|
||||||
|
// 获得字典配置
|
||||||
|
const getDictOptions = computed(() => {
|
||||||
|
switch (props.valueType) {
|
||||||
|
case 'bool': {
|
||||||
|
return getBoolDictOptions(props.dictType);
|
||||||
|
}
|
||||||
|
case 'int': {
|
||||||
|
return getIntDictOptions(props.dictType);
|
||||||
|
}
|
||||||
|
case 'str': {
|
||||||
|
return getStrDictOptions(props.dictType);
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Select v-if="selectType === 'select'" class="w-1/1" v-bind="attrs">
|
||||||
|
<SelectOption
|
||||||
|
v-for="(dict, index) in getDictOptions"
|
||||||
|
:key="index"
|
||||||
|
:value="dict.value"
|
||||||
|
>
|
||||||
|
{{ dict.label }}
|
||||||
|
</SelectOption>
|
||||||
|
</Select>
|
||||||
|
<RadioGroup v-if="selectType === 'radio'" class="w-1/1" v-bind="attrs">
|
||||||
|
<Radio
|
||||||
|
v-for="(dict, index) in getDictOptions"
|
||||||
|
:key="index"
|
||||||
|
:value="dict.value"
|
||||||
|
>
|
||||||
|
{{ dict.label }}
|
||||||
|
</Radio>
|
||||||
|
</RadioGroup>
|
||||||
|
<CheckboxGroup v-if="selectType === 'checkbox'" class="w-1/1" v-bind="attrs">
|
||||||
|
<Checkbox
|
||||||
|
v-for="(dict, index) in getDictOptions"
|
||||||
|
:key="index"
|
||||||
|
:value="dict.value"
|
||||||
|
>
|
||||||
|
{{ dict.label }}
|
||||||
|
</Checkbox>
|
||||||
|
</CheckboxGroup>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,280 @@
|
||||||
|
import type { ApiSelectProps } from '#/components/FormCreate/src/type';
|
||||||
|
|
||||||
|
import { defineComponent, onMounted, ref, useAttrs } from 'vue';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Checkbox,
|
||||||
|
CheckboxGroup,
|
||||||
|
Radio,
|
||||||
|
RadioGroup,
|
||||||
|
Select,
|
||||||
|
SelectOption,
|
||||||
|
} from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
import { isEmpty } from '#/utils/is';
|
||||||
|
|
||||||
|
export const useApiSelect = (option: ApiSelectProps) => {
|
||||||
|
return defineComponent({
|
||||||
|
name: option.name,
|
||||||
|
props: {
|
||||||
|
// 选项标签
|
||||||
|
labelField: {
|
||||||
|
type: String,
|
||||||
|
default: () => option.labelField ?? 'label',
|
||||||
|
},
|
||||||
|
// 选项的值
|
||||||
|
valueField: {
|
||||||
|
type: String,
|
||||||
|
default: () => option.valueField ?? 'value',
|
||||||
|
},
|
||||||
|
// api 接口
|
||||||
|
url: {
|
||||||
|
type: String,
|
||||||
|
default: () => option.url ?? '',
|
||||||
|
},
|
||||||
|
// 请求类型
|
||||||
|
method: {
|
||||||
|
type: String,
|
||||||
|
default: 'GET',
|
||||||
|
},
|
||||||
|
// 选项解析函数
|
||||||
|
parseFunc: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
// 请求参数
|
||||||
|
data: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
// 选择器类型,下拉框 select、多选框 checkbox、单选框 radio
|
||||||
|
selectType: {
|
||||||
|
type: String,
|
||||||
|
default: 'select',
|
||||||
|
},
|
||||||
|
// 是否多选
|
||||||
|
multiple: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
// 是否远程搜索
|
||||||
|
remote: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
// 远程搜索时携带的参数
|
||||||
|
remoteField: {
|
||||||
|
type: String,
|
||||||
|
default: 'label',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setup(props) {
|
||||||
|
const attrs = useAttrs();
|
||||||
|
const options = ref<any[]>([]); // 下拉数据
|
||||||
|
const loading = ref(false); // 是否正在从远程获取数据
|
||||||
|
const queryParam = ref<any>(); // 当前输入的值
|
||||||
|
const getOptions = async () => {
|
||||||
|
options.value = [];
|
||||||
|
// 接口选择器
|
||||||
|
if (isEmpty(props.url)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (props.method) {
|
||||||
|
case 'GET': {
|
||||||
|
let url: string = props.url;
|
||||||
|
if (props.remote && queryParam.value !== undefined) {
|
||||||
|
url = url.includes('?')
|
||||||
|
? `${url}&${props.remoteField}=${queryParam.value}`
|
||||||
|
: `${url}?${props.remoteField}=${queryParam.value}`;
|
||||||
|
}
|
||||||
|
parseOptions(await requestClient.get(url));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'POST': {
|
||||||
|
const data: any = JSON.parse(props.data);
|
||||||
|
if (props.remote) {
|
||||||
|
data[props.remoteField] = queryParam.value;
|
||||||
|
}
|
||||||
|
parseOptions(await requestClient.post(props.url, data));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function parseOptions(data: any) {
|
||||||
|
// 情况一:如果有自定义解析函数优先使用自定义解析
|
||||||
|
if (!isEmpty(props.parseFunc)) {
|
||||||
|
options.value = parseFunc()?.(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 情况二:返回的直接是一个列表
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
parseOptions0(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 情况二:返回的是分页数据,尝试读取 list
|
||||||
|
data = data.list;
|
||||||
|
if (!!data && Array.isArray(data)) {
|
||||||
|
parseOptions0(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 情况三:不是 yudao-vue-pro 标准返回
|
||||||
|
console.warn(
|
||||||
|
`接口[${props.url}] 返回结果不是 yudao-vue-pro 标准返回建议采用自定义解析函数处理`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseOptions0(data: any[]) {
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
options.value = data.map((item: any) => ({
|
||||||
|
label: parseExpression(item, props.labelField),
|
||||||
|
value: parseExpression(item, props.valueField),
|
||||||
|
}));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.warn(`接口[${props.url}] 返回结果不是一个数组`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseFunc() {
|
||||||
|
let parse: any = null;
|
||||||
|
if (props.parseFunc) {
|
||||||
|
// 解析字符串函数
|
||||||
|
// eslint-disable-next-line no-new-func
|
||||||
|
parse = new Function(`return ${props.parseFunc}`)();
|
||||||
|
}
|
||||||
|
return parse;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseExpression(data: any, template: string) {
|
||||||
|
// 检测是否使用了表达式
|
||||||
|
if (!template.includes('${')) {
|
||||||
|
return data[template];
|
||||||
|
}
|
||||||
|
// 正则表达式匹配模板字符串中的 ${...}
|
||||||
|
const pattern = /\$\{([^}]*)\}/g;
|
||||||
|
// 使用replace函数配合正则表达式和回调函数来进行替换
|
||||||
|
return template.replaceAll(pattern, (_, expr) => {
|
||||||
|
// expr 是匹配到的 ${} 内的表达式(这里是属性名),从 data 中获取对应的值
|
||||||
|
const result = data[expr.trim()]; // 去除前后空白,以防用户输入带空格的属性名
|
||||||
|
if (!result) {
|
||||||
|
console.warn(
|
||||||
|
`接口选择器选项模版[${template}][${expr.trim()}] 解析值失败结果为[${result}], 请检查属性名称是否存在于接口返回值中,存在则忽略此条!!!`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const remoteMethod = async (query: any) => {
|
||||||
|
if (!query) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
queryParam.value = query;
|
||||||
|
await getOptions();
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await getOptions();
|
||||||
|
});
|
||||||
|
|
||||||
|
const buildSelect = () => {
|
||||||
|
if (props.multiple) {
|
||||||
|
// fix:多写此步是为了解决 multiple 属性问题
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
class="w-1/1"
|
||||||
|
loading={loading.value}
|
||||||
|
mode="multiple"
|
||||||
|
{...attrs}
|
||||||
|
// TODO: remote 对等实现
|
||||||
|
// remote={props.remote}
|
||||||
|
{...(props.remote && { remoteMethod })}
|
||||||
|
>
|
||||||
|
{options.value.map(
|
||||||
|
(item: { label: any; value: any }, index: any) => (
|
||||||
|
<SelectOption key={index} value={item.value}>
|
||||||
|
{item.label}
|
||||||
|
</SelectOption>
|
||||||
|
),
|
||||||
|
)}
|
||||||
|
</Select>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
class="w-1/1"
|
||||||
|
loading={loading.value}
|
||||||
|
{...attrs}
|
||||||
|
// remote={props.remote}
|
||||||
|
{...(props.remote && { remoteMethod })}
|
||||||
|
>
|
||||||
|
{options.value.map(
|
||||||
|
(item: { label: any; value: any }, index: any) => (
|
||||||
|
<SelectOption key={index} value={item.value}>
|
||||||
|
{item.label}
|
||||||
|
</SelectOption>
|
||||||
|
),
|
||||||
|
)}
|
||||||
|
</Select>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const buildCheckbox = () => {
|
||||||
|
if (isEmpty(options.value)) {
|
||||||
|
options.value = [
|
||||||
|
{ label: '选项1', value: '选项1' },
|
||||||
|
{ label: '选项2', value: '选项2' },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<CheckboxGroup class="w-1/1" {...attrs}>
|
||||||
|
{options.value.map(
|
||||||
|
(item: { label: any; value: any }, index: any) => (
|
||||||
|
<Checkbox key={index} value={item.value}>
|
||||||
|
{item.label}
|
||||||
|
</Checkbox>
|
||||||
|
),
|
||||||
|
)}
|
||||||
|
</CheckboxGroup>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const buildRadio = () => {
|
||||||
|
if (isEmpty(options.value)) {
|
||||||
|
options.value = [
|
||||||
|
{ label: '选项1', value: '选项1' },
|
||||||
|
{ label: '选项2', value: '选项2' },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<RadioGroup class="w-1/1" {...attrs}>
|
||||||
|
{options.value.map(
|
||||||
|
(item: { label: any; value: any }, index: any) => (
|
||||||
|
<Radio key={index} value={item.value}>
|
||||||
|
{item.label}
|
||||||
|
</Radio>
|
||||||
|
),
|
||||||
|
)}
|
||||||
|
</RadioGroup>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
return () => (
|
||||||
|
<>
|
||||||
|
{props.selectType === 'select'
|
||||||
|
? buildSelect()
|
||||||
|
: props.selectType === 'radio'
|
||||||
|
? buildRadio()
|
||||||
|
: // eslint-disable-next-line unicorn/no-nested-ternary
|
||||||
|
props.selectType === 'checkbox'
|
||||||
|
? buildCheckbox()
|
||||||
|
: buildSelect()}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
export { useDictSelectRule } from './useDictSelectRule';
|
||||||
|
export { useEditorRule } from './useEditorRule';
|
||||||
|
export { useSelectRule } from './useSelectRule';
|
||||||
|
export { useUploadFileRule } from './useUploadFileRule';
|
||||||
|
export { useUploadImgRule } from './useUploadImgRule';
|
||||||
|
export { useUploadImgsRule } from './useUploadImgsRule';
|
||||||
|
|
@ -0,0 +1,182 @@
|
||||||
|
/* eslint-disable no-template-curly-in-string */
|
||||||
|
const selectRule = [
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
field: 'selectType',
|
||||||
|
title: '选择器类型',
|
||||||
|
value: 'select',
|
||||||
|
options: [
|
||||||
|
{ label: '下拉框', value: 'select' },
|
||||||
|
{ label: '单选框', value: 'radio' },
|
||||||
|
{ label: '多选框', value: 'checkbox' },
|
||||||
|
],
|
||||||
|
// 参考 https://www.form-create.com/v3/guide/control 组件联动,单选框和多选框不需要多选属性
|
||||||
|
control: [
|
||||||
|
{
|
||||||
|
value: 'select',
|
||||||
|
condition: '==',
|
||||||
|
method: 'hidden',
|
||||||
|
rule: [
|
||||||
|
'multiple',
|
||||||
|
'clearable',
|
||||||
|
'collapseTags',
|
||||||
|
'multipleLimit',
|
||||||
|
'allowCreate',
|
||||||
|
'filterable',
|
||||||
|
'noMatchText',
|
||||||
|
'remote',
|
||||||
|
'remoteMethod',
|
||||||
|
'reserveKeyword',
|
||||||
|
'defaultFirstOption',
|
||||||
|
'automaticDropdown',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'switch',
|
||||||
|
field: 'filterable',
|
||||||
|
title: '是否可搜索',
|
||||||
|
},
|
||||||
|
{ type: 'switch', field: 'multiple', title: '是否多选' },
|
||||||
|
{
|
||||||
|
type: 'switch',
|
||||||
|
field: 'disabled',
|
||||||
|
title: '是否禁用',
|
||||||
|
},
|
||||||
|
{ type: 'switch', field: 'clearable', title: '是否可以清空选项' },
|
||||||
|
{
|
||||||
|
type: 'switch',
|
||||||
|
field: 'collapseTags',
|
||||||
|
title: '多选时是否将选中值按文字的形式展示',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'inputNumber',
|
||||||
|
field: 'multipleLimit',
|
||||||
|
title: '多选时用户最多可以选择的项目数,为 0 则不限制',
|
||||||
|
props: { min: 0 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'autocomplete',
|
||||||
|
title: 'autocomplete 属性',
|
||||||
|
},
|
||||||
|
{ type: 'input', field: 'placeholder', title: '占位符' },
|
||||||
|
{ type: 'switch', field: 'allowCreate', title: '是否允许用户创建新条目' },
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'noMatchText',
|
||||||
|
title: '搜索条件无匹配时显示的文字',
|
||||||
|
},
|
||||||
|
{ type: 'input', field: 'noDataText', title: '选项为空时显示的文字' },
|
||||||
|
{
|
||||||
|
type: 'switch',
|
||||||
|
field: 'reserveKeyword',
|
||||||
|
title: '多选且可搜索时,是否在选中一个选项后保留当前的搜索关键词',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'switch',
|
||||||
|
field: 'defaultFirstOption',
|
||||||
|
title: '在输入框按下回车,选择第一个匹配项',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'switch',
|
||||||
|
field: 'popperAppendToBody',
|
||||||
|
title: '是否将弹出框插入至 body 元素',
|
||||||
|
value: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'switch',
|
||||||
|
field: 'automaticDropdown',
|
||||||
|
title: '对于不可搜索的 Select,是否在输入框获得焦点后自动弹出选项菜单',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const apiSelectRule = [
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'url',
|
||||||
|
title: 'url 地址',
|
||||||
|
props: {
|
||||||
|
placeholder: '/system/user/simple-list',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
field: 'method',
|
||||||
|
title: '请求类型',
|
||||||
|
value: 'GET',
|
||||||
|
options: [
|
||||||
|
{ label: 'GET', value: 'GET' },
|
||||||
|
{ label: 'POST', value: 'POST' },
|
||||||
|
],
|
||||||
|
control: [
|
||||||
|
{
|
||||||
|
value: 'GET',
|
||||||
|
condition: '!=',
|
||||||
|
method: 'hidden',
|
||||||
|
rule: [
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'data',
|
||||||
|
title: '请求参数 JSON 格式',
|
||||||
|
props: {
|
||||||
|
autosize: true,
|
||||||
|
type: 'textarea',
|
||||||
|
placeholder: '{"type": 1}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'labelField',
|
||||||
|
title: 'label 属性',
|
||||||
|
info: '可以使用 el 表达式:${属性},来实现复杂数据组合。如:${nickname}-${id}',
|
||||||
|
props: {
|
||||||
|
placeholder: 'nickname',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'valueField',
|
||||||
|
title: 'value 属性',
|
||||||
|
info: '可以使用 el 表达式:${属性},来实现复杂数据组合。如:${nickname}-${id}',
|
||||||
|
props: {
|
||||||
|
placeholder: 'id',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'parseFunc',
|
||||||
|
title: '选项解析函数',
|
||||||
|
info: `data 为接口返回值,需要写一个匿名函数解析返回值为选择器 options 列表
|
||||||
|
(data: any)=>{ label: string; value: any }[]`,
|
||||||
|
props: {
|
||||||
|
autosize: true,
|
||||||
|
rows: { minRows: 2, maxRows: 6 },
|
||||||
|
type: 'textarea',
|
||||||
|
placeholder: `
|
||||||
|
function (data) {
|
||||||
|
console.log(data)
|
||||||
|
return data.list.map(item=> ({label: item.nickname,value: item.id}))
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'switch',
|
||||||
|
field: 'remote',
|
||||||
|
info: '是否可搜索',
|
||||||
|
title: '其中的选项是否从服务器远程加载',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'remoteField',
|
||||||
|
title: '请求参数',
|
||||||
|
info: '远程请求时请求携带的参数名称,如:name',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export { apiSelectRule, selectRule };
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
|
||||||
|
import cloneDeep from 'lodash.clonedeep';
|
||||||
|
|
||||||
|
import * as DictDataApi from '#/api/system/dict/type';
|
||||||
|
import { selectRule } from '#/components/FormCreate/src/config/selectRule';
|
||||||
|
import {
|
||||||
|
localeProps,
|
||||||
|
makeRequiredRule,
|
||||||
|
} from '#/components/FormCreate/src/utils';
|
||||||
|
import { generateUUID } from '#/utils';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典选择器规则,如果规则使用到动态数据则需要单独配置不能使用 useSelectRule
|
||||||
|
*/
|
||||||
|
export const useDictSelectRule = () => {
|
||||||
|
const label = '字典选择器';
|
||||||
|
const name = 'DictSelect';
|
||||||
|
const rules = cloneDeep(selectRule);
|
||||||
|
const dictOptions = ref<{ label: string; value: string }[]>([]); // 字典类型下拉数据
|
||||||
|
onMounted(async () => {
|
||||||
|
const data = await DictDataApi.getSimpleDictTypeList();
|
||||||
|
if (!data || data.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dictOptions.value =
|
||||||
|
data?.map((item: DictDataApi.DictTypeVO) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.type,
|
||||||
|
})) ?? [];
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
icon: 'icon-descriptions',
|
||||||
|
label,
|
||||||
|
name,
|
||||||
|
rule() {
|
||||||
|
return {
|
||||||
|
type: name,
|
||||||
|
field: generateUUID(),
|
||||||
|
title: label,
|
||||||
|
info: '',
|
||||||
|
$required: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
props(_: any, { t }: any) {
|
||||||
|
return localeProps(t, `${name}.props`, [
|
||||||
|
makeRequiredRule(),
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
field: 'dictType',
|
||||||
|
title: '字典类型',
|
||||||
|
value: '',
|
||||||
|
options: dictOptions.value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
field: 'valueType',
|
||||||
|
title: '字典值类型',
|
||||||
|
value: 'str',
|
||||||
|
options: [
|
||||||
|
{ label: '数字', value: 'int' },
|
||||||
|
{ label: '字符串', value: 'str' },
|
||||||
|
{ label: '布尔值', value: 'bool' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
...rules,
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
import {
|
||||||
|
localeProps,
|
||||||
|
makeRequiredRule,
|
||||||
|
} from '#/components/FormCreate/src/utils';
|
||||||
|
import { generateUUID } from '#/utils';
|
||||||
|
|
||||||
|
export const useEditorRule = () => {
|
||||||
|
const label = '富文本';
|
||||||
|
const name = 'Editor';
|
||||||
|
return {
|
||||||
|
icon: 'icon-editor',
|
||||||
|
label,
|
||||||
|
name,
|
||||||
|
rule() {
|
||||||
|
return {
|
||||||
|
type: name,
|
||||||
|
field: generateUUID(),
|
||||||
|
title: label,
|
||||||
|
info: '',
|
||||||
|
$required: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
props(_: any, { t }: any) {
|
||||||
|
return localeProps(t, `${name}.props`, [
|
||||||
|
makeRequiredRule(),
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'height',
|
||||||
|
title: '高度',
|
||||||
|
},
|
||||||
|
{ type: 'switch', field: 'readonly', title: '是否只读' },
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
import type { SelectRuleOption } from '#/components/FormCreate/src/type';
|
||||||
|
|
||||||
|
import cloneDeep from 'lodash.clonedeep';
|
||||||
|
|
||||||
|
import { selectRule } from '#/components/FormCreate/src/config/selectRule';
|
||||||
|
import {
|
||||||
|
localeProps,
|
||||||
|
makeRequiredRule,
|
||||||
|
} from '#/components/FormCreate/src/utils';
|
||||||
|
import { generateUUID } from '#/utils';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用选择器规则 hook
|
||||||
|
*
|
||||||
|
* @param option 规则配置
|
||||||
|
*/
|
||||||
|
export const useSelectRule = (option: SelectRuleOption) => {
|
||||||
|
const label = option.label;
|
||||||
|
const name = option.name;
|
||||||
|
const rules = cloneDeep(selectRule);
|
||||||
|
return {
|
||||||
|
icon: option.icon,
|
||||||
|
label,
|
||||||
|
name,
|
||||||
|
event: option.event,
|
||||||
|
rule() {
|
||||||
|
return {
|
||||||
|
type: name,
|
||||||
|
field: generateUUID(),
|
||||||
|
title: label,
|
||||||
|
info: '',
|
||||||
|
$required: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
props(_: any, { t }: any) {
|
||||||
|
if (!option.props) {
|
||||||
|
option.props = [];
|
||||||
|
}
|
||||||
|
return localeProps(t, `${name}.props`, [
|
||||||
|
makeRequiredRule(),
|
||||||
|
...option.props,
|
||||||
|
...rules,
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
import {
|
||||||
|
localeProps,
|
||||||
|
makeRequiredRule,
|
||||||
|
} from '#/components/FormCreate/src/utils';
|
||||||
|
import { generateUUID } from '#/utils';
|
||||||
|
|
||||||
|
export const useUploadFileRule = () => {
|
||||||
|
const label = '文件上传';
|
||||||
|
const name = 'UploadFile';
|
||||||
|
return {
|
||||||
|
icon: 'icon-upload',
|
||||||
|
label,
|
||||||
|
name,
|
||||||
|
rule() {
|
||||||
|
return {
|
||||||
|
type: name,
|
||||||
|
field: generateUUID(),
|
||||||
|
title: label,
|
||||||
|
info: '',
|
||||||
|
$required: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
props(_: any, { t }: any) {
|
||||||
|
return localeProps(t, `${name}.props`, [
|
||||||
|
makeRequiredRule(),
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
field: 'fileType',
|
||||||
|
title: '文件类型',
|
||||||
|
value: ['doc', 'xls', 'ppt', 'txt', 'pdf'],
|
||||||
|
options: [
|
||||||
|
{ label: 'doc', value: 'doc' },
|
||||||
|
{ label: 'xls', value: 'xls' },
|
||||||
|
{ label: 'ppt', value: 'ppt' },
|
||||||
|
{ label: 'txt', value: 'txt' },
|
||||||
|
{ label: 'pdf', value: 'pdf' },
|
||||||
|
],
|
||||||
|
props: {
|
||||||
|
multiple: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'switch',
|
||||||
|
field: 'autoUpload',
|
||||||
|
title: '是否在选取文件后立即进行上传',
|
||||||
|
value: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'switch',
|
||||||
|
field: 'drag',
|
||||||
|
title: '拖拽上传',
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'switch',
|
||||||
|
field: 'isShowTip',
|
||||||
|
title: '是否显示提示',
|
||||||
|
value: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'inputNumber',
|
||||||
|
field: 'fileSize',
|
||||||
|
title: '大小限制(MB)',
|
||||||
|
value: 5,
|
||||||
|
props: { min: 0 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'inputNumber',
|
||||||
|
field: 'limit',
|
||||||
|
title: '数量限制',
|
||||||
|
value: 5,
|
||||||
|
props: { min: 0 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'switch',
|
||||||
|
field: 'disabled',
|
||||||
|
title: '是否禁用',
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
import {
|
||||||
|
localeProps,
|
||||||
|
makeRequiredRule,
|
||||||
|
} from '#/components/FormCreate/src/utils';
|
||||||
|
import { generateUUID } from '#/utils';
|
||||||
|
|
||||||
|
export const useUploadImgRule = () => {
|
||||||
|
const label = '单图上传';
|
||||||
|
const name = 'UploadImg';
|
||||||
|
return {
|
||||||
|
icon: 'icon-image',
|
||||||
|
label,
|
||||||
|
name,
|
||||||
|
rule() {
|
||||||
|
return {
|
||||||
|
type: name,
|
||||||
|
field: generateUUID(),
|
||||||
|
title: label,
|
||||||
|
info: '',
|
||||||
|
$required: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
props(_: any, { t }: any) {
|
||||||
|
return localeProps(t, `${name}.props`, [
|
||||||
|
makeRequiredRule(),
|
||||||
|
{
|
||||||
|
type: 'switch',
|
||||||
|
field: 'drag',
|
||||||
|
title: '拖拽上传',
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
field: 'fileType',
|
||||||
|
title: '图片类型限制',
|
||||||
|
value: ['image/jpeg', 'image/png', 'image/gif'],
|
||||||
|
options: [
|
||||||
|
{ label: 'image/apng', value: 'image/apng' },
|
||||||
|
{ label: 'image/bmp', value: 'image/bmp' },
|
||||||
|
{ label: 'image/gif', value: 'image/gif' },
|
||||||
|
{ label: 'image/jpeg', value: 'image/jpeg' },
|
||||||
|
{ label: 'image/pjpeg', value: 'image/pjpeg' },
|
||||||
|
{ label: 'image/svg+xml', value: 'image/svg+xml' },
|
||||||
|
{ label: 'image/tiff', value: 'image/tiff' },
|
||||||
|
{ label: 'image/webp', value: 'image/webp' },
|
||||||
|
{ label: 'image/x-icon', value: 'image/x-icon' },
|
||||||
|
],
|
||||||
|
props: {
|
||||||
|
multiple: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'inputNumber',
|
||||||
|
field: 'fileSize',
|
||||||
|
title: '大小限制(MB)',
|
||||||
|
value: 5,
|
||||||
|
props: { min: 0 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'height',
|
||||||
|
title: '组件高度',
|
||||||
|
value: '150px',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'width',
|
||||||
|
title: '组件宽度',
|
||||||
|
value: '150px',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'borderradius',
|
||||||
|
title: '组件边框圆角',
|
||||||
|
value: '8px',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'switch',
|
||||||
|
field: 'disabled',
|
||||||
|
title: '是否显示删除按钮',
|
||||||
|
value: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'switch',
|
||||||
|
field: 'showBtnText',
|
||||||
|
title: '是否显示按钮文字',
|
||||||
|
value: true,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
import {
|
||||||
|
localeProps,
|
||||||
|
makeRequiredRule,
|
||||||
|
} from '#/components/FormCreate/src/utils';
|
||||||
|
import { generateUUID } from '#/utils';
|
||||||
|
|
||||||
|
export const useUploadImgsRule = () => {
|
||||||
|
const label = '多图上传';
|
||||||
|
const name = 'UploadImgs';
|
||||||
|
return {
|
||||||
|
icon: 'icon-image',
|
||||||
|
label,
|
||||||
|
name,
|
||||||
|
rule() {
|
||||||
|
return {
|
||||||
|
type: name,
|
||||||
|
field: generateUUID(),
|
||||||
|
title: label,
|
||||||
|
info: '',
|
||||||
|
$required: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
props(_: any, { t }: any) {
|
||||||
|
return localeProps(t, `${name}.props`, [
|
||||||
|
makeRequiredRule(),
|
||||||
|
{
|
||||||
|
type: 'switch',
|
||||||
|
field: 'drag',
|
||||||
|
title: '拖拽上传',
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
field: 'fileType',
|
||||||
|
title: '图片类型限制',
|
||||||
|
value: ['image/jpeg', 'image/png', 'image/gif'],
|
||||||
|
options: [
|
||||||
|
{ label: 'image/apng', value: 'image/apng' },
|
||||||
|
{ label: 'image/bmp', value: 'image/bmp' },
|
||||||
|
{ label: 'image/gif', value: 'image/gif' },
|
||||||
|
{ label: 'image/jpeg', value: 'image/jpeg' },
|
||||||
|
{ label: 'image/pjpeg', value: 'image/pjpeg' },
|
||||||
|
{ label: 'image/svg+xml', value: 'image/svg+xml' },
|
||||||
|
{ label: 'image/tiff', value: 'image/tiff' },
|
||||||
|
{ label: 'image/webp', value: 'image/webp' },
|
||||||
|
{ label: 'image/x-icon', value: 'image/x-icon' },
|
||||||
|
],
|
||||||
|
props: {
|
||||||
|
multiple: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'inputNumber',
|
||||||
|
field: 'fileSize',
|
||||||
|
title: '大小限制(MB)',
|
||||||
|
value: 5,
|
||||||
|
props: { min: 0 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'inputNumber',
|
||||||
|
field: 'limit',
|
||||||
|
title: '数量限制',
|
||||||
|
value: 5,
|
||||||
|
props: { min: 0 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'height',
|
||||||
|
title: '组件高度',
|
||||||
|
value: '150px',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'width',
|
||||||
|
title: '组件宽度',
|
||||||
|
value: '150px',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'borderradius',
|
||||||
|
title: '组件边框圆角',
|
||||||
|
value: '8px',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
import type { Rule } from '@form-create/ant-design-vue'; // 左侧拖拽按钮
|
||||||
|
// 左侧拖拽按钮
|
||||||
|
|
||||||
|
// 左侧拖拽按钮
|
||||||
|
export interface MenuItem {
|
||||||
|
label: string;
|
||||||
|
name: string;
|
||||||
|
icon: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 左侧拖拽按钮分类
|
||||||
|
export interface Menu {
|
||||||
|
title: string;
|
||||||
|
name: string;
|
||||||
|
list: MenuItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type MenuList = Array<Menu>;
|
||||||
|
|
||||||
|
// 拖拽组件的规则
|
||||||
|
export interface DragRule {
|
||||||
|
icon: string;
|
||||||
|
name: string;
|
||||||
|
label: string;
|
||||||
|
children?: string;
|
||||||
|
inside?: true;
|
||||||
|
drag?: string | true;
|
||||||
|
dragBtn?: false;
|
||||||
|
mask?: false;
|
||||||
|
|
||||||
|
rule(): Rule;
|
||||||
|
|
||||||
|
props(v: any, v1: any): Rule[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 通用下拉组件 Props 类型
|
||||||
|
export interface ApiSelectProps {
|
||||||
|
name: string; // 组件名称
|
||||||
|
labelField?: string; // 选项标签
|
||||||
|
valueField?: string; // 选项的值
|
||||||
|
url?: string; // url 接口
|
||||||
|
isDict?: boolean; // 是否字典选择器
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择组件规则配置类型
|
||||||
|
export interface SelectRuleOption {
|
||||||
|
label: string; // label 名称
|
||||||
|
name: string; // 组件名称
|
||||||
|
icon: string; // 组件图标
|
||||||
|
props?: any[]; // 组件规则
|
||||||
|
event?: any[]; // 事件配置
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
import type { Ref } from 'vue';
|
||||||
|
|
||||||
|
import type { Menu } from '#/components/FormCreate/src/type';
|
||||||
|
|
||||||
|
import { nextTick, onMounted } from 'vue';
|
||||||
|
|
||||||
|
import { apiSelectRule } from '#/components/FormCreate/src/config/selectRule';
|
||||||
|
|
||||||
|
import {
|
||||||
|
useDictSelectRule,
|
||||||
|
useEditorRule,
|
||||||
|
useSelectRule,
|
||||||
|
useUploadFileRule,
|
||||||
|
useUploadImgRule,
|
||||||
|
useUploadImgsRule,
|
||||||
|
} from './config';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单设计器增强 hook
|
||||||
|
* 新增
|
||||||
|
* - 文件上传
|
||||||
|
* - 单图上传
|
||||||
|
* - 多图上传
|
||||||
|
* - 字典选择器
|
||||||
|
* - 用户选择器
|
||||||
|
* - 部门选择器
|
||||||
|
* - 富文本
|
||||||
|
*/
|
||||||
|
export const useFormCreateDesigner = async (designer: Ref) => {
|
||||||
|
const editorRule = useEditorRule();
|
||||||
|
const uploadFileRule = useUploadFileRule();
|
||||||
|
const uploadImgRule = useUploadImgRule();
|
||||||
|
const uploadImgsRule = useUploadImgsRule();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建表单组件
|
||||||
|
*/
|
||||||
|
const buildFormComponents = () => {
|
||||||
|
// 移除自带的上传组件规则,使用 uploadFileRule、uploadImgRule、uploadImgsRule 替代
|
||||||
|
designer.value?.removeMenuItem('upload');
|
||||||
|
// 移除自带的富文本组件规则,使用 editorRule 替代
|
||||||
|
designer.value?.removeMenuItem('fc-editor');
|
||||||
|
const components = [
|
||||||
|
editorRule,
|
||||||
|
uploadFileRule,
|
||||||
|
uploadImgRule,
|
||||||
|
uploadImgsRule,
|
||||||
|
];
|
||||||
|
components.forEach((component) => {
|
||||||
|
// 插入组件规则
|
||||||
|
designer.value?.addComponent(component);
|
||||||
|
// 插入拖拽按钮到 `main` 分类下
|
||||||
|
designer.value?.appendMenuItem('main', {
|
||||||
|
icon: component.icon,
|
||||||
|
name: component.name,
|
||||||
|
label: component.label,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const userSelectRule = useSelectRule({
|
||||||
|
name: 'UserSelect',
|
||||||
|
label: '用户选择器',
|
||||||
|
icon: 'icon-eye',
|
||||||
|
});
|
||||||
|
const deptSelectRule = useSelectRule({
|
||||||
|
name: 'DeptSelect',
|
||||||
|
label: '部门选择器',
|
||||||
|
icon: 'icon-tree',
|
||||||
|
});
|
||||||
|
const dictSelectRule = useDictSelectRule();
|
||||||
|
const apiSelectRule0 = useSelectRule({
|
||||||
|
name: 'ApiSelect',
|
||||||
|
label: '接口选择器',
|
||||||
|
icon: 'icon-json',
|
||||||
|
props: [...apiSelectRule],
|
||||||
|
event: ['click', 'change', 'visibleChange', 'clear', 'blur', 'focus'],
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建系统字段菜单
|
||||||
|
*/
|
||||||
|
const buildSystemMenu = () => {
|
||||||
|
// 移除自带的下拉选择器组件,使用 currencySelectRule 替代
|
||||||
|
// designer.value?.removeMenuItem('select')
|
||||||
|
// designer.value?.removeMenuItem('radio')
|
||||||
|
// designer.value?.removeMenuItem('checkbox')
|
||||||
|
const components = [
|
||||||
|
userSelectRule,
|
||||||
|
deptSelectRule,
|
||||||
|
dictSelectRule,
|
||||||
|
apiSelectRule0,
|
||||||
|
];
|
||||||
|
const menu: Menu = {
|
||||||
|
name: 'system',
|
||||||
|
title: '系统字段',
|
||||||
|
list: components.map((component) => {
|
||||||
|
// 插入组件规则
|
||||||
|
designer.value?.addComponent(component);
|
||||||
|
// 插入拖拽按钮到 `system` 分类下
|
||||||
|
return {
|
||||||
|
icon: component.icon,
|
||||||
|
name: component.name,
|
||||||
|
label: component.label,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
designer.value?.addMenu(menu);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await nextTick();
|
||||||
|
buildFormComponents();
|
||||||
|
buildSystemMenu();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
export function makeRequiredRule() {
|
||||||
|
return {
|
||||||
|
type: 'Required',
|
||||||
|
field: 'formCreate$required',
|
||||||
|
title: '是否必填',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const localeProps = (
|
||||||
|
t: (msg: string) => any,
|
||||||
|
prefix: string,
|
||||||
|
rules: any[],
|
||||||
|
) => {
|
||||||
|
return rules.map((rule: { field: string; title: any }) => {
|
||||||
|
if (rule.field === 'formCreate$required') {
|
||||||
|
rule.title = t('props.required') || rule.title;
|
||||||
|
} else if (rule.field && rule.field !== '_optionType') {
|
||||||
|
rule.title = t(`components.${prefix}.${rule.field}`) || rule.title;
|
||||||
|
}
|
||||||
|
return rule;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析表单组件的 field, title 等字段(递归,如果组件包含子组件)
|
||||||
|
*
|
||||||
|
* @param rule 组件的生成规则 https://www.form-create.com/v3/guide/rule
|
||||||
|
* @param fields 解析后表单组件字段
|
||||||
|
* @param parentTitle 如果是子表单,子表单的标题,默认为空
|
||||||
|
*/
|
||||||
|
export const parseFormFields = (
|
||||||
|
rule: Record<string, any>,
|
||||||
|
fields: Array<Record<string, any>> = [],
|
||||||
|
parentTitle: string = '',
|
||||||
|
) => {
|
||||||
|
const { type, field, $required, title: tempTitle, children } = rule;
|
||||||
|
if (field && tempTitle) {
|
||||||
|
let title = tempTitle;
|
||||||
|
if (parentTitle) {
|
||||||
|
title = `${parentTitle}.${tempTitle}`;
|
||||||
|
}
|
||||||
|
let required = false;
|
||||||
|
if ($required) {
|
||||||
|
required = true;
|
||||||
|
}
|
||||||
|
fields.push({
|
||||||
|
field,
|
||||||
|
title,
|
||||||
|
type,
|
||||||
|
required,
|
||||||
|
});
|
||||||
|
// TODO 子表单 需要处理子表单字段
|
||||||
|
// if (type === 'group' && rule.props?.rule && Array.isArray(rule.props.rule)) {
|
||||||
|
// // 解析子表单的字段
|
||||||
|
// rule.props.rule.forEach((item) => {
|
||||||
|
// parseFields(item, fieldsPermission, title)
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
if (children && Array.isArray(children)) {
|
||||||
|
children.forEach((rule) => {
|
||||||
|
parseFormFields(rule, fields);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -1,57 +1,71 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// TODO @芋艿:貌似不用 src 目录
|
import { computed } from 'vue';
|
||||||
import { computed, defineProps } from 'vue'
|
|
||||||
import { Tag } from 'ant-design-vue'
|
import { Tag } from 'ant-design-vue';
|
||||||
|
|
||||||
// import { isHexColor } from '@/utils/color' // TODO @芋艿:【可优化】增加 cssClass 的处理 https://gitee.com/yudaocode/yudao-ui-admin-vben/blob/v2.4.1/src/components/DictTag/src/DictTag.vue#L60
|
// import { isHexColor } from '@/utils/color' // TODO @芋艿:【可优化】增加 cssClass 的处理 https://gitee.com/yudaocode/yudao-ui-admin-vben/blob/v2.4.1/src/components/DictTag/src/DictTag.vue#L60
|
||||||
import { getDictObj } from '#/utils/dict'
|
import { getDictObj } from '#/utils/dict';
|
||||||
|
|
||||||
interface DictTagProps {
|
interface DictTagProps {
|
||||||
/**
|
/**
|
||||||
* 字典类型
|
* 字典类型
|
||||||
*/
|
*/
|
||||||
type: string
|
type: string;
|
||||||
/**
|
/**
|
||||||
* 字典值
|
* 字典值
|
||||||
*/
|
*/
|
||||||
value: any
|
value: any;
|
||||||
/**
|
/**
|
||||||
* 图标
|
* 图标
|
||||||
*/
|
*/
|
||||||
icon?: string
|
icon?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<DictTagProps>()
|
const props = defineProps<DictTagProps>();
|
||||||
|
|
||||||
/** 获取字典标签 */
|
/** 获取字典标签 */
|
||||||
const dictTag = computed(() => {
|
const dictTag = computed(() => {
|
||||||
// 校验参数有效性
|
// 校验参数有效性
|
||||||
if (!props.type || props.value === undefined || props.value === null) {
|
if (!props.type || props.value === undefined || props.value === null) {
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取字典对象
|
// 获取字典对象
|
||||||
const dict = getDictObj(props.type, String(props.value))
|
const dict = getDictObj(props.type, String(props.value));
|
||||||
if (!dict) {
|
if (!dict) {
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理颜色类型
|
// 处理颜色类型
|
||||||
let colorType = dict.colorType
|
let colorType = dict.colorType;
|
||||||
if (colorType === 'primary') {
|
switch (colorType) {
|
||||||
colorType = 'processing'
|
case 'danger': {
|
||||||
} else if (colorType === 'danger') {
|
colorType = 'error';
|
||||||
colorType = 'error'
|
|
||||||
} else if (colorType === 'info') {
|
break;
|
||||||
colorType = 'default'
|
}
|
||||||
} else if (!colorType) {
|
case 'info': {
|
||||||
colorType = 'default'
|
colorType = 'default';
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'primary': {
|
||||||
|
colorType = 'processing';
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
if (!colorType) {
|
||||||
|
colorType = 'default';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
label: dict.label || '',
|
label: dict.label || '',
|
||||||
colorType
|
colorType,
|
||||||
}
|
};
|
||||||
})
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1 @@
|
||||||
import DictTag from './dict-tag.vue'
|
export { default as DictTag } from './dict-tag.vue';
|
||||||
|
|
||||||
export { DictTag }
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
// TODO @芋艿:貌似不用 src 目录
|
// TODO @芋艿:貌似不用 src 目录
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
|
||||||
import { Alert, Typography } from 'ant-design-vue';
|
import { Alert, Typography } from 'ant-design-vue';
|
||||||
|
|
||||||
export interface DocAlertProps {
|
export interface DocAlertProps {
|
||||||
|
|
@ -28,12 +29,7 @@ const isEnabled = computed(() => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Alert
|
<Alert v-if="isEnabled" type="info" show-icon class="mb-2 rounded">
|
||||||
v-if="isEnabled"
|
|
||||||
type="info"
|
|
||||||
show-icon
|
|
||||||
class="mb-2 rounded"
|
|
||||||
>
|
|
||||||
<template #message>
|
<template #message>
|
||||||
<Typography.Link @click="goToUrl">
|
<Typography.Link @click="goToUrl">
|
||||||
【{{ title }}】文档地址:{{ url }}
|
【{{ title }}】文档地址:{{ url }}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1 @@
|
||||||
import DocAlert from './doc-alert.vue'
|
export { default as DocAlert } from './doc-alert.vue';
|
||||||
|
|
||||||
export { DocAlert }
|
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,41 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// TODO @芋艿:貌似不用 src 目录
|
// TODO @芋艿:貌似不用 src 目录
|
||||||
import { onMounted, ref } from 'vue'
|
import { onMounted, ref } from 'vue';
|
||||||
|
|
||||||
interface IFrameProps {
|
interface IFrameProps {
|
||||||
/**
|
/**
|
||||||
* iframe 的源地址
|
* iframe 的源地址
|
||||||
*/
|
*/
|
||||||
src: string
|
src: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<IFrameProps>()
|
const props = defineProps<IFrameProps>();
|
||||||
|
|
||||||
const loading = ref(true)
|
const loading = ref(true);
|
||||||
const height = ref('')
|
const height = ref('');
|
||||||
const frameRef = ref<HTMLElement | null>(null)
|
const frameRef = ref<HTMLElement | null>(null);
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
height.value = `${document.documentElement.clientHeight - 94.5}px`
|
height.value = `${document.documentElement.clientHeight - 94.5}px`;
|
||||||
loading.value = false
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
init()
|
init();
|
||||||
}, 300)
|
}, 300);
|
||||||
})
|
});
|
||||||
// TODO @芋艿:优化:未来使用 vben 自带的内链实现
|
// TODO @芋艿:优化:未来使用 vben 自带的内链实现
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-loading="loading" :style="`height:${height}`">
|
<div v-loading="loading" :style="`height:${height}`">
|
||||||
<iframe ref="frameRef" :src="props.src" style="width: 100%; height: 100%" frameborder="no" scrolling="auto" />
|
<iframe
|
||||||
|
ref="frameRef"
|
||||||
|
:src="props.src"
|
||||||
|
style="width: 100%; height: 100%"
|
||||||
|
frameborder="no"
|
||||||
|
scrolling="auto"
|
||||||
|
></iframe>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1 @@
|
||||||
import IFrame from './iframe.vue'
|
export { default as IFrame } from './iframe.vue';
|
||||||
|
|
||||||
export { IFrame }
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,8 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { Editor as EditorType } from 'tinymce/tinymce';
|
|
||||||
import type { IPropTypes } from '@tinymce/tinymce-vue/lib/cjs/main/ts/components/EditorPropTypes';
|
import type { IPropTypes } from '@tinymce/tinymce-vue/lib/cjs/main/ts/components/EditorPropTypes';
|
||||||
type InitOptions = IPropTypes['init'];
|
import type { Editor as EditorType } from 'tinymce/tinymce';
|
||||||
import type { PropType } from 'vue';
|
|
||||||
|
|
||||||
import Editor from '@tinymce/tinymce-vue';
|
import type { PropType } from 'vue';
|
||||||
import ImgUpload from './img-upload.vue';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
computed,
|
computed,
|
||||||
|
|
@ -21,12 +18,21 @@ import {
|
||||||
} from 'vue';
|
} from 'vue';
|
||||||
|
|
||||||
import { preferences, usePreferences } from '@vben/preferences';
|
import { preferences, usePreferences } from '@vben/preferences';
|
||||||
|
import { buildShortUUID, isNumber } from '@vben/utils';
|
||||||
|
|
||||||
|
import Editor from '@tinymce/tinymce-vue';
|
||||||
|
|
||||||
import { isNumber, buildShortUUID } from '@vben/utils';
|
|
||||||
import { bindHandlers } from './helper';
|
|
||||||
import { plugins as defaultPlugins, toolbar as defaultToolbar } from './tinymce';
|
|
||||||
import { useUpload } from '#/components/upload/use-upload';
|
import { useUpload } from '#/components/upload/use-upload';
|
||||||
|
|
||||||
|
import { bindHandlers } from './helper';
|
||||||
|
import ImgUpload from './img-upload.vue';
|
||||||
|
import {
|
||||||
|
plugins as defaultPlugins,
|
||||||
|
toolbar as defaultToolbar,
|
||||||
|
} from './tinymce';
|
||||||
|
|
||||||
|
type InitOptions = IPropTypes['init'];
|
||||||
|
|
||||||
defineOptions({ inheritAttrs: false });
|
defineOptions({ inheritAttrs: false });
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
|
@ -151,11 +157,11 @@ const initOptions = computed((): InitOptions => {
|
||||||
const { httpRequest } = useUpload();
|
const { httpRequest } = useUpload();
|
||||||
httpRequest(file)
|
httpRequest(file)
|
||||||
.then((url) => {
|
.then((url) => {
|
||||||
console.log('tinymce 上传图片成功:', url);
|
// console.log('tinymce 上传图片成功:', url);
|
||||||
resolve(url);
|
resolve(url);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error('tinymce 上传图片失败:', error);
|
// console.error('tinymce 上传图片失败:', error);
|
||||||
reject(error.message);
|
reject(error.message);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -300,8 +306,8 @@ function handleError(name: string) {
|
||||||
if (!editor) {
|
if (!editor) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const content = editor?.getContent()?? '';
|
const content = editor?.getContent() ?? '';
|
||||||
const val = content?.replace(getUploadingImgName(name), '')?? '';
|
const val = content?.replace(getUploadingImgName(name), '') ?? '';
|
||||||
setValue(editor, val);
|
setValue(editor, val);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
|
import type { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
|
||||||
|
|
||||||
import { Upload, Button } from 'ant-design-vue';
|
import { computed, ref } from 'vue';
|
||||||
|
|
||||||
import { $t } from '@vben/locales';
|
import { $t } from '@vben/locales';
|
||||||
import { computed, ref } from 'vue';
|
|
||||||
|
import { Button, Upload } from 'ant-design-vue';
|
||||||
|
|
||||||
import { useUpload } from '#/components/upload/use-upload';
|
import { useUpload } from '#/components/upload/use-upload';
|
||||||
|
|
||||||
defineOptions({ name: 'TinymceImageUpload' });
|
defineOptions({ name: 'TinymceImageUpload' });
|
||||||
|
|
@ -14,7 +16,8 @@ const props = defineProps({
|
||||||
default: false,
|
default: false,
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
},
|
},
|
||||||
fullscreen: { // 图片上传,是否放到全屏的位置
|
fullscreen: {
|
||||||
|
// 图片上传,是否放到全屏的位置
|
||||||
default: false,
|
default: false,
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
},
|
},
|
||||||
|
|
@ -45,7 +48,7 @@ async function customRequest(info: UploadRequestOption<any>) {
|
||||||
try {
|
try {
|
||||||
const url = await httpRequest(file);
|
const url = await httpRequest(file);
|
||||||
emit('done', name, url);
|
emit('done', name, url);
|
||||||
} catch (e) {
|
} catch {
|
||||||
emit('error', name);
|
emit('error', name);
|
||||||
} finally {
|
} finally {
|
||||||
uploading.value = false;
|
uploading.value = false;
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,19 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { UploadFile, UploadProps } from 'ant-design-vue';
|
import type { UploadFile, UploadProps } from 'ant-design-vue';
|
||||||
import type { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
|
import type { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
|
||||||
import type { AxiosProgressEvent } from '#/api/infra/file';
|
|
||||||
import type { AxiosResponse } from '@vben/request';
|
import type { AxiosResponse } from '@vben/request';
|
||||||
|
|
||||||
import { CloudUpload } from '@vben/icons';
|
import type { AxiosProgressEvent } from '#/api/infra/file';
|
||||||
import { message, Upload, Button } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { $t } from '@vben/locales';
|
|
||||||
import { ref, toRefs, watch } from 'vue';
|
import { ref, toRefs, watch } from 'vue';
|
||||||
|
|
||||||
|
import { CloudUpload } from '@vben/icons';
|
||||||
|
import { $t } from '@vben/locales';
|
||||||
import { isFunction, isObject, isString } from '@vben/utils';
|
import { isFunction, isObject, isString } from '@vben/utils';
|
||||||
|
|
||||||
|
import { Button, message, Upload } from 'ant-design-vue';
|
||||||
|
|
||||||
import { checkFileType } from './helper';
|
import { checkFileType } from './helper';
|
||||||
import { UploadResultStatus } from './typing';
|
import { UploadResultStatus } from './typing';
|
||||||
import { useUpload, useUploadType } from './use-upload';
|
import { useUpload, useUploadType } from './use-upload';
|
||||||
|
|
@ -36,7 +40,7 @@ const props = withDefaults(
|
||||||
resultField?: string;
|
resultField?: string;
|
||||||
// 是否显示下面的描述
|
// 是否显示下面的描述
|
||||||
showDescription?: boolean;
|
showDescription?: boolean;
|
||||||
value?: string[] | string;
|
value?: string | string[];
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
value: () => [],
|
value: () => [],
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ export function checkFileType(file: File, accepts: string[]) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const newTypes = accepts.join('|');
|
const newTypes = accepts.join('|');
|
||||||
const reg = new RegExp('\\.(' + newTypes + ')$', 'i');
|
const reg = new RegExp(`${String.raw`\.(` + newTypes})$`, 'i');
|
||||||
return reg.test(file.name);
|
return reg.test(file.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -12,6 +12,9 @@ export function checkFileType(file: File, accepts: string[]) {
|
||||||
*/
|
*/
|
||||||
export const defaultImageAccepts = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
|
export const defaultImageAccepts = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
|
||||||
|
|
||||||
export function checkImgType(file: File, accepts: string[] = defaultImageAccepts) {
|
export function checkImgType(
|
||||||
|
file: File,
|
||||||
|
accepts: string[] = defaultImageAccepts,
|
||||||
|
) {
|
||||||
return checkFileType(file, accepts);
|
return checkFileType(file, accepts);
|
||||||
}
|
}
|
||||||
|
|
@ -1,19 +1,25 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { UploadFile, UploadProps } from 'ant-design-vue';
|
import type { UploadFile, UploadProps } from 'ant-design-vue';
|
||||||
import type { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
|
import type { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
|
||||||
import type { AxiosProgressEvent } from '#/api/infra/file';
|
|
||||||
import type { AxiosResponse } from '@vben/request';
|
import type { AxiosResponse } from '@vben/request';
|
||||||
|
|
||||||
import { CloudUpload } from '@vben/icons';
|
import type { AxiosProgressEvent } from '#/api/infra/file';
|
||||||
import { message, Upload, Modal } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { $t } from '@vben/locales';
|
|
||||||
import { ref, toRefs, watch } from 'vue';
|
import { ref, toRefs, watch } from 'vue';
|
||||||
|
|
||||||
|
import { CloudUpload } from '@vben/icons';
|
||||||
|
import { $t } from '@vben/locales';
|
||||||
import { isFunction, isObject, isString } from '@vben/utils';
|
import { isFunction, isObject, isString } from '@vben/utils';
|
||||||
|
|
||||||
|
import { message, Modal, Upload } from 'ant-design-vue';
|
||||||
|
|
||||||
import { checkImgType, defaultImageAccepts } from './helper';
|
import { checkImgType, defaultImageAccepts } from './helper';
|
||||||
import { UploadResultStatus } from './typing';
|
import { UploadResultStatus } from './typing';
|
||||||
import { useUpload, useUploadType } from './use-upload';
|
import { useUpload, useUploadType } from './use-upload';
|
||||||
|
|
||||||
|
type ListType = 'picture' | 'picture-card' | 'text';
|
||||||
|
|
||||||
defineOptions({ name: 'ImageUpload', inheritAttrs: false });
|
defineOptions({ name: 'ImageUpload', inheritAttrs: false });
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
|
|
@ -37,7 +43,7 @@ const props = withDefaults(
|
||||||
resultField?: string;
|
resultField?: string;
|
||||||
// 是否显示下面的描述
|
// 是否显示下面的描述
|
||||||
showDescription?: boolean;
|
showDescription?: boolean;
|
||||||
value?: string[] | string;
|
value?: string | string[];
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
value: () => [],
|
value: () => [],
|
||||||
|
|
@ -54,7 +60,6 @@ const props = withDefaults(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
const emit = defineEmits(['change', 'update:value', 'delete']);
|
const emit = defineEmits(['change', 'update:value', 'delete']);
|
||||||
type ListType = 'picture' | 'picture-card' | 'text';
|
|
||||||
const { accept, helpText, maxNumber, maxSize } = toRefs(props);
|
const { accept, helpText, maxNumber, maxSize } = toRefs(props);
|
||||||
const isInnerOperate = ref<boolean>(false);
|
const isInnerOperate = ref<boolean>(false);
|
||||||
const { getStringAccept } = useUploadType({
|
const { getStringAccept } = useUploadType({
|
||||||
|
|
@ -231,7 +236,10 @@ function getValue() {
|
||||||
@preview="handlePreview"
|
@preview="handlePreview"
|
||||||
@remove="handleRemove"
|
@remove="handleRemove"
|
||||||
>
|
>
|
||||||
<div v-if="fileList && fileList.length < maxNumber" class="flex flex-col items-center justify-center">
|
<div
|
||||||
|
v-if="fileList && fileList.length < maxNumber"
|
||||||
|
class="flex flex-col items-center justify-center"
|
||||||
|
>
|
||||||
<CloudUpload />
|
<CloudUpload />
|
||||||
<div class="mt-2">{{ $t('ui.upload.imgUpload') }}</div>
|
<div class="mt-2">{{ $t('ui.upload.imgUpload') }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -241,7 +249,7 @@ function getValue() {
|
||||||
class="mt-2 flex flex-wrap items-center text-[14px]"
|
class="mt-2 flex flex-wrap items-center text-[14px]"
|
||||||
>
|
>
|
||||||
请上传不超过
|
请上传不超过
|
||||||
<div class="mx-1 font-bold text-primary">{{ maxSize }}MB</div>
|
<div class="text-primary mx-1 font-bold">{{ maxSize }}MB</div>
|
||||||
的
|
的
|
||||||
<div class="text-primary mx-1 font-bold">{{ accept.join('/') }}</div>
|
<div class="text-primary mx-1 font-bold">{{ accept.join('/') }}</div>
|
||||||
格式文件
|
格式文件
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,25 @@
|
||||||
import type { Ref } from 'vue';
|
import type { Ref } from 'vue';
|
||||||
|
|
||||||
import type { AxiosProgressEvent, InfraFileApi } from '#/api/infra/file';
|
import type { AxiosProgressEvent, InfraFileApi } from '#/api/infra/file';
|
||||||
|
|
||||||
import { computed, unref } from 'vue';
|
import { computed, unref } from 'vue';
|
||||||
|
|
||||||
import { $t } from '@vben/locales';
|
import { $t } from '@vben/locales';
|
||||||
import CryptoJS from 'crypto-js'
|
|
||||||
import axios from 'axios'
|
import axios from 'axios';
|
||||||
import { uploadFile, getFilePresignedUrl, createFile } from '#/api/infra/file';
|
import CryptoJS from 'crypto-js';
|
||||||
|
|
||||||
|
import { createFile, getFilePresignedUrl, uploadFile } from '#/api/infra/file';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传类型
|
||||||
|
*/
|
||||||
|
enum UPLOAD_TYPE {
|
||||||
|
// 客户端直接上传(只支持S3服务)
|
||||||
|
CLIENT = 'client',
|
||||||
|
// 客户端发送到后端上传
|
||||||
|
SERVER = 'server',
|
||||||
|
}
|
||||||
|
|
||||||
export function useUploadType({
|
export function useUploadType({
|
||||||
acceptRef,
|
acceptRef,
|
||||||
|
|
@ -66,48 +80,54 @@ export function useUploadType({
|
||||||
// TODO @芋艿:目前保持和 admin-vue3 一致,后续可能重构
|
// TODO @芋艿:目前保持和 admin-vue3 一致,后续可能重构
|
||||||
export const useUpload = () => {
|
export const useUpload = () => {
|
||||||
// 后端上传地址
|
// 后端上传地址
|
||||||
const uploadUrl = getUploadUrl()
|
const uploadUrl = getUploadUrl();
|
||||||
// 是否使用前端直连上传
|
// 是否使用前端直连上传
|
||||||
const isClientUpload = UPLOAD_TYPE.CLIENT === import.meta.env.VITE_UPLOAD_TYPE
|
const isClientUpload =
|
||||||
|
UPLOAD_TYPE.CLIENT === import.meta.env.VITE_UPLOAD_TYPE;
|
||||||
// 重写ElUpload上传方法
|
// 重写ElUpload上传方法
|
||||||
const httpRequest = async (file: File, onUploadProgress?: AxiosProgressEvent) => {
|
const httpRequest = async (
|
||||||
|
file: File,
|
||||||
|
onUploadProgress?: AxiosProgressEvent,
|
||||||
|
) => {
|
||||||
// 模式一:前端上传
|
// 模式一:前端上传
|
||||||
if (isClientUpload) {
|
if (isClientUpload) {
|
||||||
// 1.1 生成文件名称
|
// 1.1 生成文件名称
|
||||||
const fileName = await generateFileName(file)
|
const fileName = await generateFileName(file);
|
||||||
// 1.2 获取文件预签名地址
|
// 1.2 获取文件预签名地址
|
||||||
const presignedInfo = await getFilePresignedUrl(fileName)
|
const presignedInfo = await getFilePresignedUrl(fileName);
|
||||||
// 1.3 上传文件
|
// 1.3 上传文件
|
||||||
return axios
|
return axios
|
||||||
.put(presignedInfo.uploadUrl, file, {
|
.put(presignedInfo.uploadUrl, file, {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': file.type
|
'Content-Type': file.type,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// 1.4. 记录文件信息到后端(异步)
|
// 1.4. 记录文件信息到后端(异步)
|
||||||
createFile0(presignedInfo, fileName, file)
|
createFile0(presignedInfo, fileName, file);
|
||||||
// 通知成功,数据格式保持与后端上传的返回结果一致
|
// 通知成功,数据格式保持与后端上传的返回结果一致
|
||||||
return { data: presignedInfo.url }
|
return { data: presignedInfo.url };
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
// 模式二:后端上传
|
// 模式二:后端上传
|
||||||
return uploadFile({ file }, onUploadProgress);
|
return uploadFile({ file }, onUploadProgress);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
uploadUrl,
|
uploadUrl,
|
||||||
httpRequest
|
httpRequest,
|
||||||
}
|
};
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得上传 URL
|
* 获得上传 URL
|
||||||
*/
|
*/
|
||||||
export const getUploadUrl = (): string => {
|
export const getUploadUrl = (): string => {
|
||||||
return import.meta.env.VITE_BASE_URL + import.meta.env.VITE_GLOB_API_URL + '/infra/file/upload'
|
return `${
|
||||||
}
|
import.meta.env.VITE_BASE_URL + import.meta.env.VITE_GLOB_API_URL
|
||||||
|
}/infra/file/upload`;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建文件信息
|
* 创建文件信息
|
||||||
|
|
@ -116,17 +136,21 @@ export const getUploadUrl = (): string => {
|
||||||
* @param name 文件名称
|
* @param name 文件名称
|
||||||
* @param file 文件
|
* @param file 文件
|
||||||
*/
|
*/
|
||||||
function createFile0(vo: InfraFileApi.FilePresignedUrlRespVO, name: string, file: File) {
|
function createFile0(
|
||||||
|
vo: InfraFileApi.FilePresignedUrlRespVO,
|
||||||
|
name: string,
|
||||||
|
file: File,
|
||||||
|
) {
|
||||||
const fileVO = {
|
const fileVO = {
|
||||||
configId: vo.configId,
|
configId: vo.configId,
|
||||||
url: vo.url,
|
url: vo.url,
|
||||||
path: name,
|
path: name,
|
||||||
name: file.name,
|
name: file.name,
|
||||||
type: file.type,
|
type: file.type,
|
||||||
size: file.size
|
size: file.size,
|
||||||
}
|
};
|
||||||
createFile(fileVO)
|
createFile(fileVO);
|
||||||
return fileVO
|
return fileVO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -136,21 +160,11 @@ function createFile0(vo: InfraFileApi.FilePresignedUrlRespVO, name: string, file
|
||||||
*/
|
*/
|
||||||
async function generateFileName(file: File) {
|
async function generateFileName(file: File) {
|
||||||
// 读取文件内容
|
// 读取文件内容
|
||||||
const data = await file.arrayBuffer()
|
const data = await file.arrayBuffer();
|
||||||
const wordArray = CryptoJS.lib.WordArray.create(data)
|
const wordArray = CryptoJS.lib.WordArray.create(data);
|
||||||
// 计算SHA256
|
// 计算SHA256
|
||||||
const sha256 = CryptoJS.SHA256(wordArray).toString()
|
const sha256 = CryptoJS.SHA256(wordArray).toString();
|
||||||
// 拼接后缀
|
// 拼接后缀
|
||||||
const ext = file.name.substring(file.name.lastIndexOf('.'))
|
const ext = file.name.slice(Math.max(0, file.name.lastIndexOf('.')));
|
||||||
return `${sha256}${ext}`
|
return `${sha256}${ext}`;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 上传类型
|
|
||||||
*/
|
|
||||||
enum UPLOAD_TYPE {
|
|
||||||
// 客户端直接上传(只支持S3服务)
|
|
||||||
CLIENT = 'client',
|
|
||||||
// 客户端发送到后端上传
|
|
||||||
SERVER = 'server'
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"copy": "Copy",
|
||||||
|
"copySuccess": "Copy Success",
|
||||||
|
"copyError": "Copy Error"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"copy": "复制",
|
||||||
|
"copySuccess": "复制成功",
|
||||||
|
"copyError": "复制失败"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
import type { App } from 'vue';
|
||||||
|
|
||||||
|
// import install from '@form-create/ant-design-vue/auto-import';
|
||||||
|
import FcDesigner from '@form-create/antd-designer';
|
||||||
|
import Antd from 'ant-design-vue';
|
||||||
|
|
||||||
|
// ======================= 自定义组件 =======================
|
||||||
|
import { useApiSelect } from '#/components/FormCreate';
|
||||||
|
// import { UploadFile, UploadImg, UploadImgs } from '#/components/UploadFile';
|
||||||
|
// import DictSelect from '#/components/FormCreate/src/components/DictSelect.vue';
|
||||||
|
|
||||||
|
const UserSelect = useApiSelect({
|
||||||
|
name: 'UserSelect',
|
||||||
|
labelField: 'nickname',
|
||||||
|
valueField: 'id',
|
||||||
|
url: '/system/user/simple-list',
|
||||||
|
});
|
||||||
|
const DeptSelect = useApiSelect({
|
||||||
|
name: 'DeptSelect',
|
||||||
|
labelField: 'name',
|
||||||
|
valueField: 'id',
|
||||||
|
url: '/system/dept/simple-list',
|
||||||
|
});
|
||||||
|
const ApiSelect = useApiSelect({
|
||||||
|
name: 'ApiSelect',
|
||||||
|
});
|
||||||
|
|
||||||
|
const components = [
|
||||||
|
// UploadImg,
|
||||||
|
// UploadImgs,
|
||||||
|
// UploadFile,
|
||||||
|
// DictSelect,
|
||||||
|
UserSelect,
|
||||||
|
DeptSelect,
|
||||||
|
ApiSelect,
|
||||||
|
];
|
||||||
|
|
||||||
|
// 参考 http://www.form-create.com/v3/ant-design-vue/auto-import.html 文档
|
||||||
|
export const setupFormCreate = (app: App<Element>) => {
|
||||||
|
components.forEach((component) => {
|
||||||
|
app.component(component.name as string, component);
|
||||||
|
});
|
||||||
|
app.use(Antd);
|
||||||
|
app.use(FcDesigner);
|
||||||
|
// formCreate.use(install);
|
||||||
|
app.use(FcDesigner.formCreate);
|
||||||
|
};
|
||||||
|
|
@ -5,11 +5,11 @@ import type {
|
||||||
|
|
||||||
import { generateAccessible } from '@vben/access';
|
import { generateAccessible } from '@vben/access';
|
||||||
import { preferences } from '@vben/preferences';
|
import { preferences } from '@vben/preferences';
|
||||||
|
|
||||||
import { BasicLayout, IFrameView } from '#/layouts';
|
|
||||||
import { useAccessStore } from '@vben/stores';
|
import { useAccessStore } from '@vben/stores';
|
||||||
import { convertServerMenuToRouteRecordStringComponent } from '@vben/utils';
|
import { convertServerMenuToRouteRecordStringComponent } from '@vben/utils';
|
||||||
|
|
||||||
|
import { BasicLayout, IFrameView } from '#/layouts';
|
||||||
|
|
||||||
const forbiddenComponent = () => import('#/views/_core/fallback/forbidden.vue');
|
const forbiddenComponent = () => import('#/views/_core/fallback/forbidden.vue');
|
||||||
|
|
||||||
async function generateAccess(options: GenerateMenuAndRoutesOptions) {
|
async function generateAccess(options: GenerateMenuAndRoutesOptions) {
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ import {
|
||||||
import { resetStaticRoutes } from '@vben/utils';
|
import { resetStaticRoutes } from '@vben/utils';
|
||||||
|
|
||||||
import { createRouterGuard } from './guard';
|
import { createRouterGuard } from './guard';
|
||||||
import { setupBaiduTongJi } from './tongji';
|
|
||||||
import { routes } from './routes';
|
import { routes } from './routes';
|
||||||
|
import { setupBaiduTongJi } from './tongji';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @zh_CN 创建vue-router实例
|
* @zh_CN 创建vue-router实例
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,8 @@ const coreRoutes: RouteRecordRaw[] = [
|
||||||
{
|
{
|
||||||
name: 'SocialLogin',
|
name: 'SocialLogin',
|
||||||
path: 'social-login',
|
path: 'social-login',
|
||||||
component: () => import('#/views/_core/authentication/social-login.vue'),
|
component: () =>
|
||||||
|
import('#/views/_core/authentication/social-login.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: $t('page.auth.login'),
|
title: $t('page.auth.login'),
|
||||||
},
|
},
|
||||||
|
|
@ -104,7 +105,7 @@ const coreRoutes: RouteRecordRaw[] = [
|
||||||
meta: {
|
meta: {
|
||||||
title: $t('page.auth.login'),
|
title: $t('page.auth.login'),
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -44,4 +44,4 @@ const componentKeys: string[] = Object.keys(
|
||||||
const path = v.replace('../../views/', '/');
|
const path = v.replace('../../views/', '/');
|
||||||
return path.endsWith('.vue') ? path.slice(0, -4) : path;
|
return path.endsWith('.vue') ? path.slice(0, -4) : path;
|
||||||
});
|
});
|
||||||
export { accessRoutes, coreRouteNames, routes, componentKeys };
|
export { accessRoutes, componentKeys, coreRouteNames, routes };
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import type { RouteRecordRaw } from 'vue-router';
|
||||||
|
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const routes: RouteRecordRaw[] = [
|
const routes: RouteRecordRaw[] = [
|
||||||
{
|
{
|
||||||
meta: {
|
meta: {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import {
|
||||||
import { IFrameView } from '#/layouts';
|
import { IFrameView } from '#/layouts';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const routes: RouteRecordRaw[] = [
|
const routes: RouteRecordRaw[] = [
|
||||||
{
|
{
|
||||||
meta: {
|
meta: {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
import type { AuthPermissionInfo, Recordable, UserInfo} from '@vben/types';
|
import type { AuthPermissionInfo, Recordable, UserInfo } from '@vben/types';
|
||||||
|
|
||||||
|
import type { AuthApi } from '#/api';
|
||||||
|
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
|
@ -9,7 +11,14 @@ import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';
|
||||||
import { notification } from 'ant-design-vue';
|
import { notification } from 'ant-design-vue';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
import { type AuthApi, getAuthPermissionInfoApi, loginApi, logoutApi, smsLogin, register, socialLogin } from '#/api';
|
import {
|
||||||
|
getAuthPermissionInfoApi,
|
||||||
|
loginApi,
|
||||||
|
logoutApi,
|
||||||
|
register,
|
||||||
|
smsLogin,
|
||||||
|
socialLogin,
|
||||||
|
} from '#/api';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
export const useAuthStore = defineStore('auth', () => {
|
export const useAuthStore = defineStore('auth', () => {
|
||||||
|
|
@ -27,7 +36,7 @@ export const useAuthStore = defineStore('auth', () => {
|
||||||
* @param onSuccess 登录成功后的回调函数
|
* @param onSuccess 登录成功后的回调函数
|
||||||
*/
|
*/
|
||||||
async function authLogin(
|
async function authLogin(
|
||||||
type: 'mobile' | 'username' | 'register' | 'social',
|
type: 'mobile' | 'register' | 'social' | 'username',
|
||||||
params: Recordable<any>,
|
params: Recordable<any>,
|
||||||
onSuccess?: () => Promise<void> | void,
|
onSuccess?: () => Promise<void> | void,
|
||||||
) {
|
) {
|
||||||
|
|
@ -35,10 +44,26 @@ export const useAuthStore = defineStore('auth', () => {
|
||||||
let userInfo: null | UserInfo = null;
|
let userInfo: null | UserInfo = null;
|
||||||
try {
|
try {
|
||||||
loginLoading.value = true;
|
loginLoading.value = true;
|
||||||
const { accessToken, refreshToken } = type === 'mobile' ? await smsLogin(params as AuthApi.SmsLoginParams)
|
let loginResult: AuthApi.LoginResult;
|
||||||
: type === 'register' ? await register(params as AuthApi.RegisterParams)
|
switch (type) {
|
||||||
: type === 'social' ? await socialLogin(params as AuthApi.SocialLoginParams)
|
case 'mobile': {
|
||||||
: await loginApi(params);
|
loginResult = await smsLogin(params as AuthApi.SmsLoginParams);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'register': {
|
||||||
|
loginResult = await register(params as AuthApi.RegisterParams);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'social': {
|
||||||
|
loginResult = await socialLogin(params as AuthApi.SocialLoginParams);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
loginResult = await loginApi(params);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const { accessToken, refreshToken } = loginResult;
|
||||||
|
|
||||||
// 如果成功获取到 accessToken
|
// 如果成功获取到 accessToken
|
||||||
if (accessToken) {
|
if (accessToken) {
|
||||||
|
|
|
||||||
|
|
@ -9,14 +9,14 @@
|
||||||
// 全局通用状态枚举
|
// 全局通用状态枚举
|
||||||
export const CommonStatusEnum = {
|
export const CommonStatusEnum = {
|
||||||
ENABLE: 0, // 开启
|
ENABLE: 0, // 开启
|
||||||
DISABLE: 1 // 禁用
|
DISABLE: 1, // 禁用
|
||||||
}
|
};
|
||||||
|
|
||||||
// 全局用户类型枚举
|
// 全局用户类型枚举
|
||||||
export const UserTypeEnum = {
|
export const UserTypeEnum = {
|
||||||
MEMBER: 1, // 会员
|
MEMBER: 1, // 会员
|
||||||
ADMIN: 2 // 管理员
|
ADMIN: 2, // 管理员
|
||||||
}
|
};
|
||||||
|
|
||||||
// ========== SYSTEM 模块 ==========
|
// ========== SYSTEM 模块 ==========
|
||||||
/**
|
/**
|
||||||
|
|
@ -25,16 +25,16 @@ export const UserTypeEnum = {
|
||||||
export const SystemMenuTypeEnum = {
|
export const SystemMenuTypeEnum = {
|
||||||
DIR: 1, // 目录
|
DIR: 1, // 目录
|
||||||
MENU: 2, // 菜单
|
MENU: 2, // 菜单
|
||||||
BUTTON: 3 // 按钮
|
BUTTON: 3, // 按钮
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 角色的类型枚举
|
* 角色的类型枚举
|
||||||
*/
|
*/
|
||||||
export const SystemRoleTypeEnum = {
|
export const SystemRoleTypeEnum = {
|
||||||
SYSTEM: 1, // 内置角色
|
SYSTEM: 1, // 内置角色
|
||||||
CUSTOM: 2 // 自定义角色
|
CUSTOM: 2, // 自定义角色
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据权限的范围枚举
|
* 数据权限的范围枚举
|
||||||
|
|
@ -44,8 +44,8 @@ export const SystemDataScopeEnum = {
|
||||||
DEPT_CUSTOM: 2, // 指定部门数据权限
|
DEPT_CUSTOM: 2, // 指定部门数据权限
|
||||||
DEPT_ONLY: 3, // 部门数据权限
|
DEPT_ONLY: 3, // 部门数据权限
|
||||||
DEPT_AND_CHILD: 4, // 部门及以下数据权限
|
DEPT_AND_CHILD: 4, // 部门及以下数据权限
|
||||||
DEPT_SELF: 5 // 仅本人数据权限
|
DEPT_SELF: 5, // 仅本人数据权限
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户的社交平台的类型枚举
|
* 用户的社交平台的类型枚举
|
||||||
|
|
@ -55,15 +55,15 @@ export const SystemUserSocialTypeEnum = {
|
||||||
title: '钉钉',
|
title: '钉钉',
|
||||||
type: 20,
|
type: 20,
|
||||||
source: 'dingtalk',
|
source: 'dingtalk',
|
||||||
img: 'https://s1.ax1x.com/2022/05/22/OzMDRs.png'
|
img: 'https://s1.ax1x.com/2022/05/22/OzMDRs.png',
|
||||||
},
|
},
|
||||||
WECHAT_ENTERPRISE: {
|
WECHAT_ENTERPRISE: {
|
||||||
title: '企业微信',
|
title: '企业微信',
|
||||||
type: 30,
|
type: 30,
|
||||||
source: 'wechat_enterprise',
|
source: 'wechat_enterprise',
|
||||||
img: 'https://s1.ax1x.com/2022/05/22/OzMrzn.png'
|
img: 'https://s1.ax1x.com/2022/05/22/OzMrzn.png',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
// ========== INFRA 模块 ==========
|
// ========== INFRA 模块 ==========
|
||||||
/**
|
/**
|
||||||
|
|
@ -72,8 +72,8 @@ export const SystemUserSocialTypeEnum = {
|
||||||
export const InfraCodegenTemplateTypeEnum = {
|
export const InfraCodegenTemplateTypeEnum = {
|
||||||
CRUD: 1, // 基础 CRUD
|
CRUD: 1, // 基础 CRUD
|
||||||
TREE: 2, // 树形 CRUD
|
TREE: 2, // 树形 CRUD
|
||||||
SUB: 15 // 主子表 CRUD
|
SUB: 15, // 主子表 CRUD
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 任务状态的枚举
|
* 任务状态的枚举
|
||||||
|
|
@ -81,8 +81,8 @@ export const InfraCodegenTemplateTypeEnum = {
|
||||||
export const InfraJobStatusEnum = {
|
export const InfraJobStatusEnum = {
|
||||||
INIT: 0, // 初始化中
|
INIT: 0, // 初始化中
|
||||||
NORMAL: 1, // 运行中
|
NORMAL: 1, // 运行中
|
||||||
STOP: 2 // 暂停运行
|
STOP: 2, // 暂停运行
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API 异常数据的处理状态
|
* API 异常数据的处理状态
|
||||||
|
|
@ -90,8 +90,8 @@ export const InfraJobStatusEnum = {
|
||||||
export const InfraApiErrorLogProcessStatusEnum = {
|
export const InfraApiErrorLogProcessStatusEnum = {
|
||||||
INIT: 0, // 未处理
|
INIT: 0, // 未处理
|
||||||
DONE: 1, // 已处理
|
DONE: 1, // 已处理
|
||||||
IGNORE: 2 // 已忽略
|
IGNORE: 2, // 已忽略
|
||||||
}
|
};
|
||||||
|
|
||||||
// ========== PAY 模块 ==========
|
// ========== PAY 模块 ==========
|
||||||
/**
|
/**
|
||||||
|
|
@ -100,78 +100,78 @@ export const InfraApiErrorLogProcessStatusEnum = {
|
||||||
export const PayChannelEnum = {
|
export const PayChannelEnum = {
|
||||||
WX_PUB: {
|
WX_PUB: {
|
||||||
code: 'wx_pub',
|
code: 'wx_pub',
|
||||||
name: '微信 JSAPI 支付'
|
name: '微信 JSAPI 支付',
|
||||||
},
|
},
|
||||||
WX_LITE: {
|
WX_LITE: {
|
||||||
code: 'wx_lite',
|
code: 'wx_lite',
|
||||||
name: '微信小程序支付'
|
name: '微信小程序支付',
|
||||||
},
|
},
|
||||||
WX_APP: {
|
WX_APP: {
|
||||||
code: 'wx_app',
|
code: 'wx_app',
|
||||||
name: '微信 APP 支付'
|
name: '微信 APP 支付',
|
||||||
},
|
},
|
||||||
WX_NATIVE: {
|
WX_NATIVE: {
|
||||||
code: 'wx_native',
|
code: 'wx_native',
|
||||||
name: '微信 Native 支付'
|
name: '微信 Native 支付',
|
||||||
},
|
},
|
||||||
WX_WAP: {
|
WX_WAP: {
|
||||||
code: 'wx_wap',
|
code: 'wx_wap',
|
||||||
name: '微信 WAP 网站支付'
|
name: '微信 WAP 网站支付',
|
||||||
},
|
},
|
||||||
WX_BAR: {
|
WX_BAR: {
|
||||||
code: 'wx_bar',
|
code: 'wx_bar',
|
||||||
name: '微信条码支付'
|
name: '微信条码支付',
|
||||||
},
|
},
|
||||||
ALIPAY_PC: {
|
ALIPAY_PC: {
|
||||||
code: 'alipay_pc',
|
code: 'alipay_pc',
|
||||||
name: '支付宝 PC 网站支付'
|
name: '支付宝 PC 网站支付',
|
||||||
},
|
},
|
||||||
ALIPAY_WAP: {
|
ALIPAY_WAP: {
|
||||||
code: 'alipay_wap',
|
code: 'alipay_wap',
|
||||||
name: '支付宝 WAP 网站支付'
|
name: '支付宝 WAP 网站支付',
|
||||||
},
|
},
|
||||||
ALIPAY_APP: {
|
ALIPAY_APP: {
|
||||||
code: 'alipay_app',
|
code: 'alipay_app',
|
||||||
name: '支付宝 APP 支付'
|
name: '支付宝 APP 支付',
|
||||||
},
|
},
|
||||||
ALIPAY_QR: {
|
ALIPAY_QR: {
|
||||||
code: 'alipay_qr',
|
code: 'alipay_qr',
|
||||||
name: '支付宝扫码支付'
|
name: '支付宝扫码支付',
|
||||||
},
|
},
|
||||||
ALIPAY_BAR: {
|
ALIPAY_BAR: {
|
||||||
code: 'alipay_bar',
|
code: 'alipay_bar',
|
||||||
name: '支付宝条码支付'
|
name: '支付宝条码支付',
|
||||||
},
|
},
|
||||||
WALLET: {
|
WALLET: {
|
||||||
code: 'wallet',
|
code: 'wallet',
|
||||||
name: '钱包支付'
|
name: '钱包支付',
|
||||||
},
|
},
|
||||||
MOCK: {
|
MOCK: {
|
||||||
code: 'mock',
|
code: 'mock',
|
||||||
name: '模拟支付'
|
name: '模拟支付',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付的展示模式每局
|
* 支付的展示模式每局
|
||||||
*/
|
*/
|
||||||
export const PayDisplayModeEnum = {
|
export const PayDisplayModeEnum = {
|
||||||
URL: {
|
URL: {
|
||||||
mode: 'url'
|
mode: 'url',
|
||||||
},
|
},
|
||||||
IFRAME: {
|
IFRAME: {
|
||||||
mode: 'iframe'
|
mode: 'iframe',
|
||||||
},
|
},
|
||||||
FORM: {
|
FORM: {
|
||||||
mode: 'form'
|
mode: 'form',
|
||||||
},
|
},
|
||||||
QR_CODE: {
|
QR_CODE: {
|
||||||
mode: 'qr_code'
|
mode: 'qr_code',
|
||||||
},
|
},
|
||||||
APP: {
|
APP: {
|
||||||
mode: 'app'
|
mode: 'app',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付类型枚举
|
* 支付类型枚举
|
||||||
|
|
@ -179,8 +179,8 @@ export const PayDisplayModeEnum = {
|
||||||
export const PayType = {
|
export const PayType = {
|
||||||
WECHAT: 'WECHAT',
|
WECHAT: 'WECHAT',
|
||||||
ALIPAY: 'ALIPAY',
|
ALIPAY: 'ALIPAY',
|
||||||
MOCK: 'MOCK'
|
MOCK: 'MOCK',
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付订单状态枚举
|
* 支付订单状态枚举
|
||||||
|
|
@ -188,17 +188,17 @@ export const PayType = {
|
||||||
export const PayOrderStatusEnum = {
|
export const PayOrderStatusEnum = {
|
||||||
WAITING: {
|
WAITING: {
|
||||||
status: 0,
|
status: 0,
|
||||||
name: '未支付'
|
name: '未支付',
|
||||||
},
|
},
|
||||||
SUCCESS: {
|
SUCCESS: {
|
||||||
status: 10,
|
status: 10,
|
||||||
name: '已支付'
|
name: '已支付',
|
||||||
},
|
},
|
||||||
CLOSED: {
|
CLOSED: {
|
||||||
status: 20,
|
status: 20,
|
||||||
name: '未支付'
|
name: '未支付',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
// ========== MALL - 商品模块 ==========
|
// ========== MALL - 商品模块 ==========
|
||||||
/**
|
/**
|
||||||
|
|
@ -207,17 +207,17 @@ export const PayOrderStatusEnum = {
|
||||||
export const ProductSpuStatusEnum = {
|
export const ProductSpuStatusEnum = {
|
||||||
RECYCLE: {
|
RECYCLE: {
|
||||||
status: -1,
|
status: -1,
|
||||||
name: '回收站'
|
name: '回收站',
|
||||||
},
|
},
|
||||||
DISABLE: {
|
DISABLE: {
|
||||||
status: 0,
|
status: 0,
|
||||||
name: '下架'
|
name: '下架',
|
||||||
},
|
},
|
||||||
ENABLE: {
|
ENABLE: {
|
||||||
status: 1,
|
status: 1,
|
||||||
name: '上架'
|
name: '上架',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
// ========== MALL - 营销模块 ==========
|
// ========== MALL - 营销模块 ==========
|
||||||
/**
|
/**
|
||||||
|
|
@ -226,13 +226,13 @@ export const ProductSpuStatusEnum = {
|
||||||
export const CouponTemplateValidityTypeEnum = {
|
export const CouponTemplateValidityTypeEnum = {
|
||||||
DATE: {
|
DATE: {
|
||||||
type: 1,
|
type: 1,
|
||||||
name: '固定日期可用'
|
name: '固定日期可用',
|
||||||
},
|
},
|
||||||
TERM: {
|
TERM: {
|
||||||
type: 2,
|
type: 2,
|
||||||
name: '领取之后可用'
|
name: '领取之后可用',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 优惠劵模板的领取方式的枚举
|
* 优惠劵模板的领取方式的枚举
|
||||||
|
|
@ -240,17 +240,17 @@ export const CouponTemplateValidityTypeEnum = {
|
||||||
export const CouponTemplateTakeTypeEnum = {
|
export const CouponTemplateTakeTypeEnum = {
|
||||||
USER: {
|
USER: {
|
||||||
type: 1,
|
type: 1,
|
||||||
name: '直接领取'
|
name: '直接领取',
|
||||||
},
|
},
|
||||||
ADMIN: {
|
ADMIN: {
|
||||||
type: 2,
|
type: 2,
|
||||||
name: '指定发放'
|
name: '指定发放',
|
||||||
},
|
},
|
||||||
REGISTER: {
|
REGISTER: {
|
||||||
type: 3,
|
type: 3,
|
||||||
name: '新人券'
|
name: '新人券',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 营销的商品范围枚举
|
* 营销的商品范围枚举
|
||||||
|
|
@ -258,17 +258,17 @@ export const CouponTemplateTakeTypeEnum = {
|
||||||
export const PromotionProductScopeEnum = {
|
export const PromotionProductScopeEnum = {
|
||||||
ALL: {
|
ALL: {
|
||||||
scope: 1,
|
scope: 1,
|
||||||
name: '通用劵'
|
name: '通用劵',
|
||||||
},
|
},
|
||||||
SPU: {
|
SPU: {
|
||||||
scope: 2,
|
scope: 2,
|
||||||
name: '商品劵'
|
name: '商品劵',
|
||||||
},
|
},
|
||||||
CATEGORY: {
|
CATEGORY: {
|
||||||
scope: 3,
|
scope: 3,
|
||||||
name: '品类劵'
|
name: '品类劵',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 营销的条件类型枚举
|
* 营销的条件类型枚举
|
||||||
|
|
@ -276,13 +276,13 @@ export const PromotionProductScopeEnum = {
|
||||||
export const PromotionConditionTypeEnum = {
|
export const PromotionConditionTypeEnum = {
|
||||||
PRICE: {
|
PRICE: {
|
||||||
type: 10,
|
type: 10,
|
||||||
name: '满 N 元'
|
name: '满 N 元',
|
||||||
},
|
},
|
||||||
COUNT: {
|
COUNT: {
|
||||||
type: 20,
|
type: 20,
|
||||||
name: '满 N 件'
|
name: '满 N 件',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 优惠类型枚举
|
* 优惠类型枚举
|
||||||
|
|
@ -290,13 +290,13 @@ export const PromotionConditionTypeEnum = {
|
||||||
export const PromotionDiscountTypeEnum = {
|
export const PromotionDiscountTypeEnum = {
|
||||||
PRICE: {
|
PRICE: {
|
||||||
type: 1,
|
type: 1,
|
||||||
name: '满减'
|
name: '满减',
|
||||||
},
|
},
|
||||||
PERCENT: {
|
PERCENT: {
|
||||||
type: 2,
|
type: 2,
|
||||||
name: '折扣'
|
name: '折扣',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
// ========== MALL - 交易模块 ==========
|
// ========== MALL - 交易模块 ==========
|
||||||
/**
|
/**
|
||||||
|
|
@ -305,89 +305,89 @@ export const PromotionDiscountTypeEnum = {
|
||||||
export const BrokerageBindModeEnum = {
|
export const BrokerageBindModeEnum = {
|
||||||
ANYTIME: {
|
ANYTIME: {
|
||||||
mode: 1,
|
mode: 1,
|
||||||
name: '首次绑定'
|
name: '首次绑定',
|
||||||
},
|
},
|
||||||
REGISTER: {
|
REGISTER: {
|
||||||
mode: 2,
|
mode: 2,
|
||||||
name: '注册绑定'
|
name: '注册绑定',
|
||||||
},
|
},
|
||||||
OVERRIDE: {
|
OVERRIDE: {
|
||||||
mode: 3,
|
mode: 3,
|
||||||
name: '覆盖绑定'
|
name: '覆盖绑定',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
/**
|
/**
|
||||||
* 分佣模式枚举
|
* 分佣模式枚举
|
||||||
*/
|
*/
|
||||||
export const BrokerageEnabledConditionEnum = {
|
export const BrokerageEnabledConditionEnum = {
|
||||||
ALL: {
|
ALL: {
|
||||||
condition: 1,
|
condition: 1,
|
||||||
name: '人人分销'
|
name: '人人分销',
|
||||||
},
|
},
|
||||||
ADMIN: {
|
ADMIN: {
|
||||||
condition: 2,
|
condition: 2,
|
||||||
name: '指定分销'
|
name: '指定分销',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
/**
|
/**
|
||||||
* 佣金记录业务类型枚举
|
* 佣金记录业务类型枚举
|
||||||
*/
|
*/
|
||||||
export const BrokerageRecordBizTypeEnum = {
|
export const BrokerageRecordBizTypeEnum = {
|
||||||
ORDER: {
|
ORDER: {
|
||||||
type: 1,
|
type: 1,
|
||||||
name: '获得推广佣金'
|
name: '获得推广佣金',
|
||||||
},
|
},
|
||||||
WITHDRAW: {
|
WITHDRAW: {
|
||||||
type: 2,
|
type: 2,
|
||||||
name: '提现申请'
|
name: '提现申请',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
/**
|
/**
|
||||||
* 佣金提现状态枚举
|
* 佣金提现状态枚举
|
||||||
*/
|
*/
|
||||||
export const BrokerageWithdrawStatusEnum = {
|
export const BrokerageWithdrawStatusEnum = {
|
||||||
AUDITING: {
|
AUDITING: {
|
||||||
status: 0,
|
status: 0,
|
||||||
name: '审核中'
|
name: '审核中',
|
||||||
},
|
},
|
||||||
AUDIT_SUCCESS: {
|
AUDIT_SUCCESS: {
|
||||||
status: 10,
|
status: 10,
|
||||||
name: '审核通过'
|
name: '审核通过',
|
||||||
},
|
},
|
||||||
AUDIT_FAIL: {
|
AUDIT_FAIL: {
|
||||||
status: 20,
|
status: 20,
|
||||||
name: '审核不通过'
|
name: '审核不通过',
|
||||||
},
|
},
|
||||||
WITHDRAW_SUCCESS: {
|
WITHDRAW_SUCCESS: {
|
||||||
status: 11,
|
status: 11,
|
||||||
name: '提现成功'
|
name: '提现成功',
|
||||||
},
|
},
|
||||||
WITHDRAW_FAIL: {
|
WITHDRAW_FAIL: {
|
||||||
status: 21,
|
status: 21,
|
||||||
name: '提现失败'
|
name: '提现失败',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
/**
|
/**
|
||||||
* 佣金提现类型枚举
|
* 佣金提现类型枚举
|
||||||
*/
|
*/
|
||||||
export const BrokerageWithdrawTypeEnum = {
|
export const BrokerageWithdrawTypeEnum = {
|
||||||
WALLET: {
|
WALLET: {
|
||||||
type: 1,
|
type: 1,
|
||||||
name: '钱包'
|
name: '钱包',
|
||||||
},
|
},
|
||||||
BANK: {
|
BANK: {
|
||||||
type: 2,
|
type: 2,
|
||||||
name: '银行卡'
|
name: '银行卡',
|
||||||
},
|
},
|
||||||
WECHAT: {
|
WECHAT: {
|
||||||
type: 3,
|
type: 3,
|
||||||
name: '微信'
|
name: '微信',
|
||||||
},
|
},
|
||||||
ALIPAY: {
|
ALIPAY: {
|
||||||
type: 4,
|
type: 4,
|
||||||
name: '支付宝'
|
name: '支付宝',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配送方式枚举
|
* 配送方式枚举
|
||||||
|
|
@ -395,38 +395,38 @@ export const BrokerageWithdrawTypeEnum = {
|
||||||
export const DeliveryTypeEnum = {
|
export const DeliveryTypeEnum = {
|
||||||
EXPRESS: {
|
EXPRESS: {
|
||||||
type: 1,
|
type: 1,
|
||||||
name: '快递发货'
|
name: '快递发货',
|
||||||
},
|
},
|
||||||
PICK_UP: {
|
PICK_UP: {
|
||||||
type: 2,
|
type: 2,
|
||||||
name: '到店自提'
|
name: '到店自提',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
/**
|
/**
|
||||||
* 交易订单 - 状态
|
* 交易订单 - 状态
|
||||||
*/
|
*/
|
||||||
export const TradeOrderStatusEnum = {
|
export const TradeOrderStatusEnum = {
|
||||||
UNPAID: {
|
UNPAID: {
|
||||||
status: 0,
|
status: 0,
|
||||||
name: '待支付'
|
name: '待支付',
|
||||||
},
|
},
|
||||||
UNDELIVERED: {
|
UNDELIVERED: {
|
||||||
status: 10,
|
status: 10,
|
||||||
name: '待发货'
|
name: '待发货',
|
||||||
},
|
},
|
||||||
DELIVERED: {
|
DELIVERED: {
|
||||||
status: 20,
|
status: 20,
|
||||||
name: '已发货'
|
name: '已发货',
|
||||||
},
|
},
|
||||||
COMPLETED: {
|
COMPLETED: {
|
||||||
status: 30,
|
status: 30,
|
||||||
name: '已完成'
|
name: '已完成',
|
||||||
},
|
},
|
||||||
CANCELED: {
|
CANCELED: {
|
||||||
status: 40,
|
status: 40,
|
||||||
name: '已取消'
|
name: '已取消',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
// ========== ERP - 企业资源计划 ==========
|
// ========== ERP - 企业资源计划 ==========
|
||||||
|
|
||||||
|
|
@ -436,31 +436,31 @@ export const ErpBizType = {
|
||||||
PURCHASE_RETURN: 12,
|
PURCHASE_RETURN: 12,
|
||||||
SALE_ORDER: 20,
|
SALE_ORDER: 20,
|
||||||
SALE_OUT: 21,
|
SALE_OUT: 21,
|
||||||
SALE_RETURN: 22
|
SALE_RETURN: 22,
|
||||||
}
|
};
|
||||||
|
|
||||||
// ========== BPM 模块 ==========
|
// ========== BPM 模块 ==========
|
||||||
|
|
||||||
export const BpmModelType = {
|
export const BpmModelType = {
|
||||||
BPMN: 10, // BPMN 设计器
|
BPMN: 10, // BPMN 设计器
|
||||||
SIMPLE: 20 // 简易设计器
|
SIMPLE: 20, // 简易设计器
|
||||||
}
|
};
|
||||||
|
|
||||||
export const BpmModelFormType = {
|
export const BpmModelFormType = {
|
||||||
NORMAL: 10, // 流程表单
|
NORMAL: 10, // 流程表单
|
||||||
CUSTOM: 20 // 业务表单
|
CUSTOM: 20, // 业务表单
|
||||||
}
|
};
|
||||||
|
|
||||||
export const BpmProcessInstanceStatus = {
|
export const BpmProcessInstanceStatus = {
|
||||||
NOT_START: -1, // 未开始
|
NOT_START: -1, // 未开始
|
||||||
RUNNING: 1, // 审批中
|
RUNNING: 1, // 审批中
|
||||||
APPROVE: 2, // 审批通过
|
APPROVE: 2, // 审批通过
|
||||||
REJECT: 3, // 审批不通过
|
REJECT: 3, // 审批不通过
|
||||||
CANCEL: 4 // 已取消
|
CANCEL: 4, // 已取消
|
||||||
}
|
};
|
||||||
|
|
||||||
export const BpmAutoApproveType = {
|
export const BpmAutoApproveType = {
|
||||||
NONE: 0, // 不自动通过
|
NONE: 0, // 不自动通过
|
||||||
APPROVE_ALL: 1, // 仅审批一次,后续重复的审批节点均自动通过
|
APPROVE_ALL: 1, // 仅审批一次,后续重复的审批节点均自动通过
|
||||||
APPROVE_SEQUENT: 2, // 仅针对连续审批的节点自动通过
|
APPROVE_SEQUENT: 2, // 仅针对连续审批的节点自动通过
|
||||||
}
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,10 @@ export function getRangePickerDefaultProps() {
|
||||||
return {
|
return {
|
||||||
showTime: {
|
showTime: {
|
||||||
format: 'HH:mm:ss',
|
format: 'HH:mm:ss',
|
||||||
defaultValue: [dayjs('00:00:00', 'HH:mm:ss'), dayjs('23:59:59', 'HH:mm:ss')],
|
defaultValue: [
|
||||||
|
dayjs('00:00:00', 'HH:mm:ss'),
|
||||||
|
dayjs('23:59:59', 'HH:mm:ss'),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||||
format: 'YYYY-MM-DD HH:mm:ss',
|
format: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,19 @@ import { isObject } from '@vben/utils';
|
||||||
|
|
||||||
import { useDictStore } from '#/store';
|
import { useDictStore } from '#/store';
|
||||||
|
|
||||||
|
export interface DictDataType {
|
||||||
|
dictType: string;
|
||||||
|
label: string;
|
||||||
|
value: boolean | number | string;
|
||||||
|
// TODO: type
|
||||||
|
colorType: '' | 'error' | 'info' | 'success' | 'warning';
|
||||||
|
cssClass: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NumberDictDataType extends DictDataType {
|
||||||
|
value: number;
|
||||||
|
}
|
||||||
|
|
||||||
const dictStore = useDictStore();
|
const dictStore = useDictStore();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -17,7 +30,7 @@ const dictStore = useDictStore();
|
||||||
*/
|
*/
|
||||||
function getDictLabel(dictType: string, value: any) {
|
function getDictLabel(dictType: string, value: any) {
|
||||||
const dictObj = dictStore.getDictData(dictType, value);
|
const dictObj = dictStore.getDictData(dictType, value);
|
||||||
return isObject(dictObj)? dictObj.label : '';
|
return isObject(dictObj) ? dictObj.label : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -71,6 +84,48 @@ function getDictOptions(
|
||||||
return dictOptions.length > 0 ? dictOptions : [];
|
return dictOptions.length > 0 ? dictOptions : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getIntDictOptions = (dictType: string): NumberDictDataType[] => {
|
||||||
|
// 获得通用的 DictDataType 列表
|
||||||
|
const dictOptions = getDictOptions(dictType) as DictDataType[];
|
||||||
|
// 转换成 number 类型的 NumberDictDataType 类型
|
||||||
|
// why 需要特殊转换:避免 IDEA 在 v-for="dict in getIntDictOptions(...)" 时,el-option 的 key 会告警
|
||||||
|
const dictOption: NumberDictDataType[] = [];
|
||||||
|
dictOptions.forEach((dict: DictDataType) => {
|
||||||
|
dictOption.push({
|
||||||
|
...dict,
|
||||||
|
value: Number.parseInt(`${dict.value}`),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return dictOption;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getStrDictOptions = (dictType: string) => {
|
||||||
|
// 获得通用的 DictDataType 列表
|
||||||
|
const dictOptions = getDictOptions(dictType) as DictDataType[];
|
||||||
|
// 转换成 string 类型的 StringDictDataType 类型
|
||||||
|
// why 需要特殊转换:避免 IDEA 在 v-for="dict in getStrDictOptions(...)" 时,el-option 的 key 会告警
|
||||||
|
const dictOption: StringDictDataType[] = [];
|
||||||
|
dictOptions.forEach((dict: DictDataType) => {
|
||||||
|
dictOption.push({
|
||||||
|
...dict,
|
||||||
|
value: `${dict.value}`,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return dictOption;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getBoolDictOptions = (dictType: string) => {
|
||||||
|
const dictOption: DictDataType[] = [];
|
||||||
|
const dictOptions = getDictOptions(dictType) as DictDataType[];
|
||||||
|
dictOptions.forEach((dict: DictDataType) => {
|
||||||
|
dictOption.push({
|
||||||
|
...dict,
|
||||||
|
value: `${dict.value}` === 'true',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return dictOption;
|
||||||
|
};
|
||||||
|
|
||||||
enum DICT_TYPE {
|
enum DICT_TYPE {
|
||||||
AI_GENERATE_MODE = 'ai_generate_mode', // AI 生成模式
|
AI_GENERATE_MODE = 'ai_generate_mode', // AI 生成模式
|
||||||
AI_IMAGE_STATUS = 'ai_image_status', // AI 图片状态
|
AI_IMAGE_STATUS = 'ai_image_status', // AI 图片状态
|
||||||
|
|
@ -205,4 +260,4 @@ enum DICT_TYPE {
|
||||||
TRADE_ORDER_TYPE = 'trade_order_type', // 订单 - 类型
|
TRADE_ORDER_TYPE = 'trade_order_type', // 订单 - 类型
|
||||||
USER_TYPE = 'user_type',
|
USER_TYPE = 'user_type',
|
||||||
}
|
}
|
||||||
export { DICT_TYPE, getDictObj, getDictLabel, getDictOptions };
|
export { DICT_TYPE, getDictLabel, getDictObj, getDictOptions };
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
/**
|
||||||
|
* 生成 UUID
|
||||||
|
*/
|
||||||
|
export const generateUUID = () => {
|
||||||
|
if (typeof crypto === 'object') {
|
||||||
|
if (typeof crypto.randomUUID === 'function') {
|
||||||
|
return crypto.randomUUID();
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
typeof crypto.getRandomValues === 'function' &&
|
||||||
|
typeof Uint8Array === 'function'
|
||||||
|
) {
|
||||||
|
const callback = (c: any) => {
|
||||||
|
const num = Number(c);
|
||||||
|
return (
|
||||||
|
num ^
|
||||||
|
(crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (num / 4)))
|
||||||
|
).toString(16);
|
||||||
|
};
|
||||||
|
return '10000000-1000-4000-8000-100000000000'.replaceAll(
|
||||||
|
/[018]/g,
|
||||||
|
callback,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let timestamp = Date.now();
|
||||||
|
let performanceNow =
|
||||||
|
(typeof performance !== 'undefined' &&
|
||||||
|
performance.now &&
|
||||||
|
performance.now() * 1000) ||
|
||||||
|
0;
|
||||||
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replaceAll(/[xy]/g, (c) => {
|
||||||
|
let random = Math.random() * 16;
|
||||||
|
if (timestamp > 0) {
|
||||||
|
random = Math.trunc((timestamp + random) % 16);
|
||||||
|
timestamp = Math.floor(timestamp / 16);
|
||||||
|
} else {
|
||||||
|
random = Math.trunc((performanceNow + random) % 16);
|
||||||
|
performanceNow = Math.floor(performanceNow / 16);
|
||||||
|
}
|
||||||
|
return (c === 'x' ? random : (random & 0x3) | 0x8).toString(16);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,125 @@
|
||||||
|
/* eslint-disable @typescript-eslint/no-unsafe-function-type */
|
||||||
|
const toString = Object.prototype.toString;
|
||||||
|
|
||||||
|
export const is = (val: unknown, type: string) => {
|
||||||
|
return toString.call(val) === `[object ${type}]`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isDef = <T = unknown>(val?: T): val is T => {
|
||||||
|
return val !== undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isUnDef = <T = unknown>(val?: T): val is T => {
|
||||||
|
return !isDef(val);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isObject = (val: any): val is Record<any, any> => {
|
||||||
|
return val !== null && is(val, 'Object');
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isEmpty = (val: any): boolean => {
|
||||||
|
if (val === null || val === undefined || val === undefined) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (isArray(val) || isString(val)) {
|
||||||
|
return val.length === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val instanceof Map || val instanceof Set) {
|
||||||
|
return val.size === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isObject(val)) {
|
||||||
|
return Object.keys(val).length === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isDate = (val: unknown): val is Date => {
|
||||||
|
return is(val, 'Date');
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isNull = (val: unknown): val is null => {
|
||||||
|
return val === null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isNullAndUnDef = (val: unknown): val is null | undefined => {
|
||||||
|
return isUnDef(val) && isNull(val);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isNullOrUnDef = (val: unknown): val is null | undefined => {
|
||||||
|
return isUnDef(val) || isNull(val);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isNumber = (val: unknown): val is number => {
|
||||||
|
return is(val, 'Number');
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isPromise = <T = any>(val: unknown): val is Promise<T> => {
|
||||||
|
return (
|
||||||
|
is(val, 'Promise') &&
|
||||||
|
isObject(val) &&
|
||||||
|
isFunction(val.then) &&
|
||||||
|
isFunction(val.catch)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isString = (val: unknown): val is string => {
|
||||||
|
return is(val, 'String');
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isFunction = (val: unknown): val is Function => {
|
||||||
|
return typeof val === 'function';
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isBoolean = (val: unknown): val is boolean => {
|
||||||
|
return is(val, 'Boolean');
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isRegExp = (val: unknown): val is RegExp => {
|
||||||
|
return is(val, 'RegExp');
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isArray = (val: any): val is Array<any> => {
|
||||||
|
return val && Array.isArray(val);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isWindow = (val: any): val is Window => {
|
||||||
|
return typeof window !== 'undefined' && is(val, 'Window');
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isElement = (val: unknown): val is Element => {
|
||||||
|
return isObject(val) && !!val.tagName;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isMap = (val: unknown): val is Map<any, any> => {
|
||||||
|
return is(val, 'Map');
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isServer = typeof window === 'undefined';
|
||||||
|
|
||||||
|
export const isClient = !isServer;
|
||||||
|
|
||||||
|
export const isUrl = (path: string): boolean => {
|
||||||
|
// fix:修复hash路由无法跳转的问题
|
||||||
|
const reg =
|
||||||
|
// eslint-disable-next-line regexp/no-unused-capturing-group, regexp/no-useless-quantifier, regexp/no-super-linear-backtracking
|
||||||
|
/(((^https?:(?:\/\/)?)(?:[-:&=+$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%#/.\w-]*)?\??[-+=&%@.\w]*(?:#\w*)?)?)$/;
|
||||||
|
return reg.test(path);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isDark = (): boolean => {
|
||||||
|
return window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 是否是图片链接
|
||||||
|
export const isImgPath = (path: string): boolean => {
|
||||||
|
return /(?:https?:\/\/|data:image\/).*?\.(?:png|jpg|jpeg|gif|svg|webp|ico)/i.test(
|
||||||
|
path,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isEmptyVal = (val: any): boolean => {
|
||||||
|
return val === '' || val === null || val === undefined;
|
||||||
|
};
|
||||||
|
|
@ -16,7 +16,7 @@ export const handleTree = (
|
||||||
data: TreeNode[],
|
data: TreeNode[],
|
||||||
id: string = 'id',
|
id: string = 'id',
|
||||||
parentId: string = 'parentId',
|
parentId: string = 'parentId',
|
||||||
children: string = 'children'
|
children: string = 'children',
|
||||||
): TreeNode[] => {
|
): TreeNode[] => {
|
||||||
if (!Array.isArray(data)) {
|
if (!Array.isArray(data)) {
|
||||||
console.warn('data must be an array');
|
console.warn('data must be an array');
|
||||||
|
|
@ -25,10 +25,10 @@ export const handleTree = (
|
||||||
const config = {
|
const config = {
|
||||||
id,
|
id,
|
||||||
parentId,
|
parentId,
|
||||||
childrenList: children
|
childrenList: children,
|
||||||
};
|
};
|
||||||
const childrenListMap: Record<string | number, TreeNode[]> = {};
|
const childrenListMap: Record<number | string, TreeNode[]> = {};
|
||||||
const nodeIds: Record<string | number, TreeNode> = {};
|
const nodeIds: Record<number | string, TreeNode> = {};
|
||||||
const tree: TreeNode[] = [];
|
const tree: TreeNode[] = [];
|
||||||
|
|
||||||
// 1. 数据预处理
|
// 1. 数据预处理
|
||||||
|
|
@ -67,4 +67,4 @@ export const handleTree = (
|
||||||
}
|
}
|
||||||
|
|
||||||
return tree;
|
return tree;
|
||||||
}
|
};
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,9 @@ const MOBILE_REGEX = /(?:0|86|\+86)?1[3-9]\d{9}/;
|
||||||
* @param value 值
|
* @param value 值
|
||||||
* @returns 是否为手机号码(中国)
|
* @returns 是否为手机号码(中国)
|
||||||
*/
|
*/
|
||||||
export function isMobile(value?: string | null): boolean {
|
export function isMobile(value?: null | string): boolean {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return MOBILE_REGEX.test(value);
|
return MOBILE_REGEX.test(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,21 +2,25 @@
|
||||||
import type { VbenFormSchema } from '@vben/common-ui';
|
import type { VbenFormSchema } from '@vben/common-ui';
|
||||||
import type { Recordable } from '@vben/types';
|
import type { Recordable } from '@vben/types';
|
||||||
|
|
||||||
import { computed, ref, onMounted } from 'vue';
|
import type { AuthApi } from '#/api';
|
||||||
|
|
||||||
|
import { computed, onMounted, ref } from 'vue';
|
||||||
|
|
||||||
import { AuthenticationCodeLogin, z } from '@vben/common-ui';
|
import { AuthenticationCodeLogin, z } from '@vben/common-ui';
|
||||||
import { $t } from '@vben/locales';
|
|
||||||
import { type AuthApi, sendSmsCode } from '#/api';
|
|
||||||
import { useAppConfig } from '@vben/hooks';
|
import { useAppConfig } from '@vben/hooks';
|
||||||
|
import { $t } from '@vben/locales';
|
||||||
|
import { useAccessStore } from '@vben/stores';
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
import { getTenantSimpleList, getTenantByWebsite } from '#/api/core/auth';
|
import { sendSmsCode } from '#/api';
|
||||||
import { useAccessStore } from '@vben/stores';
|
import { getTenantByWebsite, getTenantSimpleList } from '#/api/core/auth';
|
||||||
import { useAuthStore } from '#/store';
|
import { useAuthStore } from '#/store';
|
||||||
const { tenantEnable } = useAppConfig(import.meta.env, import.meta.env.PROD);
|
|
||||||
|
|
||||||
defineOptions({ name: 'CodeLogin' });
|
defineOptions({ name: 'CodeLogin' });
|
||||||
|
|
||||||
|
const { tenantEnable } = useAppConfig(import.meta.env, import.meta.env.PROD);
|
||||||
|
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
const accessStore = useAccessStore();
|
const accessStore = useAccessStore();
|
||||||
|
|
||||||
|
|
@ -37,7 +41,7 @@ const fetchTenantList = async () => {
|
||||||
tenantList.value = await getTenantSimpleList();
|
tenantList.value = await getTenantSimpleList();
|
||||||
|
|
||||||
// 选中租户:域名 > store 中的租户 > 首个租户
|
// 选中租户:域名 > store 中的租户 > 首个租户
|
||||||
let tenantId: number | null = null;
|
let tenantId: null | number = null;
|
||||||
const websiteTenant = await websiteTenantPromise;
|
const websiteTenant = await websiteTenantPromise;
|
||||||
if (websiteTenant?.id) {
|
if (websiteTenant?.id) {
|
||||||
tenantId = websiteTenant.id;
|
tenantId = websiteTenant.id;
|
||||||
|
|
@ -80,7 +84,10 @@ const formSchema = computed((): VbenFormSchema[] => {
|
||||||
rules: z
|
rules: z
|
||||||
.number()
|
.number()
|
||||||
.nullable()
|
.nullable()
|
||||||
.refine((val) => val != null && val > 0, $t('authentication.tenantTip'))
|
.refine(
|
||||||
|
(val) => val !== null && val > 0,
|
||||||
|
$t('authentication.tenantTip'),
|
||||||
|
)
|
||||||
.default(null),
|
.default(null),
|
||||||
dependencies: {
|
dependencies: {
|
||||||
triggerFields: ['tenantId'],
|
triggerFields: ['tenantId'],
|
||||||
|
|
@ -140,7 +147,7 @@ const formSchema = computed((): VbenFormSchema[] => {
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
fieldName: 'code',
|
fieldName: 'code',
|
||||||
label: $t('authentication.code'),
|
label: $t('authentication.code'),
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,21 @@
|
||||||
import type { VbenFormSchema } from '@vben/common-ui';
|
import type { VbenFormSchema } from '@vben/common-ui';
|
||||||
import type { Recordable } from '@vben/types';
|
import type { Recordable } from '@vben/types';
|
||||||
|
|
||||||
import { computed, ref, onMounted, h } from 'vue';
|
import type { AuthApi } from '#/api';
|
||||||
|
|
||||||
import { AuthenticationForgetPassword, z } from '@vben/common-ui';
|
import { computed, onMounted, ref } from 'vue';
|
||||||
import { $t } from '@vben/locales';
|
|
||||||
import { type AuthApi, sendSmsCode, smsResetPassword } from '#/api';
|
|
||||||
import { useAppConfig } from '@vben/hooks';
|
|
||||||
import { message } from 'ant-design-vue';
|
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
import { getTenantSimpleList, getTenantByWebsite } from '#/api/core/auth';
|
import { AuthenticationForgetPassword, z } from '@vben/common-ui';
|
||||||
|
import { useAppConfig } from '@vben/hooks';
|
||||||
|
import { $t } from '@vben/locales';
|
||||||
import { useAccessStore } from '@vben/stores';
|
import { useAccessStore } from '@vben/stores';
|
||||||
|
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { sendSmsCode, smsResetPassword } from '#/api';
|
||||||
|
import { getTenantByWebsite, getTenantSimpleList } from '#/api/core/auth';
|
||||||
|
|
||||||
defineOptions({ name: 'ForgetPassword' });
|
defineOptions({ name: 'ForgetPassword' });
|
||||||
|
|
||||||
const { tenantEnable } = useAppConfig(import.meta.env, import.meta.env.PROD);
|
const { tenantEnable } = useAppConfig(import.meta.env, import.meta.env.PROD);
|
||||||
|
|
@ -36,7 +39,7 @@ const fetchTenantList = async () => {
|
||||||
tenantList.value = await getTenantSimpleList();
|
tenantList.value = await getTenantSimpleList();
|
||||||
|
|
||||||
// 选中租户:域名 > store 中的租户 > 首个租户
|
// 选中租户:域名 > store 中的租户 > 首个租户
|
||||||
let tenantId: number | null = null;
|
let tenantId: null | number = null;
|
||||||
const websiteTenant = await websiteTenantPromise;
|
const websiteTenant = await websiteTenantPromise;
|
||||||
if (websiteTenant?.id) {
|
if (websiteTenant?.id) {
|
||||||
tenantId = websiteTenant.id;
|
tenantId = websiteTenant.id;
|
||||||
|
|
@ -79,7 +82,10 @@ const formSchema = computed((): VbenFormSchema[] => {
|
||||||
rules: z
|
rules: z
|
||||||
.number()
|
.number()
|
||||||
.nullable()
|
.nullable()
|
||||||
.refine((val) => val != null && val > 0, $t('authentication.tenantTip'))
|
.refine(
|
||||||
|
(val) => val !== null && val > 0,
|
||||||
|
$t('authentication.tenantTip'),
|
||||||
|
)
|
||||||
.default(null),
|
.default(null),
|
||||||
dependencies: {
|
dependencies: {
|
||||||
triggerFields: ['tenantId'],
|
triggerFields: ['tenantId'],
|
||||||
|
|
@ -139,7 +145,7 @@ const formSchema = computed((): VbenFormSchema[] => {
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
fieldName: 'code',
|
fieldName: 'code',
|
||||||
label: $t('authentication.code'),
|
label: $t('authentication.code'),
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,32 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { VbenFormSchema } from '@vben/common-ui';
|
import type { VbenFormSchema } from '@vben/common-ui';
|
||||||
import { type AuthApi, checkCaptcha, getCaptcha, socialAuthRedirect } from '#/api/core/auth';
|
|
||||||
|
import type { AuthApi } from '#/api/core/auth';
|
||||||
|
|
||||||
import { computed, onMounted, ref } from 'vue';
|
import { computed, onMounted, ref } from 'vue';
|
||||||
|
|
||||||
import { AuthenticationLogin, Verification, z } from '@vben/common-ui';
|
|
||||||
import { $t } from '@vben/locales';
|
|
||||||
import { useAppConfig } from '@vben/hooks';
|
|
||||||
|
|
||||||
import { useAuthStore } from '#/store';
|
|
||||||
import { useAccessStore } from '@vben/stores';
|
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
import { getTenantSimpleList, getTenantByWebsite } from '#/api/core/auth';
|
import { AuthenticationLogin, Verification, z } from '@vben/common-ui';
|
||||||
import {message} from 'ant-design-vue';
|
import { useAppConfig } from '@vben/hooks';
|
||||||
|
import { $t } from '@vben/locales';
|
||||||
|
import { useAccessStore } from '@vben/stores';
|
||||||
|
|
||||||
const { tenantEnable, captchaEnable } = useAppConfig(import.meta.env, import.meta.env.PROD);
|
import {
|
||||||
|
checkCaptcha,
|
||||||
|
getCaptcha,
|
||||||
|
getTenantByWebsite,
|
||||||
|
getTenantSimpleList,
|
||||||
|
socialAuthRedirect,
|
||||||
|
} from '#/api/core/auth';
|
||||||
|
import { useAuthStore } from '#/store';
|
||||||
|
|
||||||
defineOptions({ name: 'Login' });
|
defineOptions({ name: 'Login' });
|
||||||
|
|
||||||
|
const { tenantEnable, captchaEnable } = useAppConfig(
|
||||||
|
import.meta.env,
|
||||||
|
import.meta.env.PROD,
|
||||||
|
);
|
||||||
|
|
||||||
const { query } = useRoute();
|
const { query } = useRoute();
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
const accessStore = useAccessStore();
|
const accessStore = useAccessStore();
|
||||||
|
|
@ -40,7 +48,7 @@ const fetchTenantList = async () => {
|
||||||
tenantList.value = await getTenantSimpleList();
|
tenantList.value = await getTenantSimpleList();
|
||||||
|
|
||||||
// 选中租户:域名 > store 中的租户 > 首个租户
|
// 选中租户:域名 > store 中的租户 > 首个租户
|
||||||
let tenantId: number | null = null;
|
let tenantId: null | number = null;
|
||||||
const websiteTenant = await websiteTenantPromise;
|
const websiteTenant = await websiteTenantPromise;
|
||||||
if (websiteTenant?.id) {
|
if (websiteTenant?.id) {
|
||||||
tenantId = websiteTenant.id;
|
tenantId = websiteTenant.id;
|
||||||
|
|
@ -72,7 +80,7 @@ const handleLogin = async (values: any) => {
|
||||||
|
|
||||||
// 无验证码,直接登录
|
// 无验证码,直接登录
|
||||||
await authStore.authLogin('username', values);
|
await authStore.authLogin('username', values);
|
||||||
}
|
};
|
||||||
|
|
||||||
/** 验证码通过,执行登录 */
|
/** 验证码通过,执行登录 */
|
||||||
const handleVerifySuccess = async ({ captchaVerification }: any) => {
|
const handleVerifySuccess = async ({ captchaVerification }: any) => {
|
||||||
|
|
@ -95,13 +103,14 @@ const handleThirdLogin = async (type: number) => {
|
||||||
try {
|
try {
|
||||||
// 计算 redirectUri
|
// 计算 redirectUri
|
||||||
// tricky: type、redirect 需要先 encode 一次,否则钉钉回调会丢失。配合 social-login.vue#getUrlValue() 使用
|
// tricky: type、redirect 需要先 encode 一次,否则钉钉回调会丢失。配合 social-login.vue#getUrlValue() 使用
|
||||||
const redirectUri =
|
const redirectUri = `${
|
||||||
location.origin +
|
location.origin
|
||||||
'/auth/social-login?' +
|
}/auth/social-login?${encodeURIComponent(
|
||||||
encodeURIComponent(`type=${type}&redirect=${redirect || '/'}`)
|
`type=${type}&redirect=${redirect || '/'}`,
|
||||||
|
)}`;
|
||||||
|
|
||||||
// 进行跳转
|
// 进行跳转
|
||||||
window.location.href = await socialAuthRedirect(type, redirectUri)
|
window.location.href = await socialAuthRedirect(type, redirectUri);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('第三方登录处理失败:', error);
|
console.error('第三方登录处理失败:', error);
|
||||||
}
|
}
|
||||||
|
|
@ -128,7 +137,10 @@ const formSchema = computed((): VbenFormSchema[] => {
|
||||||
rules: z
|
rules: z
|
||||||
.number()
|
.number()
|
||||||
.nullable()
|
.nullable()
|
||||||
.refine((val) => val != null && val > 0, $t('authentication.tenantTip'))
|
.refine(
|
||||||
|
(val) => val !== null && val > 0,
|
||||||
|
$t('authentication.tenantTip'),
|
||||||
|
)
|
||||||
.default(null),
|
.default(null),
|
||||||
dependencies: {
|
dependencies: {
|
||||||
triggerFields: ['tenantId'],
|
triggerFields: ['tenantId'],
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,30 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { VbenFormSchema } from '@vben/common-ui';
|
import type { VbenFormSchema } from '@vben/common-ui';
|
||||||
import { type AuthApi, checkCaptcha, getCaptcha } from '#/api/core/auth';
|
|
||||||
|
import type { AuthApi } from '#/api/core/auth';
|
||||||
|
|
||||||
import { computed, h, onMounted, ref } from 'vue';
|
import { computed, h, onMounted, ref } from 'vue';
|
||||||
|
|
||||||
import { AuthenticationRegister, Verification, z } from '@vben/common-ui';
|
import { AuthenticationRegister, Verification, z } from '@vben/common-ui';
|
||||||
import { $t } from '@vben/locales';
|
|
||||||
import { useAppConfig } from '@vben/hooks';
|
import { useAppConfig } from '@vben/hooks';
|
||||||
|
import { $t } from '@vben/locales';
|
||||||
import { useAccessStore } from '@vben/stores';
|
import { useAccessStore } from '@vben/stores';
|
||||||
import { useAuthStore } from '#/store';
|
|
||||||
import { getTenantSimpleList, getTenantByWebsite } from '#/api/core/auth';
|
|
||||||
|
|
||||||
const { tenantEnable, captchaEnable } = useAppConfig(import.meta.env, import.meta.env.PROD);
|
import {
|
||||||
|
checkCaptcha,
|
||||||
|
getCaptcha,
|
||||||
|
getTenantByWebsite,
|
||||||
|
getTenantSimpleList,
|
||||||
|
} from '#/api/core/auth';
|
||||||
|
import { useAuthStore } from '#/store';
|
||||||
|
|
||||||
defineOptions({ name: 'Register' });
|
defineOptions({ name: 'Register' });
|
||||||
|
|
||||||
|
const { tenantEnable, captchaEnable } = useAppConfig(
|
||||||
|
import.meta.env,
|
||||||
|
import.meta.env.PROD,
|
||||||
|
);
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const registerRef = ref();
|
const registerRef = ref();
|
||||||
const verifyRef = ref();
|
const verifyRef = ref();
|
||||||
|
|
@ -36,7 +45,7 @@ const fetchTenantList = async () => {
|
||||||
tenantList.value = await getTenantSimpleList();
|
tenantList.value = await getTenantSimpleList();
|
||||||
|
|
||||||
// 选中租户:域名 > store 中的租户 > 首个租户
|
// 选中租户:域名 > store 中的租户 > 首个租户
|
||||||
let tenantId: number | null = null;
|
let tenantId: null | number = null;
|
||||||
const websiteTenant = await websiteTenantPromise;
|
const websiteTenant = await websiteTenantPromise;
|
||||||
if (websiteTenant?.id) {
|
if (websiteTenant?.id) {
|
||||||
tenantId = websiteTenant.id;
|
tenantId = websiteTenant.id;
|
||||||
|
|
@ -103,7 +112,10 @@ const formSchema = computed((): VbenFormSchema[] => {
|
||||||
rules: z
|
rules: z
|
||||||
.number()
|
.number()
|
||||||
.nullable()
|
.nullable()
|
||||||
.refine((val) => val != null && val > 0, $t('authentication.tenantTip'))
|
.refine(
|
||||||
|
(val) => val !== null && val > 0,
|
||||||
|
$t('authentication.tenantTip'),
|
||||||
|
)
|
||||||
.default(null),
|
.default(null),
|
||||||
dependencies: {
|
dependencies: {
|
||||||
triggerFields: ['tenantId'],
|
triggerFields: ['tenantId'],
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,31 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { VbenFormSchema } from '@vben/common-ui';
|
import type { VbenFormSchema } from '@vben/common-ui';
|
||||||
import { type AuthApi, checkCaptcha, getCaptcha } from '#/api/core/auth';
|
|
||||||
|
import type { AuthApi } from '#/api/core/auth';
|
||||||
|
|
||||||
import { computed, onMounted, ref } from 'vue';
|
import { computed, onMounted, ref } from 'vue';
|
||||||
|
|
||||||
import { AuthenticationLogin, Verification, z } from '@vben/common-ui';
|
|
||||||
import { $t } from '@vben/locales';
|
|
||||||
import { useAppConfig } from '@vben/hooks';
|
|
||||||
|
|
||||||
import { useAuthStore } from '#/store';
|
|
||||||
import { useAccessStore } from '@vben/stores';
|
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
|
||||||
import { getTenantSimpleList, getTenantByWebsite } from '#/api/core/auth';
|
import { AuthenticationLogin, Verification, z } from '@vben/common-ui';
|
||||||
|
import { useAppConfig } from '@vben/hooks';
|
||||||
|
import { $t } from '@vben/locales';
|
||||||
|
import { useAccessStore } from '@vben/stores';
|
||||||
|
|
||||||
const { tenantEnable, captchaEnable } = useAppConfig(import.meta.env, import.meta.env.PROD);
|
import {
|
||||||
|
checkCaptcha,
|
||||||
|
getCaptcha,
|
||||||
|
getTenantByWebsite,
|
||||||
|
getTenantSimpleList,
|
||||||
|
} from '#/api/core/auth';
|
||||||
|
import { useAuthStore } from '#/store';
|
||||||
|
|
||||||
defineOptions({ name: 'SocialLogin' });
|
defineOptions({ name: 'SocialLogin' });
|
||||||
|
|
||||||
|
const { tenantEnable, captchaEnable } = useAppConfig(
|
||||||
|
import.meta.env,
|
||||||
|
import.meta.env.PROD,
|
||||||
|
);
|
||||||
|
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
const accessStore = useAccessStore();
|
const accessStore = useAccessStore();
|
||||||
const { query } = useRoute();
|
const { query } = useRoute();
|
||||||
|
|
@ -41,7 +49,7 @@ const fetchTenantList = async () => {
|
||||||
tenantList.value = await getTenantSimpleList();
|
tenantList.value = await getTenantSimpleList();
|
||||||
|
|
||||||
// 选中租户:域名 > store 中的租户 > 首个租户
|
// 选中租户:域名 > store 中的租户 > 首个租户
|
||||||
let tenantId: number | null = null;
|
let tenantId: null | number = null;
|
||||||
const websiteTenant = await websiteTenantPromise;
|
const websiteTenant = await websiteTenantPromise;
|
||||||
if (websiteTenant?.id) {
|
if (websiteTenant?.id) {
|
||||||
tenantId = websiteTenant.id;
|
tenantId = websiteTenant.id;
|
||||||
|
|
@ -74,8 +82,8 @@ const tryLogin = async () => {
|
||||||
await router.replace({
|
await router.replace({
|
||||||
query: {
|
query: {
|
||||||
...query,
|
...query,
|
||||||
redirect: encodeURIComponent(redirect)
|
redirect: encodeURIComponent(redirect),
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,7 +93,7 @@ const tryLogin = async () => {
|
||||||
code: socialCode,
|
code: socialCode,
|
||||||
state: socialState,
|
state: socialState,
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/** 处理登录 */
|
/** 处理登录 */
|
||||||
const handleLogin = async (values: any) => {
|
const handleLogin = async (values: any) => {
|
||||||
|
|
@ -102,7 +110,7 @@ const handleLogin = async (values: any) => {
|
||||||
socialCode,
|
socialCode,
|
||||||
socialState,
|
socialState,
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/** 验证码通过,执行登录 */
|
/** 验证码通过,执行登录 */
|
||||||
const handleVerifySuccess = async ({ captchaVerification }: any) => {
|
const handleVerifySuccess = async ({ captchaVerification }: any) => {
|
||||||
|
|
@ -121,8 +129,8 @@ const handleVerifySuccess = async ({ captchaVerification }: any) => {
|
||||||
|
|
||||||
/** tricky: 配合 login.vue 中,redirectUri 需要对参数进行 encode,需要在回调后进行decode */
|
/** tricky: 配合 login.vue 中,redirectUri 需要对参数进行 encode,需要在回调后进行decode */
|
||||||
function getUrlValue(key: string): string {
|
function getUrlValue(key: string): string {
|
||||||
const url = new URL(decodeURIComponent(location.href))
|
const url = new URL(decodeURIComponent(location.href));
|
||||||
return url.searchParams.get(key) ?? ''
|
return url.searchParams.get(key) ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 组件挂载时获取租户信息 */
|
/** 组件挂载时获取租户信息 */
|
||||||
|
|
@ -148,7 +156,10 @@ const formSchema = computed((): VbenFormSchema[] => {
|
||||||
rules: z
|
rules: z
|
||||||
.number()
|
.number()
|
||||||
.nullable()
|
.nullable()
|
||||||
.refine((val) => val != null && val > 0, $t('authentication.tenantTip'))
|
.refine(
|
||||||
|
(val) => val !== null && val > 0,
|
||||||
|
$t('authentication.tenantTip'),
|
||||||
|
)
|
||||||
.default(null),
|
.default(null),
|
||||||
dependencies: {
|
dependencies: {
|
||||||
triggerFields: ['tenantId'],
|
triggerFields: ['tenantId'],
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { VbenFormSchema } from '#/adapter/form';
|
import type { VbenFormSchema } from '#/adapter/form';
|
||||||
|
|
||||||
|
import { computed, onMounted, reactive, ref } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
import { AuthenticationAuthTitle, VbenButton } from '@vben/common-ui';
|
import { AuthenticationAuthTitle, VbenButton } from '@vben/common-ui';
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
import { useVbenForm } from '#/adapter/form';
|
||||||
import { computed, reactive, ref, onMounted } from 'vue';
|
|
||||||
import { useRoute } from 'vue-router';
|
|
||||||
import { authorize, getAuthorize } from '#/api/system/oauth2/open';
|
import { authorize, getAuthorize } from '#/api/system/oauth2/open';
|
||||||
|
|
||||||
defineOptions({ name: 'SSOLogin' });
|
defineOptions({ name: 'SSOLogin' });
|
||||||
|
|
@ -14,7 +15,7 @@ const { query } = useRoute(); // 路由参数
|
||||||
|
|
||||||
const client = ref({
|
const client = ref({
|
||||||
name: '',
|
name: '',
|
||||||
logo: ''
|
logo: '',
|
||||||
}); // 客户端信息
|
}); // 客户端信息
|
||||||
|
|
||||||
const queryParams = reactive({
|
const queryParams = reactive({
|
||||||
|
|
@ -22,7 +23,7 @@ const queryParams = reactive({
|
||||||
clientId: '',
|
clientId: '',
|
||||||
redirectUri: '',
|
redirectUri: '',
|
||||||
state: '',
|
state: '',
|
||||||
scopes: [] as string[] // 优先从 query 参数获取;如果未传递,从后端获取
|
scopes: [] as string[], // 优先从 query 参数获取;如果未传递,从后端获取
|
||||||
}); // URL 上的 client_id、scope 等参数
|
}); // URL 上的 client_id、scope 等参数
|
||||||
|
|
||||||
const loading = ref(false); // 表单是否提交中
|
const loading = ref(false); // 表单是否提交中
|
||||||
|
|
@ -30,7 +31,7 @@ const loading = ref(false); // 表单是否提交中
|
||||||
/** 初始化授权信息 */
|
/** 初始化授权信息 */
|
||||||
const init = async () => {
|
const init = async () => {
|
||||||
// 防止在没有登录的情况下循环弹窗
|
// 防止在没有登录的情况下循环弹窗
|
||||||
if (typeof query.client_id === 'undefined') {
|
if (query.client_id === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 解析参数
|
// 解析参数
|
||||||
|
|
@ -60,15 +61,20 @@ const init = async () => {
|
||||||
let scopes;
|
let scopes;
|
||||||
// 如果 params.scope 非空,则过滤下返回的 scopes
|
// 如果 params.scope 非空,则过滤下返回的 scopes
|
||||||
if (queryParams.scopes.length > 0) {
|
if (queryParams.scopes.length > 0) {
|
||||||
scopes = data.scopes.filter(scope => queryParams.scopes.includes(scope.key));
|
scopes = data.scopes.filter((scope) =>
|
||||||
|
queryParams.scopes.includes(scope.key),
|
||||||
|
);
|
||||||
// 如果 params.scope 为空,则使用返回的 scopes 设置它
|
// 如果 params.scope 为空,则使用返回的 scopes 设置它
|
||||||
} else {
|
} else {
|
||||||
scopes = data.scopes;
|
scopes = data.scopes;
|
||||||
queryParams.scopes = scopes.map(scope => scope.key);
|
queryParams.scopes = scopes.map((scope) => scope.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2.设置表单的初始值
|
// 2.设置表单的初始值
|
||||||
formApi.setFieldValue('scopes', scopes.filter(scope => scope.value).map(scope => scope.key));
|
formApi.setFieldValue(
|
||||||
|
'scopes',
|
||||||
|
scopes.filter((scope) => scope.value).map((scope) => scope.key),
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 处理授权的提交 */
|
/** 处理授权的提交 */
|
||||||
|
|
@ -78,8 +84,11 @@ const handleSubmit = async (approved: boolean) => {
|
||||||
let uncheckedScopes: string[];
|
let uncheckedScopes: string[];
|
||||||
if (approved) {
|
if (approved) {
|
||||||
// 同意授权,按照用户的选择
|
// 同意授权,按照用户的选择
|
||||||
checkedScopes = (await formApi.getValues()).scopes;
|
const { scopes } = await formApi.getValues();
|
||||||
uncheckedScopes = queryParams.scopes.filter((item) => checkedScopes.indexOf(item) === -1);
|
checkedScopes = scopes;
|
||||||
|
uncheckedScopes = queryParams.scopes.filter(
|
||||||
|
(item) => !checkedScopes.includes(item),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
// 拒绝,则都是取消
|
// 拒绝,则都是取消
|
||||||
checkedScopes = [];
|
checkedScopes = [];
|
||||||
|
|
@ -101,7 +110,11 @@ const handleSubmit = async (approved: boolean) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 调用授权 API 接口 */
|
/** 调用授权 API 接口 */
|
||||||
const doAuthorize = (autoApprove: boolean, checkedScopes: string[], uncheckedScopes: string[]) => {
|
const doAuthorize = (
|
||||||
|
autoApprove: boolean,
|
||||||
|
checkedScopes: string[],
|
||||||
|
uncheckedScopes: string[],
|
||||||
|
) => {
|
||||||
return authorize(
|
return authorize(
|
||||||
queryParams.responseType,
|
queryParams.responseType,
|
||||||
queryParams.clientId,
|
queryParams.clientId,
|
||||||
|
|
@ -109,7 +122,7 @@ const doAuthorize = (autoApprove: boolean, checkedScopes: string[], uncheckedSco
|
||||||
queryParams.state,
|
queryParams.state,
|
||||||
autoApprove,
|
autoApprove,
|
||||||
checkedScopes,
|
checkedScopes,
|
||||||
uncheckedScopes
|
uncheckedScopes,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -118,13 +131,16 @@ const formatScope = (scope: string) => {
|
||||||
// 格式化 scope 授权范围,方便用户理解。
|
// 格式化 scope 授权范围,方便用户理解。
|
||||||
// 这里仅仅是一个 demo,可以考虑录入到字典数据中,例如说字典类型 "system_oauth2_scope",它的每个 scope 都是一条字典数据。
|
// 这里仅仅是一个 demo,可以考虑录入到字典数据中,例如说字典类型 "system_oauth2_scope",它的每个 scope 都是一条字典数据。
|
||||||
switch (scope) {
|
switch (scope) {
|
||||||
case 'user.read':
|
case 'user.read': {
|
||||||
return '访问你的个人信息';
|
return '访问你的个人信息';
|
||||||
case 'user.write':
|
}
|
||||||
|
case 'user.write': {
|
||||||
return '修改你的个人信息';
|
return '修改你的个人信息';
|
||||||
default:
|
}
|
||||||
|
default: {
|
||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const formSchema = computed((): VbenFormSchema[] => {
|
const formSchema = computed((): VbenFormSchema[] => {
|
||||||
|
|
@ -134,11 +150,11 @@ const formSchema = computed((): VbenFormSchema[] => {
|
||||||
label: '授权范围',
|
label: '授权范围',
|
||||||
component: 'CheckboxGroup',
|
component: 'CheckboxGroup',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
options: queryParams.scopes.map(scope => ({
|
options: queryParams.scopes.map((scope) => ({
|
||||||
label: formatScope(scope),
|
label: formatScope(scope),
|
||||||
value: scope
|
value: scope,
|
||||||
})),
|
})),
|
||||||
class: 'flex flex-col gap-2'
|
class: 'flex flex-col gap-2',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
@ -158,7 +174,7 @@ const [Form, formApi] = useVbenForm(
|
||||||
/** 初始化 */
|
/** 初始化 */
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
init();
|
init();
|
||||||
})
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
import type { BpmCategoryApi } from '#/api/bpm/category';
|
import type { BpmCategoryApi } from '#/api/bpm/category';
|
||||||
|
|
||||||
import { useAccess } from '@vben/access';
|
import { useAccess } from '@vben/access';
|
||||||
|
|
||||||
import { z } from '#/adapter/form';
|
import { z } from '#/adapter/form';
|
||||||
import { CommonStatusEnum } from '#/utils/constants';
|
import { CommonStatusEnum } from '#/utils/constants';
|
||||||
import { DICT_TYPE, getDictOptions } from '#/utils/dict';
|
import { DICT_TYPE, getDictOptions } from '#/utils/dict';
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,20 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter/vxe-table';
|
import type {
|
||||||
|
OnActionClickParams,
|
||||||
|
VxeTableGridOptions,
|
||||||
|
} from '#/adapter/vxe-table';
|
||||||
import type { BpmCategoryApi } from '#/api/bpm/category';
|
import type { BpmCategoryApi } from '#/api/bpm/category';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
|
|
||||||
import { Button, message } from 'ant-design-vue';
|
import { Button, message } from 'ant-design-vue';
|
||||||
import Form from './modules/form.vue';
|
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
import { deleteCategory, getCategoryPage } from '#/api/bpm/category';
|
import { deleteCategory, getCategoryPage } from '#/api/bpm/category';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
import { useGridColumns, useGridFormSchema } from './data';
|
import { useGridColumns, useGridFormSchema } from './data';
|
||||||
|
import Form from './modules/form.vue';
|
||||||
|
|
||||||
const [FormModal, formModalApi] = useVbenModal({
|
const [FormModal, formModalApi] = useVbenModal({
|
||||||
connectedComponent: Form,
|
connectedComponent: Form,
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,18 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { BpmCategoryApi } from '#/api/bpm/category';
|
import type { BpmCategoryApi } from '#/api/bpm/category';
|
||||||
|
|
||||||
|
import { computed, ref } from 'vue';
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
import { computed, ref } from 'vue';
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
import { useVbenForm } from '#/adapter/form';
|
||||||
import {createCategory, getCategory, updateCategory } from '#/api/bpm/category';
|
import {
|
||||||
|
createCategory,
|
||||||
|
getCategory,
|
||||||
|
updateCategory,
|
||||||
|
} from '#/api/bpm/category';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
import { useFormSchema } from '../data';
|
import { useFormSchema } from '../data';
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue