ow
This commit is contained in:
1 parent
a8896cbfb2
commit
282d8ce583
20 files changed
+1256
-524
No files matched your search
@@ -2,20 +2,16 @@
|
||||
/**
|
||||
* 角色查询(ActorEnquiry):旧 WebVue views/security/ActorEnquiry.vue 的移动端等价物
|
||||
*
|
||||
* 它有两种打开方式,同一套列表:
|
||||
* 1. 从菜单进(无 channel):普通查询页(点行看详情,右上可新增、长按多选可批量删除);
|
||||
* 2. 被 user-operation 当"角色选择器"跳进来(带 ?channel=&multiple=1):
|
||||
* 选完 uni.$emit 回传再 navigateBack(见 useAdminPick / useAdminPickTarget 协议)。
|
||||
*
|
||||
* 旧系统里这个选择能力是 Operation 用 <dragModal> 内嵌 Enquiry + provide/inject 实现的;
|
||||
* 移动端页面之间没有 provide/inject,只能真跳一页再回传,所以这个页面本身就是 Enquiry。
|
||||
* 普通查询页:点行看详情,右上可新增、多选可批量删除。
|
||||
* 旧系统里 user-operation 用 <dragModal> 内嵌本页做"角色选择器";
|
||||
* 移动端的弹窗选择已由 user-operation 内嵌 <admin-pick-popup> 实现,
|
||||
* 本页不再承担选择器职责(useAdminPick / useAdminPickTarget 协议已移除)。
|
||||
*/
|
||||
import type { AdminColumn, AdminQuery, AdminRow } from "@/admin/admin-types";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { useLocale } from "uview-pro";
|
||||
import { computed, nextTick, reactive, ref } from "vue";
|
||||
import { fillCriteria, makeFilterOption } from "@/admin/admin-filter";
|
||||
import { useAdminList, useAdminPickTarget, useAuthGuard } from "@/composables";
|
||||
import { useAdminList, useAuthGuard } from "@/composables";
|
||||
import { SecurityActorEntity } from "@/data/auto/securityActorEntity";
|
||||
import { SecurityActorSearchCriteria } from "@/data/auto/securityActorSearchCriteria";
|
||||
import { SearchFilterOperatorPolicy } from "@/data/custom/searchFilterOperatorPolicy";
|
||||
@@ -25,12 +21,8 @@ import { pageUrl } from "@/router/routes";
|
||||
import securityActorService from "@/service/security/securityActorService";
|
||||
|
||||
const { t } = useLocale();
|
||||
const pickTarget = useAdminPickTarget();
|
||||
const perm = usePagePermission("actorEnquiry");
|
||||
|
||||
/** 选择器模式:带 channel 进来时点行回传;否则作为普通菜单页点行进详情 */
|
||||
const isPick = ref(false);
|
||||
|
||||
const bindOptions = reactive([
|
||||
makeFilterOption(
|
||||
SecurityActorEntity.DB_ACTOR_LOCAL_NAME,
|
||||
@@ -73,28 +65,12 @@ function onSearch(): void {
|
||||
}
|
||||
|
||||
function onRowTap(row: AdminRow): void {
|
||||
// 选择器模式:多选态交给勾选,单选态点一行即选中回传
|
||||
if (isPick.value) {
|
||||
if (pickTarget.multiple.value) {
|
||||
return;
|
||||
}
|
||||
pickTarget.deliverOne(row);
|
||||
return;
|
||||
}
|
||||
// 菜单模式:进角色详情(旧页面双击行开编辑弹窗,移动端改点行进详情页)
|
||||
// 进角色详情(旧页面双击行开编辑弹窗,移动端改点行进详情页)
|
||||
uni.navigateTo({
|
||||
url: `${pageUrl("actorOperation")}?id=${row.ActorName}&mode=view`,
|
||||
});
|
||||
}
|
||||
|
||||
function onConfirm(rows: AdminRow[]): void {
|
||||
if (!rows.length) {
|
||||
uni.showToast({ title: t("AdminPage.pickNoneTip"), icon: "none" });
|
||||
return;
|
||||
}
|
||||
pickTarget.deliver(rows);
|
||||
}
|
||||
|
||||
function onCreate(): void {
|
||||
uni.navigateTo({ url: `${pageUrl("actorOperation")}?mode=create` });
|
||||
}
|
||||
@@ -121,11 +97,6 @@ async function onDelete(rows: AdminRow[]): Promise<void> {
|
||||
});
|
||||
}
|
||||
|
||||
onLoad((options) => {
|
||||
pickTarget.readOptions(options);
|
||||
isPick.value = String(options?.channel ?? "").trim().length > 0;
|
||||
});
|
||||
|
||||
useAuthGuard(() => {
|
||||
// 每次显示都重拉第一页:增/改/删后从详情返回能看到最新数据(navigateBack 不重新挂页面)
|
||||
nextTick(() => listRef.value?.refresh());
|
||||
@@ -135,23 +106,20 @@ useAuthGuard(() => {
|
||||
<template>
|
||||
<view class="page">
|
||||
<admin-list ref="listRef" v-model:keyword="keyword" :nav-title="t('UserPage.actorEnquiryTitle')"
|
||||
:show-nav-back="!isPick" :columns="columns" :loader="state.query" :row-key="SecurityActorEntity.ACTOR_NAME"
|
||||
title-key="ActorLocalName" :selectable="isPick ? pickTarget.multiple.value : Boolean(perm.canDelete.value)"
|
||||
:filter-count="filterCount" :filter-visible="filterVisible" :filter-items="draft" :search-token="searchToken"
|
||||
:keep-selection-on-reload="isPick" @search="onSearch" @open-filter="state.openFilter()"
|
||||
@close-filter="state.closeFilter()" @apply-filter="state.applyFilter($event)"
|
||||
:show-nav-back="true" :columns="columns" :loader="state.query" :row-key="SecurityActorEntity.ACTOR_NAME"
|
||||
title-key="ActorLocalName" :selectable="Boolean(perm.canDelete.value)" :filter-count="filterCount"
|
||||
:filter-visible="filterVisible" :filter-items="draft" :search-token="searchToken" @search="onSearch"
|
||||
@open-filter="state.openFilter()" @close-filter="state.closeFilter()" @apply-filter="state.applyFilter($event)"
|
||||
@clear-filter="state.clearFiltersAndSearch()" @row-tap="onRowTap">
|
||||
<template v-if="!isPick && perm.canCreate.value" #toolbar-actions>
|
||||
<template v-if="perm.canCreate.value" #toolbar-actions>
|
||||
<view class="create-entry" @click="onCreate">
|
||||
<u-icon name="plus" size="40" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<template #actions="{ rows }">
|
||||
<u-button v-if="isPick" type="primary" shape="circle" size="mini" :text="t('AdminPage.pickDoneBut')"
|
||||
@click="onConfirm(rows)" />
|
||||
<u-button v-else-if="perm.canDelete.value" type="error" shape="circle" size="mini"
|
||||
:text="t('AdminPage.deleteBut')" @click="onDelete(rows)" />
|
||||
<u-button v-if="perm.canDelete.value" type="error" shape="circle" size="mini" :text="t('AdminPage.deleteBut')"
|
||||
@click="onDelete(rows)" />
|
||||
</template>
|
||||
</admin-list>
|
||||
</view>
|
||||
|
||||
@@ -6,17 +6,19 @@
|
||||
* - onLoad 读 id(=ActorName)与 mode(view|create|amend);
|
||||
* - FindByKey 取 SecurityActorData,取不到提示"记录不存在";
|
||||
* - 保存按 CreatedBy 有无决定 Update / Insert,成功后回填主键、退回只读;
|
||||
* - 两个子表:组别明细(SecurityActorGroups,选 group-enquiry 多选)、
|
||||
* 用户明细(SecurityUserActors,选 user-enquiry 多选),均按主键去重合并、删除即剔除。
|
||||
* - 两个子表:组别明细(SecurityActorGroups,弹窗多选组别)、
|
||||
* 用户明细(SecurityUserActors,弹窗多选用户),均按主键去重合并、删除即剔除。
|
||||
*
|
||||
* 旧页面用 dragModal 内嵌 Enquiry + provide/inject 做选择;移动端改成真跳选择页再回传
|
||||
* (见 composables/useAdminPick),所以两个子表放在 admin-form 的 #extra 插槽里自绘。
|
||||
* 旧页面用 dragModal 内嵌 Enquiry + provide/inject 做选择;移动端用
|
||||
* <admin-pick-popup> 底部弹窗(数据源见 composables/usePickerConfigs),
|
||||
* 两个子表放在 admin-form 的 #extra 插槽里自绘。
|
||||
*/
|
||||
import type { AdminFormAction, AdminFormField, AdminFormSection } from "@/admin/admin-types";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { useLocale } from "uview-pro";
|
||||
import { computed, ref } from "vue";
|
||||
import { useAdminPick, useAuthGuard } from "@/composables";
|
||||
import { useAuthGuard } from "@/composables";
|
||||
import { useGroupPickConfig, useUserPickConfig } from "@/composables/usePickerConfigs";
|
||||
import { SecurityActorData } from "@/data/auto/securityActorData";
|
||||
import { SecurityActorGroupViewEntity } from "@/data/auto/securityActorGroupViewEntity";
|
||||
import { SecurityUserActorViewEntity } from "@/data/auto/securityUserActorViewEntity";
|
||||
@@ -167,25 +169,29 @@ function onBack(): void {
|
||||
smartBack("mineTab");
|
||||
}
|
||||
|
||||
// 组别选择:跳 group-enquiry(多选),回传后按 GroupName 去重合并
|
||||
const groupPicker = useAdminPick<SecurityActorGroupViewEntity>("group");
|
||||
// 组别选择弹窗
|
||||
const groupConfig = useGroupPickConfig();
|
||||
const showGroupPicker = ref(false);
|
||||
|
||||
function onAddGroup(): void {
|
||||
groupPicker.open({ page: "groupEnquiry", params: { multiple: "1" } }, (rows) => {
|
||||
const exists = new Set(data.value.SecurityActorGroups.map(item => item.GroupName));
|
||||
for (const row of rows) {
|
||||
const groupName = String(row.GroupName ?? "");
|
||||
if (!groupName || exists.has(groupName)) {
|
||||
continue;
|
||||
}
|
||||
const entity = new SecurityActorGroupViewEntity();
|
||||
entity.ActorName = String(actor.value.ActorName ?? "");
|
||||
entity.GroupName = groupName;
|
||||
entity.GroupLocalName = String(row.GroupLocalName ?? "");
|
||||
data.value.SecurityActorGroups.push(entity);
|
||||
exists.add(groupName);
|
||||
showGroupPicker.value = true;
|
||||
}
|
||||
|
||||
function onGroupPicked(rows: any[]): void {
|
||||
const exists = new Set(data.value.SecurityActorGroups.map(item => item.GroupName));
|
||||
for (const row of rows) {
|
||||
const groupName = String(row.GroupName ?? "");
|
||||
if (!groupName || exists.has(groupName)) {
|
||||
continue;
|
||||
}
|
||||
});
|
||||
const entity = new SecurityActorGroupViewEntity();
|
||||
entity.ActorName = String(actor.value.ActorName ?? "");
|
||||
entity.GroupName = groupName;
|
||||
entity.GroupLocalName = String(row.GroupLocalName ?? "");
|
||||
data.value.SecurityActorGroups.push(entity);
|
||||
exists.add(groupName);
|
||||
}
|
||||
showGroupPicker.value = false;
|
||||
}
|
||||
|
||||
function onDeleteGroup(groupName: string): void {
|
||||
@@ -194,25 +200,29 @@ function onDeleteGroup(groupName: string): void {
|
||||
);
|
||||
}
|
||||
|
||||
// 用户选择:跳 user-enquiry(多选),回传后按 UserName 去重合并
|
||||
const userPicker = useAdminPick<SecurityUserActorViewEntity>("user");
|
||||
// 用户选择弹窗
|
||||
const userConfig = useUserPickConfig();
|
||||
const showUserPicker = ref(false);
|
||||
|
||||
function onAddUser(): void {
|
||||
userPicker.open({ page: "userEnquiry", params: { multiple: "1" } }, (rows) => {
|
||||
const exists = new Set(data.value.SecurityUserActors.map(item => item.UserName));
|
||||
for (const row of rows) {
|
||||
const userName = String(row.UserName ?? "");
|
||||
if (!userName || exists.has(userName)) {
|
||||
continue;
|
||||
}
|
||||
const entity = new SecurityUserActorViewEntity();
|
||||
entity.UserName = userName;
|
||||
entity.UserLocalName = String(row.UserLocalName ?? "");
|
||||
entity.ActorName = String(actor.value.ActorName ?? "");
|
||||
data.value.SecurityUserActors.push(entity);
|
||||
exists.add(userName);
|
||||
showUserPicker.value = true;
|
||||
}
|
||||
|
||||
function onUserPicked(rows: any[]): void {
|
||||
const exists = new Set(data.value.SecurityUserActors.map(item => item.UserName));
|
||||
for (const row of rows) {
|
||||
const userName = String(row.UserName ?? "");
|
||||
if (!userName || exists.has(userName)) {
|
||||
continue;
|
||||
}
|
||||
});
|
||||
const entity = new SecurityUserActorViewEntity();
|
||||
entity.UserName = userName;
|
||||
entity.UserLocalName = String(row.UserLocalName ?? "");
|
||||
entity.ActorName = String(actor.value.ActorName ?? "");
|
||||
data.value.SecurityUserActors.push(entity);
|
||||
exists.add(userName);
|
||||
}
|
||||
showUserPicker.value = false;
|
||||
}
|
||||
|
||||
function onDeleteUser(userName: string): void {
|
||||
@@ -317,6 +327,16 @@ useAuthGuard(() => {
|
||||
</view>
|
||||
</template>
|
||||
</admin-form>
|
||||
|
||||
<!-- 弹窗选择器 -->
|
||||
<admin-pick-popup v-model:visible="showGroupPicker" :title="t('GroupPage.title')"
|
||||
:columns="groupConfig.columns.value" :loader="groupConfig.loader" :row-key="groupConfig.rowKey"
|
||||
:title-key="groupConfig.titleKey" :multiple="true" :fixed-filters="groupConfig.fixedFilters.value"
|
||||
@confirm="onGroupPicked" @close="showGroupPicker = false" />
|
||||
|
||||
<admin-pick-popup v-model:visible="showUserPicker" :title="t('UserPage.title')" :columns="userConfig.columns.value"
|
||||
:loader="userConfig.loader" :row-key="userConfig.rowKey" :title-key="userConfig.titleKey" :multiple="true"
|
||||
:fixed-filters="userConfig.fixedFilters.value" @confirm="onUserPicked" @close="showUserPicker = false" />
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -7,16 +7,15 @@
|
||||
* data.SecurityFunctionDisplayDatas(不是普通的 data.Datas!),这里逐字照抄;
|
||||
* - 中文名称筛选用 CN_CONTAIN(旧页面即如此),功能名称用 CONTAIN;
|
||||
* - 菜单? 是 SINGLE_SELECTION + yesNo 候选,列显示 Y->是 / N->否。
|
||||
* 行点击进详情(无 channel)/ 作为选择器回传(带 channel)。
|
||||
* 行点击进详情。function-operation 的"选权限/上级/下级"弹窗已由调用方内嵌
|
||||
* <admin-pick-popup> 实现,本页不再承担选择器职责(useAdminPick 协议已移除)。
|
||||
*/
|
||||
import type { AdminColumn, AdminQuery, AdminRow } from "@/admin/admin-types";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { useLocale } from "uview-pro";
|
||||
import { computed, nextTick, reactive, ref, watch } from "vue";
|
||||
import { fillCriteria, makeFilterOption } from "@/admin/admin-filter";
|
||||
import {
|
||||
useAdminList,
|
||||
useAdminPickTarget,
|
||||
useAuthGuard,
|
||||
} from "@/composables";
|
||||
import { SecurityFunctionDisplayData } from "@/data/auto/securityFunctionDisplayData";
|
||||
@@ -29,9 +28,6 @@ import securityFunctionService from "@/service/security/securityFunctionService"
|
||||
|
||||
const { t, currentLocale } = useLocale();
|
||||
const perm = usePagePermission("functionEnquiry");
|
||||
const pickTarget = useAdminPickTarget();
|
||||
|
||||
const isPick = ref(false);
|
||||
|
||||
function yesNo() {
|
||||
return [
|
||||
@@ -116,13 +112,6 @@ function onSearch(): void {
|
||||
}
|
||||
|
||||
function onRowTap(row: AdminRow): void {
|
||||
if (isPick.value) {
|
||||
if (pickTarget.multiple.value) {
|
||||
return;
|
||||
}
|
||||
pickTarget.deliverOne(row);
|
||||
return;
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: `${pageUrl("functionOperation")}?id=${row.FunctionName}&mode=view`,
|
||||
});
|
||||
@@ -132,14 +121,6 @@ function onCreate(): void {
|
||||
uni.navigateTo({ url: `${pageUrl("functionOperation")}?mode=create` });
|
||||
}
|
||||
|
||||
function onConfirm(rows: AdminRow[]): void {
|
||||
if (!rows.length) {
|
||||
uni.showToast({ title: t("AdminPage.pickNoneTip"), icon: "none" });
|
||||
return;
|
||||
}
|
||||
pickTarget.deliver(rows);
|
||||
}
|
||||
|
||||
async function onDelete(rows: AdminRow[]): Promise<void> {
|
||||
if (!rows.length) {
|
||||
uni.showToast({ title: t("AdminPage.pickNoneTip"), icon: "none" });
|
||||
@@ -176,22 +157,6 @@ watch(currentLocale, () => {
|
||||
}
|
||||
});
|
||||
|
||||
onLoad((options) => {
|
||||
pickTarget.readOptions(options);
|
||||
isPick.value = String(options?.channel ?? "").trim().length > 0;
|
||||
// function-operation 选上级目录时锁 FunctionIndc=N、选下级菜单时锁 Y:
|
||||
// 用 ?indc= 传进来预置到菜单? 筛选,回传后按该类型过滤候选功能。
|
||||
const indc = String(options?.indc ?? "").trim();
|
||||
if (indc) {
|
||||
const option = bindOptions.find(
|
||||
item => item.BindValue === SecurityFunctionDisplayData.DB_FUNCTION_INDC,
|
||||
);
|
||||
if (option) {
|
||||
option.Value = indc;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
useAuthGuard(() => {
|
||||
// 每次显示都重拉第一页:增/改/删后从详情返回能看到最新数据(navigateBack 不重新挂页面)
|
||||
nextTick(() => listRef.value?.refresh());
|
||||
@@ -200,24 +165,20 @@ useAuthGuard(() => {
|
||||
|
||||
<template>
|
||||
<view class="page">
|
||||
<admin-list ref="listRef" v-model:keyword="keyword" :nav-title="t('FunctionPage.title')"
|
||||
:show-nav-back="!isPick" :columns="columns" :loader="state.query"
|
||||
:row-key="SecurityFunctionDisplayData.FUNCTION_NAME" title-key="FunctionName"
|
||||
:selectable="isPick ? pickTarget.multiple.value : Boolean(perm.canDelete.value)" :filter-count="filterCount"
|
||||
:filter-visible="filterVisible" :filter-items="draft" :search-token="searchToken"
|
||||
:keep-selection-on-reload="isPick" @search="onSearch" @open-filter="state.openFilter()"
|
||||
@close-filter="state.closeFilter()" @apply-filter="state.applyFilter($event)"
|
||||
@clear-filter="state.clearFiltersAndSearch()" @row-tap="onRowTap">
|
||||
<template v-if="!isPick && perm.canCreate.value" #toolbar-actions>
|
||||
<admin-list ref="listRef" v-model:keyword="keyword" :nav-title="t('FunctionPage.title')" :show-nav-back="true"
|
||||
:columns="columns" :loader="state.query" :row-key="SecurityFunctionDisplayData.FUNCTION_NAME"
|
||||
title-key="FunctionName" :selectable="Boolean(perm.canDelete.value)" :filter-count="filterCount"
|
||||
:filter-visible="filterVisible" :filter-items="draft" :search-token="searchToken" @search="onSearch"
|
||||
@open-filter="state.openFilter()" @close-filter="state.closeFilter()"
|
||||
@apply-filter="state.applyFilter($event)" @clear-filter="state.clearFiltersAndSearch()" @row-tap="onRowTap">
|
||||
<template v-if="perm.canCreate.value" #toolbar-actions>
|
||||
<view class="create-entry" @click="onCreate">
|
||||
<u-icon name="plus" size="40" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<template #actions="{ rows }">
|
||||
<u-button v-if="isPick" type="primary" shape="circle" size="mini" :text="t('AdminPage.pickDoneBut')"
|
||||
@click="onConfirm(rows)" />
|
||||
<u-button v-else-if="perm.canDelete.value" type="error" shape="circle" size="mini"
|
||||
<u-button v-if="perm.canDelete.value" type="error" shape="circle" size="mini"
|
||||
:text="t('AdminPage.deleteBut')" @click="onDelete(rows)" />
|
||||
</template>
|
||||
</admin-list>
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
*
|
||||
* 对齐旧逻辑:
|
||||
* - 主表 SecurityFunction(DisplayData 形状),字段含 菜单?(FunctionIndc Y/N)、权限名称(选择器)等;
|
||||
* - 上级目录 SecurityFunctionMapParents:选 function-enquiry(单选、锁 FunctionIndc=N,
|
||||
* - 上级目录 SecurityFunctionMapParents:弹窗选功能(单选、锁 FunctionIndc=N,
|
||||
* 即只能挂在"目录"型功能下),最多一条(旧页面父为空时才显示新增);
|
||||
* - 下级菜单 SecurityFunctionMapSons:选 function-enquiry(多选、锁 FunctionIndc=Y),
|
||||
* - 下级菜单 SecurityFunctionMapSons:弹窗选功能(多选、锁 FunctionIndc=Y),
|
||||
* 仅当本页 FunctionIndc=N(目录)才能加;可上下移动重排,重排后 Orderby=序号+1;
|
||||
* - 菜单? 从 N 改成非 N 时清空下级菜单(旧 onFunctionIndcChange);
|
||||
* - 保存按 CreatedBy 有无决定 Update / Insert(SecurityFunctionData)。
|
||||
@@ -16,7 +16,8 @@ import type { AdminFormAction, AdminFormField, AdminFormSection } from "@/admin/
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { useLocale } from "uview-pro";
|
||||
import { computed, ref } from "vue";
|
||||
import { useAdminPick, useAuthGuard } from "@/composables";
|
||||
import { useAuthGuard } from "@/composables";
|
||||
import { useFunctionPickConfig, usePermissionPickConfig } from "@/composables/usePickerConfigs";
|
||||
import { SecurityFunctionData } from "@/data/auto/securityFunctionData";
|
||||
import { SecurityFunctionMapViewEntity } from "@/data/auto/securityFunctionMapViewEntity";
|
||||
import { usePagePermission } from "@/permission/permission-context";
|
||||
@@ -180,37 +181,49 @@ function onBack(): void {
|
||||
smartBack("mineTab");
|
||||
}
|
||||
|
||||
// 权限名称:单选 permission-enquiry,回传写进 FunctionName 之外不影响
|
||||
const permissionPicker = useAdminPick("permission");
|
||||
// 权限名称:单选弹窗
|
||||
const permissionConfig = usePermissionPickConfig();
|
||||
const showPermissionPicker = ref(false);
|
||||
|
||||
function pickPermission(): void {
|
||||
if (readonly.value || !perm.canAmend.value) {
|
||||
return;
|
||||
}
|
||||
permissionPicker.open({ page: "permissionEnquiry" }, (rows) => {
|
||||
if (rows.length) {
|
||||
func.value.PermissionName = String(rows[0].PermissionName ?? "");
|
||||
}
|
||||
});
|
||||
showPermissionPicker.value = true;
|
||||
}
|
||||
|
||||
// 上级目录:单选 function-enquiry(锁 FunctionIndc=N),仅当父为空时可加
|
||||
const parentPicker = useAdminPick("parent");
|
||||
function onPermissionPicked(rows: any[]): void {
|
||||
if (rows.length) {
|
||||
func.value.PermissionName = String(rows[0].PermissionName ?? "");
|
||||
}
|
||||
showPermissionPicker.value = false;
|
||||
}
|
||||
|
||||
// 上级目录:单选弹窗(锁 FunctionIndc=N)
|
||||
const parentConfig = useFunctionPickConfig();
|
||||
const showParentPicker = ref(false);
|
||||
|
||||
function addParent(): void {
|
||||
if (data.value.SecurityFunctionMapParents.length > 0) {
|
||||
return;
|
||||
}
|
||||
parentPicker.open({ page: "functionEnquiry", params: { indc: "N" } }, (rows) => {
|
||||
ensureLists();
|
||||
if (!rows.length) {
|
||||
return;
|
||||
parentConfig.fixedFilters.value = { indc: "N" };
|
||||
showParentPicker.value = true;
|
||||
}
|
||||
|
||||
function onParentPicked(rows: any[]): void {
|
||||
ensureLists();
|
||||
if (rows.length) {
|
||||
const parentName = String(rows[0].FunctionName ?? "");
|
||||
// 防御:不能把自己设为自己的上级目录(旧跳页版也没挡,弹窗化顺手补上)
|
||||
if (parentName && parentName !== func.value.FunctionName) {
|
||||
const parent = new SecurityFunctionMapViewEntity();
|
||||
parent.ParentFunctionName = parentName;
|
||||
parent.ParentFunctionLocalName = String(rows[0].FunctionLocalName ?? "");
|
||||
data.value.SecurityFunctionMapParents.push(parent);
|
||||
}
|
||||
const parent = new SecurityFunctionMapViewEntity();
|
||||
parent.ParentFunctionName = String(rows[0].FunctionName ?? "");
|
||||
parent.ParentFunctionLocalName = String(rows[0].FunctionLocalName ?? "");
|
||||
data.value.SecurityFunctionMapParents.push(parent);
|
||||
});
|
||||
}
|
||||
showParentPicker.value = false;
|
||||
}
|
||||
|
||||
function deleteParent(parentFunctionName: string): void {
|
||||
@@ -219,26 +232,32 @@ function deleteParent(parentFunctionName: string): void {
|
||||
);
|
||||
}
|
||||
|
||||
// 下级菜单:多选 function-enquiry(锁 FunctionIndc=Y),仅目录(FunctionIndc=N)可加
|
||||
const sonPicker = useAdminPick("son");
|
||||
// 下级菜单:多选弹窗(锁 FunctionIndc=Y),仅目录(FunctionIndc=N)可加
|
||||
const sonConfig = useFunctionPickConfig();
|
||||
const showSonPicker = ref(false);
|
||||
|
||||
function addSon(): void {
|
||||
sonPicker.open({ page: "functionEnquiry", params: { multiple: "1", indc: "Y" } }, (rows) => {
|
||||
ensureLists();
|
||||
const exists = new Set(data.value.SecurityFunctionMapSons.map(item => item.SonFunctionName));
|
||||
for (const row of rows) {
|
||||
const sonName = String(row.FunctionName ?? "");
|
||||
if (!sonName || exists.has(sonName)) {
|
||||
continue;
|
||||
}
|
||||
const son = new SecurityFunctionMapViewEntity();
|
||||
son.SonFunctionName = sonName;
|
||||
son.SonFunctionLocalName = String(row.FunctionLocalName ?? "");
|
||||
son.Orderby = data.value.SecurityFunctionMapSons.length + 1;
|
||||
data.value.SecurityFunctionMapSons.push(son);
|
||||
exists.add(sonName);
|
||||
sonConfig.fixedFilters.value = { indc: "Y" };
|
||||
showSonPicker.value = true;
|
||||
}
|
||||
|
||||
function onSonPicked(rows: any[]): void {
|
||||
ensureLists();
|
||||
const exists = new Set(data.value.SecurityFunctionMapSons.map(item => item.SonFunctionName));
|
||||
for (const row of rows) {
|
||||
const sonName = String(row.FunctionName ?? "");
|
||||
// 防御:跳过空、自身(不能把自己挂成自己的下级菜单)、以及已在列表里的
|
||||
if (!sonName || sonName === func.value.FunctionName || exists.has(sonName)) {
|
||||
continue;
|
||||
}
|
||||
});
|
||||
const son = new SecurityFunctionMapViewEntity();
|
||||
son.SonFunctionName = sonName;
|
||||
son.SonFunctionLocalName = String(row.FunctionLocalName ?? "");
|
||||
son.Orderby = data.value.SecurityFunctionMapSons.length + 1;
|
||||
data.value.SecurityFunctionMapSons.push(son);
|
||||
exists.add(sonName);
|
||||
}
|
||||
showSonPicker.value = false;
|
||||
}
|
||||
|
||||
function deleteSon(sonFunctionName: string): void {
|
||||
@@ -393,6 +412,22 @@ useAuthGuard(() => {
|
||||
</view>
|
||||
</template>
|
||||
</admin-form>
|
||||
|
||||
<!-- 弹窗选择器 -->
|
||||
<admin-pick-popup v-model:visible="showPermissionPicker" :title="t('PermissionPage.title')"
|
||||
:columns="permissionConfig.columns.value" :loader="permissionConfig.loader" :row-key="permissionConfig.rowKey"
|
||||
:title-key="permissionConfig.titleKey" :multiple="false" :fixed-filters="permissionConfig.fixedFilters.value"
|
||||
@confirm="onPermissionPicked" @close="showPermissionPicker = false" />
|
||||
|
||||
<admin-pick-popup v-model:visible="showParentPicker" :title="t('FunctionPage.parentTitle')"
|
||||
:columns="parentConfig.columns.value" :loader="parentConfig.loader" :row-key="parentConfig.rowKey"
|
||||
:title-key="parentConfig.titleKey" :multiple="false" :fixed-filters="parentConfig.fixedFilters.value"
|
||||
@confirm="onParentPicked" @close="showParentPicker = false" />
|
||||
|
||||
<admin-pick-popup v-model:visible="showSonPicker" :title="t('FunctionPage.sonTitle')"
|
||||
:columns="sonConfig.columns.value" :loader="sonConfig.loader" :row-key="sonConfig.rowKey"
|
||||
:title-key="sonConfig.titleKey" :multiple="true" :fixed-filters="sonConfig.fixedFilters.value"
|
||||
@confirm="onSonPicked" @close="showSonPicker = false" />
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -3,22 +3,20 @@
|
||||
* 用户组查询(列表页):旧 WebVue views/security/GroupEnquiry.vue 的移动端等价物
|
||||
*
|
||||
* 保留:三条筛选(组别名称/中文名称 文本包含、创建日期 区间)、每页 20 条、
|
||||
* 行点击进详情、多选批量删除(旧页面也是循环 Delete(GroupName))、多选选择器模式。
|
||||
* 行点击进详情、多选批量删除(旧页面也是循环 Delete(GroupName))。
|
||||
* 丢掉:多列网格、列配置、打印、桌面双击弹窗。
|
||||
*
|
||||
* 两种打开方式,同一套列表:
|
||||
* 1. 从菜单/枢纽页进(无 channel):普通查询页,点行 -> group-operation 详情;
|
||||
* 2. 被 actor-operation / group-operation 当"组别选择器"跳进来(带 ?channel=&multiple=1):
|
||||
* 选完 uni.$emit 回传再 navigateBack(见 useAdminPick / useAdminPickTarget 协议)。
|
||||
* 普通查询页:点行 -> group-operation 详情。
|
||||
* 旧系统里 actor-operation / group-operation 用 <dragModal> 内嵌本页做"组别选择器";
|
||||
* 移动端的弹窗选择已由调用方内嵌 <admin-pick-popup> 实现,
|
||||
* 本页不再承担选择器职责(useAdminPick / useAdminPickTarget 协议已移除)。
|
||||
*/
|
||||
import type { AdminColumn, AdminQuery, AdminRow } from "@/admin/admin-types";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { useLocale } from "uview-pro";
|
||||
import { computed, nextTick, reactive, ref, watch } from "vue";
|
||||
import { fillCriteria, makeFilterOption } from "@/admin/admin-filter";
|
||||
import {
|
||||
useAdminList,
|
||||
useAdminPickTarget,
|
||||
useAuthGuard,
|
||||
} from "@/composables";
|
||||
import { SecurityGroupEntity } from "@/data/auto/securityGroupEntity";
|
||||
@@ -31,10 +29,6 @@ import securityGroupService from "@/service/security/securityGroupService";
|
||||
|
||||
const { t, currentLocale } = useLocale();
|
||||
const perm = usePagePermission("groupEnquiry");
|
||||
const pickTarget = useAdminPickTarget();
|
||||
|
||||
/** 选择器模式:带 channel 进来时点行回传而非跳详情 */
|
||||
const isPick = ref(false);
|
||||
|
||||
const LABEL_KEYS: Record<string, string> = {
|
||||
[SecurityGroupEntity.DB_GROUP_NAME]: "GroupPage.groupName",
|
||||
@@ -109,13 +103,6 @@ function onSearch(): void {
|
||||
}
|
||||
|
||||
function onRowTap(row: AdminRow): void {
|
||||
if (isPick.value) {
|
||||
if (pickTarget.multiple.value) {
|
||||
return;
|
||||
}
|
||||
pickTarget.deliverOne(row);
|
||||
return;
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: `${pageUrl("groupOperation")}?id=${row.GroupName}&mode=view`,
|
||||
});
|
||||
@@ -125,14 +112,6 @@ function onCreate(): void {
|
||||
uni.navigateTo({ url: `${pageUrl("groupOperation")}?mode=create` });
|
||||
}
|
||||
|
||||
function onConfirm(rows: AdminRow[]): void {
|
||||
if (!rows.length) {
|
||||
uni.showToast({ title: t("AdminPage.pickNoneTip"), icon: "none" });
|
||||
return;
|
||||
}
|
||||
pickTarget.deliver(rows);
|
||||
}
|
||||
|
||||
async function onDelete(rows: AdminRow[]): Promise<void> {
|
||||
if (!rows.length) {
|
||||
uni.showToast({ title: t("AdminPage.pickNoneTip"), icon: "none" });
|
||||
@@ -163,11 +142,6 @@ watch(currentLocale, () => {
|
||||
}
|
||||
});
|
||||
|
||||
onLoad((options) => {
|
||||
pickTarget.readOptions(options);
|
||||
isPick.value = String(options?.channel ?? "").trim().length > 0;
|
||||
});
|
||||
|
||||
useAuthGuard(() => {
|
||||
// 每次显示都重拉第一页:增/改/删后从详情返回能看到最新数据(navigateBack 不重新挂页面)
|
||||
nextTick(() => listRef.value?.refresh());
|
||||
@@ -176,23 +150,20 @@ useAuthGuard(() => {
|
||||
|
||||
<template>
|
||||
<view class="page">
|
||||
<admin-list ref="listRef" v-model:keyword="keyword" :nav-title="t('GroupPage.title')" :show-nav-back="!isPick"
|
||||
<admin-list ref="listRef" v-model:keyword="keyword" :nav-title="t('GroupPage.title')" :show-nav-back="true"
|
||||
:columns="columns" :loader="state.query" :row-key="SecurityGroupEntity.GROUP_NAME" title-key="GroupName"
|
||||
:selectable="isPick ? pickTarget.multiple.value : Boolean(perm.canDelete.value)" :filter-count="filterCount"
|
||||
:filter-visible="filterVisible" :filter-items="draft" :search-token="searchToken"
|
||||
:keep-selection-on-reload="isPick" @search="onSearch" @open-filter="state.openFilter()"
|
||||
:selectable="Boolean(perm.canDelete.value)" :filter-count="filterCount" :filter-visible="filterVisible"
|
||||
:filter-items="draft" :search-token="searchToken" @search="onSearch" @open-filter="state.openFilter()"
|
||||
@close-filter="state.closeFilter()" @apply-filter="state.applyFilter($event)"
|
||||
@clear-filter="state.clearFiltersAndSearch()" @row-tap="onRowTap">
|
||||
<template v-if="!isPick && perm.canCreate.value" #toolbar-actions>
|
||||
<template v-if="perm.canCreate.value" #toolbar-actions>
|
||||
<view class="create-entry" @click="onCreate">
|
||||
<u-icon name="plus" size="40" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<template #actions="{ rows }">
|
||||
<u-button v-if="isPick" type="primary" shape="circle" size="mini" :text="t('AdminPage.pickDoneBut')"
|
||||
@click="onConfirm(rows)" />
|
||||
<u-button v-else-if="perm.canDelete.value" type="error" shape="circle" size="mini"
|
||||
<u-button v-if="perm.canDelete.value" type="error" shape="circle" size="mini"
|
||||
:text="t('AdminPage.deleteBut')" @click="onDelete(rows)" />
|
||||
</template>
|
||||
</admin-list>
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
/**
|
||||
* 组别详情(查看 / 新增 / 修改):旧 WebVue views/security/GroupOperation.vue 的移动端等价物
|
||||
*
|
||||
* 三个子表(旧页用 dragModal 内嵌 Enquiry + provide/inject,移动端改成真跳选择页再回传):
|
||||
* 1. 权限明细 SecurityGroupPermissionViews —— 选 permission-enquiry(多选),
|
||||
* 三个子表(旧页用 dragModal 内嵌 Enquiry + provide/inject,移动端改用 admin-pick-popup 底部弹窗):
|
||||
* 1. 权限明细 SecurityGroupPermissionViews —— 弹窗选 permission(多选),
|
||||
* 每行带 查看/新增/修改/删除 四个勾选(对齐旧 GroupPermissionActions 的四个 checkbox);
|
||||
* 删除权限行会连同其扩展权限明细一起剔除(旧 deletePermission 同款)。
|
||||
* 2. 扩展权限明细 SecurityGroupPermissionDependentViews —— 由权限行的"扩展名称"点开
|
||||
* permission-dependent-enquiry(多选、按 dependent 过滤)补入;
|
||||
* 3. 组别内角色群 SecurityActorGroups —— 选 actor-enquiry(多选)。
|
||||
* 扩展权限弹窗(多选、按 dependent 过滤)补入;
|
||||
* 3. 组别内角色群 SecurityActorGroups —— 弹窗选角色(多选)。
|
||||
* 新增权限/扩展权限行时四个勾选全部置 false(旧页面 ent.IsAmend=...=false)。
|
||||
* 保存按 CreatedBy 有无决定 Update / Insert(SecurityGroupData)。
|
||||
*/
|
||||
@@ -16,7 +16,8 @@ import type { AdminFormAction, AdminFormField, AdminFormSection } from "@/admin/
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { useLocale } from "uview-pro";
|
||||
import { computed, ref } from "vue";
|
||||
import { useAdminPick, useAuthGuard } from "@/composables";
|
||||
import { useAuthGuard } from "@/composables";
|
||||
import { useActorPickConfig, useDependentPickConfig, usePermissionPickConfig } from "@/composables/usePickerConfigs";
|
||||
import { SecurityActorGroupViewEntity } from "@/data/auto/securityActorGroupViewEntity";
|
||||
import { SecurityGroupData } from "@/data/auto/securityGroupData";
|
||||
import { SecurityGroupPermissionDependentViewDisplayData } from "@/data/auto/securityGroupPermissionDependentViewDisplayData";
|
||||
@@ -197,28 +198,32 @@ function actionLabel(key: string): string {
|
||||
return map[key] ?? key;
|
||||
}
|
||||
|
||||
// 权限选择:跳 permission-enquiry(多选),按 PermissionName 去重
|
||||
const permissionPicker = useAdminPick("permission");
|
||||
// 权限选择弹窗
|
||||
const permissionConfig = usePermissionPickConfig();
|
||||
const showPermissionPicker = ref(false);
|
||||
|
||||
function addPermission(): void {
|
||||
permissionPicker.open({ page: "permissionEnquiry", params: { multiple: "1" } }, (rows) => {
|
||||
ensureLists();
|
||||
const exists = new Set(data.value.SecurityGroupPermissionViews.map(item => item.PermissionName));
|
||||
for (const row of rows) {
|
||||
const permissionName = String(row.PermissionName ?? "");
|
||||
if (!permissionName || exists.has(permissionName)) {
|
||||
continue;
|
||||
}
|
||||
const ent = new SecurityGroupPermissionViewDisplayData();
|
||||
ent.GroupName = String(group.value.GroupName ?? "");
|
||||
ent.PermissionName = permissionName;
|
||||
ent.PermissionDescription = String(row.Description ?? "");
|
||||
ent.Dependent = String(row.Dependent ?? "");
|
||||
ent.IsView = ent.IsCreate = ent.IsAmend = ent.IsDelete = false;
|
||||
data.value.SecurityGroupPermissionViews.push(ent);
|
||||
exists.add(permissionName);
|
||||
showPermissionPicker.value = true;
|
||||
}
|
||||
|
||||
function onPermissionPicked(rows: any[]): void {
|
||||
ensureLists();
|
||||
const exists = new Set(data.value.SecurityGroupPermissionViews.map(item => item.PermissionName));
|
||||
for (const row of rows) {
|
||||
const permissionName = String(row.PermissionName ?? "");
|
||||
if (!permissionName || exists.has(permissionName)) {
|
||||
continue;
|
||||
}
|
||||
});
|
||||
const ent = new SecurityGroupPermissionViewDisplayData();
|
||||
ent.GroupName = String(group.value.GroupName ?? "");
|
||||
ent.PermissionName = permissionName;
|
||||
ent.PermissionDescription = String(row.Description ?? "");
|
||||
ent.Dependent = String(row.Dependent ?? "");
|
||||
ent.IsView = ent.IsCreate = ent.IsAmend = ent.IsDelete = false;
|
||||
data.value.SecurityGroupPermissionViews.push(ent);
|
||||
exists.add(permissionName);
|
||||
}
|
||||
showPermissionPicker.value = false;
|
||||
}
|
||||
|
||||
function deletePermission(permissionName: string): void {
|
||||
@@ -231,37 +236,39 @@ function deletePermission(permissionName: string): void {
|
||||
);
|
||||
}
|
||||
|
||||
// 扩展权限选择:跳 permission-dependent-enquiry(多选、按当前权限行的 dependent 过滤)
|
||||
const dependentPicker = useAdminPick("dependent");
|
||||
// 扩展权限选择弹窗
|
||||
const dependentConfig = useDependentPickConfig();
|
||||
const showDependentPicker = ref(false);
|
||||
|
||||
function addPermissionDependent(dependent: string): void {
|
||||
if (readonly.value || !dependent) {
|
||||
return;
|
||||
}
|
||||
dependentPicker.open(
|
||||
{ page: "permissionDependentEnquiry", params: { multiple: "1", dependent } },
|
||||
(rows) => {
|
||||
ensureLists();
|
||||
const exists = new Set(
|
||||
data.value.SecurityGroupPermissionDependentViews.map(item => item.DependentDetailName),
|
||||
);
|
||||
for (const row of rows) {
|
||||
const detailName = String(row.DependentDetailName ?? "");
|
||||
if (!detailName || exists.has(detailName)) {
|
||||
continue;
|
||||
}
|
||||
const ent = new SecurityGroupPermissionDependentViewDisplayData();
|
||||
ent.GroupName = String(group.value.GroupName ?? "");
|
||||
ent.PermissionName = String(row.PermissionName ?? "");
|
||||
ent.Dependent = String(row.Dependent ?? "");
|
||||
ent.DependentDetailName = detailName;
|
||||
ent.DependentDetailDescription = String(row.DependentDetailDescription ?? "");
|
||||
ent.IsView = ent.IsCreate = ent.IsAmend = ent.IsDelete = false;
|
||||
data.value.SecurityGroupPermissionDependentViews.push(ent);
|
||||
exists.add(detailName);
|
||||
}
|
||||
},
|
||||
dependentConfig.fixedFilters.value = { dependent };
|
||||
showDependentPicker.value = true;
|
||||
}
|
||||
|
||||
function onDependentPicked(rows: any[]): void {
|
||||
ensureLists();
|
||||
const exists = new Set(
|
||||
data.value.SecurityGroupPermissionDependentViews.map(item => item.DependentDetailName),
|
||||
);
|
||||
for (const row of rows) {
|
||||
const detailName = String(row.DependentDetailName ?? "");
|
||||
if (!detailName || exists.has(detailName)) {
|
||||
continue;
|
||||
}
|
||||
const ent = new SecurityGroupPermissionDependentViewDisplayData();
|
||||
ent.GroupName = String(group.value.GroupName ?? "");
|
||||
ent.PermissionName = String(row.PermissionName ?? "");
|
||||
ent.Dependent = String(row.Dependent ?? "");
|
||||
ent.DependentDetailName = detailName;
|
||||
ent.DependentDetailDescription = String(row.DependentDetailDescription ?? "");
|
||||
ent.IsView = ent.IsCreate = ent.IsAmend = ent.IsDelete = false;
|
||||
data.value.SecurityGroupPermissionDependentViews.push(ent);
|
||||
exists.add(detailName);
|
||||
}
|
||||
showDependentPicker.value = false;
|
||||
}
|
||||
|
||||
function deletePermissionDependent(detailName: string): void {
|
||||
@@ -270,26 +277,30 @@ function deletePermissionDependent(detailName: string): void {
|
||||
);
|
||||
}
|
||||
|
||||
// 角色选择:跳 actor-enquiry(多选),按 ActorName 去重
|
||||
const actorPicker = useAdminPick("actor");
|
||||
// 角色选择弹窗
|
||||
const actorConfig = useActorPickConfig();
|
||||
const showActorPicker = ref(false);
|
||||
|
||||
function addActor(): void {
|
||||
actorPicker.open({ page: "actorEnquiry", params: { multiple: "1" } }, (rows) => {
|
||||
ensureLists();
|
||||
const exists = new Set(data.value.SecurityActorGroups.map(item => item.ActorName));
|
||||
for (const row of rows) {
|
||||
const actorName = String(row.ActorName ?? "");
|
||||
if (!actorName || exists.has(actorName)) {
|
||||
continue;
|
||||
}
|
||||
const ent = new SecurityActorGroupViewEntity();
|
||||
ent.GroupName = String(group.value.GroupName ?? "");
|
||||
ent.ActorName = actorName;
|
||||
ent.ActorLocalName = String(row.ActorLocalName ?? "");
|
||||
data.value.SecurityActorGroups.push(ent);
|
||||
exists.add(actorName);
|
||||
showActorPicker.value = true;
|
||||
}
|
||||
|
||||
function onActorPicked(rows: any[]): void {
|
||||
ensureLists();
|
||||
const exists = new Set(data.value.SecurityActorGroups.map(item => item.ActorName));
|
||||
for (const row of rows) {
|
||||
const actorName = String(row.ActorName ?? "");
|
||||
if (!actorName || exists.has(actorName)) {
|
||||
continue;
|
||||
}
|
||||
});
|
||||
const ent = new SecurityActorGroupViewEntity();
|
||||
ent.GroupName = String(group.value.GroupName ?? "");
|
||||
ent.ActorName = actorName;
|
||||
ent.ActorLocalName = String(row.ActorLocalName ?? "");
|
||||
data.value.SecurityActorGroups.push(ent);
|
||||
exists.add(actorName);
|
||||
}
|
||||
showActorPicker.value = false;
|
||||
}
|
||||
|
||||
function deleteActor(actorName: string): void {
|
||||
@@ -460,6 +471,22 @@ useAuthGuard(() => {
|
||||
</view>
|
||||
</template>
|
||||
</admin-form>
|
||||
|
||||
<!-- 弹窗选择器 -->
|
||||
<admin-pick-popup v-model:visible="showPermissionPicker" :title="t('PermissionPage.title')"
|
||||
:columns="permissionConfig.columns.value" :loader="permissionConfig.loader" :row-key="permissionConfig.rowKey"
|
||||
:title-key="permissionConfig.titleKey" :multiple="true" :fixed-filters="permissionConfig.fixedFilters.value"
|
||||
@confirm="onPermissionPicked" @close="showPermissionPicker = false" />
|
||||
|
||||
<admin-pick-popup v-model:visible="showDependentPicker" :title="t('PermissionPage.dependentTitle')"
|
||||
:columns="dependentConfig.columns.value" :loader="dependentConfig.loader" :row-key="dependentConfig.rowKey"
|
||||
:title-key="dependentConfig.titleKey" :multiple="true" :fixed-filters="dependentConfig.fixedFilters.value"
|
||||
@confirm="onDependentPicked" @close="showDependentPicker = false" />
|
||||
|
||||
<admin-pick-popup v-model:visible="showActorPicker" :title="t('UserPage.actorTitle')"
|
||||
:columns="actorConfig.columns.value" :loader="actorConfig.loader" :row-key="actorConfig.rowKey"
|
||||
:title-key="actorConfig.titleKey" :multiple="true" :fixed-filters="actorConfig.fixedFilters.value"
|
||||
@confirm="onActorPicked" @close="showActorPicker = false" />
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -7,17 +7,16 @@
|
||||
* - "所属组"列存的是组主键(HelpFeatureGroupId),靠 FindAll 取回的组表翻译成组编码显示;
|
||||
* - 点一条功能点进它【所属组】的维护页(旧 gotoGroup 语义:id=组编码);
|
||||
* - 三条筛选:功能点名称 / 作用说明 / 图标 文本包含。
|
||||
* help-function-operation 会把它当"功能点组选择器"跳进来(单选),回传后按组主键翻译成组编码。
|
||||
* help-function-operation 的"选功能点组"弹窗已由调用方内嵌 <admin-pick-popup> 实现,
|
||||
* 本页不再承担选择器职责(useAdminPick / useAdminPickTarget 协议已移除)。
|
||||
*/
|
||||
import type { AdminColumn, AdminQuery, AdminRow } from "@/admin/admin-types";
|
||||
import type { SecurityHelpFeatureGroupEntity } from "@/data/auto/securityHelpFeatureGroupEntity";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { useLocale } from "uview-pro";
|
||||
import { computed, nextTick, reactive, ref, watch } from "vue";
|
||||
import { fillCriteria, makeFilterOption } from "@/admin/admin-filter";
|
||||
import {
|
||||
useAdminList,
|
||||
useAdminPickTarget,
|
||||
useAuthGuard,
|
||||
} from "@/composables";
|
||||
import { SecurityHelpFeatureEntity } from "@/data/auto/securityHelpFeatureEntity";
|
||||
@@ -30,9 +29,6 @@ import securityHelpFunctionService from "@/service/security/securityHelpFunction
|
||||
|
||||
const { t, currentLocale } = useLocale();
|
||||
const perm = usePagePermission("helpFeatureEnquiry");
|
||||
const pickTarget = useAdminPickTarget();
|
||||
|
||||
const isPick = ref(false);
|
||||
|
||||
const LABEL_KEYS: Record<string, string> = {
|
||||
[SecurityHelpFeatureEntity.DB_NAME]: "HelpFeaturePage.name",
|
||||
@@ -132,13 +128,6 @@ function onSearch(): void {
|
||||
}
|
||||
|
||||
function onRowTap(row: AdminRow): void {
|
||||
if (isPick.value) {
|
||||
if (pickTarget.multiple.value) {
|
||||
return;
|
||||
}
|
||||
pickTarget.deliverOne(row);
|
||||
return;
|
||||
}
|
||||
const groupCode = groupCodeOf(row.HelpFeatureGroupId);
|
||||
if (!groupCode) {
|
||||
uni.showToast({ title: t("HelpFeaturePage.noGroupTip"), icon: "none" });
|
||||
@@ -153,14 +142,6 @@ function onCreate(): void {
|
||||
uni.navigateTo({ url: `${pageUrl("helpFeatureOperation")}?mode=create` });
|
||||
}
|
||||
|
||||
function onConfirm(rows: AdminRow[]): void {
|
||||
if (!rows.length) {
|
||||
uni.showToast({ title: t("AdminPage.pickNoneTip"), icon: "none" });
|
||||
return;
|
||||
}
|
||||
pickTarget.deliver(rows);
|
||||
}
|
||||
|
||||
watch(currentLocale, () => {
|
||||
for (const option of bindOptions) {
|
||||
const key = LABEL_KEYS[option.BindValue];
|
||||
@@ -170,11 +151,6 @@ watch(currentLocale, () => {
|
||||
}
|
||||
});
|
||||
|
||||
onLoad((options) => {
|
||||
pickTarget.readOptions(options);
|
||||
isPick.value = String(options?.channel ?? "").trim().length > 0;
|
||||
});
|
||||
|
||||
useAuthGuard(() => {
|
||||
// 每次显示都重拉组表与第一页:增/改/删后从详情返回能看到最新数据(navigateBack 不重新挂页面)
|
||||
loadGroups();
|
||||
@@ -185,23 +161,16 @@ useAuthGuard(() => {
|
||||
<template>
|
||||
<view class="page">
|
||||
<admin-list ref="listRef" v-model:keyword="keyword" :nav-title="t('HelpFeaturePage.title')"
|
||||
:show-nav-back="!isPick" :columns="columns" :loader="state.query"
|
||||
:row-key="SecurityHelpFeatureEntity.HELP_FEATURE_ID" title-key="Name"
|
||||
:selectable="isPick && pickTarget.multiple.value" :filter-count="filterCount"
|
||||
:filter-visible="filterVisible" :filter-items="draft" :search-token="searchToken"
|
||||
:keep-selection-on-reload="isPick" @search="onSearch" @open-filter="state.openFilter()"
|
||||
@close-filter="state.closeFilter()" @apply-filter="state.applyFilter($event)"
|
||||
@clear-filter="state.clearFiltersAndSearch()" @row-tap="onRowTap">
|
||||
<template v-if="!isPick && perm.canCreate.value" #toolbar-actions>
|
||||
:show-nav-back="true" :columns="columns" :loader="state.query"
|
||||
:row-key="SecurityHelpFeatureEntity.HELP_FEATURE_ID" title-key="Name" :filter-count="filterCount"
|
||||
:filter-visible="filterVisible" :filter-items="draft" :search-token="searchToken" @search="onSearch"
|
||||
@open-filter="state.openFilter()" @close-filter="state.closeFilter()"
|
||||
@apply-filter="state.applyFilter($event)" @clear-filter="state.clearFiltersAndSearch()" @row-tap="onRowTap">
|
||||
<template v-if="perm.canCreate.value" #toolbar-actions>
|
||||
<view class="create-entry" @click="onCreate">
|
||||
<u-icon name="plus" size="40" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<template #actions="{ rows }">
|
||||
<u-button v-if="isPick" type="primary" shape="circle" size="mini" :text="t('AdminPage.pickDoneBut')"
|
||||
@click="onConfirm(rows)" />
|
||||
</template>
|
||||
</admin-list>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -6,15 +6,15 @@
|
||||
* - FindBySearchCriteria 的返回落在 data.Datas(SecurityHelpFunctionEntity[]);
|
||||
* - 两条筛选:功能名称 / 功能说明 文本包含;
|
||||
* - 作废走 DeleteByFunctionName(不是 Delete!旧页面即如此),行点击进详情。
|
||||
* 本页从不作为选择器被跳入,选择器的弹窗能力已由调用方内嵌 <admin-pick-popup> 实现,
|
||||
* 遗留的 useAdminPickTarget 模式代码已移除。
|
||||
*/
|
||||
import type { AdminColumn, AdminQuery, AdminRow } from "@/admin/admin-types";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { useLocale } from "uview-pro";
|
||||
import { computed, nextTick, reactive, ref, watch } from "vue";
|
||||
import { fillCriteria, makeFilterOption } from "@/admin/admin-filter";
|
||||
import {
|
||||
useAdminList,
|
||||
useAdminPickTarget,
|
||||
useAuthGuard,
|
||||
} from "@/composables";
|
||||
import { SecurityHelpFunctionEntity } from "@/data/auto/securityHelpFunctionEntity";
|
||||
@@ -27,9 +27,6 @@ import securityHelpFunctionService from "@/service/security/securityHelpFunction
|
||||
|
||||
const { t, currentLocale } = useLocale();
|
||||
const perm = usePagePermission("helpFunctionEnquiry");
|
||||
const pickTarget = useAdminPickTarget();
|
||||
|
||||
const isPick = ref(false);
|
||||
|
||||
const LABEL_KEYS: Record<string, string> = {
|
||||
[SecurityHelpFunctionEntity.DB_FUNCTION_NAME]: "HelpFunctionPage.functionName",
|
||||
@@ -97,13 +94,6 @@ function onSearch(): void {
|
||||
}
|
||||
|
||||
function onRowTap(row: AdminRow): void {
|
||||
if (isPick.value) {
|
||||
if (pickTarget.multiple.value) {
|
||||
return;
|
||||
}
|
||||
pickTarget.deliverOne(row);
|
||||
return;
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: `${pageUrl("helpFunctionOperation")}?id=${row.FunctionName}&mode=view`,
|
||||
});
|
||||
@@ -113,14 +103,6 @@ function onCreate(): void {
|
||||
uni.navigateTo({ url: `${pageUrl("helpFunctionOperation")}?mode=create` });
|
||||
}
|
||||
|
||||
function onConfirm(rows: AdminRow[]): void {
|
||||
if (!rows.length) {
|
||||
uni.showToast({ title: t("AdminPage.pickNoneTip"), icon: "none" });
|
||||
return;
|
||||
}
|
||||
pickTarget.deliver(rows);
|
||||
}
|
||||
|
||||
async function onDelete(rows: AdminRow[]): Promise<void> {
|
||||
if (!rows.length) {
|
||||
uni.showToast({ title: t("AdminPage.pickNoneTip"), icon: "none" });
|
||||
@@ -151,11 +133,6 @@ watch(currentLocale, () => {
|
||||
}
|
||||
});
|
||||
|
||||
onLoad((options) => {
|
||||
pickTarget.readOptions(options);
|
||||
isPick.value = String(options?.channel ?? "").trim().length > 0;
|
||||
});
|
||||
|
||||
useAuthGuard(() => {
|
||||
// 每次显示都重拉第一页:增/改/删后从详情返回能看到最新数据(navigateBack 不重新挂页面)
|
||||
nextTick(() => listRef.value?.refresh());
|
||||
@@ -165,23 +142,20 @@ useAuthGuard(() => {
|
||||
<template>
|
||||
<view class="page">
|
||||
<admin-list ref="listRef" v-model:keyword="keyword" :nav-title="t('HelpFunctionPage.title')"
|
||||
:show-nav-back="!isPick" :columns="columns" :loader="state.query"
|
||||
:show-nav-back="true" :columns="columns" :loader="state.query"
|
||||
:row-key="SecurityHelpFunctionEntity.FUNCTION_NAME" title-key="FunctionName"
|
||||
:selectable="isPick ? pickTarget.multiple.value : Boolean(perm.canDelete.value)" :filter-count="filterCount"
|
||||
:filter-visible="filterVisible" :filter-items="draft" :search-token="searchToken"
|
||||
:keep-selection-on-reload="isPick" @search="onSearch" @open-filter="state.openFilter()"
|
||||
:selectable="Boolean(perm.canDelete.value)" :filter-count="filterCount" :filter-visible="filterVisible"
|
||||
:filter-items="draft" :search-token="searchToken" @search="onSearch" @open-filter="state.openFilter()"
|
||||
@close-filter="state.closeFilter()" @apply-filter="state.applyFilter($event)"
|
||||
@clear-filter="state.clearFiltersAndSearch()" @row-tap="onRowTap">
|
||||
<template v-if="!isPick && perm.canCreate.value" #toolbar-actions>
|
||||
<template v-if="perm.canCreate.value" #toolbar-actions>
|
||||
<view class="create-entry" @click="onCreate">
|
||||
<u-icon name="plus" size="40" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<template #actions="{ rows }">
|
||||
<u-button v-if="isPick" type="primary" shape="circle" size="mini" :text="t('AdminPage.pickDoneBut')"
|
||||
@click="onConfirm(rows)" />
|
||||
<u-button v-else-if="perm.canDelete.value" type="error" shape="circle" size="mini"
|
||||
<u-button v-if="perm.canDelete.value" type="error" shape="circle" size="mini"
|
||||
:text="t('AdminPage.deleteBut')" @click="onDelete(rows)" />
|
||||
</template>
|
||||
</admin-list>
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
*
|
||||
* 对齐旧逻辑:
|
||||
* - onLoad 读 id(=FunctionName)与 mode;FindByFunctionName 取 SecurityHelpFunctionData;
|
||||
* - 主字段:功能名称(给哪个功能写帮助,新建时靠 function-enquiry 单选回填、之后锁死)、
|
||||
* - 主字段:功能名称(给哪个功能写帮助,新建时靠功能选择弹窗单选回填、之后锁死)、
|
||||
* 启用?(EnabledIndc Y/N switch)、功能说明(Intro textarea);
|
||||
* - 子表1 操作步骤 SecurityHelpSteps:内联可编辑 Title/Description/Tips/Icon,可上下移动;
|
||||
* - 子表2 引用的功能点组 SecurityHelpFunctionFeatures:GroupCode 靠 help-feature-enquiry 单选,
|
||||
* - 子表2 引用的功能点组 SecurityHelpFunctionFeatures:GroupCode 靠功能点选择弹窗单选,
|
||||
* 回传的功能点按 HelpFeatureGroupId 翻译成组编码写入;可上下移动;
|
||||
* - 保存前按界面顺序重排 StepNo=i+1 / SortNo=i+1,调 SaveFunction(不是 Insert/Update!);
|
||||
* 删除走 DeleteByFunctionName;新建默认 EnabledIndc='Y'。
|
||||
@@ -19,7 +19,8 @@ import type { SecurityHelpFeatureGroupEntity } from "@/data/auto/securityHelpFea
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { useLocale } from "uview-pro";
|
||||
import { computed, ref } from "vue";
|
||||
import { useAdminPick, useAuthGuard } from "@/composables";
|
||||
import { useAuthGuard } from "@/composables";
|
||||
import { useFunctionPickConfig, useHelpFeaturePickConfig } from "@/composables/usePickerConfigs";
|
||||
import { SecurityHelpFunctionData } from "@/data/auto/securityHelpFunctionData";
|
||||
import { SecurityHelpFunctionFeatureEntity } from "@/data/auto/securityHelpFunctionFeatureEntity";
|
||||
import { SecurityHelpStepEntity } from "@/data/auto/securityHelpStepEntity";
|
||||
@@ -213,44 +214,52 @@ function onBack(): void {
|
||||
smartBack("mineTab");
|
||||
}
|
||||
|
||||
// 功能名称:新建时单选 function-enquiry 回填(旧页用 FindFunctionNameOptions 下拉,移动端退化成选择器)
|
||||
const functionNamePicker = useAdminPick("functionName");
|
||||
// 功能名称:新建时单选弹窗回填
|
||||
const functionConfig = useFunctionPickConfig();
|
||||
const showFunctionPicker = ref(false);
|
||||
|
||||
function pickFunctionName(): void {
|
||||
if (readonly.value || !isNew.value || !perm.canAmend.value) {
|
||||
return;
|
||||
}
|
||||
functionNamePicker.open({ page: "functionEnquiry" }, (rows) => {
|
||||
if (rows.length) {
|
||||
helpFunction.value.FunctionName = String(rows[0].FunctionName ?? "");
|
||||
}
|
||||
});
|
||||
showFunctionPicker.value = true;
|
||||
}
|
||||
|
||||
// 引用的功能点组:单选 help-feature-enquiry,回传功能点后翻译成组编码
|
||||
const groupPicker = useAdminPick("group");
|
||||
function onFunctionPicked(rows: any[]): void {
|
||||
if (rows.length) {
|
||||
helpFunction.value.FunctionName = String(rows[0].FunctionName ?? "");
|
||||
}
|
||||
showFunctionPicker.value = false;
|
||||
}
|
||||
|
||||
// 引用的功能点组:单选弹窗,回传功能点后翻译成组编码
|
||||
const featureConfig = useHelpFeaturePickConfig();
|
||||
const showFeaturePicker = ref(false);
|
||||
|
||||
function addFeature(): void {
|
||||
groupPicker.open({ page: "helpFeatureEnquiry" }, (rows) => {
|
||||
ensureLists();
|
||||
if (!rows.length) {
|
||||
return;
|
||||
}
|
||||
const groupCode = groupCodeOf(rows[0].HelpFeatureGroupId);
|
||||
if (!groupCode) {
|
||||
uni.showToast({ title: t("HelpFeaturePage.noGroupTip"), icon: "none" });
|
||||
return;
|
||||
}
|
||||
const exists = data.value.SecurityHelpFunctionFeatures.some(item => item.GroupCode === groupCode);
|
||||
if (exists) {
|
||||
return;
|
||||
}
|
||||
const row = new SecurityHelpFunctionFeatureEntity();
|
||||
row.FunctionName = String(helpFunction.value.FunctionName ?? "");
|
||||
row.GroupCode = groupCode;
|
||||
row.SortNo = data.value.SecurityHelpFunctionFeatures.length + 1;
|
||||
data.value.SecurityHelpFunctionFeatures.push(row);
|
||||
});
|
||||
showFeaturePicker.value = true;
|
||||
}
|
||||
|
||||
function onFeaturePicked(rows: any[]): void {
|
||||
ensureLists();
|
||||
if (!rows.length) {
|
||||
return;
|
||||
}
|
||||
const groupCode = groupCodeOf(rows[0].HelpFeatureGroupId);
|
||||
if (!groupCode) {
|
||||
uni.showToast({ title: t("HelpFeaturePage.noGroupTip"), icon: "none" });
|
||||
return;
|
||||
}
|
||||
const exists = data.value.SecurityHelpFunctionFeatures.some(item => item.GroupCode === groupCode);
|
||||
if (exists) {
|
||||
return;
|
||||
}
|
||||
const row = new SecurityHelpFunctionFeatureEntity();
|
||||
row.FunctionName = String(helpFunction.value.FunctionName ?? "");
|
||||
row.GroupCode = groupCode;
|
||||
row.SortNo = data.value.SecurityHelpFunctionFeatures.length + 1;
|
||||
data.value.SecurityHelpFunctionFeatures.push(row);
|
||||
showFeaturePicker.value = false;
|
||||
}
|
||||
|
||||
function deleteFeature(index: number): void {
|
||||
@@ -486,6 +495,17 @@ useAuthGuard(() => {
|
||||
|
||||
<help-doc-preview :visible="previewVisible" :title="heroTitle" :intro="helpFunction.Intro" :steps="previewSteps"
|
||||
:features="previewFeatures" @close="previewVisible = false" />
|
||||
|
||||
<!-- 弹窗选择器 -->
|
||||
<admin-pick-popup v-model:visible="showFunctionPicker" :title="t('FunctionPage.title')"
|
||||
:columns="functionConfig.columns.value" :loader="functionConfig.loader" :row-key="functionConfig.rowKey"
|
||||
:title-key="functionConfig.titleKey" :multiple="false" :fixed-filters="functionConfig.fixedFilters.value"
|
||||
@confirm="onFunctionPicked" @close="showFunctionPicker = false" />
|
||||
|
||||
<admin-pick-popup v-model:visible="showFeaturePicker" :title="t('HelpFeaturePage.title')"
|
||||
:columns="featureConfig.columns.value" :loader="featureConfig.loader" :row-key="featureConfig.rowKey"
|
||||
:title-key="featureConfig.titleKey" :multiple="false" :fixed-filters="featureConfig.fixedFilters.value"
|
||||
@confirm="onFeaturePicked" @close="showFeaturePicker = false" />
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* 扩展权限选择页:旧 WebVue views/security/PermissionDependentModal.vue 的移动端等价物
|
||||
* 扩展权限查询页:旧 WebVue views/security/PermissionDependentModal.vue 的移动端等价物
|
||||
*
|
||||
* 旧页面就是一个纯"选择弹窗"(dragModal 内嵌),供 group-operation 挑扩展权限明细,
|
||||
* 移动端改成独立选择页:用 FindDependentsBySearchCriteria,返回落在 data.Dependents;
|
||||
* 唯一筛选是按"扩展名称"等值(EQUAL_TO)——由调用方通过 ?dependent= 传进来锁死,
|
||||
* 旧页面就是一个纯"选择弹窗"(dragModal 内嵌),移动端弹窗选择已由 group-operation 内嵌
|
||||
* <admin-pick-popup> 实现,本页保留为独立查询列表页:
|
||||
* 用 FindDependentsBySearchCriteria,返回落在 data.Dependents;
|
||||
* 唯一筛选是按"扩展名称"等值(EQUAL_TO)——可由 ?dependent= 传入锁定范围,
|
||||
* 因为扩展权限明细必须归属某个权限的扩展名称之下。
|
||||
*/
|
||||
import type { AdminColumn, AdminQuery, AdminRow } from "@/admin/admin-types";
|
||||
import type { AdminColumn, AdminQuery } from "@/admin/admin-types";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { useLocale } from "uview-pro";
|
||||
import { computed, nextTick, reactive, ref, watch } from "vue";
|
||||
import { fillCriteria, makeFilterOption } from "@/admin/admin-filter";
|
||||
import {
|
||||
useAdminList,
|
||||
useAdminPickTarget,
|
||||
useAuthGuard,
|
||||
} from "@/composables";
|
||||
import { SecurityPermissionDependentEntity } from "@/data/auto/securityPermissionDependentEntity";
|
||||
@@ -24,7 +24,6 @@ import { SearchFilterTypePolicy } from "@/data/custom/searchFilterTypePolicy";
|
||||
import securityPermissionService from "@/service/security/securityPermissionService";
|
||||
|
||||
const { t, currentLocale } = useLocale();
|
||||
const pickTarget = useAdminPickTarget();
|
||||
|
||||
const LABEL_KEYS: Record<string, string> = {
|
||||
[SecurityPermissionDependentEntity.DB_DEPENDENT]: "PermissionPage.dependent",
|
||||
@@ -79,22 +78,6 @@ function onSearch(): void {
|
||||
state.reload();
|
||||
}
|
||||
|
||||
function onRowTap(row: AdminRow): void {
|
||||
// 单选语义:直接回传;多选交给底部"确定"按钮统一交付
|
||||
if (pickTarget.multiple.value) {
|
||||
return;
|
||||
}
|
||||
pickTarget.deliverOne(row);
|
||||
}
|
||||
|
||||
function onConfirm(rows: AdminRow[]): void {
|
||||
if (!rows.length) {
|
||||
uni.showToast({ title: t("AdminPage.pickNoneTip"), icon: "none" });
|
||||
return;
|
||||
}
|
||||
pickTarget.deliver(rows);
|
||||
}
|
||||
|
||||
watch(currentLocale, () => {
|
||||
for (const option of bindOptions) {
|
||||
const key = LABEL_KEYS[option.BindValue];
|
||||
@@ -105,8 +88,7 @@ watch(currentLocale, () => {
|
||||
});
|
||||
|
||||
onLoad((options) => {
|
||||
pickTarget.readOptions(options);
|
||||
// 调用方锁死的扩展名称:写进等值筛选,只列出该扩展名称下的子项目
|
||||
// 可选的扩展名称过滤:?dependent= 传入时只列出该扩展名称下的子项目
|
||||
const dependent = String(options?.dependent ?? "").trim();
|
||||
if (dependent) {
|
||||
const option = bindOptions.find(
|
||||
@@ -127,16 +109,12 @@ useAuthGuard(() => {
|
||||
<template>
|
||||
<view class="page">
|
||||
<admin-list ref="listRef" v-model:keyword="keyword" :nav-title="t('PermissionPage.dependentTitle')"
|
||||
:show-nav-back="false" :columns="columns" :loader="state.query"
|
||||
:show-nav-back="true" :columns="columns" :loader="state.query"
|
||||
:row-key="SecurityPermissionDependentEntity.DEPENDENT_DETAIL_NAME" title-key="DependentDetailName"
|
||||
:selectable="pickTarget.multiple.value" :filter-count="filterCount" :filter-visible="filterVisible"
|
||||
:filter-items="draft" :search-token="searchToken" @search="onSearch" @open-filter="state.openFilter()"
|
||||
:filter-count="filterCount" :filter-visible="filterVisible" :filter-items="draft"
|
||||
:search-token="searchToken" @search="onSearch" @open-filter="state.openFilter()"
|
||||
@close-filter="state.closeFilter()" @apply-filter="state.applyFilter($event)"
|
||||
@clear-filter="state.clearFiltersAndSearch()" @row-tap="onRowTap">
|
||||
<template #actions="{ rows }">
|
||||
<u-button type="primary" shape="circle" size="mini" :text="t('AdminPage.pickDoneBut')"
|
||||
@click="onConfirm(rows)" />
|
||||
</template>
|
||||
@clear-filter="state.clearFiltersAndSearch()">
|
||||
</admin-list>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -5,17 +5,14 @@
|
||||
* 与旧页面对齐的关键点:
|
||||
* - findBySearchCriteria 的返回落在 data.Permissions(不是 Datas!),逐字照抄;
|
||||
* - 四条筛选:权限名称/中文名称/扩展名称 文本包含、创建日期 区间;
|
||||
* - 行点击进详情(无 channel)/ 作为选择器回传(带 channel)。
|
||||
* group-operation、function-operation 会把它当"权限选择器"跳进来(多选 / 单选)。
|
||||
* - 行点击进详情。
|
||||
*/
|
||||
import type { AdminColumn, AdminQuery, AdminRow } from "@/admin/admin-types";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { useLocale } from "uview-pro";
|
||||
import { computed, nextTick, reactive, ref, watch } from "vue";
|
||||
import { fillCriteria, makeFilterOption } from "@/admin/admin-filter";
|
||||
import {
|
||||
useAdminList,
|
||||
useAdminPickTarget,
|
||||
useAuthGuard,
|
||||
} from "@/composables";
|
||||
import { SecurityPermissionEntity } from "@/data/auto/securityPermissionEntity";
|
||||
@@ -28,9 +25,6 @@ import securityPermissionService from "@/service/security/securityPermissionServ
|
||||
|
||||
const { t, currentLocale } = useLocale();
|
||||
const perm = usePagePermission("permissionEnquiry");
|
||||
const pickTarget = useAdminPickTarget();
|
||||
|
||||
const isPick = ref(false);
|
||||
|
||||
const LABEL_KEYS: Record<string, string> = {
|
||||
[SecurityPermissionEntity.DB_PERMISSION_NAME]: "PermissionPage.permissionName",
|
||||
@@ -116,13 +110,6 @@ function onSearch(): void {
|
||||
}
|
||||
|
||||
function onRowTap(row: AdminRow): void {
|
||||
if (isPick.value) {
|
||||
if (pickTarget.multiple.value) {
|
||||
return;
|
||||
}
|
||||
pickTarget.deliverOne(row);
|
||||
return;
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: `${pageUrl("permissionOperation")}?id=${row.PermissionName}&mode=view`,
|
||||
});
|
||||
@@ -132,14 +119,6 @@ function onCreate(): void {
|
||||
uni.navigateTo({ url: `${pageUrl("permissionOperation")}?mode=create` });
|
||||
}
|
||||
|
||||
function onConfirm(rows: AdminRow[]): void {
|
||||
if (!rows.length) {
|
||||
uni.showToast({ title: t("AdminPage.pickNoneTip"), icon: "none" });
|
||||
return;
|
||||
}
|
||||
pickTarget.deliver(rows);
|
||||
}
|
||||
|
||||
async function onDelete(rows: AdminRow[]): Promise<void> {
|
||||
if (!rows.length) {
|
||||
uni.showToast({ title: t("AdminPage.pickNoneTip"), icon: "none" });
|
||||
@@ -170,11 +149,6 @@ watch(currentLocale, () => {
|
||||
}
|
||||
});
|
||||
|
||||
onLoad((options) => {
|
||||
pickTarget.readOptions(options);
|
||||
isPick.value = String(options?.channel ?? "").trim().length > 0;
|
||||
});
|
||||
|
||||
useAuthGuard(() => {
|
||||
// 每次显示都重拉第一页:增/改/删后从详情返回能看到最新数据(navigateBack 不重新挂页面)
|
||||
nextTick(() => listRef.value?.refresh());
|
||||
@@ -183,24 +157,20 @@ useAuthGuard(() => {
|
||||
|
||||
<template>
|
||||
<view class="page">
|
||||
<admin-list ref="listRef" v-model:keyword="keyword" :nav-title="t('PermissionPage.title')"
|
||||
:show-nav-back="!isPick" :columns="columns" :loader="state.query"
|
||||
:row-key="SecurityPermissionEntity.PERMISSION_NAME" title-key="PermissionName"
|
||||
:selectable="isPick ? pickTarget.multiple.value : Boolean(perm.canDelete.value)" :filter-count="filterCount"
|
||||
:filter-visible="filterVisible" :filter-items="draft" :search-token="searchToken"
|
||||
:keep-selection-on-reload="isPick" @search="onSearch" @open-filter="state.openFilter()"
|
||||
@close-filter="state.closeFilter()" @apply-filter="state.applyFilter($event)"
|
||||
@clear-filter="state.clearFiltersAndSearch()" @row-tap="onRowTap">
|
||||
<template v-if="!isPick && perm.canCreate.value" #toolbar-actions>
|
||||
<admin-list ref="listRef" v-model:keyword="keyword" :nav-title="t('PermissionPage.title')" :show-nav-back="true"
|
||||
:columns="columns" :loader="state.query" :row-key="SecurityPermissionEntity.PERMISSION_NAME"
|
||||
title-key="PermissionName" :selectable="Boolean(perm.canDelete.value)" :filter-count="filterCount"
|
||||
:filter-visible="filterVisible" :filter-items="draft" :search-token="searchToken" @search="onSearch"
|
||||
@open-filter="state.openFilter()" @close-filter="state.closeFilter()"
|
||||
@apply-filter="state.applyFilter($event)" @clear-filter="state.clearFiltersAndSearch()" @row-tap="onRowTap">
|
||||
<template v-if="perm.canCreate.value" #toolbar-actions>
|
||||
<view class="create-entry" @click="onCreate">
|
||||
<u-icon name="plus" size="40" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<template #actions="{ rows }">
|
||||
<u-button v-if="isPick" type="primary" shape="circle" size="mini" :text="t('AdminPage.pickDoneBut')"
|
||||
@click="onConfirm(rows)" />
|
||||
<u-button v-else-if="perm.canDelete.value" type="error" shape="circle" size="mini"
|
||||
<u-button v-if="perm.canDelete.value" type="error" shape="circle" size="mini"
|
||||
:text="t('AdminPage.deleteBut')" @click="onDelete(rows)" />
|
||||
</template>
|
||||
</admin-list>
|
||||
|
||||
@@ -7,13 +7,14 @@
|
||||
* 丢掉的东西:多列网格、列配置、打印——手机上没有对应交互。
|
||||
*
|
||||
* 页面只组数据与路由,列表/筛选/分页的机制全在 admin-list + useAdminList 里。
|
||||
* actor-operation 的"选用户"弹窗已由调用方内嵌 <admin-pick-popup> 实现,
|
||||
* 本页不再承担选择器职责(useAdminPick / useAdminPickTarget 协议已移除)。
|
||||
*/
|
||||
import type { AdminColumn, AdminQuery, AdminRow } from "@/admin/admin-types";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { useLocale } from "uview-pro";
|
||||
import { computed, nextTick, reactive, ref, watch } from "vue";
|
||||
import { fillCriteria, makeFilterOption } from "@/admin/admin-filter";
|
||||
import { useAdminList, useAdminPickTarget, useAuthGuard } from "@/composables";
|
||||
import { useAdminList, useAuthGuard } from "@/composables";
|
||||
import { SecurityUserEntity } from "@/data/auto/securityUserEntity";
|
||||
import { SecurityUserSearchCriteria } from "@/data/auto/securityUserSearchCriteria";
|
||||
import { SearchFilterOperatorPolicy } from "@/data/custom/searchFilterOperatorPolicy";
|
||||
@@ -24,10 +25,6 @@ import securityUserService from "@/service/security/securityUserService";
|
||||
|
||||
const { t, currentLocale } = useLocale();
|
||||
const perm = usePagePermission("userEnquiry");
|
||||
const pickTarget = useAdminPickTarget();
|
||||
|
||||
/** 选择器模式:带 channel 进来(如 actor-operation 选用户)时点行回传而非跳详情 */
|
||||
const isPick = ref(false);
|
||||
|
||||
/** 列名 -> i18n key:抽屉标签、卡片行标签都靠它,切换语言时就地刷新而不重建条件 */
|
||||
const LABEL_KEYS: Record<string, string> = {
|
||||
@@ -107,28 +104,13 @@ function onSearch(): void {
|
||||
}
|
||||
|
||||
function onRowTap(row: AdminRow): void {
|
||||
if (isPick.value) {
|
||||
if (pickTarget.multiple.value) {
|
||||
return;
|
||||
}
|
||||
pickTarget.deliverOne(row);
|
||||
return;
|
||||
}
|
||||
// 与旧页面一致:id 用 UserName,mode 决定详情页是只读还是编辑
|
||||
// 不做 encodeURIComponent:见 composables/useAdminPick 的说明(H5 二次编码坑)
|
||||
// 不做 encodeURIComponent:URL 参数按原样透传,避免 H5 二次编码坑
|
||||
uni.navigateTo({
|
||||
url: `${pageUrl("userOperation")}?id=${row.UserName}&mode=view`,
|
||||
});
|
||||
}
|
||||
|
||||
function onConfirm(rows: AdminRow[]): void {
|
||||
if (!rows.length) {
|
||||
uni.showToast({ title: t("AdminPage.pickNoneTip"), icon: "none" });
|
||||
return;
|
||||
}
|
||||
pickTarget.deliver(rows);
|
||||
}
|
||||
|
||||
function onCreate(): void {
|
||||
uni.navigateTo({ url: `${pageUrl("userOperation")}?mode=create` });
|
||||
}
|
||||
@@ -165,11 +147,6 @@ watch(currentLocale, () => {
|
||||
}
|
||||
});
|
||||
|
||||
onLoad((options) => {
|
||||
pickTarget.readOptions(options);
|
||||
isPick.value = String(options?.channel ?? "").trim().length > 0;
|
||||
});
|
||||
|
||||
// 取数排在登录守卫之后:admin-list 的 auto 默认 false,首屏由这里手动触发一次
|
||||
useAuthGuard(() => {
|
||||
// 每次显示都重拉第一页:增/改/删后从详情返回能看到最新数据(navigateBack 不重新挂页面)
|
||||
@@ -179,23 +156,20 @@ useAuthGuard(() => {
|
||||
|
||||
<template>
|
||||
<view class="page">
|
||||
<admin-list ref="listRef" v-model:keyword="keyword" :nav-title="t('UserPage.title')" :show-nav-back="!isPick"
|
||||
<admin-list ref="listRef" v-model:keyword="keyword" :nav-title="t('UserPage.title')" :show-nav-back="true"
|
||||
:columns="columns" :loader="state.query" :row-key="SecurityUserEntity.USER_NAME" title-key="UserLocalName"
|
||||
:selectable="isPick ? pickTarget.multiple.value : Boolean(perm.canDelete.value)" :filter-count="filterCount"
|
||||
:filter-visible="filterVisible" :filter-items="draft" :search-token="searchToken"
|
||||
:keep-selection-on-reload="isPick" @search="onSearch" @open-filter="state.openFilter()"
|
||||
:selectable="Boolean(perm.canDelete.value)" :filter-count="filterCount" :filter-visible="filterVisible"
|
||||
:filter-items="draft" :search-token="searchToken" @search="onSearch" @open-filter="state.openFilter()"
|
||||
@close-filter="state.closeFilter()" @apply-filter="state.applyFilter($event)"
|
||||
@clear-filter="state.clearFiltersAndSearch()" @row-tap="onRowTap">
|
||||
<template v-if="!isPick && perm.canCreate.value" #toolbar-actions>
|
||||
<template v-if="perm.canCreate.value" #toolbar-actions>
|
||||
<view class="create-entry" @click="onCreate">
|
||||
<u-icon name="plus" size="40" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<template #actions="{ rows }">
|
||||
<u-button v-if="isPick" type="primary" shape="circle" size="mini" :text="t('AdminPage.pickDoneBut')"
|
||||
@click="onConfirm(rows)" />
|
||||
<u-button v-else-if="perm.canDelete.value" type="error" shape="circle" size="mini"
|
||||
<u-button v-if="perm.canDelete.value" type="error" shape="circle" size="mini"
|
||||
:text="t('AdminPage.deleteBut')" @click="onDelete(rows)" />
|
||||
</template>
|
||||
</admin-list>
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
* - 密码编辑的是 SecurityUserDisplayData.OrgUserPassword(留空即不改);
|
||||
* - 角色明细按 ActorName 去重合并,删除即从数组里剔除。
|
||||
*
|
||||
* 旧页面的"选角色"是弹窗内嵌 Enquiry + provide/inject;这里改成真跳 actor-enquiry 页
|
||||
* 再回传(见 composables/useAdminPick),所以角色区放在 admin-form 的 #extra 插槽里自绘。
|
||||
* 旧页面的"选角色"是弹窗内嵌 Enquiry + provide/inject;这里用 <admin-pick-popup>
|
||||
* 底部弹窗(数据源见 composables/usePickerConfigs),角色区放在 admin-form 的 #extra 插槽里自绘。
|
||||
*/
|
||||
import type {
|
||||
AdminFormAction,
|
||||
@@ -20,7 +20,8 @@ import type {
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { useLocale } from "uview-pro";
|
||||
import { computed, ref } from "vue";
|
||||
import { useAdminPick, useAuthGuard } from "@/composables";
|
||||
import { useAuthGuard } from "@/composables";
|
||||
import { useActorPickConfig } from "@/composables/usePickerConfigs";
|
||||
import { SecurityUserActorViewEntity } from "@/data/auto/securityUserActorViewEntity";
|
||||
import { SecurityUserData } from "@/data/auto/securityUserData";
|
||||
import { usePagePermission } from "@/permission/permission-context";
|
||||
@@ -174,30 +175,31 @@ function onBack(): void {
|
||||
smartBack("mineTab");
|
||||
}
|
||||
|
||||
// 角色选择:跳 actor-enquiry(可多选),回传后按 ActorName 去重合并
|
||||
const actorPicker = useAdminPick<SecurityUserActorViewEntity>("actor");
|
||||
// 角色选择弹窗
|
||||
const actorConfig = useActorPickConfig();
|
||||
const showActorPicker = ref(false);
|
||||
|
||||
function onAddActor(): void {
|
||||
actorPicker.open(
|
||||
{ page: "actorEnquiry", params: { multiple: "1" } },
|
||||
(rows) => {
|
||||
const exists = new Set(
|
||||
data.value.SecurityUserActors.map(item => item.ActorName),
|
||||
);
|
||||
for (const row of rows) {
|
||||
const actorName = String(row.ActorName ?? "");
|
||||
if (!actorName || exists.has(actorName)) {
|
||||
continue;
|
||||
}
|
||||
const entity = new SecurityUserActorViewEntity();
|
||||
entity.UserName = String(user.value.UserName ?? "");
|
||||
entity.ActorName = actorName;
|
||||
entity.ActorLocalName = String(row.ActorLocalName ?? "");
|
||||
data.value.SecurityUserActors.push(entity);
|
||||
exists.add(actorName);
|
||||
}
|
||||
},
|
||||
showActorPicker.value = true;
|
||||
}
|
||||
|
||||
function onActorPicked(rows: any[]): void {
|
||||
const exists = new Set(
|
||||
data.value.SecurityUserActors.map(item => item.ActorName),
|
||||
);
|
||||
for (const row of rows) {
|
||||
const actorName = String(row.ActorName ?? "");
|
||||
if (!actorName || exists.has(actorName)) {
|
||||
continue;
|
||||
}
|
||||
const entity = new SecurityUserActorViewEntity();
|
||||
entity.UserName = String(user.value.UserName ?? "");
|
||||
entity.ActorName = actorName;
|
||||
entity.ActorLocalName = String(row.ActorLocalName ?? "");
|
||||
data.value.SecurityUserActors.push(entity);
|
||||
exists.add(actorName);
|
||||
}
|
||||
showActorPicker.value = false;
|
||||
}
|
||||
|
||||
function onDeleteActor(actorName: string): void {
|
||||
@@ -266,6 +268,12 @@ useAuthGuard(() => {
|
||||
</view>
|
||||
</template>
|
||||
</admin-form>
|
||||
|
||||
<!-- 弹窗选择器 -->
|
||||
<admin-pick-popup v-model:visible="showActorPicker" :title="t('UserPage.actorTitle')"
|
||||
:columns="actorConfig.columns.value" :loader="actorConfig.loader" :row-key="actorConfig.rowKey"
|
||||
:title-key="actorConfig.titleKey" :multiple="true" :fixed-filters="actorConfig.fixedFilters.value"
|
||||
@confirm="onActorPicked" @close="showActorPicker = false" />
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -336,7 +336,7 @@ function onRemoveGroup(familyName: string): void {
|
||||
<text class="seg-bar__text">{{ t(seg.labelKey) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<search-input v-if="showSearch" v-model="keyword" :placeholder="t('FilePage.searchPlaceholder')"
|
||||
<search-input v-if="showSearch" v-model="keyword" :placeholder="t('MediaPage.searchPlaceholder')"
|
||||
@search="onSearch" />
|
||||
</view>
|
||||
<view class="media-page__scroll-wrap">
|
||||
|
||||
@@ -320,7 +320,7 @@ function groupDesc(group: FamilyGroupEntity): string {
|
||||
<page-navbar :title="t('SharePage.title')" :show-back="false" :search-on="showSearch"
|
||||
:show-transfer="false" :show-quick-toggle="false" @back="onBack"
|
||||
@toggle-search="onToggleSearch" />
|
||||
<search-input v-if="showSearch" v-model="keyword" :placeholder="t('FilePage.searchPlaceholder')"
|
||||
<search-input v-if="showSearch" v-model="keyword" :placeholder="t('SharePage.searchPlaceholder')"
|
||||
@search="onSearch" />
|
||||
</view>
|
||||
<view class="share-page__scroll-wrap">
|
||||
|
||||
Reference in new issue
Block a user