CostSurveyTab.vue 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523
  1. <template>
  2. <div>
  3. <!-- 调查表填报弹窗(单记录类型) -->
  4. <survey-form-dialog
  5. :visible.sync="surveyFormDialogVisible"
  6. :survey-data="{ ...currentSurveyRow, ...surveyDetailData }"
  7. :form-fields="formFields"
  8. :is-view-mode="isViewMode"
  9. :audited-unit-id="auditedUnitId"
  10. :request-type="1"
  11. :upload-id="
  12. currentSurveyRow && currentSurveyRow.id ? currentSurveyRow.id : uploadId
  13. "
  14. :survey-template-id="
  15. currentSurveyRow && currentSurveyRow.surveyTemplateId
  16. ? currentSurveyRow.surveyTemplateId
  17. : surveyTemplateId
  18. "
  19. :catalog-id="catalogId"
  20. :task-id="taskId"
  21. @save="handleSurveyFormSave"
  22. @refresh="handleRefresh"
  23. />
  24. <!-- 固定表填报弹窗 -->
  25. <fixed-table-dialog
  26. :visible.sync="fixedTableDialogVisible"
  27. :survey-data="{ ...currentSurveyRow, fixedHeaders }"
  28. :fixed-fields="fixedFields || ''"
  29. :fixed-fieldids="fixedFieldids || ''"
  30. :columns-meta="columnsMeta"
  31. :table-items="tableItems"
  32. :audit-periods="auditPeriods"
  33. :project-audit-periods="auditPeriods"
  34. :project-audit-period="auditPeriod"
  35. :is-view-mode="isViewMode"
  36. :request-type="1"
  37. :audited-unit-id="auditedUnitId"
  38. :upload-id="
  39. currentSurveyRow && currentSurveyRow.id ? currentSurveyRow.id : uploadId
  40. "
  41. :survey-template-id="
  42. currentSurveyRow && currentSurveyRow.surveyTemplateId
  43. ? currentSurveyRow.surveyTemplateId
  44. : surveyTemplateId
  45. "
  46. :catalog-id="catalogId"
  47. :task-id="taskId"
  48. @save="handleFixedTableSave"
  49. @refresh="handleRefresh"
  50. />
  51. <!-- 动态表填报弹窗 -->
  52. <dynamic-table-dialog
  53. :key="dynamicDialogKey"
  54. :visible.sync="dynamicTableDialogVisible"
  55. :survey-data="currentSurveyRow"
  56. :table-data="dynamicTableData"
  57. :table-items="tableItems"
  58. :is-view-mode="isViewMode"
  59. :request-type="1"
  60. :audited-unit-id="auditedUnitId"
  61. :upload-id="
  62. currentSurveyRow && (currentSurveyRow.uploadId || currentSurveyRow.id)
  63. ? currentSurveyRow.uploadId || currentSurveyRow.id
  64. : uploadId
  65. "
  66. :catalog-id="catalogId"
  67. :survey-template-id="
  68. currentSurveyRow && currentSurveyRow.surveyTemplateId
  69. ? currentSurveyRow.surveyTemplateId
  70. : surveyTemplateId
  71. "
  72. @save="handleDynamicTableSave"
  73. @refresh="handleRefresh"
  74. />
  75. <el-table
  76. style="width: 100%; margin-top: 20px"
  77. :data="paginatedData"
  78. border
  79. size="medium"
  80. >
  81. <!-- 序号列 -->
  82. <el-table-column prop="index" label="序号" width="60" align="center">
  83. <template slot-scope="scope">
  84. {{ scope.$index + 1 }}
  85. </template>
  86. </el-table-column>
  87. <el-table-column
  88. label="成本调查表"
  89. min-width="220"
  90. header-align="center"
  91. align="left"
  92. >
  93. <template slot-scope="scope">
  94. <span
  95. :style="{
  96. color: scope.row.isDisabled ? '#909399' : '#409EFF',
  97. cursor: scope.row.isDisabled ? 'default' : 'pointer',
  98. }"
  99. @click="
  100. !scope.row.isDisabled && $emit('handle-survey-click', scope.row)
  101. "
  102. >
  103. {{ scope.row.name }}
  104. </span>
  105. </template>
  106. </el-table-column>
  107. <!-- 资料类型列 -->
  108. <el-table-column
  109. prop="dataType"
  110. label="资料类型"
  111. width="120"
  112. align="center"
  113. ></el-table-column>
  114. <!-- 表格类型列 -->
  115. <el-table-column
  116. prop="tableType"
  117. label="表格类型"
  118. width="120"
  119. align="center"
  120. ></el-table-column>
  121. <!-- 是否必填列 -->
  122. <el-table-column
  123. prop="isRequired"
  124. label="是否必填"
  125. width="100"
  126. align="center"
  127. >
  128. <template slot-scope="scope">
  129. <span>
  130. {{
  131. scope.row.isRequired === '是' ||
  132. scope.row.isRequired === '1' ||
  133. scope.row.isRequired === 1
  134. ? '是'
  135. : '否'
  136. }}
  137. </span>
  138. </template>
  139. </el-table-column>
  140. <!-- 是否上传列(红色“未上传”、绿色“已上传”) -->
  141. <el-table-column label="是否上传" width="100" align="center">
  142. <template slot-scope="scope">
  143. <span
  144. :style="{
  145. color: scope.row.isUploaded === true ? '#67c23a' : '#f56c6c',
  146. }"
  147. >
  148. {{ scope.row.isUploaded === true ? '已上传' : '未上传' }}
  149. </span>
  150. </template>
  151. </el-table-column>
  152. <el-table-column label="初审结果" width="100" align="center">
  153. <template slot-scope="scope">
  154. <span
  155. :class="{
  156. 'result-pending':
  157. !scope.row.auditedStatus || scope.row.auditedStatus === '0',
  158. 'result-pass': scope.row.auditedStatus === '1',
  159. 'result-fail': scope.row.auditedStatus === '2',
  160. }"
  161. >
  162. {{
  163. !scope.row.auditedStatus || scope.row.auditedStatus === '0'
  164. ? '未审核'
  165. : scope.row.auditedStatus === '1'
  166. ? '通过'
  167. : '不通过'
  168. }}
  169. </span>
  170. </template>
  171. </el-table-column>
  172. <!-- 操作列(根据“表格类型”显示不同按钮) -->
  173. <el-table-column label="操作" width="320" align="center">
  174. <template slot-scope="scope">
  175. <!-- 在线填报:所有类型均显示 -->
  176. <el-button
  177. type="text"
  178. size="small"
  179. :disabled="isViewMode"
  180. @click="handleOnlineFillClick(scope.row)"
  181. >
  182. 在线填报
  183. </el-button>
  184. <!-- 动态表:数据下载、数据上传 -->
  185. <template v-if="scope.row.tableType === '动态表'">
  186. <el-button
  187. type="text"
  188. size="small"
  189. :disabled="isViewMode"
  190. @click="handleDataDownload(scope.row)"
  191. >
  192. 数据下载
  193. </el-button>
  194. </template>
  195. <!-- 固定表:模版下载、数据上传 -->
  196. <template v-else-if="scope.row.tableType === '固定表'">
  197. <el-button
  198. type="text"
  199. size="small"
  200. :disabled="isViewMode"
  201. @click="handleDataDownload(scope.row)"
  202. >
  203. 模版下载
  204. </el-button>
  205. <el-button
  206. type="text"
  207. size="small"
  208. :disabled="isViewMode"
  209. @click="handleDataUpload(scope.row)"
  210. >
  211. 数据上传
  212. </el-button>
  213. </template>
  214. <!-- 单记录:仅显示在线填报(上面已显示),不再追加其他按钮 -->
  215. </template>
  216. </el-table-column>
  217. </el-table>
  218. <input
  219. ref="dynamicUploadInput"
  220. type="file"
  221. accept=".xls,.xlsx"
  222. style="display: none"
  223. @change="handleDynamicUploadChange"
  224. />
  225. <el-pagination
  226. background
  227. layout="total, sizes, prev, pager, next"
  228. :current-page="pagination.currentPage"
  229. :page-sizes="[10, 20, 30, 50]"
  230. :page-size="pagination.pageSize"
  231. :total="pagination.total"
  232. style="margin-top: 20px; text-align: right"
  233. @current-change="$emit('handle-page-change', $event)"
  234. @size-change="$emit('handle-size-change', $event)"
  235. />
  236. </div>
  237. </template>
  238. <script>
  239. import SurveyFormDialog from './SurveyFormDialog.vue'
  240. import FixedTableDialog from './FixedTableDialog.vue'
  241. import DynamicTableDialog from './DynamicTableDialog.vue'
  242. import {
  243. getSingleRecordSurveyList,
  244. getSurveyDetail,
  245. getDynamicTableData,
  246. downloadTemplate,
  247. importData,
  248. } from '@/api/audit/survey'
  249. import { getListBySurveyTemplateIdAndVersion } from '@/api/costSurveyTemplateHeaders'
  250. export default {
  251. name: 'CostSurveyTab',
  252. components: {
  253. SurveyFormDialog,
  254. FixedTableDialog,
  255. DynamicTableDialog,
  256. },
  257. props: {
  258. paginatedData: {
  259. type: Array,
  260. default: () => [],
  261. },
  262. pagination: {
  263. type: Object,
  264. default: () => ({ currentPage: 1, pageSize: 10, total: 0 }),
  265. },
  266. isViewMode: {
  267. type: Boolean,
  268. default: false,
  269. },
  270. // 被监审单位ID
  271. auditedUnitId: {
  272. type: String,
  273. default: '',
  274. },
  275. // 上传记录ID
  276. uploadId: {
  277. type: String,
  278. default: '',
  279. },
  280. // 成本调查表模板ID
  281. surveyTemplateId: {
  282. type: String,
  283. default: '',
  284. },
  285. // 目录ID
  286. catalogId: {
  287. type: String,
  288. default: '',
  289. },
  290. // 任务ID(用于上传)
  291. taskId: {
  292. type: [String, Number],
  293. default: '',
  294. },
  295. // 监审期间(从立项信息中获取)
  296. auditPeriod: {
  297. type: [String, Array],
  298. default: null,
  299. },
  300. },
  301. data() {
  302. return {
  303. surveyFormDialogVisible: false,
  304. fixedTableDialogVisible: false,
  305. dynamicTableDialogVisible: false,
  306. currentSurveyRow: null,
  307. // 表单字段配置(可以从后台获取,或通过 props 传入)
  308. formFields: [],
  309. // 表单详情数据(用于回显)
  310. surveyDetailData: {},
  311. // 固定表数据配置
  312. tableItems: [],
  313. // 监审期间(年份数组)
  314. auditPeriods: [],
  315. // 动态表数据
  316. dynamicTableData: [],
  317. dynamicDialogKey: 0,
  318. dynamicTableLoading: false,
  319. fixedHeaders: null,
  320. fixedFields: '',
  321. fixedFieldids: '',
  322. columnsMeta: [],
  323. // 上传相关
  324. pendingDynamicRow: null,
  325. }
  326. },
  327. watch: {
  328. auditPeriod: {
  329. immediate: true,
  330. deep: true,
  331. handler() {
  332. this.syncAuditPeriodsFromProp()
  333. },
  334. },
  335. },
  336. mounted() {
  337. // 表单字段配置在打开弹窗时动态加载,不需要在 mounted 中初始化
  338. this.syncAuditPeriodsFromProp()
  339. },
  340. methods: {
  341. // 同步并规范化来自 props 的监审期间到本地数组
  342. syncAuditPeriodsFromProp() {
  343. const input = this.auditPeriod
  344. if (!input) {
  345. this.auditPeriods = []
  346. return
  347. }
  348. if (Array.isArray(input)) {
  349. this.auditPeriods = input.map((p) => String(p))
  350. return
  351. }
  352. const str = String(input).trim()
  353. if (!str) {
  354. this.auditPeriods = []
  355. return
  356. }
  357. if (str.includes(',')) {
  358. this.auditPeriods = str
  359. .split(',')
  360. .map((s) => s.trim())
  361. .filter(Boolean)
  362. return
  363. }
  364. if (str.includes('-')) {
  365. const parts = str.split('-')
  366. if (parts.length === 2) {
  367. const start = parseInt(parts[0].trim())
  368. const end = parseInt(parts[1].trim())
  369. const years = []
  370. if (!isNaN(start) && !isNaN(end) && end >= start) {
  371. for (let y = start; y <= end; y++) years.push(String(y))
  372. }
  373. this.auditPeriods = years
  374. return
  375. }
  376. }
  377. this.auditPeriods = [str]
  378. },
  379. // 处理在线填报点击
  380. async handleOnlineFillClick(row) {
  381. this.currentSurveyRow = row
  382. // 重置详情数据
  383. this.surveyDetailData = {}
  384. // 如果表格类型是"单记录",弹出调查表填报弹窗
  385. if (row.tableType === '单记录') {
  386. console.log(this.auditedUnitId, 'this.auditedUnitId')
  387. // 如果该行有 id,先调用接口获取详情数据
  388. if (row.id && this.auditedUnitId) {
  389. try {
  390. const params = {
  391. uploadId: row.id,
  392. auditedUnitId: this.auditedUnitId,
  393. type: 1,
  394. }
  395. const res = await getSurveyDetail(params)
  396. console.log('单记录详情数据', res)
  397. if (res && res.code === 200 && res.value) {
  398. // 将详情数据转换为表单数据格式
  399. // 接口返回的数据可能是数组格式 [{rowid: 'xxx', rkey: 'xxx', rvalue: 'xxx'}, ...]
  400. // 需要转换为 {rowid: 'rvalue', ...} 的格式
  401. const detailData = {}
  402. if (Array.isArray(res.value)) {
  403. res.value.forEach((item) => {
  404. if (item.rowid && item.rvalue !== undefined) {
  405. detailData[item.rowid] = item.rvalue
  406. }
  407. })
  408. } else if (res.value) {
  409. // 如果不是数组,可能是对象格式,直接使用
  410. Object.assign(detailData, res.value)
  411. }
  412. this.surveyDetailData = detailData
  413. console.log('转换后的详情数据', this.surveyDetailData)
  414. }
  415. } catch (err) {
  416. console.error('获取单记录详情失败', err)
  417. }
  418. }
  419. // 调用接口获取单记录表单字段配置(详情数据已准备好)
  420. await this.initFormFields()
  421. // 接口调用完成后会自动打开弹窗(在 initFormFields 中处理)
  422. } else if (row.tableType === '固定表') {
  423. // 如果表格类型是"固定表",弹出固定表填报弹窗
  424. // 调用接口获取固定表配置
  425. await this.initFixedTableData()
  426. // 接口调用完成后会自动打开弹窗(在 initFixedTableData 中处理)
  427. } else if (row.tableType === '动态表') {
  428. // 如果表格类型是"动态表",弹出动态表填报弹窗
  429. this.resetDynamicDialogState()
  430. await this.initDynamicTableData()
  431. } else {
  432. // 其他类型,触发原有事件
  433. this.$emit('handle-online-fill', row)
  434. }
  435. },
  436. // 处理调查表保存
  437. handleSurveyFormSave(formData) {
  438. // 可以将保存的数据传递给父组件
  439. this.$emit('handle-survey-form-save', {
  440. row: this.currentSurveyRow,
  441. formData: formData,
  442. })
  443. },
  444. // 处理刷新事件
  445. handleRefresh() {
  446. // 触发父组件的刷新事件
  447. this.$emit('handle-survey-form-save', {
  448. row: this.currentSurveyRow,
  449. formData: {},
  450. })
  451. },
  452. // 处理固定表保存
  453. handleFixedTableSave(tableData) {
  454. // 可以将保存的数据传递给父组件
  455. this.$emit('handle-fixed-table-save', {
  456. row: this.currentSurveyRow,
  457. tableData: tableData,
  458. })
  459. },
  460. // 处理动态表保存
  461. handleDynamicTableSave(tableData) {
  462. // 将保存的数据传递给父组件
  463. this.$emit('handle-dynamic-table-save', {
  464. row: this.currentSurveyRow,
  465. tableData: tableData,
  466. })
  467. // 触发刷新事件
  468. this.handleRefresh()
  469. },
  470. // 触发动态表数据上传
  471. handleDataUpload(row) {
  472. if (this.isViewMode) return
  473. this.pendingDynamicRow = row || null
  474. this.$nextTick(() => {
  475. const input = this.$refs.dynamicUploadInput
  476. if (input) {
  477. input.value = ''
  478. input.click()
  479. }
  480. })
  481. },
  482. // 文件选择后上传
  483. async handleDynamicUploadChange(e) {
  484. const files = e && e.target && e.target.files
  485. if (!files || !files.length || !this.pendingDynamicRow) return
  486. const file = files[0]
  487. const row = this.pendingDynamicRow
  488. // 参数收集
  489. const surveyTemplateId =
  490. (row && (row.surveyTemplateId || row.templateId)) ||
  491. this.surveyTemplateId ||
  492. ''
  493. const taskId = (row && row.taskId) || this.taskId || ''
  494. const materialId = row && (row.materialId || row.materialID || row.id)
  495. const periodRecordId =
  496. row && (row.periodRecordId || row.uploadId || row.id)
  497. if (!surveyTemplateId || !taskId) {
  498. this.$message &&
  499. this.$message.warning &&
  500. this.$message.warning('缺少必要参数,无法上传')
  501. return
  502. }
  503. const formData = new FormData()
  504. formData.append('file', file)
  505. formData.append('surveyTemplateId', surveyTemplateId)
  506. formData.append('taskId', taskId)
  507. if (materialId) formData.append('materialId', materialId)
  508. if (periodRecordId) formData.append('periodRecordId', periodRecordId)
  509. formData.append('type', '1')
  510. let loading
  511. try {
  512. loading = this.$loading({
  513. lock: true,
  514. text: '数据上传中...',
  515. spinner: 'el-icon-loading',
  516. background: 'rgba(0, 0, 0, 0.7)',
  517. })
  518. await importData(formData)
  519. this.$message &&
  520. this.$message.success &&
  521. this.$message.success('数据上传成功')
  522. // 上传成功后触发刷新
  523. this.$emit('handle-dynamic-table-save', { row, tableData: {} })
  524. this.handleRefresh()
  525. } catch (err) {
  526. console.error('数据上传失败:', err)
  527. } finally {
  528. if (loading && loading.close) loading.close()
  529. this.pendingDynamicRow = null
  530. if (this.$refs.dynamicUploadInput)
  531. this.$refs.dynamicUploadInput.value = ''
  532. }
  533. },
  534. // 动态表-数据下载
  535. async handleDataDownload(row) {
  536. try {
  537. const loading = this.$loading({
  538. lock: true,
  539. text: '数据下载中...',
  540. spinner: 'el-icon-loading',
  541. background: 'rgba(0, 0, 0, 0.7)',
  542. })
  543. // 取 surveyTemplateId 与 versionId
  544. const surveyTemplateId =
  545. (row && (row.surveyTemplateId || row.templateId)) ||
  546. this.surveyTemplateId ||
  547. ''
  548. const versionId =
  549. (row && (row.versionId || row.version || row.templateVersionId)) ||
  550. ''
  551. // if (!surveyTemplateId || !versionId) {
  552. // loading.close()
  553. // this.$message &&
  554. // this.$message.warning &&
  555. // this.$message.warning('缺少模板或版本信息,无法下载')
  556. // return
  557. // }
  558. const params = { surveyTemplateId, versionId, type: 1 }
  559. // 追加 taskId(来自行或页面 props)
  560. const taskId = (row && (row.taskId || row.taskID)) || this.taskId
  561. if (taskId) params.taskId = taskId
  562. const res = await downloadTemplate(params)
  563. loading.close()
  564. // 处理响应数据(可能是 axios 响应或直接 Blob)
  565. const headers = (res && res.headers) || {}
  566. const contentDisposition =
  567. headers['content-disposition'] || headers['Content-Disposition']
  568. let fileName =
  569. this.extractFileNameFromHeader(contentDisposition) ||
  570. `${row.name || '数据'}.xlsx`
  571. if (!/\.[a-zA-Z0-9]+$/.test(fileName)) {
  572. fileName += '.xlsx'
  573. }
  574. const blobData = (res && res.data) || res
  575. const blob =
  576. blobData instanceof Blob ? blobData : new Blob([blobData])
  577. const url = window.URL.createObjectURL(blob)
  578. const link = document.createElement('a')
  579. link.style.display = 'none'
  580. link.href = url
  581. link.download = fileName
  582. document.body.appendChild(link)
  583. link.click()
  584. document.body.removeChild(link)
  585. window.URL.revokeObjectURL(url)
  586. this.$message &&
  587. this.$message.success &&
  588. this.$message.success('开始下载文件')
  589. } catch (e) {
  590. console.error('数据下载失败: ', e)
  591. }
  592. },
  593. extractFileNameFromHeader(contentDisposition) {
  594. if (!contentDisposition) return ''
  595. const match = /filename[^;=\n]*=((['"])?.*?\2|[^;\n]*)/i.exec(
  596. contentDisposition
  597. )
  598. if (match && match[1]) {
  599. try {
  600. return decodeURIComponent(match[1].replace(/['"]/g, ''))
  601. } catch (e) {
  602. return match[1].replace(/['"]/g, '')
  603. }
  604. }
  605. return ''
  606. },
  607. // 初始化动态表数据
  608. async initDynamicTableData() {
  609. try {
  610. this.dynamicTableLoading = true
  611. const uploadId =
  612. (this.currentSurveyRow &&
  613. (this.currentSurveyRow.uploadId || this.currentSurveyRow.id)) ||
  614. this.uploadId ||
  615. ''
  616. const auditedUnitId =
  617. this.auditedUnitId ||
  618. (this.currentSurveyRow && this.currentSurveyRow.auditedUnitId) ||
  619. ''
  620. const catalogId =
  621. (this.currentSurveyRow && this.currentSurveyRow.catalogId) ||
  622. this.catalogId ||
  623. ''
  624. const surveyTemplateId =
  625. (this.currentSurveyRow && this.currentSurveyRow.surveyTemplateId) ||
  626. this.surveyTemplateId ||
  627. ''
  628. const params = {
  629. uploadId,
  630. auditedUnitId,
  631. catalogId,
  632. surveyTemplateId,
  633. type: 1,
  634. }
  635. const res = await getDynamicTableData(params)
  636. if (res && res.code === 200) {
  637. const records = res.value?.records || res.value || []
  638. this.dynamicTableData = Array.isArray(records) ? records : []
  639. } else {
  640. // 接口调用失败,使用当前行的动态表数据或空数组
  641. this.dynamicTableData =
  642. this.currentSurveyRow?.dynamicTableData || []
  643. }
  644. // 初始化表格项配置(用于详情/编辑时显示表单)
  645. if (
  646. this.currentSurveyRow &&
  647. this.currentSurveyRow.tableItems &&
  648. this.currentSurveyRow.tableItems.length > 0
  649. ) {
  650. this.tableItems = this.currentSurveyRow.tableItems
  651. } else {
  652. this.tableItems = this.getMockTableItems()
  653. }
  654. this.dynamicTableDialogVisible = true
  655. } catch (error) {
  656. console.error('获取动态表数据失败', error)
  657. // 出错时使用当前行的动态表数据或空数组
  658. this.dynamicTableData = this.currentSurveyRow?.dynamicTableData || []
  659. this.tableItems =
  660. this.currentSurveyRow?.tableItems || this.getMockTableItems()
  661. // 出错时也打开弹窗
  662. this.dynamicTableDialogVisible = true
  663. } finally {
  664. this.dynamicTableLoading = false
  665. }
  666. },
  667. // 初始化表单字段配置
  668. async initFormFields() {
  669. // 如果是单记录类型,调用接口获取表单字段配置(包含校验规则)
  670. if (
  671. this.currentSurveyRow &&
  672. this.currentSurveyRow.tableType === '单记录' &&
  673. this.currentSurveyRow.surveyTemplateId
  674. ) {
  675. try {
  676. const params = {
  677. surveyTemplateId: this.currentSurveyRow.surveyTemplateId,
  678. type: 1,
  679. }
  680. // 调用 getListBySurveyTemplateIdAndVersion 获取完整的字段配置(包含校验规则)
  681. const res = await getListBySurveyTemplateIdAndVersion(params)
  682. console.log('单记录表单字段配置(含校验规则)', res)
  683. if (res && res.code === 200) {
  684. let mapped = []
  685. if (Array.isArray(res.value)) {
  686. // 数组格式:直接映射每个字段(包含完整的校验规则)
  687. mapped = res.value
  688. .map((item, index) =>
  689. this.mapApiFieldToFormField(item, index)
  690. )
  691. .filter(Boolean)
  692. } else if (res.value && typeof res.value === 'object') {
  693. // 对象格式:从 fixedFields 和 fixedFieldids 解析(兼容旧格式)
  694. const { fixedFields, fixedFieldids } = res.value
  695. if (fixedFields && fixedFieldids) {
  696. const labels = fixedFields
  697. .split(',')
  698. .map((item) => item.trim())
  699. const ids = fixedFieldids
  700. .split(',')
  701. .map((item) => item.trim())
  702. mapped = labels.map((label, index) => ({
  703. prop: ids[index] || `field_${index}`,
  704. label: label,
  705. type: 'input',
  706. colSpan: 12,
  707. placeholder: `请输入${label}`,
  708. rules: [],
  709. defaultValue: '',
  710. disabled: false,
  711. clearable: true,
  712. multiple: false,
  713. required: false,
  714. }))
  715. }
  716. }
  717. if (mapped.length > 0) {
  718. // 使用包含完整校验规则的字段配置
  719. this.formFields = mapped
  720. console.log(
  721. '转换后的表单字段配置(含校验规则)',
  722. this.formFields
  723. )
  724. } else {
  725. // 如果没有数据,使用默认配置
  726. this.formFields = this.getMockFormFields()
  727. }
  728. } else {
  729. // 接口返回失败,使用默认配置
  730. this.formFields = this.getMockFormFields()
  731. }
  732. // 打开弹窗
  733. this.surveyFormDialogVisible = true
  734. } catch (err) {
  735. console.error('获取单记录表单字段配置失败', err)
  736. // 出错时使用默认配置
  737. this.formFields = this.getMockFormFields()
  738. this.surveyFormDialogVisible = true
  739. }
  740. } else if (this.currentSurveyRow && this.currentSurveyRow.formFields) {
  741. // 如果当前行有表单配置,则使用
  742. this.formFields = this.currentSurveyRow.formFields
  743. this.surveyFormDialogVisible = true
  744. } else {
  745. // 使用假数据作为测试(实际开发中应该从后台获取)
  746. this.formFields = this.getMockFormFields()
  747. this.surveyFormDialogVisible = true
  748. }
  749. },
  750. // 将 API 返回的字段数据映射为表单字段配置(包含校验规则)
  751. mapApiFieldToFormField(item, index = 0) {
  752. if (!item) return null
  753. const getVal = (keys, fallback) => {
  754. for (const key of keys) {
  755. if (
  756. key &&
  757. item[key] !== undefined &&
  758. item[key] !== null &&
  759. item[key] !== ''
  760. ) {
  761. return item[key]
  762. }
  763. }
  764. return fallback
  765. }
  766. const toBool = (value) => {
  767. if (value === undefined || value === null) return false
  768. if (typeof value === 'boolean') return value
  769. if (typeof value === 'number') return value === 1
  770. const str = String(value).trim().toLowerCase()
  771. return ['1', 'true', 'y', 'yes', '是'].includes(str)
  772. }
  773. const toNumber = (value) => {
  774. if (value === undefined || value === null || value === '')
  775. return undefined
  776. const num = Number(value)
  777. return Number.isNaN(num) ? undefined : num
  778. }
  779. const prop =
  780. getVal(
  781. [
  782. 'fieldName',
  783. 'field_name',
  784. 'columnName',
  785. 'column_name',
  786. 'fieldCode',
  787. ],
  788. undefined
  789. ) || `field_${index}`
  790. const label =
  791. getVal(
  792. [
  793. 'columnComment',
  794. 'column_comment',
  795. 'fieldCname',
  796. 'field_cname',
  797. 'fieldLabel',
  798. 'field_label',
  799. ],
  800. prop
  801. ) || prop
  802. const columnType =
  803. (getVal(
  804. ['columnType', 'column_type', 'fieldType', 'field_type'],
  805. ''
  806. ) || '') + ''
  807. const columnTypeLower = columnType.toLowerCase()
  808. const totalLength = toNumber(
  809. getVal(
  810. ['fieldTypeLen', 'field_typelen', 'length', 'fieldLength'],
  811. undefined
  812. )
  813. )
  814. const decimalLength = toNumber(
  815. getVal(
  816. ['fieldTypeNointLen', 'field_typenointlen', 'scale'],
  817. undefined
  818. )
  819. )
  820. const isAuditPeriod = toBool(
  821. getVal(['isAuditPeriod', 'is_audit_period'], false)
  822. )
  823. const dictCode =
  824. getVal(
  825. [
  826. 'dictCode',
  827. 'dict_code',
  828. 'dictId',
  829. 'dictid',
  830. 'dictType',
  831. 'dict_type',
  832. ],
  833. ''
  834. ) || ''
  835. const optionsRaw = getVal(['options'], [])
  836. let options = []
  837. if (Array.isArray(optionsRaw)) {
  838. options = optionsRaw
  839. } else if (typeof optionsRaw === 'string' && optionsRaw.trim() !== '') {
  840. options = optionsRaw.split(',').map((value) => ({
  841. label: value.trim(),
  842. value: value.trim(),
  843. }))
  844. }
  845. let type = getVal(['componentType', 'type'], '')
  846. if (!type) {
  847. if (dictCode || options.length > 0) {
  848. type = 'select'
  849. } else if (
  850. columnTypeLower.includes('datetime') ||
  851. columnTypeLower.includes('timestamp') ||
  852. columnTypeLower.includes('date time')
  853. ) {
  854. type = 'datetime'
  855. } else if (columnTypeLower.includes('date')) {
  856. type = 'date'
  857. } else if (columnTypeLower.includes('year')) {
  858. type = 'year'
  859. } else if (
  860. columnTypeLower.includes('int') ||
  861. columnTypeLower.includes('number') ||
  862. columnTypeLower.includes('decimal') ||
  863. columnTypeLower.includes('float') ||
  864. columnTypeLower.includes('double')
  865. ) {
  866. type = 'number'
  867. } else {
  868. type = 'input'
  869. }
  870. }
  871. const required = toBool(
  872. getVal(['isRequired', 'is_required', 'required'], false)
  873. )
  874. const multiple = toBool(
  875. getVal(['isMultiple', 'is_multiple', 'multiple'], false)
  876. )
  877. const colSpan =
  878. toNumber(
  879. getVal(['colSpan', 'colspan', 'columnSpan', 'column_span'], 12)
  880. ) || 12
  881. const placeholder =
  882. getVal(
  883. ['placeholder', 'columnComment', 'column_comment'],
  884. undefined
  885. ) || (type === 'select' ? `请选择${label}` : `请输入${label}`)
  886. const defaultValue = getVal(
  887. ['defaultValue', 'default_value', 'defaultVal', 'default_val'],
  888. undefined
  889. )
  890. const precision = toNumber(
  891. getVal(
  892. ['fieldTypeNointLen', 'field_typenointlen', 'precision'],
  893. undefined
  894. )
  895. )
  896. const min = toNumber(getVal(['min'], undefined))
  897. const max = toNumber(getVal(['max'], undefined))
  898. const format = getVal(['format'], undefined)
  899. const valueFormat =
  900. getVal(['valueFormat', 'value_format'], undefined) ||
  901. (type === 'datetime'
  902. ? 'yyyy-MM-dd HH:mm:ss'
  903. : type === 'date'
  904. ? 'yyyy-MM-dd'
  905. : type === 'year'
  906. ? 'yyyy'
  907. : undefined)
  908. const formatLength = this.extractLengthFromFormat(format)
  909. const rules = this.buildFieldRules({
  910. type,
  911. label,
  912. required,
  913. totalLength,
  914. decimalLength,
  915. formatLength,
  916. format,
  917. isAuditPeriod,
  918. })
  919. return {
  920. prop,
  921. label,
  922. type,
  923. colSpan,
  924. placeholder,
  925. dictCode,
  926. dictType: dictCode,
  927. options,
  928. required,
  929. defaultValue,
  930. multiple,
  931. precision,
  932. min,
  933. max,
  934. format,
  935. valueFormat,
  936. totalLength,
  937. decimalLength,
  938. formatLength,
  939. rules, // 包含完整的校验规则
  940. }
  941. },
  942. // 从 format 中提取长度
  943. extractLengthFromFormat(format) {
  944. if (!format) return undefined
  945. const str = String(format).trim()
  946. if (!str) return undefined
  947. const match = str.match(/\d+/)
  948. if (match && match[0]) {
  949. const len = Number(match[0])
  950. return Number.isNaN(len) ? undefined : len
  951. }
  952. return undefined
  953. },
  954. // 构建字段校验规则
  955. buildFieldRules(meta) {
  956. const {
  957. type,
  958. label,
  959. required,
  960. totalLength,
  961. decimalLength,
  962. formatLength,
  963. format,
  964. isAuditPeriod,
  965. } = meta || {}
  966. const rules = []
  967. const trigger = type === 'select' ? 'change' : 'blur'
  968. if (required) {
  969. rules.push({
  970. required: true,
  971. message: `${type === 'select' ? '请选择' : '请输入'}${label}`,
  972. trigger,
  973. })
  974. }
  975. const inputMaxLength = formatLength || totalLength
  976. if (type === 'input' && inputMaxLength) {
  977. rules.push({
  978. validator: (_, value, callback) => {
  979. if (value === undefined || value === null || value === '') {
  980. callback()
  981. return
  982. }
  983. const str = String(value)
  984. if (str.length > inputMaxLength) {
  985. callback(
  986. new Error(`${label}长度不能超过${inputMaxLength}个字符`)
  987. )
  988. } else {
  989. callback()
  990. }
  991. },
  992. trigger: 'blur',
  993. })
  994. }
  995. const numberTotal = totalLength || formatLength
  996. if (type === 'number') {
  997. rules.push({
  998. validator: (_, value, callback) => {
  999. if (value === undefined || value === null || value === '') {
  1000. callback()
  1001. return
  1002. }
  1003. if (Number.isNaN(Number(value))) {
  1004. callback(new Error(`${label}必须为数字`))
  1005. return
  1006. }
  1007. const pure = String(value).replace('-', '')
  1008. if (numberTotal && pure.replace('.', '').length > numberTotal) {
  1009. callback(new Error(`${label}总位数不能超过${numberTotal}`))
  1010. return
  1011. }
  1012. if (decimalLength !== undefined && decimalLength !== null) {
  1013. const decimals = pure.split('.')[1] || ''
  1014. if (decimals.length > decimalLength) {
  1015. callback(
  1016. new Error(`${label}小数位不能超过${decimalLength}位`)
  1017. )
  1018. return
  1019. }
  1020. }
  1021. callback()
  1022. },
  1023. trigger: 'blur',
  1024. })
  1025. }
  1026. if (type === 'datetime' || type === 'date') {
  1027. if (format) {
  1028. rules.push({
  1029. validator: (_, value, callback) => {
  1030. if (value === undefined || value === null || value === '') {
  1031. callback()
  1032. return
  1033. }
  1034. callback()
  1035. },
  1036. trigger: 'change',
  1037. })
  1038. }
  1039. }
  1040. if (type === 'year' || isAuditPeriod) {
  1041. rules.push({
  1042. validator: (_, value, callback) => {
  1043. if (value === undefined || value === null || value === '') {
  1044. callback()
  1045. return
  1046. }
  1047. const pattern = /^\d{4}$/
  1048. if (!pattern.test(String(value))) {
  1049. callback(new Error(`${label}必须是四位年份`))
  1050. } else {
  1051. callback()
  1052. }
  1053. },
  1054. trigger: 'change',
  1055. })
  1056. }
  1057. return rules
  1058. },
  1059. // 获取假数据表单字段配置(用于测试)
  1060. getMockFormFields() {
  1061. // return [
  1062. // {
  1063. // prop: 'institutionName',
  1064. // label: '机构名称',
  1065. // type: 'input',
  1066. // colSpan: 12,
  1067. // defaultValue: '幼儿园基本情况',
  1068. // placeholder: '请输入机构名称',
  1069. // required: true,
  1070. // },
  1071. // {
  1072. // prop: 'institutionNature',
  1073. // label: '机构性质',
  1074. // type: 'select',
  1075. // colSpan: 12,
  1076. // dictType: 'institutionNature', // 字典类型
  1077. // defaultValue: '公办',
  1078. // placeholder: '请选择机构性质',
  1079. // required: true,
  1080. // clearable: true,
  1081. // },
  1082. // {
  1083. // prop: 'institutionLevel',
  1084. // label: '机构评定等级',
  1085. // type: 'select',
  1086. // colSpan: 12,
  1087. // dictType: 'institutionLevel', // 字典类型
  1088. // defaultValue: '省一级',
  1089. // placeholder: '请选择机构评定等级',
  1090. // required: true,
  1091. // clearable: true,
  1092. // },
  1093. // {
  1094. // prop: 'educationMode',
  1095. // label: '机构办学方式',
  1096. // type: 'select',
  1097. // colSpan: 12,
  1098. // dictType: 'educationMode', // 字典类型
  1099. // defaultValue: '全日制',
  1100. // placeholder: '请选择机构办学方式',
  1101. // required: true,
  1102. // clearable: true,
  1103. // },
  1104. // {
  1105. // prop: 'institutionAddress',
  1106. // label: '机构地址',
  1107. // type: 'input',
  1108. // colSpan: 12,
  1109. // placeholder: '请输入机构地址',
  1110. // required: true,
  1111. // },
  1112. // {
  1113. // prop: 'formFiller',
  1114. // label: '机构填表人',
  1115. // type: 'input',
  1116. // colSpan: 12,
  1117. // placeholder: '请输入机构填表人',
  1118. // required: true,
  1119. // },
  1120. // {
  1121. // prop: 'financialManager',
  1122. // label: '机构财务负责人',
  1123. // type: 'input',
  1124. // colSpan: 12,
  1125. // placeholder: '请输入机构财务负责人',
  1126. // required: true,
  1127. // },
  1128. // {
  1129. // prop: 'contactPhone',
  1130. // label: '机构联系电话',
  1131. // type: 'input',
  1132. // colSpan: 12,
  1133. // placeholder: '请输入机构联系电话',
  1134. // required: true,
  1135. // rules: [
  1136. // {
  1137. // required: true,
  1138. // message: '请输入机构联系电话',
  1139. // trigger: 'blur',
  1140. // },
  1141. // {
  1142. // pattern: /^1[3-9]\d{9}$/,
  1143. // message: '请输入正确的手机号码',
  1144. // trigger: 'blur',
  1145. // },
  1146. // ],
  1147. // },
  1148. // ]
  1149. },
  1150. // 初始化固定表数据
  1151. async initFixedTableData() {
  1152. // 如果是固定表类型,调用接口获取固定表配置
  1153. if (
  1154. this.currentSurveyRow &&
  1155. this.currentSurveyRow.tableType === '固定表' &&
  1156. this.currentSurveyRow.surveyTemplateId
  1157. ) {
  1158. try {
  1159. const params = {
  1160. surveyTemplateId: this.currentSurveyRow.surveyTemplateId,
  1161. type: 1,
  1162. }
  1163. const res = await getSingleRecordSurveyList(params)
  1164. console.log('固定表配置数据', res)
  1165. if (res && res.code === 200 && res.value) {
  1166. // 将接口返回的数据转换为固定表配置格式
  1167. // 固定表使用 itemlist,不使用 fixedFields 和 fixedFieldids
  1168. const { itemlist } = res.value
  1169. console.log('itemlist', itemlist)
  1170. // 如果有 itemlist,使用 itemlist 作为表格项配置
  1171. if (itemlist && Array.isArray(itemlist) && itemlist.length > 0) {
  1172. this.tableItems = itemlist.map((item, index) => ({
  1173. id: item.id || item.itemId || '',
  1174. rowid: item.rowid || item.id || item.itemId || '', // rowid 用于父子关系
  1175. seq: item.序号, // 序号就是序号
  1176. itemName: item.项目 || '', // 项目就是项目
  1177. unit: item.unit || '', // 单位是 unit
  1178. isCategory: item.isCategory || false,
  1179. categorySeq: item.categorySeq || '',
  1180. categoryId: item.categoryId || '',
  1181. parentid:
  1182. item.parentid !== undefined
  1183. ? item.parentid
  1184. : item.parentId !== undefined
  1185. ? item.parentId
  1186. : '-1', // 父项ID,默认为 '-1'(父项)
  1187. validateRules: item.validateRules || {},
  1188. linkageRules: item.linkageRules || {},
  1189. children: item.children || [],
  1190. ...item, // 保留其他字段
  1191. }))
  1192. // 若该接口同时提供 fixedFields/fixedFieldids,则同步到弹窗表头
  1193. if (res.value.fixedFields && res.value.fixedFieldids) {
  1194. this.fixedFields = res.value.fixedFields
  1195. console.log(this.fixedFields, 'biaogeshuju')
  1196. this.fixedFieldids = res.value.fixedFieldids
  1197. }
  1198. } else {
  1199. // 如果没有 itemlist,使用假数据
  1200. this.tableItems = this.getMockTableItems()
  1201. }
  1202. } else {
  1203. // 接口返回失败,使用默认配置
  1204. this.tableItems = this.getMockTableItems()
  1205. }
  1206. } catch (err) {
  1207. console.error('获取固定表配置失败', err)
  1208. // 出错时使用默认配置
  1209. this.tableItems = this.getMockTableItems()
  1210. }
  1211. } else if (this.currentSurveyRow && this.currentSurveyRow.tableItems) {
  1212. // 如果当前行有表格配置,则使用
  1213. this.tableItems = this.currentSurveyRow.tableItems
  1214. } else {
  1215. // 使用假数据作为测试(实际开发中应该从后台获取)
  1216. this.tableItems = this.getMockTableItems()
  1217. }
  1218. // 初始化监审期间(从立项信息中获取)
  1219. if (this.auditPeriod) {
  1220. // 如果传入了监审期间,使用传入的值
  1221. if (Array.isArray(this.auditPeriod)) {
  1222. this.auditPeriods = this.auditPeriod.map((p) => String(p))
  1223. } else {
  1224. this.auditPeriods = this.parseAuditPeriod(this.auditPeriod)
  1225. }
  1226. } else if (this.currentSurveyRow && this.currentSurveyRow.auditPeriod) {
  1227. // 如果当前行有监审期间,使用当前行的
  1228. this.auditPeriods = this.parseAuditPeriod(
  1229. this.currentSurveyRow.auditPeriod
  1230. )
  1231. } else {
  1232. // 默认使用最近3年
  1233. const currentYear = new Date().getFullYear()
  1234. this.auditPeriods = [
  1235. String(currentYear - 2),
  1236. String(currentYear - 1),
  1237. String(currentYear),
  1238. ]
  1239. }
  1240. // 额外拉取表头/规则信息,并透传给弹窗
  1241. try {
  1242. const headerRes = await getListBySurveyTemplateIdAndVersion({
  1243. surveyTemplateId: this.currentSurveyRow.surveyTemplateId,
  1244. type: 1,
  1245. })
  1246. if (headerRes && headerRes.code === 200) {
  1247. this.fixedHeaders = headerRes.value || null
  1248. // 解析并下发 fixedFields/columnsMeta
  1249. if (Array.isArray(headerRes.value)) {
  1250. // 数组:作为 columnsMeta 使用;fixedFields 从 getSingleRecordSurveyList 的表头或留空
  1251. this.columnsMeta = headerRes.value
  1252. } else if (headerRes.value && typeof headerRes.value === 'object') {
  1253. const { fixedFields, fixedFieldids, items } = headerRes.value
  1254. this.fixedFields = fixedFields || ''
  1255. this.fixedFieldids = fixedFieldids || ''
  1256. // 如果对象里还有 items 数组,作为 columnsMeta;否则整对象不便直接使用
  1257. if (Array.isArray(items)) {
  1258. this.columnsMeta = items
  1259. } else {
  1260. this.columnsMeta = []
  1261. }
  1262. } else {
  1263. this.columnsMeta = []
  1264. }
  1265. } else {
  1266. this.fixedHeaders = null
  1267. this.columnsMeta = []
  1268. }
  1269. } catch (e) {
  1270. this.fixedHeaders = null
  1271. this.columnsMeta = []
  1272. }
  1273. // 打开弹窗
  1274. this.fixedTableDialogVisible = true
  1275. },
  1276. // 解析监审期间字符串(如 "2022,2023,2024" 或 "2022-2024")
  1277. parseAuditPeriod(periodStr) {
  1278. if (!periodStr) return []
  1279. if (periodStr.includes(',')) {
  1280. return periodStr.split(',').map((p) => p.trim())
  1281. }
  1282. if (periodStr.includes('-')) {
  1283. const parts = periodStr.split('-')
  1284. if (parts.length === 2) {
  1285. const start = parseInt(parts[0].trim())
  1286. const end = parseInt(parts[1].trim())
  1287. const years = []
  1288. for (let year = start; year <= end; year++) {
  1289. years.push(String(year))
  1290. }
  1291. return years
  1292. }
  1293. }
  1294. return [String(periodStr)]
  1295. },
  1296. // 获取假数据表格配置(用于测试)
  1297. getMockTableItems() {
  1298. // return [
  1299. // {
  1300. // id: '1',
  1301. // itemName: '班级数',
  1302. // unit: '个',
  1303. // isCategory: false,
  1304. // seq: 1,
  1305. // validateRules: {
  1306. // required: true,
  1307. // type: 'number',
  1308. // min: 0,
  1309. // },
  1310. // },
  1311. // {
  1312. // id: '2',
  1313. // itemName: '幼儿学生人数',
  1314. // unit: '人',
  1315. // isCategory: false,
  1316. // seq: 2,
  1317. // validateRules: {
  1318. // required: true,
  1319. // type: 'number',
  1320. // min: 0,
  1321. // },
  1322. // },
  1323. // {
  1324. // id: 'III',
  1325. // itemName: '在取做保职工总人数',
  1326. // unit: '人',
  1327. // isCategory: true,
  1328. // categorySeq: 'III',
  1329. // children: [
  1330. // {
  1331. // id: '3-1',
  1332. // itemName: '行政管理人员数',
  1333. // unit: '人',
  1334. // isCategory: false,
  1335. // categoryId: 'III',
  1336. // seq: 3,
  1337. // validateRules: {
  1338. // required: true,
  1339. // type: 'number',
  1340. // min: 0,
  1341. // },
  1342. // linkageRules: {
  1343. // parent: 'III',
  1344. // relation: 'sum',
  1345. // },
  1346. // },
  1347. // {
  1348. // id: '3-2',
  1349. // itemName: '教师人数',
  1350. // unit: '人',
  1351. // isCategory: false,
  1352. // categoryId: 'III',
  1353. // seq: 4,
  1354. // validateRules: {
  1355. // required: true,
  1356. // type: 'number',
  1357. // min: 0,
  1358. // },
  1359. // linkageRules: {
  1360. // parent: 'III',
  1361. // relation: 'sum',
  1362. // },
  1363. // },
  1364. // {
  1365. // id: '3-3',
  1366. // itemName: '保育员人数',
  1367. // unit: '人',
  1368. // isCategory: false,
  1369. // categoryId: 'III',
  1370. // seq: 5,
  1371. // validateRules: {
  1372. // required: true,
  1373. // type: 'number',
  1374. // min: 0,
  1375. // },
  1376. // linkageRules: {
  1377. // parent: 'III',
  1378. // relation: 'sum',
  1379. // },
  1380. // },
  1381. // {
  1382. // id: '3-4',
  1383. // itemName: '医务人员',
  1384. // unit: '人',
  1385. // isCategory: false,
  1386. // categoryId: 'III',
  1387. // seq: 6,
  1388. // validateRules: {
  1389. // required: true,
  1390. // type: 'number',
  1391. // min: 0,
  1392. // },
  1393. // linkageRules: {
  1394. // parent: 'III',
  1395. // relation: 'sum',
  1396. // },
  1397. // },
  1398. // {
  1399. // id: '3-5',
  1400. // itemName: '工勤人员',
  1401. // unit: '人',
  1402. // isCategory: false,
  1403. // categoryId: 'III',
  1404. // seq: 7,
  1405. // validateRules: {
  1406. // required: true,
  1407. // type: 'number',
  1408. // min: 0,
  1409. // },
  1410. // linkageRules: {
  1411. // parent: 'III',
  1412. // relation: 'sum',
  1413. // },
  1414. // children: [
  1415. // {
  1416. // id: '3-5-1',
  1417. // itemName: '炊事员',
  1418. // unit: '人',
  1419. // isCategory: false,
  1420. // categoryId: '3-5',
  1421. // seq: 8,
  1422. // validateRules: {
  1423. // required: true,
  1424. // type: 'number',
  1425. // min: 0,
  1426. // },
  1427. // linkageRules: {
  1428. // parent: '3-5',
  1429. // relation: 'sum',
  1430. // },
  1431. // },
  1432. // {
  1433. // id: '3-5-2',
  1434. // itemName: '司机',
  1435. // unit: '人',
  1436. // isCategory: false,
  1437. // categoryId: '3-5',
  1438. // seq: 9,
  1439. // validateRules: {
  1440. // required: true,
  1441. // type: 'number',
  1442. // min: 0,
  1443. // },
  1444. // linkageRules: {
  1445. // parent: '3-5',
  1446. // relation: 'sum',
  1447. // },
  1448. // },
  1449. // {
  1450. // id: '3-5-3',
  1451. // itemName: '清洁工',
  1452. // unit: '人',
  1453. // isCategory: false,
  1454. // categoryId: '3-5',
  1455. // seq: 10,
  1456. // validateRules: {
  1457. // required: true,
  1458. // type: 'number',
  1459. // min: 0,
  1460. // },
  1461. // linkageRules: {
  1462. // parent: '3-5',
  1463. // relation: 'sum',
  1464. // },
  1465. // },
  1466. // ],
  1467. // },
  1468. // {
  1469. // id: '3-6',
  1470. // itemName: '其他人员',
  1471. // unit: '人',
  1472. // isCategory: false,
  1473. // categoryId: 'III',
  1474. // seq: 11,
  1475. // validateRules: {
  1476. // required: true,
  1477. // type: 'number',
  1478. // min: 0,
  1479. // },
  1480. // linkageRules: {
  1481. // parent: 'III',
  1482. // relation: 'sum',
  1483. // },
  1484. // },
  1485. // ],
  1486. // },
  1487. // ]
  1488. },
  1489. resetDynamicDialogState() {
  1490. this.dynamicTableDialogVisible = false
  1491. this.dynamicTableData = []
  1492. this.tableItems = []
  1493. this.dynamicDialogKey = Date.now()
  1494. },
  1495. },
  1496. }
  1497. </script>