Files
intc-single-ultra-app/src/pages_mine/pages/system/dictData/list.vue
2026-02-08 01:12:36 +08:00

668 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="container">
<u-sticky offsetTop="0rpx" customNavHeight="0rpx">
<view class="search-view">
<view class="dict-name-row">
<view class="divider-line"></view>
<view class="dict-name-text">
<text>字典类型{{ dictName }}</text>
</view>
<view class="divider-line"></view>
</view>
<view class="search-row">
<u--input v-model="queryParams.dictLabel" border="false" placeholder="请输入字典标签" class="search-input"
@blur="searchBlur" suffixIcon="search" suffixIconStyle="color: #909399">
</u--input>
<view class="filter-btn" @click="filterPanel = !filterPanel">
<uni-icons type="list" size="18" color="#667eea"></uni-icons>
<text>筛选</text>
</view>
<view class="add-btn" @click="handleAdd()">
<uni-icons type="plusempty" size="18" color="#667eea"></uni-icons>
<text>新增</text>
</view>
</view>
<u-transition :show="filterPanel" mode="fade">
<view class="filter-panel" :style="{ height: `${windowHeight - 42}px` }">
<view class="filter-panel-content">
<view class="filter-title">状态</view>
<view class="state-list">
<view v-for="item in statusList" :key="item.dictValue" class="state-item"
:class="item.selected ? 'active' : ''" @click="selectStatus(item)">{{ item.dictLabel }}</view>
</view>
</view>
<view class="btn-box">
<view class="btn-reset" @click="resetQuery()">
<uni-icons type="reload" size="16" color="#909399"></uni-icons>
<text>重置</text>
</view>
<view class="btn-confirm" @click="searchSubmit()">
<uni-icons type="checkmarkempty" size="16" color="#ffffff"></uni-icons>
<text>确定</text>
</view>
</view>
</view>
</u-transition>
</view>
</u-sticky>
<u-list @scrolltolower="loadmore" :spaceHeight="116" lowerThreshold="100">
<u-list-item v-for="(item, index) in listData" :key="index">
<view class="list-item" @click="enterDetails(item)">
<view class="item-header">
<view class="card-name-section">
<view class="card-icon">
<uni-icons type="star" size="20" color="#ffffff"></uni-icons>
</view>
<view class="card-info">
<view class="card-name">
<text class="label-text">{{ item.dictLabel }}</text>
<text class="value-text" v-if="item.dictValue">{{ item.dictValue }}</text>
</view>
</view>
</view>
</view>
<view class="card-body">
<view class="info-row">
<view class="info-item">
<text class="info-label">显示排序</text>
<text class="info-value">{{ item.dictSort }}</text>
</view>
<view class="info-item">
<text class="info-label">字典类型</text>
<text class="info-value">{{ item.dictType }}</text>
</view>
<view class="info-item" v-if="item.createTime">
<text class="info-label">创建时间</text>
<text class="info-value">{{ item.createTime }}</text>
</view>
<view class="info-item" v-if="item.listClass">
<text class="info-label">回显样式</text>
<text class="info-value">{{ item.listClass }}</text>
</view>
<view class="info-item" v-if="item.remark">
<text class="info-label">备注</text>
<text class="info-value">{{ item.remark }}</text>
</view>
</view>
</view>
<view class="operate" @click.stop>
<view class="btn-edit" @click="handleUpdate(item)">
<uni-icons type="compose" size="16" color="#667eea"></uni-icons>
<text>修改</text>
</view>
<view class="btn-delete" @click="handleDelete(item)">
<uni-icons type="trash" size="16" color="#f5576c"></uni-icons>
<text>删除</text>
</view>
</view>
</view>
</u-list-item>
<view></view>
<u-loadmore :status="loadStatus" loadingIcon="semicircle" height="88" fontSize="32rpx" @loadmore="loadmore" />
</u-list>
</view>
<systemBtn></systemBtn>
<refresh></refresh>
</template>
<script setup>
import { ref, reactive, computed } from 'vue'
import { listData as getDataList, delData } from '@/api/system/dict/data'
import { getType } from '@/api/system/dict/type'
import { getDicts } from "@/api/system/dict/data"
import { onLoad, onShow } from "@dcloudio/uni-app"
import modal from '@/plugins/modal'
const pageNum = ref(1)
const listData = ref([])
const isShow = ref(false)
const loadStatus = ref('loadmore')
const statusList = ref([])
const filterPanel = ref(false)
const dictType = ref('')
const dictName = ref('')
const queryParams = reactive({
dictType: undefined,
dictLabel: undefined,
status: undefined
})
const windowHeight = computed(() => {
uni.getSystemInfoSync().windowHeight - 50
})
onLoad((option) => {
getDicts('sys_normal_disable').then(res => {
statusList.value = res.data.map(item => ({
...item,
selected: false
}))
})
if (option.dictId) {
// 获取字典类型信息
getType(option.dictId).then(res => {
queryParams.dictType = res.data.dictType
dictType.value = res.data.dictType
dictName.value = res.data.dictName
// 在获取字典类型后再查询列表
getList()
})
} else {
getList()
}
})
onShow(() => {
if (isShow.value) {
listData.value = []
pageNum.value = 1
getList()
isShow.value = false
}
})
// 获取列表
function getList() {
loadStatus.value = 'loading'
getDataList({ pageSize: 10, pageNum: pageNum.value, ...queryParams }).then(res => {
listData.value = listData.value.concat(res.rows)
if (listData.value.length < res.total) {
loadStatus.value = 'loadmore'
} else {
loadStatus.value = 'nomore'
}
}).catch(() => {
loadStatus.value = 'nomore'
})
}
// 搜索框失焦
function searchBlur() {
listData.value = []
pageNum.value = 1
getList()
}
// 选择状态
function selectStatus(item) {
statusList.value.forEach(v => v.selected = false)
item.selected = !item.selected
queryParams.status = item.dictValue
}
// 搜索提交
function searchSubmit() {
listData.value = []
pageNum.value = 1
filterPanel.value = false
getList()
}
// 重置查询
function resetQuery() {
queryParams.dictLabel = undefined
queryParams.status = undefined
listData.value = []
pageNum.value = 1
statusList.value.forEach(v => v.selected = false)
filterPanel.value = false
getList()
}
// 上拉加载
function loadmore() {
pageNum.value += 1
if (loadStatus.value == 'loadmore') {
getList()
}
}
// 新增
function handleAdd() {
isShow.value = true
uni.navigateTo({
url: `/pages_mine/pages/system/dictData/addEdit?dictType=${dictType.value}`
})
}
// 编辑
function handleUpdate(row) {
isShow.value = true
uni.navigateTo({
url: `/pages_mine/pages/system/dictData/addEdit?dictCode=${row.dictCode}`
})
}
// 删除
function handleDelete(row) {
modal.confirm('是否确认删除字典编码为"' + row.dictCode + '"的数据项?').then(() => {
return delData(row.dictCode)
}).then(() => {
listData.value = []
pageNum.value = 1
getList()
modal.msgSuccess('删除成功')
}).catch(() => {})
}
// 进入详情
function enterDetails(item) {
isShow.value = true
uni.navigateTo({
url: `/pages_mine/pages/system/dictData/details?dictCode=${item.dictCode}`
})
}
// 字典翻译
function dictStr(value, list) {
const item = list.find(v => v.dictValue === value)
return item ? item.dictLabel : value
}
</script>
<style lang="scss" scoped>
page {
height: 100%;
overflow: auto;
}
.container {
min-height: 100vh;
background-color: #f5f5f5;
}
.search-view {
display: flex;
flex-direction: column;
padding: 20rpx 24rpx;
background-color: #ffffff;
position: relative;
gap: 16rpx;
.dict-name-row {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 16rpx;
padding: 0 24rpx;
.divider-line {
flex: 1;
height: 2rpx;
background: linear-gradient(to right, transparent, #667eea, transparent);
}
.dict-name-text {
padding: 0 24rpx;
white-space: nowrap;
text {
color: #667eea;
font-size: 26rpx;
font-weight: 600;
letter-spacing: 1rpx;
}
}
}
.search-row {
display: flex;
align-items: center;
gap: 16rpx;
}
.search-input {
background: rgba(102, 126, 234, 0.08);
color: #333333;
flex: 1;
min-width: 0;
margin-right: 16rpx;
border-radius: 24rpx;
border: 2rpx solid rgba(102, 126, 234, 0.3);
height: 66rpx !important;
display: flex;
align-items: center;
}
.filter-btn {
display: flex;
align-items: center;
gap: 6rpx;
padding: 12rpx 24rpx;
background: rgba(102, 126, 234, 0.08);
border-radius: 24rpx;
border: 2rpx solid rgba(102, 126, 234, 0.3);
transition: all 0.3s ease;
flex-shrink: 0;
&:active {
transform: scale(0.95);
background: rgba(102, 126, 234, 0.12);
}
text {
color: #667eea;
font-size: 28rpx;
font-weight: 600;
}
uni-icons {
color: #667eea;
}
}
.add-btn {
display: flex;
align-items: center;
gap: 6rpx;
padding: 12rpx 24rpx;
background: rgba(102, 126, 234, 0.08);
border-radius: 24rpx;
border: 2rpx solid rgba(102, 126, 234, 0.3);
transition: all 0.3s ease;
flex-shrink: 0;
margin-left: 10rpx;
&:active {
transform: scale(0.95);
background: rgba(102, 126, 234, 0.12);
}
text {
color: #667eea;
font-size: 28rpx;
font-weight: 600;
}
uni-icons {
color: #667eea;
}
}
.filter-panel {
position: absolute;
top: 100rpx;
left: 0;
right: 0;
background-color: #ffffff;
z-index: 999;
display: flex;
flex-direction: column;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
.filter-panel-content {
flex: 1;
padding: 32rpx;
overflow-y: auto;
.filter-title {
font-size: 28rpx;
font-weight: bold;
margin: 32rpx 0 24rpx 0;
color: #303133;
&:first-child {
margin-top: 0;
}
}
.state-list {
display: flex;
flex-wrap: wrap;
gap: 16rpx;
.state-item {
padding: 16rpx 32rpx;
background-color: #f5f5f5;
border-radius: 32rpx;
font-size: 28rpx;
color: #606266;
&.active {
background-color: #667eea;
color: #ffffff;
}
}
}
}
.btn-box {
display: flex;
padding: 24rpx 32rpx;
border-top: 1rpx solid #f0f0f0;
.btn-reset,
.btn-confirm {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 20rpx 0;
border-radius: 32rpx;
font-size: 28rpx;
text {
margin-left: 12rpx;
}
}
.btn-reset {
background-color: #f5f5f5;
color: #909399;
margin-right: 16rpx;
}
.btn-confirm {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #ffffff;
}
}
}
}
.list-item {
margin: 10rpx 24rpx;
background-color: #fff;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
transition: all 0.2s ease;
&:active {
transform: scale(0.98);
box-shadow: 0 1rpx 6rpx rgba(0, 0, 0, 0.06);
}
.item-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16rpx 24rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
.card-name-section {
display: flex;
align-items: center;
flex: 1;
min-width: 0;
margin-right: 16rpx;
}
.card-icon {
width: 40rpx;
height: 40rpx;
background: rgba(255, 255, 255, 0.25);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-right: 12rpx;
flex-shrink: 0;
}
.card-info {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: 4rpx;
.card-name {
display: flex;
align-items: center;
gap: 160rpx;
color: #ffffff;
font-size: 26rpx;
font-weight: 600;
line-height: 1.2;
.label-text {
color: #ffffff;
}
.value-text {
color: rgba(255, 255, 255, 0.85);
}
}
.card-code {
color: rgba(255, 255, 255, 0.85);
font-size: 22rpx;
font-weight: 400;
line-height: 1;
}
}
.balance-section {
display: flex;
align-items: center;
flex-shrink: 0;
white-space: nowrap;
.status-tag {
padding: 8rpx 20rpx;
border-radius: 20rpx;
font-size: 22rpx;
font-weight: 500;
&.status-normal {
background-color: rgba(82, 196, 26, 0.2);
color: #52c41a;
}
&.status-disabled {
background-color: rgba(255, 77, 79, 0.15);
color: #ff4d4f;
}
}
}
}
.card-body {
padding: 24rpx;
background: #fafbfc;
border: 2rpx solid #f0f2f5;
margin: 15rpx 16rpx 2rpx;
border-radius: 12rpx;
}
.info-row {
display: flex;
flex-wrap: wrap;
margin-bottom: 0;
.info-item {
width: 50%;
box-sizing: border-box;
padding-right: 12rpx;
padding-bottom: 16rpx;
display: flex;
flex-direction: column;
gap: 4rpx;
min-width: 0;
margin-bottom: 0;
&:nth-child(2n) {
padding-right: 0;
padding-left: 12rpx;
}
&.info-item-full {
width: 100%;
padding-right: 0;
padding-left: 0;
}
.info-label {
font-size: 24rpx;
color: #667eea;
font-weight: 500;
background: rgba(102, 126, 234, 0.08);
padding: 6rpx 12rpx;
border-radius: 8rpx;
align-self: flex-start;
}
.info-value {
font-size: 26rpx;
color: #333;
font-weight: 500;
flex: 1;
line-height: 1.5;
word-break: break-all;
}
&:not(.info-item-full) .info-value {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
.operate {
display: flex;
justify-content: flex-end;
padding: 16rpx 24rpx 24rpx;
gap: 8rpx;
flex-wrap: nowrap;
.btn-edit,
.btn-delete {
display: flex;
align-items: center;
justify-content: center;
gap: 4rpx;
padding: 0 14rpx;
height: 60rpx;
border-radius: 10rpx;
font-size: 24rpx;
font-weight: 500;
transition: all 0.3s ease;
white-space: nowrap;
flex-shrink: 0;
&:active {
transform: scale(0.95);
}
}
.btn-edit {
background: rgba(102, 126, 234, 0.1);
color: #667eea;
border: 1rpx solid rgba(102, 126, 234, 0.3);
}
.btn-delete {
background: rgba(245, 87, 108, 0.1);
color: #f5576c;
border: 1rpx solid rgba(245, 87, 108, 0.3);
}
}
}
</style>