更新
This commit is contained in:
34
src/App.vue
34
src/App.vue
@@ -1,7 +1,9 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, computed } from 'vue'
|
import { onMounted, computed, watch, nextTick } from 'vue'
|
||||||
|
import { storeToRefs } from 'pinia'
|
||||||
import { useI18nStore } from './stores/modules/i18n'
|
import { useI18nStore } from './stores/modules/i18n'
|
||||||
import { useLayoutStore } from './stores/modules/layout'
|
import { useLayoutStore } from './stores/modules/layout'
|
||||||
|
import { theme } from 'ant-design-vue'
|
||||||
import i18n from './i18n'
|
import i18n from './i18n'
|
||||||
import zhCN from 'ant-design-vue/es/locale/zh_CN'
|
import zhCN from 'ant-design-vue/es/locale/zh_CN'
|
||||||
import enUS from 'ant-design-vue/es/locale/en_US'
|
import enUS from 'ant-design-vue/es/locale/en_US'
|
||||||
@@ -9,12 +11,20 @@ import dayjs from 'dayjs'
|
|||||||
import 'dayjs/locale/zh-cn'
|
import 'dayjs/locale/zh-cn'
|
||||||
import 'dayjs/locale/en'
|
import 'dayjs/locale/en'
|
||||||
|
|
||||||
|
// 定义组件名称
|
||||||
|
defineOptions({
|
||||||
|
name: 'App'
|
||||||
|
})
|
||||||
|
|
||||||
// i18n store
|
// i18n store
|
||||||
const i18nStore = useI18nStore()
|
const i18nStore = useI18nStore()
|
||||||
|
|
||||||
// layout store
|
// layout store
|
||||||
const layoutStore = useLayoutStore()
|
const layoutStore = useLayoutStore()
|
||||||
|
|
||||||
|
// 解构 themeColor 以确保响应式
|
||||||
|
const { themeColor } = storeToRefs(layoutStore)
|
||||||
|
|
||||||
// Ant Design Vue 语言配置
|
// Ant Design Vue 语言配置
|
||||||
const antLocale = computed(() => {
|
const antLocale = computed(() => {
|
||||||
return i18nStore.currentLocale === 'zh-CN' ? zhCN : enUS
|
return i18nStore.currentLocale === 'zh-CN' ? zhCN : enUS
|
||||||
@@ -28,8 +38,9 @@ const getPopupContainer = () => {
|
|||||||
// Ant Design Vue 主题配置
|
// Ant Design Vue 主题配置
|
||||||
const antdTheme = computed(() => {
|
const antdTheme = computed(() => {
|
||||||
return {
|
return {
|
||||||
|
algorithm: theme.defaultAlgorithm,
|
||||||
token: {
|
token: {
|
||||||
colorPrimary: layoutStore.themeColor,
|
colorPrimary: themeColor.value || '#1890ff',
|
||||||
borderRadius: 6,
|
borderRadius: 6,
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
},
|
},
|
||||||
@@ -40,21 +51,34 @@ const antdTheme = computed(() => {
|
|||||||
},
|
},
|
||||||
Menu: {
|
Menu: {
|
||||||
darkItemBg: '#001529',
|
darkItemBg: '#001529',
|
||||||
darkItemSelectedBg: '#1890ff',
|
darkItemSelectedBg: themeColor.value || '#1890ff',
|
||||||
darkItemHoverBg: '#002140',
|
darkItemHoverBg: '#002140',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
// 监听主题颜色变化,更新 CSS 变量
|
||||||
|
watch(
|
||||||
|
themeColor,
|
||||||
|
(newColor) => {
|
||||||
|
if (newColor) {
|
||||||
|
document.documentElement.style.setProperty('--primary-color', newColor)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await nextTick()
|
||||||
|
|
||||||
// 从持久化的 store 中读取语言设置并同步到 i18n
|
// 从持久化的 store 中读取语言设置并同步到 i18n
|
||||||
i18n.global.locale.value = i18nStore.currentLocale
|
i18n.global.locale.value = i18nStore.currentLocale
|
||||||
|
|
||||||
// 同步 dayjs 语言
|
// 同步 dayjs 语言
|
||||||
dayjs.locale(i18nStore.currentLocale === 'zh-CN' ? 'zh-cn' : 'en')
|
dayjs.locale(i18nStore.currentLocale === 'zh-CN' ? 'zh-cn' : 'en')
|
||||||
|
|
||||||
// 初始化主题颜色
|
// 初始化主题颜色到 CSS 变量
|
||||||
if (layoutStore.themeColor) {
|
if (layoutStore.themeColor) {
|
||||||
document.documentElement.style.setProperty('--primary-color', layoutStore.themeColor)
|
document.documentElement.style.setProperty('--primary-color', layoutStore.themeColor)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,12 +301,12 @@ onBeforeUnmount(() => {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
||||||
&::-webkit-scrollbar {
|
&::-webkit-scrollbar {
|
||||||
height: 4px;
|
height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb {
|
&::-webkit-scrollbar-thumb {
|
||||||
background: rgba(0, 0, 0, 0.2);
|
background: rgba(0, 0, 0, 0.2);
|
||||||
border-radius: 2px;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-scrollbar-track {
|
&::-webkit-scrollbar-track {
|
||||||
|
|||||||
@@ -88,20 +88,18 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive, computed, onMounted } from 'vue'
|
import { ref, reactive, onMounted } from 'vue'
|
||||||
import { message, Modal } from 'ant-design-vue'
|
import { message, Modal } from 'ant-design-vue'
|
||||||
import { SearchOutlined, RedoOutlined, DeleteOutlined, PlusOutlined, FolderOutlined, FileOutlined } from '@ant-design/icons-vue'
|
import { SearchOutlined, RedoOutlined, DeleteOutlined, PlusOutlined, FolderOutlined, FileOutlined } from '@ant-design/icons-vue'
|
||||||
import scTable from '@/components/scTable/index.vue'
|
import scTable from '@/components/scTable/index.vue'
|
||||||
import areaModal from './components/AreaModal.vue'
|
import areaModal from './components/AreaModal.vue'
|
||||||
import systemApi from '@/api/system'
|
import systemApi from '@/api/system'
|
||||||
|
import { useTable } from '@/hooks/useTable'
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'systemArea'
|
name: 'systemArea'
|
||||||
})
|
})
|
||||||
|
|
||||||
// 表格引用
|
|
||||||
const tableRef = ref(null)
|
|
||||||
|
|
||||||
// 对话框状态
|
// 对话框状态
|
||||||
const dialog = reactive({
|
const dialog = reactive({
|
||||||
save: false
|
save: false
|
||||||
@@ -116,37 +114,44 @@ const filteredAreaTree = ref([])
|
|||||||
const selectedAreaKeys = ref([])
|
const selectedAreaKeys = ref([])
|
||||||
const areaKeyword = ref('')
|
const areaKeyword = ref('')
|
||||||
|
|
||||||
// 选中的行
|
// 使用useTable hooks
|
||||||
const selectedRowKeys = ref([])
|
const {
|
||||||
|
tableRef,
|
||||||
// 行选择配置
|
searchForm,
|
||||||
const rowSelection = computed(() => ({
|
tableData,
|
||||||
selectedRowKeys: selectedRowKeys.value,
|
loading,
|
||||||
onChange: (selectedKeys) => {
|
pagination,
|
||||||
selectedRowKeys.value = selectedKeys
|
rowSelection,
|
||||||
},
|
selectedRowKeys,
|
||||||
}))
|
handleSearch,
|
||||||
|
handleReset,
|
||||||
// 搜索表单
|
loadData
|
||||||
const searchForm = reactive({
|
} = useTable({
|
||||||
|
api: systemApi.area.list.get,
|
||||||
|
searchParams: {
|
||||||
title: '',
|
title: '',
|
||||||
level: null,
|
level: null,
|
||||||
parent_code: null
|
parent_code: null
|
||||||
|
},
|
||||||
|
rowSelection: true,
|
||||||
|
onSearchBefore: () => {
|
||||||
|
// 重置地区选择
|
||||||
|
selectedAreaKeys.value = []
|
||||||
|
},
|
||||||
|
onResetBefore: () => {
|
||||||
|
// 重置地区选择和搜索
|
||||||
|
selectedAreaKeys.value = []
|
||||||
|
areaKeyword.value = ''
|
||||||
|
filteredAreaTree.value = areaTree.value
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// 表格数据
|
// 分页变化处理
|
||||||
const tableData = ref([])
|
const handlePaginationChange = ({ page, pageSize }) => {
|
||||||
const loading = ref(false)
|
pagination.current = page
|
||||||
|
pagination.pageSize = pageSize
|
||||||
// 分页配置
|
loadData()
|
||||||
const pagination = reactive({
|
}
|
||||||
current: 1,
|
|
||||||
pageSize: 20,
|
|
||||||
total: 0,
|
|
||||||
showSizeChanger: true,
|
|
||||||
showTotal: (total) => `共 ${total} 条`,
|
|
||||||
pageSizeOptions: ['20', '50', '100', '200']
|
|
||||||
})
|
|
||||||
|
|
||||||
// 行key
|
// 行key
|
||||||
const rowKey = 'id'
|
const rowKey = 'id'
|
||||||
@@ -238,36 +243,6 @@ const handleAreaSearch = (e) => {
|
|||||||
filteredAreaTree.value = filterTree(areaTree.value)
|
filteredAreaTree.value = filterTree(areaTree.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载地区列表数据
|
|
||||||
const loadData = async () => {
|
|
||||||
loading.value = true
|
|
||||||
try {
|
|
||||||
const params = {
|
|
||||||
page: pagination.current,
|
|
||||||
limit: pagination.pageSize,
|
|
||||||
...searchForm
|
|
||||||
}
|
|
||||||
const res = await systemApi.area.list.get(params)
|
|
||||||
if (res.code === 1) {
|
|
||||||
tableData.value = res.data?.data || res.data?.list || []
|
|
||||||
pagination.total = res.data?.total || 0
|
|
||||||
} else {
|
|
||||||
message.error(res.message || '加载数据失败')
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('加载地区列表失败:', error)
|
|
||||||
message.error('加载数据失败')
|
|
||||||
} finally {
|
|
||||||
loading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页变化处理
|
|
||||||
const handlePaginationChange = ({ page, pageSize }) => {
|
|
||||||
pagination.current = page
|
|
||||||
pagination.pageSize = pageSize
|
|
||||||
loadData()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 地区选择事件
|
// 地区选择事件
|
||||||
const onAreaSelect = (selectedKeys) => {
|
const onAreaSelect = (selectedKeys) => {
|
||||||
@@ -276,26 +251,7 @@ const onAreaSelect = (selectedKeys) => {
|
|||||||
} else {
|
} else {
|
||||||
searchForm.parent_code = null
|
searchForm.parent_code = null
|
||||||
}
|
}
|
||||||
pagination.current = 1
|
handleSearch()
|
||||||
loadData()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 搜索
|
|
||||||
const handleSearch = () => {
|
|
||||||
pagination.current = 1
|
|
||||||
loadData()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重置
|
|
||||||
const handleReset = () => {
|
|
||||||
searchForm.title = ''
|
|
||||||
searchForm.level = null
|
|
||||||
searchForm.parent_code = null
|
|
||||||
selectedAreaKeys.value = []
|
|
||||||
areaKeyword.value = ''
|
|
||||||
filteredAreaTree.value = areaTree.value
|
|
||||||
pagination.current = 1
|
|
||||||
loadData()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增地区
|
// 新增地区
|
||||||
|
|||||||
@@ -55,21 +55,19 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive, computed, onMounted } from 'vue'
|
import { ref, reactive, onMounted } from 'vue'
|
||||||
import { message, Modal } from 'ant-design-vue'
|
import { message, Modal } from 'ant-design-vue'
|
||||||
import { SearchOutlined, RedoOutlined, DeleteOutlined, PlusOutlined } from '@ant-design/icons-vue'
|
import { SearchOutlined, RedoOutlined, DeleteOutlined, PlusOutlined } from '@ant-design/icons-vue'
|
||||||
import scTable from '@/components/scTable/index.vue'
|
import scTable from '@/components/scTable/index.vue'
|
||||||
import saveDialog from './save.vue'
|
import saveDialog from './save.vue'
|
||||||
import menuDrawer from './menu.vue'
|
import menuDrawer from './menu.vue'
|
||||||
import systemApi from '@/api/system'
|
import systemApi from '@/api/system'
|
||||||
|
import { useTable } from '@/hooks/useTable'
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'systemClient'
|
name: 'systemClient'
|
||||||
})
|
})
|
||||||
|
|
||||||
// 表格引用
|
|
||||||
const tableRef = ref(null)
|
|
||||||
|
|
||||||
// 对话框状态
|
// 对话框状态
|
||||||
const dialog = reactive({
|
const dialog = reactive({
|
||||||
save: false,
|
save: false,
|
||||||
@@ -80,34 +78,24 @@ const dialog = reactive({
|
|||||||
const saveDialogRef = ref(null)
|
const saveDialogRef = ref(null)
|
||||||
const menuDrawerRef = ref(null)
|
const menuDrawerRef = ref(null)
|
||||||
|
|
||||||
// 选中的行
|
// 使用useTable hooks
|
||||||
const selectedRowKeys = ref([])
|
const {
|
||||||
|
tableRef,
|
||||||
// 行选择配置
|
searchForm,
|
||||||
const rowSelection = computed(() => ({
|
tableData,
|
||||||
selectedRowKeys: selectedRowKeys.value,
|
loading,
|
||||||
onChange: (selectedKeys) => {
|
pagination,
|
||||||
selectedRowKeys.value = selectedKeys
|
rowSelection,
|
||||||
},
|
selectedRowKeys,
|
||||||
}))
|
handleSearch,
|
||||||
|
handleReset,
|
||||||
// 搜索表单
|
loadData
|
||||||
const searchForm = reactive({
|
} = useTable({
|
||||||
|
api: systemApi.client.list.get,
|
||||||
|
searchParams: {
|
||||||
title: ''
|
title: ''
|
||||||
})
|
},
|
||||||
|
rowSelection: true
|
||||||
// 表格数据
|
|
||||||
const tableData = ref([])
|
|
||||||
const loading = ref(false)
|
|
||||||
|
|
||||||
// 分页配置
|
|
||||||
const pagination = reactive({
|
|
||||||
current: 1,
|
|
||||||
pageSize: 20,
|
|
||||||
total: 0,
|
|
||||||
showSizeChanger: true,
|
|
||||||
showTotal: (total) => `共 ${total} 条`,
|
|
||||||
pageSizeOptions: ['20', '50', '100', '200']
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// 行key
|
// 行key
|
||||||
@@ -124,30 +112,6 @@ const columns = [
|
|||||||
{ title: '操作', dataIndex: 'action', key: 'action', width: 220, align: 'center', slot: 'action', fixed: 'right' }
|
{ title: '操作', dataIndex: 'action', key: 'action', width: 220, align: 'center', slot: 'action', fixed: 'right' }
|
||||||
]
|
]
|
||||||
|
|
||||||
// 加载客户端列表数据
|
|
||||||
const loadData = async () => {
|
|
||||||
loading.value = true
|
|
||||||
try {
|
|
||||||
const params = {
|
|
||||||
page: pagination.current,
|
|
||||||
limit: pagination.pageSize,
|
|
||||||
...searchForm
|
|
||||||
}
|
|
||||||
const res = await systemApi.client.list.get(params)
|
|
||||||
if (res.code === 1) {
|
|
||||||
tableData.value = res.data?.data || []
|
|
||||||
pagination.total = res.data?.total || 0
|
|
||||||
} else {
|
|
||||||
message.error(res.message || '加载数据失败')
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('加载客户端列表失败:', error)
|
|
||||||
message.error('加载数据失败')
|
|
||||||
} finally {
|
|
||||||
loading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页变化处理
|
// 分页变化处理
|
||||||
const handlePaginationChange = ({ page, pageSize }) => {
|
const handlePaginationChange = ({ page, pageSize }) => {
|
||||||
pagination.current = page
|
pagination.current = page
|
||||||
@@ -155,19 +119,6 @@ const handlePaginationChange = ({ page, pageSize }) => {
|
|||||||
loadData()
|
loadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 搜索
|
|
||||||
const handleSearch = () => {
|
|
||||||
pagination.current = 1
|
|
||||||
loadData()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重置
|
|
||||||
const handleReset = () => {
|
|
||||||
searchForm.title = ''
|
|
||||||
pagination.current = 1
|
|
||||||
loadData()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新增客户端
|
// 新增客户端
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
dialog.save = true
|
dialog.save = true
|
||||||
|
|||||||
@@ -73,9 +73,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive, computed, onMounted, watch } from 'vue'
|
import { ref, reactive, computed, onMounted } from 'vue'
|
||||||
import { message, Modal } from 'ant-design-vue'
|
import { message, Modal } from 'ant-design-vue'
|
||||||
import { SearchOutlined, RedoOutlined, DeleteOutlined, PlusOutlined, FolderOutlined, FileOutlined, EditOutlined } from '@ant-design/icons-vue'
|
|
||||||
import scTable from '@/components/scTable/index.vue'
|
import scTable from '@/components/scTable/index.vue'
|
||||||
import dicDialog from './dic.vue'
|
import dicDialog from './dic.vue'
|
||||||
import listDialog from './list.vue'
|
import listDialog from './list.vue'
|
||||||
@@ -229,7 +228,7 @@ const handlePaginationChange = ({ page, pageSize }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 字典选择事件
|
// 字典选择事件
|
||||||
const onDicSelect = (selectedKeys, info) => {
|
const onDicSelect = (selectedKeys) => {
|
||||||
if (selectedKeys && selectedKeys.length > 0) {
|
if (selectedKeys && selectedKeys.length > 0) {
|
||||||
const selectedId = selectedKeys[0]
|
const selectedId = selectedKeys[0]
|
||||||
currentDic.value = findDicById(filteredDicList.value, selectedId)
|
currentDic.value = findDicById(filteredDicList.value, selectedId)
|
||||||
|
|||||||
Reference in New Issue
Block a user