| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461 |
- <template>
- <cwg-page-wrapper class="create-page" :isHeaderFixed="true">
- <cwg-header :title="t('Ib.PammManager.title1') + ' - ' + row.login">
- <template #right>
- <view class="header-btn" @click="backIndex">
- <cwg-icon name="icon_back" :size="18" />
- <text>{{ t('Ib.Settings.Title') }}</text>
- </view>
- </template>
- </cwg-header>
- <view class="main-content account-content">
- <view class="tips-text">{{ t('Ib.PammManager.tips3') }}</view>
- <view class="tab-group">
- <view class="tab-item" :class="{ active: subs === '1' }" @click="tableSearch('1')">
- {{ t('Ib.Settings.Hang') }}
- </view>
- <view class="tab-item" :class="{ active: subs === '2' }" @click="tableSearch('2')">
- {{ t('Ib.Settings.Undo') }}
- </view>
- </view>
- <!-- 穿梭框 (模拟 el-transfer) -->
- <view class="transfer-container">
- <!-- 左侧面板 (未选择) -->
- <view class="transfer-panel">
- <view class="transfer-header">
- <checkbox :checked="isAllLeftChecked" @click="toggleAllLeft" style="transform:scale(0.7)" />
- <text>{{ subs === '1' ? t('Ib.Settings.NotHang') : t('Ib.Settings.NotUndo') }}</text>
- <text class="count">{{ leftListData.length }}</text>
- </view>
- <view class="transfer-search">
- <uni-easyinput prefixIcon="search" v-model="searchLeft" :placeholder="t('placeholder.input')" />
- </view>
- <scroll-view scroll-y class="transfer-list">
- <checkbox-group @change="onLeftChange">
- <label class="transfer-item" v-for="item in filteredLeftList" :key="item.key">
- <checkbox :value="item.key" :checked="leftChecked.includes(item.key)" style="transform:scale(0.7)" />
- <text>{{ item.label }}</text>
- </label>
- </checkbox-group>
- <view v-if="filteredLeftList.length === 0" class="empty-text">{{ t('Documentary.tradingCenter.item143') }}
- </view>
- </scroll-view>
- </view>
- <!-- 中间操作按钮 -->
- <view class="transfer-actions">
- <button class="action-btn right" :disabled="leftChecked.length === 0" @click="moveToRight">
- <text>></text>
- </button>
- <button class="action-btn left" :disabled="rightChecked.length === 0" @click="moveToLeft">
- <text><</text>
- </button>
- </view>
- <!-- 右侧面板 (已选择) -->
- <view class="transfer-panel">
- <view class="transfer-header">
- <checkbox :checked="isAllRightChecked" @click="toggleAllRight" style="transform:scale(0.7)" />
- <text>{{ subs === '1' ? t('Ib.Settings.HaveHang') : t('Ib.Settings.HaveUndo') }}</text>
- <text class="count">{{ rightListData.length }}</text>
- </view>
- <view class="transfer-search">
- <uni-easyinput prefixIcon="search" v-model="searchRight" :placeholder="t('placeholder.input')" />
- </view>
- <scroll-view scroll-y class="transfer-list">
- <checkbox-group @change="onRightChange">
- <label class="transfer-item" v-for="item in filteredRightList" :key="item.key">
- <checkbox :value="item.key" :checked="rightChecked.includes(item.key)" style="transform:scale(0.7)" />
- <text>{{ item.label }}</text>
- </label>
- </checkbox-group>
- <view v-if="filteredRightList.length === 0" class="empty-text">{{ t('Documentary.tradingCenter.item143') }}
- </view>
- </scroll-view>
- </view>
- </view>
- <view class="submit-bar">
- <button type="primary" class="submit-btn btn btn-dark waves-effect waves-light" @click="applySubmit">{{ t('Btn.Confirm') }}</button>
- </view>
- </view>
- <!-- 提交结果弹窗 -->
- <cwg-popup :visible="dialogCheck" :showClose="false" :showFooters="true" :confirmText="t('Btn.Confirm')"
- :cancelText="t('Btn.Cancel')" @confirm="closeDia" @close="closeDia">
- <view class="result-dialog">
- <view v-if="dialogVisible" class="icon-wrap">
- <cwg-icon name="icon_success" :size="50" color="#67C23A" />
- <view class="result-text">{{ t('ApplicationDialog.Des1') }}</view>
- </view>
- <view v-else class="icon-wrap">
- <cwg-icon name="icon_warning" :size="50" color="#E6A23C" />
- <view class="result-text">{{ RES }}</view>
- </view>
- </view>
- </cwg-popup>
- </cwg-page-wrapper>
- </template>
- <script setup lang="ts">
- import { ref, computed, onMounted } from 'vue'
- import { onLoad } from '@dcloudio/uni-app'
- import { useI18n } from 'vue-i18n'
- import { ibApi } from '@/service/ib'
- import Config from '@/config/index'
- const { t } = useI18n()
- const { Code } = Config
- const row = ref({ login: '', mamId: '' })
- const subs = ref('1')
- const transData1 = ref<any[]>([]) // 挂入的数据源
- const transValue1 = ref<string[]>([]) // 挂入的选中项
- const transData = ref<any[]>([]) // 撤销的数据源
- const transValue = ref<string[]>([]) // 撤销的选中项
- const flag = ref(false)
- const RES = ref('')
- const dialogCheck = ref(false)
- const dialogVisible = ref(false)
- // 穿梭框搜索和选择状态
- const searchLeft = ref('')
- const searchRight = ref('')
- const leftChecked = ref<string[]>([])
- const rightChecked = ref<string[]>([])
- // 根据 subs (挂入/撤销) 动态绑定当前的数据源
- const currentData = computed(() => subs.value === '1' ? transData1.value : transData.value)
- const currentValue = computed({
- get: () => subs.value === '1' ? transValue1.value : transValue.value,
- set: (val) => {
- if (subs.value === '1') transValue1.value = val
- else transValue.value = val
- }
- })
- // 左侧列表(全集 - 已选)
- const leftListData = computed(() => currentData.value.filter(item => !currentValue.value.includes(item.key)))
- // 右侧列表(已选)
- const rightListData = computed(() => currentData.value.filter(item => currentValue.value.includes(item.key)))
- // 搜索过滤
- const filteredLeftList = computed(() => leftListData.value.filter(item => item.label.toLowerCase().includes(searchLeft.value.toLowerCase())))
- const filteredRightList = computed(() => rightListData.value.filter(item => item.label.toLowerCase().includes(searchRight.value.toLowerCase())))
- const isAllLeftChecked = computed(() => filteredLeftList.value.length > 0 && leftChecked.value.length === filteredLeftList.value.length)
- const isAllRightChecked = computed(() => filteredRightList.value.length > 0 && rightChecked.value.length === filteredRightList.value.length)
- // 勾选事件
- const onLeftChange = (e: any) => { leftChecked.value = e.detail.value }
- const onRightChange = (e: any) => { rightChecked.value = e.detail.value }
- // 全选/反选
- const toggleAllLeft = () => {
- if (isAllLeftChecked.value) leftChecked.value = []
- else leftChecked.value = filteredLeftList.value.map(item => item.key)
- }
- const toggleAllRight = () => {
- if (isAllRightChecked.value) rightChecked.value = []
- else rightChecked.value = filteredRightList.value.map(item => item.key)
- }
- // 移动选中项
- const moveToRight = () => {
- currentValue.value = [...currentValue.value, ...leftChecked.value]
- leftChecked.value = []
- }
- const moveToLeft = () => {
- currentValue.value = currentValue.value.filter(key => !rightChecked.value.includes(key))
- rightChecked.value = []
- }
- // 切换 Tabs (挂入 / 撤销)
- const tableSearch = (val: string) => {
- subs.value = val
- searchLeft.value = ''
- searchRight.value = ''
- leftChecked.value = []
- rightChecked.value = []
- }
- // 获取挂入数据
- const getSubs = async () => {
- const res = await ibApi.MamSubsInfo({ mamId: Number(row.value.mamId), type: 1 })
- if (res.code === Code.StatusOK) {
- transData1.value = (res.data || []).map((item: string) => ({ key: item, label: item }))
- } else {
- uni.showToast({ title: res.msg, icon: 'none' })
- }
- }
- // 获取撤销数据
- const getSubs1 = async () => {
- const res = await ibApi.MamSubsInfo({ mamId: Number(row.value.mamId), type: 2 })
- if (res.code === Code.StatusOK) {
- transData.value = (res.data || []).map((item: string) => ({ key: item, label: item }))
- } else {
- uni.showToast({ title: res.msg, icon: 'none' })
- }
- }
- // 提交申请
- const applySubmit = async () => {
- if (flag.value) return
- flag.value = true
- const type = subs.value === '1' ? 1 : 2
- const selectedSubs = currentValue.value
- if (!selectedSubs || !selectedSubs.length) {
- flag.value = false
- uni.showToast({ title: t('placeholder.choose'), icon: 'none' })
- return
- }
- try {
- const res = await ibApi.MamSubsApply({
- mamId: Number(row.value.mamId),
- type,
- subs: selectedSubs
- })
- if (res.code === Code.StatusOK) {
- dialogCheck.value = true
- dialogVisible.value = true
- } else {
- RES.value = res.msg
- dialogCheck.value = true
- dialogVisible.value = false
- }
- } catch (error) {
- RES.value = t('Msg.Fail')
- dialogCheck.value = true
- dialogVisible.value = false
- } finally {
- flag.value = false
- }
- }
- // 关闭结果弹窗
- const closeDia = () => {
- dialogCheck.value = false
- dialogVisible.value = false
- // 刷新数据并清空选中
- if (subs.value === '1') getSubs()
- else getSubs1()
- currentValue.value = []
- }
- // 返回
- const backIndex = () => {
- uni.navigateBack({ delta: 1 })
- }
- onLoad((options: any) => {
- if (options) {
- row.value.login = options.login || ''
- row.value.mamId = options.id || ''
- }
- getSubs()
- getSubs1()
- })
- </script>
- <style lang="scss" scoped>
- @import "@/uni.scss";
- .header-btn {
- display: flex;
- align-items: center;
- font-size: px2rpx(14);
- color: var(--bs-heading-color);
- cursor: pointer;
- text {
- margin-left: px2rpx(5);
- }
- }
- .main-content {
- padding: px2rpx(20);
- background-color: rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important;
- border-radius: px2rpx(8);
- margin-top: px2rpx(15);
- min-height: calc(100vh - 100px);
- }
- .tips-text {
- margin-bottom: px2rpx(20);
- font-size: px2rpx(16);
- line-height: 1.7;
- font-weight: bold;
- }
- .tab-group {
- display: flex;
- margin-bottom: px2rpx(20);
- .tab-item {
- height: px2rpx(32);
- line-height: px2rpx(32);
- padding: 0 px2rpx(20);
- text-align: center;
- border-bottom: 1px solid #dcdfe6;
- background-color: rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important;
- font-size: px2rpx(14);
- cursor: pointer;
- &:first-child {
- //border-radius: px2rpx(4) 0 0 px2rpx(4);
- }
- &:last-child {
- //border-radius: 0 px2rpx(4) px2rpx(4) 0;
- border-left: none;
- }
- &.active {
- font-weight: bold;
- background-color: var(--color-error);
- color: var(--bs-emphasis-color);
- border-color: var(--color-error);
- }
- }
- }
- /* 穿梭框样式 */
- .transfer-container {
- display: flex;
- align-items: center;
- justify-content: space-between;
- margin-bottom: px2rpx(20);
- }
- .transfer-panel {
- flex: 1;
- border: 1px solid #ebeef5;
- border-radius: px2rpx(4);
- background: #fff;
- display: flex;
- flex-direction: column;
- height: px2rpx(350);
- }
- .transfer-header {
- height: px2rpx(40);
- line-height: px2rpx(40);
- background: #f5f7fa;
- margin: 0;
- padding: 0 px2rpx(15);
- border-bottom: 1px solid #ebeef5;
- box-sizing: border-box;
- color: #000;
- display: flex;
- align-items: center;
- font-size: px2rpx(14);
- .count {
- margin-left: auto;
- color: #909399;
- font-size: px2rpx(12);
- }
- }
- .transfer-search {
- padding: px2rpx(10);
- }
- .transfer-list {
- flex: 1;
- overflow: hidden;
- padding: px2rpx(10);
- }
- .transfer-item {
- display: flex;
- align-items: center;
- margin-bottom: px2rpx(10);
- font-size: px2rpx(14);
- color: #606266;
- }
- .empty-text {
- text-align: center;
- color: #909399;
- font-size: px2rpx(14);
- margin-top: px2rpx(50);
- }
- .transfer-actions {
- display: flex;
- flex-direction: column;
- justify-content: center;
- padding: 0 px2rpx(15);
- .action-btn {
- width: px2rpx(32);
- height: px2rpx(32);
- border-radius: px2rpx(4);
- background-color: var(--color-error);
- color: var(--bs-emphasis-color);
- display: flex;
- align-items: center;
- justify-content: center;
- margin-bottom: px2rpx(10);
- padding: 0;
- font-size: px2rpx(16);
- &[disabled] {
- background-color: rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important;
- border: 1px solid #ebeef5;
- color: #c0c4cc;
- cursor: not-allowed;
- }
- }
- }
- .submit-bar {
- margin-top: px2rpx(20);
- .submit-btn {
- width: 100%;
- }
- }
- .result-dialog {
- text-align: center;
- padding: px2rpx(20);
- .icon-wrap {
- margin-bottom: px2rpx(20);
- }
- .result-text {
- font-size: px2rpx(16);
- font-weight: bold;
- margin-top: px2rpx(10);
- line-height: 1.5;
- }
- .dialog-footer {
- display: flex;
- justify-content: center;
- gap: px2rpx(15);
- margin-top: px2rpx(30);
- button {
- min-width: px2rpx(100);
- margin: 0;
- }
- }
- }
- </style>
|