Files
akmon/pages/info/cominfoedit.uvue
2026-01-20 08:04:15 +08:00

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>