Files
supervision-test-frontend-repo/src/views/bg/xispeak/BgXiSpeakList.vue
T

1048 lines
29 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="erpNativeList">
<div class="content">
<!--引用表格-->
<BasicTable @register="registerTable" :expandedRowKeys="expandedRowKeys" @expand="handleExpand" @fetch-success="onFetchSuccess">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" v-auth="'bg.xispeak:bg_xi_speak:add'" @click="handleAdd" preIcon="ant-design:plus-outlined">新增</a-button>
<a-button type="primary" v-auth="'bg.xispeak:bg_xi_speak:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"
>导出</a-button
>
<j-upload-button type="primary" v-auth="'bg.xispeak:bg_xi_speak:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls"
>导入</j-upload-button
>
<a-dropdown v-if="selectedRowKeys.length > 0">
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="batchHandleDelete">
<Icon icon="ant-design:delete-outlined"></Icon>
删除
</a-menu-item>
</a-menu>
</template>
<a-button v-auth="'bg.xispeak:bg_xi_speak:deleteBatch'"
>批量操作
<Icon icon="ant-design:down-outlined"></Icon>
</a-button>
</a-dropdown>
<!-- 高级查询 -->
<super-query :config="superQueryConfig" @search="handleSuperQuery" />
</template>
<!-- 自定义展开图标完全复刻 Jeecg 原生树形效果 -->
<template #expandIcon="{ expanded, onExpand, record }">
<span v-if="record.hasChild === '1'" class="jeecg-tree-expand-icon" @click="(e) => onExpand(record, e)">
<!-- 用方块样式的加减号 Jeecg 原生一致 -->
<Icon :icon="expanded ? 'ant-design:minus-square-outlined' : 'ant-design:plus-square-outlined'" />
</span>
<span v-else class="jeecg-tree-expand-placeholder"></span>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)" />
</template>
<!--字段回显插槽-->
<template v-slot:bodyCell="{ column, record, index, text }"> </template>
<!--嵌套子表-->
<template #expandedRowRender="{ record }">
<div class="feedback-expand-table" v-if="selectedFeedbackId === record.id">
<div class="feedback-expand-header">
<div class="feedback-expand-title">
<span class="feedback-expand-icon">
<Icon icon="ant-design:message-outlined" />
</span>
<span>反馈信息</span>
<a-tag class="feedback-expand-count" color="processing">
{{ getFeedbackTableLoading(record) ? '加载中' : `${getFeedbackCount(record)} 条` }}
</a-tag>
</div>
<div class="feedback-expand-actions">
<a-button type="link" size="small" @click="handleCloseFeedback">收起</a-button>
</div>
</div>
<BasicTable
class="feedback-inner-table"
bordered
size="small"
rowKey="id"
:canResize="false"
:showIndexColumn="false"
:showActionColumn="false"
:showTableSetting="false"
:clickToRowSelect="false"
:columns="feedbackExpandColumns"
:dataSource="getFeedbackTableData(record)"
:loading="getFeedbackTableLoading(record)"
:pagination="false"
:scroll="{ x: 1220 }"
>
<template #feedbackAttachments="{ record: feedbackRecord }">
<SUploadFile
v-if="feedbackRecord.id"
class="feedback-attachment-list"
:bussiness-id="feedbackRecord.id"
:disabled="true"
:multiple="true"
/>
<span v-else>-</span>
</template>
</BasicTable>
</div>
</template>
</BasicTable>
</div>
<!-- 表单区域 -->
<BgXiSpeakModal ref="registerModal" @success="handleSuccess"></BgXiSpeakModal>
<!-- 审批记录 -->
<BpmPictureModal @register="registerBpmModal" />
<FlowScheduleStartModal ref="flowScheduleModalRef" @confirm="handleFlowScheduleConfirm" />
<BusinessProcessListModal ref="businessProcessListModalRef" />
</div>
</template>
<script lang="ts" name="bg.xispeak-bgXiSpeak" setup>
import { ref, reactive, unref, computed, provide } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import type { BasicColumn } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { useModal } from '/@/components/Modal';
import { useMessage } from '/@/hooks/web/useMessage';
import { startProcessSchedules } from '/@/api/common/api';
import { dateUtil } from '/@/utils/dateUtil';
import Icon from '/@/components/Icon/index';
import BgXiSpeakModal from './components/BgXiSpeakModal.vue';
import SUploadFile from '/@/components/semri/fileComponent/SUploadFile.vue';
import BusinessProcessListModal from '/src/components/semri/process/BusinessProcessListModal.vue';
import FlowScheduleStartModal from '/src/components/semri/process/FlowScheduleStartModal.vue';
import { columns as taskTaskColumns } from '/@/views/taskProcess/TaskTask.data';
import { columns, superQuerySchema, bgXiSpeakFeedbackColumns } from './BgXiSpeak.data';
import {
list,
deleteBgXiSpeak,
batchDeleteBgXiSpeak,
getExportUrl,
getImportUrl,
getChildList,
getChildListBatch,
updateLaunchType,
saveOrUpdateDict,
bgXiSpeakFeedbackList,
} from './BgXiSpeak.api';
const FLOW_CODE = 'dev_bg_xi_speak_001';
const FLOW_NAME = '习总书记重要讲话指示批示';
const FLOW_CODE_JBR = 'bg_xi_speak_fb_01';
const BUSINESS_TABLE_NAME = 'bg_xi_speak';
const FORM_URL = 'bg/xispeak/components/BgXiSpeakBPMForm';
const [registerBpmModal, { openModal: bpmPicModal }] = useModal();
const { createMessage } = useMessage();
const expandedRowKeys = ref([]);
const queryParam = ref<any>({});
const toggleSearchStatus = ref<boolean>(false);
const registerModal = ref();
const flowScheduleModalRef = ref();
const businessProcessListModalRef = ref();
const processColumns = taskTaskColumns;
const selectedFeedbackId = ref<string | number | null>(null);
const feedbackTableData = reactive<Record<string, Recordable[]>>({});
const feedbackTableLoading = reactive<Record<string, boolean>>({});
// 注册table数据
const feedbackExpandColumns: BasicColumn[] = [
...bgXiSpeakFeedbackColumns,
{
title: '附件下载',
dataIndex: 'id',
key: 'attachments',
align: 'left',
width: 340,
slots: { customRender: 'feedbackAttachments' },
},
];
// 是否显示DW领导列表选择
const showSdwLeaderSelect = computed(() => queryParam.value.needSdwApproval === '1');
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '习总书记重要讲话指示批示情况',
api: list,
columns,
canResize: false,
useSearchForm: false,
isTreeTable: true,
indentSize: 24, // 和 Jeecg 原生树形缩进保持一致
expandIconColumnIndex: 0,
clickToRowSelect: true,
treeProps: {
children: 'children',
indent: 24, // 和 indentSize 保持一致,保证缩进对齐
},
actionColumn: {
width: 120,
fixed: 'right',
},
beforeFetch: async (params) => {
params.hasQuery = 'true';
return Object.assign(params, queryParam.value);
},
afterFetch: (result) => {
if (result && result.length > 0) {
// 为有子节点的记录设置 children(用于显示展开图标)
result.forEach((item) => {
if (item.hasChild == '1' && (!item.children || item.children.length === 0)) {
item.children = [{ id: item.id + '_loadChild', name: 'loading...', isLoading: true }];
}
});
}
return result;
},
pagination: {
current: 1,
pageSize: 10,
pageSizeOptions: ['10', '20', '30'],
},
},
exportConfig: {
name: '习总书记重要讲话指示批示情况',
url: getExportUrl,
},
importConfig: {
url: getImportUrl,
success: success,
},
});
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { selectedRowKeys }] = tableContext;
const mainId = computed(() => (unref(selectedRowKeys).length > 0 ? unref(selectedRowKeys)[0] : ''));
provide('mainId', mainId);
const labelCol = reactive({
xs: 24,
sm: 4,
xl: 6,
xxl: 4,
});
const wrapperCol = reactive({
xs: 24,
sm: 20,
});
// 高级查询配置
const superQueryConfig = reactive(superQuerySchema);
/**
* 高级查询事件
*/
function handleSuperQuery(params) {
Object.keys(params).map((k) => {
queryParam.value[k] = params[k];
});
reload();
}
/**
* 新增事件
*/
function handleAdd() {
registerModal.value.disableSubmit = false;
registerModal.value.add();
}
/**
* 编辑事件
*/
async function handleEdit(record) {
registerModal.value.disableSubmit = false;
registerModal.value.edit(record);
}
/**
* 详情
*/
async function handleDetail(record) {
registerModal.value.disableSubmit = true;
registerModal.value.edit(record);
}
/**
* 删除事件
*/
async function handleDelete(record) {
await deleteBgXiSpeak({ id: record.id }, success);
}
/**
* 批量删除事件
*/
async function batchHandleDelete() {
const ids = selectedRowKeys.value.filter((item) => !item.includes('loadChild'));
await batchDeleteBgXiSpeak({ id: ids }, success);
}
/**
* 成功回调刷新页面
*/
function success() {
selectedRowKeys.value = [];
reload();
}
/**
* 成功回调
*/
async function handleSuccess({ isUpdate, values, expandedArr, changeParent }) {
if (isUpdate) {
if (changeParent) {
reload();
} else {
let data = await list({ id: values.id, pageSize: 1, pageNo: 1, pid: values['pid'] });
if (data && data.records && data.records.length > 0) {
updateTableDataRecord(values.id, data.records[0]);
} else {
updateTableDataRecord(values.id, values);
}
}
} else {
if (!values['id'] || !values['pid']) {
reload();
} else {
expandedRowKeys.value = [];
for (let key of unref(expandedArr)) {
await expandTreeNode(key);
}
}
}
}
/**
* 树节点展开合并
*/
async function handleExpand(expanded, record) {
if (expanded) {
expandedRowKeys.value.push(record.id);
// 懒加载子节点
if (record.children && record.children.length > 0 && record.children[0].isLoading) {
let result = await getChildList({ pid: record.id });
result = result.records ? result.records : result;
if (result && result.length > 0) {
record.children = getDataByResult(result);
} else {
record.children = null;
record.hasChild = '0';
}
}
} else {
let keyIndex = expandedRowKeys.value.indexOf(record.id);
if (keyIndex >= 0) {
expandedRowKeys.value.splice(keyIndex, 1);
}
}
}
/**
* 处理数据集,标记有子节点的记录
*/
function getDataByResult(result) {
if (result && result.length > 0) {
return result.map((item) => {
if (item['hasChild'] == '1') {
let loadChild = { id: item.id + '_loadChild', name: 'loading...', isLoading: true };
item.children = [loadChild];
}
return item;
});
}
}
/**
* 接口请求成功后回调
*/
function onFetchSuccess(result) {
getDataByResult(result.items) && loadDataByExpandedRows();
}
/**
* 根据已展开的行查询数据
*/
async function loadDataByExpandedRows() {
if (unref(expandedRowKeys).length > 0) {
const res = await getChildListBatch({ parentIds: unref(expandedRowKeys).join(',') });
if (res.success && res.result.records.length > 0) {
let records = res.result.records;
const listMap = new Map();
for (let item of records) {
let pid = item['pid'];
if (unref(expandedRowKeys).includes(pid)) {
let mapList = listMap.get(pid);
if (mapList == null) {
mapList = [];
}
mapList.push(item);
listMap.set(pid, mapList);
}
}
let childrenMap = listMap;
let fn = (list) => {
if (list) {
list.forEach((data) => {
if (unref(expandedRowKeys).includes(data.id)) {
data.children = getDataByResult(childrenMap.get(data.id));
fn(data.children);
}
});
}
};
fn(getDataSource());
}
}
}
/**
* 操作表格后处理树节点展开合并
*/
async function expandTreeNode(key) {
let record = findTableDataRecord(key);
if (record) {
expandedRowKeys.value.push(key);
let result = await getChildList({ pid: key });
result = result.records ? result.records : result;
if (result && result.length > 0) {
record.children = getDataByResult(result);
} else {
record.children = null;
record.hasChild = '0';
}
updateTableDataRecord(key, record);
}
}
/**
* 添加下级
*/
function handleAddSub(record) {
registerModal.value.disableSubmit = false;
registerModal.value.add(record);
}
/**
* 操作栏
*/
function getTableAction(record) {
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
auth: 'bg.xispeak:bg_xi_speak:edit',
},
];
}
/**
* 下拉操作栏
*/
function getDropDownAction(record) {
let dropDownAction = [
{
label: '详情',
onClick: handleDetail.bind(null, record),
},
{
label: '添加下级',
onClick: handleAddSub.bind(null, { pid: record.id }),
},
{
label: '删除',
popConfirm: {
title: '确定删除吗?',
confirm: handleDelete.bind(null, record),
placement: 'topLeft',
},
auth: 'bg.xispeak:bg_xi_speak:delete',
},
{
label: '审批进度',
onClick: handlePreviewPic.bind(null, record),
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
},
{
label: '查询督办流程',
onClick: handleQueryProcess.bind(null, record),
},
{
label: selectedFeedbackId.value === record.id ? '收起反馈信息' : '查看反馈',
onClick: handleViewFeedback.bind(null, record),
},
];
if (record.bpmStatus == '1' || !record.bpmStatus) {
dropDownAction.push({
label: '发起督办计划收集流程',
onClick: handleProcess.bind(null, record),
});
dropDownAction.push({
label: '发起经办人执行反馈流程',
onClick: handleProcessJbr.bind(null, record),
});
}
return dropDownAction;
}
function splitDeptValue(value) {
if (Array.isArray(value)) {
return value.map((item) => String(item || '').trim()).filter(Boolean);
}
return String(value || '')
.split(/[,\uFF0C]/)
.map((item) => item.trim())
.filter(Boolean);
}
function getImplDeptOptions(record) {
const deptIds = splitDeptValue(record?.implDept);
const deptNames = splitDeptValue(record?.implDept_dictText);
return deptIds.map((deptId, index) => ({
value: deptId,
label: deptNames[index] || deptId,
}));
}
function getLeadDeptOptions(record) {
const deptIds = splitDeptValue(record?.leadDepartment);
const deptNames = splitDeptValue(record?.leadDepartment_dictText);
return deptIds.map((deptId, index) => ({
value: deptId,
label: deptNames[index] || deptId,
}));
}
function getNextSuperviseCount(value) {
const count = Number(value || 0);
return Number.isFinite(count) ? count + 1 : 1;
}
function handleProcess(record) {
flowScheduleModalRef.value?.open({
title: '发起督办计划收集流程',
payload: { record },
deptOptions: getLeadDeptOptions(record),
showSuoleaderFields: true,
isNeedAppro: record?.needSdwApproval,
supDeptleaderid: record?.sdwLeaderList,
});
}
function handleProcessJbr(record) {
flowScheduleModalRef.value?.open({
title: '发起落实部门经办人执行反馈流程',
payload: { record, flowCode: FLOW_CODE_JBR },
deptOptions: getImplDeptOptions(record),
showSuoleaderFields: true,
isNeedAppro: record?.needSdwApproval,
supDeptleaderid: record?.sdwLeaderList,
});
}
function handleQueryProcess(record) {
businessProcessListModalRef.value?.open({
title: '流程列表',
businessId: record.id,
columns: '',
});
}
async function handleFlowScheduleConfirm({ payload, options }) {
const record = payload?.record || {};
const flowCode = payload?.flowCode || FLOW_CODE;
const formatDate = (value, format) => {
return value ? dateUtil(value).format(format) : undefined;
};
const launchType = options.triggerType === 2 ? 1 : 0;
if (flowCode === FLOW_CODE) {
await updateLaunchType({ id: record.id, launchType });
}
const nextSuperviseCount = getNextSuperviseCount(record.supervisionCount);
const flowJsonData = {
...record,
isNeedAppro: options.isNeedAppro ?? record.needSdwApproval ?? '',
supDeptleaderid: options.supDeptleaderid ?? record.sdwLeaderList ?? '',
supervisionCount: nextSuperviseCount,
};
if (flowCode === FLOW_CODE_JBR) {
const selectedDeptIds = options.deptIds || [];
if (selectedDeptIds.length === 0) {
createMessage.warning('请选择落实部门');
return;
}
let successCount = 0;
const total = selectedDeptIds.length;
for (const deptId of selectedDeptIds) {
const params = {
intervalType: options.intervalType,
startCount: options.startCount,
taskTask: {
triggerType: options.triggerType,
startTime: options.intervalStartTime,
flowCode: flowCode,
formUrl: FORM_URL,
flowName: '落实部门经办人执行反馈流程',
jsonData: {
...flowJsonData,
currentDeptId: deptId,
},
businessTablename: BUSINESS_TABLE_NAME,
businessId: record.id,
title: record.speakStatus,
content: record.implStatus,
urgencyLevel: record.completionStatus,
deptId: deptId,
deptLeaderId: deptId,
requireFinishDate: formatDate(record.time, 'YYYY-MM-DD'),
deadline: formatDate(record.time, 'YYYY-MM-DD HH:mm:ss'),
},
};
try {
await startProcessSchedules(params);
successCount++;
if (successCount === total) {
await saveOrUpdateDict({ id: record.id, bpmStatus: '2', supervisionCount: nextSuperviseCount }, true);
createMessage.success(`成功发起 ${total} 个经办人执行反馈流程`);
reload();
}
} catch (e) {
createMessage.error(`部门 ${deptId} 流程发起失败`);
}
}
return;
}
const params = {
intervalType: options.intervalType,
startCount: options.startCount,
taskTask: {
triggerType: options.triggerType,
startTime: options.intervalStartTime,
flowCode: flowCode,
formUrl: FORM_URL,
flowName: FLOW_NAME,
jsonData: flowJsonData,
businessTablename: BUSINESS_TABLE_NAME,
businessId: record.id,
title: record.speakStatus,
content: record.implStatus,
urgencyLevel: record.completionStatus,
deptId: options.deptId || record.leadDepartment,
deptLeaderId: record.responsiblePerson,
requireFinishDate: formatDate(record.time, 'YYYY-MM-DD'),
deadline: formatDate(record.time, 'YYYY-MM-DD HH:mm:ss'),
},
};
await startProcessSchedules(params);
await saveOrUpdateDict({ id: record.id, bpmStatus: '2', supervisionCount: nextSuperviseCount }, true);
createMessage.success('发起成功');
reload();
}
async function handlePreviewPic(record) {
bpmPicModal(true, {
flowCode: FLOW_CODE,
dataId: record.id,
});
}
function getFeedbackKey(record: Recordable) {
return String(record?.id ?? '');
}
function getFeedbackTableData(record: Recordable) {
return feedbackTableData[getFeedbackKey(record)] || [];
}
function getFeedbackCount(record: Recordable) {
return getFeedbackTableData(record).length;
}
function getFeedbackTableLoading(record: Recordable) {
return !!feedbackTableLoading[getFeedbackKey(record)];
}
function handleCloseFeedback() {
selectedFeedbackId.value = null;
}
async function loadFeedbackTableData(mainId: string | number) {
const key = String(mainId);
feedbackTableLoading[key] = true;
try {
const res = await bgXiSpeakFeedbackList({
mainId,
pageNo: 1,
pageSize: 9999,
column: 'createTime',
order: 'desc',
});
feedbackTableData[key] = Array.isArray(res) ? res : res?.records || [];
} finally {
feedbackTableLoading[key] = false;
}
}
async function handleViewFeedback(record: Recordable) {
const mainId = record.id;
if (selectedFeedbackId.value === mainId) {
selectedFeedbackId.value = null;
} else {
selectedFeedbackId.value = mainId;
if (!feedbackTableData[mainId] || feedbackTableData[mainId].length === 0) {
await loadFeedbackTableData(mainId);
}
}
}
/**
* 查询
*/
function searchQuery() {
reload();
}
/**
* 重置
*/
function searchReset() {
queryParam.value = {};
selectedRowKeys.value = [];
reload();
}
/**
* form点击事件(以逗号分割)
*/
function handleFormJoinChange(key, value) {
if (typeof value != 'string') {
queryParam.value[key] = value.join(',');
}
}
</script>
<style lang="less" scoped>
.erpNativeList {
height: 100%;
padding: 16px;
background: #f5f7fa;
// 查询区域卡片
.search-card {
background: #fff;
border-radius: 8px;
padding: 20px 24px;
margin-bottom: 16px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
transition: box-shadow 0.3s ease;
&:hover {
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
}
:deep(.ant-form-item) {
margin-bottom: 0;
}
:deep(.ant-select),
:deep(.ant-picker) {
border-radius: 6px;
}
}
// 内容区域
.content {
background: #fff;
border-radius: 8px;
padding: 0;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
overflow: hidden;
}
// 表格标题区域
:deep(.ant-table-title) {
padding: 16px 20px !important;
border-bottom: 1px solid #f0f0f0;
background: #fafafa;
.ant-btn {
height: 32px;
padding: 0 16px;
border-radius: 6px;
font-size: 13px;
margin-right: 8px;
border: none;
transition: all 0.2s ease;
&:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(24, 144, 255, 0.3);
}
&:active {
transform: translateY(0);
}
}
.ant-btn-primary {
background: linear-gradient(135deg, #1890ff 0%, #096dd9 100%);
&:hover {
background: linear-gradient(135deg, #40a9ff 0%, #1890ff 100%);
}
}
}
// 表格样式优化
:deep(.ant-table-thead > tr > th) {
background: #fafafa;
font-weight: 600;
color: #333;
border-bottom: 1px solid #f0f0f0;
padding: 12px 16px;
}
:deep(.ant-table-tbody > tr > td) {
padding: 14px 16px;
border-bottom: 1px solid #f5f5f5;
transition: background 0.2s ease;
}
// 树形表格缩进样式,和 Jeecg 原生对齐
:deep(.ant-table-row) {
.ant-table-row-indent {
display: inline-block;
width: 24px; // 和 indentSize 保持一致
height: 1px;
}
}
:deep(.ant-table-tbody > tr:hover > td) {
background: #f5f7fa;
}
// Jeecg 原生风格的树形展开图标
:deep(.jeecg-tree-expand-icon) {
display: inline-flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
margin-right: 6px;
cursor: pointer;
border-radius: 2px;
transition: all 0.2s;
&:hover {
background-color: #f0f0f0;
}
.anticon {
font-size: 14px;
color: #666;
transition: color 0.2s;
}
&:hover .anticon {
color: #1890ff;
}
}
:deep(.jeecg-tree-expand-placeholder) {
display: inline-block;
width: 20px;
height: 20px;
margin-right: 6px;
}
// 操作按钮样式
:deep(.ant-btn-link) {
padding: 4px 8px;
height: auto;
border-radius: 4px;
&:hover {
background: rgba(24, 144, 255, 0.1);
}
}
// 标签页样式
:deep(.ant-tabs) {
margin: 16px;
.ant-tabs-nav {
margin-bottom: 12px;
}
.ant-tabs-tab {
padding: 8px 0;
font-size: 14px;
&:hover {
color: #1890ff;
}
}
.ant-tabs-tab-active .ant-tabs-tab-btn {
color: #1890ff;
font-weight: 500;
}
}
// 下拉菜单样式
:deep(.ant-dropdown-menu-item) {
border-radius: 4px;
margin: 2px 4px;
&:hover {
background: #e6f7ff;
}
}
// 分页样式
:deep(.ant-pagination) {
padding: 16px 20px;
margin: 0 !important;
border-top: 1px solid #f0f0f0;
background: #fafafa;
}
// 搜索和重置按钮
:deep(.ant-form-item-with-search) {
display: flex;
justify-content: flex-end;
gap: 8px;
}
}
.feedback-expand-table {
margin: 4px 10px 12px 42px;
padding: 12px 14px 14px;
background: #f6fbff;
border: 1px solid #d6e8ff;
border-left: 4px solid #1677ff;
border-radius: 6px;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.72);
.feedback-expand-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-bottom: 10px;
}
.feedback-expand-title {
display: inline-flex;
align-items: center;
min-width: 0;
color: #1f2937;
font-size: 14px;
font-weight: 600;
line-height: 24px;
}
.feedback-expand-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
margin-right: 8px;
color: #1677ff;
background: #e6f4ff;
border-radius: 50%;
}
.feedback-expand-count {
margin-left: 10px;
}
.feedback-expand-desc {
color: #64748b;
font-size: 13px;
line-height: 22px;
white-space: nowrap;
}
.feedback-expand-actions {
display: flex;
align-items: center;
}
:deep(.jeecg-basic-table) {
background: #fff;
}
:deep(.feedback-inner-table .ant-table-wrapper) {
padding: 0;
border-radius: 4px;
}
:deep(.feedback-inner-table .ant-table-thead > tr > th) {
background: #eef6ff;
color: #334155;
font-weight: 600;
}
:deep(.feedback-inner-table .ant-table-tbody > tr > td) {
background: #fff;
}
:deep(.feedback-inner-table .ant-table-tbody > tr:hover > td) {
background: #f8fbff;
}
.feedback-attachment-list {
min-width: 300px;
:deep(.file-list-wrapper) {
min-height: auto;
padding: 8px;
}
:deep(.file-list-header) {
margin-bottom: 6px;
padding-bottom: 6px;
}
:deep(.file-list .file-item) {
padding: 8px;
margin-bottom: 6px;
}
:deep(.ant-empty) {
margin: 0;
}
}
}
// 响应式适配
@media (max-width: 768px) {
.erpNativeList {
padding: 12px;
.search-card {
padding: 16px;
}
}
}
</style>