uploadCost.vue 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095
  1. <template>
  2. <div class="uploadCost">
  3. <el-dialog
  4. v-loading="loading"
  5. :before-close="closeUpload"
  6. :close-on-click-modal="false"
  7. :close-on-press-escape="false"
  8. :title="importTitle"
  9. :visible.sync="dialogVisible"
  10. append-to-body
  11. width="50%"
  12. >
  13. <!-- :title="isImport?'导入结果':'批量导入'"-->
  14. <div v-if="!isImport">
  15. <!-- <p v-for="(item, index) in uploadTitle" :key="index" class="uploadtitle">-->
  16. <!-- {{ item }}-->
  17. <!-- </p>-->
  18. <el-card style="padding-top: 10px;padding-bottom: 10px">
  19. <div style="width: 50%;float:left;">
  20. <p class="uploadtitle txtcenter">1.下载模板按要求填写</p>
  21. <img class="mtmb16 mgauto" src="@/assets/excelicon.png" width="50px">
  22. <div style="width: 100%">
  23. <el-button class="mtmb16 mgauto" size="small" type="primary" @click="downloadTemplate()">下载模板
  24. </el-button>
  25. </div>
  26. </div>
  27. <div style="width: 50%;float:left;">
  28. <p class="uploadtitle txtcenter">2.上传填写好的文件</p>
  29. <img class="mtmb16 mgauto" src="@/assets/excelicon.png" width="50px">
  30. <div class="mgauto2">
  31. <el-upload
  32. :file-list="fileUrlList"
  33. :http-request="uploadFile"
  34. :limit="1"
  35. accept=".xlsx"
  36. action="#"
  37. >
  38. <el-button class="mtmb16" size="small" style="margin-top: 0;height: 33px" type="primary">上传文件</el-button>
  39. <div slot="file" slot-scope="{file}">
  40. <a :href="file.url">{{ file.name }}</a>
  41. <span class="el-upload-list__item-actions">
  42. <i class="el-icon-delete" @click="handlePictureRemove(file,fileUrlList)" />
  43. </span>
  44. </div>
  45. </el-upload>
  46. </div>
  47. </div>
  48. </el-card>
  49. </div>
  50. <div v-if="isImport" style="margin:10px">
  51. <p>导入成功 <span>{{ successCount }} 条</span> ,失败 <span>{{ errorCount }}</span> 条 </p>
  52. <p>您可以下载失败记录,修改后重新上传。以下标红为校验失败项</p>
  53. <el-table
  54. :data="tableData"
  55. style="width: 100%;"
  56. >
  57. <el-table-column align="center" label="楼盘/小区名称" prop="groupName">
  58. <template v-slot="scope">
  59. <span>{{ scope.row.groupName }}</span>
  60. </template>
  61. </el-table-column>
  62. <el-table-column align="center" label="分期名称" prop="discName">
  63. <template v-slot="scope">
  64. <span>{{ scope.row.discName }}</span>
  65. </template>
  66. </el-table-column>
  67. <el-table-column align="center" label="单元/楼栋号" prop="buildNum">
  68. <template v-slot="scope">
  69. <span>{{ scope.row.buildNum }}</span>
  70. </template>
  71. </el-table-column>
  72. <el-table-column align="center" label="户室号" prop="roomNo">
  73. <template v-slot="scope">
  74. <span>{{ scope.row.roomNo }}</span>
  75. </template>
  76. </el-table-column>
  77. <el-table-column align="center" label="异常原因" prop="reason">
  78. <template v-slot="scope">
  79. <span style="color: red">{{ scope.row.reason }}</span>
  80. </template>
  81. </el-table-column>
  82. </el-table>
  83. </div>
  84. <span slot="footer" class="dialog-footer">
  85. <el-button @click="closeUpload()">取 消</el-button>
  86. <el-button
  87. v-if="!isImport"
  88. :disabled="fileUrlList.length===0"
  89. type="primary"
  90. @click="importFile()"
  91. class="ch-button-else"
  92. >导入</el-button>
  93. <el-button
  94. v-if="isImport"
  95. type="primary"
  96. @click="exportError()"
  97. >
  98. 下载失败记录
  99. </el-button>
  100. </span>
  101. </el-dialog>
  102. </div>
  103. </template>
  104. <script>
  105. // import XLSX from 'xlsx'
  106. // import XLSXStyle from 'xlsx-style-fixedver'
  107. const XLSX = require('xlsx')
  108. const XLSXStyle = require('xlsx-style-fixedver')
  109. const defaultTitle = '批量导入'
  110. export default {
  111. props: {
  112. // 弹框状态
  113. dialogVisible: { type: Boolean, default: false },
  114. // 类型
  115. importType: { type: String, default: '' },
  116. // 上传说明
  117. uploadTitle: { type: Array, default: () => ([]) },
  118. // 名称
  119. importTitle: { type: String, default: '' }
  120. },
  121. data() {
  122. return {
  123. fileUrlList: [],
  124. tableData: [],
  125. title: defaultTitle.repeat(1),
  126. loading: false,
  127. isImport: false,
  128. file: null,
  129. successCount: 0,
  130. errorCount: ''
  131. }
  132. },
  133. methods: {
  134. importFile() {
  135. if (this.importType === 'groupInsert') {
  136. this.importGroup()
  137. }
  138. if (this.importType === 'FQInsert') {
  139. this.importFQ()
  140. }
  141. if (this.importType === 'buildInsert') {
  142. this.importBuild()
  143. }
  144. if (this.importType === 'roomInsert') {
  145. this.importRoom()
  146. }
  147. },
  148. importGroup() {
  149. this.loading = true
  150. this.$axios({
  151. headers: {
  152. 'Content-Type': 'multipart/form-data'
  153. },
  154. method: 'post',
  155. url: this.$constant.BASE_URI + '/ParkInfoController/handleImport',
  156. data: this.file
  157. }).then((res) => {
  158. this.loading = false
  159. if (res.data.code === 200) {
  160. this.$message({
  161. message: '上传成功',
  162. type: 'success'
  163. })
  164. // this.$emit('cancelUpload', true)
  165. this.successCount = res.data.data.successCount
  166. this.errorCount = res.data.data.errorCount
  167. this.tableData = res.data.data.errorList || []
  168. this.isImport = true
  169. console.log('上传成功....')
  170. } else {
  171. this.$message({
  172. message: res.data.msg,
  173. type: 'error'
  174. })
  175. }
  176. }).catch((err, x) => {
  177. console.log('biz user list error', err, x)
  178. })
  179. },
  180. importFQ() {
  181. this.loading = true
  182. this.$axios({
  183. headers: {
  184. 'Content-Type': 'multipart/form-data'
  185. },
  186. method: 'post',
  187. url: this.$constant.BASE_URI + '/ParkFloorDiscController/handleImport',
  188. data: this.file
  189. }).then((res) => {
  190. this.loading = false
  191. if (res.data.code === 200) {
  192. this.$message({
  193. message: '上传成功',
  194. type: 'success'
  195. })
  196. // this.$emit('cancelUpload', true)
  197. this.successCount = res.data.data.successCount
  198. this.errorCount = res.data.data.errorCount
  199. this.tableData = res.data.data.errorList || []
  200. this.isImport = true
  201. console.log('上传成功....')
  202. } else {
  203. this.$message({
  204. message: res.data.msg,
  205. type: 'error'
  206. })
  207. }
  208. }).catch((err, x) => {
  209. console.log('biz user list error', err, x)
  210. })
  211. },
  212. importBuild() {
  213. this.loading = true
  214. this.$axios({
  215. headers: {
  216. 'Content-Type': 'multipart/form-data'
  217. },
  218. method: 'post',
  219. url: this.$constant.BASE_URI + '/MnpBuildingController/handleImport',
  220. data: this.file
  221. }).then((res) => {
  222. this.loading = false
  223. if (res.data.code === 200) {
  224. this.$message({
  225. message: '上传成功',
  226. type: 'success'
  227. })
  228. // this.$emit('cancelUpload', true)
  229. this.successCount = res.data.data.successCount
  230. this.errorCount = res.data.data.errorCount
  231. this.tableData = res.data.data.errorList || []
  232. this.isImport = true
  233. console.log('上传成功....')
  234. } else {
  235. this.$message({
  236. message: res.data.msg,
  237. type: 'error'
  238. })
  239. }
  240. }).catch((err, x) => {
  241. console.log('biz user list error', err, x)
  242. })
  243. },
  244. importRoom() {
  245. this.loading = true
  246. this.$axios({
  247. headers: {
  248. 'Content-Type': 'multipart/form-data'
  249. },
  250. method: 'post',
  251. url: this.$constant.BASE_URI + '/ParkRoomController/handleImport',
  252. data: this.file
  253. }).then((res) => {
  254. this.loading = false
  255. if (res.data.code === 200) {
  256. this.$message({
  257. message: '上传成功',
  258. type: 'success'
  259. })
  260. // this.$emit('cancelUpload', true)
  261. this.successCount = res.data.data.successCount
  262. this.errorCount = res.data.data.errorCount
  263. this.tableData = res.data.data.errorList || []
  264. this.isImport = true
  265. console.log('上传成功....')
  266. } else {
  267. this.$message({
  268. message: res.data.msg,
  269. type: 'error'
  270. })
  271. }
  272. }).catch((err, x) => {
  273. console.log('biz user list error', err, x)
  274. })
  275. },
  276. closeUpload() {
  277. // 关闭弹窗
  278. this.$emit('cancelUpload')
  279. },
  280. uploadFile(param) {
  281. const formParam = new FormData()
  282. formParam.append('file', param.file)
  283. this.file = formParam
  284. this.fileUrlList.push({ name: param.file.name })
  285. },
  286. handlePictureRemove(file, fileUrlList) {
  287. const index = fileUrlList.indexOf(file)
  288. fileUrlList.splice(index, 1)
  289. this.file = null
  290. },
  291. exportError() {
  292. if (this.importType === 'groupInsert') {
  293. this.exportErrorGroup()
  294. }
  295. if (this.importType === 'FQInsert') {
  296. this.exportErrorFQ()
  297. }
  298. if (this.importType === 'buildInsert') {
  299. this.exportErrorBuild()
  300. }
  301. if (this.importType === 'roomInsert') {
  302. this.exportErrorRoom()
  303. }
  304. },
  305. exportErrorGroup() {
  306. if (!this.tableData.length) {
  307. this.$message.error('失败记录为空!')
  308. return
  309. }
  310. const outData = []
  311. const title = []
  312. title.push('楼盘/小区名称')
  313. title.push('性质')
  314. title.push('预销售许可证编号')
  315. title.push('开发公司')
  316. title.push('总建筑面积(㎡)')
  317. title.push('总用地面积(㎡)')
  318. title.push('立项批文')
  319. title.push('工程规划许可证')
  320. title.push('施工许可证')
  321. title.push('土地证号')
  322. title.push('用地许可证号')
  323. title.push('容积率')
  324. title.push('绿化率')
  325. title.push('标准单价')
  326. title.push('超标单价')
  327. title.push('楼盘面积测绘状态')
  328. title.push('楼盘销售状态')
  329. title.push('行政区划')
  330. title.push('详细地址')
  331. title.push('备注')
  332. title.push('异常原因')
  333. outData.push(title)
  334. const errorFiled = []
  335. this.tableData.forEach((item, index) => {
  336. const jsonArray = []
  337. jsonArray.push(item.groupName)
  338. jsonArray.push(item.nature)
  339. jsonArray.push(item.preSalesLicenseNumber)
  340. jsonArray.push(item.companyName)
  341. jsonArray.push(item.buildArea)
  342. jsonArray.push(item.landArea)
  343. jsonArray.push(item.projectApprovalDocument)
  344. jsonArray.push(item.engineeringPlanningPermit)
  345. jsonArray.push(item.constructionPermit)
  346. jsonArray.push(item.landCertificateNumber)
  347. jsonArray.push(item.landUsePermitNumber)
  348. jsonArray.push(item.volumeRatio)
  349. jsonArray.push(item.greenRatio)
  350. jsonArray.push(item.price)
  351. jsonArray.push(item.exceededPrice)
  352. jsonArray.push(item.areaStatus)
  353. jsonArray.push(item.saleStatus)
  354. jsonArray.push(item.regionalismCode)
  355. jsonArray.push(item.address)
  356. jsonArray.push(item.introduction)
  357. jsonArray.push(item.reason)
  358. outData.push(jsonArray)
  359. })
  360. const outSize = []
  361. title.forEach(item => {
  362. if (item.length > 4) {
  363. outSize.push({
  364. wch: 30
  365. })
  366. } else {
  367. outSize.push({
  368. wch: 15
  369. })
  370. }
  371. })
  372. const fileName = '失败记录导出 ' + new Date().Format('yyyy-MM-dd hh:mm')
  373. const ws = XLSX.utils.aoa_to_sheet(outData)
  374. ws['!cols'] = outSize
  375. ws['!rows'] = []
  376. if (errorFiled.length) {
  377. errorFiled.forEach(item => {
  378. if (!ws[item]) {
  379. ws[item] = {
  380. v: '',
  381. t: 's',
  382. s: {
  383. fill: {
  384. bgColor: { indexed: 64 }, fgColor: { rgb: 'FF0000' }
  385. },
  386. font: {
  387. color: { rgb: 'FFFFFF' }
  388. }
  389. }
  390. }
  391. } else {
  392. ws[item].s = {
  393. fill: {
  394. bgColor: { indexed: 64 }, fgColor: { rgb: 'FF0000' }
  395. },
  396. font: {
  397. color: { rgb: 'FFFFFF' }
  398. }
  399. }
  400. }
  401. })
  402. }
  403. const wb = XLSX.utils.book_new()
  404. XLSX.utils.book_append_sheet(wb, ws, fileName)
  405. const tmpDown = new Blob([
  406. this.s2ab(
  407. XLSXStyle.write(wb, {
  408. bookType: 'xlsx',
  409. bookSST: true,
  410. type: 'binary',
  411. cellStyles: true
  412. })
  413. )
  414. ])
  415. const elink = document.createElement('a')
  416. elink.download = decodeURIComponent(fileName + '.xlsx')
  417. elink.style.display = 'none'
  418. elink.href = URL.createObjectURL(tmpDown)
  419. document.body.appendChild(elink)
  420. elink.click()
  421. URL.revokeObjectURL(elink.href) // 释放URL 对象
  422. document.body.removeChild(elink)
  423. },
  424. exportErrorFQ() {
  425. if (!this.tableData.length) {
  426. this.$message.error('失败记录为空!')
  427. return
  428. }
  429. const outData = []
  430. const title = []
  431. title.push('楼盘/小区名称')
  432. title.push('分期名称')
  433. title.push('房屋买卖单价(元/㎡)')
  434. title.push('物业费单价(元/㎡)')
  435. title.push('住宅专项维修资金(元/㎡)')
  436. title.push('认购金(元)')
  437. title.push('共持比例')
  438. title.push('支付方式')
  439. title.push('异常原因')
  440. outData.push(title)
  441. const errorFiled = []
  442. this.tableData.forEach((item, index) => {
  443. const jsonArray = []
  444. jsonArray.push(item.groupName)
  445. jsonArray.push(item.name)
  446. jsonArray.push(item.unitPrice)
  447. jsonArray.push(item.propertyUnitPrice)
  448. jsonArray.push(item.maintenanceFunds)
  449. jsonArray.push(item.subscriptionFunds)
  450. jsonArray.push(item.proportion)
  451. jsonArray.push(item.paymentMethods)
  452. jsonArray.push(item.reason)
  453. outData.push(jsonArray)
  454. })
  455. const outSize = []
  456. title.forEach(item => {
  457. if (item.length > 4) {
  458. outSize.push({
  459. wch: 30
  460. })
  461. } else {
  462. outSize.push({
  463. wch: 15
  464. })
  465. }
  466. })
  467. const fileName = '失败记录导出 ' + new Date().Format('yyyy-MM-dd hh:mm')
  468. const ws = XLSX.utils.aoa_to_sheet(outData)
  469. ws['!cols'] = outSize
  470. ws['!rows'] = []
  471. if (errorFiled.length) {
  472. errorFiled.forEach(item => {
  473. if (!ws[item]) {
  474. ws[item] = {
  475. v: '',
  476. t: 's',
  477. s: {
  478. fill: {
  479. bgColor: { indexed: 64 }, fgColor: { rgb: 'FF0000' }
  480. },
  481. font: {
  482. color: { rgb: 'FFFFFF' }
  483. }
  484. }
  485. }
  486. } else {
  487. ws[item].s = {
  488. fill: {
  489. bgColor: { indexed: 64 }, fgColor: { rgb: 'FF0000' }
  490. },
  491. font: {
  492. color: { rgb: 'FFFFFF' }
  493. }
  494. }
  495. }
  496. })
  497. }
  498. const wb = XLSX.utils.book_new()
  499. XLSX.utils.book_append_sheet(wb, ws, fileName)
  500. const tmpDown = new Blob([
  501. this.s2ab(
  502. XLSXStyle.write(wb, {
  503. bookType: 'xlsx',
  504. bookSST: true,
  505. type: 'binary',
  506. cellStyles: true
  507. })
  508. )
  509. ])
  510. const elink = document.createElement('a')
  511. elink.download = decodeURIComponent(fileName + '.xlsx')
  512. elink.style.display = 'none'
  513. elink.href = URL.createObjectURL(tmpDown)
  514. document.body.appendChild(elink)
  515. elink.click()
  516. URL.revokeObjectURL(elink.href) // 释放URL 对象
  517. document.body.removeChild(elink)
  518. },
  519. exportErrorBuild() {
  520. if (!this.tableData.length) {
  521. this.$message.error('失败记录为空!')
  522. return
  523. }
  524. const outData = []
  525. const title = []
  526. title.push('楼盘/小区名称')
  527. title.push('分期名称')
  528. title.push('单元/楼栋号')
  529. title.push('总面积(㎡)')
  530. title.push('住宅面积(㎡)')
  531. title.push('非住宅面积(㎡)')
  532. title.push('占地面积(㎡)')
  533. title.push('地下面积(㎡)')
  534. title.push('房号')
  535. title.push('套数')
  536. title.push('总层数')
  537. title.push('地上层数')
  538. title.push('地下层数')
  539. title.push('结构')
  540. title.push('行政区划')
  541. title.push('地号')
  542. title.push('备注')
  543. title.push('标准价格参考层及差价系数备注说明')
  544. title.push('异常原因')
  545. outData.push(title)
  546. const errorFiled = []
  547. this.tableData.forEach((item, index) => {
  548. const jsonArray = []
  549. jsonArray.push(item.groupName)
  550. jsonArray.push(item.discName)
  551. jsonArray.push(item.buildNum)
  552. jsonArray.push(item.area)
  553. jsonArray.push(item.residentialArea)
  554. jsonArray.push(item.unResidentialArea)
  555. jsonArray.push(item.coverAnArea)
  556. jsonArray.push(item.undergroundArea)
  557. jsonArray.push(item.roomNum)
  558. jsonArray.push(item.numberInfo)
  559. jsonArray.push(item.floors)
  560. jsonArray.push(item.overgroundFloors)
  561. jsonArray.push(item.undergroundFloors)
  562. jsonArray.push(item.structure)
  563. jsonArray.push(item.regionalismCode)
  564. jsonArray.push(item.landCode)
  565. jsonArray.push(item.remark)
  566. jsonArray.push(item.priceRemark)
  567. jsonArray.push(item.reason)
  568. outData.push(jsonArray)
  569. })
  570. const outSize = []
  571. title.forEach(item => {
  572. if (item.length > 4) {
  573. outSize.push({
  574. wch: 30
  575. })
  576. } else {
  577. outSize.push({
  578. wch: 15
  579. })
  580. }
  581. })
  582. const fileName = '失败记录导出 ' + new Date().Format('yyyy-MM-dd hh:mm')
  583. const ws = XLSX.utils.aoa_to_sheet(outData)
  584. ws['!cols'] = outSize
  585. ws['!rows'] = []
  586. if (errorFiled.length) {
  587. errorFiled.forEach(item => {
  588. if (!ws[item]) {
  589. ws[item] = {
  590. v: '',
  591. t: 's',
  592. s: {
  593. fill: {
  594. bgColor: { indexed: 64 }, fgColor: { rgb: 'FF0000' }
  595. },
  596. font: {
  597. color: { rgb: 'FFFFFF' }
  598. }
  599. }
  600. }
  601. } else {
  602. ws[item].s = {
  603. fill: {
  604. bgColor: { indexed: 64 }, fgColor: { rgb: 'FF0000' }
  605. },
  606. font: {
  607. color: { rgb: 'FFFFFF' }
  608. }
  609. }
  610. }
  611. })
  612. }
  613. const wb = XLSX.utils.book_new()
  614. XLSX.utils.book_append_sheet(wb, ws, fileName)
  615. const tmpDown = new Blob([
  616. this.s2ab(
  617. XLSXStyle.write(wb, {
  618. bookType: 'xlsx',
  619. bookSST: true,
  620. type: 'binary',
  621. cellStyles: true
  622. })
  623. )
  624. ])
  625. const elink = document.createElement('a')
  626. elink.download = decodeURIComponent(fileName + '.xlsx')
  627. elink.style.display = 'none'
  628. elink.href = URL.createObjectURL(tmpDown)
  629. document.body.appendChild(elink)
  630. elink.click()
  631. URL.revokeObjectURL(elink.href) // 释放URL 对象
  632. document.body.removeChild(elink)
  633. },
  634. exportErrorRoom() {
  635. if (!this.tableData.length) {
  636. this.$message.error('失败记录为空!')
  637. return
  638. }
  639. const outData = []
  640. const title = []
  641. title.push('楼盘/小区名称')
  642. title.push('分期名称')
  643. title.push('单元/楼栋号')
  644. title.push('户室号')
  645. title.push('所在层')
  646. title.push('预测套内面积')
  647. title.push('预测分摊面积')
  648. title.push('预测建筑面积')
  649. title.push('预测土地面积')
  650. title.push('实测套内面积')
  651. title.push('实测分摊面积')
  652. title.push('实测建筑面积')
  653. title.push('实测土地面积')
  654. title.push('用途')
  655. title.push('户编号')
  656. title.push('装修情况')
  657. title.push('2.2M以')
  658. title.push('户型')
  659. title.push('备注')
  660. title.push('可售状态')
  661. title.push('异常原因')
  662. outData.push(title)
  663. const errorFiled = []
  664. this.tableData.forEach((item, index) => {
  665. const jsonArray = []
  666. jsonArray.push(item.groupName)
  667. jsonArray.push(item.discName)
  668. jsonArray.push(item.buildNum)
  669. jsonArray.push(item.roomNo)
  670. jsonArray.push(item.floor)
  671. jsonArray.push(item.predictionInternalArea)
  672. jsonArray.push(item.predictionShareArea)
  673. jsonArray.push(item.predictionBuildArea)
  674. jsonArray.push(item.predictionLandArea)
  675. jsonArray.push(item.actualInternalArea)
  676. jsonArray.push(item.actualShareArea)
  677. jsonArray.push(item.actualBuildArea)
  678. jsonArray.push(item.actualLandArea)
  679. jsonArray.push(item.roomUse)
  680. jsonArray.push(item.roomNumber)
  681. jsonArray.push(item.decorationSituation)
  682. jsonArray.push(item.twoPointTwo)
  683. jsonArray.push(item.houseType)
  684. jsonArray.push(item.remark)
  685. jsonArray.push(item.saleStatus)
  686. jsonArray.push(item.reason)
  687. outData.push(jsonArray)
  688. })
  689. const outSize = []
  690. title.forEach(item => {
  691. if (item.length > 4) {
  692. outSize.push({
  693. wch: 30
  694. })
  695. } else {
  696. outSize.push({
  697. wch: 15
  698. })
  699. }
  700. })
  701. const fileName = '失败记录导出 ' + new Date().Format('yyyy-MM-dd hh:mm')
  702. const ws = XLSX.utils.aoa_to_sheet(outData)
  703. ws['!cols'] = outSize
  704. ws['!rows'] = []
  705. if (errorFiled.length) {
  706. errorFiled.forEach(item => {
  707. if (!ws[item]) {
  708. ws[item] = {
  709. v: '',
  710. t: 's',
  711. s: {
  712. fill: {
  713. bgColor: { indexed: 64 }, fgColor: { rgb: 'FF0000' }
  714. },
  715. font: {
  716. color: { rgb: 'FFFFFF' }
  717. }
  718. }
  719. }
  720. } else {
  721. ws[item].s = {
  722. fill: {
  723. bgColor: { indexed: 64 }, fgColor: { rgb: 'FF0000' }
  724. },
  725. font: {
  726. color: { rgb: 'FFFFFF' }
  727. }
  728. }
  729. }
  730. })
  731. }
  732. const wb = XLSX.utils.book_new()
  733. XLSX.utils.book_append_sheet(wb, ws, fileName)
  734. const tmpDown = new Blob([
  735. this.s2ab(
  736. XLSXStyle.write(wb, {
  737. bookType: 'xlsx',
  738. bookSST: true,
  739. type: 'binary',
  740. cellStyles: true
  741. })
  742. )
  743. ])
  744. const elink = document.createElement('a')
  745. elink.download = decodeURIComponent(fileName + '.xlsx')
  746. elink.style.display = 'none'
  747. elink.href = URL.createObjectURL(tmpDown)
  748. document.body.appendChild(elink)
  749. elink.click()
  750. URL.revokeObjectURL(elink.href) // 释放URL 对象
  751. document.body.removeChild(elink)
  752. },
  753. s2ab(s) {
  754. var cuf
  755. var i
  756. if (typeof ArrayBuffer !== 'undefined') {
  757. cuf = new ArrayBuffer(s.length)
  758. var view = new Uint8Array(cuf)
  759. for (i = 0; i !== s.length; i++) {
  760. view[i] = s.charCodeAt(i) & 0xFF
  761. }
  762. return cuf
  763. } else {
  764. cuf = new Array(s.length)
  765. for (i = 0; i !== s.length; ++i) {
  766. cuf[i] = s.charCodeAt(i) & 0xFF
  767. }
  768. return cuf
  769. }
  770. },
  771. downloadTemplate() {
  772. if (this.importType === 'groupInsert') {
  773. this.downloadGroupTemplate()
  774. }
  775. if (this.importType === 'FQInsert') {
  776. this.downloadFQTemplate()
  777. }
  778. if (this.importType === 'buildInsert') {
  779. this.downloadBuildTemplate()
  780. }
  781. if (this.importType === 'roomInsert') {
  782. this.downloadRoomTemplate()
  783. }
  784. },
  785. downloadGroupTemplate() {
  786. const outData = []
  787. const title = []
  788. title.push('楼盘/小区名称')
  789. title.push('性质')
  790. title.push('预销售许可证编号')
  791. title.push('开发公司')
  792. title.push('总建筑面积(㎡)')
  793. title.push('总用地面积(㎡)')
  794. title.push('立项批文')
  795. title.push('工程规划许可证')
  796. title.push('施工许可证')
  797. title.push('土地证号')
  798. title.push('用地许可证号')
  799. title.push('容积率')
  800. title.push('绿化率')
  801. title.push('标准单价')
  802. title.push('超标单价')
  803. title.push('楼盘面积测绘状态')
  804. title.push('楼盘销售状态')
  805. title.push('行政区划')
  806. title.push('详细地址')
  807. title.push('备注')
  808. outData.push(title)
  809. const outSize = []
  810. title.forEach(item => {
  811. if (item.length > 4) {
  812. outSize.push({
  813. wch: 30
  814. })
  815. } else {
  816. outSize.push({
  817. wch: 15
  818. })
  819. }
  820. })
  821. let fileName = '模板'
  822. if (this.importTitle.includes('批量导入')) {
  823. fileName = '楼盘导入模版'
  824. }
  825. // if (this.importTitle.includes('批量更新')) {
  826. // fileName = '更新模板'
  827. // }
  828. const ws = XLSX.utils.aoa_to_sheet(outData)
  829. ws['!cols'] = outSize
  830. ws['!rows'] = []
  831. const wb = XLSX.utils.book_new()
  832. XLSX.utils.book_append_sheet(wb, ws, fileName)
  833. const tmpDown = new Blob([
  834. this.s2ab(
  835. XLSXStyle.write(wb, {
  836. bookType: 'xlsx',
  837. bookSST: true,
  838. type: 'binary',
  839. cellStyles: true
  840. })
  841. )
  842. ])
  843. const elink = document.createElement('a')
  844. elink.download = decodeURIComponent(fileName + '.xlsx')
  845. elink.style.display = 'none'
  846. elink.href = URL.createObjectURL(tmpDown)
  847. document.body.appendChild(elink)
  848. elink.click()
  849. URL.revokeObjectURL(elink.href) // 释放URL 对象
  850. document.body.removeChild(elink)
  851. },
  852. downloadFQTemplate() {
  853. const outData = []
  854. const title = []
  855. title.push('楼盘/小区名称')
  856. title.push('分期名称')
  857. title.push('房屋买卖单价(元/㎡)')
  858. title.push('物业费单价(元/㎡)')
  859. title.push('住宅专项维修资金(元/㎡)')
  860. title.push('认购金(元)')
  861. title.push('共持比例')
  862. title.push('支付方式')
  863. outData.push(title)
  864. const outSize = []
  865. title.forEach(item => {
  866. if (item.length > 4) {
  867. outSize.push({
  868. wch: 30
  869. })
  870. } else {
  871. outSize.push({
  872. wch: 15
  873. })
  874. }
  875. })
  876. let fileName = '模板'
  877. if (this.importTitle.includes('批量导入')) {
  878. fileName = '楼盘分期导入'
  879. }
  880. // if (this.importTitle === '批量更新') {
  881. // fileName = '更新模板'
  882. // }
  883. const ws = XLSX.utils.aoa_to_sheet(outData)
  884. ws['!cols'] = outSize
  885. ws['!rows'] = []
  886. const wb = XLSX.utils.book_new()
  887. XLSX.utils.book_append_sheet(wb, ws, fileName)
  888. const tmpDown = new Blob([
  889. this.s2ab(
  890. XLSXStyle.write(wb, {
  891. bookType: 'xlsx',
  892. bookSST: true,
  893. type: 'binary',
  894. cellStyles: true
  895. })
  896. )
  897. ])
  898. const elink = document.createElement('a')
  899. elink.download = decodeURIComponent(fileName + '.xlsx')
  900. elink.style.display = 'none'
  901. elink.href = URL.createObjectURL(tmpDown)
  902. document.body.appendChild(elink)
  903. elink.click()
  904. URL.revokeObjectURL(elink.href) // 释放URL 对象
  905. document.body.removeChild(elink)
  906. },
  907. downloadBuildTemplate() {
  908. const outData = []
  909. const title = []
  910. title.push('楼盘/小区名称')
  911. title.push('分期名称')
  912. title.push('单元/楼栋号')
  913. title.push('总面积(㎡)')
  914. title.push('住宅面积(㎡)')
  915. title.push('非住宅面积(㎡)')
  916. title.push('占地面积(㎡)')
  917. title.push('地下面积(㎡)')
  918. title.push('房号')
  919. title.push('套数')
  920. title.push('总层数')
  921. title.push('地上层数')
  922. title.push('地下层数')
  923. title.push('结构')
  924. title.push('行政区划')
  925. title.push('地号')
  926. title.push('备注')
  927. title.push('标准价格参考层及差价系数备注说明')
  928. outData.push(title)
  929. const outSize = []
  930. title.forEach(item => {
  931. if (item.length > 4) {
  932. outSize.push({
  933. wch: 30
  934. })
  935. } else {
  936. outSize.push({
  937. wch: 15
  938. })
  939. }
  940. })
  941. let fileName = '模板'
  942. if (this.importTitle.includes('批量导入')) {
  943. fileName = '楼栋管理模板'
  944. }
  945. // if (this.importTitle === '批量更新') {
  946. // fileName = '更新模板'
  947. // }
  948. const ws = XLSX.utils.aoa_to_sheet(outData)
  949. ws['!cols'] = outSize
  950. ws['!rows'] = []
  951. const wb = XLSX.utils.book_new()
  952. XLSX.utils.book_append_sheet(wb, ws, fileName)
  953. const tmpDown = new Blob([
  954. this.s2ab(
  955. XLSXStyle.write(wb, {
  956. bookType: 'xlsx',
  957. bookSST: true,
  958. type: 'binary',
  959. cellStyles: true
  960. })
  961. )
  962. ])
  963. const elink = document.createElement('a')
  964. elink.download = decodeURIComponent(fileName + '.xlsx')
  965. elink.style.display = 'none'
  966. elink.href = URL.createObjectURL(tmpDown)
  967. document.body.appendChild(elink)
  968. elink.click()
  969. URL.revokeObjectURL(elink.href) // 释放URL 对象
  970. document.body.removeChild(elink)
  971. },
  972. downloadRoomTemplate() {
  973. const outData = []
  974. const title = []
  975. title.push('楼盘/小区名称')
  976. title.push('分期名称')
  977. title.push('单元/楼栋号')
  978. title.push('户室号')
  979. title.push('所在层')
  980. title.push('预测套内面积')
  981. title.push('预测分摊面积')
  982. title.push('预测建筑面积')
  983. title.push('预测土地面积')
  984. title.push('实测套内面积')
  985. title.push('实测分摊面积')
  986. title.push('实测建筑面积')
  987. title.push('实测土地面积')
  988. title.push('用途')
  989. title.push('户编号')
  990. title.push('装修情况')
  991. title.push('2.2M以')
  992. title.push('户型')
  993. title.push('备注')
  994. title.push('可售状态')
  995. outData.push(title)
  996. const outSize = []
  997. title.forEach(item => {
  998. if (item.length > 4) {
  999. outSize.push({
  1000. wch: 30
  1001. })
  1002. } else {
  1003. outSize.push({
  1004. wch: 15
  1005. })
  1006. }
  1007. })
  1008. let fileName = '模板'
  1009. if (this.importTitle.includes('批量导入')) {
  1010. fileName = '房间管理导入'
  1011. }
  1012. // if (this.importTitle === '批量更新') {
  1013. // fileName = '更新模板'
  1014. // }
  1015. const ws = XLSX.utils.aoa_to_sheet(outData)
  1016. ws['!cols'] = outSize
  1017. ws['!rows'] = []
  1018. const wb = XLSX.utils.book_new()
  1019. XLSX.utils.book_append_sheet(wb, ws, fileName)
  1020. const tmpDown = new Blob([
  1021. this.s2ab(
  1022. XLSXStyle.write(wb, {
  1023. bookType: 'xlsx',
  1024. bookSST: true,
  1025. type: 'binary',
  1026. cellStyles: true
  1027. })
  1028. )
  1029. ])
  1030. const elink = document.createElement('a')
  1031. elink.download = decodeURIComponent(fileName + '.xlsx')
  1032. elink.style.display = 'none'
  1033. elink.href = URL.createObjectURL(tmpDown)
  1034. document.body.appendChild(elink)
  1035. elink.click()
  1036. URL.revokeObjectURL(elink.href) // 释放URL 对象
  1037. document.body.removeChild(elink)
  1038. },
  1039. handleClose() {
  1040. this.dialogVisible = false
  1041. }
  1042. }
  1043. }
  1044. </script>
  1045. <style lang="scss">
  1046. .uploadCost {
  1047. .el-card__body {
  1048. padding: 0 !important;
  1049. }
  1050. .uploadtitle {
  1051. color: #C5C5C5;
  1052. }
  1053. .el-dialog__body {
  1054. padding: 15px !important;
  1055. color: #606266 !important;
  1056. font-size: 14px !important;
  1057. word-break: break-all !important;
  1058. }
  1059. .el-upload {
  1060. width: 100%;
  1061. }
  1062. .el-upload-list {
  1063. li {
  1064. text-align: center;
  1065. }
  1066. }
  1067. .mgauto {
  1068. display: block;
  1069. margin: 0 auto;
  1070. }
  1071. .mtmb16 {
  1072. margin-top: 16px;
  1073. margin-bottom: 16px;
  1074. }
  1075. .txtcenter {
  1076. text-align: center;
  1077. }
  1078. }
  1079. </style>