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.

982 lines
30 KiB

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