index.vue 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. <template>
  2. <div class="merchant-config-page">
  3. <!-- 顶部导航 -->
  4. <s-header :name="$t('remote.C32')" :noback="false" />
  5. <!-- 设备名称标题 -->
  6. <div class="device-header">
  7. <div class="vertical-indicator"></div>
  8. <h3 class="device-name">
  9. {{ $t("device.equipmentName") }}:{{ deviceName }}
  10. </h3>
  11. </div>
  12. <!-- 商户信息表单 -->
  13. <van-form @submit="handleSubmit">
  14. <div class="settings-card">
  15. <!-- Merchant ID -->
  16. <div class="config-item">
  17. <div class="config-info">
  18. <van-icon name="user-circle-o" class="config-icon" />
  19. <div class="config-detail">
  20. <h3 class="config-title">merchant_id</h3>
  21. <van-field
  22. v-model="configData.merchantId"
  23. class="config-input"
  24. :border="false"
  25. :rules="[
  26. {
  27. required: true,
  28. message: 'merchant_id',
  29. },
  30. ]"
  31. />
  32. </div>
  33. </div>
  34. </div>
  35. <!-- Secret Code -->
  36. <div class="config-item">
  37. <div class="config-info">
  38. <van-icon name="lock" class="config-icon" />
  39. <div class="config-detail">
  40. <h3 class="config-title">secret_code</h3>
  41. <van-field
  42. v-model="configData.secretCode"
  43. class="config-input"
  44. type="password"
  45. :border="false"
  46. :rules="[
  47. {
  48. required: true,
  49. message: 'secret_code',
  50. },
  51. ]"
  52. />
  53. </div>
  54. </div>
  55. </div>
  56. <!-- Product Ability Code -->
  57. <div class="config-item">
  58. <div class="config-info">
  59. <van-icon name="setting-o" class="config-icon" />
  60. <div class="config-detail">
  61. <h3 class="config-title">product_ability_code</h3>
  62. <van-field
  63. v-model="configData.productAbilityCode"
  64. class="config-input"
  65. :border="false"
  66. :rules="[
  67. {
  68. required: true,
  69. message: 'product_ability_code',
  70. },
  71. ]"
  72. />
  73. </div>
  74. </div>
  75. </div>
  76. <!-- Area Code -->
  77. <div class="config-item">
  78. <div class="config-info">
  79. <van-icon name="location-o" class="config-icon" />
  80. <div class="config-detail">
  81. <h3 class="config-title">area_code</h3>
  82. <van-field
  83. v-model="configData.areaCode"
  84. class="config-input"
  85. :border="false"
  86. :rules="[
  87. {
  88. required: true,
  89. message: 'area_code',
  90. },
  91. ]"
  92. />
  93. </div>
  94. </div>
  95. </div>
  96. </div>
  97. <!-- 提交按钮 -->
  98. <div class="submit-footer">
  99. <van-button round type="primary" class="submit-btn" native-type="submit">
  100. <template #icon>
  101. <van-icon name="success" class="btn-icon" />
  102. </template>
  103. {{ $t("device.modify") }}
  104. </van-button>
  105. </div>
  106. </van-form>
  107. </div>
  108. </template>
  109. <script>
  110. import sHeader from "@/components/SimpleHeader";
  111. import { showConfirmDialog, showSuccessToast, showFailToast } from "vant";
  112. import { useRoute, useRouter } from "vue-router";
  113. import { ref } from "vue";
  114. import { useI18n } from "vue-i18n";
  115. import { onMounted } from "vue";
  116. import { getPayConfig, pushPayInfo } from "@/service/device/index";
  117. export default {
  118. components: { sHeader },
  119. setup() {
  120. const { t } = useI18n();
  121. const route = useRoute();
  122. const router = useRouter();
  123. const deviceId = ref(route.query.clientId);
  124. const deviceName = ref(route.query.name);
  125. // 配置数据
  126. const configData = ref({
  127. clientId: deviceId.value,
  128. merchantId: "",
  129. secretCode: "",
  130. productAbilityCode: "",
  131. areaCode: "",
  132. });
  133. onMounted(() => {
  134. if (deviceId.value) {
  135. handleGetPayConfig();
  136. }
  137. });
  138. const handleGetPayConfig = async () => {
  139. const { data } = await getPayConfig({ clientId: deviceId.value });
  140. if (data.data) {
  141. configData.value.merchantId = data.data.merchantId;
  142. configData.value.secretCode = data.data.secretCode;
  143. configData.value.productAbilityCode = data.data.productAbilityCode;
  144. configData.value.areaCode = data.data.areaCode;
  145. }
  146. };
  147. const handleSubmit = () => {
  148. showConfirmDialog({
  149. title: t("device.operationConfirmation"),
  150. message: t("device.pleaseConfirmAgainWhetherToOperate"),
  151. })
  152. .then(async () => {
  153. // on confirm
  154. const { data } = await pushPayInfo(configData.value);
  155. if (data.code === "00000") {
  156. showSuccessToast(t("device.modificationSucceeded"));
  157. setTimeout(() => {
  158. router.go(-1);
  159. }, 2000);
  160. } else {
  161. showFailToast(data.message);
  162. }
  163. })
  164. .catch(() => {
  165. // on cancel
  166. });
  167. };
  168. return {
  169. deviceName,
  170. handleSubmit,
  171. configData,
  172. };
  173. },
  174. };
  175. </script>
  176. <style lang="less" scoped>
  177. @theme-color: #4d6add;
  178. @light-bg: #f5f8ff;
  179. @card-bg: #ffffff;
  180. @text-dark: #333;
  181. @text-light: #666;
  182. @border-radius: 12px;
  183. @card-shadow: 0 4px 12px rgba(77, 106, 221, 0.15);
  184. @hover-shadow: 0 8px 20px rgba(77, 106, 221, 0.25);
  185. @transition: all 0.3s ease;
  186. .merchant-config-page {
  187. display: flex;
  188. flex-direction: column;
  189. height: 100vh;
  190. background-color: @light-bg;
  191. font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
  192. sans-serif;
  193. }
  194. .device-header {
  195. display: flex;
  196. align-items: center;
  197. padding: 12px 15px;
  198. background: #fff;
  199. margin: 12px 16px;
  200. border-radius: 8px;
  201. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
  202. .vertical-indicator {
  203. width: 4px;
  204. height: 15px;
  205. background: var(--active-color, #4d6add);
  206. border-radius: 2px;
  207. margin-right: 10px;
  208. }
  209. .device-name {
  210. margin: 0;
  211. font-size: 15px;
  212. color: #404d74;
  213. font-weight: 550;
  214. // 长名称处理
  215. overflow: hidden;
  216. text-overflow: ellipsis;
  217. white-space: nowrap;
  218. max-width: 70vw;
  219. }
  220. }
  221. .settings-card {
  222. background-color: @card-bg;
  223. border-radius: @border-radius;
  224. box-shadow: @card-shadow;
  225. padding: 16px;
  226. margin: 0 16px 24px;
  227. }
  228. .config-item {
  229. margin-bottom: 24px;
  230. &:last-child {
  231. margin-bottom: 0;
  232. }
  233. }
  234. .config-info {
  235. display: flex;
  236. align-items: center;
  237. }
  238. .config-icon {
  239. font-size: 24px;
  240. color: @theme-color;
  241. margin-right: 16px;
  242. }
  243. .config-detail {
  244. flex: 1;
  245. }
  246. .config-title {
  247. font-size: 15px;
  248. font-weight: 500;
  249. color: @text-dark;
  250. margin: 0 0 8px;
  251. }
  252. .config-input {
  253. background-color: #f9fafc;
  254. border-radius: 8px;
  255. padding: 10px 16px;
  256. :deep(.van-field__control) {
  257. font-size: 15px;
  258. color: @text-dark;
  259. }
  260. :deep(.van-field__placeholder) {
  261. color: #a0a4ab;
  262. }
  263. }
  264. .submit-footer {
  265. padding: 0 16px 24px;
  266. position: sticky;
  267. bottom: 0;
  268. background-color: @light-bg;
  269. }
  270. .submit-btn {
  271. width: 100%;
  272. height: 52px;
  273. background-color: @theme-color;
  274. border: none;
  275. font-size: 17px;
  276. font-weight: 500;
  277. letter-spacing: 0.5px;
  278. box-shadow: 0 6px 16px fade(@theme-color, 35%);
  279. .btn-icon {
  280. font-size: 22px;
  281. margin-right: 8px;
  282. }
  283. &:active {
  284. opacity: 0.92;
  285. transform: translateY(1px);
  286. }
  287. &:disabled {
  288. opacity: 0.7;
  289. transform: none;
  290. }
  291. }
  292. // 响应式调整
  293. @media (max-width: 360px) {
  294. .device-header .device-name {
  295. font-size: 16px;
  296. }
  297. .config-title {
  298. font-size: 14px;
  299. }
  300. .submit-btn {
  301. height: 48px;
  302. font-size: 16px;
  303. }
  304. }
  305. </style>