Commit cd0dd754 authored by drigle's avatar drigle

feat: make process list names clickable

parent 06524564
...@@ -66,7 +66,8 @@ export default defineConfig({ ...@@ -66,7 +66,8 @@ export default defineConfig({
npmClient: 'pnpm', npmClient: 'pnpm',
proxy: { proxy: {
'/api': { '/api': {
target: 'https://xy.streams7.com/api', // target: 'https://xy.streams7.com/api',
target: 'http://127.0.0.1:3000/',
changeOrigin: true, changeOrigin: true,
pathRewrite: { '^/api': '' }, pathRewrite: { '^/api': '' },
secure: false, secure: false,
......
{ {
"name": "oa_process_monitor", "name": "oa_process_monitor",
"version": "1.0.3", "version": "1.0.4",
"build": "abc", "build": "abc",
"description": "merge master", "description": "oa 流程监控",
"date": "2025-07-14 19:27:20", "date": "2025-07-14 19:27:20",
"author": "yang", "author": "yang",
"spa": true "spa": true
......
...@@ -2,7 +2,7 @@ import { useAuthorization } from '@/hooks/user'; ...@@ -2,7 +2,7 @@ import { useAuthorization } from '@/hooks/user';
import { Check, Close, DataStore, Delete, Edit, Eye, FileText, FilterControls, FolderOpen, PlusIcon, Search, Team } from '@/components/AppIcons'; import { Check, Close, DataStore, Delete, Edit, Eye, FileText, FilterControls, FolderOpen, PlusIcon, Search, Team } from '@/components/AppIcons';
import { TableActionButton, TableActionGroup } from '@/components/TableActionButton'; import { TableActionButton, TableActionGroup } from '@/components/TableActionButton';
import XinyuanAutocomplete from '@/components/XinyuanAutocomplete'; import XinyuanAutocomplete from '@/components/XinyuanAutocomplete';
import { Alert, AlertDialog, Button, Checkbox, Input, Label, Modal, Pagination, Popover, SearchField, Surface, Tabs, Tooltip, toast } from '@heroui/react'; import { Alert, AlertDialog, Button, Checkbox, Input, Label, Link, Modal, Pagination, Popover, SearchField, Surface, Tabs, Tooltip, toast } from '@heroui/react';
import { DataGrid } from '@heroui-pro/react/data-grid'; import { DataGrid } from '@heroui-pro/react/data-grid';
import { EmptyState } from '@heroui-pro/react/empty-state'; import { EmptyState } from '@heroui-pro/react/empty-state';
import { KPI } from '@heroui-pro/react/kpi'; import { KPI } from '@heroui-pro/react/kpi';
...@@ -196,7 +196,7 @@ export default function ProcessMonitorPage() { ...@@ -196,7 +196,7 @@ export default function ProcessMonitorPage() {
const listColumns = useMemo(() => { const listColumns = useMemo(() => {
const columns = [ const columns = [
{ id: 'title', header: '模板名称', isRowHeader: true, width: '1fr', minWidth: 220, allowsResizing: false, cell: (template) => <span className="pm-data-grid-text">{template.title}</span> }, { id: 'title', header: '模板名称', isRowHeader: true, width: '1fr', minWidth: 220, allowsResizing: false, cell: (template) => <Link className="max-w-full min-w-0 truncate" title={template.title} onPress={() => navigate(`/process_monitor/${template._id}?tab=${activeGroup?.name || ''}`)}>{template.title}</Link> },
{ id: 'department', header: '所属部门', width: 180, minWidth: 160, allowsResizing: false, cell: (item) => <span className="pm-data-grid-text">{item?.metadata?.department || '-'}</span> }, { id: 'department', header: '所属部门', width: 180, minWidth: 160, allowsResizing: false, cell: (item) => <span className="pm-data-grid-text">{item?.metadata?.department || '-'}</span> },
{ id: 'templateCode', header: '模板编码', width: 200, minWidth: 180, allowsResizing: false, cell: (item) => <span className="pm-data-grid-text">{item?.metadata?.template_code || '-'}</span> }, { id: 'templateCode', header: '模板编码', width: 200, minWidth: 180, allowsResizing: false, cell: (item) => <span className="pm-data-grid-text">{item?.metadata?.template_code || '-'}</span> },
{ id: 'condition', header: '显示条件', width: 220, minWidth: 190, allowsResizing: false, cell: (item) => <span className="pm-data-grid-text">{item?.metadata?.conditions?.key ? `${item.metadata.conditions.key} = ${item.metadata.conditions.value || '-'}` : '-'}</span> }, { id: 'condition', header: '显示条件', width: 220, minWidth: 190, allowsResizing: false, cell: (item) => <span className="pm-data-grid-text">{item?.metadata?.conditions?.key ? `${item.metadata.conditions.key} = ${item.metadata.conditions.value || '-'}` : '-'}</span> },
......
...@@ -2,7 +2,7 @@ import { Close, DataStore, Delete, Eye, FieldTime, FileText, Filter, FolderOpen, ...@@ -2,7 +2,7 @@ import { Close, DataStore, Delete, Eye, FieldTime, FileText, Filter, FolderOpen,
import { TableActionButton, TableActionGroup } from '@/components/TableActionButton'; import { TableActionButton, TableActionGroup } from '@/components/TableActionButton';
import { TitleInfo } from '@/components/XinyuanUi'; import { TitleInfo } from '@/components/XinyuanUi';
import XinyuanAutocomplete from '@/components/XinyuanAutocomplete'; import XinyuanAutocomplete from '@/components/XinyuanAutocomplete';
import { Alert, Button, Input, Label, Modal, Pagination, SearchField, Tooltip, toast } from '@heroui/react'; import { Alert, Button, Input, Label, Link, Modal, Pagination, SearchField, Tooltip, toast } from '@heroui/react';
import { DataGrid } from '@heroui-pro/react/data-grid'; import { DataGrid } from '@heroui-pro/react/data-grid';
import { EmptyState } from '@heroui-pro/react/empty-state'; import { EmptyState } from '@heroui-pro/react/empty-state';
import { KPI } from '@heroui-pro/react/kpi'; import { KPI } from '@heroui-pro/react/kpi';
...@@ -132,7 +132,11 @@ export default function ProcessTemplateListPage() { ...@@ -132,7 +132,11 @@ export default function ProcessTemplateListPage() {
const lookups = useMemo(() => ({ memberLookup: buildMemberLookup(members), departmentLookup: buildDepartmentLookup(departments) }), [departments, members]); const lookups = useMemo(() => ({ memberLookup: buildMemberLookup(members), departmentLookup: buildDepartmentLookup(departments) }), [departments, members]);
const totalPages = Math.max(Math.ceil(total / pageSize), 1); const totalPages = Math.max(Math.ceil(total / pageSize), 1);
const instanceColumns = useMemo(() => [ const instanceColumns = useMemo(() => [
{ id: 'title', header: '表单名称', isRowHeader: true, width: '1fr', minWidth: 220, allowsResizing: false, pinned: 'start', cell: (record) => <span className="pm-data-grid-primary">{record.title}</span> }, { id: 'title', header: '表单名称', isRowHeader: true, width: '1fr', minWidth: 220, allowsResizing: false, pinned: 'start', cell: (record) => <Link className="max-w-full min-w-0 truncate" title={record.title} onPress={() => {
if (!record?._id) return;
const tabQuery = tabName ? `?tab=${encodeURIComponent(tabName)}` : '';
navigate(`/process_monitor/${processId}/${record._id}${tabQuery}`);
}}>{record.title}</Link> },
...fieldsDefinition.map((field) => ({ id: `${field.display_name}-${field.type}`, header: field.display_name, width: 220, minWidth: 180, allowsResizing: false, cell: (record) => <span className="pm-data-grid-text">{renderFieldValue(field, record, lookups)}</span> })), ...fieldsDefinition.map((field) => ({ id: `${field.display_name}-${field.type}`, header: field.display_name, width: 220, minWidth: 180, allowsResizing: false, cell: (record) => <span className="pm-data-grid-text">{renderFieldValue(field, record, lookups)}</span> })),
{ id: 'actions', header: '操作', width: 80, minWidth: 80, maxWidth: 80, allowsResizing: false, align: 'start', pinned: 'end', cell: (record) => <TableActionGroup><TableActionButton icon={Eye} label="查看" onPress={() => { { id: 'actions', header: '操作', width: 80, minWidth: 80, maxWidth: 80, allowsResizing: false, align: 'start', pinned: 'end', cell: (record) => <TableActionGroup><TableActionButton icon={Eye} label="查看" onPress={() => {
if (!record?._id) return; if (!record?._id) return;
......
...@@ -91,7 +91,7 @@ Shell 中的应用切换入口继续读取当前登录用户可访问应用, ...@@ -91,7 +91,7 @@ Shell 中的应用切换入口继续读取当前登录用户可访问应用,
- 管理角色可从分组 Tabs 同行的“删除分组”入口删除当前空分组;有关联监控模板的分组必须先逐个取消监控,不执行级联删除 - 管理角色可从分组 Tabs 同行的“删除分组”入口删除当前空分组;有关联监控模板的分组必须先逐个取消监控,不执行级联删除
- 通过 `sync_progress:get_template_list` 获取可加入监控的模板库 - 通过 `sync_progress:get_template_list` 获取可加入监控的模板库
- 在当前分组下展示 `metadata.progresses` 关联的监控模板 - 在当前分组下展示 `metadata.progresses` 关联的监控模板
- 模板名称列仅展示模板标题文本,不在标题下方展示外部模板 ID;外部模板 ID 仍保留在 `metadata.external_id` 中用于模板关联和去重。通过操作列的“查看”图标进入模板实例列表;管理角色在其后继续使用编辑和取消监控操作 - 模板名称列展示为 HeroUI 链接,点击后与操作列“查看”图标进入同一模板实例列表;标题超长时省略展示并保留完整标题提示。列标题下方不展示外部模板 ID;外部模板 ID 仍保留在 `metadata.external_id` 中用于模板关联和去重。管理角色在操作列继续使用编辑和取消监控操作
- 按模板标题和所属部门筛选当前分组模板 - 按模板标题和所属部门筛选当前分组模板
- “所属部门”以同名 HeroUI Popover 入口收纳在模板列表工具栏中,按需展开且不单独占用筛选 Surface;弹窗内标签独占一行,选择器与重置按钮同行,选择和重置仍沿用原有实时过滤状态 - “所属部门”以同名 HeroUI Popover 入口收纳在模板列表工具栏中,按需展开且不单独占用筛选 Surface;弹窗内标签独占一行,选择器与重置按钮同行,选择和重置仍沿用原有实时过滤状态
- 管理角色可执行: - 管理角色可执行:
...@@ -133,7 +133,7 @@ Shell 中的应用切换入口继续读取当前登录用户可访问应用, ...@@ -133,7 +133,7 @@ Shell 中的应用切换入口继续读取当前登录用户可访问应用,
列表交互: 列表交互:
- 使用 HeroUI Pro DataGrid 生成动态列并承载选择状态 - 使用 HeroUI Pro DataGrid 生成动态列并承载选择状态
- 表单名称列仅展示文本,通过操作列的“查看”图标进入 `/process_monitor/:processId/:application` 独立流程实例详情页;顶部 Navbar 面包屑显示“流程监控 / 实例列表 / 流程详情”,前级节点可点击返回 - 表单名称列展示为 HeroUI 链接,点击后与操作列“查看”图标进入 `/process_monitor/:processId/:application` 独立流程实例详情页;标题超长时省略展示并保留完整标题提示。顶部 Navbar 面包屑显示“流程监控 / 实例列表 / 流程详情”,前级节点可点击返回
- Pagination 保留原有页码语义和 `page` / `page_size` 请求参数,条数选择器支持 20/50/100 条,宽度为 128px - Pagination 保留原有页码语义和 `page` / `page_size` 请求参数,条数选择器支持 20/50/100 条,宽度为 128px
- 有选中记录时由 HeroUI Pro ActionBar 承载批量附件下载;空数据使用 HeroUI Pro EmptyState - 有选中记录时由 HeroUI Pro ActionBar 承载批量附件下载;空数据使用 HeroUI Pro EmptyState
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment