SendRecord.vue 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. <script setup lang="ts">
  2. import { ref, reactive, shallowRef, onMounted } from 'vue';
  3. import SeeSatisfaction from '@/satisfaction/SeeQuestionnaire.vue';
  4. import type { SatisfactionSendRecordModel, SatisfactionSendRecordQuery } from '@/model/satisfaction.model';
  5. // 接口数据
  6. import { satisfactionSendRecordMethod } from '@/request/api/satisfaction.api';
  7. import { usePagination } from 'alova/client';
  8. import dayjs from 'dayjs';
  9. import { type VxeFormListeners, type VxeFormProps, type VxeGridInstance, type VxeGridListeners, type VxeGridProps, VxeUI } from 'vxe-pc-ui';
  10. const model = shallowRef<SatisfactionSendRecordQuery>();
  11. const searchFormProps = reactive<VxeFormProps<SatisfactionSendRecordQuery>>({
  12. titleWidth: 100,
  13. titleAlign: 'right',
  14. titleColon: true,
  15. data: { name: '' },
  16. items: [
  17. {
  18. field: 'name',
  19. title: '问卷名称',
  20. span: 6,
  21. itemRender: { name: 'VxeInput', props: { placeholder: '请输入满意度问卷名称' } },
  22. },
  23. {
  24. field: 'sendTime',
  25. title: '发送日期',
  26. span: 6,
  27. slots: {
  28. default: 'createTimes',
  29. },
  30. },
  31. {
  32. field: 'isFilled',
  33. title: '填写状态',
  34. span: 6,
  35. itemRender: {
  36. name: 'VxeRadioGroup',
  37. props: {
  38. options: [
  39. { label: '已填写', value: true },
  40. { label: '未填写', value: false },
  41. ],
  42. },
  43. },
  44. },
  45. {
  46. span: 6,
  47. itemRender: {
  48. name: 'VxeButtonGroup',
  49. options: [
  50. { name: 'submits', type: 'submit', content: '查询', status: 'primary' },
  51. { name: 'reset', type: 'reset', content: '重置', status: 'warning' },
  52. ],
  53. },
  54. },
  55. ],
  56. });
  57. const searchFormEmits: VxeFormListeners<SatisfactionSendRecordQuery> = {
  58. submit({ data }) {
  59. data.sendTimeStart = sendTimeStart.value ? dayjs(sendTimeStart.value).format('YYYY-MM-DD HH:mm') : '';
  60. data.sendTimeEnd = sendTimeEnd.value ? dayjs(sendTimeEnd.value).format('YYYY-MM-DD HH:mm') : '';
  61. onSearch(data);
  62. },
  63. // 重置
  64. reset({ data }) {
  65. sendTimeStart.value = '';
  66. sendTimeEnd.value = '';
  67. onSearch(data);
  68. },
  69. };
  70. function onSearch(data: SatisfactionSendRecordQuery) {
  71. model.value = { ...data };
  72. nextTick(() => {
  73. (searchFormProps.data as any)!.name = data.name;
  74. (searchFormProps.data as any)!.isFilled = data.isFilled;
  75. (searchFormProps.data as any)!.sendTimeStart = data.sendTimeStart;
  76. (searchFormProps.data as any)!.sendTimeEnd = data.sendTimeEnd;
  77. });
  78. }
  79. const gridRef = ref<VxeGridInstance<SatisfactionSendRecordModel>>();
  80. const gridOptions = reactive<VxeGridProps<SatisfactionSendRecordModel>>({
  81. id: 'tag-list',
  82. border: true,
  83. showOverflow: true,
  84. height: 'auto',
  85. autoResize: true,
  86. syncResize: true,
  87. scrollY: { enabled: true, gt: 0 },
  88. rowConfig: {
  89. isHover: true,
  90. isCurrent: true,
  91. },
  92. toolbarConfig: {
  93. custom: true,
  94. zoom: true,
  95. slots: {
  96. tools: 'toolbar-extra',
  97. },
  98. },
  99. columnConfig: {
  100. resizable: true,
  101. },
  102. customConfig: {
  103. storage: true,
  104. },
  105. columns: [
  106. { type: 'seq', width: 70, fixed: 'left' },
  107. { field: 'name', title: '问卷名称' },
  108. { field: 'patientName', title: '用户姓名' },
  109. { field: 'phone', title: '手机号码' },
  110. { field: 'score', title: '得分' },
  111. { field: 'sendTime', title: '发送时间' },
  112. { field: 'submitTime', title: '提交时间' },
  113. {
  114. field: 'action',
  115. title: '操作',
  116. align: 'center',
  117. width: 150,
  118. showOverflow: false,
  119. cellRender: {
  120. name: 'VxeButtonGroup',
  121. props: {
  122. mode: 'text',
  123. },
  124. options: [
  125. { content: '查看', status: 'primary', name: 'seeDetail' },
  126. ],
  127. events: {
  128. click({ row, rowIndex }: any, { name }: any) {
  129. let method;
  130. if (name === 'seeDetail') {
  131. method = seeDetail;
  132. }
  133. method?.(row, rowIndex);
  134. },
  135. },
  136. },
  137. },
  138. ],
  139. data: [],
  140. });
  141. const gridEvents: VxeGridListeners = {};
  142. const {
  143. loading,
  144. page,
  145. pageSize,
  146. total,
  147. onSuccess,
  148. replace,
  149. refresh,
  150. remove,
  151. send: sendRefresh,
  152. } = usePagination((page, size) => satisfactionSendRecordMethod(page, size, model.value), {
  153. initialData: { data: [], total: 0 },
  154. initialPage: 1,
  155. initialPageSize: 100,
  156. watchingStates: [model],
  157. immediate: true,
  158. });
  159. onSuccess((res: any) => {
  160. gridRef.value?.loadData(res?.data?.data ?? []);
  161. });
  162. onMounted(() => {
  163. onSearch(toRaw(searchFormProps.data) as any);
  164. });
  165. function seeDetail(model?: SatisfactionSendRecordModel, index?: number) {
  166. const type=1;
  167. VxeUI.modal.open({
  168. title: model?.name,
  169. fullscreen: true,
  170. escClosable: true,
  171. destroyOnClose: true,
  172. id: `see-satisfaction-modal`,
  173. remember: true,
  174. storage: true,
  175. slots: {
  176. default() {
  177. return h(SeeSatisfaction, <any>{
  178. data:{...model, type},
  179. });
  180. },
  181. },
  182. });
  183. }
  184. // 日期验证
  185. const sendTimeStart = ref<string>('');
  186. const sendTimeEnd = ref<string>('');
  187. // 禁用结束时间的日期(早于开始时间的日期)
  188. function disabledEndDate(current: any) {
  189. if (!sendTimeStart.value) return false;
  190. return current && current < dayjs(sendTimeStart.value);
  191. }
  192. defineExpose({
  193. send: sendRefresh,
  194. });
  195. </script>
  196. <template>
  197. <div class="page-container flex flex-col">
  198. <header class="flex-none mt-4">
  199. <vxe-form v-bind="searchFormProps" v-on="searchFormEmits">
  200. <template #createTimes>
  201. <div class="date-range-container">
  202. <a-date-picker v-model:value="sendTimeStart" placeholder="请选择开始日期" style="flex: 1" :show-time="{ format: 'HH:mm' }" />
  203. <span class="date-separator">至</span>
  204. <a-date-picker v-model:value="sendTimeEnd" placeholder="请选择结束日期" style="flex: 1" :disabledDate="disabledEndDate" :show-time="{ format: 'HH:mm' }" />
  205. </div>
  206. </template>
  207. </vxe-form>
  208. </header>
  209. <main class="flex-auto overflow-hidden">
  210. <vxe-grid ref="gridRef" v-bind="gridOptions" v-on="gridEvents" :loading="loading">
  211. <template #conditioningProgramSupplierNameCell="{ row }">
  212. {{ row.conditioningProgramSupplierName == '0' ? '启用' : '禁用' }}
  213. </template>
  214. <template #toolbar-extra>
  215. <vxe-button style="margin-right: 12px" icon="vxe-icon-repeat" circle @click="refresh(page)"></vxe-button>
  216. </template>
  217. </vxe-grid>
  218. </main>
  219. <footer class="flex-none">
  220. <vxe-pager
  221. v-model:current-page="page"
  222. v-model:page-size="pageSize"
  223. :total="total"
  224. :layouts="['Home', 'PrevJump', 'PrevPage', 'Number', 'NextPage', 'NextJump', 'End', 'Sizes', 'FullJump', 'Total']"
  225. />
  226. </footer>
  227. </div>
  228. </template>
  229. <style scoped lang="scss">
  230. .page-container {
  231. height: 100%;
  232. display: flex;
  233. flex-direction: column;
  234. }
  235. .date-range-container {
  236. display: flex;
  237. align-items: center;
  238. gap: 12px;
  239. width: 100%;
  240. .vxe-input {
  241. flex: 1;
  242. min-width: 0;
  243. }
  244. .date-separator {
  245. color: #666;
  246. font-size: 14px;
  247. font-weight: 500;
  248. white-space: nowrap;
  249. padding: 0 8px;
  250. }
  251. }
  252. </style>