form.vue 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. <template>
  2. <el-dialog
  3. :close-on-click-modal="false"
  4. :title="form.userId ? (readonly ? '查看详情' : $t('common.editBtn')) : $t('common.addBtn')"
  5. draggable
  6. v-model="visible"
  7. width="920px"
  8. >
  9. <el-alert v-if="!form.userId" :title="$t('merchantUser.defaultPasswordTip')" type="warning" :closable="false" style="margin-bottom: 15px" />
  10. <el-form :model="form" :rules="dataRules" label-width="140px" ref="dataFormRef" v-loading="loading">
  11. <!-- 基本信息 -->
  12. <el-divider content-position="left">{{ $t('merchantUser.basicInfo') }}</el-divider>
  13. <el-row :gutter="24">
  14. <el-col :span="12" class="mb20">
  15. <el-form-item :label="$t('merchantUser.merchantName')" prop="merchantName">
  16. <el-input :placeholder="$t('merchantUser.inputMerchantNameTip')" v-model="form.merchantName" :disabled="readonly || !!form.userId" />
  17. </el-form-item>
  18. </el-col>
  19. <el-col :span="12" class="mb20">
  20. <el-form-item :label="$t('merchantUser.username')" prop="username">
  21. <el-input :placeholder="$t('merchantUser.inputUsernameTip')" v-model="form.username" :disabled="readonly || !!form.userId" />
  22. </el-form-item>
  23. </el-col>
  24. <el-col :span="12" class="mb20">
  25. <el-form-item :label="$t('merchantUser.realname')" prop="realname">
  26. <el-input :placeholder="$t('merchantUser.inputRealnameTip')" v-model="form.realname" :disabled="readonly" />
  27. </el-form-item>
  28. </el-col>
  29. <el-col :span="12" class="mb20">
  30. <el-form-item :label="$t('merchantUser.phone')" prop="phone">
  31. <el-input :placeholder="$t('merchantUser.inputPhoneTip')" v-model="form.phone" :disabled="readonly || !!form.userId" />
  32. </el-form-item>
  33. </el-col>
  34. <el-col :span="12" class="mb20">
  35. <el-form-item :label="$t('merchantUser.email')" prop="email">
  36. <el-input :placeholder="$t('merchantUser.inputEmailTip')" v-model="form.email" :disabled="readonly || !!form.userId" />
  37. </el-form-item>
  38. </el-col>
  39. <el-col :span="12" class="mb20">
  40. <el-form-item :label="$t('merchantUser.idcard')" prop="idcard">
  41. <el-input :placeholder="$t('merchantUser.inputIdcardTip')" v-model="form.idcard" :disabled="readonly" />
  42. </el-form-item>
  43. </el-col>
  44. <el-col :span="12" class="mb20">
  45. <el-form-item :label="$t('merchantUser.contactAddress')" prop="contactAddress">
  46. <el-input :placeholder="$t('merchantUser.inputContactAddressTip')" v-model="form.contactAddress" :disabled="readonly" />
  47. </el-form-item>
  48. </el-col>
  49. <el-col :span="12" class="mb20">
  50. <el-form-item :label="$t('merchantUser.agentId')" prop="agentId">
  51. <el-select v-model="form.agentId" :placeholder="$t('merchantUser.selectAgentTip')" :disabled="readonly" style="width: 100%">
  52. <el-option v-for="item in agentList" :key="item.userId" :label="item.agentName" :value="item.userId" />
  53. </el-select>
  54. </el-form-item>
  55. </el-col>
  56. <el-col :span="12" class="mb20">
  57. <el-form-item :label="$t('merchantUser.offlineRechargeRate')" prop="offlineRechargeRate">
  58. <el-input-number
  59. :placeholder="$t('merchantUser.inputOfflineRechargeRateTip')"
  60. v-model="form.offlineRechargeRate"
  61. :min="0"
  62. :max="100"
  63. :precision="2"
  64. :disabled="readonly"
  65. style="width: 100%"
  66. />
  67. </el-form-item>
  68. </el-col>
  69. <el-col :span="12" class="mb20">
  70. <el-form-item :label="$t('merchantUser.status')" prop="status">
  71. <el-radio-group v-model="form.status" :disabled="readonly || !!form.userId">
  72. <el-radio :label="true">{{ $t('merchantUser.statusEnable') }}</el-radio>
  73. <el-radio :label="false">{{ $t('merchantUser.statusDisable') }}</el-radio>
  74. </el-radio-group>
  75. </el-form-item>
  76. </el-col>
  77. </el-row>
  78. <!-- 网站信息 -->
  79. <el-divider content-position="left">{{ $t('merchantUser.websiteInfo') }}</el-divider>
  80. <el-row :gutter="24">
  81. <el-col :span="12" class="mb20">
  82. <el-form-item :label="$t('merchantUser.websiteName')" prop="websiteName">
  83. <el-input :placeholder="$t('merchantUser.inputWebsiteNameTip')" v-model="form.websiteName" :disabled="readonly" />
  84. </el-form-item>
  85. </el-col>
  86. <el-col :span="12" class="mb20">
  87. <el-form-item :label="$t('merchantUser.websiteAddress')" prop="websiteAddress">
  88. <el-input :placeholder="$t('merchantUser.inputWebsiteAddressTip')" v-model="form.websiteAddress" :disabled="readonly" />
  89. </el-form-item>
  90. </el-col>
  91. <el-col :span="12" class="mb20" v-if="form.userId">
  92. <el-form-item :label="$t('merchantUser.appId')" prop="appId">
  93. <el-input :placeholder="'AppId'" v-model="form.appId" disabled />
  94. </el-form-item>
  95. </el-col>
  96. </el-row>
  97. </el-form>
  98. <template #footer>
  99. <span class="dialog-footer">
  100. <el-button @click="visible = false">{{ readonly ? $t('common.closeBtn') : $t('common.cancelButtonText') }}</el-button>
  101. <el-button @click="onSubmit" type="primary" :disabled="loading" v-if="!readonly">{{ $t('common.confirmButtonText') }}</el-button>
  102. </span>
  103. </template>
  104. </el-dialog>
  105. </template>
  106. <script lang="ts" name="MerchantUserDialog" setup>
  107. // 定义子组件向父组件传值/事件
  108. import { useMessage } from '/@/hooks/message';
  109. import { addObj, getObj, putObj, getAgentList } from '/@/api/merchant/merchantUser';
  110. import { useI18n } from 'vue-i18n';
  111. import { rule } from '/@/utils/validate';
  112. const emit = defineEmits(['refresh']);
  113. const { t } = useI18n();
  114. // 定义变量内容
  115. const dataFormRef = ref();
  116. const visible = ref(false);
  117. const loading = ref(false);
  118. const readonly = ref(false);
  119. const agentList = ref<any[]>([]);
  120. // 提交表单数据(严格按照接口文档字段)
  121. const form = reactive({
  122. userId: '',
  123. username: '',
  124. merchantName: '',
  125. phone: '',
  126. email: '',
  127. websiteName: '',
  128. websiteAddress: '',
  129. appId: '',
  130. idcard: '',
  131. realname: '',
  132. contactAddress: '',
  133. offlineRechargeRate: 0,
  134. status: true,
  135. agentId: undefined as number | undefined,
  136. });
  137. // 定义校验规则(根据接口文档,必填字段:username, merchantName, phone, email)
  138. const dataRules = ref({
  139. username: [
  140. { required: true, message: t('merchantUser.usernameRequired'), trigger: 'blur' },
  141. { validator: rule.overLength, trigger: 'blur' },
  142. ],
  143. merchantName: [
  144. { required: true, message: t('merchantUser.merchantNameRequired'), trigger: 'blur' },
  145. { validator: rule.overLength, trigger: 'blur' },
  146. ],
  147. phone: [
  148. { required: true, message: t('merchantUser.phoneRequired'), trigger: 'blur' },
  149. { validator: rule.validatePhone, trigger: 'blur' },
  150. ],
  151. email: [
  152. { required: true, message: t('merchantUser.emailRequired'), trigger: 'blur' },
  153. { validator: rule.email, trigger: 'blur' },
  154. ],
  155. });
  156. // 打开弹窗
  157. const openDialog = (id: string, isReadonly = false) => {
  158. visible.value = true;
  159. readonly.value = isReadonly;
  160. form.userId = '';
  161. // 重置表单数据
  162. nextTick(() => {
  163. dataFormRef.value?.resetFields();
  164. });
  165. // 加载代理商列表
  166. loadAgentList();
  167. // 获取商户用户信息
  168. if (id) {
  169. form.userId = id;
  170. getMerchantUserData(id);
  171. }
  172. };
  173. // 加载代理商列表
  174. const loadAgentList = async () => {
  175. try {
  176. const res = await getAgentList('0');
  177. agentList.value = res.data || [];
  178. } catch (err: any) {
  179. useMessage().error(err.msg);
  180. }
  181. };
  182. // 获取商户用户数据
  183. const getMerchantUserData = (id: string) => {
  184. loading.value = true;
  185. getObj(id)
  186. .then((res: any) => {
  187. Object.assign(form, res.data);
  188. })
  189. .finally(() => {
  190. loading.value = false;
  191. });
  192. };
  193. // 提交
  194. const onSubmit = async () => {
  195. const valid = await dataFormRef.value.validate().catch(() => {});
  196. if (!valid) return false;
  197. try {
  198. loading.value = true;
  199. if (form.userId) {
  200. await putObj(form.userId, form);
  201. } else {
  202. await addObj(form);
  203. }
  204. useMessage().success(t(form.userId ? 'common.editSuccessText' : 'common.addSuccessText'));
  205. visible.value = false;
  206. emit('refresh');
  207. } catch (err: any) {
  208. useMessage().error(err.msg);
  209. } finally {
  210. loading.value = false;
  211. }
  212. };
  213. /**
  214. * 暴露变量
  215. */
  216. defineExpose({
  217. openDialog,
  218. });
  219. </script>