addDialog.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. <!-- 新增/编辑弹窗 -->
  2. <template>
  3. <ele-modal
  4. width="700px"
  5. :visible="visible"
  6. :append-to-body="true"
  7. :close-on-click-modal="false"
  8. custom-class="ele-dialog-form"
  9. :title="isDetail ? '详情' : (isUpdate ? '修改' : '新增')"
  10. @update:visible="updateVisible"
  11. >
  12. <el-form
  13. ref="form"
  14. :model="form"
  15. :rules="rules"
  16. label-width="140px"
  17. >
  18. <!-- 收/付款条件编码 -->
  19. <el-form-item :label="conditionType == 'rules' ? '收款条件编码:' : '付款条件编码:'" prop="code">
  20. <el-input
  21. v-model="form.code"
  22. placeholder="自动生成"
  23. :disabled="true"
  24. />
  25. </el-form-item>
  26. <!-- 收款条件名称 -->
  27. <el-form-item :label="conditionType == 'rules' ? '收款条件名称:' : '付款条件名称:'" prop="name">
  28. <el-input
  29. clearable
  30. v-model="form.name"
  31. placeholder="请输入条件名称"
  32. :disabled="isDetail"
  33. />
  34. </el-form-item>
  35. <!-- 收/付款日计算日期 -->
  36. <el-form-item :label="conditionType == 'rules' ? '收款日计算日期:' : '付款日计算日期:'" prop="dateType">
  37. <el-select
  38. v-model="form.dateType"
  39. placeholder="请选择"
  40. style="width: 100%"
  41. :disabled="isDetail"
  42. >
  43. <el-option v-for="item in calcReceiveDateTypeOp" :key="item.value" :label="item.label" :value="item.value" />
  44. </el-select>
  45. </el-form-item>
  46. <!-- 收/付款日确定方式 -->
  47. <el-form-item :label="conditionType == 'rules' ? '收款日确定方式:' : '付款日确定方式:'" prop="determinationMethod">
  48. <el-select
  49. v-model="form.determinationMethod"
  50. placeholder="请选择"
  51. style="width: 100%"
  52. :disabled="isDetail"
  53. @change="handleConfirmTypeChange"
  54. >
  55. <el-option v-for="item in payConfirmTypeOp" :key="item.value" :label="item.label" :value="item.value" />
  56. </el-select>
  57. </el-form-item>
  58. <!-- 月数(X天后显示) -->
  59. <el-form-item label="月数:" v-if="form.determinationMethod == 2">
  60. <el-input-number
  61. v-model="form.determinationMethodMonth"
  62. :min="0"
  63. :precision="0"
  64. controls-position="right"
  65. style="width: 100%"
  66. :disabled="isDetail"
  67. />
  68. </el-form-item>
  69. <!-- 天数(X天后显示) -->
  70. <el-form-item label="天数:" v-if="form.determinationMethod == 2">
  71. <el-input-number
  72. v-model="form.determinationMethodDay"
  73. :min="0"
  74. :precision="0"
  75. controls-position="right"
  76. style="width: 100%"
  77. :disabled="isDetail"
  78. />
  79. </el-form-item>
  80. <!-- 支付方式列表 -->
  81. <el-form-item
  82. v-for="(item, index) in form.rulesTypePOList"
  83. :key="item.id"
  84. :label="index === 0 ? '支付方式:' : ''"
  85. :required="index === 0"
  86. class="payment-method-item"
  87. >
  88. <div class="payment-method-row">
  89. <el-input-number
  90. v-model="item.percentage"
  91. :min="0"
  92. :max="100"
  93. :precision="0"
  94. controls-position="right"
  95. class="payment-input"
  96. placeholder="比例"
  97. :disabled="isDetail"
  98. />
  99. <span class="payment-unit">%</span>
  100. <el-input-number
  101. v-model="item.paymentSum"
  102. :min="0"
  103. :precision="0"
  104. controls-position="right"
  105. class="payment-input"
  106. placeholder="请输入"
  107. :disabled="isDetail"
  108. />
  109. <el-select
  110. v-model="item.dateType"
  111. placeholder="请选择"
  112. class="payment-unit-select"
  113. :disabled="isDetail"
  114. >
  115. <el-option v-for="opt in dateUnitOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
  116. </el-select>
  117. <DictSelection
  118. v-model="item.paymentType"
  119. dictName="支付类型"
  120. placeholder="请选择"
  121. class="payment-select"
  122. :disabled="isDetail"
  123. />
  124. <el-button
  125. v-if="!isDetail && index === form.rulesTypePOList.length - 1"
  126. type="text"
  127. icon="el-icon-circle-plus-outline"
  128. class="add-payment-btn"
  129. @click="addPaymentRow"
  130. />
  131. <el-button
  132. v-if="!isDetail && form.rulesTypePOList.length > 1 && index !== 0"
  133. type="text"
  134. icon="el-icon-remove-outline"
  135. class="remove-payment-btn"
  136. @click="removePaymentRow(index)"
  137. />
  138. </div>
  139. </el-form-item>
  140. <!-- 备注 -->
  141. <el-form-item label="备注:" prop="remark">
  142. <el-input
  143. type="textarea"
  144. :rows="3"
  145. v-model="form.remark"
  146. placeholder="请输入"
  147. :disabled="isDetail"
  148. />
  149. </el-form-item>
  150. </el-form>
  151. <template v-slot:footer>
  152. <template v-if="isDetail">
  153. <el-button @click="updateVisible(false)">关闭</el-button>
  154. </template>
  155. <template v-else>
  156. <el-button type="primary" :loading="loading" @click="save">
  157. 确定
  158. </el-button>
  159. <el-button @click="updateVisible(false)">取消</el-button>
  160. </template>
  161. </template>
  162. </ele-modal>
  163. </template>
  164. <script>
  165. import { addReceiveTerms, updateReceiveTerms, getInfo } from '@/api/rulesManagement/receiveTerms';
  166. import { calcReceiveDateTypeOp, payConfirmTypeOp, dateUnitOptions } from '@/enum/dict';
  167. let paymentId = 0;
  168. export default {
  169. props: {
  170. // 收款/付款:rules/terms
  171. conditionType: {
  172. type: String,
  173. default: ''
  174. }
  175. },
  176. data() {
  177. return {
  178. visible: false,
  179. loading: false,
  180. isUpdate: false,
  181. isDetail: false,
  182. calcReceiveDateTypeOp,
  183. payConfirmTypeOp,
  184. // 支付周期单位(天/月/年)
  185. dateUnitOptions,
  186. form: {
  187. id: null,
  188. code: '',
  189. name: '',
  190. dateType: null,
  191. determinationMethod: null,
  192. determinationMethodMonth: 0,
  193. determinationMethodDay: 0,
  194. rulesTypePOList: [],
  195. remark: '',
  196. ruleState: 1,
  197. conditionConfigurationType: this.conditionType
  198. },
  199. rules: {
  200. // code: [{ required: true, message: '请输入收款条件编码', trigger: 'blur' }],
  201. name: [{ required: true, message: '请输入收款条件名称', trigger: 'blur' }],
  202. dateType: [{ required: true, message: '请选择收款日计算日期', trigger: 'change' }],
  203. determinationMethod: [{ required: true, message: '请选择收款日确定方式', trigger: 'change' }]
  204. }
  205. };
  206. },
  207. methods: {
  208. // 生成编码 SKTJ+年月日+3位数字
  209. generateCode() {
  210. const now = new Date();
  211. const year = now.getFullYear();
  212. const month = String(now.getMonth() + 1).padStart(2, '0');
  213. const day = String(now.getDate()).padStart(2, '0');
  214. const random = String(Math.floor(Math.random() * 900) + 100);
  215. this.form.code = `SKTJ${year}${month}${day}${random}`;
  216. },
  217. open(type, row) {
  218. this.visible = true;
  219. this.isUpdate = type === 'edit';
  220. this.isDetail = type === 'detail';
  221. if ((this.isUpdate || this.isDetail) && row) {
  222. this.getDetail(row.id)
  223. } else {
  224. this.resetForm();
  225. // this.generateCode();
  226. }
  227. this.$nextTick(() => {
  228. this.$refs.form && this.$refs.form.clearValidate();
  229. });
  230. },
  231. getDetail(id) {
  232. getInfo(id).then(res => {
  233. console.log('getInfo res', res);
  234. this.form = {
  235. ...res,
  236. };
  237. })
  238. },
  239. resetForm() {
  240. this.form = {
  241. // id: null,
  242. code: '',
  243. name: '',
  244. dateType: '1', // 默认:订单日期
  245. determinationMethod: '1', // 默认:交易日(隐藏月数、天数)
  246. determinationMethodMonth: 0,
  247. determinationMethodDay: 0,
  248. rulesTypePOList: [this.createEmptyPayment()], // 默认:100% 0月 现金
  249. remark: '',
  250. ruleState: 1,
  251. conditionConfigurationType: this.conditionType
  252. };
  253. },
  254. createEmptyPayment() {
  255. return {
  256. key: ++paymentId,
  257. percentage: 100,
  258. paymentSum: 0,
  259. dateType: 'month',
  260. paymentType: '1'
  261. };
  262. },
  263. // 收款日确定方式变化
  264. handleConfirmTypeChange() {
  265. if (this.form.determinationMethod == 1) {
  266. this.form.determinationMethodMonth = 0;
  267. this.form.determinationMethodDay = 0;
  268. }
  269. },
  270. // 添加支付方式行
  271. addPaymentRow() {
  272. this.form.rulesTypePOList.push(this.createEmptyPayment());
  273. },
  274. // 移除支付方式行
  275. removePaymentRow(index) {
  276. this.form.rulesTypePOList.splice(index, 1);
  277. },
  278. // 构建支付方式字符串
  279. buildPaymentMethod() {
  280. return this.form.rulesTypePOList
  281. .map(item => `${item.percentage}% ${item.paymentSum}${item.dateType || 'month'} ${item.paymentType}`)
  282. .join(',');
  283. },
  284. // 构建确认方式描述
  285. buildConfirmDesc() {
  286. if (this.form.determinationMethod === 1) {
  287. return '交易日';
  288. }
  289. const parts = [];
  290. if (this.form.determinationMethodMonth > 0) parts.push(`月数:${this.form.determinationMethodMonth}`);
  291. if (this.form.determinationMethodDay > 0) parts.push(`天数:${this.form.determinationMethodDay}`);
  292. if (parts.length === 0) return '0月0天即交易日';
  293. return parts.join(',');
  294. },
  295. save() {
  296. this.$refs.form.validate((valid) => {
  297. if (!valid) return;
  298. // 校验支付方式比例总和
  299. const totalRatio = this.form.rulesTypePOList.reduce((sum, item) => sum + item.percentage, 0);
  300. if (totalRatio !== 100) {
  301. this.$message.warning('支付比例总和必须等于100%');
  302. return;
  303. }
  304. this.loading = true;
  305. const data = {
  306. ...this.form,
  307. // paymentMethod: this.buildPaymentMethod(),
  308. // confirmDesc: this.buildConfirmDesc()
  309. };
  310. // delete data.rulesTypePOList;
  311. console.log('save data', data);
  312. // return
  313. const saveOrUpdate = this.isUpdate ? updateReceiveTerms : addReceiveTerms;
  314. saveOrUpdate(data)
  315. .then(() => {
  316. this.loading = false;
  317. this.$message.success(this.isUpdate ? '修改成功' : '新增成功');
  318. this.updateVisible(false);
  319. this.$emit('done');
  320. })
  321. .catch(() => {
  322. this.loading = false;
  323. });
  324. });
  325. },
  326. updateVisible(value) {
  327. this.visible = value;
  328. if (!value) {
  329. this.resetForm();
  330. }
  331. }
  332. }
  333. };
  334. </script>
  335. <style lang="scss" scoped>
  336. .payment-method-row {
  337. display: flex;
  338. align-items: center;
  339. gap: 8px;
  340. }
  341. .payment-input {
  342. width: 100px;
  343. }
  344. .payment-unit {
  345. color: #606266;
  346. font-size: 14px;
  347. }
  348. .payment-unit-select {
  349. width: 80px;
  350. }
  351. .payment-select {
  352. width: 120px!important;
  353. }
  354. .add-payment-btn,
  355. .remove-payment-btn {
  356. font-size: 18px;
  357. padding: 0;
  358. }
  359. .remove-payment-btn {
  360. color: #f56c6c;
  361. }
  362. </style>