diff --git a/index.html b/index.html index 11603f8..0c18c48 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,5 @@ - + diff --git a/package.json b/package.json index 008d81d..5b12744 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "dependencies": { "axios": "^0.22.0", "element-plus": "^1.1.0-beta.19", + "moment": "^2.29.1", "unplugin-element-plus": "^0.1.0", "vue": "^3.2.16", "vue-axios": "^3.3.7", diff --git a/src/App.vue b/src/App.vue index 3e6b30b..4263498 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,16 +1,22 @@ diff --git a/src/config/menu.ts b/src/config/menu.ts index b42d87e..89df1f4 100644 --- a/src/config/menu.ts +++ b/src/config/menu.ts @@ -4,29 +4,29 @@ export default [ title: '系统管理', icon: 'el-icon-s-operation', child: [ - { title: '系统配置', path: '/system/config', icon: 'md-settings' }, - { title: '用户管理', path: '/system/user', icon: 'md-contact' }, - { title: '角色管理', path: '/system/role', icon: 'md-contacts' }, - { title: '博客文章', path: '/system/article', icon: 'md-paper' }, - { title: '分析统计', path: '/system/statistics', icon: 'md-pie' } + { title: '系统配置', path: '/system/config' }, + { title: '用户管理', path: '/system/user' }, + { title: '角色管理', path: '/system/role' }, + { title: '博客文章', path: '/system/article' }, + { title: '分析统计', path: '/system/statistics' } ] },{ name: 'api', title: 'API数据', icon: 'el-icon-s-data', child: [ - { title: '一言', path: '/api/hitokoto', icon: 'md-chatbubbles' }, - { title: '照片墙', path: '/api/photoWall', icon: 'md-images' }, - { title: '图片资源库', path: '/api/sourceImage', icon: 'md-image' }, - { title: '中国行政区划', path: '/api/chinaProvince', icon: 'md-map' }, - { title: '歌曲库', path: '/api/music', icon: 'md-musical-note' } + { title: '一言', path: '/api/hitokoto' }, + { title: '照片墙', path: '/api/photoWall' }, + { title: '图片资源库', path: '/api/sourceImage' }, + { title: '中国行政区划', path: '/api/chinaProvince' }, + { title: '歌曲库', path: '/api/music' } ] },{ name: 'tool', title: '工具', icon: 'el-icon-s-tools', child: [ - { title: 'SQL占位符替换', path: '/tool/sqlReplace', icon: 'md-copy' } + { title: 'SQL占位符替换', path: '/tool/sqlReplace' } ] } ] \ No newline at end of file diff --git a/src/env.d.ts b/src/env.d.ts index eb4b22b..d27eb5a 100644 --- a/src/env.d.ts +++ b/src/env.d.ts @@ -1,7 +1,7 @@ /// declare module '*.vue' { - import { DefineComponent, ComponentCustomProperties } from 'vue' + import { DefineComponent } from 'vue' // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types const component: DefineComponent<{}, {}, any> export default component diff --git a/src/main.ts b/src/main.ts index 2126736..b6b3e3d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -10,14 +10,15 @@ const service = axios.create({ timeout: 10000 }) -import { ElMessage } from 'element-plus' +import { ElMessage, ElLoading } from 'element-plus' // 添加请求拦截器 service.interceptors.request.use(config => { // 在发送请求之前添加token到请求头 - // if (localStorage.getItem('login_token')) { - // config.headers.token = localStorage.getItem('login_token') - // } + const token = localStorage.getItem('login_token') + if (token !== null && config.headers) { + config.headers.token = token + } return config }, err => { // 请求错误的处理 @@ -45,7 +46,7 @@ service.interceptors.response.use(res=> { }) // 全局路由导航前置守卫 -router.beforeEach(function (to, from, next: Function) { +router.beforeEach(function (to, from, next) { app.$store.commit('setBreadcrumb', routePathes[to.path] || []) if(filterExclude.indexOf(to.path) !== -1 || localStorage.getItem('login_token')) { next() @@ -58,4 +59,5 @@ const app = createApp(App) .use(router) .use(store) .use(VueAxios, service) + .directive('loading', ElLoading.directive) .mount('#app') diff --git a/src/model/api/hitokoto.ts b/src/model/api/hitokoto.ts new file mode 100644 index 0000000..225828d --- /dev/null +++ b/src/model/api/hitokoto.ts @@ -0,0 +1,9 @@ +export default interface HitokotoModel { + _id: string + hitokoto: string + type: string + from: string + creator: string + created_at: Date + number: number +} \ No newline at end of file diff --git a/src/model/api/music.ts b/src/model/api/music.ts new file mode 100644 index 0000000..6b225a0 --- /dev/null +++ b/src/model/api/music.ts @@ -0,0 +1,35 @@ +export interface MusicModel { + _id: string + name: string // 文件名 + ext: string // 扩展名 + md5?: string // md5哈希值 + size: number // 文件大小 + title?: string // 标题 + album?: string // 唱片集 + artist?: string // 艺术家 + lib_id: string // 歌单ID + lyric_id: string // 歌词ID +} + +export interface MusicLibModel { + _id: string + name: string // 歌单名称 + path: string // 歌单文件路径 +} + +export interface MusicLyricModel { + _id?: string + cloud_id?: number + name?: string + lyric?: string +} + +export interface MusicPlayerItem { + id: number + name: string + artist: string + album: string + url: string + cover: string + lrc: string | undefined +} \ No newline at end of file diff --git a/src/model/api/photowall.ts b/src/model/api/photowall.ts new file mode 100644 index 0000000..6b6ce86 --- /dev/null +++ b/src/model/api/photowall.ts @@ -0,0 +1,9 @@ +export default interface PhotoWallModel { + _id: string + name: string // 图片文件名 + md5: string // 文件md5哈希值 + thumbnail: string // 缩略图名称 + width: number // 宽度 + height: number // 高度 + index: number // 序号 +} \ No newline at end of file diff --git a/src/model/api/source-image.ts b/src/model/api/source-image.ts new file mode 100644 index 0000000..aea6477 --- /dev/null +++ b/src/model/api/source-image.ts @@ -0,0 +1,17 @@ +export interface SourceImageModel { + _id: string + mime: string // MIME类型 + hash: string // 图片md5值 + size: number // 图片大小 + label: string[] // 图片标签 + img: ArrayBuffer // 图片二进制数据 + created_at: Date +} + +/** + * 图片标签 + */ +export interface ImageLabel { + name: string // 标签名称 + color: string // 标签颜色 +} \ No newline at end of file diff --git a/src/model/baselist.ts b/src/model/baselist.ts new file mode 100644 index 0000000..7b5fd3d --- /dev/null +++ b/src/model/baselist.ts @@ -0,0 +1,65 @@ +import { Vue } from 'vue-class-component' +import { Page } from './common.dto' +import moment from 'moment' + +export default abstract class BaseList extends Vue { + /** + * 表格数据加载中 + */ + protected loading: boolean = false + /** + * 表单提交中 + */ + protected modalLoading: boolean = true + /** + * 数据总数 + */ + protected total: number = 0 + protected abstract search: T + /** + * 加载数据的实现 + */ + abstract loadData(): Promise + /** + * 加载数据 + * @param resetPage 是否重置页码 + */ + loadDataBase(resetPage: boolean = false): void { + if(resetPage) { + this.search.pageNum = 1 + } + this.loadData() + } + /** + * 重置搜索项 + */ + reset() { + this.search.reset() + this.loadData() + } + /** + * 页码变更 + * @param pageNum 页码 + */ + pageChange(pageNum: number) { + this.search.pageNum = pageNum + this.loadData() + } + + /** + * 每页数据条数变更 + * @param pageSize 每页数据条数 + */ + pageSizeChange(pageSize: number) { + this.search.limit = pageSize + this.loadData() + } + + /** + * 日期时间格式化 + * @param dateStr 日期时间 + */ + datetimeFormat(dateStr: string) { + return moment(dateStr).format('YYYY-MM-DD HH:mm:ss') + } +} \ No newline at end of file diff --git a/src/model/common.dto.ts b/src/model/common.dto.ts new file mode 100644 index 0000000..9581242 --- /dev/null +++ b/src/model/common.dto.ts @@ -0,0 +1,21 @@ +export interface MsgResult { + status: boolean + message: string +} + +/** + * 分页查询基础类 + */ +export class Page { + // 页码 + pageNum: number = 1 + // 每页数据条数 + limit: number = 10 + /** + * 重置分页 + */ + public reset() { + this.pageNum = 1 + this.limit = 10 + } +} \ No newline at end of file diff --git a/src/model/system/article.ts b/src/model/system/article.ts new file mode 100644 index 0000000..8d781c8 --- /dev/null +++ b/src/model/system/article.ts @@ -0,0 +1,34 @@ +// import { CreateElement, VNode } from 'vue' + +export interface ArticleModel { + _id: string + path: string[] // 访问路径 + categories: string[] //分类 + tags: string[] // 标签 + title: string // 标题 + create_date: Date // 文章发布日期 + content_len: number // 正文长度 + is_splited: boolean // 是否分词 +} + +export interface TreeNodeBase { + name: string | null // 节点名称(ID) + deep: number // 节点深度(根节点为0) +} + +export interface TreeNode extends TreeNodeBase { + expand: boolean // 是否展开 + id?: string // 文章ID + title: string //显示的文字 + children?: TreeNode[] // 子节点 + loading?: boolean // 是否显示加载中 + nodeKey?: number // 树节点唯一标识 + isDirectory: boolean // 该节点是否为目录 + // render?: (h: CreateElement, {data}: {data: TreeNode}) => Array +} + +export interface TreeNodeSource { + _id: string + cnt: number + article_id: string | null +} \ No newline at end of file diff --git a/src/model/system/system-config.ts b/src/model/system/system-config.ts new file mode 100644 index 0000000..fbde539 --- /dev/null +++ b/src/model/system/system-config.ts @@ -0,0 +1,9 @@ +export interface SystemConfigModel { + _id?: string + name: string // 配置项名称 + value: object | string // 配置项内容 + description: string // 描述 + is_public: boolean // 是否公开 + created_at?: Date // 创建时间 + updated_at?: Date // 更新时间 +} \ No newline at end of file diff --git a/src/model/system/system-role.ts b/src/model/system/system-role.ts new file mode 100644 index 0000000..39a9a54 --- /dev/null +++ b/src/model/system/system-role.ts @@ -0,0 +1,10 @@ +export interface SystemRoleModel { + _id: string | null + name: string | null // 角色名称 + description: string | null // 描述 + methods: string[] // 允许的请求类型(优先级3) + include_uri: string[] // 包含的URI(优先级2) + exclude_uri: string[] // 排除的URI(优先级1) + created_at?: Date // 创建时间 + updated_at?: Date // 更新时间 +} \ No newline at end of file diff --git a/src/model/system/system-user.ts b/src/model/system/system-user.ts new file mode 100644 index 0000000..d2cebfc --- /dev/null +++ b/src/model/system/system-user.ts @@ -0,0 +1,9 @@ +export interface SystemUserModel { + _id: string | null + username: string | null + password: string | null + realname: string | null + role_ids: string[] + created_at?: Date + updated_at?: Date +} \ No newline at end of file diff --git a/src/router.ts b/src/router.ts index 1ed98a2..7ab0021 100644 --- a/src/router.ts +++ b/src/router.ts @@ -2,11 +2,16 @@ import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router' import Login from './views/Login.vue' import Home from './views/Home.vue' -// import Welcome from '@/views/Welcome.vue' - +import Welcome from './views/Welcome.vue' +import SystemUser from './views/system/SystemUser.vue' +import SystemRole from './views/system/SystemRole.vue' const routes: Array = [ { path: '/login', name: 'Login', component: Login }, - { path: '/', name: 'Home', component: Home, children: []} + { path: '/', name: 'Home', component: Home, children: [ + { path: '/', name: 'Welcome', component: Welcome }, + { path: '/system/user', name: 'SystemUser', component: SystemUser }, + { path: '/system/role', name: 'SystemRole', component: SystemRole }, + ]} ] export const router = createRouter({ diff --git a/src/static/common.less b/src/static/common.less index bb0aaef..9e5364e 100644 --- a/src/static/common.less +++ b/src/static/common.less @@ -41,16 +41,11 @@ html,body,#app,.layout { color: #9ea7b4; } } -.search-title { - line-height: 32px; - text-align: right; - padding-right: 5px; -} .table-container { position: relative; } .btn-container { - padding: 10px 0; + margin-bottom: 10px; button { margin-right: 3px; } diff --git a/src/types.ts b/src/types.ts deleted file mode 100644 index 76cc4e6..0000000 --- a/src/types.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type VForm = Vue & { - validate: (callback: (valid: boolean) => void) => void - resetValidation: () => boolean - reset: () => void -} \ No newline at end of file diff --git a/src/views/Home.vue b/src/views/Home.vue index 2df7b33..79516b4 100644 --- a/src/views/Home.vue +++ b/src/views/Home.vue @@ -51,6 +51,7 @@ \ No newline at end of file diff --git a/src/views/system/SystemRole.vue b/src/views/system/SystemRole.vue new file mode 100644 index 0000000..0d6e216 --- /dev/null +++ b/src/views/system/SystemRole.vue @@ -0,0 +1,212 @@ + + + \ No newline at end of file diff --git a/src/views/system/SystemUser.vue b/src/views/system/SystemUser.vue new file mode 100644 index 0000000..e69de29 diff --git a/src/vuex.d.ts b/src/vuex.d.ts new file mode 100644 index 0000000..b7528a4 --- /dev/null +++ b/src/vuex.d.ts @@ -0,0 +1,10 @@ +import { ComponentCustomProperties } from 'vue' +import { Store } from 'vuex' +import { StateType } from './store/types' + +declare module '@vue/runtime-core' { + // provide typings for `this.$store` + interface ComponentCustomProperties { + $store: Store + } +} \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts index 524a6ba..bb0fa03 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -21,6 +21,6 @@ export default defineConfig({ build: { outDir: 'dist', assetsDir: 'assets', // 静态资源的存放路径, 相对于outDir - cssCodeSplit: true + cssCodeSplit: true // 是否拆分css } }) diff --git a/yarn.lock b/yarn.lock index fd3ebb7..19c6adb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -663,6 +663,11 @@ mime@^1.4.1: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== +moment@^2.29.1: + version "2.29.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" + integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== + ms@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" @@ -1068,9 +1073,9 @@ vscode-uri@^3.0.2: integrity sha512-jkjy6pjU1fxUvI51P+gCsxg1u2n8LSt0W6KrCNQceaziKzff74GoWmjVG46KieVzybO1sttPQmYfrwSHey7GUA== vscode-vue-languageservice@^0.27.0: - version "0.27.27" - resolved "https://registry.yarnpkg.com/vscode-vue-languageservice/-/vscode-vue-languageservice-0.27.27.tgz#abaf6190768d30e317d24220c76e96c0c7d31751" - integrity sha512-q5vaaTxQpsqr4O2h2A5zXQtK17ZHKdrcjv6gZaItTBcI4rxw6GIHoblYsNXMo+dhBZEmFmyI18iPn+a7RajFEQ== + version "0.27.28" + resolved "https://registry.yarnpkg.com/vscode-vue-languageservice/-/vscode-vue-languageservice-0.27.28.tgz#97f537cf8d9be80f835b440de49a6a3d492d5b3d" + integrity sha512-dkYufKL/kchAxIxz2mYJDwsQuc7wnjTY+vc+sVz/DkFWfPEK0VaOStuKc85UME6VJ2IJzGEN1LHERGM65u8deQ== dependencies: "@volar/code-gen" "^0.27.24" "@volar/html2pug" "^0.27.13"