index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. <template>
  2. <zj-tab-page ref="tabPage" :defaultActives="[{ key: 'list', label: $route.meta.title + '-列表', essential: true }]">
  3. <template slot-scope="{ activeKey, data }">
  4. <template-page
  5. v-if="activeKey == 'list'"
  6. ref="pageRef"
  7. :get-list="getList"
  8. :table-attributes="tableAttributes"
  9. :table-events="tableEvents"
  10. :options-evens-group="optionsEvensGroup"
  11. :moreParameters="moreParameters"
  12. :column-parsing="columnParsing"
  13. :operation="operation()"
  14. :exportList="exportList"
  15. >
  16. </template-page>
  17. <div v-if="~['detail'].indexOf(activeKey)" style="box-sizing: border-box; padding: 16px">
  18. <el-descriptions border title="" :column="4" :colon="false" labelStyle="width: 8%" contentStyle="width: 17%">
  19. <el-descriptions-item label="状态">
  20. {{ detailData.status | statusFilter }}
  21. </el-descriptions-item>
  22. <el-descriptions-item label="订单编号">
  23. {{ detailData.orderId }}
  24. </el-descriptions-item>
  25. <el-descriptions-item label="订单类型">
  26. {{ detailData.orderType | orderTypeFilter }}
  27. </el-descriptions-item>
  28. <el-descriptions-item label="发票类型">
  29. {{ detailData.taxType | taxTypeFilter }}
  30. </el-descriptions-item>
  31. <el-descriptions-item label="发票内容">
  32. {{ detailData.content }}
  33. </el-descriptions-item>
  34. <el-descriptions-item label="抬头类型">
  35. {{ detailData.type | typeFilter }}
  36. </el-descriptions-item>
  37. <el-descriptions-item label="抬头名称">
  38. {{ detailData.name }}
  39. </el-descriptions-item>
  40. <el-descriptions-item label="单位税号">
  41. {{ detailData.taxNo }}
  42. </el-descriptions-item>
  43. <el-descriptions-item label="收票邮箱">
  44. {{ detailData.receiverEmail }}
  45. </el-descriptions-item>
  46. <el-descriptions-item label="开票金额">
  47. {{ detailData.amount }}
  48. </el-descriptions-item>
  49. <el-descriptions-item label=""> </el-descriptions-item>
  50. <el-descriptions-item label="创建人">
  51. {{ detailData.createBy }}
  52. </el-descriptions-item>
  53. <el-descriptions-item label="创建时间">
  54. {{ detailData.createTime }}
  55. </el-descriptions-item>
  56. <el-descriptions-item label="上传人">
  57. {{ detailData.upName }}
  58. </el-descriptions-item>
  59. <el-descriptions-item label="上传时间">
  60. {{ detailData.upTime }}
  61. </el-descriptions-item>
  62. </el-descriptions>
  63. <h3>上传发票</h3>
  64. <el-form ref="formRef" :model="formData" :rules="formRules" label-position="left" label-width="80px">
  65. <el-row :gutter="20">
  66. <el-col :span="8">
  67. <el-form-item label="发票时间" prop="taxTime">
  68. <el-date-picker
  69. :disabled="detailData.status"
  70. v-model="formData.taxTime"
  71. type="date"
  72. value-format="yyyy-MM-dd"
  73. placeholder="选择发票时间"
  74. >
  75. </el-date-picker>
  76. </el-form-item>
  77. </el-col>
  78. <el-col :span="8">
  79. <el-form-item label="发票代码" prop="taxNumber">
  80. <el-input
  81. v-model="formData.taxNumber"
  82. autocomplete="off"
  83. placeholder="请输入发票代码"
  84. :disabled="detailData.status"
  85. ></el-input>
  86. </el-form-item>
  87. </el-col>
  88. <el-col :span="8">
  89. <el-form-item label="发票号码" prop="taxCode">
  90. <el-input
  91. v-model="formData.taxCode"
  92. autocomplete="off"
  93. placeholder="请输入发票号码"
  94. :disabled="detailData.status"
  95. ></el-input>
  96. </el-form-item>
  97. </el-col>
  98. <el-col :span="24">
  99. <el-form-item label="上传发票" prop="taxlink">
  100. <el-upload
  101. class="avatar-uploader imageListUpload"
  102. style="height: 0"
  103. :action="baseURL + 'common/upload'"
  104. :headers="myHeaders"
  105. :show-file-list="false"
  106. :on-success="uploadSuccess"
  107. :before-upload="beforeUpload"
  108. :disabled="detailData.status"
  109. >
  110. </el-upload>
  111. <div class="images">
  112. <div class="item" v-if="formData.taxlink">
  113. <div class="img">
  114. <el-image
  115. :src="require('@/assets/common/pdf.png')"
  116. style="width: 120px; height: 120px; padding: 30px"
  117. fit="cover"
  118. v-if="formData.taxlink.indexOf('pdf') >= 0"
  119. ></el-image>
  120. <el-image
  121. class="mainimg"
  122. ref="img"
  123. :src="$showImgUrl(formData.taxlink)"
  124. style="width: 120px; height: 120px"
  125. fit="cover"
  126. :preview-src-list="[$showImgUrl(formData.taxlink)]"
  127. v-else
  128. ></el-image>
  129. <div class="mask" v-if="!detailData.status">
  130. <div class="row">
  131. <div class="it" @click="uploadImage()"><i class="el-icon-upload2"></i></div>
  132. <div class="it" @click="formData.taxlink = ''"><i class="el-icon-delete"></i></div>
  133. </div>
  134. </div>
  135. </div>
  136. <div>
  137. <el-button @click="formData.taxlink.indexOf('pdf') >= 0 ? openFile() : openImage()" size="small"
  138. >预览</el-button
  139. >
  140. <el-button @click="downloadFile" size="small">下载</el-button>
  141. </div>
  142. </div>
  143. <div class="item" v-else>
  144. <div class="add" @click="uploadImage()">
  145. <i class="el-icon-plus avatar-uploader-icon"></i>
  146. </div>
  147. </div>
  148. </div>
  149. </el-form-item>
  150. </el-col>
  151. <el-col :span="24">
  152. <el-form-item label="备注" prop="remark">
  153. <el-input
  154. type="textarea"
  155. v-model="formData.remark"
  156. autocomplete="off"
  157. placeholder="请输入备注"
  158. :disabled="detailData.status"
  159. ></el-input>
  160. </el-form-item>
  161. </el-col>
  162. </el-row>
  163. </el-form>
  164. <div slot="footer" class="dialog-footer">
  165. <el-button size="mini" @click="data.removeTab()">取 消</el-button>
  166. <el-button size="mini" @click="formConfirm(data.removeTab)" type="primary" v-if="!detailData.status"
  167. >确 定</el-button
  168. >
  169. </div>
  170. </div>
  171. </template>
  172. </zj-tab-page>
  173. </template>
  174. <script>
  175. import { getToken } from '@/utils/auth'
  176. import TemplatePage from '@/components/template/template-page-1.vue'
  177. import import_mixin from '@/components/template/import_mixin.js'
  178. import { required, mobileRequired, mobile } from '@/components/template/rules_verify.js'
  179. import { getList, pageExport, saveData, getDetail } from '@/api/invoice2'
  180. import operation_mixin from '@/components/template/operation_mixin.js'
  181. export default {
  182. components: { TemplatePage },
  183. mixins: [import_mixin, operation_mixin],
  184. filters: {
  185. statusFilter(val) {
  186. const MAP = {
  187. true: '已开票',
  188. false: '待开票'
  189. }
  190. return MAP[val]
  191. },
  192. orderTypeFilter(val) {
  193. const MAP = {
  194. INCRE: '增值服务',
  195. ORDER: '商城订单'
  196. }
  197. return MAP[val]
  198. },
  199. taxTypeFilter(val) {
  200. const MAP = {
  201. true: '专票',
  202. false: '普票'
  203. }
  204. return MAP[val]
  205. },
  206. typeFilter(val) {
  207. const MAP = {
  208. true: '公司',
  209. false: '个人'
  210. }
  211. return MAP[val]
  212. }
  213. },
  214. data() {
  215. return {
  216. baseURL: process.env.VUE_APP_BASE_API,
  217. myHeaders: { 'x-token': getToken() },
  218. // 表格属性
  219. tableAttributes: {
  220. // 启用勾选列
  221. selectColumn: false
  222. },
  223. // 表格事件
  224. tableEvents: {
  225. 'selection-change': this.selectionChange
  226. },
  227. // 勾选选中行
  228. recordSelected: [],
  229. /** 表单变量 */
  230. formDialogType: 0,
  231. formDialogTitles: ['新增', '编辑'],
  232. formDialog: false,
  233. formData: {
  234. taxTime: '',
  235. taxNumber: '',
  236. taxCode: '',
  237. taxlink: '',
  238. remark: ''
  239. },
  240. formRules: {
  241. taxTime: [{ required: true, message: '请选择发票时间', trigger: 'change' }],
  242. taxNumber: [{ required: true, message: '请输入发票代码', trigger: 'blur' }],
  243. taxCode: [{ required: true, message: '请输入发票号码', trigger: 'blur' }],
  244. taxlink: [{ required: true, message: '请上传发票文件', trigger: 'change' }]
  245. },
  246. formType: 'add',
  247. formVisible: false,
  248. detailData: {}
  249. }
  250. },
  251. computed: {
  252. // 事件组合
  253. optionsEvensGroup() {
  254. return [
  255. [
  256. [
  257. this.optionsEvensAuth('add', {
  258. click: () => {
  259. this.openForm('add')
  260. }
  261. })
  262. ]
  263. ]
  264. ]
  265. },
  266. // 更多参数
  267. moreParameters() {
  268. return []
  269. }
  270. },
  271. methods: {
  272. // 列表请求函数
  273. getList: getList,
  274. // 列表导出函数
  275. exportList: pageExport,
  276. // 表格列解析渲染数据更改
  277. columnParsing(item, defaultData) {
  278. return defaultData
  279. },
  280. // 监听勾选变化
  281. selectionChange(data) {
  282. this.recordSelected = data
  283. },
  284. // 表格操作列
  285. operation() {
  286. return this.operationBtn({
  287. detail: {
  288. btnType: 'text',
  289. click: ({ row, index, column }) => {
  290. this.openForm('detail', row.orderTaxId)
  291. }
  292. }
  293. })
  294. },
  295. // 打开 新增编辑 网点表单
  296. openForm(type, id) {
  297. this.$refs.tabPage.addTab({
  298. // 对应显示的模块
  299. activeKey: type,
  300. // 唯一标识
  301. key: type,
  302. // 页签名称
  303. label: { detail: '详情' }[type],
  304. // 打开时事件
  305. triggerEvent: () => {
  306. this.formCancel()
  307. this.$nextTick(() => {
  308. this.formType = type
  309. this.formVisible = true
  310. if (type == 'add') {
  311. this.formDialogType = 0
  312. } else if (type == 'detail') {
  313. this.formDialogType = 1
  314. getDetail({ orderTaxId: id }).then(res => {
  315. this.detailData = res.data || {}
  316. this.formData.taxTime = res.data.taxTime || ''
  317. this.formData.taxNumber = res.data.taxNumber || ''
  318. this.formData.taxCode = res.data.taxCode || ''
  319. this.formData.taxlink = res.data.taxLink || ''
  320. this.formData.remark = res.data.remark || ''
  321. })
  322. }
  323. })
  324. },
  325. // 关闭时事件
  326. closeEvent: () => {}
  327. })
  328. },
  329. formCancel() {
  330. this.formVisible = false
  331. this.$refs?.formRef?.resetFields()
  332. this.$data.formData = this.$options.data().formData
  333. },
  334. formConfirm(cancel) {
  335. this.$refs.formRef.validate((valid, invalidFields, errLabels) => {
  336. if (valid) {
  337. saveData({ ...this.formData, orderTaxId: this.detailData.orderTaxId }).then(res => {
  338. this.$message({ type: 'success', message: `${this.formDialogTitles[this.formDialogType]}成功!` })
  339. cancel('list')
  340. this.$refs.pageRef.refreshList()
  341. })
  342. }
  343. })
  344. },
  345. uploadImage(id) {
  346. document.querySelector('.imageListUpload input').click()
  347. },
  348. // 附件 - 上传成功
  349. uploadSuccess(res, file) {
  350. this.formData.taxlink = res.data.url
  351. },
  352. // 附件 - 上传前
  353. beforeUpload(file) {
  354. const fileSuffix = file.name.substring(file.name.lastIndexOf('.') + 1)
  355. const whiteList = ['jpg', 'jpeg', 'png', 'pdf']
  356. if (whiteList.indexOf(fileSuffix) === -1) {
  357. this.$errorMsg('只支持上传图片/pdf文件!')
  358. return false
  359. }
  360. },
  361. openImage() {
  362. this.$refs.img.showViewer = true
  363. },
  364. openFile() {
  365. window.open(this.$xdocUrl + encodeURIComponent(Base64.encode(this.formData.taxlink)), '_blank')
  366. },
  367. downloadFile() {
  368. window.open(this.formData.taxlink)
  369. }
  370. }
  371. }
  372. </script>
  373. <style lang="scss" scoped></style>
  374. <style scoped lang="scss">
  375. .images {
  376. display: flex;
  377. flex-wrap: wrap;
  378. .item {
  379. display: flex;
  380. align-items: flex-end;
  381. .img {
  382. border: 1px dashed #eaeaea;
  383. border-radius: 5px;
  384. overflow: hidden;
  385. position: relative;
  386. margin-right: 20px;
  387. .el-image {
  388. display: block;
  389. }
  390. .mask {
  391. position: absolute;
  392. left: 0;
  393. top: 0;
  394. width: 120px;
  395. height: 120px;
  396. background: rgba($color: #000000, $alpha: 0.5);
  397. display: flex;
  398. align-items: center;
  399. justify-content: center;
  400. flex-direction: column;
  401. opacity: 0;
  402. &:hover {
  403. opacity: 1;
  404. }
  405. .row {
  406. display: flex;
  407. align-items: center;
  408. justify-content: center;
  409. .it {
  410. display: flex;
  411. align-items: center;
  412. justify-content: center;
  413. cursor: pointer;
  414. margin: 5px;
  415. i {
  416. font-size: 20px;
  417. color: #ffffff;
  418. }
  419. span {
  420. font-size: 14px;
  421. color: #ffffff;
  422. }
  423. }
  424. }
  425. }
  426. }
  427. .add {
  428. border: 1px dashed #eaeaea;
  429. border-radius: 5px;
  430. cursor: pointer;
  431. .avatar-uploader-icon {
  432. width: 120px;
  433. height: 120px;
  434. line-height: 120px;
  435. }
  436. &:hover {
  437. border: 1px dashed #66b1ff;
  438. }
  439. }
  440. }
  441. }
  442. </style>