This commit is contained in:
ahjung
2023-08-10 13:54:53 +08:00
parent 9b2effbc55
commit 347cd91735
35 changed files with 3485 additions and 10010 deletions

View File

@@ -1,5 +1,18 @@
# CHANGELOG # CHANGELOG
## 1.9.0
- 新增 `BasicForm` 组件,支持 `setLoading`, `setSchema` 方法
- 新增 `countField` 总数字段名配置
- 优化 `yarn` 切换至 `pnpm`
- 优化 `BasicForm` 组件,验证返回值
- 优化 `BasicTable` 组件
- 修复 `TableAction组件左右间隔不生效` 关闭[253](https://github.com/jekip/naive-ui-admin/issues/253)
- 修复 `BasicTable组件没有数据会一直请求接口` 关闭[#251](https://github.com/jekip/naive-ui-admin/issues/251)
- 修复 `useModal+useForm组件的bug` 关闭[#250](https://github.com/jekip/naive-ui-admin/issues/250)
- 修复 `手机端侧边导航风格不一致bug` 关闭[#247](https://github.com/jekip/naive-ui-admin/issues/247
- 移除 `yarn.lock` 文件
- 依赖升级
## 1.8.2 ## 1.8.2
- ### ✨ Features - ### ✨ Features

View File

@@ -27,12 +27,15 @@ export default [
timeout: 1000, timeout: 1000,
method: 'get', method: 'get',
response: ({ query }) => { response: ({ query }) => {
const { page = 1, pageSize = 10 } = query; const { page = 1, pageSize = 10, name } = query;
const list = tableList(Number(pageSize)); const list = tableList(Number(pageSize));
//并非真实,只是为了模拟搜索结果
const count = name ? 30 : 60;
return resultSuccess({ return resultSuccess({
page: Number(page), page: Number(page),
pageSize: Number(pageSize), pageSize: Number(pageSize),
pageCount: 60, pageCount: count,
itemCount: count * Number(pageSize),
list, list,
}); });
}, },

View File

@@ -1,6 +1,6 @@
{ {
"name": "naive-ui-admin", "name": "naive-ui-admin",
"version": "1.8.2", "version": "1.9.0",
"author": { "author": {
"name": "Ahjung", "name": "Ahjung",
"email": "735878602@qq.com", "email": "735878602@qq.com",
@@ -8,11 +8,11 @@
}, },
"private": true, "private": true,
"scripts": { "scripts": {
"bootstrap": "yarn install", "bootstrap": "pnpm install",
"serve": "npm run dev", "serve": "pnpm run dev",
"dev": "vite", "dev": "vite",
"build": "vite build && esno ./build/script/postBuild.ts", "build": "vite build && esno ./build/script/postBuild.ts",
"build:no-cache": "yarn clean:cache && npm run build", "build:no-cache": "pnpm clean:cache && npm run build",
"report": "cross-env REPORT=true npm run build", "report": "cross-env REPORT=true npm run build",
"preview": "npm run build && vite preview", "preview": "npm run build && vite preview",
"preview:dist": "vite preview", "preview:dist": "vite preview",
@@ -30,73 +30,73 @@
"dependencies": { "dependencies": {
"@vicons/antd": "^0.12.0", "@vicons/antd": "^0.12.0",
"@vicons/ionicons5": "^0.12.0", "@vicons/ionicons5": "^0.12.0",
"@vueup/vue-quill": "^1.0.0", "@vueup/vue-quill": "^1.2.0",
"@vueuse/core": "^9.5.0", "@vueuse/core": "^9.13.0",
"axios": "^1.1.3", "axios": "^1.4.0",
"blueimp-md5": "^2.19.0", "blueimp-md5": "^2.19.0",
"date-fns": "^2.29.3", "date-fns": "^2.30.0",
"echarts": "^5.4.0", "echarts": "^5.4.3",
"element-resize-detector": "^1.2.4", "element-resize-detector": "^1.2.4",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"mitt": "^3.0.0", "mitt": "^3.0.1",
"mockjs": "^1.1.0", "mockjs": "^1.1.0",
"naive-ui": "^2.34.2", "naive-ui": "^2.34.4",
"pinia": "^2.0.23", "pinia": "^2.1.6",
"qs": "^6.11.0", "qs": "^6.11.2",
"vfonts": "^0.0.3", "vfonts": "^0.0.3",
"vue": "^3.2.45", "vue": "^3.3.4",
"vue-router": "^4.1.6", "vue-router": "^4.2.4",
"vue-types": "^4.2.1" "vue-types": "^4.2.1"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^17.2.0", "@commitlint/cli": "^17.7.0",
"@commitlint/config-conventional": "^17.2.0", "@commitlint/config-conventional": "^17.7.0",
"@types/lodash": "^4.14.188", "@types/lodash": "^4.14.197",
"@types/node": "^18.11.9", "@types/node": "^18.17.4",
"@typescript-eslint/eslint-plugin": "^5.42.1", "@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.42.1", "@typescript-eslint/parser": "^5.62.0",
"@vitejs/plugin-vue": "^3.2.0", "@vitejs/plugin-vue": "^3.2.0",
"@vitejs/plugin-vue-jsx": "^2.1.1", "@vitejs/plugin-vue-jsx": "^2.1.1",
"@vue/compiler-sfc": "^3.2.45", "@vue/compiler-sfc": "^3.3.4",
"@vue/eslint-config-typescript": "^11.0.2", "@vue/eslint-config-typescript": "^11.0.3",
"autoprefixer": "^10.4.13", "autoprefixer": "^10.4.14",
"commitizen": "^4.2.5", "commitizen": "^4.3.0",
"core-js": "^3.26.0", "core-js": "^3.32.0",
"dotenv": "^16.0.3", "cross-env": "^7.0.3",
"eslint": "^8.27.0", "dotenv": "^16.3.1",
"eslint-config-prettier": "^8.5.0", "eslint": "^8.46.0",
"eslint-config-prettier": "^8.10.0",
"eslint-define-config": "1.12.0", "eslint-define-config": "1.12.0",
"eslint-plugin-jest": "^27.1.5", "eslint-plugin-jest": "^27.2.3",
"eslint-plugin-prettier": "^4.2.1", "eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-vue": "^9.7.0", "eslint-plugin-vue": "^9.17.0",
"esno": "^0.16.3", "esno": "^0.16.3",
"gh-pages": "^4.0.0", "gh-pages": "^4.0.0",
"husky": "^8.0.2", "husky": "^8.0.3",
"jest": "^29.3.1", "jest": "^29.6.2",
"less": "^4.1.3", "less": "^4.2.0",
"less-loader": "^11.1.0", "less-loader": "^11.1.3",
"lint-staged": "^13.0.3", "lint-staged": "^13.2.3",
"postcss": "^8.4.19", "postcss": "^8.4.27",
"prettier": "^2.7.1", "prettier": "^2.8.8",
"pretty-quick": "^3.1.3", "pretty-quick": "^3.1.3",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"stylelint": "^14.14.1", "stylelint": "^14.16.1",
"stylelint-config-prettier": "^9.0.4", "stylelint-config-prettier": "^9.0.5",
"stylelint-config-standard": "^29.0.0", "stylelint-config-standard": "^29.0.0",
"stylelint-order": "^5.0.0", "stylelint-order": "^5.0.0",
"stylelint-scss": "^4.3.0", "stylelint-scss": "^4.7.0",
"tailwindcss": "^3.2.3", "tailwindcss": "^3.3.3",
"typescript": "^4.8.4", "typescript": "^4.9.5",
"unplugin-vue-components": "^0.22.9", "unplugin-vue-components": "^0.22.12",
"vite": "^3.2.3", "vite": "^3.2.7",
"vite-plugin-compression": "^0.5.1", "vite-plugin-compression": "^0.5.1",
"vite-plugin-html": "^3.2.0", "vite-plugin-html": "^3.2.0",
"vite-plugin-mock": "^2.9.6", "vite-plugin-mock": "^2.9.8",
"vite-plugin-style-import": "^2.0.0", "vite-plugin-style-import": "^2.0.0",
"vue-demi": "^0.13.11", "vue-demi": "^0.13.11",
"vue-draggable-next": "^2.1.1", "vue-draggable-next": "^2.2.1",
"vue-eslint-parser": "^9.1.0", "vue-eslint-parser": "^9.3.1",
"vuedraggable": "^4.1.0" "vuedraggable": "^4.1.0"
}, },
"lint-staged": { "lint-staged": {
@@ -127,6 +127,6 @@
}, },
"homepage": "https://github.com/jekip/naive-ui-admin", "homepage": "https://github.com/jekip/naive-ui-admin",
"engines": { "engines": {
"node": "^12 || >=14" "node": ">=16"
} }
} }

5725
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@
{{ schema.label }} {{ schema.label }}
<n-tooltip trigger="hover" :style="schema.labelMessageStyle"> <n-tooltip trigger="hover" :style="schema.labelMessageStyle">
<template #trigger> <template #trigger>
<n-icon size="18" class="cursor-pointer text-gray-400"> <n-icon size="18" class="text-gray-400 cursor-pointer">
<QuestionCircleOutlined /> <QuestionCircleOutlined />
</n-icon> </n-icon>
</template> </template>

View File

@@ -80,6 +80,15 @@ export function useForm(props?: Props): UseFormReturnType {
const form = await getForm(); const form = await getForm();
return form.validate(nameList); return form.validate(nameList);
}, },
setLoading: (value: boolean) => {
loadedRef.value = value;
},
setSchema: async (values) => {
const form = await getForm();
form.setSchema(values);
},
}; };
return [register, methods]; return [register, methods];

View File

@@ -32,24 +32,28 @@ export function useFormEvents({
} }
// 提交 // 提交
async function handleSubmit(e?: Event): Promise<void> { async function handleSubmit(e?: Event): Promise<object | boolean> {
e && e.preventDefault(); e && e.preventDefault();
loadingSub.value = true; loadingSub.value = true;
const { submitFunc } = unref(getProps); const { submitFunc } = unref(getProps);
if (submitFunc && isFunction(submitFunc)) { if (submitFunc && isFunction(submitFunc)) {
await submitFunc(); await submitFunc();
return; loadingSub.value = false;
return false;
} }
const formEl = unref(formElRef); const formEl = unref(formElRef);
if (!formEl) return; if (!formEl) return false;
try { try {
await validate(); await validate();
const values = getFieldsValue();
loadingSub.value = false; loadingSub.value = false;
emit('submit', formModel); emit('submit', values);
return; return values;
} catch (error) { } catch (error: any) {
emit('submit', false);
loadingSub.value = false; loadingSub.value = false;
return; console.error(error);
return false;
} }
} }
@@ -96,6 +100,10 @@ export function useFormEvents({
}); });
} }
function setLoading(value: boolean): void {
loadingSub.value = value;
}
return { return {
handleSubmit, handleSubmit,
validate, validate,
@@ -103,5 +111,6 @@ export function useFormEvents({
getFieldsValue, getFieldsValue,
clearValidate, clearValidate,
setFieldsValue, setFieldsValue,
setLoading,
}; };
} }

View File

@@ -47,11 +47,13 @@ export interface FormProps {
export interface FormActionType { export interface FormActionType {
submit: () => Promise<any>; submit: () => Promise<any>;
setProps: (formProps: Partial<FormProps>) => Promise<void>; setProps: (formProps: Partial<FormProps>) => Promise<void>;
setFieldsValue: (values: Recordable) => Promise<void>; setSchema: (schemaProps: Partial<FormSchema[]>) => Promise<void>;
setFieldsValue: (values: Recordable) => void;
clearValidate: (name?: string | string[]) => Promise<void>; clearValidate: (name?: string | string[]) => Promise<void>;
getFieldsValue: () => Recordable; getFieldsValue: () => Recordable;
resetFields: () => Promise<void>; resetFields: () => Promise<void>;
validate: (nameList?: any[]) => Promise<any>; validate: (nameList?: any[]) => Promise<any>;
setLoading: (status: boolean) => void;
} }
export type RegisterFn = (formInstance: FormActionType) => void; export type RegisterFn = (formInstance: FormActionType) => void;

View File

@@ -21,16 +21,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { import { getCurrentInstance, ref, nextTick, unref, computed, useAttrs } from 'vue';
getCurrentInstance,
ref,
nextTick,
unref,
computed,
useAttrs,
defineEmits,
defineProps,
} from 'vue';
import { basicProps } from './props'; import { basicProps } from './props';
import startDrag from '@/utils/Drag'; import startDrag from '@/utils/Drag';
import { deepMerge } from '@/utils'; import { deepMerge } from '@/utils';
@@ -93,7 +84,6 @@
function handleSubmit() { function handleSubmit() {
subLoading.value = true; subLoading.value = true;
console.log(subLoading.value);
emit('on-ok'); emit('on-ok');
} }

View File

@@ -2,7 +2,7 @@
<div class="tableAction"> <div class="tableAction">
<div class="flex items-center justify-center"> <div class="flex items-center justify-center">
<template v-for="(action, index) in getActions" :key="`${index}-${action.label}`"> <template v-for="(action, index) in getActions" :key="`${index}-${action.label}`">
<n-button v-bind="action" class="mx-2"> <n-button v-bind="action" class="mx-1">
{{ action.label }} {{ action.label }}
<template #icon v-if="action.hasOwnProperty('icon')"> <template #icon v-if="action.hasOwnProperty('icon')">
<n-icon :component="action.icon" /> <n-icon :component="action.icon" />
@@ -16,7 +16,7 @@
@select="select" @select="select"
> >
<slot name="more"></slot> <slot name="more"></slot>
<n-button v-bind="getMoreProps" class="mx-2" v-if="!$slots.more" icon-placement="right"> <n-button v-bind="getMoreProps" class="mx-1" v-if="!$slots.more" icon-placement="right">
<div class="flex items-center"> <div class="flex items-center">
<span>更多</span> <span>更多</span>
<n-icon size="14" class="ml-1"> <n-icon size="14" class="ml-1">

View File

@@ -17,7 +17,7 @@
:class="getWrapperClass" :class="getWrapperClass"
ref="elRef" ref="elRef"
@options-change="handleOptionsChange" @options-change="handleOptionsChange"
@pressEnter="handleEnter" @press-enter="handleEnter"
/> />
</div> </div>
<div class="editable-cell-action" v-if="!getRowEditable"> <div class="editable-cell-action" v-if="!getRowEditable">

View File

@@ -53,7 +53,7 @@ export function useDataSource(
const sizeField = APISETTING.sizeField; const sizeField = APISETTING.sizeField;
const totalField = APISETTING.totalField; const totalField = APISETTING.totalField;
const listField = APISETTING.listField; const listField = APISETTING.listField;
const itemCount = APISETTING.countField;
let pageParams = {}; let pageParams = {};
const { page = 1, pageSize = 10 } = unref(getPaginationInfo) as PaginationProps; const { page = 1, pageSize = 10 } = unref(getPaginationInfo) as PaginationProps;
@@ -66,23 +66,27 @@ export function useDataSource(
let params = { let params = {
...pageParams, ...pageParams,
...opt,
}; };
if (beforeRequest && isFunction(beforeRequest)) { if (beforeRequest && isFunction(beforeRequest)) {
// The params parameter can be modified by outsiders // The params parameter can be modified by outsiders
params = (await beforeRequest(params)) || params; params = (await beforeRequest(params)) || params;
} }
const res = await request(params); const res = await request(params);
const resultTotal = res[totalField];
const resultTotal = res[totalField] || 0;
const currentPage = res[pageField]; const currentPage = res[pageField];
const total = res[itemCount];
const results = res[listField] ? res[listField] : [];
// 如果数据异常,需获取正确的页码再次执行 // 如果数据异常,需获取正确的页码再次执行
if (resultTotal) { if (resultTotal) {
if (page > resultTotal) { const currentTotalPage = Math.ceil(total / pageSize);
if (page > currentTotalPage) {
setPagination({ setPagination({
[pageField]: resultTotal, page: currentTotalPage,
itemCount: total,
}); });
fetch(opt); return await fetch(opt);
} }
} }
let resultInfo = res[listField] ? res[listField] : []; let resultInfo = res[listField] ? res[listField] : [];
@@ -92,12 +96,13 @@ export function useDataSource(
} }
dataSourceRef.value = resultInfo; dataSourceRef.value = resultInfo;
setPagination({ setPagination({
[pageField]: currentPage, page: currentPage,
[totalField]: resultTotal, pageCount: resultTotal,
itemCount: total,
}); });
if (opt && opt[pageField]) { if (opt && opt[pageField]) {
setPagination({ setPagination({
[pageField]: opt[pageField] || 1, page: opt[pageField] || 1,
}); });
} }
emit('fetch-success', { emit('fetch-success', {
@@ -108,9 +113,9 @@ export function useDataSource(
console.error(error); console.error(error);
emit('fetch-error', error); emit('fetch-error', error);
dataSourceRef.value = []; dataSourceRef.value = [];
// setPagination({ setPagination({
// pageCount: 0, pageCount: 0,
// }); });
} finally { } finally {
setLoading(false); setLoading(false);
} }

View File

@@ -1,28 +1,40 @@
import type { PaginationProps } from '../types/pagination'; import type { PaginationProps } from '../types/pagination';
import type { BasicTableProps } from '../types/table'; import type { BasicTableProps } from '../types/table';
import { computed, unref, ref, ComputedRef } from 'vue'; import { computed, unref, ref, ComputedRef, watch } from 'vue';
import { isBoolean } from '@/utils/is'; import { isBoolean } from '@/utils/is';
import { APISETTING, DEFAULTPAGESIZE, PAGESIZES } from '../const'; import { DEFAULTPAGESIZE, PAGESIZES } from '../const';
export function usePagination(refProps: ComputedRef<BasicTableProps>) { export function usePagination(refProps: ComputedRef<BasicTableProps>) {
const configRef = ref<PaginationProps>({}); const configRef = ref<PaginationProps>({});
const show = ref(true); const show = ref(true);
watch(
() => unref(refProps).pagination,
(pagination) => {
if (!isBoolean(pagination) && pagination) {
configRef.value = {
...unref(configRef),
...(pagination ?? {}),
};
}
}
);
const getPaginationInfo = computed((): PaginationProps | boolean => { const getPaginationInfo = computed((): PaginationProps | boolean => {
const { pagination } = unref(refProps); const { pagination } = unref(refProps);
if (!unref(show) || (isBoolean(pagination) && !pagination)) { if (!unref(show) || (isBoolean(pagination) && !pagination)) {
return false; return false;
} }
const { totalField } = APISETTING;
return { return {
pageSize: DEFAULTPAGESIZE, page: 1, //当前页
pageSizes: PAGESIZES, pageSize: DEFAULTPAGESIZE, //分页大小
pageSizes: PAGESIZES, // 每页条数
showSizePicker: true, showSizePicker: true,
showQuickJumper: true, showQuickJumper: true,
prefix: (pagingInfo) => `${pagingInfo.itemCount}`, // 不需要可以通过 pagination 重置或者删除
...(isBoolean(pagination) ? {} : pagination), ...(isBoolean(pagination) ? {} : pagination),
...unref(configRef), ...unref(configRef),
pageCount: unref(configRef)[totalField],
}; };
}); });

View File

@@ -5,4 +5,5 @@ export type ComponentType =
| 'NCheckbox' | 'NCheckbox'
| 'NSwitch' | 'NSwitch'
| 'NDatePicker' | 'NDatePicker'
| 'NTimePicker'; | 'NTimePicker'
| 'NCascader';

View File

@@ -1,8 +1,10 @@
export interface PaginationProps { export interface PaginationProps {
page?: number; page?: number; //受控模式下的当前页
pageCount?: number; itemCount?: number; //总条数
pageSize?: number; pageCount?: number; //总页数
pageSizes?: number[]; pageSize?: number; //受控模式下的分页大小
showSizePicker?: boolean; pageSizes?: number[]; //每页条数, 可自定义
showQuickJumper?: boolean; showSizePicker?: boolean; //是否显示每页条数的选择器
showQuickJumper?: boolean; //是否显示快速跳转
prefix?: any; //分页前缀
} }

View File

@@ -1,5 +1,5 @@
import { ref, onMounted, onUnmounted } from 'vue'; import { ref, onMounted, onUnmounted } from 'vue';
import { debounce } from 'lodash'; import { debounce } from 'lodash-es';
/** /**
* description: 获取页面宽度 * description: 获取页面宽度

View File

@@ -259,8 +259,7 @@
title: props.title, title: props.title,
isDrawer: false, isDrawer: false,
placement: 'right', placement: 'right',
alertText: alertText: '该功能主要实时预览各种布局效果,更多完整配置在 projectSetting.ts 中设置',
'该功能主要实时预览各种布局效果,更多完整配置在 projectSetting.ts 中设置,建议在生产环境关闭该布局预览功能。',
appThemeList: designStore.appThemeList, appThemeList: designStore.appThemeList,
}); });

View File

@@ -35,7 +35,7 @@
<div <div
:id="`tag${element.fullPath.split('/').join('\/')}`" :id="`tag${element.fullPath.split('/').join('\/')}`"
class="tabs-card-scroll-item" class="tabs-card-scroll-item"
:class="{ 'active-item': activeKey === element.path }" :class="{ 'active-item': activeKey === element.fullPath }"
@click.stop="goPage(element)" @click.stop="goPage(element)"
@contextmenu="handleContextMenu($event, element)" @contextmenu="handleContextMenu($event, element)"
> >

View File

@@ -25,9 +25,18 @@
:width="menuWidth" :width="menuWidth"
:placement="'left'" :placement="'left'"
class="layout-side-drawer" class="layout-side-drawer"
>
<n-layout-sider
:position="fixedMenu"
:collapsed="false"
:width="menuWidth"
:native-scrollbar="false"
:inverted="inverted"
class="layout-sider"
> >
<Logo :collapsed="collapsed" /> <Logo :collapsed="collapsed" />
<AsideMenu @clickMenuItem="collapsed = false" /> <AsideMenu v-model:location="getMenuLocation" />
</n-layout-sider>
</n-drawer> </n-drawer>
<n-layout :inverted="inverted"> <n-layout :inverted="inverted">

View File

@@ -66,6 +66,7 @@ import {
NTimePicker, NTimePicker,
NBackTop, NBackTop,
NSkeleton, NSkeleton,
NCascader,
} from 'naive-ui'; } from 'naive-ui';
// https://www.naiveui.com/en-US/os-theme/docs/import-on-demand // https://www.naiveui.com/en-US/os-theme/docs/import-on-demand
@@ -136,6 +137,7 @@ const naive = create({
NTimePicker, NTimePicker,
NBackTop, NBackTop,
NSkeleton, NSkeleton,
NCascader,
], ],
}); });

View File

@@ -9,6 +9,8 @@ export default {
listField: 'list', listField: 'list',
// 接口返回总页数字段名 // 接口返回总页数字段名
totalField: 'pageCount', totalField: 'pageCount',
//总数字段名
countField: 'itemCount',
}, },
//默认分页数量 //默认分页数量
defaultPageSize: 10, defaultPageSize: 10,

View File

@@ -23,7 +23,7 @@ import {
VisualMapComponent, VisualMapComponent,
TimelineComponent, TimelineComponent,
CalendarComponent, CalendarComponent,
GraphicComponent GraphicComponent,
} from 'echarts/components'; } from 'echarts/components';
import { SVGRenderer } from 'echarts/renderers'; import { SVGRenderer } from 'echarts/renderers';
@@ -49,7 +49,7 @@ echarts.use([
VisualMapComponent, VisualMapComponent,
TimelineComponent, TimelineComponent,
CalendarComponent, CalendarComponent,
GraphicComponent GraphicComponent,
]); ]);
export default echarts; export default echarts;

View File

@@ -153,6 +153,9 @@
const message = useMessage(); const message = useMessage();
function handleSubmit(values: Recordable) { function handleSubmit(values: Recordable) {
if (!values) {
return message.error('请填写完整信息');
}
console.log(values); console.log(values);
message.success(JSON.stringify(values)); message.success(JSON.stringify(values));
} }

View File

@@ -176,6 +176,9 @@
}); });
function handleSubmit(values: Recordable) { function handleSubmit(values: Recordable) {
if (!values) {
return message.error('请填写完整信息');
}
console.log(values); console.log(values);
message.success(JSON.stringify(values)); message.success(JSON.stringify(values));
} }

View File

@@ -8,7 +8,7 @@
方式ref方式也支持使用方式和其他组件一致modalRef.value.closeModal() 方式ref方式也支持使用方式和其他组件一致modalRef.value.closeModal()
</n-card> </n-card>
</div> </div>
<n-card :bordered="false" class="proCard mt-4"> <n-card :bordered="false" class="mt-4 proCard">
<n-alert title="Modal嵌套Form" type="info"> <n-alert title="Modal嵌套Form" type="info">
使用 useModal 进行弹窗展示和操作并演示了在Modal内和Form组件组合使用方法 使用 useModal 进行弹窗展示和操作并演示了在Modal内和Form组件组合使用方法
</n-alert> </n-alert>
@@ -250,6 +250,7 @@
const formRes = await submit(); const formRes = await submit();
if (formRes) { if (formRes) {
closeModal(); closeModal();
console.log('formRes', formRes);
message.success('提交成功'); message.success('提交成功');
} else { } else {
message.error('验证失败,请填写完整信息'); message.error('验证失败,请填写完整信息');

View File

@@ -29,7 +29,7 @@
name="files" name="files"
:width="100" :width="100"
:height="100" :height="100"
@uploadChange="uploadChange" @upload-change="uploadChange"
v-model:value="formValue.images" v-model:value="formValue.images"
helpText="单个文件不超过2MB最多只能上传10个文件" helpText="单个文件不超过2MB最多只能上传10个文件"
/> />

View File

@@ -12,11 +12,11 @@
<template #header-extra> <template #header-extra>
<n-tag type="success"></n-tag> <n-tag type="success"></n-tag>
</template> </template>
<div class="py-1 px-1 flex justify-between"> <div class="flex justify-between px-1 py-1">
<n-skeleton v-if="loading" :width="100" size="medium" /> <n-skeleton v-if="loading" :width="100" size="medium" />
<CountTo v-else :startVal="1" :endVal="visits.dayVisits" class="text-3xl" /> <CountTo v-else :startVal="1" :endVal="visits.dayVisits" class="text-3xl" />
</div> </div>
<div class="py-1 px-1 flex justify-between"> <div class="flex justify-between px-1 py-1">
<div class="text-sn"> <div class="text-sn">
<n-skeleton v-if="loading" :width="100" size="medium" /> <n-skeleton v-if="loading" :width="100" size="medium" />
<template v-else> <template v-else>
@@ -61,7 +61,7 @@
<template #header-extra> <template #header-extra>
<n-tag type="info"></n-tag> <n-tag type="info"></n-tag>
</template> </template>
<div class="py-1 px-1 flex justify-between"> <div class="flex justify-between px-1 py-1">
<n-skeleton v-if="loading" :width="100" size="medium" /> <n-skeleton v-if="loading" :width="100" size="medium" />
<CountTo <CountTo
v-else v-else
@@ -71,8 +71,8 @@
class="text-3xl" class="text-3xl"
/> />
</div> </div>
<div class="py-2 px-2 flex justify-between"> <div class="flex justify-between px-2 py-2">
<div class="text-sn flex-1"> <div class="flex-1 text-sn">
<n-progress <n-progress
type="line" type="line"
:percentage="saleroom.degree" :percentage="saleroom.degree"
@@ -104,11 +104,11 @@
<template #header-extra> <template #header-extra>
<n-tag type="warning"></n-tag> <n-tag type="warning"></n-tag>
</template> </template>
<div class="py-1 px-1 flex justify-between"> <div class="flex justify-between px-1 py-1">
<n-skeleton v-if="loading" :width="100" size="medium" /> <n-skeleton v-if="loading" :width="100" size="medium" />
<CountTo v-else :startVal="1" :endVal="orderLarge.weekLarge" class="text-3xl" /> <CountTo v-else :startVal="1" :endVal="orderLarge.weekLarge" class="text-3xl" />
</div> </div>
<div class="py-1 px-1 flex justify-between"> <div class="flex justify-between px-1 py-1">
<div class="text-sn"> <div class="text-sn">
<n-skeleton v-if="loading" :width="100" size="medium" /> <n-skeleton v-if="loading" :width="100" size="medium" />
<template v-else> <template v-else>
@@ -153,11 +153,11 @@
<template #header-extra> <template #header-extra>
<n-tag type="error"></n-tag> <n-tag type="error"></n-tag>
</template> </template>
<div class="py-1 px-1 flex justify-between"> <div class="flex justify-between px-1 py-1">
<n-skeleton v-if="loading" :width="100" size="medium" /> <n-skeleton v-if="loading" :width="100" size="medium" />
<CountTo v-else prefix="¥" :startVal="1" :endVal="volume.weekLarge" class="text-3xl" /> <CountTo v-else prefix="¥" :startVal="1" :endVal="volume.weekLarge" class="text-3xl" />
</div> </div>
<div class="py-1 px-1 flex justify-between"> <div class="flex justify-between px-1 py-1">
<div class="text-sn"> <div class="text-sn">
<n-skeleton v-if="loading" :width="100" size="medium" /> <n-skeleton v-if="loading" :width="100" size="medium" />
<template v-else> <template v-else>
@@ -245,7 +245,7 @@
const visits = ref<any>({}); const visits = ref<any>({});
const saleroom = ref<any>({}); const saleroom = ref<any>({});
const orderLarge = ref<any>({}); const orderLarge = ref<any>({});
const volume = ref({}); const volume = ref(<any>{});
// 图标列表 // 图标列表
const iconList = [ const iconList = [

View File

@@ -16,15 +16,15 @@
</n-gi> </n-gi>
<n-gi> <n-gi>
<div class="flex justify-end w-full"> <div class="flex justify-end w-full">
<div class="flex flex-1 flex-col justify-center text-right"> <div class="flex flex-col justify-center flex-1 text-right">
<span class="text-secondary">项目数</span> <span class="text-secondary">项目数</span>
<span class="text-2xl">16</span> <span class="text-2xl">16</span>
</div> </div>
<div class="flex flex-1 flex-col justify-center text-right"> <div class="flex flex-col justify-center flex-1 text-right">
<span class="text-secondary">待办</span> <span class="text-secondary">待办</span>
<span class="text-2xl">3/15</span> <span class="text-2xl">3/15</span>
</div> </div>
<div class="flex flex-1 flex-col justify-center text-right"> <div class="flex flex-col justify-center flex-1 text-right">
<span class="text-secondary">消息</span> <span class="text-secondary">消息</span>
<span class="text-2xl">35</span> <span class="text-2xl">35</span>
</div> </div>
@@ -54,12 +54,12 @@
<GithubOutlined /> <GithubOutlined />
</n-icon> </n-icon>
</span> </span>
<span class="text-lg ml-4">Github</span> <span class="ml-4 text-lg">Github</span>
</div> </div>
<div class="flex mt-2 h-10 text-gray-400"> <div class="flex h-10 mt-2 text-gray-400">
是一个面向开源及私有软件项目的托管平台 是一个面向开源及私有软件项目的托管平台
</div> </div>
<div class="flex mt-2 h-10 text-gray-400"> 开源君2021-07-04 </div> <div class="flex h-10 mt-2 text-gray-400"> 开源君2021-07-04 </div>
</n-card> </n-card>
<n-card <n-card
size="small" size="small"
@@ -72,10 +72,10 @@
<LogoVue /> <LogoVue />
</n-icon> </n-icon>
</span> </span>
<span class="text-lg ml-4">Vue</span> <span class="ml-4 text-lg">Vue</span>
</div> </div>
<div class="flex mt-2 h-10 text-gray-400"> 渐进式 JavaScript 框架 </div> <div class="flex h-10 mt-2 text-gray-400"> 渐进式 JavaScript 框架 </div>
<div class="flex mt-2 h-10 text-gray-400"> 学不动也要学2021-07-04 </div> <div class="flex h-10 mt-2 text-gray-400"> 学不动也要学2021-07-04 </div>
</n-card> </n-card>
<n-card <n-card
size="small" size="small"
@@ -88,10 +88,10 @@
<Html5Outlined /> <Html5Outlined />
</n-icon> </n-icon>
</span> </span>
<span class="text-lg ml-4">Html5</span> <span class="ml-4 text-lg">Html5</span>
</div> </div>
<div class="flex mt-2 h-10 text-gray-400"> HTML5是互联网的下一代标准 </div> <div class="flex h-10 mt-2 text-gray-400"> HTML5是互联网的下一代标准 </div>
<div class="flex mt-2 h-10 text-gray-400"> 撸码也是一种艺术 2021-04-01 </div> <div class="flex h-10 mt-2 text-gray-400"> 撸码也是一种艺术 2021-04-01 </div>
</n-card> </n-card>
<n-card <n-card
size="small" size="small"
@@ -104,10 +104,10 @@
<LogoAngular /> <LogoAngular />
</n-icon> </n-icon>
</span> </span>
<span class="text-lg ml-4">Angular</span> <span class="ml-4 text-lg">Angular</span>
</div> </div>
<div class="flex mt-2 h-10 text-gray-400"> 现代 Web 开发平台百万粉丝热捧 </div> <div class="flex h-10 mt-2 text-gray-400"> 现代 Web 开发平台百万粉丝热捧 </div>
<div class="flex mt-2 h-10 text-gray-400"> 铁粉君 2021-07-04 </div> <div class="flex h-10 mt-2 text-gray-400"> 铁粉君 2021-07-04 </div>
</n-card> </n-card>
<n-card <n-card
size="small" size="small"
@@ -120,10 +120,10 @@
<LogoReact /> <LogoReact />
</n-icon> </n-icon>
</span> </span>
<span class="text-lg ml-4">React</span> <span class="ml-4 text-lg">React</span>
</div> </div>
<div class="flex mt-2 h-10 text-gray-400"> 用于构建用户界面的 JavaScript </div> <div class="flex h-10 mt-2 text-gray-400"> 用于构建用户界面的 JavaScript </div>
<div class="flex mt-2 h-10 text-gray-400"> 技术牛 2021-07-04 </div> <div class="flex h-10 mt-2 text-gray-400"> 技术牛 2021-07-04 </div>
</n-card> </n-card>
<n-card <n-card
size="small" size="small"
@@ -136,10 +136,10 @@
<LogoJavascript /> <LogoJavascript />
</n-icon> </n-icon>
</span> </span>
<span class="text-lg ml-4">Js</span> <span class="ml-4 text-lg">Js</span>
</div> </div>
<div class="flex mt-2 h-10 text-gray-400"> 路是走出来的而不是空想出来的 </div> <div class="flex h-10 mt-2 text-gray-400"> 路是走出来的而不是空想出来的 </div>
<div class="flex mt-2 h-10 text-gray-400"> 架构组 2021-07-04 </div> <div class="flex h-10 mt-2 text-gray-400"> 架构组 2021-07-04 </div>
</n-card> </n-card>
</div> </div>
</n-card> </n-card>
@@ -235,7 +235,7 @@
<DashboardOutlined /> <DashboardOutlined />
</n-icon> </n-icon>
</span> </span>
<span class="text-lx text-center">主控台</span> <span class="text-center text-lx">主控台</span>
</div> </div>
</n-card> </n-card>
<n-card size="small" class="cursor-pointer project-card-item" hoverable> <n-card size="small" class="cursor-pointer project-card-item" hoverable>
@@ -245,7 +245,7 @@
<ProfileOutlined /> <ProfileOutlined />
</n-icon> </n-icon>
</span> </span>
<span class="text-lx text-center">列表</span> <span class="text-center text-lx">列表</span>
</div> </div>
</n-card> </n-card>
<n-card size="small" class="cursor-pointer project-card-item" hoverable> <n-card size="small" class="cursor-pointer project-card-item" hoverable>
@@ -255,7 +255,7 @@
<FileProtectOutlined /> <FileProtectOutlined />
</n-icon> </n-icon>
</span> </span>
<span class="text-lx text-center">表单</span> <span class="text-center text-lx">表单</span>
</div> </div>
</n-card> </n-card>
<n-card size="small" class="cursor-pointer project-card-item" hoverable> <n-card size="small" class="cursor-pointer project-card-item" hoverable>
@@ -265,7 +265,7 @@
<ApartmentOutlined /> <ApartmentOutlined />
</n-icon> </n-icon>
</span> </span>
<span class="text-lx text-center">权限管理</span> <span class="text-center text-lx">权限管理</span>
</div> </div>
</n-card> </n-card>
<n-card size="small" class="cursor-pointer project-card-item" hoverable> <n-card size="small" class="cursor-pointer project-card-item" hoverable>
@@ -275,7 +275,7 @@
<SettingOutlined /> <SettingOutlined />
</n-icon> </n-icon>
</span> </span>
<span class="text-lx text-center">系统管理</span> <span class="text-center text-lx">系统管理</span>
</div> </div>
</n-card> </n-card>
<n-card size="small" class="cursor-pointer project-card-item" hoverable> <n-card size="small" class="cursor-pointer project-card-item" hoverable>
@@ -285,7 +285,7 @@
<DashboardOutlined /> <DashboardOutlined />
</n-icon> </n-icon>
</span> </span>
<span class="text-lx text-center">主控台</span> <span class="text-center text-lx">主控台</span>
</div> </div>
</n-card> </n-card>
</div> </div>
@@ -298,6 +298,10 @@
</div> </div>
</template> </template>
<script lang="ts">
export default { name: 'DashboardWorkplace' };
</script>
<script lang="ts" setup> <script lang="ts" setup>
import schoolboy from '@/assets/images/schoolboy.png'; import schoolboy from '@/assets/images/schoolboy.png';
import { import {

View File

@@ -63,7 +63,7 @@
name="files" name="files"
:width="100" :width="100"
:height="100" :height="100"
@uploadChange="uploadChange" @upload-change="uploadChange"
v-model:value="uploadList" v-model:value="uploadList"
helpText="单个文件不超过20MB最多只能上传10个文件" helpText="单个文件不超过20MB最多只能上传10个文件"
/> />

View File

@@ -12,9 +12,9 @@
<n-step title="确认转账信息" description="确认转账信息" /> <n-step title="确认转账信息" description="确认转账信息" />
<n-step title="完成转账" description="恭喜您,转账成功" /> <n-step title="完成转账" description="恭喜您,转账成功" />
</n-steps> </n-steps>
<step1 v-if="currentTab === 1" @nextStep="nextStep" /> <step1 v-if="currentTab === 1" @next-step="nextStep" />
<step2 v-if="currentTab === 2" @nextStep="nextStep" @prevStep="prevStep" /> <step2 v-if="currentTab === 2" @next-step="nextStep" @prevStep="prevStep" />
<step3 v-if="currentTab === 3" @prevStep="prevStep" @finish="finish" /> <step3 v-if="currentTab === 3" @prev-step="prevStep" @finish="finish" />
</n-space> </n-space>
</n-card> </n-card>
</div> </div>

View File

@@ -63,7 +63,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import { h, reactive, ref } from 'vue'; import { h, reactive, ref } from 'vue';
// import { useMessage } from 'naive-ui';
import { BasicTable, TableAction } from '@/components/Table'; import { BasicTable, TableAction } from '@/components/Table';
import { BasicForm, FormSchema, useForm } from '@/components/Form/index'; import { BasicForm, FormSchema, useForm } from '@/components/Form/index';
import { getTableList } from '@/api/table/list'; import { getTableList } from '@/api/table/list';
@@ -217,7 +216,6 @@
const router = useRouter(); const router = useRouter();
const formRef: any = ref(null); const formRef: any = ref(null);
// const message = useMessage();
const actionRef = ref(); const actionRef = ref();
const showModal = ref(false); const showModal = ref(false);
@@ -228,11 +226,6 @@
date: null, date: null,
}); });
const params = ref({
pageSize: 5,
name: 'xiaoMa',
});
const actionColumn = reactive({ const actionColumn = reactive({
width: 220, width: 220,
title: '操作', title: '操作',
@@ -285,7 +278,7 @@
}, },
}); });
const [register, {}] = useForm({ const [register, { getFieldsValue }] = useForm({
gridProps: { cols: '1 s:1 m:2 l:3 xl:4 2xl:4' }, gridProps: { cols: '1 s:1 m:2 l:3 xl:4 2xl:4' },
labelWidth: 80, labelWidth: 80,
schemas, schemas,
@@ -296,7 +289,7 @@
} }
const loadDataTable = async (res) => { const loadDataTable = async (res) => {
return await getTableList({ ...formParams, ...params.value, ...res }); return await getTableList({ ...getFieldsValue(), ...res });
}; };
function onCheckedRow(rowKeys) { function onCheckedRow(rowKeys) {

View File

@@ -1,23 +1,7 @@
module.exports = { module.exports = {
content: ['./index.html', './src/**/*.{vue,ts,tsx}'], content: ['./index.html', './src/**/*.{vue,ts,tsx}'],
important: true,
theme: { theme: {
extend: { extend: {},
zIndex: {
'-1': '-1',
},
colors: {
primary: {
DEFAULT: '#0960bd',
// dark: primaryColorDark,
},
},
screens: {
sm: '576px',
md: '768px',
lg: '992px',
xl: '1200px',
'2xl': '1600px',
},
},
}, },
}; };

View File

@@ -22,7 +22,7 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
const root = process.cwd(); const root = process.cwd();
const env = loadEnv(mode, root); const env = loadEnv(mode, root);
const viteEnv = wrapperEnv(env); const viteEnv = wrapperEnv(env);
const { VITE_PUBLIC_PATH, VITE_DROP_CONSOLE, VITE_PORT, VITE_GLOB_PROD_MOCK, VITE_PROXY } = const { VITE_PUBLIC_PATH, VITE_PORT, VITE_GLOB_PROD_MOCK, VITE_PROXY } =
viteEnv; viteEnv;
const prodMock = VITE_GLOB_PROD_MOCK; const prodMock = VITE_GLOB_PROD_MOCK;
const isBuild = command === 'build'; const isBuild = command === 'build';
@@ -46,26 +46,10 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
define: { define: {
__APP_INFO__: JSON.stringify(__APP_INFO__), __APP_INFO__: JSON.stringify(__APP_INFO__),
}, },
// css: {
// preprocessorOptions: {
// less: {
// modifyVars: {},
// javascriptEnabled: true,
// additionalData: `@import "src/styles/var.less";`,
// },
// },
// },
server: { server: {
host: true, host: true,
port: VITE_PORT, port: VITE_PORT,
proxy: createProxy(VITE_PROXY), proxy: createProxy(VITE_PROXY),
// proxy: {
// '/api': {
// target: '',
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api/, '/api/v1')
// }
// }
}, },
optimizeDeps: { optimizeDeps: {
include: [], include: [],
@@ -75,12 +59,6 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
target: 'es2015', target: 'es2015',
cssTarget: 'chrome80', cssTarget: 'chrome80',
outDir: OUTPUT_DIR, outDir: OUTPUT_DIR,
// terserOptions: {
// compress: {
// keep_infinity: true,
// drop_console: VITE_DROP_CONSOLE,
// },
// },
reportCompressedSize: false, reportCompressedSize: false,
chunkSizeWarningLimit: 2000, chunkSizeWarningLimit: 2000,
}, },

7338
yarn.lock

File diff suppressed because it is too large Load Diff