You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1030 lines
31 KiB

8 months ago
8 months ago
8 months ago
4 weeks ago
8 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
5 months ago
8 months ago
6 months ago
5 months ago
6 months ago
6 months ago
6 months ago
6 months ago
  1. <script setup>
  2. import {onMounted, reactive, ref} from 'vue'
  3. import {ElIcon, ElMessage, ElMessageBox} from 'element-plus'
  4. import {Plus, WarnTriangleFilled} from '@element-plus/icons-vue'
  5. import axios from 'axios'
  6. import API from '@/util/http.js'
  7. import moment from 'moment'
  8. import Cookies from 'js-cookie';
  9. import Decimal from 'decimal.js';
  10. // 国际化
  11. import { useI18n } from 'vue-i18n';
  12. const { t } = useI18n();
  13. // 定义 fixedAdminId
  14. // const fixedAdminId = 1;
  15. // 精网号去空格
  16. const trimJwCode = () => {
  17. if (recharge.value.jwcode) {
  18. recharge.value.jwcode = recharge.value.jwcode.replace(/\s/g, '');
  19. }
  20. }
  21. // 上传图片前的验证函数
  22. const beforeAvatarUpload = (file) => {
  23. const validTypes = ['image/jpeg', 'image/png'];
  24. const isImage = validTypes.includes(file.type);
  25. const isLt1M = file.size / 1024 / 1024 < 1;
  26. if (!isImage) {
  27. ElMessage.error(t('elmessage.onlyUploadJPGPNG'));
  28. return false;
  29. }
  30. if (!isLt1M) {
  31. ElMessage.error(t('elmessage.limitImageSize'));
  32. return false;
  33. }
  34. return true;
  35. };
  36. // 这是添加上传图片的接口
  37. const imageUrl = ref('')
  38. const voucher = ref('')
  39. // const rateName = ref()
  40. const adminData = ref({})
  41. // 获取管理员信息
  42. const getAdminData = async function () {
  43. try {
  44. const result = await API({
  45. url: '/admin/userinfo',
  46. data: {}
  47. })
  48. adminData.value = result
  49. recharge.value.adminId = adminData.value.id
  50. recharge.value.market = adminData.value.market
  51. console.log('请求成功', result)
  52. console.log('用户信息', user.value)
  53. } catch (error) {
  54. console.log('请求失败', error)
  55. }
  56. }
  57. //提交禁止重复点击
  58. const addDisabled = ref(false)
  59. // 这是添加充值信息的表单
  60. const recharge = ref({
  61. jwcode: '', // jwcode 字段
  62. activity: '', // activity 字段
  63. voucher: '',
  64. rechargeWay: '客服充值',
  65. freeGold: "",
  66. money: null,
  67. permanentGold: "",
  68. rateName: null,
  69. rateId: null,
  70. payModel: '', // payModel 字段
  71. payTime: null, // payTime 字段
  72. remark: '', // remark 字段
  73. rechargeRatio: ''
  74. })
  75. // 用来写的 cookie 的 key
  76. const WriteCookies = ref(null)
  77. // 用来写的 cookie 的 value
  78. const WriteCookiesVale = ref(null)
  79. // 用来读的 cookie 的 key
  80. const ReadCookies = ref(null)
  81. // 用来读的 cookie 的 value
  82. const ReadCookiesValue = ref({})
  83. const orderStatus = ref('')
  84. // 这是添加充值信息的接口
  85. const add = async function () {
  86. try {
  87. const formattedRecharge = {...recharge.value}
  88. // 将永久金币数、免费金币数和充值金额数乘以 100
  89. if (formattedRecharge.permanentGold) {
  90. formattedRecharge.permanentGold = Number(formattedRecharge.permanentGold) * 100;
  91. }
  92. if (formattedRecharge.freeGold) {
  93. formattedRecharge.freeGold = Number(formattedRecharge.freeGold) * 100;
  94. }
  95. if (formattedRecharge.money) {
  96. formattedRecharge.money = new Decimal(formattedRecharge.money).mul(100).toNumber();
  97. }
  98. if (formattedRecharge.payTime) {
  99. // 使用 moment.js 格式化 payTime
  100. formattedRecharge.payTime = moment(formattedRecharge.payTime).format('YYYY-MM-DD HH:mm:ss')
  101. }
  102. console.log('开始添加充值信息', recharge.value)
  103. //存一下 用户的jwcode
  104. // 发送POST请求
  105. addDisabled.value = true
  106. const result = await API({
  107. url: '/recharge/add',
  108. data: formattedRecharge
  109. })
  110. addDisabled.value = false
  111. if(result.code == 200){
  112. // 拼接 jwcode:permanentGold:freeGold
  113. WriteCookies.value = `coinRecharge-${recharge.value.jwcode}-${recharge.value.permanentGold}-${recharge.value.freeGold}`
  114. //value 为充值时间
  115. WriteCookiesVale.value = JSON.stringify({
  116. payTime: moment(result.data.createTime).format("YYYY-MM-DD HH:mm:ss"),
  117. orderCode: result.data.orderCoder,
  118. });
  119. // 设置cookies,用户jwcode为key,value也是jwcode,过期时间为1天
  120. Cookies.set(WriteCookies.value, WriteCookiesVale.value, {expires: 1, path: '/'});
  121. }
  122. if (result.code === 0) {
  123. ElMessage.error(result.msg)
  124. return
  125. }
  126. // 将响应结果存储到响应式数据中
  127. console.log('请求成功', result)
  128. // 显示成功消息
  129. ElMessage.success(t('elmessage.addSuccess'))
  130. // 重置表单
  131. deleteRecharge()
  132. user.value = {}
  133. } catch (error) {
  134. console.log('请求失败', error)
  135. // 在这里可以处理错误逻辑,比如显示错误提示等
  136. }
  137. }
  138. // 二次校验充值对话框显示状态
  139. const RechargeDialogVisible = ref(false);
  140. // 第一次弹窗
  141. const FirstRechargeDialogVisible = ref(false);
  142. // 关闭第一次对话框
  143. const FirstRechargeDialogVisiblehandleClose = () => {
  144. FirstRechargeDialogVisible.value = false;
  145. // 重置表单数据
  146. deleteRecharge()
  147. user.value = {}
  148. };
  149. // 关闭第二次对话框
  150. const RechargeDialogVisiblehandleClose = () => {
  151. RechargeDialogVisible.value = false;
  152. // 重置表单数据
  153. deleteRecharge()
  154. user.value = {}
  155. };
  156. // 确认使用cookie继续充值
  157. const RechargeDialogVisibleContinue = () => {
  158. RechargeDialogVisible.value = false;
  159. add();
  160. };
  161. const RechargeDialogVisibleCancel = () => {
  162. RechargeDialogVisible.value = false
  163. deleteRecharge()
  164. user.value = {}
  165. };
  166. // 第一次实际执行充值操作
  167. // const proceedWithRecharge = () => {
  168. // FirstRechargeDialogVisible.value = false
  169. // add()
  170. // };
  171. const FistRechargeDialogVisibleContinue = () => {
  172. FirstRechargeDialogVisible.value = false
  173. add()
  174. };
  175. // 第一次取消
  176. const FirstRechargeDialogVisibleCancel = () => {
  177. FirstRechargeDialogVisible.value = false
  178. deleteRecharge()
  179. user.value = {}
  180. };
  181. const historyOrder = ref({})
  182. // 查询订单号对应的状态
  183. const selectByOrderCode = async function (data) {
  184. try {
  185. const result = await API({
  186. url: '/recharge/selectByOrderCode',
  187. data: data,
  188. headers: {
  189. 'Content-Type': 'text/plain;charset=utf-8'
  190. },
  191. })
  192. if(result.code == 200){
  193. historyOrder.value = result.data
  194. }
  195. } catch (error) {
  196. console.log('请求失败', error)
  197. // 在这里可以处理错误逻辑,比如显示错误提示等
  198. }
  199. }
  200. // 添加充值信息前的按钮点击事件,进行表单验证和用户确认操作
  201. const addBefore = () => {
  202. // 为未输入的金币字段设置默认值
  203. if (!recharge.value.permanentGold) {
  204. recharge.value.permanentGold = '0';
  205. }
  206. if (!recharge.value.freeGold) {
  207. recharge.value.freeGold = '0';
  208. }
  209. // 表单验证
  210. Ref.value.validate(async (valid) => {
  211. if (!valid) {
  212. ElMessage({
  213. type: 'error',
  214. message: t('elmessage.checkInputContent')
  215. });
  216. return;
  217. }
  218. // 验证金币不能同时为0
  219. if (Number(recharge.value.permanentGold) === 0 && Number(recharge.value.freeGold) === 0) {
  220. ElMessage({
  221. type: 'error',
  222. message: t('elmessage.permanentAndFreeNoZero')
  223. });
  224. return;
  225. }
  226. // 验证币种选择
  227. if (!recharge.value.rateName) {
  228. ElMessage({
  229. type: 'error',
  230. message: t('elmessage.checkRate')
  231. });
  232. return;
  233. }
  234. // 验证充值金额
  235. if (!recharge.value.money) {
  236. ElMessage({
  237. type: 'error',
  238. message: t('elmessage.checkMoney')
  239. });
  240. return;
  241. }
  242. // 设置对应的rateId,传负载用的
  243. const selectedRate = rateName.value.find(item => item.value === recharge.value.rateName);
  244. if (selectedRate) {
  245. recharge.value.rateId = selectedRate.value;
  246. recharge.value.rateName = selectedRate.label; // 将rateName设置为货币名称
  247. }
  248. // 检查是否有用户信息
  249. if (!user.value.jwcode) {
  250. ElMessage.warning(t('elmessage.checkUserInfo'))
  251. return
  252. }
  253. // 检查cookie
  254. // 拼接 jwcode:permanentGold:freeGold
  255. ReadCookies.value = `coinRecharge-${recharge.value.jwcode}-${recharge.value.permanentGold}-${recharge.value.freeGold}`
  256. console.log('ReadCookies',ReadCookies.value);
  257. // 获取cookie
  258. const cookieValue = Cookies.get(ReadCookies.value);
  259. if (cookieValue) {
  260. // 解析为对象
  261. const rechargeInfo = JSON.parse(cookieValue);
  262. console.log('充值时间:', rechargeInfo.payTime);
  263. console.log('订单号:', rechargeInfo.orderCode);
  264. ReadCookiesValue.value = {
  265. ...rechargeInfo,
  266. }
  267. }else{
  268. ReadCookiesValue.value = {}
  269. }
  270. if (Object.keys(ReadCookiesValue.value).length > 0) {
  271. await selectByOrderCode(ReadCookiesValue.value.orderCode)
  272. if(historyOrder.value.type == 0 ){
  273. if(historyOrder.value.auditStatus == 0){
  274. orderStatus.value = t('recharge.waitAudit')
  275. }else if(historyOrder.value.auditStatus == 1){
  276. if(historyOrder.value.isRefund == 1){
  277. orderStatus.value = t('recharge.refunded')
  278. }else{
  279. orderStatus.value = t('recharge.passed')
  280. }
  281. }else if(historyOrder.value.auditStatus == 2){
  282. orderStatus.value = t('recharge.rejected')
  283. }
  284. }
  285. RechargeDialogVisible.value = true;
  286. } else {
  287. FirstRechargeDialogVisible.value = true;
  288. }
  289. });
  290. };
  291. // 表单验证
  292. // 开始时间改变时,重新验证结束时间
  293. const Ref = ref(null)
  294. const rules = reactive({
  295. jwcode: [{
  296. required: true, validator: (rule, value, callback) => {
  297. if (!value) {
  298. callback(new Error(t('elmessage.noEmptyJwcode')));
  299. return;
  300. }
  301. if (/[^0-9]/.test(value)) {
  302. callback(new Error(t('elmessage.limitDigitJwcode')));
  303. return;
  304. }
  305. callback();
  306. }, trigger: 'blur'
  307. }],
  308. activity: [{required: true, message: t('elmessage.checkActivity'), trigger: 'blur'}],
  309. permanentGold: [
  310. {required: true, message: t('elmessage.checkPermanentGold'), trigger: 'change'},
  311. {
  312. validator: (rule, value, callback) => {
  313. if (!value) {
  314. value = '0'
  315. }
  316. // 检查是否包含特殊符号
  317. if (/[^0-9.]/.test(value)) {
  318. callback(new Error(t('elmessage.limitNoSpecialChar')));
  319. return;
  320. }
  321. // 检查整数位数
  322. const integerPart = value.split('.')[0];
  323. if (integerPart.length > 6) {
  324. callback(new Error(t('elmessage.limitSix')));
  325. return;
  326. }
  327. // 检查小数位数
  328. if (value.includes('.')) {
  329. const decimalPart = value.split('.')[1];
  330. if (decimalPart.length > 2) {
  331. callback(new Error(t('elmessage.limitTwoDecimal')));
  332. return;
  333. }
  334. }
  335. const numValue = Number(value);
  336. if (isNaN(numValue)) {
  337. callback(new Error(t('elmessage.checkNumber')));
  338. } else if (numValue < 0) {
  339. callback(new Error(t('elmessage.limitZero')));
  340. } else {
  341. callback();
  342. }
  343. },
  344. trigger: 'blur'
  345. }
  346. ],
  347. freeGold: [
  348. {required: true, message: t('elmessage.checkFreeGold'), trigger: 'change'},
  349. {
  350. validator: (rule, value, callback) => {
  351. if (!value) {
  352. value = '0'
  353. }
  354. // 检查是否包含特殊符号
  355. if (/[^0-9.]/.test(value)) {
  356. callback(new Error(t('elmessage.limitNoSpecialChar')));
  357. return;
  358. }
  359. // 检查整数位数
  360. const integerPart = value.split('.')[0];
  361. if (integerPart.length > 6) {
  362. callback(new Error(t('elmessage.limitSix')));
  363. return;
  364. }
  365. // 检查小数位数
  366. if (value.includes('.')) {
  367. const decimalPart = value.split('.')[1];
  368. if (decimalPart.length > 2) {
  369. callback(new Error(t('elmessage.limitTwoDecimal')));
  370. return;
  371. }
  372. }
  373. const numValue = Number(value);
  374. if (isNaN(numValue)) {
  375. callback(new Error(t('elmessage.checkNumber')));
  376. } else if (numValue < 0) {
  377. callback(new Error(t('elmessage.limitZero')));
  378. } else {
  379. callback();
  380. }
  381. },
  382. trigger: 'blur'
  383. }
  384. ],
  385. rateName: [{
  386. required: true,
  387. message: t('elmessage.checkRate'),
  388. trigger: 'blur'
  389. }],
  390. money: [
  391. {required: true, message: t('elmessage.checkMoney'), trigger: 'blur'},
  392. {
  393. validator: (rule, value, callback) => {
  394. // 检查是否包含特殊符号
  395. if (/[^0-9.]/.test(value)) {
  396. callback(new Error(t('elmessage.limitNoSpecialChar')));
  397. return;
  398. }
  399. // 检查整数位数
  400. const integerPart = value.split('.')[0];
  401. if (integerPart.length > 6) {
  402. callback(new Error(t('elmessage.limitSix')));
  403. return;
  404. }
  405. // 检查小数位数
  406. if (value.includes('.')) {
  407. const decimalPart = value.split('.')[1];
  408. if (decimalPart.length > 2) {
  409. callback(new Error(t('elmessage.limitTwoDecimal')));
  410. return;
  411. }
  412. }
  413. const numValue = Number(value);
  414. if (isNaN(numValue)) {
  415. callback(new Error(t('elmessage.checkNumber')));
  416. } else if (numValue < 0) {
  417. callback(new Error(t('elmessage.limitZero')));
  418. } else {
  419. callback();
  420. }
  421. },
  422. trigger: 'blur'
  423. }
  424. ],
  425. payModel: [{required: true, message: t('elmessage.checkPayModel'), trigger: 'blur'}],
  426. payTime: [{required: true, message: t('elmessage.checkPayTime'), trigger: 'blur'}]
  427. });
  428. // 查找客户信息的方法
  429. const user = ref({})
  430. const getUser = async function (jwcode) {
  431. trimJwCode();
  432. // 验证精网号
  433. if (!jwcode) {
  434. ElMessage.warning(t('elmessage.noEmptyJwcode'));
  435. return;
  436. }
  437. // 验证精网号是否为数字
  438. if (!/^\d{1,9}$/.test(jwcode)) {
  439. ElMessage.warning(t('elmessage.limitJwcodeNine'));
  440. deleteRecharge()
  441. return;
  442. }
  443. try {
  444. const result = await API({
  445. url: '/user/selectUser',
  446. data: {
  447. jwcode: recharge.value.jwcode
  448. }
  449. })
  450. const { code, data } = result
  451. const region = data && data.market
  452. if (!data || Object.keys(data).length === 0) {
  453. user.value = {}
  454. ElMessage.error(t('elmessage.jwcodeError'))
  455. return
  456. }
  457. user.value = data
  458. if (code === 0 && region) {
  459. ElMessage.info({
  460. message: t('elmessage.userRegionHint', { region }),
  461. customClass: 'custom-blue-message'
  462. })
  463. return
  464. }
  465. ElMessage.success(t('elmessage.searchSuccess'))
  466. } catch (error) {
  467. console.log("请求失败", error);
  468. ElMessage.error(t('elmessage.jwcodeError'));
  469. }
  470. }
  471. // 这是查询活动的接口,一期没有调用这个接口
  472. const activity = ref([])
  473. // const getActivity = async function () {
  474. // try {
  475. // // 发送POST请求
  476. // const result = await API({
  477. // url: '/general/activity',
  478. // data: {
  479. // }
  480. // })
  481. // // 将响应结果存储到响应式数据中
  482. // console.log('请求成功', result)
  483. // // 存储表格数据
  484. // activity.value = result.data
  485. // console.log('活动信息', activity.value)
  486. // } catch (error) {
  487. // console.log('activity请求失败', error)
  488. // // 在这里可以处理错误逻辑,比如显示错误提示等
  489. // }
  490. // }
  491. //货币条目
  492. const rateName = ref([])
  493. const fetchRateData = async () => {
  494. try {
  495. const result = await API({
  496. url: '/general/getRate',
  497. data: {}
  498. });
  499. console.log('response', result);
  500. if (result.code === 200) {
  501. rateName.value = result.data.map(item => ({
  502. value: item.id,
  503. label: item.rateName,
  504. }));
  505. }
  506. console.log('货币信息', rateName.value);
  507. } catch (error) {
  508. console.error('获取货币信息失败:', error);
  509. }
  510. };
  511. // 修改上传处理
  512. const customUpload = async (options) => {
  513. try {
  514. const formData = new FormData();
  515. formData.append('file', options.file);
  516. const response = await axios.post(import.meta.env.VITE_UPLOAD_URL, formData, {
  517. headers: {
  518. 'Content-Type': 'multipart/form-data',
  519. 'Authorization': `Bearer ${localStorage.getItem('token')}`
  520. }
  521. });
  522. if (response.data.code === 200 && response.data.data) {
  523. // 传递原始文件对象和响应数据
  524. handleAvatarSuccess(response.data, options.file);
  525. ElMessage.success(t('elmessage.uploadSuccess'));
  526. } else {
  527. ElMessage.error(response.data.msg || t('elmessage.uploadFailed'));
  528. }
  529. } catch (error) {
  530. console.error('上传错误:', error);
  531. ElMessage.error(`${t('elmessage.uploadFailed')}: ${error.response?.data?.message || error.message}`);
  532. }
  533. };
  534. // 获取环境变量
  535. // const uploadUrl = import.meta.env.VITE_UPLOAD_URL;
  536. // 上传图片成功的回调函数
  537. const handleAvatarSuccess = (response, file) => {
  538. // 直接使用 file 对象创建 Object URL
  539. imageUrl.value = URL.createObjectURL(file);
  540. // 使用服务器返回的文件路径(根据实际响应结构调整)
  541. if (response && response.filePath) {
  542. recharge.value.voucher = response.filePath;
  543. } else if (response && response.url) {
  544. recharge.value.voucher = response.url;
  545. } else if (response && response.data) {
  546. // 假设响应结构为 { code: 200, data: { filePath: ... } }
  547. recharge.value.voucher = response.data.filePath || response.data.url;
  548. } else {
  549. // 后备方案:使用环境变量中的上传URL
  550. recharge.value.voucher = import.meta.env.VITE_UPLOAD_URL;
  551. }
  552. }
  553. //支付方式条目
  554. const payModel = [
  555. {
  556. value: '银行转账',
  557. label: t('audit.payMethods.bankTransfer')
  558. },
  559. {
  560. value: '现金',
  561. label: t('audit.payMethods.cash')
  562. },
  563. {
  564. value: '支票',
  565. label: t('audit.payMethods.check')
  566. },
  567. {
  568. value: '刷卡',
  569. label: t('audit.payMethods.card')
  570. },
  571. {
  572. value: 'Grabpay',
  573. label: t('audit.payMethods.grabpay')
  574. },
  575. {
  576. value: 'Nets',
  577. label: t('audit.payMethods.nets')
  578. },
  579. {
  580. value: 'PayPal',
  581. label: t('audit.payMethods.paypal')
  582. },
  583. {
  584. value: 'Stripe',
  585. label: t('audit.payMethods.stripe')
  586. },
  587. {
  588. value: 'Ipay88',
  589. label: t('audit.payMethods.ipay88')
  590. },
  591. {
  592. value: 'PaymentAsia',
  593. label: t('audit.payMethods.paymentAsia')
  594. },
  595. {
  596. value: '其他',
  597. label: t('audit.payMethods.other')
  598. }
  599. ]
  600. // // }
  601. // function handleActivityChange(value) {
  602. // // 在这里执行逻辑,例如获取选中的值
  603. // console.log('选中的值:', value)
  604. // // getActivityById(value)
  605. // console.log('看看', recharge.value)
  606. // }
  607. //这是重置重置表单的方法
  608. const deleteRecharge = function () {
  609. Ref.value.resetFields();
  610. recharge.value = {
  611. adminId: adminData.value.id,
  612. //adminId: fixedAdminId,
  613. market: adminData.value.market,
  614. voucher: '',
  615. rechargeWay: '客服充值',
  616. freeGold: '',
  617. money: null,
  618. permanentGold: '',
  619. rateId: null
  620. }
  621. imageUrl.value = ''
  622. recharge.value.rateName = ''
  623. }
  624. onMounted(async function () {
  625. await getAdminData()
  626. await fetchRateData()
  627. // await getCurrency()
  628. // await getActivity()// 现在的活动就是文字输入框,不需要请求接口,具体等后续需求
  629. })
  630. onMounted(() => {
  631. console.log('上传URL:', import.meta.env.VITE_UPLOAD_URL);
  632. });
  633. </script>
  634. <template>
  635. <div>
  636. <div class="userAndForm">
  637. <div class="left">
  638. <el-form :model="recharge" ref="Ref" :rules="rules" label-width="auto" label-position="right"
  639. style="min-width: 500px" class="add-form">
  640. <el-form-item prop="jwcode" :label="$t('common_add.jwcode')">
  641. <el-input v-model="recharge.jwcode" style="width: 220px" @keyup.enter="getUser(recharge.jwcode)"/>
  642. <el-button type="primary" @click="getUser(recharge.jwcode)" style="margin-left: 20px">{{ $t('common.search') }}</el-button>
  643. </el-form-item>
  644. <el-form-item prop="activity" :label="$t('common_add.activity')">
  645. <el-input v-model="recharge.activity" :placeholder="$t('common_add.activityPlaceholder')" style="width: 300px"/>
  646. </el-form-item>
  647. <el-form-item prop="permanentGold" :label="$t('common_add.permanentGold')">
  648. <el-input v-model="recharge.permanentGold" placeholder="0" style="width: 100px"/>
  649. <p>&nbsp;</p>
  650. </el-form-item>
  651. <el-form-item prop="freeGold" :label="$t('common_add.freeGold')">
  652. <el-input v-model="recharge.freeGold" placeholder="0" style="width: 100px"/>
  653. <p>&nbsp;</p>
  654. </el-form-item>
  655. <el-form-item :label="$t('common_add.rechargeAmount')" required style="margin-bottom: 25px;">
  656. <el-form-item prop="rateName" style="display: inline-block; margin-left:0;">
  657. <el-select v-model="recharge.rateName" :placeholder="$t('common_add.currencyName')" style="width: 100px">
  658. <el-option v-for="item in rateName" :key="item.value" :label="item.label" :value="item.value"/>
  659. </el-select>
  660. </el-form-item>
  661. <el-form-item prop="money" style="display: inline-block; margin-left:10px; vertical-align: top;">
  662. <el-input v-model="recharge.money" style="width: 190px"/>
  663. </el-form-item>
  664. </el-form-item>
  665. <el-form-item prop="payModel" :label="$t('common_add.payModel')">
  666. <el-select v-model="recharge.payModel" :placeholder="$t('common_add.payModelPlaceholder')" style="width: 300px">
  667. <el-option v-for="item in payModel" :key="item.value" :label="item.label" :value="item.value"/>
  668. </el-select>
  669. </el-form-item>
  670. <el-form-item prop="payTime" :label="$t('common_add.paymentTime')">
  671. <!-- 修改 type 属性为 datetime 以支持时分秒选择 -->
  672. <el-date-picker v-model="recharge.payTime" type="datetime" style="width: 300px"/>
  673. </el-form-item>
  674. <el-form-item prop="voucher" :label="$t('common_add.paymentVoucher')" style="margin-bottom: 5px">
  675. <el-upload :http-request="customUpload" class="avatar-uploader" :show-file-list="false"
  676. :before-upload="beforeAvatarUpload" style="width: 100px; height: 115px">
  677. <img v-if="imageUrl" :src="imageUrl" class="avatar" style="width: 100px; height: 115px"/>
  678. <el-icon v-else class="avatar-uploader-icon" style="width: 100px; height: 100px">
  679. <Plus/>
  680. </el-icon>
  681. </el-upload>
  682. <p style="margin-left: 10px; color: rgb(177, 176, 176)">
  683. {{ $t('common_add.paymentVoucherPlaceholder') }}
  684. </p>
  685. </el-form-item>
  686. <el-form-item prop="remark" :label="$t('common_add.remark')">
  687. <el-input v-model="recharge.remark" style="width: 300px" :rows="4" maxlength="100" show-word-limit
  688. type="textarea"/>
  689. </el-form-item>
  690. <el-button @click="deleteRecharge" style="margin-left: 220px;margin-top:20px" type="success">{{ $t('common.reset') }}</el-button>
  691. <el-button type="primary" style="margin-top:20px" :disabled="addDisabled" @click="addBefore"> {{ $t('common.confirm') }}</el-button>
  692. </el-form>
  693. </div>
  694. <div class="right">
  695. <!-- 客户信息栏 -->
  696. <el-card v-if="user.jwcode" style="width: 800px; float: right" class="customer-info">
  697. <el-form :model="user" label-width="auto" style="max-width: 1000px" label-position="left">
  698. <el-text size="large" style="margin-left: 20px">{{ $t('common_add_user.customerInfo') }}</el-text>
  699. <!-- 第一行姓名 + 历史金币 -->
  700. <el-row style="margin-top: 20px">
  701. <el-col :span="9">
  702. <el-form-item :label="$t('common_add_user.name')">
  703. <p>{{ user.name }}</p>
  704. </el-form-item>
  705. </el-col>
  706. <el-col :span="14">
  707. <el-form-item :label="$t('common_add_user.currentGoldCoinTotal')" style="width: 500px">
  708. <span style="color: #2fa1ff; margin-right: 5px" v-if="user.nowSumGold !== undefined">{{
  709. user.nowSumGold
  710. }}</span>
  711. </el-form-item>
  712. <!-- 金币详情独立显示 -->
  713. <el-form-item style="margin-top: -23px"> <!-- 负边距减少间距 -->
  714. <span style="color: #b1b1b1; margin-left: 0px" v-if="user.nowPermanentGold !== undefined">({{ $t('common_add_user.permanentGold') }}:{{
  715. user.nowPermanentGold
  716. }};
  717. {{ $t('common_add_user.freeGold') }}:{{ user.nowFreeGold }};
  718. {{ $t('common_add_user.taskGold') }}:{{ user.nowTaskGold }})</span>
  719. </el-form-item>
  720. </el-col>
  721. </el-row>
  722. <!-- 第二行精网号 + 当前金币独立行 -->
  723. <el-row>
  724. <el-col :span="9">
  725. <el-form-item :label="$t('common_add_user.jwcode')">
  726. <p>{{ user.jwcode }}</p>
  727. </el-form-item>
  728. </el-col>
  729. <el-col :span="14">
  730. <el-form-item :label="$t('common_add_user.consumptionTimes')">
  731. <p style="color: #2fa1ff">{{ user.consumeNum }} </p>
  732. </el-form-item>
  733. <el-form-item style="margin-top: -23px"> <!-- 负边距减少间距 -->
  734. <p style="font-size: small; color: #b1b1b1">({{ $t('common_add_user.onlyStatisticsDataAfter20250101') }})</p>
  735. </el-form-item>
  736. </el-col>
  737. </el-row>
  738. <!-- 第三行首次充值日期 + 充值次数 -->
  739. <!-- <el-row >
  740. <el-col :span="9">
  741. <el-form-item label="首次充值日期">
  742. <p v-if="user.firstRecharge">
  743. {{ moment(user.firstRecharge).format('YYYY-MM-DD HH:mm:ss') }}
  744. </p>
  745. </el-form-item>
  746. </el-col>
  747. </el-row> -->
  748. <!-- 第四行消费次数 + 所属门店 -->
  749. <el-row>
  750. <el-col :span="9">
  751. <el-form-item :label="$t('common_add_user.store')">
  752. <p>{{ user.market }}</p>
  753. </el-form-item>
  754. </el-col>
  755. </el-row>
  756. </el-form>
  757. </el-card>
  758. </div>
  759. </div>
  760. <el-dialog v-model="FirstRechargeDialogVisible" :title="$t('common_add.operationConfirm')"
  761. :before-close="FirstRechargeDialogVisiblehandleClose"
  762. :close-on-click-modal="false" width="400px">
  763. <!-- 内容整体居中且收窄 -->
  764. <div class="confirm-body">
  765. <!-- 用户信息 -->
  766. <div>
  767. <div class="field-label">{{ $t('common_add.userInfo') }}</div>
  768. <el-input :model-value="user.jwcode + (user.name ? '' + user.name + '' : '')" disabled/>
  769. </div>
  770. <!-- 活动名称 -->
  771. <div class="field">
  772. <div class="field-label">{{ $t('common_add.activity') }}</div>
  773. <el-input v-model="recharge.activity" disabled/>
  774. </div>
  775. <!-- 金币信息同一行左右排列 -->
  776. <el-row :gutter="20" class="coins-row">
  777. <el-col :span="12">
  778. <div class="field">
  779. <div class="field-label">{{ $t('common_add.permanentGold') }}</div>
  780. <el-input v-model="recharge.permanentGold" disabled/>
  781. </div>
  782. </el-col>
  783. <el-col :span="12">
  784. <div class="field">
  785. <div class="field-label">{{ $t('common_add.freeGold') }}</div>
  786. <el-input v-model="recharge.freeGold" disabled/>
  787. </div>
  788. </el-col>
  789. </el-row>
  790. <div class="field">
  791. <div class="field-label">{{ $t('common_add.remark') }}</div>
  792. <el-input v-model="recharge.remark" disabled/>
  793. </div>
  794. </div>
  795. <!-- 底部按钮居中 -->
  796. <template #footer>
  797. <div class="dialog-footer-center">
  798. <el-button @click="FirstRechargeDialogVisibleCancel">{{ $t('common.cancel') }}</el-button>
  799. <el-button type="primary" @click="FistRechargeDialogVisibleContinue">{{ $t('common.confirmRecharge') }}</el-button>
  800. </div>
  801. </template>
  802. </el-dialog>
  803. <el-dialog v-model="RechargeDialogVisible" :title="$t('common_add.operationConfirm')" :before-close="RechargeDialogVisiblehandleClose"
  804. :close-on-click-modal="false" width="480px">
  805. <!-- 内容整体居中且收窄 -->
  806. <div class="confirm-body">
  807. <!-- 用户信息 -->
  808. <div>
  809. <div class="field-label">{{ $t('common_add.userInfo') }}</div>
  810. <el-input :model-value="user.jwcode + (user.name ? '' + user.name + '' : '')" disabled/>
  811. </div>
  812. <!-- 活动名称 -->
  813. <div class="field">
  814. <div class="field-label">{{ $t('common_add.activity') }}</div>
  815. <el-input v-model="recharge.activity" disabled/>
  816. </div>
  817. <!-- 金币信息同一行左右排列 -->
  818. <el-row :gutter="20" class="coins-row">
  819. <el-col :span="12">
  820. <div class="field">
  821. <div class="field-label">{{ $t('common_add.permanentGold') }}</div>
  822. <el-input v-model="recharge.permanentGold" disabled/>
  823. </div>
  824. </el-col>
  825. <el-col :span="12">
  826. <div class="field">
  827. <div class="field-label">{{ $t('common_add.freeGold') }}</div>
  828. <el-input v-model="recharge.freeGold" disabled/>
  829. </div>
  830. </el-col>
  831. </el-row>
  832. <!-- 风险提示 -->
  833. <div style="display: flex; align-items: center; margin-top: 20px;">
  834. <el-icon :size="24" color="#FFD700">
  835. <WarnTriangleFilled/>
  836. </el-icon>
  837. <p>{{ $t('common_add.prompt') }}</p>
  838. </div>
  839. <!-- 记录 + 虚线分隔 -->
  840. <div>
  841. <el-divider border-style="dashed"/>
  842. <p>{{ $t('common_add.similarRechargeRecords') }}</p>
  843. · {{ moment(ReadCookiesValue.payTime).format('YYYY-MM-DD HH:mm:ss') }} {{ $t('common_add.rechargePermanentGold') }}: {{ recharge.permanentGold }}
  844. {{ $t('common_add.freeGold') }}: {{ recharge.freeGold }} {{ $t('common_add.orderStatus')}}: {{ orderStatus }}({{ $t('common_add.operator') }}{{ adminData.adminName }})
  845. </div>
  846. <div style="margin-top: 10px">
  847. <p>{{ $t('common_add.continueOperation') }}</p>
  848. </div>
  849. </div>
  850. <!-- 底部按钮居中 -->
  851. <template #footer>
  852. <div class="dialog-footer-center">
  853. <el-button @click="RechargeDialogVisibleCancel">{{ $t('common.cancel') }}</el-button>
  854. <el-button type="primary" @click="RechargeDialogVisibleContinue">{{ $t('common.confirmRecharge') }}</el-button>
  855. </div>
  856. </template>
  857. </el-dialog>
  858. </div>
  859. </template>
  860. <style scoped lang="scss">
  861. .userAndForm {
  862. width: 1150px;
  863. height: 100%;
  864. display: flex;
  865. align-items: center;
  866. .left {
  867. width: 35%;
  868. display: flex;
  869. .add-form {
  870. width: 100%;
  871. margin-top: 50px;
  872. }
  873. }
  874. .right {
  875. flex: 1;
  876. margin-left: 100px;
  877. display: flex;
  878. .customer-info{
  879. width: 90%;
  880. display: flex;
  881. margin-left: 20px;
  882. justify-content: center;
  883. align-items: center;
  884. padding: 0 10px;
  885. }
  886. }
  887. }
  888. p {
  889. margin: 0px;
  890. }
  891. // .batch-btn {
  892. // margin-top: 20px;
  893. // margin-left: auto;
  894. // }
  895. .field-label {
  896. font-size: 14px;
  897. color: #606266;
  898. margin-bottom: 6px;
  899. }
  900. /* 金币行紧凑 */
  901. .coins-row .field {
  902. margin-bottom: 0;
  903. }
  904. /* 底部按钮居中 */
  905. .dialog-footer-center {
  906. display: flex;
  907. justify-content: center;
  908. gap: 12px;
  909. }
  910. :deep(.avatar-uploader .avatar) {
  911. width: 50px;
  912. height: 50px;
  913. display: block;
  914. }
  915. :deep(.avatar-uploader .el-upload) {
  916. border: 1px dashed var(--el-border-color);
  917. border-radius: 6px;
  918. cursor: pointer;
  919. position: relative;
  920. overflow: hidden;
  921. transition: var(--el-transition-duration-fast);
  922. }
  923. :deep(.avatar-uploader .el-upload:hover) {
  924. border-color: var(--el-color-primary);
  925. }
  926. :deep(.el-icon.avatar-uploader-icon) {
  927. font-size: 28px;
  928. color: #8c939d;
  929. width: 50px;
  930. height: 50px;
  931. text-align: center;
  932. }
  933. </style>