addDialog.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  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 dateTypeOptions" :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. :isProhibit="isDetail"
  124. />
  125. <el-button
  126. v-if="!isDetail && index === form.rulesTypePOList.length - 1"
  127. type="text"
  128. icon="el-icon-circle-plus-outline"
  129. class="add-payment-btn"
  130. @click="addPaymentRow"
  131. />
  132. <el-button
  133. v-if="!isDetail && form.rulesTypePOList.length > 1 && index !== 0"
  134. type="text"
  135. icon="el-icon-remove-outline"
  136. class="remove-payment-btn"
  137. @click="removePaymentRow(index)"
  138. />
  139. </div>
  140. </el-form-item>
  141. <!-- 备注 -->
  142. <el-form-item label="备注:" prop="remark">
  143. <el-input
  144. type="textarea"
  145. :rows="3"
  146. v-model="form.remark"
  147. placeholder="请输入"
  148. :disabled="isDetail"
  149. />
  150. </el-form-item>
  151. </el-form>
  152. <template v-slot:footer>
  153. <template v-if="isDetail">
  154. <el-button @click="updateVisible(false)">关闭</el-button>
  155. </template>
  156. <template v-else>
  157. <el-button type="primary" :loading="loading" @click="save">
  158. 确定
  159. </el-button>
  160. <el-button @click="updateVisible(false)">取消</el-button>
  161. </template>
  162. </template>
  163. </ele-modal>
  164. </template>
  165. <script>
  166. import { addReceiveTerms, updateReceiveTerms, getInfo } from '@/api/rulesManagement/receiveTerms';
  167. import {
  168. calcReceiveDateTypeOp,
  169. calcPayDateTypeOp,
  170. payConfirmTypeOp,
  171. dateUnitOptions,
  172. PaymentDateCalcTypeEnum,
  173. ReceiveDateCalcTypeEnum
  174. } from '@/enum/dict';
  175. let paymentId = 0;
  176. export default {
  177. props: {
  178. // 收款/付款:rules/terms
  179. conditionType: {
  180. type: String,
  181. default: ''
  182. }
  183. },
  184. data() {
  185. return {
  186. visible: false,
  187. loading: false,
  188. isUpdate: false,
  189. isDetail: false,
  190. payConfirmTypeOp,
  191. // 支付周期单位(天/月/年)
  192. dateUnitOptions,
  193. form: {
  194. id: null,
  195. code: '',
  196. name: '',
  197. dateType: null,
  198. determinationMethod: null,
  199. determinationMethodMonth: 0,
  200. determinationMethodDay: 0,
  201. rulesTypePOList: [],
  202. remark: '',
  203. ruleState: 1,
  204. conditionConfigurationType: this.conditionType
  205. },
  206. rules: {
  207. // code: [{ required: true, message: '请输入收款条件编码', trigger: 'blur' }],
  208. name: [{ required: true, message: '请输入收款条件名称', trigger: 'blur' }],
  209. dateType: [{ required: true, message: '请选择收款日计算日期', trigger: 'change' }],
  210. determinationMethod: [{ required: true, message: '请选择收款日确定方式', trigger: 'change' }]
  211. }
  212. };
  213. },
  214. computed: {
  215. // 收/付款日计算日期:根据 conditionType 切换对应枚举选项
  216. dateTypeOptions() {
  217. return this.conditionType === 'rules' ? calcReceiveDateTypeOp : calcPayDateTypeOp;
  218. }
  219. },
  220. methods: {
  221. // 生成编码 SKTJ+年月日+3位数字
  222. generateCode() {
  223. const now = new Date();
  224. const year = now.getFullYear();
  225. const month = String(now.getMonth() + 1).padStart(2, '0');
  226. const day = String(now.getDate()).padStart(2, '0');
  227. const random = String(Math.floor(Math.random() * 900) + 100);
  228. this.form.code = `SKTJ${year}${month}${day}${random}`;
  229. },
  230. open(type, row) {
  231. this.visible = true;
  232. this.isUpdate = type === 'edit';
  233. this.isDetail = type === 'detail';
  234. if ((this.isUpdate || this.isDetail) && row) {
  235. this.getDetail(row.id)
  236. } else {
  237. this.resetForm();
  238. // this.generateCode();
  239. }
  240. this.$nextTick(() => {
  241. this.$refs.form && this.$refs.form.clearValidate();
  242. });
  243. },
  244. getDetail(id) {
  245. getInfo(id).then(res => {
  246. console.log('getInfo res', res);
  247. this.form = {
  248. ...res,
  249. };
  250. })
  251. },
  252. resetForm() {
  253. // 收/付款日计算日期默认值:按当前条件类型取对应枚举的"订单日期"
  254. const defaultDateType = this.conditionType === 'rules'
  255. ? ReceiveDateCalcTypeEnum.ORDER_DATE
  256. : PaymentDateCalcTypeEnum.ORDER_DATE;
  257. this.form = {
  258. // id: null,
  259. code: '',
  260. name: '',
  261. dateType: defaultDateType, // 默认:订单日期
  262. determinationMethod: '1', // 默认:交易日(隐藏月数、天数)
  263. determinationMethodMonth: 0,
  264. determinationMethodDay: 0,
  265. rulesTypePOList: [this.createEmptyPayment()], // 默认:100% 0月 现金
  266. remark: '',
  267. ruleState: 1,
  268. conditionConfigurationType: this.conditionType
  269. };
  270. },
  271. createEmptyPayment() {
  272. return {
  273. key: ++paymentId,
  274. percentage: 100,
  275. paymentSum: 0,
  276. dateType: 'month',
  277. paymentType: '1'
  278. };
  279. },
  280. // 收款日确定方式变化
  281. handleConfirmTypeChange() {
  282. if (this.form.determinationMethod == 1) {
  283. this.form.determinationMethodMonth = 0;
  284. this.form.determinationMethodDay = 0;
  285. }
  286. },
  287. // 添加支付方式行
  288. addPaymentRow() {
  289. this.form.rulesTypePOList.push(this.createEmptyPayment());
  290. },
  291. // 移除支付方式行
  292. removePaymentRow(index) {
  293. this.form.rulesTypePOList.splice(index, 1);
  294. },
  295. // 构建支付方式字符串
  296. buildPaymentMethod() {
  297. return this.form.rulesTypePOList
  298. .map(item => `${item.percentage}% ${item.paymentSum}${item.dateType || 'month'} ${item.paymentType}`)
  299. .join(',');
  300. },
  301. // 构建确认方式描述
  302. buildConfirmDesc() {
  303. if (this.form.determinationMethod === 1) {
  304. return '交易日';
  305. }
  306. const parts = [];
  307. if (this.form.determinationMethodMonth > 0) parts.push(`月数:${this.form.determinationMethodMonth}`);
  308. if (this.form.determinationMethodDay > 0) parts.push(`天数:${this.form.determinationMethodDay}`);
  309. if (parts.length === 0) return '0月0天即交易日';
  310. return parts.join(',');
  311. },
  312. save() {
  313. this.$refs.form.validate((valid) => {
  314. if (!valid) return;
  315. // 校验支付方式比例总和
  316. const totalRatio = this.form.rulesTypePOList.reduce((sum, item) => sum + item.percentage, 0);
  317. if (totalRatio !== 100) {
  318. this.$message.warning('支付比例总和必须等于100%');
  319. return;
  320. }
  321. this.loading = true;
  322. const data = {
  323. ...this.form,
  324. // paymentMethod: this.buildPaymentMethod(),
  325. // confirmDesc: this.buildConfirmDesc()
  326. };
  327. // delete data.rulesTypePOList;
  328. console.log('save data', data);
  329. // return
  330. const saveOrUpdate = this.isUpdate ? updateReceiveTerms : addReceiveTerms;
  331. saveOrUpdate(data)
  332. .then(() => {
  333. this.loading = false;
  334. this.$message.success(this.isUpdate ? '修改成功' : '新增成功');
  335. this.updateVisible(false);
  336. this.$emit('done');
  337. })
  338. .catch(() => {
  339. this.loading = false;
  340. });
  341. });
  342. },
  343. updateVisible(value) {
  344. this.visible = value;
  345. if (!value) {
  346. this.resetForm();
  347. }
  348. }
  349. }
  350. };
  351. </script>
  352. <style lang="scss" scoped>
  353. .payment-method-row {
  354. display: flex;
  355. align-items: center;
  356. gap: 8px;
  357. }
  358. .payment-input {
  359. width: 100px;
  360. }
  361. .payment-unit {
  362. color: #606266;
  363. font-size: 14px;
  364. }
  365. .payment-unit-select {
  366. width: 80px;
  367. }
  368. .payment-select {
  369. width: 120px!important;
  370. }
  371. .add-payment-btn,
  372. .remove-payment-btn {
  373. font-size: 18px;
  374. padding: 0;
  375. }
  376. .remove-payment-btn {
  377. color: #f56c6c;
  378. }
  379. </style>