|
|
@@ -133,6 +133,50 @@
|
|
|
</template>
|
|
|
</Card>
|
|
|
|
|
|
+ <!-- 工作流模块 -->
|
|
|
+ <Card>
|
|
|
+ <template #header>
|
|
|
+ <view class="workflow-header">
|
|
|
+ <text class="workflow-icon">🔄</text>
|
|
|
+ <text class="card-title">工作流</text>
|
|
|
+ </view>
|
|
|
+ </template>
|
|
|
+ <template #default>
|
|
|
+ <view class="workflow-tabs">
|
|
|
+ <view
|
|
|
+ v-for="tab in workflowTabs"
|
|
|
+ :key="tab.key"
|
|
|
+ class="workflow-tab"
|
|
|
+ :class="{ active: activeWorkflowTab === tab.key }"
|
|
|
+ @click="handleWorkflowTabClick(tab.key)"
|
|
|
+ >
|
|
|
+ <text class="tab-icon">{{ tab.icon }}</text>
|
|
|
+ <text class="tab-text">{{ tab.label }}</text>
|
|
|
+ <view v-if="tab.badge > 0" class="tab-badge">
|
|
|
+ <text class="tab-badge-text">{{ tab.badge }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 我发起的内容 -->
|
|
|
+ <view v-if="activeWorkflowTab === 'initiated'" class="workflow-content">
|
|
|
+ <view class="workflow-empty">
|
|
|
+ <u-button type="primary" @click="gotoInitiatedList">
|
|
|
+ 查看我发起的流程
|
|
|
+ </u-button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 其他标签页内容(暂时显示占位) -->
|
|
|
+ <view v-else class="workflow-placeholder">
|
|
|
+ <text class="placeholder-icon">🚧</text>
|
|
|
+ <text class="placeholder-text">
|
|
|
+ {{ getTabName(activeWorkflowTab) }}功能开发中
|
|
|
+ </text>
|
|
|
+ </view>
|
|
|
+ </template>
|
|
|
+ </Card>
|
|
|
+
|
|
|
<!-- 快捷功能 -->
|
|
|
<Card>
|
|
|
<template #header>
|
|
|
@@ -169,6 +213,7 @@ import GridLayout from '@/components/GridLayout.vue';
|
|
|
import { userStorage } from '@/utils/request';
|
|
|
import { userManager, userState } from '@/utils/user';
|
|
|
import { guardedSwitchTab } from '@/utils/route-guard';
|
|
|
+import { workflowApi, getStatusStyle, formatTime, routerJump } from '@/utils/workflow-api';
|
|
|
|
|
|
export default {
|
|
|
name: 'HomePage',
|
|
|
@@ -279,12 +324,32 @@ export default {
|
|
|
{ title: '校历', icon: '📅' },
|
|
|
{ title: '帮助', icon: '❓' },
|
|
|
],
|
|
|
+ // 工作流相关数据
|
|
|
+ workflowTabs: [
|
|
|
+ { key: 'initiated', label: '我发起的', icon: '📝', badge: 0 },
|
|
|
+ { key: 'todo', label: '我的待办', icon: '⏰', badge: 0 },
|
|
|
+ { key: 'finished', label: '我的已办', icon: '✅', badge: 0 },
|
|
|
+ { key: 'copy', label: '我的抄送', icon: '📋', badge: 0 },
|
|
|
+ ],
|
|
|
+ activeWorkflowTab: 'initiated',
|
|
|
+ workflowList: [],
|
|
|
+ workflowLoading: false,
|
|
|
+ workflowQuery: {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ flowCode: '',
|
|
|
+ category: '',
|
|
|
+ },
|
|
|
+ categoryList: [],
|
|
|
+ showCategories: false,
|
|
|
+ hasMore: true,
|
|
|
};
|
|
|
},
|
|
|
onLoad() {
|
|
|
this.checkLoginStatus();
|
|
|
this.updateDateTime();
|
|
|
this.startTimeUpdate();
|
|
|
+ this.loadWorkflowData();
|
|
|
},
|
|
|
onUnload() {
|
|
|
if (this.timeTimer) {
|
|
|
@@ -359,6 +424,282 @@ export default {
|
|
|
viewAllNews() {
|
|
|
uni.showToast({ title: '查看全部动态', icon: 'none' });
|
|
|
},
|
|
|
+
|
|
|
+ // 工作流相关方法
|
|
|
+ switchWorkflowTab(tab) {
|
|
|
+ this.activeWorkflowTab = tab;
|
|
|
+ this.workflowQuery.pageNum = 1;
|
|
|
+ this.workflowList = [];
|
|
|
+ this.hasMore = true;
|
|
|
+
|
|
|
+ if (tab === 'initiated') {
|
|
|
+ this.loadWorkflowData();
|
|
|
+ } else {
|
|
|
+ // 其他标签页暂时不加载数据
|
|
|
+ uni.showToast({ title: this.getTabName(tab) + '功能开发中', icon: 'none' });
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ async loadWorkflowData() {
|
|
|
+ if (this.workflowLoading) return;
|
|
|
+
|
|
|
+ this.workflowLoading = true;
|
|
|
+ try {
|
|
|
+ const response = await workflowApi.pageByCurrent(this.workflowQuery);
|
|
|
+
|
|
|
+ if (response.code === 200) {
|
|
|
+ const newData = response.rows || [];
|
|
|
+
|
|
|
+ if (this.workflowQuery.pageNum === 1) {
|
|
|
+ this.workflowList = newData;
|
|
|
+ } else {
|
|
|
+ this.workflowList = [...this.workflowList, ...newData];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否还有更多数据
|
|
|
+ this.hasMore = newData.length === this.workflowQuery.pageSize;
|
|
|
+
|
|
|
+ // 更新待办数量徽章
|
|
|
+ this.updateWorkflowBadges();
|
|
|
+ } else {
|
|
|
+ uni.showToast({
|
|
|
+ title: response.msg || '加载失败',
|
|
|
+ icon: 'error',
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('加载工作流数据失败:', error);
|
|
|
+ uni.showToast({
|
|
|
+ title: '网络错误',
|
|
|
+ icon: 'error',
|
|
|
+ });
|
|
|
+ } finally {
|
|
|
+ this.workflowLoading = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ async loadCategoryData() {
|
|
|
+ try {
|
|
|
+ const response = await workflowApi.categoryTree();
|
|
|
+ if (response.code === 200) {
|
|
|
+ this.categoryList = response.data || [];
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('加载分类数据失败:', error);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ loadMoreWorkflow() {
|
|
|
+ if (!this.hasMore || this.workflowLoading) return;
|
|
|
+
|
|
|
+ this.workflowQuery.pageNum += 1;
|
|
|
+ this.loadWorkflowData();
|
|
|
+ },
|
|
|
+
|
|
|
+ handleWorkflowSearch() {
|
|
|
+ this.workflowQuery.pageNum = 1;
|
|
|
+ this.workflowList = [];
|
|
|
+ this.hasMore = true;
|
|
|
+ this.loadWorkflowData();
|
|
|
+ },
|
|
|
+
|
|
|
+ showCategoryFilter() {
|
|
|
+ this.showCategories = !this.showCategories;
|
|
|
+ if (this.showCategories && this.categoryList.length === 0) {
|
|
|
+ this.loadCategoryData();
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ selectCategory(categoryId) {
|
|
|
+ this.workflowQuery.category = categoryId;
|
|
|
+ this.showCategories = false;
|
|
|
+ this.handleWorkflowSearch();
|
|
|
+ },
|
|
|
+
|
|
|
+ // 保证 handleWorkflowItemClick 统一跳转详情
|
|
|
+ handleWorkflowItemClick(item) {
|
|
|
+ this.handleView(item);
|
|
|
+ },
|
|
|
+
|
|
|
+ handleEdit(item) {
|
|
|
+ const routerJumpVo = {
|
|
|
+ businessId: item.businessId,
|
|
|
+ taskId: item.id,
|
|
|
+ type: 'update',
|
|
|
+ formCustom: item.formCustom,
|
|
|
+ formPath: item.formPath,
|
|
|
+ };
|
|
|
+ routerJump(routerJumpVo);
|
|
|
+ },
|
|
|
+
|
|
|
+ handleView(item) {
|
|
|
+ const routerJumpVo = {
|
|
|
+ businessId: item.businessId,
|
|
|
+ taskId: item.id,
|
|
|
+ type: 'view',
|
|
|
+ formCustom: item.formCustom,
|
|
|
+ formPath: item.formPath,
|
|
|
+ };
|
|
|
+ // 直接使用 uni.navigateTo 跳转到新页面
|
|
|
+ const params = Object.keys(routerJumpVo)
|
|
|
+ .filter((key) => routerJumpVo[key] !== undefined && routerJumpVo[key] !== null)
|
|
|
+ .map((key) => `${key}=${encodeURIComponent(routerJumpVo[key])}`)
|
|
|
+ .join('&');
|
|
|
+ uni.navigateTo({
|
|
|
+ url: `/pages/workflow/process?${params}`,
|
|
|
+ fail: () => {
|
|
|
+ uni.showToast({
|
|
|
+ title: '页面跳转失败',
|
|
|
+ icon: 'error',
|
|
|
+ });
|
|
|
+ },
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ async handleDelete(item) {
|
|
|
+ try {
|
|
|
+ const confirmed = await this.showConfirm('确认删除', '是否确认删除该工作流?');
|
|
|
+ if (!confirmed) return;
|
|
|
+
|
|
|
+ const response = await workflowApi.deleteByInstanceIds([item.id]);
|
|
|
+ if (response.code === 200) {
|
|
|
+ uni.showToast({
|
|
|
+ title: '删除成功',
|
|
|
+ icon: 'success',
|
|
|
+ });
|
|
|
+ this.handleWorkflowSearch();
|
|
|
+ } else {
|
|
|
+ uni.showToast({
|
|
|
+ title: response.msg || '删除失败',
|
|
|
+ icon: 'error',
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('删除失败:', error);
|
|
|
+ uni.showToast({
|
|
|
+ title: '删除失败',
|
|
|
+ icon: 'error',
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ async handleCancel(item) {
|
|
|
+ try {
|
|
|
+ const confirmed = await this.showConfirm('确认撤销', '是否确认撤销该工作流?');
|
|
|
+ if (!confirmed) return;
|
|
|
+
|
|
|
+ const data = {
|
|
|
+ businessId: item.businessId,
|
|
|
+ message: '申请人撤销流程!',
|
|
|
+ };
|
|
|
+
|
|
|
+ const response = await workflowApi.cancelProcessApply(data);
|
|
|
+ if (response.code === 200) {
|
|
|
+ uni.showToast({
|
|
|
+ title: '撤销成功',
|
|
|
+ icon: 'success',
|
|
|
+ });
|
|
|
+ this.handleWorkflowSearch();
|
|
|
+ } else {
|
|
|
+ uni.showToast({
|
|
|
+ title: response.msg || '撤销失败',
|
|
|
+ icon: 'error',
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('撤销失败:', error);
|
|
|
+ uni.showToast({
|
|
|
+ title: '撤销失败',
|
|
|
+ icon: 'error',
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 工具方法
|
|
|
+ getStatusText(status) {
|
|
|
+ const statusMap = {
|
|
|
+ draft: '草稿',
|
|
|
+ waiting: '待审批',
|
|
|
+ complete: '已完成',
|
|
|
+ cancel: '已取消',
|
|
|
+ back: '已退回',
|
|
|
+ suspend: '挂起',
|
|
|
+ terminate: '终止',
|
|
|
+ };
|
|
|
+ return statusMap[status] || '未知';
|
|
|
+ },
|
|
|
+
|
|
|
+ getStatusColor(status) {
|
|
|
+ const colorMap = {
|
|
|
+ draft: 'background-color: #909399; color: white',
|
|
|
+ waiting: 'background-color: #e6a23c; color: white',
|
|
|
+ complete: 'background-color: #67c23a; color: white',
|
|
|
+ cancel: 'background-color: #f56c6c; color: white',
|
|
|
+ back: 'background-color: #409eff; color: white',
|
|
|
+ suspend: 'background-color: #909399; color: white',
|
|
|
+ terminate: 'background-color: #f56c6c; color: white',
|
|
|
+ };
|
|
|
+ return colorMap[status] || colorMap.draft;
|
|
|
+ },
|
|
|
+
|
|
|
+ formatWorkflowTime(timeStr) {
|
|
|
+ return formatTime(timeStr);
|
|
|
+ },
|
|
|
+
|
|
|
+ canEdit(status) {
|
|
|
+ return ['draft', 'cancel', 'back'].includes(status);
|
|
|
+ },
|
|
|
+
|
|
|
+ canDelete(status) {
|
|
|
+ return ['draft', 'cancel', 'back'].includes(status);
|
|
|
+ },
|
|
|
+
|
|
|
+ canCancel(status) {
|
|
|
+ return status === 'waiting';
|
|
|
+ },
|
|
|
+
|
|
|
+ getTabName(tab) {
|
|
|
+ const tabMap = {
|
|
|
+ initiated: '我发起的',
|
|
|
+ todo: '我的待办',
|
|
|
+ finished: '我的已办',
|
|
|
+ copy: '我的抄送',
|
|
|
+ };
|
|
|
+ return tabMap[tab] || '';
|
|
|
+ },
|
|
|
+
|
|
|
+ updateWorkflowBadges() {
|
|
|
+ // 这里可以根据实际需求更新各个标签页的徽章数量
|
|
|
+ // 暂时设置为工作流列表的长度
|
|
|
+ const tabIndex = this.workflowTabs.findIndex((tab) => tab.key === 'initiated');
|
|
|
+ if (tabIndex !== -1) {
|
|
|
+ this.workflowTabs[tabIndex].badge = this.workflowList.length;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ showConfirm(title, content) {
|
|
|
+ return new Promise((resolve) => {
|
|
|
+ uni.showModal({
|
|
|
+ title,
|
|
|
+ content,
|
|
|
+ success: (res) => {
|
|
|
+ resolve(res.confirm);
|
|
|
+ },
|
|
|
+ fail: () => {
|
|
|
+ resolve(false);
|
|
|
+ },
|
|
|
+ });
|
|
|
+ });
|
|
|
+ },
|
|
|
+ gotoInitiatedList() {
|
|
|
+ uni.navigateTo({
|
|
|
+ url: '/pages/workflow/initiated',
|
|
|
+ });
|
|
|
+ },
|
|
|
+ handleWorkflowTabClick(tab) {
|
|
|
+ this.activeWorkflowTab = tab;
|
|
|
+ // 其他tab逻辑可保留
|
|
|
+ },
|
|
|
},
|
|
|
};
|
|
|
</script>
|
|
|
@@ -637,6 +978,332 @@ export default {
|
|
|
height: 20px;
|
|
|
}
|
|
|
|
|
|
+/* 工作流模块样式 */
|
|
|
+.workflow-header {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.workflow-icon {
|
|
|
+ color: #409eff;
|
|
|
+ font-size: $uni-font-size-lg;
|
|
|
+}
|
|
|
+
|
|
|
+.workflow-tabs {
|
|
|
+ display: flex;
|
|
|
+ margin-bottom: $uni-spacing-col-lg;
|
|
|
+ background: $uni-bg-color-grey;
|
|
|
+ border-radius: $uni-border-radius-base;
|
|
|
+ padding: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.workflow-tab {
|
|
|
+ flex: 1;
|
|
|
+ padding: 8px 12px;
|
|
|
+ text-align: center;
|
|
|
+ border-radius: $uni-border-radius-base;
|
|
|
+ position: relative;
|
|
|
+ transition: $uni-transition;
|
|
|
+
|
|
|
+ &.active {
|
|
|
+ background: $uni-color-primary;
|
|
|
+ color: $uni-text-color-inverse;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.tab-icon {
|
|
|
+ font-size: 16px;
|
|
|
+ margin-bottom: 2px;
|
|
|
+}
|
|
|
+
|
|
|
+.tab-text {
|
|
|
+ font-size: $uni-font-size-sm;
|
|
|
+ font-weight: 500;
|
|
|
+}
|
|
|
+
|
|
|
+.tab-badge {
|
|
|
+ position: absolute;
|
|
|
+ top: -2px;
|
|
|
+ right: -2px;
|
|
|
+ background: #ff4757;
|
|
|
+ border-radius: $uni-border-radius-circle;
|
|
|
+ min-width: 16px;
|
|
|
+ height: 16px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+
|
|
|
+.tab-badge-text {
|
|
|
+ color: $uni-text-color-inverse;
|
|
|
+ font-size: 10px;
|
|
|
+ font-weight: 500;
|
|
|
+ padding: 0 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.workflow-content {
|
|
|
+ margin-top: $uni-spacing-col-base;
|
|
|
+}
|
|
|
+
|
|
|
+/* 搜索和筛选 */
|
|
|
+.workflow-filter {
|
|
|
+ margin-bottom: $uni-spacing-col-lg;
|
|
|
+}
|
|
|
+
|
|
|
+.filter-row {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 12px;
|
|
|
+ margin-bottom: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.search-input {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ background: $uni-bg-color-grey;
|
|
|
+ border-radius: $uni-border-radius-base;
|
|
|
+ padding: 0 12px;
|
|
|
+ height: 36px;
|
|
|
+
|
|
|
+ .iconfont {
|
|
|
+ margin-right: 8px;
|
|
|
+ color: $uni-text-color-grey;
|
|
|
+ font-size: 16px;
|
|
|
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%23999' viewBox='0 0 24 24'%3E%3Cpath d='M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z'/%3E%3C/svg%3E");
|
|
|
+ width: 16px;
|
|
|
+ height: 16px;
|
|
|
+ background-size: contain;
|
|
|
+ background-repeat: no-repeat;
|
|
|
+ background-position: center;
|
|
|
+ filter: invert(60%);
|
|
|
+ }
|
|
|
+
|
|
|
+ input {
|
|
|
+ flex: 1;
|
|
|
+ border: none;
|
|
|
+ background: transparent;
|
|
|
+ font-size: $uni-font-size-base;
|
|
|
+ color: $uni-text-color;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.filter-button {
|
|
|
+ width: 36px;
|
|
|
+ height: 36px;
|
|
|
+ background: $uni-color-primary;
|
|
|
+ border-radius: $uni-border-radius-base;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+
|
|
|
+ .iconfont {
|
|
|
+ color: $uni-text-color-inverse;
|
|
|
+ font-size: 16px;
|
|
|
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%23fff' viewBox='0 0 24 24'%3E%3Cpath d='M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z'/%3E%3C/svg%3E");
|
|
|
+ width: 16px;
|
|
|
+ height: 16px;
|
|
|
+ background-size: contain;
|
|
|
+ background-repeat: no-repeat;
|
|
|
+ background-position: center;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.category-filter {
|
|
|
+ margin-top: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.category-scroll {
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.category-list {
|
|
|
+ display: flex;
|
|
|
+ gap: 8px;
|
|
|
+ white-space: nowrap;
|
|
|
+ padding-bottom: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.category-item {
|
|
|
+ padding: 6px 12px;
|
|
|
+ background: $uni-bg-color-grey;
|
|
|
+ border-radius: $uni-border-radius-base;
|
|
|
+ white-space: nowrap;
|
|
|
+ transition: $uni-transition;
|
|
|
+
|
|
|
+ &.active {
|
|
|
+ background: $uni-color-primary;
|
|
|
+ color: $uni-text-color-inverse;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.category-text {
|
|
|
+ font-size: $uni-font-size-sm;
|
|
|
+}
|
|
|
+
|
|
|
+/* 工作流列表 */
|
|
|
+.workflow-loading {
|
|
|
+ text-align: center;
|
|
|
+ padding: 40px 0;
|
|
|
+ color: $uni-text-color-grey;
|
|
|
+}
|
|
|
+
|
|
|
+.workflow-empty {
|
|
|
+ text-align: center;
|
|
|
+ padding: 40px 0;
|
|
|
+ color: $uni-text-color-grey;
|
|
|
+}
|
|
|
+
|
|
|
+.empty-icon {
|
|
|
+ font-size: 48px;
|
|
|
+ margin-bottom: 12px;
|
|
|
+ display: block;
|
|
|
+}
|
|
|
+
|
|
|
+.empty-text {
|
|
|
+ font-size: $uni-font-size-base;
|
|
|
+}
|
|
|
+
|
|
|
+.workflow-list {
|
|
|
+ margin-top: $uni-spacing-col-base;
|
|
|
+}
|
|
|
+
|
|
|
+.workflow-item {
|
|
|
+ background: $uni-bg-color;
|
|
|
+ border-radius: $uni-border-radius-base;
|
|
|
+ padding: $uni-spacing-col-lg;
|
|
|
+ margin-bottom: 12px;
|
|
|
+ box-shadow: $uni-shadow;
|
|
|
+ transition: $uni-transition;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ box-shadow: $uni-shadow-hover;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.workflow-header-info {
|
|
|
+ margin-bottom: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.workflow-title-row {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: flex-start;
|
|
|
+ margin-bottom: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.workflow-title {
|
|
|
+ font-size: $uni-font-size-lg;
|
|
|
+ font-weight: 500;
|
|
|
+ color: $uni-text-color;
|
|
|
+ flex: 1;
|
|
|
+ margin-right: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.workflow-status {
|
|
|
+ padding: 4px 8px;
|
|
|
+ border-radius: $uni-border-radius-base;
|
|
|
+ font-size: $uni-font-size-sm;
|
|
|
+ font-weight: 500;
|
|
|
+ white-space: nowrap;
|
|
|
+}
|
|
|
+
|
|
|
+.workflow-code {
|
|
|
+ font-size: $uni-font-size-sm;
|
|
|
+ color: $uni-text-color-grey;
|
|
|
+}
|
|
|
+
|
|
|
+.workflow-meta {
|
|
|
+ margin-bottom: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.meta-item {
|
|
|
+ display: flex;
|
|
|
+ margin-bottom: 4px;
|
|
|
+
|
|
|
+ &:last-child {
|
|
|
+ margin-bottom: 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.meta-label {
|
|
|
+ font-size: $uni-font-size-sm;
|
|
|
+ color: $uni-text-color-grey;
|
|
|
+ width: 70px;
|
|
|
+ flex-shrink: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.meta-value {
|
|
|
+ font-size: $uni-font-size-sm;
|
|
|
+ color: $uni-text-color;
|
|
|
+ flex: 1;
|
|
|
+}
|
|
|
+
|
|
|
+.workflow-actions {
|
|
|
+ display: flex;
|
|
|
+ gap: 8px;
|
|
|
+ flex-wrap: wrap;
|
|
|
+}
|
|
|
+
|
|
|
+.action-button {
|
|
|
+ padding: 6px 12px;
|
|
|
+ border-radius: $uni-border-radius-base;
|
|
|
+ font-size: $uni-font-size-sm;
|
|
|
+ font-weight: 500;
|
|
|
+ text-align: center;
|
|
|
+ min-width: 50px;
|
|
|
+ transition: $uni-transition;
|
|
|
+
|
|
|
+ &.edit {
|
|
|
+ background: #409eff;
|
|
|
+ color: $uni-text-color-inverse;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.delete {
|
|
|
+ background: #f56c6c;
|
|
|
+ color: $uni-text-color-inverse;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.view {
|
|
|
+ background: $uni-color-primary;
|
|
|
+ color: $uni-text-color-inverse;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.cancel {
|
|
|
+ background: #e6a23c;
|
|
|
+ color: $uni-text-color-inverse;
|
|
|
+ }
|
|
|
+
|
|
|
+ &:active {
|
|
|
+ opacity: 0.8;
|
|
|
+ transform: scale(0.98);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.load-more {
|
|
|
+ text-align: center;
|
|
|
+ padding: 20px 0;
|
|
|
+ color: $uni-color-primary;
|
|
|
+ font-size: $uni-font-size-base;
|
|
|
+}
|
|
|
+
|
|
|
+.workflow-placeholder {
|
|
|
+ text-align: center;
|
|
|
+ padding: 60px 0;
|
|
|
+ color: $uni-text-color-grey;
|
|
|
+}
|
|
|
+
|
|
|
+.placeholder-icon {
|
|
|
+ font-size: 48px;
|
|
|
+ margin-bottom: 12px;
|
|
|
+ display: block;
|
|
|
+}
|
|
|
+
|
|
|
+.placeholder-text {
|
|
|
+ font-size: $uni-font-size-base;
|
|
|
+}
|
|
|
+
|
|
|
/* 页面进入动画 */
|
|
|
.page-container {
|
|
|
animation: fadeInUp 0.6s ease-out;
|