index.vue 13 KB

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