feat: 第三方库作为VUE插件进行初始化
parent
95021c503e
commit
7f9cbe8466
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"tabWidth": 2,
|
"tabWidth": 2,
|
||||||
"printWidth": 120,
|
"printWidth": 180,
|
||||||
"bracketSpacing": true,
|
"bracketSpacing": true,
|
||||||
"singleQuote": true,
|
"singleQuote": true,
|
||||||
"arrowParens": "avoid"
|
"arrowParens": "avoid"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "starter-vue",
|
"name": "starter-vue",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.0",
|
"version": "0.0.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@ addToastInterceptor(api.instance);
|
||||||
* 添加异常处理拦截器
|
* 添加异常处理拦截器
|
||||||
*/
|
*/
|
||||||
addExceptionInterceptor(api.instance, () => api.expireHandler?.());
|
addExceptionInterceptor(api.instance, () => api.expireHandler?.());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加登陆令牌拦截器
|
* 添加登陆令牌拦截器
|
||||||
*/
|
*/
|
||||||
addAuthInterceptor(api.instance);
|
addAuthInterceptor(api.instance);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { App } from 'vue';
|
||||||
import { Api } from '../generated/Api';
|
import { Api } from '../generated/Api';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -9,4 +10,12 @@ export class Service extends Api<unknown> {
|
||||||
* @description 勿动
|
* @description 勿动
|
||||||
*/
|
*/
|
||||||
expireHandler: () => void = () => {};
|
expireHandler: () => void = () => {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 作为VUE插件进行初始化
|
||||||
|
* @param app
|
||||||
|
*/
|
||||||
|
install(app: App) {
|
||||||
|
app.config.globalProperties.$api = this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,6 @@
|
||||||
<BreadCrumb></BreadCrumb>
|
<BreadCrumb></BreadCrumb>
|
||||||
<div>
|
<div>
|
||||||
<a-link>需要帮助?</a-link>
|
<a-link>需要帮助?</a-link>
|
||||||
<a-button size="mini" @click="router.push({ path: route.path, query: { s: Math.random() }, force: true })">
|
|
||||||
<template #icon>
|
|
||||||
<i class="icon-park-outline-redo"></i>
|
|
||||||
</template>
|
|
||||||
</a-button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,4 @@
|
||||||
import {
|
import { AnForm, AnFormInstance, AnFormModal, AnFormModalInstance, AnFormModalProps, AnFormProps, getModel } from '@/components/AnForm';
|
||||||
AnForm,
|
|
||||||
AnFormInstance,
|
|
||||||
AnFormModal,
|
|
||||||
AnFormModalInstance,
|
|
||||||
AnFormModalProps,
|
|
||||||
AnFormProps,
|
|
||||||
getModel,
|
|
||||||
} from '@/components/AnForm';
|
|
||||||
import AnEmpty from '@/components/AnEmpty/AnEmpty.vue';
|
import AnEmpty from '@/components/AnEmpty/AnEmpty.vue';
|
||||||
import { Button, PaginationProps, Table, TableColumnData, TableData, TableInstance } from '@arco-design/web-vue';
|
import { Button, PaginationProps, Table, TableColumnData, TableData, TableInstance } from '@arco-design/web-vue';
|
||||||
import { isArray, isFunction, merge } from 'lodash-es';
|
import { isArray, isFunction, merge } from 'lodash-es';
|
||||||
|
|
@ -14,14 +6,8 @@ import { InjectionKey, PropType, Ref, VNodeChild, defineComponent, ref } from 'v
|
||||||
import { PluginContainer } from '../hooks/useTablePlugin';
|
import { PluginContainer } from '../hooks/useTablePlugin';
|
||||||
|
|
||||||
type DataFn = (filter: { page: number; size: number; [key: string]: any }) => any | Promise<any>;
|
type DataFn = (filter: { page: number; size: number; [key: string]: any }) => any | Promise<any>;
|
||||||
|
export type ArcoTableProps = Omit<TableInstance['$props'], 'ref' | 'pagination' | 'loading' | 'data' | 'onPageChange' | 'onPageSizeChange'>;
|
||||||
export type ArcoTableProps = Omit<
|
|
||||||
TableInstance['$props'],
|
|
||||||
'ref' | 'pagination' | 'loading' | 'data' | 'onPageChange' | 'onPageSizeChange'
|
|
||||||
>;
|
|
||||||
|
|
||||||
export const AnTableContextKey = Symbol('AnTableContextKey') as InjectionKey<AnTableContext>;
|
export const AnTableContextKey = Symbol('AnTableContextKey') as InjectionKey<AnTableContext>;
|
||||||
|
|
||||||
export type TableColumnRender = (data: { record: TableData; column: TableColumnData; rowIndex: number }) => VNodeChild;
|
export type TableColumnRender = (data: { record: TableData; column: TableColumnData; rowIndex: number }) => VNodeChild;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -207,9 +193,7 @@ export const AnTable = defineComponent({
|
||||||
<div class="an-table table w-full">
|
<div class="an-table table w-full">
|
||||||
<div class={`mb-3 flex gap-2 toolbar justify-between`}>
|
<div class={`mb-3 flex gap-2 toolbar justify-between`}>
|
||||||
{this.create && <AnFormModal {...this.create} ref="createRef" onSubmited={this.reload}></AnFormModal>}
|
{this.create && <AnFormModal {...this.create} ref="createRef" onSubmited={this.reload}></AnFormModal>}
|
||||||
{this.modify && (
|
{this.modify && <AnFormModal {...this.modify} trigger={false} ref="modifyRef" onSubmited={this.refresh}></AnFormModal>}
|
||||||
<AnFormModal {...this.modify} trigger={false} ref="modifyRef" onSubmited={this.refresh}></AnFormModal>
|
|
||||||
)}
|
|
||||||
{this.$slots.action?.(this.renderData)}
|
{this.$slots.action?.(this.renderData)}
|
||||||
{this.pluginer?.actions && (
|
{this.pluginer?.actions && (
|
||||||
<div class={`flex-1 flex gap-2 items-center`}>
|
<div class={`flex-1 flex gap-2 items-center`}>
|
||||||
|
|
@ -220,12 +204,7 @@ export const AnTable = defineComponent({
|
||||||
)}
|
)}
|
||||||
{this.search && (
|
{this.search && (
|
||||||
<div>
|
<div>
|
||||||
<AnForm
|
<AnForm ref="searchRef" v-model:model={this.search.model} items={this.search.items} formProps={this.search.formProps}>
|
||||||
ref="searchRef"
|
|
||||||
v-model:model={this.search.model}
|
|
||||||
items={this.search.items}
|
|
||||||
formProps={this.search.formProps}
|
|
||||||
>
|
|
||||||
{{
|
{{
|
||||||
submit: () => (
|
submit: () => (
|
||||||
<Button type="primary" loading={this.loading} onClick={this.reload}>
|
<Button type="primary" loading={this.loading} onClick={this.reload}>
|
||||||
|
|
@ -279,10 +258,7 @@ export type AnTableInstance = InstanceType<typeof AnTable>;
|
||||||
/**
|
/**
|
||||||
* 表格组件参数
|
* 表格组件参数
|
||||||
*/
|
*/
|
||||||
export type AnTableProps = Pick<
|
export type AnTableProps = Pick<AnTableInstance['$props'], 'source' | 'columns' | 'search' | 'paging' | 'create' | 'modify' | 'tableProps' | 'pluginer'>;
|
||||||
AnTableInstance['$props'],
|
|
||||||
'source' | 'columns' | 'search' | 'paging' | 'create' | 'modify' | 'tableProps' | 'pluginer'
|
|
||||||
>;
|
|
||||||
|
|
||||||
export interface AnTableContext {
|
export interface AnTableContext {
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { ButtonProps, TableData } from '@arco-design/web-vue';
|
||||||
|
|
||||||
|
export interface AnTableActionBase {
|
||||||
|
text: string;
|
||||||
|
icon: string | Component;
|
||||||
|
visible: () => boolean;
|
||||||
|
disable: () => boolean;
|
||||||
|
buttonProps: ButtonProps;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AnTableActionBatch {
|
||||||
|
type: 'batch';
|
||||||
|
onClick: (rows: TableData) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AnTableAction = AnTableActionBase & AnTableActionBatch;
|
||||||
|
|
@ -35,6 +35,16 @@ export interface TableUseOptions extends Pick<AnTableProps, 'source' | 'tablePro
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
columns?: TableColumn[];
|
columns?: TableColumn[];
|
||||||
|
/**
|
||||||
|
* 操作栏
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* [{
|
||||||
|
* text: '按钮',
|
||||||
|
* onClick: () => null,
|
||||||
|
* }]
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
actions?: any[];
|
actions?: any[];
|
||||||
/**
|
/**
|
||||||
* 搜索表单
|
* 搜索表单
|
||||||
|
|
|
||||||
|
|
@ -2,22 +2,7 @@ import dayjs from 'dayjs';
|
||||||
import 'dayjs/locale/zh-cn';
|
import 'dayjs/locale/zh-cn';
|
||||||
import localData from 'dayjs/plugin/localeData';
|
import localData from 'dayjs/plugin/localeData';
|
||||||
import relativeTime from 'dayjs/plugin/relativeTime';
|
import relativeTime from 'dayjs/plugin/relativeTime';
|
||||||
|
import { App } from 'vue';
|
||||||
/**
|
|
||||||
*
|
|
||||||
* 默认日期时间格式
|
|
||||||
*/
|
|
||||||
const DATETIME = 'YYYY-MM-DD HH:mm';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 默认日期格式
|
|
||||||
*/
|
|
||||||
const DATE = 'YYYY-MM-DD';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 默认时间格式
|
|
||||||
*/
|
|
||||||
const TIME = 'HH:mm:ss';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 中文语言包
|
* 中文语言包
|
||||||
|
|
@ -63,4 +48,11 @@ dayjs.prototype.format = function (format: string = dayjs.DATETIME) {
|
||||||
return this._format(format);
|
return this._format(format);
|
||||||
};
|
};
|
||||||
|
|
||||||
export { DATE, DATETIME, TIME, dayjs };
|
/**
|
||||||
|
* 作为VUE插件进行初始化
|
||||||
|
*/
|
||||||
|
dayjs.install = function dayjsPlugin(app: App) {
|
||||||
|
app.config.globalProperties.$dayjs = dayjs;
|
||||||
|
};
|
||||||
|
|
||||||
|
export { dayjs };
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import 'dayjs';
|
import 'dayjs';
|
||||||
|
import { App } from 'vue';
|
||||||
|
|
||||||
declare module 'dayjs' {
|
declare module 'dayjs' {
|
||||||
/**
|
/**
|
||||||
|
|
@ -13,4 +14,6 @@ declare module 'dayjs' {
|
||||||
interface Dayjs {
|
interface Dayjs {
|
||||||
_format: Dayjs['format'];
|
_format: Dayjs['format'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export var install: (app: App) => void;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import NProgress from 'nprogress';
|
import NProgress from 'nprogress';
|
||||||
import 'nprogress/nprogress.css';
|
import 'nprogress/nprogress.css';
|
||||||
import './nprogress.css';
|
import './nprogress.css';
|
||||||
|
import { App } from 'vue';
|
||||||
|
|
||||||
NProgress.configure({
|
NProgress.configure({
|
||||||
showSpinner: false,
|
showSpinner: false,
|
||||||
|
|
@ -8,5 +9,9 @@ NProgress.configure({
|
||||||
minimum: 0.3,
|
minimum: 0.3,
|
||||||
});
|
});
|
||||||
|
|
||||||
export { NProgress };
|
/**
|
||||||
|
* 作为VUE插件进行初始化
|
||||||
|
*/
|
||||||
|
NProgress.install = function (app: App) {};
|
||||||
|
|
||||||
|
export { NProgress };
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
import 'nprogress';
|
||||||
|
import { App } from 'vue';
|
||||||
|
|
||||||
|
declare module 'nprogress' {
|
||||||
|
interface NProgress {
|
||||||
|
install: (app: App) => void;
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/main.ts
14
src/main.ts
|
|
@ -1,12 +1,18 @@
|
||||||
import { createApp } from 'vue';
|
import { createApp } from 'vue';
|
||||||
import App from './App.vue';
|
import App from '@/App.vue';
|
||||||
import { router } from './router';
|
import { router } from '@/router';
|
||||||
import { store } from './store';
|
import { store } from '@/store';
|
||||||
import { style } from './styles';
|
import { style } from '@/styles';
|
||||||
|
import { dayjs } from '@/libs/dayjs';
|
||||||
|
import { NProgress } from '@/libs/nprogress';
|
||||||
|
import { api } from '@/api';
|
||||||
|
|
||||||
const run = async () => {
|
const run = async () => {
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
|
app.use(dayjs);
|
||||||
|
app.use(NProgress);
|
||||||
app.use(store);
|
app.use(store);
|
||||||
|
app.use(api);
|
||||||
app.use(style);
|
app.use(style);
|
||||||
app.use(router);
|
app.use(router);
|
||||||
await router.isReady();
|
await router.isReady();
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,17 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<a-menu-item key={route.path} v-slots={{ icon }} onClick={() => goto(route)}>
|
<a-menu-item key={route.path} v-slots={{ icon }}>
|
||||||
|
{route.link ? (
|
||||||
|
<div class="flex items-center justify-between gap-2" onClick={() => goto(route)}>
|
||||||
|
<div>{route.title}</div>
|
||||||
|
<div class="text-xs text-gray-400">
|
||||||
|
{/* <a-badge count={8}>8</a-badge> */}
|
||||||
|
{route.hide === 'prod' ? <a-tag color="red">{'开发'}</a-tag> : null}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<router-link to={route.path}>
|
||||||
<div class="flex items-center justify-between gap-2">
|
<div class="flex items-center justify-between gap-2">
|
||||||
<div>{route.title}</div>
|
<div>{route.title}</div>
|
||||||
<div class="text-xs text-gray-400">
|
<div class="text-xs text-gray-400">
|
||||||
|
|
@ -50,6 +60,8 @@ export default defineComponent({
|
||||||
{route.hide === 'prod' ? <a-tag color="red">{'开发'}</a-tag> : null}
|
{route.hide === 'prod' ? <a-tag color="red">{'开发'}</a-tag> : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</router-link>
|
||||||
|
)}
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<a-layout class="layout">
|
<a-layout class="layout">
|
||||||
<a-layout-header
|
<a-layout-header class="h-13 overflow-hidden flex justify-between items-center gap-4 px-2 pr-4 border-b border-slate-200 bg-white dark:bg-slate-800 dark:border-slate-700">
|
||||||
class="h-13 overflow-hidden flex justify-between items-center gap-4 px-2 pr-4 border-b border-slate-200 bg-white dark:bg-slate-800 dark:border-slate-700"
|
|
||||||
>
|
|
||||||
<div class="h-13 flex items-center">
|
<div class="h-13 flex items-center">
|
||||||
<!-- <a-button size="small" @click="isCollapsed = !isCollapsed">
|
<!-- <a-button size="small" @click="isCollapsed = !isCollapsed">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
|
|
@ -19,18 +17,6 @@
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<div>
|
|
||||||
<a-input-search placeholder="搜索菜单/页面" :allow-clear="true"></a-input-search>
|
|
||||||
</div>
|
|
||||||
<a-tooltip content="上传文件">
|
|
||||||
<a-button @click="() => null" class="!bg-transparent !hover:bg-gray-100">
|
|
||||||
<template #icon>
|
|
||||||
<a-badge :count="1" :dot="true">
|
|
||||||
<i class="text-base icon-park-outline-upload-one"></i>
|
|
||||||
</a-badge>
|
|
||||||
</template>
|
|
||||||
</a-button>
|
|
||||||
</a-tooltip>
|
|
||||||
<a-tooltip v-for="btn in buttons" :key="btn.icon" :content="btn.tooltip">
|
<a-tooltip v-for="btn in buttons" :key="btn.icon" :content="btn.tooltip">
|
||||||
<a-button @click="btn.onClick" class="!bg-transparent !hover:bg-gray-100">
|
<a-button @click="btn.onClick" class="!bg-transparent !hover:bg-gray-100">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
|
|
@ -90,9 +76,9 @@ import { useAppStore } from '@/store/app';
|
||||||
import { useMenuStore } from '@/store/menu';
|
import { useMenuStore } from '@/store/menu';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
import { IconSync } from '@arco-design/web-vue/es/icon';
|
import { IconSync } from '@arco-design/web-vue/es/icon';
|
||||||
|
import { useFullscreen } from '@vueuse/core';
|
||||||
import Menu from './Menu.vue';
|
import Menu from './Menu.vue';
|
||||||
import userDropdown from './UserDropdown.vue';
|
import userDropdown from './UserDropdown.vue';
|
||||||
import { useFullscreen } from '@vueuse/core';
|
|
||||||
|
|
||||||
defineOptions({ name: 'LayoutPage' });
|
defineOptions({ name: 'LayoutPage' });
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,6 @@
|
||||||
<AnPage></AnPage>
|
<AnPage></AnPage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="tsx"></script>
|
|
||||||
|
|
||||||
<style lang="less"></style>
|
|
||||||
|
|
||||||
<route lang="json">
|
<route lang="json">
|
||||||
{
|
{
|
||||||
"redirect": "/setting/common",
|
"redirect": "/setting/common",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { NProgress } from '@/libs/nprogress';
|
import NProgress from 'nprogress';
|
||||||
import { useAppStore } from '@/store/app';
|
import { useAppStore } from '@/store/app';
|
||||||
import { Router } from 'vue-router';
|
import { Router } from 'vue-router';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,10 +78,10 @@ body {
|
||||||
background-color: var(--color-neutral-2);
|
background-color: var(--color-neutral-2);
|
||||||
}
|
}
|
||||||
&.arco-menu-selected {
|
&.arco-menu-selected {
|
||||||
color: @arcoblue-6;
|
// color: @arcoblue-6;
|
||||||
background-color: rgb(var(--primary-1));
|
// background-color: rgb(var(--primary-1));
|
||||||
// color: #fff;
|
color: #fff;
|
||||||
// background-color: rgb(var(--primary-6));
|
background-color: rgb(var(--primary-6));
|
||||||
.arco-menu-icon {
|
.arco-menu-icon {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import { Router, RouteLocationNormalizedLoaded } from "vue-router";
|
import { Router, RouteLocationNormalizedLoaded } from 'vue-router';
|
||||||
|
|
||||||
declare module "vue" {
|
declare module 'vue' {
|
||||||
interface ComponentCustomProperties {
|
interface ComponentCustomProperties {
|
||||||
$router: Router;
|
$router: Router;
|
||||||
$route: RouteLocationNormalizedLoaded;
|
$route: RouteLocationNormalizedLoaded;
|
||||||
|
$dayjs: Dayjs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue