packageOrderDetails.vue 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. <template>
  2. <div style="background-color: #f0f2f5; padding-bottom: 20px; min-height: 100%; " >
  3. <div style="padding: 20px; background-color: #fff;">
  4. 套餐订单详情
  5. </div>
  6. <div class="content" v-if="item!=null">
  7. <div class="desct"></div>
  8. <div class="order-status" v-if="item!=null" >
  9. <el-steps :active="item.status==3?item.status:item.status-1" align-center finish-status="success">
  10. <el-step title="待支付"></el-step>
  11. <el-step title="服务中"></el-step>
  12. <el-step title="已完成"></el-step>
  13. </el-steps>
  14. </div>
  15. <el-card shadow="never" style="margin-top: 15px">
  16. <div class="operate-container" v-if="item!=null">
  17. <span style="margin-left: 20px" class="color-danger">订单状态:
  18. <el-tag prop="status" v-for="(ite, index) in statusOptions" v-if="item.status==ite.dictValue">{{ite.dictLabel}}</el-tag>
  19. </span>
  20. <!-- <div class="operate-button-container" v-if="item.status==2">
  21. <el-button size="mini" @click="orderRefund()" v-hasPermi="['his:packageOrder:refund']">全部退款 </el-button>
  22. </div> -->
  23. <div class="operate-button-container" v-if="item.status==2 &&item.packageSubType!=3 &&item.packageSubType!=3&& item.inquiryRefundStatus==0" >
  24. <el-button size="mini" @click="inquiryOrderRefund()" v-hasPermi="['his:packageOrder:refund']">问诊退款</el-button>
  25. </div>
  26. <div class="operate-button-container" v-if="item.status==2 &&item.packageSubType!=1 && item.storeRefundStatus==0" >
  27. <el-button size="mini" @click="storeOrderRefund()" v-hasPermi="['his:packageOrder:refund']">商品退款</el-button>
  28. </div>
  29. <div class="operate-button-container" v-if="item.storeOrderId!=null&&item.storeOrderId!=''">
  30. <el-button size="mini" @click="showStoreOrder()">商品订单</el-button>
  31. </div>
  32. <div class="operate-button-container" v-if="item.inquiryOrderId!=null&&item.inquiryOrderId!=''">
  33. <el-button size="mini" @click="showInquiryOrder()">问诊订单</el-button>
  34. </div>
  35. <!-- <div class="operate-button-container" v-if="item.refundStatus==1">
  36. <el-button size="mini" @click="orderRefundAudit()" v-hasPermi="['his:packageOrder:refund']">退款审核</el-button>
  37. </div> -->
  38. </div>
  39. <div class="desct">
  40. 基本信息
  41. </div>
  42. <el-descriptions :column="3" border >
  43. <el-descriptions-item label="订单号"><span v-if="item!=null">{{item.orderSn}}</span></el-descriptions-item>
  44. <el-descriptions-item label="套餐名称"><span v-if="item!=null">{{item.packageName}}</span></el-descriptions-item>
  45. <el-descriptions-item label="套餐价格"><span v-if="item!=null">{{item.totalPrice}}</span></el-descriptions-item>
  46. <el-descriptions-item label="医生名称"><span v-if="item!=null">{{item.doctorName}}</span></el-descriptions-item>
  47. <el-descriptions-item label="用户昵称"><span v-if="item!=null">{{item.nickName}}</span></el-descriptions-item>
  48. <el-descriptions-item label="用户电话"><span v-if="item!=null">{{item.phone}}</span>
  49. <el-button type="text" size="mini" @click="callNumber(0,0,0,item.orderId)" v-if="item.companyUserId == user.userId" v-hasPermi="['store:packageOrder:callNumber']">拨号</el-button>
  50. <el-button type="text" size="mini" @click="handleSms(item.phone)" v-if="item.companyUserId == user.userId" v-hasPermi="['store:packageOrder:sendSms']">短信</el-button>
  51. <el-button icon="el-icon-search" size="mini" @click="handlePhone()" style="margin-left: 20px;" circle v-hasPermi="['store:packageOrder:queryPhone']"></el-button>
  52. </el-descriptions-item>
  53. <el-descriptions-item label="是否支付"> <dict-tag :options="isPayOptions" :value="item.isPay"/></el-descriptions-item>
  54. <el-descriptions-item label="付款类别"> <dict-tag :options="payTypeOptions" :value="item.payType"/></el-descriptions-item>
  55. <el-descriptions-item label="套餐包类别"> <dict-tag :options="packageSubTypeOptions" :value="item.packageSubType"/></el-descriptions-item>
  56. <el-descriptions-item label="天数"><span v-if="item!=null">{{item.days}}</span></el-descriptions-item>
  57. <el-descriptions-item label="状态"> <dict-tag :options="statusOptions" :value="item.status"/></el-descriptions-item>
  58. <el-descriptions-item label="所属公司"><span v-if="item!=null">{{item.companyName}}</span></el-descriptions-item>
  59. <el-descriptions-item label="公司员工"><span v-if="item!=null">{{item.companyUserName}}</span></el-descriptions-item>
  60. <el-descriptions-item label="问诊退款状态"> <dict-tag :options="refundStatusOptions" :value="item.inquiryRefundStatus"/></el-descriptions-item>
  61. <el-descriptions-item label="药品退款状态"> <dict-tag :options="refundStatusOptions" :value="item.storeRefundStatus"/></el-descriptions-item>
  62. <el-descriptions-item label="退款状态"> <dict-tag :options="refundStatusOptions" :value="item.refundStatus"/></el-descriptions-item>
  63. <el-descriptions-item label="退款用户说明"><span v-if="item!=null">{{item.refundExplain}}</span></el-descriptions-item>
  64. <el-descriptions-item label="不退款的理由"><span v-if="item!=null">{{item.refundReason}}</span></el-descriptions-item>
  65. <el-descriptions-item label="退款时间"><span v-if="item!=null">{{item.refundTime}}</span></el-descriptions-item>
  66. <el-descriptions-item label="退款金额"><span v-if="item!=null">{{item.refundMoney}}</span></el-descriptions-item>
  67. <el-descriptions-item label="备注"><span v-if="item!=null">{{item.remark}}</span></el-descriptions-item>
  68. <el-descriptions-item label="支付时间"><span v-if="item!=null">{{item.startTime}}</span></el-descriptions-item>
  69. <el-descriptions-item label="开始时间"><span v-if="item!=null">{{item.payTime}}</span></el-descriptions-item>
  70. <el-descriptions-item label="结束时间"><span v-if="item!=null">{{item.finishTime}}</span></el-descriptions-item>
  71. <el-descriptions-item label="创建时间"><span v-if="item!=null">{{item.createTime}}</span></el-descriptions-item>
  72. </el-descriptions>
  73. </el-card>
  74. </div>
  75. <div class="contentx" v-if="item!=null">
  76. <div class="desct">
  77. 支付信息
  78. </div>
  79. <el-table
  80. border
  81. :data="pay"
  82. size="small"
  83. style="width: 100%;margin-top: 20px" >
  84. <el-table-column label="支付单号" align="center" prop="payCode" width="120px" />
  85. <el-table-column label="支付金额" align="center" prop="payMoney" />
  86. <el-table-column label="类型" align="center" prop="payTypeCode" />
  87. <el-table-column label="交易单号" align="center" prop="bankTransactionId" />
  88. <el-table-column label="银行流水号" align="center" prop="bankSerialNo" />
  89. <el-table-column label="创建时间" align="center" prop="createTime" />
  90. <el-table-column label="支付时间" align="center" prop="payTime" />
  91. </el-table>
  92. </div>
  93. <div class="contentx" v-if="item!=null" style="padding-bottom: 70px;">
  94. <div class="desct">
  95. 商品信息
  96. </div>
  97. <el-tooltip class="item" effect="dark" :content="showList ? '显示全部' : '隐藏'" placement="top" style="float: right;">
  98. <el-button size="mini" circle icon="el-icon-search" @click="showListD()" />
  99. </el-tooltip>
  100. <el-table border v-if="showProd!=null" :data="showProd" size="small" style="width: 100%;margin-top: 20px" >
  101. <el-table-column label="商品图片" width="150" align="center">
  102. <template slot-scope="scope">
  103. <img :src="JSON.parse(scope.row.jsonInfo).image" style="height: 80px">
  104. </template>
  105. </el-table-column>
  106. <el-table-column label="商品编码" width="300" align="center">
  107. <template slot-scope="scope">
  108. <p>{{JSON.parse(scope.row.jsonInfo).barCode}}</p>
  109. </template>
  110. </el-table-column>
  111. <el-table-column label="商品名称" width="300" align="center">
  112. <template slot-scope="scope">
  113. <p>{{JSON.parse(scope.row.jsonInfo).productName}}</p>
  114. </template>
  115. </el-table-column>
  116. <el-table-column label="单价" width="240" align="center">
  117. <template slot-scope="scope">
  118. <p>¥{{JSON.parse(scope.row.jsonInfo).price.toFixed(2)}}</p>
  119. </template>
  120. </el-table-column>
  121. <el-table-column label="规格" width="240" align="center">
  122. <template slot-scope="scope">
  123. {{JSON.parse(scope.row.jsonInfo).sku}}
  124. </template>
  125. </el-table-column>
  126. <el-table-column label="数量" width="180" align="center">
  127. <template slot-scope="scope">
  128. {{scope.row.num}}
  129. </template>
  130. </el-table-column>
  131. <el-table-column label="处方药" width="240" align="center">
  132. <template slot-scope="scope">
  133. {{scope.row.isPrescribe!=null&&scope.row.isPrescribe==1?'是':'否'}}
  134. </template>
  135. </el-table-column>
  136. <el-table-column label="小计" align="center">
  137. <template slot-scope="scope" >
  138. ¥{{(scope.row.num*JSON.parse(scope.row.jsonInfo).price).toFixed(2)}}
  139. </template>
  140. </el-table-column>
  141. </el-table>
  142. </div>
  143. <div class="contentx" v-if="item!=null">
  144. <div class="desct">
  145. 费用信息
  146. </div>
  147. <el-descriptions :column="3" border >
  148. <el-descriptions-item label="商品合计" ><span v-if="item.totalPrice!=null">¥{{item.totalPrice.toFixed(2)}} </span></el-descriptions-item>
  149. <el-descriptions-item label="处方应付金额" ><span v-if="item.payPrice!=null"> ¥{{item.payPrice.toFixed(2)}}</span></el-descriptions-item>
  150. <el-descriptions-item label="运费" ><span v-if="item.payDelivery!=null">¥{{item.payDelivery.toFixed(2)}}</span></el-descriptions-item>
  151. <el-descriptions-item label="优惠劵" ><span v-if="item.discountMoney!=null">¥{{item.discountMoney.toFixed(2)}}</span></el-descriptions-item>
  152. <el-descriptions-item label="实付金额" ><span v-if="item.payMoney!=null">¥{{item.payMoney.toFixed(2)}}</span></el-descriptions-item>
  153. <el-descriptions-item label="代收金额" ><span v-if="item.payRemain!=null">¥{{item.payRemain.toFixed(2)}}</span></el-descriptions-item>
  154. </el-descriptions>
  155. </div>
  156. <!-- 首诊图片管理 -->
  157. <div class="contentx" v-if="item!=null">
  158. <div class="desct">
  159. 首诊图片管理
  160. <el-button
  161. type="primary"
  162. size="mini"
  163. style="float: right; margin-top: -5px;"
  164. @click="showPatientImagesDialog"
  165. :disabled="item.status == 3"
  166. >
  167. 管理首诊图片
  168. </el-button>
  169. </div>
  170. </div>
  171. <el-drawer
  172. :with-header="false"
  173. :append-to-body="true"
  174. size="75%"
  175. :title="show.title" :visible.sync="show.open"
  176. >
  177. <storeOrderDetails ref="Details" />
  178. </el-drawer>
  179. <el-drawer
  180. :with-header="false"
  181. :append-to-body="true"
  182. size="75%"
  183. :title="inquiryOrderShow.title" :visible.sync="inquiryOrderShow.open">
  184. <inquiryOrderDetails ref="inquiryOrderDetails" />
  185. </el-drawer>
  186. <el-dialog
  187. width="50%"
  188. title="退款审核"
  189. :visible.sync="auditVisible"
  190. append-to-body @close="auditCancel">
  191. <el-form ref="form" :model="refundForm" :rules="rules" label-width="120px">
  192. <el-form-item label="审核" prop="deliveryCode">
  193. <el-radio v-model="refundForm.refundStatus" label="2">同意</el-radio>
  194. <el-radio v-model="refundForm.refundStatus" label="3">拒绝</el-radio>
  195. </el-form-item>
  196. <el-form-item label="拒绝理由" prop="deliveryName">
  197. <el-input v-model="refundForm.refundReason" placeholder="请输入快递名称" type="textarea"/>
  198. </el-form-item>
  199. </el-form>
  200. <div slot="footer" class="dialog-footer">
  201. <el-button type="primary" @click="auditOk">确 定</el-button>
  202. <el-button @click="auditCancel">取 消</el-button>
  203. </div>
  204. </el-dialog>
  205. <el-dialog :title="addSms.title" :visible.sync="addSms.open" width="800px" append-to-body>
  206. <add-sms ref="sms" @close="closeSms()"></add-sms>
  207. </el-dialog>
  208. <!-- 首诊图片管理对话框 -->
  209. <el-dialog
  210. title="首诊图片管理"
  211. :visible.sync="patientImagesDialog.visible"
  212. width="80%"
  213. append-to-body
  214. @close="closePatientImagesDialog"
  215. >
  216. <div v-loading="patientImagesDialog.loading">
  217. <div style="margin-bottom: 20px;">
  218. <h4>当前首诊图片:</h4>
  219. <div v-if="patientImagesDialog.images.length > 0" class="image-gallery">
  220. <div
  221. v-for="(image, index) in patientImagesDialog.images"
  222. :key="index"
  223. class="image-item"
  224. >
  225. <img :src="image" class="thumbnail" @click="previewImage(image)" />
  226. <div class="image-actions">
  227. <el-button
  228. size="mini"
  229. type="danger"
  230. icon="el-icon-delete"
  231. circle
  232. @click="removeImage(index)"
  233. ></el-button>
  234. </div>
  235. </div>
  236. </div>
  237. <div v-else style="color: #999; text-align: center; padding: 20px;">
  238. 暂无首诊图片
  239. </div>
  240. </div>
  241. <div style="margin-bottom: 20px;">
  242. <h4>添加新图片:</h4>
  243. <ImageUpload
  244. v-model="patientImagesDialog.newImages"
  245. :limit="10"
  246. :file-size="5"
  247. :file-type="['jpg', 'jpeg', 'png', 'gif']"
  248. />
  249. </div>
  250. </div>
  251. <div slot="footer" class="dialog-footer">
  252. <el-button @click="closePatientImagesDialog">取 消</el-button>
  253. <el-button type="primary" @click="savePatientImages" :loading="patientImagesDialog.saving">
  254. 保 存
  255. </el-button>
  256. </div>
  257. </el-dialog>
  258. <!-- 图片预览对话框 -->
  259. <el-dialog
  260. title="图片预览"
  261. :visible.sync="previewDialog.visible"
  262. width="60%"
  263. append-to-body
  264. >
  265. <div style="text-align: center;">
  266. <img :src="previewDialog.image" style="max-width: 100%; max-height: 500px;" />
  267. </div>
  268. </el-dialog>
  269. </div>
  270. </template>
  271. <script>
  272. import { listPackageOrder,storeRefund,inquiryRefund, payment,getPackageOrder, delPackageOrder,refundAudit, addPackageOrder,refund, updatePackageOrder, exportPackageOrder,getUserPhone, editPatientImages } from "@/api/store/packageOrder";
  273. import { listOrderitem} from "@/api/store/storeOrder";
  274. import storeOrderDetails from '../components/storeOrderDetails2.vue';
  275. import inquiryOrderDetails from '../components/inquiryOrderDetails.vue';
  276. import addSms from '../../crm/components/addSms.vue';
  277. import ImageUpload from '@/components/ImageUpload/index.vue';
  278. export default {
  279. name: "patdetails",
  280. components: { storeOrderDetails,inquiryOrderDetails,addSms, ImageUpload },
  281. props:["data"],
  282. data() {
  283. return {
  284. addSms:{
  285. open:false,
  286. title:"发短信"
  287. },
  288. show:{
  289. open:false,
  290. title:"订单详情"
  291. },
  292. auditVisible:false,
  293. rules:{},
  294. inquiryOrderShow:{
  295. open:false,
  296. title:"订单详情"
  297. },
  298. showList:true,
  299. prod:null,
  300. showProd:null,
  301. // 状态字典
  302. isPayOptions: [],
  303. packageSubTypeOptions: [],
  304. productJson:[],
  305. refundForm:{
  306. orderId:null,
  307. refundReason:null,
  308. refundStatus:null,
  309. },
  310. // 状态字典
  311. statusOptions: [],
  312. refundStatusOptions: [],
  313. item:null,
  314. pay:[],
  315. // 患者图片管理对话框数据
  316. patientImagesDialog: {
  317. visible: false,
  318. loading: false,
  319. saving: false,
  320. images: [], // 当前患者图片列表
  321. newImages: '' // 新上传的图片
  322. },
  323. // 图片预览对话框数据
  324. previewDialog: {
  325. visible: false,
  326. image: ''
  327. }
  328. }
  329. },
  330. computed: {
  331. user(){
  332. return this.$store.state.user.user;
  333. }
  334. },
  335. created() {
  336. this.getDicts("sys_company_or").then(response => {
  337. this.isPayOptions = response.data;
  338. });
  339. this.getDicts("sys_package_order_status").then(response => {
  340. this.statusOptions = response.data;
  341. });
  342. this.getDicts("sys_refund_status").then(response => {
  343. this.refundStatusOptions = response.data;
  344. });
  345. this.getDicts("sys_package_pay_type").then(response => {
  346. this.payTypeOptions = response.data;
  347. });
  348. this.getDicts("sys_package_sub_type").then(response => {
  349. this.packageSubTypeOptions = response.data;
  350. });
  351. },
  352. methods: {
  353. closeSms(){
  354. this.addSms.open=false;
  355. },
  356. handleSms(mobile){
  357. this.addSms.open=true;
  358. var that=this;
  359. setTimeout(() => {
  360. that.$refs.sms.getPackageOrderId(this.item.orderId,mobile,3);
  361. }, 500);
  362. },
  363. handlePhone(){
  364. const orderId = this.item.orderId;
  365. getUserPhone(orderId).then(response =>{
  366. this.item.phone = response.userPhone;
  367. })
  368. },
  369. getDetails(orderId) {
  370. this.item=null;
  371. getPackageOrder(orderId).then(response => {
  372. this.item = response.data;
  373. payment(orderId).then(response => {
  374. this.pay = response.data;
  375. });
  376. if(this.item.storeOrderId!=null){
  377. this.getlistOrderitem(this.item.storeOrderId)
  378. }
  379. });
  380. },
  381. showStoreOrder(){
  382. this.show.open=true;
  383. setTimeout(() => {
  384. this.$refs.Details.getDetails(this.item.storeOrderId,this.item.nickName,null);
  385. }, 1);
  386. },
  387. showListD(){
  388. if(this.showList){
  389. this.showProd=this.prod
  390. }else{
  391. this.showProd=[this.prod[0]]
  392. }
  393. this.showList=this.showList?false:true;
  394. },
  395. orderRefundAudit(){
  396. this.refundForm.orderId=this.item.orderId;
  397. this.refundForm.refundReason=null;
  398. this.refundForm.refundStatus="2";
  399. this.auditVisible=true;
  400. },
  401. showInquiryOrder(){
  402. this.inquiryOrderShow.open=true;
  403. setTimeout(() => {
  404. this.$refs.inquiryOrderDetails.getDetails(this.item.inquiryOrderId);
  405. }, 1);
  406. },
  407. auditCancel(){
  408. this.auditVisible=false;
  409. },
  410. auditOk(){
  411. refundAudit(this.refundForm).then(response => {
  412. this.msgSuccess("操作成功");
  413. getPackageOrder(this.item.orderId).then(response => {
  414. this.item = response.data;
  415. payment(orderId).then(response => {
  416. this.pay = response.data;
  417. });
  418. });
  419. });
  420. this.auditVisible=false;
  421. },
  422. getlistOrderitem(orderId){
  423. listOrderitem(orderId).then(response => {
  424. this.prod = response.rows;
  425. this.showProd=[this.prod[0]]
  426. });
  427. },
  428. orderRefund(){
  429. var that=this;
  430. this.$confirm('是否确认退款?', "警告", {
  431. confirmButtonText: "确定",
  432. cancelButtonText: "取消",
  433. type: "warning"
  434. }).then(function() {
  435. return refund(that.item.orderId);
  436. }).then(() => {
  437. this.msgSuccess("操作成功");
  438. getPackageOrder(that.item.orderId).then(response => {
  439. this.item = response.data;
  440. payment(orderId).then(response => {
  441. this.pay = response.data;
  442. });
  443. });
  444. }).catch(function() {});
  445. },
  446. inquiryOrderRefund(){
  447. var that=this;
  448. this.$confirm('是否确认问诊退款?', "警告", {
  449. confirmButtonText: "确定",
  450. cancelButtonText: "取消",
  451. type: "warning"
  452. }).then(function() {
  453. return inquiryRefund(that.item.orderId);
  454. }).then(() => {
  455. this.msgSuccess("操作成功");
  456. getPackageOrder(that.item.orderId).then(response => {
  457. this.item = response.data;
  458. payment(orderId).then(response => {
  459. this.pay = response.data;
  460. });
  461. });
  462. }).catch(function() {});
  463. },
  464. storeOrderRefund(){
  465. var that=this;
  466. this.$confirm('是否确认退款?', "警告", {
  467. confirmButtonText: "确定",
  468. cancelButtonText: "取消",
  469. type: "warning"
  470. }).then(function() {
  471. return storeRefund(that.item.orderId);
  472. }).then(() => {
  473. this.msgSuccess("操作成功");
  474. getPackageOrder(that.item.orderId).then(response => {
  475. this.item = response.data;
  476. payment(orderId).then(response => {
  477. this.pay = response.data;
  478. });
  479. });
  480. }).catch(function() {});
  481. },
  482. // 显示患者图片管理对话框
  483. showPatientImagesDialog() {
  484. // 解析patientJson中的firstVisitImages字段
  485. if (this.item.patientJson) {
  486. try {
  487. const patientData = JSON.parse(this.item.patientJson);
  488. // 修改:imagesList参数接受的是图片的path字符串,可能包含多个路径用逗号分隔
  489. const imagesPath = patientData.firstVisitImages;
  490. if (imagesPath) {
  491. // 如果是字符串,按逗号分割成数组用于显示
  492. if (typeof imagesPath === 'string') {
  493. this.patientImagesDialog.images = imagesPath.split(',').filter(img => img.trim() !== '');
  494. } else {
  495. // 如果已经是数组,直接使用
  496. this.patientImagesDialog.images = imagesPath;
  497. }
  498. } else {
  499. this.patientImagesDialog.images = [];
  500. }
  501. } catch (e) {
  502. console.error('解析patientJson失败:', e);
  503. this.patientImagesDialog.images = [];
  504. }
  505. } else {
  506. this.patientImagesDialog.images = [];
  507. }
  508. // 重置新上传的图片
  509. this.patientImagesDialog.newImages = '';
  510. this.patientImagesDialog.visible = true;
  511. },
  512. // 关闭患者图片管理对话框
  513. closePatientImagesDialog() {
  514. this.patientImagesDialog.visible = false;
  515. this.patientImagesDialog.images = [];
  516. this.patientImagesDialog.newImages = '';
  517. },
  518. // 预览图片
  519. previewImage(image) {
  520. this.previewDialog.image = image;
  521. this.previewDialog.visible = true;
  522. },
  523. // 移除图片
  524. removeImage(index) {
  525. this.$confirm('确定要删除这张图片吗?', '提示', {
  526. confirmButtonText: '确定',
  527. cancelButtonText: '取消',
  528. type: 'warning'
  529. }).then(() => {
  530. this.patientImagesDialog.images.splice(index, 1);
  531. this.$message.success('删除成功');
  532. }).catch(() => {});
  533. },
  534. // 保存患者图片
  535. savePatientImages() {
  536. this.patientImagesDialog.saving = true;
  537. // 合并原有图片和新上传的图片
  538. let allImages = [...this.patientImagesDialog.images];
  539. // 如果有新上传的图片,添加到列表中
  540. if (this.patientImagesDialog.newImages) {
  541. const newImages = this.patientImagesDialog.newImages.split(',').filter(img => img.trim() !== '');
  542. allImages = [...allImages, ...newImages];
  543. }
  544. // 修改:根据后端API要求,imagesList参数应该是字符串类型
  545. // 将所有图片路径用逗号连接成一个字符串
  546. const imagesParam = allImages.join(',');
  547. console.log('保存患者图片,参数:', {
  548. orderId: this.item.orderId,
  549. imagesParam: imagesParam
  550. });
  551. // 调用API保存图片
  552. editPatientImages(this.item.orderId, imagesParam).then(response => {
  553. console.log('保存患者图片成功:', response);
  554. this.$message.success('保存成功');
  555. this.patientImagesDialog.saving = false;
  556. this.patientImagesDialog.visible = false;
  557. // 更新item中的patientJson
  558. if (this.item.patientJson) {
  559. try {
  560. const patientData = JSON.parse(this.item.patientJson);
  561. // 保存时保持与API一致的格式,存储字符串
  562. patientData.firstVisitImages = imagesParam;
  563. this.item.patientJson = JSON.stringify(patientData);
  564. } catch (e) {
  565. console.error('更新patientJson失败:', e);
  566. }
  567. }
  568. }).catch(error => {
  569. console.error('保存患者图片失败:', error);
  570. this.$message.error('保存失败: ' + (error.message || '未知错误'));
  571. this.patientImagesDialog.saving = false;
  572. }).finally(() => {
  573. // 确保无论成功还是失败,都重置saving状态
  574. if (this.patientImagesDialog.saving) {
  575. this.patientImagesDialog.saving = false;
  576. }
  577. });
  578. }
  579. }
  580. }
  581. </script>
  582. <style>
  583. .el-descriptions-item__content {
  584. max-width: 150px;
  585. min-width: 100px;
  586. }
  587. .content{
  588. height: 100%;
  589. background-color: #fff;
  590. padding: 0px 20px 20px;
  591. margin: 20px;
  592. }
  593. .el-descriptions-item__label.is-bordered-label{
  594. font-weight: normal;
  595. }
  596. .desct{
  597. padding-top: 20px;
  598. padding-bottom: 20px;
  599. color: #524b4a;
  600. font-weight: bold;
  601. }
  602. </style>
  603. <style scoped>
  604. .order-content{
  605. margin: 10px;
  606. }
  607. .operate-container {
  608. background: #F2F6FC;
  609. height: 60px;
  610. margin: -20px -20px 0;
  611. line-height: 60px;
  612. }
  613. .operate-button-container {
  614. float: right;
  615. margin-right: 20px
  616. }
  617. /* 图片画廊样式 */
  618. .image-gallery {
  619. display: flex;
  620. flex-wrap: wrap;
  621. gap: 15px;
  622. margin-top: 10px;
  623. }
  624. .image-item {
  625. position: relative;
  626. width: 120px;
  627. height: 120px;
  628. border: 1px solid #ddd;
  629. border-radius: 4px;
  630. overflow: hidden;
  631. }
  632. .thumbnail {
  633. width: 100%;
  634. height: 100%;
  635. object-fit: cover;
  636. cursor: pointer;
  637. transition: transform 0.3s;
  638. }
  639. .thumbnail:hover {
  640. transform: scale(1.05);
  641. }
  642. .image-actions {
  643. position: absolute;
  644. top: 5px;
  645. right: 5px;
  646. opacity: 0;
  647. transition: opacity 0.3s;
  648. }
  649. .image-item:hover .image-actions {
  650. opacity: 1;
  651. }
  652. </style>