This commit is contained in:
孟帅
2024-07-21 22:21:02 +08:00
parent 7d8330f72f
commit a37d088360
440 changed files with 6303 additions and 3339 deletions

View File

@@ -44,9 +44,9 @@
primaryColorHover: lightenStr,
primaryColorPressed: lightenStr,
// 纵向滚动条宽
scrollbarWidth: '10px',
scrollbarWidth: '8px',
// 横向滚动条高
scrollbarHeight: '10px',
scrollbarHeight: '8px',
},
LoadingBar: {
colorLoading: appTheme,

View File

@@ -40,13 +40,6 @@ export function View(params) {
});
}
export function ChooserOption() {
return http.request({
url: '/attachment/chooserOption',
method: 'GET',
});
}
export function ClearKind(params) {
return http.request({
url: '/attachment/clearKind',

View File

@@ -27,6 +27,15 @@ export function Edit(params) {
});
}
// 修改CURD列表状态
export function Status(params) {
return http.request({
url: '/curdDemo/status',
method: 'POST',
params,
});
}
// 操作CURD列表开关
export function Switch(params) {
return http.request({
@@ -56,4 +65,4 @@ export function MaxSort() {
// 导出CURD列表
export function Export(params) {
jumpExport('/curdDemo/export', params);
}
}

View File

@@ -2,7 +2,7 @@
<n-grid :x-gap="5" :y-gap="5" :cols="pageGridCols" responsive="screen">
<n-gi :span="2">
<n-menu
:options="options.kind"
:options="generateKindOptions()"
style="width: 100%"
:default-value="defaultKindValue"
:on-update:value="handleUpdateKind"
@@ -60,8 +60,8 @@
</n-ellipsis>
</template>
<template #action style="padding: 5px">
<n-space justify="center">
<template #action>
<n-space justify="center" style="padding: 5px">
<n-button
strong
secondary
@@ -75,7 +75,6 @@
<DownloadOutlined v-else />
</n-icon>
</template>
{{ item.kind === 'image' ? '预览' : '下载' }}
</n-button>
<n-button
@@ -130,14 +129,15 @@
import { defRangeShortcuts } from '@/utils/dateUtil';
import { EyeOutlined, DeleteOutlined, DownloadOutlined, ClearOutlined } from '@vicons/antd';
import { useProjectSettingStore } from '@/store/modules/projectSetting';
import { ChooserOption, ClearKind, Delete, List } from '@/api/apply/attachment';
import { ClearKind, Delete, List } from '@/api/apply/attachment';
import { constantRouterIcon } from '@/router/router-icons';
import { errorImg } from '@/utils/hotgo';
import { getFileExt } from '@/utils/urlUtils';
import { renderIcon } from '@/utils';
import { Attachment, FileType, KindOption, KindRawOption } from './model';
import { Attachment, FileType, KindOption } from './model';
import Preview from './Preview.vue';
import { VNode } from '@vue/runtime-core';
import { VNode } from 'vue';
import { Option, useDictStore } from '@/store/modules/dict';
export interface Props {
fileList: string[] | null;
@@ -152,6 +152,7 @@
});
const emit = defineEmits(['saveChange']);
const dict = useDictStore();
const settingStore = useProjectSettingStore();
const message = useMessage();
const dialog = useDialog();
@@ -191,7 +192,7 @@
defaultValue: null,
componentProps: {
placeholder: '请选择上传驱动',
options: options.value.drive,
options: dict.getOption('config_upload_drive'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -250,9 +251,6 @@
reloadTable();
});
},
onNegativeClick: () => {
// message.error('取消');
},
});
}
@@ -295,14 +293,14 @@
return selectList.value.some((selected) => selected === item.fileUrl);
}
function generateKindOptions(kinds: KindRawOption[]): any {
function generateKindOptions(): any {
const option: KindOption[] = [];
kinds.forEach((item: KindRawOption) => {
dict.getOptionUnRef('AttachmentKindOption').forEach((item: Option) => {
const data: KindOption = {
label: () => h(NEllipsis, null, { default: () => item.label }),
key: item.key,
key: item.key.toString(),
extra: () => (item.key !== '' ? createExtraContent(item) : null),
icon: constantRouterIcon[item.icon] || null,
icon: constantRouterIcon[item.extra] || null,
disabled: isDisabledKindOption(item),
};
option.push(data);
@@ -310,14 +308,14 @@
return option;
}
function isDisabledKindOption(item: KindRawOption): boolean {
function isDisabledKindOption(item: Option): boolean {
if (props.fileType === 'default') {
return false;
}
return item.key !== props.fileType;
}
function createExtraContent(item: KindRawOption): VNode {
function createExtraContent(item: Option): VNode {
return h(
NButton,
{
@@ -338,9 +336,6 @@
reloadTable();
});
},
onNegativeClick: () => {
// message.error('取消');
},
});
},
},
@@ -348,20 +343,6 @@
);
}
async function loadOptions() {
let tmpOptions = await ChooserOption();
options.value.drive = tmpOptions.drive;
options.value.kind = generateKindOptions(tmpOptions.kind);
for (const item of schemas.value) {
switch (item.field) {
case 'drive':
item.componentProps.options = options.value.drive;
break;
}
}
}
function loadList() {
loading.value = true;
List({ ...params.value, ...searchFormRef.value?.formModel }).then((res) => {
@@ -392,8 +373,12 @@
loadList();
}
function loadOptions() {
dict.loadOptions(['AttachmentKindOption', 'config_upload_drive']);
}
onMounted(async () => {
await loadOptions();
loadOptions();
loadList();
});

View File

@@ -21,12 +21,6 @@ export type Attachment = {
sizeFormat: string;
};
export interface KindRawOption {
key: string;
label: string;
icon: string;
}
export interface KindOption {
key: string;
label: any;

View File

@@ -0,0 +1,124 @@
// 本地字典
// 一些不需要放在服务端注册的字典,也可以在这里进行注册
import { DictOptions, Option } from '@/store/modules/dict';
export const noticeTypeOptions: Option[] = [
{
key: 1,
value: 1,
label: '通知',
listClass: 'warning',
extra: null,
},
{
key: 2,
value: 2,
label: '公告',
listClass: 'error',
extra: null,
},
{
key: 3,
value: 3,
label: '私信',
listClass: 'info',
extra: null,
},
];
export const noticeTagOptions: Option[] = [
{
value: 0,
label: '无标签',
key: 0,
listClass: 'default',
extra: null,
},
{
value: 1,
label: '一般',
key: 1,
listClass: 'info',
extra: null,
},
{
value: 2,
label: '紧急',
key: 2,
listClass: 'error',
extra: null,
},
{
value: 3,
label: '重要',
key: 3,
listClass: 'warning',
extra: null,
},
{
value: 4,
label: '提醒',
key: 4,
listClass: 'success',
extra: null,
},
{
value: 5,
label: '次要',
key: 5,
listClass: 'default',
extra: null,
},
];
export const tagTypeOptions: Option[] = [
{
value: 'success',
label: '绿色',
key: 'success',
listClass: 'success',
extra: null,
},
{
value: 'warning',
label: '橙色',
key: 'warning',
listClass: 'warning',
extra: null,
},
{
value: 'error',
label: '红色',
key: 'error',
listClass: 'error',
extra: null,
},
{
value: 'info',
label: '蓝色',
key: 'info',
listClass: 'info',
extra: null,
},
{
value: 'default',
label: '灰色',
key: 'default',
listClass: 'default',
extra: null,
},
{
value: 'primary',
label: '主题色',
key: 'primary',
listClass: 'primary',
extra: null,
},
];
export const localDict: DictOptions = {
noticeTypeOptions: noticeTypeOptions, // 消息通知类型
noticeTagOptions: noticeTagOptions, // 消息标签类型
tagTypeOptions: tagTypeOptions, // 标签类型选项
};

View File

@@ -1,67 +1,7 @@
import { NAvatar, NTag, NText, SelectRenderLabel, SelectRenderTag } from 'naive-ui';
import { Component, h } from 'vue';
import { getOptionLabel, getOptionTag, Option } from '@/utils/hotgo';
import { BellOutlined, NotificationOutlined, SendOutlined } from '@vicons/antd';
export const noticeTypeOptions: Option[] = [
{
key: 1,
value: 1,
label: '通知',
listClass: 'warning',
},
{
key: 2,
value: 2,
label: '公告',
listClass: 'error',
},
{
key: 3,
value: 3,
label: '私信',
listClass: 'info',
},
];
export const noticeTagOptions: Option[] = [
{
value: 0,
label: '无标签',
key: 0,
listClass: 'default',
},
{
value: 1,
label: '一般',
key: 1,
listClass: 'info',
},
{
value: 2,
label: '紧急',
key: 2,
listClass: 'error',
},
{
value: 3,
label: '重要',
key: 3,
listClass: 'warning',
},
{
value: 4,
label: '提醒',
key: 4,
listClass: 'success',
},
{
value: 5,
label: '次要',
key: 5,
listClass: 'default',
},
];
import { useDictStore } from '@/store/modules/dict';
export interface personOption {
value: number;
@@ -231,8 +171,9 @@ export function parseMessage(row): MessageRow {
if (row.tag <= 0) {
return row;
}
row.tagTitle = getOptionLabel(noticeTagOptions, row.tag);
row.tagProps = { type: getOptionTag(noticeTagOptions, row.tag) };
const dict = useDictStore();
const label = dict.getLabel('noticeTagOptions', row.tag);
row.tagTitle = label;
row.tagProps = { type: label };
return row;
}

View File

@@ -4,8 +4,8 @@ import { RedirectRoute } from '@/router/base';
import { PageEnum } from '@/enums/pageEnum';
import { createRouterGuards } from './router-guards';
// @ts-ignore
const modules = import.meta.globEager('./modules/**/*.ts');
const routeModuleList: RouteRecordRaw[] = [];
Object.keys(modules).forEach((key) => {

View File

@@ -0,0 +1,181 @@
import { computed, ComputedRef } from 'vue';
import { defineStore } from 'pinia';
import { createStorage, storage } from '@/utils/Storage';
import { store } from '@/store';
import { CURRENT_DICT } from '@/store/mutation-types';
import { Dicts } from '@/api/dict/dict';
import { SelectMixedOption } from 'naive-ui/es/select/src/interface';
import { localDict } from '@/enums/localDictEnum';
const Storage = createStorage({ storage: localStorage });
// 默认字典类型,通过后台字典管理添加的
export type DefaultDictType = 'sys_normal_disable' | 'sys_switch' | 'sys_user_sex';
// 枚举字典类型
export type EnumsDictType = 'creditType' | 'creditGroup' | 'deptType';
// 方法字典类型
export type FuncDictType = 'testCategoryOption';
// 可以把常用的字典类型加入进来这样会有IDE提示
export type DictType = DefaultDictType | EnumsDictType | FuncDictType | string;
export interface Option {
label: string;
value: string | number;
key: string | number;
listClass: 'default' | 'error' | 'primary' | 'info' | 'success' | 'warning';
extra: any;
}
export class DictOptions {
[name: DictType]: Option[];
}
export type IDictState = {
options: DictOptions;
};
export const useDictStore = defineStore({
id: 'app-dict',
state: (): IDictState => ({
options: Storage.get(CURRENT_DICT, new DictOptions()),
}),
getters: {},
actions: {
// 加载字典数据选项
loadOptions(types: DictType[]) {
Dicts({
types: types,
}).then((res) => {
if (!res) {
return;
}
Object.keys(res).forEach((key) => {
if (res[key]) {
this.options[key] = res[key] as unknown as Option[];
}
});
storage.set(CURRENT_DICT, this.options);
});
},
// 设置指定类型的字典选项
setOption(type: DictType, opts: Option[]) {
this.options[type] = opts;
storage.set(CURRENT_DICT, this.options);
},
// 获取指定类型的字典选项
getOption(type: DictType): ComputedRef<SelectMixedOption[]> {
return computed(() => {
const opts = this.checkOptionValue(type) ?? [];
return opts as unknown as SelectMixedOption[];
});
},
// 获取指定类型的字典选项
getOptionUnRef(type: DictType): any[] {
return this.checkOptionValue(type) ?? [];
},
// 是否存在选项不存在返回null存在就返回选项
checkOptionValue(type: DictType): null | Option[] {
// 本地字典
const local = localDict[type] ?? [];
if (local && local.length > 0) {
return local;
}
const opts = this.options[type] ?? [];
if (opts === undefined || opts?.length === 0) {
return null;
}
return opts;
},
// 获取选项名称
getLabel(type: DictType, value: any) {
const opts = this.checkOptionValue(type);
if (!opts) {
return ``;
}
for (const item of opts) {
if (item.value.toString() === value.toString()) {
return item.label;
}
}
return ``;
},
// 获取选项标签类型
getType(
type: DictType,
value: any
): 'default' | 'error' | 'primary' | 'info' | 'success' | 'warning' {
const opts = this.checkOptionValue(type);
if (!opts) {
return `default`;
}
for (const item of opts) {
if (item.value.toString() === value.toString()) {
return item.listClass;
}
}
return `default`;
},
// 获取选项额外的数据配置
getExtra(type: DictType, value: any): any {
const opts = this.checkOptionValue(type);
if (!opts) {
return null;
}
for (const item of opts) {
if (item.value.toString() === value.toString()) {
return item?.extra;
}
}
return null;
},
// 是否存在指定选项值
hasValue(type: DictType, value: any): boolean {
const opts = this.checkOptionValue(type);
if (!opts) {
return false;
}
for (const item of opts) {
if (item.value.toString() === value.toString()) {
return true;
}
}
return false;
},
// 获取指定类型的可选项数量
getOptionLength(type: DictType): number {
const opts = this.checkOptionValue(type);
if (!opts) {
return 0;
}
return opts?.length;
},
// 生成单个选项
genOption(key: any, label: string, type = 'default', extra: any = null): Option {
return <Option>{
label: label,
value: key,
key: key,
listClass: type,
extra: extra,
};
},
},
});
// Need to be used outside the setup
export function useDictStoreWidthOut() {
return useDictStore(store);
}

View File

@@ -1,3 +1,4 @@
// @ts-ignore
const allModules = import.meta.globEager('./*/index.ts');
const modules = {} as any;
Object.keys(allModules).forEach((path) => {
@@ -14,10 +15,13 @@ import user from './user';
import tabsView from './tabs-view';
// @ts-ignore
import lockscreen from './lockscreen';
// @ts-ignore
import dict from './dict';
export default {
asyncRoute,
user,
tabsView,
lockscreen,
dict,
};

View File

@@ -4,6 +4,7 @@ import { store } from '@/store';
import {
ACCESS_TOKEN,
CURRENT_CONFIG,
CURRENT_DICT,
CURRENT_LOGIN_CONFIG,
CURRENT_USER,
IS_LOCKSCREEN,
@@ -256,6 +257,7 @@ export const useUserStore = defineStore({
this.setUserInfo(null);
storage.remove(ACCESS_TOKEN);
storage.remove(CURRENT_USER);
storage.remove(CURRENT_DICT);
}
return Promise.resolve(response);
} catch (e) {

View File

@@ -4,3 +4,4 @@ export const CURRENT_CONFIG = 'CURRENT-CONFIG'; // 当前基础配置
export const CURRENT_LOGIN_CONFIG = 'CURRENT-LOGIN-CONFIG'; // 当前登录配置
export const IS_LOCKSCREEN = 'IS-LOCKSCREEN'; // 是否锁屏
export const TABS_ROUTES = 'TABS-ROUTES'; // 标签页
export const CURRENT_DICT = 'CURRENT-DICT'; // 当前用户字典配置

View File

@@ -3,12 +3,14 @@ import { IUserState } from '@/store/modules/user';
import { ILockscreenState } from '@/store/modules/lockscreen';
import { ITabsViewState } from '@/store/modules/tabsView';
import { INotificationStore } from '@/store/modules/notification';
import { IDictState } from '@/store/modules/dict';
export interface IStore {
asyncRoute: IAsyncRouteState;
user: IUserState;
lockscreen: ILockscreenState;
tabsView: ITabsViewState;
dict: IDictState;
notification: INotificationStore;
count: number;
}

View File

@@ -1,9 +1,13 @@
// @ts-ignore
import onerrorImg from '@/assets/images/onerror.png';
import { usePermission } from '@/hooks/web/usePermission';
import { ActionItem } from '@/components/Table';
import { isBoolean, isFunction } from '@/utils/is';
import { PermissionsEnum } from '@/enums/permissionsEnum';
/**
* @deprecated 这个方法将来未来版本完全弃用请统一使用useDictStore()来维护字典选项
*/
export interface Option {
label: string;
value: string | number;
@@ -12,11 +16,17 @@ export interface Option {
listClass: 'default' | 'error' | 'primary' | 'info' | 'success' | 'warning';
}
/**
* @deprecated 这个方法将来未来版本完全弃用请统一使用useDictStore()来维护字典选项
*/
export interface Options {
[name: string]: Option[];
}
// 获取选项名称
/**
* 获取选项名称
* @deprecated 这个方法将来未来版本完全弃用请统一使用useDictStore()来维护字典选项
*/
export function getOptionLabel(options: Option[], value) {
if (options === undefined || options?.length === 0) {
return `unknown`;
@@ -30,7 +40,10 @@ export function getOptionLabel(options: Option[], value) {
return `unknown`;
}
// 获取选项标签
/**
* 获取选项标签
* @deprecated 这个方法将来未来版本完全弃用请统一使用useDictStore()来维护字典选项
*/
export function getOptionTag(options: Option[], value) {
if (options === undefined || options?.length === 0) {
return 'default';
@@ -54,7 +67,7 @@ export function adaModalWidth(def = 840) {
}
}
interface TableColumn {
export interface TableColumn {
width?: number | string;
auth?: PermissionsEnum | PermissionsEnum[] | string | string[];
ifShow?: boolean | ((action: ActionItem) => boolean);
@@ -91,12 +104,17 @@ export function isIfShow(action: ActionItem): boolean {
return isIfShow;
}
// 图片加载失败显示自定义默认图片(缺省图)
// 图片加载失败显示自定义默认图片(缺省图) img标签使用
export function errorImg(e: any): void {
e.target.src = onerrorImg;
e.target.onerror = null;
}
// 图片加载失败显示自定义默认图片(缺省图) NImage组件使用
export function fallbackSrc(): string {
return onerrorImg;
}
export function timeFix() {
const time = new Date();
const hour = time.getHours();
@@ -144,8 +162,8 @@ export function convertListToTree(list: any[], idField = 'id', pidField = 'pid')
// 从树选项中获取所有key
export function getTreeKeys(data: any[], idField = 'id') {
const keys = [];
data.map((item) => {
const keys: any = [];
data.map((item: any) => {
keys.push(item[idField]);
if (item.children && item.children.length) {
keys.push(...getTreeKeys(item.children));

View File

@@ -13,9 +13,10 @@ import {
} from 'naive-ui';
import { EllipsisHorizontalCircleOutline } from '@vicons/ionicons5';
import { PageEnum } from '@/enums/pageEnum';
import { isObject } from './is/index';
import { isNullObject, isObject } from './is/index';
import { cloneDeep } from 'lodash-es';
import { VNode } from '@vue/runtime-core';
import { VNode } from 'vue';
import { DictType, useDictStore } from '@/store/modules/dict';
export const renderTooltip = (trigger, content) => {
return h(NTooltip, null, {
@@ -73,6 +74,27 @@ export const renderTag: SelectRenderTag = ({ option }) => {
);
};
// renderOptionTag 选项标签
export const renderOptionTag = (type: DictType, value: any) => {
if (isNullObject(value)) {
return ``;
}
const dict = useDictStore();
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: dict.getType(type, value),
bordered: false,
},
{
default: () => dict.getLabel(type, value),
}
);
};
export interface MemberSumma {
id: number; // 用户ID
realName: string; // 真实姓名
@@ -329,7 +351,7 @@ export function lighten(color: string, amount: number) {
// 获取树的所有节点key
export function getAllExpandKeys(treeData: any): any[] {
let expandedKeys = [];
let expandedKeys: any = [];
const expandKeys = (items: any[]) => {
items.forEach((item: any) => {
expandedKeys.push(item.key);
@@ -347,7 +369,7 @@ export function getAllExpandKeys(treeData: any): any[] {
}
// 从树中查找指定节点
export function findTreeNode(data: any[], key?: string | number, keyField = 'key'): any {
export function findTreeNode(data: any, key?: string | number, keyField = 'key'): any {
for (const item of data) {
if (item[keyField] == key) {
return item;

View File

@@ -1,3 +1,6 @@
import { RouteLocationRaw } from 'vue-router';
import router from '@/router';
/**
* 将对象添加当作参数拼接到URL上面
* @param baseUrl 需要拼接的url
@@ -49,3 +52,14 @@ export function getNowUrl(): string {
const w = window.location;
return w.protocol + '//' + w.host + w.pathname;
}
// 返回上一页
export function goBackOrToPage(to: RouteLocationRaw): void {
if (router.currentRoute.value.matched.length > 0) {
router.go(-1);
} else {
router.push(to).catch((e) => {
console.log('返回上一页失败:', e);
});
}
}

View File

@@ -3,7 +3,8 @@ import { FormItemRule } from 'naive-ui';
* @description 表单验证封装
*/
export const validate = {
ip(rule: FormItemRule, value: any, callback: Function) {
// 验证ipv4
ip(rule: FormItemRule, value: any, callback: Function): boolean | Error {
// 支持通配符的ipv4正则
const ipv4Regex =
/^(?:[1-9]?[0-9]|1[0-9]{2}|2(?:[0-4][0-9]|5[0-5]))(?!.*?\.\*\.[*\d])(?:\.(?:(?:[1-9]?[0-9]|1[0-9]{2}|2(?:[0-4][0-9]|5[0-5]))|\*)){1,3}$/;
@@ -20,9 +21,10 @@ export const validate = {
} else {
callback();
}
return true;
},
//0-100百分比验证
percentage(rule: FormItemRule, value: any, callback: Function) {
percentage(rule: FormItemRule, value: any, callback: Function): boolean | Error {
const reg = /^([1-9]{1,2}$)|(^[0-9]{1,2}\.[0-9]{1,2}$)|100$/;
if (!value && !rule.required) {
callback(new Error('请输入比例'));
@@ -31,9 +33,10 @@ export const validate = {
} else {
callback();
}
return true;
},
// 手机号 eg:138********,159********
phone(rule: FormItemRule, value: any, callback: Function) {
phone(rule: FormItemRule, value: any, callback: Function): boolean | Error {
const regPhone = /^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/;
if (!value && !rule.required) {
callback();
@@ -44,9 +47,10 @@ export const validate = {
} else {
callback();
}
return true;
},
// 用户名 eg:a123456
userName(rule: FormItemRule, value: any, callback: Function) {
userName(rule: FormItemRule, value: any, callback: Function): boolean | Error {
const regUserName = /^[0-9a-zA-Z]{6,16}$/;
if (!value && !rule.required) {
callback(new Error('请输入登录账号'));
@@ -55,9 +59,10 @@ export const validate = {
} else {
callback();
}
return true;
},
// 账号
account(rule: FormItemRule, value: any, callback: Function) {
account(rule: FormItemRule, value: any, callback: Function): boolean | Error {
const regex = /^[\w_\d]{6,16}$/;
if (!value && !rule.required) {
callback();
@@ -68,9 +73,10 @@ export const validate = {
} else {
callback();
}
return true;
},
// 密码
password(rule: FormItemRule, value: any, callback: Function) {
password(rule: FormItemRule, value: any, callback: Function): boolean | Error {
const regPassword = /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,18}$/;
if (!value && !rule.required) {
callback(new Error('请输入密码'));
@@ -79,9 +85,10 @@ export const validate = {
} else {
callback();
}
return true;
},
// 邮箱
email(rule: FormItemRule, value: any, callback: Function) {
email(rule: FormItemRule, value: any, callback: Function): boolean | Error {
const regEmails = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
// console.log('isRequired is: ', JSON.stringify(isRequired))
if (!value && !rule.required) {
@@ -93,9 +100,10 @@ export const validate = {
} else {
callback();
}
return true;
},
// 金额验证
amount(rule: FormItemRule, value: any, callback: Function) {
amount(rule: FormItemRule, value: any, callback: Function): boolean | Error {
const regAmount = /(^[0-9]{1,10}$)|(^[0-9]{1,10}[\.]{1}[0-9]{1,2}$)/;
if (!value && !rule.required) {
callback();
@@ -106,9 +114,10 @@ export const validate = {
} else {
callback();
}
return true;
},
// 身份证验证
idCard(rule: FormItemRule, value: any, callback: Function, isEnabled = true) {
idCard(rule: FormItemRule, value: any, callback: Function, isEnabled = true): boolean | Error {
const regIdCard =
/^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X|x)$/;
if (!isEnabled) {
@@ -122,9 +131,10 @@ export const validate = {
} else {
callback();
}
return true;
},
// 银行卡验证
bank(rule: FormItemRule, value: any, callback: Function) {
bank(rule: FormItemRule, value: any, callback: Function): boolean | Error {
const regBank = /^([1-9]{1})(\d{15}|\d{16}|\d{18})$/;
if (!value && !rule.required) {
callback();
@@ -135,9 +145,10 @@ export const validate = {
} else {
callback();
}
return true;
},
// 非零正整数验证
num(rule: FormItemRule, value: any, callback: Function) {
num(rule: FormItemRule, value: any, callback: Function): boolean | Error {
const reg = /^\+?[1-9][0-9]*$/;
if (!value && !rule.required) {
callback(new Error('请填写非零正整数'));
@@ -148,9 +159,10 @@ export const validate = {
callback();
}
}
return true;
},
// 银行卡
bankCard(rule: FormItemRule, value: any, callback: Function) {
bankCard(rule: FormItemRule, value: any, callback: Function): boolean | Error {
const regBankCard = /^(\d{16}|\d{19})$/;
if (value == '' && !rule.required) {
callback(new Error('请输入银行卡号'));
@@ -161,9 +173,10 @@ export const validate = {
callback();
}
}
return true;
},
// 固话格式
tel(rule: FormItemRule, value: any, callback: Function) {
tel(rule: FormItemRule, value: any, callback: Function): boolean | Error {
const regTel = /^(0\d{2,3}-?)?\d{7,8}$/;
if (value == '' && !rule.required) {
callback(new Error('请输入座机号码'));
@@ -174,9 +187,10 @@ export const validate = {
callback();
}
}
return true;
},
// QQ号码
qq(rule: FormItemRule, value: any, callback: Function) {
qq(rule: FormItemRule, value: any, callback: Function): boolean | Error {
const regex = /^[1-9][0-9]{4,}$/;
if (!value && !rule.required) {
callback();
@@ -189,9 +203,10 @@ export const validate = {
callback();
}
}
return true;
},
// weibo号
weibo(rule: FormItemRule, value: any, callback: Function) {
weibo(rule: FormItemRule, value: any, callback: Function): boolean | Error {
const regex = /^[0-9a-zA-Z\u4e00-\u9fa5_-]*$/;
if (!value && !rule.required) {
callback();
@@ -204,9 +219,11 @@ export const validate = {
callback();
}
}
return true;
},
// 不验证
none(_rule: FormItemRule, _value: any, callback: Function) {
none(_rule: FormItemRule, _value: any, callback: Function): boolean {
callback();
return true;
},
};

View File

@@ -29,7 +29,7 @@
<n-checkbox-group v-model:value="params.flag">
<n-space>
<n-checkbox
v-for="item in options.sys_notice_type"
v-for="item in dict.getOptionUnRef('sys_notice_type')"
:key="item.value"
:value="item.value"
:label="item.label"
@@ -96,7 +96,10 @@
</n-form-item>
<n-form-item label="用户渠道" path="channel">
<n-select v-model:value="params.channel" :options="options.sys_user_channel" />
<n-select
v-model:value="params.channel"
:options="dict.getOptionUnRef('sys_user_channel')"
/>
</n-form-item>
<n-form-item label="所在城市" path="cityId">
@@ -104,7 +107,11 @@
</n-form-item>
<n-form-item label="用户爱好" path="hobby">
<n-select multiple v-model:value="params.hobby" :options="options.sys_user_hobby" />
<n-select
multiple
v-model:value="params.hobby"
:options="dict.getOptionUnRef('sys_user_hobby')"
/>
</n-form-item>
<n-form-item label="QQ" path="qq">
@@ -126,7 +133,7 @@
<n-form-item label="状态" path="status">
<n-radio-group v-model:value="params.status" name="status">
<n-radio-button
v-for="status in options.sys_normal_disable"
v-for="status in dict.getOptionUnRef('sys_normal_disable')"
:key="Number(status.value)"
:value="Number(status.value)"
:label="status.label"
@@ -151,7 +158,7 @@
<script lang="ts" setup>
import { ref, computed, watch } from 'vue';
import { rules, options, State, newState } from './model';
import { rules, State, newState } from './model';
import { Edit, MaxSort } from '@/api/addons/hgexample/table';
import { useMessage } from 'naive-ui';
import { adaModalWidth } from '@/utils/hotgo';
@@ -161,6 +168,7 @@
import UploadFile from '@/components/Upload/uploadFile.vue';
import CitySelector from '@/components/CitySelector/citySelector.vue';
import FileChooser from '@/components/FileChooser/index.vue';
import { useDictStore } from '@/store/modules/dict';
const emit = defineEmits(['reloadTable', 'updateShowModal']);
interface Props {
@@ -188,6 +196,7 @@
return props.formParams;
});
const dict = useDictStore();
const message = useMessage();
const formRef = ref<any>({});
const formBtnLoading = ref(false);

View File

@@ -66,8 +66,8 @@
</BasicTable>
</n-card>
<Edit
@reloadTable="reloadTable"
@updateShowModal="updateShowModal"
@reload-table="reloadTable"
@update-show-modal="updateShowModal"
:showModal="showModal"
:formParams="formParams"
/>
@@ -75,18 +75,20 @@
</template>
<script lang="ts" setup>
import { computed, h, reactive, ref } from 'vue';
import { computed, h, onMounted, reactive, ref } from 'vue';
import { useDialog, useMessage } from 'naive-ui';
import { BasicTable, TableAction } from '@/components/Table';
import { BasicForm, useForm } from '@/components/Form/index';
import { useSorter } from '@/hooks/common';
import { Delete, List, Status, Export } from '@/api/addons/hgexample/table';
import { State, columns, schemas, options, newState } from './model';
import { State, columns, schemas, newState, loadOptions } from './model';
import { DeleteOutlined, PlusOutlined, ExportOutlined } from '@vicons/antd';
import { useRouter } from 'vue-router';
import { adaTableScrollX, getOptionLabel } from '@/utils/hotgo';
import { adaTableScrollX } from '@/utils/hotgo';
import Edit from './edit.vue';
import { useDictStore } from '@/store/modules/dict';
const dict = useDictStore();
const router = useRouter();
const dialog = useDialog();
const message = useMessage();
@@ -218,9 +220,6 @@
reloadTable();
});
},
onNegativeClick: () => {
// message.error('取消');
},
});
}
@@ -238,9 +237,6 @@
reloadTable();
});
},
onNegativeClick: () => {
// message.error('取消');
},
});
}
@@ -251,12 +247,16 @@
function handleStatus(record: Recordable, status: number) {
Status({ id: record.id, status: status }).then((_res) => {
message.success('设为' + getOptionLabel(options.value.sys_normal_disable, status) + '成功');
message.success('设为' + dict.getLabel('sys_normal_disable', status) + '成功');
setTimeout(() => {
reloadTable();
});
});
}
onMounted(() => {
loadOptions();
});
</script>
<style lang="less" scoped></style>

View File

@@ -2,14 +2,19 @@ import { h, ref } from 'vue';
import { NAvatar, NImage, NTag, NSwitch, NRate } from 'naive-ui';
import { cloneDeep } from 'lodash-es';
import { FormSchema } from '@/components/Form';
import { Dicts } from '@/api/dict/dict';
import { Switch } from '@/api/addons/hgexample/table';
import { isNullObject } from '@/utils/is';
import { getFileExt } from '@/utils/urlUtils';
import { defRangeShortcuts, defShortcuts, formatToDate } from '@/utils/dateUtil';
import { validate } from '@/utils/validateUtil';
import { errorImg, getOptionLabel, getOptionTag, Options } from '@/utils/hotgo';
import { fallbackSrc } from '@/utils/hotgo';
import { useDictStore } from '@/store/modules/dict';
import { renderOptionTag } from '@/utils';
import type { FormRules } from 'naive-ui/es/form/src/interface';
const dict = useDictStore();
const $message = window['$message'];
export interface State {
id: number;
memberId: number;
@@ -95,16 +100,7 @@ export function newState(state: State | null): State {
return cloneDeep(defaultState);
}
export const options = ref<Options>({
sys_normal_disable: [],
sys_user_sex: [],
sys_notice_type: [],
sys_user_channel: [],
sys_user_hobby: [],
sys_switch: [],
});
export const rules = {
export const rules: FormRules = {
title: {
required: true,
trigger: ['blur', 'input'],
@@ -207,7 +203,7 @@ export const schemas = ref<FormSchema[]>([
},
componentProps: {
placeholder: '请选择标签',
options: [],
options: dict.getOption('sys_notice_type'),
onUpdateChecked: (e: any) => {
console.log(e);
},
@@ -221,7 +217,7 @@ export const schemas = ref<FormSchema[]>([
//span: 24,
},
componentProps: {
options: [],
options: dict.getOption('sys_switch'),
onUpdateChecked: (e: any) => {
console.log(e);
},
@@ -235,7 +231,7 @@ export const schemas = ref<FormSchema[]>([
componentProps: {
multiple: true,
placeholder: '请选择爱好',
options: [],
options: dict.getOption('sys_user_hobby'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -248,7 +244,7 @@ export const schemas = ref<FormSchema[]>([
defaultValue: null,
componentProps: {
placeholder: '请选择类型',
options: [],
options: dict.getOption('sys_normal_disable'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -280,19 +276,7 @@ export const columns = [
return ``;
}
return row.flag.map((tagKey) => {
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.sys_notice_type, tagKey),
bordered: false,
},
{
default: () => getOptionLabel(options.value.sys_notice_type, tagKey),
}
);
return renderOptionTag('sys_notice_type', tagKey);
});
},
},
@@ -304,7 +288,7 @@ export const columns = [
width: 32,
height: 32,
src: row.image,
fallbackSrc: errorImg,
fallbackSrc: fallbackSrc(),
style: {
width: '32px',
height: '32px',
@@ -326,7 +310,7 @@ export const columns = [
width: 32,
height: 32,
src: image,
fallbackSrc: errorImg,
fallbackSrc: fallbackSrc(),
style: {
width: '32px',
height: '32px',
@@ -443,22 +427,7 @@ export const columns = [
title: '状态',
key: 'status',
render(row) {
if (isNullObject(row.status)) {
return ``;
}
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.sys_normal_disable, row.status),
bordered: false,
},
{
default: () => getOptionLabel(options.value.sys_normal_disable, row.status),
}
);
return renderOptionTag('sys_normal_disable', row.status);
},
},
{
@@ -469,19 +438,7 @@ export const columns = [
return ``;
}
return row.hobby.map((tagKey) => {
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.sys_user_hobby, tagKey),
bordered: false,
},
{
default: () => getOptionLabel(options.value.sys_user_hobby, tagKey),
}
);
return renderOptionTag('sys_user_hobby', tagKey);
});
},
},
@@ -497,33 +454,13 @@ export const columns = [
},
];
async function loadOptions() {
options.value = await Dicts({
types: [
'sys_normal_disable',
'sys_user_sex',
'sys_notice_type',
'sys_switch',
'sys_user_hobby',
'sys_user_channel',
],
});
for (const item of schemas.value) {
switch (item.field) {
case 'status':
item.componentProps.options = options.value.sys_normal_disable;
break;
case 'flag':
item.componentProps.options = options.value.sys_notice_type;
break;
case 'switch':
item.componentProps.options = options.value.sys_switch;
break;
case 'hobby':
item.componentProps.options = options.value.sys_user_hobby;
break;
}
}
export function loadOptions() {
dict.loadOptions([
'sys_normal_disable',
'sys_user_sex',
'sys_notice_type',
'sys_switch',
'sys_user_hobby',
'sys_user_channel',
]);
}
await loadOptions();

View File

@@ -4,7 +4,7 @@
<n-card :bordered="false" title="基础详情"> 基础详情有时也用于显示只读信息 </n-card>
</div>
<n-card :bordered="false" class="proCard mt-4" size="small" :segmented="{ content: true }">
<n-descriptions label-placement="left" class="py-2" column="4">
<n-descriptions label-placement="left" class="py-2" :column="4">
<n-descriptions-item>
<template #label>分类ID</template>
{{ formValue.categoryId }}
@@ -13,10 +13,10 @@
<n-descriptions-item label="标签">
<template v-for="(item, key) in formValue?.flag" :key="key">
<n-tag
:type="getOptionTag(options.sys_notice_type, item)"
:type="dict.getType('sys_notice_type', item)"
size="small"
class="min-left-space"
>{{ getOptionLabel(options.sys_notice_type, item) }}</n-tag
>{{ dict.getLabel('sys_notice_type', item) }}</n-tag
>
</template>
</n-descriptions-item>
@@ -37,19 +37,19 @@
</n-card>
<n-card :bordered="false" class="proCard mt-4" size="small" :segmented="{ content: true }">
<n-descriptions label-placement="top" title="内容" class="py-2" column="1">
<n-descriptions label-placement="top" title="内容" class="py-2" :column="1">
<n-descriptions-item><span v-html="formValue.content"></span></n-descriptions-item>
</n-descriptions>
</n-card>
<n-card :bordered="false" class="proCard mt-4" size="small" :segmented="{ content: true }">
<n-descriptions label-placement="top" title="单图" class="py-2" column="1">
<n-descriptions label-placement="top" title="单图" class="py-2" :column="1">
<n-descriptions-item>
<n-image style="margin-left: 10px; height: 100px; width: 100px" :src="formValue.image"
/></n-descriptions-item>
</n-descriptions>
<n-descriptions label-placement="top" title="多图" class="py-2" column="1">
<n-descriptions label-placement="top" title="多图" class="py-2" :column="1">
<n-descriptions-item>
<n-image-group>
<n-space>
@@ -61,7 +61,7 @@
</n-descriptions-item>
</n-descriptions>
<n-descriptions label-placement="top" title="附件" class="py-2" column="1">
<n-descriptions label-placement="top" title="附件" class="py-2" :column="1">
<n-descriptions-item>
<div
class="upload-card"
@@ -79,7 +79,7 @@
</n-descriptions-item>
</n-descriptions>
<n-descriptions label-placement="top" title="多附件" class="py-2" column="1">
<n-descriptions label-placement="top" title="多附件" class="py-2" :column="1">
<n-descriptions-item>
<div class="upload-card">
<n-space style="gap: 0px 0px">
@@ -110,10 +110,11 @@
import { useRouter } from 'vue-router';
import { useMessage } from 'naive-ui';
import { View } from '@/api/addons/hgexample/table';
import { newState, options } from './model';
import { getOptionLabel, getOptionTag } from '@/utils/hotgo';
import { newState } from './model';
import { getFileExt } from '@/utils/urlUtils';
import { useDictStore } from '@/store/modules/dict';
const dict = useDictStore();
const message = useMessage();
const router = useRouter();
const id = Number(router.currentRoute.value.params.id);

View File

@@ -71,7 +71,10 @@
</n-gi>
<n-gi span="1">
<n-form-item label="支付状态" path="status">
<n-select v-model:value="formValue.status" :options="options.payStatus" />
<n-select
v-model:value="formValue.status"
:options="dict.getOptionUnRef('payStatus')"
/>
</n-form-item>
</n-gi>
</n-grid>
@@ -91,13 +94,15 @@
<script lang="ts" setup>
import { ref, computed } from 'vue';
import { Edit, View } from '@/api/addons/hgexample/tenantOrder';
import { options, State, newState, rules } from './model';
import { State, newState, rules } from './model';
import { useProjectSettingStore } from '@/store/modules/projectSetting';
import { useMessage } from 'naive-ui';
import { adaModalWidth } from '@/utils/hotgo';
import { useUserStore } from '@/store/modules/user';
import { useDictStore } from '@/store/modules/dict';
const emit = defineEmits(['reloadTable']);
const dict = useDictStore();
const message = useMessage();
const settingStore = useProjectSettingStore();
const userStore = useUserStore();

View File

@@ -1,13 +1,13 @@
import { h, ref } from 'vue';
import { NTag } from 'naive-ui';
import { ref } from 'vue';
import { cloneDeep } from 'lodash-es';
import { FormSchema } from '@/components/Form';
import { Dicts } from '@/api/dict/dict';
import { isNullObject } from '@/utils/is';
import { defRangeShortcuts } from '@/utils/dateUtil';
import { Option, getOptionLabel, getOptionTag } from '@/utils/hotgo';
import { useUserStore } from '@/store/modules/user';
import { useDictStore } from '@/store/modules/dict';
import { renderOptionTag } from '@/utils';
import type { FormRules } from 'naive-ui/es/form/src/interface';
const dict = useDictStore();
const userStore = useUserStore();
export class State {
@@ -41,7 +41,7 @@ export function newState(state: State | Record<string, any> | null): State {
}
// 表单验证规则
export const rules = {
export const rules: FormRules = {
money: {
required: true,
trigger: ['blur', 'input'],
@@ -195,22 +195,7 @@ export const columns = [
align: 'left',
width: 100,
render(row) {
if (isNullObject(row.status)) {
return ``;
}
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.payStatus, row.status),
bordered: false,
},
{
default: () => getOptionLabel(options.value.payStatus, row.status),
}
);
return renderOptionTag('payStatus', row.status);
},
},
{
@@ -221,23 +206,7 @@ export const columns = [
},
];
// 字典数据选项
export const options = ref({
payStatus: [] as Option[],
});
// 加载字典数据选项
export function loadOptions() {
Dicts({
types: ['payStatus'],
}).then((res) => {
options.value = res;
for (const item of schemas.value) {
switch (item.field) {
case 'status':
item.componentProps.options = options.value.payStatus;
break;
}
}
});
dict.loadOptions(['payStatus']);
}

View File

@@ -37,7 +37,7 @@
<n-checkbox-group v-model:value="params.flag">
<n-space>
<n-checkbox
v-for="item in options.sys_notice_type"
v-for="item in dict.getOptionUnRef('sys_notice_type')"
:key="item.value"
:value="item.value"
:label="item.label"
@@ -104,7 +104,10 @@
</n-form-item>
<n-form-item label="用户渠道" path="channel">
<n-select v-model:value="params.channel" :options="options.sys_user_channel" />
<n-select
v-model:value="params.channel"
:options="dict.getOptionUnRef('sys_user_channel')"
/>
</n-form-item>
<n-form-item label="所在城市" path="cityId">
@@ -112,7 +115,11 @@
</n-form-item>
<n-form-item label="用户爱好" path="hobby">
<n-select multiple v-model:value="params.hobby" :options="options.sys_user_hobby" />
<n-select
multiple
v-model:value="params.hobby"
:options="dict.getOptionUnRef('sys_user_hobby')"
/>
</n-form-item>
<n-form-item label="QQ" path="qq">
@@ -134,7 +141,7 @@
<n-form-item label="状态" path="status">
<n-radio-group v-model:value="params.status" name="status">
<n-radio-button
v-for="status in options.sys_normal_disable"
v-for="status in dict.getOptionUnRef('sys_normal_disable')"
:key="Number(status.value)"
:value="Number(status.value)"
:label="status.label"
@@ -158,8 +165,8 @@
</template>
<script lang="ts" setup>
import { onMounted, ref, computed, watch } from 'vue';
import { rules, options, State, newState } from './model';
import { ref, computed, watch } from 'vue';
import { rules, State, newState } from './model';
import { Edit, MaxSort } from '@/api/addons/hgexample/treeTable';
import { useMessage } from 'naive-ui';
import { adaModalWidth } from '@/utils/hotgo';
@@ -169,6 +176,7 @@
import UploadFile from '@/components/Upload/uploadFile.vue';
import CitySelector from '@/components/CitySelector/citySelector.vue';
import FileChooser from '@/components/FileChooser/index.vue';
import { useDictStore } from '@/store/modules/dict';
const emit = defineEmits(['reloadTable', 'updateShowModal']);
interface Props {
@@ -198,6 +206,7 @@
return props.formParams;
});
const dict = useDictStore();
const message = useMessage();
const formRef = ref<any>({});
const formBtnLoading = ref(false);

View File

@@ -22,7 +22,7 @@
type="info"
icon-placement="left"
@click="openEditDrawer"
:disabled="formParams?.id === null || formParams?.id <= 0"
:disabled="!formParams?.id || formParams?.id < 1"
>
<template #icon>
<div class="flex items-center">
@@ -104,15 +104,15 @@
<List
:checkedId="checkedId"
:optionTreeData="optionTreeData"
@reloadTable="reloadTable"
@reload-table="reloadTable"
/>
</n-card>
</n-gi>
</n-grid>
<Edit
@reloadTable="reloadTable"
@updateShowModal="updateShowModal"
@reload-table="reloadTable"
@update-show-modal="updateShowModal"
:showModal="showModal"
:formParams="formParams"
:optionTreeData="optionTreeData"
@@ -133,7 +133,7 @@
import List from './list.vue';
import { Delete, Select } from '@/api/addons/hgexample/treeTable';
import Edit from './edit.vue';
import { newState } from './model';
import { newState, loadOptions } from './model';
const showModal = ref(false);
const message = useMessage();
@@ -228,4 +228,8 @@
function updateShowModal(value) {
showModal.value = value;
}
onMounted(() => {
loadOptions();
});
</script>

View File

@@ -71,8 +71,8 @@
</n-card>
<Edit
@reloadTable="reloadTable"
@updateShowModal="updateShowModal"
@reload-table="reloadTable"
@update-show-modal="updateShowModal"
:showModal="showModal"
:formParams="formParams"
:optionTreeData="optionTreeData"
@@ -87,10 +87,11 @@
import { BasicForm, useForm } from '@/components/Form/index';
import { useSorter } from '@/hooks/common';
import { Delete, List, Status, Export } from '@/api/addons/hgexample/treeTable';
import { State, columns, schemas, options, newState } from './model';
import { State, columns, schemas, newState } from './model';
import { DeleteOutlined, PlusOutlined, ExportOutlined } from '@vicons/antd';
import { adaTableScrollX, getOptionLabel } from '@/utils/hotgo';
import { adaTableScrollX } from '@/utils/hotgo';
import Edit from './edit.vue';
import { useDictStore } from '@/store/modules/dict';
interface Props {
checkedId?: number;
@@ -99,6 +100,7 @@
const props = withDefaults(defineProps<Props>(), { checkedId: 0, optionTreeData: [] });
const emit = defineEmits(['reloadTable']);
const dict = useDictStore();
const dialog = useDialog();
const message = useMessage();
const searchFormRef = ref<any>();
@@ -232,7 +234,7 @@
function handleStatus(record: Recordable, status: number) {
Status({ id: record.id, status: status }).then((_res) => {
message.success('设为' + getOptionLabel(options.value.sys_normal_disable, status) + '成功');
message.success('设为' + dict.getLabel('sys_normal_disable', status) + '成功');
setTimeout(() => {
reloadTable();
});

View File

@@ -2,14 +2,18 @@ import { h, ref } from 'vue';
import { NAvatar, NImage, NTag, NSwitch, NRate } from 'naive-ui';
import { cloneDeep } from 'lodash-es';
import { FormSchema } from '@/components/Form';
import { Dicts } from '@/api/dict/dict';
import { Switch } from '@/api/addons/hgexample/table';
import { isNullObject } from '@/utils/is';
import { getFileExt } from '@/utils/urlUtils';
import { defRangeShortcuts, defShortcuts, formatToDate } from '@/utils/dateUtil';
import { validate } from '@/utils/validateUtil';
import { errorImg, getOptionLabel, getOptionTag, Options } from '@/utils/hotgo';
import { fallbackSrc } from '@/utils/hotgo';
import { useDictStore } from '@/store/modules/dict';
import { renderOptionTag } from '@/utils';
const dict = useDictStore();
const $message = window['$message'];
export interface State {
id: number;
memberId: number;
@@ -21,7 +25,7 @@ export interface State {
images: string[] | null;
attachfile: string;
attachfiles: string[] | null;
map: unknown[] | null;
map: any | null;
star: number;
description: string;
price: number;
@@ -95,15 +99,6 @@ export function newState(state: State | null): State {
return cloneDeep(defaultState);
}
export const options = ref<Options>({
sys_normal_disable: [],
sys_user_sex: [],
sys_notice_type: [],
sys_user_channel: [],
sys_user_hobby: [],
sys_switch: [],
});
export const rules = {
title: {
required: true,
@@ -207,7 +202,7 @@ export const schemas = ref<FormSchema[]>([
},
componentProps: {
placeholder: '请选择标签',
options: [],
options: dict.getOption('sys_notice_type'),
onUpdateChecked: (e: any) => {
console.log(e);
},
@@ -221,7 +216,7 @@ export const schemas = ref<FormSchema[]>([
//span: 24,
},
componentProps: {
options: [],
options: dict.getOption('sys_switch'),
onUpdateChecked: (e: any) => {
console.log(e);
},
@@ -235,7 +230,7 @@ export const schemas = ref<FormSchema[]>([
componentProps: {
multiple: true,
placeholder: '请选择爱好',
options: [],
options: dict.getOption('sys_user_hobby'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -248,7 +243,7 @@ export const schemas = ref<FormSchema[]>([
defaultValue: null,
componentProps: {
placeholder: '请选择类型',
options: [],
options: dict.getOption('sys_normal_disable'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -280,19 +275,7 @@ export const columns = [
return ``;
}
return row.flag.map((tagKey) => {
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.sys_notice_type, tagKey),
bordered: false,
},
{
default: () => getOptionLabel(options.value.sys_notice_type, tagKey),
}
);
return renderOptionTag('sys_notice_type', tagKey);
});
},
},
@@ -304,7 +287,7 @@ export const columns = [
width: 32,
height: 32,
src: row.image,
fallbackSrc: errorImg,
fallbackSrc: fallbackSrc(),
style: {
width: '32px',
height: '32px',
@@ -326,7 +309,7 @@ export const columns = [
width: 32,
height: 32,
src: image,
fallbackSrc: errorImg,
fallbackSrc: fallbackSrc(),
style: {
width: '32px',
height: '32px',
@@ -443,46 +426,14 @@ export const columns = [
title: '状态',
key: 'status',
render(row) {
if (isNullObject(row.status)) {
return ``;
}
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.sys_normal_disable, row.status),
bordered: false,
},
{
default: () => getOptionLabel(options.value.sys_normal_disable, row.status),
}
);
return renderOptionTag('sys_normal_disable', row.status);
},
},
{
title: '爱好',
key: 'hobby',
render(row) {
if (isNullObject(row.hobby)) {
return ``;
}
return row.hobby.map((tagKey) => {
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.sys_user_hobby, tagKey),
bordered: false,
},
{
default: () => getOptionLabel(options.value.sys_user_hobby, tagKey),
}
);
});
return renderOptionTag('sys_user_hobby', row.hobby);
},
},
{
@@ -497,33 +448,13 @@ export const columns = [
},
];
async function loadOptions() {
options.value = await Dicts({
types: [
'sys_normal_disable',
'sys_user_sex',
'sys_notice_type',
'sys_switch',
'sys_user_hobby',
'sys_user_channel',
],
});
for (const item of schemas.value) {
switch (item.field) {
case 'status':
item.componentProps.options = options.value.sys_normal_disable;
break;
case 'flag':
item.componentProps.options = options.value.sys_notice_type;
break;
case 'switch':
item.componentProps.options = options.value.sys_switch;
break;
case 'hobby':
item.componentProps.options = options.value.sys_user_hobby;
break;
}
}
export function loadOptions() {
dict.loadOptions([
'sys_normal_disable',
'sys_user_sex',
'sys_notice_type',
'sys_switch',
'sys_user_hobby',
'sys_user_channel',
]);
}
await loadOptions();

View File

@@ -1,15 +1,13 @@
import { h, ref } from 'vue';
import { NAvatar, NImage, NTag } from 'naive-ui';
import { NAvatar, NImage } from 'naive-ui';
import { getFileExt } from '@/utils/urlUtils';
import { getOptionLabel, getOptionTag, Options } from '@/utils/hotgo';
import { FormSchema } from '@/components/Form';
import { errorImg } from '@/utils/hotgo';
import { fallbackSrc } from '@/utils/hotgo';
import { defRangeShortcuts } from '@/utils/dateUtil';
import { ChooserOption } from '@/api/apply/attachment';
export const options = ref<Options>({
kind: [],
drive: [],
});
import { useDictStore } from '@/store/modules/dict';
import { renderOptionTag } from '@/utils';
const dict = useDictStore();
export const schemas = ref<FormSchema[]>([
{
@@ -19,7 +17,7 @@ export const schemas = ref<FormSchema[]>([
defaultValue: null,
componentProps: {
placeholder: '请选择上传驱动',
options: [],
options: dict.getOption('config_upload_drive'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -32,7 +30,7 @@ export const schemas = ref<FormSchema[]>([
defaultValue: null,
componentProps: {
placeholder: '请选择上传类型',
options: [],
options: dict.getOption('AttachmentKindOption'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -89,11 +87,6 @@ export const columns = [
key: 'appId',
width: 100,
},
// {
// title: '用户ID',
// key: 'memberId',
// width: 100,
// },
{
title: '驱动',
key: 'drive',
@@ -106,19 +99,7 @@ export const columns = [
title: '上传类型',
key: 'kind',
render(row) {
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.kind, row.kind),
bordered: false,
},
{
default: () => getOptionLabel(options.value.kind, row.kind),
}
);
return renderOptionTag('AttachmentKindOption', row.kind);
},
width: 120,
},
@@ -153,7 +134,7 @@ export const columns = [
width: 40,
height: 40,
src: row.fileUrl,
fallbackSrc: errorImg,
fallbackSrc: fallbackSrc(),
style: {
width: '40px',
height: '40px',
@@ -185,18 +166,6 @@ export const columns = [
},
];
async function loadOptions() {
options.value = await ChooserOption();
for (const item of schemas.value) {
switch (item.field) {
case 'kind':
item.componentProps.options = options.value.kind;
break;
case 'drive':
item.componentProps.options = options.value.drive;
break;
}
}
export function loadOptions() {
dict.loadOptions(['AttachmentKindOption', 'config_upload_drive']);
}
await loadOptions();

View File

@@ -72,17 +72,17 @@
<FileUpload ref="fileUploadRef" :finish-call="handleFinishCall" />
<FileUpload ref="imageUploadRef" :finish-call="handleFinishCall" upload-type="image" />
<FileUpload ref="docUploadRef" :finish-call="handleFinishCall" upload-type="doc" />
<MultipartUpload ref="multipartUploadRef" @onFinish="handleFinishCall" />
<MultipartUpload ref="multipartUploadRef" @on-finish="handleFinishCall" />
</div>
</template>
<script lang="ts" setup>
import { h, reactive, ref } from 'vue';
import { h, onMounted, reactive, ref } from 'vue';
import { useDialog, useMessage } from 'naive-ui';
import { BasicTable, TableAction } from '@/components/Table';
import { BasicForm, useForm } from '@/components/Form/index';
import { Delete, List } from '@/api/apply/attachment';
import { columns, schemas } from './columns';
import { columns, schemas, loadOptions } from './columns';
import {
DeleteOutlined,
UploadOutlined,
@@ -179,9 +179,6 @@
reloadTable();
});
},
onNegativeClick: () => {
// message.error('取消');
},
});
}
@@ -197,9 +194,6 @@
reloadTable();
});
},
onNegativeClick: () => {
// message.error('取消');
},
});
}
@@ -216,6 +210,10 @@
reloadTable();
}
}
onMounted(async () => {
loadOptions();
});
</script>
<style lang="less" scoped></style>

View File

@@ -1,8 +1,9 @@
import { h } from 'vue';
import { NAvatar, NAvatarGroup, NTag, NTooltip } from 'naive-ui';
import { noticeTagOptions, noticeTypeOptions } from '@/enums/systemMessageEnum';
import { getOptionLabel, getOptionTag } from '@/utils/hotgo';
import { NAvatar, NAvatarGroup, NTooltip } from 'naive-ui';
import { renderOptionTag } from '@/utils';
import { useDictStore } from '@/store/modules/dict';
const dict = useDictStore();
export const columns = [
{
title: 'ID',
@@ -25,19 +26,7 @@ export const columns = [
title: '消息类型',
key: 'type',
render(row) {
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(noticeTypeOptions, row.type),
bordered: false,
},
{
default: () => getOptionLabel(noticeTypeOptions, row.type),
}
);
return renderOptionTag('noticeTypeOptions', row.type);
},
width: 100,
},
@@ -45,19 +34,7 @@ export const columns = [
title: '标签',
key: 'tag',
render(row) {
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(noticeTagOptions, row.tag),
bordered: false,
},
{
default: () => getOptionLabel(noticeTagOptions, row.tag),
}
);
return renderOptionTag('noticeTagOptions', row.tag);
},
width: 100,
},
@@ -129,3 +106,7 @@ export const columns = [
width: 180,
},
];
export function loadOptions() {
dict.loadOptions(['sys_normal_disable']);
}

View File

@@ -97,8 +97,8 @@
preset="dialog"
:title="
formParams.id > 0
? '编辑' + getOptionLabel(noticeTypeOptions, formParams.type) + ' #' + formParams.id
: '发送' + getOptionLabel(noticeTypeOptions, formParams.type)
? '编辑' + dict.getLabel('noticeTypeOptions', formParams.type) + ' #' + formParams.id
: '发送' + dict.getLabel('noticeTypeOptions', formParams.type)
"
:style="{
width: dialogWidth,
@@ -152,7 +152,7 @@
placeholder="可以不填"
:render-tag="renderTag"
v-model:value="formParams.tag"
:options="noticeTagOptions"
:options="dict.getOptionUnRef('noticeTagOptions')"
/>
</n-form-item>
</n-gi>
@@ -208,23 +208,19 @@
MaxSort,
Status,
} from '@/api/apply/notice';
import { columns } from './columns';
import { columns, loadOptions } from './columns';
import { BellOutlined, DeleteOutlined, NotificationOutlined, SendOutlined } from '@vicons/antd';
import { statusOptions } from '@/enums/optionsiEnum';
import {
noticeTagOptions,
noticeTypeOptions,
personOption,
renderLabel,
renderMultipleSelectTag,
} from '@/enums/systemMessageEnum';
import { adaModalWidth, getOptionLabel } from '@/utils/hotgo';
import { personOption, renderLabel, renderMultipleSelectTag } from '@/enums/systemMessageEnum';
import { adaModalWidth } from '@/utils/hotgo';
import { renderTag } from '@/utils';
import Editor from '@/components/Editor/editor.vue';
import { cloneDeep } from 'lodash-es';
import { GetMemberOption } from '@/api/org/user';
import { usePermission } from '@/hooks/web/usePermission';
import { useDictStore } from '@/store/modules/dict';
const dict = useDictStore();
const rules = {
title: {
required: true,
@@ -241,7 +237,7 @@
defaultValue: null,
componentProps: {
placeholder: '请选择消息类型',
options: noticeTypeOptions,
options: dict.getOption('noticeTypeOptions'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -278,7 +274,7 @@
defaultValue: null,
componentProps: {
placeholder: '请选择类型',
options: statusOptions,
options: dict.getOption('sys_normal_disable'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -483,6 +479,7 @@
}
onMounted(async () => {
loadOptions();
await getMemberOption();
});
</script>

View File

@@ -59,7 +59,7 @@
<n-form-item label="状态" path="status">
<n-radio-group v-model:value="params.status" name="status">
<n-radio-button
v-for="status in options.sys_normal_disable"
v-for="status in dict.getOptionUnRef('sys_normal_disable')"
:key="Number(status.value)"
:value="Number(status.value)"
:label="status.label"
@@ -80,10 +80,11 @@
<script lang="ts" setup>
import { ref, computed, watch } from 'vue';
import { options, State, newState } from './model';
import { State, newState } from './model';
import { Edit, MaxSort, CheckProvincesUniqueId } from '@/api/apply/provinces';
import { FormItemRule, useMessage } from 'naive-ui';
import { adaModalWidth } from '@/utils/hotgo';
import { useDictStore } from '@/store/modules/dict';
const emit = defineEmits(['reloadTable', 'updateShowModal']);
interface Props {
@@ -138,6 +139,7 @@
},
};
const dict = useDictStore();
const message = useMessage();
const formRef = ref<any>({});
const formBtnLoading = ref(false);

View File

@@ -101,14 +101,14 @@
</n-space>
</template>
<List :checkedId="checkedId" :optionTreeData="optionTreeData" @reloadTable="loadData" />
<List :checkedId="checkedId" :optionTreeData="optionTreeData" @reload-table="loadData" />
</n-card>
</n-gi>
</n-grid>
<Edit
@reloadTable="loadData"
@updateShowModal="updateShowModal"
@reload-table="loadData"
@update-show-modal="updateShowModal"
:showModal="showModal"
:formParams="formParams"
:optionTreeData="optionTreeData"
@@ -130,7 +130,7 @@
import List from './list.vue';
import { getProvincesTree, Delete } from '@/api/apply/provinces';
import Edit from './edit.vue';
import { newState } from './model';
import { newState, loadOptions } from './model';
const isUpdate = ref(false);
const showModal = ref(false);
@@ -196,10 +196,6 @@
}
}
onMounted(async () => {
await loadData();
});
async function loadData() {
const treeMenuList = await getProvincesTree();
Object.assign(
@@ -228,4 +224,9 @@
function updateShowModal(value) {
showModal.value = value;
}
onMounted(async () => {
loadOptions();
await loadData();
});
</script>

View File

@@ -183,9 +183,6 @@
reloadTable();
});
},
onNegativeClick: () => {
// message.error('取消');
},
});
}

View File

@@ -1,9 +1,10 @@
import { h, ref } from 'vue';
import { h } from 'vue';
import { NTag } from 'naive-ui';
import { cloneDeep } from 'lodash-es';
import { getOptionLabel, getOptionTag, Options } from '@/utils/hotgo';
import { Dicts } from '@/api/dict/dict';
import { isNullObject } from '@/utils/is';
import { useDictStore } from '@/store/modules/dict';
import { renderOptionTag } from '@/utils';
const dict = useDictStore();
export const listColumns = [
{
@@ -45,22 +46,7 @@ export const listColumns = [
title: '状态',
key: 'status',
render(row) {
if (isNullObject(row.status)) {
return ``;
}
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.sys_normal_disable, row.status),
bordered: false,
},
{
default: () => getOptionLabel(options.value.sys_normal_disable, row.status),
}
);
return renderOptionTag('sys_normal_disable', row.status);
},
},
];
@@ -96,14 +82,6 @@ export function newState(state: State | null): State {
return cloneDeep(defaultState);
}
export const options = ref<Options>({
sys_normal_disable: [],
});
async function loadOptions() {
options.value = await Dicts({
types: ['sys_normal_disable'],
});
export function loadOptions() {
dict.loadOptions(['sys_normal_disable']);
}
await loadOptions();

View File

@@ -100,7 +100,6 @@
>
<n-form
:model="paymentParams"
:rules="rules"
ref="PaymentRef"
label-placement="left"
:label-width="100"
@@ -329,15 +328,14 @@
formBtnLoading.value = true;
formRef.value.validate((errors) => {
if (!errors) {
Apply({ money: formParams.value.money })
.then((_res) => {
message.success('操作成功');
setTimeout(() => {
showModal.value = false;
reloadTable();
formParams.value = ref(resetFormParams);
});
Apply({ money: formParams.value.money }).then((_res) => {
message.success('操作成功');
setTimeout(() => {
showModal.value = false;
reloadTable();
formParams.value = ref(resetFormParams);
});
});
} else {
message.error('请填写完整信息');
}
@@ -358,15 +356,14 @@
id: PaymentRef.value.model.id,
status: PaymentRef.value.model.status,
msg: PaymentRef.value.model.msg,
})
.then((_res) => {
message.success('操作成功');
setTimeout(() => {
showPaymentModal.value = false;
reloadTable();
PaymentRef.value = ref(resetPaymentParams);
});
}).then((_res) => {
message.success('操作成功');
setTimeout(() => {
showPaymentModal.value = false;
reloadTable();
PaymentRef.value = ref(resetPaymentParams);
});
});
} else {
message.error('请填写完整信息');
}

View File

@@ -26,19 +26,21 @@
import { onMounted, ref } from 'vue';
import List from './list.vue';
import { useRouter } from 'vue-router';
import { loadOptions } from './model';
const router = useRouter();
const defaultTab = ref('');
function handleBeforeLeave(tabName: string) {
defaultTab.value = tabName;
}
onMounted(() => {
if (router.currentRoute.value.query?.type) {
defaultTab.value = router.currentRoute.value.query.type as string;
}
loadOptions();
});
function handleBeforeLeave(tabName: string) {
defaultTab.value = tabName;
}
</script>
<style lang="less" scoped></style>

View File

@@ -1,62 +1,10 @@
import { h, ref } from 'vue';
import { NTag } from 'naive-ui';
import { cloneDeep } from 'lodash-es';
import { ref } from 'vue';
import { FormSchema } from '@/components/Form';
import { Option } from '@/api/creditsLog';
import { isNullObject } from '@/utils/is';
import { defRangeShortcuts } from '@/utils/dateUtil';
import { getOptionLabel, getOptionTag, Options } from '@/utils/hotgo';
import {Dicts} from "@/api/dict/dict";
import { useDictStore } from '@/store/modules/dict';
import { renderOptionTag } from '@/utils';
export interface State {
id: number;
memberId: number;
appId: string;
addonsName: string;
creditType: string;
creditGroup: string;
beforeNum: number;
num: number;
afterNum: number;
remark: string;
ip: string;
mapId: number;
status: number;
createdAt: string;
updatedAt: string;
}
export const defaultState = {
id: 0,
memberId: 0,
appId: '',
addonsName: '',
creditType: '',
creditGroup: '',
beforeNum: 0,
num: 0,
afterNum: 0,
remark: '',
ip: '',
mapId: 0,
status: 1,
createdAt: '',
updatedAt: '',
};
export function newState(state: State | null): State {
if (state !== null) {
return cloneDeep(state);
}
return cloneDeep(defaultState);
}
export const options = ref<Options>({
creditType: [],
creditGroup: [],
});
export const rules = {};
const dict = useDictStore();
export const schemas = ref<FormSchema[]>([
{
@@ -77,7 +25,7 @@ export const schemas = ref<FormSchema[]>([
defaultValue: null,
componentProps: {
placeholder: '请选择变动的组别',
options: [],
options: dict.getOption('creditGroup'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -146,22 +94,7 @@ export const columns = [
title: '变动类型',
key: 'creditType',
render(row) {
if (isNullObject(row.creditType)) {
return ``;
}
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.creditType, row.creditType),
bordered: false,
},
{
default: () => getOptionLabel(options.value.creditType, row.creditType),
}
);
return renderOptionTag('creditType', row.creditType);
},
width: 150,
},
@@ -169,22 +102,7 @@ export const columns = [
title: '组别',
key: 'creditGroup',
render(row) {
if (isNullObject(row.creditGroup)) {
return ``;
}
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.creditGroup, row.creditGroup),
bordered: false,
},
{
default: () => getOptionLabel(options.value.creditGroup, row.creditGroup),
}
);
return renderOptionTag('creditGroup', row.creditGroup);
},
width: 150,
},
@@ -240,20 +158,6 @@ export const columns = [
},
];
async function loadOptions() {
options.value = await Dicts({
types: ['creditType', 'creditGroup'],
});
for (const item of schemas.value) {
switch (item.field) {
case 'creditType':
item.componentProps.options = options.value.creditType;
break;
case 'creditGroup':
item.componentProps.options = options.value.creditGroup;
break;
}
}
export function loadOptions() {
dict.loadOptions(['creditType', 'creditGroup']);
}
await loadOptions();

View File

@@ -24,8 +24,6 @@
:request="loadDataTable"
:row-key="(row) => row.id"
ref="actionRef"
:actionColumn="actionColumn"
@update:checked-row-keys="onCheckedRow"
:scroll-x="1090"
:resizeHeightOffset="-10000"
size="small"
@@ -51,33 +49,19 @@
</template>
<script lang="ts" setup>
import { h, reactive, ref } from 'vue';
import { onMounted, ref } from 'vue';
import { useMessage } from 'naive-ui';
import { BasicTable, TableAction } from '@/components/Table';
import { BasicTable } from '@/components/Table';
import { BasicForm, useForm } from '@/components/Form/index';
import { usePermission } from '@/hooks/web/usePermission';
import { List, Export } from '@/api/pay/refund';
import { columns, schemas } from './model';
import { columns, schemas, loadOptions } from './model';
import { ExportOutlined } from '@vicons/antd';
const { hasPermission } = usePermission();
const actionRef = ref();
const message = useMessage();
const searchFormRef = ref<any>({});
const actionColumn = reactive({
width: 300,
title: '操作',
key: 'action',
// fixed: 'right',
render(record) {
return h(TableAction as any, {
style: 'button',
actions: [],
});
},
});
const [register, {}] = useForm({
gridProps: { cols: '1 s:1 m:2 l:3 xl:4 2xl:4' },
labelWidth: 80,
@@ -96,6 +80,10 @@
message.loading('正在导出列表...', { duration: 1200 });
Export(searchFormRef.value?.formModel);
}
onMounted(async () => {
loadOptions();
});
</script>
<style lang="less" scoped></style>

View File

@@ -1,60 +1,10 @@
import { h, ref } from 'vue';
import { NAvatar, NImage, NTag, NSwitch, NRate } from 'naive-ui';
import { cloneDeep } from 'lodash-es';
import { ref } from 'vue';
import { FormSchema } from '@/components/Form';
import { Dicts } from '@/api/dict/dict';
import { isNullObject } from '@/utils/is';
import { defRangeShortcuts } from '@/utils/dateUtil';
import { getOptionLabel, getOptionTag, Options } from '@/utils/hotgo';
import { useDictStore } from '@/store/modules/dict';
import { renderOptionTag } from '@/utils';
export interface State {
id: number;
memberId: number;
appId: string;
addonsName: string;
creditType: string;
creditGroup: string;
beforeNum: number;
num: number;
afterNum: number;
remark: string;
ip: string;
mapId: number;
status: number;
createdAt: string;
updatedAt: string;
}
export const defaultState = {
id: 0,
memberId: 0,
appId: '',
addonsName: '',
creditType: '',
creditGroup: '',
beforeNum: 0,
num: 0,
afterNum: 0,
remark: '',
ip: '',
mapId: 0,
status: 1,
createdAt: '',
updatedAt: '',
};
export function newState(state: State | null): State {
if (state !== null) {
return cloneDeep(state);
}
return cloneDeep(defaultState);
}
export const options = ref<Options>({
sys_normal_disable: [],
});
export const rules = {};
const dict = useDictStore();
export const schemas = ref<FormSchema[]>([
{
@@ -211,22 +161,7 @@ export const columns = [
title: '状态',
key: 'status',
render(row) {
if (isNullObject(row.status)) {
return ``;
}
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.sys_normal_disable, row.status),
bordered: false,
},
{
default: () => getOptionLabel(options.value.sys_normal_disable, row.status),
}
);
return renderOptionTag('sys_normal_disable', row.status);
},
},
{
@@ -239,17 +174,8 @@ export const columns = [
},
];
async function loadOptions() {
options.value = await Dicts({
types: ['sys_normal_disable'],
});
for (const item of schemas.value) {
switch (item.field) {
case 'status':
item.componentProps.options = options.value.sys_normal_disable;
break;
}
}
export function loadOptions() {
dict.loadOptions(['sys_normal_disable']);
}
await loadOptions();
loadOptions();

View File

@@ -36,7 +36,10 @@
</n-form-item>
<n-form-item label="更新状态" path="status">
<n-select v-model:value="params.status" :options="options.acceptRefundStatus" />
<n-select
v-model:value="params.status"
:options="dict.getOptionUnRef('acceptRefundStatus')"
/>
</n-form-item>
<n-form-item label="拒绝原因" path="rejectRefundReason" v-if="params.status === 9">
@@ -64,10 +67,11 @@
<script lang="ts" setup>
import { ref, computed, watch } from 'vue';
import { rules, State, newState, options } from './model';
import { rules, State, newState } from './model';
import { useMessage } from 'naive-ui';
import { adaModalWidth } from '@/utils/hotgo';
import { AcceptRefund, View } from '@/api/order';
import { useDictStore } from '@/store/modules/dict';
const emit = defineEmits(['reloadTable', 'updateShowModal']);
interface Props {
@@ -93,6 +97,7 @@
const loading = ref(false);
const params = ref<State>(props.formParams);
const dict = useDictStore();
const message = useMessage();
const formRef = ref<any>({});
const formBtnLoading = ref(false);

View File

@@ -86,20 +86,21 @@
function confirmForm(e) {
e.preventDefault();
formBtnLoading.value = true;
formRef.value.validate((errors) => {
if (!errors) {
ApplyRefund(params.value).then((_res) => {
message.success('操作成功');
setTimeout(() => {
formBtnLoading.value = true;
ApplyRefund(params.value)
.then((_res) => {
message.success('操作成功');
isShowModal.value = false;
emit('reloadTable');
})
.finally(() => {
formBtnLoading.value = false;
});
});
} else {
message.error('请填写完整信息');
}
formBtnLoading.value = false;
});
}

View File

@@ -14,7 +14,7 @@
<n-tab-pane
:name="item.key.toString()"
:tab="item.label"
v-for="item in options.orderStatus"
v-for="item in dict.getOptionUnRef('orderStatus')"
:key="item.key"
>
<List :type="defaultTab" />
@@ -28,18 +28,21 @@
import { onMounted, ref } from 'vue';
import List from './list.vue';
import { useRouter } from 'vue-router';
import { options } from '@/views/asset/rechargeLog/model';
import { loadOptions } from './model';
import { useDictStore } from '@/store/modules/dict';
const dict = useDictStore();
const router = useRouter();
const defaultTab = ref('-1');
function handleBeforeLeave(tabName: string) {
defaultTab.value = tabName;
}
onMounted(() => {
if (router.currentRoute.value.query?.type) {
defaultTab.value = router.currentRoute.value.query.type as string;
}
loadOptions();
});
function handleBeforeLeave(tabName: string) {
defaultTab.value = tabName;
}
</script>

View File

@@ -58,15 +58,15 @@
</n-card>
<ApplyRefund
@reloadTable="reloadTable"
@updateShowModal="updateShowModal"
@reload-table="reloadTable"
@update-show-modal="updateShowModal"
:showModal="showModal"
:formParams="formParams"
/>
<AcceptRefund
@reloadTable="reloadTable"
@updateShowModal="updateAcceptShowModal"
@reload-table="reloadTable"
@update-show-modal="updateAcceptShowModal"
:showModal="showAcceptModal"
:formParams="formParams"
/>
@@ -184,9 +184,6 @@
reloadTable();
});
},
onNegativeClick: () => {
// message.error('取消');
},
});
}

View File

@@ -1,12 +1,9 @@
import { h, ref } from 'vue';
import { NTag } from 'naive-ui';
import { ref } from 'vue';
import { cloneDeep } from 'lodash-es';
import { FormSchema } from '@/components/Form';
import { Option } from '@/api/order';
import { isNullObject } from '@/utils/is';
import { defRangeShortcuts } from '@/utils/dateUtil';
import { getOptionLabel, getOptionTag, Options } from '@/utils/hotgo';
import { Dicts } from '@/api/dict/dict';
import { useDictStore } from '@/store/modules/dict';
import { renderOptionTag } from '@/utils';
export interface State {
id: number;
@@ -49,12 +46,7 @@ export function newState(state: State | null): State {
return cloneDeep(defaultState);
}
export const options = ref<Options>({
orderStatus: [],
acceptRefundStatus: [],
payType: [],
});
const dict = useDictStore();
export const rules = {};
export const schemas = ref<FormSchema[]>([
@@ -131,22 +123,7 @@ export const columns = [
title: '支付方式',
key: 'payLogPayType',
render(row) {
if (isNullObject(row.payLogPayType)) {
return ``;
}
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.payType, row.payLogPayType),
bordered: false,
},
{
default: () => getOptionLabel(options.value.payType, row.payLogPayType),
}
);
return renderOptionTag('payType', row.payLogPayType);
},
width: 150,
},
@@ -162,24 +139,7 @@ export const columns = [
title: '订单状态',
key: 'status',
render(row) {
if (isNullObject(row.status)) {
return ``;
}
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.orderStatus, row.status),
bordered: false,
},
{
default: () =>
getOptionLabel(options.value.orderStatus, row.status) +
(row.status === 9 ? '' + row.rejectRefundReason : ''),
}
);
return renderOptionTag('orderStatus', row.status);
},
width: 150,
},
@@ -190,23 +150,6 @@ export const columns = [
},
];
async function loadOptions() {
options.value = await Dicts({
types: ['payType', 'orderStatus', 'acceptRefundStatus'],
});
for (const item of schemas.value) {
switch (item.field) {
case 'status':
item.componentProps.options = options.value.orderStatus;
break;
case 'acceptRefundStatus':
item.componentProps.options = options.value.acceptRefundStatus;
break;
case 'payType':
item.componentProps.options = options.value.payType;
break;
}
}
export function loadOptions() {
dict.loadOptions(['payType', 'orderStatus', 'acceptRefundStatus']);
}
await loadOptions();

View File

@@ -63,16 +63,6 @@
/>
</n-form-item>
</n-gi>
<n-gi span="1">
<n-form-item label="状态" path="status">
<n-select v-model:value="formValue.status" :options="options.sys_normal_disable" />
</n-form-item>
</n-gi>
<n-gi span="1">
<n-form-item label="测试分类" path="categoryId">
<n-select v-model:value="formValue.categoryId" :options="options.testCategoryOption" />
</n-form-item>
</n-gi>
</n-grid>
</n-form>
</n-spin>
@@ -93,8 +83,9 @@
<script lang="ts" setup>
import { ref, computed } from 'vue';
import { useDictStore } from '@/store/modules/dict';
import { Edit, View, MaxSort } from '@/api/curdDemo';
import { options, State, newState, rules } from './model';
import { State, newState, rules } from './model';
import Editor from '@/components/Editor/editor.vue';
import UploadImage from '@/components/Upload/uploadImage.vue';
import UploadFile from '@/components/Upload/uploadFile.vue';
@@ -106,6 +97,7 @@
const emit = defineEmits(['reloadTable']);
const message = useMessage();
const settingStore = useProjectSettingStore();
const dict = useDictStore();
const loading = ref(false);
const showModal = ref(false);
const formValue = ref<State>(newState(null));
@@ -144,25 +136,28 @@
});
}
// 提交表单
function confirmForm(e) {
e.preventDefault();
formBtnLoading.value = true;
formRef.value.validate((errors) => {
if (!errors) {
Edit(formValue.value).then((_res) => {
message.success('操作成功');
setTimeout(() => {
formBtnLoading.value = true;
Edit(formValue.value)
.then((_res) => {
message.success('操作成功');
closeForm();
emit('reloadTable');
})
.finally(() => {
formBtnLoading.value = false;
});
});
} else {
message.error('请填写完整信息');
}
formBtnLoading.value = false;
});
}
// 关闭表单
function closeForm() {
showModal.value = false;
loading.value = false;
@@ -173,4 +168,4 @@
});
</script>
<style lang="less"></style>
<style lang="less"></style>

View File

@@ -50,7 +50,8 @@
import { BasicTable, TableAction } from '@/components/Table';
import { BasicForm, useForm } from '@/components/Form/index';
import { usePermission } from '@/hooks/web/usePermission';
import { List, Export, Delete } from '@/api/curdDemo';
import { useDictStore } from '@/store/modules/dict';
import { List, Export, Delete, Status } from '@/api/curdDemo';
import { PlusOutlined, ExportOutlined, DeleteOutlined } from '@vicons/antd';
import { columns, schemas, loadOptions } from './model';
import { adaTableScrollX } from '@/utils/hotgo';
@@ -59,6 +60,7 @@
const dialog = useDialog();
const message = useMessage();
const { hasPermission } = usePermission();
const dict = useDictStore();
const actionRef = ref();
const searchFormRef = ref<any>({});
const editRef = ref();
@@ -66,7 +68,7 @@
const checkedIds = ref([]);
const actionColumn = reactive({
width: 144,
width: 216,
title: '操作',
key: 'action',
fixed: 'right',
@@ -80,6 +82,22 @@
auth: ['/curdDemo/edit'],
},
{
label: '禁用',
onClick: handleStatus.bind(null, record, 2),
ifShow: () => {
return record.status === 1;
},
auth: ['/curdDemo/status'],
},
{
label: '启用',
onClick: handleStatus.bind(null, record, 1),
ifShow: () => {
return record.status === 2;
},
auth: ['/curdDemo/status'],
},
{
label: '删除',
onClick: handleDelete.bind(null, record),
@@ -170,9 +188,20 @@
Export(searchFormRef.value?.formModel);
}
// 修改状态
function handleStatus(record: Recordable, status: number) {
Status({ id: record.id, status: status }).then((_res) => {
message.success('设为' + dict.getLabel('sys_normal_disable', status) + '成功');
setTimeout(() => {
reloadTable();
});
});
}
onMounted(() => {
loadOptions();
});
</script>
<style lang="less" scoped></style>
<style lang="less" scoped></style>

View File

@@ -1,15 +1,16 @@
import { h, ref } from 'vue';
import { NImage, NAvatar, NSwitch, NTag } from 'naive-ui';
import { NImage, NAvatar, NSwitch } from 'naive-ui';
import { cloneDeep } from 'lodash-es';
import { FormSchema } from '@/components/Form';
import { Dicts } from '@/api/dict/dict';
import { isNullObject } from '@/utils/is';
import { getFileExt } from '@/utils/urlUtils';
import { defRangeShortcuts } from '@/utils/dateUtil';
import { Option, errorImg, getOptionLabel, getOptionTag } from '@/utils/hotgo';
import { fallbackSrc } from '@/utils/hotgo';
import { renderPopoverMemberSumma, MemberSumma } from '@/utils';
import { Switch } from '@/api/curdDemo';
import { useDictStore } from '@/store/modules/dict';
import { usePermission } from '@/hooks/web/usePermission';
const dict = useDictStore();
const { hasPermission } = usePermission();
const $message = window['$message'];
@@ -76,12 +77,6 @@ export const rules = {
type: 'number',
message: '请输入排序',
},
categoryId: {
required: true,
trigger: ['blur', 'input'],
type: 'number',
message: '请输入测试分类',
},
};
// 表格搜索表单
@@ -119,19 +114,6 @@ export const schemas = ref<FormSchema[]>([
},
},
},
{
field: 'status',
component: 'NSelect',
label: '状态',
defaultValue: null,
componentProps: {
placeholder: '请选择状态',
options: [],
onUpdateValue: (e: any) => {
console.log(e);
},
},
},
{
field: 'createdBy',
component: 'NInput',
@@ -156,19 +138,6 @@ export const schemas = ref<FormSchema[]>([
},
},
},
{
field: 'categoryId',
component: 'NSelect',
label: '测试分类',
defaultValue: null,
componentProps: {
placeholder: '请选择测试分类',
options: [],
onUpdateValue: (e: any) => {
console.log(e);
},
},
},
{
field: 'testCategoryName',
component: 'NInput',
@@ -212,8 +181,7 @@ export const columns = [
width: 32,
height: 32,
src: row.image,
fallbackSrc: errorImg,
onError: errorImg,
fallbackSrc: fallbackSrc(),
style: {
width: '32px',
height: '32px',
@@ -270,30 +238,6 @@ export const columns = [
});
},
},
{
title: '状态',
key: 'status',
align: 'left',
width: 100,
render(row) {
if (isNullObject(row.status)) {
return ``;
}
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.sys_normal_disable, row.status),
bordered: false,
},
{
default: () => getOptionLabel(options.value.sys_normal_disable, row.status),
}
);
},
},
{
title: '创建者',
key: 'createdBy',
@@ -324,30 +268,6 @@ export const columns = [
align: 'left',
width: 180,
},
{
title: '测试分类',
key: 'categoryId',
align: 'left',
width: 100,
render(row) {
if (isNullObject(row.categoryId)) {
return ``;
}
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.testCategoryOption, row.categoryId),
bordered: false,
},
{
default: () => getOptionLabel(options.value.testCategoryOption, row.categoryId),
}
);
},
},
{
title: '关联分类',
key: 'testCategoryName',
@@ -356,27 +276,7 @@ export const columns = [
},
];
// 字典数据选项
export const options = ref({
sys_normal_disable: [] as Option[],
testCategoryOption: [] as Option[],
});
// 加载字典数据选项
export function loadOptions() {
Dicts({
types: ['sys_normal_disable', 'testCategoryOption'],
}).then((res) => {
options.value = res;
for (const item of schemas.value) {
switch (item.field) {
case 'status':
item.componentProps.options = options.value.sys_normal_disable;
break;
case 'categoryId':
item.componentProps.options = options.value.testCategoryOption;
break;
}
}
});
}
dict.loadOptions(['sys_normal_disable', 'testCategoryOption']);
}

View File

@@ -1,123 +0,0 @@
<template>
<div>
<n-drawer v-model:show="showModal" :width="dialogWidth">
<n-drawer-content title="CURD列表详情" closable>
<n-spin :show="loading" description="请稍候...">
<n-descriptions label-placement="left" class="py-2" column="1">
<n-descriptions-item label="测试分类">
<n-tag :type="getOptionTag(options.testCategoryOption, formValue?.categoryId)" size="small" class="min-left-space">
{{ getOptionLabel(options.testCategoryOption, formValue?.categoryId) }}
</n-tag>
</n-descriptions-item>
<n-descriptions-item>
<template #label>
标题
</template>
{{ formValue.title }}
</n-descriptions-item>
<n-descriptions-item>
<template #label>
描述
</template>
<span v-html="formValue.description"></span>
</n-descriptions-item>
<n-descriptions-item>
<template #label>
内容
</template>
<span v-html="formValue.content"></span>
</n-descriptions-item>
<n-descriptions-item>
<template #label>
所在城市
</template>
{{ formValue.cityId }}
</n-descriptions-item>
<n-descriptions-item>
<template #label>
排序
</template>
{{ formValue.sort }}
</n-descriptions-item>
<n-descriptions-item>
<template #label>
单图
</template>
<n-image style="margin-left: 10px; height: 100px; width: 100px" :src="formValue.image"/>
</n-descriptions-item>
<n-descriptions-item label="显示开关">
<n-switch v-model:value="formValue.switch" :unchecked-value="2" :checked-value="1" :disabled="true"/>
</n-descriptions-item>
<n-descriptions-item>
<template #label>
附件
</template>
<div class="upload-card" v-show="formValue.attachfile !== ''" @click="download(formValue.attachfile)">
<div class="upload-card-item" style="height: 100px; width: 100px">
<div class="upload-card-item-info">
<div class="img-box">
<n-avatar :style="fileAvatarCSS">
{{ getFileExt(formValue.attachfile) }}
</n-avatar>
</div>
</div>
</div>
</div>
</n-descriptions-item>
<n-descriptions-item label="状态">
<n-tag :type="getOptionTag(options.sys_normal_disable, formValue?.status)" size="small" class="min-left-space">
{{ getOptionLabel(options.sys_normal_disable, formValue?.status) }}
</n-tag>
</n-descriptions-item>
</n-descriptions>
</n-spin>
</n-drawer-content>
</n-drawer>
</div>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue';
import { useMessage } from 'naive-ui';
import { View } from '@/api/curdDemo';
import { State, newState, options } from './model';
import { adaModalWidth, getOptionLabel, getOptionTag } from '@/utils/hotgo';
import { getFileExt } from '@/utils/urlUtils';
const message = useMessage();
const loading = ref(false);
const showModal = ref(false);
const formValue = ref(newState(null));
const dialogWidth = computed(() => {
return adaModalWidth(580);
});
const fileAvatarCSS = computed(() => {
return {
'--n-merged-size': `var(--n-avatar-size-override, 80px)`,
'--n-font-size': `18px`,
};
});
//下载
function download(url: string) {
window.open(url);
}
function openModal(state: State) {
showModal.value = true;
loading.value = true;
View({ id: state.id })
.then((res) => {
formValue.value = res;
})
.finally(() => {
loading.value = false;
});
}
defineExpose({
openModal,
});
</script>
<style lang="less" scoped></style>

View File

@@ -3,9 +3,7 @@
</template>
<script lang="ts">
import { defineComponent, onMounted, ref, Ref } from 'vue';
import { useECharts } from '@/hooks/web/useECharts';
import { basicProps } from './props';
export default defineComponent({

View File

@@ -74,7 +74,7 @@
<n-form-item label="功能分组" path="group">
<n-select
placeholder="请选择"
:options="options.addonsGroupOptions"
:options="dict.getOptionUnRef('addonsGroupOptions')"
v-model:value="formParams.group"
:on-update:value="onUpdateValueGroup"
/>
@@ -86,7 +86,7 @@
<n-checkbox
:value="option.value"
:label="option.label"
v-for="option in options.addonsExtend"
v-for="option in dict.getOptionUnRef('addonsExtend')"
:key="option"
/>
</n-space>
@@ -128,15 +128,17 @@
</template>
<script lang="ts" setup>
import { computed, h, reactive, ref } from 'vue';
import { computed, h, onMounted, reactive, ref } from 'vue';
import { NIcon, useMessage, useDialog, useNotification } from 'naive-ui';
import { BasicTable, TableAction } from '@/components/Table';
import { BasicForm, useForm } from '@/components/Form/index';
import { List, Build, UnInstall, Install, Upgrade } from '@/api/develop/addons';
import { PlusOutlined } from '@vicons/antd';
import { newState, schemas, columns, options } from './model';
import { newState, schemas, columns, loadOptions } from './model';
import { adaModalWidth } from '@/utils/hotgo';
import { useDictStore } from '@/store/modules/dict';
const dict = useDictStore();
const dialog = useDialog();
const message = useMessage();
const notification = useNotification();
@@ -315,6 +317,10 @@
},
});
}
onMounted(async () => {
loadOptions();
});
</script>
<style lang="less" scoped></style>

View File

@@ -1,11 +1,13 @@
import { cloneDeep } from 'lodash-es';
import { h, ref } from 'vue';
import { Dicts } from '@/api/dict/dict';
import { errorImg, Option, Options } from '@/utils/hotgo';
import { fallbackSrc } from '@/utils/hotgo';
import { isUrl } from '@/utils/is';
import { NIcon, NIconWrapper, NImage, NTag } from 'naive-ui';
import { getIconComponent } from '@/utils/icons';
import { FormSchema } from '@/components/Form';
import { useDictStore } from '@/store/modules/dict';
const dict = useDictStore();
export const genInfoObj = {
label: '',
@@ -36,7 +38,7 @@ export const columns = [
width: 48,
height: 48,
src: row.logo,
fallbackSrc: errorImg,
fallbackSrc: fallbackSrc(),
style: {
width: '48px',
height: '48px',
@@ -152,7 +154,7 @@ export const schemas = ref<FormSchema[]>([
label: '分组',
componentProps: {
placeholder: '请选择分组',
options: [],
options: dict.getOption('addonsGroupOptions'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -164,7 +166,7 @@ export const schemas = ref<FormSchema[]>([
label: '安装状态',
componentProps: {
placeholder: '请选择状态',
options: [],
options: dict.getOption('addonsInstallStatus'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -172,32 +174,6 @@ export const schemas = ref<FormSchema[]>([
},
]);
export interface IOptions extends Options {
addonsGroupOptions: Option[];
addonsInstallStatus: Option[];
addonsExtend: Option[];
export function loadOptions() {
dict.loadOptions(['addonsGroupOptions', 'addonsInstallStatus', 'addonsExtend']);
}
export const options = ref<IOptions>({
addonsGroupOptions: [],
addonsInstallStatus: [],
addonsExtend: [],
});
async function loadOptions() {
options.value = await Dicts({
types: ['addonsGroupOptions', 'addonsInstallStatus', 'addonsExtend'],
});
for (const item of schemas.value) {
switch (item.field) {
case 'status':
item.componentProps.options = options.value.addonsInstallStatus;
break;
case 'group':
item.componentProps.options = options.value.addonsGroupOptions;
break;
}
}
}
await loadOptions();

View File

@@ -31,7 +31,12 @@
</template>
立即生成
</n-button>
<n-button type="error" @click="batchDelete" :disabled="batchDeleteDisabled" class="min-left-space">
<n-button
type="error"
@click="batchDelete"
:disabled="batchDeleteDisabled"
class="min-left-space"
>
<template #icon>
<n-icon>
<DeleteOutlined />
@@ -145,14 +150,13 @@
<script lang="ts" setup>
import { h, onBeforeMount, reactive, ref } from 'vue';
import { NTag, TreeSelectOption, useDialog, useMessage } from 'naive-ui';
import { NTag, useDialog, useMessage } from 'naive-ui';
import { BasicTable, TableAction } from '@/components/Table';
import { BasicForm, FormSchema, useForm } from '@/components/Form/index';
import { List, Delete, Edit, Selects, TableSelect } from '@/api/develop/code';
import { useRouter } from 'vue-router';
import { PlusOutlined, DeleteOutlined } from '@vicons/antd';
import { newState } from '@/views/develop/code/components/model';
import { getOptionLabel } from '@/utils/hotgo';
const selectList = ref({
db: [],
@@ -347,9 +351,6 @@
reloadTable();
});
},
onNegativeClick: () => {
// message.error('取消');
},
});
}
@@ -365,9 +366,6 @@
reloadTable();
});
},
onNegativeClick: () => {
// message.error('取消');
},
});
}
@@ -401,9 +399,7 @@
e.preventDefault();
formBtnLoading.value = true;
formRef.value.validate((errors) => {
console.log('formParams:' + JSON.stringify(formParams.value));
if (!errors) {
console.log('formParams:' + JSON.stringify(formParams.value));
Edit(formParams.value).then((res) => {
message.success('生成成功,正在前往配置');
setTimeout(() => {
@@ -427,17 +423,23 @@
} else {
dialogWidth.value = def + 'px';
}
return dialogWidth.value;
}
onBeforeMount(async () => {
await loadSelect();
});
function getOptionLabel(options, value) {
if (!options || options?.length === 0) {
return `unknown`;
}
for (const item of options) {
if (item.value == value) {
return item.label;
}
}
return `unknown`;
}
const loadSelect = async () => {
selectList.value = await Selects({});
for (const item of schemas.value) {
switch (item.field) {
case 'status':
@@ -452,10 +454,7 @@
const tablesLoading = ref(false);
// 处理选项更新
async function handleDbUpdateValue(
value: string | number | Array<string | number> | null,
_option: TreeSelectOption | null | Array<TreeSelectOption | null>
) {
async function handleDbUpdateValue(value: string | number | Array<string | number> | null) {
tablesLoading.value = true;
await loadTableSelect(value);
tablesLoading.value = false;
@@ -491,6 +490,10 @@
formParams.value.genTemplate = value;
selectAddon.value = option.isAddon === true;
}
onBeforeMount(async () => {
await loadSelect();
});
</script>
<style lang="less" scoped></style>

View File

@@ -1,8 +1,39 @@
import { FormSchema } from '@/components/Form';
import { ref } from 'vue';
import { defRangeShortcuts } from '@/utils/dateUtil';
import { Option } from '@/utils/hotgo';
import { Dicts } from '@/api/dict/dict';
import { useDictStore } from '@/store/modules/dict';
const dict = useDictStore();
export class State {
id = 0;
reqId = '';
appId = '';
merchantId = 0;
memberId = 0;
method = '';
module = '';
url = '';
getData: Record<string, any> | null = null;
postData: Record<string, string[]> | null = null;
headerData: Record<string, string[]> | null = null;
ip = '';
provinceId = 0;
cityId = 0;
errorCode = 0;
errorMsg = '';
errorData: string[] = [];
userAgent = '';
takeUpTime = 0;
timestamp = 0;
status = 0;
createdAt = '';
updatedAt = '';
cityLabel = '';
tags = '';
summary = '';
description = '';
}
export const schemas = ref<FormSchema[]>([
{
@@ -39,6 +70,17 @@ export const schemas = ref<FormSchema[]>([
},
},
},
{
field: 'keyword',
component: 'NInput',
label: '关键词',
componentProps: {
placeholder: '请输入关键词',
onInput: (e: any) => {
console.log(e);
},
},
},
{
field: 'ip',
component: 'NInput',
@@ -56,7 +98,7 @@ export const schemas = ref<FormSchema[]>([
label: '请求方式',
componentProps: {
placeholder: '请选择请求方式',
options: [],
options: dict.getOption('HTTPMethod'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -81,7 +123,7 @@ export const schemas = ref<FormSchema[]>([
label: '请求耗时',
componentProps: {
placeholder: '请选择请求耗时',
options: [],
options: dict.getOption('HTTPHandlerTime'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -94,7 +136,7 @@ export const schemas = ref<FormSchema[]>([
labelMessage: '支持填入自定义状态码',
componentProps: {
placeholder: '请选择状态码',
options: [],
options: dict.getOption('HTTPApiCode'),
filterable: true,
tag: true,
onUpdateValue: (e: any) => {
@@ -104,31 +146,7 @@ export const schemas = ref<FormSchema[]>([
},
]);
// 字典数据选项
export const options = ref({
HTTPMethod: [] as Option[],
HTTPHandlerTime: [] as Option[],
HTTPApiCode: [] as Option[],
});
// 加载字典数据选项
export function loadOptions() {
Dicts({
types: ['HTTPMethod', 'HTTPHandlerTime', 'HTTPApiCode'],
}).then((res) => {
options.value = res;
for (const item of schemas.value) {
switch (item.field) {
case 'method':
item.componentProps.options = options.value.HTTPMethod;
break;
case 'takeUpTime':
item.componentProps.options = options.value.HTTPHandlerTime;
break;
case 'errorCode':
item.componentProps.options = options.value.HTTPApiCode;
break;
}
}
});
dict.loadOptions(['HTTPMethod', 'HTTPHandlerTime', 'HTTPApiCode']);
}

View File

@@ -8,7 +8,17 @@
:segmented="{ content: true }"
:title="data.id ? '日志详情 ID' + data.id : '日志详情'"
>
<n-descriptions label-placement="left" class="py-2">
<template #header-extra>
<n-button icon-placement="right" @click="goBackOrToPage({ name: 'log' })">
<template #icon>
<n-icon>
<ArrowRightOutlined />
</n-icon>
</template>
返回
</n-button>
</template>
<n-descriptions label-placement="left" class="py-2" :column="settingStore.isMobile ? 1 : 3">
<n-descriptions-item label="请求方式">{{ data.method }}</n-descriptions-item>
<n-descriptions-item>
<template #label>请求地址</template>
@@ -131,18 +141,23 @@
import { useMessage } from 'naive-ui';
import { View } from '@/api/log/log';
import { timestampToTime } from '@/utils/dateUtil';
import { ArrowRightOutlined } from '@vicons/antd';
import { goBackOrToPage } from '@/utils/urlUtils';
import { State } from '@/views/log/log/model';
import { useProjectSettingStore } from '@/store/modules/projectSetting';
const message = useMessage();
const router = useRouter();
const settingStore = useProjectSettingStore();
const params = router.currentRoute.value.params;
const loading = ref(false);
const data = ref({});
const data = ref<State>(new State());
const getInfo = () => {
loading.value = true;
View(params)
.then((res) => {
data.value = res;
data.value = res as unknown as State;
})
.finally(() => {
loading.value = false;

View File

@@ -83,7 +83,7 @@
const checkedIds = ref([]);
const actionColumn = reactive({
width: 180,
width: 160,
title: '操作',
key: 'action',
fixed: 'right',

View File

@@ -1,46 +1,11 @@
import { h, ref } from 'vue';
import { NTag } from 'naive-ui';
import { cloneDeep } from 'lodash-es';
import { FormSchema } from '@/components/Form';
import { isNullObject } from '@/utils/is';
import { defRangeShortcuts } from '@/utils/dateUtil';
import { getOptionLabel, getOptionTag, Option } from '@/utils/hotgo';
import { Dicts } from '@/api/dict/dict';
import { NTag } from 'naive-ui';
import { useDictStore } from '@/store/modules/dict';
import { renderOptionTag } from '@/utils';
export interface State {
id: number;
reqId: string;
memberId: number;
username: string;
response: any;
loginAt: number;
errMsg: string;
status: number;
createdAt: string;
updatedAt: string;
}
export const defaultState = {
id: 0,
reqId: '',
memberId: 0,
username: '',
response: null,
loginAt: 0,
errMsg: '',
status: 1,
createdAt: '',
updatedAt: '',
};
export function newState(state: State | null): State {
if (state !== null) {
return cloneDeep(state);
}
return cloneDeep(defaultState);
}
export const rules = {};
const dict = useDictStore();
export const schemas = ref<FormSchema[]>([
{
@@ -72,7 +37,7 @@ export const schemas = ref<FormSchema[]>([
defaultValue: null,
componentProps: {
placeholder: '请选择状态',
options: [],
options: dict.getOption('sys_login_status'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -143,22 +108,7 @@ export const columns = [
title: '状态',
key: 'status',
render(row) {
if (isNullObject(row.status)) {
return ``;
}
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.sys_login_status, row.status),
bordered: false,
},
{
default: () => getOptionLabel(options.value.sys_login_status, row.status),
}
);
return renderOptionTag('sys_login_status', row.status);
},
width: 150,
},
@@ -184,23 +134,7 @@ export const columns = [
},
];
// 字典数据选项
export const options = ref({
sys_login_status: [] as Option[],
});
// 加载字典数据选项
export function loadOptions() {
Dicts({
types: ['sys_login_status'],
}).then((res) => {
options.value = res;
for (const item of schemas.value) {
switch (item.field) {
case 'status':
item.componentProps.options = options.value.sys_login_status;
break;
}
}
});
dict.loadOptions(['sys_login_status']);
}

View File

@@ -44,19 +44,18 @@
</template>
<script lang="ts" setup>
import { computed, h, reactive, ref } from 'vue';
import { NTag, useDialog, useMessage } from 'naive-ui';
import { computed, h, onMounted, reactive, ref } from 'vue';
import { useDialog, useMessage } from 'naive-ui';
import { BasicTable, TableAction } from '@/components/Table';
import { BasicForm, FormSchema, useForm } from '@/components/Form/index';
import { getLogList, Delete } from '@/api/log/smslog';
import { DeleteOutlined } from '@vicons/antd';
import { Dicts } from '@/api/dict/dict';
import { adaTableScrollX, getOptionLabel, getOptionTag, Options } from '@/utils/hotgo';
import { adaTableScrollX } from '@/utils/hotgo';
import { defRangeShortcuts } from '@/utils/dateUtil';
import { useDictStore } from '@/store/modules/dict';
import { renderOptionTag } from '@/utils';
const options = ref<Options>({
config_sms_template: [],
});
const dict = useDictStore();
const columns = [
{
@@ -68,19 +67,7 @@
title: '事件模板',
key: 'event',
render(row) {
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.config_sms_template, row.event),
bordered: false,
},
{
default: () => getOptionLabel(options.value.config_sms_template, row.event),
}
);
return renderOptionTag('config_sms_template', row.event);
},
width: 150,
},
@@ -111,19 +98,7 @@
title: '状态',
key: 'status',
render(row) {
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: row.status == 2 ? 'success' : 'warning',
bordered: false,
},
{
default: () => (row.status == 2 ? '已使用' : '未使用'),
}
);
return renderOptionTag('CodeStatusOptions', row.status);
},
width: 100,
},
@@ -153,7 +128,7 @@
label: '事件模板',
componentProps: {
placeholder: '请选择事件模板',
options: [],
options: dict.getOption('config_sms_template'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -188,16 +163,7 @@
label: '状态',
componentProps: {
placeholder: '请选择状态',
options: [
{
label: '未使用',
value: '1',
},
{
label: '已使用',
value: '2',
},
],
options: dict.getOption('CodeStatusOptions'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -264,9 +230,6 @@
reloadTable();
});
},
onNegativeClick: () => {
// message.error('不确定');
},
});
}
@@ -282,14 +245,10 @@
reloadTable();
});
},
onNegativeClick: () => {
// message.error('不确定');
},
});
}
const loadDataTable = async (res) => {
await loadOptions();
return await getLogList({ ...searchFormRef.value?.formModel, ...res });
};
@@ -307,18 +266,13 @@
reloadTable();
}
async function loadOptions() {
options.value = await Dicts({
types: ['config_sms_template'],
});
for (const item of schemas.value) {
switch (item.field) {
case 'event':
item.componentProps.options = options.value.config_sms_template;
break;
}
}
function loadOptions() {
dict.loadOptions(['config_sms_template', 'CodeStatusOptions']);
}
onMounted(() => {
loadOptions();
});
</script>
<style lang="less" scoped></style>

View File

@@ -1,9 +1,7 @@
import { h } from 'vue';
import { NButton, NTag } from 'naive-ui';
import { timestampToTime, formatBefore } from '@/utils/dateUtil';
import { getOptionLabel } from '@/utils/hotgo';
import { options } from '@/views/monitor/netconn/modal/model';
import { renderIcon, renderTooltip } from '@/utils';
import { renderIcon, renderOptionTag, renderTooltip } from '@/utils';
import { HelpCircleOutline } from '@vicons/ionicons5';
export const columns = [
@@ -95,19 +93,7 @@ export const columns = [
key: 'group',
width: 100,
render(row) {
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: 'info',
bordered: false,
},
{
default: () => getOptionLabel(options.value.group, row.group),
}
);
return renderOptionTag('ServerLicenseGroupOptions', row.group);
},
},
{

View File

@@ -38,8 +38,8 @@
<GroupModal ref="GroupModalRef" />
<Edit
@reloadTable="reloadTable"
@updateShowModal="updateShowModal"
@reload-table="reloadTable"
@update-show-modal="updateShowModal"
:showModal="showModal"
:formParams="formEditParams"
/>
@@ -47,7 +47,7 @@
</template>
<script lang="ts" setup>
import { computed, h, reactive, ref } from 'vue';
import { computed, h, onMounted, reactive, ref } from 'vue';
import { useDialog, useMessage } from 'naive-ui';
import { BasicTable, TableAction } from '@/components/Table';
import { BasicForm, FormSchema, useForm } from '@/components/Form/index';
@@ -56,12 +56,14 @@
import { TrademarkOutlined } from '@vicons/antd';
import GroupModal from './modal/modal.vue';
import Edit from '@/views/monitor/netconn/modal/edit.vue';
import { newState, options, State } from '@/views/monitor/netconn/modal/model';
import { loadOptions, newState, State } from '@/views/monitor/netconn/modal/model';
import { defRangeShortcuts } from '@/utils/dateUtil';
import { adaTableScrollX } from '@/utils/hotgo';
import { useDictStore } from '@/store/modules/dict';
const message = useMessage();
const dialog = useDialog();
const dict = useDictStore();
const showModal = ref(false);
const formEditParams = ref<State>(newState(null));
const actionRef = ref();
@@ -115,7 +117,7 @@
defaultValue: null,
componentProps: {
placeholder: '请选择授权分组',
options: options.value.group,
options: dict.getOption('ServerLicenseGroupOptions'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -213,6 +215,10 @@
function updateShowModal(value) {
showModal.value = value;
}
onMounted(async () => {
loadOptions();
});
</script>
<style lang="less" scoped></style>

View File

@@ -24,7 +24,10 @@
<n-grid x-gap="24" :cols="2">
<n-gi>
<n-form-item label="分组" path="group">
<n-select v-model:value="params.group" :options="options.group" />
<n-select
v-model:value="params.group"
:options="dict.getOptionUnRef('ServerLicenseGroupOptions')"
/>
</n-form-item>
</n-gi>
<n-gi>
@@ -78,7 +81,10 @@
</n-form-item>
<n-form-item label="授权状态" path="status">
<n-select v-model:value="params.status" :options="options.sys_normal_disable" />
<n-select
v-model:value="params.status"
:options="dict.getOptionUnRef('sys_normal_disable')"
/>
</n-form-item>
<n-form-item label="备注" path="remark">
@@ -100,9 +106,10 @@
import { ref, computed, watch } from 'vue';
import { Edit, View } from '@/api/serveLicense';
import DatePicker from '@/components/DatePicker/datePicker.vue';
import { rules, options, State, newState } from './model';
import { rules, State, newState } from './model';
import { useMessage } from 'naive-ui';
import { adaModalWidth } from '@/utils/hotgo';
import { useDictStore } from '@/store/modules/dict';
const emit = defineEmits(['reloadTable', 'updateShowModal']);
@@ -129,6 +136,7 @@
const loading = ref(false);
const params = ref<State>(props.formParams);
const dict = useDictStore();
const message = useMessage();
const formRef = ref<any>({});
const formBtnLoading = ref(false);

View File

@@ -70,8 +70,8 @@
</BasicTable>
</n-card>
<Edit
@reloadTable="reloadTable"
@updateShowModal="updateShowModal"
@reload-table="reloadTable"
@update-show-modal="updateShowModal"
:showModal="showModal"
:formParams="formParams"
/>
@@ -99,7 +99,7 @@
ref="transfer"
v-model:value="formParams.routes"
virtual-scroll
:options="options.routes"
:options="routesOptions"
source-filterable
:render-source-label="renderLabel"
:render-target-label="renderLabel"
@@ -117,17 +117,20 @@
</template>
<script lang="ts" setup>
import { computed, h, reactive, ref } from 'vue';
import { computed, h, onMounted, reactive, ref } from 'vue';
import { useDialog, useMessage, NTag } from 'naive-ui';
import { BasicTable, TableAction } from '@/components/Table';
import { BasicForm, useForm } from '@/components/Form/index';
import { usePermission } from '@/hooks/web/usePermission';
import { Delete, Export, List, Status, AssignRouter } from '@/api/serveLicense';
import { columns, newState, options, schemas, State } from './model';
import { columns, newState, loadOptions, schemas, State } from './model';
import { DeleteOutlined, ExportOutlined, PlusOutlined } from '@vicons/antd';
import { adaModalWidth, adaTableScrollX, getOptionLabel } from '@/utils/hotgo';
import { adaModalWidth, adaTableScrollX } from '@/utils/hotgo';
import Edit from './edit.vue';
import { NetOption } from '@/api/monitor/monitor';
import { useDictStore } from '@/store/modules/dict';
const dict = useDictStore();
const { hasPermission } = usePermission();
const actionRef = ref();
const dialog = useDialog();
@@ -136,10 +139,11 @@
const batchDeleteDisabled = ref(true);
const checkedIds = ref([]);
const showModal = ref(false);
const formParams = ref<State>();
const formParams = ref<State>(newState(null));
const showRoutesModal = ref(false);
const formBtnLoading = ref(false);
const formRef = ref<any>({});
const routesOptions = ref([]);
const dialogWidth = computed(() => {
return adaModalWidth();
});
@@ -265,7 +269,7 @@
function handleStatus(record: Recordable, status: number) {
Status({ id: record.id, status: status }).then((_res) => {
message.success('设为' + getOptionLabel(options.value.sys_normal_disable, status) + '成功');
message.success('设为' + dict.getLabel('sys_normal_disable', status) + '成功');
setTimeout(() => {
reloadTable();
});
@@ -276,7 +280,6 @@
e.preventDefault();
formBtnLoading.value = true;
formRef.value.validate((errors) => {
console.log('formParams.value:' + JSON.stringify(formParams.value));
if (!errors) {
AssignRouter(formParams.value).then((_res) => {
message.success('操作成功');
@@ -340,6 +343,17 @@
}
);
}
function loadRoutesOptions() {
NetOption().then((res) => {
routesOptions.value = res.routes;
});
}
onMounted(async () => {
loadOptions();
loadRoutesOptions();
});
</script>
<style lang="less" scoped></style>

View File

@@ -1,12 +1,11 @@
import { h, ref } from 'vue';
import { NTag } from 'naive-ui';
import { cloneDeep } from 'lodash-es';
import { FormSchema } from '@/components/Form';
import { Dicts } from '@/api/dict/dict';
import { isNullObject } from '@/utils/is';
import { defRangeShortcuts, formatBefore } from '@/utils/dateUtil';
import { getOptionLabel, getOptionTag, Options } from '@/utils/hotgo';
import { NetOption } from '@/api/monitor/monitor';
import { useDictStore } from '@/store/modules/dict';
import { renderOptionTag } from '@/utils';
const dict = useDictStore();
export interface State {
id: number;
@@ -55,12 +54,6 @@ export function newState(state: State | null): State {
return cloneDeep(defaultState);
}
export const options = ref<Options>({
sys_normal_disable: [],
group: [],
routes: [],
});
export const rules = {
group: {
required: true,
@@ -107,7 +100,7 @@ export const schemas = ref<FormSchema[]>([
defaultValue: null,
componentProps: {
placeholder: '请选择授权分组',
options: options.value.group,
options: dict.getOption('ServerLicenseGroupOptions'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -142,7 +135,7 @@ export const schemas = ref<FormSchema[]>([
defaultValue: null,
componentProps: {
placeholder: '请选择状态',
options: [],
options: dict.getOption('sys_normal_disable'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -187,19 +180,7 @@ export const columns = [
key: 'group',
width: 100,
render(row) {
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: 'info',
bordered: false,
},
{
default: () => getOptionLabel(options.value.group, row.group),
}
);
return renderOptionTag('ServerLicenseGroupOptions', row.group);
},
},
{
@@ -235,22 +216,7 @@ export const columns = [
key: 'status',
width: 100,
render(row) {
if (isNullObject(row.status)) {
return ``;
}
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.sys_normal_disable, row.status),
bordered: false,
},
{
default: () => getOptionLabel(options.value.sys_normal_disable, row.status),
}
);
return renderOptionTag('sys_normal_disable', row.status);
},
},
{
@@ -283,25 +249,6 @@ export const columns = [
},
];
async function loadOptions() {
options.value = await Dicts({
types: ['sys_normal_disable'],
});
const netOption = await NetOption();
options.value.group = netOption.licenseGroup;
options.value.routes = netOption.routes;
for (const item of schemas.value) {
switch (item.field) {
case 'status':
item.componentProps.options = options.value.sys_normal_disable;
break;
case 'group':
item.componentProps.options = options.value.group;
break;
}
}
export function loadOptions() {
dict.loadOptions(['sys_normal_disable', 'ServerLicenseGroupOptions']);
}
await loadOptions();

View File

@@ -100,7 +100,7 @@
</template>
<script lang="ts" setup>
import { computed, h, reactive, ref } from 'vue';
import { computed, h, onMounted, reactive, ref } from 'vue';
import { useDialog, useMessage } from 'naive-ui';
import { BasicTable, TableAction } from '@/components/Table';
import { BasicForm, useForm } from '@/components/Form/index';
@@ -112,6 +112,7 @@
import { JsonViewer } from 'vue3-json-viewer';
import 'vue3-json-viewer/dist/index.css';
import { adaTableScrollX } from '@/utils/hotgo';
import { loadOptions } from './model';
const { hasPermission } = usePermission();
const router = useRouter();
@@ -198,9 +199,6 @@
reloadTable();
});
},
onNegativeClick: () => {
// message.error('取消');
},
});
}
@@ -218,9 +216,6 @@
reloadTable();
});
},
onNegativeClick: () => {
// message.error('取消');
},
});
}
@@ -228,6 +223,10 @@
message.loading('正在导出列表...', { duration: 1200 });
Export(searchFormRef.value?.formModel);
}
onMounted(async () => {
loadOptions();
});
</script>
<style lang="less" scoped></style>

View File

@@ -1,57 +1,13 @@
import { h, ref } from 'vue';
import { NTag, NButton } from 'naive-ui';
import { cloneDeep } from 'lodash-es';
import { FormSchema } from '@/components/Form';
import { Dicts } from '@/api/dict/dict';
import { isNullObject } from '@/utils/is';
import { defRangeShortcuts } from '@/utils/dateUtil';
import { format } from 'date-fns';
import { getOptionLabel, getOptionTag, Options } from '@/utils/hotgo';
import { renderIcon, renderTooltip } from '@/utils';
import { renderIcon, renderOptionTag, renderTooltip } from '@/utils';
import { HelpCircleOutline } from '@vicons/ionicons5';
import { useDictStore } from '@/store/modules/dict';
export interface State {
id: number;
env: string;
traceid: string;
levelFormat: string;
content: string;
stack: any;
line: string;
triggerNs: number;
status: number;
createdAt: string;
updatedAt: string;
}
export const defaultState = {
id: 0,
env: '',
traceid: '',
levelFormat: '',
content: '',
stack: null,
line: '',
triggerNs: 0,
status: 1,
createdAt: '',
updatedAt: '',
};
export function newState(state: State | null): State {
if (state !== null) {
return cloneDeep(state);
}
return cloneDeep(defaultState);
}
export const options = ref<Options>({
sys_normal_disable: [],
sys_log_type: [],
});
export const rules = {};
const dict = useDictStore();
export const schemas = ref<FormSchema[]>([
{
@@ -65,6 +21,17 @@ export const schemas = ref<FormSchema[]>([
},
},
},
{
field: 'content',
component: 'NInput',
label: '日志内容',
componentProps: {
placeholder: '请输入日志内容关键词',
onUpdateValue: (e: any) => {
console.log(e);
},
},
},
{
field: 'levelFormat',
component: 'NSelect',
@@ -72,7 +39,7 @@ export const schemas = ref<FormSchema[]>([
defaultValue: null,
componentProps: {
placeholder: '请选择日志级别',
options: [],
options: dict.getOption('sys_log_type'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -138,22 +105,7 @@ export const columns = [
title: '日志级别',
key: 'levelFormat',
render(row) {
if (isNullObject(row.levelFormat)) {
return ``;
}
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.sys_log_type, row.levelFormat),
bordered: false,
},
{
default: () => getOptionLabel(options.value.sys_log_type, row.levelFormat),
}
);
return renderOptionTag('sys_log_type', row.levelFormat);
},
width: 120,
},
@@ -162,11 +114,6 @@ export const columns = [
key: 'content',
width: 320,
},
// {
// title: '调用行',
// key: 'line',
// width: 150,
// },
{
title: '触发时间',
key: 'triggerNs',
@@ -185,20 +132,6 @@ export const columns = [
},
];
async function loadOptions() {
options.value = await Dicts({
types: ['sys_normal_disable', 'sys_log_type'],
});
for (const item of schemas.value) {
switch (item.field) {
case 'status':
item.componentProps.options = options.value.sys_normal_disable;
break;
case 'levelFormat':
item.componentProps.options = options.value.sys_log_type;
break;
}
}
export function loadOptions() {
dict.loadOptions(['sys_normal_disable', 'sys_log_type']);
}
await loadOptions();

View File

@@ -43,7 +43,7 @@
</n-gi>
<n-gi span="2">
<n-form-item label="测试分类" path="categoryId">
<n-select v-model:value="formValue.categoryId" :options="options.testCategoryOption" />
<n-select v-model:value="formValue.categoryId" :options="dict.getOptionUnRef('testCategoryOption')" />
</n-form-item>
</n-gi>
<n-gi span="2">
@@ -58,7 +58,7 @@
</n-gi>
<n-gi span="1">
<n-form-item label="状态" path="status">
<n-select v-model:value="formValue.status" :options="options.sys_normal_disable" />
<n-select v-model:value="formValue.status" :options="dict.getOptionUnRef('sys_normal_disable')" />
</n-form-item>
</n-gi>
</n-grid>
@@ -81,8 +81,9 @@
<script lang="ts" setup>
import { ref, computed } from 'vue';
import { useDictStore } from '@/store/modules/dict';
import { Edit, View, MaxSort } from '@/api/normalTreeDemo';
import { options, State, newState, treeOption, loadTreeOption, rules } from './model';
import { State, newState, treeOption, loadTreeOption, rules } from './model';
import { useProjectSettingStore } from '@/store/modules/projectSetting';
import { useMessage } from 'naive-ui';
import { adaModalWidth } from '@/utils/hotgo';
@@ -90,6 +91,7 @@
const emit = defineEmits(['reloadTable']);
const message = useMessage();
const settingStore = useProjectSettingStore();
const dict = useDictStore();
const loading = ref(false);
const showModal = ref(false);
const formValue = ref<State>(newState(null));
@@ -131,25 +133,28 @@
});
}
// 提交表单
function confirmForm(e) {
e.preventDefault();
formBtnLoading.value = true;
formRef.value.validate((errors) => {
if (!errors) {
Edit(formValue.value).then((_res) => {
message.success('操作成功');
setTimeout(() => {
formBtnLoading.value = true;
Edit(formValue.value)
.then((_res) => {
message.success('操作成功');
closeForm();
emit('reloadTable');
})
.finally(() => {
formBtnLoading.value = false;
});
});
} else {
message.error('请填写完整信息');
}
formBtnLoading.value = false;
});
}
// 关闭表单
function closeForm() {
showModal.value = false;
loading.value = false;

View File

@@ -11,7 +11,7 @@
<n-input v-model:value="model[field]" />
</template>
</BasicForm>
<BasicTable ref="actionRef" openChecked :columns="columns" :request="loadDataTable" :row-key="(row) => row.id" :actionColumn="actionColumn" :scroll-x="1280" :resizeHeightOffset="-10000" :cascade="false" :expanded-row-keys="expandedKeys" @update:expanded-row-keys="updateExpandedKeys" :checked-row-keys="checkedIds" @update:checked-row-keys="handleOnCheckedRow">
<BasicTable ref="actionRef" openChecked :columns="columns" :request="loadDataTable" :row-key="(row) => row.id" :actionColumn="actionColumn" :scroll-x="scrollX" :resizeHeightOffset="-10000" :cascade="false" :expanded-row-keys="expandedKeys" @update:expanded-row-keys="updateExpandedKeys" :checked-row-keys="checkedIds" @update:checked-row-keys="handleOnCheckedRow">
<template #tableTitle>
<n-button type="primary" @click="addTable" class="min-left-space" v-if="hasPermission(['/normalTreeDemo/edit'])">
<template #icon>
@@ -47,15 +47,16 @@
</template>
<script lang="ts" setup>
import { h, reactive, ref, onMounted } from 'vue';
import { h, reactive, ref, computed, onMounted } from 'vue';
import { useDialog, useMessage } from 'naive-ui';
import { BasicTable, TableAction } from '@/components/Table';
import { BasicForm, useForm } from '@/components/Form/index';
import { usePermission } from '@/hooks/web/usePermission';
import { useDictStore } from '@/store/modules/dict';
import { List, Delete } from '@/api/normalTreeDemo';
import { PlusOutlined, DeleteOutlined, AlignLeftOutlined } from '@vicons/antd';
import { columns, schemas, loadOptions, newState } from './model';
import { convertListToTree } from '@/utils/hotgo';
import { adaTableScrollX, convertListToTree } from '@/utils/hotgo';
import Edit from './edit.vue';
const dialog = useDialog();
@@ -63,8 +64,9 @@
const { hasPermission } = usePermission();
const actionRef = ref();
const searchFormRef = ref<any>({});
const viewRef = ref();
const editRef = ref();
const dict = useDictStore();
const checkedIds = ref([]);
const expandedKeys = ref([]);
const allTreeKeys = ref([]);
@@ -100,6 +102,10 @@
},
});
const scrollX = computed(() => {
return adaTableScrollX(columns, actionColumn.width);
});
const [register, {}] = useForm({
gridProps: { cols: '1 s:1 m:2 l:3 xl:4 2xl:4' },
labelWidth: 80,
@@ -196,6 +202,7 @@
onMounted(() => {
loadOptions();
});
</script>

View File

@@ -2,12 +2,13 @@ import { h, ref } from 'vue';
import { NTag } from 'naive-ui';
import { cloneDeep } from 'lodash-es';
import { FormSchema } from '@/components/Form';
import { Dicts } from '@/api/dict/dict';
import { isNullObject } from '@/utils/is';
import { defRangeShortcuts } from '@/utils/dateUtil';
import { Option, getOptionLabel, getOptionTag } from '@/utils/hotgo';
import { renderPopoverMemberSumma, MemberSumma } from '@/utils';
import { TreeOption } from '@/api/normalTreeDemo';
import { useDictStore } from '@/store/modules/dict';
const dict = useDictStore();
export class State {
public title = ''; // 标题
@@ -73,7 +74,7 @@ export const schemas = ref<FormSchema[]>([
defaultValue: null,
componentProps: {
placeholder: '请选择测试分类',
options: [],
options: dict.getOption('testCategoryOption'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -86,7 +87,7 @@ export const schemas = ref<FormSchema[]>([
defaultValue: null,
componentProps: {
placeholder: '请选择状态',
options: [],
options: dict.getOption('sys_normal_disable'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -130,11 +131,11 @@ export const columns = [
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.testCategoryOption, row.categoryId),
type: dict.getType('testCategoryOption', row.categoryId),
bordered: false,
},
{
default: () => getOptionLabel(options.value.testCategoryOption, row.categoryId),
default: () => dict.getLabel('testCategoryOption', row.categoryId),
}
);
},
@@ -160,11 +161,11 @@ export const columns = [
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.sys_normal_disable, row.status),
type: dict.getType('sys_normal_disable', row.status),
bordered: false,
},
{
default: () => getOptionLabel(options.value.sys_normal_disable, row.status),
default: () => dict.getLabel('sys_normal_disable', row.status),
}
);
},
@@ -186,29 +187,9 @@ export const columns = [
},
];
// 字典数据选项
export const options = ref({
sys_normal_disable: [] as Option[],
testCategoryOption: [] as Option[],
});
// 加载字典数据选项
export function loadOptions() {
Dicts({
types: ['sys_normal_disable', 'testCategoryOption'],
}).then((res) => {
options.value = res;
for (const item of schemas.value) {
switch (item.field) {
case 'status':
item.componentProps.options = options.value.sys_normal_disable;
break;
case 'categoryId':
item.componentProps.options = options.value.testCategoryOption;
break;
}
}
});
dict.loadOptions(['sys_normal_disable', 'testCategoryOption']);
}
// 关系树选项

View File

@@ -1,92 +0,0 @@
<template>
<div>
<n-drawer v-model:show="showModal" :width="dialogWidth">
<n-drawer-content title="普通树表详情" closable>
<n-spin :show="loading" description="请稍候...">
<n-descriptions label-placement="left" class="py-2" column="1">
<n-descriptions-item>
<template #label>
标题
</template>
{{ formValue.title }}
</n-descriptions-item>
<n-descriptions-item>
<template #label>
上级
</template>
{{ formValue.pid }}
</n-descriptions-item>
<n-descriptions-item label="测试分类">
<n-tag :type="getOptionTag(options.testCategoryOption, formValue?.categoryId)" size="small" class="min-left-space">
{{ getOptionLabel(options.testCategoryOption, formValue?.categoryId) }}
</n-tag>
</n-descriptions-item>
<n-descriptions-item>
<template #label>
描述
</template>
{{ formValue.description }}
</n-descriptions-item>
<n-descriptions-item>
<template #label>
排序
</template>
{{ formValue.sort }}
</n-descriptions-item>
<n-descriptions-item label="状态">
<n-tag :type="getOptionTag(options.sys_normal_disable, formValue?.status)" size="small" class="min-left-space">
{{ getOptionLabel(options.sys_normal_disable, formValue?.status) }}
</n-tag>
</n-descriptions-item>
</n-descriptions>
</n-spin>
</n-drawer-content>
</n-drawer>
</div>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue';
import { useMessage } from 'naive-ui';
import { View } from '@/api/normalTreeDemo';
import { State, newState, options } from './model';
import { adaModalWidth, getOptionLabel, getOptionTag } from '@/utils/hotgo';
import { getFileExt } from '@/utils/urlUtils';
const message = useMessage();
const loading = ref(false);
const showModal = ref(false);
const formValue = ref(newState(null));
const dialogWidth = computed(() => {
return adaModalWidth(580);
});
const fileAvatarCSS = computed(() => {
return {
'--n-merged-size': `var(--n-avatar-size-override, 80px)`,
'--n-font-size': `18px`,
};
});
//下载
function download(url: string) {
window.open(url);
}
function openModal(state: State) {
showModal.value = true;
loading.value = true;
View({ id: state.id })
.then((res) => {
formValue.value = res;
})
.finally(() => {
loading.value = false;
});
}
defineExpose({
openModal,
});
</script>
<style lang="less" scoped></style>

View File

@@ -43,12 +43,12 @@
</n-gi>
<n-gi span="2">
<n-form-item label="测试分类" path="categoryId">
<n-select v-model:value="formValue.categoryId" :options="options.testCategoryOption" />
<n-select v-model:value="formValue.categoryId" :options="dict.getOptionUnRef('testCategoryOption')" />
</n-form-item>
</n-gi>
<n-gi span="2">
<n-form-item label="描述" path="description">
<n-input type="textarea" placeholder="描述" v-model:value="formValue.description" />
<n-input placeholder="请输入描述" v-model:value="formValue.description" />
</n-form-item>
</n-gi>
<n-gi span="1">
@@ -58,7 +58,7 @@
</n-gi>
<n-gi span="1">
<n-form-item label="状态" path="status">
<n-select v-model:value="formValue.status" :options="options.sys_normal_disable" />
<n-select v-model:value="formValue.status" :options="dict.getOptionUnRef('sys_normal_disable')" />
</n-form-item>
</n-gi>
</n-grid>
@@ -81,8 +81,9 @@
<script lang="ts" setup>
import { ref, computed } from 'vue';
import { useDictStore } from '@/store/modules/dict';
import { Edit, View, MaxSort } from '@/api/optionTreeDemo';
import { options, State, newState, treeOption, loadTreeOption, rules } from './model';
import { State, newState, treeOption, loadTreeOption, rules } from './model';
import { useProjectSettingStore } from '@/store/modules/projectSetting';
import { useMessage } from 'naive-ui';
import { adaModalWidth } from '@/utils/hotgo';
@@ -90,6 +91,7 @@
const emit = defineEmits(['reloadTable']);
const message = useMessage();
const settingStore = useProjectSettingStore();
const dict = useDictStore();
const loading = ref(false);
const showModal = ref(false);
const formValue = ref<State>(newState(null));
@@ -99,6 +101,34 @@
return adaModalWidth(840);
});
// 提交表单
function confirmForm(e) {
e.preventDefault();
formRef.value.validate((errors) => {
if (!errors) {
formBtnLoading.value = true;
Edit(formValue.value)
.then((_res) => {
message.success('操作成功');
closeForm();
emit('reloadTable');
})
.finally(() => {
formBtnLoading.value = false;
});
} else {
message.error('请填写完整信息');
}
});
}
// 关闭表单
function closeForm() {
showModal.value = false;
loading.value = false;
}
// 打开模态框
function openModal(state: State) {
showModal.value = true;
@@ -131,30 +161,6 @@
});
}
function confirmForm(e) {
e.preventDefault();
formBtnLoading.value = true;
formRef.value.validate((errors) => {
if (!errors) {
Edit(formValue.value).then((_res) => {
message.success('操作成功');
setTimeout(() => {
closeForm();
emit('reloadTable');
});
});
} else {
message.error('请填写完整信息');
}
formBtnLoading.value = false;
});
}
function closeForm() {
showModal.value = false;
loading.value = false;
}
defineExpose({
openModal,
});

View File

@@ -30,7 +30,7 @@
</template>
编辑
</n-button>
<n-button v-if="hasPermission(['/optionTreeDemo/delete'])" type="error" icon-placement="left" @click="handleEdit(selectedState)" :disabled="selectedState.id < 1">
<n-button v-if="hasPermission(['/optionTreeDemo/delete'])" type="error" icon-placement="left" @click="handleDelete(selectedState)" :disabled="selectedState.id < 1">
<template #icon>
<div class="flex items-center">
<n-icon size="14">
@@ -135,12 +135,14 @@
import { BasicTable, TableAction } from '@/components/Table';
import { BasicForm, useForm } from '@/components/Form/index';
import { usePermission } from '@/hooks/web/usePermission';
import { useDictStore } from '@/store/modules/dict';
import { List, Delete, TreeOption } from '@/api/optionTreeDemo';
import { PlusOutlined, EditOutlined, DeleteOutlined, AlignLeftOutlined, FormOutlined, SearchOutlined } from '@vicons/antd';
import { columns, schemas, loadOptions, loadTreeOption, treeOption, State, newState } from './model';
import { adaTableScrollX, getTreeKeys } from '@/utils/hotgo';
import Edit from './edit.vue';
const dict = useDictStore();
const dialog = useDialog();
const message = useMessage();
const { hasPermission } = usePermission();
@@ -160,7 +162,7 @@
title: '操作',
key: 'action',
fixed: 'right',
render(record) {
render(record: State) {
return h(TableAction as any, {
style: 'button',
actions: [
@@ -274,6 +276,7 @@
});
}
// 选中树节点
function handleSelected(keys, option) {
if (keys.length) {
selectedState.value = newState(option[0]);
@@ -283,10 +286,12 @@
}
}
// 展开指定节点
function handleOnExpandedKeys(keys) {
expandedKeys.value = keys;
}
// 展开全部节点
function handleAllExpanded() {
if (expandedKeys.value.length) {
expandedKeys.value = [];

View File

@@ -1,20 +1,19 @@
import { h, ref } from 'vue';
import { NTag } from 'naive-ui';
import { cloneDeep } from 'lodash-es';
import { FormSchema } from '@/components/Form';
import { Dicts } from '@/api/dict/dict';
import { isNullObject } from '@/utils/is';
import { defRangeShortcuts } from '@/utils/dateUtil';
import { Option, getOptionLabel, getOptionTag } from '@/utils/hotgo';
import { renderPopoverMemberSumma, MemberSumma } from '@/utils';
import { renderOptionTag, renderPopoverMemberSumma, MemberSumma } from '@/utils';
import { TreeOption } from '@/api/optionTreeDemo';
import { useDictStore } from '@/store/modules/dict';
const dict = useDictStore();
export class State {
public title = ''; // 标题
public id = 0; // ID
public pid = 0; // 上级
public level = 1; // 关系树级别
public tree = ''; // 关系树
public tree = null; // 关系树
public categoryId = null; // 测试分类
public description = ''; // 描述
public sort = 0; // 排序
@@ -73,7 +72,7 @@ export const schemas = ref<FormSchema[]>([
defaultValue: null,
componentProps: {
placeholder: '请选择测试分类',
options: [],
options: dict.getOption('testCategoryOption'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -86,7 +85,7 @@ export const schemas = ref<FormSchema[]>([
defaultValue: null,
componentProps: {
placeholder: '请选择状态',
options: [],
options: dict.getOption('sys_normal_disable'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -120,23 +119,8 @@ export const columns = [
key: 'categoryId',
align: 'left',
width: 100,
render(row) {
if (isNullObject(row.categoryId)) {
return ``;
}
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.testCategoryOption, row.categoryId),
bordered: false,
},
{
default: () => getOptionLabel(options.value.testCategoryOption, row.categoryId),
}
);
render(row: State) {
return renderOptionTag('testCategoryOption', row.categoryId);
},
},
{
@@ -144,23 +128,8 @@ export const columns = [
key: 'status',
align: 'left',
width: 150,
render(row) {
if (isNullObject(row.status)) {
return ``;
}
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.sys_normal_disable, row.status),
bordered: false,
},
{
default: () => getOptionLabel(options.value.sys_normal_disable, row.status),
}
);
render(row: State) {
return renderOptionTag('sys_normal_disable', row.status);
},
},
{
@@ -168,7 +137,7 @@ export const columns = [
key: 'createdBy',
align: 'left',
width: 100,
render(row) {
render(row: State) {
return renderPopoverMemberSumma(row.createdBySumma);
},
},
@@ -180,29 +149,9 @@ export const columns = [
},
];
// 字典数据选项
export const options = ref({
sys_normal_disable: [] as Option[],
testCategoryOption: [] as Option[],
});
// 加载字典数据选项
export function loadOptions() {
Dicts({
types: ['sys_normal_disable', 'testCategoryOption'],
}).then((res) => {
options.value = res;
for (const item of schemas.value) {
switch (item.field) {
case 'status':
item.componentProps.options = options.value.sys_normal_disable;
break;
case 'categoryId':
item.componentProps.options = options.value.testCategoryOption;
break;
}
}
});
dict.loadOptions(['sys_normal_disable', 'testCategoryOption']);
}
// 关系树选项

View File

@@ -1,92 +0,0 @@
<template>
<div>
<n-drawer v-model:show="showModal" :width="dialogWidth">
<n-drawer-content title="选项树表详情" closable>
<n-spin :show="loading" description="请稍候...">
<n-descriptions label-placement="left" class="py-2" column="1">
<n-descriptions-item>
<template #label>
标题
</template>
{{ formValue.title }}
</n-descriptions-item>
<n-descriptions-item>
<template #label>
上级
</template>
{{ formValue.pid }}
</n-descriptions-item>
<n-descriptions-item label="测试分类">
<n-tag :type="getOptionTag(options.testCategoryOption, formValue?.categoryId)" size="small" class="min-left-space">
{{ getOptionLabel(options.testCategoryOption, formValue?.categoryId) }}
</n-tag>
</n-descriptions-item>
<n-descriptions-item>
<template #label>
描述
</template>
{{ formValue.description }}
</n-descriptions-item>
<n-descriptions-item>
<template #label>
排序
</template>
{{ formValue.sort }}
</n-descriptions-item>
<n-descriptions-item label="状态">
<n-tag :type="getOptionTag(options.sys_normal_disable, formValue?.status)" size="small" class="min-left-space">
{{ getOptionLabel(options.sys_normal_disable, formValue?.status) }}
</n-tag>
</n-descriptions-item>
</n-descriptions>
</n-spin>
</n-drawer-content>
</n-drawer>
</div>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue';
import { useMessage } from 'naive-ui';
import { View } from '@/api/optionTreeDemo';
import { State, newState, options } from './model';
import { adaModalWidth, getOptionLabel, getOptionTag } from '@/utils/hotgo';
import { getFileExt } from '@/utils/urlUtils';
const message = useMessage();
const loading = ref(false);
const showModal = ref(false);
const formValue = ref(newState(null));
const dialogWidth = computed(() => {
return adaModalWidth(580);
});
const fileAvatarCSS = computed(() => {
return {
'--n-merged-size': `var(--n-avatar-size-override, 80px)`,
'--n-font-size': `18px`,
};
});
//下载
function download(url: string) {
window.open(url);
}
function openModal(state: State) {
showModal.value = true;
loading.value = true;
View({ id: state.id })
.then((res) => {
formValue.value = res;
})
.finally(() => {
loading.value = false;
});
}
defineExpose({
openModal,
});
</script>
<style lang="less" scoped></style>

View File

@@ -50,7 +50,7 @@
<n-form-item label="部门类型" path="type">
<n-radio-group v-model:value="formValue.type" name="type">
<n-space>
<n-radio v-for="item in options.deptType" :value="item.value">
<n-radio v-for="item in dict.getOptionUnRef('deptType')" :value="item.value">
{{ item.label }}
</n-radio>
</n-space>
@@ -86,7 +86,7 @@
<n-form-item label="状态" path="status">
<n-radio-group v-model:value="formValue.status" name="status">
<n-radio-button
v-for="status in options.sys_normal_disable"
v-for="status in dict.getOptionUnRef('sys_normal_disable')"
:key="status.value"
:value="status.value"
:label="status.label"
@@ -111,14 +111,16 @@
<script lang="ts" setup>
import { ref, computed } from 'vue';
import { Edit, View, MaxSort } from '@/api/org/dept';
import { options, State, newState, treeOption, loadTreeOption, rules } from './model';
import { State, newState, treeOption, loadTreeOption, rules } from './model';
import { useProjectSettingStore } from '@/store/modules/projectSetting';
import { useMessage } from 'naive-ui';
import { adaModalWidth } from '@/utils/hotgo';
import { useDictStore } from '@/store/modules/dict';
const emit = defineEmits(['reloadTable']);
const message = useMessage();
const settingStore = useProjectSettingStore();
const dict = useDictStore();
const loading = ref(false);
const showModal = ref(false);
const formValue = ref<State>(newState(null));

View File

@@ -2,14 +2,15 @@ import { h, ref } from 'vue';
import { NTag, NButton } from 'naive-ui';
import { cloneDeep } from 'lodash-es';
import { FormSchema } from '@/components/Form';
import { Dicts } from '@/api/dict/dict';
import { defRangeShortcuts } from '@/utils/dateUtil';
import { validate } from '@/utils/validateUtil';
import { Option, getOptionLabel, getOptionTag } from '@/utils/hotgo';
import { renderTooltip, renderIcon } from '@/utils';
import { renderTooltip, renderIcon, renderOptionTag } from '@/utils';
import { HelpCircleOutline } from '@vicons/ionicons5';
import { TreeOption } from '@/api/org/dept';
import { isNullObject } from '@/utils/is';
import { useDictStore } from '@/store/modules/dict';
import type { FormRules } from 'naive-ui/es/form/src/interface';
const dict = useDictStore();
export class State {
public id = 0; // 部门ID
@@ -45,7 +46,7 @@ export function newState(state: State | Record<string, any> | null): State {
}
// 表单验证规则
export const rules = {
export const rules: FormRules = {
email: {
required: false,
trigger: ['blur', 'input'],
@@ -155,22 +156,7 @@ export const columns = [
align: 'left',
width: 100,
render(row) {
if (isNullObject(row.type)) {
return ``;
}
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.deptType, row.type),
bordered: false,
},
{
default: () => getOptionLabel(options.value.deptType, row.type),
}
);
return renderOptionTag('deptType', row.type);
},
},
{
@@ -189,22 +175,7 @@ export const columns = [
align: 'left',
width: 80,
render(row) {
if (isNullObject(row.status)) {
return ``;
}
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.sys_normal_disable, row.status),
bordered: false,
},
{
default: () => getOptionLabel(options.value.sys_normal_disable, row.status),
}
);
return renderOptionTag('sys_normal_disable', row.status);
},
},
{
@@ -214,26 +185,9 @@ export const columns = [
},
];
// 字典数据选项
export const options = ref({
sys_normal_disable: [] as Option[],
deptType: [] as Option[],
});
// 加载字典数据选项
export function loadOptions() {
Dicts({
types: ['sys_normal_disable', 'deptType'],
}).then((res) => {
options.value = res;
for (const item of schemas.value) {
switch (item.field) {
case 'status':
item.componentProps.options = options.value.sys_normal_disable;
break;
}
}
});
dict.loadOptions(['sys_normal_disable', 'deptType']);
}
// 关系树选项

View File

@@ -20,7 +20,7 @@
ref="actionRef"
:actionColumn="actionColumn"
@update:checked-row-keys="onCheckedRow"
:scroll-x="1500"
:scroll-x="scrollX"
:resizeHeightOffset="-10000"
>
<template #tableTitle>
@@ -108,7 +108,7 @@
<n-form-item label="所属部门" path="deptId">
<n-tree-select
key-field="id"
:options="options.dept"
:options="deptTreeOptions"
:default-value="formParams.deptId"
@update:value="handleUpdateDeptValue"
clearable
@@ -121,7 +121,7 @@
<n-form-item label="绑定角色" path="roleId">
<n-tree-select
key-field="id"
:options="options.role"
:options="roleTreeOptions"
:default-value="formParams.roleId"
@update:value="handleUpdateRoleValue"
clearable
@@ -143,7 +143,7 @@
<n-form-item label="绑定岗位" path="postIds">
<n-select
:default-value="formParams.postIds"
:options="options.post"
:options="dict.getOptionUnRef('adminPostOption')"
@update:value="handleUpdatePostValue"
multiple
clearable
@@ -171,7 +171,7 @@
<n-form-item label="性别" path="sex">
<n-radio-group v-model:value="formParams.sex" name="sex">
<n-radio-button
v-for="status in options.sys_user_sex"
v-for="status in dict.getOptionUnRef('sys_user_sex')"
:key="status.value"
:value="status.value"
:label="status.label"
@@ -183,7 +183,7 @@
<n-form-item label="状态" path="status">
<n-radio-group v-model:value="formParams.status" name="status">
<n-radio-button
v-for="status in options.sys_normal_disable"
v-for="status in dict.getOptionUnRef('sys_normal_disable')"
:key="status.value"
:value="status.value"
:label="status.label"
@@ -207,15 +207,15 @@
</n-modal>
<AddBalance
@reloadTable="reloadTable"
@updateShowModal="updateBalanceShowModal"
@reload-table="reloadTable"
@update-show-modal="updateBalanceShowModal"
:showModal="showBalanceModal"
:formParams="formParams"
/>
<AddIntegral
@reloadTable="reloadTable"
@updateShowModal="updateIntegralShowModal"
@reload-table="reloadTable"
@update-show-modal="updateIntegralShowModal"
:showModal="showIntegralModal"
:formParams="formParams"
/>
@@ -237,25 +237,33 @@
</template>
<script lang="ts" setup>
import { h, reactive, ref, onMounted, computed } from 'vue';
import { h, reactive, ref, computed } from 'vue';
import { useDialog, useMessage } from 'naive-ui';
import { ActionItem, BasicTable, TableAction } from '@/components/Table';
import { BasicForm } from '@/components/Form/index';
import { Delete, Edit, List, Status, ResetPwd } from '@/api/org/user';
import { Delete, Edit, List, ResetPwd } from '@/api/org/user';
import { columns } from './columns';
import { PlusOutlined, DeleteOutlined } from '@vicons/antd';
import { QrCodeOutline } from '@vicons/ionicons5';
import { adaModalWidth } from '@/utils/hotgo';
import { adaModalWidth, adaTableScrollX } from '@/utils/hotgo';
import { getRandomString } from '@/utils/charset';
import { cloneDeep } from 'lodash-es';
import QrcodeVue from 'qrcode.vue';
import AddBalance from './addBalance.vue';
import AddIntegral from './addIntegral.vue';
import { addNewState, addState, options, register, defaultState, loadOptions } from './model';
import {
addNewState,
addState,
register,
defaultState,
deptTreeOptions,
roleTreeOptions,
} from './model';
import { usePermission } from '@/hooks/web/usePermission';
import { useUserStore } from '@/store/modules/user';
import { LoginRoute } from '@/router';
import { getNowUrl } from '@/utils/urlUtils';
import { useDictStore } from '@/store/modules/dict';
interface Props {
type?: string;
@@ -273,6 +281,7 @@
},
};
const dict = useDictStore();
const { hasPermission } = usePermission();
const userStore = useUserStore();
const showIntegralModal = ref(false);
@@ -292,12 +301,13 @@
name: '',
qrUrl: '',
});
const dialogWidth = computed(() => {
return adaModalWidth();
});
const actionColumn = reactive({
width: 280,
width: 200,
title: '操作',
key: 'action',
fixed: 'right',
@@ -306,22 +316,6 @@
return h(TableAction as any, {
style: 'button',
actions: [
{
label: '已启用',
onClick: handleStatus.bind(null, record, 2),
ifShow: () => {
return record.status === 1 && record.id !== 1;
},
auth: ['/member/status'],
},
{
label: '已禁用',
onClick: handleStatus.bind(null, record, 1),
ifShow: () => {
return record.status === 2 && record.id !== 1;
},
auth: ['/member/status'],
},
{
label: '编辑',
onClick: handleEdit.bind(null, record),
@@ -362,6 +356,10 @@
},
});
const scrollX = computed(() => {
return adaTableScrollX(columns, actionColumn.width);
});
function getDropDownActions(record: Recordable): ActionItem[] {
if (record.id === 1) {
return [];
@@ -488,15 +486,6 @@
reloadTable();
}
function handleStatus(record: Recordable, status) {
Status({ id: record.id, status: status }).then((_res) => {
message.success('操作成功');
setTimeout(() => {
reloadTable();
});
});
}
function handleUpdateDeptValue(value) {
formParams.value.deptId = Number(value);
}
@@ -532,10 +521,6 @@
qrParams.value.qrUrl = domain + LoginRoute.path + '?scope=register&inviteCode=' + code;
showQrModal.value = true;
}
onMounted(async () => {
await loadOptions();
});
</script>
<style lang="less" scoped></style>

View File

@@ -3,12 +3,13 @@ import { ref } from 'vue';
import { getDeptOption } from '@/api/org/dept';
import { getRoleOption } from '@/api/system/role';
import { FormSchema, useForm } from '@/components/Form';
import { statusOptions } from '@/enums/optionsiEnum';
import { defRangeShortcuts } from '@/utils/dateUtil';
import { Dicts } from '@/api/dict/dict';
import { useDictStore, Option } from '@/store/modules/dict';
// 增加余额/积分.
const dict = useDictStore();
export interface addState {
id: number;
username: string;
@@ -166,7 +167,7 @@ const schemas: FormSchema[] = [
defaultValue: null,
componentProps: {
placeholder: '请选择类型',
options: statusOptions,
options: dict.getOption('sys_normal_disable'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -193,42 +194,44 @@ export const [register, {}] = useForm({
schemas,
});
export const options = ref<any>({
role: [],
roleTabs: [{ id: -1, name: '全部' }],
dept: [],
post: [],
sys_user_sex: [],
sys_normal_disable: [],
});
export const deptTreeOptions = ref([]);
export const roleTreeOptions = ref([]);
export async function loadOptions() {
const dept = await getDeptOption();
if (dept.list) {
options.value.dept = dept.list;
}
dict.loadOptions(['adminPostOption', 'sys_user_sex', 'sys_normal_disable']);
const role = await getRoleOption();
if (role.list) {
options.value.role = role.list;
options.value.roleTabs = [{ id: -1, name: '全部' }];
treeDataToCompressed(role.list);
}
const tmpOptions = await Dicts({
types: ['adminPostOption', 'sys_user_sex', 'sys_normal_disable'],
getDeptOption().then((res) => {
if (res.list) {
deptTreeOptions.value = res.list;
}
});
getRoleOption().then((res) => {
if (res.list) {
roleTreeOptions.value = res.list;
registerRoleTabsOption();
}
});
options.value.post = tmpOptions?.adminPostOption;
options.value.sys_user_sex = tmpOptions?.sys_user_sex;
options.value.sys_normal_disable = tmpOptions?.sys_normal_disable;
}
function treeDataToCompressed(source) {
// 将角色Tabs选项注册到字典
function registerRoleTabsOption() {
const items = [{ id: -1, name: '全部' }];
treeDataToCompressed(items, roleTreeOptions.value);
const roleTabs: Option[] = [];
for (const item of items) {
roleTabs.push(dict.genOption(item.id, item.name));
}
dict.setOption('roleTabs', roleTabs);
}
function treeDataToCompressed(items: any[], source: any) {
for (const i in source) {
options.value.roleTabs.push(source[i]);
items.push(source[i]);
source[i].children && source[i].children.length > 0
? treeDataToCompressed(source[i].children)
? treeDataToCompressed(items, source[i].children)
: ''; // 子级递归
}
return options.value.roleTabs;
return items;
}

View File

@@ -12,9 +12,9 @@
@before-leave="handleBeforeLeave"
>
<n-tab-pane
:name="item.id.toString()"
:tab="item.name"
v-for="item in options.roleTabs"
:name="item.key.toString()"
:tab="item.label"
v-for="item in dict.getOptionUnRef('roleTabs')"
:key="item.key"
>
<List :type="defaultTab" />
@@ -28,8 +28,10 @@
import { onMounted, ref } from 'vue';
import List from './list.vue';
import { useRouter } from 'vue-router';
import { options } from './model';
import { loadOptions } from './model';
import { useDictStore } from '@/store/modules/dict';
const dict = useDictStore();
const router = useRouter();
const defaultTab = ref('-1');
@@ -37,6 +39,7 @@
if (router.currentRoute.value.query?.type) {
defaultTab.value = router.currentRoute.value.query.type as string;
}
loadOptions();
});
function handleBeforeLeave(tabName: string): boolean | Promise<boolean> {

View File

@@ -17,7 +17,7 @@
:on-update:value="handleUpdateType"
>
<n-radio-button
v-for="menuType in options.sys_menu_types"
v-for="menuType in dict.getOptionUnRef('sys_menu_types')"
:key="menuType.value"
:value="menuType.value"
:label="menuType.label"
@@ -91,7 +91,7 @@
<n-form-item label="目录组件" path="component">
<n-select
v-if="formParams.type === 1"
:options="options.sys_menu_component"
:options="dict.getOptionUnRef('sys_menu_component')"
v-model:value="formParams.component"
placeholder="请选择目录组件"
clearable
@@ -159,7 +159,7 @@
<n-input-group>
<n-select
:style="{ width: '33%', minWidth: '80px' }"
:options="options.sys_switch"
:options="dict.getOptionUnRef('sys_switch')"
v-model:value="formParams.isFrame"
/>
<n-input
@@ -173,7 +173,7 @@
<n-form-item label="菜单状态" path="status">
<n-radio-group v-model:value="formParams.status" name="status">
<n-radio-button
v-for="status in options.sys_normal_disable"
v-for="status in dict.getOptionUnRef('sys_normal_disable')"
:key="status.value"
:value="status.value"
:label="status.label"
@@ -210,13 +210,15 @@
import { QuestionCircleOutlined } from '@vicons/antd';
import IconSelector from '@/components/IconSelector/index.vue';
import { computed, ref } from 'vue';
import { newState, State, options } from '@/views/permission/menu/model';
import { newState, State } from '@/views/permission/menu/model';
import { FormItemRule, useDialog, useMessage } from 'naive-ui';
import { cloneDeep } from 'lodash-es';
import { DeleteMenu, EditMenu } from '@/api/system/menu';
import { findTreeNode } from '@/utils';
import { useDictStore } from '@/store/modules/dict';
import type { FormRules } from 'naive-ui/es/form/src/interface';
const rules = {
const rules: FormRules = {
title: {
required: true,
message: '请输入名称',
@@ -231,15 +233,17 @@
required: false,
message: '请输入路由地址',
trigger: 'blur',
validator: function (_rule: FormItemRule, value: any, callback: Function) {
validator: function (_rule: FormItemRule, value: any, callback: Function): boolean | Error {
if (formParams.value.type != 3 && !value) {
callback(new Error('请输入路由地址'));
}
return true;
},
},
};
const emit = defineEmits(['reloadTable', 'closeForm']);
const dict = useDictStore();
const message = useMessage();
const dialog = useDialog();
const loading = ref(false);

View File

@@ -21,14 +21,14 @@
import { computed, ref } from 'vue';
import Menu from './menu.vue';
import { adaModalWidth } from '@/utils/hotgo';
const emit = defineEmits(['reloadTable']);
const showModal = ref(false);
const isModal = ref(true);
const dialogWidth = computed(() => {
return adaModalWidth(1280);
});
const emit = defineEmits(['reloadTable']);
function openModal() {
showModal.value = true;
}

View File

@@ -1,11 +1,11 @@
import { ref } from 'vue';
import { cloneDeep } from 'lodash-es';
import { Option } from '@/utils/hotgo';
import { Dicts } from '@/api/dict/dict';
import { useDictStore } from '@/store/modules/dict';
const dict = useDictStore();
export interface State {
id: number;
pid?: number;
pid?: number | null;
title: string;
name: string;
path: string;
@@ -15,7 +15,7 @@ export interface State {
redirect: string;
permissions: string;
permissionName: string;
component?: string;
component?: string | null;
alwaysShow: number;
activeMenu: string;
isRoot: number;
@@ -27,7 +27,7 @@ export interface State {
status: number;
sort: number;
disabled: boolean;
children?: State[];
children?: State[] | null;
}
export const defaultState: State = {
@@ -66,7 +66,10 @@ export function newState(state: State | null): State {
// 默认值校正,主要为了解决历史数据格式不规范问题
export function defaultValueCheck(state: State): State {
if (state.pid < 1) {
if (!state) {
state = newState(null);
}
if (!state.pid || state.pid < 1) {
state.pid = null;
}
if (state.alwaysShow != 1) {
@@ -93,19 +96,7 @@ export function defaultValueCheck(state: State): State {
return state;
}
// 字典数据选项
export const options = ref({
sys_menu_types: [] as Option[],
sys_menu_component: [] as Option[],
sys_normal_disable: [] as Option[],
sys_switch: [] as Option[],
});
// 加载字典数据选项
export function loadOptions() {
Dicts({
types: ['sys_menu_types', 'sys_menu_component', 'sys_normal_disable', 'sys_switch'],
}).then((res) => {
options.value = res;
});
dict.loadOptions(['sys_menu_types', 'sys_menu_component', 'sys_normal_disable', 'sys_switch']);
}

View File

@@ -73,7 +73,7 @@
<n-form-item label="状态" path="status">
<n-radio-group v-model:value="formParams.status" name="status">
<n-radio-button
v-for="status in blacklistOptions"
v-for="status in dict.getOptionUnRef('BlacklistStatusOptions')"
:key="status.value"
:value="status.value"
:label="status.label"
@@ -98,31 +98,18 @@
</template>
<script lang="ts" setup>
import { h, reactive, ref } from 'vue';
import { NTag, useDialog, useMessage } from 'naive-ui';
import { h, onMounted, reactive, ref } from 'vue';
import { useDialog, useMessage } from 'naive-ui';
import { BasicTable, TableAction } from '@/components/Table';
import { BasicForm, FormSchema, useForm } from '@/components/Form/index';
import { Delete, Edit, List, Status } from '@/api/sys/blacklist';
import { DeleteOutlined, PlusOutlined } from '@vicons/antd';
import { statusActions } from '@/enums/optionsiEnum';
import { getOptionLabel, getOptionTag, Option } from '@/utils/hotgo';
import { defRangeShortcuts } from '@/utils/dateUtil';
import { useDictStore } from '@/store/modules/dict';
import { renderOptionTag } from '@/utils';
const blacklistOptions: Option[] = [
{
key: 1,
value: 1,
label: '封禁中',
listClass: 'warning',
},
{
key: 2,
value: 2,
label: '已解封',
listClass: 'success',
},
];
const dict = useDictStore();
const columns = [
{
title: 'ID',
@@ -140,19 +127,7 @@
title: '状态',
key: 'status',
render(row) {
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: getOptionTag(blacklistOptions, row.status),
bordered: false,
},
{
default: () => getOptionLabel(blacklistOptions, row.status),
}
);
return renderOptionTag('BlacklistStatusOptions', row.status);
},
},
{
@@ -190,7 +165,7 @@
defaultValue: null,
componentProps: {
placeholder: '请选择类型',
options: blacklistOptions,
options: dict.getOption('BlacklistStatusOptions'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -240,13 +215,13 @@
sort: 0,
status: 1,
};
let formParams = ref<any>(resetFormParams);
const formParams = ref<any>(resetFormParams);
const actionColumn = reactive({
width: 220,
width: 150,
title: '操作',
key: 'action',
// fixed: 'right',
fixed: 'right',
render(record) {
return h(TableAction as any, {
style: 'button',
@@ -260,10 +235,6 @@
onClick: handleDelete.bind(null, record),
},
],
dropDownActions: statusActions,
select: (key) => {
updateStatus(record.id, key);
},
});
},
});
@@ -284,7 +255,6 @@
};
function onCheckedRow(rowKeys) {
console.log(rowKeys);
batchDeleteDisabled.value = rowKeys.length <= 0;
checkedIds.value = rowKeys;
}
@@ -334,9 +304,6 @@
reloadTable();
});
},
onNegativeClick: () => {
// message.error('取消');
},
});
}
@@ -356,9 +323,6 @@
message.error(e.message ?? '操作失败');
});
},
onNegativeClick: () => {
// message.error('取消');
},
});
}
@@ -372,14 +336,9 @@
reloadTable();
}
function updateStatus(id, status) {
Status({ id: id, status: status }).then((_res) => {
message.success('操作成功');
setTimeout(() => {
reloadTable();
});
});
}
onMounted(() => {
dict.loadOptions(['BlacklistStatusOptions']);
});
</script>
<style lang="less" scoped></style>

View File

@@ -119,7 +119,10 @@
class="py-4"
>
<n-form-item label="事件模板" path="event">
<n-select :options="options.config_sms_template" v-model:value="formParams.event" />
<n-select
:options="dict.getOptionUnRef('config_sms_template')"
v-model:value="formParams.event"
/>
</n-form-item>
<n-form-item label="手机号" path="mobile">
@@ -153,8 +156,7 @@
import { ref, onMounted } from 'vue';
import { useMessage } from 'naive-ui';
import { getConfig, sendTestSms, updateConfig } from '@/api/sys/config';
import { Dicts } from '@/api/dict/dict';
import { Options } from '@/utils/hotgo';
import { useDictStore } from '@/store/modules/dict';
const group = ref('pay');
const show = ref(false);
@@ -165,11 +167,7 @@
const formTestRef = ref<any>();
const formRef: any = ref(null);
const message = useMessage();
const options = ref<Options>({
config_sms_template: [],
config_sms_drive: [],
});
const dict = useDictStore();
const formValue = ref({
payDebug: true,
@@ -188,11 +186,6 @@
payQQPayApiKey: '',
});
function sendTest() {
showModal.value = true;
formBtnLoading.value = false;
}
function formSubmit() {
formRef.value.validate((errors) => {
if (!errors) {
@@ -206,28 +199,20 @@
});
}
onMounted(() => {
load();
});
async function load() {
function load() {
show.value = true;
await loadOptions();
new Promise((_resolve, _reject) => {
getConfig({ group: group.value })
.then((res) => {
formValue.value = res.list;
})
.finally(() => {
show.value = false;
});
});
loadOptions();
getConfig({ group: group.value })
.then((res) => {
formValue.value = res.list;
})
.finally(() => {
show.value = false;
});
}
async function loadOptions() {
options.value = await Dicts({
types: ['config_sms_template', 'config_sms_drive'],
});
function loadOptions() {
dict.loadOptions(['config_sms_template', 'config_sms_drive']);
}
function confirmForm(e) {
@@ -245,4 +230,8 @@
formBtnLoading.value = false;
});
}
onMounted(() => {
load();
});
</script>

View File

@@ -6,17 +6,16 @@
:model="formValue"
:rules="rules"
ref="formRef"
label-placement="left"
label-placement="top"
>
<n-divider title-placement="left">基础设置</n-divider>
<n-form-item label="默认驱动" path="smsDrive">
<n-select
placeholder="默认发送驱动"
:options="options.config_sms_drive"
:options="dict.getOptionUnRef('config_sms_drive')"
v-model:value="formValue.smsDrive"
/>
</n-form-item>
<n-divider title-placement="left">发信限制</n-divider>
<n-form-item label="最小发送间隔" path="smsMinInterval">
<n-input-number
:show-button="false"
@@ -179,7 +178,10 @@
class="py-4"
>
<n-form-item label="事件模板" path="event">
<n-select :options="options.config_sms_template" v-model:value="formParams.event" />
<n-select
:options="dict.getOptionUnRef('config_sms_template')"
v-model:value="formParams.event"
/>
</n-form-item>
<n-form-item label="手机号" path="mobile">
@@ -213,17 +215,23 @@
import { ref, onMounted, watch } from 'vue';
import { useMessage } from 'naive-ui';
import { getConfig, sendTestSms, updateConfig } from '@/api/sys/config';
import { Dicts } from '@/api/dict/dict';
import { Options } from '@/utils/hotgo';
import { GlassesOutline, Glasses } from '@vicons/ionicons5';
import { useDictStore } from '@/store/modules/dict';
import type { FormRules } from 'naive-ui/es/form/src/interface';
const dict = useDictStore();
const message = useMessage();
const group = ref('sms');
const show = ref(false);
const showModal = ref(false);
const formBtnLoading = ref(false);
const formParams = ref({ mobile: '', event: '', code: '1234' });
const formTestRef = ref<any>();
const formRef: any = ref(null);
const defaultTabName = 'aliyun';
const tabName = ref<string>(defaultTabName);
const rules = {
const rules: FormRules = {
smsDrive: {
required: true,
message: '请输入默认驱动',
@@ -231,20 +239,6 @@
},
};
const formTestRef = ref<any>();
const formRef: any = ref(null);
const message = useMessage();
const options = ref<Options>({
config_sms_template: [],
config_sms_drive: [],
});
/** 默认选项卡 */
const defaultTabName = 'aliyun';
/** 选项卡名称 */
const tabName = ref<string>(defaultTabName);
const formValue = ref({
smsDrive: defaultTabName,
smsMinInterval: 60,
@@ -263,14 +257,6 @@
smsTencentTemplate: null,
});
/** 监听类型变化,同步到选项卡中 */
watch(
() => formValue.value.smsDrive,
(smsDrive: string) => {
tabName.value = smsDrive;
}
);
function sendTest() {
showModal.value = true;
formBtnLoading.value = false;
@@ -289,30 +275,21 @@
});
}
onMounted(() => {
load();
});
async function load() {
function load() {
show.value = true;
await loadOptions();
new Promise((_resolve, _reject) => {
getConfig({ group: group.value })
.then((res) => {
res.list.smsAliYunTemplate = JSON.parse(res.list.smsAliYunTemplate);
res.list.smsTencentTemplate = JSON.parse(res.list.smsTencentTemplate);
formValue.value = res.list;
})
.finally(() => {
show.value = false;
});
});
getConfig({ group: group.value })
.then((res) => {
res.list.smsAliYunTemplate = JSON.parse(res.list.smsAliYunTemplate);
res.list.smsTencentTemplate = JSON.parse(res.list.smsTencentTemplate);
formValue.value = res.list;
})
.finally(() => {
show.value = false;
});
}
async function loadOptions() {
options.value = await Dicts({
types: ['config_sms_template', 'config_sms_drive'],
});
function loadOptions() {
dict.loadOptions(['config_sms_template', 'config_sms_drive']);
}
function confirmForm(e) {
@@ -330,4 +307,16 @@
formBtnLoading.value = false;
});
}
watch(
() => formValue.value.smsDrive,
(smsDrive: string) => {
tabName.value = smsDrive;
}
);
onMounted(() => {
loadOptions();
load();
});
</script>

View File

@@ -6,17 +6,16 @@
:model="formValue"
:rules="rules"
ref="formRef"
label-placement="left"
label-placement="top"
>
<n-divider title-placement="left">基础设置</n-divider>
<n-form-item label="默认驱动" path="uploadDrive">
<n-select
placeholder="默认驱动"
:options="options.config_upload_drive"
:options="dict.getOptionUnRef('config_upload_drive')"
v-model:value="formValue.uploadDrive"
/>
</n-form-item>
<n-divider title-placement="left">上传限制</n-divider>
<n-form-item label="图片大小限制" path="uploadImageSize">
<n-input-number
:show-button="false"
@@ -311,15 +310,18 @@
import { useMessage } from 'naive-ui';
import { getConfig, updateConfig } from '@/api/sys/config';
import { Glasses, GlassesOutline } from '@vicons/ionicons5';
import { Dicts } from '@/api/dict/dict';
import { Options } from '@/utils/hotgo';
import { useDictStore } from '@/store/modules/dict';
import type { FormRules } from 'naive-ui/es/form/src/interface';
const dict = useDictStore();
const message = useMessage();
const group = ref('upload');
const show = ref(false);
const formRef: any = ref(null);
const message = useMessage();
const defaultTabName = 'local';
const tabName = ref<string>(defaultTabName);
const rules = {
const rules: FormRules = {
uploadDrive: {
required: true,
message: '请输入默认驱动',
@@ -327,15 +329,6 @@
},
};
const options = ref<Options>({
config_upload_drive: [],
});
/** 默认选项卡 */
const defaultTabName = 'local';
/** 选项卡名称 */
const tabName = ref<string>(defaultTabName);
const formValue = ref({
uploadDrive: defaultTabName,
uploadImageSize: 2,
@@ -374,14 +367,6 @@
uploadMinioDomain: '',
});
/** 监听类型变化,同步到选项卡中 */
watch(
() => formValue.value.uploadDrive,
(uploadDrive: string) => {
tabName.value = uploadDrive;
}
);
function formSubmit() {
formRef.value.validate((errors) => {
if (!errors) {
@@ -395,27 +380,30 @@
});
}
onMounted(async () => {
load();
await loadOptions();
});
function load() {
show.value = true;
new Promise((_resolve, _reject) => {
getConfig({ group: group.value })
.then((res) => {
formValue.value = res.list;
})
.finally(() => {
show.value = false;
});
});
getConfig({ group: group.value })
.then((res) => {
formValue.value = res.list;
})
.finally(() => {
show.value = false;
});
}
async function loadOptions() {
options.value = await Dicts({
types: ['config_upload_drive'],
});
function loadOptions() {
dict.loadOptions(['config_upload_drive']);
}
watch(
() => formValue.value.uploadDrive,
(uploadDrive: string) => {
tabName.value = uploadDrive;
}
);
onMounted(async () => {
loadOptions();
load();
});
</script>

View File

@@ -1,5 +1,9 @@
<template>
<n-drawer v-model:show="isDrawer" :width="width" :placement="placement">
<n-drawer
v-model:show="isDrawer"
:width="dialogWidth"
:label-placement="settingStore.isMobile ? 'top' : 'left'"
>
<n-drawer-content :title="title" closable>
<n-form
:model="formParams"
@@ -28,7 +32,7 @@
<n-form-item label="状态" path="status">
<n-radio-group v-model:value="formParams.status" name="status">
<n-radio-button
v-for="status in statusMap"
v-for="status in dict.getOptionUnRef('sys_normal_disable')"
:key="status.value"
:value="status.value"
:label="status.label"
@@ -39,34 +43,25 @@
<template #footer>
<n-space>
<n-button type="primary" :loading="subLoading" @click="formSubmit">提交</n-button>
<n-button @click="handleReset">重置</n-button>
<n-button type="primary" :loading="btnLoading" @click="formSubmit">提交</n-button>
<n-button @click="closeDrawer">取消</n-button>
</n-space>
</template>
</n-drawer-content>
</n-drawer>
</template>
<script lang="ts">
import { defineComponent, reactive, ref, toRefs } from 'vue';
import { TreeSelectOption, useMessage } from 'naive-ui';
import { QuestionCircleOutlined } from '@vicons/antd';
<script lang="ts" setup>
import { computed, ref } from 'vue';
import { useMessage } from 'naive-ui';
import { EditDict } from '@/api/dict/dict';
import { useDictStore } from '@/store/modules/dict';
import type { FormRules } from 'naive-ui/es/form/src/interface';
import { State } from '@/views/system/dict/model';
import { adaModalWidth } from '@/utils/hotgo';
import { useProjectSettingStore } from '@/store/modules/projectSetting';
const statusMap = [
{
value: 0,
label: '禁用',
},
{
value: 1,
label: '启用',
},
].map((s) => {
return s;
});
const rules = {
const rules: FormRules = {
label: {
required: true,
message: '请输入标题',
@@ -78,96 +73,60 @@
trigger: 'blur',
},
};
export default defineComponent({
name: 'CreateDrawer',
components: {},
props: {
title: {
type: String,
default: '添加顶级菜单',
},
optionTreeData: {
type: Object || Array,
default: [],
},
},
emits: ['loadData'],
setup(_props, context) {
const message = useMessage();
const formRef: any = ref(null);
const defaultValueRef = () => ({
id: 0,
pid: 0,
type: '',
name: '',
remark: '',
status: 1,
sort: 10,
});
const state = reactive<any>({
width: 500,
isDrawer: false,
subLoading: false,
formParams: defaultValueRef(),
placement: 'right',
icon: '',
alertText:
'该功能主要实时预览各种布局效果,更多完整配置在 projectSetting.ts 中设置,建议在生产环境关闭该布局预览功能。',
});
interface Props {
title: '添加顶级菜单';
optionTreeData: [];
}
function openDrawer(form) {
if (document.body.clientWidth < 500) {
state.width = document.body.clientWidth;
}
state.isDrawer = true;
state.formParams = Object.assign(state.formParams, form);
const emit = defineEmits(['loadData']);
const props = withDefaults(defineProps<Props>(), {});
const dict = useDictStore();
const message = useMessage();
const settingStore = useProjectSettingStore();
const formRef: any = ref(null);
const formParams = ref<State>(new State());
const btnLoading = ref(false);
const isDrawer = ref(false);
const dialogWidth = computed(() => {
return adaModalWidth(500);
});
function openDrawer(state: State) {
isDrawer.value = true;
formParams.value = state;
}
function closeDrawer() {
isDrawer.value = false;
}
function formSubmit() {
formRef.value.validate((errors) => {
if (!errors) {
btnLoading.value = true;
EditDict(formParams.value)
.then(async (_res) => {
message.success('操作成功');
emit('loadData');
closeDrawer();
})
.finally(() => {
btnLoading.value = false;
});
} else {
message.error('请填写完整信息');
}
});
}
function closeDrawer() {
state.isDrawer = false;
}
// 处理选项更新
function handleUpdateValue(value: number) {
formParams.value.pid = value;
}
function formSubmit() {
formRef.value.validate((errors) => {
if (!errors) {
EditDict({ ...state.formParams }).then(async (_res) => {
message.success('操作成功');
handleReset();
await context.emit('loadData');
closeDrawer();
});
} else {
message.error('请填写完整信息');
}
});
}
function handleReset() {
formRef.value.restoreValidation();
state.formParams = Object.assign(state.formParams, defaultValueRef());
}
// 处理选项更新
function handleUpdateValue(
value: string | number | Array<string | number> | null,
_option: TreeSelectOption | null | Array<TreeSelectOption | null>
) {
state.formParams.pid = value;
}
return {
...toRefs(state),
formRef,
rules,
formSubmit,
handleReset,
openDrawer,
closeDrawer,
statusMap,
handleUpdateValue,
QuestionCircleOutlined,
};
},
defineExpose({
openDrawer,
});
</script>

View File

@@ -58,7 +58,7 @@
</n-space>
</template>
<div class="w-full menu">
<n-input type="input" v-model:value="pattern" placeholder="输入字典名称搜索">
<n-input type="text" v-model:value="pattern" placeholder="输入字典名称搜索">
<template #suffix>
<n-icon size="18" class="cursor-pointer">
<SearchOutlined />
@@ -111,7 +111,7 @@
ref="createDrawerRef"
:title="drawerTitle"
:optionTreeData="optionTreeData"
@loadData="loadData"
@load-data="loadData"
/>
</div>
</template>
@@ -129,6 +129,7 @@
import CreateDrawer from './CreateDrawer.vue';
import List from './list.vue';
import { DeleteDict, getDictTree } from '@/api/dict/dict';
import { State } from '@/views/system/dict/model';
const createDrawerRef = ref();
const message = useMessage();
@@ -143,28 +144,18 @@
const pattern = ref('');
const drawerTitle = ref('');
const optionTreeData = ref([]);
const defaultValueRef = () => ({
id: 0,
pid: 0,
type: '',
name: '',
remark: '',
status: 1,
sort: 10,
});
const formParams = reactive(defaultValueRef());
const formParams = ref<State>(new State());
function openCreateDrawer() {
drawerTitle.value = '添加字典类型';
const { openDrawer } = createDrawerRef.value;
openDrawer(defaultValueRef());
openDrawer(new State());
}
function openEditDrawer() {
drawerTitle.value = '编辑字典类型';
const { openDrawer } = createDrawerRef.value;
openDrawer(formParams);
openDrawer(formParams.value);
}
function selectedTree(keys, opts) {
@@ -172,7 +163,7 @@
const treeItem = opts[0];
treeItemKey.value = keys;
treeItemTitle.value = treeItem.label;
Object.assign(formParams, treeItem);
formParams.value = unref(treeItem);
isEditMenu.value = true;
checkedId.value = treeItem.id;
} else {
@@ -189,14 +180,11 @@
positiveText: '确定',
negativeText: '取消',
onPositiveClick: () => {
DeleteDict({ ...formParams }).then(async (_res) => {
DeleteDict(formParams.value).then(async (_res) => {
message.success('操作成功');
await loadData();
});
},
onNegativeClick: () => {
message.error('已取消');
},
});
}
@@ -208,14 +196,10 @@
}
}
onMounted(async () => {
await loadData();
});
async function loadData() {
const treeMenuList = await getDictTree();
const keys = treeMenuList.list.map((item) => item.key);
Object.assign(formParams, keys);
Object.assign(formParams.value, keys);
treeData.value = [];
optionTreeData.value = [];
treeData.value = treeMenuList.list;
@@ -226,4 +210,8 @@
function onExpandedKeys(keys) {
expandedKeys.value = keys;
}
onMounted(async () => {
await loadData();
});
</script>

View File

@@ -57,7 +57,7 @@
<n-select
:render-tag="renderTag"
v-model:value="formParams.listClass"
:options="labelOptions"
:options="dict.getOptionUnRef('tagTypeOptions')"
/>
</n-form-item>
<n-form-item label="字典键值" path="value">
@@ -72,7 +72,7 @@
<n-form-item label="状态" path="status">
<n-radio-group v-model:value="formParams.status" name="status">
<n-radio-button
v-for="status in statusOptions"
v-for="status in dict.getOptionUnRef('sys_normal_disable')"
:key="status.value"
:value="status.value"
:label="status.label"
@@ -103,17 +103,17 @@
import { getDataList, getDictSelect, EditData, DeleteData } from '@/api/dict/dict';
import { columns } from './columns';
import { PlusOutlined } from '@vicons/antd';
import { statusOptions } from '@/enums/optionsiEnum';
import { TypeSelect } from '@/api/sys/config';
import { Option } from '@/utils/hotgo';
import { findTreeNode } from '@/utils';
import { cloneDeep } from 'lodash-es';
import { defRangeShortcuts } from '@/utils/dateUtil';
import { Option, useDictStore } from '@/store/modules/dict';
import { State } from '@/views/system/dict/model';
interface Props {
checkedId?: number;
}
const dict = useDictStore();
const props = withDefaults(defineProps<Props>(), { checkedId: 0 });
const typeList = ref<any>([]);
const rules = {
@@ -162,53 +162,22 @@
return h(
NTag,
{
type: option.type as 'success' | 'warning' | 'error' | 'info' | 'primary' | 'default',
type: option.listClass as 'success' | 'warning' | 'error' | 'info' | 'primary' | 'default',
},
{ default: () => option.label }
);
};
const labelOptions = ref([
{
label: '绿色',
value: 'success',
type: 'success',
},
{
label: '橙色',
value: 'warning',
type: 'warning',
},
{
label: '红色',
value: 'error',
type: 'error',
},
{
label: '蓝色',
value: 'info',
type: 'info',
},
{
label: '灰色',
value: 'default',
type: 'default',
},
{
label: '主题色',
value: 'primary',
type: 'primary',
},
]);
const formRef: any = ref(null);
const message = useMessage();
const dialog = useDialog();
const actionRef = ref();
const showModal = ref(false);
const formBtnLoading = ref(false);
const formParams = ref<any>({ typeId: 0 });
const formParams = ref<State>(new State());
const options = ref<Option>();
const typeId = ref(0);
const params = ref({
pageSize: 10,
typeId: props.checkedId,
@@ -217,7 +186,7 @@
});
const actionColumn = reactive({
width: 120,
width: 140,
title: '操作',
key: 'action',
fixed: 'right',
@@ -246,16 +215,10 @@
function addTable() {
showModal.value = true;
formParams.value = {
typeId: props.checkedId,
label: '',
value: '',
listClass: 'default',
valueType: 'string',
sort: 0,
status: 1,
remark: '',
};
formParams.value = new State();
if (typeId.value > 0) {
formParams.value.typeId = typeId.value;
}
}
const loadDataTable = async (res) => {
@@ -272,25 +235,26 @@
function confirmForm(e) {
e.preventDefault();
formBtnLoading.value = true;
formRef.value.validate((errors) => {
if (!errors) {
EditData(formParams.value).then((_res) => {
message.success('操作成功');
setTimeout(() => {
formBtnLoading.value = true;
EditData(formParams.value)
.then((_res) => {
message.success('操作成功');
showModal.value = false;
reloadTable();
})
.finally(() => {
formBtnLoading.value = false;
});
});
} else {
message.error('请填写完整信息');
}
formBtnLoading.value = false;
});
}
function handleDelete(record: Recordable) {
console.log('点击了删除', record);
dialog.warning({
title: '警告',
content: '你确定要删除?',
@@ -307,7 +271,7 @@
function handleEdit(record: Recordable) {
showModal.value = true;
formParams.value = cloneDeep(record);
formParams.value = cloneDeep(record) as unknown as State;
}
function handleSubmit(_values: Recordable) {
@@ -316,16 +280,10 @@
function handleReset(_values: Recordable) {
params.value.label = '';
params.value.value = '';
reloadTable();
}
watch(props, (newVal, _oldVal) => {
params.value.typeId = newVal.checkedId;
formParams.value.typeId = newVal.checkedId;
actionRef.value.reload();
setDictSelect();
});
async function setDictSelect() {
const tmp = await getDictSelect({});
typeList.value = tmp.list;
@@ -344,13 +302,23 @@
formParams.value.type = row.type;
}
async function loadOptions() {
options.value = await TypeSelect();
function loadOptions() {
dict.loadOptions(['sys_normal_disable']);
TypeSelect().then((res) => {
options.value = res;
});
}
watch(props, (newVal, _oldVal) => {
params.value.typeId = newVal.checkedId;
typeId.value = newVal.checkedId;
actionRef.value.reload();
setDictSelect();
});
onMounted(async () => {
loadOptions();
await setDictSelect();
await loadOptions();
});
</script>

View File

@@ -0,0 +1,18 @@
export class State {
typeId = 0;
key = '';
id = 0;
label = '';
value = '';
valueType = 'string';
type = '';
listClass = 'primary';
isDefault = 0;
sort = 0;
remark = '';
status = 1;
createdAt = '';
updatedAt = '';
pid: number | null = 0;
name = '';
}

View File

@@ -44,7 +44,7 @@
</n-gi>
<n-gi span="1">
<n-form-item label="状态" path="status">
<n-select v-model:value="formValue.status" :options="options.sys_normal_disable" />
<n-select v-model:value="formValue.status" :options="dict.getOptionUnRef('sys_normal_disable')" />
</n-form-item>
</n-gi>
<n-gi span="2">
@@ -72,8 +72,9 @@
<script lang="ts" setup>
import { ref, computed } from 'vue';
import { useDictStore } from '@/store/modules/dict';
import { Edit, View, MaxSort } from '@/api/testCategory';
import { options, State, newState, rules } from './model';
import { State, newState, rules } from './model';
import { useProjectSettingStore } from '@/store/modules/projectSetting';
import { useMessage } from 'naive-ui';
import { adaModalWidth } from '@/utils/hotgo';
@@ -81,6 +82,7 @@
const emit = defineEmits(['reloadTable']);
const message = useMessage();
const settingStore = useProjectSettingStore();
const dict = useDictStore();
const loading = ref(false);
const showModal = ref(false);
const formValue = ref<State>(newState(null));
@@ -119,25 +121,28 @@
});
}
// 提交表单
function confirmForm(e) {
e.preventDefault();
formBtnLoading.value = true;
formRef.value.validate((errors) => {
if (!errors) {
Edit(formValue.value).then((_res) => {
message.success('操作成功');
setTimeout(() => {
formBtnLoading.value = true;
Edit(formValue.value)
.then((_res) => {
message.success('操作成功');
closeForm();
emit('reloadTable');
})
.finally(() => {
formBtnLoading.value = false;
});
});
} else {
message.error('请填写完整信息');
}
formBtnLoading.value = false;
});
}
// 关闭表单
function closeForm() {
showModal.value = false;
loading.value = false;

View File

@@ -42,10 +42,11 @@
import { BasicTable, TableAction } from '@/components/Table';
import { BasicForm, useForm } from '@/components/Form/index';
import { usePermission } from '@/hooks/web/usePermission';
import { useDictStore } from '@/store/modules/dict';
import { List, Delete, Status } from '@/api/testCategory';
import { PlusOutlined, DeleteOutlined } from '@vicons/antd';
import { columns, schemas, options, loadOptions } from './model';
import { adaTableScrollX, getOptionLabel } from '@/utils/hotgo';
import { columns, schemas, loadOptions } from './model';
import { adaTableScrollX } from '@/utils/hotgo';
import Edit from './edit.vue';
const dialog = useDialog();
@@ -54,6 +55,7 @@
const actionRef = ref();
const searchFormRef = ref<any>({});
const editRef = ref();
const dict = useDictStore();
const checkedIds = ref([]);
@@ -175,7 +177,7 @@
// 修改状态
function handleStatus(record: Recordable, status: number) {
Status({ id: record.id, status: status }).then((_res) => {
message.success('设为' + getOptionLabel(options.value.sys_normal_disable, status) + '成功');
message.success('设为' + dict.getLabel('sys_normal_disable', status) + '成功');
setTimeout(() => {
reloadTable();
});
@@ -184,6 +186,7 @@
onMounted(() => {
loadOptions();
});
</script>

View File

@@ -2,10 +2,12 @@ import { h, ref } from 'vue';
import { NTag } from 'naive-ui';
import { cloneDeep } from 'lodash-es';
import { FormSchema } from '@/components/Form';
import { Dicts } from '@/api/dict/dict';
import { isNullObject } from '@/utils/is';
import { defRangeShortcuts } from '@/utils/dateUtil';
import { Option, getOptionLabel, getOptionTag } from '@/utils/hotgo';
import { useDictStore } from '@/store/modules/dict';
import type { FormRules } from 'naive-ui/es/form/src/interface';
const dict = useDictStore();
export class State {
public id = 0; // 分类ID
@@ -37,7 +39,7 @@ export function newState(state: State | Record<string, any> | null): State {
}
// 表单验证规则
export const rules = {
export const rules: FormRules = {
name: {
required: true,
trigger: ['blur', 'input'],
@@ -83,7 +85,7 @@ export const schemas = ref<FormSchema[]>([
defaultValue: null,
componentProps: {
placeholder: '请选择状态',
options: [],
options: dict.getOption('sys_normal_disable'),
onUpdateValue: (e: any) => {
console.log(e);
},
@@ -145,11 +147,11 @@ export const columns = [
style: {
marginRight: '6px',
},
type: getOptionTag(options.value.sys_normal_disable, row.status),
type: dict.getType('sys_normal_disable', row.status),
bordered: false,
},
{
default: () => getOptionLabel(options.value.sys_normal_disable, row.status),
default: () => dict.getLabel('sys_normal_disable', row.status),
}
);
},
@@ -162,23 +164,7 @@ export const columns = [
},
];
// 字典数据选项
export const options = ref({
sys_normal_disable: [] as Option[],
});
// 加载字典数据选项
export function loadOptions() {
Dicts({
types: ['sys_normal_disable'],
}).then((res) => {
options.value = res;
for (const item of schemas.value) {
switch (item.field) {
case 'status':
item.componentProps.options = options.value.sys_normal_disable;
break;
}
}
});
}
dict.loadOptions(['sys_normal_disable']);
}