From 282d8ce583dc5962f00290ce64e35a36b93ab18f Mon Sep 17 00:00:00 2001 From: owenchen Date: Sat, 17 Oct 2026 16:39:54 +0800 Subject: [PATCH] ow --- .../admin-pick-popup/admin-pick-popup.vue | 465 ++++++++++++++++++ .../src/composables/usePickerConfigs.ts | 380 ++++++++++++++ uniapp/youjiala/src/locale/lang/en-US.json | 6 +- uniapp/youjiala/src/locale/lang/zh-CN.json | 6 +- uniapp/youjiala/src/md/admin-pages.md | 26 +- .../src/pages/security/actor-enquiry.vue | 58 +-- .../src/pages/security/actor-operation.vue | 94 ++-- .../src/pages/security/function-enquiry.vue | 59 +-- .../src/pages/security/function-operation.vue | 111 +++-- .../src/pages/security/group-enquiry.vue | 49 +- .../src/pages/security/group-operation.vue | 159 +++--- .../pages/security/help-feature-enquiry.vue | 47 +- .../pages/security/help-function-enquiry.vue | 40 +- .../security/help-function-operation.vue | 84 ++-- .../security/permission-dependent-enquiry.vue | 44 +- .../src/pages/security/permission-enquiry.vue | 48 +- .../src/pages/security/user-enquiry.vue | 44 +- .../src/pages/security/user-operation.vue | 56 ++- uniapp/youjiala/src/pages/tab/media.vue | 2 +- uniapp/youjiala/src/pages/tab/share.vue | 2 +- 20 files changed, 1256 insertions(+), 524 deletions(-) create mode 100644 uniapp/youjiala/src/components/admin-pick-popup/admin-pick-popup.vue create mode 100644 uniapp/youjiala/src/composables/usePickerConfigs.ts diff --git a/uniapp/youjiala/src/components/admin-pick-popup/admin-pick-popup.vue b/uniapp/youjiala/src/components/admin-pick-popup/admin-pick-popup.vue new file mode 100644 index 0000000..44b725c --- /dev/null +++ b/uniapp/youjiala/src/components/admin-pick-popup/admin-pick-popup.vue @@ -0,0 +1,465 @@ + + + + + diff --git a/uniapp/youjiala/src/composables/usePickerConfigs.ts b/uniapp/youjiala/src/composables/usePickerConfigs.ts new file mode 100644 index 0000000..a144947 --- /dev/null +++ b/uniapp/youjiala/src/composables/usePickerConfigs.ts @@ -0,0 +1,380 @@ +/** + * 安全域"弹窗选择器"配置工厂:为 admin-pick-popup 提供 columns / loader / rowKey / titleKey。 + * + * 每个工厂对应一种被选实体,内部封装 service 调用与 criteria 构建。 + * fixedFilters 是一个响应式 ref,调用方在打开弹窗前动态设值(如 { dependent: "xxx" }), + * loader 会将其作为等值条件注入 criteria.Filter。 + * + * keyword 搜索统一映射到各实体的"主名称字段"(CONTAIN 模糊)。 + */ +import type { PickColumn } from "@/components/admin-pick-popup/admin-pick-popup.vue"; +import { useLocale } from "uview-pro"; +import { computed, ref } from "vue"; +import { SearchFilter } from "@/data/auto/searchFilter"; +import { SecurityActorEntity } from "@/data/auto/securityActorEntity"; +import { SecurityActorSearchCriteria } from "@/data/auto/securityActorSearchCriteria"; +import { SecurityFunctionDisplayData } from "@/data/auto/securityFunctionDisplayData"; +import { SecurityFunctionSearchCriteria } from "@/data/auto/securityFunctionSearchCriteria"; +import { SecurityGroupEntity } from "@/data/auto/securityGroupEntity"; +import { SecurityGroupSearchCriteria } from "@/data/auto/securityGroupSearchCriteria"; +import { SecurityHelpFeatureEntity } from "@/data/auto/securityHelpFeatureEntity"; +import { SecurityHelpFunctionSearchCriteria } from "@/data/auto/securityHelpFunctionSearchCriteria"; +import { SecurityPermissionDependentEntity } from "@/data/auto/securityPermissionDependentEntity"; +import { SecurityPermissionEntity } from "@/data/auto/securityPermissionEntity"; +import { SecurityPermissionSearchCriteria } from "@/data/auto/securityPermissionSearchCriteria"; +import { SecurityUserEntity } from "@/data/auto/securityUserEntity"; +import { SecurityUserSearchCriteria } from "@/data/auto/securityUserSearchCriteria"; +import { SearchFilterOperatorPolicy } from "@/data/custom/searchFilterOperatorPolicy"; +import { SearchFilterTypePolicy } from "@/data/custom/searchFilterTypePolicy"; +import securityActorService from "@/service/security/securityActorService"; +import securityFunctionService from "@/service/security/securityFunctionService"; +import securityGroupService from "@/service/security/securityGroupService"; +import securityHelpFunctionService from "@/service/security/securityHelpFunctionService"; +import securityPermissionService from "@/service/security/securityPermissionService"; +import securityUserService from "@/service/security/securityUserService"; + +/** 构建一条文本 CONTAIN 过滤 */ +function containFilter(column: string, value: string): SearchFilter { + const f = new SearchFilter(); + f.Column = column; + f.Type = SearchFilterTypePolicy.TEXT; + f.Operator = SearchFilterOperatorPolicy.CONTAIN; + f.Value = value; + return f; +} + +/** 构建一条等值过滤 */ +function equalFilter(column: string, value: string): SearchFilter { + const f = new SearchFilter(); + f.Column = column; + f.Type = SearchFilterTypePolicy.TEXT; + f.Operator = SearchFilterOperatorPolicy.EQUAL_TO; + f.Value = value; + return f; +} + +/** 通用返回值 */ +export interface PickerConfig { + columns: PickColumn[]; + loader: ( + page: number, + pageSize: number, + keyword: string, + fixedFilters: Record, + ) => Promise<{ rows: any[]; total: number }>; + rowKey: string; + titleKey: string; + fixedFilters: Record; +} + +// ===== Permission ===== +export function usePermissionPickConfig() { + const { t } = useLocale(); + const fixedFilters = ref>({}); + + const columns = computed(() => [ + { + label: t("PermissionPage.permissionName"), + prop: SecurityPermissionEntity.PERMISSION_NAME, + }, + { + label: t("PermissionPage.description"), + prop: SecurityPermissionEntity.DESCRIPTION, + }, + { + label: t("PermissionPage.dependent"), + prop: SecurityPermissionEntity.DEPENDENT, + }, + ]); + + async function loader(page: number, pageSize: number, keyword: string) { + const criteria = new SecurityPermissionSearchCriteria(); + criteria.GridColumns = []; + criteria.page = page; + criteria.limit = pageSize; + criteria.orderby = SecurityPermissionEntity.DB_PERMISSION_NAME; + const filters: SearchFilter[] = []; + if (keyword) { + filters.push( + containFilter(SecurityPermissionEntity.DB_PERMISSION_NAME, keyword), + ); + } + criteria.Filter = filters; + const data = await securityPermissionService.FindBySearchCriteria(criteria); + return { rows: data?.Permissions ?? [], total: data?.Total ?? 0 }; + } + + return { + columns, + loader, + rowKey: SecurityPermissionEntity.PERMISSION_NAME, + titleKey: SecurityPermissionEntity.PERMISSION_NAME, + fixedFilters, + }; +} + +// ===== Permission Dependent ===== +export function useDependentPickConfig() { + const { t } = useLocale(); + const fixedFilters = ref>({}); + + const columns = computed(() => [ + { + label: t("PermissionPage.dependentDetailName"), + prop: SecurityPermissionDependentEntity.DEPENDENT_DETAIL_NAME, + }, + { + label: t("PermissionPage.dependentDetailDescription"), + prop: SecurityPermissionDependentEntity.DEPENDENT_DETAIL_DESCRIPTION, + }, + ]); + + async function loader( + page: number, + pageSize: number, + keyword: string, + filters: Record, + ) { + const criteria = new SecurityPermissionSearchCriteria(); + criteria.GridColumns = []; + criteria.page = page; + criteria.limit = pageSize; + criteria.orderby = + SecurityPermissionDependentEntity.DB_DEPENDENT_DETAIL_NAME; + const filterList: SearchFilter[] = []; + // 固定过滤:按 dependent 等值(由调用方设定) + if (filters.dependent) { + filterList.push( + equalFilter( + SecurityPermissionDependentEntity.DB_DEPENDENT, + filters.dependent, + ), + ); + } + if (keyword) { + filterList.push( + containFilter( + SecurityPermissionDependentEntity.DB_DEPENDENT_DETAIL_NAME, + keyword, + ), + ); + } + criteria.Filter = filterList; + const data = + await securityPermissionService.FindDependentsBySearchCriteria(criteria); + return { rows: data?.Dependents ?? [], total: data?.Total ?? 0 }; + } + + return { + columns, + loader, + rowKey: SecurityPermissionDependentEntity.DEPENDENT_DETAIL_NAME, + titleKey: SecurityPermissionDependentEntity.DEPENDENT_DETAIL_NAME, + fixedFilters, + }; +} + +// ===== Actor ===== +export function useActorPickConfig() { + const { t } = useLocale(); + const fixedFilters = ref>({}); + + const columns = computed(() => [ + { + label: t("UserPage.actorLocalName"), + prop: SecurityActorEntity.ACTOR_LOCAL_NAME, + }, + { label: t("UserPage.actorName"), prop: SecurityActorEntity.ACTOR_NAME }, + ]); + + async function loader(page: number, pageSize: number, keyword: string) { + const criteria = new SecurityActorSearchCriteria(); + criteria.GridColumns = []; + criteria.page = page; + criteria.limit = pageSize; + const filters: SearchFilter[] = []; + if (keyword) { + filters.push( + containFilter(SecurityActorEntity.DB_ACTOR_LOCAL_NAME, keyword), + ); + } + criteria.Filter = filters; + const data = await securityActorService.FindBySearchCriteria(criteria); + return { rows: data?.Datas ?? [], total: data?.Total ?? 0 }; + } + + return { + columns, + loader, + rowKey: SecurityActorEntity.ACTOR_NAME, + titleKey: SecurityActorEntity.ACTOR_LOCAL_NAME, + fixedFilters, + }; +} + +// ===== Group ===== +export function useGroupPickConfig() { + const { t } = useLocale(); + const fixedFilters = ref>({}); + + const columns = computed(() => [ + { label: t("GroupPage.groupName"), prop: SecurityGroupEntity.GROUP_NAME }, + { + label: t("GroupPage.groupLocalName"), + prop: SecurityGroupEntity.GROUP_LOCAL_NAME, + }, + ]); + + async function loader(page: number, pageSize: number, keyword: string) { + const criteria = new SecurityGroupSearchCriteria(); + criteria.GridColumns = []; + criteria.page = page; + criteria.limit = pageSize; + criteria.orderby = SecurityGroupEntity.DB_GROUP_NAME; + const filters: SearchFilter[] = []; + if (keyword) { + filters.push(containFilter(SecurityGroupEntity.DB_GROUP_NAME, keyword)); + } + criteria.Filter = filters; + const data = await securityGroupService.FindBySearchCriteria(criteria); + return { rows: data?.Datas ?? [], total: data?.Total ?? 0 }; + } + + return { + columns, + loader, + rowKey: SecurityGroupEntity.GROUP_NAME, + titleKey: SecurityGroupEntity.GROUP_NAME, + fixedFilters, + }; +} + +// ===== User ===== +export function useUserPickConfig() { + const { t } = useLocale(); + const fixedFilters = ref>({}); + + const columns = computed(() => [ + { + label: t("UserPage.userLocalName"), + prop: SecurityUserEntity.USER_LOCAL_NAME, + }, + { label: t("UserPage.userName"), prop: SecurityUserEntity.USER_NAME }, + ]); + + async function loader(page: number, pageSize: number, keyword: string) { + const criteria = new SecurityUserSearchCriteria(); + criteria.GridColumns = []; + criteria.page = page; + criteria.limit = pageSize; + const filters: SearchFilter[] = []; + if (keyword) { + filters.push(containFilter(SecurityUserEntity.DB_USER_NAME, keyword)); + } + criteria.Filter = filters; + const data = await securityUserService.FindBySearchCriteria(criteria); + return { rows: data?.Datas ?? [], total: data?.Total ?? 0 }; + } + + return { + columns, + loader, + rowKey: SecurityUserEntity.USER_NAME, + titleKey: SecurityUserEntity.USER_LOCAL_NAME, + fixedFilters, + }; +} + +// ===== Function ===== +export function useFunctionPickConfig() { + const { t } = useLocale(); + const fixedFilters = ref>({}); + + const columns = computed(() => [ + { + label: t("FunctionPage.functionName"), + prop: SecurityFunctionDisplayData.FUNCTION_NAME, + }, + { + label: t("FunctionPage.functionLocalName"), + prop: SecurityFunctionDisplayData.FUNCTION_LOCAL_NAME, + }, + ]); + + async function loader( + page: number, + pageSize: number, + keyword: string, + filters: Record, + ) { + const criteria = new SecurityFunctionSearchCriteria(); + criteria.GridColumns = []; + criteria.page = page; + criteria.limit = pageSize; + criteria.orderby = SecurityFunctionDisplayData.DB_FUNCTION_NAME; + const filterList: SearchFilter[] = []; + if (keyword) { + filterList.push( + containFilter(SecurityFunctionDisplayData.DB_FUNCTION_NAME, keyword), + ); + } + // 固定过滤:按 FunctionIndc 等值(如 indc=N 只要目录、indc=Y 只要功能) + if (filters.indc) { + filterList.push( + equalFilter(SecurityFunctionDisplayData.DB_FUNCTION_INDC, filters.indc), + ); + } + criteria.Filter = filterList; + const data = await securityFunctionService.FindBySearchCriteria(criteria); + return { + rows: data?.SecurityFunctionDisplayDatas ?? [], + total: data?.Total ?? 0, + }; + } + + return { + columns, + loader, + rowKey: SecurityFunctionDisplayData.FUNCTION_NAME, + titleKey: SecurityFunctionDisplayData.FUNCTION_NAME, + fixedFilters, + }; +} + +// ===== Help Feature ===== +export function useHelpFeaturePickConfig() { + const { t } = useLocale(); + const fixedFilters = ref>({}); + + const columns = computed(() => [ + { label: t("HelpFeaturePage.name"), prop: SecurityHelpFeatureEntity.NAME }, + { + label: t("HelpFeaturePage.description"), + prop: SecurityHelpFeatureEntity.DESCRIPTION, + }, + ]); + + async function loader(page: number, pageSize: number, keyword: string) { + const criteria = new SecurityHelpFunctionSearchCriteria(); + criteria.GridColumns = []; + criteria.page = page; + criteria.limit = pageSize; + criteria.orderby = SecurityHelpFeatureEntity.DB_NAME; + const filters: SearchFilter[] = []; + if (keyword) { + filters.push(containFilter(SecurityHelpFeatureEntity.DB_NAME, keyword)); + } + criteria.Filter = filters; + const data = + await securityHelpFunctionService.FindFeatureBySearchCriteria(criteria); + return { rows: data?.Features ?? [], total: data?.Total ?? 0 }; + } + + return { + columns, + loader, + rowKey: SecurityHelpFeatureEntity.NAME, + titleKey: SecurityHelpFeatureEntity.NAME, + fixedFilters, + }; +} diff --git a/uniapp/youjiala/src/locale/lang/en-US.json b/uniapp/youjiala/src/locale/lang/en-US.json index a2208b6..2020f2b 100644 --- a/uniapp/youjiala/src/locale/lang/en-US.json +++ b/uniapp/youjiala/src/locale/lang/en-US.json @@ -545,6 +545,7 @@ }, "SharePage": { "title": "Family Groups", + "searchPlaceholder": "Search group name", "createTitle": "Create Group", "noAccess": "This group is private and you are not a member", "unnamed": "Unnamed", @@ -599,6 +600,7 @@ }, "MediaPage": { "title": "Media", + "searchPlaceholder": "Search album name", "createTitle": "New Album", "segPhoto": "Photos", "segAudio": "Music", @@ -690,7 +692,9 @@ "menuSection": "Features", "menuEmptyText": "The server returned no authorized function", "loadingTip": "Loading…", - "savingTip": "Saving…" + "savingTip": "Saving…", + "pickLoadingMore": "Pull up for more…", + "pickNoMore": "— No more —" }, "UserPage": { "title": "User Query", diff --git a/uniapp/youjiala/src/locale/lang/zh-CN.json b/uniapp/youjiala/src/locale/lang/zh-CN.json index d4c18e0..f7bc086 100644 --- a/uniapp/youjiala/src/locale/lang/zh-CN.json +++ b/uniapp/youjiala/src/locale/lang/zh-CN.json @@ -545,6 +545,7 @@ }, "SharePage": { "title": "家庭群组", + "searchPlaceholder": "搜索群组名称", "createTitle": "创建群组", "noAccess": "该群组为私密,您还不是成员", "unnamed": "未命名", @@ -599,6 +600,7 @@ }, "MediaPage": { "title": "多媒体", + "searchPlaceholder": "搜索专辑名称", "createTitle": "新建专辑", "segPhoto": "相册", "segAudio": "音乐", @@ -690,7 +692,9 @@ "menuSection": "功能菜单", "menuEmptyText": "后端没有返回你有权限的功能", "loadingTip": "加载中…", - "savingTip": "保存中…" + "savingTip": "保存中…", + "pickLoadingMore": "上拉加载更多…", + "pickNoMore": "— 没有更多了 —" }, "UserPage": { "title": "用户查询", diff --git a/uniapp/youjiala/src/md/admin-pages.md b/uniapp/youjiala/src/md/admin-pages.md index aaeca49..3a6bcfb 100644 --- a/uniapp/youjiala/src/md/admin-pages.md +++ b/uniapp/youjiala/src/md/admin-pages.md @@ -14,15 +14,15 @@ - **保留** `bindOption` 数据模型(后端列名 / `Type` / `Operator` / `SelectOptions`)与查询语义(分页、条件、`orderby`),因为后端 `FindBySearchCriteria` 吃的就是这个形状; - **砍掉** 多列网格、列配置、打印、排序表头——手机没有对应交互; -- **重写** 列表为卡片流、详情为单列卡、选择为"真跳一页再回传"。 +- **重写** 列表为卡片流、详情为单列卡、选择为"页内底部弹窗"(`admin-pick-popup`,见 §3.3)。 复用分三层,边界清楚,换域移植(Group/Function/Dms/Publish…)时机械部分零改动: | 层 | 文件 | 认识什么 | 不认识什么 | | --- | --- | --- | --- | | 纯函数 | `admin/admin-filter.ts`、`admin-date.ts`、`admin-column.ts`、`admin-types.ts` | SearchFilter / BindOption / 日期口径 | vue、uni、service | -| composable | `useAdminList`、`useAdminPick`、`useAdminMenu` | 上面那层 + vue 响应式 | z-paging、service、权限名 | -| 组件 | `admin-list`、`admin-form`、`admin-filter-drawer` | z-paging + uview-pro | service、**权限** | +| composable | `useAdminList`、`useAdminPick`、`usePickerConfigs`、`useAdminMenu` | 上面那层 + vue 响应式 | z-paging、service、权限名 | +| 组件 | `admin-list`、`admin-form`、`admin-filter-drawer`、`admin-pick-popup` | z-paging / u-popup + uview-pro | service、**权限** | **组件不判权限**:按钮由页面按 `canCreate/canAmend/canDelete` 组好数组(详情)或用 `v-if`(列表工具条)传进来。这样公共组件不需要知道任何一个域的权限名。 @@ -34,7 +34,7 @@ | --- | --- | --- | --- | | `userEnquiry` | `pages/security/user-enquiry` | `UserEnquiry.vue` | 用户列表:三条筛选(用户名/中文名/创建日期区间)、每页 20、按创建日期倒序、行点进详情、多选批量作废 | | `userOperation` | `pages/security/user-operation` | `UserOperation.vue` | 用户详情:查看/新增/修改,`?id=&mode=`;角色明细在 `#extra` 插槽自绘 | -| `actorEnquiry` | `pages/security/actor-enquiry` | `ActorEnquiry.vue` | 角色查询,**双用途**(见 §3.3) | +| `actorEnquiry` | `pages/security/actor-enquiry` | `ActorEnquiry.vue` | 角色查询,纯列表页(选角色改由调用方弹窗,见 §3.3) | | `dashboard` | `pages/dashboard/dashboard` | `layout` 菜单 | 入口九宫格,`FindMenuByUsername` 驱动(见 §5) | 列表页写法(`user-enquiry.vue` 为准):`reactive(bindOptions)` + 一个只碰具体 service 的 `fetchData(query)` 交给 `useAdminList`;解构出的 `filterCount/filterVisible/draft/searchToken` 是 ref/computed,模板自动 unwrap,方法仍走 `state.xxx`。取数排在 `useAuthGuard` 之后(`admin-list` 的 `auto` 默认 false,首屏手动 `listRef.refresh()` 一次)。 @@ -53,16 +53,20 @@ ### 3.2 user-operation 的取数与保存 `onLoad` 读 `id`(=`UserName`)与 `mode`;`FindByKey` 取 `SecurityUserData`,取不到提示"记录不存在"。保存按有无 `CreatedBy` 决定 `Update`/`Insert`,成功后用后端回写的档案刷新、回填主键、退回只读。密码编辑的是 `SecurityUserDisplayData.OrgUserPassword`(留空即不改),只在编辑态出现。 -### 3.3 选择页回传协议(useAdminPick / useAdminPickTarget) -旧系统的"选角色"是 Operation 用 `` 内嵌 Enquiry + `provide/inject`。移动端改成**真跳一页再回传**: +### 3.3 选择器:`admin-pick-popup` 页内底部弹窗 +旧系统的"选角色/选权限/选功能"是 Operation 用 `` 内嵌 Enquiry + `provide/inject`。移动端第一版改成"真跳一页再回传",但多数选择页 `show-nav-back=false` 且没有取消按钮,用户进去就退不出来。现已改为**页内弹窗**: -- 调用方 `useAdminPick(channel).open({ page, params }, onPicked)`——先退订再订阅,`onUnmounted` 兜底清理; -- 目标页(`actor-enquiry`)`useAdminPickTarget()` 在 `onLoad` 里 `readOptions(options)` 存下 `channel`/`multiple`,确定时 `deliver(rows)`(`uni.$emit('admin:pick:'+channel, rows)` + `navigateBack`); -- `actor-enquiry` 因此**同一个列表两种用法**:菜单进入(无 `channel`)是普通查询;被带 `?channel=&multiple=1` 打开就是选择器,单选点行即回传、多选底部"完成"批量回传。 +- 组件 `components/admin-pick-popup/admin-pick-popup.vue`:`u-popup mode="bottom"`(80vh)+ `scroll-view` 手动分页(**不能用 z-paging**:它默认 `position:fixed` 撑满视口,在弹层内会打架); +- Props `visible / title / columns / loader / rowKey / titleKey / multiple / fixedFilters / pageSize`,Emits `update:visible / close / confirm(rows)`; +- 数据源在 `composables/usePickerConfigs.ts`:每个被选数据一个工厂函数(`usePermissionPickConfig`、`useDependentPickConfig`、`useActorPickConfig`、`useGroupPickConfig`、`useUserPickConfig`、`useFunctionPickConfig`、`useHelpFeaturePickConfig`),返回 `{ columns, loader, rowKey, titleKey, fixedFilters }`; +- 调用方只需 `const xxxConfig = useXxxPickConfig(); const showXxxPicker = ref(false);`,点入口置 `true`,`@confirm` 里做原来的去重合并逻辑。需要动态过滤(如扩展权限按 `dependent`)时写 `xxxConfig.fixedFilters.value = { dependent }`; +- 单选点行即 `confirm` + 关闭;多选勾选后点确定;X / 遮罩 / 取消三条退路都通。 -**协议参数一律不做 `encodeURIComponent`**:H5 侧 uni/vue-router 拼 URL 用 `encodeURI`,预编码会把 `%` 再编成 `%25`。`channel` 与 `params` 的值只允许字母/数字/下划线/连字符/点/斜杠。 +**security 域的 enquiry 页因此回归纯列表页**:`isPick` / `pickTarget` / `onLoad(channel)` / `deliver()` 全部删除,`:show-nav-back="true"` 恒定,`+` 新增入口不再被选择器态隐藏。 -> 命名订正:这个页面就叫 `actor-enquiry`(旧系统本是 `ActorEnquiry.vue`),早期草稿里的 `actor-pick` 是造错的概念——"选择"只是它带 `channel` 打开时的一种模式,不是另一张页面。 +`useAdminPick` / `useAdminPickTarget` 机制本身**保留**:`family-person-enquiry` 仍作为「族员选择器」被首页 dashboard 以 `?channel=person` 调起。那条老路子的协议参数一律不做 `encodeURIComponent`(H5 侧 uni/vue-router 拼 URL 用 `encodeURI`,预编码会把 `%` 再编成 `%25`)。 + +> 命名订正:`actor-enquiry` 就是旧 `ActorEnquiry.vue` 的移植,早期草稿里的 `actor-pick` 是造错的概念——它现在只是普通查询页,选择能力在调用方的弹窗里。 --- diff --git a/uniapp/youjiala/src/pages/security/actor-enquiry.vue b/uniapp/youjiala/src/pages/security/actor-enquiry.vue index b8e1d24..123810c 100644 --- a/uniapp/youjiala/src/pages/security/actor-enquiry.vue +++ b/uniapp/youjiala/src/pages/security/actor-enquiry.vue @@ -2,20 +2,16 @@ /** * 角色查询(ActorEnquiry):旧 WebVue views/security/ActorEnquiry.vue 的移动端等价物 * - * 它有两种打开方式,同一套列表: - * 1. 从菜单进(无 channel):普通查询页(点行看详情,右上可新增、长按多选可批量删除); - * 2. 被 user-operation 当"角色选择器"跳进来(带 ?channel=&multiple=1): - * 选完 uni.$emit 回传再 navigateBack(见 useAdminPick / useAdminPickTarget 协议)。 - * - * 旧系统里这个选择能力是 Operation 用 内嵌 Enquiry + provide/inject 实现的; - * 移动端页面之间没有 provide/inject,只能真跳一页再回传,所以这个页面本身就是 Enquiry。 + * 普通查询页:点行看详情,右上可新增、多选可批量删除。 + * 旧系统里 user-operation 用 内嵌本页做"角色选择器"; + * 移动端的弹窗选择已由 user-operation 内嵌 实现, + * 本页不再承担选择器职责(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 { }); } -onLoad((options) => { - pickTarget.readOptions(options); - isPick.value = String(options?.channel ?? "").trim().length > 0; -}); - useAuthGuard(() => { // 每次显示都重拉第一页:增/改/删后从详情返回能看到最新数据(navigateBack 不重新挂页面) nextTick(() => listRef.value?.refresh()); @@ -135,23 +106,20 @@ useAuthGuard(() => {