index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. <!-- 资费管理 -->
  2. <template>
  3. <div class="container">
  4. <div class="head-title">
  5. <span>{{ route.meta.title }} </span>
  6. <span class="head-title-right">
  7. <a-button class="m-r-10" type="primary" @click="dictShowModel(1, null)">{{ $t('form.Add') }}</a-button>
  8. </span>
  9. </div>
  10. <!-- 搜索条件区 -->
  11. <div class="search-section">
  12. <a-form :model="searchForm" layout="inline">
  13. <a-form-item field="sim_data_plan_id" :label="$t('tariffManagement.simDataPlanId')">
  14. <a-input v-model="searchForm.sim_data_plan_id"
  15. :placeholder="$t('lotCard.please') + $t('tariffManagement.simDataPlanId')" allow-clear />
  16. </a-form-item>
  17. <a-form-item>
  18. <a-space>
  19. <a-button type="primary" @click="handleSearch">{{ $t('form.Search') }}</a-button>
  20. <a-button @click="resetSearch">{{ $t('form.Reset') }}</a-button>
  21. </a-space>
  22. </a-form-item>
  23. </a-form>
  24. </div>
  25. <div class="audit-btn">
  26. <a-button type="text" @click="dictShowModel(1, null)">
  27. <template #icon>
  28. <icon-plus-circle />
  29. </template>
  30. <template #default>{{ $t('form.Add') }}</template>
  31. </a-button>
  32. </div>
  33. <a-table row-key="id" :data="dataSource" :columns="columns" :pagination="pagination"
  34. :row-selection="rowSelection" v-model:selectedKeys="selectedKeys" :scroll="{ x: 'auto' }">
  35. <template #id="{ record }">
  36. <!-- 修改 -->
  37. <a class="a-link" href="javascript:;" style="margin-right: 1rem" @click="dictShowModel(2, record)">{{
  38. $t('form.Edit') }}</a>
  39. <!-- 删除 -->
  40. <a-popconfirm :content="$t('form.Delete')" :ok-text="$t('form.Confirm')"
  41. :cancel-text="$t('form.Cancel')" @ok="handleDel(record.id)">
  42. <a class="a-link" href="javascript:;" style="margin-right: 1rem">{{ $t('form.Delete')
  43. }}</a>
  44. </a-popconfirm>
  45. </template>
  46. </a-table>
  47. <!-- 弹框 -->
  48. <a-modal :title="typeCurrent == 1 ? $t('form.Add') : $t('form.Edit')" v-model:visible="visible"
  49. @onCancel="resetForm" centered :maskClosable="false" :footer="null">
  50. <a-form ref="formRef" :rules="rules" :model="formState" @submit="handleSubmit">
  51. <a-form-item :label="$t('tariffManagement.simDataPlanId')" field="sim_data_plan_id">
  52. <a-input v-model="formState.sim_data_plan_id" />
  53. </a-form-item>
  54. <a-form-item :label="$t('tariffManagement.label')" field="label">
  55. <a-input v-model="formState.label" />
  56. </a-form-item>
  57. <a-form-item :label="$t('tariffManagement.userId')" field="user_id">
  58. <a-input v-model="formState.user_id" />
  59. </a-form-item>
  60. <a-form-item :label="$t('tariffManagement.source')" field="source">
  61. <a-select v-model="formState.source">
  62. <a-option v-for=" item in sourceList" :key="item.id" :value="item.value">{{ item.label
  63. }}</a-option>
  64. </a-select>
  65. </a-form-item>
  66. <a-form-item :label="$t('tariffManagement.trafficType')" field="traffic_type">
  67. <a-select v-model="formState.traffic_type">
  68. <a-option v-for=" item in trafficList" :key="item.id" :value="item.value">{{ item.label
  69. }}</a-option>
  70. </a-select>
  71. </a-form-item>
  72. <a-form-item :label="$t('tariffManagement.billingType')" field="billing_type">
  73. <a-select v-model="formState.billing_type">
  74. <a-option v-for=" item in typeList" :key="item.id" :value="item.value">{{ item.label
  75. }}</a-option>
  76. </a-select>
  77. </a-form-item>
  78. <a-form-item :label="$t('tariffManagement.bagSize')" field="bag_size">
  79. <a-input v-model="formState.bag_size" />
  80. </a-form-item>
  81. <a-form-item :label="$t('tariffManagement.billingCycle')" field="billing_cycle">
  82. <a-select v-model="formState.billing_cycle">
  83. <a-option v-for=" item in cycleist" :key="item.id" :value="item.value">{{ item.label
  84. }}</a-option>
  85. </a-select>
  86. </a-form-item>
  87. <a-form-item :label="$t('tariffManagement.billingMethod')" field="billing_method">
  88. <a-select v-model="formState.billing_method">
  89. <a-option v-for=" item in methodList" :key="item.id" :value="item.value">{{ item.label
  90. }}</a-option>
  91. </a-select>
  92. </a-form-item>
  93. <a-form-item :label="$t('tariffManagement.settlementCycle')" field="settlement_cycle">
  94. <a-select v-model="formState.settlement_cycle">
  95. <a-option v-for=" item in settlementCycleList" :key="item.id" :value="item.value">{{ item.label
  96. }}</a-option>
  97. </a-select>
  98. </a-form-item>
  99. <a-form-item :label="$t('tariffManagement.pricing')" field="pricing">
  100. <a-input v-model="formState.pricing" />
  101. </a-form-item>
  102. <a-form-item :label="$t('tariffManagement.currency')" field="currency">
  103. <a-input v-model="formState.currency" />
  104. </a-form-item>
  105. <a-form-item>
  106. <a-button type="primary" html-type="submit" style="margin-right: 10px;">{{ $t('form.Confirm')
  107. }}</a-button>
  108. <a-button @click="resetForm">{{ $t('form.Cancel') }}</a-button>
  109. </a-form-item>
  110. </a-form>
  111. </a-modal>
  112. </div>
  113. </template>
  114. <script setup>
  115. import { onMounted, ref, reactive, getCurrentInstance, nextTick } from "vue";
  116. import { useRoute } from "vue-router";
  117. import { columns } from "./config";
  118. import { Message, Notification } from '@arco-design/web-vue'
  119. import { deleteTariff, updateTariff, addTariff, tariffList } from "@/api/path/tariffManagement.api"
  120. import { enum_dict } from "@/hooks/enum";
  121. import { useSystemStore } from '@/store/modules/systemStore'
  122. const { proxy } = getCurrentInstance()
  123. const formRef = ref()
  124. const searchForm = ref({
  125. "sim_data_plan_id": "",
  126. });
  127. const dataSource = ref([]);
  128. const route = useRoute();
  129. const pagination = ref({
  130. total: 0,
  131. pageSize: 10,
  132. current: 1,
  133. })
  134. const rowSelection = reactive({
  135. type: 'checkbox',
  136. showCheckedAll: true,
  137. onlyCurrent: false,
  138. });
  139. const selectedKeys = ref([])
  140. const intData = async () => {
  141. const param = {
  142. current: pagination.value.current,
  143. size: pagination.value.pageSize,
  144. ...searchForm.value,
  145. }
  146. const { data } = await tariffList(param)
  147. dataSource.value = (data.records || []).map((item, index) => {
  148. const sourceName = sourceList.value.find(val => val.value == item.source)?.label
  149. const trafficTypeName = trafficList.value.find(val => val.value == item.traffic_type)?.label
  150. const billingTypeName = typeList.value.find(val => val.value == item.billing_type)?.label
  151. const billingCycleName = cycleist.value.find(val => val.value == item.billing_cycle)?.label
  152. // const methodName = methodList.value.find(val => val.value == item.billing_method)?.label
  153. const settlementCycleName = settlementCycleList.value.find(val => val.value == item.settlement_cycle)?.label
  154. return {
  155. ...item,
  156. sourceName,
  157. trafficTypeName,
  158. billingTypeName,
  159. billingCycleName,
  160. settlementCycleName,
  161. feeCode: "NR0" + (index + 1),
  162. status: "正常"
  163. }
  164. })
  165. pagination.value.total = data.total
  166. }
  167. // 删除
  168. const handleDel = async (id) => {
  169. const { code } = await deleteTariff({ id })
  170. if (code == 200) {
  171. Message.success({
  172. content: "删除成功!",
  173. duration: 2000,
  174. })
  175. intData()
  176. }
  177. };
  178. //
  179. const handleSearch = () => {
  180. intData()
  181. }
  182. const resetSearch = () => {
  183. proxy.$refs.formRef.resetFields()
  184. intData()
  185. }
  186. // -------------------弹窗数据------------------------------------
  187. const visible = ref(false);
  188. const typeCurrent = ref(null);
  189. const sourceList = ref([])
  190. const trafficList = ref([])
  191. const cycleist = ref([])
  192. const typeList = ref([])
  193. const methodList = ref([])
  194. const settlementCycleList = ref([])
  195. const formState = ref({
  196. id: "",
  197. // 资费名称(必填)
  198. "label": "",
  199. // 流量包ID(必填)
  200. "sim_data_plan_id": "",
  201. // 用户ID(必填)
  202. "user_id": 0,
  203. // 来源(必填)
  204. "source": "",
  205. // 流量类型(必填)
  206. "traffic_type": "",
  207. // 计费类型(必填)
  208. "billing_type": "",
  209. // 流量包Size(必填)
  210. "bag_size": "",
  211. // 计费周期(必填)
  212. "billing_cycle": "",
  213. // 计费方式(必填)
  214. "billing_method": "",
  215. // 结算周期(必填)
  216. "settlement_cycle": "",
  217. // 价格(必填)
  218. "pricing": "",
  219. // 币种(必填)
  220. "currency": ""
  221. });
  222. const rules = {
  223. label: [{ required: true, trigger: 'change', }],
  224. sim_data_plan_id: [{ required: true, trigger: 'change', }],
  225. user_id: [{ required: true, trigger: 'change', }],
  226. source: [{ required: true, trigger: 'change', }],
  227. traffic_type: [{ required: true, trigger: 'change', }],
  228. billing_type: [{ required: true, trigger: 'change', }],
  229. bag_size: [{ required: true, trigger: 'change', }],
  230. billing_cycle: [{ required: true, trigger: 'change', }],
  231. billing_method: [{ required: true, trigger: 'change', }],
  232. settlement_cycle: [{ required: true, trigger: 'change', }],
  233. pricing: [{ required: true, trigger: 'change', }],
  234. currency: [{ required: true, trigger: 'change', }],
  235. };
  236. // 提交
  237. const handleSubmit = ({ values, errors }) => {
  238. formRef.value.validate(async (errors) => {
  239. if (!errors) {
  240. values.user_id = Number(values.user_id)
  241. if (formState.value.id) {
  242. const { code, data } = await updateTariff(values)
  243. if (code == 200) {
  244. Message.success({
  245. content: "修改成功!",
  246. duration: 2000,
  247. })
  248. visible.value = false;
  249. intData()
  250. }
  251. } else {
  252. const { code, data } = await addTariff(values)
  253. if (code == 200) {
  254. Message.success({
  255. content: "添加成功!",
  256. duration: 2000,
  257. })
  258. visible.value = false;
  259. intData()
  260. }
  261. }
  262. }
  263. });
  264. }
  265. // 弹框
  266. const dictShowModel = (type, data) => {
  267. typeCurrent.value = type;
  268. visible.value = true;
  269. // 编辑
  270. if (type == 2) {
  271. Object.assign(formState.value, data);
  272. }
  273. }
  274. // 取消
  275. const resetForm = () => {
  276. visible.value = false;
  277. formRef.value.resetFields();
  278. }
  279. // --------------------------------------------------------
  280. // 获取字典
  281. const handleDictValue = () => {
  282. const dictList = JSON.parse(window.localStorage.getItem('dictList')) ?? []
  283. sourceList.value = dictList.filter((item) => item.type_key == enum_dict.SOURCE)
  284. trafficList.value = dictList.filter((item) => item.type_key == enum_dict.TRAFFI_CTYPE)
  285. cycleist.value = dictList.filter((item) => item.type_key == enum_dict.BILLING_CYCLE)
  286. typeList.value = dictList.filter((item) => item.type_key == enum_dict.BILLING_TYPE)
  287. methodList.value = dictList.filter((item) => item.type_key == enum_dict.BILLING_METHOD)
  288. settlementCycleList.value = dictList.filter((item) => item.type_key == enum_dict.SETTLEMENT_CYCLE)
  289. }
  290. onMounted(() => {
  291. handleDictValue()
  292. intData()
  293. })
  294. </script>
  295. <style scoped lang="less">
  296. .head-title-right {
  297. .m-r-10 {
  298. margin-right: 10px;
  299. }
  300. }
  301. .search-section {
  302. margin-top: 20px;
  303. margin-bottom: 20px;
  304. }
  305. .container {
  306. .head-title {
  307. display: flex;
  308. justify-content: space-between;
  309. }
  310. .form-row {
  311. display: flex;
  312. .form-row-col {
  313. width: 25%;
  314. display: flex;
  315. align-items: center;
  316. .form-row-label {
  317. width: 120px;
  318. text-align: right;
  319. }
  320. }
  321. }
  322. }
  323. .audit-btn {
  324. margin-bottom: 10px;
  325. }
  326. </style>