Procházet zdrojové kódy

总后台增加商城处方-未开放数据统计

cgp před 1 dnem
rodič
revize
0054f21e3c

+ 13 - 0
src/api/his/scrmPrescribe.js

@@ -49,3 +49,16 @@ export function getPrescribeInfoByOrderCode(orderCode) {
     params: { orderCode }
   })
 }
+
+/**
+ * 获取医生不开方列表
+ * @param {Object} query - { patientName, doctorId, beginTime, endTime, pageNum, pageSize }
+ * @returns {Promise}
+ */
+export function doctorNotPrescribeList(query) {
+  return request({
+    url: '/his/prescribeDataScrm/doctorNotPrescribeList',
+    method: 'post',
+    data: query
+  });
+}

+ 430 - 0
src/views/his/statistics/doctorNotPrescribeStats/doctorNotPrescribeDetail.vue

@@ -0,0 +1,430 @@
+<template>
+  <el-dialog
+    title="详情"
+    :visible.sync="dialogVisible"
+    width="1000px"
+    top="5vh"
+    :close-on-click-modal="false"
+    @close="handleClose"
+  >
+    <!-- 医生不开方理由(只读) -->
+    <div class="not-prescribe-reason-section">
+      <el-form label-width="120px" size="small">
+        <el-form-item label="不开方理由:">
+          <el-input
+            type="textarea"
+            :value="notPrescribeReason"
+            readonly
+            disabled
+            :rows="3"
+            style="color: #1a1a1a; background-color: #f5f7fa;"
+          />
+        </el-form-item>
+      </el-form>
+      <el-divider />
+    </div>
+
+    <!-- 患者基本信息 -->
+    <div v-if="customerInfo && Object.keys(customerInfo).length" class="customer-info-section">
+      <div class="section-title">患者信息</div>
+      <el-row :gutter="20">
+        <el-col :span="4">
+          <span class="info-label">姓名:</span>
+          <span class="info-value">{{ customerInfo.customerName || '-' }}</span>
+        </el-col>
+        <el-col :span="4">
+          <span class="info-label">性别:</span>
+          <span class="info-value">{{ sexText }}</span>
+        </el-col>
+        <el-col :span="4">
+          <span class="info-label">年龄:</span>
+          <span class="info-value">{{ customerInfo.age || '-' }}</span>
+        </el-col>
+        <el-col :span="6">
+          <span class="info-label">电话:</span>
+          <span class="info-value">{{ customerInfo.phone || '-' }}</span>
+        </el-col>
+        <el-col :span="6">
+          <span class="info-label">会诊时间:</span>
+          <span class="info-value">{{ customerInfo.createTime | formatDate }}</span>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="24">
+          <span class="info-label">现病史:</span>
+          <span class="info-value">{{ customerInfo.presentIllness || '-' }}</span>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="24">
+          <span class="info-label">过敏史:</span>
+          <span class="info-value">{{ customerInfo.allergyHistory || '-' }}</span>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="24">
+          <span class="info-label">现用药:</span>
+          <span class="info-value">{{ customerInfo.currentMedication || '-' }}</span>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="24">
+          <span class="info-label">患者主诉:</span>
+          <span class="info-value">{{ customerInfo.patientMainComplaint || '-' }}</span>
+        </el-col>
+      </el-row>
+      <el-divider />
+    </div>
+
+    <!-- 客户问答 -->
+    <div v-if="questionAnswers.length > 0" class="question-answer-section">
+      <div class="section-title">患者病情问答</div>
+      <div class="qa-list" style="max-height: 120px; overflow-y: auto;">
+        <div v-for="(item, idx) in questionAnswers" :key="idx" class="qa-item">
+          <span class="qa-title">{{ item.title }}</span>
+          <span class="qa-answer">{{ item.answerText || '未回答' }}</span>
+        </div>
+      </div>
+      <el-divider />
+    </div>
+
+    <!-- 医生建议及处置(只读) -->
+    <div class="section-title">医生建议及处置</div>
+    <el-form :model="formData" label-width="120px" size="small">
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="诊断">
+            <el-input v-model="formData.diagnose" type="textarea" :rows="4" readonly disabled />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="舌诊,面诊,手诊">
+            <el-input v-model="formData.facialDiagnosis" type="textarea" :rows="4" readonly disabled />
+          </el-form-item>
+        </el-col>
+      </el-row>
+
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="饮食运动建议">
+            <el-input v-model="formData.foodAndExerciseGuidance" type="textarea" :rows="4" readonly disabled />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="注意禁忌">
+            <el-input v-model="formData.noteTaboos" type="textarea" :rows="4" readonly disabled />
+          </el-form-item>
+        </el-col>
+      </el-row>
+
+      <el-form-item label="治疗方面">
+        <el-table :data="formData.healingList" border stripe max-height="300">
+          <el-table-column label="诊断内容" prop="diagnosisContent" min-width="200" />
+          <el-table-column label="建议治疗" prop="suggestTreatment" min-width="200" />
+        </el-table>
+      </el-form-item>
+
+      <el-divider content-position="left">医生及药师信息</el-divider>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="医生职称" label-width="80px">
+            <el-input v-model="signInfo.doctorPosition" readonly disabled size="small" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="执业医师证号" label-width="100px">
+            <el-input :value="displayLicenseNumber" readonly disabled size="small" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="执业医师签字" label-width="100px">
+            <div v-if="signInfo.doctorSignUrl" style="display: flex; align-items: center;">
+              <el-image :src="signInfo.doctorSignUrl" style="width: 80px; height: 30px;" fit="contain" />
+              <span style="margin-left: 6px; color: #606266; font-size: 12px;">({{ signInfo.doctorName || '' }})</span>
+            </div>
+            <el-input v-else :value="signInfo.doctorName || '暂无医生签名'" readonly disabled size="small" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="药师签字" label-width="80px">
+            <div v-if="signInfo.drugDoctorSignUrl" style="display: flex; align-items: center;">
+              <el-image :src="signInfo.drugDoctorSignUrl" style="width: 80px; height: 30px;" fit="contain" />
+              <span style="margin-left: 6px; color: #606266; font-size: 12px;">({{ signInfo.drugDoctorName || '' }})</span>
+            </div>
+            <el-input v-else :value="signInfo.drugDoctorName || '暂无药师签名'" readonly disabled size="small" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
+
+    <div slot="footer" class="dialog-footer">
+      <el-button @click="dialogVisible = false">关闭</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import {
+  getDoctorSignInfo,
+  getCustomerInfoAndQuestionAnswer,
+  getDoctorAdvice
+} from "@/api/his/scrmPrescribe";
+
+export default {
+  name: "DoctorNotPrescribeDetail",
+  props: {
+    visible: Boolean,
+    prescribeId: Number,
+    doctorId: Number,
+    drugDoctorId: Number,
+    companyCustomerId: Number,
+    notPrescribeReason: String
+  },
+  data() {
+    return {
+      dialogVisible: false,
+      customerInfo: {},
+      questionAnswers: [],
+      formData: {
+        diagnose: '',
+        facialDiagnosis: '',
+        foodAndExerciseGuidance: '',
+        healingList: [],
+        noteTaboos: ''
+      },
+      signInfo: {
+        doctorPosition: '',
+        doctorPractiseCode: '',
+        doctorCertificateCode: '',
+        doctorName: '',
+        drugDoctorName: '',
+        doctorSignUrl: '',
+        drugDoctorSignUrl: ''
+      }
+    };
+  },
+  computed: {
+    displayLicenseNumber() {
+      return this.signInfo.doctorPractiseCode || this.signInfo.doctorCertificateCode || '暂无证号';
+    },
+    sexText() {
+      const sex = this.customerInfo.sex;
+      if (sex === '1') return '男';
+      if (sex === '0') return '女';
+      return '未知';
+    }
+  },
+  filters: {
+    formatDate(val) {
+      if (!val) return '-';
+      const date = new Date(val);
+      if (isNaN(date)) return '-';
+      const pad = n => String(n).padStart(2, '0');
+      return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
+    }
+  },
+  watch: {
+    visible(val) {
+      this.dialogVisible = val;
+      if (val) {
+        if (!this.prescribeId) {
+          this.$message.error('处方ID无效,请刷新页面重试');
+          this.dialogVisible = false;
+          this.$emit('update:visible', false);
+          return;
+        }
+        this.resetFormData();
+        this.fetchSignInfo();
+        this.fetchCustomerInfoAndQuestions();
+        this.fetchDoctorAdvice();
+      }
+    }
+  },
+  methods: {
+    resetFormData() {
+      this.formData = {
+        diagnose: '',
+        facialDiagnosis: '',
+        foodAndExerciseGuidance: '',
+        healingList: [],
+        noteTaboos: ''
+      };
+    },
+    fetchSignInfo() {
+      const ids = [];
+      if (this.doctorId) ids.push(this.doctorId);
+      if (this.drugDoctorId) ids.push(this.drugDoctorId);
+      if (ids.length === 0) {
+        this.$message.warning('缺少医生或药师信息,无法获取签名');
+        return;
+      }
+      getDoctorSignInfo(ids).then(response => {
+        const data = response.data;
+        this.signInfo = {
+          doctorPosition: data.position || '',
+          doctorPractiseCode: data.PractiseCode || '',
+          doctorCertificateCode: data.certificateCode || '',
+          doctorName: data.doctorName || '',
+          drugDoctorName: data.drugDoctorName || '',
+          doctorSignUrl: data.doctorSignUrl || '',
+          drugDoctorSignUrl: data.drugDoctorSignUrl || ''
+        };
+      }).catch(error => {
+        console.error('获取签名信息失败', error);
+        this.$message.error('获取医生签名信息失败');
+      });
+    },
+    fetchCustomerInfoAndQuestions() {
+      if (!this.companyCustomerId) {
+        this.customerInfo = {};
+        this.questionAnswers = [];
+        return;
+      }
+      getCustomerInfoAndQuestionAnswer(this.companyCustomerId).then(response => {
+        const data = response.data;
+        if (data) {
+          this.customerInfo = {
+            customerName: data.customerName,
+            sex: data.sex,
+            age: data.age,
+            phone: data.phone,
+            createTime: data.createTime,
+            patientMainComplaint: data.patientMainComplaint,
+            presentIllness: data.presentIllness,
+            allergyHistory: data.allergyHistory,
+            currentMedication: data.currentMedication
+          };
+          this.questionAnswers = data.customerQuestionAnswerVOList || [];
+        } else {
+          this.customerInfo = {};
+          this.questionAnswers = [];
+        }
+      }).catch(error => {
+        console.error('获取客户信息及问答失败', error);
+        this.customerInfo = {};
+        this.questionAnswers = [];
+      });
+    },
+    fetchDoctorAdvice() {
+      getDoctorAdvice(this.prescribeId).then(response => {
+        const data = response.data;
+        if (data) {
+          this.formData.diagnose = data.diagnose || '';
+          this.formData.facialDiagnosis = data.facialDiagnosis || '';
+          this.formData.foodAndExerciseGuidance = data.foodAndExerciseGuidance || '';
+          this.formData.noteTaboos = data.noteTaboos || '';
+          if (data.healingAreaJson) {
+            try {
+              const list = JSON.parse(data.healingAreaJson);
+              if (Array.isArray(list) && list.length > 0) {
+                this.formData.healingList = list;
+              }
+            } catch (e) {
+              console.error('解析治疗方面JSON失败', e);
+            }
+          }
+        }
+      }).catch(error => {
+        console.error('获取医生建议信息失败', error);
+      });
+    },
+    handleClose() {
+      this.$emit('update:visible', false);
+      this.$emit('close');
+    }
+  }
+};
+</script>
+
+<style scoped>
+.dialog-footer {
+  text-align: right;
+}
+
+.not-prescribe-reason-section {
+  margin-bottom: 14px;
+  background-color: #fdf6ec;
+  padding: 10px 16px;
+  border-radius: 8px;
+  border-left: 4px solid #e6a23c;
+}
+
+.customer-info-section {
+  margin-bottom: 14px;
+  background-color: #f5f7fa;
+  padding: 10px 16px;
+  border-radius: 8px;
+}
+
+.question-answer-section {
+  margin-bottom: 14px;
+  background-color: #f9f9f9;
+  padding: 10px 16px;
+  border-radius: 8px;
+}
+
+.section-title {
+  font-weight: bold;
+  font-size: 15px;
+  margin-bottom: 10px;
+  color: #303133;
+}
+
+.qa-list {
+  display: flex;
+  flex-direction: column;
+  gap: 6px;
+}
+
+.qa-item {
+  display: flex;
+  align-items: baseline;
+  font-size: 13px;
+}
+
+.qa-title {
+  width: 45%;
+  color: #606266;
+  font-weight: 500;
+}
+
+.qa-answer {
+  width: 55%;
+  color: #409EFF;
+  font-weight: normal;
+}
+
+.info-label {
+  display: inline-block;
+  width: 70px;
+  color: #606266;
+  font-weight: 500;
+  font-size: 13px;
+}
+
+.info-value {
+  color: #303133;
+  word-break: break-all;
+  font-size: 13px;
+}
+
+.el-row {
+  margin-bottom: 4px;
+}
+
+/* 只读输入框样式 */
+.el-input__inner,
+.el-textarea__inner {
+  color: #1a1a1a !important;
+}
+
+.el-input.is-disabled .el-input__inner,
+.el-textarea.is-disabled .el-textarea__inner {
+  color: #1a1a1a !important;
+  -webkit-text-fill-color: #1a1a1a !important;
+  background-color: #f5f7fa !important;
+  cursor: default;
+}
+</style>

+ 244 - 0
src/views/his/statistics/doctorNotPrescribeStats/doctorNotPrescribeList.vue

@@ -0,0 +1,244 @@
+<template>
+  <div class="app-container">
+    <!-- 搜索表单 -->
+    <el-form
+      :model="queryParams"
+      ref="queryForm"
+      :inline="true"
+      v-show="showSearch"
+      label-width="80px"
+    >
+      <el-form-item label="患者姓名" prop="patientName">
+        <el-input
+          v-model="queryParams.patientName"
+          placeholder="请输入患者姓名"
+          clearable
+          size="small"
+          style="width: 150px"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="医生" prop="doctorId">
+        <el-select
+          v-model="queryParams.doctorId"
+          placeholder="请选择医生"
+          clearable
+          size="small"
+          style="width: 180px"
+        >
+          <el-option
+            v-for="item in doctorList"
+            :key="item.doctorId"
+            :label="item.doctorName"
+            :value="item.doctorId"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="开始时间" prop="beginTime">
+        <el-date-picker
+          v-model="queryParams.beginTime"
+          type="datetime"
+          placeholder="选择开始时间"
+          size="small"
+          style="width: 180px"
+          value-format="yyyy-MM-dd HH:mm:ss"
+        />
+      </el-form-item>
+      <el-form-item label="结束时间" prop="endTime">
+        <el-date-picker
+          v-model="queryParams.endTime"
+          type="datetime"
+          placeholder="选择结束时间"
+          size="small"
+          style="width: 180px"
+          value-format="yyyy-MM-dd HH:mm:ss"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <!-- 数据表格 -->
+    <el-table v-loading="loading" :data="prescribeList" stripe border>
+      <el-table-column label="处方编号" align="center" prop="prescribeCode" width="180" show-overflow-tooltip />
+      <el-table-column label="医生姓名" align="center" prop="doctorName" width="100" />
+      <el-table-column label="患者姓名" align="center" prop="patientName" width="100" />
+      <el-table-column label="患者年龄" align="center" prop="patientAge" width="80" />
+      <el-table-column label="患者电话" align="center" prop="patientTel" width="80" />
+      <el-table-column label="处方状态" align="center" prop="doctorConfirm" width="120">
+        <template slot-scope="scope">
+          <span v-if="scope.row.doctorConfirm === 0" class="warning">待开方</span>
+          <span v-else-if="scope.row.doctorConfirm === -2" class="primary">暂不开方</span>
+          <span v-else-if="scope.row.status === 0" class="default">待审核</span>
+          <span v-else-if="scope.row.status === 1" class="success">已完成</span>
+          <span v-else-if="scope.row.status === 2" class="danger">已拒方</span>
+          <span v-else>-</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="销售制单状态" align="center" prop="isDocument" width="120">
+        <template slot-scope="scope">
+          <span v-if="scope.row.isDocument === 0" class="success">未制单</span>
+          <span v-else-if="scope.row.isDocument === 1" class="error">已制单</span>
+          <span v-else>-</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="不开方理由" align="center" prop="notPrescribeReason" min-width="120" show-overflow-tooltip>
+        <template slot-scope="scope">
+          <span v-if="scope.row.notPrescribeReason" class="primary">{{ scope.row.notPrescribeReason }}</span>
+          <span v-else class="empty-text">-</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160" />
+      <el-table-column
+        label="操作"
+        align="center"
+        width="100"
+        class-name="small-padding fixed-width"
+      >
+        <template slot-scope="scope">
+          <el-button
+            type="text"
+            size="mini"
+            icon="el-icon-document"
+            @click="handleViewDetail(scope.row)"
+          >详情</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 分页 -->
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 详情弹窗 -->
+    <doctor-not-prescribe-detail
+      :visible.sync="detailDialogVisible"
+      :prescribe-id="currentPrescribeId"
+      :doctor-id="currentDoctorId"
+      :drug-doctor-id="currentDrugDoctorId"
+      :company-customer-id="currentCompanyCustomerId"
+      :not-prescribe-reason="currentNotPrescribeReason"
+    />
+  </div>
+</template>
+
+<script>
+import { doctorNotPrescribeList} from "@/api/his/scrmPrescribe";
+import {  getDoctorList } from "@/api/his/doctor";
+import DoctorNotPrescribeDetail from "./doctorNotPrescribeDetail.vue";
+
+export default {
+  name: "DoctorNotPrescribeList",
+  components: {
+    DoctorNotPrescribeDetail
+  },
+  data() {
+    return {
+      loading: true,
+      showSearch: true,
+      prescribeList: [],
+      total: 0,
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        patientName: null,
+        doctorId: null,
+        beginTime: null,
+        endTime: null
+      },
+      prescribeTypeOptions: [
+        { dictLabel: "西药", dictValue: "1" },
+        { dictLabel: "中药", dictValue: "2" },
+        { dictLabel: "中药+西药", dictValue: "3" }
+      ],
+      doctorList: [],
+
+      // 详情弹窗
+      detailDialogVisible: false,
+      currentPrescribeId: null,
+      currentDoctorId: null,
+      currentDrugDoctorId: null,
+      currentCompanyCustomerId: null,
+      currentNotPrescribeReason: null
+    };
+  },
+  created() {
+    this.getDoctorList();
+    this.getList();
+  },
+  methods: {
+    /** 获取医生列表 */
+    getDoctorList() {
+      getDoctorList()
+        .then(response => {
+          this.doctorList = response.data || [];
+        })
+        .catch(() => {
+          this.$message.error('获取医生列表失败');
+        });
+    },
+
+    /** 获取列表数据 */
+    getList() {
+      this.loading = true;
+      doctorNotPrescribeList(this.queryParams)
+        .then(response => {
+          this.prescribeList = response.rows || [];
+          this.total = response.total || 0;
+          this.loading = false;
+        })
+        .catch(() => {
+          this.loading = false;
+        });
+    },
+
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+
+    resetQuery() {
+      this.$refs.queryForm.resetFields();
+      this.queryParams.beginTime = null;
+      this.queryParams.endTime = null;
+      this.handleQuery();
+    },
+
+    /** 查看详情 */
+    handleViewDetail(row) {
+      this.currentPrescribeId = row.prescribeId;
+      this.currentDoctorId = row.doctorId;
+      this.currentDrugDoctorId = row.drugDoctorId;
+      this.currentCompanyCustomerId = row.companyCustomerId;
+      this.currentNotPrescribeReason = row.notPrescribeReason || '';
+      this.detailDialogVisible = true;
+    }
+  }
+};
+</script>
+
+<style scoped>
+.warning {
+  color: #e6a23c;
+}
+.success {
+  color: #67c23a;
+}
+.danger {
+  color: #f56c6c;
+}
+.primary {
+  color: #409eff;
+}
+.empty-text {
+  color: #909399;
+  font-size: 12px;
+}
+</style>