370 lines
8.8 KiB
Plaintext
370 lines
8.8 KiB
Plaintext
<template>
|
|
<view class="config-edit-page">
|
|
<text class="page-title">公司全局配置管理</text>
|
|
<button type="primary" @click="openAddModal">新增配置项</button>
|
|
<list-view :loading="isLoading" class="config-list-view">
|
|
<template #header>
|
|
<view class="list-header-row">
|
|
<text class="list-header-cell">配置键</text>
|
|
<text class="list-header-cell">配置值</text>
|
|
<text class="list-header-cell">类型</text>
|
|
<text class="list-header-cell">分类</text>
|
|
<text class="list-header-cell">可翻译</text>
|
|
<text class="list-header-cell">排序</text>
|
|
<text class="list-header-cell">启用</text>
|
|
<text class="list-header-cell">操作</text>
|
|
</view>
|
|
</template>
|
|
<list-item v-for="item in configList" :key="item.id" class="list-row">
|
|
<text class="list-cell">{{ item.config_key }}</text>
|
|
<text class="list-cell">{{ item.default_value }}</text>
|
|
<text class="list-cell">{{ item.config_type }}</text>
|
|
<text class="list-cell">{{ item.default_key }}</text>
|
|
<text class="list-cell">{{ item.config_category }}</text>
|
|
<text class="list-cell">{{ item.is_translatable ? '是' : '否' }}</text>
|
|
<text class="list-cell">{{ item.sort_order }}</text>
|
|
<view class="list-cell">
|
|
<text
|
|
:class="['tag', item.is_active ? 'tag-success' : 'tag-default']">{{ item.is_active ? '启用' : '停用' }}</text>
|
|
</view>
|
|
<view class="list-cell">
|
|
<button size="mini" @click="openEditModal(item)">编辑</button>
|
|
</view>
|
|
</list-item>
|
|
</list-view>
|
|
<button type="default" @click="loadConfigList">刷新</button>
|
|
|
|
<!-- 编辑/新增弹窗 -->
|
|
<l-popup v-model="editPopupVisible" position="bottom" :closeable="true" @click-close="closeEditModal">
|
|
<view class="popup-content">
|
|
<view class="popup-title-bar">
|
|
<text class="popup-title">{{ editMode === 'add' ? '新增配置项' : '编辑配置项' }}</text>
|
|
<button class="popup-close-btn" @click="closeEditModal">关闭</button>
|
|
</view>
|
|
<form @submit="saveConfig">
|
|
<view class="form-item">
|
|
<text class="form-label">配置键</text>
|
|
<input v-model="editForm.config_key" placeholder="如 social_weibo_url" required />
|
|
</view>
|
|
<view class="form-item">
|
|
<text class="form-label">提示键</text>
|
|
<input v-model="editForm.default_key" placeholder="如 social_weibo_url" required />
|
|
</view>
|
|
<view class="form-item">
|
|
<text class="form-label">配置值</text>
|
|
<input v-model="editForm.default_value" placeholder="如 https://weibo.com/innovation-tech" required />
|
|
</view>
|
|
<view class="form-item">
|
|
<text class="form-label">类型</text>
|
|
<input v-model="editForm.config_type" placeholder="如 string" />
|
|
</view>
|
|
<view class="form-item">
|
|
<text class="form-label">分类</text>
|
|
<input v-model="editForm.config_category" placeholder="如 social" />
|
|
</view>
|
|
<view class="form-item">
|
|
<text class="form-label">可翻译</text>
|
|
<switch :checked="!!editForm.is_translatable" @change="e => editForm.is_translatable = e.detail.value" />
|
|
</view>
|
|
<view class="form-item">
|
|
<text class="form-label">排序</text>
|
|
<input v-model="editForm.sort_order" type="number" placeholder="如 31" />
|
|
</view>
|
|
<view class="form-item">
|
|
<text class="form-label">启用</text>
|
|
<switch :checked="!!editForm.is_active" @change="e => editForm.is_active = e.detail.value" />
|
|
</view>
|
|
<view class="popup-actions">
|
|
<button type="primary" form-type="submit">保存</button>
|
|
<button @click="closeEditModal" type="button">取消</button>
|
|
</view>
|
|
</form>
|
|
</view>
|
|
</l-popup>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup lang="uts">
|
|
import { ref, reactive, onMounted } from 'vue'
|
|
import supa from '@/components/supadb/aksupainstance.uts'
|
|
|
|
type CompanyConfig = {
|
|
id ?: string
|
|
config_key : string
|
|
default_key : string
|
|
default_value : string
|
|
config_type : string
|
|
config_category ?: string
|
|
is_translatable ?: boolean
|
|
sort_order ?: number
|
|
is_active ?: boolean
|
|
created_at ?: string
|
|
updated_at ?: string
|
|
}
|
|
|
|
const configList = ref<Array<CompanyConfig>>([])
|
|
const isLoading = ref(false)
|
|
const editMode = ref<'add' | 'edit'>('add')
|
|
const editForm = reactive<CompanyConfig>({
|
|
config_key: '',
|
|
default_key:'',
|
|
default_value: '',
|
|
config_type: '',
|
|
config_category: '',
|
|
is_translatable: true,
|
|
sort_order: 0,
|
|
is_active: true
|
|
})
|
|
const editPopupVisible = ref(false)
|
|
|
|
function loadConfigList() {
|
|
isLoading.value = true
|
|
supa
|
|
.from('ak_global_config')
|
|
.select('*')
|
|
.order('created_at', { ascending: false })
|
|
.execute()
|
|
.then((res) => {
|
|
configList.value = res.data ?? []
|
|
})
|
|
.catch((err) => {
|
|
uni.showToast({ title: '加载失败', icon: 'none' })
|
|
})
|
|
.finally(() => {
|
|
isLoading.value = false
|
|
})
|
|
}
|
|
|
|
function openAddModal() {
|
|
editMode.value = 'add'
|
|
Object.assign(editForm, {
|
|
config_key: '',
|
|
default_value: '',
|
|
config_type: '',
|
|
config_category: '',
|
|
is_translatable: true,
|
|
sort_order: 0,
|
|
is_active: true
|
|
})
|
|
editPopupVisible.value = true
|
|
}
|
|
|
|
function openEditModal(item : CompanyConfig) {
|
|
editMode.value = 'edit'
|
|
Object.assign(editForm, item)
|
|
editPopupVisible.value = true
|
|
}
|
|
|
|
function closeEditModal() {
|
|
editPopupVisible.value = false
|
|
}
|
|
|
|
function saveConfig() {
|
|
if (!editForm.config_key || !editForm.default_value) {
|
|
uni.showToast({ title: '请填写必填项', icon: 'none' })
|
|
return
|
|
}
|
|
isLoading.value = true
|
|
if (editMode.value === 'add') {
|
|
supa
|
|
.from('ak_global_config')
|
|
.insert([editForm])
|
|
.execute()
|
|
.then(() => {
|
|
uni.showToast({ title: '新增成功', icon: 'success' })
|
|
loadConfigList()
|
|
closeEditModal()
|
|
})
|
|
.catch(() => {
|
|
uni.showToast({ title: '新增失败', icon: 'none' })
|
|
})
|
|
.finally(() => {
|
|
isLoading.value = false
|
|
})
|
|
} else {
|
|
supa
|
|
.from('ak_global_config')
|
|
.update(editForm)
|
|
.eq('id', editForm.id)
|
|
.execute()
|
|
.then(() => {
|
|
uni.showToast({ title: '保存成功', icon: 'success' })
|
|
loadConfigList()
|
|
closeEditModal()
|
|
})
|
|
.catch(() => {
|
|
uni.showToast({ title: '保存失败', icon: 'none' })
|
|
})
|
|
.finally(() => {
|
|
isLoading.value = false
|
|
})
|
|
}
|
|
}
|
|
|
|
function deleteConfig(id : string) {
|
|
uni.showModal({
|
|
title: '确认删除',
|
|
content: '确定要删除该配置项吗?',
|
|
success: (res) => {
|
|
if (res.confirm) {
|
|
isLoading.value = true
|
|
supa
|
|
.from('ak_global_config')
|
|
.delete()
|
|
.eq('id', id)
|
|
.then(() => {
|
|
uni.showToast({ title: '删除成功', icon: 'success' })
|
|
loadConfigList()
|
|
})
|
|
.catch(() => {
|
|
uni.showToast({ title: '删除失败', icon: 'none' })
|
|
})
|
|
.finally(() => {
|
|
isLoading.value = false
|
|
})
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
onMounted(() => {
|
|
loadConfigList()
|
|
})
|
|
</script>
|
|
|
|
<style>
|
|
.config-edit-page {
|
|
padding: 20px;
|
|
background: #f8fafc;
|
|
}
|
|
|
|
.page-title {
|
|
font-size: 22px;
|
|
font-weight: bold;
|
|
text-align: center;
|
|
margin-bottom: 18px;
|
|
color: #1f2937;
|
|
}
|
|
|
|
.config-list-view {
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.list-header-row {
|
|
display: flex;
|
|
flex-direction: row;
|
|
background: #f1f5f9;
|
|
padding: 8px 0;
|
|
font-weight: bold;
|
|
border-bottom-width: 1px;
|
|
border-bottom-color: #e2e8f0;
|
|
}
|
|
|
|
.list-header-cell {
|
|
flex: 1;
|
|
text-align: center;
|
|
color: #475569;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.list-row {
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
padding: 8px 0;
|
|
border-bottom-width: 1px;
|
|
border-bottom-color: #e5e7eb;
|
|
background: #fff;
|
|
}
|
|
|
|
.list-cell {
|
|
flex: 1;
|
|
text-align: center;
|
|
font-size: 13px;
|
|
color: #334155;
|
|
padding: 0 4px;
|
|
}
|
|
|
|
.tag {
|
|
padding: 2px 8px;
|
|
border-radius: 8px;
|
|
font-size: 12px;
|
|
color: #fff;
|
|
background: #9ca3af;
|
|
margin: 0 auto;
|
|
min-width: 40px;
|
|
text-align: center;
|
|
}
|
|
|
|
.tag-success {
|
|
background: #3b82f6;
|
|
}
|
|
|
|
.tag-default {
|
|
background: #9ca3af;
|
|
}
|
|
|
|
.popup-content {
|
|
padding: 20px;
|
|
}
|
|
|
|
.popup-title-bar {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.popup-title {
|
|
font-size: 18px;
|
|
font-weight: bold;
|
|
color: #1f2937;
|
|
}
|
|
|
|
.popup-close-btn {
|
|
background: none;
|
|
border: none;
|
|
color: #475569;
|
|
font-size: 16px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.form-item {
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.form-label {
|
|
width: 80px;
|
|
font-size: 14px;
|
|
color: #475569;
|
|
margin-right: 8px;
|
|
}
|
|
|
|
input {
|
|
flex: 1;
|
|
border: 1px solid #e5e7eb;
|
|
border-radius: 6px;
|
|
padding: 6px 10px;
|
|
font-size: 14px;
|
|
color: #334155;
|
|
background: #fff;
|
|
}
|
|
|
|
.picker-value {
|
|
padding: 6px 10px;
|
|
font-size: 14px;
|
|
color: #334155;
|
|
background: #f1f5f9;
|
|
border-radius: 6px;
|
|
}
|
|
|
|
.popup-actions {
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 16px;
|
|
margin-top: 16px;
|
|
}
|
|
</style> |