feat: 状态展示统一为圆点
- 新增状态圆点组件,用户管理、角色与字典的状态改用圆点 - 用户管理操作列放宽到 200,登录页移动端版本号紧随项目名 - 应用中心分组按内容高度排列 - 函数注释统一为展开式多行 - 格式校验脚本忽略不存在的目录
This commit is contained in:
1 parent
53a97cac21
commit
f443eb6bbe
13 files changed
+133
-39
No files matched your search
@@ -36,7 +36,9 @@ const tableList = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
/** 下划线命名转驼峰首字母大写,如 sys_user → SysUser */
|
/**
|
||||||
|
* 下划线命名转驼峰首字母大写,如 sys_user → SysUser
|
||||||
|
*/
|
||||||
function toPascalCase(name: string): string {
|
function toPascalCase(name: string): string {
|
||||||
return name
|
return name
|
||||||
.split("_")
|
.split("_")
|
||||||
@@ -196,7 +198,9 @@ const genConfigMap: Record<string, any> = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 未配置表的默认生成配置(无 id,进入抽屉后从基础配置步骤开始) */
|
/**
|
||||||
|
* 未配置表的默认生成配置(无 id,进入抽屉后从基础配置步骤开始)
|
||||||
|
*/
|
||||||
function buildDefaultConfig(tableName: string) {
|
function buildDefaultConfig(tableName: string) {
|
||||||
return {
|
return {
|
||||||
tableName,
|
tableName,
|
||||||
@@ -214,7 +218,9 @@ function buildDefaultConfig(tableName: string) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 构造代码生成预览文件列表 */
|
/**
|
||||||
|
* 构造代码生成预览文件列表
|
||||||
|
*/
|
||||||
function buildPreviewFiles(tableName: string, tableComment: string) {
|
function buildPreviewFiles(tableName: string, tableComment: string) {
|
||||||
const bizName = tableName.replace(/^sys_/, "");
|
const bizName = tableName.replace(/^sys_/, "");
|
||||||
const entityName = toPascalCase(bizName);
|
const entityName = toPascalCase(bizName);
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@
|
|||||||
"lint:lint-staged": "lint-staged",
|
"lint:lint-staged": "lint-staged",
|
||||||
"lint": "pnpm run lint:eslint && pnpm run lint:prettier && pnpm run lint:stylelint",
|
"lint": "pnpm run lint:eslint && pnpm run lint:prettier && pnpm run lint:stylelint",
|
||||||
"lint:check": "eslint src mock vite.config.ts uno.config.ts eslint.config.ts",
|
"lint:check": "eslint src mock vite.config.ts uno.config.ts eslint.config.ts",
|
||||||
"format:check": "prettier --check \"src/**/*.{ts,vue,scss,css,json}\" \"mock/**/*.ts\" \"*.{ts,cjs,mjs,json,yaml}\" \".github/workflows/*.{yml,yaml}\"",
|
"format:check": "prettier --check --no-error-on-unmatched-pattern \"src/**/*.{ts,vue,scss,css,json}\" \"mock/**/*.ts\" \"*.{ts,cjs,mjs,json,yaml}\" \".github/workflows/*.{yml,yaml}\"",
|
||||||
"style:check": "stylelint \"src/**/*.{css,scss,vue}\"",
|
"style:check": "stylelint \"src/**/*.{css,scss,vue}\"",
|
||||||
"check": "pnpm run type-check && pnpm run lint:check && pnpm run format:check && pnpm run style:check",
|
"check": "pnpm run type-check && pnpm run lint:check && pnpm run format:check && pnpm run style:check",
|
||||||
"preinstall": "npx only-allow pnpm",
|
"preinstall": "npx only-allow pnpm",
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<!-- 状态圆点:启用为成功色,停用为占位色 -->
|
||||||
|
<template>
|
||||||
|
<span class="status-dot" :class="{ 'is-stopped': !active }" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
defineOptions({ name: "StatusDot" });
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否处于启用状态
|
||||||
|
*/
|
||||||
|
defineProps<{ active: boolean }>();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.status-dot {
|
||||||
|
display: inline-block;
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
background-color: var(--el-color-success);
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-dot.is-stopped {
|
||||||
|
background-color: var(--el-text-color-placeholder);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -161,7 +161,9 @@ export interface ISelectConfig<T = any> {
|
|||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
/** popover 组件属性 */
|
/** popover 组件属性 */
|
||||||
popover?: Partial<Omit<PopoverProps, "visible" | "v-model:visible">>;
|
popover?: Partial<Omit<PopoverProps, "visible" | "v-model:visible">>;
|
||||||
/** 列表的网络请求函数(需返回 Promise) */
|
/**
|
||||||
|
* 列表的网络请求函数(需返回 Promise)
|
||||||
|
*/
|
||||||
indexAction: (_queryParams: T) => Promise<any>;
|
indexAction: (_queryParams: T) => Promise<any>;
|
||||||
/** 主键(跨页选择必填,默认为 id) */
|
/** 主键(跨页选择必填,默认为 id) */
|
||||||
pk?: string;
|
pk?: string;
|
||||||
|
|||||||
@@ -78,7 +78,9 @@ export function usePageTable<T, Q extends PageQuery = PageQuery>(
|
|||||||
export interface UsePageTableOptions<T, Q extends PageQuery> {
|
export interface UsePageTableOptions<T, Q extends PageQuery> {
|
||||||
/** 初值会深复制,请求和编辑不会改变重置基准。 */
|
/** 初值会深复制,请求和编辑不会改变重置基准。 */
|
||||||
initialParams: Q;
|
initialParams: Q;
|
||||||
/** 接收查询快照;请求异常由调用方处理。 */
|
/**
|
||||||
|
* 接收查询快照;请求异常由调用方处理。
|
||||||
|
*/
|
||||||
request: (params: Q) => Promise<PageResult<T>>;
|
request: (params: Q) => Promise<PageResult<T>>;
|
||||||
/** 恢复参数前,同步重置页面自有的搜索控件。 */
|
/** 恢复参数前,同步重置页面自有的搜索控件。 */
|
||||||
onBeforeReset?: () => void;
|
onBeforeReset?: () => void;
|
||||||
@@ -93,10 +95,16 @@ export interface UsePageTableReturn<T, Q extends PageQuery> {
|
|||||||
total: Ref<number>;
|
total: Ref<number>;
|
||||||
params: Q;
|
params: Q;
|
||||||
fetchData: () => Promise<void>;
|
fetchData: () => Promise<void>;
|
||||||
/** 回到第一页并查询。 */
|
/**
|
||||||
|
* 回到第一页并查询。
|
||||||
|
*/
|
||||||
handleQuery: () => Promise<void>;
|
handleQuery: () => Promise<void>;
|
||||||
/** 恢复初始条件后重新查询。 */
|
/**
|
||||||
|
* 恢复初始条件后重新查询。
|
||||||
|
*/
|
||||||
handleResetQuery: () => Promise<void>;
|
handleResetQuery: () => Promise<void>;
|
||||||
/** 仅恢复参数,不发请求。 */
|
/**
|
||||||
|
* 仅恢复参数,不发请求。
|
||||||
|
*/
|
||||||
resetParams: () => void;
|
resetParams: () => void;
|
||||||
}
|
}
|
||||||
@@ -721,11 +721,17 @@ const xModalEvent: VxeModalListeners = {
|
|||||||
const crudStore = {
|
const crudStore = {
|
||||||
/** 表单类型,true 表示修改,false 表示新增 */
|
/** 表单类型,true 表示修改,false 表示新增 */
|
||||||
isUpdate: true,
|
isUpdate: true,
|
||||||
/** 加载表格数据 */
|
/**
|
||||||
|
* 加载表格数据
|
||||||
|
*/
|
||||||
commitQuery: () => xGridDom.value?.commitProxy("query"),
|
commitQuery: () => xGridDom.value?.commitProxy("query"),
|
||||||
/** 清空表格数据 */
|
/**
|
||||||
|
* 清空表格数据
|
||||||
|
*/
|
||||||
clearTable: () => xGridDom.value?.reloadData([]),
|
clearTable: () => xGridDom.value?.reloadData([]),
|
||||||
/** 新增后是否跳入最后一页 */
|
/**
|
||||||
|
* 新增后是否跳入最后一页
|
||||||
|
*/
|
||||||
afterInsert: () => {
|
afterInsert: () => {
|
||||||
const pager = xGridDom.value?.getProxyInfo()?.pager;
|
const pager = xGridDom.value?.getProxyInfo()?.pager;
|
||||||
if (pager) {
|
if (pager) {
|
||||||
@@ -735,7 +741,9 @@ const crudStore = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/** 删除后是否返回上一页 */
|
/**
|
||||||
|
* 删除后是否返回上一页
|
||||||
|
*/
|
||||||
afterDelete: () => {
|
afterDelete: () => {
|
||||||
const tableData: RowMeta[] = xGridDom.value!.getData();
|
const tableData: RowMeta[] = xGridDom.value!.getData();
|
||||||
const pager = xGridDom.value?.getProxyInfo()?.pager;
|
const pager = xGridDom.value?.getProxyInfo()?.pager;
|
||||||
@@ -743,7 +751,9 @@ const crudStore = {
|
|||||||
--pager.currentPage;
|
--pager.currentPage;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/** 点击显示弹窗 */
|
/**
|
||||||
|
* 点击显示弹窗
|
||||||
|
*/
|
||||||
onShowModal: (row?: RowMeta) => {
|
onShowModal: (row?: RowMeta) => {
|
||||||
if (row) {
|
if (row) {
|
||||||
crudStore.isUpdate = true;
|
crudStore.isUpdate = true;
|
||||||
@@ -755,7 +765,9 @@ const crudStore = {
|
|||||||
}
|
}
|
||||||
xModalDom.value?.open();
|
xModalDom.value?.open();
|
||||||
},
|
},
|
||||||
/** 确定并保存 */
|
/**
|
||||||
|
* 确定并保存
|
||||||
|
*/
|
||||||
onSubmitForm: () => {
|
onSubmitForm: () => {
|
||||||
if (xModalOpt.loading) return;
|
if (xModalOpt.loading) return;
|
||||||
// 表单校验
|
// 表单校验
|
||||||
@@ -775,7 +787,9 @@ const crudStore = {
|
|||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
/** 删除 */
|
/**
|
||||||
|
* 删除
|
||||||
|
*/
|
||||||
onDelete: (row?: RowMeta) => {
|
onDelete: (row?: RowMeta) => {
|
||||||
let ids = [];
|
let ids = [];
|
||||||
if (row === undefined) {
|
if (row === undefined) {
|
||||||
@@ -808,7 +822,9 @@ const crudStore = {
|
|||||||
onModify: (id: number, field: string, value: any) => {
|
onModify: (id: number, field: string, value: any) => {
|
||||||
console.debug("🚀 ~ onModify", { id, field, value });
|
console.debug("🚀 ~ onModify", { id, field, value });
|
||||||
},
|
},
|
||||||
/** 更多自定义方法 */
|
/**
|
||||||
|
* 更多自定义方法
|
||||||
|
*/
|
||||||
moreFn: () => {},
|
moreFn: () => {},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -954,6 +954,18 @@ $input-h: 44px;
|
|||||||
|
|
||||||
.login-brand {
|
.login-brand {
|
||||||
padding: 24px 24px 28px;
|
padding: 24px 24px 28px;
|
||||||
|
|
||||||
|
/* 版本号移到名称下方,避免与右上角工具栏图标重叠 */
|
||||||
|
&__identity {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__name {
|
||||||
|
font-size: 20px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-card {
|
.login-card {
|
||||||
|
|||||||
@@ -61,9 +61,10 @@
|
|||||||
<el-table-column label="排序" prop="sort" align="center" width="80" />
|
<el-table-column label="排序" prop="sort" align="center" width="80" />
|
||||||
<el-table-column label="状态" align="center" width="100">
|
<el-table-column label="状态" align="center" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tag :type="scope.row.status === CommonStatus.ENABLED ? 'success' : 'info'">
|
<span class="dict-item-panel__status">
|
||||||
|
<StatusDot :active="scope.row.status === CommonStatus.ENABLED" />
|
||||||
{{ scope.row.status === CommonStatus.ENABLED ? "启用" : "禁用" }}
|
{{ scope.row.status === CommonStatus.ENABLED ? "启用" : "禁用" }}
|
||||||
</el-tag>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
@@ -172,6 +173,7 @@ import { FullScreen, QuestionFilled, Refresh } from "@element-plus/icons-vue";
|
|||||||
import DictAPI from "@/api/system/dict";
|
import DictAPI from "@/api/system/dict";
|
||||||
import type { DictItem, DictItemForm, DictItemQuery } from "@/api/system/dict";
|
import type { DictItem, DictItemForm, DictItemQuery } from "@/api/system/dict";
|
||||||
import { usePageTable, useTableSelection } from "@/composables";
|
import { usePageTable, useTableSelection } from "@/composables";
|
||||||
|
import StatusDot from "@/components/StatusDot/index.vue";
|
||||||
import { CommonStatus } from "@/enums";
|
import { CommonStatus } from "@/enums";
|
||||||
import { useDictStoreHook } from "@/stores/dict";
|
import { useDictStoreHook } from "@/stores/dict";
|
||||||
|
|
||||||
@@ -378,4 +380,10 @@ onMounted(() => {
|
|||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: var(--el-text-color-placeholder);
|
color: var(--el-text-color-placeholder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dict-item-panel__status {
|
||||||
|
display: inline-flex;
|
||||||
|
gap: 6px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -29,7 +29,10 @@
|
|||||||
@click="handleTypeClick(row)"
|
@click="handleTypeClick(row)"
|
||||||
>
|
>
|
||||||
<div class="dict-type__info">
|
<div class="dict-type__info">
|
||||||
<span class="dict-type__name" :title="row.name">{{ row.name }}</span>
|
<span class="dict-type__name" :title="row.name">
|
||||||
|
<StatusDot :active="row.status === CommonStatus.ENABLED" />
|
||||||
|
{{ row.name }}
|
||||||
|
</span>
|
||||||
<span class="dict-type__code" :title="row.dictCode">{{ row.dictCode }}</span>
|
<span class="dict-type__code" :title="row.dictCode">{{ row.dictCode }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="dict-type__actions">
|
<div class="dict-type__actions">
|
||||||
@@ -143,6 +146,7 @@ import { ArrowLeft, ArrowRight, Delete, Edit, Plus } from "@element-plus/icons-v
|
|||||||
import DictAPI from "@/api/system/dict";
|
import DictAPI from "@/api/system/dict";
|
||||||
import type { DictTypeForm, DictTypeItem, DictTypeQuery } from "@/api/system/dict";
|
import type { DictTypeForm, DictTypeItem, DictTypeQuery } from "@/api/system/dict";
|
||||||
import { usePageTable } from "@/composables";
|
import { usePageTable } from "@/composables";
|
||||||
|
import StatusDot from "@/components/StatusDot/index.vue";
|
||||||
import { CommonStatus } from "@/enums";
|
import { CommonStatus } from "@/enums";
|
||||||
import DictItemPanel from "./components/DictItemPanel.vue";
|
import DictItemPanel from "./components/DictItemPanel.vue";
|
||||||
|
|
||||||
@@ -376,6 +380,20 @@ onMounted(() => {
|
|||||||
line-height: 1.35;
|
line-height: 1.35;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__dot {
|
||||||
|
display: inline-block;
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
margin-right: 6px;
|
||||||
|
vertical-align: middle;
|
||||||
|
background-color: var(--el-color-success);
|
||||||
|
border-radius: 50%;
|
||||||
|
|
||||||
|
&.is-stopped {
|
||||||
|
background-color: var(--el-text-color-placeholder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&__name {
|
&__name {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
|||||||
@@ -34,10 +34,7 @@
|
|||||||
>
|
>
|
||||||
<div class="role-list__info">
|
<div class="role-list__info">
|
||||||
<span class="role-list__title">
|
<span class="role-list__title">
|
||||||
<span
|
<StatusDot :active="row.status === CommonStatus.ENABLED" />
|
||||||
class="role-list__dot"
|
|
||||||
:class="{ 'is-stopped': row.status !== CommonStatus.ENABLED }"
|
|
||||||
/>
|
|
||||||
<span class="role-list__name" :title="row.name">{{ row.name }}</span>
|
<span class="role-list__name" :title="row.name">{{ row.name }}</span>
|
||||||
</span>
|
</span>
|
||||||
<span class="role-list__meta">
|
<span class="role-list__meta">
|
||||||
@@ -310,6 +307,7 @@ import type { MenuItem } from "@/api/system/menu";
|
|||||||
import DeptAPI from "@/api/system/dept";
|
import DeptAPI from "@/api/system/dept";
|
||||||
import type { OptionItem } from "@/api/common";
|
import type { OptionItem } from "@/api/common";
|
||||||
import { usePageTable } from "@/composables";
|
import { usePageTable } from "@/composables";
|
||||||
|
import StatusDot from "@/components/StatusDot/index.vue";
|
||||||
import { CommonStatus } from "@/enums";
|
import { CommonStatus } from "@/enums";
|
||||||
import { ROLE_ROOT } from "@/constants";
|
import { ROLE_ROOT } from "@/constants";
|
||||||
|
|
||||||
@@ -957,18 +955,6 @@ onMounted(() => {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__dot {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
width: 6px;
|
|
||||||
height: 6px;
|
|
||||||
background-color: var(--el-color-success);
|
|
||||||
border-radius: 50%;
|
|
||||||
|
|
||||||
&.is-stopped {
|
|
||||||
background-color: var(--el-text-color-placeholder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__meta {
|
&__meta {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
|
|||||||
@@ -153,7 +153,7 @@
|
|||||||
<el-table-column label="手机号码" prop="mobile" width="130" />
|
<el-table-column label="手机号码" prop="mobile" width="130" />
|
||||||
<el-table-column label="邮箱" prop="email" min-width="180" show-overflow-tooltip />
|
<el-table-column label="邮箱" prop="email" min-width="180" show-overflow-tooltip />
|
||||||
<el-table-column label="创建时间" prop="createTime" width="160" show-overflow-tooltip />
|
<el-table-column label="创建时间" prop="createTime" width="160" show-overflow-tooltip />
|
||||||
<el-table-column label="操作" fixed="right" width="260">
|
<el-table-column label="操作" fixed="right" width="200">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<TableActions :actions="getUserActions(scope.row as UserItem)" />
|
<TableActions :actions="getUserActions(scope.row as UserItem)" />
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -381,9 +381,13 @@ onBeforeUnmount(() => {
|
|||||||
defineExpose({
|
defineExpose({
|
||||||
/** 供承载页触发的保存动作(与工具栏保存共用一套导出逻辑) */
|
/** 供承载页触发的保存动作(与工具栏保存共用一套导出逻辑) */
|
||||||
save: handleSave,
|
save: handleSave,
|
||||||
/** 画布是否有未保存的修改 */
|
/**
|
||||||
|
* 画布是否有未保存的修改
|
||||||
|
*/
|
||||||
isDirty: () => dirty.value,
|
isDirty: () => dirty.value,
|
||||||
/** 持久化成功后清除脏标记(由承载页调用) */
|
/**
|
||||||
|
* 持久化成功后清除脏标记(由承载页调用)
|
||||||
|
*/
|
||||||
markSaved: () => {
|
markSaved: () => {
|
||||||
dirty.value = false;
|
dirty.value = false;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -195,6 +195,13 @@ function handleAppClick(app: AppCard): void {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
/* 分组按内容高度排列,不占用页面剩余高度 */
|
||||||
|
.page-content :deep(.el-card__body) {
|
||||||
|
grid-template-rows: none;
|
||||||
|
grid-auto-rows: min-content;
|
||||||
|
align-content: start;
|
||||||
|
}
|
||||||
|
|
||||||
.app-section + .app-section {
|
.app-section + .app-section {
|
||||||
padding-top: 24px;
|
padding-top: 24px;
|
||||||
margin-top: 24px;
|
margin-top: 24px;
|
||||||
|
|||||||
Reference in new issue
Block a user