提示:仅能选择全局角色或该用户所属组织类型【{{
@@ -74,12 +38,10 @@
+
+
diff --git a/src/components/user/UserFormContent.vue b/src/components/user/UserFormContent.vue
new file mode 100644
index 0000000..14818c3
--- /dev/null
+++ b/src/components/user/UserFormContent.vue
@@ -0,0 +1,176 @@
+
+
+
+
+
+
+
+ {
+ $emit('update:username', value);
+ }
+ "
+ />
+
+
+
+ {
+ $emit('update:mobile', value);
+ }
+ "
+ />
+
+
+
+ {
+ updateEmail(value);
+ }
+ "
+ />
+
+
+
+ {{ formError.__root__ }}
+
+
+
+
+ {
+ $emit('update:name', value);
+ }
+ "
+ />
+
+
+
+
+
+ 填写有效邮箱后才可启用
+
+
+
+
+
+
+
+
+
diff --git a/src/components/user/UserOperations.ts b/src/components/user/UserOperations.ts
index 3cc4e17..7c5a63a 100644
--- a/src/components/user/UserOperations.ts
+++ b/src/components/user/UserOperations.ts
@@ -2,11 +2,11 @@ import { api } from 'boot/axios';
import { Dialog } from 'quasar';
import ConfirmDialog from 'components/dialog/ConfirmDialog.vue';
-import { Role } from 'pages/role/type';
-import { Organization } from 'pages/type';
-import { User } from 'pages/user/type';
-import { UserOperationsType } from './type';
+import { Organization } from '../organization/type';
+import { Role } from '../role/type';
+
+import { User, UserOperationsType } from './type';
export const UserOperationsMixin: UserOperationsType = {
methods: {
diff --git a/src/components/user/type.ts b/src/components/user/type.ts
index bd1e86c..9cc9a95 100644
--- a/src/components/user/type.ts
+++ b/src/components/user/type.ts
@@ -1,6 +1,52 @@
-import { Role } from 'pages/role/type';
-import { Organization } from 'pages/type';
-import { User } from 'pages/user/type';
+import { Organization, OrgType } from '../organization/type';
+import { Role } from '../role/type';
+
+export interface User {
+ /** 用户 ID */
+ id: string;
+ /** 用户姓名 */
+ name?: string;
+ /** 用户手机号 */
+ mobile?: string;
+ /** 用户邮箱 */
+ email?: string;
+ /** 用户用户名 */
+ username?: string;
+ /** 用户直属组织:企业、部门 */
+ departments?: Organization[];
+ /** 用户关联角色 */
+ roles?: Role[];
+ /** 用户属于的组织类型 */
+ org_type?: OrgType;
+ /** 用户最后登录时间 */
+ last_login_at?: Date;
+ /** 用户创建时间 */
+ created_at?: Date;
+ /** 用户状态:true-禁用;false-正常 */
+ is_deleted?: boolean;
+}
+
+export interface UserPostData {
+ /** 用户姓名 */
+ name?: string;
+ /** 用户手机号 */
+ mobile?: string;
+ /** 用户邮箱 */
+ email?: string;
+ /** 用户用户名 */
+ username?: string;
+ /** 用户直属部门 */
+ organization_ids?: string[];
+}
+
+export interface UserPostError {
+ name?: string;
+ mobile?: string;
+ email?: string;
+ username?: string;
+ organization_ids?: string;
+ __root__?: string;
+}
export interface UserOperationsType {
methods: {
diff --git a/src/css/app.scss b/src/css/app.scss
index c86c157..2fc10f9 100644
--- a/src/css/app.scss
+++ b/src/css/app.scss
@@ -23,21 +23,6 @@
}
/** the style for tree structure */
-.tree-item {
- .more-icon {
- visibility: hidden;
- right: 2px;
- top: 2px;
- background-color: rgba(255, 255, 255, 0.07);
- }
-
- &:hover {
- .more-icon {
- visibility: visible;
- }
- }
-}
-
.q-tree__node--selected {
background-color: $primary;
@@ -117,16 +102,6 @@
box-shadow: 0 0 5px 2px rgba(0, 0, 0, 0.2), 0 0px 5px rgba(0, 0, 0, 0.24) !important;
}
-.chip-status-on {
- background-color: $blue-1;
- color: $blue-14;
-}
-
-.chip-status-off {
- background-color: $red-1;
- color: $red-8;
-}
-
.q-chip--clickable:focus {
box-shadow: none !important;
}
@@ -169,14 +144,4 @@
box-shadow: 0 0 5px 2px rgba(255, 255, 255, 0.2),
0 0px 5px rgba(255, 255, 255, 0.24) !important;
}
-
- .chip-status-on {
- background-color: rgb(54, 72, 113);
- color: $blue-1;
- }
-
- .chip-status-off {
- background-color: #6f3a3a;
- color: $red-1;
- }
}
diff --git a/src/layouts/MainLayout.vue b/src/layouts/MainLayout.vue
index 67b49c1..2f91cf9 100644
--- a/src/layouts/MainLayout.vue
+++ b/src/layouts/MainLayout.vue
@@ -119,7 +119,7 @@
import { defineComponent, ref } from 'vue';
import { mapActions, mapState } from 'pinia';
-import { MainMenuSection } from 'components/type';
+import { MainMenuSection } from 'components/common/type';
import { authStore } from 'stores/auth-store';
const menuLinkList: MainMenuSection[] = [
diff --git a/src/layouts/PageWrapper.vue b/src/layouts/PageWrapper.vue
new file mode 100644
index 0000000..91565d5
--- /dev/null
+++ b/src/layouts/PageWrapper.vue
@@ -0,0 +1,51 @@
+
+
+
+ 返回
+
+
+ {{ pageTitle }}
+
+
+
+
+
+
+
+
diff --git a/src/layouts/ProfilePage.vue b/src/layouts/ProfilePage.vue
index 15cca2d..c9dc526 100644
--- a/src/layouts/ProfilePage.vue
+++ b/src/layouts/ProfilePage.vue
@@ -1,18 +1,9 @@
-
-
- 返回
-
+
-
- {{ name }}
+
+ {{ name }}
@@ -37,11 +28,11 @@
-
+
-
+
diff --git a/src/layouts/type.ts b/src/layouts/type.ts
index eb00204..653847a 100644
--- a/src/layouts/type.ts
+++ b/src/layouts/type.ts
@@ -2,7 +2,3 @@ export interface ProfileTab {
name: string;
label: string;
}
-
-export interface ProfileComponent {
- goBack: () => void;
-}
diff --git a/src/pages/AppAdminPanel.vue b/src/pages/AppAdminPanel.vue
index 62f2dd9..c1b0d2a 100644
--- a/src/pages/AppAdminPanel.vue
+++ b/src/pages/AppAdminPanel.vue
@@ -1,18 +1,10 @@
-
-
- 应用管理
-
+
-
@@ -72,49 +60,54 @@
-
-
-
-
-
-
-
-
-
-
-
+
+
+
diff --git a/src/pages/CommonSettings.vue b/src/pages/CommonSettings.vue
index 635436e..eb91a49 100644
--- a/src/pages/CommonSettings.vue
+++ b/src/pages/CommonSettings.vue
@@ -1,7 +1,7 @@
-
+
你好,小熊
-
+
diff --git a/src/pages/permission/PermProfile.vue b/src/pages/permission/PermProfile.vue
index 1174754..a0515df 100644
--- a/src/pages/permission/PermProfile.vue
+++ b/src/pages/permission/PermProfile.vue
@@ -40,91 +40,12 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
- {{ props.row.org_type ? props.row.org_type.name : '全局' }}
-
+
-
@@ -254,28 +172,15 @@
-
- {{ dept.name }}
-
+
-
@@ -294,75 +199,12 @@
-
-
+
-
-
-
- 找不到任何匹配项
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ scope.opt.name }}({{ scope.opt.name }})
-
-
- {{ scope.opt.mobile }} {{ scope.opt.email }}
-
-
-
-
-
-
-
-
+ option-api-url="/roles/query"
+ />
import { defineComponent, ref } from 'vue';
-import { date, QSelect, QTableProps } from 'quasar';
+import { date, QTableProps } from 'quasar';
import { FormDialogComponent } from 'components/dialog/type';
+import { FormAction } from 'components/form/type';
import { PermOperationsMixin } from 'components/permission/PermOperations';
-import { DataTableComponent } from 'components/table/type';
-import { ProfileComponent } from 'layouts/type';
-
-import { Role } from '../role/type';
-// eslint-disable-next-line @typescript-eslint/no-unused-vars
-import { Department, Tag } from '../type';
-
import {
BindRolesToPermsPostData,
BindRolesToPermsPostError,
Permission,
- PermissionPostData,
- PermissionPostError,
-} from './type';
+} from 'components/permission/type';
+import { Role } from 'components/role/type';
+import { DataTableComponent } from 'components/table/type';
const roleColumns: QTableProps['columns'] = [
{
@@ -497,44 +333,25 @@ export default defineComponent({
id: '',
}),
panelTab: ref('perm'),
-
- permissionFormData: ref
({}),
- permissionFormError: ref({}),
-
roleColumns: roleColumns,
userColumns: userColumns,
+ FormAction,
bindRolesForm: ref(false),
- roleOptions: ref([]),
selectedRoles: ref([]),
bindRolesFormData: ref({}),
bindRolesFormError: ref({}),
-
- initialTagOptions: ref([]),
- tagOptions: ref([]),
- selectedTags: ref([]),
};
},
mounted() {
this.loadPermInfo();
- this.loadTagOptions();
},
methods: {
async loadPermInfo() {
const resp = await this.$api.get(`/permissions/${this.permId}`);
this.permission = resp.data;
- this.permissionFormData = Object.assign({}, resp.data);
- this.selectedTags = this.permission.tags
- ? this.permission.tags.map((p) => p.id)
- : [];
- },
-
- async loadTagOptions() {
- const resp = await this.$api.get('/permission_tags');
- this.initialTagOptions = resp.data.permission_tags;
- this.tagOptions = resp.data.permission_tags;
},
switchPanelTab(val: string) {
@@ -550,39 +367,6 @@ export default defineComponent({
et.setApiInfo(`/permissions/${this.permission.id}/users`, 'POST');
et.fetchRows();
}, 20);
- } else if (val === 'perm') {
- this.loadTagOptions();
- }
- },
-
- async savePermissionForm() {
- this.permissionFormData.existing_tag_ids = this.selectedTags.filter(
- (tag) => this.initialTagOptions.map((t) => t.id).includes(tag)
- );
- this.permissionFormData.new_tags = this.selectedTags.filter(
- (tag) => !this.initialTagOptions.map((t) => t.id).includes(tag)
- );
- if (
- JSON.stringify(this.permission) ===
- JSON.stringify(this.permissionFormData)
- )
- return;
- try {
- this.permissionFormError = {};
- this.permissionFormData.application_id =
- this.permission.application?.id;
- const resp = await this.$api.put(
- `/permissions/${this.permission.id}`,
- this.permissionFormData,
- {
- successMsg: '权限更新成功',
- }
- );
- this.permission = resp.data;
- this.permissionFormData = Object.assign({}, resp.data);
- this.permissionFormError = {};
- } catch (e) {
- this.permissionFormError = (e as Error).cause || {};
}
},
@@ -590,35 +374,13 @@ export default defineComponent({
if (['disable', 'enable'].includes(op)) {
this.loadPermInfo();
} else if (op === 'delete') {
- (this.$refs.profile as ProfileComponent).goBack();
+ this.$router.back();
} else if (op === 'unbind') {
this.loadPermInfo();
(this.$refs.rolesTable as DataTableComponent).fetchRows();
}
},
- searchRole(
- val: string,
- update: (fn: () => void) => void,
- abort: () => void
- ) {
- const kw = val.trim();
- if (kw === '') {
- abort();
- return;
- }
- update(async () => {
- let resp = await this.$api.post('/roles/query', {
- q: kw,
- });
- this.roleOptions = resp.data.rows;
- });
- },
-
- clearFilter() {
- (this.$refs.select as QSelect).updateInputValue('');
- },
-
async saveBindRolesForm() {
this.bindRolesFormData.role_ids = this.selectedRoles
? this.selectedRoles.map((role) => role.id)
@@ -647,30 +409,6 @@ export default defineComponent({
this.bindRolesFormError = {};
this.selectedRoles = [];
},
-
- createValue(
- val: string,
- done: (item?: string, mode?: 'add' | 'add-unique' | 'toggle') => void
- ) {
- if (val.length > 0) {
- if (!this.initialTagOptions.map((tag) => tag.name).includes(val)) {
- done(val, 'add-unique');
- }
- }
- },
-
- filterFn(val: string, update: (fn: () => void) => void) {
- update(() => {
- if (val === '') {
- this.tagOptions = this.initialTagOptions;
- } else {
- const needle = val.toLowerCase();
- this.tagOptions = this.initialTagOptions.filter(
- (v) => v.name.toLowerCase().indexOf(needle) > -1
- );
- }
- });
- },
},
});
diff --git a/src/pages/permission/type.ts b/src/pages/permission/type.ts
deleted file mode 100644
index 735c240..0000000
--- a/src/pages/permission/type.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-import { Role } from '../role/type';
-import { Application, Tag } from '../type';
-
-export interface Permission {
- /** 权限 ID */
- id: string;
- /** 权限名称 */
- name?: string;
- /** 权限 Code */
- code?: string;
- /** 权限描述 */
- description?: string;
- /** 权限关联的角色 */
- roles?: Role[];
- /** 权限所属应用 */
- application?: Application;
- /** 权限关联标签列表 */
- tags?: Tag[];
- /** 权限创建时间 */
- created_at?: Date;
- /** 权限状态:true-禁用;false-正常 */
- is_deleted?: boolean;
-}
-
-export interface PermissionPostData {
- /** 权限名称 */
- name?: string;
- /** 权限 Code */
- code?: string;
- /** 权限描述 */
- description?: string;
- /** 所属应用 ID */
- application_id?: string;
- /** 已有标签 ID 列表 */
- existing_tag_ids?: string[];
- /** 新建标签名称列表 */
- new_tags?: string[];
-}
-
-export interface PermissionPostError {
- name?: string;
- code?: string;
- application_id?: string;
-}
-
-export interface BindRolesToPermsPostData {
- /** 权限的 ID 列表 */
- permission_ids?: string[];
- /** 角色的 ID 列表 */
- role_ids?: string[];
-}
-
-export interface BindRolesToPermsPostError {
- permission_ids?: string;
- role_ids?: string;
-}
diff --git a/src/pages/role/RoleAdminPanel.vue b/src/pages/role/RoleAdminPanel.vue
index cef63a3..f71f760 100644
--- a/src/pages/role/RoleAdminPanel.vue
+++ b/src/pages/role/RoleAdminPanel.vue
@@ -1,15 +1,7 @@
-
+
-
-
- 角色管理
-
+
-
- {{ props.row.org_type ? props.row.org_type.name : '全局' }}
-
+
-
@@ -124,17 +113,13 @@
-
+
@@ -154,7 +139,7 @@
-
+
可用角色
@@ -173,16 +158,12 @@
{{ role.name }}
-
@@ -215,7 +196,7 @@
-
-
标签:
-
-
+ 标签:
+
+
- local_offer
- {{ item.name }}
-
+ selection="multiple"
+ @selected-change="filterByTags"
+ />
@@ -252,41 +151,20 @@
-
-
- local_offer
-
- {{ tag.name }}
-
+
-
+
-
@@ -305,75 +183,16 @@
-
-
+
-
-
-
- 找不到任何匹配项
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ scope.opt.name }}({{ scope.opt.username }})
-
-
- {{ scope.opt.mobile }} {{ scope.opt.email }}
-
-
-
-
-
-
-
-
+ placeholder="输入用户信息进行搜索"
+ option-api-url="/users/query"
+ :option-api-params="{
+ org_type_id: role.org_type?.id,
+ include_unassigned_users: !!role.org_type ? false : true,
+ }"
+ />
import { defineComponent, ref } from 'vue';
-import { QSelect, QTableProps, VueStyleObjectProp } from 'quasar';
+import { QTableProps, VueStyleObjectProp } from 'quasar';
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+import { ChipGroupItem } from 'src/components/common/type';
+import { Application } from 'components/application/type';
import { FormDialogComponent } from 'components/dialog/type';
+import { FormAction } from 'components/form/type';
import { RoleOperationsMixin } from 'components/role/RoleOperations';
-import { DataTableComponent } from 'components/table/type';
-import { ProfileComponent } from 'layouts/type';
import {
BindUsersToRolesPostData,
BindUsersToRolesPostError,
Role,
- RolePostData,
- RolePostError,
-} from 'pages/role/type';
-import { User } from 'pages/user/type';
-
-// eslint-disable-next-line @typescript-eslint/no-unused-vars
-import { Application, Department, Tag } from '../type';
+} from 'components/role/type';
+import { DataTableComponent } from 'components/table/type';
+import { Tag } from 'components/tag/type';
+import { User } from 'components/user/type';
const userColumns: QTableProps['columns'] = [
{
@@ -524,13 +342,9 @@ export default defineComponent({
panelTab: ref('role'),
userColumns: userColumns,
permColumns: permColumns,
-
- roleTypeTab: ref('global'),
- roleFormData: ref
({}),
- roleFormError: ref({}),
+ FormAction,
bindUsersForm: ref(false),
- userOptions: ref([]),
selectedUsers: ref([]),
bindUsersFormData: ref({}),
bindUsersFormError: ref({}),
@@ -560,8 +374,6 @@ export default defineComponent({
async loadRoleInfo() {
const resp = await this.$api.get(`/roles/${this.roleId}`);
this.role = resp.data;
- this.roleFormData = Object.assign({}, resp.data);
- this.roleTypeTab = !!this.role.org_type ? 'org_type' : 'global';
},
switchPanelTab(val: string) {
@@ -584,35 +396,10 @@ export default defineComponent({
},
async loadTagOptions() {
- this.selectedTags = [];
const resp = await this.$api.get('/permission_tags');
this.tagChips = resp.data.permission_tags;
},
- searchUser(
- val: string,
- update: (fn: () => void) => void,
- abort: () => void
- ) {
- const kw = val.trim();
- if (kw === '') {
- abort();
- return;
- }
- update(async () => {
- let resp = await this.$api.post('/users/query', {
- q: kw,
- org_type_id: this.role.org_type?.id,
- include_unassigned_users: !!this.role.org_type ? false : true,
- });
- this.userOptions = resp.data.rows;
- });
- },
-
- clearFilter() {
- (this.$refs.select as QSelect).updateInputValue('');
- },
-
async saveBindUsersForm() {
this.bindUsersFormData.user_ids = this.selectedUsers
? this.selectedUsers.map((user) => user.id)
@@ -638,31 +425,11 @@ export default defineComponent({
this.selectedUsers = [];
},
- async saveRoleForm() {
- if (JSON.stringify(this.role) === JSON.stringify(this.roleFormData))
- return;
- try {
- this.roleFormError = {};
- const resp = await this.$api.put(
- `/roles/${this.role.id}`,
- this.roleFormData,
- {
- successMsg: '角色更新成功',
- }
- );
- this.role = resp.data;
- this.roleFormData = Object.assign({}, resp.data);
- this.roleFormError = {};
- } catch (e) {
- this.roleFormError = (e as Error).cause || {};
- }
- },
-
refreshRoleData(op: string) {
if (['disable', 'enable'].includes(op)) {
this.loadRoleInfo();
} else if (op === 'delete') {
- (this.$refs.profile as ProfileComponent).goBack();
+ this.$router.back();
} else if (op === 'unbind') {
this.loadRoleInfo();
(this.$refs.userTable as DataTableComponent).fetchRows();
@@ -673,18 +440,15 @@ export default defineComponent({
console.error('TODO');
},
- clickApplicationChip(app: Application) {
+ filterByApp(selected: string[]) {
+ console.error(selected);
this.selectedApplication =
- this.selectedApplication.id === app.id ? { id: '' } : app;
+ selected.length === 0 ? { id: '' } : { id: selected[0] };
this.loadPermissionsbyApp();
},
- clickTagChip(tag: Tag) {
- if (this.selectedTags.includes(tag.id)) {
- this.selectedTags = this.selectedTags.filter((tid) => tid != tag.id);
- } else {
- this.selectedTags.push(tag.id);
- }
+ filterByTags() {
+ console.error('TODO');
},
async loadPermissionsbyApp() {
diff --git a/src/pages/role/type.ts b/src/pages/role/type.ts
deleted file mode 100644
index 689159d..0000000
--- a/src/pages/role/type.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-import { Organization } from '../type';
-
-export interface Role {
- /** 角色 ID */
- id: string;
- /** 角色名称 */
- name?: string;
- /** 角色 Code */
- code?: string;
- /** 角色描述 */
- description?: string;
- /** 所属组织类型 */
- org_type?: Organization;
- /** 角色创建时间 */
- created_at?: Date;
- /** 角色状态:true-禁用;false-正常 */
- is_deleted?: boolean;
-}
-
-export interface RoleSet {
- label: string;
- roles: Role[];
-}
-
-export interface RolePostData {
- /** 角色名称 */
- name?: string;
- /** 角色 Code */
- code?: string;
- /** 角色描述 */
- description?: string;
- /** 所属组织类型 ID */
- org_type_id?: string;
-}
-
-export interface RolePostError {
- name?: string;
- code?: string;
- org_type_id?: string;
-}
-
-export interface BindUsersToRolesPostData {
- /** 用户的 ID 列表 */
- user_ids?: string[];
- /** 角色的 ID 列表 */
- role_ids?: string[];
-}
-
-export interface BindUsersToRolesPostError {
- user_ids?: string;
- role_ids?: string;
-}
diff --git a/src/pages/user/UserAdminPanel.vue b/src/pages/user/UserAdminPanel.vue
index bd45833..da8c07f 100644
--- a/src/pages/user/UserAdminPanel.vue
+++ b/src/pages/user/UserAdminPanel.vue
@@ -1,22 +1,14 @@
-
-
- 用户管理
-
+
toggleUsersStatus(selected, true, refreshUserData)
@@ -32,7 +24,7 @@
dense
label="创建用户"
class="q-ml-sm q-px-md primary-btn"
- @click="newUserForm = true"
+ @click="openUserForm"
/>
@@ -46,19 +38,15 @@
-
-
+
-
-
-
-
-
-
-
-
-
-
-
- {{ newUserFormError.__root__ }}
-
-
-
-
-
-
-
-
-
-
- 填写有效邮箱后才可启用
-
-
-
-
-
-
-
+
+