Преглед изворни кода

充值功能发布、增加表单验证文件、优化上传地址匹配

kevin_zhangl пре 3 година
родитељ
комит
725bfc20b4

+ 11 - 0
src/api/file.js

@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+// 获取token
+export function fetchToken() {
+  return request({
+    url: '/v1/file/token',
+    method: 'get',
+    params: {}
+  })
+}
+

+ 31 - 2
src/api/finance.js

@@ -14,7 +14,7 @@ export function fetchApplyTransfer(data) {
   return request({
     url: '/v1/finance/transfer-add',
     method: 'post',
-    params: data
+    data
   })
 }
 
@@ -48,8 +48,37 @@ export function fetchFullInfo(data) {
 // 获取转账授权吗
 export function fetchTransferCode() {
   return request({
-    url: '/v1/finance/mult-point\n',
+    url: '/v1/finance/mult-point',
+    method: 'get',
+    params: {}
+  })
+}
+
+// 充值列表
+export function fetchRechargeList(data) {
+  return request({
+    url: '/v1/finance/recharge',
+    method: 'get',
+    params: data
+  })
+}
+
+// 银行列表
+export function fetchBankList() {
+  return request({
+    url: '/v1/finance/recharge-add',
     method: 'get',
     params: {}
   })
 }
+
+// 发起充值
+export function fetchApplyRecharge(data) {
+  return request({
+    url: '/v1/finance/recharge-add',
+    method: 'post',
+    data
+  })
+}
+
+

+ 10 - 0
src/lang/en.js

@@ -241,6 +241,7 @@ export default {
     cancel: 'Cancel',
     confirm: 'Confirm',
     successfully: 'Successfully',
+    close: 'Close',
   },
 
   shop: {
@@ -368,5 +369,14 @@ export default {
     successTips: 'Successfully.',
     enterPasswordTips: 'Please enter your payment password',
     executing: 'executing...',
+    recharge: 'Recharge',
+    createdTime: 'Created Time',
+    rechargeAmount: 'Recharge Amount',
+    rechargeStatus: 'Recharge Status',
+    bankName: 'Bank Name',
+    bankAccount: 'Bank Account',
+    printVoucher: 'Recharge Voucher',
+    uploadVoucher: 'Upload',
+    viewVoucher: 'View',
   },
 }

+ 10 - 0
src/lang/zh.js

@@ -240,6 +240,7 @@ export default {
     confirm: '确定',
     cancel: '取消',
     successfully: '成功',
+    close: '关闭',
   },
   shop: {
     productCode: '商品编号',
@@ -363,5 +364,14 @@ export default {
     successTips: '转账成功',
     enterPasswordTips: '请输入支付密码',
     executing: '执行中...',
+    recharge: '充值',
+    createdTime: '转账时间',
+    rechargeAmount: '充值金额',
+    rechargeStatus: '充值状态',
+    bankName: '汇款银行',
+    bankAccount: '汇款账号',
+    printVoucher: '充值凭证',
+    uploadVoucher: '上传',
+    viewVoucher: '查看',
   },
 }

+ 6 - 0
src/router/modules/finance.js

@@ -16,6 +16,12 @@ const financeRouter = {
       name: 'TransferList',
       meta: { title: 'transferList', icon: 'el-icon-coin' }
     },
+    {
+      path: 'recharge',  // 充值列表
+      component: () => import('@/views/finance/recharge-list'),
+      name: 'RechargeList',
+      meta: { title: 'rechargeList', icon: 'el-icon-coin' }
+    },
   ]
 }
 export default financeRouter

+ 144 - 0
src/utils/rules.js

@@ -0,0 +1,144 @@
+/**
+ * 必填
+ * @type {{trigger: string, message: string, required: boolean}}
+ */
+export const required = {
+	required: true,
+	message: '请填写此项内容',
+	trigger: 'blur'
+}
+
+/**
+ * 手机号-中国
+ * @type {{pattern: RegExp, trigger: string, message: string}}
+ */
+export const chiPhone = {
+	pattern: /^(13[0-9]|14[01456879]|15[0-3,5-9]|16[2567]|17[0-8]|18[0-9]|19[0-3,5-9])\d{8}$/,
+	message: '请输入正确的手机号',
+	trigger: 'blur'
+}
+
+/**
+ * 整数
+ * @type {{pattern: RegExp, trigger: string, message: string}}
+ */
+export const integer = {
+	pattern: /^(\-|\+)?\d+?$/,
+	message: '请输入正确的数字',
+	trigger: 'blur'
+}
+
+/**
+ * 整数/小数
+ * @type {{pattern: RegExp, trigger: string, message: string}}
+ */
+export const float = {
+	pattern: /^(\-|\+)?\d+(\.\d+)?$/,
+	message: '请输入正确的数字(整数或小数)',
+	trigger: 'blur'
+}
+
+
+/**
+ * 日期
+ * @type {{trigger: string, type: string, message: string}}
+ */
+export const date = {
+	type: 'date',
+	message: '请选择日期',
+	trigger: 'blur'
+}
+
+/**
+ * 邮箱
+ * @type {{trigger: string, type: string, message: string}}
+ */
+export const email = {
+	type: 'email',
+	message: '请输入正确的邮箱地址',
+	trigger: 'blur'
+}
+
+/**
+ * 微信号
+ * @type {{pattern: RegExp, trigger: string, message: string}}
+ */
+export const wecheat = {
+	pattern: /^[a-zA-Z][a-zA-Z0-9_-]{5,19}$/,
+	message: '请输入正确的微信号',
+	trigger: 'blur'
+}
+
+/**
+ * 营业执照
+ * @type {{pattern: RegExp, trigger: string, message: string}}
+ */
+export const businessLicense = {
+	pattern: /(^(?:(?![IOZSV])[\dA-Z]){2}\d{6}(?:(?![IOZSV])[\dA-Z]){10}$)|(^\d{15}$)/,
+	message: '请输入正确的营业执照',
+	trigger: 'blur'
+};
+
+/**
+ * 字符长度
+ * @param max
+ * @param min
+ * @returns {{min: number, max: number, trigger: string, message: string}}
+ */
+export function len(max = 255, min = 0) {
+	return {
+		min,
+		max,
+		message: `长度在 ${min} 到 ${max} 个字符`,
+		trigger: 'blur'
+	}
+}
+
+/**
+ * 数字范围
+ * @param max
+ * @param min
+ * @returns {{validator: validator, trigger: string, message: string}}
+ */
+export function range(min = 0, max = 99999999.99) {
+	const validator = (rule, val, cb) => {
+		val = +val
+		if (!(val >= min && val <= max)) {
+			cb(new Error(rule.message))
+		}
+		cb()
+	}
+	return {
+		validator,
+		message: `数字范围在 ${min} 到 ${max}`,
+		trigger: 'blur'
+	}
+}
+
+/**
+ * 银行卡号
+ * @returns {{validator: validator, trigger: string}}
+ */
+export function bankAccount() {
+	const validator = (rule, value, cb) => {
+		const strBin = '10,18,30,35,37,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,58,60,62,65,68,69,84,87,88,94,95,98,99'
+		if (!value) {
+			cb(new Error('收款账户不能为空'))
+		} else if (!Number.isInteger(+value)) {
+			cb(new Error('银行卡号必须全为数字'))
+		} else if (value.trim().length < 12 || value.trim().length > 19) {
+			cb(new Error('银行卡号长度必须在12到19之间'))
+		} else if (strBin.indexOf(value.substring(0, 2)) === -1) {
+			cb(new Error('银行卡号开头6位不符合规范'))
+		} else {
+			cb();
+		}
+
+	};
+
+	return {
+		validator,
+		trigger: 'blur'
+
+	}
+}

+ 1 - 1
src/utils/tool.js

@@ -230,7 +230,7 @@ const tool = {
    * @returns {string}
    */
   getArImage(imageUrl, path) {
-    return process.env.VUE_APP_CDN_API + `/${path}${imageUrl}`
+    return process.env.VUE_APP_CDN_API + `/${path}/${imageUrl}`
   },
 
   getEmpLv(id) {

+ 214 - 0
src/views/finance/recharge-list.vue

@@ -0,0 +1,214 @@
+<template>
+	<div class="app-container" v-loading="listLoading">
+		<el-table :data="list" border fit highlight-current-row>
+			<el-table-column align="center" :label="$t('finance.createdTime')" prop="CREATED_AT" min-width="100px">
+				<template slot-scope="{row}">
+					<span>{{ row.CREATED_AT | parseTime('{y}-{m}-{d} {h}:{i}:{s}') }}</span>
+				</template>
+			</el-table-column>
+			<el-table-column align="center" :label="$t('finance.rechargeAmount')" prop="AMOUNT"></el-table-column>
+			<el-table-column align="center" :label="$t('finance.rechargeStatus')" prop="STATUS_NAME" min-width="110px">
+				<template slot-scope="{row}">
+					<el-tag :type="row.AUDIT_STATUS | statusFilter">{{row.STATUS_NAME}}</el-tag>
+				</template>
+			</el-table-column>
+			<el-table-column align="center" :label="$t('finance.bankName')" prop="OPEN_BANK_NAME"></el-table-column>
+			<el-table-column align="center" :label="$t('finance.bankAccount')" prop="BANK_NO"></el-table-column>
+			<el-table-column align="center" :label="$t('finance.printVoucher')" min-width="100px">
+				<template slot-scope="{row}">
+					<el-button type="primary" size="mini" v-if="row.AUDIT_STATUS === '0'" @click="handleUpload(row)">{{ $t('finance.uploadVoucher') }}</el-button>
+					<el-button type="success" size="mini" v-if="row.AUDIT_STATUS !== '0'" @click="handleView(row)">{{ $t('finance.viewVoucher') }}</el-button>
+				</template>
+			</el-table-column>
+		</el-table>
+
+		<div class="white-box-footer" style="margin-top: 10px;">
+			<el-button size="small" type="primary" @click="dialog = true">{{ $t('finance.recharge') }}</el-button>
+			<pagination v-show="total > 0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.pageSize" @pagination="getList" />
+		</div>
+
+		<el-dialog :title="$t('finance.recharge')" :visible.sync="dialog" :width="screenWidth" style="margin-top: -70px;">
+			<el-form ref="form" :model="form" :rules="rules" :label-position="labelPosition" v-loading="loading" style="margin-top: -20px; margin-bottom: -30px;">
+				<el-row :gutter="20">
+					<el-col :xs="24" :sm="24" :lg="24">
+						<el-form-item :label="$t('finance.rechargeAmount')" prop="applyAmount" required>
+							<el-input-number v-model.number="form.applyAmount" :min="minAmount" :max="maxAmount" :step="10000" style="width: 100%" clearable></el-input-number>
+						</el-form-item>
+						<el-form-item :label="$t('finance.bankAccount')" prop="bankNo" required>
+							<el-input v-model.trim="form.bankNo" type="text" clearable style="width: 100%"></el-input>
+						</el-form-item>
+						<el-form-item :label="$t('finance.bankName')" prop="openBank" required>
+							<el-select v-model="form.openBank" clearable filterable style="width: 100%">
+								<el-option v-for="(item,key) in bankList" :key="key" :label="item.BANK_NAME" :value="item.BANK_CODE"></el-option>
+							</el-select>
+						</el-form-item>
+						<el-form-item>
+							<el-button type="warning" size="small" @click="onCancel">{{ $t('table.cancel') }}</el-button>
+							<el-button type="primary" size="small" @click="onSubmit">{{ $t('table.confirm') }}</el-button>
+						</el-form-item>
+					</el-col>
+				</el-row>
+			</el-form>
+		</el-dialog>
+
+		<el-dialog :title="$t('finance.viewVoucher')" :visible.sync="viewVoucher" :width="screenWidth" style="margin-top: -70px;">
+			<div>
+				<img :src="voucher" alt="" style="height: 100%; width: 100%;" />
+			</div>
+			<div slot="footer" class="dialog-footer">
+				<el-button size="small" type="primary" @click="uploadAgain(auditId)">{{ $t('finance.uploadVoucher') }}</el-button>
+				<el-button size="small" type="normal"  @click="viewVoucher = false">{{ $t('common.close') }}</el-button>
+			</div>
+		</el-dialog>
+
+		<el-dialog :title="$t('finance.uploadVoucher')" :visible.sync="uploadVoucher" :width="screenWidth" style="margin-top: -70px;">
+			<el-upload action="#" list-type="picture-card" :auto-upload="false">
+				<i slot="default" class="el-icon-plus"></i>
+				<div slot="file" slot-scope="{file}">
+					<img class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
+				</div>
+			</el-upload>
+			<el-dialog :visible.sync="dialogVisible">
+				<img width="100%" :src="dialogImageUrl" alt="">
+			</el-dialog>
+		</el-dialog>
+	</div>
+</template>
+
+<script>
+import {fetchApplyRecharge,fetchBankList, fetchRechargeList} from '@/api/finance'
+import {fetchToken} from "@/api/file"
+import waves from '@/directive/waves'
+import Pagination from '@/components/Pagination'
+import tool from "@/utils/tool"
+import {getScreenWidth} from "@/utils"
+import {integer, range, required} from "@/utils/rules"
+
+export default {
+	name: 'rechargeList',
+	components: { Pagination },
+	directives: { waves },
+	filters: {
+		statusFilter(status) {
+			const statusEnums = {
+				'0': 'info',
+				'1': 'primary',
+				'2': 'success',
+				'3': 'danger',
+			}
+			return statusEnums[status] || 'warning'
+		}
+	},
+	data() {
+		return {
+			tool: tool,
+			list: [],
+			total: 0,
+			listLoading: true,
+			listQuery: {
+				page: 1,
+				pageSize: 5,
+			},
+
+			dialog: false,
+			loading: false,
+			form: {
+				applyAmount: 0,
+				bankNo: '',
+				openBank: '',
+				bankAddress: '',
+			},
+			minAmount: 1,
+			maxAmount: 10000000000,
+			rules: {
+				applyAmount: [required, integer, range(this.minAmount, this.maxAmount)],
+				bankNo: [required],
+				openBank: [required],
+			},
+			bankList: [],
+
+			screenWidth: getScreenWidth() > 600 ? '500px' : getScreenWidth() + 'px',
+			labelPosition: getScreenWidth() > 600 ? 'right' : 'top',
+
+			viewVoucher: false,
+			voucher: '',
+			auditId: null,
+
+			voucherLoading: false,
+			uploadVoucher: false,
+
+		}
+	},
+	created() {
+		this.getList()
+	},
+	mounted() {
+		this.fetchBankList()
+	},
+	methods: {
+		getList() {
+			this.listLoading = true
+			fetchRechargeList(this.listQuery).then(response => {
+				this.list = response.data.list
+				this.total = response.data.totalCount
+
+				setTimeout(() => {
+					this.listLoading = false
+				}, 0.5 * 1000)
+			})
+		},
+		fetchBankList() {
+			fetchBankList().then(response => {
+				this.bankList = response.data.allOpenBank
+			})
+		},
+		onSubmit() {
+			this.$refs['form'].validate((valid) => {
+				if (valid) {
+					this.loading = true
+					fetchApplyRecharge(this.form).then(response => {
+						this.$message({
+							message: response.data,
+							type: 'success',
+							duration: 1.5 * 1000
+						})
+
+						this.$refs['form'].resetFields()
+						this.dialog = false
+						this.loading = false
+
+						this.getList()
+					}).catch((err) => {
+						this.$message({
+							message: err,
+							type: 'error',
+							duration: 3 * 1000
+						})
+
+						this.loading = false
+					})
+				} else {
+					return false;
+				}
+			});
+		},
+		onCancel() {
+			this.dialog = false
+			this.$refs['form'].resetFields()
+		},
+		handleUpload() {
+
+		},
+		handleView(row) {
+			this.voucher = tool.getArImage(row.BANK_PROVE, 'files/')
+			this.auditId = row.ID
+			this.viewVoucher = true
+			console.log('this.voucher', this.voucher)
+		},
+		uploadAgain(id) {
+			// 获取上传token
+			fetchToken()
+		},
+	}
+}
+</script>

+ 48 - 50
src/views/finance/transfer-list.vue

@@ -38,7 +38,7 @@
 					<el-input size="small" v-model="listQuery.userName" clearable :placeholder="$t('finance.receiveMemberCodeHint')" class="filter-item" style="width: 100%; margin: 10px 0;"></el-input>
 				</el-col>
 				<el-col :xs="24" :sm="24" :lg="6" :span="6">
-					<el-input size="small" v-model="listQuery.realName" clearable :placeholder="$t('finance.receiveMemberNameHint')" class="filter-item" auto-complate="false" style="width: 100%; margin: 10px 0;"></el-input>
+					<el-input size="small" v-model="listQuery.realName" clearable :placeholder="$t('finance.receiveMemberNameHint')" class="filter-item" autoComplete="off" style="width: 100%; margin: 10px 0;"></el-input>
 				</el-col>
 				<el-col :xs="24" :sm="24" :lg="12" :span="12">
 					<div class="grid-content bg-purple" align="right" style="width: 100%; margin: 10px 0;">
@@ -83,11 +83,11 @@
 		</el-table>
 
 		<div class="white-box-footer" style="margin-top: 5px;">
-			<el-button size="small" type="primary" @click="dialog = true">{{ $t('finance.applyTransfer') }}</el-button>
+			<el-button size="small" type="primary" @click="handleApplyTransfer">{{ $t('finance.applyTransfer') }}</el-button>
 			<pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.pageSize" @pagination="getList" />
 		</div>
 
-		<el-dialog :title="$t('finance.applyTransfer')" :visible.sync="dialog" :width="screenWidth" v-loading="loading" style="margin-top: -70px;">
+		<el-dialog :title="$t('finance.applyTransfer')" :visible.sync="dialog" :width="screenWidth" v-loading="loading" :close-on-click-modal="false" :destroy-on-close="true" style="margin-top: -70px;">
 			<el-form ref="form" :model="form" :label-position="labelPosition" v-loading="loading" style="margin-top: -20px; margin-bottom: -30px;">
 				<el-row :gutter="5">
 					<el-col :xs="24" :sm="24" :lg="24">
@@ -135,8 +135,8 @@
 							<el-input size="small" v-model.trim="form.remark" type="text"></el-input>
 						</el-form-item>
 						<el-form-item>
-							<el-button type="warning" size="small" @click="transferList">{{ $t('table.cancel') }}</el-button>
-							<el-button type="primary" size="small" @click="submit('form')">{{ $t('table.confirm') }}</el-button>
+							<el-button type="warning" size="small" @click="onCancel">{{ $t('table.cancel') }}</el-button>
+							<el-button type="primary" size="small" @click="onSubmit('form')">{{ $t('table.confirm') }}</el-button>
 						</el-form-item>
 					</el-col>
 				</el-row>
@@ -172,7 +172,7 @@ export default {
 			listLoading: true,
 			listQuery: {
 				page: 1,
-				pageSize: 5,
+				pageSize: 20,
 				inWallet: '',
 				outWallet: '',
 				realName: '',
@@ -240,7 +240,7 @@ export default {
 		},
 		handleFilterClear(){
 			this.listQuery.page = 1
-			this.listQuery.pageSize = 5
+			this.listQuery.pageSize = 20
 			this.listQuery.inWallet = ''
 			this.listQuery.outWallet = ''
 			this.listQuery.realName = ''
@@ -248,6 +248,20 @@ export default {
 			this.listQuery.dateRange = []
 			this.getList()
 		},
+		handleApplyTransfer() {
+			// 获取转账码
+			fetchTransferCode().then(response => {
+				this.form.transferCode = response.data.transferCode
+			}).catch((err) => {
+				this.$message({
+					message: err,
+					type: 'error',
+					duration: 3 * 1000
+				})
+				return false
+			})
+			this.dialog = true
+		},
 		applyTransfer() {
 			this.loading = true
 			fetchChkTransferUser().then(response => {
@@ -270,7 +284,7 @@ export default {
 				this.transferProp = this.userInfo.TRANSFER_PROP
 			})
 		},
-		fetchMember () {
+		fetchMember() {
 			let toUserName = this.form.toUserName.trim()
 			// 不允许向自己转账
 			if (usersInfo.userName() === toUserName) {
@@ -300,61 +314,45 @@ export default {
 			}
 			return true
 		},
-		submit() {
+		onSubmit() {
 			if (this.chkReal() === false) {
 				return false
 			}
 
-			// 获取转账码
-			fetchTransferCode().then(response => {
-				this.form.transferCode = response.data.transferCode
-			}).catch((err) => {
-				this.$message({
-					message: err,
-					type: 'error',
-					duration: 3 * 1000
-				})
-				return false
-			})
-
 			this.$prompt(this.$t('finance.enterPasswordTips'), this.$t('common.hint'), {
 				confirmButtonText: this.$t('common.confirm'),
 				cancelButtonText: this.$t('common.cancel'),
 				inputType: 'password',
 				inputPattern: /\S+/,
 				inputErrorMessage: this.$t('finance.enterPasswordTips'),
-				beforeClose: async (action, instance, done) => {
-					if (action === 'confirm') {
-						instance.confirmButtonLoading = true
-						instance.confirmButtonText = 'executing..'// this.$t('finance.executing')
-						this.form.payPassword = instance.inputValue
-						this.submitButtonStat = true
-						fetchApplyTransfer(this.form).then(() => {
-							this.$refs['form'].resetFields()
-							this.$message({
-								message: this.$t('finance.messageApplyTransfer'),
-								type: 'success',
-								duration: 3 * 1000
-							})
-							this.submitButtonStat = false
-						}).catch((err) => {
-							this.$message({
-								message: err,
-								type: 'error',
-								duration: 3 * 1000
-							})
-							this.submitButtonStat = false
-						})
-					} else {
-						this.submitButtonStat = false
-						done()
-					}
-				}
+			}).then(({ value }) => {
+				this.form.payPassword = value.trim()
+				this.loading = true
+				fetchApplyTransfer(this.form).then(response => {
+					this.$refs['form'].resetFields()
+					this.$message({
+						message: response.data,
+						type: 'success',
+						duration: 3 * 1000
+					})
+					this.submitButtonStat = false
+					this.dialog = false
+					this.handleFilterClear()
+					this.getList()
+				}).catch((err) => {
+					this.$message({
+						message: err,
+						type: 'error',
+						duration: 3 * 1000
+					})
+					this.submitButtonStat = false
+					this.loading = false
+				})
 			})
 		},
-		transferList() {
+		onCancel() {
+			this.dialog = false
 			this.$refs['form'].resetFields()
-			this.$router.push({path: `/finance/transfer-list`})
 		},
 	}
 }