surveyCrudMixin.js 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. /**
  2. * Survey模块avue-crud配置mixin
  3. * @fileoverview 提供基于avue-crud的调查问卷管理功能
  4. * @author 开发者
  5. * @date 2024-XX-XX
  6. */
  7. import {
  8. getList,
  9. add,
  10. update,
  11. getDetail
  12. } from '@/api/survey/survey'
  13. import {
  14. SURVEY_STATUS_OPTIONS,
  15. SURVEY_TEMPLATE_OPTIONS,
  16. getSurveyStatusLabel,
  17. getSurveyStatusType,
  18. getSurveyTemplateLabel,
  19. getSurveyTemplateType
  20. } from '@/constants/survey'
  21. export default {
  22. data() {
  23. return {
  24. // avue-crud标准配置
  25. option: {
  26. height: 'auto',
  27. calcHeight: 80,
  28. tip: false,
  29. searchShow: true,
  30. searchMenuSpan: 12,
  31. searchIndex: 3,
  32. border: true,
  33. index: true,
  34. viewBtn: true,
  35. editBtn: true,
  36. delBtn: false, // 暂时禁用删除
  37. addBtn: true,
  38. selection: false,
  39. dialogClickModal: false,
  40. menu: true,
  41. menuWidth: 200,
  42. column: [
  43. // 问卷编码列
  44. {
  45. label: '问卷编码',
  46. prop: 'surveyCode',
  47. width: 150,
  48. search: true,
  49. rules: [{
  50. required: true,
  51. message: '请输入问卷编码',
  52. trigger: 'blur'
  53. }, {
  54. min: 3,
  55. max: 50,
  56. message: '长度在 3 到 50 个字符',
  57. trigger: 'blur'
  58. }, {
  59. pattern: /^[A-Za-z0-9_-]+$/,
  60. message: '只能包含字母、数字、下划线和横线',
  61. trigger: 'blur'
  62. }]
  63. },
  64. // 问卷标题列
  65. {
  66. label: '问卷标题',
  67. prop: 'title',
  68. minWidth: 200,
  69. search: true,
  70. overHidden: true,
  71. rules: [{
  72. required: true,
  73. message: '请输入问卷标题',
  74. trigger: 'blur'
  75. }, {
  76. min: 2,
  77. max: 100,
  78. message: '长度在 2 到 100 个字符',
  79. trigger: 'blur'
  80. }]
  81. },
  82. // 问卷描述列
  83. {
  84. label: '问卷描述',
  85. prop: 'description',
  86. minWidth: 250,
  87. search: false,
  88. overHidden: true,
  89. type: 'textarea',
  90. span: 24,
  91. minRows: 3,
  92. maxRows: 6,
  93. rules: [{
  94. required: true,
  95. message: '请输入问卷描述',
  96. trigger: 'blur'
  97. }, {
  98. min: 5,
  99. max: 500,
  100. message: '长度在 5 到 500 个字符',
  101. trigger: 'blur'
  102. }]
  103. },
  104. // 状态列
  105. {
  106. label: '状态',
  107. prop: 'status',
  108. width: 100,
  109. search: true,
  110. type: 'select',
  111. dicData: SURVEY_STATUS_OPTIONS,
  112. slot: true,
  113. rules: [{
  114. required: true,
  115. message: '请选择状态',
  116. trigger: 'change'
  117. }]
  118. },
  119. // 是否模板列
  120. {
  121. label: '是否模板',
  122. prop: 'isTemplate',
  123. width: 100,
  124. search: true,
  125. type: 'select',
  126. dicData: SURVEY_TEMPLATE_OPTIONS,
  127. slot: true
  128. },
  129. // 开始时间列
  130. {
  131. label: '开始时间',
  132. prop: 'startTime',
  133. width: 160,
  134. type: 'datetime',
  135. format: 'yyyy-MM-dd HH:mm:ss',
  136. valueFormat: 'yyyy-MM-dd HH:mm:ss',
  137. searchRange: true,
  138. search: true,
  139. rules: [{
  140. required: true,
  141. message: '请选择开始时间',
  142. trigger: 'change'
  143. }]
  144. },
  145. // 结束时间列
  146. {
  147. label: '结束时间',
  148. prop: 'endTime',
  149. width: 160,
  150. type: 'datetime',
  151. format: 'yyyy-MM-dd HH:mm:ss',
  152. valueFormat: 'yyyy-MM-dd HH:mm:ss',
  153. searchRange: true,
  154. search: true,
  155. rules: [{
  156. required: true,
  157. message: '请选择结束时间',
  158. trigger: 'change'
  159. }]
  160. },
  161. // 创建时间列
  162. {
  163. label: '创建时间',
  164. prop: 'createTime',
  165. width: 160,
  166. type: 'datetime',
  167. format: 'yyyy-MM-dd HH:mm:ss',
  168. valueFormat: 'yyyy-MM-dd HH:mm:ss',
  169. addDisplay: false,
  170. editDisplay: false,
  171. search: false
  172. }
  173. ]
  174. },
  175. // 数据和分页
  176. data: [],
  177. page: {
  178. currentPage: 1,
  179. pageSize: 20,
  180. total: 0
  181. },
  182. // 查询和表单
  183. query: {},
  184. form: {},
  185. loading: true,
  186. // 题目编辑相关
  187. questionEditorVisible: false,
  188. currentSurveyId: null,
  189. // 权限配置
  190. permissionList: {
  191. addBtn: true,
  192. viewBtn: true,
  193. editBtn: true,
  194. delBtn: false
  195. }
  196. }
  197. },
  198. mounted() {
  199. this.onLoad(this.page)
  200. },
  201. methods: {
  202. // 导入工具函数
  203. getSurveyStatusLabel,
  204. getSurveyStatusType,
  205. getSurveyTemplateLabel,
  206. getSurveyTemplateType,
  207. // avue-crud标准方法
  208. async onLoad(page, params = {}) {
  209. this.loading = true
  210. try {
  211. // 处理时间范围查询
  212. const queryParams = { ...params }
  213. if (queryParams.startTime && Array.isArray(queryParams.startTime)) {
  214. queryParams.startTimeStart = queryParams.startTime[0]
  215. queryParams.startTimeEnd = queryParams.startTime[1]
  216. delete queryParams.startTime
  217. }
  218. if (queryParams.endTime && Array.isArray(queryParams.endTime)) {
  219. queryParams.endTimeStart = queryParams.endTime[0]
  220. queryParams.endTimeEnd = queryParams.endTime[1]
  221. delete queryParams.endTime
  222. }
  223. const response = await getList(
  224. page.currentPage,
  225. page.pageSize,
  226. queryParams
  227. )
  228. if (response.data && response.data.success) {
  229. const { records, total } = response.data.data
  230. this.data = records || []
  231. this.page.total = total || 0
  232. } else {
  233. this.$message.error(response.data?.msg || '获取数据失败')
  234. }
  235. } catch (error) {
  236. console.error('加载数据失败:', error)
  237. this.$message.error('加载数据失败,请稍后重试')
  238. } finally {
  239. this.loading = false
  240. }
  241. },
  242. searchChange(params, done) {
  243. this.query = params
  244. this.onLoad(this.page, params)
  245. done()
  246. },
  247. searchReset(done) {
  248. this.query = {}
  249. this.onLoad(this.page)
  250. done()
  251. },
  252. currentChange(currentPage) {
  253. this.page.currentPage = currentPage
  254. },
  255. sizeChange(pageSize) {
  256. this.page.pageSize = pageSize
  257. },
  258. refreshChange() {
  259. this.onLoad(this.page, this.query)
  260. },
  261. // CRUD操作
  262. async beforeOpen(done, type) {
  263. if (['edit', 'view'].includes(type)) {
  264. try {
  265. const response = await getDetail(this.form.id)
  266. if (response.data && response.data.success) {
  267. this.form = response.data.data
  268. } else {
  269. this.$message.error('获取详情失败')
  270. return
  271. }
  272. } catch (error) {
  273. console.error('获取详情失败:', error)
  274. this.$message.error('获取详情失败')
  275. return
  276. }
  277. }
  278. done()
  279. },
  280. async rowSave(row, done, loading) {
  281. try {
  282. // 时间验证
  283. if (new Date(row.startTime) >= new Date(row.endTime)) {
  284. this.$message.error('开始时间必须小于结束时间')
  285. loading()
  286. return
  287. }
  288. const response = await add(row)
  289. if (response.data && response.data.success) {
  290. this.$message.success('新增问卷成功')
  291. this.onLoad(this.page)
  292. done()
  293. } else {
  294. this.$message.error(response.data?.msg || '新增失败')
  295. loading()
  296. }
  297. } catch (error) {
  298. console.error('新增失败:', error)
  299. this.$message.error('新增失败,请稍后重试')
  300. loading()
  301. }
  302. },
  303. async rowUpdate(row, index, done, loading) {
  304. try {
  305. // 时间验证
  306. if (new Date(row.startTime) >= new Date(row.endTime)) {
  307. this.$message.error('开始时间必须小于结束时间')
  308. loading()
  309. return
  310. }
  311. const response = await update(row)
  312. if (response.data && response.data.success) {
  313. this.$message.success('更新问卷成功')
  314. this.onLoad(this.page)
  315. done()
  316. } else {
  317. this.$message.error(response.data?.msg || '更新失败')
  318. loading()
  319. }
  320. } catch (error) {
  321. console.error('更新失败:', error)
  322. this.$message.error('更新失败,请稍后重试')
  323. loading()
  324. }
  325. },
  326. // 题目编辑功能
  327. handleEditQuestions(row) {
  328. this.currentSurveyId = row.id
  329. this.questionEditorVisible = true
  330. this.$nextTick(() => {
  331. if (this.$refs.questionEditor) {
  332. this.$refs.questionEditor.loadQuestionList()
  333. }
  334. })
  335. },
  336. handleCloseQuestionEditor() {
  337. this.questionEditorVisible = false
  338. this.currentSurveyId = null
  339. this.$nextTick(() => {
  340. if (this.$refs.questionEditor) {
  341. this.$refs.questionEditor = null
  342. }
  343. })
  344. }
  345. }
  346. }