499 lines
16 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.

<!--
* 病例库-病例交流
*
* @Author: xing
* @Date: 2025-08-08 18:28:17
* @Copyright gdxz
-->
<template>
<!---------- 查询表单form begin ----------->
<a-form class="smart-query-form">
<a-row class="smart-query-form-row">
<a-form-item label="关键字" class="smart-query-form-item">
<a-input style="width: 200px" v-model:value="queryForm.keyword" placeholder="标题" />
</a-form-item>
<a-form-item label="状态" name="exchangeStatus" class="smart-query-form-item">
<SmartEnumSelect enum-name="STATUS_ENUM" v-model:value="queryForm.exchangeStatus" width="160px" />
</a-form-item>
<a-form-item label="精选状态" name="isSelected" class="smart-query-form-item">
<SmartEnumSelect enum-name="SELECTED_ENUM" v-model:value="queryForm.isSelected" width="160px" />
</a-form-item>
<a-form-item label="审核状态" name="auditStatus" class="smart-query-form-item">
<SmartEnumSelect enum-name="AUDIT_STATUS_ENUM" v-model:value="queryForm.auditStatus" width="160px" />
</a-form-item>
<a-form-item class="smart-query-form-item">
<a-button type="primary" @click="onSearch">
<template #icon>
<SearchOutlined />
</template>
查询
</a-button>
<a-button @click="resetQuery" class="smart-margin-left10">
<template #icon>
<ReloadOutlined />
</template>
重置
</a-button>
</a-form-item>
</a-row>
</a-form>
<!---------- 查询表单form end ----------->
<a-card size="small" :bordered="false" :hoverable="true">
<!---------- 表格操作行 begin ----------->
<a-row class="smart-table-btn-block">
<div class="smart-table-operate-block">
<a-button @click="confirmBatchDelete" type="primary" danger size="small" :disabled="selectedRowKeyList.length == 0">
<template #icon>
<DeleteOutlined />
</template>
批量删除
</a-button>
</div>
<div class="smart-table-setting-block">
<TableOperator v-model="columns" :tableId="null" :refresh="queryData" />
</div>
</a-row>
<!---------- 表格操作行 end ----------->
<!---------- 表格 begin ----------->
<a-table
size="small"
:scroll="{ y: 800 }"
:dataSource="tableData"
:columns="columns"
rowKey="exchangeId"
bordered
:loading="tableLoading"
:pagination="false"
:row-selection="{ selectedRowKeys: selectedRowKeyList, onChange: onSelectChange }"
>
<template #bodyCell="{ text, record, column }">
<template v-if="column.dataIndex === 'exchangeTitle'">
<div class="text-wrap">{{ text }}</div>
</template>
<template v-if="column.dataIndex === 'hospitalName'">
<div class="text-wrap">{{ text }}</div>
</template>
<template v-if="column.dataIndex === 'exchangeStatus'">
<a-switch
:checked="text === 1"
@change="(checked) => onStatusChange(record, checked)"
:loading="record.statusLoading"
size="small"
/>
</template>
<template v-if="column.dataIndex === 'isSelected'">
<a-switch
:checked="text === 1"
@change="(checked) => onSelectedChange(record, checked)"
:loading="record.selectedLoading"
size="small"
/>
</template>
<template v-if="column.dataIndex === 'auditStatus'">
<a-tag :color="getAuditStatusColor(text)">
{{ getAuditStatusText(text) }}
</a-tag>
</template>
<template v-if="column.dataIndex === 'caseExchangeLabel'">
<div v-if="text && text.length > 0" class="label-list-display">
<div v-for="label in text" :key="label.exchangeLabelId" class="label-item-display">
<span class="label-name">{{ label.labelName }}</span>
</div>
</div>
<span v-else>-</span>
</template>
<template v-if="column.dataIndex === 'action'">
<div class="smart-table-operate">
<a-button @click="showAuditModal(record)" type="link" v-if="hasPermission('caseExchange:auditStatusUpdate')" :disabled="record.auditStatus === 1">审核</a-button>
<a-button @click="showForm(record)" type="link">编辑</a-button>
<a-button @click="onDelete(record)" danger type="link">删除</a-button>
</div>
</template>
</template>
</a-table>
<!---------- 表格 end ----------->
<div class="smart-query-table-page">
<a-pagination
showSizeChanger
showQuickJumper
show-less-items
:pageSizeOptions="PAGE_SIZE_OPTIONS"
:defaultPageSize="queryForm.pageSize"
v-model:current="queryForm.pageNum"
v-model:pageSize="queryForm.pageSize"
:total="total"
@change="queryData"
@showSizeChange="queryData"
:show-total="(total) => `${total}`"
/>
</div>
<CaseExchangeForm ref="formRef" @reloadList="queryData"/>
</a-card>
</template>
<script setup>
import { reactive, ref, onMounted } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { SmartLoading } from '/@/components/framework/smart-loading';
import { caseExchangeApi } from '/@/api/business/case-exchange/case-exchange-api';
import { PAGE_SIZE_OPTIONS } from '/@/constants/common-const';
import { smartSentry } from '/@/lib/smart-sentry';
import TableOperator from '/@/components/support/table-operator/index.vue';
import SmartEnumSelect from "/@/components/framework/smart-enum-select/index.vue";
import CaseExchangeForm from './case-exchange-form.vue';
// ---------------------------- 表格列 ----------------------------
const columns = ref([
{
title: '标题',
dataIndex: 'exchangeTitle',
ellipsis: true,
width: 200,
},
{
title: '作者',
dataIndex: 'userName',
ellipsis: true,
width: 150,
},
{
title: '医院名称',
dataIndex: 'hospitalName',
ellipsis: true,
width: 150,
},
{
title: '标签',
dataIndex: 'caseExchangeLabel',
ellipsis: true,
width: 200,
},
{
title: '状态',
dataIndex: 'exchangeStatus',
resizable: true,
filterOptions: {
type: 'enum-select',
enumName: 'STATUS_ENUM',
},
width: 100,
},
{
title: '精选',
dataIndex: 'isSelected',
resizable: true,
filterOptions: {
type: 'enum-select',
enumName: 'SELECTED_ENUM',
},
width: 100,
},
{
title: '审核状态',
dataIndex: 'auditStatus',
resizable: true,
filterOptions: {
type: 'enum-select',
enumName: 'AUDIT_STATUS_ENUM',
},
width: 100,
},
{
title: '阅读量',
dataIndex: 'readNum',
ellipsis: true,
width: 100,
},
{
title: '收藏量',
dataIndex: 'collectNum',
ellipsis: true,
width: 100,
},
{
title: '评论数',
dataIndex: 'commentNum',
ellipsis: true,
width: 100,
},
{
title: '发表时间',
dataIndex: 'pushDate',
ellipsis: true,
width: 150,
},
{
title: '创建时间',
dataIndex: 'createdAt',
ellipsis: true,
width: 150,
},
{
title: '修改时间',
dataIndex: 'updatedAt',
ellipsis: true,
width: 150,
},
{
title: '操作',
dataIndex: 'action',
fixed: 'right',
width: 150,
},
]);
// ---------------------------- 查询数据表单和方法 ----------------------------
const queryFormState = {
keyword: undefined, //关键字
exchangeStatus: undefined, //状态
isSelected: undefined, //精选状态
auditStatus: undefined, //审核状态
pageNum: 1,
pageSize: 10,
};
// 查询表单form
const queryForm = reactive({ ...queryFormState });
// 表格加载loading
const tableLoading = ref(false);
// 表格数据
const tableData = ref([]);
// 总数
const total = ref(0);
// 重置查询条件
function resetQuery() {
let pageSize = queryForm.pageSize;
Object.assign(queryForm, queryFormState);
queryForm.pageSize = pageSize;
queryData();
}
// 搜索
function onSearch(){
queryForm.pageNum = 1;
queryData();
}
// 查询数据
async function queryData() {
tableLoading.value = true;
try {
let queryResult = await caseExchangeApi.queryPage(queryForm);
tableData.value = queryResult.data.list;
total.value = queryResult.data.total;
} catch (e) {
smartSentry.captureError(e);
} finally {
tableLoading.value = false;
}
}
onMounted(queryData);
// ---------------------------- 添加/修改 ----------------------------
const formRef = ref();
function showForm(data) {
formRef.value.show(data);
}
// ---------------------------- 单个删除 ----------------------------
//确认删除
function onDelete(data){
Modal.confirm({
title: '提示',
content: '确定要删除选吗?',
okText: '删除',
okType: 'danger',
onOk() {
requestDelete(data);
},
cancelText: '取消',
onCancel() {},
});
}
//请求删除
async function requestDelete(data){
SmartLoading.show();
try {
await caseExchangeApi.delete(data.exchangeId);
message.success('删除成功');
queryData();
} catch (e) {
smartSentry.captureError(e);
} finally {
SmartLoading.hide();
}
}
// ---------------------------- 批量删除 ----------------------------
// 选中的行
const selectedRowKeyList = ref([]);
// 选择变化
function onSelectChange(selectedRowKeys) {
selectedRowKeyList.value = selectedRowKeys;
}
// 确认批量删除
function confirmBatchDelete() {
if (selectedRowKeyList.value.length === 0) {
message.warning('请选择要删除的数据');
return;
}
Modal.confirm({
title: '提示',
content: `确定要删除选中的 ${selectedRowKeyList.value.length} 条数据吗?`,
okText: '删除',
okType: 'danger',
onOk() {
requestBatchDelete();
},
cancelText: '取消',
onCancel() {},
});
}
// 请求批量删除
async function requestBatchDelete() {
SmartLoading.show();
try {
await caseExchangeApi.batchDelete(selectedRowKeyList.value);
message.success('批量删除成功');
selectedRowKeyList.value = [];
queryData();
} catch (e) {
smartSentry.captureError(e);
} finally {
SmartLoading.hide();
}
}
// ---------------------------- 状态切换 ----------------------------
// 获取审核状态文本
function getAuditStatusText(status) {
switch (status) {
case 0: return '待审核';
case 1: return '审核通过';
case 2: return '审核不通过';
default: return '未知';
}
}
// 获取审核状态颜色
function getAuditStatusColor(status) {
switch (status) {
case 0: return 'orange';
case 1: return 'green';
case 2: return 'red';
default: return 'default';
}
}
// 权限检查
function hasPermission(permission) {
// 这里应该根据实际的权限系统来实现
// 暂时返回true您需要根据实际情况修改
return true;
}
// 显示审核弹窗
function showAuditModal(record) {
Modal.confirm({
title: '审核病例交流',
content: `确定要将"${record.exchangeTitle}"标记为审核通过吗`,
okText: '审核通过',
okType: 'primary',
cancelText: '取消',
onOk() {
updateAuditStatus(record, 1);
},
onCancel() {},
});
}
// 更新审核状态
async function updateAuditStatus(record, auditStatus) {
try {
await caseExchangeApi.updateAuditStatus(record.exchangeId, auditStatus);
record.auditStatus = auditStatus;
message.success('审核状态更新成功');
} catch (e) {
smartSentry.captureError(e);
message.error('审核状态更新失败');
}
}
// 状态切换
async function onStatusChange(record, checked) {
try {
record.statusLoading = true;
const newStatus = checked ? 1 : 2;
await caseExchangeApi.updateStatus(record.exchangeId, newStatus);
record.exchangeStatus = newStatus;
message.success('状态更新成功');
} catch (e) {
smartSentry.captureError(e);
// 恢复原状态
record.exchangeStatus = checked ? 2 : 1;
} finally {
record.statusLoading = false;
}
}
// 精选状态切换
async function onSelectedChange(record, checked) {
try {
record.selectedLoading = true;
const newSelected = checked ? 1 : 0;
await caseExchangeApi.updateSelected(record.exchangeId, newSelected);
record.isSelected = newSelected;
message.success('精选状态更新成功');
} catch (e) {
smartSentry.captureError(e);
// 恢复原状态
record.isSelected = checked ? 1 : 0;
} finally {
record.selectedLoading = false;
}
}
</script>
<style scoped>
.text-wrap {
word-break: break-all;
white-space: pre-wrap;
line-height: 1.4;
}
.label-list-display {
display: flex;
flex-direction: column;
gap: 2px;
}
.label-item-display {
display: flex;
flex-direction: column;
gap: 1px;
}
.label-item-display .label-name {
font-weight: 500;
color: #1890ff;
font-size: 12px;
}
</style>