InvoiceFormTask.vue 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009
  1. <template>
  2. <view>
  3. <cu-custom :backUrl="'/pages/index/index'" :isBack="true" bgColor="bg-gradual-blue" >
  4. <block slot="content">发票申请</block>
  5. </cu-custom>
  6. <u--form :model="inputForm" labelWidth="100px" class="u-form" labelPosition="left" :rules="rules" ref="inputForm" v-if="!nodeFlag">
  7. <el-row :gutter="15" :key="index_experience" v-for="(item,index_experience) in this.inputForm.financeInvoiceBaseDTOList">
  8. <el-col :span="24">
  9. <u-form-item label="" >
  10. <el-divider content-position="left"> 基本信息详情 {{index_experience + 1}}</el-divider>
  11. </u-form-item>
  12. </el-col>
  13. <el-col :span="24">
  14. <u-form-item label="项目名称" :prop="'financeInvoiceBaseDTOList[' + index_experience + '].programName'"
  15. :rules="[
  16. ]">
  17. <u--input v-model="inputForm.financeInvoiceBaseDTOList[index_experience].programName" placeholder="请选择项目名称" @focus="showProject(index_experience)" clearable></u--input>
  18. </u-form-item>
  19. <u-form-item label="合同名称" :prop="'financeInvoiceBaseDTOList[' + index_experience + '].contractName'"
  20. :rules="[
  21. ]">
  22. <u--input v-model="inputForm.financeInvoiceBaseDTOList[index_experience].contractName" :readonly="true" placeholder="请填写合同名称" clearable></u--input>
  23. </u-form-item>
  24. <u-form-item label="项目编号" :prop="'financeInvoiceBaseDTOList[' + index_experience + '].programNo'"
  25. :rules="[
  26. ]">
  27. <u--input v-model="inputForm.financeInvoiceBaseDTOList[index_experience].programNo" :readonly="true" placeholder="请填写项目编号" clearable></u--input>
  28. </u-form-item>
  29. <u-form-item label="报告号" :prop="'financeInvoiceBaseDTOList[' + index_experience + '].reportNo'"
  30. :rules="[
  31. ]">
  32. <u--input v-model="inputForm.financeInvoiceBaseDTOList[index_experience].reportNo" :readonly="true" placeholder="请填写报告号" clearable></u--input>
  33. </u-form-item>
  34. <u-form-item label="发票金额(元)" :prop="'financeInvoiceBaseDTOList[' + index_experience + '].account'" :required="true"
  35. :rules="[
  36. ]">
  37. <u--input v-model="inputForm.financeInvoiceBaseDTOList[index_experience].account" @blur="onInputCode(index_experience, $event,'account')" placeholder="请填写发票金额(元)" clearable></u--input>
  38. </u-form-item>
  39. </el-col>
  40. <el-col :span="24" style="text-align: center">
  41. <u-form-item label="" >
  42. <el-button style="width: 100%" type="danger" @click="removeRow(index_experience)" plain>删除基本信息 {{index_experience + 1}}</el-button>
  43. </u-form-item>
  44. </el-col>
  45. </el-row>
  46. <u-form-item label="" >
  47. <el-button style="width: 100%" type="primary" @click="addRow()" plain>新增基本信息</el-button>
  48. </u-form-item>
  49. <u-form-item label="" >
  50. <el-divider content-position="left"> 发票详情</el-divider>
  51. </u-form-item>
  52. <u-form-item label="发票类型" borderBottom prop="type" :required="true">
  53. <u-radio-group v-model="inputForm.type" >
  54. <u-radio
  55. :disabled="testFlag"
  56. :customStyle="{marginRight: '16px'}"
  57. v-for="(item, index) in typeList"
  58. :key="index"
  59. :label="item.name"
  60. :name="item.value"
  61. ></u-radio>
  62. </u-radio-group>
  63. </u-form-item>
  64. <u-form-item label="发票申请编号" prop="no"
  65. :rules="[
  66. ]">
  67. <u--input v-model="inputForm.no" :disabled="true" placeholder="请填写发票申请编号" clearable></u--input>
  68. </u-form-item>
  69. <u-form-item label="开票类型" borderBottom prop="billingType" :required="true">
  70. <u-radio-group v-model="inputForm.billingType" >
  71. <u-radio
  72. :disabled="testFlag"
  73. :customStyle="{marginRight: '16px'}"
  74. v-for="(item, index) in billingTypeList"
  75. :key="index"
  76. :label="item.name"
  77. :name="item.value"
  78. @change="reimbursementTypeChange"
  79. ></u-radio>
  80. </u-radio-group>
  81. </u-form-item>
  82. <u-form-item label="实际开票单位" prop="billingWorkplaceReal" v-if="inputForm.billingType === '1'" :required="true"
  83. :rules="[
  84. ]">
  85. <u--input v-model="inputForm.billingWorkplaceReal" @focus="showWorkplace()" placeholder="请填写实际开票单位" clearable></u--input>
  86. </u-form-item>
  87. <template v-if="inputForm.type === '1'">
  88. <u-form-item label="纳税人识别号" prop="taxpayerIdentificationNo" v-if="inputForm.billingType === '1'" :required="true"
  89. :rules="[
  90. ]">
  91. <u--input v-model="inputForm.taxpayerIdentificationNo" placeholder="请填写纳税人识别号" clearable></u--input>
  92. </u-form-item>
  93. <u-form-item label="地址" prop="address" v-if="inputForm.billingType === '1'" :required="true"
  94. :rules="[
  95. ]">
  96. <u--input v-model="inputForm.address" placeholder="请填写地址" clearable></u--input>
  97. </u-form-item>
  98. <u-form-item label="电话" prop="telPhone" v-if="inputForm.billingType === '1'" :required="true"
  99. :rules="[
  100. ]">
  101. <u--input v-model="inputForm.telPhone" placeholder="请填写电话" clearable></u--input>
  102. </u-form-item>
  103. <u-form-item label="开户银行" borderBottom v-if="inputForm.billingType === '1'" prop="openBank" :required="true">
  104. <jp-picker v-model="inputForm.openBank" @input="changeBank" rangeKey="label" rangeValue="value" :range=bankList ></jp-picker>
  105. </u-form-item>
  106. <u-form-item label="银行账号" borderBottom v-if="inputForm.billingType === '1'" prop="bankAccount" :required="true">
  107. <u--input v-model="inputForm.bankAccount" :disabled="true" placeholder="请填写银行账号" clearable></u--input>
  108. </u-form-item>
  109. </template>
  110. <template v-if="inputForm.type !== '1'">
  111. <u-form-item label="纳税人识别号" v-if="inputForm.billingType === '1'" prop="taxpayerIdentificationNo"
  112. :rules="[
  113. ]">
  114. <u--input v-model="inputForm.taxpayerIdentificationNo" placeholder="请填写纳税人识别号" clearable></u--input>
  115. </u-form-item>
  116. <u-form-item label="地址" prop="address" v-if="inputForm.billingType === '1'"
  117. :rules="[
  118. ]">
  119. <u--input v-model="inputForm.address" placeholder="请填写地址" clearable></u--input>
  120. </u-form-item>
  121. <u-form-item label="电话" prop="telPhone" v-if="inputForm.billingType === '1'"
  122. :rules="[
  123. ]">
  124. <u--input v-model="inputForm.telPhone" placeholder="请填写电话" clearable></u--input>
  125. </u-form-item>
  126. <u-form-item label="开户银行" borderBottom v-if="inputForm.billingType === '1'" prop="openBank" >
  127. <jp-picker v-model="inputForm.openBank" @input="changeBank" rangeKey="label" rangeValue="value" :range=bankList ></jp-picker>
  128. </u-form-item>
  129. <u-form-item label="银行账号" v-if="inputForm.billingType === '1'" borderBottom prop="bankAccount" >
  130. <u--input v-model="inputForm.bankAccount" :disabled="true" placeholder="请填写银行账号" clearable></u--input>
  131. </u-form-item>
  132. </template>
  133. <u-form-item label="姓名" v-if="inputForm.billingType === '2'" prop="nameShow" :required="true"
  134. :rules="[
  135. ]">
  136. <u--input v-model="inputForm.nameShow" placeholder="请选择" @focus="openUserPullForm('','姓名')" clearable></u--input>
  137. </u-form-item>
  138. <u-form-item label="收款类型" borderBottom prop="receivablesType" :required="true">
  139. <jp-picker v-model="inputForm.receivablesType" rangeKey="label" rangeValue="value" :range="[
  140. { label: '单一收费', value: '1' },
  141. { label: '合并收费', value: '2' },
  142. ]" ></jp-picker>
  143. </u-form-item>
  144. <u-form-item label="开票内容" borderBottom prop="billingContent" :required="true">
  145. <jp-picker v-model="inputForm.billingContent" rangeKey="label" rangeValue="value" :range="[
  146. { label: '审计费', value: '1' },
  147. { label: '工程审核费', value: '2' },
  148. { label: '咨询费', value: '3' },
  149. { label: '预算编制费', value: '4' },
  150. { label: '招标代理费', value: '5' },
  151. { label: '司法鉴定费', value: '6' },
  152. { label: '其他', value: '8' },
  153. { label: '技术服务费', value: '9' },
  154. { label: '鉴证咨询服务*评估费', value: '10' },
  155. { label: '其他咨询服务*专家咨询费', value: '11' },
  156. { label: '会计服务', value: '12' },
  157. { label: '竣工决算编制费', value: '13' },
  158. { label: '*信息技术服务*技术服务费', value: '14' },
  159. ]" ></jp-picker>
  160. </u-form-item>
  161. <u-form-item label="发票金额(元)" borderBottom prop="accountTotal" :required="true">
  162. <u--input v-model="inputForm.accountTotal" :disabled="true" placeholder="请填写发票金额" clearable></u--input>
  163. </u-form-item>
  164. <u-form-item label="报备类型" borderBottom prop="reportType" :required="true">
  165. <jp-picker v-model="inputForm.reportType" rangeKey="label" rangeValue="value" :range="[
  166. { label: '上市公司审计', value: '1' },
  167. { label: '国有大型企业审计', value: '2' },
  168. { label: '新三板企业审计', value: '3' },
  169. { label: '一般企业审计', value: '4' },
  170. { label: '事业单位审计', value: '5' },
  171. { label: '民间非营利组织等其他单位审计', value: '6' },
  172. { label: '内控审计报告', value: '7' },
  173. { label: '内控鉴证报告', value: '8' },
  174. { label: '其他报告', value: '9' },
  175. { label: '专项审计业务', value: '10' },
  176. { label: '验资业务', value: '11' },
  177. ]" ></jp-picker>
  178. </u-form-item>
  179. <u-form-item label="是否多张开票" borderBottom prop="isMultiple" :required="true">
  180. <u-radio-group v-model="inputForm.isMultiple" >
  181. <u-radio
  182. :disabled="testFlag"
  183. :customStyle="{marginRight: '16px'}"
  184. v-for="(item, index) in yesNoFlag"
  185. :key="index"
  186. :label="item.name"
  187. :name="item.value"
  188. ></u-radio>
  189. </u-radio-group>
  190. </u-form-item>
  191. <u-form-item label="开票内容要求" borderBottom prop="billingContentTerms">
  192. <u--textarea placeholder='开票内容要求' :maxlength="500" v-model="inputForm.billingContentTerms" ></u--textarea>
  193. </u-form-item>
  194. <u-form-item label="开票人" borderBottom prop="billingPeople" >
  195. <u--input v-model="inputForm.billingPeople" :disabled="true" placeholder="请选择开票人" clearable></u--input>
  196. </u-form-item>
  197. <u-form-item label="开票时间" prop="billingDate" :required="true"
  198. :rules="[
  199. ]">
  200. <el-date-picker
  201. :disabled="true"
  202. v-model="inputForm.billingDate"
  203. type="date"
  204. style="width:100%"
  205. size="default"
  206. placement="bottom-start"
  207. clearable>
  208. </el-date-picker>
  209. </u-form-item>
  210. <u-form-item label="领票时间" prop="collectDate"
  211. :rules="[
  212. ]">
  213. <el-date-picker
  214. :disabled="true"
  215. v-model="inputForm.collectDate"
  216. type="date"
  217. style="width:100%"
  218. size="default"
  219. placement="bottom-start"
  220. clearable>
  221. </el-date-picker>
  222. </u-form-item>
  223. <u-form-item label="实际开票人" prop="billingPeopleRealName" :required="true"
  224. :rules="[
  225. ]">
  226. <u--input v-model="inputForm.billingPeopleRealName" placeholder="请选择实际开票人" @focus="openUserPullForm('','实际')" clearable></u--input>
  227. </u-form-item>
  228. <u-form-item label="接收邮箱" prop="actualDrawerEmailAddress"
  229. :rules="[
  230. ]">
  231. <u--input v-model="inputForm.actualDrawerEmailAddress" placeholder="请输入接收邮箱" clearable></u--input>
  232. <view class="button-container">
  233. <button @click="openDia">完善邮箱</button>
  234. </view>
  235. </u-form-item>
  236. <u-form-item label="对账人" prop="reconciliationPeopleName" :required="true"
  237. :rules="[
  238. ]">
  239. <u--input v-model="inputForm.reconciliationPeopleName" placeholder="请选择对账人" @focus="openUserPullForm('','对账')" clearable></u--input>
  240. </u-form-item>
  241. <u-form-item label="对账地区" borderBottom prop="reconciliationArea" :required="true">
  242. <jp-area-select v-model="inputForm.reconciliationArea"></jp-area-select>
  243. </u-form-item>
  244. <u-form-item label="备注" borderBottom prop="remarks">
  245. <u--textarea placeholder='请填写备注' :maxlength="500" v-model="inputForm.remarks" ></u--textarea>
  246. </u-form-item>
  247. <u-form-item label="附件">
  248. <el-upload
  249. class="upload-demo"
  250. :action="`http://5hrd5v.natappfree.cc/api/public-modules-server/oss/file/webUpload/upload`"
  251. :on-remove="(file, fileList) => handleRemove(file, fileList)"
  252. :file-list="inputForm.files"
  253. :on-success="(response, file, fileList) => handleUploadSuccess(response, file, fileList)"
  254. :limit="3">
  255. <el-button size="small" type="primary">点击上传</el-button>
  256. <div slot="tip" class="el-upload__tip">只能上传不超过 3 个文件</div>
  257. <template slot="file" slot-scope="{ file }" v-if="shouldShowFile(file) || testFlag">
  258. <span @click="handleFileClick(file)">{{ file.name }}</span>
  259. <el-button type="text" icon="el-icon-close" @click="handleDelete(file)">✕</el-button>
  260. </template>
  261. </el-upload>
  262. </u-form-item>
  263. </u--form>
  264. <user-select ref="userPicker" @input="handleEvent"></user-select>
  265. <InvoiceProjectChoose ref="invoiceProjectChoose" @input="selectProjectChange" title="报告项目选择"/>
  266. <WorkPlaceChoose ref="workPlaceChoose" @input="getWorkClient" title="客户选择"/>
  267. <EmailForm ref="emailForm" @input="emailForm" title="完善邮箱"/>
  268. </view>
  269. </template>
  270. <script>
  271. import financeInvoiceService from '@/api/cw/invoice/CwFinanceInvoiceService'
  272. var graceChecker = require("@/common/graceChecker.js");
  273. import workClientService from '@/api/cw/workClientInfo/WorkClientService'
  274. import InvoiceProjectChoose from './InvoiceProjectChoose'
  275. import WorkPlaceChoose from './WorkPlaceChoose'
  276. import EmailForm from './EmailForm'
  277. import userSelect from '@/components/user-select/user-select-radio.vue'
  278. import OSSService from "@/api/sys/OSSService"
  279. import MaterialTypeService from '@/api/materialManagement/MaterialTypeService'
  280. import WareHouseService from '@/api/materialManagement/WareHouseService'
  281. import CommonApi from '@/api/common/CommonApi'
  282. import {mapState, mapMutations, mapActions} from 'vuex'
  283. export default {
  284. components: {
  285. EmailForm,
  286. userSelect,
  287. InvoiceProjectChoose,
  288. WorkPlaceChoose,
  289. },
  290. computed: mapState({
  291. userInfo: (state) => state.user.userInfo,
  292. avatar: (state) => state.user.avatar
  293. }),
  294. data () {
  295. return {
  296. isPreInvoice: '',
  297. yesNoFlag: [{name: '否', value: '0'}, {name: '是', value: '1'}],
  298. bj1: "",
  299. areaList: [],
  300. typeList: [{
  301. name: '专票',
  302. value: '1',
  303. disabled: false
  304. },{
  305. name: '普票',
  306. value: '2',
  307. disabled: false
  308. }],
  309. billingTypeList: [{
  310. name: '企业开票',
  311. value: '1',
  312. disabled: false
  313. },{
  314. name: '个人开票',
  315. value: '2',
  316. disabled: false
  317. }],
  318. showFileList: [], // 控制每个文件是否显示的数组
  319. testFlag: false,
  320. nodeFlag: false,
  321. bankList: [],
  322. inputForm: {
  323. account: '',
  324. accountTotal: '',//发票汇总金额
  325. financeInvoiceBaseDTOList: [],
  326. files: [], // 附件信息
  327. procInsId: '',
  328. type: '1',
  329. no: '',
  330. billingType: '1',
  331. billingWorkplaceReal: '',
  332. billingWorkplaceRealId: '',
  333. taxpayerIdentificationNo: '',
  334. address: '',
  335. telPhone: '',
  336. billingId: '',
  337. openBank: '',
  338. bankAccount: '',
  339. receivablesType: '',
  340. billingContent: '',
  341. reportType: '',
  342. isMultiple: '0',
  343. billingContentTerms: '',
  344. billingPeople: '',
  345. billingPeopleRealName: '',
  346. billingPeopleReal: '',
  347. actualDrawerEmailAddress: '',
  348. reconciliationPeopleName: '',
  349. reconciliationPeople: '',
  350. reconciliationArea: '',
  351. remarks: '',
  352. name: '',
  353. nameShow: '',
  354. billingDate: '',
  355. collectDate: '',
  356. programId: '',
  357. },
  358. rules: {
  359. 'telPhone': [
  360. {
  361. required: true,
  362. message: '电话不能为空',
  363. trigger: ['blur', 'change']
  364. },
  365. {
  366. validator: (rule, value, callback) => this.validatePhone(value, callback),
  367. trigger: ['blur', 'change']
  368. }
  369. ],
  370. 'actualDrawerEmailAddress': [
  371. {
  372. validator: (rule, value, callback) => this.checkEmail(value, callback),
  373. trigger: ['blur']
  374. }
  375. ],
  376. }
  377. }
  378. },
  379. ossService: null,
  380. materialTypeService: null,
  381. wareHouseService: null,
  382. commonApi: null,
  383. // 页面加载时执行
  384. created() {
  385. this.ossService = new OSSService()
  386. this.commonApi = new CommonApi()
  387. this.materialTypeService = new MaterialTypeService()
  388. this.wareHouseService = new WareHouseService()
  389. this.inputForm.actualDrawerEmailAddress = this.userInfo.email
  390. this.inputForm.handledBy = this.userInfo.name
  391. this.inputForm.handledById = this.userInfo.id
  392. this.inputForm.handledByOffice = this.userInfo.officeDTO.id
  393. this.inputForm.handledByOfficeName = this.userInfo.officeDTO.name
  394. },
  395. props: {
  396. businessId: {
  397. type: String,
  398. default: ''
  399. },
  400. formReadOnly: {
  401. type: Boolean,
  402. default: false
  403. }
  404. },
  405. watch: {
  406. 'businessId': {
  407. handler (newVal) {
  408. if (this.businessId) {
  409. this.init(this.businessId)
  410. } else {
  411. this.$nextTick(() => {
  412. // this.$refs.inputForm.reset()
  413. })
  414. }
  415. },
  416. immediate: true,
  417. deep: false
  418. }
  419. },
  420. methods: {
  421. init (id) {
  422. this.nodeFlag = true
  423. this.inputForm.id = id
  424. if (id) {
  425. financeInvoiceService.queryById(id).then((data) => {
  426. this.commonApi.getTaskNameByProcInsId(data.procInsId).then((data) => {
  427. if (this.isNotEmpty(data)) {
  428. if (data === '发起人重新申请' || this.isEmpty(data)) {
  429. this.nodeFlag = false
  430. } else {
  431. this.nodeFlag = true
  432. }
  433. }
  434. })
  435. this.inputForm = this.recover(this.inputForm, data)
  436. if (this.inputForm.files) {
  437. this.inputForm.files.forEach( (item,index) => {
  438. this.$set(this.showFileList, index, true);
  439. })
  440. }
  441. })
  442. if (!this.isEmpty(this.inputForm.billingWorkplaceRealId)) {
  443. this.bankList = []
  444. workClientService.queryById(this.inputForm.billingWorkplaceRealId).then((data) => {
  445. if (this.isNotEmpty(data.cwWorkClientBillingDTOList)) {
  446. data.cwWorkClientBillingDTOList.forEach(i => {
  447. i.ourBank = i.accountHolder
  448. this.bankList.push(i)
  449. this.inputForm.openBank = i.ourBank
  450. })
  451. } else {
  452. this.bankList = []
  453. }
  454. })
  455. }
  456. }
  457. },
  458. formatDate(date) {
  459. const dateNew = new Date(date); // 将日期字符串转换为 Date 对象
  460. const year = dateNew.getFullYear();
  461. const month = (dateNew.getMonth() + 1).toString().padStart(2, '0');
  462. const day = dateNew.getDate().toString().padStart(2, '0');
  463. return `${year}-${month}-${day}`;
  464. },
  465. isEmpty(value) {
  466. let result = false;
  467. if (value == null || value == undefined) {
  468. result = true;
  469. }
  470. if (typeof value == 'string' && (value.replace(/\s+/g, "") == "" || value == "")) {
  471. result = true;
  472. }
  473. if (typeof value == "object" && value instanceof Array && value.length === 0) {
  474. result = true;
  475. }
  476. return result;
  477. },
  478. isNotEmpty (value) {
  479. return !this.isEmpty(value)
  480. },
  481. /**
  482. * 判断是否为空
  483. */
  484. isNull(val) {
  485. if (val instanceof Array) {
  486. if (val.length === 0) return true;
  487. } else if (val instanceof Object) {
  488. if (JSON.stringify(val) === "{}") return true;
  489. } else {
  490. if (
  491. val === "null" ||
  492. val == null ||
  493. val === "undefined" ||
  494. val === undefined ||
  495. val === ""
  496. )
  497. return true;
  498. return false;
  499. }
  500. return false;
  501. },
  502. addRow() {
  503. if (this.inputForm.financeInvoiceBaseDTOList.length === 0) {
  504. this.inputForm.financeInvoiceBaseDTOList.push({ recipientAgent: this.userInfo.name,
  505. recipientAgentId: this.userInfo.id, recipientOffice: this.userInfo.officeDTO.name });
  506. } else {
  507. if (this.isNotEmpty(this.inputForm.financeInvoiceBaseDTOList[0].programName)) {
  508. this.inputForm.financeInvoiceBaseDTOList.push({ recipientAgent: this.userInfo.name,
  509. recipientAgentId: this.userInfo.id, recipientOffice: this.userInfo.officeDTO.name });
  510. } else {
  511. uni.showToast({
  512. title: '非项目,只能有一条非项目数据',
  513. icon: 'none',
  514. duration: 2000
  515. });
  516. }
  517. }
  518. // 点击新增按钮时,向表格中添加一行空数据
  519. // this.inputForm.financeInvoiceBaseDTOList.push({ recipientAgent: this.userInfo.name,
  520. // recipientAgentId: this.userInfo.id, recipientOffice: this.userInfo.officeDTO.name });
  521. },
  522. removeRow(index) {
  523. // 点击删除按钮时,从表格中移除指定行
  524. this.inputForm.financeInvoiceBaseDTOList.splice(index, 1);
  525. let currentAccountTotal = 0; // 初始化为 0
  526. // 遍历 financeInvoiceBaseDTOList,累加每一行的 account
  527. this.inputForm.financeInvoiceBaseDTOList.forEach(item => {
  528. currentAccountTotal += parseFloat(item.account || 0); // 获取当前行的 account,若为空则设为 0
  529. });
  530. // 设置新的 accountTotal
  531. this.$set(this.inputForm, 'accountTotal', currentAccountTotal);
  532. },
  533. formatDateNew(date) {
  534. const year = date.getFullYear();
  535. const month = (date.getMonth() + 1).toString().padStart(2, '0');
  536. const day = date.getDate().toString().padStart(2, '0');
  537. const hours = date.getHours().toString().padStart(2, '0');
  538. const minutes = date.getMinutes().toString().padStart(2, '0');
  539. const seconds = date.getSeconds().toString().padStart(2, '0');
  540. return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  541. },
  542. handleUploadSuccess (res, file, fileList) {
  543. // 将 fileList 转换为你期望的格式
  544. const formattedFiles = fileList.map(fileItem => {
  545. return {
  546. name: fileItem.name,
  547. size: fileItem.size,
  548. url: fileItem.response ? '/' + fileItem.response.url : fileItem.url,
  549. lsUrl: fileItem.response ? fileItem.response.lsUrl : fileItem.lsUrl, // 如果没有 lsUrl,可以根据需要设置为空字符串或其他默认值
  550. createBy: this.userInfo,
  551. by: this.userInfo.id,
  552. createTime: this.formatDateNew(new Date())
  553. };
  554. });
  555. this.inputForm.files = formattedFiles
  556. fileList.forEach((item, index) => {
  557. if (item === file) {
  558. this.$set(this.showFileList, index, true);
  559. }
  560. });
  561. // 强制更新视图
  562. this.$forceUpdate();
  563. },
  564. handleRemove(file, fileList) {
  565. // 处理移除文件逻辑
  566. // file 是移除的文件
  567. // fileList 是当前文件列表
  568. const formattedFiles = fileList.map(fileItem => {
  569. return {
  570. name: fileItem.name,
  571. size: fileItem.size,
  572. url: '/' + fileItem.response.url,
  573. createBy: this.userInfo,
  574. by: this.userInfo.id,
  575. createTime: this.formatDateNew(new Date())
  576. };
  577. });
  578. this.inputForm.files = formattedFiles
  579. },
  580. saveForm(callback) {
  581. return new Promise((resolve, reject) => {
  582. // 表单规则验证
  583. // ...
  584. let errors = [];
  585. if (this.isEmpty(this.inputForm.financeInvoiceBaseDTOList)) {
  586. errors.push('至少新增一条基本信息');
  587. } else {
  588. let i = this.inputForm.financeInvoiceBaseDTOList.length;
  589. for (let j = 0; j < i; j++) {
  590. let k = j + 1;
  591. if (this.isEmpty(this.inputForm.financeInvoiceBaseDTOList[j].account)) {
  592. errors.push('第' + k + '行的发票金额不能为空');
  593. }
  594. }
  595. }
  596. //验证邮箱
  597. if (this.isNotEmpty(this.inputForm.actualDrawerEmailAddress)) {
  598. var reg = /^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
  599. if (!reg.test(this.inputForm.actualDrawerEmailAddress)) {
  600. errors.push('请输入正确的邮箱地址');
  601. }
  602. }
  603. if (errors.length > 0) {
  604. // 存在错误,显示提示信息
  605. errors.forEach(error => {
  606. uni.showToast({
  607. title: error,
  608. icon: 'none',
  609. duration: 2000
  610. });
  611. });
  612. reject('Form validation failed');
  613. } else {
  614. this.inputForm.account = this.inputForm.accountTotal
  615. // 所有验证通过,执行保存操作
  616. this.$refs.inputForm.validate().then(() => {
  617. uni.showLoading();
  618. this.inputForm.status = '2';
  619. financeInvoiceService.saveForm(this.inputForm).then(data => {
  620. callback(data.businessTable, data.businessId);
  621. resolve('Form saved successfully');
  622. }).catch(error => {
  623. reject('Save operation failed');
  624. });
  625. }).catch(() => {
  626. reject('Form validation failed');
  627. });
  628. }
  629. });
  630. },
  631. // 修改状态
  632. async updateStatusById (type, callback) {
  633. if (type === 'reject' || type === 'reback') {
  634. financeInvoiceService.queryById(this.inputForm.id).then((data) => {
  635. if (data.status !== '2') { // status的值不等于“审核中”,就弹出提示
  636. this.loading = false
  637. this.$message.error('任务数据已发生改变或不存在,请在待办任务中确认此任务是否存在')
  638. throw new Error()
  639. } else {
  640. if (type === 'reject') {
  641. // 驳回
  642. this.inputForm.status = '4'
  643. }
  644. if (type === 'reback') {
  645. // 撤回
  646. this.inputForm.status = '3'
  647. }
  648. if (type === 'reject' || type === 'reback') {
  649. let param = {status: this.inputForm.status, id: this.inputForm.id}
  650. financeInvoiceService.updateStatusById(param).then(() => {
  651. this.loading = false
  652. callback()
  653. })
  654. }
  655. }
  656. })
  657. } else if (type === 'hold') {
  658. financeInvoiceService.queryById(this.inputForm.id).then((data) => {
  659. if (data.status !== '4') { // status的值不等于“驳回”就弹出提示
  660. this.loading = false
  661. this.$message.error('任务数据已发生改变或不存在,请在待办任务中确认此任务是否存在')
  662. throw new Error()
  663. } else {
  664. // 终止
  665. let param = {status: '1', id: this.inputForm.id}
  666. financeInvoiceService.updateStatusById(param).then(() => {
  667. this.loading = false
  668. callback()
  669. })
  670. }
  671. })
  672. }
  673. },
  674. reapplyForm (callback) {
  675. this.loading = true
  676. financeInvoiceService.queryById(this.inputForm.id).then((data) => {
  677. if (data.status !== '4') { // 审核状态不是“驳回”,就弹出提示
  678. this.loading = false
  679. this.$message.error('任务数据已发生改变或不存在,请在待办任务中确认此任务是否存在')
  680. throw new Error('任务数据已发生改变或不存在,请在待办任务中确认此任务是否存在')
  681. } else {
  682. this.startFormTrue(callback)
  683. }
  684. })
  685. },
  686. // 送审
  687. async startFormTrue (callback) {
  688. this.$refs.inputForm.validate().then(res => {
  689. this.inputForm.status = '2'
  690. financeInvoiceService.saveForm(this.inputForm).then((data) => {
  691. this.inputForm.id = data.businessId
  692. callback(data.businessTable, data.businessId, this.inputForm)
  693. this.$refs.inputForm.resetFields()
  694. this.loading = false
  695. }).catch(() => {
  696. this.$refs.inputForm.resetFields()
  697. }).catch((e) => {
  698. })
  699. })
  700. },
  701. // 通过
  702. async agreeForm (callback) {
  703. this.$refs.inputForm.validate().then(res => {
  704. this.inputForm.status = '5'
  705. financeInvoiceService.saveForm(this.inputForm).then((data) => {
  706. callback(data.businessTable, data.businessId, this.inputForm)
  707. this.$refs.inputForm.resetFields()
  708. this.loading = false
  709. }).catch(() => {
  710. this.loading = false
  711. this.$refs.inputForm.resetFields()
  712. })
  713. })
  714. },
  715. shouldShowFile(file) {
  716. if (this.inputForm.files && this.inputForm.files.length > 0) {
  717. // 返回一个布尔值,确定是否显示上传成功后的文件
  718. return this.showFileList[this.inputForm.files.indexOf(file)];
  719. }
  720. return false; // 默认返回 false 或者其他适当的
  721. },
  722. async handleFileClick(file) {
  723. await this.ossService.getTemporaryUrl(file.url).then((data) => {
  724. file.lsUrl = data
  725. })
  726. if (this.isImage(file.name)) {
  727. // 如果是图片文件,则执行放大显示图片的逻辑
  728. this.handleImageClick(file);
  729. } else {
  730. // window.open(file.lsUrl, '_blank')
  731. window.location.href = file.lsUrl
  732. // 如果不是图片文件,则执行其他操作,比如下载文件等
  733. }
  734. },
  735. handleImageClick(file) {
  736. // 在点击图片时执行放大显示的逻辑
  737. this.$alert(`<img src="${file.lsUrl}" style="max-width: 100%; max-height: 100%;" />`, '图片详情', {
  738. dangerouslyUseHTMLString: true,
  739. customClass: 'custom-alert'
  740. });
  741. },
  742. // 判断文件是否是图片类型
  743. isImage(fileName) {
  744. const ext = fileName.toLowerCase().split('.').pop(); // 获取文件的后缀名
  745. return ['jpg', 'jpeg', 'png', 'gif', 'bmp'].includes(ext); // 判断后缀名是否是图片类型
  746. },
  747. handleDelete(file) {
  748. // 处理删除文件的逻辑
  749. // 从文件列表中移除文件
  750. const index = this.inputForm.files.indexOf(file);
  751. if (index !== -1) {
  752. this.inputForm.files.splice(index, 1);
  753. this.showFileList.splice(index, 1); // 从showFileList中移除对应的元素
  754. }
  755. },
  756. // 输入值改变事件处理程序
  757. onInputCode(index, event,type) {
  758. const inputValue = event
  759. const formattedValue = this.formatInput(inputValue);
  760. if (type === 'account') {
  761. this.$set(this.inputForm.financeInvoiceBaseDTOList[index], 'account', formattedValue)
  762. // 计算 accountTotal 的新值
  763. const currentAccountTotal = parseFloat(this.inputForm.accountTotal || 0); // 获取当前 accountTotal,若为空则设为 0
  764. const newAccountTotal = currentAccountTotal + parseFloat(formattedValue);
  765. // 设置新的 accountTotal
  766. this.$set(this.inputForm, 'accountTotal', newAccountTotal);
  767. }
  768. },
  769. // 通用的输入限制和格式化方法
  770. formatInput(inputValue, decimalLimit = 2) {
  771. // 如果输入值不是数字或者不是有效的小数,则返回空字符串
  772. if (!/^\d*\.?\d*$/.test(inputValue)) {
  773. return '';
  774. }
  775. // 只保留数字和一个小数点
  776. let value = inputValue.replace(/[^\d.]/g, '');
  777. // 只允许一个小数点
  778. const dotIndex = value.indexOf('.');
  779. if (dotIndex !== -1) {
  780. const substr = value.substr(dotIndex + 1);
  781. if (substr.indexOf('.') !== -1) {
  782. value = value.substr(0, dotIndex + 1) + substr.replace(/\./g, '');
  783. }
  784. }
  785. // 限制小数位数为指定的decimalLimit位数
  786. if (dotIndex !== -1) {
  787. const integerPart = value.substring(0, dotIndex);
  788. const decimalPart = value.substring(dotIndex + 1);
  789. value = integerPart + '.' + decimalPart.slice(0, decimalLimit);
  790. }
  791. return value;
  792. },
  793. reimbursementTypeChange(value) {
  794. this.inputForm.address = ''
  795. this.inputForm.telPhone = ''
  796. this.inputForm.billingId = ''
  797. this.inputForm.billingWorkplaceReal = ''
  798. this.inputForm.billingWorkplaceRealId = ''
  799. this.inputForm.taxpayerIdentificationNo = ''
  800. this.bankList = []
  801. this.inputForm.bankAccount = ''
  802. this.inputForm.openBank = ''
  803. this.inputForm.name = ''
  804. },
  805. openUserPullForm(index,type) {
  806. // 点击 "采购人" 输入框时打开userPullForm页面,传入index用于区分不同的行
  807. // uni.navigateTo({
  808. // url: '/pages/materialManagement/collect/UserPullForm?index=' + index // userPullForm页面的路径
  809. // });
  810. this.$refs.userPicker.open(index,type);
  811. },
  812. handleEvent(data,index,type) {
  813. if (type === '实际') {
  814. this.inputForm.billingPeopleRealName = data.label
  815. this.inputForm.billingPeopleReal = data.id
  816. } else if (type === '对账') {
  817. this.inputForm.reconciliationPeopleName = data.label
  818. this.inputForm.reconciliationPeople = data.id
  819. } else if (type === '姓名') {
  820. this.inputForm.nameShow = data.label
  821. this.inputForm.name = data.id
  822. }
  823. },
  824. // 显示 项目选择器
  825. showProject(index) {
  826. if (this.inputForm.financeInvoiceBaseDTOList.length > 0 && this.isNotEmpty(this.inputForm.financeInvoiceBaseDTOList[0].programName)){
  827. if (this.isNotEmpty(this.inputForm.financeInvoiceBaseDTOList[0].reportNo)) {
  828. this.$refs.invoiceProjectChoose.init(index,'2');
  829. } else {
  830. this.$refs.invoiceProjectChoose.init(index,'1');
  831. }
  832. } else {
  833. this.$refs.invoiceProjectChoose.init(index);
  834. }
  835. },
  836. // 实际开票单位选择
  837. showWorkplace() {
  838. this.$refs.workPlaceChoose.init();
  839. },
  840. selectProjectChange(rows, index) {
  841. if (rows.length > 0) {
  842. rows.forEach((item, rowIndex) => {
  843. this.inputForm.programId = item.id;
  844. if (rowIndex === 0) {
  845. let r = this.inputForm.financeInvoiceBaseDTOList[index];
  846. if (!r) {
  847. r = {};
  848. }
  849. r.programName = item.projectName;
  850. r.contractName = item.contractName;
  851. r.programNo = item.projectNumber;
  852. r.contractId = item.contractId;
  853. r.programId = item.id;
  854. r.reportNo = item.reportNo;
  855. r.reportType = item.reportType;
  856. r.isPreInvoice = item.isPreInvoice;
  857. this.$set(this.inputForm.financeInvoiceBaseDTOList, index, r);
  858. } else {
  859. let r = {
  860. programName: item.projectName,
  861. contractName: item.contractName,
  862. programNo: item.projectNumber,
  863. contractId: item.contractId,
  864. programId: item.id,
  865. reportNo: item.reportNo,
  866. reportType: item.reportType,
  867. isPreInvoice: item.isPreInvoice
  868. }
  869. this.inputForm.financeInvoiceBaseDTOList.push(r);
  870. }
  871. });
  872. } else {
  873. let r = {
  874. programName: rows.projectName,
  875. contractName: rows.contractName,
  876. programNo: rows.projectNumber,
  877. contractId: rows.contractId,
  878. programId: rows.id,
  879. reportNo: rows.reportNo,
  880. reportType: rows.reportType,
  881. isPreInvoice: rows.isPreInvoice
  882. }
  883. if (!this.inputForm.detailInfoReports) {
  884. this.$set(this.inputForm, 'detailInfoReports', []);
  885. }
  886. this.$set(this.inputForm.detailInfoReports, index, r);
  887. this.isPreInvoice = rows.isPreInvoice;
  888. this.inputForm.programId = rows.id;
  889. }
  890. },
  891. getWorkClient(row) {
  892. this.bankList = []
  893. this.inputForm.billingWorkplaceReal = row.name // 实际开票单位姓名
  894. this.inputForm.billingWorkplaceRealId = row.id // 实际开票单位id ‘客户id’
  895. this.inputForm.taxpayerIdentificationNo = this.isEmpty(row.uscCode) ? '' : row.uscCode // 纳税人识别号 ‘统一社会信用代码’
  896. this.inputForm.address = this.isEmpty(row.address) ? '' : row.address // 地址
  897. this.inputForm.telPhone = this.isEmpty(row.mobile) ? '' : row.mobile // 电话
  898. this.inputForm.billingId = '' // 实际开票单位的开票信息id
  899. // this.inputForm.telPhone = '' // 电话
  900. for (let i=0;i<row.cwWorkClientBillingDTOList.length;i++) {
  901. row.cwWorkClientBillingDTOList[i].ourBank = row.cwWorkClientBillingDTOList[i].accountHolder
  902. let test = {label: row.cwWorkClientBillingDTOList[i].ourBank, value: row.cwWorkClientBillingDTOList[i].id, account: row.cwWorkClientBillingDTOList[i].account}
  903. this.bankList.push(test)
  904. }
  905. // row.cwWorkClientBillingDTOList.forEach(item => {
  906. // item.ourBank = item.accountHolder
  907. // this.bankList.push(item)
  908. // })
  909. this.inputForm.bankAccount = ''
  910. this.inputForm.openBank = ''
  911. this.$forceUpdate()
  912. },
  913. changeBank(value) {
  914. this.bankList.forEach(item => {
  915. if (item.value === value) {
  916. this.inputForm.bankAccount = item.account
  917. }
  918. })
  919. },
  920. validatePhone (str,callback) {
  921. const phone = /(^(\d{3,4}-)?\d{6,8}$)|(^(\d{3,4}-)?\d{6,8}(-\d{1,5})?$)|(^(((13[0-9]{1})|(15[0-9]{1})|(16[0-9]{1})|(18[0-9]{1})|(17[0-9]{1})|(19[0-9]{1}))+\d{8})$)/
  922. if (str && !phone.test(str)) {
  923. callback(new Error('请输入正确的电话号码'))
  924. } else {
  925. callback()
  926. }
  927. },
  928. checkEmail(str,callback) {
  929. if (!this.isNotEmpty(str)) {
  930. callback(); // 输入框为空时不进行验证,直接清除错误提示
  931. return;
  932. }
  933. var reg = /^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
  934. if (!reg.test(str)) {
  935. callback(new Error('请输入正确的邮箱地址'))
  936. } else {
  937. callback()
  938. }
  939. },
  940. openDia() {
  941. let id = this.userInfo.id
  942. let userEmail = this.inputForm.actualDrawerEmailAddress
  943. this.$refs.emailForm.init(id,userEmail);
  944. },
  945. emailForm(row) {
  946. this.inputForm.actualDrawerEmailAddress=row
  947. },
  948. }
  949. }
  950. </script>
  951. <style>
  952. .cu-form-group .title {
  953. min-width: calc(4em + 40px);
  954. }
  955. /* 样式示例,您可能需要根据实际情况调整 */
  956. .upload-demo {
  957. width: 40%;
  958. }
  959. .button-container {
  960. margin-top: 10px;
  961. text-align: right;
  962. }
  963. </style>