Compare commits

...

4 Commits

Author SHA1 Message Date
卢会旭 ab87fa37ce 1、提示词管理模块
2、设置病例提示词模块
4 months ago
卢会旭 d09210a735 1、增加提示词模板设置
2、生成数字人功能模块
4 months ago
卢会旭 109b526cab 1、修改测试问题 4 months ago
卢会旭 09968731b2 1、修改测试问题 4 months ago

@ -8,4 +8,4 @@ VITE_PUBLIC_PATH = ./
VITE_ROUTER_HISTORY = "hash"
# 开发环境后端地址
VITE_APP_BASE_URL = 'http://192.168.10.13:8000'
VITE_APP_BASE_URL = 'http://192.168.1.113:8891'

5
.gitignore vendored

@ -1,6 +1,7 @@
node_modules
npm cache clean --forcenode_modules
.DS_Store
dist
dist.*
dist-ssr
*.local
.eslintcache
@ -18,4 +19,4 @@ tests/**/coverage/
*.ntvs*
*.njsproj
*.sln
tsconfig.tsbuildinfo
tsconfig.tsbuildinfo

@ -1,6 +0,0 @@
#!/bin/sh
# shellcheck source=./_/husky.sh
. "$(dirname "$0")/_/husky.sh"
npx --no-install commitlint --edit "$1"

@ -1,9 +0,0 @@
#!/bin/sh
command_exists () {
command -v "$1" >/dev/null 2>&1
}
# Workaround for Windows 10, Git Bash and Pnpm
if command_exists winpty && test -t 1; then
exec < /dev/tty
fi

@ -1,8 +0,0 @@
module.exports = {
"*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"],
"{!(package)*.json}": ["prettier --write--parser json"],
"package.json": ["prettier --write"],
"*.vue": ["eslint --fix", "prettier --write", "stylelint --fix"],
"*.{vue,css,scss,postcss,less}": ["stylelint --fix", "prettier --write"],
"*.md": ["prettier --write"]
};

@ -1,10 +0,0 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
. "$(dirname "$0")/common.sh"
[ -n "$CI" ] && exit 0
# Format and submit code according to lintstagedrc.js configuration
npm run lint:lint-staged
npm run lint:pretty

@ -1,18 +0,0 @@
{
"recommendations": [
"christian-kohler.path-intellisense",
"vscode-icons-team.vscode-icons",
"davidanson.vscode-markdownlint",
"ms-azuretools.vscode-docker",
"stylelint.vscode-stylelint",
"bradlc.vscode-tailwindcss",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"redhat.vscode-yaml",
"csstools.postcss",
"mikestead.dotenv",
"eamodio.gitlens",
"antfu.iconify",
"Vue.volar"
]
}

@ -1,31 +0,0 @@
{
"editor.formatOnType": true,
"editor.formatOnSave": true,
"[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"editor.tabSize": 2,
"editor.formatOnPaste": true,
"editor.guides.bracketPairs": "active",
"files.autoSave": "off",
"git.confirmSync": false,
"workbench.startupEditor": "newUntitledFile",
"editor.suggestSelection": "first",
"editor.acceptSuggestionOnCommitCharacter": false,
"css.lint.propertyIgnoredDueToDisplay": "ignore",
"editor.quickSuggestions": {
"other": true,
"comments": true,
"strings": true
},
"files.associations": {
"editor.snippetSuggestions": "top"
},
"[css]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"iconify.excludes": ["el"]
}

@ -1,22 +0,0 @@
{
"Vue3.0快速生成模板": {
"scope": "vue",
"prefix": "Vue3.0",
"body": [
"<template>",
"\t<div>test</div>",
"</template>\n",
"<script lang='ts'>",
"export default {",
"\tsetup() {",
"\t\treturn {}",
"\t}",
"}",
"</script>\n",
"<style lang='scss' scoped>\n",
"</style>",
"$2"
],
"description": "Vue3.0"
}
}

@ -1,17 +0,0 @@
{
"Vue3.2+快速生成模板": {
"scope": "vue",
"prefix": "Vue3.2+",
"body": [
"<script setup lang='ts'>",
"</script>\n",
"<template>",
"\t<div>test</div>",
"</template>\n",
"<style lang='scss' scoped>\n",
"</style>",
"$2"
],
"description": "Vue3.2+"
}
}

@ -1,20 +0,0 @@
{
"Vue3.3+defineOptions快速生成模板": {
"scope": "vue",
"prefix": "Vue3.3+",
"body": [
"<script setup lang='ts'>",
"defineOptions({",
"\tname: ''",
"})",
"</script>\n",
"<template>",
"\t<div>test</div>",
"</template>\n",
"<style lang='scss' scoped>\n",
"</style>",
"$2"
],
"description": "Vue3.3+defineOptions快速生成模板"
}
}

@ -8,7 +8,7 @@ import { configCompressPlugin } from "./compress";
// import ElementPlus from "unplugin-element-plus/vite";
import { visualizer } from "rollup-plugin-visualizer";
import removeConsole from "vite-plugin-remove-console";
import themePreprocessorPlugin from "@pureadmin/theme";
import { themePreprocessorPlugin } from "@pureadmin/theme";
import { genScssMultipleScopeVars } from "../src/layout/theme";
export function getPluginsList(

Binary file not shown.

@ -141,5 +141,6 @@
"stable": "*"
}
},
"license": "MIT"
"license": "MIT",
"packageManager": "pnpm@9.9.0+sha512.60c18acd138bff695d339be6ad13f7e936eea6745660d4cc4a776d5247c540d0edee1a563695c183a66eb917ef88f2b4feb1fc25f32a7adcadc7aaf3438e99c1"
}

File diff suppressed because it is too large Load Diff

@ -127,3 +127,53 @@ export const talkRasa = (data?: object) => {
data
});
};
/** 查询提示词列表 */
export const queryMedicalRecAiManage = (data?: object) => {
return http.request(
"get",
"/virtual-patient-manage/medicalRecAiManage/query",
{
params: data
}
);
};
/** 新增提示词 */
export const createMedicalRecAiManage = (data?: object) => {
return http.request(
"post",
"/virtual-patient-manage/medicalRecAiManage/create",
{
data
}
);
};
/** 修改提示词 */
export const modifyMedicalRecAiManage = (data?: object) => {
return http.request(
"put",
"/virtual-patient-manage/medicalRecAiManage/modify",
{
data
}
);
};
/** 删除提示词 */
export const deleteMedicalRecAiManage = (data?: object) => {
return http.request(
"get",
"/virtual-patient-manage/medicalRecAiManage/delete",
{
params: data
}
);
};
/** 查询模板列表 */
export const queryMedicalPromptStats = (data?: object) => {
return http.request(
"get",
"/virtual-patient-manage/medicalRecManage/queryMedicalPromptStats",
{
params: data
}
);
};

@ -10,6 +10,16 @@ export const queryDiseaseListByDropList = (data?: object) => {
}
);
};
/** 下载病历导入模板 */
export const downloadMedicalTemplate = (data?: object) => {
return http.request(
"get",
"/virtual-patient-manage/medicalRecManage/downloadMedicalTemplate",
{
params: data
}
);
};
/** 病历管理分页查询 */
export const queryMedicalRecPage = (data?: object) => {
return http.request(
@ -110,3 +120,39 @@ export const modifyMedicalRec = (data?: object) => {
}
);
};
/** 导入病历 */
export const uploadMedical = (data?: object) => {
return http.request(
"post",
"/virtual-patient-manage/medicalRecManage/uploadMedical",
{
data,
headers: {
"Content-Type": "multipart/form-data"
}
}
);
};
/** 生成数字人 */
export const createHuman = (data?: object) => {
return http.request(
"post",
"/virtual-patient-manage/humanManage/createHuman",
{
data,
headers: {
"Content-Type": "multipart/form-data"
}
}
);
};
/** 设置提示词模板 */
export const uploadMedicalAiById = (data?: object) => {
return http.request(
"put",
"/virtual-patient-manage/medicalRecManage/uploadMedicalAiById",
{
data
}
);
};

@ -29,6 +29,17 @@ export default {
showParent: true,
roles: ["admin", "common"]
}
},
{
path: "/generalRules/promptManage",
name: "PromptManage",
component: () => import("@/views/generalRules/promptManage/index.vue"),
meta: {
title: "提示词管理 ",
showLink: true,
showParent: true,
roles: ["admin", "common"]
}
}
]
} as RouteConfigsTable;

@ -33,6 +33,10 @@ const columns: TableColumnList = [
return requireCheckFlag === 0 ? "否" : "是";
}
},
{
label: "诊断依据",
prop: "diagnosticCriteriaName"
},
{
label: "预期诊断结果",
prop: "expectedDiagnosisResult",

@ -1,6 +1,6 @@
<script setup lang="ts">
import router from "@/router";
import { PaginationProps } from "@pureadmin/table";
import { PaginationProps, PureTable } from "@pureadmin/table";
import AddEdit from "./compontents/addEdit.vue";
import ProblemBase from "./compontents/problemBase.vue";
import { reactive, ref } from "vue";
@ -18,6 +18,19 @@ const loading = ref(false);
const addEditRef = ref(null);
const AddComplexDiseasesRef = ref();
const problemBaseRef = ref(null);
const errorTableGrid = reactive({
columns: [
{ label: "序号", type: "seq" },
{ label: "类目编码", prop: "code" },
{ label: "疾病分类名称", prop: "diseaseName" },
{ label: "错误信息", prop: "errorMsg" }
],
data: []
});
const errorDialog = reactive({
show: false,
title: "错误信息提示"
});
const seachForm = reactive({
diseaseName: "",
diseaseType: ""
@ -207,8 +220,8 @@ onMounted(() => {
><template #operation="{ row }">
<el-button link type="primary" @click="edit(row)"> </el-button>
<!-- <el-button link type="primary" @click="inspect(row)">
问诊
</el-button> -->
问诊
</el-button> -->
<el-button link type="primary" @click="openBodyInspect(row)">
体格检查
</el-button>
@ -224,7 +237,20 @@ onMounted(() => {
</template>
</pure-table>
</div>
<!-- 导入错误 -->
<el-dialog v-model="errorDialog.show" :title="errorDialog.title">
<template #default>
<pure-table
:columns="errorTableGrid.columns"
:data="errorTableGrid.data"
:height="500"
:header-cell-style="{
background: 'var(--el-table-row-hover-bg-color)',
color: 'var(--el-text-color-primary)'
}"
/>
</template>
</el-dialog>
<AddEdit @update="getData" ref="addEditRef" />
<ProblemBase ref="problemBaseRef" />
<AddComplexDiseases @update="getData" ref="AddComplexDiseasesRef" />

@ -27,6 +27,10 @@ const columns: TableColumnList = [
return requireCheckFlag === 0 ? "否" : "是";
}
},
{
label: "诊断依据",
prop: "diagnosticCriteriaName"
},
{
label: "预期诊断结果",
prop: "expectedDiagnosisResult",

@ -0,0 +1,247 @@
<!--
* @description: 提示词模板
* @fileName: index
* @author: 17076
* @date: 2024/11/11-上午9:56
* @version: V1.0.0
-->
<template>
<el-drawer
:size="650"
append-to-body
v-model="drawerOption.show"
:show-close="false"
:with-header="false"
:before-close="closeDialog"
custom-class="AddEdit"
>
<div class="AddEdit">
<div class="header-title">
<div class="tip" />
<span>设置提示词模板</span>
</div>
<div class="line" />
<el-form ref="formRef" :model="forms" label-width="80px">
<!-- <el-form-item label="提示词模板" prop="medicalRecordAi">-->
<!-- <el-input-->
<!-- v-model="forms.medicalRecordAi"-->
<!-- type="textarea"-->
<!-- :autosize="{ minRows: 5 }"-->
<!-- placeholder="请输入提示词模板"-->
<!-- />-->
<!-- </el-form-item>-->
<el-form-item label="通用模板" prop="general">
<el-select
v-model="forms.general"
placeholder="请选择通用模板"
@change="selectChange"
style="width: 100%"
clearable
filterable
>
<el-option
v-for="item in templateOptions"
:key="item.id"
:label="item.attributeName"
:value="item.attributeParam"
/>
</el-select>
</el-form-item>
<el-input
v-if="forms.commonModelParam"
v-model="forms.commonModelParam"
type="textarea"
disabled
:autosize="{ minRows: 5 }"
style="margin-bottom: 10px"
/>
<div
v-for="(item, index) in forms.medicalRecCreateListAiManageVOS"
:key="index"
class="property-item"
>
<el-form-item
:label="'属性' + (index + 1)"
:prop="
'medicalRecCreateListAiManageVOS.' + index + '.attributeName'
"
style="margin-top: 20px"
>
<el-select
v-model="item.attributeName"
placeholder="请选择属性模板"
@change="selectChangeProperty(item, $event)"
style="flex: 1"
clearable
filterable
>
<el-option
v-for="item in templatePropertyOptions"
:key="item.id"
:label="item.attributeName"
:value="item.attributeName"
/>
</el-select>
<el-button
plain
type="primary"
style="margin-left: 10px"
@click="addItem()"
>新增</el-button
>
<el-button
plain
type="danger"
:disabled="index === 0"
@click="removeItem(index)"
>删除</el-button
>
</el-form-item>
<el-input
v-if="item.attributeParam"
v-model="item.attributeParam"
type="textarea"
disabled
:autosize="{ minRows: 5 }"
/>
</div>
<!-- <pure-table-->
<!-- align-whole="center"-->
<!-- showOverflowTooltip-->
<!-- table-layout="auto"-->
<!-- adaptive-->
<!-- :data="dataList"-->
<!-- :columns="columns"-->
<!-- :header-cell-style="{-->
<!-- background: 'var(&#45;&#45;el-table-row-hover-bg-color)',-->
<!-- color: 'var(&#45;&#45;el-text-color-primary)'-->
<!-- }"-->
<!-- />-->
</el-form>
</div>
<template #footer>
<el-button plain size="large" @click="reset" style="width: 120px"
>重置</el-button
>
<el-button
type="primary"
size="large"
@click="save(formRef)"
style="width: 120px"
>生成</el-button
>
</template>
</el-drawer>
</template>
<script setup lang="ts">
import { ref } from "vue";
import { FormInstance, ElMessage } from "element-plus";
import { uploadMedicalAiById } from "@/api/medicalRecord";
import { queryMedicalPromptStats } from "@/api/generalRules";
// import PureTable from "@pureadmin/table";
//
const drawerOption = ref({
show: false
});
const formRef = ref<FormInstance>();
const forms = ref({
general: undefined,
commonModelParam: undefined,
medicalRecCreateListAiManageVOS: [
{ attributeParam: undefined, attributeName: undefined }
],
medicalRecId: undefined
});
// const dataList = ref([]);
// const columns = [
// {
// label: "",
// prop: "propertyName",
// minWidth: 100
// },
// {
// label: "",
// prop: "propertyTemplate",
// minWidth: 100
// }
// ];
const templateOptions = ref([]);
const templatePropertyOptions = ref([]);
const emit = defineEmits(["update"]);
//
async function queryTemplateList() {
const res = await queryMedicalPromptStats();
templateOptions.value = res.data.medicalRecAisCommon;
templatePropertyOptions.value = res.data.medicalRecAisPara;
}
//
function selectChange(val) {
forms.value.commonModelParam = val;
}
//
function selectChangeProperty(item, val) {
const currentName = templatePropertyOptions.value.find(
property => property.attributeName === val
).attributeParam;
item.attributeParam = currentName;
}
//
function addItem() {
forms.value.medicalRecCreateListAiManageVOS.push({
attributeParam: undefined,
attributeName: undefined
});
}
//
function removeItem(index) {
forms.value.medicalRecCreateListAiManageVOS.splice(index, 1);
}
//
function closeDialog() {
drawerOption.value.show = false;
reset();
}
//
function reset() {
formRef.value.resetFields();
}
//
function save(formEl: FormInstance | undefined) {
formEl.validate(async valid => {
if (valid) {
const res: any = await uploadMedicalAiById({ ...forms.value, medicalRecId: forms.value.medicalId });
if (res.code === 200) {
ElMessage.success(res.msg || "设置成功!");
drawerOption.value.show = false;
emit.apply("update", [true]);
}
}
});
}
defineExpose({
show(data: any) {
forms.value = Object.assign(
{
medicalRecCreateListAiManageVOS: [
{ attributeParam: undefined, attributeName: undefined }
]
},
data
);
drawerOption.value.show = true;
queryTemplateList();
}
});
</script>
<style scoped lang="scss">
.property-item {
border: 1px solid #cdd0d6;
border-radius: 8px;
padding: 20px 10px;
box-sizing: border-box;
margin-bottom: 10px;
}
</style>

@ -105,7 +105,7 @@ onMounted(() => {
<div class="right">{{ detailInfo.differentialDiagnosisCriteria }}</div>
</div>
<div class="text_item">
<div class="left">全面检查</div>
<div class="left">预期诊断结果</div>
<div class="right">{{ detailInfo.fullCheck }}</div>
</div>
</div>
@ -156,7 +156,7 @@ onMounted(() => {
<span>病历信息</span>
</div>
</template>
</el-collapse-item>
<el-collapse-item name="2">
<template #title>

@ -0,0 +1,159 @@
<!--
* @description: 生成数字人
* @fileName: CreateDigitalHuman
* @author: 17076
* @date: 2024/11/6-上午9:59
* @version: V1.0.0
-->
<script setup lang="ts">
import { ref } from "vue";
import { FormInstance, ElMessage } from "element-plus";
import { Plus } from "@element-plus/icons-vue";
import { createHuman } from "@/api/medicalRecord";
//
const drawerOption = ref({
show: false
});
const formRef = ref<FormInstance>();
const upload = ref();
const forms = ref({
image: undefined,
file: undefined,
medicalId: undefined
});
const rules = ref({
file: [{ required: true, message: "请上传文件", trigger: "blur" }]
});
const emit = defineEmits(["update"]);
//
function closeDialog() {
drawerOption.value.show = false;
reset();
}
//
function reset() {
formRef.value.resetFields();
}
//
function save(formEl: FormInstance | undefined) {
formEl.validate(async valid => {
if (valid) {
const formData = new FormData();
formData.append("file", forms.value.file);
formData.append("medicalId", forms.value.medicalId);
const res: any = await createHuman(formData);
if (res.code === 200) {
ElMessage.success(res.msg || "上传成功,数字人生成中");
drawerOption.value.show = false;
emit.apply("update", [true]);
}
}
});
}
//
const handleOnChange = () => {
upload.value.value = null;
upload.value.click();
};
//
const handleFileChange = e => {
const files = e.target.files;
forms.value.file = files[0];
const render = new FileReader();
render.readAsDataURL(files[0]);
render.onload = result => {
forms.value.image = result.target.result;
};
};
defineExpose({
show(data: any) {
forms.value = Object.assign({}, data);
drawerOption.value.show = true;
}
});
</script>
<template>
<el-drawer
:size="650"
append-to-body
v-model="drawerOption.show"
:show-close="false"
:with-header="false"
:before-close="closeDialog"
custom-class="AddEdit"
>
<div class="AddEdit">
<div class="header-title">
<div class="tip" />
<span>生成数字人</span>
</div>
<div class="line" />
<el-form
ref="formRef"
:model="forms"
:rules="rules"
label-width="80px"
label-position="top"
>
<el-form-item label="上传素材" prop="file">
<div class="avatar-uploader" @click="handleOnChange">
<img v-if="forms.image" :src="forms.image" class="avatar" />
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
<input
ref="upload"
hidden
type="file"
accept=".png,.jpg,.jpeg"
@change="handleFileChange"
/>
</div>
</el-form-item>
</el-form>
</div>
<template #footer>
<el-button plain size="large" @click="reset" style="width: 120px"
>重置</el-button
>
<el-button
type="primary"
size="large"
@click="save(formRef)"
style="width: 120px"
>确定</el-button
>
</template>
</el-drawer>
</template>
<style lang="scss">
.AddEdit {
.avatar-uploader {
width: 178px;
height: 178px;
display: block;
border: 1px dashed var(--el-border-color);
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: var(--el-transition-duration-fast);
&:hover {
border-color: var(--el-color-primary);
}
.avatar {
object-fit: contain;
}
}
.el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
text-align: center;
}
.el-drawer__body {
overflow-x: hidden;
}
}
</style>

@ -4,11 +4,22 @@ import { PaginationProps } from "@pureadmin/table";
import { reactive, ref } from "vue";
import {
queryDiseaseListByDropList,
queryMedicalRecPage
queryMedicalRecPage,
uploadMedical
} from "@/api/medicalRecord";
import { onMounted } from "vue";
import { clearObject } from "@/utils/auth";
import { useCaseStoreHooks } from "@/store/modules/caseManagement";
import { ElMessage } from "element-plus";
import {
More,
View,
Edit,
User,
ChatLineSquare
} from "@element-plus/icons-vue";
import CreateDigitalHuman from "./digitalHuman/CreateDigitalHuman.vue";
import PromptTemplate from "./PromptTemplate/index.vue";
defineOptions({
name: "CaseManagement"
@ -16,7 +27,9 @@ defineOptions({
const dataList = ref([]);
const loading = ref(false);
const upload = ref(null);
const digital = ref();
const prompt = ref();
const seachForm = reactive({
gender: "",
diseaseId: "",
@ -30,6 +43,12 @@ const pagination = reactive<PaginationProps>({
background: true
});
const columns: TableColumnList = [
{
label: "状态",
prop: "medicalDataStatus",
slot: "status",
minWidth: 100
},
{
label: "病历编号",
prop: "no",
@ -59,6 +78,11 @@ const columns: TableColumnList = [
label: "机构",
prop: "alarmTask"
},
{
label: "提示词模板",
prop: "medicalRecordAi",
minWidth: 200
},
{
label: "更新时间",
prop: "time"
@ -123,6 +147,45 @@ const handleEdit = item => {
}
});
};
//
const handelCreateDigital = row => {
digital.value.show(row);
};
//
const handelPrompt = row => {
prompt.value.show(row);
};
// tagName
const formatterTagName = val => {
let tagName = "";
switch (val) {
case "00":
tagName = "已创建病例";
break;
case "01":
tagName = "数字人生成中";
break;
case "02":
tagName = "完成";
break;
}
return tagName;
};
const formatterType = val => {
let tagName = "";
switch (val) {
case "00":
tagName = "primary";
break;
case "01":
tagName = "warning";
break;
case "02":
tagName = "success";
break;
}
return tagName;
};
// const handleDelete = item => {
// ElMessageBox.confirm(
// item ? `, ` : "",
@ -145,6 +208,40 @@ onMounted(() => {
getData();
useCaseStoreHooks().changeActivedStep(0);
});
const downloadFile = (url, fileName) => {
const link = document.createElement("a");
link.href = url;
link.download = fileName;
link.click();
};
//
const handleDownload = () => {
downloadFile(
"/virtual-patient-manage/medicalRecManage/downloadMedicalTemplate",
"病历导入模版"
);
};
//
const handleImport = () => {
upload.value.value = null;
upload.value.click();
};
//
const handleFileChange = e => {
const files = e.target.files;
const rawFile = files[0];
if (!rawFile) return;
const formData = new FormData();
formData.append("multipartFile", rawFile);
// errorDialog.show = true;
uploadMedical(formData).then(res => {
res.code === 200
? ElMessage.success(res.msg || "导入成功")
: ElMessage.error(res.msg || "导入失败!");
getData();
});
};
</script>
<template>
@ -198,6 +295,20 @@ onMounted(() => {
</div>
<el-row class="mb-6">
<el-button size="large" @click="add" type="primary">新增</el-button>
<el-button size="large" type="warning" @click="handleDownload">
模板下载
</el-button>
<el-button size="large" type="success" @click="handleImport">
模板导入
</el-button>
<!--文件导入-->
<input
ref="upload"
hidden
type="file"
accept=".xls,.xlsx"
@change="handleFileChange"
/>
</el-row>
</div>
<pure-table
@ -215,18 +326,72 @@ onMounted(() => {
}"
@page-size-change="handleSizeChange"
@page-current-change="handleCurrentChange"
><template #operation="{ row }">
<el-button link type="primary" @click="openDetail(row)">
详情
</el-button>
<el-button link type="primary" @click="handleEdit(row)">
编辑
</el-button>
<!-- <el-button link type="danger" @click="handleDelete(row)">
删除
</el-button> -->
>
<template #operation="{ row }">
<el-popover trigger="hover" placement="left-start">
<template #reference>
<el-icon size="17"><More /></el-icon>
</template>
<template #default>
<el-row>
<el-col :span="24">
<el-button
link
type="primary"
:icon="View"
@click="openDetail(row)"
>详情</el-button
>
</el-col>
<el-col style="margin-top: 10px">
<el-button
link
type="primary"
:icon="Edit"
@click="handleEdit(row)"
>
编辑
</el-button>
</el-col>
<el-col
:span="24"
v-if="row.medicalDataStatus === '00'"
style="margin-top: 10px"
>
<el-button
link
type="primary"
:icon="User"
@click="handelCreateDigital(row)"
>生成数字人</el-button
>
</el-col>
<el-col :span="24" style="margin-top: 10px">
<el-button
link
type="primary"
:icon="ChatLineSquare"
@click="handelPrompt(row)"
>提示词模板</el-button
>
</el-col>
</el-row>
<!-- <el-button link type="danger" @click="handleDelete(row)">
删除
</el-button> -->
</template>
</el-popover>
</template>
<template #status="{ row }">
<el-tag :type="formatterType(row.medicalDataStatus)">{{
formatterTagName(row.medicalDataStatus)
}}</el-tag>
</template>
</pure-table>
</div>
<!--生成数字人-->
<create-digital-human ref="digital" @update="getData" />
<!--设置提示词-->
<prompt-template ref="prompt" @update="getData" />
</div>
</template>

@ -76,13 +76,13 @@ onMounted(() => {
</el-form-item>
</el-row>
<el-row>
<el-form-item label="全面检查" prop="fullCheck">
<el-form-item label="预期诊断结果" prop="fullCheck">
<el-input
:rows="4"
style="width: 500px"
type="textarea"
:maxLength="500"
placeholder="请输入全面检查"
placeholder="请输入预期诊断结果"
v-model="diagnosticBasisInfo.fullCheck"
/>
</el-form-item>

@ -147,6 +147,9 @@ onMounted(() => {
>
{{ item.diseaseName }}
</div>
<div>
{{ state.dataInfo.fullCheck ? state.dataInfo.fullCheck : "" }}
</div>
</el-tab-pane>
<el-tab-pane name="2">
<template #label>

@ -0,0 +1,143 @@
<!--
* @description: 编辑提示词
* @fileName: EditPrompt
* @author: 17076
* @date: 2024/11/14-上午9:40
* @version: V1.0.0
-->
<template>
<el-drawer
:size="800"
append-to-body
v-model="dialogVisible"
:show-close="false"
:with-header="false"
:before-close="closeDialog"
custom-class="AddEdit"
>
<div class="AddEdit">
<div class="header-title">
<div class="tip" />
<span>编辑提示词</span>
</div>
<div class="line" />
<el-form
ref="refForm"
:model="formData"
:rules="rules"
label-width="100px"
>
<el-form-item label="模板类型" prop="commonType">
<el-select
v-model="formData.commonType"
placeholder="请选择模板类型"
style="width: 100%"
:disabled="isEditFlag"
>
<el-option
v-for="item in typeOptions"
:key="item.value"
:value="item.value"
:label="item.label"
/>
</el-select>
</el-form-item>
<el-form-item label="提示词名称" prop="attributeName">
<el-input
v-model="formData.attributeName"
placeholder="请输入提示词名称"
/>
</el-form-item>
<el-form-item label="提示词" prop="attributeParam">
<el-input
v-model="formData.attributeParam"
type="textarea"
:rows="5"
placeholder="请输入提示词"
/>
</el-form-item>
</el-form>
</div>
<template #footer>
<div class="footer_btn">
<div class="reset" @click="resetForm"></div>
<div class="main" @click="submit(refForm)"></div>
</div>
</template>
</el-drawer>
</template>
<script setup lang="ts">
import { ref } from "vue";
import { FormInstance } from "element-plus";
import {
createMedicalRecAiManage,
modifyMedicalRecAiManage
} from "@/api/generalRules";
import { message } from "@/utils/message";
const isEditFlag = ref(false);
const dialogVisible = ref(false);
const formData = ref({
commonType: "",
attributeName: "",
attributeParam: ""
});
const typeOptions = [
{ label: "通用模板", value: "00" },
{ label: "属性模板", value: "01" }
];
const refForm = ref<FormInstance>();
const rules = {
commonType: [
{ required: true, message: "模板类型不能为空!", trigger: "blur" }
],
attributeName: [
{ required: true, message: "提示词名称不能为空!", trigger: "blur" }
],
attributeParam: [
{ required: true, message: "提示词不能为空!", trigger: "blur" }
]
};
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.resetFields();
};
const closeDialog = () => {
dialogVisible.value = false;
resetForm();
};
const emit = defineEmits(["update"]);
const submit = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
await formEl.validate(async valid => {
if (valid) {
if (isEditFlag.value) {
const res: any = await modifyMedicalRecAiManage(formData.value);
if (res.code === 200) {
message("修改成功", { type: "success" });
emit("update");
dialogVisible.value = false;
}
} else {
const res = await createMedicalRecAiManage(formData.value);
if (res.code === 200) {
message("新增成功", { type: "success" });
emit("update");
dialogVisible.value = false;
}
}
}
});
};
defineExpose({
show(data, isEdit) {
isEditFlag.value = isEdit;
formData.value = isEdit ? Object.assign({}, data) : {};
dialogVisible.value = true;
}
});
</script>
<style scoped lang="scss"></style>

@ -0,0 +1,167 @@
<!--
* @description: 提示词管理
* @fileName: index
* @author: 17076
* @date: 2024/11/14-上午9:39
* @version: V1.0.0
-->
<template>
<div class="app-main-content">
<div class="seach">
<el-form :model="searchForm">
<el-row>
<el-form-item label="属性名称:">
<el-input size="large" v-model="searchForm.attribute_name" />
</el-form-item>
<el-button class="ml-8" size="large" @click="search" type="primary"
>搜索</el-button
>
<el-button size="large" @click="reset"></el-button>
</el-row>
</el-form>
</div>
<div class="main-table">
<div class="main-table-title">
<div class="title">
<div class="line" />
<span>提示词配置</span>
</div>
<el-row class="mb-6">
<el-button size="large" @click="handleAdd" type="primary"
>新建</el-button
>
</el-row>
</div>
<pure-table
align-whole="center"
show-overflow-tooltip
table-layout="auto"
:loading="loading"
adaptive
:data="dataList"
:columns="columns"
:pagination="pagination"
:header-cell-style="{
background: 'var(--el-table-row-hover-bg-color)',
color: 'var(--el-text-color-primary)'
}"
@page-size-change="handleSizeChange"
@page-current-change="handleCurrentChange"
>
<template #operation="{ row }">
<el-button link type="primary" @click="handleEdit(row)"
>编辑</el-button
>
<el-button link type="danger" @click="handleDelete(row)"
>删除</el-button
>
</template>
</pure-table>
</div>
<!--编辑提示词-->
<edit-prompt ref="edit" @update="getData" />
</div>
</template>
<script setup lang="ts">
import { onMounted, reactive, ref } from "vue";
import { PaginationProps } from "@pureadmin/table";
import {
deleteMedicalRecAiManage,
queryMedicalRecAiManage
} from "@/api/generalRules";
import EditPrompt from "@/views/generalRules/promptManage/components/EditPrompt.vue";
import { ElMessageBox } from "element-plus";
import { message } from "@/utils/message";
const dataList = ref([{}]);
const loading = ref(false);
const edit = ref(null);
const searchForm = reactive({
attribute_name: ""
});
const pagination = reactive<PaginationProps>({
total: 0,
pageSize: 10,
currentPage: 1,
background: true
});
const columns: TableColumnList = [
{
label: "类型",
prop: "commonName",
minWidth: 240
},
{
label: "属性名称",
prop: "attributeName",
minWidth: 240
},
{
label: "提示词",
prop: "attributeParam",
minWidth: 240
},
{
label: "操作",
fixed: "right",
slot: "operation"
}
];
const getData = async () => {
const params = {
pageNum: pagination.currentPage,
pageSize: pagination.pageSize,
...searchForm
};
const res: any = await queryMedicalRecAiManage(params);
dataList.value = res.data.records;
pagination.total = res.data.total;
};
function handleSizeChange(val: number) {
pagination.pageSize = val;
getData();
}
function handleCurrentChange(val: number) {
pagination.currentPage = val;
getData();
}
const search = () => {
pagination.currentPage = 1;
pagination.pageSize = 10;
getData();
};
const reset = () => {
seachForm.description = "";
seachForm.similarityDescription = "";
search();
};
const handleAdd = () => {
edit.value.show(undefined, false);
};
const handleEdit = item => {
edit.value.show(item, true);
};
//
const handleDelete = item => {
ElMessageBox.confirm("确定删除此项吗?", "提示", {
confirmButtonText: "确定",
callback: async () => {
const res = await deleteMedicalRecAiManage({ id: item.id });
res.code === 200
? message(res.msg || "删除成功!", { type: "success" })
: message(res.msg || "删除失败!", { type: "error" });
await getData();
}
});
};
onMounted(() => {
getData();
});
</script>
<style scoped lang="scss"></style>

@ -17,7 +17,8 @@ const formData = reactive({
dictId: "",
dicIdPath: [],
description: "",
defaultAnswer: ""
defaultAnswer: "",
question: ""
});
const dictList = ref([]);
const ruleFormRef = ref<FormInstance>();
@ -174,13 +175,21 @@ const submit = (formEl: FormInstance | undefined) => {
:fetch-suggestions="querySearchAsync"
/>
</el-form-item>
<el-form-item label="回答 " prop="defaultAnswer">
<el-form-item v-if="isEditFlag" label="相似问题" prop="question">
<el-input
size="large"
v-model="formData.defaultAnswer"
placeholder="请输入"
v-model="formData.question"
type="textarea"
:rows="5"
disabled
/>
</el-form-item>
<!-- <el-form-item label="回答 " prop="defaultAnswer">-->
<!-- <el-input-->
<!-- size="large"-->
<!-- v-model="formData.defaultAnswer"-->
<!-- placeholder="请输入"-->
<!-- />-->
<!-- </el-form-item>-->
</el-form>
</div>
<template #footer>

@ -16,7 +16,8 @@ const dataList = ref([{}]);
const loading = ref(false);
const AddEditRef = ref(null);
const seachForm = reactive({
description: ""
description: "",
similarityDescription: ""
});
const pagination = reactive<PaginationProps>({
total: 0,
@ -34,12 +35,13 @@ const columns: TableColumnList = [
{
label: "问题",
prop: "description",
minWidth: 240
},
{
label: "回复",
prop: "defaultAnswer"
minWidth: 240,
slot: "question"
},
// {
// label: "",
// prop: "defaultAnswer"
// },
{
label: "操作",
fixed: "right",
@ -50,7 +52,7 @@ const getData = async () => {
const params = {
pageNum: pagination.currentPage,
pageSize: pagination.pageSize,
description: seachForm.description
...seachForm
};
const res: any = await queryPageList(params);
dataList.value = res.data.records;
@ -73,6 +75,7 @@ const search = () => {
const reset = () => {
seachForm.description = "";
seachForm.similarityDescription = "";
search();
};
const add = () => {
@ -103,6 +106,9 @@ onMounted(() => {
<el-form-item label="问题:">
<el-input size="large" v-model="seachForm.description" />
</el-form-item>
<el-form-item label="相似问题:" style="margin-left: 10px">
<el-input size="large" v-model="seachForm.similarityDescription" />
</el-form-item>
<el-button class="ml-8" size="large" @click="search" type="primary"
>搜索</el-button
@ -129,7 +135,7 @@ onMounted(() => {
</div>
<pure-table
align-whole="center"
showOverflowTooltip
show-overflow-tooltip
table-layout="auto"
:loading="loading"
adaptive
@ -142,7 +148,23 @@ onMounted(() => {
}"
@page-size-change="handleSizeChange"
@page-current-change="handleCurrentChange"
><template #operation="{ row }">
>
<template #question="{ row }">
<div>{{ row["description"] }}</div>
<el-tooltip>
<el-button link type="primary">[相似问题]</el-button>
<template #content>
<div class="tooltip-content">
{{
row.question && row.question.length > 0
? row.question.join(",")
: "无"
}}
</div>
</template>
</el-tooltip>
</template>
<template #operation="{ row }">
<el-button link type="primary" @click="edit(row)"></el-button>
</template>
</pure-table>
@ -151,3 +173,10 @@ onMounted(() => {
<UploadFile @update="getData" ref="UploadFileref" />
</div>
</template>
<style lang="scss" scoped>
.tooltip-content {
max-width: 400px;
max-height: 500px;
overflow: hidden auto;
}
</style>

@ -169,7 +169,7 @@ onMounted(() => {
<el-collapse-item name="6">
<template #title>
<div class="title">
<span>全面检查</span>
<span>预期诊断结果</span>
</div>
</template>
</el-collapse-item>

@ -221,6 +221,7 @@ const activeName = ref("");
>
{{ item.diseaseName }}
</div>
<div style="margin-top: 10px">{{ state.dataInfo?.fullCheck }}</div>
</div>
</el-tab-pane>
<el-tab-pane label="初步诊断依据" name="4">
@ -337,6 +338,7 @@ const activeName = ref("");
/>
</div>
</div>
<!-- <div>{{ state.dataInfo.dealPan }}</div>-->
</div>
</el-tab-pane>
</el-tabs>

@ -46,28 +46,28 @@ export default ({ command, mode }: ConfigEnv): UserConfigExport => {
proxy: {
// 类型: Record<string, string | ProxyOp 为开发服务器配置自定义代理规则
"/virtual-patient-manage/": {
target: "http://192.168.10.137:8891/",
target: "http://192.168.1.113:8891/",
changeOrigin: true,
secure: false
// eslint-disable-next-line no-shadow
// rewrite: path => path.replace("/ask", "")
},
"/virtual-patient/": {
target: "http://192.168.10.137:8899/",
target: "http://192.168.1.113:8899/",
changeOrigin: true,
secure: false
// eslint-disable-next-line no-shadow
// rewrite: path => path.replace("/ask", "")
},
"/virtual-patient-rasa/": {
target: "http://192.168.10.137:8890/",
target: "http://192.168.10.113:8890/",
changeOrigin: true,
secure: false
// eslint-disable-next-line no-shadow
// rewrite: path => path.replace("/ask", "")
},
"/virtual-patient-graph/": {
target: "http://192.168.10.137:8892/",
target: "http://192.168.10.113:8892/",
changeOrigin: true,
secure: false
// eslint-disable-next-line no-shadow

Loading…
Cancel
Save