ServiceItemsSystem.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. <script setup lang="ts">
  2. import Enabled from '@/components/Enabled.vue';
  3. import AddItems from './AddItems.vue';
  4. import type { SystemIteQuery, SystemItemModel } from '@/model/care.model';
  5. // 接口数据
  6. import { pageSystemCpMethod, deleteSystemCpMethod, selectSystemCpMethod } from '@/request/api/care.api';
  7. import { usePagination, useRequest } from 'alova/client';
  8. import { notification } from 'ant-design-vue';
  9. import { type VxeFormListeners, type VxeFormProps, type VxeGridInstance, type VxeGridListeners, type VxeGridProps, VxeUI } from 'vxe-pc-ui';
  10. import ServiceDetail from './ServiceDetail.vue';
  11. import HealthEvaluation from './HealthEvaluation.vue';
  12. import seeHealthEvaluation from './seeHealthEvaluation.vue';
  13. const model = shallowRef<SystemIteQuery>();
  14. const searchFormProps = reactive<VxeFormProps<SystemIteQuery>>({
  15. titleWidth: 100,
  16. titleAlign: 'right',
  17. titleColon: true,
  18. data: {},
  19. items: [
  20. {
  21. field: 'name',
  22. title: '项目名称',
  23. span: 8,
  24. itemRender: { name: 'VxeInput', props: { placeholder: '请输入' } },
  25. },
  26. {
  27. field: 'conditioningProgramType',
  28. title: '方案类型',
  29. span: 8,
  30. itemRender: { name: 'VxeInput', props: { placeholder: '请输入' } },
  31. },
  32. {
  33. span: 6,
  34. itemRender: {
  35. name: 'VxeButtonGroup',
  36. options: [
  37. { name: 'search', type: 'submit', content: '查询', status: 'primary' },
  38. { name: 'reset', type: 'reset', content: '清空', status: 'warning' },
  39. { name: 'add', content: '新增', status: 'primary', permissionCode: 'fdhb:service_items_system:add' },
  40. ],
  41. events: {
  42. click(slotParams, { name }) {
  43. if (name === 'add') {
  44. // 新增
  45. editItems();
  46. }
  47. },
  48. },
  49. },
  50. },
  51. {
  52. span: 24,
  53. itemRender: {
  54. name: 'VxeButton',
  55. props: {
  56. content: '选择引入',
  57. type: 'warning',
  58. style: 'margin-top: 8px;background-color: #DE7D13;color: #FFFFFF;',
  59. },
  60. events: {
  61. click() {
  62. // 这里写你的选择引入逻辑
  63. selectImport();
  64. },
  65. },
  66. },
  67. },
  68. ],
  69. });
  70. function selectImport() {
  71. let ids = selectedRows.value.map((item: any) => item.id);
  72. if (ids.length > 0) {
  73. selectSystemCpMethod(ids).then((res) => {
  74. refresh(page.value);
  75. selectedRows.value = [];
  76. notification.success({
  77. message: '引入项目成功',
  78. });
  79. });
  80. } else {
  81. notification.warning({
  82. message: '请选择要引入的项目',
  83. });
  84. }
  85. }
  86. const searchFormEmits: VxeFormListeners<SystemIteQuery> = {
  87. // 查询随访计划
  88. submit({ data }) {
  89. model.value = { ...data };
  90. },
  91. // 重置
  92. reset({ data }) {
  93. model.value = { ...data };
  94. },
  95. };
  96. const gridRef = ref<VxeGridInstance<SystemItemModel>>();
  97. const gridOptions = reactive<VxeGridProps<SystemItemModel>>({
  98. id: 'tag-list',
  99. border: true,
  100. showOverflow: true,
  101. height: 'auto',
  102. autoResize: true,
  103. syncResize: true,
  104. scrollY: { enabled: true, gt: 0 },
  105. toolbarConfig: {
  106. custom: true,
  107. zoom: true,
  108. slots: {
  109. // buttons: 'handle',
  110. tools: 'toolbar-extra',
  111. },
  112. },
  113. columnConfig: {
  114. resizable: true,
  115. },
  116. customConfig: {
  117. storage: true,
  118. },
  119. columns: [
  120. { type: 'checkbox', width: 100, fixed: 'left', title: '批量' },
  121. { field: 'name', title: '项目名称' },
  122. { field: 'conditioningProgramType', title: '方案类型' },
  123. { field: 'cpFixedPricingRule.unitPrice', title: '单价(元)', slots: { default: 'unitPriceCell' }, width: 150 },
  124. { field: 'cpFixedPricingRule.pricingUnit', title: '计价单位', slots: { default: 'pricingUnitCell' } },
  125. { field: 'cpFixedPricingRule.convertDose', title: '计价说明', width: 150, slots: { default: 'convertDoseCell' } },
  126. { field: 'conditioningProgramSupplierName', title: '供应商' },
  127. {
  128. field: 'action',
  129. title: '操作',
  130. align: 'center',
  131. width: 160,
  132. showOverflow: false,
  133. slots: { default: 'actionSlot' },
  134. },
  135. ],
  136. data: [],
  137. });
  138. const gridEvents: VxeGridListeners = {};
  139. const { loading, page, pageSize, total, onSuccess, replace, refresh, remove,send:sendRefresh } = usePagination((page, size) => pageSystemCpMethod(page, size, model.value), {
  140. initialData: { data: [], total: 0 },
  141. initialPage: 1,
  142. initialPageSize: 100,
  143. watchingStates: [model],
  144. immediate: true,
  145. });
  146. onSuccess(({ data: { data } }) => {
  147. gridRef.value?.loadData(data);
  148. });
  149. onMounted(() => {
  150. model.value = toRaw(searchFormProps.data);
  151. });
  152. function deleteItems(model: SystemItemModel, index: number) {
  153. const { name } = model;
  154. VxeUI.modal.confirm({
  155. title: `删除项目`,
  156. content: `确认要删除 ${name} 项目吗?`,
  157. showClose: false,
  158. onConfirm() {
  159. deleteSystemCpMethod(model).then(() => {
  160. notification.success({
  161. message: `删除项目: ${name}`,
  162. description: '操作成功',
  163. });
  164. refresh(page.value);
  165. });
  166. },
  167. });
  168. }
  169. function seeItems(model?: SystemItemModel, index?: number) {
  170. if (model?.isErasable === 'N') {
  171. // 健康咨询 健康评估 查看
  172. VxeUI.modal.open({
  173. title: model?.conditioningProgramType,
  174. height: 500,
  175. width: 750,
  176. id: `see-health-evaluation-modal`,
  177. remember: true,
  178. storage: true,
  179. slots: {
  180. default() {
  181. return h(seeHealthEvaluation, <any>{
  182. data: model,
  183. });
  184. },
  185. },
  186. });
  187. } else {
  188. VxeUI.modal.open({
  189. title: '查看',
  190. height: 600,
  191. width: 850,
  192. position: {
  193. top: Math.min(100, window.innerHeight * 0.1),
  194. },
  195. escClosable: true,
  196. destroyOnClose: true,
  197. id: `service-detail-modal`,
  198. remember: true,
  199. storage: true,
  200. slots: {
  201. default() {
  202. return h(ServiceDetail, <any>{
  203. data: model,
  204. onSubmit(data: SystemItemModel) {
  205. refresh(page.value);
  206. VxeUI.modal.close(`service-detail-modal`);
  207. },
  208. });
  209. },
  210. },
  211. });
  212. }
  213. }
  214. function editItems(model?: SystemItemModel, index?: number) {
  215. const addType = 'system';
  216. if (model?.isErasable === 'N') {
  217. // 健康咨询 健康评估 x显示
  218. VxeUI.modal.open({
  219. title: model?.conditioningProgramType ?? '项目',
  220. height: 400,
  221. width: 750,
  222. id: `health-consultation-modal`,
  223. remember: true,
  224. storage: true,
  225. slots: {
  226. default() {
  227. return h(HealthEvaluation, <any>{
  228. data: {
  229. ...model,
  230. addType,
  231. },
  232. onSubmit(data: SystemItemModel) {
  233. refresh(page.value);
  234. VxeUI.modal.close(`health-consultation-modal`);
  235. },
  236. });
  237. },
  238. },
  239. });
  240. } else {
  241. VxeUI.modal.open({
  242. title: model?.id ? `编辑项目` : `新增项目`,
  243. height: 700,
  244. width: 850,
  245. position: {
  246. top: Math.min(100, window.innerHeight * 0.1),
  247. },
  248. escClosable: true,
  249. destroyOnClose: true,
  250. id: `add-items-modal`,
  251. remember: true,
  252. storage: true,
  253. slots: {
  254. default() {
  255. return h(AddItems, <any>{
  256. data: {
  257. ...model,
  258. addType,
  259. },
  260. onSubmit(data: SystemItemModel) {
  261. refresh(page.value);
  262. VxeUI.modal.close(`add-items-modal`);
  263. },
  264. });
  265. },
  266. },
  267. });
  268. }
  269. }
  270. const selectedRows = ref<any[]>([]);
  271. const onCheckboxChange = (params: any) => {
  272. const { records } = params; // 当前选中的行数据
  273. selectedRows.value = records;
  274. };
  275. const onCheckboxAll = (params: any) => {
  276. const { records } = params; // 全选时选中的行数据
  277. selectedRows.value = records;
  278. };
  279. defineExpose({
  280. send: sendRefresh,
  281. })
  282. </script>
  283. <template>
  284. <div class="page-container flex flex-col">
  285. <header class="flex-none mt-4">
  286. <vxe-form v-bind="searchFormProps" v-on="searchFormEmits"></vxe-form>
  287. </header>
  288. <main class="flex-auto overflow-hidden">
  289. <vxe-grid ref="gridRef" v-bind="gridOptions" v-on="gridEvents" :loading="loading" @checkbox-change="onCheckboxChange" @checkbox-all="onCheckboxAll">
  290. <template #pricingUnitCell="{ row }">
  291. {{ row.cpFixedPricingRule?.pricingUnit ? row.cpFixedPricingRule?.pricingUnit : '次' }}
  292. </template>
  293. <template #unitPriceCell="{ row }">
  294. <!-- {{ row.cpDynamicPricingRule }} -->
  295. {{ row.pricingType === '1' ? `` : row.cpFixedPricingRule?.unitPrice }}
  296. </template>
  297. <template #convertDoseCell="{ row }">
  298. {{
  299. row.pricingType === '1'
  300. ? `当"穴位/经络/部位 ≤${row?.cpDynamicPricingRule ? row?.cpDynamicPricingRule[1]?.max || 0 : 0}个时,
  301. 单价为${row?.cpDynamicPricingRule ? row?.cpDynamicPricingRule[0]?.price || 0 : 0}元,
  302. 当"穴位/经络/部位 >${row?.cpDynamicPricingRule ? row?.cpDynamicPricingRule[1]?.max || 0 : 0}个时,
  303. 单价为${row?.cpDynamicPricingRule ? row?.cpDynamicPricingRule[1]?.price || 0 : 0}元`
  304. : ''
  305. }}
  306. </template>
  307. <template #toolbar-extra>
  308. <vxe-button style="margin-right: 12px" icon="vxe-icon-repeat" circle @click="refresh(page)"></vxe-button>
  309. </template>
  310. <template #actionSlot="{ row, rowIndex }">
  311. <vxe-button mode="text" status="primary" @click="seeItems(row, rowIndex)">查看</vxe-button>
  312. <vxe-button mode="text" status="primary" permission-code="fdhb:service_items_system:edit" @click="editItems(row, rowIndex)">编辑</vxe-button>
  313. <vxe-button mode="text" status="primary" permission-code="fdhb:service_items_system:remove" v-if="row.isErasable !== 'N'" @click="deleteItems(row, rowIndex)">删除</vxe-button>
  314. </template>
  315. </vxe-grid>
  316. </main>
  317. <footer class="flex-none">
  318. <vxe-pager
  319. v-model:current-page="page"
  320. v-model:page-size="pageSize"
  321. :total="total"
  322. :layouts="['Home', 'PrevJump', 'PrevPage', 'Number', 'NextPage', 'NextJump', 'End', 'Sizes', 'FullJump', 'Total']"
  323. />
  324. </footer>
  325. </div>
  326. </template>
  327. <style scoped lang="scss">
  328. .page-container {
  329. height: 100%;
  330. display: flex;
  331. flex-direction: column;
  332. }
  333. </style>