leiyun 15 часов назад
Родитель
Сommit
8570c7e610
3 измененных файлов: 86 добавлений и 9 удалений
  1. +20
    -0
      src/controller/admin/patient.js
  2. +2
    -1
      src/controller/admin/system/role.js
  3. +64
    -8
      view/admin/patient_index.html

+ 20
- 0
src/controller/admin/patient.js Просмотреть файл

@@ -13,6 +13,7 @@ module.exports = class extends Base {
this.assign('canExport', this.isSuperAdmin || (this.userPermissions || []).includes('patient:export')); this.assign('canExport', this.isSuperAdmin || (this.userPermissions || []).includes('patient:export'));
this.assign('canAudit', this.isSuperAdmin || (this.userPermissions || []).includes('patient:audit')); this.assign('canAudit', this.isSuperAdmin || (this.userPermissions || []).includes('patient:audit'));
this.assign('canView', this.isSuperAdmin || (this.userPermissions || []).includes('patient:view')); this.assign('canView', this.isSuperAdmin || (this.userPermissions || []).includes('patient:view'));
this.assign('canDelete', this.isSuperAdmin || (this.userPermissions || []).includes('patient:delete'));
return this.display(); return this.display();
} }


@@ -275,6 +276,25 @@ module.exports = class extends Base {
return this.success(); return this.success();
} }


// 删除患者(软删除,支持批量)
async deleteAction() {
const { ids } = this.post();
if (!ids || !ids.length) return this.fail('参数错误');

const model = this.model('patient');
const patients = await model.where({ id: ['in', ids], is_deleted: 0 }).select();
if (!patients.length) return this.fail('患者不存在');

await model.where({ id: ['in', ids] }).update({
is_deleted: 1,
update_by: this.adminUser?.id || 0
});

const names = patients.map(p => p.name).join('、');
await this.log('delete', '患者管理', `删除患者「${names}」共${patients.length}条`);
return this.success();
}

// 编辑患者 // 编辑患者
async editAction() { async editAction() {
const data = this.post(); const data = this.post();


+ 2
- 1
src/controller/admin/system/role.js Просмотреть файл

@@ -255,7 +255,8 @@ module.exports = class extends Base {
{ name: '新增', key: 'patient:add' }, { name: '新增', key: 'patient:add' },
{ name: '编辑', key: 'patient:edit' }, { name: '编辑', key: 'patient:edit' },
{ name: '导出', key: 'patient:export' }, { name: '导出', key: 'patient:export' },
{ name: '审核', key: 'patient:audit' }
{ name: '审核', key: 'patient:audit' },
{ name: '删除', key: 'patient:delete' }
] ]
}, },
{ {


+ 64
- 8
view/admin/patient_index.html Просмотреть файл

@@ -34,6 +34,7 @@
<div style="display:flex;gap:8px;margin-top:12px;"> <div style="display:flex;gap:8px;margin-top:12px;">
<el-button v-if="perms.canAdd" type="success" :icon="Plus" @click="showAddDialog">新增患者</el-button> <el-button v-if="perms.canAdd" type="success" :icon="Plus" @click="showAddDialog">新增患者</el-button>
<el-button v-if="perms.canExport" :icon="Download" @click="handleExport" :loading="exporting">导出</el-button> <el-button v-if="perms.canExport" :icon="Download" @click="handleExport" :loading="exporting">导出</el-button>
<el-button v-if="perms.canDelete && selectedIds.length" type="danger" :icon="Delete" @click="handleBatchDelete">批量删除 (${ selectedIds.length })</el-button>
</div> </div>
</el-card> </el-card>


@@ -57,7 +58,8 @@
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>


<el-table :data="tableData" v-loading="loading" stripe border>
<el-table :data="tableData" v-loading="loading" stripe border @selection-change="onSelectionChange">
<el-table-column v-if="perms.canDelete" type="selection" width="45"></el-table-column>
<el-table-column prop="patient_no" label="编号" min-width="200"></el-table-column> <el-table-column prop="patient_no" label="编号" min-width="200"></el-table-column>
<el-table-column prop="name" label="姓名" min-width="80"></el-table-column> <el-table-column prop="name" label="姓名" min-width="80"></el-table-column>
<el-table-column label="身份证号" min-width="180"> <el-table-column label="身份证号" min-width="180">
@@ -86,11 +88,12 @@
<el-tag v-else-if="row.status === 2" type="danger" size="small">已驳回</el-tag> <el-tag v-else-if="row.status === 2" type="danger" size="small">已驳回</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" width="200" align="center" fixed="right">
<el-table-column label="操作" width="240" align="center" fixed="right">
<template #default="{ row }"> <template #default="{ row }">
<el-button type="primary" link @click="viewDetail(row)">查看详情</el-button> <el-button type="primary" link @click="viewDetail(row)">查看详情</el-button>
<el-button v-if="perms.canEdit" type="info" link @click="showEditDialog(row)">编辑</el-button> <el-button v-if="perms.canEdit" type="info" link @click="showEditDialog(row)">编辑</el-button>
<el-button v-if="row.status === 0 && perms.canAudit" type="warning" link @click="viewDetail(row)">去审核</el-button> <el-button v-if="row.status === 0 && perms.canAudit" type="warning" link @click="viewDetail(row)">去审核</el-button>
<el-button v-if="perms.canDelete" type="danger" link @click="handleDelete(row)">删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@@ -254,14 +257,15 @@
{% block js %} {% block js %}
<script> <script>
const { createApp, ref, reactive, onMounted, computed } = Vue; const { createApp, ref, reactive, onMounted, computed } = Vue;
const { Plus, Download } = ElementPlusIconsVue;
const { Plus, Download, Delete } = ElementPlusIconsVue;


const perms = { const perms = {
canAdd: {{ canAdd | dump | safe }}, canAdd: {{ canAdd | dump | safe }},
canEdit: {{ canEdit | dump | safe }}, canEdit: {{ canEdit | dump | safe }},
canExport: {{ canExport | dump | safe }}, canExport: {{ canExport | dump | safe }},
canAudit: {{ canAudit | dump | safe }}, canAudit: {{ canAudit | dump | safe }},
canView: {{ canView | dump | safe }}
canView: {{ canView | dump | safe }},
canDelete: {{ canDelete | dump | safe }}
}; };


const app = createApp({ const app = createApp({
@@ -374,6 +378,58 @@ const app = createApp({
loadList(); loadList();
} }


// 多选
const selectedIds = ref([]);
function onSelectionChange(rows) {
selectedIds.value = rows.map(function(r) { return r.id; });
}

// 单条删除
async function handleDelete(row) {
try {
await ElementPlus.ElMessageBox.confirm(
'确定要删除患者「' + row.name + '」吗?删除后不可恢复。',
'确认删除',
{ confirmButtonText: '确认删除', cancelButtonText: '取消', type: 'warning' }
);
var res = await fetch('/admin/patient/delete', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ids: [row.id] })
}).then(function(r) { return r.json(); });
if (res.code === 0) {
ElementPlus.ElMessage.success('删除成功');
loadList();
} else {
ElementPlus.ElMessage.error(res.msg || '删除失败');
}
} catch(e) {}
}

// 批量删除
async function handleBatchDelete() {
if (!selectedIds.value.length) return;
try {
await ElementPlus.ElMessageBox.confirm(
'确定要删除选中的 ' + selectedIds.value.length + ' 条患者记录吗?删除后不可恢复。',
'批量删除确认',
{ confirmButtonText: '确认删除', cancelButtonText: '取消', type: 'warning' }
);
var res = await fetch('/admin/patient/delete', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ids: selectedIds.value })
}).then(function(r) { return r.json(); });
if (res.code === 0) {
ElementPlus.ElMessage.success('删除成功');
selectedIds.value = [];
loadList();
} else {
ElementPlus.ElMessage.error(res.msg || '删除失败');
}
} catch(e) {}
}

function viewDetail(row) { function viewDetail(row) {
if (!perms.canView) { if (!perms.canView) {
ElementPlus.ElMessageBox.alert('暂无查看详情权限,请先联系管理员授权', '温馨提示', { ElementPlus.ElMessageBox.alert('暂无查看详情权限,请先联系管理员授权', '温馨提示', {
@@ -542,10 +598,10 @@ const app = createApp({


return { return {
keyword, dateRange, tagFilter, regionFilter, activeTab, loading, tableData, pagination, counts, keyword, dateRange, tagFilter, regionFilter, activeTab, loading, tableData, pagination, counts,
uploadHeaders, addVisible, addSaving, addForm, exporting, editingId, perms,
regionTree, tagOptions, isMinorComputed, Plus, Download,
loadList, resetFilter, onTabChange, onSizeChange, viewDetail, showAddDialog, showEditDialog, handleExport,
onIdCardInput, onDocUpload, onSignUpload, submitAdd
uploadHeaders, addVisible, addSaving, addForm, exporting, editingId, perms, selectedIds,
regionTree, tagOptions, isMinorComputed, Plus, Download, Delete,
loadList, resetFilter, onTabChange, onSizeChange, onSelectionChange, viewDetail, showAddDialog, showEditDialog, handleExport,
onIdCardInput, onDocUpload, onSignUpload, submitAdd, handleDelete, handleBatchDelete
}; };
} }
}); });


Загрузка…
Отмена
Сохранить