subsList.vue 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. <template>
  2. <cwg-page-wrapper class="create-page" :isHeaderFixed="true">
  3. <cwg-header :title="t('Ib.Custom.Manage2')" />
  4. <view class="account-content">
  5. <!-- 移动端:按钮在筛选上方 -->
  6. <cwg-match-media :max-width="991">
  7. <view class="search-content mobile-search-content">
  8. <view class="search-bar mobile-add-btn-wrap">
  9. <button type="primary" class="search-button" @click="addSub">
  10. <cwg-icon name="icon_add" :size="18" color="#fff"></cwg-icon>
  11. {{t('Ib.Report.Title5')}}
  12. </button>
  13. </view>
  14. <view class="search-bar">
  15. <cwg-complex-search :fields="filterFields" v-model="searchParams" @search="handleSearch" @reset="handleReset" />
  16. </view>
  17. </view>
  18. </cwg-match-media>
  19. <!-- PC端:按钮和筛选在同一行 -->
  20. <cwg-match-media :min-width="991">
  21. <view class="search-content pc-search-content">
  22. <view class="search-bar">
  23. <cwg-complex-search :fields="filterFields" v-model="searchParams" @search="handleSearch" @reset="handleReset" />
  24. </view>
  25. <view class="search-bar">
  26. <button type="primary" class="search-button" @click="addSub">
  27. <cwg-icon name="icon_add" :size="18" color="#fff"></cwg-icon>
  28. {{t('Ib.Report.Title5')}}
  29. </button>
  30. </view>
  31. </view>
  32. </cwg-match-media>
  33. <cwg-tabel
  34. ref="tableRef"
  35. :columns="columns"
  36. :mobilePrimaryFields="mobilePrimaryFields"
  37. :queryParams="search"
  38. :api="listApi"
  39. :show-operation="true"
  40. :showPagination="true"
  41. >
  42. <template #action="{ row }">
  43. <cwg-dropdown :menu-list="menuList(row)" @menuClick="handleMenuClick">
  44. <view class="pc-header-btn">
  45. <cwg-icon name="crm-ellipsis" :size="24" />
  46. </view>
  47. </cwg-dropdown>
  48. </template>
  49. </cwg-tabel>
  50. </view>
  51. <ApplyIbDialog ref="applyIbDialogRef" :visible="applyVisible" @close="closeApplyIb" @confirm="confirmApply" :title="formDia?'Ib.Custom.Commit3':'Ib.Report.Title5'" :isFormApplyIb="formDia" :paramsType="applyType" :detail="applyDetail"/>
  52. <cwg-popup
  53. :visible="exclusiveVisible"
  54. :title="t('Ib.Custom.Commit5')"
  55. :cancelText="t('Btn.Cancel')"
  56. :confirmText="t('Btn.Confirm')"
  57. @close="cancelExclusiveCommission"
  58. @confirm="confirmExclusiveCommission"
  59. >
  60. <view class="dia-content">
  61. <uni-forms ref="exclusiveCommissionFormRef" labelWidth="240">
  62. <uni-forms-item :label="t('Ib.Custom.Commit5')" prop="selectedPoint">
  63. <cwg-combox
  64. v-model:value="exclusiveCommissionForm.selectedPoint"
  65. :options="exclusiveCommissionForm.pointOptions"
  66. :placeholder="t('placeholder.choose')"
  67. />
  68. </uni-forms-item>
  69. </uni-forms>
  70. </view>
  71. </cwg-popup>
  72. </cwg-page-wrapper>
  73. </template>
  74. <script setup lang="ts">
  75. // 代理管理
  76. import { ref, reactive, computed, onMounted, onUnmounted } from 'vue'
  77. import { onLoad } from '@dcloudio/uni-app'
  78. import { useI18n } from 'vue-i18n' // uni-app 中已集成,但需配置
  79. import { customApi } from '@/service/custom'
  80. import { financialApi } from '@/service/financial'
  81. import Config from '@/config/index'
  82. import { lang } from '@/composables/config'
  83. import { ibApi } from '@/service/ib'
  84. import { useFilters } from '@/composables/useFilters'
  85. import ApplyIbDialog from '@/pages/ib/components/applyIbDialog.vue'
  86. import { nextTick } from 'vue'
  87. const { numberFormat, numberDecimal } = useFilters()
  88. const { t, locale } = useI18n()
  89. const { Code } = Config
  90. const searchParams = ref({})
  91. const search = ref({
  92. ibNo: '',
  93. name: '',
  94. cId: '',
  95. startDate: '',
  96. endDate: '',
  97. })
  98. const filterFields = [
  99. { key: 'ibNo', type: 'input', label: t('Label.IbAccount'), placeholder: t('Label.IbAccount'), defaultValue: '' },
  100. { key: 'name', type: 'input', label: t('Ib.Custom.NameLabel'), placeholder: t('Ib.Custom.NameLabel'), defaultValue: '' },
  101. { key: 'cId', type: 'input', label: 'CID', placeholder: 'CID', defaultValue: '' },
  102. { key: 'date', label: t('placeholder.Start') + ' - ' + t('placeholder.End'), type: 'daterange' }
  103. ]
  104. const tableRef = ref(null)
  105. const applyIbDialogRef = ref(null)
  106. const applyVisible = ref(false)
  107. const applyType = ref('')
  108. const applyDetail = ref()
  109. const formDia = ref(false)
  110. const exclusiveVisible = ref(false)
  111. const exclusiveCommissionFormRef = ref(null)
  112. const exclusiveCommissionForm = ref({
  113. agentId: "",
  114. selectedPoint: '',
  115. pointOptions: [],
  116. })
  117. const exclusiveRow = ref<any>(null)
  118. // 表格列配置
  119. const columns = ref([
  120. {
  121. prop: 'cId',
  122. label: t('Label.CidAccount'),
  123. align: 'center',
  124. },
  125. {
  126. prop: 'ibNo',
  127. label: t('Label.IbAccount'),
  128. align: 'center',
  129. },
  130. {
  131. prop: 'name',
  132. label: t('Ib.Custom.NameLabel'),
  133. align: 'center',
  134. },
  135. {
  136. prop: 'agentNum',
  137. label: t('Ib.Custom.AgentNum'),
  138. align: 'center',
  139. },
  140. {
  141. prop: 'customNum',
  142. label: t('Ib.Custom.CustomerNum'),
  143. align: 'center',
  144. },
  145. {
  146. prop: 'addTime',
  147. label: t('Label.ApplyTime'),
  148. align: 'center',
  149. },
  150. {
  151. prop: 'lastTime',
  152. label: t('Ib.Custom.LastActiveTime'),
  153. align: 'center',
  154. },
  155. {
  156. prop: 'action',
  157. label: t('Label.Action'),
  158. align: 'center',
  159. slot: 'action',
  160. },
  161. ])
  162. const mobilePrimaryFields = ref([
  163. {
  164. prop: 'cId',
  165. label: t('Label.CidAccount'),
  166. align: 'center',
  167. },
  168. {
  169. prop: 'ibNo',
  170. label: t('Label.IbAccount'),
  171. align: 'center',
  172. },
  173. {
  174. prop: 'name',
  175. label: t('Ib.Custom.NameLabel'),
  176. align: 'center',
  177. },
  178. {
  179. prop: 'more',
  180. type: 'more',
  181. width: 20,
  182. align: 'right',
  183. },
  184. ])
  185. const listApi = ref(ibApi.IbSubs)
  186. const handleSearch = (params: any) => {
  187. // 拦截处理 daterange,将 date 拆分为 startDate 和 endDate
  188. const payload = { ...params }
  189. if (payload.date && payload.date.length === 2) {
  190. payload.startDate = payload.date[0]
  191. payload.endDate = payload.date[1]
  192. } else {
  193. payload.startDate = ''
  194. payload.endDate = ''
  195. }
  196. delete payload.date
  197. search.value = payload
  198. nextTick(() => {
  199. tableRef.value.refreshTable()
  200. })
  201. }
  202. const handleReset = () => {
  203. search.value = {
  204. ibNo: '',
  205. name: '',
  206. cId: '',
  207. startDate: '',
  208. endDate: '',
  209. }
  210. nextTick(() => {
  211. tableRef.value.refreshTable()
  212. })
  213. }
  214. onMounted(()=>{
  215. // applyVisible.value = true
  216. })
  217. // 下拉菜单配置
  218. const menuList = (row) => {
  219. return [
  220. {
  221. label: t('Ib.Custom.Commit3'),
  222. type: 'vietnamDistribution',
  223. row,
  224. show: true,
  225. },
  226. {
  227. label: t('Ib.Custom.Commit5'),
  228. type: 'exclusiveCommission',
  229. row,
  230. show: row.exclusiveCommissionOptions?.length > 0,
  231. },
  232. ].filter((item) => item.show)
  233. }
  234. const handleMenuClick = (item) => {
  235. if (item.type == 'vietnamDistribution') {
  236. const { agentId, id } = item.row
  237. applyDetail.value = {
  238. id: id|| agentId
  239. }
  240. formDia.value = true
  241. applyType.value = 'vietnam'
  242. applyVisible.value = true
  243. } else if (item.type == 'exclusiveCommission') {
  244. openExclusiveCommission(item.row)
  245. }
  246. }
  247. const addSub = () => {
  248. formDia.value = false
  249. applyVisible.value = true
  250. }
  251. const closeApplyIb = () => {
  252. applyVisible.value = false
  253. }
  254. const confirmApply = (data) => {
  255. tableRef.value.refreshTable()
  256. }
  257. const normalizePointOptions = (options: any[]) => {
  258. if (!Array.isArray(options)) return []
  259. return options.map((o: any) => ({
  260. text: o.label ?? o.text ?? o.name ?? String(o.value ?? ''),
  261. value: o.value,
  262. }))
  263. }
  264. const openExclusiveCommission = async (row: any) => {
  265. exclusiveCommissionForm.value.agentId = row.id
  266. exclusiveCommissionForm.value.selectedPoint = ''
  267. exclusiveCommissionForm.value.pointOptions = normalizePointOptions(row?.exclusiveCommissionOptions || [])
  268. exclusiveVisible.value = true
  269. }
  270. const cancelExclusiveCommission = () => {
  271. exclusiveVisible.value = false
  272. exclusiveCommissionForm.value.selectedPoint = ''
  273. exclusiveCommissionForm.value.pointOptions = []
  274. }
  275. const confirmExclusiveCommission = async () => {
  276. try {
  277. const res = await ibApi.agentHiddenPointAdd({
  278. agentId: exclusiveCommissionForm.value.agentId,
  279. point: [{ value: exclusiveCommissionForm.value.selectedPoint }],
  280. })
  281. if (res.code == Code.StatusOK) {
  282. cancelExclusiveCommission()
  283. tableRef.value?.refreshTable?.()
  284. }
  285. } catch (e) {
  286. }
  287. }
  288. </script>
  289. <style lang="scss" scoped>
  290. @import "@/uni.scss";
  291. .search-content {
  292. display: flex;
  293. }
  294. /* PC 端对齐方式 */
  295. .pc-search-content {
  296. justify-content: space-between;
  297. align-items: flex-start;
  298. margin-bottom: px2rpx(10);
  299. }
  300. /* 移动端排版方式 */
  301. .mobile-search-content {
  302. flex-direction: column;
  303. margin-bottom: px2rpx(10);
  304. .mobile-add-btn-wrap {
  305. display: flex;
  306. justify-content: flex-end;
  307. width: 100%;
  308. margin-bottom: px2rpx(10);
  309. .search-button {
  310. margin: 0 0 0 auto; /* 强制按钮靠右且消除其它 margin */
  311. }
  312. }
  313. }
  314. .search-button{
  315. display: flex;
  316. align-items: center;
  317. line-height: px2rpx(36);
  318. min-width: px2rpx(120);
  319. }
  320. </style>